@nymbalhq/web-components 1.0.0 → 1.2.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/astro/NymbalElement.astro +19 -0
- package/dist/base-element-CPMgAdyQ.d.ts +91 -0
- package/dist/chunk-2TPQNQYO.js +155 -0
- package/dist/chunk-2TPQNQYO.js.map +1 -0
- package/dist/chunk-2XXBQPDB.js +113 -0
- package/dist/chunk-2XXBQPDB.js.map +1 -0
- package/dist/chunk-42SSME5H.js +84 -0
- package/dist/chunk-42SSME5H.js.map +1 -0
- package/dist/chunk-4COVK727.js +204 -0
- package/dist/chunk-4COVK727.js.map +1 -0
- package/dist/chunk-5VWZ2U5K.js +149 -0
- package/dist/chunk-5VWZ2U5K.js.map +1 -0
- package/dist/chunk-6XCCAAMF.js +656 -0
- package/dist/chunk-6XCCAAMF.js.map +1 -0
- package/dist/chunk-7JAAOVCE.js +114 -0
- package/dist/chunk-7JAAOVCE.js.map +1 -0
- package/dist/chunk-B73QVSA5.js +206 -0
- package/dist/chunk-B73QVSA5.js.map +1 -0
- package/dist/chunk-DR5QB5VN.js +17 -0
- package/dist/chunk-DR5QB5VN.js.map +1 -0
- package/dist/chunk-DXWMNB5F.js +70 -0
- package/dist/chunk-DXWMNB5F.js.map +1 -0
- package/dist/chunk-EBMA7JGV.js +130 -0
- package/dist/chunk-EBMA7JGV.js.map +1 -0
- package/dist/chunk-EYDMJNNK.js +176 -0
- package/dist/chunk-EYDMJNNK.js.map +1 -0
- package/dist/chunk-FIF6GQ6U.js +141 -0
- package/dist/chunk-FIF6GQ6U.js.map +1 -0
- package/dist/chunk-GHXTJ2CF.js +109 -0
- package/dist/chunk-GHXTJ2CF.js.map +1 -0
- package/dist/chunk-H3ZBYNHV.js +153 -0
- package/dist/chunk-H3ZBYNHV.js.map +1 -0
- package/dist/chunk-HPBC3OG7.js +174 -0
- package/dist/chunk-HPBC3OG7.js.map +1 -0
- package/dist/chunk-IYT7VXFS.js +105 -0
- package/dist/chunk-IYT7VXFS.js.map +1 -0
- package/dist/chunk-LHYXNQWY.js +105 -0
- package/dist/chunk-LHYXNQWY.js.map +1 -0
- package/dist/chunk-LO2EW5YP.js +25 -0
- package/dist/chunk-LO2EW5YP.js.map +1 -0
- package/dist/chunk-LSQPUZK6.js +291 -0
- package/dist/chunk-LSQPUZK6.js.map +1 -0
- package/dist/chunk-N4Y5DI4X.js +82 -0
- package/dist/chunk-N4Y5DI4X.js.map +1 -0
- package/dist/chunk-NE6UHTOT.js +148 -0
- package/dist/chunk-NE6UHTOT.js.map +1 -0
- package/dist/chunk-NW47OJVN.js +138 -0
- package/dist/chunk-NW47OJVN.js.map +1 -0
- package/dist/chunk-O2YKCDR2.js +77 -0
- package/dist/chunk-O2YKCDR2.js.map +1 -0
- package/dist/chunk-PN6QKYE4.js +71 -0
- package/dist/chunk-PN6QKYE4.js.map +1 -0
- package/dist/chunk-RAOGZH3Z.js +188 -0
- package/dist/chunk-RAOGZH3Z.js.map +1 -0
- package/dist/chunk-RVSKX2RX.js +11 -0
- package/dist/chunk-RVSKX2RX.js.map +1 -0
- package/dist/chunk-RZVFA3N5.js +154 -0
- package/dist/chunk-RZVFA3N5.js.map +1 -0
- package/dist/chunk-SM7TASEW.js +135 -0
- package/dist/chunk-SM7TASEW.js.map +1 -0
- package/dist/chunk-U2PU4CWB.js +124 -0
- package/dist/chunk-U2PU4CWB.js.map +1 -0
- package/dist/chunk-UCEVCLQ7.js +5 -0
- package/dist/chunk-UCEVCLQ7.js.map +1 -0
- package/dist/chunk-UYSZOEOA.js +32 -0
- package/dist/chunk-UYSZOEOA.js.map +1 -0
- package/dist/chunk-V55K2CS5.js +126 -0
- package/dist/chunk-V55K2CS5.js.map +1 -0
- package/dist/chunk-VTQVGNVC.js +346 -0
- package/dist/chunk-VTQVGNVC.js.map +1 -0
- package/dist/chunk-W23P7SI4.js +239 -0
- package/dist/chunk-W23P7SI4.js.map +1 -0
- package/dist/chunk-W7D3STJH.js +279 -0
- package/dist/chunk-W7D3STJH.js.map +1 -0
- package/dist/chunk-WEEHXWM3.js +172 -0
- package/dist/chunk-WEEHXWM3.js.map +1 -0
- package/dist/chunk-WTEVTCIL.js +128 -0
- package/dist/chunk-WTEVTCIL.js.map +1 -0
- package/dist/chunk-XE6IWISA.js +137 -0
- package/dist/chunk-XE6IWISA.js.map +1 -0
- package/dist/elements/nymbal-add-to-cart.d.ts +14 -0
- package/dist/elements/nymbal-add-to-cart.js +10 -0
- package/dist/elements/nymbal-add-to-cart.js.map +1 -0
- package/dist/elements/nymbal-address-book.d.ts +30 -0
- package/dist/elements/nymbal-address-book.js +13 -0
- package/dist/elements/nymbal-address-book.js.map +1 -0
- package/dist/elements/nymbal-address-form.d.ts +29 -0
- package/dist/elements/nymbal-address-form.js +12 -0
- package/dist/elements/nymbal-address-form.js.map +1 -0
- package/dist/elements/nymbal-breadcrumb.d.ts +15 -0
- package/dist/elements/nymbal-breadcrumb.js +11 -0
- package/dist/elements/nymbal-breadcrumb.js.map +1 -0
- package/dist/elements/nymbal-cart-drawer.d.ts +24 -0
- package/dist/elements/nymbal-cart-drawer.js +11 -0
- package/dist/elements/nymbal-cart-drawer.js.map +1 -0
- package/dist/elements/nymbal-cart-page.d.ts +20 -0
- package/dist/elements/nymbal-cart-page.js +14 -0
- package/dist/elements/nymbal-cart-page.js.map +1 -0
- package/dist/elements/nymbal-category-nav.d.ts +15 -0
- package/dist/elements/nymbal-category-nav.js +11 -0
- package/dist/elements/nymbal-category-nav.js.map +1 -0
- package/dist/elements/nymbal-checkout.d.ts +77 -0
- package/dist/elements/nymbal-checkout.js +15 -0
- package/dist/elements/nymbal-checkout.js.map +1 -0
- package/dist/elements/nymbal-image-gallery.d.ts +19 -0
- package/dist/elements/nymbal-image-gallery.js +10 -0
- package/dist/elements/nymbal-image-gallery.js.map +1 -0
- package/dist/elements/nymbal-login-form.d.ts +17 -0
- package/dist/elements/nymbal-login-form.js +12 -0
- package/dist/elements/nymbal-login-form.js.map +1 -0
- package/dist/elements/nymbal-mini-cart.d.ts +17 -0
- package/dist/elements/nymbal-mini-cart.js +10 -0
- package/dist/elements/nymbal-mini-cart.js.map +1 -0
- package/dist/elements/nymbal-order-summary.d.ts +20 -0
- package/dist/elements/nymbal-order-summary.js +11 -0
- package/dist/elements/nymbal-order-summary.js.map +1 -0
- package/dist/elements/nymbal-payment-element.d.ts +4 -0
- package/dist/elements/nymbal-payment-element.js +10 -0
- package/dist/elements/nymbal-payment-element.js.map +1 -0
- package/dist/elements/nymbal-product-card.d.ts +4 -0
- package/dist/elements/nymbal-product-card.js +12 -0
- package/dist/elements/nymbal-product-card.js.map +1 -0
- package/dist/elements/nymbal-product-filter.d.ts +32 -0
- package/dist/elements/nymbal-product-filter.js +10 -0
- package/dist/elements/nymbal-product-filter.js.map +1 -0
- package/dist/elements/nymbal-product-grid.d.ts +24 -0
- package/dist/elements/nymbal-product-grid.js +14 -0
- package/dist/elements/nymbal-product-grid.js.map +1 -0
- package/dist/elements/nymbal-product-price.d.ts +18 -0
- package/dist/elements/nymbal-product-price.js +12 -0
- package/dist/elements/nymbal-product-price.js.map +1 -0
- package/dist/elements/nymbal-profile-form.d.ts +19 -0
- package/dist/elements/nymbal-profile-form.js +12 -0
- package/dist/elements/nymbal-profile-form.js.map +1 -0
- package/dist/elements/nymbal-quantity-selector.d.ts +20 -0
- package/dist/elements/nymbal-quantity-selector.js +10 -0
- package/dist/elements/nymbal-quantity-selector.js.map +1 -0
- package/dist/elements/nymbal-register-form.d.ts +17 -0
- package/dist/elements/nymbal-register-form.js +12 -0
- package/dist/elements/nymbal-register-form.js.map +1 -0
- package/dist/elements/nymbal-review-form.d.ts +17 -0
- package/dist/elements/nymbal-review-form.js +12 -0
- package/dist/elements/nymbal-review-form.js.map +1 -0
- package/dist/elements/nymbal-review-list.d.ts +14 -0
- package/dist/elements/nymbal-review-list.js +10 -0
- package/dist/elements/nymbal-review-list.js.map +1 -0
- package/dist/elements/nymbal-search-bar.d.ts +19 -0
- package/dist/elements/nymbal-search-bar.js +10 -0
- package/dist/elements/nymbal-search-bar.js.map +1 -0
- package/dist/elements/nymbal-search-results.d.ts +29 -0
- package/dist/elements/nymbal-search-results.js +14 -0
- package/dist/elements/nymbal-search-results.js.map +1 -0
- package/dist/elements/nymbal-site-footer.d.ts +15 -0
- package/dist/elements/nymbal-site-footer.js +11 -0
- package/dist/elements/nymbal-site-footer.js.map +1 -0
- package/dist/elements/nymbal-site-header.d.ts +19 -0
- package/dist/elements/nymbal-site-header.js +11 -0
- package/dist/elements/nymbal-site-header.js.map +1 -0
- package/dist/elements/nymbal-sort-dropdown.d.ts +28 -0
- package/dist/elements/nymbal-sort-dropdown.js +10 -0
- package/dist/elements/nymbal-sort-dropdown.js.map +1 -0
- package/dist/elements/nymbal-stock-badge.d.ts +16 -0
- package/dist/elements/nymbal-stock-badge.js +11 -0
- package/dist/elements/nymbal-stock-badge.js.map +1 -0
- package/dist/elements/nymbal-toast.d.ts +18 -0
- package/dist/elements/nymbal-toast.js +10 -0
- package/dist/elements/nymbal-toast.js.map +1 -0
- package/dist/elements/nymbal-variant-selector.d.ts +16 -0
- package/dist/elements/nymbal-variant-selector.js +10 -0
- package/dist/elements/nymbal-variant-selector.js.map +1 -0
- package/dist/form-element-C-qo3gpD.d.ts +25 -0
- package/dist/hydrate-support.d.ts +2 -0
- package/dist/hydrate-support.js +3 -0
- package/dist/hydrate-support.js.map +1 -0
- package/dist/index.d.ts +37 -105
- package/dist/index.js +130 -1098
- package/dist/index.js.map +1 -1
- package/dist/nymbal-payment-element-Bt8EF42T.d.ts +51 -0
- package/dist/nymbal-product-card-C8HkE_rG.d.ts +47 -0
- package/dist/register-components.d.ts +46 -0
- package/dist/register-components.js +48 -0
- package/dist/register-components.js.map +1 -0
- package/dist/selected-variant-Dym0shlJ.d.ts +23 -0
- package/dist/ssr/index.d.ts +30 -0
- package/dist/ssr/index.js +143 -0
- package/dist/ssr/index.js.map +1 -0
- package/package.json +33 -6
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/registry.ts","../src/base-element.ts","../src/styles.ts","../src/components/add-to-cart.ts","../src/components/cart-drawer.ts","../src/components/mini-cart.ts","../src/components/variant-selector.ts","../src/components/quantity-selector.ts","../src/components/search-bar.ts","../src/components/product-filter.ts","../src/components/toast.ts","../src/index.ts"],"sourcesContent":["import type { NymbalClient } from '@nymbalhq/sdk'\n\nconst CLIENT_KEY = Symbol.for('nymbal.client')\n\nexport function registerClient(client: NymbalClient): void {\n (globalThis as Record<symbol, unknown>)[CLIENT_KEY] = client\n}\n\nexport function getClient(): NymbalClient {\n const client = (globalThis as Record<symbol, unknown>)[CLIENT_KEY] as NymbalClient | undefined\n if (!client) {\n throw new Error('NymbalClient not registered. Call registerClient() before using components.')\n }\n return client\n}\n","import type { NymbalClient } from '@nymbalhq/sdk'\nimport { getClient } from './registry.js'\n\nconst HTMLElementBase =\n typeof HTMLElement !== 'undefined' ? HTMLElement : (class {} as unknown as typeof HTMLElement)\n\nexport abstract class NymbalElement extends HTMLElementBase {\n private _unsubs: Array<() => void> = []\n private _renderQueued = false\n\n protected get client(): NymbalClient {\n return getClient()\n }\n\n protected subscribeToStore(store: { subscribe(fn: () => void): () => void }): void {\n this._unsubs.push(store.subscribe(() => this.requestRender()))\n }\n\n protected requestRender(): void {\n if (this._renderQueued) return\n this._renderQueued = true\n queueMicrotask(() => {\n this._renderQueued = false\n this.render()\n })\n }\n\n connectedCallback(): void {\n this.setup()\n this.render()\n }\n\n disconnectedCallback(): void {\n for (const fn of this._unsubs) fn()\n this._unsubs = []\n }\n\n protected abstract setup(): void\n protected abstract render(): void\n}\n","const injected = new Set<string>()\n\nexport function injectStyles(tagName: string, css: string): void {\n if (injected.has(tagName)) return\n if (typeof document === 'undefined') return\n const style = document.createElement('style')\n style.setAttribute('data-nymbal', tagName)\n style.textContent = css\n document.head.appendChild(style)\n injected.add(tagName)\n}\n","import { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-add-to-cart {\n display: inline-block;\n}\nnymbal-add-to-cart button {\n font-family: var(--nymbal-font-family);\n font-size: var(--nymbal-font-size-base);\n font-weight: var(--nymbal-font-weight-medium);\n background: var(--nymbal-color-primary);\n color: var(--nymbal-color-text-inverse);\n border: none;\n border-radius: var(--nymbal-radius-md);\n padding: var(--nymbal-spacing-sm) var(--nymbal-spacing-lg);\n cursor: pointer;\n transition: background var(--nymbal-transition-fast);\n min-width: 140px;\n}\nnymbal-add-to-cart button:hover:not(:disabled) {\n background: var(--nymbal-color-primary-hover);\n}\nnymbal-add-to-cart button:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n`\n\nexport class NymbalAddToCart extends NymbalElement {\n static get observedAttributes(): string[] {\n return ['variant-id', 'disabled']\n }\n\n private button!: HTMLButtonElement\n\n protected setup(): void {\n injectStyles('nymbal-add-to-cart', STYLES)\n this.subscribeToStore(this.client.cart)\n }\n\n protected render(): void {\n const variantId = this.getAttribute('variant-id')\n const isDisabled = this.hasAttribute('disabled')\n const cartState = this.client.cart.getState()\n\n if (!this.button) {\n this.button = document.createElement('button')\n this.button.setAttribute('type', 'button')\n this.button.setAttribute('data-testid', 'add-to-cart')\n this.button.addEventListener('click', this.handleClick)\n this.innerHTML = ''\n this.appendChild(this.button)\n }\n\n this.button.disabled = isDisabled || cartState.loading || !variantId\n this.button.setAttribute('aria-busy', String(cartState.loading))\n this.button.textContent = cartState.loading ? 'Adding...' : 'Add to Cart'\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected) this.requestRender()\n }\n\n private handleClick = async (): Promise<void> => {\n const variantId = this.getAttribute('variant-id')\n if (!variantId) return\n try {\n await this.client.cart.addItem(variantId)\n this.dispatchEvent(\n new CustomEvent('nymbal:cart:item-added', {\n bubbles: true,\n composed: true,\n detail: { variantId },\n }),\n )\n } catch {\n // error is stored in cart state\n }\n }\n}\n","import { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-cart-drawer {\n display: block;\n}\nnymbal-cart-drawer .nymbal-drawer-overlay {\n position: fixed;\n inset: 0;\n background: var(--nymbal-color-overlay);\n z-index: var(--nymbal-z-drawer);\n opacity: 0;\n visibility: hidden;\n transition: opacity var(--nymbal-transition-normal), visibility var(--nymbal-transition-normal);\n}\nnymbal-cart-drawer[open] .nymbal-drawer-overlay {\n opacity: 1;\n visibility: visible;\n}\nnymbal-cart-drawer .nymbal-drawer-panel {\n position: fixed;\n top: 0;\n right: 0;\n bottom: 0;\n width: min(400px, 90vw);\n background: var(--nymbal-color-surface);\n z-index: var(--nymbal-z-drawer);\n transform: translateX(100%);\n transition: transform var(--nymbal-transition-normal);\n display: flex;\n flex-direction: column;\n font-family: var(--nymbal-font-family);\n}\nnymbal-cart-drawer[open] .nymbal-drawer-panel {\n transform: translateX(0);\n}\nnymbal-cart-drawer .nymbal-drawer-header {\n display: flex;\n justify-content: space-between;\n align-items: center;\n padding: var(--nymbal-spacing-md) var(--nymbal-spacing-lg);\n border-bottom: 1px solid var(--nymbal-color-border);\n}\nnymbal-cart-drawer .nymbal-drawer-header h2 {\n margin: 0;\n font-size: var(--nymbal-font-size-lg);\n font-weight: var(--nymbal-font-weight-bold);\n}\nnymbal-cart-drawer .nymbal-drawer-close {\n background: none;\n border: none;\n font-size: var(--nymbal-font-size-xl);\n cursor: pointer;\n padding: var(--nymbal-spacing-xs);\n color: var(--nymbal-color-text-muted);\n}\nnymbal-cart-drawer .nymbal-drawer-items {\n flex: 1;\n overflow-y: auto;\n padding: var(--nymbal-spacing-md) var(--nymbal-spacing-lg);\n}\nnymbal-cart-drawer .nymbal-cart-item {\n display: flex;\n gap: var(--nymbal-spacing-md);\n padding: var(--nymbal-spacing-md) 0;\n border-bottom: 1px solid var(--nymbal-color-border);\n}\nnymbal-cart-drawer .nymbal-cart-item-info {\n flex: 1;\n}\nnymbal-cart-drawer .nymbal-cart-item-name {\n font-weight: var(--nymbal-font-weight-medium);\n margin-bottom: var(--nymbal-spacing-xs);\n}\nnymbal-cart-drawer .nymbal-cart-item-variant {\n font-size: var(--nymbal-font-size-sm);\n color: var(--nymbal-color-text-muted);\n}\nnymbal-cart-drawer .nymbal-cart-item-actions {\n display: flex;\n align-items: center;\n gap: var(--nymbal-spacing-sm);\n}\nnymbal-cart-drawer .nymbal-cart-item-remove {\n background: none;\n border: none;\n color: var(--nymbal-color-error);\n cursor: pointer;\n font-size: var(--nymbal-font-size-sm);\n padding: var(--nymbal-spacing-xs);\n}\nnymbal-cart-drawer .nymbal-drawer-footer {\n padding: var(--nymbal-spacing-md) var(--nymbal-spacing-lg);\n border-top: 1px solid var(--nymbal-color-border);\n}\nnymbal-cart-drawer .nymbal-cart-subtotal {\n display: flex;\n justify-content: space-between;\n font-weight: var(--nymbal-font-weight-bold);\n margin-bottom: var(--nymbal-spacing-md);\n}\nnymbal-cart-drawer .nymbal-checkout-btn {\n width: 100%;\n font-family: var(--nymbal-font-family);\n font-size: var(--nymbal-font-size-base);\n font-weight: var(--nymbal-font-weight-medium);\n background: var(--nymbal-color-primary);\n color: var(--nymbal-color-text-inverse);\n border: none;\n border-radius: var(--nymbal-radius-md);\n padding: var(--nymbal-spacing-sm) var(--nymbal-spacing-lg);\n cursor: pointer;\n transition: background var(--nymbal-transition-fast);\n}\nnymbal-cart-drawer .nymbal-checkout-btn:hover {\n background: var(--nymbal-color-primary-hover);\n}\nnymbal-cart-drawer .nymbal-drawer-empty {\n text-align: center;\n color: var(--nymbal-color-text-muted);\n padding: var(--nymbal-spacing-xl) 0;\n}\n`\n\nexport class NymbalCartDrawer extends NymbalElement {\n static get observedAttributes(): string[] {\n return ['open']\n }\n\n private readonly handleItemAdded = (): void => {\n this.open()\n }\n\n private readonly handleMiniCartClicked = (): void => {\n this.toggle()\n }\n\n protected setup(): void {\n injectStyles('nymbal-cart-drawer', STYLES)\n this.subscribeToStore(this.client.cart)\n document.addEventListener('nymbal:cart:item-added', this.handleItemAdded)\n document.addEventListener('nymbal:mini-cart:clicked', this.handleMiniCartClicked)\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n document.removeEventListener('nymbal:cart:item-added', this.handleItemAdded)\n document.removeEventListener('nymbal:mini-cart:clicked', this.handleMiniCartClicked)\n }\n\n open(): void {\n this.setAttribute('open', '')\n window.dispatchEvent(new CustomEvent('nymbal:cart:open'))\n }\n\n close(): void {\n this.removeAttribute('open')\n window.dispatchEvent(new CustomEvent('nymbal:cart:close'))\n }\n\n toggle(): void {\n if (this.hasAttribute('open')) {\n this.close()\n } else {\n this.open()\n }\n }\n\n protected render(): void {\n const state = this.client.cart.getState()\n const currency = state.currency\n\n const itemsHtml = state.items.length === 0\n ? `<div class=\"nymbal-drawer-empty\">Your cart is empty</div>`\n : state.items.map((item) => `\n <div class=\"nymbal-cart-item\" data-testid=\"cart-item-${item.variantId}\">\n <div class=\"nymbal-cart-item-info\">\n <div class=\"nymbal-cart-item-name\">${this.esc(item.productName)}</div>\n <div class=\"nymbal-cart-item-variant\">${this.esc(item.variantName)}</div>\n <div class=\"nymbal-cart-item-qty\">Qty: ${item.qty}</div>\n </div>\n <div class=\"nymbal-cart-item-actions\">\n <span>${this.formatPrice(item.priceMinor * item.qty, currency)}</span>\n <button type=\"button\" class=\"nymbal-cart-item-remove\" data-testid=\"remove-item-${item.variantId}\" data-variant-id=\"${item.variantId}\">Remove</button>\n </div>\n </div>\n `).join('')\n\n this.innerHTML = `\n <div class=\"nymbal-drawer-overlay\" data-testid=\"cart-drawer-overlay\"></div>\n <div class=\"nymbal-drawer-panel\" role=\"dialog\" aria-label=\"Shopping cart\" aria-modal=\"true\" data-testid=\"cart-drawer\">\n <div class=\"nymbal-drawer-header\">\n <h2>Cart (${state.itemCount})</h2>\n <button type=\"button\" class=\"nymbal-drawer-close\" data-testid=\"cart-drawer-close\" aria-label=\"Close cart\">×</button>\n </div>\n <div class=\"nymbal-drawer-items\">${itemsHtml}</div>\n ${state.items.length > 0 ? `\n <div class=\"nymbal-drawer-footer\">\n <div class=\"nymbal-cart-subtotal\">\n <span>Subtotal</span>\n <span>${this.formatPrice(state.subtotalMinor, currency)}</span>\n </div>\n <button type=\"button\" class=\"nymbal-checkout-btn\" data-testid=\"cart-checkout-btn\">Checkout</button>\n </div>\n ` : ''}\n </div>\n `\n\n this.querySelector('.nymbal-drawer-overlay')?.addEventListener('click', () => this.close())\n this.querySelector('.nymbal-drawer-close')?.addEventListener('click', () => this.close())\n this.querySelector('.nymbal-checkout-btn')?.addEventListener('click', () => {\n this.dispatchEvent(new CustomEvent('nymbal:cart:checkout-clicked', { bubbles: true, composed: true }))\n })\n this.querySelectorAll('.nymbal-cart-item-remove').forEach((btn) => {\n btn.addEventListener('click', () => {\n const variantId = (btn as HTMLElement).dataset['variantId']\n if (variantId) this.client.cart.removeItem(variantId)\n })\n })\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected) this.requestRender()\n }\n\n private esc(str: string): string {\n const div = document.createElement('div')\n div.textContent = str\n return div.innerHTML\n }\n\n private formatPrice(minor: number, currency: string): string {\n return new Intl.NumberFormat(undefined, {\n style: 'currency',\n currency,\n }).format(minor / 100)\n }\n}\n","import { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-mini-cart {\n display: inline-block;\n position: relative;\n}\nnymbal-mini-cart button {\n background: none;\n border: none;\n cursor: pointer;\n position: relative;\n padding: var(--nymbal-spacing-sm);\n font-family: var(--nymbal-font-family);\n color: var(--nymbal-color-text);\n}\nnymbal-mini-cart .nymbal-mini-cart-icon {\n width: 24px;\n height: 24px;\n}\nnymbal-mini-cart .nymbal-mini-cart-badge {\n position: absolute;\n top: 0;\n right: 0;\n background: var(--nymbal-color-accent);\n color: var(--nymbal-color-text-inverse);\n font-size: var(--nymbal-font-size-xs);\n font-weight: var(--nymbal-font-weight-bold);\n min-width: 18px;\n height: 18px;\n border-radius: var(--nymbal-radius-full);\n display: flex;\n align-items: center;\n justify-content: center;\n line-height: 1;\n}\nnymbal-mini-cart .nymbal-mini-cart-badge:empty {\n display: none;\n}\n`\n\nconst CART_SVG = `<svg class=\"nymbal-mini-cart-icon\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><circle cx=\"9\" cy=\"21\" r=\"1\"/><circle cx=\"20\" cy=\"21\" r=\"1\"/><path d=\"M1 1h4l2.68 13.39a2 2 0 0 0 2 1.61h9.72a2 2 0 0 0 2-1.61L23 6H6\"/></svg>`\n\nexport class NymbalMiniCart extends NymbalElement {\n protected setup(): void {\n injectStyles('nymbal-mini-cart', STYLES)\n this.subscribeToStore(this.client.cart)\n }\n\n protected render(): void {\n const { itemCount } = this.client.cart.getState()\n\n this.innerHTML = `\n <button type=\"button\" data-testid=\"mini-cart\" aria-label=\"Cart (${itemCount} items)\">\n ${CART_SVG}\n <span class=\"nymbal-mini-cart-badge\" data-testid=\"mini-cart-badge\">${itemCount > 0 ? itemCount : ''}</span>\n </button>\n `\n\n this.querySelector('button')?.addEventListener('click', () => {\n this.dispatchEvent(new CustomEvent('nymbal:mini-cart:clicked', { bubbles: true, composed: true }))\n })\n }\n}\n","import type { DenormalisedVariant, DenormalisedProduct } from '@nymbalhq/sdk'\nimport type { VariantOption } from '@nymbalhq/types'\nimport { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-variant-selector {\n display: block;\n font-family: var(--nymbal-font-family);\n}\nnymbal-variant-selector .nymbal-option-group {\n margin-bottom: var(--nymbal-spacing-md);\n}\nnymbal-variant-selector .nymbal-option-label {\n display: block;\n font-size: var(--nymbal-font-size-sm);\n font-weight: var(--nymbal-font-weight-medium);\n margin-bottom: var(--nymbal-spacing-sm);\n color: var(--nymbal-color-text);\n}\nnymbal-variant-selector .nymbal-option-buttons {\n display: flex;\n flex-wrap: wrap;\n gap: var(--nymbal-spacing-sm);\n}\nnymbal-variant-selector .nymbal-option-btn {\n font-family: var(--nymbal-font-family);\n font-size: var(--nymbal-font-size-sm);\n background: var(--nymbal-color-surface);\n color: var(--nymbal-color-text);\n border: 1px solid var(--nymbal-color-border);\n border-radius: var(--nymbal-radius-md);\n padding: var(--nymbal-spacing-xs) var(--nymbal-spacing-md);\n cursor: pointer;\n transition: border-color var(--nymbal-transition-fast), background var(--nymbal-transition-fast);\n}\nnymbal-variant-selector .nymbal-option-btn:hover {\n border-color: var(--nymbal-color-primary);\n}\nnymbal-variant-selector .nymbal-option-btn[aria-pressed=\"true\"] {\n background: var(--nymbal-color-primary);\n color: var(--nymbal-color-text-inverse);\n border-color: var(--nymbal-color-primary);\n}\nnymbal-variant-selector .nymbal-option-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n`\n\ninterface OptionGroup {\n name: string\n values: string[]\n}\n\nexport class NymbalVariantSelector extends NymbalElement {\n static get observedAttributes(): string[] {\n return ['options']\n }\n\n protected setup(): void {\n injectStyles('nymbal-variant-selector', STYLES)\n this.subscribeToStore(this.client.product)\n }\n\n protected render(): void {\n const state = this.client.product.getState()\n const product = state.product\n if (!product) {\n this.innerHTML = ''\n return\n }\n\n const optionGroups = this.getOptionGroups(product)\n const selected = state.selectedVariant\n\n this.innerHTML = optionGroups.map((group) => `\n <div class=\"nymbal-option-group\">\n <span class=\"nymbal-option-label\">${this.esc(group.name)}</span>\n <div class=\"nymbal-option-buttons\">\n ${group.values.map((value) => {\n const isSelected = selected?.options.some(\n (o: VariantOption) => o.name === group.name && o.value === value,\n ) ?? false\n return `<button\n class=\"nymbal-option-btn\"\n data-testid=\"variant-option-${this.esc(group.name)}-${this.esc(value)}\"\n data-option-name=\"${this.esc(group.name)}\"\n data-option-value=\"${this.esc(value)}\"\n aria-pressed=\"${isSelected}\"\n >${this.esc(value)}</button>`\n }).join('')}\n </div>\n </div>\n `).join('')\n\n this.querySelectorAll('.nymbal-option-btn').forEach((btn) => {\n btn.addEventListener('click', () => {\n const el = btn as HTMLElement\n const optionName = el.dataset['optionName']\n const optionValue = el.dataset['optionValue']\n if (!optionName || !optionValue || !product) return\n\n const currentSelections = new Map<string, string>()\n if (selected) {\n for (const opt of selected.options as VariantOption[]) {\n currentSelections.set(opt.name, opt.value)\n }\n }\n currentSelections.set(optionName, optionValue)\n\n const match = product.variants.find((v: DenormalisedVariant) => {\n const vRaw = v.options\n let vOpts: VariantOption[] = []\n if (typeof vRaw === 'string') {\n try { vOpts = JSON.parse(vRaw) } catch (e) { console.warn('[variant-selector] malformed variant options JSON', e); vOpts = [] }\n } else if (Array.isArray(vRaw)) {\n vOpts = vRaw\n }\n return vOpts.every((o) => currentSelections.get(o.name) === o.value)\n })\n\n if (match) {\n this.client.product.selectVariant(match)\n this.dispatchEvent(\n new CustomEvent('nymbal:variant:selected', {\n bubbles: true,\n composed: true,\n detail: { variant: match },\n }),\n )\n }\n })\n })\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected) this.requestRender()\n }\n\n private getOptionGroups(product: DenormalisedProduct): OptionGroup[] {\n const optionsAttr = this.getAttribute('options')\n if (optionsAttr) {\n try {\n return JSON.parse(optionsAttr) as OptionGroup[]\n } catch (e) {\n console.warn('[variant-selector] malformed options attribute, falling back to variant derivation', e)\n }\n }\n\n const groups = new Map<string, Set<string>>()\n for (const variant of product.variants) {\n const raw = variant.options\n let opts: VariantOption[] = []\n if (typeof raw === 'string') {\n try { opts = JSON.parse(raw) } catch (e) { console.warn('[variant-selector] malformed variant options in getOptionGroups', e); opts = [] }\n } else if (Array.isArray(raw)) {\n opts = raw\n }\n for (const opt of opts) {\n let values = groups.get(opt.name)\n if (!values) {\n values = new Set()\n groups.set(opt.name, values)\n }\n values.add(opt.value)\n }\n }\n return Array.from(groups.entries()).map(([name, values]) => ({\n name,\n values: Array.from(values),\n }))\n }\n\n private esc(str: string): string {\n const div = document.createElement('div')\n div.textContent = str\n return div.innerHTML\n }\n}\n","import { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-quantity-selector {\n display: inline-flex;\n align-items: center;\n font-family: var(--nymbal-font-family);\n}\nnymbal-quantity-selector button {\n font-family: var(--nymbal-font-family);\n font-size: var(--nymbal-font-size-base);\n background: var(--nymbal-color-surface);\n color: var(--nymbal-color-text);\n border: 1px solid var(--nymbal-color-border);\n width: 36px;\n height: 36px;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n transition: background var(--nymbal-transition-fast);\n}\nnymbal-quantity-selector button:hover:not(:disabled) {\n background: var(--nymbal-color-secondary, #f4f4f5);\n}\nnymbal-quantity-selector button:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\nnymbal-quantity-selector button:first-child {\n border-radius: var(--nymbal-radius-md) 0 0 var(--nymbal-radius-md);\n}\nnymbal-quantity-selector button:last-child {\n border-radius: 0 var(--nymbal-radius-md) var(--nymbal-radius-md) 0;\n}\nnymbal-quantity-selector input {\n font-family: var(--nymbal-font-family);\n font-size: var(--nymbal-font-size-base);\n width: 48px;\n height: 36px;\n text-align: center;\n border: 1px solid var(--nymbal-color-border);\n border-left: none;\n border-right: none;\n -moz-appearance: textfield;\n}\nnymbal-quantity-selector input::-webkit-outer-spin-button,\nnymbal-quantity-selector input::-webkit-inner-spin-button {\n -webkit-appearance: none;\n margin: 0;\n}\n`\n\nexport class NymbalQuantitySelector extends NymbalElement {\n static get observedAttributes(): string[] {\n return ['value', 'min', 'max']\n }\n\n private _value = 1\n\n protected setup(): void {\n injectStyles('nymbal-quantity-selector', STYLES)\n this._value = Number(this.getAttribute('value')) || 1\n }\n\n protected render(): void {\n const min = Number(this.getAttribute('min')) || 1\n const max = Number(this.getAttribute('max')) || 99\n\n this.innerHTML = `\n <button data-testid=\"qty-decrement\" aria-label=\"Decrease quantity\" ${this._value <= min ? 'disabled' : ''}>−</button>\n <input data-testid=\"qty-input\" type=\"number\" value=\"${this._value}\" min=\"${min}\" max=\"${max}\" aria-label=\"Quantity\">\n <button data-testid=\"qty-increment\" aria-label=\"Increase quantity\" ${this._value >= max ? 'disabled' : ''}>+</button>\n `\n\n this.querySelector('[data-testid=\"qty-decrement\"]')?.addEventListener('click', () => {\n if (this._value > min) {\n this._value--\n this.emitChange()\n this.render()\n }\n })\n\n this.querySelector('[data-testid=\"qty-increment\"]')?.addEventListener('click', () => {\n if (this._value < max) {\n this._value++\n this.emitChange()\n this.render()\n }\n })\n\n const input = this.querySelector('input')\n input?.addEventListener('change', () => {\n const val = Math.min(max, Math.max(min, Number(input.value) || min))\n this._value = val\n this.emitChange()\n this.render()\n })\n }\n\n attributeChangedCallback(name: string): void {\n if (name === 'value') {\n this._value = Number(this.getAttribute('value')) || 1\n }\n if (this.isConnected) this.requestRender()\n }\n\n private emitChange(): void {\n this.dispatchEvent(\n new CustomEvent('nymbal:quantity:changed', {\n bubbles: true,\n composed: true,\n detail: { value: this._value },\n }),\n )\n }\n}\n","import { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\nimport type { DenormalisedProduct } from '@nymbalhq/sdk'\n\nconst STYLES = `\nnymbal-search-bar {\n display: block;\n position: relative;\n font-family: var(--nymbal-font-family);\n}\nnymbal-search-bar input {\n font-family: var(--nymbal-font-family);\n font-size: var(--nymbal-font-size-base);\n width: 100%;\n padding: var(--nymbal-spacing-sm) var(--nymbal-spacing-md);\n border: 1px solid var(--nymbal-color-border);\n border-radius: var(--nymbal-radius-md);\n outline: none;\n transition: border-color var(--nymbal-transition-fast);\n box-sizing: border-box;\n}\nnymbal-search-bar input:focus {\n border-color: var(--nymbal-color-accent);\n}\nnymbal-search-bar .nymbal-search-results {\n position: absolute;\n top: 100%;\n left: 0;\n right: 0;\n background: var(--nymbal-color-surface);\n border: 1px solid var(--nymbal-color-border);\n border-top: none;\n border-radius: 0 0 var(--nymbal-radius-md) var(--nymbal-radius-md);\n box-shadow: var(--nymbal-shadow-md);\n z-index: var(--nymbal-z-dropdown);\n max-height: 300px;\n overflow-y: auto;\n}\nnymbal-search-bar .nymbal-search-result-item {\n padding: var(--nymbal-spacing-sm) var(--nymbal-spacing-md);\n cursor: pointer;\n transition: background var(--nymbal-transition-fast);\n}\nnymbal-search-bar .nymbal-search-result-item:hover,\nnymbal-search-bar .nymbal-search-result-item[aria-selected=\"true\"] {\n background: var(--nymbal-color-secondary, #f4f4f5);\n}\nnymbal-search-bar .nymbal-search-result-name {\n font-weight: var(--nymbal-font-weight-medium);\n}\nnymbal-search-bar .nymbal-search-result-price {\n font-size: var(--nymbal-font-size-sm);\n color: var(--nymbal-color-text-muted);\n}\nnymbal-search-bar .nymbal-search-loading {\n padding: var(--nymbal-spacing-md);\n text-align: center;\n color: var(--nymbal-color-text-muted);\n font-size: var(--nymbal-font-size-sm);\n}\n`\n\nexport class NymbalSearchBar extends NymbalElement {\n static get observedAttributes(): string[] {\n return ['placeholder', 'debounce-ms']\n }\n\n private debounceTimer: ReturnType<typeof setTimeout> | null = null\n private selectedIndex = -1\n\n protected setup(): void {\n injectStyles('nymbal-search-bar', STYLES)\n this.subscribeToStore(this.client.search)\n }\n\n protected render(): void {\n const state = this.client.search.getState()\n const placeholder = this.getAttribute('placeholder') ?? 'Search products...'\n\n let resultsHtml = ''\n if (state.query) {\n if (state.loading) {\n resultsHtml = `<div class=\"nymbal-search-results\" data-testid=\"search-results\"><div class=\"nymbal-search-loading\">Searching...</div></div>`\n } else if (state.results.length > 0) {\n resultsHtml = `<div class=\"nymbal-search-results\" data-testid=\"search-results\">\n ${state.results\n .map(\n (product, i) => `\n <div class=\"nymbal-search-result-item\" data-testid=\"search-result-${this.esc(product.slug)}\" data-slug=\"${this.esc(product.slug)}\" aria-selected=\"${i === this.selectedIndex}\">\n <div class=\"nymbal-search-result-name\">${this.esc(product.name)}</div>\n ${product.priceMinor !== null ? `<div class=\"nymbal-search-result-price\">${this.formatPrice(product.priceMinor, product.currency ?? 'USD')}</div>` : ''}\n </div>\n `,\n )\n .join('')}\n </div>`\n }\n }\n\n this.innerHTML = `\n <input data-testid=\"search-input\" type=\"search\" placeholder=\"${this.esc(placeholder)}\" value=\"${this.esc(state.query)}\" autocomplete=\"off\" role=\"combobox\" aria-expanded=\"${state.results.length > 0}\" aria-haspopup=\"listbox\">\n ${resultsHtml}\n `\n\n this.querySelectorAll<HTMLElement>('.nymbal-search-result-item').forEach((item, i) => {\n item.addEventListener('click', () => {\n const product = state.results[i]\n if (product) this.select(product)\n })\n })\n\n const input = this.querySelector('input')!\n input.addEventListener('input', () => {\n const query = input.value\n const debounceMs = Number(this.getAttribute('debounce-ms')) || 300\n if (this.debounceTimer !== null) clearTimeout(this.debounceTimer)\n this.debounceTimer = setTimeout(() => {\n this.selectedIndex = -1\n if (query.trim()) {\n this.client.search.search(query)\n } else {\n this.client.search.clearSearch()\n }\n }, debounceMs)\n })\n\n input.addEventListener('keydown', (e) => {\n const results = state.results\n if (e.key === 'ArrowDown') {\n e.preventDefault()\n this.selectedIndex = Math.min(this.selectedIndex + 1, results.length - 1)\n this.render()\n } else if (e.key === 'ArrowUp') {\n e.preventDefault()\n this.selectedIndex = Math.max(this.selectedIndex - 1, -1)\n this.render()\n } else if (e.key === 'Enter') {\n e.preventDefault()\n const selected = this.selectedIndex >= 0 ? results[this.selectedIndex] : undefined\n if (selected) {\n this.select(selected)\n } else {\n const query = input.value.trim()\n if (query) {\n window.location.href = `/search?q=${encodeURIComponent(query)}`\n }\n }\n } else if (e.key === 'Escape') {\n this.client.search.clearSearch()\n this.selectedIndex = -1\n }\n })\n }\n\n private select(product: DenormalisedProduct): void {\n this.dispatchEvent(\n new CustomEvent('nymbal:search:selected', {\n bubbles: true,\n composed: true,\n detail: { product, query: product.name },\n }),\n )\n this.client.search.clearSearch()\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected) this.requestRender()\n }\n\n override disconnectedCallback(): void {\n super.disconnectedCallback()\n if (this.debounceTimer !== null) {\n clearTimeout(this.debounceTimer)\n this.debounceTimer = null\n }\n }\n\n /** Escapes a value for both text and quoted-attribute contexts. */\n private esc(str: string): string {\n return str\n .replace(/&/g, '&')\n .replace(/</g, '<')\n .replace(/>/g, '>')\n .replace(/\"/g, '"')\n .replace(/'/g, ''')\n }\n\n private formatPrice(minor: number, currency: string): string {\n return new Intl.NumberFormat(undefined, { style: 'currency', currency }).format(minor / 100)\n }\n}\n","import type { Facet } from '@nymbalhq/types'\nimport { NymbalElement } from '../base-element.js'\nimport { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-product-filter {\n display: block;\n font-family: var(--nymbal-font-family);\n}\nnymbal-product-filter .nymbal-filter-group {\n margin-bottom: var(--nymbal-spacing-lg);\n}\nnymbal-product-filter .nymbal-filter-label {\n display: block;\n font-size: var(--nymbal-font-size-sm);\n font-weight: var(--nymbal-font-weight-bold);\n margin-bottom: var(--nymbal-spacing-sm);\n color: var(--nymbal-color-text);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n}\nnymbal-product-filter .nymbal-filter-option {\n display: flex;\n align-items: center;\n gap: var(--nymbal-spacing-sm);\n padding: var(--nymbal-spacing-xs) 0;\n cursor: pointer;\n font-size: var(--nymbal-font-size-sm);\n color: var(--nymbal-color-text);\n}\nnymbal-product-filter .nymbal-filter-option input[type=\"checkbox\"] {\n accent-color: var(--nymbal-color-primary);\n}\nnymbal-product-filter .nymbal-filter-count {\n color: var(--nymbal-color-text-muted);\n font-size: var(--nymbal-font-size-xs);\n}\n`\n\n\nexport class NymbalProductFilter extends NymbalElement {\n static get observedAttributes(): string[] {\n return ['facets']\n }\n\n protected setup(): void {\n injectStyles('nymbal-product-filter', STYLES)\n this.subscribeToStore(this.client.productList)\n }\n\n protected render(): void {\n const state = this.client.productList.getState()\n const facets = this.getFacets()\n\n if (facets.length === 0) {\n this.innerHTML = ''\n return\n }\n\n this.innerHTML = facets.map((facet) => {\n const activeFilter = state.filters[facet.field]\n const activeValues = Array.isArray(activeFilter)\n ? activeFilter\n : (activeFilter ? [activeFilter] : [])\n\n return `\n <div class=\"nymbal-filter-group\" data-testid=\"filter-group-${facet.field}\">\n <span class=\"nymbal-filter-label\">${this.esc(facet.label)}</span>\n ${facet.values.map((v) => {\n const checked = activeValues.includes(v.value)\n return `\n <label class=\"nymbal-filter-option\" data-testid=\"filter-option-${v.value}\">\n <input type=\"checkbox\" data-filter-name=\"${facet.field}\" data-filter-value=\"${v.value}\" ${checked ? 'checked' : ''}>\n <span>${this.esc(v.label ?? v.value)}</span>\n ${v.count !== undefined ? `<span class=\"nymbal-filter-count\">(${v.count})</span>` : ''}\n </label>\n `\n }).join('')}\n </div>\n `\n }).join('')\n\n this.querySelectorAll('input[type=\"checkbox\"]').forEach((input) => {\n input.addEventListener('change', () => {\n const el = input as HTMLInputElement\n const name = el.dataset['filterName']!\n const value = el.dataset['filterValue']!\n if (el.checked) {\n const current = state.filters[name]\n const values = Array.isArray(current) ? [...current, value] : (current ? [current, value] : value)\n this.client.productList.applyFilter(name, values)\n } else {\n const current = state.filters[name]\n if (Array.isArray(current)) {\n const remaining = current.filter((v) => v !== value)\n if (remaining.length > 0) {\n this.client.productList.applyFilter(name, remaining)\n } else {\n this.client.productList.removeFilter(name)\n }\n } else {\n this.client.productList.removeFilter(name)\n }\n }\n this.dispatchEvent(\n new CustomEvent('nymbal:filter:changed', { bubbles: true, composed: true, detail: { name, value } }),\n )\n })\n })\n }\n\n attributeChangedCallback(): void {\n if (this.isConnected) this.requestRender()\n }\n\n private getFacets(): Facet[] {\n const attr = this.getAttribute('facets')\n if (!attr) return []\n try {\n return JSON.parse(attr) as Facet[]\n } catch (err) {\n console.error('[nymbal-product-filter] failed to parse facets attribute', err)\n return []\n }\n }\n\n private esc(str: string): string {\n const div = document.createElement('div')\n div.textContent = str\n return div.innerHTML\n }\n}\n","import { injectStyles } from '../styles.js'\n\nconst STYLES = `\nnymbal-toast {\n position: fixed;\n z-index: var(--nymbal-z-toast);\n display: flex;\n flex-direction: column;\n gap: var(--nymbal-spacing-sm);\n pointer-events: none;\n font-family: var(--nymbal-font-family);\n}\nnymbal-toast[position=\"top-right\"],\nnymbal-toast:not([position]) {\n top: var(--nymbal-spacing-lg);\n right: var(--nymbal-spacing-lg);\n}\nnymbal-toast[position=\"top-left\"] {\n top: var(--nymbal-spacing-lg);\n left: var(--nymbal-spacing-lg);\n}\nnymbal-toast[position=\"bottom-right\"] {\n bottom: var(--nymbal-spacing-lg);\n right: var(--nymbal-spacing-lg);\n}\nnymbal-toast[position=\"bottom-left\"] {\n bottom: var(--nymbal-spacing-lg);\n left: var(--nymbal-spacing-lg);\n}\nnymbal-toast .nymbal-toast-item {\n pointer-events: auto;\n display: flex;\n align-items: center;\n gap: var(--nymbal-spacing-sm);\n padding: var(--nymbal-spacing-sm) var(--nymbal-spacing-md);\n border-radius: var(--nymbal-radius-md);\n box-shadow: var(--nymbal-shadow-lg);\n font-size: var(--nymbal-font-size-sm);\n background: var(--nymbal-color-surface);\n color: var(--nymbal-color-text);\n border: 1px solid var(--nymbal-color-border);\n animation: nymbal-toast-in var(--nymbal-transition-normal) forwards;\n max-width: 360px;\n}\nnymbal-toast .nymbal-toast-item[data-type=\"success\"] {\n border-left: 3px solid var(--nymbal-color-success);\n}\nnymbal-toast .nymbal-toast-item[data-type=\"error\"] {\n border-left: 3px solid var(--nymbal-color-error);\n}\nnymbal-toast .nymbal-toast-item[data-type=\"warning\"] {\n border-left: 3px solid var(--nymbal-color-warning);\n}\nnymbal-toast .nymbal-toast-item[data-type=\"info\"] {\n border-left: 3px solid var(--nymbal-color-accent);\n}\nnymbal-toast .nymbal-toast-close {\n background: none;\n border: none;\n cursor: pointer;\n color: var(--nymbal-color-text-muted);\n font-size: var(--nymbal-font-size-base);\n padding: 0;\n margin-left: auto;\n}\n@keyframes nymbal-toast-in {\n from { opacity: 0; transform: translateY(-8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n`\n\nconst HTMLElementBase =\n typeof HTMLElement !== 'undefined' ? HTMLElement : (class {} as unknown as typeof HTMLElement)\n\nexport class NymbalToast extends HTMLElementBase {\n static get observedAttributes(): string[] {\n return ['position', 'duration-ms']\n }\n\n connectedCallback(): void {\n injectStyles('nymbal-toast', STYLES)\n this.setAttribute('data-testid', 'toast')\n }\n\n show(message: string, type: 'success' | 'error' | 'warning' | 'info' = 'info'): void {\n const durationMs = Number(this.getAttribute('duration-ms')) || 4000\n\n const item = document.createElement('div')\n item.className = 'nymbal-toast-item'\n item.setAttribute('data-type', type)\n item.setAttribute('role', 'alert')\n\n const text = document.createElement('span')\n text.textContent = message\n\n const close = document.createElement('button')\n close.className = 'nymbal-toast-close'\n close.setAttribute('aria-label', 'Dismiss')\n close.textContent = '×'\n close.addEventListener('click', () => this.dismiss(item))\n\n item.appendChild(text)\n item.appendChild(close)\n this.appendChild(item)\n\n setTimeout(() => this.dismiss(item), durationMs)\n }\n\n private dismiss(item: HTMLElement): void {\n if (item.parentNode === this) {\n this.removeChild(item)\n }\n }\n\n static showGlobal(message: string, type: 'success' | 'error' | 'warning' | 'info' = 'info'): void {\n let toastEl = document.querySelector('nymbal-toast') as NymbalToast | null\n if (!toastEl) {\n toastEl = document.createElement('nymbal-toast') as NymbalToast\n document.body.appendChild(toastEl)\n }\n toastEl.show(message, type)\n }\n}\n","export { registerClient, getClient } from './registry.js'\nexport { NymbalElement } from './base-element.js'\nexport { injectStyles } from './styles.js'\n\nimport { NymbalAddToCart } from './components/add-to-cart.js'\nimport { NymbalCartDrawer } from './components/cart-drawer.js'\nimport { NymbalMiniCart } from './components/mini-cart.js'\nimport { NymbalVariantSelector } from './components/variant-selector.js'\nimport { NymbalQuantitySelector } from './components/quantity-selector.js'\nimport { NymbalSearchBar } from './components/search-bar.js'\nimport { NymbalProductFilter } from './components/product-filter.js'\nimport { NymbalToast } from './components/toast.js'\n\nexport {\n NymbalAddToCart,\n NymbalCartDrawer,\n NymbalMiniCart,\n NymbalVariantSelector,\n NymbalQuantitySelector,\n NymbalSearchBar,\n NymbalProductFilter,\n NymbalToast,\n}\n\nexport function registerComponents(): void {\n const components: Array<[string, CustomElementConstructor]> = [\n ['nymbal-add-to-cart', NymbalAddToCart],\n ['nymbal-cart-drawer', NymbalCartDrawer],\n ['nymbal-mini-cart', NymbalMiniCart],\n ['nymbal-variant-selector', NymbalVariantSelector],\n ['nymbal-quantity-selector', NymbalQuantitySelector],\n ['nymbal-search-bar', NymbalSearchBar],\n ['nymbal-product-filter', NymbalProductFilter],\n ['nymbal-toast', NymbalToast],\n ]\n\n for (const [name, ctor] of components) {\n if (!customElements.get(name)) {\n customElements.define(name, ctor)\n }\n }\n}\n"],"mappings":"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","names":["STYLES","STYLES","STYLES","STYLES","STYLES","STYLES","STYLES","HTMLElementBase"]}
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import * as lit from 'lit';
|
|
2
|
+
import { CSSResult } from 'lit';
|
|
3
|
+
import { PaymentConfirmContext, PaymentConfirmation } from '@nymbalhq/sdk';
|
|
4
|
+
import { N as NymbalElement, a as ElementSchema } from './base-element-CPMgAdyQ.js';
|
|
5
|
+
|
|
6
|
+
/** `pending` while a driver mounts; `error` when no payment can be taken, which a checkout must not submit past. */
|
|
7
|
+
type PaymentElementStatus = 'pending' | 'ready' | 'error';
|
|
8
|
+
/**
|
|
9
|
+
* <nymbal-payment-element client='<json>'>: renders the payments adapter's client half (GET /api/capabilities'
|
|
10
|
+
* `payments.client`) through the driver the SDK registry holds under its `driver` name, and confirms a payment
|
|
11
|
+
* through it. It emits `nymbal:payment:status` whenever `status` changes.
|
|
12
|
+
*/
|
|
13
|
+
declare class NymbalPaymentElement extends NymbalElement {
|
|
14
|
+
static schema: ElementSchema;
|
|
15
|
+
/** The built-in drivers, except a name the project registered first: the project's driver wins, as its tag does. */
|
|
16
|
+
static beforeDefine(): void;
|
|
17
|
+
static properties: lit.PropertyDeclarations;
|
|
18
|
+
static styles: CSSResult;
|
|
19
|
+
private _status;
|
|
20
|
+
private _error;
|
|
21
|
+
private _driver;
|
|
22
|
+
private _mounted;
|
|
23
|
+
private _rendered;
|
|
24
|
+
private _generation;
|
|
25
|
+
get status(): PaymentElementStatus;
|
|
26
|
+
/**
|
|
27
|
+
* The light DOM, so the payment driver's UI (Stripe's iframe) and the checkout form share one tree. Its styles join
|
|
28
|
+
* the sheets of the tree it is in, where a shadow root would have held them.
|
|
29
|
+
*/
|
|
30
|
+
protected createRenderRoot(): HTMLElement;
|
|
31
|
+
connectedCallback(): void;
|
|
32
|
+
attributeChangedCallback(name: string, old: string | null, value: string | null): void;
|
|
33
|
+
/** The children are the driver's, mounted imperatively, so Lit renders none of its own. */
|
|
34
|
+
protected render(): symbol;
|
|
35
|
+
/**
|
|
36
|
+
* Completes a payment the API left `requires_action`, once the driver has mounted, handing the driver the
|
|
37
|
+
* checkout's `context`; the driver's answer as is.
|
|
38
|
+
*/
|
|
39
|
+
confirm(clientSecret: string, context?: PaymentConfirmContext): Promise<PaymentConfirmation>;
|
|
40
|
+
private mountClient;
|
|
41
|
+
private fail;
|
|
42
|
+
/**
|
|
43
|
+
* Replaces what a driver or an error rendered. Lit's marker comment stays: its next update (a new `client`) writes
|
|
44
|
+
* at it, and throws once it is gone.
|
|
45
|
+
*/
|
|
46
|
+
private clear;
|
|
47
|
+
private setStatus;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export { NymbalPaymentElement as N };
|
|
51
|
+
export type { PaymentElementStatus as P };
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as lit from 'lit';
|
|
2
|
+
import { nothing } from 'lit';
|
|
3
|
+
import { N as NymbalElement, a as ElementSchema } from './base-element-CPMgAdyQ.js';
|
|
4
|
+
|
|
5
|
+
/** The fields a card reads; a search result or a listing product carries them. */
|
|
6
|
+
interface CardProduct {
|
|
7
|
+
slug: string;
|
|
8
|
+
name: string;
|
|
9
|
+
priceMinor?: number | null;
|
|
10
|
+
priceRange?: {
|
|
11
|
+
minMinor: number;
|
|
12
|
+
maxMinor: number;
|
|
13
|
+
} | null;
|
|
14
|
+
currency?: string | null;
|
|
15
|
+
imageUrl?: string | null;
|
|
16
|
+
media?: Array<{
|
|
17
|
+
url?: string;
|
|
18
|
+
alt?: string;
|
|
19
|
+
}>;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The product's own image, else a placeholder seeded by its slug so a card without media keeps its shape. Exported so
|
|
23
|
+
* a page preloads exactly the image its first card requests.
|
|
24
|
+
*/
|
|
25
|
+
declare function cardImageOf(p: CardProduct): {
|
|
26
|
+
url: string;
|
|
27
|
+
alt: string;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* A product as a card reads it, and nothing else: a listing's products carry their variants, descriptions and
|
|
31
|
+
* categories, which a page of cards would otherwise put in its HTML once per card.
|
|
32
|
+
*/
|
|
33
|
+
declare function cardProductOf(p: Omit<CardProduct, 'media'> & {
|
|
34
|
+
media?: unknown;
|
|
35
|
+
}): CardProduct;
|
|
36
|
+
/** One product as a link to its page: image, name and price. */
|
|
37
|
+
declare class NymbalProductCard extends NymbalElement {
|
|
38
|
+
static schema: ElementSchema;
|
|
39
|
+
static properties: lit.PropertyDeclarations;
|
|
40
|
+
static styles: lit.CSSResult[];
|
|
41
|
+
product: string | undefined;
|
|
42
|
+
eager: boolean | undefined;
|
|
43
|
+
protected render(): typeof nothing | lit.TemplateResult<1>;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export { NymbalProductCard as N, cardProductOf as a, cardImageOf as c };
|
|
47
|
+
export type { CardProduct as C };
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { NymbalAddToCart } from './elements/nymbal-add-to-cart.js';
|
|
2
|
+
import { NymbalCartDrawer } from './elements/nymbal-cart-drawer.js';
|
|
3
|
+
import { NymbalMiniCart } from './elements/nymbal-mini-cart.js';
|
|
4
|
+
import { NymbalVariantSelector } from './elements/nymbal-variant-selector.js';
|
|
5
|
+
import { NymbalQuantitySelector } from './elements/nymbal-quantity-selector.js';
|
|
6
|
+
import { NymbalSearchBar } from './elements/nymbal-search-bar.js';
|
|
7
|
+
import { NymbalProductFilter } from './elements/nymbal-product-filter.js';
|
|
8
|
+
import { NymbalToast } from './elements/nymbal-toast.js';
|
|
9
|
+
import { NymbalPaymentElement } from './elements/nymbal-payment-element.js';
|
|
10
|
+
import { NymbalSortDropdown } from './elements/nymbal-sort-dropdown.js';
|
|
11
|
+
import { NymbalCartPage } from './elements/nymbal-cart-page.js';
|
|
12
|
+
import { NymbalProductCard } from './elements/nymbal-product-card.js';
|
|
13
|
+
import { NymbalSearchResults } from './elements/nymbal-search-results.js';
|
|
14
|
+
import { NymbalLoginForm } from './elements/nymbal-login-form.js';
|
|
15
|
+
import { NymbalRegisterForm } from './elements/nymbal-register-form.js';
|
|
16
|
+
import { NymbalProfileForm } from './elements/nymbal-profile-form.js';
|
|
17
|
+
import { NymbalAddressForm } from './elements/nymbal-address-form.js';
|
|
18
|
+
import { NymbalAddressBook } from './elements/nymbal-address-book.js';
|
|
19
|
+
import { NymbalCheckout } from './elements/nymbal-checkout.js';
|
|
20
|
+
import { NymbalProductGrid } from './elements/nymbal-product-grid.js';
|
|
21
|
+
import { NymbalProductPrice } from './elements/nymbal-product-price.js';
|
|
22
|
+
import { NymbalStockBadge } from './elements/nymbal-stock-badge.js';
|
|
23
|
+
import { NymbalBreadcrumb } from './elements/nymbal-breadcrumb.js';
|
|
24
|
+
import { NymbalImageGallery } from './elements/nymbal-image-gallery.js';
|
|
25
|
+
import { NymbalSiteHeader } from './elements/nymbal-site-header.js';
|
|
26
|
+
import { NymbalSiteFooter } from './elements/nymbal-site-footer.js';
|
|
27
|
+
import { NymbalCategoryNav } from './elements/nymbal-category-nav.js';
|
|
28
|
+
import { NymbalReviewList } from './elements/nymbal-review-list.js';
|
|
29
|
+
import { NymbalReviewForm } from './elements/nymbal-review-form.js';
|
|
30
|
+
import { NymbalOrderSummary } from './elements/nymbal-order-summary.js';
|
|
31
|
+
import '@nymbalhq/sdk';
|
|
32
|
+
import 'lit';
|
|
33
|
+
import './base-element-CPMgAdyQ.js';
|
|
34
|
+
import './form-element-C-qo3gpD.js';
|
|
35
|
+
import '@nymbalhq/types';
|
|
36
|
+
import './selected-variant-Dym0shlJ.js';
|
|
37
|
+
|
|
38
|
+
/** Every element the package defines. */
|
|
39
|
+
declare const ELEMENTS: (typeof NymbalAddToCart | typeof NymbalCartDrawer | typeof NymbalMiniCart | typeof NymbalVariantSelector | typeof NymbalQuantitySelector | typeof NymbalSearchBar | typeof NymbalProductFilter | typeof NymbalToast | typeof NymbalPaymentElement | typeof NymbalSortDropdown | typeof NymbalCartPage | typeof NymbalProductCard | typeof NymbalSearchResults | typeof NymbalLoginForm | typeof NymbalRegisterForm | typeof NymbalProfileForm | typeof NymbalAddressForm | typeof NymbalAddressBook | typeof NymbalCheckout | typeof NymbalProductGrid | typeof NymbalProductPrice | typeof NymbalStockBadge | typeof NymbalBreadcrumb | typeof NymbalImageGallery | typeof NymbalSiteHeader | typeof NymbalSiteFooter | typeof NymbalCategoryNav | typeof NymbalReviewList | typeof NymbalReviewForm | typeof NymbalOrderSummary)[];
|
|
40
|
+
/**
|
|
41
|
+
* Defines every element, and registers the built-in payment drivers, except a tag or driver name the project has
|
|
42
|
+
* already defined: the project's wins. A page that renders a few elements passes those to `define` instead.
|
|
43
|
+
*/
|
|
44
|
+
declare function registerComponents(): void;
|
|
45
|
+
|
|
46
|
+
export { ELEMENTS, registerComponents };
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import '@lit-labs/ssr-client/lit-element-hydrate-support.js'
|
|
2
|
+
import {
|
|
3
|
+
ELEMENTS,
|
|
4
|
+
registerComponents
|
|
5
|
+
} from "./chunk-XE6IWISA.js";
|
|
6
|
+
import "./chunk-H3ZBYNHV.js";
|
|
7
|
+
import "./chunk-7JAAOVCE.js";
|
|
8
|
+
import "./chunk-4COVK727.js";
|
|
9
|
+
import "./chunk-RAOGZH3Z.js";
|
|
10
|
+
import "./chunk-FIF6GQ6U.js";
|
|
11
|
+
import "./chunk-W23P7SI4.js";
|
|
12
|
+
import "./chunk-EBMA7JGV.js";
|
|
13
|
+
import "./chunk-O2YKCDR2.js";
|
|
14
|
+
import "./chunk-2TPQNQYO.js";
|
|
15
|
+
import "./chunk-WEEHXWM3.js";
|
|
16
|
+
import "./chunk-5VWZ2U5K.js";
|
|
17
|
+
import "./chunk-RZVFA3N5.js";
|
|
18
|
+
import "./chunk-DXWMNB5F.js";
|
|
19
|
+
import "./chunk-UYSZOEOA.js";
|
|
20
|
+
import "./chunk-WTEVTCIL.js";
|
|
21
|
+
import "./chunk-NW47OJVN.js";
|
|
22
|
+
import "./chunk-NE6UHTOT.js";
|
|
23
|
+
import "./chunk-VTQVGNVC.js";
|
|
24
|
+
import "./chunk-HPBC3OG7.js";
|
|
25
|
+
import "./chunk-IYT7VXFS.js";
|
|
26
|
+
import "./chunk-6XCCAAMF.js";
|
|
27
|
+
import "./chunk-U2PU4CWB.js";
|
|
28
|
+
import "./chunk-42SSME5H.js";
|
|
29
|
+
import "./chunk-2XXBQPDB.js";
|
|
30
|
+
import "./chunk-SM7TASEW.js";
|
|
31
|
+
import "./chunk-RVSKX2RX.js";
|
|
32
|
+
import "./chunk-W7D3STJH.js";
|
|
33
|
+
import "./chunk-LHYXNQWY.js";
|
|
34
|
+
import "./chunk-B73QVSA5.js";
|
|
35
|
+
import "./chunk-V55K2CS5.js";
|
|
36
|
+
import "./chunk-PN6QKYE4.js";
|
|
37
|
+
import "./chunk-GHXTJ2CF.js";
|
|
38
|
+
import "./chunk-N4Y5DI4X.js";
|
|
39
|
+
import "./chunk-LO2EW5YP.js";
|
|
40
|
+
import "./chunk-LSQPUZK6.js";
|
|
41
|
+
import "./chunk-DR5QB5VN.js";
|
|
42
|
+
import "./chunk-EYDMJNNK.js";
|
|
43
|
+
import "./chunk-UCEVCLQ7.js";
|
|
44
|
+
export {
|
|
45
|
+
ELEMENTS,
|
|
46
|
+
registerComponents
|
|
47
|
+
};
|
|
48
|
+
//# sourceMappingURL=register-components.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import * as _nymbalhq_sdk from '@nymbalhq/sdk';
|
|
2
|
+
import { DenormalisedProduct, DenormalisedVariant } from '@nymbalhq/sdk';
|
|
3
|
+
import { N as NymbalElement } from './base-element-CPMgAdyQ.js';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* An element showing one product's selected variant (its price, its stock). It renders from its attributes until the
|
|
7
|
+
* product store settles on the product its `product-id` names, then from the store's selected variant. A store
|
|
8
|
+
* settled on another product (the page a soft navigation left) is not this element's, so it keeps its attributes.
|
|
9
|
+
*/
|
|
10
|
+
declare abstract class NymbalVariantElement extends NymbalElement {
|
|
11
|
+
productId: string | undefined;
|
|
12
|
+
private following;
|
|
13
|
+
protected stores(): _nymbalhq_sdk.ProductStore[];
|
|
14
|
+
protected storeSettled(): void;
|
|
15
|
+
private ownProduct;
|
|
16
|
+
/** The store's product and its selected variant, once this element follows the store; else null. */
|
|
17
|
+
protected selected(): {
|
|
18
|
+
product: DenormalisedProduct;
|
|
19
|
+
variant: DenormalisedVariant | null;
|
|
20
|
+
} | null;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export { NymbalVariantElement as N };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export { C as CardProduct, c as cardImageOf, a as cardProductOf } from '../nymbal-product-card-C8HkE_rG.js';
|
|
2
|
+
import 'lit';
|
|
3
|
+
import '../base-element-CPMgAdyQ.js';
|
|
4
|
+
import '@nymbalhq/sdk';
|
|
5
|
+
|
|
6
|
+
/** Thrown for a tag the server does not render: neither a package element nor one a project registered. */
|
|
7
|
+
declare class UnknownElement extends Error {
|
|
8
|
+
name: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Registers a project's own element classes by tag, as its elements entry exports them: the server renders each in
|
|
12
|
+
* place of the package's element under that tag, as the browser defines it there. A tag keeps the first class it was
|
|
13
|
+
* registered with; a different class under it is refused, so the server and the browser cannot disagree.
|
|
14
|
+
*/
|
|
15
|
+
declare function registerServerElements(map: Record<string, CustomElementConstructor>): void;
|
|
16
|
+
interface RenderOptions {
|
|
17
|
+
/** The host's attributes; a JSON attribute's value is its JSON text. */
|
|
18
|
+
attributes?: Record<string, string> | undefined;
|
|
19
|
+
/** Light-DOM HTML after the shadow root: a slotted child, as the payment element is the checkout's. */
|
|
20
|
+
children?: string | undefined;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* One element as HTML: `<tag …attributes><template shadowrootmode="open">…</template>…children</tag>`, the template
|
|
24
|
+
* holding the element's first render from its attributes (no client, no store) with its styles, and the markers Lit's
|
|
25
|
+
* hydration reads. The browser parses the template into the element's shadow root, and the element takes it over.
|
|
26
|
+
*/
|
|
27
|
+
declare function renderElement(tag: string, options?: RenderOptions): string;
|
|
28
|
+
|
|
29
|
+
export { UnknownElement, registerServerElements, renderElement };
|
|
30
|
+
export type { RenderOptions };
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import '@lit-labs/ssr-client/lit-element-hydrate-support.js'
|
|
2
|
+
import {
|
|
3
|
+
ELEMENTS
|
|
4
|
+
} from "../chunk-XE6IWISA.js";
|
|
5
|
+
import "../chunk-H3ZBYNHV.js";
|
|
6
|
+
import "../chunk-7JAAOVCE.js";
|
|
7
|
+
import "../chunk-4COVK727.js";
|
|
8
|
+
import "../chunk-RAOGZH3Z.js";
|
|
9
|
+
import "../chunk-FIF6GQ6U.js";
|
|
10
|
+
import "../chunk-W23P7SI4.js";
|
|
11
|
+
import "../chunk-EBMA7JGV.js";
|
|
12
|
+
import "../chunk-O2YKCDR2.js";
|
|
13
|
+
import "../chunk-2TPQNQYO.js";
|
|
14
|
+
import "../chunk-WEEHXWM3.js";
|
|
15
|
+
import "../chunk-5VWZ2U5K.js";
|
|
16
|
+
import {
|
|
17
|
+
cardImageOf,
|
|
18
|
+
cardProductOf
|
|
19
|
+
} from "../chunk-RZVFA3N5.js";
|
|
20
|
+
import "../chunk-DXWMNB5F.js";
|
|
21
|
+
import "../chunk-UYSZOEOA.js";
|
|
22
|
+
import "../chunk-WTEVTCIL.js";
|
|
23
|
+
import "../chunk-NW47OJVN.js";
|
|
24
|
+
import "../chunk-NE6UHTOT.js";
|
|
25
|
+
import "../chunk-VTQVGNVC.js";
|
|
26
|
+
import "../chunk-HPBC3OG7.js";
|
|
27
|
+
import "../chunk-IYT7VXFS.js";
|
|
28
|
+
import "../chunk-6XCCAAMF.js";
|
|
29
|
+
import "../chunk-U2PU4CWB.js";
|
|
30
|
+
import "../chunk-42SSME5H.js";
|
|
31
|
+
import "../chunk-2XXBQPDB.js";
|
|
32
|
+
import "../chunk-SM7TASEW.js";
|
|
33
|
+
import "../chunk-RVSKX2RX.js";
|
|
34
|
+
import "../chunk-W7D3STJH.js";
|
|
35
|
+
import "../chunk-LHYXNQWY.js";
|
|
36
|
+
import "../chunk-B73QVSA5.js";
|
|
37
|
+
import "../chunk-V55K2CS5.js";
|
|
38
|
+
import "../chunk-PN6QKYE4.js";
|
|
39
|
+
import "../chunk-GHXTJ2CF.js";
|
|
40
|
+
import "../chunk-N4Y5DI4X.js";
|
|
41
|
+
import "../chunk-LO2EW5YP.js";
|
|
42
|
+
import "../chunk-LSQPUZK6.js";
|
|
43
|
+
import "../chunk-DR5QB5VN.js";
|
|
44
|
+
import "../chunk-EYDMJNNK.js";
|
|
45
|
+
import "../chunk-UCEVCLQ7.js";
|
|
46
|
+
|
|
47
|
+
// src/ssr/render-root.ts
|
|
48
|
+
import { LitElement } from "lit";
|
|
49
|
+
var prototype = LitElement.prototype;
|
|
50
|
+
var createRenderRoot = prototype.createRenderRoot;
|
|
51
|
+
function restoreCreateRenderRoot() {
|
|
52
|
+
prototype.createRenderRoot = createRenderRoot;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
// src/ssr/index.ts
|
|
56
|
+
import { LitElementRenderer } from "@lit-labs/ssr/lib/lit-element-renderer.js";
|
|
57
|
+
import { collectResultSync } from "@lit-labs/ssr/lib/render-result.js";
|
|
58
|
+
restoreCreateRenderRoot();
|
|
59
|
+
var UnknownElement = class extends Error {
|
|
60
|
+
name = "UnknownElement";
|
|
61
|
+
};
|
|
62
|
+
var CLIENT_MOUNTED = /* @__PURE__ */ new Set(["nymbal-payment-element"]);
|
|
63
|
+
var PACKAGE = new Map(
|
|
64
|
+
ELEMENTS.filter((e) => !CLIENT_MOUNTED.has(e.schema.tag)).map((e) => [
|
|
65
|
+
e.schema.tag,
|
|
66
|
+
e
|
|
67
|
+
])
|
|
68
|
+
);
|
|
69
|
+
var projectElements = /* @__PURE__ */ new Map();
|
|
70
|
+
function registerServerElements(map) {
|
|
71
|
+
for (const [tag, element] of Object.entries(map)) {
|
|
72
|
+
const lit = element;
|
|
73
|
+
if (lit._$litElement$ !== true) {
|
|
74
|
+
throw new TypeError(`${tag}: the server renders Lit elements only`);
|
|
75
|
+
}
|
|
76
|
+
const registered = projectElements.get(tag);
|
|
77
|
+
if (registered !== void 0 && registered !== lit) {
|
|
78
|
+
throw new Error(`${tag} is already registered for the server with another class`);
|
|
79
|
+
}
|
|
80
|
+
projectElements.set(tag, lit);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function classFor(tag) {
|
|
84
|
+
return projectElements.get(tag) ?? PACKAGE.get(tag);
|
|
85
|
+
}
|
|
86
|
+
var ServerElementRenderer = class extends LitElementRenderer {
|
|
87
|
+
static matchesClass(_ctor, tagName) {
|
|
88
|
+
return tagName !== void 0 && classFor(tagName) !== void 0;
|
|
89
|
+
}
|
|
90
|
+
constructor(tagName) {
|
|
91
|
+
super(tagName);
|
|
92
|
+
const element = classFor(tagName);
|
|
93
|
+
if (this.element.constructor !== element) this.element = new element();
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
function defineAll() {
|
|
97
|
+
for (const tag of /* @__PURE__ */ new Set([...projectElements.keys(), ...PACKAGE.keys()])) {
|
|
98
|
+
const element = classFor(tag);
|
|
99
|
+
if (customElements.get(tag) === void 0) customElements.define(tag, element);
|
|
100
|
+
else if (customElements.getName(element) === null)
|
|
101
|
+
customElements.define(`${tag}-server`, element);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
function compactStyles(html) {
|
|
105
|
+
return html.replace(
|
|
106
|
+
/<style>([^<]*)<\/style>/g,
|
|
107
|
+
(_, css) => `<style>${css.replace(/\s+/g, " ").trim()}</style>`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
function renderElement(tag, options = {}) {
|
|
111
|
+
if (CLIENT_MOUNTED.has(tag)) {
|
|
112
|
+
throw new UnknownElement(`${tag} is client-mounted and is not server-rendered`);
|
|
113
|
+
}
|
|
114
|
+
if (classFor(tag) === void 0) {
|
|
115
|
+
throw new UnknownElement(`${tag} is neither a Nymbal element nor a registered server element`);
|
|
116
|
+
}
|
|
117
|
+
defineAll();
|
|
118
|
+
const renderer = new ServerElementRenderer(tag);
|
|
119
|
+
for (const [name, value] of Object.entries(options.attributes ?? {})) {
|
|
120
|
+
renderer.setAttribute(name, value);
|
|
121
|
+
}
|
|
122
|
+
renderer.connectedCallback();
|
|
123
|
+
const renderInfo = {
|
|
124
|
+
elementRenderers: [ServerElementRenderer, LitElementRenderer],
|
|
125
|
+
customElementInstanceStack: [renderer],
|
|
126
|
+
customElementHostStack: [renderer],
|
|
127
|
+
eventTargetStack: [renderer.element],
|
|
128
|
+
slotStack: [],
|
|
129
|
+
deferHydration: false
|
|
130
|
+
};
|
|
131
|
+
const attributes = collectResultSync(renderer.renderAttributes());
|
|
132
|
+
const shadow = compactStyles(collectResultSync(renderer.renderShadow(renderInfo)));
|
|
133
|
+
const { mode = "open" } = renderer.shadowRootOptions;
|
|
134
|
+
return `<${tag}${attributes}><template shadowrootmode="${mode}">${shadow}</template>${options.children ?? ""}</${tag}>`;
|
|
135
|
+
}
|
|
136
|
+
export {
|
|
137
|
+
UnknownElement,
|
|
138
|
+
cardImageOf,
|
|
139
|
+
cardProductOf,
|
|
140
|
+
registerServerElements,
|
|
141
|
+
renderElement
|
|
142
|
+
};
|
|
143
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/ssr/render-root.ts","../../src/ssr/index.ts"],"sourcesContent":["import { LitElement } from 'lit'\n\ntype WithRenderRoot = { createRenderRoot: () => HTMLElement | DocumentFragment }\n\n// Lit SSR replaces LitElement's createRenderRoot when it loads, dropping the hydrate support's, which is what makes a\n// client element take over a server's shadow root. A realm that both renders on the server and runs elements (a test,\n// a DOM-shimmed server) keeps the one it had: this module is imported before Lit SSR, and the ssr entry restores it.\nconst prototype = LitElement.prototype as unknown as WithRenderRoot\nconst createRenderRoot = prototype.createRenderRoot\n\nexport function restoreCreateRenderRoot(): void {\n prototype.createRenderRoot = createRenderRoot\n}\n","import { restoreCreateRenderRoot } from './render-root.js'\nimport type { RenderInfo } from '@lit-labs/ssr'\nimport { LitElementRenderer } from '@lit-labs/ssr/lib/lit-element-renderer.js'\nimport { collectResultSync } from '@lit-labs/ssr/lib/render-result.js'\nimport type { LitElement } from 'lit'\nimport { ELEMENTS } from '../register-components.js'\n\nexport { cardImageOf, cardProductOf, type CardProduct } from '../components/product-card.js'\n\nrestoreCreateRenderRoot()\n\n/** Thrown for a tag the server does not render: neither a package element nor one a project registered. */\nexport class UnknownElement extends Error {\n override name = 'UnknownElement'\n}\n\ntype LitElementClass = (new () => LitElement) & { _$litElement$?: boolean }\n\n/** Mounted by its payment driver in the browser, in the light DOM; a checkout's server render leaves its slot. */\nconst CLIENT_MOUNTED = new Set(['nymbal-payment-element'])\n\nconst PACKAGE = new Map<string, LitElementClass>(\n ELEMENTS.filter((e) => !CLIENT_MOUNTED.has(e.schema.tag)).map((e) => [\n e.schema.tag,\n e as unknown as LitElementClass,\n ]),\n)\n\n/** The project's elements by tag (its `serverElements`), which the server renders in place of the package's. */\nconst projectElements = new Map<string, LitElementClass>()\n\n/**\n * Registers a project's own element classes by tag, as its elements entry exports them: the server renders each in\n * place of the package's element under that tag, as the browser defines it there. A tag keeps the first class it was\n * registered with; a different class under it is refused, so the server and the browser cannot disagree.\n */\nexport function registerServerElements(map: Record<string, CustomElementConstructor>): void {\n for (const [tag, element] of Object.entries(map)) {\n const lit = element as unknown as LitElementClass\n if (lit._$litElement$ !== true) {\n throw new TypeError(`${tag}: the server renders Lit elements only`)\n }\n const registered = projectElements.get(tag)\n if (registered !== undefined && registered !== lit) {\n throw new Error(`${tag} is already registered for the server with another class`)\n }\n projectElements.set(tag, lit)\n }\n}\n\n/** The class the server renders under `tag`, resolved per call, so a registration after a first render wins. */\nfunction classFor(tag: string): LitElementClass | undefined {\n return projectElements.get(tag) ?? PACKAGE.get(tag)\n}\n\n/**\n * Lit SSR finds the elements a template renders, and constructs them, through `customElements`, which defines a tag\n * once per process. This renderer constructs the class `classFor` resolves instead, so a project's element renders\n * under its tag whatever `customElements` held first.\n */\nclass ServerElementRenderer extends LitElementRenderer {\n static override matchesClass(_ctor: typeof HTMLElement, tagName?: string): boolean {\n return tagName !== undefined && classFor(tagName) !== undefined\n }\n\n constructor(tagName: string) {\n super(tagName)\n const element = classFor(tagName)!\n if (this.element.constructor !== element) this.element = new element()\n }\n}\n\n/**\n * Every tag the server may render is known to `customElements`, which is where Lit SSR finds nested elements. A DOM\n * (not Lit's server shim) constructs only the classes it defined, so a project class whose tag already holds another\n * class is defined under a name of its own.\n */\nfunction defineAll(): void {\n for (const tag of new Set([...projectElements.keys(), ...PACKAGE.keys()])) {\n const element = classFor(tag)!\n if (customElements.get(tag) === undefined) customElements.define(tag, element)\n else if (customElements.getName(element) === null)\n customElements.define(`${tag}-server`, element)\n }\n}\n\n/**\n * The elements' styles, with their indentation collapsed: written for reading, they would otherwise be bytes a page\n * downloads before its first paint, once per element.\n */\nfunction compactStyles(html: string): string {\n return html.replace(\n /<style>([^<]*)<\\/style>/g,\n (_, css: string) => `<style>${css.replace(/\\s+/g, ' ').trim()}</style>`,\n )\n}\n\nexport interface RenderOptions {\n /** The host's attributes; a JSON attribute's value is its JSON text. */\n attributes?: Record<string, string> | undefined\n /** Light-DOM HTML after the shadow root: a slotted child, as the payment element is the checkout's. */\n children?: string | undefined\n}\n\n/**\n * One element as HTML: `<tag …attributes><template shadowrootmode=\"open\">…</template>…children</tag>`, the template\n * holding the element's first render from its attributes (no client, no store) with its styles, and the markers Lit's\n * hydration reads. The browser parses the template into the element's shadow root, and the element takes it over.\n */\nexport function renderElement(tag: string, options: RenderOptions = {}): string {\n if (CLIENT_MOUNTED.has(tag)) {\n throw new UnknownElement(`${tag} is client-mounted and is not server-rendered`)\n }\n if (classFor(tag) === undefined) {\n throw new UnknownElement(`${tag} is neither a Nymbal element nor a registered server element`)\n }\n defineAll()\n\n const renderer = new ServerElementRenderer(tag)\n for (const [name, value] of Object.entries(options.attributes ?? {})) {\n renderer.setAttribute(name, value)\n }\n renderer.connectedCallback()\n const renderInfo: RenderInfo = {\n elementRenderers: [ServerElementRenderer, LitElementRenderer],\n customElementInstanceStack: [renderer],\n customElementHostStack: [renderer],\n eventTargetStack: [renderer.element],\n slotStack: [],\n deferHydration: false,\n }\n const attributes = collectResultSync(renderer.renderAttributes())\n const shadow = compactStyles(collectResultSync(renderer.renderShadow(renderInfo)))\n const { mode = 'open' } = renderer.shadowRootOptions\n return `<${tag}${attributes}><template shadowrootmode=\"${mode}\">${shadow}</template>${options.children ?? ''}</${tag}>`\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nymbalhq/web-components",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "Interactive commerce UI as native Web Components",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"astro-component",
|
|
7
|
+
"web-components"
|
|
8
|
+
],
|
|
5
9
|
"license": "MIT",
|
|
6
10
|
"repository": {
|
|
7
11
|
"type": "git",
|
|
@@ -17,28 +21,51 @@
|
|
|
17
21
|
},
|
|
18
22
|
"main": "./dist/index.js",
|
|
19
23
|
"types": "./dist/index.d.ts",
|
|
24
|
+
"sideEffects": [
|
|
25
|
+
"*.css",
|
|
26
|
+
"./dist/hydrate-support.js",
|
|
27
|
+
"./src/hydrate-support.ts"
|
|
28
|
+
],
|
|
20
29
|
"exports": {
|
|
21
30
|
".": {
|
|
22
31
|
"types": "./dist/index.d.ts",
|
|
23
32
|
"import": "./dist/index.js"
|
|
24
33
|
},
|
|
34
|
+
"./elements/*": {
|
|
35
|
+
"types": "./dist/elements/*.d.ts",
|
|
36
|
+
"import": "./dist/elements/*.js"
|
|
37
|
+
},
|
|
38
|
+
"./hydrate-support": {
|
|
39
|
+
"types": "./dist/hydrate-support.d.ts",
|
|
40
|
+
"import": "./dist/hydrate-support.js"
|
|
41
|
+
},
|
|
42
|
+
"./ssr": {
|
|
43
|
+
"types": "./dist/ssr/index.d.ts",
|
|
44
|
+
"import": "./dist/ssr/index.js"
|
|
45
|
+
},
|
|
46
|
+
"./astro": "./astro/NymbalElement.astro",
|
|
25
47
|
"./tokens.css": "./src/tokens/tokens.css"
|
|
26
48
|
},
|
|
27
49
|
"files": [
|
|
28
50
|
"dist",
|
|
51
|
+
"astro",
|
|
29
52
|
"src/tokens/tokens.css"
|
|
30
53
|
],
|
|
31
54
|
"dependencies": {
|
|
32
|
-
"@
|
|
33
|
-
"@
|
|
55
|
+
"@lit-labs/ssr": "^3.3.1",
|
|
56
|
+
"@lit-labs/ssr-client": "^1.1.8",
|
|
57
|
+
"@nymbalhq/sdk": "1.2.0",
|
|
58
|
+
"@nymbalhq/types": "1.2.0",
|
|
59
|
+
"lit": "^3.3.3"
|
|
34
60
|
},
|
|
35
61
|
"devDependencies": {
|
|
36
|
-
"
|
|
37
|
-
"
|
|
62
|
+
"@typescript/native": "npm:typescript@^7.0.2",
|
|
63
|
+
"tsup": "^9.0.0",
|
|
64
|
+
"typescript": "npm:@typescript/typescript6@^6.0.2"
|
|
38
65
|
},
|
|
39
66
|
"scripts": {
|
|
40
67
|
"build": "tsup",
|
|
41
68
|
"dev": "tsup --watch",
|
|
42
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
69
|
+
"typecheck": "tsc -p tsconfig.json --noEmit --rootDir ../.."
|
|
43
70
|
}
|
|
44
71
|
}
|