@wix/interact 1.74.0 → 1.76.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.
Files changed (52) hide show
  1. package/README.md +33 -21
  2. package/dist/cjs/WixInteractElement.js +61 -17
  3. package/dist/cjs/WixInteractElement.js.map +1 -1
  4. package/dist/cjs/__tests__/interact.spec.js +761 -109
  5. package/dist/cjs/__tests__/interact.spec.js.map +1 -1
  6. package/dist/cjs/core/Interact.js +190 -0
  7. package/dist/cjs/core/Interact.js.map +1 -0
  8. package/dist/cjs/core/add.js +231 -0
  9. package/dist/cjs/core/add.js.map +1 -0
  10. package/dist/cjs/core/remove.js +37 -0
  11. package/dist/cjs/core/remove.js.map +1 -0
  12. package/dist/cjs/handlers/click.js +1 -1
  13. package/dist/cjs/handlers/click.js.map +1 -1
  14. package/dist/cjs/handlers/hover.js +1 -1
  15. package/dist/cjs/handlers/hover.js.map +1 -1
  16. package/dist/cjs/index.js +6 -4
  17. package/dist/cjs/index.js.map +1 -1
  18. package/dist/cjs/types.js.map +1 -1
  19. package/dist/cjs/utils.js +12 -10
  20. package/dist/cjs/utils.js.map +1 -1
  21. package/dist/esm/WixInteractElement.js +61 -17
  22. package/dist/esm/WixInteractElement.js.map +1 -1
  23. package/dist/esm/__tests__/interact.spec.js +743 -91
  24. package/dist/esm/__tests__/interact.spec.js.map +1 -1
  25. package/dist/esm/core/Interact.js +186 -0
  26. package/dist/esm/core/Interact.js.map +1 -0
  27. package/dist/esm/core/add.js +226 -0
  28. package/dist/esm/core/add.js.map +1 -0
  29. package/dist/esm/core/remove.js +32 -0
  30. package/dist/esm/core/remove.js.map +1 -0
  31. package/dist/esm/handlers/click.js +1 -1
  32. package/dist/esm/handlers/click.js.map +1 -1
  33. package/dist/esm/handlers/hover.js +1 -1
  34. package/dist/esm/handlers/hover.js.map +1 -1
  35. package/dist/esm/index.js +3 -1
  36. package/dist/esm/index.js.map +1 -1
  37. package/dist/esm/types.js.map +1 -1
  38. package/dist/esm/utils.js +12 -10
  39. package/dist/esm/utils.js.map +1 -1
  40. package/dist/types/WixInteractElement.d.ts +5 -2
  41. package/dist/types/core/Interact.d.ts +24 -0
  42. package/dist/types/core/add.d.ts +6 -0
  43. package/dist/types/core/remove.d.ts +5 -0
  44. package/dist/types/index.d.ts +3 -1
  45. package/dist/types/types.d.ts +22 -9
  46. package/dist/types/utils.d.ts +1 -1
  47. package/package.json +7 -6
  48. package/dist/cjs/interact.js +0 -308
  49. package/dist/cjs/interact.js.map +0 -1
  50. package/dist/esm/interact.js +0 -301
  51. package/dist/esm/interact.js.map +0 -1
  52. package/dist/types/interact.d.ts +0 -26
@@ -1,4 +1,6 @@
1
- import { Interact, add, remove } from '../interact';
1
+ import { Interact } from '../core/Interact';
2
+ import { add, addListItems } from '../core/add';
3
+ import { remove } from '../core/remove';
2
4
  import { effectToAnimationOptions } from '../handlers/utilities';
3
5
 
4
6
  // Mock @wix/motion module
@@ -40,75 +42,75 @@ describe('interact', () => {
40
42
  const mockConfig = {
41
43
  interactions: [{
42
44
  trigger: 'viewEnter',
43
- source: '#logo-entrance',
45
+ key: 'logo-entrance',
44
46
  params: {
45
47
  threshold: 0.2
46
48
  },
47
49
  effects: [{
48
- target: '#logo-entrance',
50
+ key: 'logo-entrance',
49
51
  effectId: 'logo-arc-in'
50
52
  }, {
51
- target: '#logo-click',
53
+ key: 'logo-click',
52
54
  effectId: 'logo-bounce'
53
55
  }]
54
56
  }, {
55
57
  trigger: 'pageVisible',
56
- source: '#logo-loop',
58
+ key: 'logo-loop',
57
59
  effects: [{
58
- target: '#logo-loop',
60
+ key: 'logo-loop',
59
61
  effectId: 'logo-poke'
60
62
  }]
61
63
  }, {
62
64
  trigger: 'animationEnd',
63
- source: '#logo-animation-end',
65
+ key: 'logo-animation-end',
64
66
  params: {
65
67
  effectId: 'logo-arc-in'
66
68
  },
67
69
  effects: [{
68
- target: '#logo-animation-end',
70
+ key: 'logo-animation-end',
69
71
  effectId: 'logo-poke'
70
72
  }]
71
73
  }, {
72
74
  trigger: 'pointerMove',
73
- source: '#logo-mouse',
75
+ key: 'logo-mouse',
74
76
  params: {
75
77
  hitArea: 'root'
76
78
  },
77
79
  effects: [{
78
- target: '#logo-mouse',
80
+ key: 'logo-mouse',
79
81
  effectId: 'logo-track-mouse'
80
82
  }]
81
83
  }, {
82
84
  trigger: 'click',
83
- source: '#logo-click',
85
+ key: 'logo-click',
84
86
  params: {
85
87
  type: 'alternate'
86
88
  },
87
89
  effects: [{
88
- target: '#logo-click',
90
+ key: 'logo-click',
89
91
  effectId: 'logo-bounce'
90
92
  }]
91
93
  }, {
92
94
  trigger: 'click',
93
- source: '#logo-click',
95
+ key: 'logo-click',
94
96
  params: {
95
97
  method: 'toggle'
96
98
  },
97
99
  effects: [{
98
- target: '#logo-click',
100
+ key: 'logo-click',
99
101
  effectId: 'logo-transition-hover'
100
102
  }]
101
103
  }, {
102
104
  trigger: 'hover',
103
- source: '#logo-hover',
105
+ key: 'logo-hover',
104
106
  params: {
105
107
  type: 'alternate'
106
108
  },
107
109
  effects: [{
108
- target: '#logo-hover',
110
+ key: 'logo-hover',
109
111
  effectId: 'logo-arc-in'
110
112
  }, {
111
- target: '#logo-hover',
113
+ key: 'logo-hover',
112
114
  effectId: 'logo-arc-in',
113
115
  namedEffect: {
114
116
  type: 'ArcIn',
@@ -118,19 +120,49 @@ describe('interact', () => {
118
120
  }]
119
121
  }, {
120
122
  trigger: 'hover',
121
- source: '#logo-hover',
123
+ key: 'logo-hover',
122
124
  params: {
123
125
  method: 'toggle'
124
126
  },
125
127
  effects: [{
126
- target: '#logo-hover',
128
+ key: 'logo-hover',
127
129
  effectId: 'logo-transition-hover'
128
130
  }]
129
131
  }, {
130
132
  trigger: 'viewProgress',
131
- source: '#logo-scroll',
133
+ key: 'logo-scroll',
132
134
  effects: [{
133
- target: '#logo-scroll',
135
+ key: 'logo-scroll',
136
+ effectId: 'logo-fade-scroll'
137
+ }]
138
+ }, {
139
+ trigger: 'click',
140
+ key: 'logo-click-container',
141
+ listContainer: '#logo-list',
142
+ effects: [{
143
+ effectId: 'logo-bounce'
144
+ }]
145
+ }, {
146
+ trigger: 'viewEnter',
147
+ key: 'logo-view-container',
148
+ effects: [{
149
+ listContainer: '#logo-list',
150
+ effectId: 'logo-bounce'
151
+ }]
152
+ }, {
153
+ trigger: 'viewProgress',
154
+ key: 'logo-scroll-container',
155
+ listContainer: '#logo-scroll-list',
156
+ effects: [{
157
+ listContainer: '#logo-scroll-list',
158
+ effectId: 'logo-fade-scroll'
159
+ }]
160
+ }, {
161
+ trigger: 'viewProgress',
162
+ key: 'logo-scroll-container',
163
+ effects: [{
164
+ key: 'logo-scroll-items',
165
+ listContainer: '#logo-scroll-list',
134
166
  effectId: 'logo-fade-scroll'
135
167
  }]
136
168
  }],
@@ -144,7 +176,7 @@ describe('interact', () => {
144
176
  duration: 1200
145
177
  },
146
178
  'logo-arc-in-with-target': {
147
- target: '#logo-hover',
179
+ key: 'logo-hover',
148
180
  namedEffect: {
149
181
  type: 'ArcIn',
150
182
  direction: 'right',
@@ -268,7 +300,8 @@ describe('interact', () => {
268
300
  window.CSSStyleSheet = class CSSStyleSheet {
269
301
  constructor(_) {
270
302
  return {
271
- replace: jest.fn()
303
+ replace: jest.fn(),
304
+ insertRule: jest.fn()
272
305
  };
273
306
  }
274
307
  };
@@ -327,12 +360,12 @@ describe('interact', () => {
327
360
  },
328
361
  interactions: [{
329
362
  trigger: 'click',
330
- source: '#cascade-source',
363
+ key: 'cascade-source',
331
364
  effects: [{
332
- target: '#cascade-target',
365
+ key: 'cascade-target',
333
366
  effectId: 'default-effect'
334
367
  }, {
335
- target: '#cascade-target',
368
+ key: 'cascade-target',
336
369
  effectId: 'default-effect',
337
370
  conditions: ['desktop'],
338
371
  namedEffect: {
@@ -342,7 +375,7 @@ describe('interact', () => {
342
375
  },
343
376
  duration: 800
344
377
  }, {
345
- target: '#cascade-target',
378
+ key: 'cascade-target',
346
379
  effectId: 'default-effect',
347
380
  conditions: ['mobile'],
348
381
  namedEffect: {
@@ -366,23 +399,25 @@ describe('interact', () => {
366
399
  }
367
400
  afterEach(() => {
368
401
  jest.clearAllMocks();
369
- remove('#logo-entrance');
370
- remove('#logo-loop');
371
- remove('#logo-animation-end');
372
- remove('#logo-mouse');
373
- remove('#logo-click');
374
- remove('#logo-hover');
375
- remove('#logo-scroll');
402
+ remove('logo-entrance');
403
+ remove('logo-loop');
404
+ remove('logo-animation-end');
405
+ remove('logo-mouse');
406
+ remove('logo-click');
407
+ remove('logo-hover');
408
+ remove('logo-scroll');
376
409
  // Clean up cascading test elements
377
- remove('#cascade-source');
378
- remove('#cascade-target');
379
- remove('#cascade-target-1');
380
- remove('#cascade-target-2');
381
- remove('#multi-source-1');
382
- remove('#multi-source-2');
410
+ remove('cascade-source');
411
+ remove('cascade-target');
412
+ remove('cascade-target-1');
413
+ remove('cascade-target-2');
414
+ remove('multi-source-1');
415
+ remove('multi-source-2');
383
416
  // Clear Interact instances to ensure test isolation
384
417
  Interact.instances.length = 0;
385
418
  Interact.elementCache.clear();
419
+ // Reset forceReducedMotion to default
420
+ Interact.forceReducedMotion = false;
386
421
  });
387
422
  describe('init Interact', () => {
388
423
  it('should initialize with valid config', () => {
@@ -399,9 +434,9 @@ describe('interact', () => {
399
434
  Interact.create({
400
435
  interactions: [{
401
436
  trigger: 'hover',
402
- source: '#logo-hover',
437
+ key: 'logo-hover',
403
438
  effects: [{
404
- target: '#logo-hover',
439
+ key: 'logo-hover',
405
440
  effectId: 'logo-arc-in'
406
441
  }]
407
442
  }],
@@ -419,12 +454,12 @@ describe('interact', () => {
419
454
  element = document.createElement('wix-interact-element');
420
455
  const div = document.createElement('div');
421
456
  element.append(div);
422
- add(element, '#logo-hover');
457
+ add(element, 'logo-hover');
423
458
  expect(getWebAnimation).toHaveBeenCalledWith(div, expect.any(Object), undefined, {
424
459
  reducedMotion: true
425
460
  });
426
461
  Interact.forceReducedMotion = false;
427
- remove('#logo-hover');
462
+ remove('logo-hover');
428
463
  });
429
464
  });
430
465
  describe('add interaction', () => {
@@ -440,7 +475,7 @@ describe('interact', () => {
440
475
  const div = document.createElement('div');
441
476
  element.append(div);
442
477
  const addEventListenerSpy = jest.spyOn(div, 'addEventListener');
443
- add(element, '#logo-hover');
478
+ add(element, 'logo-hover');
444
479
  expect(addEventListenerSpy).toHaveBeenCalledTimes(4);
445
480
  expect(addEventListenerSpy).toHaveBeenCalledWith('mouseenter', expect.any(Function), expect.objectContaining({
446
481
  passive: true
@@ -466,7 +501,7 @@ describe('interact', () => {
466
501
  const div = document.createElement('div');
467
502
  element.append(div);
468
503
  const addEventListenerSpy = jest.spyOn(div, 'addEventListener');
469
- add(element, '#logo-click');
504
+ add(element, 'logo-click');
470
505
  expect(addEventListenerSpy).toHaveBeenCalledTimes(2);
471
506
  expect(addEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
472
507
  passive: true
@@ -481,7 +516,7 @@ describe('interact', () => {
481
516
  element = document.createElement('wix-interact-element');
482
517
  const div = document.createElement('div');
483
518
  element.append(div);
484
- add(element, '#logo-entrance');
519
+ add(element, 'logo-entrance');
485
520
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
486
521
  expect(getWebAnimation).toHaveBeenCalledWith(expect.any(HTMLElement), expect.any(Object), undefined, {
487
522
  reducedMotion: false
@@ -493,14 +528,25 @@ describe('interact', () => {
493
528
  } = require('@wix/motion');
494
529
  element = document.createElement('wix-interact-element');
495
530
  const div = document.createElement('div');
531
+ div.id = 'logo-entrance';
496
532
  element.append(div);
497
533
  const elementClick = document.createElement('wix-interact-element');
498
534
  const divClick = document.createElement('div');
499
- element.append(divClick);
500
- add(elementClick, '#logo-click');
501
- add(element, '#logo-entrance');
502
- expect(getWebAnimation).toHaveBeenCalledTimes(1);
503
- expect(getWebAnimation).toHaveBeenCalledWith(expect.any(HTMLElement), expect.any(Object), undefined, {
535
+ divClick.id = 'logo-click';
536
+ elementClick.append(divClick);
537
+ add(elementClick, 'logo-click');
538
+ add(element, 'logo-entrance');
539
+ expect(getWebAnimation).toHaveBeenCalledTimes(3);
540
+ expect(getWebAnimation.mock.calls[0][0]).toBe(divClick);
541
+ expect(getWebAnimation.mock.calls[1][0]).toBe(div);
542
+ expect(getWebAnimation.mock.calls[2][0]).toBe(divClick);
543
+ expect(getWebAnimation.mock.calls[0][3]).toMatchObject({
544
+ reducedMotion: false
545
+ });
546
+ expect(getWebAnimation.mock.calls[1][3]).toMatchObject({
547
+ reducedMotion: false
548
+ });
549
+ expect(getWebAnimation.mock.calls[2][3]).toMatchObject({
504
550
  reducedMotion: false
505
551
  });
506
552
  });
@@ -513,7 +559,7 @@ describe('interact', () => {
513
559
  element = document.createElement('wix-interact-element');
514
560
  const div = document.createElement('div');
515
561
  element.append(div);
516
- add(element, '#logo-loop');
562
+ add(element, 'logo-loop');
517
563
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
518
564
  expect(getWebAnimation).toHaveBeenCalledWith(expect.any(HTMLElement), expect.any(Object), undefined, {
519
565
  reducedMotion: false
@@ -528,7 +574,7 @@ describe('interact', () => {
528
574
  element = document.createElement('wix-interact-element');
529
575
  const div = document.createElement('div');
530
576
  element.append(div);
531
- add(element, '#logo-animation-end');
577
+ add(element, 'logo-animation-end');
532
578
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
533
579
  expect(getWebAnimation).toHaveBeenCalledWith(expect.any(HTMLElement), expect.any(Object), undefined, {
534
580
  reducedMotion: false
@@ -551,7 +597,7 @@ describe('interact', () => {
551
597
  element = document.createElement('wix-interact-element');
552
598
  const div = document.createElement('div');
553
599
  element.append(div);
554
- add(element, '#logo-mouse');
600
+ add(element, 'logo-mouse');
555
601
  expect(getScrubScene).toHaveBeenCalledTimes(1);
556
602
  expect(getScrubScene).toHaveBeenCalledWith(expect.any(HTMLElement), expect.objectContaining(effectToAnimationOptions(mockConfig.effects['logo-track-mouse'])), expect.objectContaining({
557
603
  trigger: 'pointer-move'
@@ -567,7 +613,7 @@ describe('interact', () => {
567
613
  element = document.createElement('wix-interact-element');
568
614
  const div = document.createElement('div');
569
615
  element.append(div);
570
- add(element, '#logo-scroll');
616
+ add(element, 'logo-scroll');
571
617
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
572
618
  expect(getWebAnimation).toHaveBeenCalledWith(expect.any(HTMLElement), expect.objectContaining(effectToAnimationOptions(mockConfig.effects['logo-fade-scroll'])), expect.objectContaining({
573
619
  trigger: 'view-progress'
@@ -590,7 +636,7 @@ describe('interact', () => {
590
636
  element = document.createElement('wix-interact-element');
591
637
  const div = document.createElement('div');
592
638
  element.append(div);
593
- add(element, '#logo-scroll');
639
+ add(element, 'logo-scroll');
594
640
  expect(getScrubScene).toHaveBeenCalledTimes(1);
595
641
  expect(getScrubScene).toHaveBeenCalledWith(expect.any(HTMLElement), expect.objectContaining(effectToAnimationOptions(mockConfig.effects['logo-fade-scroll'])), expect.objectContaining({
596
642
  trigger: 'view-progress'
@@ -600,6 +646,116 @@ describe('interact', () => {
600
646
  }, 0);
601
647
  });
602
648
  });
649
+ describe('listContainer', () => {
650
+ it('should add a handler per list item for click trigger with listContainer', () => {
651
+ element = document.createElement('wix-interact-element');
652
+ const div = document.createElement('div');
653
+ const ul = document.createElement('ul');
654
+ ul.id = 'logo-list';
655
+ div.append(ul);
656
+ const li = document.createElement('li');
657
+ const li2 = li.cloneNode(true);
658
+ ul.append(li);
659
+ ul.append(li2);
660
+ element.append(div);
661
+ const addEventListenerSpy = jest.spyOn(li, 'addEventListener');
662
+ const addEventListenerSpy2 = jest.spyOn(li2, 'addEventListener');
663
+ add(element, 'logo-click-container');
664
+ expect(addEventListenerSpy).toHaveBeenCalledTimes(1);
665
+ expect(addEventListenerSpy2).toHaveBeenCalledTimes(1);
666
+ expect(addEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
667
+ passive: true
668
+ }));
669
+ expect(addEventListenerSpy2).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
670
+ passive: true
671
+ }));
672
+ });
673
+ it('should add a handler per list item for viewEnter trigger with listContainer in effect', () => {
674
+ const {
675
+ getWebAnimation
676
+ } = require('@wix/motion');
677
+ element = document.createElement('wix-interact-element');
678
+ const div = document.createElement('div');
679
+ const ul = document.createElement('ul');
680
+ ul.id = 'logo-list';
681
+ div.append(ul);
682
+ const li = document.createElement('li');
683
+ const li2 = li.cloneNode(true);
684
+ ul.append(li);
685
+ ul.append(li2);
686
+ element.append(div);
687
+ add(element, 'logo-view-container');
688
+ expect(getWebAnimation).toHaveBeenCalledTimes(2);
689
+ expect(getWebAnimation.mock.calls[0][0]).toBe(li);
690
+ expect(getWebAnimation.mock.calls[1][0]).toBe(li2);
691
+ });
692
+ it('should add a handler per newly added list item for click trigger with listContainer', () => {
693
+ element = document.createElement('wix-interact-element');
694
+ const div = document.createElement('div');
695
+ const ul = document.createElement('ul');
696
+ ul.id = 'logo-list';
697
+ div.append(ul);
698
+ const li = document.createElement('li');
699
+ const li2 = li.cloneNode(true);
700
+ ul.append(li);
701
+ ul.append(li2);
702
+ element.append(div);
703
+ const addEventListenerSpy = jest.spyOn(li, 'addEventListener');
704
+ const addEventListenerSpy2 = jest.spyOn(li2, 'addEventListener');
705
+ add(element, 'logo-click-container');
706
+ expect(addEventListenerSpy).toHaveBeenCalledTimes(1);
707
+ expect(addEventListenerSpy2).toHaveBeenCalledTimes(1);
708
+ expect(addEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
709
+ passive: true
710
+ }));
711
+ expect(addEventListenerSpy2).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
712
+ passive: true
713
+ }));
714
+ const li3 = document.createElement('li');
715
+ ul.append(li3);
716
+ const addEventListenerSpy3 = jest.spyOn(li3, 'addEventListener');
717
+ addListItems(element, 'logo-click-container', '#logo-list', [li3]);
718
+ expect(addEventListenerSpy3).toHaveBeenCalledTimes(1);
719
+ expect(addEventListenerSpy3).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
720
+ passive: true
721
+ }));
722
+ });
723
+ it('should add a handler per newly added list item for viewProgress trigger but not add same interaction twice', () => {
724
+ const {
725
+ getWebAnimation
726
+ } = require('@wix/motion');
727
+ element = document.createElement('wix-interact-element');
728
+ const div = document.createElement('div');
729
+ const targetElement = document.createElement('wix-interact-element');
730
+ const divTarget = document.createElement('div');
731
+ const ul = document.createElement('ul');
732
+ ul.id = 'logo-scroll-list';
733
+ divTarget.append(ul);
734
+ const li = document.createElement('li');
735
+ const li2 = li.cloneNode(true);
736
+ ul.append(li);
737
+ ul.append(li2);
738
+ element.append(div);
739
+ targetElement.append(divTarget);
740
+ add(element, 'logo-scroll-container');
741
+ expect(getWebAnimation).toHaveBeenCalledTimes(0);
742
+ add(targetElement, 'logo-scroll-items');
743
+ expect(getWebAnimation).toHaveBeenCalledTimes(2);
744
+ expect(getWebAnimation).toHaveBeenCalledWith(li, expect.objectContaining(effectToAnimationOptions(mockConfig.effects['logo-fade-scroll'])), expect.objectContaining({
745
+ trigger: 'view-progress'
746
+ }));
747
+ expect(getWebAnimation).toHaveBeenCalledWith(li2, expect.objectContaining(effectToAnimationOptions(mockConfig.effects['logo-fade-scroll'])), expect.objectContaining({
748
+ trigger: 'view-progress'
749
+ }));
750
+ const li3 = document.createElement('li');
751
+ ul.append(li3);
752
+ addListItems(targetElement, 'logo-scroll-items', '#logo-scroll-list', [li3]);
753
+ expect(getWebAnimation).toHaveBeenCalledTimes(3);
754
+ expect(getWebAnimation).toHaveBeenCalledWith(li3, expect.objectContaining(effectToAnimationOptions(mockConfig.effects['logo-fade-scroll'])), expect.objectContaining({
755
+ trigger: 'view-progress'
756
+ }));
757
+ });
758
+ });
603
759
  });
604
760
  describe('remove interaction', () => {
605
761
  beforeEach(() => {
@@ -610,8 +766,8 @@ describe('interact', () => {
610
766
  const div = document.createElement('div');
611
767
  element.append(div);
612
768
  const removeEventListenerSpy = jest.spyOn(div, 'removeEventListener');
613
- add(element, '#logo-click');
614
- remove('#logo-click');
769
+ add(element, 'logo-click');
770
+ remove('logo-click');
615
771
  expect(removeEventListenerSpy).toHaveBeenCalledTimes(2);
616
772
  expect(removeEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function));
617
773
  });
@@ -630,8 +786,8 @@ describe('interact', () => {
630
786
  element = document.createElement('wix-interact-element');
631
787
  const div = document.createElement('div');
632
788
  element.append(div);
633
- add(element, '#logo-mouse');
634
- remove('#logo-mouse');
789
+ add(element, 'logo-mouse');
790
+ remove('logo-mouse');
635
791
  expect(pointerInstance.destroy).toHaveBeenCalledTimes(1);
636
792
  });
637
793
  });
@@ -650,8 +806,8 @@ describe('interact', () => {
650
806
  const targetDiv = document.createElement('div');
651
807
  targetElement.append(targetDiv);
652
808
  const addEventListenerSpy = jest.spyOn(sourceDiv, 'addEventListener');
653
- add(sourceElement, '#cascade-source');
654
- add(targetElement, '#cascade-target');
809
+ add(sourceElement, 'cascade-source');
810
+ add(targetElement, 'cascade-target');
655
811
  expect(addEventListenerSpy).toHaveBeenCalledTimes(1);
656
812
  expect(addEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.objectContaining({
657
813
  passive: true
@@ -681,8 +837,8 @@ describe('interact', () => {
681
837
  const targetElement = document.createElement('wix-interact-element');
682
838
  const targetDiv = document.createElement('div');
683
839
  targetElement.append(targetDiv);
684
- add(sourceElement, '#cascade-source');
685
- add(targetElement, '#cascade-target');
840
+ add(sourceElement, 'cascade-source');
841
+ add(targetElement, 'cascade-target');
686
842
 
687
843
  // Should create animation with default effect
688
844
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
@@ -707,8 +863,8 @@ describe('interact', () => {
707
863
  const targetElement = document.createElement('wix-interact-element');
708
864
  const targetDiv = document.createElement('div');
709
865
  targetElement.append(targetDiv);
710
- add(sourceElement, '#cascade-source');
711
- add(targetElement, '#cascade-target');
866
+ add(sourceElement, 'cascade-source');
867
+ add(targetElement, 'cascade-target');
712
868
 
713
869
  // Should create animation with mobile effect
714
870
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
@@ -737,9 +893,9 @@ describe('interact', () => {
737
893
  targetElement.append(targetDiv);
738
894
 
739
895
  // Add source first
740
- add(sourceElement, '#cascade-source');
896
+ add(sourceElement, 'cascade-source');
741
897
  // Add target second
742
- add(targetElement, '#cascade-target');
898
+ add(targetElement, 'cascade-target');
743
899
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
744
900
  expect(getWebAnimation).toHaveBeenCalledWith(targetElement.firstElementChild, expect.objectContaining({
745
901
  namedEffect: expect.objectContaining({
@@ -763,9 +919,9 @@ describe('interact', () => {
763
919
  targetElement.append(targetDiv);
764
920
 
765
921
  // Add target first
766
- add(targetElement, '#cascade-target');
922
+ add(targetElement, 'cascade-target');
767
923
  // Add source second
768
- add(sourceElement, '#cascade-source');
924
+ add(sourceElement, 'cascade-source');
769
925
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
770
926
  expect(getWebAnimation).toHaveBeenCalledWith(targetElement.firstElementChild, expect.objectContaining({
771
927
  namedEffect: expect.objectContaining({
@@ -794,13 +950,13 @@ describe('interact', () => {
794
950
  },
795
951
  interactions: [{
796
952
  trigger: 'click',
797
- source: '#multi-source-1',
953
+ key: 'multi-source-1',
798
954
  effects: [{
799
- target: '#cascade-target-1',
955
+ key: 'cascade-target-1',
800
956
  effectId: 'desktop-effect',
801
957
  conditions: ['desktop']
802
958
  }, {
803
- target: '#cascade-target-2',
959
+ key: 'cascade-target-2',
804
960
  effectId: 'mobile-effect',
805
961
  conditions: ['mobile']
806
962
  }]
@@ -835,9 +991,9 @@ describe('interact', () => {
835
991
  const target2Element = document.createElement('wix-interact-element');
836
992
  const target2Div = document.createElement('div');
837
993
  target2Element.append(target2Div);
838
- add(sourceElement, '#multi-source-1');
839
- add(target1Element, '#cascade-target-1');
840
- add(target2Element, '#cascade-target-2');
994
+ add(sourceElement, 'multi-source-1');
995
+ add(target1Element, 'cascade-target-1');
996
+ add(target2Element, 'cascade-target-2');
841
997
 
842
998
  // Only desktop effect should be applied (mobile condition doesn't match)
843
999
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
@@ -875,12 +1031,12 @@ describe('interact', () => {
875
1031
  },
876
1032
  interactions: [{
877
1033
  trigger: 'click',
878
- source: '#cascade-source',
1034
+ key: 'cascade-source',
879
1035
  effects: [{
880
- target: '#cascade-target',
1036
+ key: 'cascade-target',
881
1037
  effectId: 'premium-effect'
882
1038
  }, {
883
- target: '#cascade-target',
1039
+ key: 'cascade-target',
884
1040
  effectId: 'premium-effect',
885
1041
  conditions: ['desktop', 'high-res']
886
1042
  }]
@@ -906,8 +1062,8 @@ describe('interact', () => {
906
1062
  const targetElement = document.createElement('wix-interact-element');
907
1063
  const targetDiv = document.createElement('div');
908
1064
  targetElement.append(targetDiv);
909
- add(sourceElement, '#cascade-source');
910
- add(targetElement, '#cascade-target');
1065
+ add(sourceElement, 'cascade-source');
1066
+ add(targetElement, 'cascade-target');
911
1067
 
912
1068
  // Premium effect should be applied since both conditions match
913
1069
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
@@ -934,12 +1090,12 @@ describe('interact', () => {
934
1090
  },
935
1091
  interactions: [{
936
1092
  trigger: 'click',
937
- source: '#cascade-source',
1093
+ key: 'cascade-source',
938
1094
  effects: [{
939
- target: '#cascade-target',
1095
+ key: 'cascade-target',
940
1096
  effectId: 'default-effect'
941
1097
  }, {
942
- target: '#cascade-target',
1098
+ key: 'cascade-target',
943
1099
  effectId: 'default-effect',
944
1100
  conditions: ['nonexistent-condition']
945
1101
  }]
@@ -962,8 +1118,8 @@ describe('interact', () => {
962
1118
  const targetElement = document.createElement('wix-interact-element');
963
1119
  const targetDiv = document.createElement('div');
964
1120
  targetElement.append(targetDiv);
965
- add(sourceElement, '#cascade-source');
966
- add(targetElement, '#cascade-target');
1121
+ add(sourceElement, 'cascade-source');
1122
+ add(targetElement, 'cascade-target');
967
1123
 
968
1124
  // Should fall back to default effect since condition doesn't exist
969
1125
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
@@ -983,9 +1139,9 @@ describe('interact', () => {
983
1139
  conditions: {},
984
1140
  interactions: [{
985
1141
  trigger: 'click',
986
- source: '#cascade-source',
1142
+ key: 'cascade-source',
987
1143
  effects: [{
988
- target: '#cascade-target',
1144
+ key: 'cascade-target',
989
1145
  effectId: 'always-applied-effect',
990
1146
  conditions: []
991
1147
  }]
@@ -1009,8 +1165,8 @@ describe('interact', () => {
1009
1165
  const targetElement = document.createElement('wix-interact-element');
1010
1166
  const targetDiv = document.createElement('div');
1011
1167
  targetElement.append(targetDiv);
1012
- add(sourceElement, '#cascade-source');
1013
- add(targetElement, '#cascade-target');
1168
+ add(sourceElement, 'cascade-source');
1169
+ add(targetElement, 'cascade-target');
1014
1170
 
1015
1171
  // Effect should be applied since empty conditions array should always match
1016
1172
  expect(getWebAnimation).toHaveBeenCalledTimes(1);
@@ -1024,5 +1180,501 @@ describe('interact', () => {
1024
1180
  });
1025
1181
  });
1026
1182
  });
1183
+ describe('selector functionality', () => {
1184
+ let sourceElement;
1185
+ let targetElement;
1186
+ beforeEach(() => {
1187
+ // Create source element with multiple child elements
1188
+ sourceElement = document.createElement('wix-interact-element');
1189
+ sourceElement.innerHTML = `
1190
+ <div class="first-child">First Child</div>
1191
+ <button class="trigger-button">Click Me</button>
1192
+ <div class="other-element">Other</div>
1193
+ <div class="list-container">
1194
+ <div class="list-item">Item 1</div>
1195
+ <div class="list-item">Item 2</div>
1196
+ <div class="list-item">Item 3</div>
1197
+ </div>
1198
+ `;
1199
+
1200
+ // Create target element with multiple child elements
1201
+ targetElement = document.createElement('wix-interact-element');
1202
+ targetElement.innerHTML = `
1203
+ <div class="first-child">Target First</div>
1204
+ <div class="animation-target">Animation Target</div>
1205
+ <div class="overlay">Overlay</div>
1206
+ <div class="nested">
1207
+ <span class="deep-target">Deep Target</span>
1208
+ </div>
1209
+ `;
1210
+ });
1211
+ describe('basic selector functionality', () => {
1212
+ it('should use selector instead of firstElementChild for source', () => {
1213
+ const config = {
1214
+ effects: {
1215
+ 'test-effect': {
1216
+ keyframeEffect: {
1217
+ name: 'test',
1218
+ keyframes: [{
1219
+ opacity: '0'
1220
+ }, {
1221
+ opacity: '1'
1222
+ }]
1223
+ },
1224
+ duration: 300
1225
+ }
1226
+ },
1227
+ interactions: [{
1228
+ key: 'selector-source',
1229
+ selector: '.trigger-button',
1230
+ trigger: 'click',
1231
+ effects: [{
1232
+ key: 'selector-target',
1233
+ effectId: 'test-effect'
1234
+ }]
1235
+ }]
1236
+ };
1237
+ Interact.create(config);
1238
+ const triggerButton = sourceElement.querySelector('.trigger-button');
1239
+ const firstChild = sourceElement.querySelector('.first-child');
1240
+ const triggerSpy = jest.spyOn(triggerButton, 'addEventListener');
1241
+ const firstChildSpy = jest.spyOn(firstChild, 'addEventListener');
1242
+ add(sourceElement, 'selector-source');
1243
+ add(targetElement, 'selector-target');
1244
+
1245
+ // Should add event listener to the selected element, not firstElementChild
1246
+ expect(triggerSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.any(Object));
1247
+ expect(firstChildSpy).not.toHaveBeenCalled();
1248
+ });
1249
+ it('should use selector instead of firstElementChild for target', () => {
1250
+ const {
1251
+ getWebAnimation
1252
+ } = require('@wix/motion');
1253
+ const config = {
1254
+ effects: {
1255
+ 'test-effect': {
1256
+ keyframeEffect: {
1257
+ name: 'test',
1258
+ keyframes: [{
1259
+ opacity: '0'
1260
+ }, {
1261
+ opacity: '1'
1262
+ }]
1263
+ },
1264
+ duration: 300
1265
+ }
1266
+ },
1267
+ interactions: [{
1268
+ key: 'selector-source',
1269
+ trigger: 'click',
1270
+ effects: [{
1271
+ key: 'selector-target',
1272
+ selector: '.animation-target',
1273
+ effectId: 'test-effect'
1274
+ }]
1275
+ }]
1276
+ };
1277
+ Interact.create(config);
1278
+ add(sourceElement, 'selector-source');
1279
+ add(targetElement, 'selector-target');
1280
+ const animationTarget = targetElement.querySelector('.animation-target');
1281
+
1282
+ // Should create animation on the selected element, not firstElementChild
1283
+ expect(getWebAnimation).toHaveBeenCalledWith(animationTarget, expect.any(Object), undefined, {
1284
+ reducedMotion: false
1285
+ });
1286
+ });
1287
+ it('should fall back to firstElementChild when no selector is provided', () => {
1288
+ const config = {
1289
+ effects: {
1290
+ 'test-effect': {
1291
+ keyframeEffect: {
1292
+ name: 'test',
1293
+ keyframes: [{
1294
+ opacity: '0'
1295
+ }, {
1296
+ opacity: '1'
1297
+ }]
1298
+ },
1299
+ duration: 300
1300
+ }
1301
+ },
1302
+ interactions: [{
1303
+ key: 'fallback-source',
1304
+ trigger: 'click',
1305
+ effects: [{
1306
+ key: 'fallback-target',
1307
+ effectId: 'test-effect'
1308
+ }]
1309
+ }]
1310
+ };
1311
+ Interact.create(config);
1312
+ const firstChild = sourceElement.querySelector('.first-child');
1313
+ const firstChildSpy = jest.spyOn(firstChild, 'addEventListener');
1314
+ add(sourceElement, 'fallback-source');
1315
+ add(targetElement, 'fallback-target');
1316
+
1317
+ // Should fall back to firstElementChild
1318
+ expect(firstChildSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.any(Object));
1319
+ });
1320
+ });
1321
+ describe('selector with listContainer', () => {
1322
+ it('should use selector within listContainer items', () => {
1323
+ const config = {
1324
+ effects: {
1325
+ 'list-effect': {
1326
+ keyframeEffect: {
1327
+ name: 'list-test',
1328
+ keyframes: [{
1329
+ transform: 'scale(1)'
1330
+ }, {
1331
+ transform: 'scale(1.1)'
1332
+ }]
1333
+ },
1334
+ duration: 200
1335
+ }
1336
+ },
1337
+ interactions: [{
1338
+ key: 'list-source',
1339
+ listContainer: '.list-container',
1340
+ selector: '.list-item',
1341
+ trigger: 'hover',
1342
+ effects: [{
1343
+ listContainer: '.list-container',
1344
+ selector: '.list-item',
1345
+ effectId: 'list-effect'
1346
+ }]
1347
+ }]
1348
+ };
1349
+ Interact.create(config);
1350
+
1351
+ // Set up spies before adding interactions
1352
+ const listItems = Array.from(sourceElement.querySelectorAll('.list-item'));
1353
+ const spies = listItems.map(item => jest.spyOn(item, 'addEventListener'));
1354
+ add(sourceElement, 'list-source');
1355
+
1356
+ // Should add event listeners to each list item
1357
+ spies.forEach(spy => {
1358
+ expect(spy).toHaveBeenCalledWith('mouseenter', expect.any(Function), expect.any(Object));
1359
+ });
1360
+ });
1361
+ it('should handle listContainer without selector (all children)', () => {
1362
+ var _sourceElement$queryS;
1363
+ const config = {
1364
+ effects: {
1365
+ 'container-effect': {
1366
+ keyframeEffect: {
1367
+ name: 'container-test',
1368
+ keyframes: [{
1369
+ opacity: '0.5'
1370
+ }, {
1371
+ opacity: '1'
1372
+ }]
1373
+ },
1374
+ duration: 150
1375
+ }
1376
+ },
1377
+ interactions: [{
1378
+ key: 'container-source',
1379
+ listContainer: '.list-container',
1380
+ trigger: 'click',
1381
+ effects: [{
1382
+ listContainer: '.list-container',
1383
+ effectId: 'container-effect'
1384
+ }]
1385
+ }]
1386
+ };
1387
+ Interact.create(config);
1388
+
1389
+ // Set up spies before adding interactions
1390
+ const containerChildren = Array.from(((_sourceElement$queryS = sourceElement.querySelector('.list-container')) == null ? void 0 : _sourceElement$queryS.children) || []);
1391
+ const spies = containerChildren.map(child => jest.spyOn(child, 'addEventListener'));
1392
+ add(sourceElement, 'container-source');
1393
+
1394
+ // Should add event listeners to all children of the container
1395
+ spies.forEach(spy => {
1396
+ expect(spy).toHaveBeenCalledWith('click', expect.any(Function), expect.any(Object));
1397
+ });
1398
+ });
1399
+ });
1400
+ describe('selector error handling', () => {
1401
+ let consoleSpy;
1402
+ beforeEach(() => {
1403
+ consoleSpy = jest.spyOn(console, 'warn').mockImplementation();
1404
+ });
1405
+ afterEach(() => {
1406
+ consoleSpy.mockRestore();
1407
+ });
1408
+ it('should warn when selector does not match any elements', () => {
1409
+ const config = {
1410
+ effects: {
1411
+ 'test-effect': {
1412
+ keyframeEffect: {
1413
+ name: 'test',
1414
+ keyframes: [{
1415
+ opacity: '0'
1416
+ }, {
1417
+ opacity: '1'
1418
+ }]
1419
+ },
1420
+ duration: 300
1421
+ }
1422
+ },
1423
+ interactions: [{
1424
+ key: 'invalid-source',
1425
+ selector: '.non-existent-element',
1426
+ trigger: 'click',
1427
+ effects: [{
1428
+ key: 'invalid-target',
1429
+ effectId: 'test-effect'
1430
+ }]
1431
+ }]
1432
+ };
1433
+ Interact.create(config);
1434
+ add(sourceElement, 'invalid-source');
1435
+ add(targetElement, 'invalid-target');
1436
+ expect(consoleSpy).toHaveBeenCalledWith('WixInteract: No element found for selector ".non-existent-element"');
1437
+ });
1438
+ it('should warn when listContainer selector does not match', () => {
1439
+ const config = {
1440
+ effects: {
1441
+ 'test-effect': {
1442
+ keyframeEffect: {
1443
+ name: 'test',
1444
+ keyframes: [{
1445
+ opacity: '0'
1446
+ }, {
1447
+ opacity: '1'
1448
+ }]
1449
+ },
1450
+ duration: 300
1451
+ }
1452
+ },
1453
+ interactions: [{
1454
+ key: 'invalid-container-source',
1455
+ listContainer: '.non-existent-container',
1456
+ trigger: 'click',
1457
+ effects: [{
1458
+ key: 'invalid-container-target',
1459
+ effectId: 'test-effect'
1460
+ }]
1461
+ }]
1462
+ };
1463
+ Interact.create(config);
1464
+ add(sourceElement, 'invalid-container-source');
1465
+ add(targetElement, 'invalid-container-target');
1466
+ expect(consoleSpy).toHaveBeenCalledWith('WixInteract: No container found for list container ".non-existent-container"');
1467
+ });
1468
+ it('should gracefully handle invalid selectors without breaking interactions', () => {
1469
+ const config = {
1470
+ effects: {
1471
+ 'valid-effect': {
1472
+ keyframeEffect: {
1473
+ name: 'valid',
1474
+ keyframes: [{
1475
+ opacity: '0'
1476
+ }, {
1477
+ opacity: '1'
1478
+ }]
1479
+ },
1480
+ duration: 300
1481
+ }
1482
+ },
1483
+ interactions: [{
1484
+ key: 'mixed-source',
1485
+ selector: '.non-existent',
1486
+ trigger: 'click',
1487
+ effects: [{
1488
+ key: 'mixed-target',
1489
+ effectId: 'valid-effect'
1490
+ }]
1491
+ }, {
1492
+ key: 'valid-source',
1493
+ selector: '.trigger-button',
1494
+ trigger: 'click',
1495
+ effects: [{
1496
+ key: 'valid-target',
1497
+ effectId: 'valid-effect'
1498
+ }]
1499
+ }]
1500
+ };
1501
+ Interact.create(config);
1502
+
1503
+ // Set up spy before adding interactions
1504
+ const triggerButton = sourceElement.querySelector('.trigger-button');
1505
+ const spy = jest.spyOn(triggerButton, 'addEventListener');
1506
+
1507
+ // This should not throw and should allow other interactions to work
1508
+ expect(() => {
1509
+ add(sourceElement, 'mixed-source');
1510
+ add(sourceElement, 'valid-source');
1511
+ add(targetElement, 'mixed-target');
1512
+ add(targetElement, 'valid-target');
1513
+ }).not.toThrow();
1514
+
1515
+ // Valid interaction should still work
1516
+ expect(spy).toHaveBeenCalled();
1517
+ });
1518
+ });
1519
+ describe('complex selector scenarios', () => {
1520
+ it('should handle nested selectors', () => {
1521
+ const {
1522
+ getWebAnimation
1523
+ } = require('@wix/motion');
1524
+ const config = {
1525
+ effects: {
1526
+ 'nested-effect': {
1527
+ keyframeEffect: {
1528
+ name: 'nested',
1529
+ keyframes: [{
1530
+ color: 'black'
1531
+ }, {
1532
+ color: 'blue'
1533
+ }]
1534
+ },
1535
+ duration: 200
1536
+ }
1537
+ },
1538
+ interactions: [{
1539
+ key: 'nested-source',
1540
+ selector: '.other-element',
1541
+ trigger: 'click',
1542
+ effects: [{
1543
+ key: 'nested-target',
1544
+ selector: '.nested .deep-target',
1545
+ effectId: 'nested-effect'
1546
+ }]
1547
+ }]
1548
+ };
1549
+ Interact.create(config);
1550
+ const addEventListenerSpy = jest.spyOn(sourceElement.querySelector('.other-element'), 'addEventListener');
1551
+ add(sourceElement, 'nested-source');
1552
+ add(targetElement, 'nested-target');
1553
+ const deepTarget = targetElement.querySelector('.nested .deep-target');
1554
+ expect(addEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function), expect.any(Object));
1555
+ expect(getWebAnimation).toHaveBeenCalledWith(deepTarget, expect.any(Object), undefined, {
1556
+ reducedMotion: false
1557
+ });
1558
+ });
1559
+ it('should handle attribute selectors', () => {
1560
+ // Add data attributes to test elements
1561
+ const buttonWithData = sourceElement.querySelector('.trigger-button');
1562
+ buttonWithData.setAttribute('data-interactive', 'true');
1563
+ buttonWithData.setAttribute('data-category', 'primary');
1564
+ const config = {
1565
+ effects: {
1566
+ 'attr-effect': {
1567
+ keyframeEffect: {
1568
+ name: 'attr',
1569
+ keyframes: [{
1570
+ backgroundColor: 'white'
1571
+ }, {
1572
+ backgroundColor: 'lightblue'
1573
+ }]
1574
+ },
1575
+ duration: 300
1576
+ }
1577
+ },
1578
+ interactions: [{
1579
+ key: 'attr-source',
1580
+ selector: '[data-interactive="true"][data-category="primary"]',
1581
+ trigger: 'click',
1582
+ effects: [{
1583
+ key: 'attr-target',
1584
+ selector: '[class*="animation"]',
1585
+ effectId: 'attr-effect'
1586
+ }]
1587
+ }]
1588
+ };
1589
+ Interact.create(config);
1590
+
1591
+ // Set up spy before adding interactions
1592
+ const spy = jest.spyOn(buttonWithData, 'addEventListener');
1593
+ add(sourceElement, 'attr-source');
1594
+ add(targetElement, 'attr-target');
1595
+ expect(spy).toHaveBeenCalledWith('click', expect.any(Function), expect.any(Object));
1596
+ });
1597
+ });
1598
+ describe('selector inheritance and priority', () => {
1599
+ it('should not inherit selector from interaction to effect', () => {
1600
+ const {
1601
+ getWebAnimation
1602
+ } = require('@wix/motion');
1603
+ const config = {
1604
+ effects: {
1605
+ 'inherit-effect': {
1606
+ keyframeEffect: {
1607
+ name: 'inherit',
1608
+ keyframes: [{
1609
+ opacity: '0'
1610
+ }, {
1611
+ opacity: '1'
1612
+ }]
1613
+ },
1614
+ duration: 300
1615
+ }
1616
+ },
1617
+ interactions: [{
1618
+ key: 'inherit-source',
1619
+ selector: '.trigger-button',
1620
+ // Interaction has selector
1621
+ trigger: 'click',
1622
+ effects: [{
1623
+ key: 'inherit-target',
1624
+ // Effect has no selector - should use firstElementChild, not inherit
1625
+ effectId: 'inherit-effect'
1626
+ }]
1627
+ }]
1628
+ };
1629
+ Interact.create(config);
1630
+ add(sourceElement, 'inherit-source');
1631
+ add(targetElement, 'inherit-target');
1632
+
1633
+ // Effect should target firstElementChild, not the interaction's selector
1634
+ const targetFirstChild = targetElement.firstElementChild;
1635
+ expect(getWebAnimation).toHaveBeenCalledWith(targetFirstChild, expect.any(Object), undefined, {
1636
+ reducedMotion: false
1637
+ });
1638
+ });
1639
+ });
1640
+ describe('selector cleanup', () => {
1641
+ it('should clean up selector-based interactions on remove', () => {
1642
+ const config = {
1643
+ effects: {
1644
+ 'cleanup-effect': {
1645
+ keyframeEffect: {
1646
+ name: 'cleanup',
1647
+ keyframes: [{
1648
+ opacity: '0'
1649
+ }, {
1650
+ opacity: '1'
1651
+ }]
1652
+ },
1653
+ duration: 300
1654
+ }
1655
+ },
1656
+ interactions: [{
1657
+ key: 'cleanup-source',
1658
+ selector: '.trigger-button',
1659
+ trigger: 'click',
1660
+ effects: [{
1661
+ key: 'cleanup-target',
1662
+ selector: '.animation-target',
1663
+ effectId: 'cleanup-effect'
1664
+ }]
1665
+ }]
1666
+ };
1667
+ Interact.create(config);
1668
+ const triggerButton = sourceElement.querySelector('.trigger-button');
1669
+ const removeEventListenerSpy = jest.spyOn(triggerButton, 'removeEventListener');
1670
+ add(sourceElement, 'cleanup-source');
1671
+ add(targetElement, 'cleanup-target');
1672
+ remove('cleanup-source');
1673
+
1674
+ // Should remove event listeners from the selected element
1675
+ expect(removeEventListenerSpy).toHaveBeenCalledWith('click', expect.any(Function));
1676
+ });
1677
+ });
1678
+ });
1027
1679
  });
1028
1680
  //# sourceMappingURL=interact.spec.js.map