tailjng 0.0.13 → 0.0.15

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 (87) hide show
  1. package/cli/component-manager.js +45 -0
  2. package/cli/dependency-manager.js +52 -0
  3. package/cli/file-operations.js +88 -0
  4. package/cli/index.js +51 -0
  5. package/cli/settings/colors.js +17 -0
  6. package/cli/settings/components-list.js +87 -0
  7. package/cli/settings/header-generator.js +42 -0
  8. package/cli/settings/path-utils.js +50 -0
  9. package/cli/settings/prompt-utils.js +37 -0
  10. package/cli/settings/tailwind-check.js +21 -0
  11. package/fesm2022/tailjng.mjs +903 -25
  12. package/fesm2022/tailjng.mjs.map +1 -1
  13. package/lib/config/tailjng-config.token.d.ts +3 -0
  14. package/lib/interfaces/alert/dialog-alert.interface.d.ts +52 -0
  15. package/lib/interfaces/alert/toast-alert.interface.d.ts +52 -0
  16. package/lib/interfaces/config.interface.d.ts +5 -0
  17. package/lib/interfaces/crud/api-response.d.ts +29 -0
  18. package/lib/interfaces/crud/crud.interface.d.ts +103 -0
  19. package/lib/services/alert/dialog-alert.service.d.ts +24 -0
  20. package/lib/services/alert/toast-alert.service.d.ts +26 -0
  21. package/lib/services/crud/converter-crud.service.d.ts +41 -0
  22. package/lib/services/crud/generic-crud.service.d.ts +81 -0
  23. package/lib/services/http/error-handler-http.service.d.ts +26 -0
  24. package/lib/services/http/params-http.service.d.ts +13 -0
  25. package/lib/services/static/icons.service.d.ts +31 -0
  26. package/lib/services/transformer/calendar.service.d.ts +71 -0
  27. package/package.json +5 -3
  28. package/public-api.d.ts +10 -3
  29. package/src/lib/components/alert/dialog-alert/dialog-alert.component.css +0 -0
  30. package/src/lib/components/alert/dialog-alert/dialog-alert.component.html +72 -0
  31. package/src/lib/components/alert/dialog-alert/dialog-alert.component.ts +66 -0
  32. package/src/lib/components/alert/toast-alert/toast-alert.component.css +5 -0
  33. package/src/lib/components/alert/toast-alert/toast-alert.component.html +76 -0
  34. package/src/lib/components/alert/toast-alert/toast-alert.component.ts +87 -0
  35. package/src/lib/components/button/button.component.css +0 -0
  36. package/src/lib/components/button/button.component.html +36 -0
  37. package/src/lib/components/button/button.component.ts +95 -0
  38. package/src/lib/components/checkbox/input-checkbox/input-checkbox.component.css +0 -0
  39. package/src/lib/components/checkbox/input-checkbox/input-checkbox.component.html +23 -0
  40. package/src/lib/components/checkbox/input-checkbox/input-checkbox.component.ts +44 -0
  41. package/src/lib/components/checkbox/switch-checkbox/switch-checkbox.component.css +0 -0
  42. package/src/lib/components/checkbox/switch-checkbox/switch-checkbox.component.html +26 -0
  43. package/src/lib/components/checkbox/switch-checkbox/switch-checkbox.component.ts +29 -0
  44. package/src/lib/components/color/colors.service.ts +109 -0
  45. package/src/lib/components/dialog/dialog.component.css +8 -0
  46. package/src/lib/components/dialog/dialog.component.html +57 -0
  47. package/src/lib/components/dialog/dialog.component.ts +179 -0
  48. package/src/lib/components/image/viewer-image/viewer-image.component.css +4 -0
  49. package/src/lib/components/image/viewer-image/viewer-image.component.html +75 -0
  50. package/src/lib/components/image/viewer-image/viewer-image.component.ts +131 -0
  51. package/src/lib/components/input/file-input/file-input.component.css +0 -0
  52. package/src/lib/components/input/file-input/file-input.component.html +49 -0
  53. package/src/lib/components/input/file-input/file-input.component.ts +218 -0
  54. package/src/lib/components/input/input/input.component.css +0 -0
  55. package/src/lib/components/input/input/input.component.html +24 -0
  56. package/src/lib/components/input/input/input.component.ts +78 -0
  57. package/src/lib/components/input/range-input/range-input.component.css +0 -0
  58. package/src/lib/components/input/range-input/range-input.component.html +64 -0
  59. package/src/lib/components/input/range-input/range-input.component.ts +78 -0
  60. package/src/lib/components/input/textarea-input/textarea-input.component.css +0 -0
  61. package/src/lib/components/input/textarea-input/textarea-input.component.html +21 -0
  62. package/src/lib/components/input/textarea-input/textarea-input.component.ts +75 -0
  63. package/src/lib/components/label/label.component.html +1 -1
  64. package/src/lib/components/label/label.component.ts +1 -1
  65. package/src/lib/components/mode-toggle/mode-toggle.component.css +0 -0
  66. package/src/lib/components/mode-toggle/mode-toggle.component.html +8 -0
  67. package/src/lib/components/mode-toggle/mode-toggle.component.ts +61 -0
  68. package/src/lib/components/progress-bar/progress-bar.component.css +0 -0
  69. package/src/lib/components/progress-bar/progress-bar.component.html +22 -0
  70. package/src/lib/components/progress-bar/progress-bar.component.ts +20 -0
  71. package/src/lib/components/select/dropdown/dropdown.component.css +0 -0
  72. package/src/lib/components/select/dropdown/dropdown.component.html +95 -0
  73. package/src/lib/components/select/dropdown/dropdown.component.ts +562 -0
  74. package/src/lib/components/select/multi-dropdown/multi-dropdown.component.css +0 -0
  75. package/src/lib/components/select/multi-dropdown/multi-dropdown.component.html +87 -0
  76. package/src/lib/components/select/multi-dropdown/multi-dropdown.component.ts +315 -0
  77. package/src/lib/components/select/multi-table/multi-table.component.css +0 -0
  78. package/src/lib/components/select/multi-table/multi-table.component.html +83 -0
  79. package/src/lib/components/select/multi-table/multi-table.component.ts +230 -0
  80. package/src/lib/components/toggle-radio/toggle-radio.component.css +0 -0
  81. package/src/lib/components/toggle-radio/toggle-radio.component.html +51 -0
  82. package/src/lib/components/toggle-radio/toggle-radio.component.ts +203 -0
  83. package/src/styles.css +126 -0
  84. package/cli/tailjng.js +0 -105
  85. package/lib/services/icons.service.d.ts +0 -9
  86. package/lib/tailjng.component.d.ts +0 -5
  87. package/lib/tailjng.service.d.ts +0 -6
@@ -0,0 +1,13 @@
1
+ import { HttpParams } from '@angular/common/http';
2
+ import { Params } from '@angular/router';
3
+ import * as i0 from "@angular/core";
4
+ export declare class JParamsHttpService {
5
+ /**
6
+ * Transform Params to HttpParams
7
+ * @param params
8
+ * @returns
9
+ */
10
+ resParams(params: Params): HttpParams;
11
+ static ɵfac: i0.ɵɵFactoryDeclaration<JParamsHttpService, never>;
12
+ static ɵprov: i0.ɵɵInjectableDeclaration<JParamsHttpService>;
13
+ }
@@ -0,0 +1,31 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class JIconsService {
3
+ icons: {
4
+ info: import("lucide-angular").LucideIconData;
5
+ success: import("lucide-angular").LucideIconData;
6
+ error: import("lucide-angular").LucideIconData;
7
+ warning: import("lucide-angular").LucideIconData;
8
+ question: import("lucide-angular").LucideIconData;
9
+ close: import("lucide-angular").LucideIconData;
10
+ check: import("lucide-angular").LucideIconData;
11
+ zoomIn: import("lucide-angular").LucideIconData;
12
+ zoomOut: import("lucide-angular").LucideIconData;
13
+ rotateRight: import("lucide-angular").LucideIconData;
14
+ rotateLeft: import("lucide-angular").LucideIconData;
15
+ reset: import("lucide-angular").LucideIconData;
16
+ fullscreen: import("lucide-angular").LucideIconData;
17
+ exitFullscreen: import("lucide-angular").LucideIconData;
18
+ imageOff: import("lucide-angular").LucideIconData;
19
+ upload: import("lucide-angular").LucideIconData;
20
+ view: import("lucide-angular").LucideIconData;
21
+ chevronDown: import("lucide-angular").LucideIconData;
22
+ squareDashedMousePointer: import("lucide-angular").LucideIconData;
23
+ search: import("lucide-angular").LucideIconData;
24
+ sun: import("lucide-angular").LucideIconData;
25
+ moon: import("lucide-angular").LucideIconData;
26
+ loading: import("lucide-angular").LucideIconData;
27
+ };
28
+ constructor();
29
+ static ɵfac: i0.ɵɵFactoryDeclaration<JIconsService, never>;
30
+ static ɵprov: i0.ɵɵInjectableDeclaration<JIconsService>;
31
+ }
@@ -0,0 +1,71 @@
1
+ import * as i0 from "@angular/core";
2
+ export declare class JCalendarService {
3
+ nameDaysAb: string[];
4
+ nameDays: string[];
5
+ nameMontsAb: string[];
6
+ nameMonts: string[];
7
+ /**
8
+ * Get month from date
9
+ * @param date The date to extract the month from, can be a Date object or a string in 'YYYY-MM-DD' format.
10
+ * @returns The name of the month in Spanish.
11
+ */
12
+ getMonthFromDate(date: Date | string): string;
13
+ /**
14
+ * Calculate the age of a person based on their birth date.
15
+ * @param birth The birth date as a Date object or a string in 'YYYY-MM-DD' format.
16
+ * @returns The age in years, or null if the birth date is invalid.
17
+ */
18
+ calculateAge(birth: Date | string): number | null;
19
+ /**
20
+ * Calculate the complete age of a person based on their birth date.
21
+ * @param birth The birth date as a Date object or a string in 'YYYY-MM-DD' format.
22
+ * @returns An object containing years, months, and days of age.
23
+ */
24
+ calculateAgeComplete(birth: Date | string): {
25
+ years: number;
26
+ months: number;
27
+ days: number;
28
+ };
29
+ /**
30
+ * Format a date string to a more readable format.
31
+ * @param date The date string in 'YYYY-MM-DD' format.
32
+ * @param month Optional parameter to add to the month name.
33
+ * @returns A formatted date string in the format 'DD de MMMM del YYYY'.
34
+ */
35
+ formatearFechaString(date: string, month?: number): string;
36
+ /**
37
+ * Format a Date object to a string in the format 'DD de MMMM del YYYY'.
38
+ * @param date The Date object to format.
39
+ * @param month Optional parameter to add to the month name.
40
+ * @returns A formatted date string.
41
+ */
42
+ formatearFechaDate(date: Date, month?: number): string;
43
+ /**
44
+ * Parse a date string in the format "dd de MMMM del yyyy" to "yyyy-MM-dd".
45
+ * @param fechaStr The date string to parse.
46
+ * @returns The parsed date string in "yyyy-MM-dd" format or null if invalid.
47
+ */
48
+ parseFechaString(fechaStr: string): string | null;
49
+ /**
50
+ * Format a date to "MMM YY" format.
51
+ * @param date The date to format, can be a Date object.
52
+ * @returns The formatted date string.
53
+ */
54
+ formatMonthYear(date: Date): string;
55
+ /**
56
+ * Format a date to the Bogotá timezone (UTC-5).
57
+ * @param date The date to format, can be a Date object.
58
+ * @returns The formatted date string in 'yyyy-MM-ddTHH:mm:ss' format.
59
+ */
60
+ formatDateToBogota(date: Date): string;
61
+ /**
62
+ * Format a date to a relative time string.
63
+ * This method uses date-fns to format the date relative to now.
64
+ * @param date The date to format, can be a string in 'YYYY-MM-DD' format.
65
+ * @returns A formatted relative time string.
66
+ * @example "hace 2 días", "hace 1 hora", etc
67
+ */
68
+ formatRelativeDate(date: string): string;
69
+ static ɵfac: i0.ɵɵFactoryDeclaration<JCalendarService, never>;
70
+ static ɵprov: i0.ɵɵInjectableDeclaration<JCalendarService>;
71
+ }
package/package.json CHANGED
@@ -1,15 +1,17 @@
1
1
  {
2
2
  "name": "tailjng",
3
- "version": "0.0.13",
3
+ "version": "0.0.15",
4
4
  "peerDependencies": {
5
5
  "@angular/common": "^19.2.0",
6
6
  "@angular/core": "^19.2.0",
7
+ "@angular/animations": "^19.2.0",
7
8
  "@ng-icons/lucide": ">=29.0.0",
8
9
  "lucide-angular": ">=0.477.0",
9
- "tailwindcss": ">=4.0.9"
10
+ "tailwindcss": ">=4.0.9",
11
+ "date-fns": "^4.1.0"
10
12
  },
11
13
  "bin": {
12
- "tailjng": "./cli/tailjng.js"
14
+ "tailjng": "./cli/index.js"
13
15
  },
14
16
  "dependencies": {
15
17
  "tslib": "^2.3.0"
package/public-api.d.ts CHANGED
@@ -1,3 +1,10 @@
1
- export * from './lib/tailjng.service';
2
- export * from './lib/tailjng.component';
3
- export * from './lib/services/icons.service';
1
+ export * from './lib/config/tailjng-config.token';
2
+ export * from './lib/services/crud/converter-crud.service';
3
+ export * from './lib/services/crud/generic-crud.service';
4
+ export * from './lib/services/http/params-http.service';
5
+ export * from './lib/services/http/error-handler-http.service';
6
+ export * from './lib/services/transformer/calendar.service';
7
+ export * from './lib/services/static/icons.service';
8
+ export * from './lib/services/alert/dialog-alert.service';
9
+ export * from './lib/services/alert/toast-alert.service';
10
+ export * from './lib/interfaces/crud/crud.interface';
@@ -0,0 +1,72 @@
1
+ @for (dialog of dialogs(); track dialog.config.title) {
2
+ <div class="fixed inset-0 z-1001 flex items-center justify-center bg-black/50">
3
+ <div @modalTransition
4
+ class="relative w-100 border border-border p-4 rounded-lg shadow-5xl overflow-hidden"
5
+ [ngClass]="getDialogClass(dialog.config.type)">
6
+
7
+ <!-- Icon big in the bottom left corner -->
8
+ <div [ngClass]="{ 'animate-spin': dialog.config.type === 'loading'}"
9
+ class="absolute -bottom-5 opacity-25 dark:opacity-25 -left-5 text-black dark:text-white pointer-events-none">
10
+ <lucide-icon
11
+ [name]="getIcon(dialog.config.type)"
12
+ [size]="130"
13
+ [ngClass]="getIconClass(dialog.config.type)"
14
+ >
15
+ </lucide-icon>
16
+ </div>
17
+
18
+ <!-- Icon small in the top right corner -->
19
+ <div [ngClass]="{ 'animate-spin': dialog.config.type === 'loading'}"
20
+ class="absolute top-5 opacity-25 dark:opacity-25 right-5 text-black dark:text-white pointer-events-none">
21
+ <lucide-icon
22
+ [name]="getIcon(dialog.config.type)"
23
+ [size]="30"
24
+ [ngClass]="getIconClass(dialog.config.type)"
25
+ >
26
+ </lucide-icon>
27
+ </div>
28
+
29
+ <h3 class="text-lg font-semibold text-black dark:text-white pb-2">{{ dialog.config.title }}</h3>
30
+ <p class="text-black/80 dark:text-dark-muted-foreground" [innerHTML]="dialog.config.description"></p>
31
+
32
+ <div class="flex justify-end gap-2 mt-4">
33
+
34
+ <!-- Button Retry (Only if type is "error") -->
35
+ @if (dialog.config.type === 'error' && dialog.config.onRetry) {
36
+ <JButton
37
+ (clicked)="handleAction('retry')"
38
+ [disabled]="dialog.isRetryLoading || dialog.isCancelLoading || dialog.isConfirmLoading"
39
+ [isLoading]="dialog.isRetryLoading"
40
+ [ngClasses]="getButtonSecondaryClass(dialog.config.type)"
41
+ >
42
+ {{ dialog.config.titleBtnRetry || 'Reintentar' }}
43
+ </JButton>
44
+ }
45
+
46
+ <!-- Button Cancel (Not shown if type is "success") -->
47
+ @if (dialog.config.type !== 'success' && dialog.config.onCancel) {
48
+ <JButton
49
+ (clicked)="handleAction('cancel')"
50
+ [disabled]="dialog.isRetryLoading || dialog.isCancelLoading || dialog.isConfirmLoading"
51
+ [isLoading]="dialog.isCancelLoading"
52
+ [ngClasses]="getButtonSecondaryClass(dialog.config.type)"
53
+ >
54
+ {{ dialog.config.titleBtnCancel || 'Cancelar' }}
55
+ </JButton>
56
+ }
57
+
58
+ <!-- Button Confirm (Not shown if type is "loading") -->
59
+ @if (dialog.config.type !== 'loading' && dialog?.config?.onConfirm) {
60
+ <JButton
61
+ (clicked)="handleAction('confirm')"
62
+ [disabled]="dialog.isRetryLoading || dialog.isCancelLoading || dialog.isConfirmLoading"
63
+ [isLoading]="dialog.isConfirmLoading"
64
+ [ngClasses]="getButtonClass(dialog.config.type)"
65
+ >
66
+ {{ dialog.config.titleBtnConfirm || 'Confirmar' }}
67
+ </JButton>
68
+ }
69
+ </div>
70
+ </div>
71
+ </div>
72
+ }
@@ -0,0 +1,66 @@
1
+ import { Component, inject, computed, Input } from "@angular/core";
2
+ import { NgClass } from "@angular/common";
3
+ import { trigger, transition, style, animate } from "@angular/animations";
4
+ import { JIconsService, JAlertDialogService } from "tailjng";
5
+ import { LucideAngularModule } from "lucide-angular";
6
+ import { JButtonComponent } from "../../button/button.component";
7
+ import { JColorsService } from "../../color/colors.service";
8
+
9
+ @Component({
10
+ selector: 'JAlertDialog',
11
+ imports: [LucideAngularModule, NgClass, JButtonComponent],
12
+ templateUrl: './dialog-alert.component.html',
13
+ styleUrl: './dialog-alert.component.css',
14
+ animations: [
15
+ trigger("modalTransition", [
16
+ transition(":enter", [
17
+ style({ transform: "translateY(1rem)", opacity: 0 }),
18
+ animate("300ms ease-out", style({ transform: "translateY(0)", opacity: 1 })),
19
+ ]),
20
+ transition(":leave", [
21
+ animate("150ms ease-in", style({ transform: "translateY(1rem)", opacity: 0 })),
22
+ ]),
23
+ ]),
24
+ ],
25
+ })
26
+ export class JAlertDialogComponent {
27
+ @Input() monocromatic: boolean = false;
28
+ private readonly alertDialogService = inject(JAlertDialogService);
29
+
30
+ constructor(
31
+ private readonly colorsService: JColorsService,
32
+ private readonly iconsService: JIconsService
33
+ ) { }
34
+
35
+ // Single computed property for dialogs
36
+ dialogs = computed(() => this.alertDialogService.dialogs());
37
+
38
+ getIcon(type: string) {
39
+ return this.iconsService.icons[type as keyof typeof this.iconsService.icons] || this.iconsService.icons.info;
40
+ }
41
+
42
+ // Method to execute the action based on the button clicked
43
+ handleAction(action: "confirm" | "cancel" | "retry") {
44
+ this.alertDialogService.executeAction(action);
45
+ }
46
+
47
+ // Get the class for the toast
48
+ getDialogClass(type: string) {
49
+ return this.colorsService.getAlertClass(type, this.monocromatic);
50
+ }
51
+
52
+ // Get the class for the icon
53
+ getIconClass(type: string) {
54
+ return this.colorsService.getIconClass(type, this.monocromatic);
55
+ }
56
+
57
+ // Get the class for the button
58
+ getButtonClass(type: string): { [key: string]: boolean } {
59
+ return this.colorsService.getButtonClass(type, this.monocromatic);
60
+ }
61
+
62
+ // Get the class for the secondary button
63
+ getButtonSecondaryClass(type: string): { [key: string]: boolean } {
64
+ return this.colorsService.getButtonSecondaryClass(type, this.monocromatic);
65
+ }
66
+ }
@@ -0,0 +1,5 @@
1
+ @media (max-width: 450px) {
2
+ .j-dialog-toas {
3
+ width: 90% !important;
4
+ }
5
+ }
@@ -0,0 +1,76 @@
1
+ <div [ngClass]="getPositionClass()">
2
+ @for (toast of toasts(); track toast.id) {
3
+ <div @toastTransition
4
+ class="j-dialog-toas relative ml-auto w-100 border border-border border-l-4 p-4 rounded-lg shadow-lg overflow-hidden flex gap-3"
5
+ [ngClass]="getToastClass(toast.config.type)">
6
+
7
+ <!-- Close button -->
8
+ <button
9
+ class="absolute p-1 top-2 right-2 cursor-pointer rounded transition duration-300 hover:bg-background dark:hover:bg-dark-background"
10
+ [ngClass]="getIconClass(toast.config.type)"
11
+ (click)="closeToast(toast.id)"
12
+ >
13
+ <lucide-icon [name]="iconsService.icons.close" [size]="16"></lucide-icon>
14
+ </button>
15
+
16
+ <!-- Big icon in the bottom left corner -->
17
+ <div [ngClass]="{ 'animate-spin': toast.config.type === 'loading'}"
18
+ class="absolute -bottom-5 opacity-15 dark:opacity-25 -left-5 text-black dark:text-white z-2 pointer-events-none">
19
+ <lucide-icon
20
+ [name]="getIcon(toast.config.type)"
21
+ [size]="100"
22
+ [ngClass]="getIconClass(toast.config.type)"
23
+ >
24
+ </lucide-icon>
25
+ </div>
26
+
27
+ <!-- Small icon in the top right corner -->
28
+ <div [ngClass]="{ 'animate-spin': toast.config.type === 'loading'}"
29
+ class="absolute top-5 opacity-15 dark:opacity-25 right-5 text-black dark:text-white z-2 pointer-events-none">
30
+ <lucide-icon
31
+ [name]="getIcon(toast.config.type)"
32
+ [size]="30"
33
+ [ngClass]="getIconClass(toast.config.type)"
34
+ >
35
+ </lucide-icon>
36
+ </div>
37
+
38
+ <!-- Content -->
39
+ <div class="flex-1">
40
+ <h3 class="text-sm font-semibold text-black dark:text-white pb-2">{{ toast.config.title }}</h3>
41
+ <p class="text-sm text-black/80 dark:text-dark-muted-foreground" [innerHTML]="toast.config.description"></p>
42
+
43
+ <!-- Action buttons -->
44
+ <div class="flex justify-end gap-2 mt-2">
45
+
46
+ <!-- Button Cancel -->
47
+ @if (toast.config.type !== 'success' && toast.onCancelCallback) {
48
+ <JButton
49
+ (clicked)="handleAction(toast.id, 'cancel')"
50
+ [disabled]="toast.isCancelLoading || toast.isActionLoading"
51
+ [isLoading]="toast.isCancelLoading"
52
+ classes="text-[10px] min-w-auto"
53
+ [ngClasses]="getButtonSecondaryClass(toast.config.type)"
54
+ >
55
+ {{toast.config.titleBtnCancel || 'Cancelar'}}
56
+ </JButton>
57
+ }
58
+
59
+ <!-- Button Action -->
60
+ @if (toast.config.type !== 'loading' && toast.onActionCallback) {
61
+ <JButton
62
+ (clicked)="handleAction(toast.id, 'action')"
63
+ [disabled]="toast.isCancelLoading || toast.isActionLoading"
64
+ [isLoading]="toast.isActionLoading"
65
+ classes="text-[10px] min-w-auto"
66
+ [ngClasses]="getButtonClass(toast.config.type)"
67
+ >
68
+ {{toast.actionNameButton}}
69
+ </JButton>
70
+ }
71
+ </div>
72
+ </div>
73
+
74
+ </div>
75
+ }
76
+ </div>
@@ -0,0 +1,87 @@
1
+ import { Component, computed, inject, Input } from '@angular/core';
2
+ import { trigger, transition, style, animate } from "@angular/animations";
3
+ import { NgClass } from '@angular/common';
4
+ import { LucideAngularModule } from 'lucide-angular';
5
+ import { JButtonComponent } from '../../button/button.component';
6
+ import { JColorsService } from '../../color/colors.service';
7
+ import { JIconsService, JAlertToastService } from 'tailjng';
8
+
9
+ @Component({
10
+ selector: 'JAlertToast',
11
+ imports: [LucideAngularModule, NgClass, JButtonComponent],
12
+ templateUrl: './toast-alert.component.html',
13
+ styleUrl: './toast-alert.component.css',
14
+ animations: [
15
+ trigger("toastTransition", [
16
+ transition(":enter", [
17
+ style({ opacity: 0, transform: "translateY(10px)" }),
18
+ animate("300ms ease-out", style({ opacity: 1, transform: "translateY(0)" }))
19
+ ]),
20
+ transition(":leave", [
21
+ animate("150ms ease-in", style({ opacity: 0, transform: "translateY(10px)" }))
22
+ ])
23
+ ])
24
+ ]
25
+ })
26
+ export class JAlertToastComponent {
27
+ @Input() monocromatic: boolean = false;
28
+ @Input() position: 'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' = 'bottom-right';
29
+
30
+ private readonly alertToastService = inject(JAlertToastService);
31
+
32
+ constructor(
33
+ private readonly colorsService: JColorsService,
34
+ public readonly iconsService: JIconsService
35
+ ) { }
36
+
37
+ toasts = computed(() => this.alertToastService.toasts());
38
+
39
+ getIcon(type: string) {
40
+ return this.iconsService.icons[type as keyof typeof this.iconsService.icons] || this.iconsService.icons.info;
41
+ }
42
+
43
+ handleAction(toastId: string, action: "action" | "cancel") {
44
+ this.alertToastService.executeToastAction(toastId, action);
45
+ }
46
+
47
+ closeToast(toastId: string) {
48
+ this.alertToastService.closeToastById(toastId);
49
+ }
50
+
51
+ // Get the class of the toast
52
+ getToastClass(type: string) {
53
+ return this.colorsService.getAlertClass(type, this.monocromatic);
54
+ }
55
+
56
+ // Get the class of the icon
57
+ getIconClass(type: string) {
58
+ return this.colorsService.getIconClass(type, this.monocromatic);
59
+ }
60
+
61
+ // Get the class of the button
62
+ getButtonClass(type: string): { [key: string]: boolean } {
63
+ return this.colorsService.getButtonClass(type, this.monocromatic);
64
+ }
65
+
66
+ // Get the class of the secondary button
67
+ getButtonSecondaryClass(type: string): { [key: string]: boolean } {
68
+ return this.colorsService.getButtonSecondaryClass(type, this.monocromatic);
69
+ }
70
+
71
+ // Assign toast position
72
+ getPositionClass(): string {
73
+ const base = 'w-full fixed z-1000 flex flex-col gap-2 max-w-md';
74
+ switch (this.position) {
75
+ case 'top-left':
76
+ return `${base} top-4 left-4`;
77
+ case 'top-right':
78
+ return `${base} top-20 right-4`;
79
+ case 'bottom-left':
80
+ return `${base} bottom-4 left-4`;
81
+ case 'bottom-right':
82
+ default:
83
+ return `${base} bottom-4 right-4`;
84
+ }
85
+ }
86
+
87
+ }
File without changes
@@ -0,0 +1,36 @@
1
+ <button
2
+ [attr.type]="type"
3
+ [jTooltip]="tooltip"
4
+ [jTooltipPosition]="tooltipPosition"
5
+ [disabled]="disabled || isLoading"
6
+ [ngClass]="computedClasses"
7
+ [class]="classes"
8
+ (click)="handleClick($event)"
9
+ >
10
+ <div class="flex items-center justify-center gap-2">
11
+
12
+ @if (isLoading) {
13
+ <div [ngClass]="{ 'pt-1 pb-1': icon }">
14
+ <lucide-icon [name]="iconsService.icons.loading" [size]="iconSize || 15" class="animate-spin" />
15
+ </div>
16
+ }
17
+
18
+ @if (!isLoading && icon) {
19
+ <div class="pt-1 pb-1">
20
+
21
+ @if (!isChangeIcon) {
22
+ <lucide-icon [name]="icon" [size]="iconSize" />
23
+ } @else {
24
+ <lucide-icon [name]="iconChange" [size]="iconSize" />
25
+ }
26
+
27
+ </div>
28
+ }
29
+
30
+ @if (!isLoading && text) {
31
+ <span>{{ text }}</span>
32
+ }
33
+
34
+ <ng-content></ng-content>
35
+ </div>
36
+ </button>
@@ -0,0 +1,95 @@
1
+ import { NgClass } from "@angular/common"
2
+ import { Component, Input, Output, EventEmitter } from "@angular/core"
3
+ import { LucideAngularModule } from "lucide-angular"
4
+ import { JIconsService } from "tailjng";
5
+ import { JColorsService } from '../color/colors.service';
6
+ import { JTooltipDirective } from "../tooltip/tooltip.directive"
7
+
8
+ @Component({
9
+ selector: 'JButton',
10
+ imports: [NgClass, LucideAngularModule, JTooltipDirective],
11
+ templateUrl: './button.component.html',
12
+ styleUrl: './button.component.css'
13
+ })
14
+ export class JButtonComponent {
15
+
16
+ @Input() type: "button" | "submit" | "reset" = "button";
17
+ @Input() tooltipPosition: "top" | "right" | "bottom" | "left" = "top";
18
+
19
+ @Input() text!: string | number;
20
+ @Input() tooltip: string = "";
21
+
22
+ @Input() icon!: any;
23
+ @Input() iconSize: number = 15;
24
+ @Input() iconChange!: any;
25
+ @Input() isChangeIcon: boolean = false;
26
+
27
+ @Output() clicked = new EventEmitter<Event>();
28
+
29
+ @Input() disabled = false;
30
+ @Input() isLoading = false;
31
+
32
+ @Input() classes: string = "";
33
+ @Input() ngClasses: { [key: string]: boolean } = {};
34
+
35
+
36
+ // Define classes based on button type (switch)
37
+ get variantClasses(): string {
38
+ return this.colorsService.variants[this.getActiveVariant()] || "min-w-[100px] text-black dark:text-white shadow-md"
39
+ }
40
+
41
+ // Combine base classes with variants
42
+ get computedClasses() {
43
+ return {
44
+ "flex gap-3 items-center justify-center font-semibold border border-border dark:border-dark-border px-3 py-2 rounded transition duration-300 select-none": true,
45
+ [this.variantClasses]: true, // Apply variant classes based on switch
46
+ "cursor-pointer": !this.disabled && !this.isLoading, // Default cursor when active
47
+ "cursor-default opacity-50 pointer-events-none": this.disabled || this.isLoading, // Disabled cursor
48
+ ...this.ngClasses, // Allows using dynamic validations with [ngClass]
49
+ }
50
+ }
51
+
52
+
53
+ constructor(
54
+ public readonly iconsService: JIconsService,
55
+ private readonly colorsService: JColorsService,
56
+ ) { }
57
+
58
+
59
+ /**
60
+ * Verify if a class is present in `classes` or `ngClasses`
61
+ * Split the class string by spaces to check each class individually
62
+ * @param className Name of the class to check
63
+ * @returns True if the class is present, false otherwise
64
+ */
65
+ private hasClass(className: string): boolean {
66
+ const classArray = this.classes.split(" ")
67
+ return classArray.includes(className) || this.ngClasses[className]
68
+ }
69
+
70
+
71
+
72
+ /**
73
+ * Get the active variant based on the provided classes.
74
+ * It checks if the class exists in the `variants` object of `JColorsService
75
+ * @returns The active variant based on the provided classes.
76
+ */
77
+ private getActiveVariant(): string {
78
+ const variant = Object.keys(this.colorsService.variants).find((variant) => this.hasClass(variant))
79
+ return variant ?? "default"
80
+ }
81
+
82
+
83
+
84
+ /**
85
+ * Handle click event on the button.
86
+ * Emits the clicked event if the button is not disabled and not loading.
87
+ * @param event The click event
88
+ */
89
+ handleClick(event: Event) {
90
+ if (!this.disabled && !this.isLoading) {
91
+ this.clicked.emit(event)
92
+ }
93
+ }
94
+
95
+ }
@@ -0,0 +1,23 @@
1
+ <div class="flex flex-col items-center justify-center gap-2">
2
+ @if (title) {
3
+ <span class="text-[8px] opacity-80">{{title}}</span>
4
+ }
5
+
6
+ <label class="relative inline-flex items-center justify-center">
7
+ <input
8
+ type="checkbox"
9
+ class="absolute opacity-0 cursor-pointer peer"
10
+ [checked]="getValue(item, column)"
11
+ (change)="onCheckboxChange(item, column)"
12
+ [disabled]="disabled"
13
+ >
14
+ <span
15
+ class="inline-flex items-center justify-center w-[25px] h-[25px] bg-white border border-primary dark:border-dark-border rounded transition-all duration-200 ease-in-out relative peer peer-checked:bg-primary peer-checked:border-primary dark:peer-checked:bg-dark-primary dark:peer-checked:border-dark-primary"
16
+ [class]="classes"
17
+ [ngClass]="{'opacity-50' : disabled, 'cursor-not-allowed': disabled, 'cursor-pointer': !disabled}"
18
+ >
19
+ <lucide-icon [name]="icon" [size]="iconSize" class="text-white"></lucide-icon>
20
+ </span>
21
+ </label>
22
+
23
+ </div>
@@ -0,0 +1,44 @@
1
+ import { Component, forwardRef, Input } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import { LucideAngularModule } from 'lucide-angular';
4
+ import { JIconsService } from 'tailjng';
5
+ import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule } from '@angular/forms';
6
+
7
+ @Component({
8
+ selector: 'JInputCheckbox',
9
+ imports: [CommonModule, LucideAngularModule, FormsModule, ReactiveFormsModule],
10
+ templateUrl: './input-checkbox.component.html',
11
+ styleUrl: './input-checkbox.component.css',
12
+ providers: [
13
+ {
14
+ provide: NG_VALUE_ACCESSOR,
15
+ useExisting: forwardRef(() => JInputCheckboxComponent),
16
+ multi: true
17
+ }
18
+ ]
19
+ })
20
+ export class JInputCheckboxComponent {
21
+
22
+ @Input() title!: string;
23
+
24
+ @Input() icon: any;
25
+ @Input() iconSize: number = 15;
26
+
27
+ @Input() disabled?: boolean;
28
+ @Input() isLoading?: boolean;
29
+ @Input() classes: string = '';
30
+
31
+ @Input() item: any;
32
+ @Input() column: any;
33
+
34
+ // Funciones
35
+ @Input() getValue: (item: any, column: any) => boolean = () => false;
36
+ @Input() onCheckboxChange: (item: any, column: any) => void = () => { };
37
+
38
+ constructor(
39
+ public readonly iconsService: JIconsService
40
+ ) {
41
+ this.icon = this.iconsService.icons.check;
42
+ }
43
+
44
+ }