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
package/README.md CHANGED
@@ -12,7 +12,7 @@ Librería UI y utilidades para **Angular 19** con **Tailwind CSS v4**. Modelo h
12
12
  |------|-----------|
13
13
  | **Config** | `TAILJNG_CONFIG` — `urlBase`, `socketUrl` para API REST |
14
14
  | **Colores** | `JColorsService` — variantes (`primary`, `success_soft`, `error_outline`, …) |
15
- | **Iconos** | `JIconsService` mapa Lucide usado por los componentes |
15
+ | **Iconos** | Registro `Icons` en `.config/icons/icons.lucide.ts` (copiado con CLI) + componente `JIcon` |
16
16
  | **Alertas** | `JAlertDialogService`, `JAlertToastService` |
17
17
  | **CRUD / HTTP** | `JGenericCrudService`, `JConverterCrudService`, params, files, error handler |
18
18
  | **Transformación** | `JTransformService`, `JCalendarService` — fechas, moneda, tablas |
@@ -112,7 +112,6 @@ export const tailjngProviders = [
112
112
 
113
113
  ```typescript
114
114
  import {
115
- JIconsService,
116
115
  JColorsService,
117
116
  JAlertToastService,
118
117
  JGenericCrudService,
@@ -134,7 +133,16 @@ import { JAlertToastComponent } from './tailjng/alert/alert-toast/toast-alert.co
134
133
  <JButton [text]="'Guardar'" classes="primary" [icon]="icons.save" (clicked)="save()" />
135
134
  ```
136
135
 
137
- ### Colores — `src/app/tailjng/colors/`
136
+ ### Configuración — `src/app/tailjng/.config/`
137
+
138
+ Colores e iconos viven fuera de los componentes UI, en subcarpetas de `.config`:
139
+
140
+ | Subcarpeta | Archivos |
141
+ |------------|----------|
142
+ | `.config/colors/` | `colors.config.ts`, `colors.safelist.css` |
143
+ | `.config/icons/` | `icons.lucide.ts` (clase `Icons`) |
144
+
145
+ ### Colores — `src/app/tailjng/.config/colors/`
138
146
 
139
147
  Las variantes (`primary`, `success_soft`, …) las resuelve **`JColorsService`**. Tailwind v4 no genera clases solo en runtime, así que cada proyecto tiene una carpeta editable:
140
148
 
@@ -143,7 +151,21 @@ Las variantes (`primary`, `success_soft`, …) las resuelve **`JColorsService`**
143
151
  | `colors.config.ts` | Lista de variantes (incluye las 77 por defecto) + las tuyas (`brand`, etc.) |
144
152
  | `colors.safelist.css` | Clases Tailwind que el build debe generar (`@apply`) |
145
153
 
146
- **`init:app`** y **`sync:app`** crean esa carpeta (sin sobrescribir si ya existe), importan `colors.safelist.css` en `styles.css` y registran `tailjngColorsProvider`.
154
+ **`init:app`** y **`sync:app`** crean esa carpeta (sin sobrescribir si ya existe), importan `colors.safelist.css` en tus estilos globales y registran `tailjngColorsProvider`.
155
+
156
+ Import del safelist según el lenguaje de estilos del proyecto:
157
+
158
+ ```css
159
+ /* styles.css */
160
+ @import "tailwindcss";
161
+ @import "./app/tailjng/.config/colors/colors.safelist.css";
162
+ ```
163
+
164
+ ```scss
165
+ /* styles.scss — todos los @use van antes de otras reglas */
166
+ @use "tailwindcss";
167
+ @use "./app/tailjng/.config/colors/colors.safelist.css";
168
+ ```
147
169
 
148
170
  Si falta la carpeta en un proyecto existente:
149
171
 
@@ -176,7 +198,7 @@ Uso en componentes:
176
198
  `init:app` / `sync:app` registran el provider automáticamente. Manualmente en `app.config.ts`:
177
199
 
178
200
  ```typescript
179
- import { tailjngColorsProvider } from './tailjng/colors/colors.config';
201
+ import { tailjngColorsProvider } from './tailjng/.config/colors/colors.config';
180
202
 
181
203
  providers: [
182
204
  tailjngColorsProvider,
@@ -33,6 +33,7 @@ const {
33
33
  ensureProjectColorsConfig,
34
34
  patchAppConfigColors,
35
35
  } = require('../settings/colors-config-utils');
36
+ const { ensureProjectIconsConfig } = require('../settings/icons-config-utils');
36
37
 
37
38
  /** Solo si pasas --with-components (opcional; no es el flujo normal). */
38
39
  const OPTIONAL_BASE_COMPONENTS = ['mode-toggle', 'alert-dialog', 'alert-toast'];
@@ -148,7 +149,8 @@ async function runInitApp() {
148
149
  // Siempre alinear @angular/animations con la versión real de @angular/core del proyecto
149
150
  const animationsAligned = alignAngularAnimationsInPackageJson(workspaceRoot);
150
151
  if (animationsAligned.changed) {
151
- console.log(`${COLORS.cyan}[tailjng CLI] Aligned @angular/animations → ${animationsAligned.version} (same as @angular/core)${COLORS.reset}`);
152
+ const label = animationsAligned.added ? 'Added' : 'Aligned';
153
+ console.log(`${COLORS.cyan}[tailjng CLI] ${label} @angular/animations → ${animationsAligned.version} (same as @angular/core)${COLORS.reset}`);
152
154
  Object.assign(packageJson, readJson(packageJsonPath));
153
155
  }
154
156
 
@@ -171,6 +173,7 @@ async function runInitApp() {
171
173
  }
172
174
 
173
175
  ensureProjectColorsConfig(workspaceRoot, appRoot, overwrite);
176
+ ensureProjectIconsConfig(workspaceRoot, appRoot, overwrite);
174
177
 
175
178
  const hasAppConfig = fileExists(appConfigPath);
176
179
  const safelistImport = getTailjngSafelistCssImport(workspaceRoot, primaryStylePath, selectedApp);
@@ -223,7 +226,7 @@ async function runInitApp() {
223
226
 
224
227
  const colorsPatched = patchAppConfigColors(appConfigPath, srcRoot);
225
228
  if (colorsPatched.changed) {
226
- console.log(`${COLORS.green}✔ Linked tailjngColorsProvider from src/app/tailjng/colors/${COLORS.reset}`);
229
+ console.log(`${COLORS.green}✔ Linked tailjngColorsProvider from src/app/tailjng/.config/colors/${COLORS.reset}`);
227
230
  }
228
231
  }
229
232
 
@@ -30,6 +30,10 @@ const {
30
30
  patchAppConfigColors,
31
31
  COLORS_FILES,
32
32
  } = require('../settings/colors-config-utils');
33
+ const {
34
+ ensureProjectIconsConfig,
35
+ ICONS_FILES,
36
+ } = require('../settings/icons-config-utils');
33
37
 
34
38
  function resolveTargetPath(workspaceRoot, appProject, relativePath, appRootRelative = false) {
35
39
  const appRoot = path.join(workspaceRoot, appProject.root || '');
@@ -89,7 +93,8 @@ async function runSyncApp() {
89
93
  const animationsAligned = alignAngularAnimationsInPackageJson(workspaceRoot);
90
94
  if (animationsAligned.changed) {
91
95
  changes += 1;
92
- console.log(`${COLORS.green}✔ Aligned @angular/animations ${animationsAligned.version}${COLORS.reset}`);
96
+ const label = animationsAligned.added ? 'Added' : 'Aligned';
97
+ console.log(`${COLORS.green}✔ ${label} @angular/animations → ${animationsAligned.version}${COLORS.reset}`);
93
98
  Object.assign(packageJson, readJson(packageJsonPath));
94
99
  }
95
100
 
@@ -137,6 +142,13 @@ async function runSyncApp() {
137
142
  console.log(`${COLORS.dim}↷ Project colors config already present${COLORS.reset}`);
138
143
  }
139
144
 
145
+ const iconsResult = ensureProjectIconsConfig(workspaceRoot, appRoot, false);
146
+ if (iconsResult.created > 0) {
147
+ changes += iconsResult.created;
148
+ } else if (iconsResult.skipped === ICONS_FILES.length) {
149
+ console.log(`${COLORS.dim}↷ Project icons config already present${COLORS.reset}`);
150
+ }
151
+
140
152
  const safelistImport = getTailjngSafelistCssImport(workspaceRoot, primaryStylePath, selectedApp);
141
153
  const safelistPatched = ensureTailjngSafelistImport(primaryStyleFullPath, safelistImport);
142
154
  if (safelistPatched.changed) {
@@ -167,7 +179,7 @@ async function runSyncApp() {
167
179
  const colorsPatched = patchAppConfigColors(appConfigPath, srcRoot);
168
180
  if (colorsPatched.changed) {
169
181
  changes += 1;
170
- console.log(`${COLORS.green}✔ Linked tailjngColorsProvider from src/app/tailjng/colors/${COLORS.reset}`);
182
+ console.log(`${COLORS.green}✔ Linked tailjngColorsProvider from src/app/tailjng/.config/colors/${COLORS.reset}`);
171
183
  }
172
184
  }
173
185
 
@@ -3,11 +3,19 @@ const path = require('path');
3
3
  const { COLORS } = require('./colors');
4
4
  const { writeFileSafe } = require('./project-utils');
5
5
 
6
- const COLORS_SOURCE_REL = 'src/lib/components/colors-config';
6
+ const CONFIG_DIR = '.config';
7
+ const COLORS_SOURCE_REL = 'src/lib/components/.config/colors';
7
8
  const COLORS_FILES = ['colors.config.ts', 'colors.safelist.css', 'README.md'];
9
+ const COLORS_PROVIDER_IMPORT = '../tailjng/.config/colors/colors.config';
10
+ const COLORS_PROVIDER_IMPORT_APP = './tailjng/.config/colors/colors.config';
11
+ const COLORS_SAFELIST_SEGMENT = 'tailjng/.config/colors/colors.safelist.css';
12
+
13
+ function getProjectConfigDir(appRoot) {
14
+ return path.join(appRoot, 'src', 'app', 'tailjng', CONFIG_DIR);
15
+ }
8
16
 
9
17
  function getProjectColorsDir(appRoot) {
10
- return path.join(appRoot, 'src', 'app', 'tailjng', 'colors');
18
+ return path.join(getProjectConfigDir(appRoot), 'colors');
11
19
  }
12
20
 
13
21
  function resolveTailjngPackageRoot(workspaceRoot) {
@@ -24,6 +32,21 @@ function resolveTailjngPackageRoot(workspaceRoot) {
24
32
  return null;
25
33
  }
26
34
 
35
+ function migrateLegacyColorsPaths(content) {
36
+ return content
37
+ .replaceAll('../tailjng/colors/colors.config', COLORS_PROVIDER_IMPORT)
38
+ .replaceAll('./tailjng/colors/colors.config', COLORS_PROVIDER_IMPORT_APP)
39
+ .replaceAll('tailjng/colors/colors.safelist.css', COLORS_SAFELIST_SEGMENT);
40
+ }
41
+
42
+ function isScssStyleEntry(styleEntry) {
43
+ return /\.(scss|sass)$/i.test(styleEntry);
44
+ }
45
+
46
+ function getSafelistDirective(styleEntry) {
47
+ return isScssStyleEntry(styleEntry) ? '@use' : '@import';
48
+ }
49
+
27
50
  function getColorsSafelistImportLine(workspaceRoot, styleEntry, appProject) {
28
51
  const appRoot = path.join(workspaceRoot, appProject.root || '');
29
52
  const colorsSafelist = path.join(getProjectColorsDir(appRoot), 'colors.safelist.css');
@@ -43,7 +66,7 @@ function getColorsSafelistImportLine(workspaceRoot, styleEntry, appProject) {
43
66
 
44
67
  let rel = path.relative(path.dirname(stylePath), targetSafelist).split(path.sep).join('/');
45
68
  if (!rel.startsWith('.')) rel = `./${rel}`;
46
- return `@import "${rel}";`;
69
+ return `${getSafelistDirective(styleEntry)} "${rel}";`;
47
70
  }
48
71
 
49
72
  function ensureProjectColorsConfig(workspaceRoot, appRoot, overwrite = false) {
@@ -80,15 +103,37 @@ function ensureColorsSafelistImport(styleFilePath, importLine) {
80
103
  if (!fs.existsSync(styleFilePath)) return { changed: false };
81
104
 
82
105
  let content = fs.readFileSync(styleFilePath, 'utf8');
83
- const projectImport = /tailjng\/colors\/colors\.safelist\.css/;
106
+ const migrated = migrateLegacyColorsPaths(content);
107
+ if (migrated !== content) {
108
+ content = migrated;
109
+ fs.writeFileSync(styleFilePath, content, 'utf8');
110
+ return { changed: true, migrated: true };
111
+ }
112
+
113
+ const isScss = /\.(scss|sass)$/i.test(styleFilePath);
114
+ const expectedDirective = isScss ? '@use' : '@import';
115
+ const projectImport = new RegExp(COLORS_SAFELIST_SEGMENT.replace(/\./g, '\\.'));
84
116
  const npmImport = /node_modules\/tailjng\/src\/colors\.safelist\.css/;
85
- const anySafelistImport = /@import\s+"[^"]*colors\.safelist\.css";?/;
117
+ const anySafelistImport = /@(?:import|use)\s+"[^"]*colors\.safelist\.css";?/;
118
+
119
+ const wrongDirectivePattern = isScss
120
+ ? /@import\s+"([^"]*colors\.safelist\.css)";?/
121
+ : /@use\s+"([^"]*colors\.safelist\.css)";?/;
86
122
 
87
- if (projectImport.test(content)) {
123
+ if (wrongDirectivePattern.test(content)) {
124
+ content = content.replace(
125
+ wrongDirectivePattern,
126
+ (_, safelistPath) => `${expectedDirective} "${safelistPath}";`,
127
+ );
128
+ fs.writeFileSync(styleFilePath, content, 'utf8');
129
+ return { changed: true, migrated: true };
130
+ }
131
+
132
+ if (projectImport.test(content) && anySafelistImport.test(content)) {
88
133
  return { changed: false };
89
134
  }
90
135
 
91
- if (npmImport.test(content) && projectImport.test(importLine)) {
136
+ if (npmImport.test(content) && importLine.includes(COLORS_SAFELIST_SEGMENT)) {
92
137
  content = content.replace(anySafelistImport, importLine);
93
138
  fs.writeFileSync(styleFilePath, content, 'utf8');
94
139
  return { changed: true, migrated: true };
@@ -114,7 +159,13 @@ function patchTailjngProvidersColors(providersPath) {
114
159
  if (!fs.existsSync(providersPath)) return { changed: false };
115
160
 
116
161
  let content = fs.readFileSync(providersPath, 'utf8');
117
- if (content.includes('tailjngColorsProvider') || content.includes('../tailjng/colors/colors.config')) {
162
+ const migrated = migrateLegacyColorsPaths(content);
163
+ if (migrated !== content) {
164
+ fs.writeFileSync(providersPath, migrated, 'utf8');
165
+ return { changed: true, migrated: true };
166
+ }
167
+
168
+ if (content.includes('tailjngColorsProvider') || content.includes(COLORS_PROVIDER_IMPORT)) {
118
169
  return { changed: false };
119
170
  }
120
171
 
@@ -124,7 +175,7 @@ function patchTailjngProvidersColors(providersPath) {
124
175
  if (lines[i].startsWith('import ')) lastImport = i;
125
176
  }
126
177
 
127
- const importLine = "import { tailjngColorsProvider } from '../tailjng/colors/colors.config';";
178
+ const importLine = `import { tailjngColorsProvider } from '${COLORS_PROVIDER_IMPORT}';`;
128
179
  if (lastImport === -1) {
129
180
  content = `${importLine}\n${content}`;
130
181
  } else {
@@ -152,7 +203,13 @@ function patchAppConfigColors(appConfigPath, srcRoot) {
152
203
  if (!fs.existsSync(appConfigPath)) return { changed: false };
153
204
 
154
205
  let content = fs.readFileSync(appConfigPath, 'utf8');
155
- if (content.includes('tailjngColorsProvider') || content.includes('./tailjng/colors/colors.config')) {
206
+ const migrated = migrateLegacyColorsPaths(content);
207
+ if (migrated !== content) {
208
+ fs.writeFileSync(appConfigPath, migrated, 'utf8');
209
+ return { changed: true, migrated: true };
210
+ }
211
+
212
+ if (content.includes('tailjngColorsProvider') || content.includes(COLORS_PROVIDER_IMPORT_APP)) {
156
213
  return { changed: false };
157
214
  }
158
215
 
@@ -162,7 +219,7 @@ function patchAppConfigColors(appConfigPath, srcRoot) {
162
219
  if (lines[i].startsWith('import ')) lastImport = i;
163
220
  }
164
221
 
165
- const importLine = "import { tailjngColorsProvider } from './tailjng/colors/colors.config';";
222
+ const importLine = `import { tailjngColorsProvider } from '${COLORS_PROVIDER_IMPORT_APP}';`;
166
223
  if (lastImport === -1) {
167
224
  content = `${importLine}\n${content}`;
168
225
  } else {
@@ -179,6 +236,7 @@ function patchAppConfigColors(appConfigPath, srcRoot) {
179
236
  }
180
237
 
181
238
  module.exports = {
239
+ getProjectConfigDir,
182
240
  getProjectColorsDir,
183
241
  getColorsSafelistImportLine,
184
242
  ensureProjectColorsConfig,
@@ -0,0 +1,62 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const { COLORS } = require('./colors');
4
+ const { writeFileSafe } = require('./project-utils');
5
+ const { getProjectConfigDir } = require('./colors-config-utils');
6
+
7
+ const ICONS_SOURCE_REL = 'src/lib/components/.config/icons';
8
+ const ICONS_FILES = ['icons.lucide.ts', 'README.md'];
9
+
10
+ function getProjectIconsDir(appRoot) {
11
+ return path.join(getProjectConfigDir(appRoot), 'icons');
12
+ }
13
+
14
+ function resolveTailjngPackageRoot(workspaceRoot) {
15
+ const fromNodeModules = path.join(workspaceRoot, 'node_modules', 'tailjng', ICONS_SOURCE_REL);
16
+ if (fs.existsSync(fromNodeModules)) {
17
+ return path.join(workspaceRoot, 'node_modules', 'tailjng');
18
+ }
19
+
20
+ const fromMonorepo = path.join(workspaceRoot, 'projects', 'tailjng', ICONS_SOURCE_REL);
21
+ if (fs.existsSync(fromMonorepo)) {
22
+ return path.join(workspaceRoot, 'projects', 'tailjng');
23
+ }
24
+
25
+ return null;
26
+ }
27
+
28
+ function ensureProjectIconsConfig(workspaceRoot, appRoot, overwrite = false) {
29
+ const packageRoot = resolveTailjngPackageRoot(workspaceRoot);
30
+ if (!packageRoot) {
31
+ console.log(`${COLORS.yellow}[tailjng CLI] WARNING: tailjng package not found — skip icons config copy${COLORS.reset}`);
32
+ return { created: 0, skipped: 0, iconsDir: getProjectIconsDir(appRoot) };
33
+ }
34
+
35
+ const sourceDir = path.join(packageRoot, ICONS_SOURCE_REL);
36
+ const iconsDir = getProjectIconsDir(appRoot);
37
+ let created = 0;
38
+ let skipped = 0;
39
+
40
+ for (const file of ICONS_FILES) {
41
+ const src = path.join(sourceDir, file);
42
+ const dest = path.join(iconsDir, file);
43
+ if (!fs.existsSync(src)) continue;
44
+
45
+ const content = fs.readFileSync(src, 'utf8');
46
+ if (writeFileSafe(dest, content, overwrite)) {
47
+ created += 1;
48
+ console.log(`${COLORS.green}✔ Created ${path.relative(workspaceRoot, dest)}${COLORS.reset}`);
49
+ } else {
50
+ skipped += 1;
51
+ console.log(`${COLORS.dim}↷ Skipped (exists) ${path.relative(workspaceRoot, dest)}${COLORS.reset}`);
52
+ }
53
+ }
54
+
55
+ return { created, skipped, iconsDir };
56
+ }
57
+
58
+ module.exports = {
59
+ getProjectIconsDir,
60
+ ensureProjectIconsConfig,
61
+ ICONS_FILES,
62
+ };
@@ -5,8 +5,26 @@ const path = require("path")
5
5
  const { getComponentsBasePath } = require("./lib-utils")
6
6
 
7
7
  const COMPONENTS_SOURCE_PREFIX = "src/lib/components/"
8
+ const CONFIG_SOURCE_PREFIX = "src/lib/components/.config/"
9
+
10
+ function isConfigPath(componentPath) {
11
+ return componentPath.startsWith(CONFIG_SOURCE_PREFIX)
12
+ }
8
13
 
9
14
  function parseComponentPath(componentPath) {
15
+ if (isConfigPath(componentPath)) {
16
+ const relativePath = componentPath.replace(CONFIG_SOURCE_PREFIX, "")
17
+ const pathParts = relativePath.split("/")
18
+ const componentFolder = pathParts[pathParts.length - 1]
19
+
20
+ return {
21
+ componentFolder,
22
+ subfolders: [".config", ...pathParts.slice(0, -1)],
23
+ hasSubfolders: true,
24
+ fullSubPath: [".config", ...pathParts.slice(0, -1)].join("/"),
25
+ }
26
+ }
27
+
10
28
  const relativePath = componentPath.replace(COMPONENTS_SOURCE_PREFIX, "")
11
29
  const pathParts = relativePath.split("/")
12
30
  const componentFolder = pathParts[pathParts.length - 1]
@@ -21,9 +39,15 @@ function parseComponentPath(componentPath) {
21
39
  }
22
40
 
23
41
  function buildTargetPath(projectRoot, componentName, componentPath) {
24
- const pathInfo = parseComponentPath(componentPath)
25
42
  const basePath = getComponentsBasePath(projectRoot)
26
43
 
44
+ if (isConfigPath(componentPath)) {
45
+ const configRel = componentPath.slice(CONFIG_SOURCE_PREFIX.length)
46
+ return path.join(basePath, ".config", configRel)
47
+ }
48
+
49
+ const pathInfo = parseComponentPath(componentPath)
50
+
27
51
  if (pathInfo.hasSubfolders) {
28
52
  return path.join(basePath, pathInfo.fullSubPath, componentName)
29
53
  }
@@ -34,4 +58,10 @@ function isComponentInstalled(projectRoot, componentName, componentPath) {
34
58
  return fs.existsSync(buildTargetPath(projectRoot, componentName, componentPath))
35
59
  }
36
60
 
37
- module.exports = { parseComponentPath, buildTargetPath, isComponentInstalled }
61
+ module.exports = {
62
+ parseComponentPath,
63
+ buildTargetPath,
64
+ isComponentInstalled,
65
+ isConfigPath,
66
+ CONFIG_SOURCE_PREFIX,
67
+ }
@@ -260,7 +260,13 @@ function alignAngularAnimationsInPackageJson(workspaceRoot) {
260
260
  const aligned = coreInstalled ? `^${coreInstalled}` : coreSpec;
261
261
  if (!aligned) return { changed: false };
262
262
 
263
- if (!deps['@angular/animations']) return { changed: false };
263
+ if (!deps['@angular/animations']) {
264
+ deps['@angular/animations'] = aligned;
265
+ pkg.dependencies = deps;
266
+ writeJson(pkgPath, pkg);
267
+ return { changed: true, version: aligned, added: true };
268
+ }
269
+
264
270
  if (deps['@angular/animations'] === aligned) return { changed: false };
265
271
 
266
272
  deps['@angular/animations'] = aligned;
@@ -70,16 +70,19 @@ ${buildDefaultThemeBlock()}
70
70
 
71
71
  .dark {
72
72
  --tw-bg-opacity: 1;
73
- color: var(--white);
73
+ color: var(--color-dark-foreground);
74
74
  }
75
75
  `;
76
76
  }
77
77
 
78
78
  function buildStylesScss(safelistImport = '') {
79
+ const safelistUse = safelistImport
80
+ ? safelistImport.replace(/^@import\s+/, '@use ')
81
+ : '';
79
82
  return `@use "tailwindcss";
80
- ${safelistImport ? `${safelistImport}\n` : ''}
81
83
  @use "./scss/scroll";
82
84
  @use "./scss/input";
85
+ ${safelistUse ? `${safelistUse}\n` : ''}
83
86
 
84
87
  html,
85
88
  body {
@@ -104,7 +107,7 @@ ${buildDefaultThemeBlock()}
104
107
 
105
108
  .dark {
106
109
  --tw-bg-opacity: 1;
107
- color: var(--white);
110
+ color: var(--color-dark-foreground);
108
111
  }
109
112
  `;
110
113
  }
@@ -114,8 +117,8 @@ function buildScrollScss() {
114
117
  padding-right: 5px;
115
118
 
116
119
  &::-webkit-scrollbar {
117
- width: 5px;
118
- height: 5px;
120
+ width: 8px;
121
+ height: 8px;
119
122
  }
120
123
 
121
124
  &::-webkit-scrollbar-track {