npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@altazion/commerce-sdk-htmx

v26.519.8051

Published

Altazion Commerce SDK — Extension HTMX + helpers Handlebars

Readme

@altazion/commerce-sdk-htmx

Extension HTMX et helpers Handlebars pour l'Altazion Commerce SDK. Permet d'intégrer le SDK dans des projets à rendu serveur utilisant htmx et/ou Handlebars, sans framework JavaScript.

Installation

npm install @altazion/commerce-sdk-htmx @altazion/commerce-sdk-core
npm install htmx.org handlebars  # peer dependencies (optionnelles)

Initialisation

import { CommerceClient } from '@altazion/commerce-sdk-core'
import { initAltazionHtmx } from '@altazion/commerce-sdk-htmx'
import Handlebars from 'handlebars'

const client = new CommerceClient({
  baseUrl: 'https://votre-api.altazion.com',
})

initAltazionHtmx({
  client,
  handlebars: Handlebars,     // optionnel — active les helpers HBS
  offlineSelector: '#app',    // optionnel — élément qui reçoit la classe altz-offline
  terminalMode: {
    interactiveSelectors: ['#app-main', '.altz-action-bar'],
    offlineScreenSelectors: '#offline-screen',
  },
})

Mode CDN (sans bundler)

<script src="https://cdn.jsdelivr.net/npm/htmx.org@2/dist/htmx.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/handlebars/dist/handlebars.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@altazion/commerce-sdk-core/dist/index.iife.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@altazion/commerce-sdk-htmx/dist/index.iife.js"></script>
<script>
  const client = new AltazionCommerceCore.CommerceClient({
    baseUrl: 'https://votre-api.altazion.com'
  })
  AltazionCommerceSdkHtmx.initAltazionHtmx({ client, handlebars: Handlebars })
</script>

Helpers Handlebars

Prix

| Helper | Description | Exemple | |---|---|---| | {{formatPrice value}} | Prix formaté selon la locale | 12,90 € | | {{formatPriceNoSymbol value}} | Prix sans symbole monétaire | 12,90 |

Produit

| Helper | Description | |---|---| | {{productUrl sku}} | URL canonique d'un produit | | {{productImageUrl url size}} | URL d'image redimensionnée |

Panier

| Helper | Description | |---|---| | {{cartItemCount}} | Nombre total d'articles dans le panier | | {{cartTotal}} | Total TTC formaté | | {{#cartHasItems}}...{{/cartHasItems}} | Bloc conditionnel si panier non vide | | {{cartLineCount}} | Nombre de lignes dans le panier |

Templates pré-compilés

Le package expose des templates Handlebars prêts à l'emploi accessibles via :

import { templates } from '@altazion/commerce-sdk-htmx'

// templates.productCard    — carte produit
// templates.cartMini       — mini panier
// templates.productList    — liste de produits

Extension HTMX Altazion

L'initialisation enregistre automatiquement une extension HTMX altazion qui :

  • injecte les headers de session sur les requêtes HTMX ;
  • interprète les attributs hx-altazion-cart-action pour appeler directement client.cart.* du SDK core ;
  • interprète les attributs hx-altazion-session-action pour appeler directement client.session.* du SDK core ;
  • interprète les attributs hx-altazion-marketing-action pour appeler directement client.marketing.* du SDK core ;
  • interprète les attributs hx-altazion-stores-action pour appeler directement client.stores.* du SDK core ;
  • émet des événements DOM altazion:cart:* exploitables par HTMX pour recharger des fragments.

Convention de nommage

La convention officielle du DSL HTMX Altazion est la suivante :

  • activation : hx-ext="altazion" ;
  • action métier : hx-altazion-<module>-action ;
  • paramètres simples : hx-altazion-<module>-<parametre-kebab-case> ;
  • payload riche : formulaire ou hx-vals ;
  • refresh partagé : hx-altazion-refresh ;
  • événements : altazion:<module>:before|after|error, avec des événements complémentaires selon le module (updated, loaded, changed, etc.).

La convention détaillée est décrite dans specs-temp/sdk.htmx-naming-convention.md.

Exemple addItem

<div hx-ext="altazion">
  <button
    hx-altazion-cart-action="addItem"
    hx-vals='{"reference":"REF-001","quantity":1}'
    hx-altazion-refresh="#cart-mini; #cart-badge"
  >
    Ajouter au panier
  </button>

  <aside
    id="cart-mini"
    hx-get="/fragments/cart-mini"
    hx-swap="outerHTML"
  ></aside>
</div>

Actions supportées

| Action | Méthode SDK | Payload attendu | |---|---|---| | getCart | client.cart.getCart() | aucun | | getValidationStatus | client.cart.getValidationStatus() | aucun | | addItem | client.cart.addItem(reference, quantity, options?) | reference, quantity | | updateItem | client.cart.updateItem(lineId, quantity) | lineId, quantity | | removeItem | client.cart.removeItem(lineId) | lineId | | applyCoupon | client.cart.applyCoupon(code) | code | | removeCoupon | client.cart.removeCoupon(code) | code |

Le payload peut être fourni via hx-vals, via les champs d'un formulaire, ou avec les attributs dédiés hx-altazion-cart-reference, hx-altazion-cart-quantity, hx-altazion-cart-line-id, hx-altazion-cart-code.

Session: lecture de la session courante

Pour les sites en server rendering, la session peut déjà exister côté serveur et être portée par cookie. Le premier besoin côté HTMX est donc souvent simplement de relire cet état pour rafraîchir des fragments.

<section
  hx-ext="altazion"
  hx-altazion-session-action="getSession"
  hx-trigger="load, altazion:session:refresh from:body"
  hx-altazion-refresh="#header-session; #mini-cart"
>
</section>

<header id="header-session" hx-get="/fragments/header-session" hx-swap="outerHTML"></header>
<aside id="mini-cart" hx-get="/fragments/cart-mini" hx-swap="outerHTML"></aside>

Action supportée pour l'instant :

| Action | Méthode SDK | Payload attendu | |---|---|---| | getSession | client.session.getSession() | aucun |

Événements émis :

| Événement | Description | |---|---| | altazion:session:before | avant l'appel au SDK | | altazion:session:after | après un appel réussi | | altazion:session:loaded | après getSession | | altazion:session:error | en cas d'erreur |

Rendu déclaratif inline

Quand handlebars est fourni à initAltazionHtmx, le package sait aussi piloter un rendu inline déclaratif dans le DOM.

Le pattern visé est :

<section
  hx-ext="altazion"
  hx-altazion-marketing-action="getItems"
  hx-altazion-marketing-codes='["HOMEPAGEHERO"]'
  hx-altazion-data-slot="homepageHero"
></section>

<aside id="store-detail" class="panel">
  <p
    hx-altazion-data-source="slot:homepageHero"
    hx-altazion-data-status="null"
    class="placeholder"
  >
    Aucun contenu marketing chargé.
  </p>

  <div
    hx-altazion-data-source="slot:homepageHero"
    hx-altazion-data-status="not-empty"
    hx-render-template="homepage-hero-template"
  ></div>
</aside>

<script id="homepage-hero-template" type="text/x-handlebars-template">
  {{#each slot}}
  <article>
    <h2>{{linkItem.altData}}</h2>
  </article>
  {{/each}}
</script>

Attributs actuellement pris en charge :

  • hx-altazion-data-source="cart|session|store|stores|marketing-item|marketing-items"
  • hx-altazion-data-source="slot:nom-libre"
  • hx-altazion-data-status="null|not-null|empty|not-empty"
  • hx-altazion-data-slot="nom-libre" sur un élément d'action Altazion pour ranger son résultat dans un slot nommé
  • hx-render-template="template-id"

Le contexte Handlebars exposé au template contient aujourd'hui : cart, session, store, stores, marketingItem, marketingItems, slots et slot.

Marketing: items de widgets et d'animation

Le module marketing sert bien au cas d'usage widgets de page: récupérer un item marketing isolé ou un lot d'items, puis laisser HTMX rafraîchir les fragments de rendu serveur associés.

<section
  hx-ext="altazion"
  hx-altazion-marketing-action="getItems"
  hx-altazion-marketing-codes='["home-hero", "home-sidebar", "home-footer"]'
  hx-trigger="load, altazion:marketing:refresh from:body"
  hx-altazion-refresh="#widget-hero; #widget-sidebar; #widget-footer"
>
</section>

<section id="widget-hero" hx-get="/fragments/widgets/hero" hx-swap="outerHTML"></section>
<aside id="widget-sidebar" hx-get="/fragments/widgets/sidebar" hx-swap="outerHTML"></aside>
<footer id="widget-footer" hx-get="/fragments/widgets/footer" hx-swap="outerHTML"></footer>

Actions supportées :

| Action | Méthode SDK | Payload attendu | |---|---|---| | getItem | client.marketing.getItem(code) | code | | getItems | client.marketing.getItems(codes) | codes |

Le payload peut être fourni via hx-vals, via un formulaire, ou avec :

  • hx-altazion-marketing-code pour un item unique ;
  • hx-altazion-marketing-codes pour une liste JSON de codes ;
  • une chaîne séparée par des virgules dans codes si c'est plus simple côté template.

Événements émis :

| Événement | Description | |---|---| | altazion:marketing:before | avant l'appel au SDK | | altazion:marketing:after | après un appel réussi | | altazion:marketing:loaded | après une lecture réussie | | altazion:marketing:item-loaded | après getItem | | altazion:marketing:items-loaded | après getItems | | altazion:marketing:error | en cas d'erreur |

Stores: store locator et détail magasin

Le domaine stores est un bon candidat HTMX parce qu'il est purement orienté lecture pour l'instant: localiser une liste de magasins ou charger la fiche d'un magasin pour un widget, une modale ou une page de retrait.

<form
  hx-ext="altazion"
  hx-altazion-stores-action="findByPostalCode"
  hx-trigger="submit"
  hx-altazion-refresh="#store-results"
>
  <input type="text" name="postalCode" value="75002">
  <input type="hidden" name="countryCode" value="FR">
  <button type="submit">Chercher un magasin</button>
</form>

<section id="store-results" hx-get="/fragments/stores/results" hx-swap="outerHTML"></section>
<button
  hx-ext="altazion"
  hx-altazion-stores-action="getStore"
  hx-altazion-stores-store-guid="STORE-GUID-001"
  hx-altazion-refresh="#store-detail"
>
  Voir ce magasin
</button>

<aside id="store-detail" hx-get="/fragments/stores/detail" hx-swap="outerHTML"></aside>

Actions supportées :

| Action | Méthode SDK | Payload attendu | |---|---|---| | findByLocation | client.stores.findByLocation(latitude, longitude, radiusKm?) | latitude, longitude | | findByPostalCode | client.stores.findByPostalCode(postalCode, countryCode?) | postalCode | | getStore | client.stores.getStore(storeGuid) | storeGuid |

Paramètres HTML pris en charge :

  • hx-altazion-stores-latitude
  • hx-altazion-stores-longitude
  • hx-altazion-stores-radius-km
  • hx-altazion-stores-postal-code
  • hx-altazion-stores-country-code
  • hx-altazion-stores-store-guid

Événements émis :

| Événement | Description | |---|---| | altazion:stores:before | avant l'appel au SDK | | altazion:stores:after | après un appel réussi | | altazion:stores:loaded | après une lecture réussie | | altazion:stores:stores-loaded | après une recherche de magasins | | altazion:stores:store-loaded | après getStore | | altazion:stores:error | en cas d'erreur |

Rafraîchissement déclaratif

L'attribut hx-altazion-refresh accepte une ou plusieurs cibles CSS séparées par ;.

  • si la cible porte un attribut hx-get, hx-post, hx-put, hx-patch ou hx-delete, l'extension force immédiatement la requête HTMX correspondante ;
  • sinon l'extension émet altazion:refresh sur la cible, ce qui laisse la main à du rendu client ou à un autre binding HTMX.
<button
  hx-ext="altazion"
  hx-altazion-cart-action="applyCoupon"
  hx-altazion-cart-code="WELCOME10"
  hx-altazion-refresh="#cart-mini; #cart-totals"
>
  Appliquer le coupon
</button>

<section id="cart-totals" hx-get="/fragments/cart-totals" hx-swap="outerHTML"></section>

Événements émis

| Événement | Description | |---|---| | altazion:cart:before | avant l'appel au SDK | | altazion:cart:after | après un appel réussi | | altazion:cart:loaded | après une lecture réussie, par exemple getCart | | altazion:cart:updated | après une action retournant un panier | | altazion:cart:changed | après une action réussie sans payload de retour | | altazion:cart:status | après getValidationStatus | | altazion:cart:error | en cas d'erreur, avec detail.errorDetail normalisé | | altazion:refresh | fallback émis sur une cible sans requête HTMX |

Le moteur HTMX générique applique désormais une sémantique commune :

  • loaded pour les actions de lecture ;
  • updated pour les mutations avec résultat métier ;
  • changed pour les mutations qui réussissent sans retourner de payload ;
  • error avec un objet detail.errorDetail structuré : name, message, status, problem, isOffline, isConflict.

Détection offline

Lorsque la connexion est perdue, l'élément ciblé par offlineSelector (par défaut body) reçoit :

  • la classe altz-offline ;
  • la classe altz-terminal-offline ou altz-terminal-online ;
  • l'attribut data-altazion-terminal-state="offline|online" ;
  • les événements altazion:connectivity:changed, altazion:offline et altazion:online.

Le mode borne peut aussi masquer des zones interactives et afficher un écran passif via terminalMode.interactiveSelectors et terminalMode.offlineScreenSelectors.

Exemple de bascule borne

<body>
  <main id="app-main">
    <!-- interface interactive -->
  </main>

  <aside id="offline-screen" hidden>
    <!-- pub, branding, message d'attente -->
  </aside>
</body>
body.altz-terminal-offline {
  background: #111;
  color: #fff;
}

#offline-screen[hidden] {
  display: none;
}

L'écran offline est affiché automatiquement quand la borne passe hors ligne, et les zones interactives ciblées sont masquées.

Exemple d'écoute des événements

document.body.addEventListener('altazion:offline', () => {
  console.log('Le terminal est hors ligne')
})

document.body.addEventListener('altazion:online', () => {
  console.log('Le terminal est de nouveau en ligne')
})

Les mutations métier continuent d'échouer immédiatement hors ligne avec OfflineError. Le mode offline borne ne réintroduit aucune synchronisation différée.

Exemple CSS minimal

Lorsque seule l'indication visuelle suffit, la classe altz-offline permet d'afficher un bandeau ou de masquer des actions :

body.altz-offline .altz-cart-actions {
  opacity: 0.5;
  pointer-events: none;
}

Licence

Propriétaire — © Altazion SAS. Tous droits réservés.