tailjng 0.1.6 → 0.1.8

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 (175) hide show
  1. package/README.md +27 -5
  2. package/cli/execute/init-app.js +5 -2
  3. package/cli/execute/sync-app.js +14 -2
  4. package/cli/settings/colors-config-utils.js +69 -11
  5. package/cli/settings/icons-config-utils.js +62 -0
  6. package/cli/settings/path-utils.js +32 -2
  7. package/cli/settings/project-utils.js +7 -1
  8. package/cli/templates/app.generator.js +8 -5
  9. package/fesm2022/tailjng.mjs +247 -80
  10. package/fesm2022/tailjng.mjs.map +1 -1
  11. package/lib/services/static/theme.service.d.ts +39 -1
  12. package/lib/utils/theme/theme-variables.util.d.ts +31 -0
  13. package/package.json +1 -1
  14. package/public-api.d.ts +2 -1
  15. package/registry/components.json +41 -18
  16. package/src/colors.safelist.css +2 -2
  17. package/src/lib/components/.config/README.md +11 -0
  18. package/src/lib/components/.config/colors/README.md +40 -0
  19. package/src/lib/components/{colors-config → .config/colors}/colors.config.ts +5 -5
  20. package/src/lib/components/{colors-config → .config/colors}/colors.safelist.css +2 -2
  21. package/src/lib/components/.config/icons/README.md +26 -0
  22. package/src/lib/components/.config/icons/icons.lucide.ts +134 -0
  23. package/src/lib/components/.config/input/README.md +24 -0
  24. package/src/lib/components/.config/input/input.classes.ts +119 -0
  25. package/src/lib/components/alert/alert-dialog/dialog-alert.component.css +177 -6
  26. package/src/lib/components/alert/alert-dialog/dialog-alert.component.html +24 -37
  27. package/src/lib/components/alert/alert-dialog/dialog-alert.component.ts +66 -56
  28. package/src/lib/components/alert/alert-dialog/dialog-alert.types.ts +19 -0
  29. package/src/lib/components/alert/alert-toast/toast-alert.component.css +494 -14
  30. package/src/lib/components/alert/alert-toast/toast-alert.component.html +106 -102
  31. package/src/lib/components/alert/alert-toast/toast-alert.component.ts +485 -128
  32. package/src/lib/components/alert/alert-toast/toast-alert.types.ts +25 -0
  33. package/src/lib/components/badge/badge.component.html +34 -21
  34. package/src/lib/components/badge/badge.component.ts +140 -31
  35. package/src/lib/components/button/button.component.html +16 -10
  36. package/src/lib/components/button/button.component.ts +162 -22
  37. package/src/lib/components/card/card-complete/complete-card.component.html +2 -2
  38. package/src/lib/components/card/card-complete/complete-card.component.ts +26 -16
  39. package/src/lib/components/card/card-crud-complete/complete-crud-card.component.html +2 -2
  40. package/src/lib/components/card/card-crud-complete/complete-crud-card.component.ts +26 -16
  41. package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.css +30 -0
  42. package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.html +58 -46
  43. package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.ts +135 -64
  44. package/src/lib/components/checkbox/checkbox-input/input-checkbox.types.ts +3 -0
  45. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.css +62 -0
  46. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.html +39 -25
  47. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.ts +74 -15
  48. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.types.ts +1 -0
  49. package/src/lib/components/coach-mark/coach-mark.component.html +6 -24
  50. package/src/lib/components/coach-mark/coach-mark.component.scss +1 -7
  51. package/src/lib/components/coach-mark/coach-mark.component.ts +51 -18
  52. package/src/lib/components/coach-mark/coach-mark.directive.ts +133 -78
  53. package/src/lib/components/coach-mark/coach-mark.types.ts +12 -0
  54. package/src/lib/components/dialog/dialog.component.css +1 -1
  55. package/src/lib/components/dialog/dialog.component.html +56 -65
  56. package/src/lib/components/dialog/dialog.component.ts +136 -110
  57. package/src/lib/components/dialog/dialog.types.ts +19 -0
  58. package/src/lib/components/filter/filter-complete/complete-filter.component.html +17 -20
  59. package/src/lib/components/filter/filter-complete/complete-filter.component.scss +25 -0
  60. package/src/lib/components/filter/filter-complete/complete-filter.component.ts +58 -34
  61. package/src/lib/components/filter/filter-complete/complete-filter.types.ts +7 -0
  62. package/src/lib/components/filter/filter-complete/complete-filter.util.ts +16 -0
  63. package/src/lib/components/form/form-container/container-form.component.css +4 -0
  64. package/src/lib/components/form/form-container/container-form.component.html +2 -2
  65. package/src/lib/components/form/form-container/container-form.component.ts +72 -16
  66. package/src/lib/components/form/form-container/container-form.types.ts +42 -0
  67. package/src/lib/components/form/form-container/form-col-span.directive.ts +25 -0
  68. package/src/lib/components/form/form-sidebar/sidebar-form.component.css +45 -0
  69. package/src/lib/components/form/form-sidebar/sidebar-form.component.html +128 -124
  70. package/src/lib/components/form/form-sidebar/sidebar-form.component.ts +114 -34
  71. package/src/lib/components/form/form-sidebar/sidebar-form.types.ts +3 -0
  72. package/src/lib/components/{toggle-radio/toggle-radio.component.css → form/form-validation/validation-form.component.css} +0 -1
  73. package/src/lib/components/form/form-validation/validation-form.component.html +10 -6
  74. package/src/lib/components/form/form-validation/validation-form.component.ts +99 -12
  75. package/src/lib/components/form/form-validation/validation-form.types.ts +33 -0
  76. package/src/lib/components/icon/icon.component.html +8 -5
  77. package/src/lib/components/icon/icon.component.ts +111 -9
  78. package/src/lib/components/input/input/input.component.css +0 -14
  79. package/src/lib/components/input/input/input.component.html +19 -16
  80. package/src/lib/components/input/input/input.component.ts +130 -53
  81. package/src/lib/components/input/input/input.types.ts +8 -0
  82. package/src/lib/components/input/input-file/file-input.component.html +65 -56
  83. package/src/lib/components/input/input-file/file-input.component.ts +276 -173
  84. package/src/lib/components/input/input-file/file-input.types.ts +2 -0
  85. package/src/lib/components/input/input-range/range-input.component.css +67 -0
  86. package/src/lib/components/input/input-range/range-input.component.html +50 -58
  87. package/src/lib/components/input/input-range/range-input.component.ts +148 -60
  88. package/src/lib/components/input/input-range/range-input.types.ts +7 -0
  89. package/src/lib/components/input/input-textarea/textarea-input.component.html +16 -7
  90. package/src/lib/components/input/input-textarea/textarea-input.component.ts +140 -50
  91. package/src/lib/components/input/input-textarea/textarea-input.types.ts +2 -0
  92. package/src/lib/components/label/label.component.html +17 -16
  93. package/src/lib/components/label/label.component.ts +94 -16
  94. package/src/lib/components/label/label.types.ts +2 -0
  95. package/src/lib/components/menu/menu-options-table/menu-options-defaults.ts +34 -0
  96. package/src/lib/components/menu/menu-options-table/options-table-menu.component.html +34 -20
  97. package/src/lib/components/menu/menu-options-table/options-table-menu.component.ts +211 -58
  98. package/src/lib/components/menu/menu-options-table/options-table-menu.types.ts +38 -0
  99. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.html +49 -52
  100. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.ts +112 -24
  101. package/src/lib/components/menu/options-coach-menu/options-coach-menu.types.ts +9 -0
  102. package/src/lib/components/mode-toggle/mode-toggle.component.html +11 -16
  103. package/src/lib/components/mode-toggle/mode-toggle.component.ts +69 -33
  104. package/src/lib/components/paginator/paginator-complete/complete-paginator.component.html +4 -4
  105. package/src/lib/components/paginator/paginator-complete/complete-paginator.component.ts +31 -7
  106. package/src/lib/components/paginator/paginator-complete/complete-paginator.types.ts +12 -0
  107. package/src/lib/components/paginator/paginator-complete/complete-paginator.util.ts +36 -0
  108. package/src/lib/components/progress-bar/progress-bar.component.html +41 -40
  109. package/src/lib/components/progress-bar/progress-bar.component.ts +95 -11
  110. package/src/lib/components/progress-bar/progress-bar.types.ts +2 -0
  111. package/src/lib/components/select/select-dropdown/dropdown-select.component.html +56 -46
  112. package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +450 -509
  113. package/src/lib/components/select/select-dropdown/dropdown-select.types.ts +43 -0
  114. package/src/lib/components/select/select-dropdown/dropdown-select.util.ts +179 -0
  115. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +131 -42
  116. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.ts +491 -475
  117. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.types.ts +22 -0
  118. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.util.ts +20 -0
  119. package/src/lib/components/select/select-multi-table/multi-table-select.component.css +4 -0
  120. package/src/lib/components/select/select-multi-table/multi-table-select.component.html +76 -60
  121. package/src/lib/components/select/select-multi-table/multi-table-select.component.ts +250 -313
  122. package/src/lib/components/select/select-multi-table/multi-table-select.types.ts +10 -0
  123. package/src/lib/components/select/select-multi-table/multi-table-select.util.ts +5 -0
  124. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.css +155 -0
  125. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.html +72 -53
  126. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.ts +84 -27
  127. package/src/lib/components/sidebar/sidebar-static/static-sidebar.types.ts +2 -0
  128. package/src/lib/components/table/table-complete/complete-table.component.html +21 -23
  129. package/src/lib/components/table/table-complete/complete-table.component.ts +190 -338
  130. package/src/lib/components/table/table-complete/complete-table.types.ts +28 -0
  131. package/src/lib/components/table/table-complete/complete-table.util.ts +236 -0
  132. package/src/lib/components/table/table-complete/index.ts +2 -0
  133. package/src/lib/components/table/table-crud-complete/complete-crud-table.animations.ts +34 -0
  134. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +87 -142
  135. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.scss +0 -63
  136. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +544 -831
  137. package/src/lib/components/table/table-crud-complete/complete-crud-table.types.ts +57 -0
  138. package/src/lib/components/table/table-crud-complete/complete-crud-table.util.ts +723 -0
  139. package/src/lib/components/table/table-crud-complete/index.ts +3 -0
  140. package/src/lib/components/theme-generator/theme-generator.component.css +21 -0
  141. package/src/lib/components/theme-generator/theme-generator.component.html +141 -116
  142. package/src/lib/components/theme-generator/theme-generator.component.ts +44 -24
  143. package/src/lib/components/toggle-radio/shared/toggle-options.types.ts +8 -0
  144. package/src/lib/components/toggle-radio/shared/toggle-options.util.ts +62 -0
  145. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.css +22 -0
  146. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.html +65 -0
  147. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.ts +192 -0
  148. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.types.ts +1 -0
  149. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.css +34 -0
  150. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.html +47 -0
  151. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.ts +187 -0
  152. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.types.ts +1 -0
  153. package/src/lib/components/tooltip/tooltip.directive.ts +12 -9
  154. package/src/lib/components/tooltip/tooltip.service.ts +331 -133
  155. package/src/lib/components/tooltip/tooltip.types.ts +9 -0
  156. package/src/lib/components/viewer/viewer-image/image-viewer.component.css +14 -4
  157. package/src/lib/components/viewer/viewer-image/image-viewer.component.html +61 -95
  158. package/src/lib/components/viewer/viewer-image/image-viewer.component.ts +182 -177
  159. package/src/lib/components/viewer/viewer-image/image-viewer.types.ts +3 -0
  160. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.css +25 -0
  161. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.html +95 -24
  162. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.ts +168 -15
  163. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.types.ts +1 -0
  164. package/src/styles.css +2 -2
  165. package/lib/services/static/icons.service.d.ts +0 -65
  166. package/src/lib/components/colors-config/README.md +0 -38
  167. package/src/lib/components/form/form-sidebar/sidebar-form.component.scss +0 -0
  168. package/src/lib/components/form/form-validation/validation-form.component.scss +0 -0
  169. package/src/lib/components/menu/menu-options-table/options-table-menu.component.scss +0 -0
  170. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.scss +0 -12
  171. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.scss +0 -0
  172. package/src/lib/components/toggle-radio/toggle-radio.component.html +0 -51
  173. package/src/lib/components/toggle-radio/toggle-radio.component.ts +0 -222
  174. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.scss +0 -0
  175. package/tailjng-0.1.6.tgz +0 -0
@@ -1,17 +1,18 @@
1
1
  import { Component, EventEmitter, Input, OnInit, Output, TemplateRef } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormsModule } from '@angular/forms';
4
- import { LucideAngularModule } from 'lucide-angular';
5
4
  import { Params } from '@angular/router';
6
5
  import { animate, state, style, transition, trigger } from '@angular/animations';
7
- import { EnableBoolean, FilterButton, FilterSelect, JAlertToastService, JConverterCrudService, JGenericCrudService, JIconsService, LoadingState, LoadingStates, OptionsTable, SortDirection, TableColumn } from 'tailjng';
6
+ import { EnableBoolean, FilterButton, FilterSelect, JAlertToastService, JConverterCrudService, JGenericCrudService, LoadingState, LoadingStates, OptionsTable, SortDirection, TableColumn } from 'tailjng';
8
7
  import { JCompletePaginatorComponent } from '../../paginator/paginator-complete/complete-paginator.component';
9
8
  import { JCompleteFilterComponent } from '../../filter/filter-complete/complete-filter.component';
9
+ import { Icons } from '../../.config/icons/icons.lucide';
10
+ import { JIconComponent } from '../../icon/icon.component';
10
11
 
11
12
  @Component({
12
13
  selector: 'JCompleteCard',
13
14
  standalone: true,
14
- imports: [CommonModule, FormsModule, JCompletePaginatorComponent, JCompleteFilterComponent, LucideAngularModule],
15
+ imports: [CommonModule, FormsModule, JCompletePaginatorComponent, JCompleteFilterComponent, JIconComponent],
15
16
  templateUrl: './complete-card.component.html',
16
17
  styleUrl: './complete-card.component.scss',
17
18
  animations: [
@@ -19,12 +20,10 @@ import { JCompleteFilterComponent } from '../../filter/filter-complete/complete-
19
20
  state('collapsed', style({
20
21
  height: '0',
21
22
  opacity: 0,
22
- overflow: 'hidden',
23
- })),
23
+ overflow: 'hidden'})),
24
24
  state('expanded', style({
25
25
  height: '*',
26
- opacity: 1,
27
- })),
26
+ opacity: 1})),
28
27
  transition('collapsed <=> expanded', [
29
28
  animate('0.3s ease-in-out')
30
29
  ])
@@ -32,6 +31,7 @@ import { JCompleteFilterComponent } from '../../filter/filter-complete/complete-
32
31
  ]
33
32
  })
34
33
  export class JCompleteCardComponent implements OnInit {
34
+ readonly Icons = Icons;
35
35
 
36
36
  Math = Math;
37
37
 
@@ -46,11 +46,11 @@ export class JCompleteCardComponent implements OnInit {
46
46
  sort: 'idle',
47
47
  aditionalButtons: {},
48
48
  checked: 'idle',
49
- action: 'idle',
50
- };
49
+ action: 'idle'};
51
50
 
52
51
  @Input() endpoint!: string;
53
52
  mainEndpoint!: string;
53
+ @Input() staticData: any[] = [];
54
54
  @Input() columns: TableColumn<any>[] = [];
55
55
  @Input() defaultFilters: { [key: string]: any } = {};
56
56
  @Input() isPaginator = true;
@@ -114,7 +114,6 @@ export class JCompleteCardComponent implements OnInit {
114
114
  titleChecked!: string;
115
115
 
116
116
  constructor(
117
- public readonly iconsService: JIconsService,
118
117
  private readonly genericService: JGenericCrudService,
119
118
  private readonly alertToastService: JAlertToastService,
120
119
  private readonly converterService: JConverterCrudService,
@@ -169,6 +168,20 @@ export class JCompleteCardComponent implements OnInit {
169
168
  // Emit search parameters
170
169
  this.loadedParams.emit(params);
171
170
 
171
+ if (this.staticData.length > 0) {
172
+ this.data = this.staticData.map(item => ({ ...item }));
173
+ this.totalItems = this.data.length;
174
+ this.updateDisplayData();
175
+ this.generatePagination();
176
+ this.setLoadingState(loadingType, 'success');
177
+ this.dataLoaded.emit();
178
+ if (loadingType === 'sort') {
179
+ this.sortingColumn = null;
180
+ }
181
+ onFinally?.();
182
+ return;
183
+ }
184
+
172
185
  // Simulating API wait
173
186
  // setTimeout(() => {
174
187
  this.genericService.findAll<any>({ endpoint: this.endpoint, params }).subscribe({
@@ -244,8 +257,7 @@ export class JCompleteCardComponent implements OnInit {
244
257
  this.alertToastService.AlertToast({
245
258
  type: "success",
246
259
  title: "Registro actualizado!",
247
- description: response.message,
248
- });
260
+ description: response.message});
249
261
  }
250
262
  })
251
263
  }
@@ -359,11 +371,9 @@ export class JCompleteCardComponent implements OnInit {
359
371
  limit: this.itemsPerPage,
360
372
  sort: {
361
373
  column: this.sortColumn,
362
- direction: this.sortDirection,
363
- },
374
+ direction: this.sortDirection},
364
375
  filters: this.filters,
365
- defaultFilters: this.defaultFilters,
366
- });
376
+ defaultFilters: this.defaultFilters});
367
377
 
368
378
  if (this.searchQuery && this.searchQuery.trim() !== '') {
369
379
  const baseSearchKeys = this.columns
@@ -46,7 +46,7 @@
46
46
  @if (isLoading('initialLoad') && displayData.length === 0) {
47
47
  <div class="w-full flex justify-center items-center h-100 bg-white dark:bg-foreground rounded-[20px] border border-border dark:border-dark-border">
48
48
  <div class="flex flex-col gap-3 items-center justify-center py-4">
49
- <lucide-icon [name]="iconsService.icons.loading" size="30" class="text-primary animate-spin"></lucide-icon>
49
+ <JIcon [icon]="Icons.Loader2" size="30" iconClass="text-primary animate-spin" [ariaHidden]="true" />
50
50
  <p>Cargando datos...</p>
51
51
  </div>
52
52
  </div>
@@ -86,7 +86,7 @@
86
86
 
87
87
  } @else if (!isLoading('pagination')) {
88
88
  <div class="j-crud-card w-full flex flex-col gap-3 justify-center items-center h-100 bg-white dark:bg-foreground rounded-[20px] border border-border dark:border-dark-border hover:border-primary/50 hover:dark:border-primary">
89
- <lucide-icon [name]="iconsService.icons.info" size="35" class="text-primary"></lucide-icon>
89
+ <JIcon [icon]="Icons.Info" size="35" iconClass="text-primary" [ariaHidden]="true" />
90
90
  <p class="text-black dark:text-white">No hay datos disponibles</p>
91
91
  </div>
92
92
  }
@@ -1,29 +1,28 @@
1
1
  import { Component, EventEmitter, Input, OnInit, Output, TemplateRef } from '@angular/core';
2
2
  import { CommonModule } from '@angular/common';
3
3
  import { FormsModule } from '@angular/forms';
4
- import { LucideAngularModule } from 'lucide-angular';
5
4
  import { Params } from '@angular/router';
6
5
  import { animate, state, style, transition, trigger } from '@angular/animations';
7
- import { EnableBoolean, FilterButton, FilterSelect, JAlertToastService, JConverterCrudService, JGenericCrudService, JIconsService, LoadingState, LoadingStates, OptionsTable, SortDirection, TableColumn } from 'tailjng';
6
+ import { EnableBoolean, FilterButton, FilterSelect, JAlertToastService, JConverterCrudService, JGenericCrudService, LoadingState, LoadingStates, OptionsTable, SortDirection, TableColumn } from 'tailjng';
8
7
  import { JCompletePaginatorComponent } from '../../paginator/paginator-complete/complete-paginator.component';
9
8
  import { JCompleteFilterComponent } from '../../filter/filter-complete/complete-filter.component';
9
+ import { Icons } from '../../.config/icons/icons.lucide';
10
+ import { JIconComponent } from '../../icon/icon.component';
10
11
 
11
12
  @Component({
12
13
  selector: 'JCompleteCrudCard',
13
14
  standalone: true,
14
- imports: [CommonModule, FormsModule, JCompletePaginatorComponent, JCompleteFilterComponent, LucideAngularModule],
15
+ imports: [CommonModule, FormsModule, JCompletePaginatorComponent, JCompleteFilterComponent, JIconComponent],
15
16
  templateUrl: './complete-crud-card.component.html',
16
17
  styleUrl: './complete-crud-card.component.scss',
17
18
  animations: [
18
19
  trigger('slideToggle', [
19
20
  state('collapsed', style({
20
21
  height: '0',
21
- opacity: 0,
22
- })),
22
+ opacity: 0})),
23
23
  state('expanded', style({
24
24
  height: '*',
25
- opacity: 1,
26
- })),
25
+ opacity: 1})),
27
26
  transition('collapsed <=> expanded', [
28
27
  animate('0.3s ease-in-out')
29
28
  ])
@@ -31,6 +30,7 @@ import { JCompleteFilterComponent } from '../../filter/filter-complete/complete-
31
30
  ]
32
31
  })
33
32
  export class JCompleteCrudCardComponent implements OnInit {
33
+ readonly Icons = Icons;
34
34
 
35
35
  Math = Math;
36
36
 
@@ -44,13 +44,13 @@ export class JCompleteCrudCardComponent implements OnInit {
44
44
  sort: 'idle',
45
45
  aditionalButtons: {},
46
46
  checked: 'idle',
47
- action: 'idle',
48
- };
47
+ action: 'idle'};
49
48
 
50
49
  @Input() endpoint!: string;
51
50
  // Clave alternativa de response.data cuando difiere del mainEndpoint (ej. reminders en reminder/mine)
52
51
  @Input() responseKey?: string;
53
52
  mainEndpoint!: string;
53
+ @Input() staticData: any[] = [];
54
54
  @Input() columns: TableColumn<any>[] = [];
55
55
  @Input() defaultFilters: { [key: string]: any } = {};
56
56
  @Input() isPaginator = true;
@@ -114,7 +114,6 @@ export class JCompleteCrudCardComponent implements OnInit {
114
114
  titleChecked!: string;
115
115
 
116
116
  constructor(
117
- public readonly iconsService: JIconsService,
118
117
  private readonly genericService: JGenericCrudService,
119
118
  private readonly alertToastService: JAlertToastService,
120
119
  private readonly converterService: JConverterCrudService,
@@ -175,6 +174,20 @@ export class JCompleteCrudCardComponent implements OnInit {
175
174
 
176
175
  const params = this.getQueryParams();
177
176
 
177
+ if (this.staticData.length > 0) {
178
+ this.data = this.staticData.map(item => ({ ...item }));
179
+ this.totalItems = this.data.length;
180
+ this.updateDisplayData();
181
+ this.generatePagination();
182
+ this.setLoadingState(loadingType, 'success');
183
+ this.dataLoaded.emit();
184
+ if (loadingType === 'sort') {
185
+ this.sortingColumn = null;
186
+ }
187
+ onFinally?.();
188
+ return;
189
+ }
190
+
178
191
  // Simulating API wait
179
192
  // setTimeout(() => {
180
193
  this.genericService.findAll<any>({ endpoint: this.endpoint, params }).subscribe({
@@ -250,8 +263,7 @@ export class JCompleteCrudCardComponent implements OnInit {
250
263
  this.alertToastService.AlertToast({
251
264
  type: "success",
252
265
  title: "Registro actualizado!",
253
- description: response.message,
254
- });
266
+ description: response.message});
255
267
  }
256
268
  })
257
269
  }
@@ -365,11 +377,9 @@ export class JCompleteCrudCardComponent implements OnInit {
365
377
  limit: this.itemsPerPage,
366
378
  sort: {
367
379
  column: this.sortColumn,
368
- direction: this.sortDirection,
369
- },
380
+ direction: this.sortDirection},
370
381
  filters: this.filters,
371
- defaultFilters: this.defaultFilters,
372
- });
382
+ defaultFilters: this.defaultFilters});
373
383
 
374
384
  if (this.searchQuery && this.searchQuery.trim() !== '') {
375
385
  const baseSearchKeys = this.columns
@@ -0,0 +1,30 @@
1
+ .j-checkbox-input:focus-visible + .j-checkbox-box {
2
+ outline: 2px solid var(--color-ring);
3
+ outline-offset: 2px;
4
+ }
5
+
6
+ .j-checkbox-box--checked {
7
+ border-color: var(--color-primary);
8
+ background-color: var(--color-primary);
9
+ color: var(--color-primary-foreground);
10
+ }
11
+
12
+ :host-context(.dark) .j-checkbox-box--checked,
13
+ :host-context(html.dark) .j-checkbox-box--checked {
14
+ border-color: var(--color-dark-primary);
15
+ background-color: var(--color-dark-primary);
16
+ color: var(--color-dark-primary-foreground);
17
+ }
18
+
19
+ .j-checkbox-box--disabled {
20
+ opacity: 0.5;
21
+ cursor: not-allowed;
22
+ }
23
+
24
+ .j-checkbox-title--disabled {
25
+ opacity: 0.45;
26
+ }
27
+
28
+ .j-checkbox-label:has(.j-checkbox-input:disabled) {
29
+ cursor: not-allowed;
30
+ }
@@ -1,52 +1,64 @@
1
- <div class="flex flex-col items-center justify-center" jTooltip="{{tooltip}}" [jTooltipPosition]="tooltipPosition">
2
-
3
- <label class="relative inline-flex items-center justify-center gap-2"
4
- [ngClass]="{
5
- 'flex-col': titlePosition === 'top' || titlePosition === 'bottom',
6
- 'flex-row align-center': titlePosition === 'left' || titlePosition === 'right'
7
- }"
1
+ <div
2
+ class="inline-flex flex-col items-center justify-center"
3
+ [jTooltip]="tooltip"
4
+ [jTooltipPosition]="tooltipPosition"
8
5
  >
9
- @if (title && (titlePosition === 'top' || titlePosition === 'left')) {
10
- <span [class]="classesTitle + ' text-[' + titleSize + '] opacity-80 user-none'"
11
- [ngClass]="{ 'opacity-50!': disabled }"
12
- >
13
- {{ title }}
14
- </span>
15
- }
6
+ <label class="j-checkbox-label inline-flex gap-2 cursor-pointer select-none" [ngClass]="layoutClasses">
7
+ @if (showTitleBefore) {
8
+ <span
9
+ [ngClass]="titleClasses"
10
+ class="text-xs leading-tight text-foreground/85 dark:text-dark-foreground"
11
+ [style.font-size]="titleSize"
12
+ >
13
+ {{ title }}
14
+ </span>
15
+ }
16
16
 
17
- <input
18
- type="checkbox"
19
- class="absolute opacity-0 cursor-pointer peer"
20
- [checked]="innerValue"
21
- (change)="onCheckboxChangeHandler($event)"
22
- [disabled]="disabled"
23
- >
24
-
25
- <span
26
- class="inline-flex items-center justify-center w-[25px] h-[25px] border rounded transition-all duration-200 ease-in-out relative"
27
- [class]="classes"
28
- [ngClass]="{
29
- 'bg-primary border-primary dark:bg-dark-primary dark:border-dark-primary': innerValue,
30
- 'bg-white border-primary dark:border-dark-border': !innerValue,
31
- 'opacity-50 cursor-not-allowed': disabled,
32
- 'cursor-pointer': !disabled
33
- }"
34
- >
35
- <lucide-icon
36
- [name]="icon"
37
- [size]="iconSize"
38
- class="text-white"
39
- [ngClass]="{'opacity-0': !innerValue, 'opacity-100': innerValue}"
40
- ></lucide-icon>
41
- </span>
17
+ <span class="relative inline-flex items-center justify-center" [class]="classes">
18
+ <input
19
+ type="checkbox"
20
+ class="j-checkbox-input absolute inset-0 z-[1] m-0 opacity-0 cursor-pointer disabled:cursor-not-allowed"
21
+ [checked]="checked"
22
+ [disabled]="isDisabled"
23
+ (change)="onCheckboxChangeHandler($event)"
24
+ />
42
25
 
43
- @if (title && (titlePosition === 'bottom' || titlePosition === 'right')) {
44
- <span [class]="classesTitle + ' text-[' + titleSize + '] opacity-80 select-none'"
45
- [ngClass]="{ 'opacity-50!': disabled }"
46
- >
47
- {{ title }}
48
- </span>
26
+ <span
27
+ [ngClass]="boxClasses"
28
+ class="inline-flex items-center justify-center w-[1.375rem] h-[1.375rem] border-[1.5px] border-border dark:border-dark-border rounded-md bg-background dark:bg-dark-background transition-[background-color,border-color,box-shadow] duration-150 ease-in-out"
29
+ aria-hidden="true"
30
+ >
31
+ @if (isLoading) {
32
+ <JIcon
33
+ [icon]="Icons.Loader2"
34
+ [size]="iconSize"
35
+ iconClass="animate-spin text-primary dark:text-dark-primary"
36
+ [ariaHidden]="true"
37
+ />
38
+ } @else {
39
+ <JIcon
40
+ [icon]="icon"
41
+ [size]="iconSize"
42
+ [inheritParentColor]="true"
43
+ [ngClasses]="{
44
+ 'opacity-0 scale-75': !checked,
45
+ 'opacity-100 scale-100': checked,
46
+ }"
47
+ iconClass="transition-all duration-150"
48
+ [ariaHidden]="true"
49
+ />
49
50
  }
50
- </label>
51
+ </span>
52
+ </span>
51
53
 
54
+ @if (showTitleAfter) {
55
+ <span
56
+ [ngClass]="titleClasses"
57
+ class="text-xs leading-tight text-foreground/85 dark:text-dark-foreground"
58
+ [style.font-size]="titleSize"
59
+ >
60
+ {{ title }}
61
+ </span>
62
+ }
63
+ </label>
52
64
  </div>
@@ -1,114 +1,185 @@
1
- import { Component, EventEmitter, forwardRef, Input, OnChanges, Output, SimpleChanges } 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, ControlValueAccessor } from '@angular/forms';
1
+ import { NgClass } from '@angular/common';
2
+ import {
3
+ Component,
4
+ EventEmitter,
5
+ Input,
6
+ OnChanges,
7
+ Output,
8
+ SimpleChanges,
9
+ forwardRef,
10
+ } from '@angular/core';
11
+ import {
12
+ ControlValueAccessor,
13
+ FormsModule,
14
+ NG_VALUE_ACCESSOR,
15
+ ReactiveFormsModule,
16
+ } from '@angular/forms';
17
+ import { LucideIconData } from 'lucide-angular';
18
+ import { Icons } from '../../.config/icons/icons.lucide';
19
+ import { JIconComponent } from '../../icon/icon.component';
6
20
  import { JTooltipDirective } from '../../tooltip/tooltip.directive';
21
+ import { CheckboxTitlePosition, CheckboxTooltipPosition } from './input-checkbox.types';
7
22
 
23
+ export type { CheckboxTitlePosition, CheckboxTooltipPosition } from './input-checkbox.types';
24
+
25
+ /**
26
+ * Checkbox with optional label, tooltip, and table-row integration via `item` / `column`.
27
+ *
28
+ * Install: `npx tailjng add checkbox-input`
29
+ */
8
30
  @Component({
9
31
  selector: 'JInputCheckbox',
10
- standalone: true,
11
- imports: [CommonModule, LucideAngularModule, FormsModule, ReactiveFormsModule, JTooltipDirective],
32
+ imports: [NgClass, FormsModule, ReactiveFormsModule, JTooltipDirective, JIconComponent],
12
33
  templateUrl: './input-checkbox.component.html',
13
- styleUrls: ['./input-checkbox.component.css'],
34
+ styleUrl: './input-checkbox.component.css',
14
35
  providers: [
15
36
  {
16
37
  provide: NG_VALUE_ACCESSOR,
17
38
  useExisting: forwardRef(() => JInputCheckboxComponent),
18
- multi: true
19
- }
20
- ]
39
+ multi: true,
40
+ },
41
+ ],
21
42
  })
22
43
  export class JInputCheckboxComponent implements OnChanges, ControlValueAccessor {
23
-
24
- @Input() title!: string;
25
- @Input() titlePosition: "top" | "right" | "bottom" | "left" = "top";
26
- @Input() titleSize: string = '8px';
27
- @Input() tooltip!: string;
28
- @Input() tooltipPosition: "top" | "right" | "bottom" | "left" = "top";
29
- @Input() icon: any;
30
- @Input() iconSize: number = 15;
31
- @Input() disabled?: boolean;
32
- @Input() isLoading?: boolean;
33
- @Input() classes: string = '';
34
- @Input() classesTitle: string = '';
44
+ readonly Icons = Icons;
45
+
46
+ @Input() title = '';
47
+ @Input() titlePosition: CheckboxTitlePosition = 'top';
48
+ @Input() titleSize = '0.75rem';
49
+ @Input() tooltip = '';
50
+ @Input() tooltipPosition: CheckboxTooltipPosition = 'top';
51
+ @Input() icon: LucideIconData = Icons.Check;
52
+ @Input() iconSize = 16;
53
+ @Input() disabled: boolean | undefined = false;
54
+ @Input() isLoading = false;
55
+ @Input() classes = '';
56
+ @Input() classesTitle = '';
35
57
  @Input() item: any;
36
58
  @Input() column: any;
37
59
 
38
60
  @Input() getValue: (item: any, column: any) => boolean = () => false;
39
- @Input() onCheckboxChange: (item: any, column: any, value: boolean) => void = () => { };
61
+ @Input() onCheckboxChange: (item: any, column: any, value?: boolean) => void = () => {};
40
62
 
41
- @Output() onCheckboxChangeOutput: EventEmitter<any> = new EventEmitter();
63
+ @Input() ngClasses: Record<string, boolean> = {};
42
64
 
43
- innerValue: boolean = false;
44
- onChange: any = () => { };
45
- onTouched: any = () => { };
65
+ @Output() onCheckboxChangeOutput = new EventEmitter<{
66
+ item: any;
67
+ column: any;
68
+ newValue: boolean;
69
+ }>();
46
70
 
47
- constructor(public readonly iconsService: JIconsService) {
48
- this.icon = this.iconsService.icons.check;
49
- }
71
+ innerValue = false;
50
72
 
51
- ngOnChanges(changes: SimpleChanges): void {
52
- if ((changes['item'] || changes['column']) && this.item && this.column) {
53
- this.innerValue = this.getValue(this.item, this.column);
54
- this.onChange(this.innerValue);
55
- }
56
- }
73
+ private onChange: (value: boolean) => void = () => {};
74
+ private onTouched: () => void = () => {};
57
75
 
76
+ /**
77
+ * Whether the checkbox is checked.
78
+ */
79
+ get checked(): boolean {
80
+ return this.innerValue;
81
+ }
58
82
 
59
83
  /**
60
- * writeValue - To write a value to the component
61
- * @param value
84
+ * Whether interaction is blocked.
62
85
  */
63
- writeValue(value: any): void {
64
- if (value !== undefined) {
65
- this.innerValue = !!value;
66
- } else if (this.item && this.column) {
67
- this.innerValue = this.getValue(this.item, this.column);
68
- }
86
+ get isDisabled(): boolean {
87
+ return this.disabled || this.isLoading;
69
88
  }
70
89
 
90
+ /**
91
+ * Layout direction for label + control.
92
+ */
93
+ get layoutClasses(): Record<string, boolean> {
94
+ const vertical = this.titlePosition === 'top' || this.titlePosition === 'bottom';
95
+ return {
96
+ 'flex-col': vertical,
97
+ 'flex-row': !vertical,
98
+ 'items-center': true,
99
+ };
100
+ }
71
101
 
72
102
  /**
73
- * registerOnChange - To register the change callback function
74
- * @param fn
103
+ * Whether the title renders before the control.
75
104
  */
76
- registerOnChange(fn: any): void {
77
- this.onChange = fn;
105
+ get showTitleBefore(): boolean {
106
+ return !!this.title && (this.titlePosition === 'top' || this.titlePosition === 'left');
78
107
  }
79
108
 
109
+ /**
110
+ * Whether the title renders after the control.
111
+ */
112
+ get showTitleAfter(): boolean {
113
+ return !!this.title && (this.titlePosition === 'bottom' || this.titlePosition === 'right');
114
+ }
80
115
 
116
+ /**
117
+ * Class map for the visible checkbox box.
118
+ */
119
+ get boxClasses(): Record<string, boolean> {
120
+ return {
121
+ 'j-checkbox-box': true,
122
+ 'j-checkbox-box--checked': this.checked,
123
+ 'j-checkbox-box--disabled': this.isDisabled,
124
+ ...this.ngClasses,
125
+ };
126
+ }
81
127
 
82
128
  /**
83
- * registerOnTouched - To register the touched callback function
84
- * @param fn
129
+ * Class map for the optional label text.
85
130
  */
86
- registerOnTouched(fn: any): void {
131
+ get titleClasses(): Record<string, boolean> {
132
+ return {
133
+ 'j-checkbox-title': true,
134
+ 'j-checkbox-title--disabled': this.isDisabled,
135
+ [this.classesTitle]: !!this.classesTitle,
136
+ };
137
+ }
138
+
139
+ ngOnChanges(changes: SimpleChanges): void {
140
+ if ((changes['item'] || changes['column']) && this.item && this.column) {
141
+ this.innerValue = this.getValue(this.item, this.column);
142
+ }
143
+ }
144
+
145
+ writeValue(value: unknown): void {
146
+ if (value !== undefined && value !== null) {
147
+ this.innerValue = !!value;
148
+ return;
149
+ }
150
+
151
+ if (this.item && this.column) {
152
+ this.innerValue = this.getValue(this.item, this.column);
153
+ }
154
+ }
155
+
156
+ registerOnChange(fn: (value: boolean) => void): void {
157
+ this.onChange = fn;
158
+ }
159
+
160
+ registerOnTouched(fn: () => void): void {
87
161
  this.onTouched = fn;
88
162
  }
89
163
 
164
+ setDisabledState(isDisabled: boolean): void {
165
+ this.disabled = isDisabled;
166
+ }
90
167
 
168
+ onCheckboxChangeHandler(event: Event): void {
169
+ if (this.isDisabled) {
170
+ return;
171
+ }
91
172
 
92
- /**
93
- * onCheckboxChangeHandler - To handle the checkbox change event
94
- * @param event
95
- */
96
- onCheckboxChangeHandler(event: Event) {
97
173
  const target = event.target as HTMLInputElement;
98
174
  const newValue = target.checked;
99
175
 
100
176
  this.innerValue = newValue;
101
-
102
- if (this.onCheckboxChange) {
103
- this.onCheckboxChange(this.item, this.column, newValue);
104
- }
105
-
177
+ this.onCheckboxChange(this.item, this.column, newValue);
106
178
  this.onCheckboxChangeOutput.emit({
107
179
  item: this.item,
108
180
  column: this.column,
109
- newValue: newValue
181
+ newValue,
110
182
  });
111
-
112
183
  this.onChange(newValue);
113
184
  this.onTouched();
114
185
  }
@@ -0,0 +1,3 @@
1
+ export type CheckboxTitlePosition = 'top' | 'right' | 'bottom' | 'left';
2
+
3
+ export type CheckboxTooltipPosition = 'top' | 'right' | 'bottom' | 'left';