@caribeng/ui 22.2.0 → 22.4.0

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 (121) hide show
  1. package/README.md +93 -11
  2. package/fesm2022/caribeng-ui-accordion.mjs +2 -2
  3. package/fesm2022/caribeng-ui-avatar.mjs +2 -2
  4. package/fesm2022/caribeng-ui-badge.mjs +8 -2
  5. package/fesm2022/caribeng-ui-breadcrumb.mjs +13 -6
  6. package/fesm2022/caribeng-ui-chart.mjs +8 -5
  7. package/fesm2022/caribeng-ui-chat.mjs +1303 -0
  8. package/fesm2022/caribeng-ui-code-block.mjs +332 -0
  9. package/fesm2022/caribeng-ui-colorpicker.mjs +99 -5
  10. package/fesm2022/caribeng-ui-command-palette.mjs +476 -0
  11. package/fesm2022/caribeng-ui-confirmdialog.mjs +78 -13
  12. package/fesm2022/caribeng-ui-confirmpopup.mjs +91 -16
  13. package/fesm2022/caribeng-ui-contextmenu.mjs +8 -4
  14. package/fesm2022/caribeng-ui-copy-button.mjs +230 -0
  15. package/fesm2022/caribeng-ui-dataview.mjs +4 -1
  16. package/fesm2022/caribeng-ui-dock.mjs +52 -12
  17. package/fesm2022/caribeng-ui-drawer.mjs +9 -4
  18. package/fesm2022/caribeng-ui-editor.mjs +21 -0
  19. package/fesm2022/caribeng-ui-fieldset.mjs +2 -2
  20. package/fesm2022/caribeng-ui-file-card.mjs +134 -17
  21. package/fesm2022/caribeng-ui-folder-card.mjs +122 -12
  22. package/fesm2022/caribeng-ui-inlinemessage.mjs +2 -2
  23. package/fesm2022/caribeng-ui-inputmask.mjs +8 -2
  24. package/fesm2022/caribeng-ui-kanban.mjs +4612 -0
  25. package/fesm2022/caribeng-ui-kbd.mjs +122 -0
  26. package/fesm2022/caribeng-ui-megamenu.mjs +13 -9
  27. package/fesm2022/caribeng-ui-mentions.mjs +495 -0
  28. package/fesm2022/caribeng-ui-menu.mjs +8 -4
  29. package/fesm2022/caribeng-ui-menubar.mjs +9 -5
  30. package/fesm2022/caribeng-ui-message.mjs +6 -3
  31. package/fesm2022/caribeng-ui-organizationchart.mjs +6 -10
  32. package/fesm2022/caribeng-ui-panel.mjs +6 -6
  33. package/fesm2022/caribeng-ui-panelmenu.mjs +9 -6
  34. package/fesm2022/caribeng-ui-phone-input.mjs +688 -0
  35. package/fesm2022/caribeng-ui-pricing.mjs +263 -69
  36. package/fesm2022/caribeng-ui-qrcode.mjs +564 -0
  37. package/fesm2022/caribeng-ui-ripple.mjs +2 -0
  38. package/fesm2022/caribeng-ui-scrolltop.mjs +3 -1
  39. package/fesm2022/caribeng-ui-sidebar.mjs +573 -0
  40. package/fesm2022/caribeng-ui-stepper.mjs +10 -3
  41. package/fesm2022/caribeng-ui-table.mjs +10 -4
  42. package/fesm2022/caribeng-ui-tabmenu.mjs +8 -4
  43. package/fesm2022/caribeng-ui-tieredmenu.mjs +109 -19
  44. package/fesm2022/caribeng-ui.mjs +388 -1
  45. package/package.json +42 -2
  46. package/schematics/collection.json +5 -0
  47. package/schematics/migrate-from-primeng/core-icons.json +1 -0
  48. package/schematics/migrate-from-primeng/icons.js +269 -0
  49. package/schematics/migrate-from-primeng/index.js +290 -0
  50. package/schematics/migrate-from-primeng/mappings/button.js +93 -0
  51. package/schematics/migrate-from-primeng/mappings/card.js +33 -0
  52. package/schematics/migrate-from-primeng/mappings/checkbox.js +44 -0
  53. package/schematics/migrate-from-primeng/mappings/confirm.js +221 -0
  54. package/schematics/migrate-from-primeng/mappings/datepicker.js +121 -0
  55. package/schematics/migrate-from-primeng/mappings/dialog.js +84 -0
  56. package/schematics/migrate-from-primeng/mappings/index.js +88 -0
  57. package/schematics/migrate-from-primeng/mappings/inputnumber.js +62 -0
  58. package/schematics/migrate-from-primeng/mappings/inputtext.js +60 -0
  59. package/schematics/migrate-from-primeng/mappings/menu.js +468 -0
  60. package/schematics/migrate-from-primeng/mappings/multiselect.js +49 -0
  61. package/schematics/migrate-from-primeng/mappings/radiobutton.js +22 -0
  62. package/schematics/migrate-from-primeng/mappings/rules.js +206 -0
  63. package/schematics/migrate-from-primeng/mappings/select.js +97 -0
  64. package/schematics/migrate-from-primeng/mappings/service-calls.js +100 -0
  65. package/schematics/migrate-from-primeng/mappings/table.js +613 -0
  66. package/schematics/migrate-from-primeng/mappings/tabs.js +225 -0
  67. package/schematics/migrate-from-primeng/mappings/tag.js +29 -0
  68. package/schematics/migrate-from-primeng/mappings/textarea.js +44 -0
  69. package/schematics/migrate-from-primeng/mappings/toast.js +173 -0
  70. package/schematics/migrate-from-primeng/mappings/toggleswitch.js +37 -0
  71. package/schematics/migrate-from-primeng/mappings/tooltip.js +44 -0
  72. package/schematics/migrate-from-primeng/mappings/types.js +10 -0
  73. package/schematics/migrate-from-primeng/report.js +79 -0
  74. package/schematics/migrate-from-primeng/schema.js +2 -0
  75. package/schematics/migrate-from-primeng/schema.json +34 -0
  76. package/schematics/migrate-from-primeng/template.js +387 -0
  77. package/schematics/migrate-from-primeng/todo.js +5 -0
  78. package/schematics/migrate-from-primeng/typescript.js +442 -0
  79. package/schematics/migrate-from-primeng/workspace.js +117 -0
  80. package/schematics/ng-add/index.js +16 -1
  81. package/types/caribeng-ui-badge.d.ts +3 -1
  82. package/types/caribeng-ui-breadcrumb.d.ts +8 -0
  83. package/types/caribeng-ui-chart.d.ts +3 -1
  84. package/types/caribeng-ui-chat.d.ts +299 -0
  85. package/types/caribeng-ui-code-block.d.ts +65 -0
  86. package/types/caribeng-ui-colorpicker.d.ts +5 -1
  87. package/types/caribeng-ui-command-palette.d.ts +133 -0
  88. package/types/caribeng-ui-confirmdialog.d.ts +34 -2
  89. package/types/caribeng-ui-confirmpopup.d.ts +39 -2
  90. package/types/caribeng-ui-contextmenu.d.ts +7 -0
  91. package/types/caribeng-ui-copy-button.d.ts +90 -0
  92. package/types/caribeng-ui-dataview.d.ts +2 -0
  93. package/types/caribeng-ui-dock.d.ts +13 -1
  94. package/types/caribeng-ui-drawer.d.ts +3 -1
  95. package/types/caribeng-ui-file-card.d.ts +27 -2
  96. package/types/caribeng-ui-folder-card.d.ts +27 -5
  97. package/types/caribeng-ui-inputmask.d.ts +3 -1
  98. package/types/caribeng-ui-kanban.d.ts +783 -0
  99. package/types/caribeng-ui-kbd.d.ts +36 -0
  100. package/types/caribeng-ui-megamenu.d.ts +11 -0
  101. package/types/caribeng-ui-mentions.d.ts +127 -0
  102. package/types/caribeng-ui-menu.d.ts +7 -0
  103. package/types/caribeng-ui-menubar.d.ts +7 -0
  104. package/types/caribeng-ui-message.d.ts +2 -0
  105. package/types/caribeng-ui-panelmenu.d.ts +7 -0
  106. package/types/caribeng-ui-phone-input.d.ts +168 -0
  107. package/types/caribeng-ui-pricing.d.ts +41 -4
  108. package/types/caribeng-ui-qrcode.d.ts +88 -0
  109. package/types/caribeng-ui-sidebar.d.ts +167 -0
  110. package/types/caribeng-ui-stepper.d.ts +2 -0
  111. package/types/caribeng-ui-table.d.ts +1 -1
  112. package/types/caribeng-ui-tabmenu.d.ts +7 -0
  113. package/types/caribeng-ui-tieredmenu.d.ts +17 -1
  114. package/types/caribeng-ui.d.ts +276 -2
  115. package/styles/caribeng.css +0 -380
  116. package/styles/scss/_mixins.scss +0 -46
  117. package/styles/scss/_overlay.scss +0 -15
  118. package/styles/scss/_tokens.scss +0 -267
  119. package/styles/scss/_utilities.scss +0 -73
  120. package/styles/scss/_variables.scss +0 -33
  121. package/styles/scss/index.scss +0 -16
@@ -0,0 +1,442 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PROVIDER_CONFIG = void 0;
37
+ exports.rewriteImports = rewriteImports;
38
+ exports.findComponents = findComponents;
39
+ exports.replaceInlineTemplate = replaceInlineTemplate;
40
+ exports.ensureComponentImports = ensureComponentImports;
41
+ const ts = __importStar(require("typescript"));
42
+ const mappings_1 = require("./mappings");
43
+ const template_1 = require("./template");
44
+ /** `providePrimeNG` (de `primeng/config`) → `provideCaribeNG` (de `@caribeng/ui`). */
45
+ const CONFIG_SYMBOLS = new Map([['providePrimeNG', { name: 'provideCaribeNG', entry: '@caribeng/ui' }]]);
46
+ /** Configuración que se escribe en lugar de la de PrimeNG (la misma que `ng add` por defecto). */
47
+ exports.PROVIDER_CONFIG = "{ locale: 'es', theme: 'light', preset: 'emerald' }";
48
+ /** Módulos que quedan sin uso tras la migración y se eliminan si nada los referencia. */
49
+ const PRUNABLE_MODULES = /^(@primeuix\/|primeng\/config$)/;
50
+ function parse(fileName, text) {
51
+ return ts.createSourceFile(fileName, text, ts.ScriptTarget.Latest, true);
52
+ }
53
+ function newline(text) {
54
+ return text.includes('\r\n') ? '\r\n' : '\n';
55
+ }
56
+ /** Rango de una sentencia incluyendo su salto de línea final (para borrarla sin dejar una línea vacía). */
57
+ function statementRange(sf, node) {
58
+ const text = sf.text;
59
+ let end = node.getEnd();
60
+ if (text.startsWith('\r\n', end))
61
+ end += 2;
62
+ else if (text[end] === '\n')
63
+ end += 1;
64
+ return { start: node.getStart(sf), end };
65
+ }
66
+ /** Nombres ya importados desde cada entry point de CaribeNG. */
67
+ function caribeImports(sf) {
68
+ const imports = new Map();
69
+ for (const statement of sf.statements) {
70
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
71
+ continue;
72
+ const module = statement.moduleSpecifier.text;
73
+ const bindings = statement.importClause?.namedBindings;
74
+ if (!module.startsWith('@caribeng/') || !bindings || !ts.isNamedImports(bindings))
75
+ continue;
76
+ const names = imports.get(module) ?? new Set();
77
+ bindings.elements.forEach((element) => names.add(element.name.text));
78
+ imports.set(module, names);
79
+ }
80
+ return imports;
81
+ }
82
+ /** El identificador es un nombre de propiedad/miembro, no una referencia al símbolo importado. */
83
+ function isMemberName(node) {
84
+ const parent = node.parent;
85
+ return ((ts.isPropertyAccessExpression(parent) && parent.name === node) ||
86
+ (ts.isQualifiedName(parent) && parent.right === node) ||
87
+ ((ts.isPropertyAssignment(parent) ||
88
+ ts.isPropertyDeclaration(parent) ||
89
+ ts.isMethodDeclaration(parent) ||
90
+ ts.isPropertySignature(parent) ||
91
+ ts.isMethodSignature(parent) ||
92
+ ts.isGetAccessorDeclaration(parent) ||
93
+ ts.isSetAccessorDeclaration(parent) ||
94
+ ts.isEnumMember(parent)) &&
95
+ parent.name === node));
96
+ }
97
+ /**
98
+ * Cambia los imports de PrimeNG por los de CaribeNG (`ButtonModule` de
99
+ * `primeng/button` → `CbButton` de `@caribeng/ui/button`), renombra sus usos
100
+ * y sustituye `providePrimeNG(…)` por `provideCaribeNG(…)`. Los símbolos sin
101
+ * equivalente se quedan importados de PrimeNG (aparecen en el informe).
102
+ */
103
+ function rewriteImports(fileName, text, templates = []) {
104
+ const sf = parse(fileName, text);
105
+ const edits = [];
106
+ const renames = new Map();
107
+ const existing = caribeImports(sf);
108
+ const eol = newline(text);
109
+ let providerLocal;
110
+ // Reescrituras que dependen del contexto (servicios, MenuItem): van primero porque
111
+ // pueden consumir símbolos de PrimeNG y pedir imports de CaribeNG.
112
+ const locals = new Map();
113
+ for (const statement of sf.statements) {
114
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier) || !statement.moduleSpecifier.text.startsWith('primeng/'))
115
+ continue;
116
+ const bindings = statement.importClause?.namedBindings;
117
+ if (bindings && ts.isNamedImports(bindings))
118
+ bindings.elements.forEach((e) => locals.set((e.propertyName ?? e.name).text, e.name.text));
119
+ }
120
+ const consumed = new Set();
121
+ const requested = new Map();
122
+ const icons = new Set();
123
+ for (const rewriteSource of mappings_1.SOURCE_REWRITERS) {
124
+ rewriteSource(sf, {
125
+ locals,
126
+ templates,
127
+ icons,
128
+ consume: (symbol) => consumed.add(symbol),
129
+ addImport: (name, entry) => {
130
+ if (existing.get(entry)?.has(name))
131
+ return;
132
+ requested.set(entry, (requested.get(entry) ?? new Set()).add(name));
133
+ },
134
+ }, edits);
135
+ }
136
+ for (const statement of sf.statements) {
137
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
138
+ continue;
139
+ const module = statement.moduleSpecifier.text;
140
+ const symbols = module === 'primeng/config' ? CONFIG_SYMBOLS : mappings_1.SYMBOLS.get(module);
141
+ const clause = statement.importClause;
142
+ const bindings = clause?.namedBindings;
143
+ if (!symbols || !clause || clause.name || !bindings || !ts.isNamedImports(bindings))
144
+ continue;
145
+ const quote = text[statement.moduleSpecifier.getStart(sf)];
146
+ const typePrefix = clause.isTypeOnly ? 'type ' : '';
147
+ const groups = new Map();
148
+ const kept = [];
149
+ let dropped = false;
150
+ for (const element of bindings.elements) {
151
+ const imported = (element.propertyName ?? element.name).text;
152
+ if (consumed.has(imported)) {
153
+ dropped = true;
154
+ continue;
155
+ }
156
+ const target = symbols.get(imported);
157
+ if (!target) {
158
+ kept.push(element.getText(sf));
159
+ continue;
160
+ }
161
+ const local = element.name.text;
162
+ if (module === 'primeng/config') {
163
+ providerLocal = local;
164
+ // Con provideCaribeNG() ya importado no hace falta importarlo otra vez.
165
+ if (existing.get(target.entry)?.has(target.name))
166
+ continue;
167
+ }
168
+ else if (!element.propertyName && local !== target.name)
169
+ renames.set(local, target.name);
170
+ const specifier = `${element.isTypeOnly ? 'type ' : ''}${element.propertyName ? `${target.name} as ${local}` : target.name}`;
171
+ const names = existing.get(target.entry) ?? new Set();
172
+ const group = groups.get(target.entry) ?? [];
173
+ if ((element.propertyName || !names.has(target.name)) && !group.includes(specifier))
174
+ group.push(specifier);
175
+ // Con alias el nombre local es otro: `CbDialog` sigue sin estar importado.
176
+ if (!element.propertyName)
177
+ names.add(target.name);
178
+ existing.set(target.entry, names);
179
+ groups.set(target.entry, group);
180
+ }
181
+ if (!groups.size && !dropped)
182
+ continue;
183
+ const lines = [...groups]
184
+ .filter(([, names]) => names.length)
185
+ .map(([entry, names]) => `import ${typePrefix}{ ${names.join(', ')} } from ${quote}${entry}${quote};`);
186
+ if (kept.length)
187
+ lines.push(`import ${typePrefix}{ ${kept.join(', ')} } from ${quote}${module}${quote};`);
188
+ const range = lines.length ? { start: statement.getStart(sf), end: statement.getEnd() } : statementRange(sf, statement);
189
+ edits.push({ ...range, text: lines.join(eol) });
190
+ }
191
+ // Si `ng add @caribeng/ui` ya registró provideCaribeNG(), providePrimeNG() se elimina en vez de sustituirse.
192
+ const hasCaribeProvider = /\bprovideCaribeNG\s*\(/.test(text);
193
+ const visit = (node) => {
194
+ if (ts.isImportDeclaration(node))
195
+ return;
196
+ if (providerLocal && ts.isCallExpression(node) && ts.isIdentifier(node.expression) && node.expression.text === providerLocal) {
197
+ if (hasCaribeProvider && ts.isArrayLiteralExpression(node.parent)) {
198
+ const elements = node.parent.elements;
199
+ const i = elements.indexOf(node);
200
+ edits.push(i > 0 ? { start: elements[i - 1].getEnd(), end: node.getEnd(), text: '' } : { start: node.getStart(sf), end: elements[1]?.getStart(sf) ?? node.getEnd(), text: '' });
201
+ return;
202
+ }
203
+ edits.push({
204
+ start: node.getStart(sf),
205
+ end: node.getEnd(),
206
+ text: `provideCaribeNG(${exports.PROVIDER_CONFIG}) /* ${template_1.TODO_MARK}: elige locale, theme y preset; la configuración de PrimeNG (tema, ripple, zIndex…) no se traslada. */`,
207
+ });
208
+ return;
209
+ }
210
+ if (ts.isIdentifier(node) && !isMemberName(node)) {
211
+ const renamed = renames.get(node.text);
212
+ if (renamed) {
213
+ const shorthand = ts.isShorthandPropertyAssignment(node.parent) && node.parent.name === node;
214
+ edits.push({ start: node.getStart(sf), end: node.getEnd(), text: shorthand ? `${node.text}: ${renamed}` : renamed });
215
+ }
216
+ }
217
+ ts.forEachChild(node, visit);
218
+ };
219
+ visit(sf);
220
+ // Imports pedidos por las reescrituras (p. ej. CbMenubarItem): tras el último import;
221
+ // mergeCaribeImports los une con los que ya hubiera del mismo entry point.
222
+ if (requested.size) {
223
+ const imports = sf.statements.filter(ts.isImportDeclaration);
224
+ const position = imports.length ? imports[imports.length - 1].getEnd() : 0;
225
+ const lines = [...requested].map(([entry, names]) => `import { ${[...names].join(', ')} } from '${entry}';`);
226
+ edits.push({ start: position, end: position, text: imports.length ? eol + lines.join(eol) : lines.join(eol) + eol });
227
+ }
228
+ if (!edits.length)
229
+ return { text, changed: false, icons };
230
+ const rewritten = mergeCaribeImports(fileName, cleanDecoratorArrays(fileName, (0, template_1.applyEdits)(text, edits)));
231
+ return { text: pruneUnusedImports(fileName, rewritten), changed: true, icons };
232
+ }
233
+ /**
234
+ * Limpia los arrays de los decoradores tras renombrar:
235
+ * - `imports: [ButtonModule, Button]` quedaría `[CbButton, CbButton]`: se deja uno.
236
+ * - `providers: [MessageService]` quedaría `[CbToastService]`: se quita, porque
237
+ * es `providedIn: 'root'` y una instancia local no compartiría los mensajes.
238
+ */
239
+ function cleanDecoratorArrays(fileName, text) {
240
+ const sf = parse(fileName, text);
241
+ const edits = [];
242
+ const visit = (node) => {
243
+ if (ts.isPropertyAssignment(node) && ts.isIdentifier(node.name) && ts.isArrayLiteralExpression(node.initializer)) {
244
+ const property = node.name.text;
245
+ const elements = node.initializer.elements;
246
+ if (['imports', 'exports', 'providers'].includes(property) && elements.length) {
247
+ const seen = new Set();
248
+ const kept = elements.filter((element) => {
249
+ if (!ts.isIdentifier(element))
250
+ return true;
251
+ const drop = seen.has(element.text) || (property === 'providers' && mappings_1.ROOT_SERVICES.has(element.text));
252
+ seen.add(element.text);
253
+ return !drop;
254
+ });
255
+ if (kept.length !== elements.length) {
256
+ const first = elements[0];
257
+ const last = elements[elements.length - 1];
258
+ const between = text.slice(first.getEnd(), elements[1]?.getStart(sf) ?? first.getEnd());
259
+ // Array en varias líneas: se conserva el separador original (coma + salto + sangría).
260
+ const separator = between.includes('\n') ? between : ', ';
261
+ edits.push({ start: first.getStart(sf), end: last.getEnd(), text: kept.map((element) => element.getText(sf)).join(separator) });
262
+ }
263
+ }
264
+ }
265
+ ts.forEachChild(node, visit);
266
+ };
267
+ visit(sf);
268
+ return edits.length ? (0, template_1.applyEdits)(text, edits) : text;
269
+ }
270
+ /**
271
+ * Une los imports del mismo entry point de CaribeNG (`MessageService` de
272
+ * primeng/api y `ToastModule` de primeng/toast acaban ambos en @caribeng/ui/toast).
273
+ */
274
+ function mergeCaribeImports(fileName, text) {
275
+ const sf = parse(fileName, text);
276
+ const first = new Map();
277
+ const extra = new Map();
278
+ const edits = [];
279
+ for (const statement of sf.statements) {
280
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
281
+ continue;
282
+ const clause = statement.importClause;
283
+ const module = statement.moduleSpecifier.text;
284
+ if (!module.startsWith('@caribeng/') || !clause || clause.name || clause.isTypeOnly || !clause.namedBindings || !ts.isNamedImports(clause.namedBindings))
285
+ continue;
286
+ const target = first.get(module);
287
+ if (!target) {
288
+ first.set(module, statement);
289
+ continue;
290
+ }
291
+ const names = extra.get(target) ?? [];
292
+ names.push(...clause.namedBindings.elements.map((element) => element.getText(sf)));
293
+ extra.set(target, names);
294
+ edits.push({ ...statementRange(sf, statement), text: '' });
295
+ }
296
+ for (const [target, names] of extra) {
297
+ const elements = target.importClause.namedBindings.elements;
298
+ const present = new Set(elements.map((element) => element.getText(sf)));
299
+ const missing = [...new Set(names)].filter((name) => !present.has(name));
300
+ if (missing.length)
301
+ edits.push({ start: elements[elements.length - 1].getEnd(), end: elements[elements.length - 1].getEnd(), text: `, ${missing.join(', ')}` });
302
+ }
303
+ return edits.length ? (0, template_1.applyEdits)(text, edits) : text;
304
+ }
305
+ /** Quita los imports de `@primeuix/*` y `primeng/config` que ya nada usa (p. ej. el preset `Aura`). */
306
+ function pruneUnusedImports(fileName, text) {
307
+ const sf = parse(fileName, text);
308
+ const used = new Set();
309
+ const collect = (node) => {
310
+ if (ts.isImportDeclaration(node))
311
+ return;
312
+ if (ts.isIdentifier(node) && !isMemberName(node))
313
+ used.add(node.text);
314
+ ts.forEachChild(node, collect);
315
+ };
316
+ collect(sf);
317
+ const edits = [];
318
+ for (const statement of sf.statements) {
319
+ if (!ts.isImportDeclaration(statement) || !ts.isStringLiteral(statement.moduleSpecifier))
320
+ continue;
321
+ if (!PRUNABLE_MODULES.test(statement.moduleSpecifier.text) || !statement.importClause)
322
+ continue;
323
+ const clause = statement.importClause;
324
+ const locals = [clause.name?.text, ...(clause.namedBindings && ts.isNamedImports(clause.namedBindings) ? clause.namedBindings.elements.map((e) => e.name.text) : [])];
325
+ if (clause.namedBindings && ts.isNamespaceImport(clause.namedBindings))
326
+ locals.push(clause.namedBindings.name.text);
327
+ if (locals.every((local) => !local || !used.has(local)))
328
+ edits.push({ ...statementRange(sf, statement), text: '' });
329
+ }
330
+ return edits.length ? (0, template_1.applyEdits)(text, edits) : text;
331
+ }
332
+ function componentDecorators(sf) {
333
+ const found = [];
334
+ const visit = (node) => {
335
+ if (ts.isDecorator(node) && ts.isCallExpression(node.expression) && ts.isIdentifier(node.expression.expression) && node.expression.expression.text === 'Component') {
336
+ const [config] = node.expression.arguments;
337
+ if (config && ts.isObjectLiteralExpression(config))
338
+ found.push(config);
339
+ }
340
+ ts.forEachChild(node, visit);
341
+ };
342
+ visit(sf);
343
+ return found;
344
+ }
345
+ function property(config, name) {
346
+ return config.properties.find((p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && p.name.text === name);
347
+ }
348
+ /** Componentes del archivo con su plantilla. */
349
+ function findComponents(fileName, text) {
350
+ return componentDecorators(parse(fileName, text)).map((config, index) => {
351
+ const template = property(config, 'template')?.initializer;
352
+ const templateUrl = property(config, 'templateUrl')?.initializer;
353
+ const standalone = property(config, 'standalone')?.initializer;
354
+ return {
355
+ index,
356
+ inlineTemplate: template && ts.isStringLiteralLike(template) ? template.text : undefined,
357
+ templateUrl: templateUrl && ts.isStringLiteralLike(templateUrl) ? templateUrl.text : undefined,
358
+ declaredInModule: standalone?.kind === ts.SyntaxKind.FalseKeyword,
359
+ };
360
+ });
361
+ }
362
+ /** Sustituye la plantilla en línea del componente `index` (se escribe como template literal). */
363
+ function replaceInlineTemplate(fileName, text, index, template) {
364
+ const literal = property(componentDecorators(parse(fileName, text))[index], 'template').initializer;
365
+ const escaped = template.replace(/\\/g, '\\\\').replace(/`/g, '\\`').replace(/\$\{/g, '\\${');
366
+ return (0, template_1.applyEdits)(text, [{ start: literal.getStart(), end: literal.getEnd(), text: `\`${escaped}\`` }]);
367
+ }
368
+ /**
369
+ * Añade al `imports` de cada componente los símbolos CaribeNG que usa su
370
+ * plantilla, y sus `import` de TypeScript. Devuelve también los que no se
371
+ * pudieron añadir (componentes de NgModule o con `imports` no literal).
372
+ */
373
+ function ensureComponentImports(fileName, text, needed) {
374
+ const sf = parse(fileName, text);
375
+ const decorators = componentDecorators(sf);
376
+ const edits = [];
377
+ const manual = [];
378
+ const toImport = new Map();
379
+ const existing = caribeImports(sf);
380
+ const eol = newline(text);
381
+ for (const [index, symbols] of needed) {
382
+ const config = decorators[index];
383
+ if (!config || !symbols.length)
384
+ continue;
385
+ const standalone = property(config, 'standalone')?.initializer;
386
+ const imports = property(config, 'imports');
387
+ const names = symbols.map((s) => s.name);
388
+ if (standalone?.kind === ts.SyntaxKind.FalseKeyword || (imports && !ts.isArrayLiteralExpression(imports.initializer))) {
389
+ manual.push(...names);
390
+ continue;
391
+ }
392
+ const present = new Set(imports && ts.isArrayLiteralExpression(imports.initializer) ? imports.initializer.elements.map((e) => e.getText(sf)) : []);
393
+ const missing = symbols.filter((s) => !present.has(s.name));
394
+ if (missing.length) {
395
+ const list = missing.map((s) => s.name).join(', ');
396
+ if (imports && ts.isArrayLiteralExpression(imports.initializer)) {
397
+ const array = imports.initializer;
398
+ const last = array.elements[array.elements.length - 1];
399
+ if (last)
400
+ edits.push({ start: last.getEnd(), end: last.getEnd(), text: `, ${list}` });
401
+ else
402
+ edits.push({ start: array.getStart(sf) + 1, end: array.getEnd() - 1, text: list });
403
+ }
404
+ else {
405
+ const last = config.properties[config.properties.length - 1];
406
+ const indent = /[ \t]*$/.exec(text.slice(0, last.getStart(sf)))?.[0] ?? ' ';
407
+ edits.push({ start: last.getEnd(), end: last.getEnd(), text: `,${eol}${indent}imports: [${list}]` });
408
+ }
409
+ }
410
+ for (const symbol of symbols) {
411
+ if (existing.get(symbol.entry)?.has(symbol.name))
412
+ continue;
413
+ const set = toImport.get(symbol.entry) ?? new Set();
414
+ set.add(symbol.name);
415
+ toImport.set(symbol.entry, set);
416
+ }
417
+ }
418
+ if (toImport.size) {
419
+ const declarations = sf.statements.filter(ts.isImportDeclaration);
420
+ const lastImport = declarations[declarations.length - 1];
421
+ const newLines = [];
422
+ for (const [entry, names] of [...toImport].sort(([a], [b]) => a.localeCompare(b))) {
423
+ const current = declarations.find((d) => ts.isStringLiteral(d.moduleSpecifier) && d.moduleSpecifier.text === entry && !d.importClause?.isTypeOnly && d.importClause?.namedBindings && ts.isNamedImports(d.importClause.namedBindings));
424
+ const elements = current && current.importClause.namedBindings.elements;
425
+ if (elements?.length) {
426
+ const end = elements[elements.length - 1].getEnd();
427
+ edits.push({ start: end, end, text: `, ${[...names].join(', ')}` });
428
+ }
429
+ else {
430
+ newLines.push(`import { ${[...names].join(', ')} } from '${entry}';`);
431
+ }
432
+ }
433
+ if (newLines.length) {
434
+ const position = lastImport ? lastImport.getEnd() : 0;
435
+ const block = newLines.join(eol);
436
+ edits.push({ start: position, end: position, text: lastImport ? `${eol}${block}` : `${block}${eol}` });
437
+ }
438
+ }
439
+ if (!edits.length)
440
+ return { text, changed: false, manual };
441
+ return { text: (0, template_1.applyEdits)(text, edits), changed: true, manual };
442
+ }
@@ -0,0 +1,117 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PRIME_PACKAGES = void 0;
4
+ exports.workspaceFiles = workspaceFiles;
5
+ exports.readPackageJson = readPackageJson;
6
+ exports.dependencyVersion = dependencyVersion;
7
+ exports.majorOf = majorOf;
8
+ exports.removePrimeDependencies = removePrimeDependencies;
9
+ exports.removePrimeStyleEntries = removePrimeStyleEntries;
10
+ exports.removePrimeStyleImports = removePrimeStyleImports;
11
+ /** Carpetas que nunca se recorren (dependencias, salidas de build, cachés). */
12
+ const SKIP_DIRS = new Set(['node_modules', 'dist', 'tmp', 'out-tsc', 'coverage', '.git', '.angular', '.nx', '.cache', '.vscode', '.idea']);
13
+ /** Archivos del workspace bajo `root`, sin entrar en {@link SKIP_DIRS}. */
14
+ function workspaceFiles(tree, root = '/') {
15
+ const files = [];
16
+ const walk = (path) => {
17
+ const dir = tree.getDir(path);
18
+ for (const file of dir.subfiles)
19
+ files.push(`${dir.path === '/' ? '' : dir.path}/${file}`);
20
+ for (const sub of dir.subdirs)
21
+ if (!SKIP_DIRS.has(sub))
22
+ walk(`${dir.path === '/' ? '' : dir.path}/${sub}`);
23
+ };
24
+ walk(root);
25
+ return files;
26
+ }
27
+ /** Paquetes del ecosistema PrimeNG que se quitan al terminar (si ya nada los usa). */
28
+ exports.PRIME_PACKAGES = ['primeng', 'primeicons', '@primeuix/themes', '@primeuix/styled', '@primeuix/styles', '@primeuix/utils', '@primeuix/motion', 'tailwindcss-primeui', 'primelocale'];
29
+ const DEPENDENCY_FIELDS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
30
+ function readPackageJson(tree) {
31
+ const raw = tree.exists('/package.json') ? tree.readText('/package.json') : null;
32
+ return raw ? JSON.parse(raw) : null;
33
+ }
34
+ /** Versión declarada de un paquete, o `null`. */
35
+ function dependencyVersion(pkg, name) {
36
+ for (const field of DEPENDENCY_FIELDS) {
37
+ const version = pkg[field]?.[name];
38
+ if (version)
39
+ return version;
40
+ }
41
+ return null;
42
+ }
43
+ /** Major de una versión de package.json (`^21.1.0` → 21). `null` si no es numérica (`latest`, `workspace:*`…). */
44
+ function majorOf(version) {
45
+ const match = /(\d+)\./.exec(version) ?? /^\D*(\d+)$/.exec(version);
46
+ return match ? Number(match[1]) : null;
47
+ }
48
+ /** Quita los paquetes de PrimeNG de package.json. Devuelve los que quitó. */
49
+ function removePrimeDependencies(tree) {
50
+ const raw = tree.readText('/package.json');
51
+ const pkg = JSON.parse(raw);
52
+ const removed = [];
53
+ for (const field of DEPENDENCY_FIELDS) {
54
+ const deps = pkg[field];
55
+ if (!deps)
56
+ continue;
57
+ for (const name of exports.PRIME_PACKAGES) {
58
+ if (name in deps) {
59
+ delete deps[name];
60
+ removed.push(name);
61
+ }
62
+ }
63
+ }
64
+ if (removed.length) {
65
+ const indent = /^\{\r?\n([ \t]+)/.exec(raw)?.[1] ?? ' ';
66
+ tree.overwrite('/package.json', JSON.stringify(pkg, null, indent) + '\n');
67
+ }
68
+ return removed;
69
+ }
70
+ /** Hoja de PrimeIcons o un tema CSS antiguo de PrimeNG (`primeng/resources/…`). */
71
+ const PRIME_STYLESHEET = /primeicons|primeng\/resources/;
72
+ /** Quita PrimeIcons y los temas CSS de PrimeNG de los `styles` de angular.json/project.json. */
73
+ function removePrimeStyleEntries(tree, path, context) {
74
+ const raw = tree.readText(path);
75
+ let config;
76
+ try {
77
+ config = JSON.parse(raw);
78
+ }
79
+ catch {
80
+ context.logger.warn(`${path}: no es JSON válido; revisa a mano si incluye primeicons.css.`);
81
+ return false;
82
+ }
83
+ let changed = false;
84
+ const visit = (node) => {
85
+ if (Array.isArray(node))
86
+ return node.forEach(visit);
87
+ if (!node || typeof node !== 'object')
88
+ return;
89
+ for (const [key, value] of Object.entries(node)) {
90
+ if (key === 'styles' && Array.isArray(value)) {
91
+ const kept = value.filter((entry) => {
92
+ const input = typeof entry === 'string' ? entry : entry?.input;
93
+ return !(typeof input === 'string' && PRIME_STYLESHEET.test(input));
94
+ });
95
+ if (kept.length !== value.length) {
96
+ node[key] = kept;
97
+ changed = true;
98
+ }
99
+ }
100
+ else {
101
+ visit(value);
102
+ }
103
+ }
104
+ };
105
+ visit(config);
106
+ if (changed) {
107
+ const indent = /^\{\r?\n([ \t]+)/.exec(raw)?.[1] ?? ' ';
108
+ tree.overwrite(path, JSON.stringify(config, null, indent) + '\n');
109
+ }
110
+ return changed;
111
+ }
112
+ /** `@import 'primeicons/primeicons.css';` y similares. */
113
+ const PRIME_STYLE_IMPORT = /^[ \t]*@(import|use|forward)\s+(url\()?\s*['"]?[^'"\n]*(primeicons|primeng\/resources)[^'"\n]*['"]?\s*\)?[^;\n]*;?[ \t]*\r?\n?/gm;
114
+ /** Quita los `@import` de PrimeIcons de una hoja de estilos global. */
115
+ function removePrimeStyleImports(text) {
116
+ return text.replace(PRIME_STYLE_IMPORT, '');
117
+ }
@@ -3,6 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.CARIBENG_STYLES = void 0;
4
4
  exports.ngAdd = ngAdd;
5
5
  exports.providerConfig = providerConfig;
6
+ exports.projectSourceRoot = projectSourceRoot;
7
+ exports.addStyles = addStyles;
8
+ exports.containsText = containsText;
6
9
  const schematics_1 = require("@angular-devkit/schematics");
7
10
  const utility_1 = require("@schematics/angular/utility");
8
11
  /** Hoja de estilos de CaribeNG (export `./styles.css` del paquete). */
@@ -97,7 +100,7 @@ function containsText(tree, root, text) {
97
100
  return found;
98
101
  }
99
102
  function logNextSteps(options) {
100
- return (_tree, context) => {
103
+ return (tree, context) => {
101
104
  const es = options.locale !== 'en';
102
105
  const lines = es
103
106
  ? [
@@ -121,5 +124,17 @@ function logNextSteps(options) {
121
124
  '',
122
125
  ];
123
126
  lines.forEach((line) => context.logger.info(line));
127
+ if (usesPrimeng(tree)) {
128
+ context.logger.warn(es
129
+ ? '⚠ Este proyecto usa PrimeNG. Para migrar sus componentes a CaribeNG ejecuta:\n ng generate @caribeng/ui:migrate-from-primeng'
130
+ : '⚠ This project uses PrimeNG. To migrate its components to CaribeNG run:\n ng generate @caribeng/ui:migrate-from-primeng');
131
+ }
124
132
  };
125
133
  }
134
+ /** `primeng` aparece en las dependencias del package.json raíz. */
135
+ function usesPrimeng(tree) {
136
+ if (!tree.exists('/package.json'))
137
+ return false;
138
+ const pkg = JSON.parse(tree.readText('/package.json'));
139
+ return Boolean(pkg['dependencies']?.['primeng'] ?? pkg['devDependencies']?.['primeng']);
140
+ }
@@ -19,8 +19,10 @@ declare class CbBadge {
19
19
  readonly size: _angular_core.InputSignal<CbSize>;
20
20
  /** Muestra solo un punto (sin texto). */
21
21
  readonly dot: _angular_core.InputSignalWithTransform<boolean, unknown>;
22
+ /** Nombre accesible que sustituye al valor (p. ej. "3 mensajes sin leer"). Sin él, un `dot` es decorativo. */
23
+ readonly ariaLabel: _angular_core.InputSignal<string>;
22
24
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<CbBadge, never>;
23
- static ɵcmp: _angular_core.ɵɵComponentDeclaration<CbBadge, "cb-badge", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "severity": { "alias": "severity"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
25
+ static ɵcmp: _angular_core.ɵɵComponentDeclaration<CbBadge, "cb-badge", never, { "value": { "alias": "value"; "required": false; "isSignal": true; }; "severity": { "alias": "severity"; "required": false; "isSignal": true; }; "size": { "alias": "size"; "required": false; "isSignal": true; }; "dot": { "alias": "dot"; "required": false; "isSignal": true; }; "ariaLabel": { "alias": "ariaLabel"; "required": false; "isSignal": true; }; }, {}, never, never, true, never>;
24
26
  }
25
27
 
26
28
  export { CbBadge };
@@ -1,5 +1,6 @@
1
1
  import * as _angular_core from '@angular/core';
2
2
  import * as _caribeng_ui from '@caribeng/ui';
3
+ import { CbMenuCommandEvent } from '@caribeng/ui';
3
4
 
4
5
  interface CbBreadcrumbItem {
5
6
  label: string;
@@ -7,6 +8,10 @@ interface CbBreadcrumbItem {
7
8
  url?: string;
8
9
  /** Icono (nombre del set de @caribeng/ui/icon) antes del texto. */
9
10
  icon?: string;
11
+ /** Acción al elegir el item (además del evento de selección), como `command` en PrimeNG. */
12
+ command?: (event: CbMenuCommandEvent<CbBreadcrumbItem>) => void;
13
+ /** `false` oculta el item. */
14
+ visible?: boolean;
10
15
  }
11
16
  /**
12
17
  * Breadcrumb de CaribeNG: rastro de navegación jerárquica.
@@ -24,10 +29,13 @@ declare class CbBreadcrumb {
24
29
  /** Textos de interfaz en el idioma activo (`provideCaribeNG({ locale })`). */
25
30
  protected readonly t: _angular_core.Signal<_caribeng_ui.CbTranslation>;
26
31
  readonly items: _angular_core.InputSignal<readonly CbBreadcrumbItem[]>;
32
+ /** Items sin los de `visible: false`. */
33
+ protected readonly visibleItems: _angular_core.Signal<CbBreadcrumbItem[]>;
27
34
  /** Icono separador entre elementos. */
28
35
  readonly separator: _angular_core.InputSignal<string>;
29
36
  /** Se emite al hacer clic en un elemento con enlace. */
30
37
  readonly itemClick: _angular_core.OutputEmitterRef<CbBreadcrumbItem>;
38
+ protected select(item: CbBreadcrumbItem, event: MouseEvent): void;
31
39
  static ɵfac: _angular_core.ɵɵFactoryDeclaration<CbBreadcrumb, never>;
32
40
  static ɵcmp: _angular_core.ɵɵComponentDeclaration<CbBreadcrumb, "cb-breadcrumb", never, { "items": { "alias": "items"; "required": false; "isSignal": true; }; "separator": { "alias": "separator"; "required": false; "isSignal": true; }; }, { "itemClick": "itemClick"; }, never, never, true, never>;
33
41
  }
@@ -213,8 +213,10 @@ declare class CbChart {
213
213
  readonly sparkline: _angular_core.InputSignalWithTransform<boolean, unknown>;
214
214
  /** Formato de los valores (ejes, tooltip y tabla). */
215
215
  readonly valueFormat: _angular_core.InputSignal<CbChartValueFormat | undefined>;
216
- /** Locale BCP 47 para el formato (por defecto, el del navegador). */
216
+ /** Locale BCP 47 para el formato (por defecto, el del idioma activo de CaribeNG: `intlLocale`). */
217
217
  readonly locale: _angular_core.InputSignal<string | undefined>;
218
+ /** Locale efectivo: el input o, si no se indica, el del idioma activo. */
219
+ protected readonly intlLocale: _angular_core.Signal<string>;
218
220
  /** Valor mínimo del medidor (`gauge`). */
219
221
  readonly min: _angular_core.InputSignal<number>;
220
222
  /** Valor que representa el 100 % en `radialBar` y el máximo del medidor (`gauge`). */