wally-ui 1.17.0 → 1.18.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 (25) hide show
  1. package/package.json +1 -1
  2. package/playground/showcase/src/app/app.routes.server.ts +4 -0
  3. package/playground/showcase/src/app/components/dialog/dialog-close/dialog-close.html +1 -0
  4. package/playground/showcase/src/app/components/dialog/dialog-close/dialog-close.ts +16 -0
  5. package/playground/showcase/src/app/components/dialog/dialog-content/dialog-content.html +15 -0
  6. package/playground/showcase/src/app/components/dialog/dialog-content/dialog-content.ts +19 -0
  7. package/playground/showcase/src/app/components/dialog/dialog-description/dialog-description.html +3 -0
  8. package/playground/showcase/src/app/components/dialog/dialog-description/dialog-description.ts +8 -0
  9. package/playground/showcase/src/app/components/dialog/dialog-footer/dialog-footer.html +3 -0
  10. package/playground/showcase/src/app/components/dialog/dialog-footer/dialog-footer.ts +8 -0
  11. package/playground/showcase/src/app/components/dialog/dialog-header/dialog-header.html +3 -0
  12. package/playground/showcase/src/app/components/dialog/dialog-header/dialog-header.ts +8 -0
  13. package/playground/showcase/src/app/components/dialog/dialog-title/dialog-title.html +3 -0
  14. package/playground/showcase/src/app/components/dialog/dialog-title/dialog-title.ts +8 -0
  15. package/playground/showcase/src/app/components/dialog/dialog-trigger/dialog-trigger.html +1 -0
  16. package/playground/showcase/src/app/components/dialog/dialog-trigger/dialog-trigger.ts +16 -0
  17. package/playground/showcase/src/app/components/dialog/dialog.html +1 -0
  18. package/playground/showcase/src/app/components/dialog/dialog.service.ts +20 -0
  19. package/playground/showcase/src/app/components/dialog/dialog.ts +29 -0
  20. package/playground/showcase/src/app/components/dropdown-menu/dropdown-menu-content/dropdown-menu-content.ts +14 -6
  21. package/playground/showcase/src/app/pages/documentation/components/components.html +310 -126
  22. package/playground/showcase/src/app/pages/documentation/components/components.routes.ts +44 -40
  23. package/playground/showcase/src/app/pages/documentation/components/dialog-docs/dialog-docs.examples.ts +275 -0
  24. package/playground/showcase/src/app/pages/documentation/components/dialog-docs/dialog-docs.html +701 -0
  25. package/playground/showcase/src/app/pages/documentation/components/dialog-docs/dialog-docs.ts +84 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "wally-ui",
3
- "version": "1.17.0",
3
+ "version": "1.18.0",
4
4
  "description": "About Where’s Wally? Right here — bringing you ready-to-use Angular components with Wally-UI. Stop searching, start building.",
5
5
  "bin": {
6
6
  "wally": "dist/cli.js"
@@ -45,6 +45,10 @@ export const serverRoutes: ServerRoute[] = [
45
45
  path: 'documentation/components/combobox',
46
46
  renderMode: RenderMode.Prerender,
47
47
  },
48
+ {
49
+ path: 'documentation/components/dialog',
50
+ renderMode: RenderMode.Prerender,
51
+ },
48
52
  {
49
53
  path: 'documentation/chat-sdk',
50
54
  renderMode: RenderMode.Prerender,
@@ -0,0 +1,16 @@
1
+ import { Component, HostListener, inject } from '@angular/core';
2
+ import { DialogService } from '../dialog.service';
3
+
4
+ @Component({
5
+ selector: 'wally-dialog-close',
6
+ imports: [],
7
+ templateUrl: './dialog-close.html'
8
+ })
9
+ export class DialogClose {
10
+ dialogService = inject(DialogService);
11
+
12
+ @HostListener('click')
13
+ onClick(): void {
14
+ this.dialogService.close();
15
+ }
16
+ }
@@ -0,0 +1,15 @@
1
+ @if (dialogService.isOpen()) {
2
+ <div
3
+ class="fixed inset-0 z-50 bg-black/50 backdrop-blur-sm transition-all duration-200"
4
+ (click)="onBackdropClick($event)"
5
+ role="dialog"
6
+ aria-modal="true">
7
+ <div class="flex min-h-screen items-center justify-center p-4">
8
+ <div
9
+ class="relative w-full max-w-lg bg-white dark:bg-neutral-950 border border-neutral-300 dark:border-neutral-700 rounded-xl shadow-2xl transition-all duration-200 ease-out"
10
+ (click)="$event.stopPropagation()">
11
+ <ng-content></ng-content>
12
+ </div>
13
+ </div>
14
+ </div>
15
+ }
@@ -0,0 +1,19 @@
1
+ import { Component, ElementRef, inject } from '@angular/core';
2
+ import { DialogService } from '../dialog.service';
3
+
4
+ @Component({
5
+ selector: 'wally-dialog-content',
6
+ imports: [],
7
+ templateUrl: './dialog-content.html'
8
+ })
9
+ export class DialogContent {
10
+ dialogService = inject(DialogService);
11
+ private elementRef = inject(ElementRef);
12
+
13
+ onBackdropClick(event: MouseEvent): void {
14
+ // Close only if clicking directly on backdrop (not on dialog content)
15
+ if (event.target === event.currentTarget && this.dialogService.closeOnBackdropClick()) {
16
+ this.dialogService.close();
17
+ }
18
+ }
19
+ }
@@ -0,0 +1,3 @@
1
+ <p class="text-sm text-neutral-600 dark:text-neutral-400">
2
+ <ng-content></ng-content>
3
+ </p>
@@ -0,0 +1,8 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'wally-dialog-description',
5
+ imports: [],
6
+ templateUrl: './dialog-description.html'
7
+ })
8
+ export class DialogDescription {}
@@ -0,0 +1,3 @@
1
+ <div class="flex flex-col-reverse sm:flex-row sm:justify-end space-y-2 space-y-reverse sm:space-y-0 sm:space-x-2 px-6 pb-6 pt-4">
2
+ <ng-content></ng-content>
3
+ </div>
@@ -0,0 +1,8 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'wally-dialog-footer',
5
+ imports: [],
6
+ templateUrl: './dialog-footer.html'
7
+ })
8
+ export class DialogFooter {}
@@ -0,0 +1,3 @@
1
+ <div class="flex flex-col space-y-1.5 text-center sm:text-left px-6 pt-6">
2
+ <ng-content></ng-content>
3
+ </div>
@@ -0,0 +1,8 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'wally-dialog-header',
5
+ imports: [],
6
+ templateUrl: './dialog-header.html'
7
+ })
8
+ export class DialogHeader {}
@@ -0,0 +1,3 @@
1
+ <h1 class="text-lg font-semibold text-[#0a0a0a] dark:text-white">
2
+ <ng-content></ng-content>
3
+ </h1>
@@ -0,0 +1,8 @@
1
+ import { Component } from '@angular/core';
2
+
3
+ @Component({
4
+ selector: 'wally-dialog-title',
5
+ imports: [],
6
+ templateUrl: './dialog-title.html'
7
+ })
8
+ export class DialogTitle {}
@@ -0,0 +1,16 @@
1
+ import { Component, HostListener, inject } from '@angular/core';
2
+ import { DialogService } from '../dialog.service';
3
+
4
+ @Component({
5
+ selector: 'wally-dialog-trigger',
6
+ imports: [],
7
+ templateUrl: './dialog-trigger.html'
8
+ })
9
+ export class DialogTrigger {
10
+ dialogService = inject(DialogService);
11
+
12
+ @HostListener('click')
13
+ onClick(): void {
14
+ this.dialogService.open();
15
+ }
16
+ }
@@ -0,0 +1 @@
1
+ <ng-content></ng-content>
@@ -0,0 +1,20 @@
1
+ import { Injectable, signal } from '@angular/core';
2
+
3
+ @Injectable()
4
+ export class DialogService {
5
+ isOpen = signal<boolean>(false);
6
+ closeOnBackdropClick = signal<boolean>(true);
7
+ closeOnEsc = signal<boolean>(true);
8
+
9
+ open(): void {
10
+ this.isOpen.set(true);
11
+ }
12
+
13
+ close(): void {
14
+ this.isOpen.set(false);
15
+ }
16
+
17
+ toggle(): void {
18
+ this.isOpen.update(value => !value);
19
+ }
20
+ }
@@ -0,0 +1,29 @@
1
+ import { Component, effect, HostListener, inject, input } from '@angular/core';
2
+ import { DialogService } from './dialog.service';
3
+
4
+ @Component({
5
+ selector: 'wally-dialog',
6
+ imports: [],
7
+ providers: [DialogService],
8
+ templateUrl: './dialog.html'
9
+ })
10
+ export class Dialog {
11
+ dialogService = inject(DialogService);
12
+
13
+ closeOnBackdropClick = input<boolean>(true);
14
+ closeOnEsc = input<boolean>(true);
15
+
16
+ constructor() {
17
+ effect(() => {
18
+ this.dialogService.closeOnBackdropClick.set(this.closeOnBackdropClick());
19
+ this.dialogService.closeOnEsc.set(this.closeOnEsc());
20
+ });
21
+ }
22
+
23
+ @HostListener('document:keydown.escape')
24
+ onEscape(): void {
25
+ if (this.dialogService.isOpen() && this.dialogService.closeOnEsc()) {
26
+ this.dialogService.close();
27
+ }
28
+ }
29
+ }
@@ -19,9 +19,15 @@ export class DropdownMenuContent {
19
19
  const position = this.calculatedPosition();
20
20
  const scrollClasses = 'max-h-96 overflow-visible';
21
21
 
22
+ // Detectar se trigger está na metade direita da viewport
23
+ const triggerElement = this.elementRef.nativeElement.parentElement;
24
+ const isRightSide = triggerElement
25
+ ? triggerElement.getBoundingClientRect().left > window.innerWidth / 2
26
+ : false;
27
+
22
28
  const positionMap = {
23
- bottom: 'top-full mt-1 left-0',
24
- top: 'bottom-full mb-1 left-0',
29
+ bottom: isRightSide ? 'top-full mt-1 right-0' : 'top-full mt-1 left-0',
30
+ top: isRightSide ? 'bottom-full mb-1 right-0' : 'bottom-full mb-1 left-0',
25
31
  right: 'left-full ml-1 top-0',
26
32
  left: 'right-full mr-1 top-0'
27
33
  };
@@ -35,10 +41,10 @@ export class DropdownMenuContent {
35
41
  ) {
36
42
  effect(() => {
37
43
  if (this.dropdownMenuService.isOpen()) {
38
- setTimeout(() => {
44
+ requestAnimationFrame(() => {
39
45
  const bestPosition = this.calculateBestPosition();
40
46
  this.calculatedPosition.set(bestPosition);
41
- }, 0);
47
+ });
42
48
  }
43
49
  });
44
50
  }
@@ -49,8 +55,10 @@ export class DropdownMenuContent {
49
55
  @HostListener('window:resize')
50
56
  onResize(): void {
51
57
  if (this.dropdownMenuService.isOpen()) {
52
- const bestPosition = this.calculateBestPosition();
53
- this.calculatedPosition.set(bestPosition);
58
+ requestAnimationFrame(() => {
59
+ const bestPosition = this.calculateBestPosition();
60
+ this.calculatedPosition.set(bestPosition);
61
+ });
54
62
  }
55
63
  }
56
64