wally-ui 1.10.0 → 1.11.1

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,233 +1,285 @@
1
1
  import { Component, signal, ViewChild, ElementRef, AfterViewInit, Renderer2, OnDestroy, HostListener, WritableSignal, input, InputSignal } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
+ import { it } from 'node:test';
3
4
 
4
5
  @Component({
5
6
  selector: 'wally-carousel',
6
7
  imports: [CommonModule],
7
8
  templateUrl: './carousel.html',
8
9
  })
9
- export class Carousel implements AfterViewInit, OnDestroy {
10
+ export class Carousel implements AfterViewInit {
10
11
  @ViewChild('carouselContainer', { static: false }) carouselContainer!: ElementRef;
11
12
 
12
- isNavigationIndicator: InputSignal<boolean> = input<boolean>(false);
13
- totalItemsCount: WritableSignal<number> = signal<number>(0);
14
- currentVisibleItemIndex: WritableSignal<number> = signal<number>(0);
15
13
  carouselItemElements: HTMLElement[] = [];
16
14
 
17
- private gestureState = {
18
- startPositionX: 0,
19
- startPositionY: 0,
20
- currentPositionX: 0,
21
- currentPositionY: 0,
22
- isCurrentlyDragging: false,
23
- gestureStartTime: 0
24
- };
25
-
26
- private readonly MINIMUM_SWIPE_DISTANCE = 50;
27
- private readonly MINIMUM_SWIPE_VELOCITY = 0.3;
28
- private readonly MAXIMUM_SWIPE_DURATION = 300;
29
-
30
- private eventListenerCleanupFunctions: (() => void)[] = [];
31
-
32
- get navigationIndicatorsArray() {
33
- return Array(this.totalItemsCount()).fill(0);
34
- }
35
-
36
15
  constructor(
37
16
  private renderer: Renderer2
38
17
  ) { }
39
18
 
40
19
  ngAfterViewInit(): void {
41
- if (this.carouselContainer) {
42
- this.initializeCarouselItems();
43
- this.setupTouchAndMouseEvents();
44
- this.setupAccessibilityAttributes();
45
- }
46
- }
20
+ console.log('carouselContainer', this.carouselContainer.nativeElement.children);
47
21
 
48
- ngOnDestroy(): void {
49
- this.eventListenerCleanupFunctions.forEach(cleanupFunction => cleanupFunction());
50
- }
51
-
52
- calculateNextItemIndex(currentItemIndex: number): number {
53
- return (currentItemIndex + 1) % this.totalItemsCount();
54
- }
55
-
56
- calculatePreviousItemIndex(currentItemIndex: number): number {
57
- return (currentItemIndex - 1 + this.totalItemsCount()) % this.totalItemsCount();
58
- }
59
-
60
- navigateToNextItem(): void {
61
- this.currentVisibleItemIndex.set(this.calculateNextItemIndex(this.currentVisibleItemIndex()));
62
- this.updateAllItemElementPositions();
63
- }
64
-
65
- navigateToPreviousItem(): void {
66
- this.currentVisibleItemIndex.set(this.calculatePreviousItemIndex(this.currentVisibleItemIndex()));
67
- this.updateAllItemElementPositions();
68
- }
69
-
70
- navigateToSpecificItem(targetItemIndex: number): void {
71
- this.currentVisibleItemIndex.set(targetItemIndex);
72
- this.updateAllItemElementPositions();
73
- }
22
+ this.carouselItemElements = Array.from(this.carouselContainer.nativeElement.children);
23
+ console.log('carouselItemElements', this.carouselItemElements);
74
24
 
75
- updateItemElementPosition(carouselItemElement: HTMLElement, itemIndex: number): void {
76
- const currentVisibleIndex = this.currentVisibleItemIndex();
77
25
 
78
- if (itemIndex === currentVisibleIndex) {
79
- this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(0)');
80
- } else if (itemIndex > currentVisibleIndex) {
81
- this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(110%)');
82
- } else {
83
- this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(-110%)');
84
- }
85
- }
86
-
87
- updateAllItemElementPositions(): void {
88
26
  this.carouselItemElements.forEach((itemElement, itemIndex) => {
89
- this.updateItemElementPosition(itemElement, itemIndex);
27
+ // this.renderer.setStyle(itemElement, 'position', 'absolute');
28
+ // this.renderer.setStyle(itemElement, 'display', 'flex');
29
+ // this.renderer.setStyle(itemElement, 'align-items', 'center');
30
+ // this.renderer.setStyle(itemElement, 'justify-content', 'center');
31
+ // this.renderer.setStyle(itemElement, 'inset', '0');
32
+ // this.renderer.setStyle(itemElement, 'padding', '8px');
33
+ // this.renderer.setStyle(itemElement, 'border-radius', '8px');
34
+ // this.renderer.setStyle(itemElement, 'transition', 'transform 700ms ease-out');
35
+
36
+ // this.renderer.addClass(item, 'flex flex-col items-center gap-4 p-2 rounded-sm transition-all duration-700 ease-in-out');
90
37
  });
91
- }
92
-
93
- @HostListener('keydown', ['$event'])
94
- handleKeyboardNavigation(keyboardEvent: KeyboardEvent): void {
95
- switch (keyboardEvent.key) {
96
- case 'ArrowLeft':
97
- keyboardEvent.preventDefault();
98
- this.navigateToPreviousItem();
99
- break;
100
- case 'ArrowRight':
101
- keyboardEvent.preventDefault();
102
- this.navigateToNextItem();
103
- break;
104
- case 'Home':
105
- keyboardEvent.preventDefault();
106
- this.navigateToSpecificItem(0);
107
- break;
108
- case 'End':
109
- keyboardEvent.preventDefault();
110
- this.navigateToSpecificItem(this.totalItemsCount() - 1);
111
- break;
112
- }
113
- }
114
-
115
- private initializeCarouselItems(): void {
116
- this.carouselItemElements = Array.from(this.carouselContainer.nativeElement.children);
117
- this.totalItemsCount.set(this.carouselItemElements.length);
118
38
 
119
39
  this.carouselItemElements.forEach((itemElement, itemIndex) => {
120
- this.renderer.setStyle(itemElement, 'position', 'absolute');
121
- this.renderer.setStyle(itemElement, 'inset', '0');
122
- this.renderer.setStyle(itemElement, 'transition', 'transform 700ms ease-out');
123
- this.renderer.setStyle(itemElement, 'display', 'flex');
124
- this.renderer.setStyle(itemElement, 'align-items', 'center');
125
- this.renderer.setStyle(itemElement, 'justify-content', 'center');
126
40
  this.updateItemElementPosition(itemElement, itemIndex);
127
41
  });
128
42
  }
129
43
 
130
- private setupTouchAndMouseEvents(): void {
131
- const carouselContainerElement = this.carouselContainer.nativeElement;
132
-
133
- const touchStartListener = this.renderer.listen(carouselContainerElement, 'touchstart', (event) => this.handleTouchStart(event));
134
- const touchMoveListener = this.renderer.listen(carouselContainerElement, 'touchmove', (event) => this.handleTouchMove(event));
135
- const touchEndListener = this.renderer.listen(carouselContainerElement, 'touchend', () => this.handleTouchEnd());
136
-
137
- const mouseDownListener = this.renderer.listen(carouselContainerElement, 'mousedown', (event) => this.handleMouseDown(event));
138
- const mouseMoveListener = this.renderer.listen(carouselContainerElement, 'mousemove', (event) => this.handleMouseMove(event));
139
- const mouseUpListener = this.renderer.listen(carouselContainerElement, 'mouseup', () => this.handleMouseUp());
140
- const mouseLeaveListener = this.renderer.listen(carouselContainerElement, 'mouseleave', () => this.handleMouseUp());
141
-
142
- this.eventListenerCleanupFunctions.push(
143
- touchStartListener,
144
- touchMoveListener,
145
- touchEndListener,
146
- mouseDownListener,
147
- mouseMoveListener,
148
- mouseUpListener,
149
- mouseLeaveListener
150
- );
151
-
152
- this.renderer.setStyle(carouselContainerElement, 'touch-action', 'pan-x');
153
- }
154
-
155
- private setupAccessibilityAttributes(): void {
156
- const carouselContainerElement = this.carouselContainer.nativeElement;
157
-
158
- this.renderer.setAttribute(carouselContainerElement, 'role', 'region');
159
- this.renderer.setAttribute(carouselContainerElement, 'aria-label', 'Carousel');
160
- this.renderer.setAttribute(carouselContainerElement, 'tabindex', '0');
161
- }
162
-
163
- private handleTouchStart(touchEvent: TouchEvent): void {
164
- this.initializeGesture(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);
165
- }
44
+ updateItemElementPosition(carouselItemElement: HTMLElement, itemIndex: number): void {
45
+ // const currentVisibleIndex = this.currentVisibleItemIndex();
166
46
 
167
- private handleTouchMove(touchEvent: TouchEvent): void {
168
- if (this.gestureState.isCurrentlyDragging) {
169
- touchEvent.preventDefault();
170
- this.updateGesturePosition(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);
47
+ // if (itemIndex === currentVisibleIndex) {
48
+ if (itemIndex === 2) {
49
+ console.log('itemIndex', itemIndex);
50
+ this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(10%)');
171
51
  }
172
- }
173
-
174
- private handleTouchEnd(): void {
175
- this.finalizeGestureAndNavigate();
176
- }
177
-
178
- private handleMouseDown(mouseEvent: MouseEvent): void {
179
- this.initializeGesture(mouseEvent.clientX, mouseEvent.clientY);
180
- }
181
-
182
- private handleMouseMove(mouseEvent: MouseEvent): void {
183
- if (this.gestureState.isCurrentlyDragging) {
184
- mouseEvent.preventDefault();
185
- this.updateGesturePosition(mouseEvent.clientX, mouseEvent.clientY);
52
+ if (itemIndex !== 2) {
53
+ this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(0)');
186
54
  }
55
+ // } else if (itemIndex > currentVisibleIndex) {
56
+ // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(110%)');
57
+ // } else {
58
+ // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(-110%)');
59
+ // }
187
60
  }
188
61
 
189
- private handleMouseUp(): void {
190
- this.finalizeGestureAndNavigate();
191
- }
192
-
193
- private initializeGesture(xPosition: number, yPosition: number): void {
194
- this.gestureState = {
195
- startPositionX: xPosition,
196
- startPositionY: yPosition,
197
- currentPositionX: xPosition,
198
- currentPositionY: yPosition,
199
- isCurrentlyDragging: true,
200
- gestureStartTime: Date.now()
201
- };
202
- }
203
-
204
- private updateGesturePosition(xPosition: number, yPosition: number): void {
205
- if (!this.gestureState.isCurrentlyDragging) return;
206
-
207
- this.gestureState.currentPositionX = xPosition;
208
- this.gestureState.currentPositionY = yPosition;
209
- }
210
-
211
- private finalizeGestureAndNavigate(): void {
212
- if (!this.gestureState.isCurrentlyDragging) return;
213
-
214
- const horizontalDistanceMoved = this.gestureState.currentPositionX - this.gestureState.startPositionX;
215
- const verticalDistanceMoved = this.gestureState.currentPositionY - this.gestureState.startPositionY;
216
- const gestureDuration = Date.now() - this.gestureState.gestureStartTime;
217
- const gestureVelocity = Math.abs(horizontalDistanceMoved) / gestureDuration;
218
-
219
- if (Math.abs(horizontalDistanceMoved) > Math.abs(verticalDistanceMoved)) {
220
- const isValidSwipeGesture = Math.abs(horizontalDistanceMoved) > this.MINIMUM_SWIPE_DISTANCE ||
221
- (gestureVelocity > this.MINIMUM_SWIPE_VELOCITY && gestureDuration < this.MAXIMUM_SWIPE_DURATION);
222
-
223
- if (isValidSwipeGesture) {
224
- if (horizontalDistanceMoved > 0) {
225
- this.navigateToPreviousItem();
226
- } else {
227
- this.navigateToNextItem();
228
- }
229
- }
230
- }
231
- this.gestureState.isCurrentlyDragging = false;
232
- }
62
+ // @ViewChild('carouselContainer', { static: false }) carouselContainer!: ElementRef;
63
+
64
+ // isNavigationIndicator: InputSignal<boolean> = input<boolean>(false);
65
+ // totalItemsCount: WritableSignal<number> = signal<number>(0);
66
+ // currentVisibleItemIndex: WritableSignal<number> = signal<number>(0);
67
+ // carouselItemElements: HTMLElement[] = [];
68
+
69
+ // private gestureState = {
70
+ // startPositionX: 0,
71
+ // startPositionY: 0,
72
+ // currentPositionX: 0,
73
+ // currentPositionY: 0,
74
+ // isCurrentlyDragging: false,
75
+ // gestureStartTime: 0
76
+ // };
77
+
78
+ // private readonly MINIMUM_SWIPE_DISTANCE = 50;
79
+ // private readonly MINIMUM_SWIPE_VELOCITY = 0.3;
80
+ // private readonly MAXIMUM_SWIPE_DURATION = 300;
81
+
82
+ // private eventListenerCleanupFunctions: (() => void)[] = [];
83
+
84
+ // get navigationIndicatorsArray() {
85
+ // return Array(this.totalItemsCount()).fill(0);
86
+ // }
87
+
88
+ // constructor(
89
+ // private renderer: Renderer2
90
+ // ) { }
91
+
92
+ // ngAfterViewInit(): void {
93
+ // if (this.carouselContainer) {
94
+ // this.initializeCarouselItems();
95
+ // this.setupTouchAndMouseEvents();
96
+ // this.setupAccessibilityAttributes();
97
+ // }
98
+ // }
99
+
100
+ // ngOnDestroy(): void {
101
+ // this.eventListenerCleanupFunctions.forEach(cleanupFunction => cleanupFunction());
102
+ // }
103
+
104
+ // calculateNextItemIndex(currentItemIndex: number): number {
105
+ // return (currentItemIndex + 1) % this.totalItemsCount();
106
+ // }
107
+
108
+ // calculatePreviousItemIndex(currentItemIndex: number): number {
109
+ // return (currentItemIndex - 1 + this.totalItemsCount()) % this.totalItemsCount();
110
+ // }
111
+
112
+ // navigateToNextItem(): void {
113
+ // this.currentVisibleItemIndex.set(this.calculateNextItemIndex(this.currentVisibleItemIndex()));
114
+ // this.updateAllItemElementPositions();
115
+ // }
116
+
117
+ // navigateToPreviousItem(): void {
118
+ // this.currentVisibleItemIndex.set(this.calculatePreviousItemIndex(this.currentVisibleItemIndex()));
119
+ // this.updateAllItemElementPositions();
120
+ // }
121
+
122
+ // navigateToSpecificItem(targetItemIndex: number): void {
123
+ // this.currentVisibleItemIndex.set(targetItemIndex);
124
+ // this.updateAllItemElementPositions();
125
+ // }
126
+
127
+ // updateItemElementPosition(carouselItemElement: HTMLElement, itemIndex: number): void {
128
+ // const currentVisibleIndex = this.currentVisibleItemIndex();
129
+
130
+ // if (itemIndex === currentVisibleIndex) {
131
+ // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(0)');
132
+ // } else if (itemIndex > currentVisibleIndex) {
133
+ // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(110%)');
134
+ // } else {
135
+ // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(-110%)');
136
+ // }
137
+ // }
138
+
139
+ // updateAllItemElementPositions(): void {
140
+ // this.carouselItemElements.forEach((itemElement, itemIndex) => {
141
+ // this.updateItemElementPosition(itemElement, itemIndex);
142
+ // });
143
+ // }
144
+
145
+ // @HostListener('keydown', ['$event'])
146
+ // handleKeyboardNavigation(keyboardEvent: KeyboardEvent): void {
147
+ // switch (keyboardEvent.key) {
148
+ // case 'ArrowLeft':
149
+ // keyboardEvent.preventDefault();
150
+ // this.navigateToPreviousItem();
151
+ // break;
152
+ // case 'ArrowRight':
153
+ // keyboardEvent.preventDefault();
154
+ // this.navigateToNextItem();
155
+ // break;
156
+ // case 'Home':
157
+ // keyboardEvent.preventDefault();
158
+ // this.navigateToSpecificItem(0);
159
+ // break;
160
+ // case 'End':
161
+ // keyboardEvent.preventDefault();
162
+ // this.navigateToSpecificItem(this.totalItemsCount() - 1);
163
+ // break;
164
+ // }
165
+ // }
166
+
167
+ // private initializeCarouselItems(): void {
168
+ // this.carouselItemElements = Array.from(this.carouselContainer.nativeElement.children);
169
+ // this.totalItemsCount.set(this.carouselItemElements.length);
170
+
171
+ // this.carouselItemElements.forEach((itemElement, itemIndex) => {
172
+ // this.renderer.setStyle(itemElement, 'position', 'absolute');
173
+ // this.renderer.setStyle(itemElement, 'inset', '0');
174
+ // this.renderer.setStyle(itemElement, 'transition', 'transform 700ms ease-out');
175
+ // this.renderer.setStyle(itemElement, 'display', 'flex');
176
+ // this.renderer.setStyle(itemElement, 'align-items', 'center');
177
+ // this.renderer.setStyle(itemElement, 'justify-content', 'center');
178
+ // this.updateItemElementPosition(itemElement, itemIndex);
179
+ // });
180
+ // }
181
+
182
+ // private setupTouchAndMouseEvents(): void {
183
+ // const carouselContainerElement = this.carouselContainer.nativeElement;
184
+
185
+ // const touchStartListener = this.renderer.listen(carouselContainerElement, 'touchstart', (event) => this.handleTouchStart(event));
186
+ // const touchMoveListener = this.renderer.listen(carouselContainerElement, 'touchmove', (event) => this.handleTouchMove(event));
187
+ // const touchEndListener = this.renderer.listen(carouselContainerElement, 'touchend', () => this.handleTouchEnd());
188
+
189
+ // const mouseDownListener = this.renderer.listen(carouselContainerElement, 'mousedown', (event) => this.handleMouseDown(event));
190
+ // const mouseMoveListener = this.renderer.listen(carouselContainerElement, 'mousemove', (event) => this.handleMouseMove(event));
191
+ // const mouseUpListener = this.renderer.listen(carouselContainerElement, 'mouseup', () => this.handleMouseUp());
192
+ // const mouseLeaveListener = this.renderer.listen(carouselContainerElement, 'mouseleave', () => this.handleMouseUp());
193
+
194
+ // this.eventListenerCleanupFunctions.push(
195
+ // touchStartListener,
196
+ // touchMoveListener,
197
+ // touchEndListener,
198
+ // mouseDownListener,
199
+ // mouseMoveListener,
200
+ // mouseUpListener,
201
+ // mouseLeaveListener
202
+ // );
203
+
204
+ // this.renderer.setStyle(carouselContainerElement, 'touch-action', 'pan-x');
205
+ // }
206
+
207
+ // private setupAccessibilityAttributes(): void {
208
+ // const carouselContainerElement = this.carouselContainer.nativeElement;
209
+
210
+ // this.renderer.setAttribute(carouselContainerElement, 'role', 'region');
211
+ // this.renderer.setAttribute(carouselContainerElement, 'aria-label', 'Carousel');
212
+ // this.renderer.setAttribute(carouselContainerElement, 'tabindex', '0');
213
+ // }
214
+
215
+ // private handleTouchStart(touchEvent: TouchEvent): void {
216
+ // this.initializeGesture(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);
217
+ // }
218
+
219
+ // private handleTouchMove(touchEvent: TouchEvent): void {
220
+ // if (this.gestureState.isCurrentlyDragging) {
221
+ // touchEvent.preventDefault();
222
+ // this.updateGesturePosition(touchEvent.touches[0].clientX, touchEvent.touches[0].clientY);
223
+ // }
224
+ // }
225
+
226
+ // private handleTouchEnd(): void {
227
+ // this.finalizeGestureAndNavigate();
228
+ // }
229
+
230
+ // private handleMouseDown(mouseEvent: MouseEvent): void {
231
+ // this.initializeGesture(mouseEvent.clientX, mouseEvent.clientY);
232
+ // }
233
+
234
+ // private handleMouseMove(mouseEvent: MouseEvent): void {
235
+ // if (this.gestureState.isCurrentlyDragging) {
236
+ // mouseEvent.preventDefault();
237
+ // this.updateGesturePosition(mouseEvent.clientX, mouseEvent.clientY);
238
+ // }
239
+ // }
240
+
241
+ // private handleMouseUp(): void {
242
+ // this.finalizeGestureAndNavigate();
243
+ // }
244
+
245
+ // private initializeGesture(xPosition: number, yPosition: number): void {
246
+ // this.gestureState = {
247
+ // startPositionX: xPosition,
248
+ // startPositionY: yPosition,
249
+ // currentPositionX: xPosition,
250
+ // currentPositionY: yPosition,
251
+ // isCurrentlyDragging: true,
252
+ // gestureStartTime: Date.now()
253
+ // };
254
+ // }
255
+
256
+ // private updateGesturePosition(xPosition: number, yPosition: number): void {
257
+ // if (!this.gestureState.isCurrentlyDragging) return;
258
+
259
+ // this.gestureState.currentPositionX = xPosition;
260
+ // this.gestureState.currentPositionY = yPosition;
261
+ // }
262
+
263
+ // private finalizeGestureAndNavigate(): void {
264
+ // if (!this.gestureState.isCurrentlyDragging) return;
265
+
266
+ // const horizontalDistanceMoved = this.gestureState.currentPositionX - this.gestureState.startPositionX;
267
+ // const verticalDistanceMoved = this.gestureState.currentPositionY - this.gestureState.startPositionY;
268
+ // const gestureDuration = Date.now() - this.gestureState.gestureStartTime;
269
+ // const gestureVelocity = Math.abs(horizontalDistanceMoved) / gestureDuration;
270
+
271
+ // if (Math.abs(horizontalDistanceMoved) > Math.abs(verticalDistanceMoved)) {
272
+ // const isValidSwipeGesture = Math.abs(horizontalDistanceMoved) > this.MINIMUM_SWIPE_DISTANCE ||
273
+ // (gestureVelocity > this.MINIMUM_SWIPE_VELOCITY && gestureDuration < this.MAXIMUM_SWIPE_DURATION);
274
+
275
+ // if (isValidSwipeGesture) {
276
+ // if (horizontalDistanceMoved > 0) {
277
+ // this.navigateToPreviousItem();
278
+ // } else {
279
+ // this.navigateToNextItem();
280
+ // }
281
+ // }
282
+ // }
283
+ // this.gestureState.isCurrentlyDragging = false;
284
+ // }
233
285
  }