wally-ui 1.11.1 → 1.12.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 (36) hide show
  1. package/dist/cli.js +7 -0
  2. package/dist/cli.js.map +1 -1
  3. package/package.json +4 -2
  4. package/playground/showcase/public/sitemap.xml +32 -0
  5. package/playground/showcase/src/app/app.routes.server.ts +8 -0
  6. package/playground/showcase/src/app/components/ai/ai-chat/ai-chat.css +0 -0
  7. package/playground/showcase/src/app/components/ai/ai-chat/ai-chat.html +5 -0
  8. package/playground/showcase/src/app/components/ai/ai-chat/ai-chat.spec.ts +23 -0
  9. package/playground/showcase/src/app/components/ai/ai-chat/ai-chat.ts +17 -0
  10. package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.css +0 -0
  11. package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.html +69 -0
  12. package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.spec.ts +23 -0
  13. package/playground/showcase/src/app/components/ai/ai-composer/ai-composer.ts +19 -0
  14. package/playground/showcase/src/app/components/ai/ai-prompt-input/ai-prompt-input.css +0 -0
  15. package/playground/showcase/src/app/components/ai/ai-prompt-input/ai-prompt-input.html +10 -0
  16. package/playground/showcase/src/app/components/ai/ai-prompt-input/ai-prompt-input.spec.ts +23 -0
  17. package/playground/showcase/src/app/components/ai/ai-prompt-input/ai-prompt-input.ts +25 -0
  18. package/playground/showcase/src/app/components/button/button.html +5 -1
  19. package/playground/showcase/src/app/components/button/button.ts +1 -0
  20. package/playground/showcase/src/app/components/carousel/carousel.html +1 -33
  21. package/playground/showcase/src/app/components/carousel/carousel.ts +199 -251
  22. package/playground/showcase/src/app/components/tooltip/tooltip.css +0 -0
  23. package/playground/showcase/src/app/components/tooltip/tooltip.html +9 -0
  24. package/playground/showcase/src/app/components/tooltip/tooltip.ts +189 -0
  25. package/playground/showcase/src/app/pages/documentation/chat-sdk/chat-sdk.html +99 -0
  26. package/playground/showcase/src/app/pages/documentation/chat-sdk/chat-sdk.ts +20 -0
  27. package/playground/showcase/src/app/pages/documentation/components/components.html +23 -0
  28. package/playground/showcase/src/app/pages/documentation/components/components.routes.ts +4 -0
  29. package/playground/showcase/src/app/pages/documentation/components/tooltip-docs/tooltip-docs.css +1 -0
  30. package/playground/showcase/src/app/pages/documentation/components/tooltip-docs/tooltip-docs.examples.ts +150 -0
  31. package/playground/showcase/src/app/pages/documentation/components/tooltip-docs/tooltip-docs.html +471 -0
  32. package/playground/showcase/src/app/pages/documentation/components/tooltip-docs/tooltip-docs.ts +69 -0
  33. package/playground/showcase/src/app/pages/documentation/documentation.routes.ts +4 -0
  34. package/playground/showcase/src/app/pages/home/home.html +26 -0
  35. package/playground/showcase/src/app/pages/home/home.ts +3 -2
  36. package/playground/showcase/src/index.html +7 -4
@@ -1,285 +1,233 @@
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';
4
3
 
5
4
  @Component({
6
5
  selector: 'wally-carousel',
7
6
  imports: [CommonModule],
8
7
  templateUrl: './carousel.html',
9
8
  })
10
- export class Carousel implements AfterViewInit {
9
+ export class Carousel implements AfterViewInit, OnDestroy {
11
10
  @ViewChild('carouselContainer', { static: false }) carouselContainer!: ElementRef;
12
11
 
12
+ isNavigationIndicator: InputSignal<boolean> = input<boolean>(false);
13
+ totalItemsCount: WritableSignal<number> = signal<number>(0);
14
+ currentVisibleItemIndex: WritableSignal<number> = signal<number>(0);
13
15
  carouselItemElements: HTMLElement[] = [];
14
16
 
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
+
15
36
  constructor(
16
37
  private renderer: Renderer2
17
38
  ) { }
18
39
 
19
40
  ngAfterViewInit(): void {
20
- console.log('carouselContainer', this.carouselContainer.nativeElement.children);
41
+ if (this.carouselContainer) {
42
+ this.initializeCarouselItems();
43
+ this.setupTouchAndMouseEvents();
44
+ this.setupAccessibilityAttributes();
45
+ }
46
+ }
21
47
 
22
- this.carouselItemElements = Array.from(this.carouselContainer.nativeElement.children);
23
- console.log('carouselItemElements', this.carouselItemElements);
48
+ ngOnDestroy(): void {
49
+ this.eventListenerCleanupFunctions.forEach(cleanupFunction => cleanupFunction());
50
+ }
51
+
52
+ calculateNextItemIndex(currentItemIndex: number): number {
53
+ return (currentItemIndex + 1) % this.totalItemsCount();
54
+ }
24
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
+ }
25
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
+ }
74
+
75
+ updateItemElementPosition(carouselItemElement: HTMLElement, itemIndex: number): void {
76
+ const currentVisibleIndex = this.currentVisibleItemIndex();
77
+
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 {
26
88
  this.carouselItemElements.forEach((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');
89
+ this.updateItemElementPosition(itemElement, itemIndex);
37
90
  });
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);
38
118
 
39
119
  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');
40
126
  this.updateItemElementPosition(itemElement, itemIndex);
41
127
  });
42
128
  }
43
129
 
44
- updateItemElementPosition(carouselItemElement: HTMLElement, itemIndex: number): void {
45
- // const currentVisibleIndex = this.currentVisibleItemIndex();
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;
46
157
 
47
- // if (itemIndex === currentVisibleIndex) {
48
- if (itemIndex === 2) {
49
- console.log('itemIndex', itemIndex);
50
- this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(10%)');
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
+ }
166
+
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);
51
171
  }
52
- if (itemIndex !== 2) {
53
- this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(0)');
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);
54
186
  }
55
- // } else if (itemIndex > currentVisibleIndex) {
56
- // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(110%)');
57
- // } else {
58
- // this.renderer.setStyle(carouselItemElement, 'transform', 'translateX(-110%)');
59
- // }
60
187
  }
61
188
 
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
- // }
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
+ }
285
233
  }
@@ -0,0 +1,9 @@
1
+ <div class="relative inline-block tooltip-wrapper " (mouseenter)="show()" (mouseleave)="hide()" (focus)="show()" (blur)="hide()">
2
+ <ng-content></ng-content>
3
+
4
+ @if (visible() && !disabled()) {
5
+ <div #tooltipElement [id]="tooltipId" [class]="tooltipClasses()" role="tooltip" [attr.aria-hidden]="!visible()">
6
+ {{ text() }}
7
+ </div>
8
+ }
9
+ </div>