tailjng 0.1.5 → 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 -3
  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.5.tgz +0 -0
@@ -1,28 +1,78 @@
1
- <div class="flex-1 flex flex-col items-center justify-center">
2
- <object
3
- [data]="safeUrl"
4
- type="application/pdf"
5
- class="w-full h-full min-h-[300px] md:h-[75vh] overflow-auto"
6
- >
7
- <div class="p-6 flex flex-col items-center justify-center text-center gap-3">
8
- <!-- Icono -->
9
- <lucide-icon [name]="iconsService.icons.circleAlert" size="35" class="text-primary"></lucide-icon>
1
+ <div class="j-pdf-viewer" [ngClass]="ngClasses">
2
+ @if (!hasUrl) {
3
+ <div class="j-pdf-viewer__empty">
4
+ <JIcon
5
+ [icon]="Icons.CircleAlert"
6
+ [size]="32"
7
+ iconClass="text-muted-foreground"
8
+ [ariaHidden]="true"
9
+ />
10
+ <p class="j-pdf-viewer__message">{{ emptyMessage }}</p>
11
+ </div>
12
+ } @else if (showDesktopEmbed) {
13
+ <iframe
14
+ class="j-pdf-viewer__frame"
15
+ [src]="safeUrl"
16
+ [title]="documentTitle"
17
+ loading="lazy"
18
+ ></iframe>
19
+ } @else if (useMobileLayout) {
20
+ <div class="j-pdf-viewer__mobile">
21
+ @if (showMobileActions) {
22
+ <div class="j-pdf-viewer__mobile-card">
23
+ <JIcon
24
+ [icon]="Icons.FileUp"
25
+ [size]="36"
26
+ iconClass="text-primary dark:text-dark-primary"
27
+ [ariaHidden]="true"
28
+ />
29
+ <div class="j-pdf-viewer__mobile-copy">
30
+ <h3 class="j-pdf-viewer__mobile-title">{{ documentTitle }}</h3>
31
+ <p class="j-pdf-viewer__mobile-text">
32
+ En móvil, abre el PDF en el visor del sistema para navegar y hacer zoom con
33
+ mejor experiencia.
34
+ </p>
35
+ </div>
36
+ <div class="j-pdf-viewer__actions j-pdf-viewer__actions--stacked">
37
+ <JButton
38
+ [text]="'Abrir PDF'"
39
+ [icon]="Icons.Eye"
40
+ (clicked)="openInBrowser()"
41
+ />
42
+ <JButton
43
+ [text]="'Descargar'"
44
+ [icon]="Icons.Download"
45
+ classes="secondary"
46
+ (clicked)="downloadPdf()"
47
+ />
48
+ </div>
49
+ </div>
50
+ }
10
51
 
11
- <!-- Texto -->
12
- <div class="space-y-1">
13
- <h3 class="text-sm font-semibold text-slate-800 dark:text-slate-100">
14
- No se pudo mostrar el PDF
15
- </h3>
16
- <p class="text-xs text-slate-500 dark:text-slate-400 max-w-xs">
17
- Tu navegador no es compatible con la visualización embebida de este documento.
18
- Puedes descargarlo y verlo en tu visor de PDF preferido.
19
- </p>
20
- </div>
52
+ @if (showMobileEmbed) {
53
+ <iframe
54
+ class="j-pdf-viewer__frame j-pdf-viewer__frame--mobile"
55
+ [src]="safeUrl"
56
+ [title]="documentTitle"
57
+ loading="lazy"
58
+ ></iframe>
21
59
 
22
- <!-- Botón -->
23
- <a [href]="safeUrl" target="_blank" class="inline-flex items-center justify-center px-4 py-2 rounded-full text-xs font-medium bg-blue-600 text-white hover:bg-blue-700 dark:bg-blue-500 dark:hover:bg-blue-600 transition-colors">
24
- Descargar archivo
25
- </a>
60
+ <div class="j-pdf-viewer__mobile-bar">
61
+ <JButton
62
+ [text]="'Abrir'"
63
+ [icon]="Icons.Eye"
64
+ size="sm"
65
+ (clicked)="openInBrowser()"
66
+ />
67
+ <JButton
68
+ [text]="'Descargar'"
69
+ [icon]="Icons.Download"
70
+ size="sm"
71
+ classes="secondary"
72
+ (clicked)="downloadPdf()"
73
+ />
74
+ </div>
75
+ }
26
76
  </div>
27
- </object>
77
+ }
28
78
  </div>
@@ -1,31 +1,184 @@
1
- import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
1
+ import { NgClass } from '@angular/common';
2
+ import {
3
+ Component,
4
+ HostListener,
5
+ Input,
6
+ OnChanges,
7
+ OnInit,
8
+ SimpleChanges,
9
+ } from '@angular/core';
2
10
  import { DomSanitizer, SafeResourceUrl } from '@angular/platform-browser';
3
- import { CircleAlert, LucideAngularModule } from 'lucide-angular';
4
- import { JIconsService } from 'tailjng';
11
+ import { Icons } from '../../.config/icons/icons.lucide';
12
+ import { JButtonComponent } from '../../button/button.component';
13
+ import { JIconComponent } from '../../icon/icon.component';
14
+ import { PdfViewerMobileMode } from './pdf-viewer.types';
5
15
 
16
+ export type { PdfViewerMobileMode } from './pdf-viewer.types';
17
+
18
+ /**
19
+ * PDF viewer with desktop embed and a mobile-friendly open/download experience.
20
+ *
21
+ * Install: `npx tailjng add viewer-pdf`
22
+ */
6
23
  @Component({
7
24
  selector: 'JPdfViewer',
8
- standalone: true,
9
- imports: [LucideAngularModule],
25
+ imports: [NgClass, JButtonComponent, JIconComponent],
10
26
  templateUrl: './pdf-viewer.component.html',
11
- styleUrls: ['./pdf-viewer.component.scss']
27
+ styleUrl: './pdf-viewer.component.css',
12
28
  })
13
- export class JPdfViewerComponent implements OnChanges {
29
+ export class JPdfViewerComponent implements OnInit, OnChanges {
30
+ readonly Icons = Icons;
14
31
 
15
- // URLs normales (strings) para usarlas en <a href="">
16
- @Input() url = 'http://example/example.pdf';
32
+ @Input() url = '';
33
+ @Input() title = '';
34
+ @Input() emptyMessage = 'No hay un PDF para mostrar';
35
+ @Input() mobileMode: PdfViewerMobileMode = 'auto';
36
+ /** When true on mobile (non-iOS), tries an iframe embed before falling back to actions only. */
37
+ @Input() mobileEmbed = true;
38
+ @Input() ngClasses: Record<string, boolean> = {};
17
39
 
18
- // URLs “seguras” para <object>
19
40
  safeUrl: SafeResourceUrl | null = null;
41
+ isMobileViewport = false;
42
+
43
+ constructor(private readonly sanitizer: DomSanitizer) {}
44
+
45
+ /**
46
+ * Whether the mobile layout should be used.
47
+ */
48
+ get useMobileLayout(): boolean {
49
+ if (this.mobileMode === 'embed') {
50
+ return false;
51
+ }
52
+
53
+ if (this.mobileMode === 'actions') {
54
+ return true;
55
+ }
56
+
57
+ return this.isMobileViewport;
58
+ }
59
+
60
+ /**
61
+ * iOS does not reliably render PDFs inside iframe/object.
62
+ */
63
+ get isIOS(): boolean {
64
+ if (typeof navigator === 'undefined') {
65
+ return false;
66
+ }
67
+
68
+ return (
69
+ /iPad|iPhone|iPod/.test(navigator.userAgent) ||
70
+ (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1)
71
+ );
72
+ }
73
+
74
+ /**
75
+ * Whether to render the iframe on mobile (typically Android).
76
+ */
77
+ get showMobileEmbed(): boolean {
78
+ return this.useMobileLayout && this.mobileEmbed && !this.isIOS && !!this.safeUrl;
79
+ }
80
+
81
+ /**
82
+ * Whether to show the mobile action card (open / download).
83
+ */
84
+ get showMobileActions(): boolean {
85
+ return this.useMobileLayout && (!this.showMobileEmbed || this.isIOS);
86
+ }
87
+
88
+ /**
89
+ * Whether desktop embed mode is active.
90
+ */
91
+ get showDesktopEmbed(): boolean {
92
+ return !this.useMobileLayout && !!this.safeUrl;
93
+ }
94
+
95
+ /**
96
+ * Display name derived from the URL or `title` input.
97
+ */
98
+ get documentTitle(): string {
99
+ if (this.title.trim()) {
100
+ return this.title.trim();
101
+ }
102
+
103
+ if (!this.url) {
104
+ return 'Documento PDF';
105
+ }
106
+
107
+ try {
108
+ const path = new URL(this.url, window.location.origin).pathname;
109
+ const fileName = path.split('/').pop();
110
+ return fileName ? decodeURIComponent(fileName) : 'Documento PDF';
111
+ } catch {
112
+ return 'Documento PDF';
113
+ }
114
+ }
115
+
116
+ /**
117
+ * Whether a PDF URL is available.
118
+ */
119
+ get hasUrl(): boolean {
120
+ return !!this.url?.trim();
121
+ }
20
122
 
21
- constructor(
22
- public iconsService: JIconsService,
23
- private sanitizer: DomSanitizer
24
- ) { }
123
+ ngOnInit(): void {
124
+ this.syncViewport();
125
+ }
25
126
 
26
127
  ngOnChanges(changes: SimpleChanges): void {
27
128
  if (changes['url']) {
28
- this.safeUrl = this.sanitizer.bypassSecurityTrustResourceUrl(this.url);
129
+ this.safeUrl = this.hasUrl
130
+ ? this.sanitizer.bypassSecurityTrustResourceUrl(this.buildEmbedUrl(this.url))
131
+ : null;
132
+ }
133
+ }
134
+
135
+ @HostListener('window:resize')
136
+ onWindowResize(): void {
137
+ this.syncViewport();
138
+ }
139
+
140
+ /**
141
+ * Opens the PDF in a new browser tab (native viewer on mobile).
142
+ */
143
+ openInBrowser(): void {
144
+ if (!this.hasUrl) {
145
+ return;
29
146
  }
147
+
148
+ window.open(this.url, '_blank', 'noopener,noreferrer');
149
+ }
150
+
151
+ /**
152
+ * Triggers download / open for the PDF file.
153
+ */
154
+ downloadPdf(): void {
155
+ if (!this.hasUrl) {
156
+ return;
157
+ }
158
+
159
+ const link = document.createElement('a');
160
+ link.href = this.url;
161
+ link.target = '_blank';
162
+ link.rel = 'noopener noreferrer';
163
+ link.download = this.documentTitle;
164
+ document.body.appendChild(link);
165
+ link.click();
166
+ document.body.removeChild(link);
167
+ }
168
+
169
+ private syncViewport(): void {
170
+ if (typeof window === 'undefined') {
171
+ return;
172
+ }
173
+
174
+ this.isMobileViewport = window.matchMedia('(max-width: 767px)').matches;
175
+ }
176
+
177
+ private buildEmbedUrl(rawUrl: string): string {
178
+ if (rawUrl.includes('#')) {
179
+ return rawUrl;
180
+ }
181
+
182
+ return `${rawUrl}#view=FitH`;
30
183
  }
31
184
  }
@@ -0,0 +1 @@
1
+ export type PdfViewerMobileMode = 'auto' | 'embed' | 'actions';
package/src/styles.css CHANGED
@@ -5,8 +5,8 @@
5
5
  }
6
6
 
7
7
  .scroll-element::-webkit-scrollbar {
8
- width: 5px;
9
- height: 5px
8
+ width: 8px;
9
+ height: 8px
10
10
  }
11
11
 
12
12
  .scroll-element::-webkit-scrollbar-track {
@@ -1,65 +0,0 @@
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
- img: import("lucide-angular").LucideIconData;
19
- imgs: import("lucide-angular").LucideIconData;
20
- imageOff: import("lucide-angular").LucideIconData;
21
- upload: import("lucide-angular").LucideIconData;
22
- view: import("lucide-angular").LucideIconData;
23
- chevronUp: import("lucide-angular").LucideIconData;
24
- chevronDown: import("lucide-angular").LucideIconData;
25
- chevronsUpDown: import("lucide-angular").LucideIconData;
26
- squareDashedMousePointer: import("lucide-angular").LucideIconData;
27
- search: import("lucide-angular").LucideIconData;
28
- copy: import("lucide-angular").LucideIconData;
29
- save: import("lucide-angular").LucideIconData;
30
- sun: import("lucide-angular").LucideIconData;
31
- moon: import("lucide-angular").LucideIconData;
32
- loading: import("lucide-angular").LucideIconData;
33
- table: import("lucide-angular").LucideIconData;
34
- listFilter: import("lucide-angular").LucideIconData;
35
- firstPage: import("lucide-angular").LucideIconData;
36
- prevPage: import("lucide-angular").LucideIconData;
37
- nextPage: import("lucide-angular").LucideIconData;
38
- lastPage: import("lucide-angular").LucideIconData;
39
- arrowBigRight: import("lucide-angular").LucideIconData;
40
- filter: import("lucide-angular").LucideIconData;
41
- filterList: import("lucide-angular").LucideIconData;
42
- eraser: import("lucide-angular").LucideIconData;
43
- transh: import("lucide-angular").LucideIconData;
44
- default: import("lucide-angular").LucideIconData;
45
- fileSpreadsheet: import("lucide-angular").LucideIconData;
46
- monitorUp: import("lucide-angular").LucideIconData;
47
- download: import("lucide-angular").LucideIconData;
48
- fileUp: import("lucide-angular").LucideIconData;
49
- listRestart: import("lucide-angular").LucideIconData;
50
- editRowLine: import("lucide-angular").LucideIconData;
51
- editRow: import("lucide-angular").LucideIconData;
52
- edit: import("lucide-angular").LucideIconData;
53
- delete: import("lucide-angular").LucideIconData;
54
- ellipsisVertical: import("lucide-angular").LucideIconData;
55
- calendar: import("lucide-angular").LucideIconData;
56
- clock: import("lucide-angular").LucideIconData;
57
- circleAlert: import("lucide-angular").LucideIconData;
58
- clipboard: import("lucide-angular").LucideIconData;
59
- link: import("lucide-angular").LucideIconData;
60
- linkOff: import("lucide-angular").LucideIconData;
61
- };
62
- constructor();
63
- static ɵfac: i0.ɵɵFactoryDeclaration<JIconsService, never>;
64
- static ɵprov: i0.ɵɵInjectableDeclaration<JIconsService>;
65
- }
@@ -1,38 +0,0 @@
1
- # Colores Tailjng — configuración del proyecto
2
-
3
- Carpeta generada por `init:app`, `sync:app` o `npx tailjng add colors`.
4
-
5
- ## Archivos
6
-
7
- | Archivo | Para qué |
8
- |---------|----------|
9
- | `colors.config.ts` | Variantes (`primary`, `success_soft`, …) + las tuyas (`brand`, etc.) |
10
- | `colors.safelist.css` | Clases Tailwind que el build debe generar (`@apply`) |
11
-
12
- ## Añadir un color propio
13
-
14
- **1.** En `colors.config.ts`:
15
-
16
- ```typescript
17
- brand: 'bg-indigo-600 text-white hover:bg-indigo-700 border border-indigo-500 shadow-md',
18
- brand_soft: 'bg-indigo-500/10 text-indigo-600 border border-indigo-500/20 shadow-sm',
19
- ```
20
-
21
- **2.** En `colors.safelist.css`, dentro del bloque `@layer utilities`:
22
-
23
- ```css
24
- .__tailjng_custom_colors__ {
25
- @apply bg-indigo-600 text-white hover:bg-indigo-700 border-indigo-500 bg-indigo-500/10 text-indigo-600;
26
- }
27
- ```
28
-
29
- **3.** Uso en componentes:
30
-
31
- ```html
32
- <JButton classes="brand" text="Guardar" />
33
- <JBadge classes="brand_soft" value="N" />
34
- ```
35
-
36
- ## Provider
37
-
38
- `app.config.ts` debe incluir `tailjngColorsProvider` (lo añade `init:app` / `sync:app`).
@@ -1,12 +0,0 @@
1
- .menu-options-list,
2
- .menu-option-item {
3
- width: 100%;
4
- min-width: 100%;
5
- }
6
-
7
- :host ::ng-deep .menu-option-item j-button,
8
- :host ::ng-deep .menu-option-item jbutton {
9
- display: flex;
10
- width: 100%;
11
- min-width: 0;
12
- }
@@ -1,51 +0,0 @@
1
- @if (internalOptions.length > 0) {
2
- <div class="flex rounded-md overflow-hidden border border-border dark:border-dark-border text-sm min-h-[40px] select-none" [ngClass]="{ 'opacity-50': isDisabled || isComponentDisabled }" [class]="classes">
3
-
4
- <ng-container>
5
- @for (opt of internalOptions; track $index) {
6
- <button
7
- type="button"
8
- [disabled]="isDisabled || isComponentDisabled"
9
- (click)="select(opt.value)"
10
- [ngClass]="{
11
- 'bg-primary dark:bg-dark-primary text-white': selectedValue === opt.value,
12
- 'bg-background dark:bg-dark-background hover:bg-muted/80 hover:dark:bg-dark-muted/30 text-gray-700 dark:text-white': selectedValue !== opt.value,
13
- 'cursor-not-allowed pointer-events-none': isDisabled || isComponentDisabled
14
- }"
15
- class="w-full py-2 px-4 font-medium border-r border-border last:border-none focus:outline-none transition-colors duration-200 ease-in-out cursor-pointer"
16
- [class]="classesElement"
17
- >
18
- {{ opt.label }}
19
- </button>
20
- }
21
- </ng-container>
22
-
23
- </div>
24
- } @else if (isLoading) {
25
-
26
- <div class="flex text-black dark:text-white gap-2 items-center justify-center rounded-md overflow-hidden border border-border dark:border-dark-border h-[40px]">
27
- <lucide-icon [name]="iconsService.icons.loading" [size]="15" class="text-gray-400 animate-spin" />
28
- <span>Cargando...</span>
29
- </div>
30
-
31
- } @else {
32
-
33
- <div class="flex text-black dark:text-white items-center justify-center rounded-md overflow-hidden border border-border dark:border-dark-border h-[40px]">
34
- No hay opciones
35
- </div>
36
-
37
- }
38
-
39
- <!-- Clear button -->
40
- @if (showClear && selectedValue !== null) {
41
- <div class="mt-2">
42
- <button
43
- type="button"
44
- (click)="clear()"
45
- [disabled]="isDisabled || isComponentDisabled"
46
- class="text-xs text-red-500 underline disabled:opacity-50 disabled:cursor-not-allowed">
47
- Limpiar selección
48
- </button>
49
- </div>
50
- }
51
-