@altazion/commerce-sdk-htmx 26.407.7565 → 26.415.7673
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +331 -5
- package/dist/index.cjs +965 -140
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +82 -7
- package/dist/index.iife.js +966 -142
- package/dist/index.iife.js.map +1 -1
- package/dist/index.js +965 -140
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","sources":["../src/extensions/altazion-auth.ts","../src/helpers/price.ts","../src/helpers/product.ts","../src/helpers/cart.ts","../src/templates/product-card.hbs?raw","../src/templates/cart-mini.hbs?raw","../src/templates/product-list.hbs?raw","../src/index.ts"],"sourcesContent":["import type { CommerceClient } from '@altazion/commerce-sdk-core'\n\ndeclare global {\n interface Window {\n htmx?: {\n on(eventName: string, listener: (event: Event) => void): void\n off(eventName: string, listener: (event: Event) => void): void\n }\n }\n}\n\ninterface HtmxConfigRequestEvent extends Event {\n detail: {\n headers: Record<string, string>\n elt: Element\n }\n}\n\n/**\n * Extension HTMX qui injecte automatiquement les headers de contexte Altazion\n * sur chaque requête HTMX.\n *\n * En modes browser et kiosk, les cookies sont transmis via credentials:'include'\n * par le navigateur. Cette extension ajoute uniquement les headers de contexte\n * (locale, currency) utiles côté serveur.\n */\nexport function registerAltazionAuthExtension(client: CommerceClient): void {\n if (typeof window === 'undefined' || !window.htmx) {\n console.warn('[AltazionHtmx] htmx non disponible sur window — extension non enregistrée')\n return\n }\n\n const handler = (event: Event): void => {\n const e = event as HtmxConfigRequestEvent\n e.detail.headers['Accept-Language'] = client.context.locale\n e.detail.headers['X-Altazion-Currency'] = client.context.currency\n }\n\n window.htmx.on('htmx:configRequest', handler)\n}\n","import type Handlebars from 'handlebars'\n\ntype HandlebarsInstance = typeof Handlebars\n\n/**\n * Formate un montant selon la locale et la devise.\n * Usage : {{formatPrice 19.99 \"EUR\" \"fr-FR\"}}\n * Si locale/currency sont omis, utilise les valeurs passées au registre.\n */\nexport function registerPriceHelpers(\n hbs: HandlebarsInstance,\n defaults: { locale: string; currency: string }\n): void {\n hbs.registerHelper(\n 'formatPrice',\n function (\n value: unknown,\n currency?: unknown,\n locale?: unknown\n ): string {\n const amount = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(amount)) return ''\n\n const resolvedCurrency =\n typeof currency === 'string' ? currency : defaults.currency\n const resolvedLocale =\n typeof locale === 'string' ? locale : defaults.locale\n\n return new Intl.NumberFormat(resolvedLocale, {\n style: 'currency',\n currency: resolvedCurrency,\n }).format(amount)\n }\n )\n\n hbs.registerHelper(\n 'formatPriceCompact',\n function (value: unknown, currency?: unknown, locale?: unknown): string {\n const amount = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(amount)) return ''\n\n const resolvedCurrency =\n typeof currency === 'string' ? currency : defaults.currency\n const resolvedLocale =\n typeof locale === 'string' ? locale : defaults.locale\n\n return new Intl.NumberFormat(resolvedLocale, {\n style: 'currency',\n currency: resolvedCurrency,\n notation: 'compact',\n }).format(amount)\n }\n )\n\n hbs.registerHelper(\n 'discountPercent',\n function (original: unknown, discounted: unknown): string {\n const orig = typeof original === 'number' ? original : parseFloat(String(original))\n const disc = typeof discounted === 'number' ? discounted : parseFloat(String(discounted))\n if (isNaN(orig) || isNaN(disc) || orig === 0) return ''\n const pct = Math.round(((orig - disc) / orig) * 100)\n return `-${pct}%`\n }\n )\n}\n","import type Handlebars from 'handlebars'\n\ntype HandlebarsInstance = typeof Handlebars\n\n/**\n * Helpers Handlebars liés aux produits.\n *\n * Usage :\n * {{productUrl reference}}\n * {{thumbnailUrl imageUrl 400}}\n * {{#if (isAvailable availability)}} ... {{/if}}\n */\nexport function registerProductHelpers(hbs: HandlebarsInstance, siteUrl: string): void {\n // URL de la fiche produit côté site vitrine\n hbs.registerHelper('productUrl', function (reference: unknown): string {\n if (typeof reference !== 'string' && typeof reference !== 'number') return ''\n const base = siteUrl.replace(/\\/$/, '')\n return `${base}/product/${encodeURIComponent(String(reference))}`\n })\n\n // Transforme une URL d'image en URL redimensionnée si le serveur le supporte\n // Pattern attendu : /media/images/{id} → /media/images/{id}?w={size}\n hbs.registerHelper('thumbnailUrl', function (imageUrl: unknown, size?: unknown): string {\n if (typeof imageUrl !== 'string' || !imageUrl) return ''\n const resolvedSize = typeof size === 'number' ? size : 300\n const separator = imageUrl.includes('?') ? '&' : '?'\n return `${imageUrl}${separator}w=${resolvedSize}`\n })\n\n // Retourne true si le produit est disponible (availability > 0 ou pas de stock géré)\n hbs.registerHelper('isAvailable', function (availability: unknown): boolean {\n if (availability === null || availability === undefined) return true\n if (typeof availability === 'boolean') return availability\n if (typeof availability === 'number') return availability > 0\n if (typeof availability === 'string') {\n const lower = availability.toLowerCase()\n return lower === 'available' || lower === 'instock'\n }\n return false\n })\n\n // Helper ifCond simple pour les comparaisons dans les templates\n hbs.registerHelper(\n 'ifCond',\n function (\n this: unknown,\n v1: unknown,\n operator: string,\n v2: unknown,\n options: Handlebars.HelperOptions\n ): string {\n let result = false\n switch (operator) {\n case '==': result = v1 == v2; break\n case '===': result = v1 === v2; break\n case '!=': result = v1 != v2; break\n case '!==': result = v1 !== v2; break\n case '>': result = (v1 as number) > (v2 as number); break\n case '<': result = (v1 as number) < (v2 as number); break\n case '>=': result = (v1 as number) >= (v2 as number); break\n case '<=': result = (v1 as number) <= (v2 as number); break\n default: result = false\n }\n return result ? options.fn(this as object) : options.inverse(this as object)\n }\n )\n}\n","import type Handlebars from 'handlebars'\nimport type { Cart, CartContent } from '@altazion/commerce-sdk-core'\n\ntype HandlebarsInstance = typeof Handlebars\n\n/**\n * Helpers Handlebars liés au panier.\n *\n * Nécessite un getter réactif sur le panier actuel.\n * Usage :\n * Nombre d'articles : {{cartCount}}\n * Total : {{cartTotal}}\n * {{#if cartHasItems}} ... {{/if}}\n */\nexport function registerCartHelpers(\n hbs: HandlebarsInstance,\n getCart: () => Cart | null,\n defaults: { locale: string; currency: string }\n): void {\n hbs.registerHelper('cartCount', function (): number {\n const cart = getCart()\n if (!cart) return 0\n return cart.totalQuantity\n })\n\n hbs.registerHelper('cartTotal', function (): string {\n const cart = getCart()\n if (!cart) return ''\n return new Intl.NumberFormat(defaults.locale, {\n style: 'currency',\n currency: defaults.currency,\n }).format(cart.totalAmountWithTax)\n })\n\n hbs.registerHelper('cartTotalRaw', function (): number {\n const cart = getCart()\n return cart?.totalAmountWithTax ?? 0\n })\n\n hbs.registerHelper('cartHasItems', function (this: unknown, options: Handlebars.HelperOptions): string {\n const cart = getCart()\n const hasItems = cart ? cart.totalQuantity > 0 : false\n return hasItems ? options.fn(this as object) : options.inverse(this as object)\n })\n\n hbs.registerHelper('cartLineCount', function (): number {\n const cart = getCart()\n if (!cart?.content) return 0\n return cart.content.reduce((sum: number, group: CartContent) => sum + (group.lines?.length ?? 0), 0)\n })\n}\n","export default \"<article class=\\\"altz-product-card{{#unless (isAvailable availability)}} altz-product-card--unavailable{{/unless}}\\\">\\n {{#if imageUrl}}\\n <a href=\\\"{{productUrl reference}}\\\" class=\\\"altz-product-card__image-link\\\" aria-label=\\\"{{name}}\\\">\\n <img\\n src=\\\"{{thumbnailUrl imageUrl 400}}\\\"\\n alt=\\\"{{name}}\\\"\\n class=\\\"altz-product-card__image\\\"\\n loading=\\\"lazy\\\"\\n width=\\\"400\\\"\\n />\\n </a>\\n {{/if}}\\n\\n <div class=\\\"altz-product-card__body\\\">\\n <a href=\\\"{{productUrl reference}}\\\" class=\\\"altz-product-card__title\\\">\\n {{name}}\\n </a>\\n\\n <div class=\\\"altz-product-card__pricing\\\">\\n {{#if discount}}\\n <span class=\\\"altz-product-card__price altz-product-card__price--discounted\\\">\\n {{formatPrice price}}\\n </span>\\n <span class=\\\"altz-product-card__price altz-product-card__price--original\\\">\\n {{formatPrice originalPrice}}\\n </span>\\n <span class=\\\"altz-product-card__discount-badge\\\">\\n {{discountPercent originalPrice price}}\\n </span>\\n {{else}}\\n <span class=\\\"altz-product-card__price\\\">\\n {{formatPrice price}}\\n </span>\\n {{/if}}\\n </div>\\n\\n {{#unless (isAvailable availability)}}\\n <p class=\\\"altz-product-card__unavailable\\\">{{unavailableLabel}}</p>\\n {{/unless}}\\n\\n {{#if (isAvailable availability)}}\\n <button\\n class=\\\"altz-product-card__add-to-cart\\\"\\n hx-post=\\\"/commerce/api/process/cart/lines\\\"\\n hx-vals='{\\\"productReference\\\":\\\"{{reference}}\\\",\\\"quantity\\\":1}'\\n hx-target=\\\"#altz-cart-summary\\\"\\n hx-swap=\\\"outerHTML\\\"\\n hx-indicator=\\\".altz-spinner\\\"\\n >\\n {{addToCartLabel}}\\n </button>\\n {{/if}}\\n </div>\\n</article>\\n\"","export default \"<div id=\\\"altz-cart-mini\\\" class=\\\"altz-cart-mini\\\">\\n <div class=\\\"altz-cart-mini__header\\\">\\n <span class=\\\"altz-cart-mini__label\\\">{{cartLabel}}</span>\\n <span class=\\\"altz-cart-mini__count\\\">{{cartCount}}</span>\\n </div>\\n\\n {{#cartHasItems}}\\n <ul class=\\\"altz-cart-mini__lines\\\">\\n {{#each lines}}\\n <li class=\\\"altz-cart-mini__line\\\">\\n <span class=\\\"altz-cart-mini__line-name\\\">{{this.productName}}</span>\\n <span class=\\\"altz-cart-mini__line-qty\\\">× {{this.quantity}}</span>\\n <span class=\\\"altz-cart-mini__line-price\\\">{{formatPrice this.unitPriceWithTax}}</span>\\n </li>\\n {{/each}}\\n </ul>\\n\\n <div class=\\\"altz-cart-mini__total\\\">\\n <span>{{totalLabel}}</span>\\n <strong>{{cartTotal}}</strong>\\n </div>\\n\\n <a href=\\\"{{cartUrl}}\\\" class=\\\"altz-cart-mini__cta\\\">\\n {{viewCartLabel}}\\n </a>\\n {{/cartHasItems}}\\n\\n {{^cartHasItems}}\\n <p class=\\\"altz-cart-mini__empty\\\">{{emptyLabel}}</p>\\n {{/cartHasItems}}\\n</div>\\n\"","export default \"<section class=\\\"altz-product-list\\\">\\n {{#if title}}\\n <h2 class=\\\"altz-product-list__title\\\">{{title}}</h2>\\n {{/if}}\\n\\n {{#if products.length}}\\n <ul class=\\\"altz-product-list__grid\\\" role=\\\"list\\\">\\n {{#each products}}\\n <li class=\\\"altz-product-list__item\\\">\\n <article class=\\\"altz-product-card{{#unless (isAvailable this.availability)}} altz-product-card--unavailable{{/unless}}\\\">\\n {{#if this.imageUrl}}\\n <a href=\\\"{{productUrl this.reference}}\\\" class=\\\"altz-product-card__image-link\\\" aria-label=\\\"{{this.name}}\\\">\\n <img\\n src=\\\"{{thumbnailUrl this.imageUrl 300}}\\\"\\n alt=\\\"{{this.name}}\\\"\\n class=\\\"altz-product-card__image\\\"\\n loading=\\\"lazy\\\"\\n width=\\\"300\\\"\\n />\\n </a>\\n {{/if}}\\n\\n <div class=\\\"altz-product-card__body\\\">\\n <a href=\\\"{{productUrl this.reference}}\\\" class=\\\"altz-product-card__title\\\">\\n {{this.name}}\\n </a>\\n\\n <div class=\\\"altz-product-card__pricing\\\">\\n {{#if this.discount}}\\n <span class=\\\"altz-product-card__price altz-product-card__price--discounted\\\">\\n {{formatPrice this.price}}\\n </span>\\n <span class=\\\"altz-product-card__price altz-product-card__price--original\\\">\\n {{formatPrice this.originalPrice}}\\n </span>\\n <span class=\\\"altz-product-card__discount-badge\\\">\\n {{discountPercent this.originalPrice this.price}}\\n </span>\\n {{else}}\\n <span class=\\\"altz-product-card__price\\\">\\n {{formatPrice this.price}}\\n </span>\\n {{/if}}\\n </div>\\n\\n {{#if (isAvailable this.availability)}}\\n <button\\n class=\\\"altz-product-card__add-to-cart\\\"\\n hx-post=\\\"/commerce/api/process/cart/lines\\\"\\n hx-vals='{\\\"productReference\\\":\\\"{{this.reference}}\\\",\\\"quantity\\\":1}'\\n hx-target=\\\"#altz-cart-summary\\\"\\n hx-swap=\\\"outerHTML\\\"\\n hx-indicator=\\\".altz-spinner\\\"\\n >\\n {{../addToCartLabel}}\\n </button>\\n {{/if}}\\n </div>\\n </article>\\n </li>\\n {{/each}}\\n </ul>\\n {{else}}\\n <p class=\\\"altz-product-list__empty\\\">{{emptyLabel}}</p>\\n {{/if}}\\n</section>\\n\"","import type { CommerceClient, Cart, QueueEvent } from '@altazion/commerce-sdk-core'\nimport type Handlebars from 'handlebars'\n\nimport { registerAltazionAuthExtension } from './extensions/altazion-auth'\nimport { registerPriceHelpers } from './helpers/price'\nimport { registerProductHelpers } from './helpers/product'\nimport { registerCartHelpers } from './helpers/cart'\n\n// Templates pré-compilés importés en tant que chaînes brutes\nimport productCardTemplate from './templates/product-card.hbs?raw'\nimport cartMiniTemplate from './templates/cart-mini.hbs?raw'\nimport productListTemplate from './templates/product-list.hbs?raw'\n\nexport type { Cart }\n\nexport interface AltazionHtmxConfig {\n /** Instance CommerceClient déjà initialisée */\n client: CommerceClient\n /**\n * Instance Handlebars (global ou importée).\n * Si omis, les helpers ne sont pas enregistrés.\n */\n handlebars?: typeof Handlebars\n /**\n * Sélecteur CSS de l'élément DOM à basculer avec la classe `altz-offline`\n * lorsque la connectivité est perdue/restaurée.\n * @default 'body'\n */\n offlineSelector?: string\n}\n\nexport interface AltazionHtmxInstance {\n /** Templates Handlebars compilés prêts à l'emploi */\n templates: {\n productCard: HandlebarsTemplateDelegate\n cartMini: HandlebarsTemplateDelegate\n productList: HandlebarsTemplateDelegate\n }\n /** Détruit les listeners et libère les ressources */\n dispose(): void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype HandlebarsTemplateDelegate = (context?: any) => string\n\n/**\n * Initialise le SDK HTMX Altazion.\n *\n * - Enregistre l'extension HTMX (headers contexte) si htmx est présent\n * - Enregistre les helpers Handlebars (prix, produits, panier) si hbs est fourni\n * - Active l'indicateur d'état offline sur le DOM\n * - Retourne les templates compilés\n *\n * @example\n * ```ts\n * import Handlebars from 'handlebars'\n * const sdk = init({ client, handlebars: Handlebars })\n * const html = sdk.templates.productCard(product)\n * document.getElementById('product')!.innerHTML = html\n * ```\n */\nexport function init(config: AltazionHtmxConfig): AltazionHtmxInstance {\n const { client, handlebars, offlineSelector = 'body' } = config\n\n // 1. Extension HTMX — headers de contexte sur chaque requête\n registerAltazionAuthExtension(client)\n\n // 2. HTMX config globale — transmettre les cookies sur les requêtes XHR HTMX\n if (typeof window !== 'undefined' && window.htmx) {\n // @ts-expect-error — htmx.config n'est pas dans les types window\n window.htmx.config = window.htmx.config ?? {}\n // @ts-expect-error\n window.htmx.config.withCredentials = true\n }\n\n // 3. Helpers Handlebars\n const defaults = {\n locale: client.context.locale,\n currency: client.context.currency,\n }\n\n // Getter réactif sur le panier (mis à jour lors du flush offline)\n let currentCart: Cart | null = null\n const getCart = (): Cart | null => currentCart\n\n // Abonnement aux events panier pour mettre à jour le getter\n client.onQueueEvent(async (event: QueueEvent) => {\n if (event.type === 'flushed') {\n try {\n currentCart = await client.cart.getCart()\n } catch {\n // Panier indisponible après flush — on ignore silencieusement\n }\n }\n })\n\n if (handlebars) {\n registerPriceHelpers(handlebars, defaults)\n registerProductHelpers(handlebars, client.context.siteUrl ?? '')\n registerCartHelpers(handlebars, getCart, defaults)\n }\n\n // 4. Indicateur offline DOM\n const offlineEl = typeof document !== 'undefined'\n ? document.querySelector(offlineSelector)\n : null\n\n const updateOfflineClass = (): void => {\n offlineEl?.classList.toggle('altz-offline', client.isOffline)\n }\n\n // Synchronisation initiale\n updateOfflineClass()\n\n // Abonnement ConnectivityManager — retourne la fonction de désabonnement\n const unsubscribeConnectivity = client.connectivity?.subscribe(() => updateOfflineClass())\n\n // 5. Templates compilés (retournés pour usage dans le code applicatif)\n const noHbs = (): HandlebarsTemplateDelegate =>\n () => '<!-- handlebars non initialisé dans @altazion/commerce-sdk-htmx -->'\n\n const templates = handlebars\n ? {\n productCard: handlebars.compile(productCardTemplate),\n cartMini: handlebars.compile(cartMiniTemplate),\n productList: handlebars.compile(productListTemplate),\n }\n : {\n productCard: noHbs(),\n cartMini: noHbs(),\n productList: noHbs(),\n }\n\n return {\n templates,\n dispose(): void {\n unsubscribeConnectivity?.()\n },\n }\n}\n\n// Re-exports helpers pour usage à la carte\nexport { registerPriceHelpers } from './helpers/price'\nexport { registerProductHelpers } from './helpers/product'\nexport { registerCartHelpers } from './helpers/cart'\nexport { registerAltazionAuthExtension } from './extensions/altazion-auth'\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.cjs","sources":["../src/extensions/altazion-engine.ts","../src/extensions/modules/cart.ts","../src/extensions/modules/session.ts","../src/extensions/modules/marketing.ts","../src/extensions/modules/stores.ts","../src/extensions/altazion-auth.ts","../src/helpers/price.ts","../src/helpers/product.ts","../src/helpers/cart.ts","../src/rendering/declarative-renderer.ts","../src/templates/product-card.hbs?raw","../src/templates/cart-mini.hbs?raw","../src/templates/product-list.hbs?raw","../src/index.ts"],"sourcesContent":["import {\n AltazionApiError,\n OfflineError,\n type CommerceClient,\n type ProblemDetails,\n} from '@altazion/commerce-sdk-core'\n\ndeclare global {\n interface Window {\n htmx?: {\n on(eventName: string, listener: (event: Event) => void): void\n off(eventName: string, listener: (event: Event) => void): void\n ajax(\n method: string,\n path: string,\n context?: {\n source?: Element\n target?: Element | string\n swap?: string\n select?: string\n values?: Record<string, unknown>\n }\n ): Promise<unknown> | void\n }\n }\n}\n\nexport interface AltazionExtensionHandle {\n dispose(): void\n}\n\nexport interface AltazionActionEventDetail<\n TModule extends string = string,\n TAction extends string = string,\n TResult = unknown,\n> {\n module: TModule\n action: TAction\n element: Element\n payload: Record<string, unknown>\n result?: TResult\n error?: unknown\n errorDetail?: AltazionActionErrorDetail\n}\n\nexport interface AltazionActionErrorDetail {\n name: string\n message: string\n status?: number\n problem?: ProblemDetails\n isOffline: boolean\n isConflict: boolean\n}\n\nexport type AltazionSuccessEventKind = 'loaded' | 'updated' | 'changed' | 'none'\n\nexport interface AltazionModuleDefinition<\n TModule extends string = string,\n TAction extends string = string,\n TResult = unknown,\n> {\n moduleName: TModule\n actionAttribute: string\n payloadAttributes?: Record<string, string>\n jsonPayloadAttributes?: Record<string, string>\n payloadAliases?: Record<string, string>\n normalizePayload?(payload: Record<string, unknown>): void\n parseAction(actionValue: string): TAction\n execute(client: CommerceClient, action: TAction, payload: Record<string, unknown>): Promise<TResult>\n successEventKind?: AltazionSuccessEventKind | ((action: TAction, result: TResult, payload: Record<string, unknown>) => AltazionSuccessEventKind)\n getResultEventSuffixes?(action: TAction, result: TResult, payload: Record<string, unknown>): string[]\n}\n\ninterface HtmxConfigRequestEvent extends Event {\n detail: {\n headers: Record<string, string>\n elt: Element\n }\n}\n\ninterface MatchedAction<TModule extends string = string, TAction extends string = string, TResult = unknown> {\n definition: AltazionModuleDefinition<TModule, TAction, TResult>\n element: Element\n}\n\ninterface DisableableElement extends HTMLElement {\n disabled: boolean\n}\n\nconst EXTENSION_NAME = 'altazion'\nconst JSON_VALUES_ATTRIBUTE = 'hx-vals'\nconst REFRESH_ATTRIBUTE = 'hx-altazion-refresh'\nconst REFRESH_EVENT_NAME = 'altazion:refresh'\n\nconst REQUEST_ATTRIBUTES = [\n { attribute: 'hx-get', method: 'GET' },\n { attribute: 'hx-post', method: 'POST' },\n { attribute: 'hx-put', method: 'PUT' },\n { attribute: 'hx-patch', method: 'PATCH' },\n { attribute: 'hx-delete', method: 'DELETE' },\n] as const\n\nexport function createAltazionExtension(\n client: CommerceClient,\n modules: readonly AltazionModuleDefinition<any, any, any>[]\n): AltazionExtensionHandle {\n const requestHandler = (event: Event): void => {\n const e = event as HtmxConfigRequestEvent\n e.detail.headers['Accept-Language'] = client.context.locale\n e.detail.headers['X-Altazion-Currency'] = client.context.currency\n }\n\n if (typeof window !== 'undefined' && window.htmx) {\n window.htmx.on('htmx:configRequest', requestHandler)\n }\n\n if (typeof document === 'undefined') {\n return {\n dispose(): void {\n if (typeof window !== 'undefined' && window.htmx) {\n window.htmx.off('htmx:configRequest', requestHandler)\n }\n },\n }\n }\n\n const handleClick = (event: Event): void => {\n const mouseEvent = event as MouseEvent\n if (\n mouseEvent.defaultPrevented\n || mouseEvent.button !== 0\n || mouseEvent.metaKey\n || mouseEvent.ctrlKey\n || mouseEvent.shiftKey\n || mouseEvent.altKey\n ) {\n return\n }\n\n const target = event.target\n if (!(target instanceof Element)) {\n return\n }\n\n const matchedAction = findMatchedAction(target, modules)\n if (!matchedAction || matchedAction.element instanceof HTMLFormElement || !hasAltazionExtension(matchedAction.element)) {\n return\n }\n\n event.preventDefault()\n void runModuleAction(client, matchedAction)\n }\n\n const handleSubmit = (event: Event): void => {\n const target = event.target\n if (!(target instanceof HTMLFormElement)) {\n return\n }\n\n const matchedAction = findMatchedAction(target, modules)\n if (!matchedAction || matchedAction.element !== target || !hasAltazionExtension(target)) {\n return\n }\n\n event.preventDefault()\n void runModuleAction(client, matchedAction)\n }\n\n document.addEventListener('click', handleClick)\n document.addEventListener('submit', handleSubmit)\n\n return {\n dispose(): void {\n if (typeof window !== 'undefined' && window.htmx) {\n window.htmx.off('htmx:configRequest', requestHandler)\n }\n\n document.removeEventListener('click', handleClick)\n document.removeEventListener('submit', handleSubmit)\n },\n }\n}\n\nexport function requireString(value: unknown, fieldName: string): string {\n if (typeof value === 'string' && value.trim().length > 0) {\n return value.trim()\n }\n\n throw new Error(`Missing payload field: ${fieldName}`)\n}\n\nexport function requireNumber(value: unknown, fieldName: string): number {\n if (typeof value === 'number' && Number.isFinite(value)) {\n return value\n }\n\n if (typeof value === 'string' && value.trim().length > 0) {\n const parsed = Number(value)\n if (Number.isFinite(parsed)) {\n return parsed\n }\n }\n\n throw new Error(`Invalid payload field: ${fieldName}`)\n}\n\nexport function asRecord(value: unknown): Record<string, unknown> | undefined {\n if (!value || typeof value !== 'object' || Array.isArray(value)) {\n return undefined\n }\n\n return value as Record<string, unknown>\n}\n\nasync function runModuleAction<TModule extends string, TAction extends string, TResult>(\n client: CommerceClient,\n matchedAction: MatchedAction<TModule, TAction, TResult>\n): Promise<void> {\n const { definition, element } = matchedAction\n const action = readActionName(element, definition)\n const payload = collectPayload(element, definition)\n const releasePending = markPending(element)\n\n dispatchModuleEvent<TModule, TAction, undefined>(element, buildModuleEventName(definition.moduleName, 'before'), {\n module: definition.moduleName,\n action,\n element,\n payload,\n })\n\n try {\n const result = await definition.execute(client, action, payload)\n\n dispatchModuleEvent<TModule, TAction, TResult>(element, buildModuleEventName(definition.moduleName, 'after'), {\n module: definition.moduleName,\n action,\n element,\n payload,\n result,\n })\n\n const successEventKind = resolveSuccessEventKind(definition, action, result, payload)\n const emittedSuffixes = new Set<string>()\n\n if (successEventKind !== 'none') {\n emittedSuffixes.add(successEventKind)\n dispatchModuleEvent<TModule, TAction, TResult>(element, buildModuleEventName(definition.moduleName, successEventKind), {\n module: definition.moduleName,\n action,\n element,\n payload,\n result,\n })\n }\n\n for (const suffix of definition.getResultEventSuffixes?.(action, result, payload) ?? []) {\n if (emittedSuffixes.has(suffix)) {\n continue\n }\n\n dispatchModuleEvent<TModule, TAction, TResult>(element, buildModuleEventName(definition.moduleName, suffix), {\n module: definition.moduleName,\n action,\n element,\n payload,\n result,\n })\n }\n\n await refreshTargets(element)\n } catch (error) {\n const errorDetail = normalizeError(error)\n\n dispatchModuleEvent<TModule, TAction, undefined>(element, buildModuleEventName(definition.moduleName, 'error'), {\n module: definition.moduleName,\n action,\n element,\n payload,\n error,\n errorDetail,\n })\n console.error(`[AltazionHtmx] ${definition.moduleName} action failed`, error)\n } finally {\n releasePending()\n }\n}\n\nfunction findMatchedAction(\n target: Element,\n modules: readonly AltazionModuleDefinition<any, any, any>[]\n): MatchedAction | null {\n let current: Element | null = target\n\n while (current) {\n for (const definition of modules) {\n if (current.hasAttribute(definition.actionAttribute)) {\n return { definition, element: current }\n }\n }\n\n current = current.parentElement\n }\n\n return null\n}\n\nfunction readActionName<TModule extends string, TAction extends string, TResult>(\n element: Element,\n definition: AltazionModuleDefinition<TModule, TAction, TResult>\n): TAction {\n const action = element.getAttribute(definition.actionAttribute)\n if (!action) {\n throw new Error(`Missing ${definition.actionAttribute} attribute`)\n }\n\n return definition.parseAction(action)\n}\n\nfunction collectPayload<TModule extends string, TAction extends string, TResult>(\n element: Element,\n definition: AltazionModuleDefinition<TModule, TAction, TResult>\n): Record<string, unknown> {\n const payload: Record<string, unknown> = {}\n const form = element instanceof HTMLFormElement ? element : element.closest('form')\n\n if (form) {\n Object.assign(payload, formDataToObject(new FormData(form)))\n mergeJsonValues(payload, form)\n applyAttributePayload(payload, form, definition.payloadAttributes)\n applyJsonAttributePayload(payload, form, definition.jsonPayloadAttributes)\n }\n\n mergeJsonValues(payload, element)\n applyAttributePayload(payload, element, definition.payloadAttributes)\n applyJsonAttributePayload(payload, element, definition.jsonPayloadAttributes)\n applyPayloadAliases(payload, definition.payloadAliases)\n definition.normalizePayload?.(payload)\n\n return payload\n}\n\nfunction mergeJsonValues(payload: Record<string, unknown>, element: Element): void {\n const values = readJsonValues(element, JSON_VALUES_ATTRIBUTE)\n if (values) {\n Object.assign(payload, values)\n }\n}\n\nfunction applyAttributePayload(\n payload: Record<string, unknown>,\n element: Element,\n attributes?: Record<string, string>\n): void {\n if (!attributes) {\n return\n }\n\n for (const [attributeName, payloadKey] of Object.entries(attributes)) {\n const value = element.getAttribute(attributeName)\n if (value !== null) {\n payload[payloadKey] = value\n }\n }\n}\n\nfunction applyJsonAttributePayload(\n payload: Record<string, unknown>,\n element: Element,\n attributes?: Record<string, string>\n): void {\n if (!attributes) {\n return\n }\n\n for (const [attributeName, payloadKey] of Object.entries(attributes)) {\n const value = readJsonValues(element, attributeName)\n if (value !== undefined) {\n payload[payloadKey] = value\n }\n }\n}\n\nfunction applyPayloadAliases(payload: Record<string, unknown>, aliases?: Record<string, string>): void {\n if (!aliases) {\n return\n }\n\n for (const [alias, canonicalKey] of Object.entries(aliases)) {\n if (payload[alias] !== undefined && payload[canonicalKey] === undefined) {\n payload[canonicalKey] = payload[alias]\n }\n }\n}\n\nfunction formDataToObject(formData: FormData): Record<string, unknown> {\n const payload: Record<string, unknown> = {}\n\n for (const [key, value] of formData.entries()) {\n const normalizedValue = typeof value === 'string' ? value : value.name\n const previous = payload[key]\n\n if (previous === undefined) {\n payload[key] = normalizedValue\n } else if (Array.isArray(previous)) {\n previous.push(normalizedValue)\n } else {\n payload[key] = [previous, normalizedValue]\n }\n }\n\n return payload\n}\n\nfunction dispatchModuleEvent<TModule extends string, TAction extends string, TResult>(\n element: Element,\n eventName: string,\n detail: AltazionActionEventDetail<TModule, TAction, TResult>\n): void {\n element.dispatchEvent(new CustomEvent<AltazionActionEventDetail<TModule, TAction, TResult>>(eventName, {\n bubbles: true,\n detail,\n }))\n}\n\nfunction buildModuleEventName(moduleName: string, suffix: string): string {\n return `altazion:${moduleName}:${suffix}`\n}\n\nfunction resolveSuccessEventKind<TModule extends string, TAction extends string, TResult>(\n definition: AltazionModuleDefinition<TModule, TAction, TResult>,\n action: TAction,\n result: TResult,\n payload: Record<string, unknown>\n): AltazionSuccessEventKind {\n const configuredKind = definition.successEventKind\n if (typeof configuredKind === 'function') {\n return configuredKind(action, result, payload)\n }\n\n if (configuredKind) {\n return configuredKind\n }\n\n return inferSuccessEventKind(action, result)\n}\n\nfunction inferSuccessEventKind<TAction extends string, TResult>(action: TAction, result: TResult): AltazionSuccessEventKind {\n if (result === undefined) {\n return 'changed'\n }\n\n const normalizedAction = action.toLowerCase()\n if (\n normalizedAction.startsWith('get')\n || normalizedAction.startsWith('find')\n || normalizedAction.startsWith('search')\n || normalizedAction.startsWith('suggest')\n || normalizedAction.startsWith('load')\n || normalizedAction.startsWith('list')\n ) {\n return 'loaded'\n }\n\n return 'updated'\n}\n\nfunction normalizeError(error: unknown): AltazionActionErrorDetail {\n if (error instanceof AltazionApiError) {\n return {\n name: error.name,\n message: error.message,\n status: error.status,\n problem: error.problem,\n isOffline: false,\n isConflict: error.status === 409,\n }\n }\n\n if (error instanceof OfflineError) {\n return {\n name: error.name,\n message: error.message,\n isOffline: true,\n isConflict: false,\n }\n }\n\n if (error instanceof Error) {\n return {\n name: error.name,\n message: error.message,\n isOffline: false,\n isConflict: false,\n }\n }\n\n return {\n name: 'UnknownError',\n message: 'Unknown error',\n isOffline: false,\n isConflict: false,\n }\n}\n\nasync function refreshTargets(element: Element): Promise<void> {\n const targets = resolveRefreshTargets(element)\n if (targets.length === 0) {\n return\n }\n\n await Promise.all(targets.map((target) => refreshTargetElement(element, target)))\n}\n\nfunction resolveRefreshTargets(element: Element): Element[] {\n if (typeof document === 'undefined') {\n return []\n }\n\n const selectors = collectRefreshSelectors(element)\n if (selectors.length === 0) {\n return []\n }\n\n const targets = new Set<Element>()\n\n for (const selector of selectors) {\n try {\n for (const target of document.querySelectorAll(selector)) {\n targets.add(target)\n }\n } catch (error) {\n console.error(`[AltazionHtmx] invalid refresh selector: ${selector}`, error)\n }\n }\n\n return [...targets]\n}\n\nfunction collectRefreshSelectors(element: Element): string[] {\n const values = new Set<string>()\n const form = element instanceof HTMLFormElement ? element : element.closest('form')\n\n addRefreshSelectors(values, form)\n addRefreshSelectors(values, element)\n\n return [...values]\n}\n\nfunction addRefreshSelectors(values: Set<string>, element: Element | null): void {\n const rawValue = element?.getAttribute(REFRESH_ATTRIBUTE)\n if (!rawValue) {\n return\n }\n\n for (const selector of rawValue.split(';')) {\n const trimmed = selector.trim()\n if (trimmed.length > 0) {\n values.add(trimmed)\n }\n }\n}\n\nasync function refreshTargetElement(sourceElement: Element, targetElement: Element): Promise<void> {\n const request = readRefreshRequest(targetElement)\n if (request && typeof window !== 'undefined' && window.htmx?.ajax) {\n const context: {\n source: Element\n target: Element\n swap?: string\n select?: string\n values?: Record<string, unknown>\n } = {\n source: sourceElement,\n target: targetElement,\n }\n\n const swap = targetElement.getAttribute('hx-swap')\n if (swap) {\n context.swap = swap\n }\n\n const select = targetElement.getAttribute('hx-select')\n if (select) {\n context.select = select\n }\n\n const values = readJsonValues(targetElement, JSON_VALUES_ATTRIBUTE)\n if (values) {\n context.values = values\n }\n\n await Promise.resolve(window.htmx.ajax(request.method, request.path, context))\n return\n }\n\n targetElement.dispatchEvent(new CustomEvent(REFRESH_EVENT_NAME, {\n bubbles: true,\n detail: {\n source: sourceElement,\n target: targetElement,\n },\n }))\n}\n\nfunction readRefreshRequest(element: Element): { method: string, path: string } | null {\n for (const requestAttribute of REQUEST_ATTRIBUTES) {\n const path = element.getAttribute(requestAttribute.attribute)\n if (path) {\n return {\n method: requestAttribute.method,\n path,\n }\n }\n }\n\n return null\n}\n\nfunction readJsonValues(element: Element, attributeName: string): Record<string, unknown> | undefined {\n const raw = element.getAttribute(attributeName)\n if (!raw) {\n return undefined\n }\n\n try {\n const parsed = JSON.parse(raw) as unknown\n if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) {\n return parsed as Record<string, unknown>\n }\n } catch {\n throw new Error(`Invalid JSON in ${attributeName}`)\n }\n\n return undefined\n}\n\nfunction markPending(element: Element): () => void {\n const previousBusy = element.getAttribute('aria-busy')\n element.setAttribute('aria-busy', 'true')\n\n const disableable = isDisableableElement(element) ? element : null\n const previousDisabled = disableable?.disabled ?? false\n if (disableable) {\n disableable.disabled = true\n }\n\n return (): void => {\n if (previousBusy === null) {\n element.removeAttribute('aria-busy')\n } else {\n element.setAttribute('aria-busy', previousBusy)\n }\n\n if (disableable) {\n disableable.disabled = previousDisabled\n }\n }\n}\n\nfunction isDisableableElement(element: Element): element is DisableableElement {\n return 'disabled' in element\n}\n\nfunction hasAltazionExtension(element: Element): boolean {\n let current: Element | null = element\n while (current) {\n const extensions = current.getAttribute('hx-ext')\n if (extensions && parseExtensions(extensions).includes(EXTENSION_NAME)) {\n return true\n }\n\n current = current.parentElement\n }\n\n return false\n}\n\nfunction parseExtensions(value: string): string[] {\n return value\n .split(/[\\s,]+/)\n .map((extension) => extension.trim())\n .filter((extension) => extension.length > 0)\n}","import type { Cart, CartValidationStatus, CommerceClient } from '@altazion/commerce-sdk-core'\n\nimport {\n asRecord,\n requireNumber,\n requireString,\n type AltazionModuleDefinition,\n type AltazionSuccessEventKind,\n} from '../altazion-engine'\n\nexport type AltazionCartActionName =\n | 'getCart'\n | 'getValidationStatus'\n | 'addItem'\n | 'updateItem'\n | 'removeItem'\n | 'applyCoupon'\n | 'removeCoupon'\n\nexport type CartActionResult = Cart | CartValidationStatus\n\nexport const cartModuleDefinition: AltazionModuleDefinition<'cart', AltazionCartActionName, CartActionResult> = {\n moduleName: 'cart',\n actionAttribute: 'hx-altazion-cart-action',\n payloadAttributes: {\n 'hx-altazion-cart-reference': 'reference',\n 'hx-altazion-cart-quantity': 'quantity',\n 'hx-altazion-cart-line-id': 'lineId',\n 'hx-altazion-cart-code': 'code',\n },\n jsonPayloadAttributes: {\n 'hx-altazion-cart-options': 'options',\n },\n payloadAliases: {\n ref: 'reference',\n productReference: 'reference',\n qty: 'quantity',\n line: 'lineId',\n coupon: 'code',\n },\n parseAction(actionValue: string): AltazionCartActionName {\n switch (actionValue) {\n case 'getCart':\n case 'getValidationStatus':\n case 'addItem':\n case 'updateItem':\n case 'removeItem':\n case 'applyCoupon':\n case 'removeCoupon':\n return actionValue\n default:\n throw new Error(`Unsupported cart action: ${actionValue}`)\n }\n },\n execute(client: CommerceClient, action: AltazionCartActionName, payload: Record<string, unknown>): Promise<CartActionResult> {\n switch (action) {\n case 'getCart':\n return client.cart.getCart()\n case 'getValidationStatus':\n return client.cart.getValidationStatus()\n case 'addItem': {\n const reference = requireString(payload.reference, 'reference')\n const quantity = requireNumber(payload.quantity, 'quantity')\n const options = buildAddItemOptions(payload)\n return client.cart.addItem(reference, quantity, options)\n }\n case 'updateItem': {\n const lineId = requireString(payload.lineId, 'lineId')\n const quantity = requireNumber(payload.quantity, 'quantity')\n return client.cart.updateItem(lineId, quantity)\n }\n case 'removeItem':\n return client.cart.removeItem(requireString(payload.lineId, 'lineId'))\n case 'applyCoupon':\n return client.cart.applyCoupon(requireString(payload.code, 'code'))\n case 'removeCoupon':\n return client.cart.removeCoupon(requireString(payload.code, 'code'))\n }\n },\n successEventKind(action: AltazionCartActionName): AltazionSuccessEventKind {\n switch (action) {\n case 'getCart':\n return 'loaded'\n case 'getValidationStatus':\n return 'none'\n case 'addItem':\n case 'updateItem':\n case 'removeItem':\n case 'applyCoupon':\n case 'removeCoupon':\n return 'updated'\n }\n },\n getResultEventSuffixes(_action: AltazionCartActionName, result: CartActionResult): string[] {\n return isCart(result) ? ['updated'] : ['status']\n },\n}\n\nfunction buildAddItemOptions(payload: Record<string, unknown>): Record<string, unknown> | undefined {\n const options = asRecord(payload.options)\n const extraEntries = Object.entries(payload).filter(([key]) => ![\n 'reference',\n 'ref',\n 'productReference',\n 'quantity',\n 'qty',\n 'options',\n ].includes(key))\n\n if (extraEntries.length === 0 && !options) {\n return undefined\n }\n\n return {\n ...Object.fromEntries(extraEntries),\n ...options,\n }\n}\n\nfunction isCart(result: CartActionResult): result is Cart {\n return 'guid' in result\n}","import type { CommerceClient, SessionInfo } from '@altazion/commerce-sdk-core'\n\nimport {\n type AltazionModuleDefinition,\n type AltazionSuccessEventKind,\n} from '../altazion-engine'\n\nexport type AltazionSessionActionName = 'getSession'\n\nexport const sessionModuleDefinition: AltazionModuleDefinition<'session', AltazionSessionActionName, SessionInfo> = {\n moduleName: 'session',\n actionAttribute: 'hx-altazion-session-action',\n parseAction(actionValue: string): AltazionSessionActionName {\n switch (actionValue) {\n case 'getSession':\n return actionValue\n default:\n throw new Error(`Unsupported session action: ${actionValue}`)\n }\n },\n execute(client: CommerceClient, action: AltazionSessionActionName): Promise<SessionInfo> {\n switch (action) {\n case 'getSession':\n return client.session.getSession()\n }\n },\n successEventKind(): AltazionSuccessEventKind {\n return 'loaded'\n },\n}","import type { CommerceClient, MarketingItem } from '@altazion/commerce-sdk-core'\n\nimport {\n requireString,\n type AltazionModuleDefinition,\n type AltazionSuccessEventKind,\n} from '../altazion-engine'\n\nexport type AltazionMarketingActionName = 'getItem' | 'getItems'\n\nexport type MarketingActionResult = MarketingItem | MarketingItem[]\n\nexport const marketingModuleDefinition: AltazionModuleDefinition<'marketing', AltazionMarketingActionName, MarketingActionResult> = {\n moduleName: 'marketing',\n actionAttribute: 'hx-altazion-marketing-action',\n payloadAttributes: {\n 'hx-altazion-marketing-code': 'code',\n },\n jsonPayloadAttributes: {\n 'hx-altazion-marketing-codes': 'codes',\n },\n parseAction(actionValue: string): AltazionMarketingActionName {\n switch (actionValue) {\n case 'getItem':\n case 'getItems':\n return actionValue\n default:\n throw new Error(`Unsupported marketing action: ${actionValue}`)\n }\n },\n execute(client: CommerceClient, action: AltazionMarketingActionName, payload: Record<string, unknown>): Promise<MarketingActionResult> {\n switch (action) {\n case 'getItem':\n return client.marketing.getItem(requireString(payload.code, 'code'))\n case 'getItems':\n return client.marketing.getItems(readCodes(payload))\n }\n },\n successEventKind(): AltazionSuccessEventKind {\n return 'loaded'\n },\n getResultEventSuffixes(action: AltazionMarketingActionName): string[] {\n switch (action) {\n case 'getItem':\n return ['item-loaded']\n case 'getItems':\n return ['items-loaded']\n }\n },\n}\n\nfunction readCodes(payload: Record<string, unknown>): string[] {\n const value = payload.codes\n\n if (Array.isArray(value)) {\n const codes = value\n .filter((entry): entry is string => typeof entry === 'string')\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0)\n\n if (codes.length > 0) {\n return codes\n }\n }\n\n if (typeof value === 'string') {\n const codes = value\n .split(',')\n .map((entry) => entry.trim())\n .filter((entry) => entry.length > 0)\n\n if (codes.length > 0) {\n return codes\n }\n }\n\n if (typeof payload.code === 'string' && payload.code.trim().length > 0) {\n return [payload.code.trim()]\n }\n\n throw new Error('Missing payload field: codes')\n}","import type { CommerceClient, StoreWithOpeningHours } from '@altazion/commerce-sdk-core'\n\nimport {\n requireNumber,\n requireString,\n type AltazionModuleDefinition,\n type AltazionSuccessEventKind,\n} from '../altazion-engine'\n\nexport type AltazionStoresActionName = 'findByLocation' | 'findByPostalCode' | 'getStore'\n\nexport type StoresActionResult = StoreWithOpeningHours | StoreWithOpeningHours[]\n\nexport const storesModuleDefinition: AltazionModuleDefinition<'stores', AltazionStoresActionName, StoresActionResult> = {\n moduleName: 'stores',\n actionAttribute: 'hx-altazion-stores-action',\n payloadAttributes: {\n 'hx-altazion-stores-store-guid': 'storeGuid',\n 'hx-altazion-stores-latitude': 'latitude',\n 'hx-altazion-stores-longitude': 'longitude',\n 'hx-altazion-stores-radius-km': 'radiusKm',\n 'hx-altazion-stores-postal-code': 'postalCode',\n 'hx-altazion-stores-country-code': 'countryCode',\n },\n payloadAliases: {\n lat: 'latitude',\n lon: 'longitude',\n lng: 'longitude',\n radius: 'radiusKm',\n storeId: 'storeGuid',\n id: 'storeGuid',\n postal: 'postalCode',\n country: 'countryCode',\n },\n parseAction(actionValue: string): AltazionStoresActionName {\n switch (actionValue) {\n case 'findByLocation':\n case 'findByPostalCode':\n case 'getStore':\n return actionValue\n default:\n throw new Error(`Unsupported stores action: ${actionValue}`)\n }\n },\n execute(client: CommerceClient, action: AltazionStoresActionName, payload: Record<string, unknown>): Promise<StoresActionResult> {\n switch (action) {\n case 'findByLocation': {\n const latitude = requireNumber(payload.latitude, 'latitude')\n const longitude = requireNumber(payload.longitude, 'longitude')\n const radiusKm = payload.radiusKm === undefined ? 50 : requireNumber(payload.radiusKm, 'radiusKm')\n return client.stores.findByLocation(latitude, longitude, radiusKm)\n }\n case 'findByPostalCode': {\n const postalCode = requireString(payload.postalCode, 'postalCode')\n const countryCode = payload.countryCode === undefined\n ? 'FR'\n : requireString(payload.countryCode, 'countryCode')\n return client.stores.findByPostalCode(postalCode, countryCode)\n }\n case 'getStore':\n return client.stores.getStore(requireString(payload.storeGuid, 'storeGuid'))\n }\n },\n successEventKind(): AltazionSuccessEventKind {\n return 'loaded'\n },\n getResultEventSuffixes(action: AltazionStoresActionName): string[] {\n switch (action) {\n case 'getStore':\n return ['store-loaded']\n case 'findByLocation':\n case 'findByPostalCode':\n return ['stores-loaded']\n }\n },\n}","import type { CommerceClient } from '@altazion/commerce-sdk-core'\n\nimport {\n createAltazionExtension,\n type AltazionActionEventDetail,\n type AltazionActionErrorDetail,\n type AltazionExtensionHandle,\n type AltazionSuccessEventKind,\n} from './altazion-engine'\nimport {\n cartModuleDefinition,\n type AltazionCartActionName,\n} from './modules/cart'\nimport {\n sessionModuleDefinition,\n type AltazionSessionActionName,\n} from './modules/session'\nimport {\n marketingModuleDefinition,\n type AltazionMarketingActionName,\n} from './modules/marketing'\nimport {\n storesModuleDefinition,\n type AltazionStoresActionName,\n} from './modules/stores'\n\nexport type { AltazionCartActionName }\nexport type { AltazionMarketingActionName }\nexport type { AltazionSessionActionName }\nexport type { AltazionStoresActionName }\nexport type {\n AltazionActionEventDetail,\n AltazionActionErrorDetail,\n AltazionExtensionHandle,\n AltazionSuccessEventKind,\n}\n\nexport type AltazionCartEventDetail<TResult = unknown> = AltazionActionEventDetail<\n 'cart',\n AltazionCartActionName,\n TResult\n>\n\nexport type AltazionSessionEventDetail<TResult = unknown> = AltazionActionEventDetail<\n 'session',\n AltazionSessionActionName,\n TResult\n>\n\nexport type AltazionMarketingEventDetail<TResult = unknown> = AltazionActionEventDetail<\n 'marketing',\n AltazionMarketingActionName,\n TResult\n>\n\nexport type AltazionStoresEventDetail<TResult = unknown> = AltazionActionEventDetail<\n 'stores',\n AltazionStoresActionName,\n TResult\n>\n\n/**\n * Extension HTMX Altazion.\n *\n * - Ajoute les headers de contexte Altazion sur les requêtes HTMX\n * - Interprète les attributs `hx-altazion-cart-action`, `hx-altazion-session-action`,\n * `hx-altazion-marketing-action` et `hx-altazion-stores-action`\n * pour appeler le SDK core\n * - Émet des événements DOM `altazion:cart:*`, `altazion:session:*`,\n * `altazion:marketing:*` et `altazion:stores:*`\n * exploitables par HTMX\n */\nexport function registerAltazionExtension(client: CommerceClient): AltazionExtensionHandle {\n return createAltazionExtension(client, [\n cartModuleDefinition,\n sessionModuleDefinition,\n marketingModuleDefinition,\n storesModuleDefinition,\n ])\n}\n\nexport const registerAltazionAuthExtension = registerAltazionExtension\n","import type Handlebars from 'handlebars'\n\ntype HandlebarsInstance = typeof Handlebars\n\n/**\n * Formate un montant selon la locale et la devise.\n * Usage : {{formatPrice 19.99 \"EUR\" \"fr-FR\"}}\n * Si locale/currency sont omis, utilise les valeurs passées au registre.\n */\nexport function registerPriceHelpers(\n hbs: HandlebarsInstance,\n defaults: { locale: string; currency: string }\n): void {\n hbs.registerHelper(\n 'formatPrice',\n function (\n value: unknown,\n currency?: unknown,\n locale?: unknown\n ): string {\n const amount = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(amount)) return ''\n\n const resolvedCurrency =\n typeof currency === 'string' ? currency : defaults.currency\n const resolvedLocale =\n typeof locale === 'string' ? locale : defaults.locale\n\n return new Intl.NumberFormat(resolvedLocale, {\n style: 'currency',\n currency: resolvedCurrency,\n }).format(amount)\n }\n )\n\n hbs.registerHelper(\n 'formatPriceCompact',\n function (value: unknown, currency?: unknown, locale?: unknown): string {\n const amount = typeof value === 'number' ? value : parseFloat(String(value))\n if (isNaN(amount)) return ''\n\n const resolvedCurrency =\n typeof currency === 'string' ? currency : defaults.currency\n const resolvedLocale =\n typeof locale === 'string' ? locale : defaults.locale\n\n return new Intl.NumberFormat(resolvedLocale, {\n style: 'currency',\n currency: resolvedCurrency,\n notation: 'compact',\n }).format(amount)\n }\n )\n\n hbs.registerHelper(\n 'discountPercent',\n function (original: unknown, discounted: unknown): string {\n const orig = typeof original === 'number' ? original : parseFloat(String(original))\n const disc = typeof discounted === 'number' ? discounted : parseFloat(String(discounted))\n if (isNaN(orig) || isNaN(disc) || orig === 0) return ''\n const pct = Math.round(((orig - disc) / orig) * 100)\n return `-${pct}%`\n }\n )\n}\n","import type Handlebars from 'handlebars'\n\ntype HandlebarsInstance = typeof Handlebars\n\n/**\n * Helpers Handlebars liés aux produits.\n *\n * Usage :\n * {{productUrl reference}}\n * {{thumbnailUrl imageUrl 400}}\n * {{#if (isAvailable availability)}} ... {{/if}}\n */\nexport function registerProductHelpers(hbs: HandlebarsInstance, siteUrl: string): void {\n // URL de la fiche produit côté site vitrine\n hbs.registerHelper('productUrl', function (reference: unknown): string {\n if (typeof reference !== 'string' && typeof reference !== 'number') return ''\n const base = siteUrl.replace(/\\/$/, '')\n return `${base}/product/${encodeURIComponent(String(reference))}`\n })\n\n // Transforme une URL d'image en URL redimensionnée si le serveur le supporte\n // Pattern attendu : /media/images/{id} → /media/images/{id}?w={size}\n hbs.registerHelper('thumbnailUrl', function (imageUrl: unknown, size?: unknown): string {\n if (typeof imageUrl !== 'string' || !imageUrl) return ''\n const resolvedSize = typeof size === 'number' ? size : 300\n const separator = imageUrl.includes('?') ? '&' : '?'\n return `${imageUrl}${separator}w=${resolvedSize}`\n })\n\n // Retourne true si le produit est disponible (availability > 0 ou pas de stock géré)\n hbs.registerHelper('isAvailable', function (availability: unknown): boolean {\n if (availability === null || availability === undefined) return true\n if (typeof availability === 'boolean') return availability\n if (typeof availability === 'number') return availability > 0\n if (typeof availability === 'string') {\n const lower = availability.toLowerCase()\n return lower === 'available' || lower === 'instock'\n }\n return false\n })\n\n // Helper ifCond simple pour les comparaisons dans les templates\n hbs.registerHelper(\n 'ifCond',\n function (\n this: unknown,\n v1: unknown,\n operator: string,\n v2: unknown,\n options: Handlebars.HelperOptions\n ): string {\n let result = false\n switch (operator) {\n case '==': result = v1 == v2; break\n case '===': result = v1 === v2; break\n case '!=': result = v1 != v2; break\n case '!==': result = v1 !== v2; break\n case '>': result = (v1 as number) > (v2 as number); break\n case '<': result = (v1 as number) < (v2 as number); break\n case '>=': result = (v1 as number) >= (v2 as number); break\n case '<=': result = (v1 as number) <= (v2 as number); break\n default: result = false\n }\n return result ? options.fn(this as object) : options.inverse(this as object)\n }\n )\n}\n","import type Handlebars from 'handlebars'\nimport type { Cart, CartContent } from '@altazion/commerce-sdk-core'\n\ntype HandlebarsInstance = typeof Handlebars\n\n/**\n * Helpers Handlebars liés au panier.\n *\n * Nécessite un getter réactif sur le panier actuel.\n * Usage :\n * Nombre d'articles : {{cartCount}}\n * Total : {{cartTotal}}\n * {{#if cartHasItems}} ... {{/if}}\n */\nexport function registerCartHelpers(\n hbs: HandlebarsInstance,\n getCart: () => Cart | null,\n defaults: { locale: string; currency: string }\n): void {\n hbs.registerHelper('cartCount', function (): number {\n const cart = getCart()\n if (!cart) return 0\n return cart.totalQuantity\n })\n\n hbs.registerHelper('cartTotal', function (): string {\n const cart = getCart()\n if (!cart) return ''\n return new Intl.NumberFormat(defaults.locale, {\n style: 'currency',\n currency: defaults.currency,\n }).format(cart.totalAmountWithTax)\n })\n\n hbs.registerHelper('cartTotalRaw', function (): number {\n const cart = getCart()\n return cart?.totalAmountWithTax ?? 0\n })\n\n hbs.registerHelper('cartHasItems', function (this: unknown, options: Handlebars.HelperOptions): string {\n const cart = getCart()\n const hasItems = cart ? cart.totalQuantity > 0 : false\n return hasItems ? options.fn(this as object) : options.inverse(this as object)\n })\n\n hbs.registerHelper('cartLineCount', function (): number {\n const cart = getCart()\n if (!cart?.content) return 0\n return cart.content.reduce((sum: number, group: CartContent) => sum + (group.lines?.length ?? 0), 0)\n })\n}\n","import type { Cart, MarketingItem, SessionInfo, StoreWithOpeningHours } from '@altazion/commerce-sdk-core'\nimport type Handlebars from 'handlebars'\n\nexport interface AltazionDeclarativeViewModel {\n cart: Cart | null\n session: SessionInfo | null\n store: StoreWithOpeningHours | null\n stores: StoreWithOpeningHours[]\n marketingItem: MarketingItem | null\n marketingItems: MarketingItem[]\n slots: Record<string, unknown>\n}\n\nexport interface AltazionDeclarativeRendererHandle {\n update<K extends keyof AltazionDeclarativeViewModel>(\n key: K,\n value: AltazionDeclarativeViewModel[K]\n ): void\n updateSlot(name: string, value: unknown): void\n render(): void\n dispose(): void\n}\n\ntype HandlebarsRuntime = typeof Handlebars\ntype ViewModelKey = keyof AltazionDeclarativeViewModel\ntype DataSourceReference =\n | { kind: 'state', key: ViewModelKey }\n | { kind: 'slot', key: string }\n\nconst DATA_SOURCE_ATTRIBUTE = 'hx-altazion-data-source'\nconst DATA_STATUS_ATTRIBUTE = 'hx-altazion-data-status'\nconst RENDER_TEMPLATE_ATTRIBUTE = 'hx-render-template'\n\nconst DATA_SOURCE_ALIASES: Record<string, ViewModelKey> = {\n cart: 'cart',\n session: 'session',\n store: 'store',\n stores: 'stores',\n 'marketing-item': 'marketingItem',\n 'marketing-items': 'marketingItems',\n}\n\nexport function createAltazionDeclarativeRenderer(\n handlebars?: HandlebarsRuntime\n): AltazionDeclarativeRendererHandle {\n const state: AltazionDeclarativeViewModel = {\n cart: null,\n session: null,\n store: null,\n stores: [],\n marketingItem: null,\n marketingItems: [],\n slots: {},\n }\n\n const templateCache = new Map<string, (context: AltazionDeclarativeViewModel) => string>()\n\n const render = (): void => {\n if (typeof document === 'undefined') {\n return\n }\n\n for (const element of document.querySelectorAll(`[${DATA_SOURCE_ATTRIBUTE}]`)) {\n const rawSource = element.getAttribute(DATA_SOURCE_ATTRIBUTE)\n const source = resolveDataSource(rawSource)\n if (!source) {\n continue\n }\n\n const rawStatus = element.getAttribute(DATA_STATUS_ATTRIBUTE)\n const sourceValue = resolveSourceValue(state, source)\n const isVisible = matchesStatus(rawStatus, sourceValue)\n applyVisibility(element, isVisible)\n renderElementTemplate(element, isVisible, state, sourceValue, handlebars, templateCache)\n }\n }\n\n return {\n update(key, value): void {\n state[key] = value\n render()\n },\n updateSlot(name, value): void {\n state.slots[name] = value\n render()\n },\n render,\n dispose(): void {\n templateCache.clear()\n },\n }\n}\n\nfunction matchesStatus(status: string | null, value: unknown): boolean {\n if (Array.isArray(value)) {\n switch (status) {\n case 'empty':\n return value.length === 0\n case 'not-empty':\n return value.length > 0\n default:\n return true\n }\n }\n\n switch (status) {\n case 'null':\n return value == null\n case 'not-null':\n return value != null\n default:\n return true\n }\n}\n\nfunction resolveDataSource(source: string | null): DataSourceReference | null {\n if (!source) {\n return null\n }\n\n if (source.startsWith('slot:')) {\n const slotKey = source.slice(5).trim()\n return slotKey.length > 0 ? { kind: 'slot', key: slotKey } : null\n }\n\n const resolvedKey = DATA_SOURCE_ALIASES[source]\n return resolvedKey ? { kind: 'state', key: resolvedKey } : null\n}\n\nfunction resolveSourceValue(\n state: AltazionDeclarativeViewModel,\n source: DataSourceReference\n): unknown {\n if (source.kind === 'slot') {\n return state.slots[source.key] ?? null\n }\n\n return state[source.key]\n}\n\nfunction applyVisibility(element: Element, isVisible: boolean): void {\n element.setAttribute('aria-hidden', isVisible ? 'false' : 'true')\n\n if (element instanceof HTMLElement) {\n element.hidden = !isVisible\n } else if (isVisible) {\n element.removeAttribute('hidden')\n } else {\n element.setAttribute('hidden', '')\n }\n}\n\nfunction renderElementTemplate(\n element: Element,\n isVisible: boolean,\n state: AltazionDeclarativeViewModel,\n sourceValue: unknown,\n handlebars: HandlebarsRuntime | undefined,\n templateCache: Map<string, (context: AltazionDeclarativeViewModel) => string>\n): void {\n if (!isVisible || !element.hasAttribute(RENDER_TEMPLATE_ATTRIBUTE) || !handlebars) {\n return\n }\n\n const templateId = element.getAttribute(RENDER_TEMPLATE_ATTRIBUTE)\n if (!templateId) {\n return\n }\n\n const template = resolveTemplate(templateId, handlebars, templateCache)\n if (!template) {\n return\n }\n\n element.innerHTML = template({\n ...state,\n slot: sourceValue,\n } as AltazionDeclarativeViewModel)\n}\n\nfunction resolveTemplate(\n templateId: string,\n handlebars: HandlebarsRuntime,\n templateCache: Map<string, (context: AltazionDeclarativeViewModel) => string>\n): ((context: AltazionDeclarativeViewModel) => string) | null {\n const cached = templateCache.get(templateId)\n if (cached) {\n return cached\n }\n\n if (typeof document === 'undefined') {\n return null\n }\n\n const templateElement = document.getElementById(templateId)\n if (!templateElement) {\n console.warn(`[AltazionHtmx] Template not found: ${templateId}`)\n return null\n }\n\n const compiled = handlebars.compile(templateElement.innerHTML)\n templateCache.set(templateId, compiled)\n return compiled\n}","export default \"<article class=\\\"altz-product-card{{#unless (isAvailable availability)}} altz-product-card--unavailable{{/unless}}\\\">\\n {{#if imageUrl}}\\n <a href=\\\"{{productUrl reference}}\\\" class=\\\"altz-product-card__image-link\\\" aria-label=\\\"{{name}}\\\">\\n <img\\n src=\\\"{{thumbnailUrl imageUrl 400}}\\\"\\n alt=\\\"{{name}}\\\"\\n class=\\\"altz-product-card__image\\\"\\n loading=\\\"lazy\\\"\\n width=\\\"400\\\"\\n />\\n </a>\\n {{/if}}\\n\\n <div class=\\\"altz-product-card__body\\\">\\n <a href=\\\"{{productUrl reference}}\\\" class=\\\"altz-product-card__title\\\">\\n {{name}}\\n </a>\\n\\n <div class=\\\"altz-product-card__pricing\\\">\\n {{#if discount}}\\n <span class=\\\"altz-product-card__price altz-product-card__price--discounted\\\">\\n {{formatPrice price}}\\n </span>\\n <span class=\\\"altz-product-card__price altz-product-card__price--original\\\">\\n {{formatPrice originalPrice}}\\n </span>\\n <span class=\\\"altz-product-card__discount-badge\\\">\\n {{discountPercent originalPrice price}}\\n </span>\\n {{else}}\\n <span class=\\\"altz-product-card__price\\\">\\n {{formatPrice price}}\\n </span>\\n {{/if}}\\n </div>\\n\\n {{#unless (isAvailable availability)}}\\n <p class=\\\"altz-product-card__unavailable\\\">{{unavailableLabel}}</p>\\n {{/unless}}\\n\\n {{#if (isAvailable availability)}}\\n <button\\n class=\\\"altz-product-card__add-to-cart\\\"\\n hx-ext=\\\"altazion\\\"\\n hx-altazion-cart-action=\\\"addItem\\\"\\n hx-altazion-cart-reference=\\\"{{reference}}\\\"\\n hx-altazion-cart-quantity=\\\"1\\\"\\n hx-altazion-refresh=\\\"#altz-cart-mini\\\"\\n hx-indicator=\\\".altz-spinner\\\"\\n >\\n {{addToCartLabel}}\\n </button>\\n {{/if}}\\n </div>\\n</article>\\n\"","export default \"<div id=\\\"altz-cart-mini\\\" class=\\\"altz-cart-mini\\\">\\n <div class=\\\"altz-cart-mini__header\\\">\\n <span class=\\\"altz-cart-mini__label\\\">{{cartLabel}}</span>\\n <span class=\\\"altz-cart-mini__count\\\">{{cartCount}}</span>\\n </div>\\n\\n {{#cartHasItems}}\\n <ul class=\\\"altz-cart-mini__lines\\\">\\n {{#each lines}}\\n <li class=\\\"altz-cart-mini__line\\\">\\n <span class=\\\"altz-cart-mini__line-name\\\">{{this.productName}}</span>\\n <span class=\\\"altz-cart-mini__line-qty\\\">× {{this.quantity}}</span>\\n <span class=\\\"altz-cart-mini__line-price\\\">{{formatPrice this.unitPriceWithTax}}</span>\\n </li>\\n {{/each}}\\n </ul>\\n\\n <div class=\\\"altz-cart-mini__total\\\">\\n <span>{{totalLabel}}</span>\\n <strong>{{cartTotal}}</strong>\\n </div>\\n\\n <a href=\\\"{{cartUrl}}\\\" class=\\\"altz-cart-mini__cta\\\">\\n {{viewCartLabel}}\\n </a>\\n {{/cartHasItems}}\\n\\n {{^cartHasItems}}\\n <p class=\\\"altz-cart-mini__empty\\\">{{emptyLabel}}</p>\\n {{/cartHasItems}}\\n</div>\\n\"","export default \"<section class=\\\"altz-product-list\\\">\\n {{#if title}}\\n <h2 class=\\\"altz-product-list__title\\\">{{title}}</h2>\\n {{/if}}\\n\\n {{#if products.length}}\\n <ul class=\\\"altz-product-list__grid\\\" role=\\\"list\\\">\\n {{#each products}}\\n <li class=\\\"altz-product-list__item\\\">\\n <article class=\\\"altz-product-card{{#unless (isAvailable this.availability)}} altz-product-card--unavailable{{/unless}}\\\">\\n {{#if this.imageUrl}}\\n <a href=\\\"{{productUrl this.reference}}\\\" class=\\\"altz-product-card__image-link\\\" aria-label=\\\"{{this.name}}\\\">\\n <img\\n src=\\\"{{thumbnailUrl this.imageUrl 300}}\\\"\\n alt=\\\"{{this.name}}\\\"\\n class=\\\"altz-product-card__image\\\"\\n loading=\\\"lazy\\\"\\n width=\\\"300\\\"\\n />\\n </a>\\n {{/if}}\\n\\n <div class=\\\"altz-product-card__body\\\">\\n <a href=\\\"{{productUrl this.reference}}\\\" class=\\\"altz-product-card__title\\\">\\n {{this.name}}\\n </a>\\n\\n <div class=\\\"altz-product-card__pricing\\\">\\n {{#if this.discount}}\\n <span class=\\\"altz-product-card__price altz-product-card__price--discounted\\\">\\n {{formatPrice this.price}}\\n </span>\\n <span class=\\\"altz-product-card__price altz-product-card__price--original\\\">\\n {{formatPrice this.originalPrice}}\\n </span>\\n <span class=\\\"altz-product-card__discount-badge\\\">\\n {{discountPercent this.originalPrice this.price}}\\n </span>\\n {{else}}\\n <span class=\\\"altz-product-card__price\\\">\\n {{formatPrice this.price}}\\n </span>\\n {{/if}}\\n </div>\\n\\n {{#if (isAvailable this.availability)}}\\n <button\\n class=\\\"altz-product-card__add-to-cart\\\"\\n hx-ext=\\\"altazion\\\"\\n hx-altazion-cart-action=\\\"addItem\\\"\\n hx-altazion-cart-reference=\\\"{{this.reference}}\\\"\\n hx-altazion-cart-quantity=\\\"1\\\"\\n hx-altazion-refresh=\\\"#altz-cart-mini\\\"\\n hx-indicator=\\\".altz-spinner\\\"\\n >\\n {{../addToCartLabel}}\\n </button>\\n {{/if}}\\n </div>\\n </article>\\n </li>\\n {{/each}}\\n </ul>\\n {{else}}\\n <p class=\\\"altz-product-list__empty\\\">{{emptyLabel}}</p>\\n {{/if}}\\n</section>\\n\"","import type { CommerceClient, Cart, ConnectivityStatus, SessionInfo, StoreWithOpeningHours } from '@altazion/commerce-sdk-core'\nimport type Handlebars from 'handlebars'\n\nimport {\n registerAltazionExtension,\n type AltazionActionEventDetail,\n type AltazionCartEventDetail,\n type AltazionExtensionHandle,\n type AltazionMarketingEventDetail,\n type AltazionSessionEventDetail,\n type AltazionStoresEventDetail,\n} from './extensions/altazion-auth'\nimport { registerPriceHelpers } from './helpers/price'\nimport { registerProductHelpers } from './helpers/product'\nimport { registerCartHelpers } from './helpers/cart'\nimport { createAltazionDeclarativeRenderer } from './rendering/declarative-renderer'\n\n// Templates pré-compilés importés en tant que chaînes brutes\nimport productCardTemplate from './templates/product-card.hbs?raw'\nimport cartMiniTemplate from './templates/cart-mini.hbs?raw'\nimport productListTemplate from './templates/product-list.hbs?raw'\n\nexport type { Cart }\n\ntype SelectorInput = string | string[]\n\nexport interface AltazionTerminalModeConfig {\n /** Zones interactives à masquer en mode hors ligne. */\n interactiveSelectors?: SelectorInput\n /** Zones passives à afficher en mode hors ligne. */\n offlineScreenSelectors?: SelectorInput\n}\n\nexport interface AltazionConnectivityEventDetail {\n status: ConnectivityStatus\n isOnline: boolean\n isOffline: boolean\n root: Element\n}\n\nexport interface AltazionHtmxConfig {\n /** Instance CommerceClient déjà initialisée */\n client: CommerceClient\n /**\n * Instance Handlebars (global ou importée).\n * Si omis, les helpers ne sont pas enregistrés.\n */\n handlebars?: typeof Handlebars\n /**\n * Sélecteur CSS de l'élément DOM à basculer avec la classe `altz-offline`\n * lorsque la connectivité est perdue/restaurée.\n * @default 'body'\n */\n offlineSelector?: string\n /** Configuration UI du mode hors ligne borne. */\n terminalMode?: AltazionTerminalModeConfig\n}\n\nexport interface AltazionHtmxInstance {\n /** Templates Handlebars compilés prêts à l'emploi */\n templates: {\n productCard: HandlebarsTemplateDelegate\n cartMini: HandlebarsTemplateDelegate\n productList: HandlebarsTemplateDelegate\n }\n /** Détruit les listeners et libère les ressources */\n dispose(): void\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\ntype HandlebarsTemplateDelegate = (context?: any) => string\n\n/**\n * Initialise le SDK HTMX Altazion.\n *\n * - Enregistre l'extension HTMX (headers contexte) si htmx est présent\n * - Enregistre les helpers Handlebars (prix, produits, panier) si hbs est fourni\n * - Active l'indicateur d'état offline sur le DOM\n * - Retourne les templates compilés\n *\n * @example\n * ```ts\n * import Handlebars from 'handlebars'\n * const sdk = init({ client, handlebars: Handlebars })\n * const html = sdk.templates.productCard(product)\n * document.getElementById('product')!.innerHTML = html\n * ```\n */\nexport function initAltazionHtmx(config: AltazionHtmxConfig): AltazionHtmxInstance {\n const {\n client,\n handlebars,\n offlineSelector = 'body',\n terminalMode,\n } = config\n\n // 1. Extension HTMX — headers de contexte + actions panier déclaratives\n const extensionHandle: AltazionExtensionHandle = registerAltazionExtension(client)\n\n // 2. HTMX config globale — transmettre les cookies sur les requêtes XHR HTMX\n if (typeof window !== 'undefined' && window.htmx) {\n // @ts-expect-error — htmx.config n'est pas dans les types window\n window.htmx.config = window.htmx.config ?? {}\n // @ts-expect-error\n window.htmx.config.withCredentials = true\n }\n\n // 3. Helpers Handlebars\n const defaults = {\n locale: client.context.locale,\n currency: client.context.currency,\n }\n\n const handlebarsRuntime = handlebars\n ?? (typeof window !== 'undefined'\n ? (window as Window & { Handlebars?: typeof Handlebars }).Handlebars\n : undefined)\n\n const declarativeRenderer = createAltazionDeclarativeRenderer(handlebarsRuntime)\n const syncSlotFromEvent = (detail: AltazionActionEventDetail): void => {\n const slotName = detail.element.getAttribute('hx-altazion-data-slot')?.trim()\n if (!slotName) {\n return\n }\n\n declarativeRenderer.updateSlot(slotName, detail.result ?? null)\n }\n\n // Getter réactif sur le panier actuel utilisé par les helpers Handlebars.\n let currentCart: Cart | null = null\n const getCart = (): Cart | null => currentCart\n\n const syncCartFromEvent = (event: Event): void => {\n const customEvent = event as CustomEvent<AltazionCartEventDetail<Cart>>\n if (customEvent.detail.result) {\n currentCart = customEvent.detail.result\n declarativeRenderer.update('cart', currentCart)\n }\n syncSlotFromEvent(customEvent.detail)\n }\n\n const syncSessionFromEvent = (event: Event): void => {\n const customEvent = event as CustomEvent<AltazionSessionEventDetail<SessionInfo>>\n declarativeRenderer.update('session', customEvent.detail.result ?? null)\n syncSlotFromEvent(customEvent.detail)\n }\n\n const syncStoreFromEvent = (event: Event): void => {\n const customEvent = event as CustomEvent<AltazionStoresEventDetail<StoreWithOpeningHours>>\n declarativeRenderer.update('store', customEvent.detail.result ?? null)\n syncSlotFromEvent(customEvent.detail)\n }\n\n const syncStoresFromEvent = (event: Event): void => {\n const customEvent = event as CustomEvent<AltazionStoresEventDetail<StoreWithOpeningHours[]>>\n declarativeRenderer.update('stores', Array.isArray(customEvent.detail.result) ? customEvent.detail.result : [])\n syncSlotFromEvent(customEvent.detail)\n }\n\n const syncMarketingItemFromEvent = (event: Event): void => {\n const customEvent = event as CustomEvent<AltazionMarketingEventDetail>\n declarativeRenderer.update('marketingItem', Array.isArray(customEvent.detail.result) ? null : customEvent.detail.result ?? null)\n syncSlotFromEvent(customEvent.detail)\n }\n\n const syncMarketingItemsFromEvent = (event: Event): void => {\n const customEvent = event as CustomEvent<AltazionMarketingEventDetail>\n declarativeRenderer.update('marketingItems', Array.isArray(customEvent.detail.result) ? customEvent.detail.result : [])\n syncSlotFromEvent(customEvent.detail)\n }\n\n if (typeof document !== 'undefined') {\n document.addEventListener('altazion:cart:loaded', syncCartFromEvent)\n document.addEventListener('altazion:cart:updated', syncCartFromEvent)\n document.addEventListener('altazion:session:loaded', syncSessionFromEvent)\n document.addEventListener('altazion:stores:store-loaded', syncStoreFromEvent)\n document.addEventListener('altazion:stores:stores-loaded', syncStoresFromEvent)\n document.addEventListener('altazion:marketing:item-loaded', syncMarketingItemFromEvent)\n document.addEventListener('altazion:marketing:items-loaded', syncMarketingItemsFromEvent)\n }\n\n void client.cart.getCart()\n .then((cart: Cart) => {\n currentCart = cart\n declarativeRenderer.update('cart', cart)\n })\n .catch(() => { /* panier non disponible au chargement */ })\n\n if (handlebars) {\n registerPriceHelpers(handlebars, defaults)\n registerProductHelpers(handlebars, client.context.siteUrl ?? '')\n registerCartHelpers(handlebars, getCart, defaults)\n }\n\n declarativeRenderer.render()\n\n // 4. Indicateur offline DOM + mode borne\n const offlineEl = typeof document !== 'undefined'\n ? document.querySelector(offlineSelector) ?? document.body\n : null\n\n let lastConnectivityStatus: ConnectivityStatus | null = null\n\n const updateOfflineClass = (): void => {\n if (!offlineEl) {\n return\n }\n\n const status: ConnectivityStatus = client.isOffline ? 'offline' : 'online'\n const isOffline = status === 'offline'\n\n offlineEl.classList.toggle('altz-offline', isOffline)\n offlineEl.classList.toggle('altz-terminal-offline', isOffline)\n offlineEl.classList.toggle('altz-terminal-online', !isOffline)\n offlineEl.setAttribute('data-altazion-terminal-state', status)\n\n updateManagedVisibility(resolveManagedElements(terminalMode?.interactiveSelectors), isOffline, 'altz-terminal-interactive-hidden')\n updateManagedVisibility(resolveManagedElements(terminalMode?.offlineScreenSelectors), !isOffline, 'altz-terminal-offline-screen-hidden')\n\n if (lastConnectivityStatus === status) {\n return\n }\n\n lastConnectivityStatus = status\n dispatchConnectivityEvent(offlineEl, 'altazion:connectivity:changed', status)\n dispatchConnectivityEvent(offlineEl, isOffline ? 'altazion:offline' : 'altazion:online', status)\n }\n\n // Synchronisation initiale\n updateOfflineClass()\n\n // Abonnement ConnectivityManager — retourne la fonction de désabonnement\n const unsubscribeConnectivity = client.connectivity?.subscribe(() => updateOfflineClass())\n\n // 5. Templates compilés (retournés pour usage dans le code applicatif)\n const noHbs = (): HandlebarsTemplateDelegate =>\n () => '<!-- handlebars non initialisé dans @altazion/commerce-sdk-htmx -->'\n\n const templates = handlebars\n ? {\n productCard: handlebars.compile(productCardTemplate),\n cartMini: handlebars.compile(cartMiniTemplate),\n productList: handlebars.compile(productListTemplate),\n }\n : {\n productCard: noHbs(),\n cartMini: noHbs(),\n productList: noHbs(),\n }\n\n return {\n templates,\n dispose(): void {\n extensionHandle.dispose()\n if (typeof document !== 'undefined') {\n document.removeEventListener('altazion:cart:loaded', syncCartFromEvent)\n document.removeEventListener('altazion:cart:updated', syncCartFromEvent)\n document.removeEventListener('altazion:session:loaded', syncSessionFromEvent)\n document.removeEventListener('altazion:stores:store-loaded', syncStoreFromEvent)\n document.removeEventListener('altazion:stores:stores-loaded', syncStoresFromEvent)\n document.removeEventListener('altazion:marketing:item-loaded', syncMarketingItemFromEvent)\n document.removeEventListener('altazion:marketing:items-loaded', syncMarketingItemsFromEvent)\n }\n declarativeRenderer.dispose()\n unsubscribeConnectivity?.()\n },\n }\n}\n\nexport const init = initAltazionHtmx\n\nfunction resolveManagedElements(selectorInput?: SelectorInput): Element[] {\n if (typeof document === 'undefined' || !selectorInput) {\n return []\n }\n\n const selectors = Array.isArray(selectorInput) ? selectorInput : [selectorInput]\n const elements = new Set<Element>()\n\n for (const selector of selectors) {\n if (!selector.trim()) {\n continue\n }\n\n try {\n for (const element of document.querySelectorAll(selector)) {\n elements.add(element)\n }\n } catch {\n // Sélecteur invalide : on ignore silencieusement.\n }\n }\n\n return [...elements]\n}\n\nfunction updateManagedVisibility(elements: Element[], hidden: boolean, hiddenClassName: string): void {\n for (const element of elements) {\n element.classList.toggle(hiddenClassName, hidden)\n element.setAttribute('aria-hidden', hidden ? 'true' : 'false')\n\n if (element instanceof HTMLElement) {\n element.hidden = hidden\n } else if (hidden) {\n element.setAttribute('hidden', '')\n } else {\n element.removeAttribute('hidden')\n }\n }\n}\n\nfunction dispatchConnectivityEvent(\n root: Element,\n eventName: string,\n status: ConnectivityStatus\n): void {\n const detail: AltazionConnectivityEventDetail = {\n status,\n isOnline: status === 'online',\n isOffline: status === 'offline',\n root,\n }\n\n root.dispatchEvent(new CustomEvent<AltazionConnectivityEventDetail>(eventName, {\n bubbles: true,\n detail,\n }))\n}\n\n// Re-exports helpers pour usage à la carte\nexport { registerPriceHelpers } from './helpers/price'\nexport { registerProductHelpers } from './helpers/product'\nexport { registerCartHelpers } from './helpers/cart'\nexport {\n registerAltazionExtension,\n registerAltazionAuthExtension,\n} from './extensions/altazion-auth'\nexport type {\n AltazionActionEventDetail,\n AltazionActionErrorDetail,\n AltazionCartActionName,\n AltazionCartEventDetail,\n AltazionExtensionHandle,\n AltazionMarketingActionName,\n AltazionMarketingEventDetail,\n AltazionSessionActionName,\n AltazionSessionEventDetail,\n AltazionStoresActionName,\n AltazionStoresEventDetail,\n AltazionSuccessEventKind,\n} from './extensions/altazion-auth'\n"],"names":["AltazionApiError","OfflineError","_a"],"mappings":"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"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,42 @@
|
|
|
1
1
|
import { Cart } from '@altazion/commerce-sdk-core';
|
|
2
2
|
import { CommerceClient } from '@altazion/commerce-sdk-core';
|
|
3
|
+
import { ConnectivityStatus } from '@altazion/commerce-sdk-core';
|
|
3
4
|
import { default as default_2 } from 'handlebars';
|
|
5
|
+
import { ProblemDetails } from '@altazion/commerce-sdk-core';
|
|
6
|
+
|
|
7
|
+
export declare interface AltazionActionErrorDetail {
|
|
8
|
+
name: string;
|
|
9
|
+
message: string;
|
|
10
|
+
status?: number;
|
|
11
|
+
problem?: ProblemDetails;
|
|
12
|
+
isOffline: boolean;
|
|
13
|
+
isConflict: boolean;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export declare interface AltazionActionEventDetail<TModule extends string = string, TAction extends string = string, TResult = unknown> {
|
|
17
|
+
module: TModule;
|
|
18
|
+
action: TAction;
|
|
19
|
+
element: Element;
|
|
20
|
+
payload: Record<string, unknown>;
|
|
21
|
+
result?: TResult;
|
|
22
|
+
error?: unknown;
|
|
23
|
+
errorDetail?: AltazionActionErrorDetail;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export declare type AltazionCartActionName = 'getCart' | 'getValidationStatus' | 'addItem' | 'updateItem' | 'removeItem' | 'applyCoupon' | 'removeCoupon';
|
|
27
|
+
|
|
28
|
+
export declare type AltazionCartEventDetail<TResult = unknown> = AltazionActionEventDetail<'cart', AltazionCartActionName, TResult>;
|
|
29
|
+
|
|
30
|
+
export declare interface AltazionConnectivityEventDetail {
|
|
31
|
+
status: ConnectivityStatus;
|
|
32
|
+
isOnline: boolean;
|
|
33
|
+
isOffline: boolean;
|
|
34
|
+
root: Element;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export declare interface AltazionExtensionHandle {
|
|
38
|
+
dispose(): void;
|
|
39
|
+
}
|
|
4
40
|
|
|
5
41
|
export declare interface AltazionHtmxConfig {
|
|
6
42
|
/** Instance CommerceClient déjà initialisée */
|
|
@@ -16,6 +52,8 @@ export declare interface AltazionHtmxConfig {
|
|
|
16
52
|
* @default 'body'
|
|
17
53
|
*/
|
|
18
54
|
offlineSelector?: string;
|
|
55
|
+
/** Configuration UI du mode hors ligne borne. */
|
|
56
|
+
terminalMode?: AltazionTerminalModeConfig;
|
|
19
57
|
}
|
|
20
58
|
|
|
21
59
|
export declare interface AltazionHtmxInstance {
|
|
@@ -29,6 +67,27 @@ export declare interface AltazionHtmxInstance {
|
|
|
29
67
|
dispose(): void;
|
|
30
68
|
}
|
|
31
69
|
|
|
70
|
+
export declare type AltazionMarketingActionName = 'getItem' | 'getItems';
|
|
71
|
+
|
|
72
|
+
export declare type AltazionMarketingEventDetail<TResult = unknown> = AltazionActionEventDetail<'marketing', AltazionMarketingActionName, TResult>;
|
|
73
|
+
|
|
74
|
+
export declare type AltazionSessionActionName = 'getSession';
|
|
75
|
+
|
|
76
|
+
export declare type AltazionSessionEventDetail<TResult = unknown> = AltazionActionEventDetail<'session', AltazionSessionActionName, TResult>;
|
|
77
|
+
|
|
78
|
+
export declare type AltazionStoresActionName = 'findByLocation' | 'findByPostalCode' | 'getStore';
|
|
79
|
+
|
|
80
|
+
export declare type AltazionStoresEventDetail<TResult = unknown> = AltazionActionEventDetail<'stores', AltazionStoresActionName, TResult>;
|
|
81
|
+
|
|
82
|
+
export declare type AltazionSuccessEventKind = 'loaded' | 'updated' | 'changed' | 'none';
|
|
83
|
+
|
|
84
|
+
export declare interface AltazionTerminalModeConfig {
|
|
85
|
+
/** Zones interactives à masquer en mode hors ligne. */
|
|
86
|
+
interactiveSelectors?: SelectorInput;
|
|
87
|
+
/** Zones passives à afficher en mode hors ligne. */
|
|
88
|
+
offlineScreenSelectors?: SelectorInput;
|
|
89
|
+
}
|
|
90
|
+
|
|
32
91
|
export { Cart }
|
|
33
92
|
|
|
34
93
|
declare type HandlebarsInstance = typeof default_2;
|
|
@@ -39,6 +98,8 @@ declare type HandlebarsInstance_3 = typeof default_2;
|
|
|
39
98
|
|
|
40
99
|
declare type HandlebarsTemplateDelegate_2 = (context?: any) => string;
|
|
41
100
|
|
|
101
|
+
export declare const init: typeof initAltazionHtmx;
|
|
102
|
+
|
|
42
103
|
/**
|
|
43
104
|
* Initialise le SDK HTMX Altazion.
|
|
44
105
|
*
|
|
@@ -55,17 +116,22 @@ declare type HandlebarsTemplateDelegate_2 = (context?: any) => string;
|
|
|
55
116
|
* document.getElementById('product')!.innerHTML = html
|
|
56
117
|
* ```
|
|
57
118
|
*/
|
|
58
|
-
export declare function
|
|
119
|
+
export declare function initAltazionHtmx(config: AltazionHtmxConfig): AltazionHtmxInstance;
|
|
120
|
+
|
|
121
|
+
export declare const registerAltazionAuthExtension: typeof registerAltazionExtension;
|
|
59
122
|
|
|
60
123
|
/**
|
|
61
|
-
* Extension HTMX
|
|
62
|
-
* sur chaque requête HTMX.
|
|
124
|
+
* Extension HTMX Altazion.
|
|
63
125
|
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
126
|
+
* - Ajoute les headers de contexte Altazion sur les requêtes HTMX
|
|
127
|
+
* - Interprète les attributs `hx-altazion-cart-action`, `hx-altazion-session-action`,
|
|
128
|
+
* `hx-altazion-marketing-action` et `hx-altazion-stores-action`
|
|
129
|
+
* pour appeler le SDK core
|
|
130
|
+
* - Émet des événements DOM `altazion:cart:*`, `altazion:session:*`,
|
|
131
|
+
* `altazion:marketing:*` et `altazion:stores:*`
|
|
132
|
+
* exploitables par HTMX
|
|
67
133
|
*/
|
|
68
|
-
export declare function
|
|
134
|
+
export declare function registerAltazionExtension(client: CommerceClient): AltazionExtensionHandle;
|
|
69
135
|
|
|
70
136
|
/**
|
|
71
137
|
* Helpers Handlebars liés au panier.
|
|
@@ -101,6 +167,8 @@ export declare function registerPriceHelpers(hbs: HandlebarsInstance, defaults:
|
|
|
101
167
|
*/
|
|
102
168
|
export declare function registerProductHelpers(hbs: HandlebarsInstance_2, siteUrl: string): void;
|
|
103
169
|
|
|
170
|
+
declare type SelectorInput = string | string[];
|
|
171
|
+
|
|
104
172
|
export { }
|
|
105
173
|
|
|
106
174
|
|
|
@@ -109,6 +177,13 @@ declare global {
|
|
|
109
177
|
htmx?: {
|
|
110
178
|
on(eventName: string, listener: (event: Event) => void): void;
|
|
111
179
|
off(eventName: string, listener: (event: Event) => void): void;
|
|
180
|
+
ajax(method: string, path: string, context?: {
|
|
181
|
+
source?: Element;
|
|
182
|
+
target?: Element | string;
|
|
183
|
+
swap?: string;
|
|
184
|
+
select?: string;
|
|
185
|
+
values?: Record<string, unknown>;
|
|
186
|
+
}): Promise<unknown> | void;
|
|
112
187
|
};
|
|
113
188
|
}
|
|
114
189
|
}
|