@nymbalhq/web-components 0.0.0-stage → 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.
@@ -0,0 +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\">&times;</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' : ''}>&#8722;</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' : ''}>&#43;</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, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#39;')\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"]}
package/package.json CHANGED
@@ -1,6 +1,44 @@
1
1
  {
2
2
  "name": "@nymbalhq/web-components",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
3
+ "version": "1.0.0",
4
+ "description": "Interactive commerce UI as native Web Components",
5
+ "license": "MIT",
6
+ "repository": {
7
+ "type": "git",
8
+ "url": "git+https://github.com/nymbalhq/nymbal.git",
9
+ "directory": "packages/web-components"
10
+ },
11
+ "publishConfig": {
12
+ "access": "public"
13
+ },
14
+ "type": "module",
15
+ "engines": {
16
+ "node": ">=22"
17
+ },
18
+ "main": "./dist/index.js",
19
+ "types": "./dist/index.d.ts",
20
+ "exports": {
21
+ ".": {
22
+ "types": "./dist/index.d.ts",
23
+ "import": "./dist/index.js"
24
+ },
25
+ "./tokens.css": "./src/tokens/tokens.css"
26
+ },
27
+ "files": [
28
+ "dist",
29
+ "src/tokens/tokens.css"
30
+ ],
31
+ "dependencies": {
32
+ "@nymbalhq/sdk": "1.0.0",
33
+ "@nymbalhq/types": "1.0.0"
34
+ },
35
+ "devDependencies": {
36
+ "tsup": "^8.3.5",
37
+ "typescript": "^5.6.3"
38
+ },
39
+ "scripts": {
40
+ "build": "tsup",
41
+ "dev": "tsup --watch",
42
+ "typecheck": "tsc -p tsconfig.json --noEmit"
43
+ }
6
44
  }
@@ -0,0 +1,48 @@
1
+ :root {
2
+ --nymbal-color-primary: #18181b;
3
+ --nymbal-color-primary-hover: #27272a;
4
+ --nymbal-color-accent: #2563eb;
5
+ --nymbal-color-accent-hover: #1d4ed8;
6
+ --nymbal-color-success: #16a34a;
7
+ --nymbal-color-error: #dc2626;
8
+ --nymbal-color-warning: #d97706;
9
+ --nymbal-color-text: #18181b;
10
+ --nymbal-color-text-muted: #71717a;
11
+ --nymbal-color-text-inverse: #ffffff;
12
+ --nymbal-color-border: #e4e4e7;
13
+ --nymbal-color-surface: #ffffff;
14
+ --nymbal-color-overlay: rgba(0, 0, 0, 0.4);
15
+
16
+ --nymbal-font-family: system-ui, -apple-system, sans-serif;
17
+ --nymbal-font-size-xs: 0.75rem;
18
+ --nymbal-font-size-sm: 0.875rem;
19
+ --nymbal-font-size-base: 1rem;
20
+ --nymbal-font-size-lg: 1.125rem;
21
+ --nymbal-font-size-xl: 1.25rem;
22
+ --nymbal-font-weight-normal: 400;
23
+ --nymbal-font-weight-medium: 500;
24
+ --nymbal-font-weight-bold: 700;
25
+
26
+ --nymbal-spacing-xs: 0.25rem;
27
+ --nymbal-spacing-sm: 0.5rem;
28
+ --nymbal-spacing-md: 1rem;
29
+ --nymbal-spacing-lg: 1.5rem;
30
+ --nymbal-spacing-xl: 2rem;
31
+
32
+ --nymbal-radius-sm: 0.25rem;
33
+ --nymbal-radius-md: 0.375rem;
34
+ --nymbal-radius-lg: 0.5rem;
35
+ --nymbal-radius-full: 9999px;
36
+
37
+ --nymbal-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.05);
38
+ --nymbal-shadow-md: 0 4px 6px rgba(0, 0, 0, 0.1);
39
+ --nymbal-shadow-lg: 0 10px 15px rgba(0, 0, 0, 0.1);
40
+
41
+ --nymbal-transition-fast: 150ms ease;
42
+ --nymbal-transition-normal: 200ms ease;
43
+ --nymbal-transition-slow: 300ms ease;
44
+
45
+ --nymbal-z-dropdown: 100;
46
+ --nymbal-z-drawer: 200;
47
+ --nymbal-z-toast: 300;
48
+ }
package/README.md DELETED
@@ -1,3 +0,0 @@
1
- # Temporary Holding Version
2
-
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.