zz-shopify-components 0.22.0 → 0.22.1-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/assets/zz-modal.js +100 -5
- package/package.json +1 -1
package/assets/zz-modal.js
CHANGED
|
@@ -4,11 +4,30 @@
|
|
|
4
4
|
- Attribute reflection and programmatic API: show(), hide(), toggle()
|
|
5
5
|
- Options via attributes: close-on-esc, close-on-backdrop, scroll-lock, inert-others
|
|
6
6
|
- Global open/close triggers: [data-zz-modal-target], [data-zz-modal-close]
|
|
7
|
+
- Analytics tracking: modal open/close/confirm events
|
|
7
8
|
*/
|
|
8
9
|
|
|
9
10
|
(() => {
|
|
10
11
|
if (customElements.get('zz-modal')) return;
|
|
11
12
|
|
|
13
|
+
// Analytics tracking utility
|
|
14
|
+
const trackModalEvent = (eventType, modalId, additionalData = {}) => {
|
|
15
|
+
try {
|
|
16
|
+
const eventData = {
|
|
17
|
+
event: 'modal_interaction',
|
|
18
|
+
modal_action: eventType,
|
|
19
|
+
modal_id: modalId || 'unknown',
|
|
20
|
+
timestamp: new Date().toISOString(),
|
|
21
|
+
...additionalData
|
|
22
|
+
};
|
|
23
|
+
window.zzAnalytics && window.zzAnalytics.trackEvent(eventType, eventData);
|
|
24
|
+
|
|
25
|
+
console.log('[ZZ-Modal Analytics]', eventData);
|
|
26
|
+
} catch (error) {
|
|
27
|
+
console.warn('[ZZ-Modal Analytics] Tracking failed:', error);
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
|
|
12
31
|
const STYLE_TEXT = `
|
|
13
32
|
:host {
|
|
14
33
|
position: relative;
|
|
@@ -155,6 +174,9 @@
|
|
|
155
174
|
this._onClick = this._onClick.bind(this);
|
|
156
175
|
this._previousActive = null;
|
|
157
176
|
this._mouseDownInsidePanel = false;
|
|
177
|
+
this._openTimestamp = null;
|
|
178
|
+
this._lastTriggerSource = null;
|
|
179
|
+
this._lastCloseMethod = null;
|
|
158
180
|
|
|
159
181
|
const shadow = this.attachShadow({ mode: 'open' });
|
|
160
182
|
const style = document.createElement('style');
|
|
@@ -176,7 +198,10 @@
|
|
|
176
198
|
|
|
177
199
|
connectedCallback() {
|
|
178
200
|
// Delegated internal events
|
|
179
|
-
this._closeBtn.addEventListener('click', () =>
|
|
201
|
+
this._closeBtn.addEventListener('click', () => {
|
|
202
|
+
this._lastCloseMethod = 'close_button';
|
|
203
|
+
this.hide();
|
|
204
|
+
});
|
|
180
205
|
this._dialog.addEventListener('close', this._onNativeClose);
|
|
181
206
|
this._dialog.addEventListener('mousedown', this._onMouseDown);
|
|
182
207
|
this._dialog.addEventListener('click', this._onClick);
|
|
@@ -214,8 +239,18 @@
|
|
|
214
239
|
get open() { return this._dialog?.open || this.hasAttribute('open'); }
|
|
215
240
|
set open(val) { if (val) this.setAttribute('open', ''); else this.removeAttribute('open'); }
|
|
216
241
|
|
|
217
|
-
show() {
|
|
218
|
-
|
|
242
|
+
show() {
|
|
243
|
+
if (!this._lastTriggerSource) {
|
|
244
|
+
this._lastTriggerSource = 'unknown';
|
|
245
|
+
}
|
|
246
|
+
this._openInternal(true);
|
|
247
|
+
}
|
|
248
|
+
hide() {
|
|
249
|
+
if (!this._lastCloseMethod) {
|
|
250
|
+
this._lastCloseMethod = 'unknown';
|
|
251
|
+
}
|
|
252
|
+
this._closeInternal(true);
|
|
253
|
+
}
|
|
219
254
|
toggle() { this.open ? this.hide() : this.show(); }
|
|
220
255
|
|
|
221
256
|
// Aliases
|
|
@@ -229,6 +264,7 @@
|
|
|
229
264
|
_openInternal(emit = false) {
|
|
230
265
|
if (this._dialog.open) return;
|
|
231
266
|
this._previousActive = document.activeElement;
|
|
267
|
+
this._openTimestamp = Date.now();
|
|
232
268
|
|
|
233
269
|
// Scroll lock
|
|
234
270
|
if (!this.hasAttribute('no-scroll-lock')) {
|
|
@@ -261,7 +297,14 @@
|
|
|
261
297
|
// Focus first focusable within panel
|
|
262
298
|
this._focusInitial();
|
|
263
299
|
|
|
264
|
-
if (emit)
|
|
300
|
+
if (emit) {
|
|
301
|
+
this._emit('zz-modal:open');
|
|
302
|
+
const modalId = this.getAttribute('data-modal-id') || this.id || 'unnamed-modal';
|
|
303
|
+
trackModalEvent('modal_open', modalId, {
|
|
304
|
+
trigger_source: this._getTriggerSource(),
|
|
305
|
+
modal_type: this.getAttribute('data-modal-type') || 'default'
|
|
306
|
+
});
|
|
307
|
+
}
|
|
265
308
|
}
|
|
266
309
|
|
|
267
310
|
_closeInternal(emit = false) {
|
|
@@ -292,13 +335,26 @@
|
|
|
292
335
|
}
|
|
293
336
|
this._previousActive = null;
|
|
294
337
|
|
|
295
|
-
if (emit)
|
|
338
|
+
if (emit) {
|
|
339
|
+
this._emit('zz-modal:close');
|
|
340
|
+
const modalId = this.getAttribute('data-modal-id') || this.id || 'unnamed-modal';
|
|
341
|
+
trackModalEvent('modal_close', modalId, {
|
|
342
|
+
close_method: this._getCloseMethod(),
|
|
343
|
+
modal_type: this.getAttribute('data-modal-type') || 'default',
|
|
344
|
+
time_open: this._getTimeOpen()
|
|
345
|
+
});
|
|
346
|
+
|
|
347
|
+
this._lastTriggerSource = null;
|
|
348
|
+
this._lastCloseMethod = null;
|
|
349
|
+
this._openTimestamp = null;
|
|
350
|
+
}
|
|
296
351
|
}
|
|
297
352
|
|
|
298
353
|
_onKeydown(e) {
|
|
299
354
|
const escAllowed = !this.hasAttribute('no-esc-close');
|
|
300
355
|
if (e.key === 'Escape' && escAllowed) {
|
|
301
356
|
e.stopPropagation();
|
|
357
|
+
this._lastCloseMethod = 'escape_key';
|
|
302
358
|
this.hide();
|
|
303
359
|
}
|
|
304
360
|
|
|
@@ -342,6 +398,7 @@
|
|
|
342
398
|
const path = e.composedPath();
|
|
343
399
|
const clickInsidePanel = path.includes(this._panel);
|
|
344
400
|
if (!clickInsidePanel && !this._mouseDownInsidePanel) {
|
|
401
|
+
this._lastCloseMethod = 'backdrop_click';
|
|
345
402
|
this.hide();
|
|
346
403
|
}
|
|
347
404
|
this._mouseDownInsidePanel = false;
|
|
@@ -401,6 +458,30 @@
|
|
|
401
458
|
if (isInert) el.setAttribute('inert', ''); else el.removeAttribute('inert');
|
|
402
459
|
});
|
|
403
460
|
}
|
|
461
|
+
|
|
462
|
+
// Analytics helper methods
|
|
463
|
+
_getTriggerSource() {
|
|
464
|
+
return this._lastTriggerSource || 'programmatic';
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
_getCloseMethod() {
|
|
468
|
+
return this._lastCloseMethod || 'unknown';
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
_getTimeOpen() {
|
|
472
|
+
if (!this._openTimestamp) return 0;
|
|
473
|
+
return Date.now() - this._openTimestamp;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
trackConfirm(confirmType = 'default', additionalData = {}) {
|
|
477
|
+
const modalId = this.getAttribute('data-modal-id') || this.id || 'unnamed-modal';
|
|
478
|
+
trackModalEvent('modal_confirm', modalId, {
|
|
479
|
+
confirm_type: confirmType,
|
|
480
|
+
modal_type: this.getAttribute('data-modal-type') || 'default',
|
|
481
|
+
time_to_confirm: this._getTimeOpen(),
|
|
482
|
+
...additionalData
|
|
483
|
+
});
|
|
484
|
+
}
|
|
404
485
|
}
|
|
405
486
|
|
|
406
487
|
customElements.define('zz-modal', ZZModal);
|
|
@@ -414,6 +495,7 @@
|
|
|
414
495
|
const modal = document.querySelector(selector);
|
|
415
496
|
if (modal && modal.show) {
|
|
416
497
|
e.preventDefault();
|
|
498
|
+
modal._lastTriggerSource = 'data_attribute';
|
|
417
499
|
modal.show();
|
|
418
500
|
}
|
|
419
501
|
}
|
|
@@ -424,9 +506,22 @@
|
|
|
424
506
|
const hostModal = closeTrigger.closest('zz-modal');
|
|
425
507
|
if (hostModal && hostModal.hide) {
|
|
426
508
|
e.preventDefault();
|
|
509
|
+
hostModal._lastCloseMethod = 'data_attribute';
|
|
427
510
|
hostModal.hide();
|
|
428
511
|
}
|
|
429
512
|
}
|
|
513
|
+
|
|
514
|
+
const confirmTrigger = e.target.closest('[data-zz-modal-confirm]');
|
|
515
|
+
if (confirmTrigger) {
|
|
516
|
+
const hostModal = confirmTrigger.closest('zz-modal');
|
|
517
|
+
if (hostModal && hostModal.trackConfirm) {
|
|
518
|
+
const confirmType = confirmTrigger.getAttribute('data-zz-modal-confirm') || 'default';
|
|
519
|
+
hostModal.trackConfirm(confirmType, {
|
|
520
|
+
button_text: confirmTrigger.textContent?.trim() || '',
|
|
521
|
+
button_class: confirmTrigger.className || ''
|
|
522
|
+
});
|
|
523
|
+
}
|
|
524
|
+
}
|
|
430
525
|
}, { capture: true });
|
|
431
526
|
})();
|
|
432
527
|
|