@altazion/commerce-sdk-htmx 26.409.7573 → 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.
@@ -1,17 +1,696 @@
1
- var AltazionCommerceSdkHtmx = function(exports) {
1
+ var AltazionCommerceSdkHtmx = function(exports, commerceSdkCore) {
2
2
  "use strict";
3
- function registerAltazionAuthExtension(client) {
4
- if (typeof window === "undefined" || !window.htmx) {
5
- console.warn("[AltazionHtmx] htmx non disponible sur window — extension non enregistrée");
6
- return;
7
- }
8
- const handler = (event) => {
3
+ const EXTENSION_NAME = "altazion";
4
+ const JSON_VALUES_ATTRIBUTE = "hx-vals";
5
+ const REFRESH_ATTRIBUTE = "hx-altazion-refresh";
6
+ const REFRESH_EVENT_NAME = "altazion:refresh";
7
+ const REQUEST_ATTRIBUTES = [
8
+ { attribute: "hx-get", method: "GET" },
9
+ { attribute: "hx-post", method: "POST" },
10
+ { attribute: "hx-put", method: "PUT" },
11
+ { attribute: "hx-patch", method: "PATCH" },
12
+ { attribute: "hx-delete", method: "DELETE" }
13
+ ];
14
+ function createAltazionExtension(client, modules) {
15
+ const requestHandler = (event) => {
9
16
  const e = event;
10
17
  e.detail.headers["Accept-Language"] = client.context.locale;
11
18
  e.detail.headers["X-Altazion-Currency"] = client.context.currency;
12
19
  };
13
- window.htmx.on("htmx:configRequest", handler);
20
+ if (typeof window !== "undefined" && window.htmx) {
21
+ window.htmx.on("htmx:configRequest", requestHandler);
22
+ }
23
+ if (typeof document === "undefined") {
24
+ return {
25
+ dispose() {
26
+ if (typeof window !== "undefined" && window.htmx) {
27
+ window.htmx.off("htmx:configRequest", requestHandler);
28
+ }
29
+ }
30
+ };
31
+ }
32
+ const handleClick = (event) => {
33
+ const mouseEvent = event;
34
+ if (mouseEvent.defaultPrevented || mouseEvent.button !== 0 || mouseEvent.metaKey || mouseEvent.ctrlKey || mouseEvent.shiftKey || mouseEvent.altKey) {
35
+ return;
36
+ }
37
+ const target = event.target;
38
+ if (!(target instanceof Element)) {
39
+ return;
40
+ }
41
+ const matchedAction = findMatchedAction(target, modules);
42
+ if (!matchedAction || matchedAction.element instanceof HTMLFormElement || !hasAltazionExtension(matchedAction.element)) {
43
+ return;
44
+ }
45
+ event.preventDefault();
46
+ void runModuleAction(client, matchedAction);
47
+ };
48
+ const handleSubmit = (event) => {
49
+ const target = event.target;
50
+ if (!(target instanceof HTMLFormElement)) {
51
+ return;
52
+ }
53
+ const matchedAction = findMatchedAction(target, modules);
54
+ if (!matchedAction || matchedAction.element !== target || !hasAltazionExtension(target)) {
55
+ return;
56
+ }
57
+ event.preventDefault();
58
+ void runModuleAction(client, matchedAction);
59
+ };
60
+ document.addEventListener("click", handleClick);
61
+ document.addEventListener("submit", handleSubmit);
62
+ return {
63
+ dispose() {
64
+ if (typeof window !== "undefined" && window.htmx) {
65
+ window.htmx.off("htmx:configRequest", requestHandler);
66
+ }
67
+ document.removeEventListener("click", handleClick);
68
+ document.removeEventListener("submit", handleSubmit);
69
+ }
70
+ };
71
+ }
72
+ function requireString(value, fieldName) {
73
+ if (typeof value === "string" && value.trim().length > 0) {
74
+ return value.trim();
75
+ }
76
+ throw new Error(`Missing payload field: ${fieldName}`);
77
+ }
78
+ function requireNumber(value, fieldName) {
79
+ if (typeof value === "number" && Number.isFinite(value)) {
80
+ return value;
81
+ }
82
+ if (typeof value === "string" && value.trim().length > 0) {
83
+ const parsed = Number(value);
84
+ if (Number.isFinite(parsed)) {
85
+ return parsed;
86
+ }
87
+ }
88
+ throw new Error(`Invalid payload field: ${fieldName}`);
89
+ }
90
+ function asRecord(value) {
91
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
92
+ return void 0;
93
+ }
94
+ return value;
95
+ }
96
+ async function runModuleAction(client, matchedAction) {
97
+ var _a;
98
+ const { definition, element } = matchedAction;
99
+ const action = readActionName(element, definition);
100
+ const payload = collectPayload(element, definition);
101
+ const releasePending = markPending(element);
102
+ dispatchModuleEvent(element, buildModuleEventName(definition.moduleName, "before"), {
103
+ module: definition.moduleName,
104
+ action,
105
+ element,
106
+ payload
107
+ });
108
+ try {
109
+ const result = await definition.execute(client, action, payload);
110
+ dispatchModuleEvent(element, buildModuleEventName(definition.moduleName, "after"), {
111
+ module: definition.moduleName,
112
+ action,
113
+ element,
114
+ payload,
115
+ result
116
+ });
117
+ const successEventKind = resolveSuccessEventKind(definition, action, result, payload);
118
+ const emittedSuffixes = /* @__PURE__ */ new Set();
119
+ if (successEventKind !== "none") {
120
+ emittedSuffixes.add(successEventKind);
121
+ dispatchModuleEvent(element, buildModuleEventName(definition.moduleName, successEventKind), {
122
+ module: definition.moduleName,
123
+ action,
124
+ element,
125
+ payload,
126
+ result
127
+ });
128
+ }
129
+ for (const suffix of ((_a = definition.getResultEventSuffixes) == null ? void 0 : _a.call(definition, action, result, payload)) ?? []) {
130
+ if (emittedSuffixes.has(suffix)) {
131
+ continue;
132
+ }
133
+ dispatchModuleEvent(element, buildModuleEventName(definition.moduleName, suffix), {
134
+ module: definition.moduleName,
135
+ action,
136
+ element,
137
+ payload,
138
+ result
139
+ });
140
+ }
141
+ await refreshTargets(element);
142
+ } catch (error) {
143
+ const errorDetail = normalizeError(error);
144
+ dispatchModuleEvent(element, buildModuleEventName(definition.moduleName, "error"), {
145
+ module: definition.moduleName,
146
+ action,
147
+ element,
148
+ payload,
149
+ error,
150
+ errorDetail
151
+ });
152
+ console.error(`[AltazionHtmx] ${definition.moduleName} action failed`, error);
153
+ } finally {
154
+ releasePending();
155
+ }
156
+ }
157
+ function findMatchedAction(target, modules) {
158
+ let current = target;
159
+ while (current) {
160
+ for (const definition of modules) {
161
+ if (current.hasAttribute(definition.actionAttribute)) {
162
+ return { definition, element: current };
163
+ }
164
+ }
165
+ current = current.parentElement;
166
+ }
167
+ return null;
168
+ }
169
+ function readActionName(element, definition) {
170
+ const action = element.getAttribute(definition.actionAttribute);
171
+ if (!action) {
172
+ throw new Error(`Missing ${definition.actionAttribute} attribute`);
173
+ }
174
+ return definition.parseAction(action);
175
+ }
176
+ function collectPayload(element, definition) {
177
+ var _a;
178
+ const payload = {};
179
+ const form = element instanceof HTMLFormElement ? element : element.closest("form");
180
+ if (form) {
181
+ Object.assign(payload, formDataToObject(new FormData(form)));
182
+ mergeJsonValues(payload, form);
183
+ applyAttributePayload(payload, form, definition.payloadAttributes);
184
+ applyJsonAttributePayload(payload, form, definition.jsonPayloadAttributes);
185
+ }
186
+ mergeJsonValues(payload, element);
187
+ applyAttributePayload(payload, element, definition.payloadAttributes);
188
+ applyJsonAttributePayload(payload, element, definition.jsonPayloadAttributes);
189
+ applyPayloadAliases(payload, definition.payloadAliases);
190
+ (_a = definition.normalizePayload) == null ? void 0 : _a.call(definition, payload);
191
+ return payload;
192
+ }
193
+ function mergeJsonValues(payload, element) {
194
+ const values = readJsonValues(element, JSON_VALUES_ATTRIBUTE);
195
+ if (values) {
196
+ Object.assign(payload, values);
197
+ }
198
+ }
199
+ function applyAttributePayload(payload, element, attributes) {
200
+ if (!attributes) {
201
+ return;
202
+ }
203
+ for (const [attributeName, payloadKey] of Object.entries(attributes)) {
204
+ const value = element.getAttribute(attributeName);
205
+ if (value !== null) {
206
+ payload[payloadKey] = value;
207
+ }
208
+ }
209
+ }
210
+ function applyJsonAttributePayload(payload, element, attributes) {
211
+ if (!attributes) {
212
+ return;
213
+ }
214
+ for (const [attributeName, payloadKey] of Object.entries(attributes)) {
215
+ const value = readJsonValues(element, attributeName);
216
+ if (value !== void 0) {
217
+ payload[payloadKey] = value;
218
+ }
219
+ }
220
+ }
221
+ function applyPayloadAliases(payload, aliases) {
222
+ if (!aliases) {
223
+ return;
224
+ }
225
+ for (const [alias, canonicalKey] of Object.entries(aliases)) {
226
+ if (payload[alias] !== void 0 && payload[canonicalKey] === void 0) {
227
+ payload[canonicalKey] = payload[alias];
228
+ }
229
+ }
230
+ }
231
+ function formDataToObject(formData) {
232
+ const payload = {};
233
+ for (const [key, value] of formData.entries()) {
234
+ const normalizedValue = typeof value === "string" ? value : value.name;
235
+ const previous = payload[key];
236
+ if (previous === void 0) {
237
+ payload[key] = normalizedValue;
238
+ } else if (Array.isArray(previous)) {
239
+ previous.push(normalizedValue);
240
+ } else {
241
+ payload[key] = [previous, normalizedValue];
242
+ }
243
+ }
244
+ return payload;
245
+ }
246
+ function dispatchModuleEvent(element, eventName, detail) {
247
+ element.dispatchEvent(new CustomEvent(eventName, {
248
+ bubbles: true,
249
+ detail
250
+ }));
251
+ }
252
+ function buildModuleEventName(moduleName, suffix) {
253
+ return `altazion:${moduleName}:${suffix}`;
254
+ }
255
+ function resolveSuccessEventKind(definition, action, result, payload) {
256
+ const configuredKind = definition.successEventKind;
257
+ if (typeof configuredKind === "function") {
258
+ return configuredKind(action, result, payload);
259
+ }
260
+ if (configuredKind) {
261
+ return configuredKind;
262
+ }
263
+ return inferSuccessEventKind(action, result);
264
+ }
265
+ function inferSuccessEventKind(action, result) {
266
+ if (result === void 0) {
267
+ return "changed";
268
+ }
269
+ const normalizedAction = action.toLowerCase();
270
+ if (normalizedAction.startsWith("get") || normalizedAction.startsWith("find") || normalizedAction.startsWith("search") || normalizedAction.startsWith("suggest") || normalizedAction.startsWith("load") || normalizedAction.startsWith("list")) {
271
+ return "loaded";
272
+ }
273
+ return "updated";
274
+ }
275
+ function normalizeError(error) {
276
+ if (error instanceof commerceSdkCore.AltazionApiError) {
277
+ return {
278
+ name: error.name,
279
+ message: error.message,
280
+ status: error.status,
281
+ problem: error.problem,
282
+ isOffline: false,
283
+ isConflict: error.status === 409
284
+ };
285
+ }
286
+ if (error instanceof commerceSdkCore.OfflineError) {
287
+ return {
288
+ name: error.name,
289
+ message: error.message,
290
+ isOffline: true,
291
+ isConflict: false
292
+ };
293
+ }
294
+ if (error instanceof Error) {
295
+ return {
296
+ name: error.name,
297
+ message: error.message,
298
+ isOffline: false,
299
+ isConflict: false
300
+ };
301
+ }
302
+ return {
303
+ name: "UnknownError",
304
+ message: "Unknown error",
305
+ isOffline: false,
306
+ isConflict: false
307
+ };
308
+ }
309
+ async function refreshTargets(element) {
310
+ const targets = resolveRefreshTargets(element);
311
+ if (targets.length === 0) {
312
+ return;
313
+ }
314
+ await Promise.all(targets.map((target) => refreshTargetElement(element, target)));
315
+ }
316
+ function resolveRefreshTargets(element) {
317
+ if (typeof document === "undefined") {
318
+ return [];
319
+ }
320
+ const selectors = collectRefreshSelectors(element);
321
+ if (selectors.length === 0) {
322
+ return [];
323
+ }
324
+ const targets = /* @__PURE__ */ new Set();
325
+ for (const selector of selectors) {
326
+ try {
327
+ for (const target of document.querySelectorAll(selector)) {
328
+ targets.add(target);
329
+ }
330
+ } catch (error) {
331
+ console.error(`[AltazionHtmx] invalid refresh selector: ${selector}`, error);
332
+ }
333
+ }
334
+ return [...targets];
335
+ }
336
+ function collectRefreshSelectors(element) {
337
+ const values = /* @__PURE__ */ new Set();
338
+ const form = element instanceof HTMLFormElement ? element : element.closest("form");
339
+ addRefreshSelectors(values, form);
340
+ addRefreshSelectors(values, element);
341
+ return [...values];
342
+ }
343
+ function addRefreshSelectors(values, element) {
344
+ const rawValue = element == null ? void 0 : element.getAttribute(REFRESH_ATTRIBUTE);
345
+ if (!rawValue) {
346
+ return;
347
+ }
348
+ for (const selector of rawValue.split(";")) {
349
+ const trimmed = selector.trim();
350
+ if (trimmed.length > 0) {
351
+ values.add(trimmed);
352
+ }
353
+ }
354
+ }
355
+ async function refreshTargetElement(sourceElement, targetElement) {
356
+ var _a;
357
+ const request = readRefreshRequest(targetElement);
358
+ if (request && typeof window !== "undefined" && ((_a = window.htmx) == null ? void 0 : _a.ajax)) {
359
+ const context = {
360
+ source: sourceElement,
361
+ target: targetElement
362
+ };
363
+ const swap = targetElement.getAttribute("hx-swap");
364
+ if (swap) {
365
+ context.swap = swap;
366
+ }
367
+ const select = targetElement.getAttribute("hx-select");
368
+ if (select) {
369
+ context.select = select;
370
+ }
371
+ const values = readJsonValues(targetElement, JSON_VALUES_ATTRIBUTE);
372
+ if (values) {
373
+ context.values = values;
374
+ }
375
+ await Promise.resolve(window.htmx.ajax(request.method, request.path, context));
376
+ return;
377
+ }
378
+ targetElement.dispatchEvent(new CustomEvent(REFRESH_EVENT_NAME, {
379
+ bubbles: true,
380
+ detail: {
381
+ source: sourceElement,
382
+ target: targetElement
383
+ }
384
+ }));
385
+ }
386
+ function readRefreshRequest(element) {
387
+ for (const requestAttribute of REQUEST_ATTRIBUTES) {
388
+ const path = element.getAttribute(requestAttribute.attribute);
389
+ if (path) {
390
+ return {
391
+ method: requestAttribute.method,
392
+ path
393
+ };
394
+ }
395
+ }
396
+ return null;
397
+ }
398
+ function readJsonValues(element, attributeName) {
399
+ const raw = element.getAttribute(attributeName);
400
+ if (!raw) {
401
+ return void 0;
402
+ }
403
+ try {
404
+ const parsed = JSON.parse(raw);
405
+ if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
406
+ return parsed;
407
+ }
408
+ } catch {
409
+ throw new Error(`Invalid JSON in ${attributeName}`);
410
+ }
411
+ return void 0;
412
+ }
413
+ function markPending(element) {
414
+ const previousBusy = element.getAttribute("aria-busy");
415
+ element.setAttribute("aria-busy", "true");
416
+ const disableable = isDisableableElement(element) ? element : null;
417
+ const previousDisabled = (disableable == null ? void 0 : disableable.disabled) ?? false;
418
+ if (disableable) {
419
+ disableable.disabled = true;
420
+ }
421
+ return () => {
422
+ if (previousBusy === null) {
423
+ element.removeAttribute("aria-busy");
424
+ } else {
425
+ element.setAttribute("aria-busy", previousBusy);
426
+ }
427
+ if (disableable) {
428
+ disableable.disabled = previousDisabled;
429
+ }
430
+ };
431
+ }
432
+ function isDisableableElement(element) {
433
+ return "disabled" in element;
434
+ }
435
+ function hasAltazionExtension(element) {
436
+ let current = element;
437
+ while (current) {
438
+ const extensions = current.getAttribute("hx-ext");
439
+ if (extensions && parseExtensions(extensions).includes(EXTENSION_NAME)) {
440
+ return true;
441
+ }
442
+ current = current.parentElement;
443
+ }
444
+ return false;
445
+ }
446
+ function parseExtensions(value) {
447
+ return value.split(/[\s,]+/).map((extension) => extension.trim()).filter((extension) => extension.length > 0);
448
+ }
449
+ const cartModuleDefinition = {
450
+ moduleName: "cart",
451
+ actionAttribute: "hx-altazion-cart-action",
452
+ payloadAttributes: {
453
+ "hx-altazion-cart-reference": "reference",
454
+ "hx-altazion-cart-quantity": "quantity",
455
+ "hx-altazion-cart-line-id": "lineId",
456
+ "hx-altazion-cart-code": "code"
457
+ },
458
+ jsonPayloadAttributes: {
459
+ "hx-altazion-cart-options": "options"
460
+ },
461
+ payloadAliases: {
462
+ ref: "reference",
463
+ productReference: "reference",
464
+ qty: "quantity",
465
+ line: "lineId",
466
+ coupon: "code"
467
+ },
468
+ parseAction(actionValue) {
469
+ switch (actionValue) {
470
+ case "getCart":
471
+ case "getValidationStatus":
472
+ case "addItem":
473
+ case "updateItem":
474
+ case "removeItem":
475
+ case "applyCoupon":
476
+ case "removeCoupon":
477
+ return actionValue;
478
+ default:
479
+ throw new Error(`Unsupported cart action: ${actionValue}`);
480
+ }
481
+ },
482
+ execute(client, action, payload) {
483
+ switch (action) {
484
+ case "getCart":
485
+ return client.cart.getCart();
486
+ case "getValidationStatus":
487
+ return client.cart.getValidationStatus();
488
+ case "addItem": {
489
+ const reference = requireString(payload.reference, "reference");
490
+ const quantity = requireNumber(payload.quantity, "quantity");
491
+ const options = buildAddItemOptions(payload);
492
+ return client.cart.addItem(reference, quantity, options);
493
+ }
494
+ case "updateItem": {
495
+ const lineId = requireString(payload.lineId, "lineId");
496
+ const quantity = requireNumber(payload.quantity, "quantity");
497
+ return client.cart.updateItem(lineId, quantity);
498
+ }
499
+ case "removeItem":
500
+ return client.cart.removeItem(requireString(payload.lineId, "lineId"));
501
+ case "applyCoupon":
502
+ return client.cart.applyCoupon(requireString(payload.code, "code"));
503
+ case "removeCoupon":
504
+ return client.cart.removeCoupon(requireString(payload.code, "code"));
505
+ }
506
+ },
507
+ successEventKind(action) {
508
+ switch (action) {
509
+ case "getCart":
510
+ return "loaded";
511
+ case "getValidationStatus":
512
+ return "none";
513
+ case "addItem":
514
+ case "updateItem":
515
+ case "removeItem":
516
+ case "applyCoupon":
517
+ case "removeCoupon":
518
+ return "updated";
519
+ }
520
+ },
521
+ getResultEventSuffixes(_action, result) {
522
+ return isCart(result) ? ["updated"] : ["status"];
523
+ }
524
+ };
525
+ function buildAddItemOptions(payload) {
526
+ const options = asRecord(payload.options);
527
+ const extraEntries = Object.entries(payload).filter(([key]) => ![
528
+ "reference",
529
+ "ref",
530
+ "productReference",
531
+ "quantity",
532
+ "qty",
533
+ "options"
534
+ ].includes(key));
535
+ if (extraEntries.length === 0 && !options) {
536
+ return void 0;
537
+ }
538
+ return {
539
+ ...Object.fromEntries(extraEntries),
540
+ ...options
541
+ };
542
+ }
543
+ function isCart(result) {
544
+ return "guid" in result;
14
545
  }
546
+ const sessionModuleDefinition = {
547
+ moduleName: "session",
548
+ actionAttribute: "hx-altazion-session-action",
549
+ parseAction(actionValue) {
550
+ switch (actionValue) {
551
+ case "getSession":
552
+ return actionValue;
553
+ default:
554
+ throw new Error(`Unsupported session action: ${actionValue}`);
555
+ }
556
+ },
557
+ execute(client, action) {
558
+ switch (action) {
559
+ case "getSession":
560
+ return client.session.getSession();
561
+ }
562
+ },
563
+ successEventKind() {
564
+ return "loaded";
565
+ }
566
+ };
567
+ const marketingModuleDefinition = {
568
+ moduleName: "marketing",
569
+ actionAttribute: "hx-altazion-marketing-action",
570
+ payloadAttributes: {
571
+ "hx-altazion-marketing-code": "code"
572
+ },
573
+ jsonPayloadAttributes: {
574
+ "hx-altazion-marketing-codes": "codes"
575
+ },
576
+ parseAction(actionValue) {
577
+ switch (actionValue) {
578
+ case "getItem":
579
+ case "getItems":
580
+ return actionValue;
581
+ default:
582
+ throw new Error(`Unsupported marketing action: ${actionValue}`);
583
+ }
584
+ },
585
+ execute(client, action, payload) {
586
+ switch (action) {
587
+ case "getItem":
588
+ return client.marketing.getItem(requireString(payload.code, "code"));
589
+ case "getItems":
590
+ return client.marketing.getItems(readCodes(payload));
591
+ }
592
+ },
593
+ successEventKind() {
594
+ return "loaded";
595
+ },
596
+ getResultEventSuffixes(action) {
597
+ switch (action) {
598
+ case "getItem":
599
+ return ["item-loaded"];
600
+ case "getItems":
601
+ return ["items-loaded"];
602
+ }
603
+ }
604
+ };
605
+ function readCodes(payload) {
606
+ const value = payload.codes;
607
+ if (Array.isArray(value)) {
608
+ const codes = value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
609
+ if (codes.length > 0) {
610
+ return codes;
611
+ }
612
+ }
613
+ if (typeof value === "string") {
614
+ const codes = value.split(",").map((entry) => entry.trim()).filter((entry) => entry.length > 0);
615
+ if (codes.length > 0) {
616
+ return codes;
617
+ }
618
+ }
619
+ if (typeof payload.code === "string" && payload.code.trim().length > 0) {
620
+ return [payload.code.trim()];
621
+ }
622
+ throw new Error("Missing payload field: codes");
623
+ }
624
+ const storesModuleDefinition = {
625
+ moduleName: "stores",
626
+ actionAttribute: "hx-altazion-stores-action",
627
+ payloadAttributes: {
628
+ "hx-altazion-stores-store-guid": "storeGuid",
629
+ "hx-altazion-stores-latitude": "latitude",
630
+ "hx-altazion-stores-longitude": "longitude",
631
+ "hx-altazion-stores-radius-km": "radiusKm",
632
+ "hx-altazion-stores-postal-code": "postalCode",
633
+ "hx-altazion-stores-country-code": "countryCode"
634
+ },
635
+ payloadAliases: {
636
+ lat: "latitude",
637
+ lon: "longitude",
638
+ lng: "longitude",
639
+ radius: "radiusKm",
640
+ storeId: "storeGuid",
641
+ id: "storeGuid",
642
+ postal: "postalCode",
643
+ country: "countryCode"
644
+ },
645
+ parseAction(actionValue) {
646
+ switch (actionValue) {
647
+ case "findByLocation":
648
+ case "findByPostalCode":
649
+ case "getStore":
650
+ return actionValue;
651
+ default:
652
+ throw new Error(`Unsupported stores action: ${actionValue}`);
653
+ }
654
+ },
655
+ execute(client, action, payload) {
656
+ switch (action) {
657
+ case "findByLocation": {
658
+ const latitude = requireNumber(payload.latitude, "latitude");
659
+ const longitude = requireNumber(payload.longitude, "longitude");
660
+ const radiusKm = payload.radiusKm === void 0 ? 50 : requireNumber(payload.radiusKm, "radiusKm");
661
+ return client.stores.findByLocation(latitude, longitude, radiusKm);
662
+ }
663
+ case "findByPostalCode": {
664
+ const postalCode = requireString(payload.postalCode, "postalCode");
665
+ const countryCode = payload.countryCode === void 0 ? "FR" : requireString(payload.countryCode, "countryCode");
666
+ return client.stores.findByPostalCode(postalCode, countryCode);
667
+ }
668
+ case "getStore":
669
+ return client.stores.getStore(requireString(payload.storeGuid, "storeGuid"));
670
+ }
671
+ },
672
+ successEventKind() {
673
+ return "loaded";
674
+ },
675
+ getResultEventSuffixes(action) {
676
+ switch (action) {
677
+ case "getStore":
678
+ return ["store-loaded"];
679
+ case "findByLocation":
680
+ case "findByPostalCode":
681
+ return ["stores-loaded"];
682
+ }
683
+ }
684
+ };
685
+ function registerAltazionExtension(client) {
686
+ return createAltazionExtension(client, [
687
+ cartModuleDefinition,
688
+ sessionModuleDefinition,
689
+ marketingModuleDefinition,
690
+ storesModuleDefinition
691
+ ]);
692
+ }
693
+ const registerAltazionAuthExtension = registerAltazionExtension;
15
694
  function registerPriceHelpers(hbs, defaults) {
16
695
  hbs.registerHelper(
17
696
  "formatPrice",
@@ -141,133 +820,153 @@ var AltazionCommerceSdkHtmx = function(exports) {
141
820
  }, 0);
142
821
  });
143
822
  }
144
- const productCardTemplate = `<article class="altz-product-card{{#unless (isAvailable availability)}} altz-product-card--unavailable{{/unless}}">
145
- {{#if imageUrl}}
146
- <a href="{{productUrl reference}}" class="altz-product-card__image-link" aria-label="{{name}}">
147
- <img
148
- src="{{thumbnailUrl imageUrl 400}}"
149
- alt="{{name}}"
150
- class="altz-product-card__image"
151
- loading="lazy"
152
- width="400"
153
- />
154
- </a>
155
- {{/if}}
156
-
157
- <div class="altz-product-card__body">
158
- <a href="{{productUrl reference}}" class="altz-product-card__title">
159
- {{name}}
160
- </a>
161
-
162
- <div class="altz-product-card__pricing">
163
- {{#if discount}}
164
- <span class="altz-product-card__price altz-product-card__price--discounted">
165
- {{formatPrice price}}
166
- </span>
167
- <span class="altz-product-card__price altz-product-card__price--original">
168
- {{formatPrice originalPrice}}
169
- </span>
170
- <span class="altz-product-card__discount-badge">
171
- {{discountPercent originalPrice price}}
172
- </span>
173
- {{else}}
174
- <span class="altz-product-card__price">
175
- {{formatPrice price}}
176
- </span>
177
- {{/if}}
178
- </div>
179
-
180
- {{#unless (isAvailable availability)}}
181
- <p class="altz-product-card__unavailable">{{unavailableLabel}}</p>
182
- {{/unless}}
183
-
184
- {{#if (isAvailable availability)}}
185
- <button
186
- class="altz-product-card__add-to-cart"
187
- hx-post="/commerce/api/process/cart/lines"
188
- hx-vals='{"productReference":"{{reference}}","quantity":1}'
189
- hx-target="#altz-cart-summary"
190
- hx-swap="outerHTML"
191
- hx-indicator=".altz-spinner"
192
- >
193
- {{addToCartLabel}}
194
- </button>
195
- {{/if}}
196
- </div>
197
- </article>
198
- `;
823
+ const DATA_SOURCE_ATTRIBUTE = "hx-altazion-data-source";
824
+ const DATA_STATUS_ATTRIBUTE = "hx-altazion-data-status";
825
+ const RENDER_TEMPLATE_ATTRIBUTE = "hx-render-template";
826
+ const DATA_SOURCE_ALIASES = {
827
+ cart: "cart",
828
+ session: "session",
829
+ store: "store",
830
+ stores: "stores",
831
+ "marketing-item": "marketingItem",
832
+ "marketing-items": "marketingItems"
833
+ };
834
+ function createAltazionDeclarativeRenderer(handlebars) {
835
+ const state = {
836
+ cart: null,
837
+ session: null,
838
+ store: null,
839
+ stores: [],
840
+ marketingItem: null,
841
+ marketingItems: [],
842
+ slots: {}
843
+ };
844
+ const templateCache = /* @__PURE__ */ new Map();
845
+ const render = () => {
846
+ if (typeof document === "undefined") {
847
+ return;
848
+ }
849
+ for (const element of document.querySelectorAll(`[${DATA_SOURCE_ATTRIBUTE}]`)) {
850
+ const rawSource = element.getAttribute(DATA_SOURCE_ATTRIBUTE);
851
+ const source = resolveDataSource(rawSource);
852
+ if (!source) {
853
+ continue;
854
+ }
855
+ const rawStatus = element.getAttribute(DATA_STATUS_ATTRIBUTE);
856
+ const sourceValue = resolveSourceValue(state, source);
857
+ const isVisible = matchesStatus(rawStatus, sourceValue);
858
+ applyVisibility(element, isVisible);
859
+ renderElementTemplate(element, isVisible, state, sourceValue, handlebars, templateCache);
860
+ }
861
+ };
862
+ return {
863
+ update(key, value) {
864
+ state[key] = value;
865
+ render();
866
+ },
867
+ updateSlot(name, value) {
868
+ state.slots[name] = value;
869
+ render();
870
+ },
871
+ render,
872
+ dispose() {
873
+ templateCache.clear();
874
+ }
875
+ };
876
+ }
877
+ function matchesStatus(status, value) {
878
+ if (Array.isArray(value)) {
879
+ switch (status) {
880
+ case "empty":
881
+ return value.length === 0;
882
+ case "not-empty":
883
+ return value.length > 0;
884
+ default:
885
+ return true;
886
+ }
887
+ }
888
+ switch (status) {
889
+ case "null":
890
+ return value == null;
891
+ case "not-null":
892
+ return value != null;
893
+ default:
894
+ return true;
895
+ }
896
+ }
897
+ function resolveDataSource(source) {
898
+ if (!source) {
899
+ return null;
900
+ }
901
+ if (source.startsWith("slot:")) {
902
+ const slotKey = source.slice(5).trim();
903
+ return slotKey.length > 0 ? { kind: "slot", key: slotKey } : null;
904
+ }
905
+ const resolvedKey = DATA_SOURCE_ALIASES[source];
906
+ return resolvedKey ? { kind: "state", key: resolvedKey } : null;
907
+ }
908
+ function resolveSourceValue(state, source) {
909
+ if (source.kind === "slot") {
910
+ return state.slots[source.key] ?? null;
911
+ }
912
+ return state[source.key];
913
+ }
914
+ function applyVisibility(element, isVisible) {
915
+ element.setAttribute("aria-hidden", isVisible ? "false" : "true");
916
+ if (element instanceof HTMLElement) {
917
+ element.hidden = !isVisible;
918
+ } else if (isVisible) {
919
+ element.removeAttribute("hidden");
920
+ } else {
921
+ element.setAttribute("hidden", "");
922
+ }
923
+ }
924
+ function renderElementTemplate(element, isVisible, state, sourceValue, handlebars, templateCache) {
925
+ if (!isVisible || !element.hasAttribute(RENDER_TEMPLATE_ATTRIBUTE) || !handlebars) {
926
+ return;
927
+ }
928
+ const templateId = element.getAttribute(RENDER_TEMPLATE_ATTRIBUTE);
929
+ if (!templateId) {
930
+ return;
931
+ }
932
+ const template = resolveTemplate(templateId, handlebars, templateCache);
933
+ if (!template) {
934
+ return;
935
+ }
936
+ element.innerHTML = template({
937
+ ...state,
938
+ slot: sourceValue
939
+ });
940
+ }
941
+ function resolveTemplate(templateId, handlebars, templateCache) {
942
+ const cached = templateCache.get(templateId);
943
+ if (cached) {
944
+ return cached;
945
+ }
946
+ if (typeof document === "undefined") {
947
+ return null;
948
+ }
949
+ const templateElement = document.getElementById(templateId);
950
+ if (!templateElement) {
951
+ console.warn(`[AltazionHtmx] Template not found: ${templateId}`);
952
+ return null;
953
+ }
954
+ const compiled = handlebars.compile(templateElement.innerHTML);
955
+ templateCache.set(templateId, compiled);
956
+ return compiled;
957
+ }
958
+ const productCardTemplate = '<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';
199
959
  const cartMiniTemplate = '<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';
200
- const productListTemplate = `<section class="altz-product-list">
201
- {{#if title}}
202
- <h2 class="altz-product-list__title">{{title}}</h2>
203
- {{/if}}
204
-
205
- {{#if products.length}}
206
- <ul class="altz-product-list__grid" role="list">
207
- {{#each products}}
208
- <li class="altz-product-list__item">
209
- <article class="altz-product-card{{#unless (isAvailable this.availability)}} altz-product-card--unavailable{{/unless}}">
210
- {{#if this.imageUrl}}
211
- <a href="{{productUrl this.reference}}" class="altz-product-card__image-link" aria-label="{{this.name}}">
212
- <img
213
- src="{{thumbnailUrl this.imageUrl 300}}"
214
- alt="{{this.name}}"
215
- class="altz-product-card__image"
216
- loading="lazy"
217
- width="300"
218
- />
219
- </a>
220
- {{/if}}
221
-
222
- <div class="altz-product-card__body">
223
- <a href="{{productUrl this.reference}}" class="altz-product-card__title">
224
- {{this.name}}
225
- </a>
226
-
227
- <div class="altz-product-card__pricing">
228
- {{#if this.discount}}
229
- <span class="altz-product-card__price altz-product-card__price--discounted">
230
- {{formatPrice this.price}}
231
- </span>
232
- <span class="altz-product-card__price altz-product-card__price--original">
233
- {{formatPrice this.originalPrice}}
234
- </span>
235
- <span class="altz-product-card__discount-badge">
236
- {{discountPercent this.originalPrice this.price}}
237
- </span>
238
- {{else}}
239
- <span class="altz-product-card__price">
240
- {{formatPrice this.price}}
241
- </span>
242
- {{/if}}
243
- </div>
244
-
245
- {{#if (isAvailable this.availability)}}
246
- <button
247
- class="altz-product-card__add-to-cart"
248
- hx-post="/commerce/api/process/cart/lines"
249
- hx-vals='{"productReference":"{{this.reference}}","quantity":1}'
250
- hx-target="#altz-cart-summary"
251
- hx-swap="outerHTML"
252
- hx-indicator=".altz-spinner"
253
- >
254
- {{../addToCartLabel}}
255
- </button>
256
- {{/if}}
257
- </div>
258
- </article>
259
- </li>
260
- {{/each}}
261
- </ul>
262
- {{else}}
263
- <p class="altz-product-list__empty">{{emptyLabel}}</p>
264
- {{/if}}
265
- </section>
266
- `;
267
- function init(config) {
960
+ const productListTemplate = '<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';
961
+ function initAltazionHtmx(config) {
268
962
  var _a;
269
- const { client, handlebars, offlineSelector = "body" } = config;
270
- registerAltazionAuthExtension(client);
963
+ const {
964
+ client,
965
+ handlebars,
966
+ offlineSelector = "body",
967
+ terminalMode
968
+ } = config;
969
+ const extensionHandle = registerAltazionExtension(client);
271
970
  if (typeof window !== "undefined" && window.htmx) {
272
971
  window.htmx.config = window.htmx.config ?? {};
273
972
  window.htmx.config.withCredentials = true;
@@ -276,24 +975,91 @@ var AltazionCommerceSdkHtmx = function(exports) {
276
975
  locale: client.context.locale,
277
976
  currency: client.context.currency
278
977
  };
978
+ const handlebarsRuntime = handlebars ?? (typeof window !== "undefined" ? window.Handlebars : void 0);
979
+ const declarativeRenderer = createAltazionDeclarativeRenderer(handlebarsRuntime);
980
+ const syncSlotFromEvent = (detail) => {
981
+ var _a2;
982
+ const slotName = (_a2 = detail.element.getAttribute("hx-altazion-data-slot")) == null ? void 0 : _a2.trim();
983
+ if (!slotName) {
984
+ return;
985
+ }
986
+ declarativeRenderer.updateSlot(slotName, detail.result ?? null);
987
+ };
279
988
  let currentCart = null;
280
989
  const getCart = () => currentCart;
281
- client.onQueueEvent(async (event) => {
282
- if (event.type === "flushed") {
283
- try {
284
- currentCart = await client.cart.getCart();
285
- } catch {
286
- }
990
+ const syncCartFromEvent = (event) => {
991
+ const customEvent = event;
992
+ if (customEvent.detail.result) {
993
+ currentCart = customEvent.detail.result;
994
+ declarativeRenderer.update("cart", currentCart);
287
995
  }
996
+ syncSlotFromEvent(customEvent.detail);
997
+ };
998
+ const syncSessionFromEvent = (event) => {
999
+ const customEvent = event;
1000
+ declarativeRenderer.update("session", customEvent.detail.result ?? null);
1001
+ syncSlotFromEvent(customEvent.detail);
1002
+ };
1003
+ const syncStoreFromEvent = (event) => {
1004
+ const customEvent = event;
1005
+ declarativeRenderer.update("store", customEvent.detail.result ?? null);
1006
+ syncSlotFromEvent(customEvent.detail);
1007
+ };
1008
+ const syncStoresFromEvent = (event) => {
1009
+ const customEvent = event;
1010
+ declarativeRenderer.update("stores", Array.isArray(customEvent.detail.result) ? customEvent.detail.result : []);
1011
+ syncSlotFromEvent(customEvent.detail);
1012
+ };
1013
+ const syncMarketingItemFromEvent = (event) => {
1014
+ const customEvent = event;
1015
+ declarativeRenderer.update("marketingItem", Array.isArray(customEvent.detail.result) ? null : customEvent.detail.result ?? null);
1016
+ syncSlotFromEvent(customEvent.detail);
1017
+ };
1018
+ const syncMarketingItemsFromEvent = (event) => {
1019
+ const customEvent = event;
1020
+ declarativeRenderer.update("marketingItems", Array.isArray(customEvent.detail.result) ? customEvent.detail.result : []);
1021
+ syncSlotFromEvent(customEvent.detail);
1022
+ };
1023
+ if (typeof document !== "undefined") {
1024
+ document.addEventListener("altazion:cart:loaded", syncCartFromEvent);
1025
+ document.addEventListener("altazion:cart:updated", syncCartFromEvent);
1026
+ document.addEventListener("altazion:session:loaded", syncSessionFromEvent);
1027
+ document.addEventListener("altazion:stores:store-loaded", syncStoreFromEvent);
1028
+ document.addEventListener("altazion:stores:stores-loaded", syncStoresFromEvent);
1029
+ document.addEventListener("altazion:marketing:item-loaded", syncMarketingItemFromEvent);
1030
+ document.addEventListener("altazion:marketing:items-loaded", syncMarketingItemsFromEvent);
1031
+ }
1032
+ void client.cart.getCart().then((cart) => {
1033
+ currentCart = cart;
1034
+ declarativeRenderer.update("cart", cart);
1035
+ }).catch(() => {
288
1036
  });
289
1037
  if (handlebars) {
290
1038
  registerPriceHelpers(handlebars, defaults);
291
1039
  registerProductHelpers(handlebars, client.context.siteUrl ?? "");
292
1040
  registerCartHelpers(handlebars, getCart, defaults);
293
1041
  }
294
- const offlineEl = typeof document !== "undefined" ? document.querySelector(offlineSelector) : null;
1042
+ declarativeRenderer.render();
1043
+ const offlineEl = typeof document !== "undefined" ? document.querySelector(offlineSelector) ?? document.body : null;
1044
+ let lastConnectivityStatus = null;
295
1045
  const updateOfflineClass = () => {
296
- offlineEl == null ? void 0 : offlineEl.classList.toggle("altz-offline", client.isOffline);
1046
+ if (!offlineEl) {
1047
+ return;
1048
+ }
1049
+ const status = client.isOffline ? "offline" : "online";
1050
+ const isOffline = status === "offline";
1051
+ offlineEl.classList.toggle("altz-offline", isOffline);
1052
+ offlineEl.classList.toggle("altz-terminal-offline", isOffline);
1053
+ offlineEl.classList.toggle("altz-terminal-online", !isOffline);
1054
+ offlineEl.setAttribute("data-altazion-terminal-state", status);
1055
+ updateManagedVisibility(resolveManagedElements(terminalMode == null ? void 0 : terminalMode.interactiveSelectors), isOffline, "altz-terminal-interactive-hidden");
1056
+ updateManagedVisibility(resolveManagedElements(terminalMode == null ? void 0 : terminalMode.offlineScreenSelectors), !isOffline, "altz-terminal-offline-screen-hidden");
1057
+ if (lastConnectivityStatus === status) {
1058
+ return;
1059
+ }
1060
+ lastConnectivityStatus = status;
1061
+ dispatchConnectivityEvent(offlineEl, "altazion:connectivity:changed", status);
1062
+ dispatchConnectivityEvent(offlineEl, isOffline ? "altazion:offline" : "altazion:online", status);
297
1063
  };
298
1064
  updateOfflineClass();
299
1065
  const unsubscribeConnectivity = (_a = client.connectivity) == null ? void 0 : _a.subscribe(() => updateOfflineClass());
@@ -310,16 +1076,74 @@ var AltazionCommerceSdkHtmx = function(exports) {
310
1076
  return {
311
1077
  templates,
312
1078
  dispose() {
1079
+ extensionHandle.dispose();
1080
+ if (typeof document !== "undefined") {
1081
+ document.removeEventListener("altazion:cart:loaded", syncCartFromEvent);
1082
+ document.removeEventListener("altazion:cart:updated", syncCartFromEvent);
1083
+ document.removeEventListener("altazion:session:loaded", syncSessionFromEvent);
1084
+ document.removeEventListener("altazion:stores:store-loaded", syncStoreFromEvent);
1085
+ document.removeEventListener("altazion:stores:stores-loaded", syncStoresFromEvent);
1086
+ document.removeEventListener("altazion:marketing:item-loaded", syncMarketingItemFromEvent);
1087
+ document.removeEventListener("altazion:marketing:items-loaded", syncMarketingItemsFromEvent);
1088
+ }
1089
+ declarativeRenderer.dispose();
313
1090
  unsubscribeConnectivity == null ? void 0 : unsubscribeConnectivity();
314
1091
  }
315
1092
  };
316
1093
  }
1094
+ const init = initAltazionHtmx;
1095
+ function resolveManagedElements(selectorInput) {
1096
+ if (typeof document === "undefined" || !selectorInput) {
1097
+ return [];
1098
+ }
1099
+ const selectors = Array.isArray(selectorInput) ? selectorInput : [selectorInput];
1100
+ const elements = /* @__PURE__ */ new Set();
1101
+ for (const selector of selectors) {
1102
+ if (!selector.trim()) {
1103
+ continue;
1104
+ }
1105
+ try {
1106
+ for (const element of document.querySelectorAll(selector)) {
1107
+ elements.add(element);
1108
+ }
1109
+ } catch {
1110
+ }
1111
+ }
1112
+ return [...elements];
1113
+ }
1114
+ function updateManagedVisibility(elements, hidden, hiddenClassName) {
1115
+ for (const element of elements) {
1116
+ element.classList.toggle(hiddenClassName, hidden);
1117
+ element.setAttribute("aria-hidden", hidden ? "true" : "false");
1118
+ if (element instanceof HTMLElement) {
1119
+ element.hidden = hidden;
1120
+ } else if (hidden) {
1121
+ element.setAttribute("hidden", "");
1122
+ } else {
1123
+ element.removeAttribute("hidden");
1124
+ }
1125
+ }
1126
+ }
1127
+ function dispatchConnectivityEvent(root, eventName, status) {
1128
+ const detail = {
1129
+ status,
1130
+ isOnline: status === "online",
1131
+ isOffline: status === "offline",
1132
+ root
1133
+ };
1134
+ root.dispatchEvent(new CustomEvent(eventName, {
1135
+ bubbles: true,
1136
+ detail
1137
+ }));
1138
+ }
317
1139
  exports.init = init;
1140
+ exports.initAltazionHtmx = initAltazionHtmx;
318
1141
  exports.registerAltazionAuthExtension = registerAltazionAuthExtension;
1142
+ exports.registerAltazionExtension = registerAltazionExtension;
319
1143
  exports.registerCartHelpers = registerCartHelpers;
320
1144
  exports.registerPriceHelpers = registerPriceHelpers;
321
1145
  exports.registerProductHelpers = registerProductHelpers;
322
1146
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
323
1147
  return exports;
324
- }({});
1148
+ }({}, AltazionCommerceCore);
325
1149
  //# sourceMappingURL=index.iife.js.map