tailjng 0.1.6 → 0.1.7

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 (176) hide show
  1. package/README.md +12 -4
  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 +43 -8
  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 +2 -2
  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 +38 -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 +244 -2
  26. package/src/lib/components/alert/alert-dialog/dialog-alert.component.html +25 -38
  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 +630 -12
  30. package/src/lib/components/alert/alert-toast/toast-alert.component.html +103 -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 +97 -0
  42. package/src/lib/components/checkbox/checkbox-input/input-checkbox.component.html +54 -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 +112 -0
  46. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.html +28 -25
  47. package/src/lib/components/checkbox/checkbox-switch/switch-checkbox.component.ts +67 -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 +4 -22
  50. package/src/lib/components/coach-mark/coach-mark.component.scss +1 -1
  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 +103 -1
  55. package/src/lib/components/dialog/dialog.component.html +46 -66
  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 +16 -19
  59. package/src/lib/components/filter/filter-complete/complete-filter.component.scss +35 -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 +276 -0
  69. package/src/lib/components/form/form-sidebar/sidebar-form.component.html +117 -125
  70. package/src/lib/components/form/form-sidebar/sidebar-form.component.ts +109 -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.html +19 -16
  79. package/src/lib/components/input/input/input.component.ts +130 -53
  80. package/src/lib/components/input/input/input.types.ts +8 -0
  81. package/src/lib/components/input/input-file/file-input.component.html +65 -56
  82. package/src/lib/components/input/input-file/file-input.component.ts +276 -173
  83. package/src/lib/components/input/input-file/file-input.types.ts +2 -0
  84. package/src/lib/components/input/input-range/range-input.component.css +67 -0
  85. package/src/lib/components/input/input-range/range-input.component.html +50 -58
  86. package/src/lib/components/input/input-range/range-input.component.ts +148 -60
  87. package/src/lib/components/input/input-range/range-input.types.ts +7 -0
  88. package/src/lib/components/input/input-textarea/textarea-input.component.html +16 -7
  89. package/src/lib/components/input/input-textarea/textarea-input.component.ts +140 -50
  90. package/src/lib/components/input/input-textarea/textarea-input.types.ts +2 -0
  91. package/src/lib/components/label/label.component.html +17 -16
  92. package/src/lib/components/label/label.component.ts +70 -16
  93. package/src/lib/components/label/label.types.ts +2 -0
  94. package/src/lib/components/menu/menu-options-table/menu-options-defaults.ts +34 -0
  95. package/src/lib/components/menu/menu-options-table/options-table-menu.component.html +34 -20
  96. package/src/lib/components/menu/menu-options-table/options-table-menu.component.ts +211 -58
  97. package/src/lib/components/menu/menu-options-table/options-table-menu.types.ts +38 -0
  98. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.html +49 -52
  99. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.ts +112 -24
  100. package/src/lib/components/menu/options-coach-menu/options-coach-menu.types.ts +9 -0
  101. package/src/lib/components/mode-toggle/mode-toggle.component.html +11 -16
  102. package/src/lib/components/mode-toggle/mode-toggle.component.ts +69 -33
  103. package/src/lib/components/paginator/paginator-complete/complete-paginator.component.html +4 -4
  104. package/src/lib/components/paginator/paginator-complete/complete-paginator.component.ts +31 -7
  105. package/src/lib/components/paginator/paginator-complete/complete-paginator.types.ts +12 -0
  106. package/src/lib/components/paginator/paginator-complete/complete-paginator.util.ts +36 -0
  107. package/src/lib/components/progress-bar/progress-bar.component.css +11 -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.css +6 -0
  112. package/src/lib/components/select/select-dropdown/dropdown-select.component.html +54 -44
  113. package/src/lib/components/select/select-dropdown/dropdown-select.component.ts +450 -509
  114. package/src/lib/components/select/select-dropdown/dropdown-select.types.ts +43 -0
  115. package/src/lib/components/select/select-dropdown/dropdown-select.util.ts +179 -0
  116. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.css +6 -0
  117. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.html +131 -42
  118. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.component.ts +491 -475
  119. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.types.ts +22 -0
  120. package/src/lib/components/select/select-multi-dropdown/multi-dropdown-select.util.ts +20 -0
  121. package/src/lib/components/select/select-multi-table/multi-table-select.component.css +10 -0
  122. package/src/lib/components/select/select-multi-table/multi-table-select.component.html +76 -60
  123. package/src/lib/components/select/select-multi-table/multi-table-select.component.ts +250 -313
  124. package/src/lib/components/select/select-multi-table/multi-table-select.types.ts +10 -0
  125. package/src/lib/components/select/select-multi-table/multi-table-select.util.ts +5 -0
  126. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.css +212 -0
  127. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.html +62 -53
  128. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.ts +84 -27
  129. package/src/lib/components/sidebar/sidebar-static/static-sidebar.types.ts +2 -0
  130. package/src/lib/components/table/table-complete/complete-table.component.html +15 -17
  131. package/src/lib/components/table/table-complete/complete-table.component.ts +190 -338
  132. package/src/lib/components/table/table-complete/complete-table.types.ts +28 -0
  133. package/src/lib/components/table/table-complete/complete-table.util.ts +236 -0
  134. package/src/lib/components/table/table-complete/index.ts +2 -0
  135. package/src/lib/components/table/table-crud-complete/complete-crud-table.animations.ts +34 -0
  136. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.html +73 -128
  137. package/src/lib/components/table/table-crud-complete/complete-crud-table.component.ts +542 -829
  138. package/src/lib/components/table/table-crud-complete/complete-crud-table.types.ts +57 -0
  139. package/src/lib/components/table/table-crud-complete/complete-crud-table.util.ts +723 -0
  140. package/src/lib/components/table/table-crud-complete/index.ts +3 -0
  141. package/src/lib/components/theme-generator/theme-generator.component.css +21 -0
  142. package/src/lib/components/theme-generator/theme-generator.component.html +146 -116
  143. package/src/lib/components/theme-generator/theme-generator.component.ts +44 -24
  144. package/src/lib/components/toggle-radio/shared/toggle-options.types.ts +8 -0
  145. package/src/lib/components/toggle-radio/shared/toggle-options.util.ts +44 -0
  146. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.css +135 -0
  147. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.html +52 -0
  148. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.component.ts +198 -0
  149. package/src/lib/components/toggle-radio/toggle-radio/toggle-radio.types.ts +1 -0
  150. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.css +108 -0
  151. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.html +37 -0
  152. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.component.ts +193 -0
  153. package/src/lib/components/toggle-radio/toggle-segment/segment-toggle.types.ts +1 -0
  154. package/src/lib/components/tooltip/tooltip.directive.ts +12 -9
  155. package/src/lib/components/tooltip/tooltip.service.ts +331 -133
  156. package/src/lib/components/tooltip/tooltip.types.ts +9 -0
  157. package/src/lib/components/viewer/viewer-image/image-viewer.component.css +90 -4
  158. package/src/lib/components/viewer/viewer-image/image-viewer.component.html +52 -103
  159. package/src/lib/components/viewer/viewer-image/image-viewer.component.ts +182 -177
  160. package/src/lib/components/viewer/viewer-image/image-viewer.types.ts +3 -0
  161. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.css +177 -0
  162. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.html +74 -24
  163. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.ts +168 -15
  164. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.types.ts +1 -0
  165. package/src/styles.css +2 -2
  166. package/lib/services/static/icons.service.d.ts +0 -65
  167. package/src/lib/components/colors-config/README.md +0 -38
  168. package/src/lib/components/form/form-sidebar/sidebar-form.component.scss +0 -0
  169. package/src/lib/components/form/form-validation/validation-form.component.scss +0 -0
  170. package/src/lib/components/menu/menu-options-table/options-table-menu.component.scss +0 -0
  171. package/src/lib/components/menu/options-coach-menu/options-coach-menu.component.scss +0 -12
  172. package/src/lib/components/sidebar/sidebar-static/static-sidebar.component.scss +0 -0
  173. package/src/lib/components/toggle-radio/toggle-radio.component.html +0 -51
  174. package/src/lib/components/toggle-radio/toggle-radio.component.ts +0 -222
  175. package/src/lib/components/viewer/viewer-pdf/pdf-viewer.component.scss +0 -0
  176. package/tailjng-0.1.6.tgz +0 -0
@@ -1,63 +1,93 @@
1
1
  import {
2
- Directive,
3
- ElementRef,
4
- Input,
5
- HostListener,
6
2
  ApplicationRef,
7
3
  ComponentRef,
8
- EnvironmentInjector,
9
4
  createComponent,
10
- TemplateRef
5
+ Directive,
6
+ ElementRef,
7
+ EnvironmentInjector,
8
+ HostListener,
9
+ Input,
10
+ OnDestroy,
11
+ TemplateRef,
11
12
  } from '@angular/core';
12
13
  import { JCoachMarkComponent } from './coach-mark.component';
13
-
14
- // Define CoachPosition localmente para coincidir con los valores de posición permitidos
15
- type CoachPosition =
16
- | 'top'
17
- | 'bottom'
18
- | 'left'
19
- | 'right'
20
- | 'top-left'
21
- | 'top-right'
22
- | 'bottom-left'
23
- | 'bottom-right';
24
-
14
+ import { CoachPosition, CoachTrigger } from './coach-mark.types';
15
+
16
+ export type { CoachPosition, CoachTrigger } from './coach-mark.types';
17
+
18
+ /**
19
+ * Contextual coach mark directive on the host element.
20
+ *
21
+ * Usage:
22
+ * ```html
23
+ * <JButton
24
+ * jCoachMark
25
+ * coachTitle="First step"
26
+ * coachDescription="Click here to get started"
27
+ * coachPosition="bottom"
28
+ * />
29
+ * ```
30
+ */
25
31
  @Directive({
26
- selector: '[jCoachMark]'
32
+ selector: '[jCoachMark]',
27
33
  })
28
- export class JCoachMarkDirective {
29
- @Input() coachTitle: string = '';
30
- @Input() coachDescription: string = '';
31
- @Input() coachContent: any;
34
+ export class JCoachMarkDirective implements OnDestroy {
35
+ // Card title text
36
+ @Input() coachTitle = '';
37
+
38
+ // Card description text
39
+ @Input() coachDescription = '';
40
+
41
+ // Alternate template (takes priority over title + description)
42
+ @Input() coachContent?: TemplateRef<unknown>;
43
+
44
+ // Alias for coachContent
32
45
  @Input() contentTemplate?: TemplateRef<unknown>;
33
46
 
34
- @Input() coachTrigger: 'click' | 'hover' = 'click'; // 'click' o 'hover'
35
- @Input() coachPosition: CoachPosition = 'bottom'; // Posición del coach
36
- @Input() coachSpotlight: boolean = true;
37
- @Input() coachDisabled: boolean = false;
47
+ // click = toggle on host click; hover = open on mouse enter
48
+ @Input() coachTrigger: CoachTrigger = 'click';
49
+
50
+ // Card position relative to the host
51
+ @Input() coachPosition: CoachPosition = 'bottom';
52
+
53
+ // true = spotlight cutout over the host
54
+ @Input() coachSpotlight = true;
55
+
56
+ // true = do not open the overlay
57
+ @Input() coachDisabled = false;
38
58
 
39
- @Input() coachWidth: string = '300px';
40
- @Input() coachMaxWidth: string = '340px';
59
+ @Input() coachWidth = '300px';
60
+ @Input() coachMaxWidth = '340px';
41
61
  @Input() coachHeight: string | null = null;
42
62
  @Input() coachMaxHeight: string | null = null;
43
- @Input() coachRadius: string = '12px';
44
- @Input() coachOffset: number = 12; // Desplazamiento para la posición
45
63
 
46
- @Input() isDescriptionFormatted: boolean = false;
64
+ // Spotlight border-radius
65
+ @Input() coachRadius = '12px';
66
+
67
+ // Gap in px between host and card
68
+ @Input() coachOffset = 12;
69
+
70
+ // true = preserve line breaks in description (<pre>)
71
+ @Input() isDescriptionFormatted = false;
47
72
 
48
73
  private overlayRef: ComponentRef<JCoachMarkComponent> | null = null;
49
74
  private isOpen = false;
50
75
 
51
76
  constructor(
52
- private elementRef: ElementRef<HTMLElement>,
53
- private appRef: ApplicationRef,
54
- private injector: EnvironmentInjector
55
- ) { }
56
-
57
- // Agregamos un HostListener para capturar el evento click y abrir el CoachMark
77
+ private readonly elementRef: ElementRef<HTMLElement>,
78
+ private readonly appRef: ApplicationRef,
79
+ private readonly injector: EnvironmentInjector,
80
+ ) {}
81
+
82
+ /**
83
+ * Toggles the overlay when `coachTrigger` is `click`.
84
+ * @param event Host click event.
85
+ */
58
86
  @HostListener('click', ['$event'])
59
87
  onClick(event: MouseEvent) {
60
- if (this.coachTrigger !== 'click') return;
88
+ if (this.coachTrigger !== 'click') {
89
+ return;
90
+ }
61
91
 
62
92
  event.stopPropagation();
63
93
  this.isOpen ? this.close() : this.open();
@@ -67,24 +97,34 @@ export class JCoachMarkDirective {
67
97
  });
68
98
  }
69
99
 
100
+ /** Opens the overlay on mouse enter when `coachTrigger` is `hover`. */
70
101
  @HostListener('mouseenter')
71
102
  onMouseEnter() {
72
- if (this.coachTrigger === 'hover') this.open();
103
+ if (this.coachTrigger === 'hover') {
104
+ this.open();
105
+ }
73
106
  }
74
107
 
108
+ /** Closes the overlay on mouse leave when `coachTrigger` is `hover`. */
75
109
  @HostListener('mouseleave')
76
110
  onMouseLeave() {
77
- if (this.coachTrigger === 'hover') this.close();
111
+ if (this.coachTrigger === 'hover') {
112
+ this.close();
113
+ }
78
114
  }
79
115
 
116
+ /**
117
+ * Closes when clicking outside the host, card, or an open alert dialog.
118
+ * @param event Document click event.
119
+ */
80
120
  private documentClickHandler = (event: MouseEvent) => {
81
121
  const host = this.elementRef.nativeElement;
82
122
  const cardElement = this.overlayRef?.location.nativeElement.querySelector(
83
- '.j-coach-card'
123
+ '.j-coach-card',
84
124
  ) as HTMLElement | null;
85
125
 
86
126
  const alertDialogElement = document.querySelector(
87
- '.j-alert-dialog'
127
+ '.j-alert-dialog',
88
128
  ) as HTMLElement | null;
89
129
 
90
130
  const target = event.target as Node;
@@ -98,30 +138,32 @@ export class JCoachMarkDirective {
98
138
  }
99
139
  };
100
140
 
141
+ /**
142
+ * Creates and attaches the overlay to `document.body`.
143
+ */
101
144
  private open() {
102
- if (this.coachDisabled) return;
103
- if (this.overlayRef) return;
145
+ if (this.coachDisabled || this.overlayRef) {
146
+ return;
147
+ }
104
148
 
105
- // Crear el componente overlay de forma dinámica
106
149
  this.overlayRef = createComponent(JCoachMarkComponent, {
107
- environmentInjector: this.injector
150
+ environmentInjector: this.injector,
108
151
  });
109
152
 
110
- this.overlayRef.instance.title = this.coachTitle;
111
- this.overlayRef.instance.description = this.coachDescription;
112
- this.overlayRef.instance.contentTemplate = this.coachContent || this.contentTemplate;
113
-
114
- this.overlayRef.instance.spotlight = this.coachSpotlight;
115
- this.overlayRef.instance.position = this.coachPosition;
116
- this.overlayRef.instance.isDescriptionFormatted = this.isDescriptionFormatted;
117
- this.overlayRef.instance.width = this.coachWidth;
118
- this.overlayRef.instance.maxWidth = this.coachMaxWidth;
119
- this.overlayRef.instance.height = this.coachHeight;
120
- this.overlayRef.instance.maxHeight = this.coachMaxHeight;
121
- this.overlayRef.instance.targetRadius = this.coachRadius;
153
+ const instance = this.overlayRef.instance;
154
+ instance.title = this.coachTitle;
155
+ instance.description = this.coachDescription;
156
+ instance.contentTemplate = this.coachContent ?? this.contentTemplate;
157
+ instance.spotlight = this.coachSpotlight;
158
+ instance.position = this.coachPosition;
159
+ instance.isDescriptionFormatted = this.isDescriptionFormatted;
160
+ instance.width = this.coachWidth;
161
+ instance.maxWidth = this.coachMaxWidth;
162
+ instance.height = this.coachHeight;
163
+ instance.maxHeight = this.coachMaxHeight;
164
+ instance.targetRadius = this.coachRadius;
122
165
 
123
166
  this.appRef.attachView(this.overlayRef.hostView);
124
-
125
167
  document.body.appendChild(this.overlayRef.location.nativeElement);
126
168
 
127
169
  this.isOpen = true;
@@ -132,28 +174,34 @@ export class JCoachMarkDirective {
132
174
  window.addEventListener('resize', this.resizeHandler);
133
175
  }
134
176
 
177
+ /**
178
+ * Recalculates spotlight and card position from the host rect.
179
+ */
135
180
  private updatePosition() {
136
- if (!this.overlayRef) return;
181
+ if (!this.overlayRef) {
182
+ return;
183
+ }
137
184
 
138
185
  const host = this.elementRef.nativeElement;
139
- const rect = host.getBoundingClientRect(); // Obtener las coordenadas del elemento
186
+ const rect = host.getBoundingClientRect();
187
+
188
+ const cardElement = this.overlayRef.location.nativeElement.querySelector(
189
+ '.j-coach-card',
190
+ ) as HTMLElement | null;
140
191
 
141
- const cardElement = this.overlayRef.location.nativeElement.querySelector('.j-coach-card') as HTMLElement;
142
- if (!cardElement) return;
192
+ if (!cardElement) {
193
+ return;
194
+ }
143
195
 
144
196
  const cardRect = cardElement.getBoundingClientRect();
145
197
 
146
198
  let cardTop = 0;
147
199
  let cardLeft = 0;
148
200
 
149
- // Cálculo de la posición
150
201
  const alignCenterX = rect.left + rect.width / 2 - cardRect.width / 2;
151
202
  const alignLeft = rect.left;
152
203
  const alignRight = rect.right - cardRect.width;
153
-
154
204
  const alignCenterY = rect.top + rect.height / 2 - cardRect.height / 2;
155
- const alignTop = rect.top;
156
- const alignBottom = rect.bottom - cardRect.height;
157
205
 
158
206
  switch (this.coachPosition) {
159
207
  case 'top':
@@ -203,17 +251,20 @@ export class JCoachMarkDirective {
203
251
  cardTop = window.innerHeight - cardRect.height - margin;
204
252
  }
205
253
 
206
- this.overlayRef.instance.targetTop = rect.top;
207
- this.overlayRef.instance.targetLeft = rect.left;
208
- this.overlayRef.instance.targetWidth = rect.width;
209
- this.overlayRef.instance.targetHeight = rect.height;
210
-
211
- this.overlayRef.instance.cardTop = cardTop;
212
- this.overlayRef.instance.cardLeft = cardLeft;
254
+ const instance = this.overlayRef.instance;
255
+ instance.targetTop = rect.top;
256
+ instance.targetLeft = rect.left;
257
+ instance.targetWidth = rect.width;
258
+ instance.targetHeight = rect.height;
259
+ instance.cardTop = cardTop;
260
+ instance.cardLeft = cardLeft;
213
261
 
214
262
  this.overlayRef.changeDetectorRef.detectChanges();
215
263
  }
216
264
 
265
+ /**
266
+ * Destroys the overlay and removes global listeners.
267
+ */
217
268
  private close() {
218
269
  this.isOpen = false;
219
270
 
@@ -221,23 +272,27 @@ export class JCoachMarkDirective {
221
272
  window.removeEventListener('scroll', this.scrollHandler, true);
222
273
  window.removeEventListener('resize', this.resizeHandler);
223
274
 
224
- if (!this.overlayRef) return;
275
+ if (!this.overlayRef) {
276
+ return;
277
+ }
225
278
 
226
279
  this.appRef.detachView(this.overlayRef.hostView);
227
280
  this.overlayRef.destroy();
228
281
  this.overlayRef = null;
229
282
  }
230
283
 
231
- // Scroll y resize handlers
284
+ /** Repositions on scroll (capture phase). */
232
285
  private scrollHandler = () => {
233
286
  this.updatePosition();
234
287
  };
235
288
 
289
+ /** Repositions on window resize. */
236
290
  private resizeHandler = () => {
237
291
  this.updatePosition();
238
292
  };
239
293
 
294
+ /** Closes the overlay when the host is destroyed. */
240
295
  ngOnDestroy() {
241
296
  this.close();
242
297
  }
243
- }
298
+ }
@@ -0,0 +1,12 @@
1
+ /** Positions supported by {@link JCoachMarkDirective} and {@link JCoachMarkComponent}. */
2
+ export type CoachPosition =
3
+ | 'top'
4
+ | 'top-left'
5
+ | 'top-right'
6
+ | 'bottom'
7
+ | 'bottom-left'
8
+ | 'bottom-right'
9
+ | 'left'
10
+ | 'right';
11
+
12
+ export type CoachTrigger = 'click' | 'hover';
@@ -5,4 +5,106 @@
5
5
  max-height: 100vh;
6
6
  margin: 0 !important;
7
7
  border-radius: 0;
8
- }
8
+ }
9
+
10
+ .jdialog-header {
11
+ display: flex;
12
+ align-items: center;
13
+ gap: 0.75rem;
14
+ min-height: 3.25rem;
15
+ padding: 0.625rem 0.75rem 0.625rem 1rem;
16
+ border-bottom: 1px solid var(--color-border);
17
+ background: linear-gradient(
18
+ 180deg,
19
+ color-mix(in srgb, var(--color-muted) 28%, var(--color-background)) 0%,
20
+ var(--color-background) 100%
21
+ );
22
+ user-select: none;
23
+ }
24
+
25
+ :host-context(.dark) .jdialog-header,
26
+ :host-context(html.dark) .jdialog-header {
27
+ border-bottom-color: var(--color-dark-border);
28
+ background: linear-gradient(
29
+ 180deg,
30
+ color-mix(in srgb, var(--color-dark-muted) 35%, var(--color-dark-background)) 0%,
31
+ var(--color-dark-background) 100%
32
+ );
33
+ }
34
+
35
+ .jdialog-header--draggable {
36
+ cursor: move;
37
+ }
38
+
39
+ .jdialog-title {
40
+ flex: 1;
41
+ min-width: 0;
42
+ margin: 0;
43
+ font-size: 0.9375rem;
44
+ font-weight: 600;
45
+ line-height: 1.3;
46
+ letter-spacing: -0.015em;
47
+ color: var(--color-foreground);
48
+ }
49
+
50
+ :host-context(.dark) .jdialog-title,
51
+ :host-context(html.dark) .jdialog-title {
52
+ color: var(--color-dark-foreground);
53
+ }
54
+
55
+ .jdialog-close {
56
+ display: inline-flex;
57
+ align-items: center;
58
+ justify-content: center;
59
+ width: 2rem;
60
+ height: 2rem;
61
+ flex: 0 0 2rem;
62
+ margin: 0;
63
+ padding: 0;
64
+ border: 0;
65
+ border-radius: 0.375rem;
66
+ background-color: transparent;
67
+ color: var(--color-muted-foreground);
68
+ line-height: 0;
69
+ cursor: pointer;
70
+ transition:
71
+ color 0.15s ease,
72
+ background-color 0.15s ease,
73
+ transform 0.15s ease;
74
+ }
75
+
76
+ .jdialog-close:hover {
77
+ color: var(--color-foreground);
78
+ background-color: color-mix(in srgb, var(--color-muted) 55%, transparent);
79
+ }
80
+
81
+ .jdialog-close:active {
82
+ transform: scale(0.94);
83
+ }
84
+
85
+ .jdialog-close:focus-visible {
86
+ outline: 2px solid var(--color-ring);
87
+ outline-offset: 2px;
88
+ }
89
+
90
+ :host-context(.dark) .jdialog-close,
91
+ :host-context(html.dark) .jdialog-close {
92
+ color: var(--color-dark-muted-foreground);
93
+ }
94
+
95
+ :host-context(.dark) .jdialog-close:hover,
96
+ :host-context(html.dark) .jdialog-close:hover {
97
+ color: var(--color-dark-foreground);
98
+ background-color: color-mix(in srgb, var(--color-dark-muted) 50%, transparent);
99
+ }
100
+
101
+ .jdialog-close JIcon,
102
+ .jdialog-close svg {
103
+ display: block;
104
+ width: 1.125rem;
105
+ height: 1.125rem;
106
+ }
107
+
108
+ .jdialog-content {
109
+ padding: 1rem;
110
+ }
@@ -1,73 +1,53 @@
1
1
  @if (openModal) {
2
+ @if (overlay) {
3
+ <div class="fixed inset-0 z-[999] bg-black/50 backdrop-blur-[1px]" aria-hidden="true"></div>
4
+ }
2
5
 
3
- <!-- Overlay -->
4
- @if (overlay) {
5
- <div class="fixed inset-0 z-[999] bg-black/50"></div>
6
- }
7
-
8
- <!-- Modal -->
9
- <div class="fixed inset-0 z-[1000] flex pointer-events-none" [ngClass]="getPositionClass()">
10
-
11
- <div @modalTransition
12
- class="pointer-events-auto bg-white dark:bg-foreground rounded-[12px] shadow-lg border-2 border-border dark:border-dark-border"
13
- [ngStyle]="getOffsetStyles()"
14
- [style.width]="getModalWidth()"
15
- [style.min-width]="!isFullScreen() ? '200px' : null"
16
- [style.min-height]="!isFullScreen() ? '40px' : null"
17
- data-draggable-dialog
6
+ <div
7
+ class="fixed inset-0 z-[1000] flex pointer-events-none"
8
+ [ngClass]="positionClass"
9
+ role="dialog"
10
+ [attr.aria-modal]="true"
11
+ [attr.aria-label]="title"
12
+ >
13
+ <div
14
+ @modalTransition
15
+ data-draggable-dialog
16
+ class="jdialog-panel"
17
+ [ngClass]="panelClasses"
18
+ [ngStyle]="offsetStyles"
19
+ [style.width]="modalWidth"
20
+ [style.min-width]="!isFullScreen ? '200px' : null"
21
+ [style.min-height]="!isFullScreen ? '40px' : null"
18
22
  >
19
- <!-- Header draggable -->
20
- @if (draggable) {
21
- <div
22
- class="flex items-center p-1 pl-4 pr-4 gap-2 bg-primary dark:bg-dark-primary border-b border-border dark:border-dark-border rounded-[10px] font-semibold text-2sm cursor-move select-none"
23
- (mousedown)="$event.stopPropagation(); startDrag($event)"
24
- >
25
- <h3
26
- class="flex-1 min-w-0 text-[1em] font-semibold text-white leading-none truncate"
27
- >
28
- {{ title }}
29
- </h3>
30
-
31
- <button
32
- type="button"
33
- (click)="$event.stopPropagation(); onClose()"
34
- class="flex-shrink-0 p-2 rounded-full border border-border dark:border-dark-border text-white hover:bg-dark-background focus:outline-none cursor-pointer"
35
- >
36
- <lucide-icon [name]="iconsService.icons.close" size="16"></lucide-icon>
37
- </button>
38
- </div>
39
- }
40
-
41
-
42
- <!-- Header normal -->
43
- @if (!draggable) {
44
- <div class="flex p-1 pl-4 pr-4 justify-between items-center bg-primary dark:bg-dark-primary border-b border-border dark:border-dark-border rounded-[10px] font-semibold text-2sm cursor-normal select-none">
45
- <h3 class="text-[1em] font-semibold text-white leading-none">{{ title }}</h3>
46
- <button
47
- type="button"
48
- (click)="onClose()"
49
- class="p-2 rounded-full border border-border dark:border-dark-border text-white hover:bg-dark-background focus:outline-none cursor-pointer"
50
- >
51
- <lucide-icon [name]="iconsService.icons.close" size="16"></lucide-icon>
52
- </button>
53
- </div>
54
- }
55
-
56
- <!-- Content -->
57
- <div class="m-2"
58
- [ngClass]="{ 'jdialog-full': isFullScreen() }"
59
- [ngStyle]="{
60
- height: getModalHeight()
61
- }"
23
+ <div
24
+ class="jdialog-header"
25
+ [class.jdialog-header--draggable]="draggable"
26
+ (mousedown)="draggable && startDrag($event)"
27
+ >
28
+ <h3 class="jdialog-title">
29
+ {{ title }}
30
+ </h3>
31
+
32
+ <button
33
+ type="button"
34
+ class="jdialog-close"
35
+ (click)="$event.stopPropagation(); onClose()"
36
+ aria-label="Cerrar"
62
37
  >
63
- @if (dialogTemplate) {
64
- <ng-container [ngTemplateOutlet]="dialogTemplate"></ng-container>
65
- }
66
- </div>
67
-
68
-
38
+ <JIcon [icon]="Icons.X" [size]="18" [inheritParentColor]="true" [ariaHidden]="true" />
39
+ </button>
69
40
  </div>
70
41
 
42
+ <div
43
+ class="jdialog-content"
44
+ [ngClass]="contentClasses"
45
+ [ngStyle]="{ height: modalHeight }"
46
+ >
47
+ @if (dialogTemplate) {
48
+ <ng-container [ngTemplateOutlet]="dialogTemplate" />
49
+ }
50
+ </div>
71
51
  </div>
72
-
73
- }
52
+ </div>
53
+ }