@c80/ui 0.0.1 → 1.0.1

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.
package/esm2022/index.mjs CHANGED
@@ -1,2 +1,3 @@
1
- export * from './lib/ui/ui.component';
2
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWJzL3VpL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHVCQUF1QixDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiZXhwb3J0ICogZnJvbSAnLi9saWIvdWkvdWkuY29tcG9uZW50JztcbiJdfQ==
1
+ export * from './lib/table/table.component';
2
+ export * from './lib/icon/icon.component';
3
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi9saWJzL3VpL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMsMkJBQTJCLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyJleHBvcnQgKiBmcm9tICcuL2xpYi90YWJsZS90YWJsZS5jb21wb25lbnQnO1xuZXhwb3J0ICogZnJvbSAnLi9saWIvaWNvbi9pY29uLmNvbXBvbmVudCc7XG4iXX0=
@@ -0,0 +1,121 @@
1
+ import { Component, Input, Output, EventEmitter, ViewChild } from '@angular/core';
2
+ import { CommonModule } from '@angular/common';
3
+ import * as i0 from "@angular/core";
4
+ import * as i1 from "@angular/common";
5
+ export class C80IconComponent {
6
+ /** Tamaño base del icono (en px) */
7
+ get iconSize() {
8
+ return 24 * this.size;
9
+ }
10
+ icon = 'check';
11
+ color = 'primary';
12
+ disabled = false;
13
+ size = 1;
14
+ /** Si es true, renderiza como <button> nativo, si es false solo como icono */
15
+ _button = false;
16
+ set button(val) {
17
+ // Permite usar 'button' a secas, cualquier valor que no sea null/undefined/false es true
18
+ this._button = val !== null && val !== undefined && val !== false && val !== 'false';
19
+ }
20
+ get button() {
21
+ return this._button;
22
+ }
23
+ /** Tipo de botón nativo (solo si button=true) */
24
+ type = 'button';
25
+ /** Output para click (solo si button=true) */
26
+ iconClick = new EventEmitter();
27
+ checkIconTpl;
28
+ cancelIconTpl;
29
+ editIconTpl;
30
+ deleteIconTpl;
31
+ addIconTpl;
32
+ defaultIconTpl;
33
+ getIconTemplate() {
34
+ switch (this.icon) {
35
+ case 'check': return this.checkIconTpl;
36
+ case 'cancel': return this.cancelIconTpl;
37
+ case 'edit': return this.editIconTpl;
38
+ case 'delete': return this.deleteIconTpl;
39
+ case 'add': return this.addIconTpl;
40
+ default: return this.defaultIconTpl;
41
+ }
42
+ }
43
+ get iconColor() {
44
+ if (this.disabled) {
45
+ return '#bdbdbd'; // gris deshabilitado
46
+ }
47
+ const palettes = {
48
+ check: {
49
+ primary: '#00234bad',
50
+ secondary: '#6c757d',
51
+ warn: '#e53935',
52
+ },
53
+ cancel: {
54
+ primary: '#00234bad',
55
+ secondary: '#6c757d',
56
+ warn: '#e53935',
57
+ },
58
+ edit: {
59
+ primary: '#00234bad',
60
+ secondary: '#6c757d',
61
+ warn: '#e53935',
62
+ },
63
+ delete: {
64
+ primary: '#00234bad',
65
+ secondary: '#6c757d',
66
+ warn: '#e53935',
67
+ },
68
+ add: {
69
+ primary: '#00234bad',
70
+ secondary: '#6c757d',
71
+ warn: '#e53935',
72
+ }
73
+ };
74
+ return palettes[this.icon]?.[this.color] ?? '#222';
75
+ }
76
+ // Handler para click en modo button
77
+ onButtonClick(event) {
78
+ if (!this.disabled) {
79
+ this.iconClick.emit(event);
80
+ }
81
+ }
82
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C80IconComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
83
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: C80IconComponent, isStandalone: true, selector: "c80-icon", inputs: { icon: "icon", color: "color", disabled: "disabled", size: "size", button: "button", type: "type" }, outputs: { iconClick: "iconClick" }, viewQueries: [{ propertyName: "checkIconTpl", first: true, predicate: ["checkIcon"], descendants: true, static: true }, { propertyName: "cancelIconTpl", first: true, predicate: ["cancelIcon"], descendants: true, static: true }, { propertyName: "editIconTpl", first: true, predicate: ["editIcon"], descendants: true, static: true }, { propertyName: "deleteIconTpl", first: true, predicate: ["deleteIcon"], descendants: true, static: true }, { propertyName: "addIconTpl", first: true, predicate: ["addIcon"], descendants: true, static: true }, { propertyName: "defaultIconTpl", first: true, predicate: ["defaultIcon"], descendants: true, static: true }], ngImport: i0, template: "@if (button) {\r\n<button type=\"{{type}}\" [disabled]=\"disabled\" class=\"icon-button\" [style.width.px]=\"iconSize + 8\"\r\n [style.height.px]=\"iconSize + 8\" (click)=\"onButtonClick($event)\">\r\n <ng-container *ngTemplateOutlet=\"getIconTemplate()\"></ng-container>\r\n</button>\r\n} @else {\r\n<span class=\"icon-span\" [style.width.px]=\"iconSize\" [style.height.px]=\"iconSize\">\r\n <ng-container *ngTemplateOutlet=\"getIconTemplate()\"></ng-container>\r\n</span>\r\n}\r\n\r\n<ng-template #checkIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M5 13l4 4L19 7\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #cancelIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M6 6l12 12M6 18L18 6\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #editIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <rect x=\"5\" y=\"19\" width=\"14\" height=\"2\" rx=\"1\" [attr.fill]=\"iconColor\" />\r\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #deleteIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M6 19a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\" [attr.fill]=\"iconColor\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #addIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M12 5v14M5 12h14\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #defaultIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" />\r\n </svg>\r\n</ng-template>", styles: [":host .icon-button{display:inline-flex;align-items:center;justify-content:center;border:none;outline:none;background:transparent;border-radius:50%;min-width:0;min-height:0;padding:4px;cursor:pointer;transition:background .2s;box-sizing:border-box}:host .icon-button:focus-visible{outline:2px solid #1976d2;outline-offset:2px}:host .icon-button:hover:not(:disabled){background:#1976d214}:host .icon-button:active:not(:disabled){background:#1976d229}:host .icon-button:disabled{opacity:.5;cursor:default;background:transparent}:host .icon-span,:host .icon-button{margin-left:4px;margin-right:4px}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] });
84
+ }
85
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C80IconComponent, decorators: [{
86
+ type: Component,
87
+ args: [{ selector: 'c80-icon', standalone: true, imports: [CommonModule], template: "@if (button) {\r\n<button type=\"{{type}}\" [disabled]=\"disabled\" class=\"icon-button\" [style.width.px]=\"iconSize + 8\"\r\n [style.height.px]=\"iconSize + 8\" (click)=\"onButtonClick($event)\">\r\n <ng-container *ngTemplateOutlet=\"getIconTemplate()\"></ng-container>\r\n</button>\r\n} @else {\r\n<span class=\"icon-span\" [style.width.px]=\"iconSize\" [style.height.px]=\"iconSize\">\r\n <ng-container *ngTemplateOutlet=\"getIconTemplate()\"></ng-container>\r\n</span>\r\n}\r\n\r\n<ng-template #checkIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M5 13l4 4L19 7\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" stroke-linecap=\"round\"\r\n stroke-linejoin=\"round\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #cancelIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M6 6l12 12M6 18L18 6\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #editIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <rect x=\"5\" y=\"19\" width=\"14\" height=\"2\" rx=\"1\" [attr.fill]=\"iconColor\" />\r\n <path d=\"M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #deleteIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M6 19a2 2 0 0 0 2 2h8a2 2 0 0 0 2-2V7H6v12zM19 4h-3.5l-1-1h-5l-1 1H5v2h14V4z\" [attr.fill]=\"iconColor\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #addIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <path d=\"M12 5v14M5 12h14\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" stroke-linecap=\"round\" />\r\n </svg>\r\n</ng-template>\r\n<ng-template #defaultIcon>\r\n <svg [attr.width]=\"iconSize\" [attr.height]=\"iconSize\" viewBox=\"0 0 24 24\" fill=\"none\">\r\n <circle cx=\"12\" cy=\"12\" r=\"10\" [attr.stroke]=\"iconColor\" stroke-width=\"2\" />\r\n </svg>\r\n</ng-template>", styles: [":host .icon-button{display:inline-flex;align-items:center;justify-content:center;border:none;outline:none;background:transparent;border-radius:50%;min-width:0;min-height:0;padding:4px;cursor:pointer;transition:background .2s;box-sizing:border-box}:host .icon-button:focus-visible{outline:2px solid #1976d2;outline-offset:2px}:host .icon-button:hover:not(:disabled){background:#1976d214}:host .icon-button:active:not(:disabled){background:#1976d229}:host .icon-button:disabled{opacity:.5;cursor:default;background:transparent}:host .icon-span,:host .icon-button{margin-left:4px;margin-right:4px}\n"] }]
88
+ }], propDecorators: { icon: [{
89
+ type: Input
90
+ }], color: [{
91
+ type: Input
92
+ }], disabled: [{
93
+ type: Input
94
+ }], size: [{
95
+ type: Input
96
+ }], button: [{
97
+ type: Input
98
+ }], type: [{
99
+ type: Input
100
+ }], iconClick: [{
101
+ type: Output
102
+ }], checkIconTpl: [{
103
+ type: ViewChild,
104
+ args: ['checkIcon', { static: true }]
105
+ }], cancelIconTpl: [{
106
+ type: ViewChild,
107
+ args: ['cancelIcon', { static: true }]
108
+ }], editIconTpl: [{
109
+ type: ViewChild,
110
+ args: ['editIcon', { static: true }]
111
+ }], deleteIconTpl: [{
112
+ type: ViewChild,
113
+ args: ['deleteIcon', { static: true }]
114
+ }], addIconTpl: [{
115
+ type: ViewChild,
116
+ args: ['addIcon', { static: true }]
117
+ }], defaultIconTpl: [{
118
+ type: ViewChild,
119
+ args: ['defaultIcon', { static: true }]
120
+ }] } });
121
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaWNvbi5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9saWJzL3VpL3NyYy9saWIvaWNvbi9pY29uLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL2xpYnMvdWkvc3JjL2xpYi9pY29uL2ljb24uY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQWUsTUFBTSxlQUFlLENBQUM7QUFDL0YsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLGlCQUFpQixDQUFDOzs7QUFZL0MsTUFBTSxPQUFPLGdCQUFnQjtJQUMzQixvQ0FBb0M7SUFDcEMsSUFBSSxRQUFRO1FBQ1YsT0FBTyxFQUFFLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQztJQUN4QixDQUFDO0lBQ1EsSUFBSSxHQUFTLE9BQU8sQ0FBQztJQUNyQixLQUFLLEdBQVUsU0FBUyxDQUFDO0lBQ3pCLFFBQVEsR0FBYSxLQUFLLENBQUM7SUFDM0IsSUFBSSxHQUFHLENBQUMsQ0FBQztJQUNsQiw4RUFBOEU7SUFDdEUsT0FBTyxHQUFHLEtBQUssQ0FBQztJQUN4QixJQUNJLE1BQU0sQ0FBQyxHQUF3QztRQUNqRCx5RkFBeUY7UUFDekYsSUFBSSxDQUFDLE9BQU8sR0FBRyxHQUFHLEtBQUssSUFBSSxJQUFJLEdBQUcsS0FBSyxTQUFTLElBQUksR0FBRyxLQUFLLEtBQUssSUFBSSxHQUFHLEtBQUssT0FBTyxDQUFDO0lBQ3ZGLENBQUM7SUFDRCxJQUFJLE1BQU07UUFDUixPQUFPLElBQUksQ0FBQyxPQUFPLENBQUM7SUFDdEIsQ0FBQztJQUNELGlEQUFpRDtJQUN4QyxJQUFJLEdBQWtDLFFBQVEsQ0FBQztJQUN4RCw4Q0FBOEM7SUFDcEMsU0FBUyxHQUFHLElBQUksWUFBWSxFQUFTLENBQUM7SUFFTixZQUFZLENBQXdCO0lBQ25DLGFB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QVM7dUJBQUMsU0FBUyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDTSxjQUFjO3NCQUF6RCxTQUFTO3VCQUFDLGFBQWEsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPdXRwdXQsIEV2ZW50RW1pdHRlciwgVmlld0NoaWxkLCBUZW1wbGF0ZVJlZiB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xyXG5pbXBvcnQgeyBDb21tb25Nb2R1bGUgfSBmcm9tICdAYW5ndWxhci9jb21tb24nO1xyXG5cclxuZXhwb3J0IHR5cGUgSWNvbiA9ICdjaGVjaycgfCAnY2FuY2VsJyB8ICdlZGl0JyB8ICdkZWxldGUnIHwgJ2FkZCc7XHJcbmV4cG9ydCB0eXBlIENvbG9yID0gJ3ByaW1hcnknIHwgJ3NlY29uZGFyeScgfCAnd2Fybic7XHJcblxyXG5AQ29tcG9uZW50KHtcclxuICBzZWxlY3RvcjogJ2M4MC1pY29uJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9pY29uLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybHM6IFsnLi9pY29uLmNvbXBvbmVudC5zY3NzJ11cclxufSlcclxuZXhwb3J0IGNsYXNzIEM4MEljb25Db21wb25lbnQge1xyXG4gIC8qKiBUYW1hw7FvIGJhc2UgZGVsIGljb25vIChlbiBweCkgKi9cclxuICBnZXQgaWNvblNpemUoKTogbnVtYmVyIHtcclxuICAgIHJldHVybiAyNCAqIHRoaXMuc2l6ZTtcclxuICB9XHJcbiAgQElucHV0KCkgaWNvbjogSWNvbiA9ICdjaGVjayc7XHJcbiAgQElucHV0KCkgY29sb3I6IENvbG9yID0gJ3ByaW1hcnknO1xyXG4gIEBJbnB1dCgpIGRpc2FibGVkPzogYm9vbGVhbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpIHNpemUgPSAxO1xyXG4gIC8qKiBTaSBlcyB0cnVlLCByZW5kZXJpemEgY29tbyA8YnV0dG9uPiBuYXRpdm8sIHNpIGVzIGZhbHNlIHNvbG8gY29tbyBpY29ubyAqL1xyXG4gIHByaXZhdGUgX2J1dHRvbiA9IGZhbHNlO1xyXG4gIEBJbnB1dCgpXHJcbiAgc2V0IGJ1dHRvbih2YWw6IGJvb2xlYW4gfCBzdHJpbmcgfCBudWxsIHwgdW5kZWZpbmVkKSB7XHJcbiAgICAvLyBQZXJtaXRlIHVzYXIgJ2J1dHRvbicgYSBzZWNhcywgY3VhbHF1aWVyIHZhbG9yIHF1ZSBubyBzZWEgbnVsbC91bmRlZmluZWQvZmFsc2UgZXMgdHJ1ZVxyXG4gICAgdGhpcy5fYnV0dG9uID0gdmFsICE9PSBudWxsICYmIHZhbCAhPT0gdW5kZWZpbmVkICYmIHZhbCAhPT0gZmFsc2UgJiYgdmFsICE9PSAnZmFsc2UnO1xyXG4gIH1cclxuICBnZXQgYnV0dG9uKCk6IGJvb2xlYW4ge1xyXG4gICAgcmV0dXJuIHRoaXMuX2J1dHRvbjtcclxuICB9XHJcbiAgLyoqIFRpcG8gZGUgYm90w7NuIG5hdGl2byAoc29sbyBzaSBidXR0b249dHJ1ZSkgKi9cclxuICBASW5wdXQoKSB0eXBlOiAnYnV0dG9uJyB8ICdzdWJtaXQnIHwgJ3Jlc2V0JyA9ICdidXR0b24nO1xyXG4gIC8qKiBPdXRwdXQgcGFyYSBjbGljayAoc29sbyBzaSBidXR0b249dHJ1ZSkgKi9cclxuICBAT3V0cHV0KCkgaWNvbkNsaWNrID0gbmV3IEV2ZW50RW1pdHRlcjxFdmVudD4oKTtcclxuXHJcbiAgQFZpZXdDaGlsZCgnY2hlY2tJY29uJywgeyBzdGF0aWM6IHRydWUgfSkgY2hlY2tJY29uVHBsITogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcbiAgQFZpZXdDaGlsZCgnY2FuY2VsSWNvbicsIHsgc3RhdGljOiB0cnVlIH0pIGNhbmNlbEljb25UcGwhOiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuICBAVmlld0NoaWxkKCdlZGl0SWNvbicsIHsgc3RhdGljOiB0cnVlIH0pIGVkaXRJY29uVHBsITogVGVtcGxhdGVSZWY8dW5rbm93bj47XHJcbiAgQFZpZXdDaGlsZCgnZGVsZXRlSWNvbicsIHsgc3RhdGljOiB0cnVlIH0pIGRlbGV0ZUljb25UcGwhOiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuICBAVmlld0NoaWxkKCdhZGRJY29uJywgeyBzdGF0aWM6IHRydWUgfSkgYWRkSWNvblRwbCE6IFRlbXBsYXRlUmVmPHVua25vd24+O1xyXG4gIEBWaWV3Q2hpbGQoJ2RlZmF1bHRJY29uJywgeyBzdGF0aWM6IHRydWUgfSkgZGVmYXVsdEljb25UcGwhOiBUZW1wbGF0ZVJlZjx1bmtub3duPjtcclxuXHJcbiAgZ2V0SWNvblRlbXBsYXRlKCk6IFRlbXBsYXRlUmVmPHVua25vd24+IHtcclxuICAgIHN3aXRjaCAodGhpcy5pY29uKSB7XHJcbiAgICAgIGNhc2UgJ2NoZWNrJzogcmV0dXJuIHRoaXMuY2hlY2tJY29uVHBsO1xyXG4gICAgICBjYXNlICdjYW5jZWwnOiByZXR1cm4gdGhpcy5jYW5jZWxJY29uVHBsO1xyXG4gICAgICBjYXNlICdlZGl0JzogcmV0dXJuIHRoaXMuZWRpdEljb25UcGw7XHJcbiAgICAgIGNhc2UgJ2RlbGV0ZSc6IHJldHVybiB0aGlzLmRlbGV0ZUljb25UcGw7XHJcbiAgICAgIGNhc2UgJ2FkZCc6IHJldHVybiB0aGlzLmFkZEljb25UcGw7XHJcbiAgICAgIGRlZmF1bHQ6IHJldHVybiB0aGlzLmRlZmF1bHRJY29uVHBsO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgZ2V0IGljb25Db2xvcigpOiBzdHJpbmcge1xyXG4gICAgaWYgKHRoaXMuZGlzYWJsZWQpIHtcclxuICAgICAgcmV0dXJuICcjYmRiZGJkJzsgLy8gZ3JpcyBkZXNoYWJpbGl0YWRvXHJcbiAgICB9XHJcbiAgICBjb25zdCBwYWxldHRlczogUmVjb3JkPEljb24sIFJlY29yZDxDb2xvciwgc3RyaW5nPj4gPSB7XHJcbiAgICAgIGNoZWNrOiB7XHJcbiAgICAgICAgcHJpbWFyeTogJyMwMDIzNGJhZCcsXHJcbiAgICAgICAgc2Vjb25kYXJ5OiAnIzZjNzU3ZCcsXHJcbiAgICAgICAgd2FybjogJyNlNTM5MzUnLFxyXG4gICAgICB9LFxyXG4gICAgICBjYW5jZWw6IHtcclxuICAgICAgICBwcmltYXJ5OiAnIzAwMjM0YmFkJyxcclxuICAgICAgICBzZWNvbmRhcnk6ICcjNmM3NTdkJyxcclxuICAgICAgICB3YXJuOiAnI2U1MzkzNScsXHJcbiAgICAgIH0sXHJcbiAgICAgIGVkaXQ6IHtcclxuICAgICAgICBwcmltYXJ5OiAnIzAwMjM0YmFkJyxcclxuICAgICAgICBzZWNvbmRhcnk6ICcjNmM3NTdkJyxcclxuICAgICAgICB3YXJuOiAnI2U1MzkzNScsXHJcbiAgICAgIH0sXHJcbiAgICAgIGRlbGV0ZToge1xyXG4gICAgICAgIHByaW1hcnk6ICcjMDAyMzRiYWQnLFxyXG4gICAgICAgIHNlY29uZGFyeTogJyM2Yzc1N2QnLFxyXG4gICAgICAgIHdhcm46ICcjZTUzOTM1JyxcclxuICAgICAgfSxcclxuICAgICAgYWRkOiB7XHJcbiAgICAgICAgcHJpbWFyeTogJyMwMDIzNGJhZCcsXHJcbiAgICAgICAgc2Vjb25kYXJ5OiAnIzZjNzU3ZCcsXHJcbiAgICAgICAgd2FybjogJyNlNTM5MzUnLFxyXG4gICAgICB9XHJcbiAgICB9O1xyXG4gICAgcmV0dXJuIHBhbGV0dGVzW3RoaXMuaWNvbl0/Llt0aGlzLmNvbG9yXSA/PyAnIzIyMic7XHJcbiAgfVxyXG5cclxuICAvLyBIYW5kbGVyIHBhcmEgY2xpY2sgZW4gbW9kbyBidXR0b25cclxuICBvbkJ1dHRvbkNsaWNrKGV2ZW50OiBFdmVudCkge1xyXG4gICAgaWYgKCF0aGlzLmRpc2FibGVkKSB7XHJcbiAgICAgIHRoaXMuaWNvbkNsaWNrLmVtaXQoZXZlbnQpO1xyXG4gICAgfVxyXG4gIH1cclxufVxyXG4iLCJAaWYgKGJ1dHRvbikge1xyXG48YnV0dG9uIHR5cGU9XCJ7e3R5cGV9fVwiIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiIGNsYXNzPVwiaWNvbi1idXR0b25cIiBbc3R5bGUud2lkdGgucHhdPVwiaWNvblNpemUgKyA4XCJcclxuICBbc3R5bGUuaGVpZ2h0LnB4XT1cImljb25TaXplICsgOFwiIChjbGljayk9XCJvbkJ1dHRvbkNsaWNrKCRldmVudClcIj5cclxuICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZ2V0SWNvblRlbXBsYXRlKClcIj48L25nLWNvbnRhaW5lcj5cclxuPC9idXR0b24+XHJcbn0gQGVsc2Uge1xyXG48c3BhbiBjbGFzcz1cImljb24tc3BhblwiIFtzdHlsZS53aWR0aC5weF09XCJpY29uU2l6ZVwiIFtzdHlsZS5oZWlnaHQucHhdPVwiaWNvblNpemVcIj5cclxuICA8bmctY29udGFpbmVyICpuZ1RlbXBsYXRlT3V0bGV0PVwiZ2V0SWNvblRlbXBsYXRlKClcIj48L25nLWNvbnRhaW5lcj5cclxuPC9zcGFuPlxyXG59XHJcblxyXG48bmctdGVtcGxhdGUgI2NoZWNrSWNvbj5cclxuICA8c3ZnIFthdHRyLndpZHRoXT1cImljb25TaXplXCIgW2F0dHIuaGVpZ2h0XT1cImljb25TaXplXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICA8cGF0aCBkPVwiTTUgMTNsNCA0TDE5IDdcIiBbYXR0ci5zdHJva2VdPVwiaWNvbkNvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIlxyXG4gICAgICBzdHJva2UtbGluZWpvaW49XCJyb3VuZFwiIC8+XHJcbiAgPC9zdmc+XHJcbjwvbmctdGVtcGxhdGU+XHJcbjxuZy10ZW1wbGF0ZSAjY2FuY2VsSWNvbj5cclxuICA8c3ZnIFthdHRyLndpZHRoXT1cImljb25TaXplXCIgW2F0dHIuaGVpZ2h0XT1cImljb25TaXplXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICA8cGF0aCBkPVwiTTYgNmwxMiAxMk02IDE4TDE4IDZcIiBbYXR0ci5zdHJva2VdPVwiaWNvbkNvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIHN0cm9rZS1saW5lY2FwPVwicm91bmRcIiAvPlxyXG4gIDwvc3ZnPlxyXG48L25nLXRlbXBsYXRlPlxyXG48bmctdGVtcGxhdGUgI2VkaXRJY29uPlxyXG4gIDxzdmcgW2F0dHIud2lkdGhdPVwiaWNvblNpemVcIiBbYXR0ci5oZWlnaHRdPVwiaWNvblNpemVcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIj5cclxuICAgIDxyZWN0IHg9XCI1XCIgeT1cIjE5XCIgd2lkdGg9XCIxNFwiIGhlaWdodD1cIjJcIiByeD1cIjFcIiBbYXR0ci5maWxsXT1cImljb25Db2xvclwiIC8+XHJcbiAgICA8cGF0aCBkPVwiTTE2LjUgMy41YTIuMTIxIDIuMTIxIDAgMCAxIDMgM0w3IDE5bC00IDEgMS00IDEyLjUtMTIuNXpcIiBbYXR0ci5zdHJva2VdPVwiaWNvbkNvbG9yXCIgc3Ryb2tlLXdpZHRoPVwiMlwiIC8+XHJcbiAgPC9zdmc+XHJcbjwvbmctdGVtcGxhdGU+XHJcbjxuZy10ZW1wbGF0ZSAjZGVsZXRlSWNvbj5cclxuICA8c3ZnIFthdHRyLndpZHRoXT1cImljb25TaXplXCIgW2F0dHIuaGVpZ2h0XT1cImljb25TaXplXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICA8cGF0aCBkPVwiTTYgMTlhMiAyIDAgMCAwIDIgMmg4YTIgMiAwIDAgMCAyLTJWN0g2djEyek0xOSA0aC0zLjVsLTEtMWgtNWwtMSAxSDV2MmgxNFY0elwiIFthdHRyLmZpbGxdPVwiaWNvbkNvbG9yXCIgLz5cclxuICA8L3N2Zz5cclxuPC9uZy10ZW1wbGF0ZT5cclxuPG5nLXRlbXBsYXRlICNhZGRJY29uPlxyXG4gIDxzdmcgW2F0dHIud2lkdGhdPVwiaWNvblNpemVcIiBbYXR0ci5oZWlnaHRdPVwiaWNvblNpemVcIiB2aWV3Qm94PVwiMCAwIDI0IDI0XCIgZmlsbD1cIm5vbmVcIj5cclxuICAgIDxwYXRoIGQ9XCJNMTIgNXYxNE01IDEyaDE0XCIgW2F0dHIuc3Ryb2tlXT1cImljb25Db2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIiBzdHJva2UtbGluZWNhcD1cInJvdW5kXCIgLz5cclxuICA8L3N2Zz5cclxuPC9uZy10ZW1wbGF0ZT5cclxuPG5nLXRlbXBsYXRlICNkZWZhdWx0SWNvbj5cclxuICA8c3ZnIFthdHRyLndpZHRoXT1cImljb25TaXplXCIgW2F0dHIuaGVpZ2h0XT1cImljb25TaXplXCIgdmlld0JveD1cIjAgMCAyNCAyNFwiIGZpbGw9XCJub25lXCI+XHJcbiAgICA8Y2lyY2xlIGN4PVwiMTJcIiBjeT1cIjEyXCIgcj1cIjEwXCIgW2F0dHIuc3Ryb2tlXT1cImljb25Db2xvclwiIHN0cm9rZS13aWR0aD1cIjJcIiAvPlxyXG4gIDwvc3ZnPlxyXG48L25nLXRlbXBsYXRlPiJdfQ==
@@ -0,0 +1,237 @@
1
+ import { Component, Input, Output, signal, EventEmitter } from '@angular/core';
2
+ import { take } from 'rxjs';
3
+ import { MatCheckboxModule } from '@angular/material/checkbox';
4
+ import { C80IconComponent } from '../icon/icon.component';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@angular/material/checkbox";
7
+ export class C80TableComponent {
8
+ service;
9
+ columns = [];
10
+ errorEvent = new EventEmitter();
11
+ data = signal([]);
12
+ keys = signal([]);
13
+ creating = signal(false);
14
+ newRow = signal(null);
15
+ editing = signal(null); // id of row being edited
16
+ editRow = signal(null);
17
+ ngOnInit() {
18
+ if (!this.service)
19
+ return;
20
+ this.refresh();
21
+ }
22
+ onInput(event, key, col) {
23
+ if (col?.type === 'boolean') {
24
+ // MatCheckboxChange
25
+ const checked = event.checked;
26
+ this.updateNewRow(key, checked);
27
+ }
28
+ else {
29
+ const target = event.target;
30
+ if (target && typeof target.value === 'string') {
31
+ this.updateNewRow(key, target.value);
32
+ }
33
+ }
34
+ }
35
+ onDelete(row) {
36
+ if (!this.service.delete)
37
+ return;
38
+ const id = row['id'];
39
+ if (typeof id !== 'number') {
40
+ this.errorEvent.emit('No se puede borrar: id inválido');
41
+ return;
42
+ }
43
+ if (confirm('¿Está seguro de que desea borrar este elemento?')) {
44
+ this.service.delete(id).pipe(take(1)).subscribe({
45
+ next: () => this.refresh(),
46
+ error: (err) => this.errorEvent.emit(err?.message || 'Error al borrar')
47
+ });
48
+ }
49
+ }
50
+ refresh() {
51
+ this.service.get().pipe(take(1)).subscribe((items) => {
52
+ this.data.update(() => items);
53
+ // Solo mostrar las columnas visibles
54
+ const visibleColumns = this.columns.filter(col => col?.visible !== false);
55
+ this.keys.update(() => visibleColumns.map(col => col.accessor));
56
+ });
57
+ }
58
+ startCreate() {
59
+ this.creating.set(true);
60
+ // Inicializa newRow solo con los accessors de columnas visibles
61
+ const row = {};
62
+ this.columns.filter(col => col.visible !== false).forEach(col => {
63
+ row[col.accessor] = '';
64
+ });
65
+ this.newRow.set(row);
66
+ }
67
+ cancelCreate() {
68
+ this.creating.set(false);
69
+ this.newRow.set(null);
70
+ }
71
+ updateNewRow(key, value) {
72
+ const current = this.newRow();
73
+ if (!current)
74
+ return;
75
+ this.newRow.set({ ...current, [key]: value });
76
+ }
77
+ saveCreate() {
78
+ const row = this.newRow();
79
+ if (!row)
80
+ return;
81
+ const visibleColumns = this.columns.filter(col => col.visible !== false);
82
+ const converted = visibleColumns.reduce((acc, col) => {
83
+ acc[col.accessor] = this.convertCellValue(row[col.accessor], col);
84
+ return acc;
85
+ }, {});
86
+ if (this.service.create) {
87
+ this.service.create(converted).pipe(take(1)).subscribe({
88
+ next: () => {
89
+ this.cancelCreate();
90
+ this.refresh();
91
+ },
92
+ error: (err) => {
93
+ this.errorEvent.emit(err?.message || 'Error al crear');
94
+ }
95
+ });
96
+ }
97
+ }
98
+ /**
99
+ * Converts a cell value based on column type or sample data.
100
+ * Handles stringification of objects for string columns.
101
+ */
102
+ /**
103
+ * Converts a cell value based on column type or sample data.
104
+ * Delegates to type-specific helpers for clarity and maintainability.
105
+ */
106
+ convertCellValue(value, col) {
107
+ if (col.type === 'boolean')
108
+ return this.toBoolean(value);
109
+ if (col.type === 'number')
110
+ return this.toNumber(value);
111
+ if (col.type === 'string')
112
+ return this.toStringValue(value);
113
+ // Fallback: use sample data if available
114
+ const sample = this.data()[0];
115
+ if (sample && col.accessor in sample) {
116
+ const sampleValue = sample[col.accessor];
117
+ if (typeof sampleValue === 'boolean')
118
+ return this.toBoolean(value);
119
+ if (typeof sampleValue === 'number')
120
+ return this.toNumber(value);
121
+ if (typeof sampleValue === 'string')
122
+ return this.toStringValue(value);
123
+ }
124
+ return value;
125
+ }
126
+ /** Converts value to boolean using best practices. */
127
+ toBoolean(value) {
128
+ if (typeof value === 'boolean')
129
+ return value;
130
+ if (typeof value === 'string')
131
+ return value.trim().toLowerCase() === 'true' || value.trim() === '1';
132
+ if (typeof value === 'number')
133
+ return value === 1;
134
+ return false;
135
+ }
136
+ /** Converts value to number using best practices. */
137
+ toNumber(value) {
138
+ if (typeof value === 'number')
139
+ return value;
140
+ if (typeof value === 'string')
141
+ return value.trim() === '' ? undefined : Number(value);
142
+ if (typeof value === 'boolean')
143
+ return value ? 1 : 0;
144
+ return undefined;
145
+ }
146
+ /** Converts value to string using best practices, always stringifies objects. */
147
+ toStringValue(value) {
148
+ if (value == null)
149
+ return '';
150
+ if (typeof value === 'string')
151
+ return value;
152
+ if (typeof value === 'number' || typeof value === 'boolean')
153
+ return String(value);
154
+ if (typeof value === 'object') {
155
+ try {
156
+ return JSON.stringify(value);
157
+ }
158
+ catch {
159
+ return '[object Object]';
160
+ }
161
+ }
162
+ // For functions, symbols, undefined, etc., return empty string
163
+ return '';
164
+ }
165
+ onEdit(row) {
166
+ this.editing.set(row['id']);
167
+ const edit = {};
168
+ this.columns.filter(col => col.visible !== false).forEach(col => {
169
+ edit[col.accessor] = row[col.accessor];
170
+ });
171
+ this.editRow.set(edit);
172
+ }
173
+ cancelEdit() {
174
+ this.editing.set(null);
175
+ this.editRow.set(null);
176
+ }
177
+ onEditInput(event, key, col) {
178
+ const current = this.editRow();
179
+ if (!current)
180
+ return;
181
+ if (col?.type === 'boolean') {
182
+ // MatCheckboxChange
183
+ const checked = event.checked;
184
+ this.editRow.set({ ...current, [key]: checked });
185
+ }
186
+ else {
187
+ const target = event.target;
188
+ if (target && typeof target.value === 'string') {
189
+ this.editRow.set({ ...current, [key]: target.value });
190
+ }
191
+ }
192
+ }
193
+ saveEdit(row) {
194
+ const id = row['id'];
195
+ if (typeof id !== 'number' || !this.editRow())
196
+ return;
197
+ const visibleColumns = this.columns.filter(col => col.visible !== false);
198
+ const converted = visibleColumns.reduce((acc, col) => {
199
+ acc[col.accessor] = this.convertCellValue(this.editRow()[col.accessor], col);
200
+ return acc;
201
+ }, {});
202
+ // Type-safe update method detection
203
+ const updateFn = this.service.update;
204
+ if (updateFn) {
205
+ updateFn(id, converted).pipe(take(1)).subscribe({
206
+ next: () => {
207
+ this.cancelEdit();
208
+ this.refresh();
209
+ },
210
+ error: (err) => {
211
+ const message = (typeof err === 'object' && err && 'message' in err) ? err.message : undefined;
212
+ this.errorEvent.emit(message || 'Error al editar');
213
+ }
214
+ });
215
+ }
216
+ }
217
+ /**
218
+ * TrackBy function for ngFor to avoid DOM re-creation (NG0956 warning).
219
+ */
220
+ trackById(index, row) {
221
+ const id = row && typeof row === 'object' && 'id' in row ? row['id'] : undefined;
222
+ return (typeof id === 'string' || typeof id === 'number') ? id : index;
223
+ }
224
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C80TableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
225
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: C80TableComponent, isStandalone: true, selector: "c80-table", inputs: { service: "service", columns: "columns" }, outputs: { errorEvent: "errorEvent" }, ngImport: i0, template: "<div class=\"table-responsive\">\n <table class=\"table table-bordered table-hover align-middle\">\n <thead class=\"thead table-light\">\n <tr>\n @for (col of columns; track col) {\n @if (col.visible !== false) {\n @if (col.type === 'boolean') {\n <th class=\"text-center\">{{ col.label }}</th>\n }\n @else {\n <th>{{ col.label }}</th>\n }\n }\n }\n <th class=\"table-actions-header\">\n <span>Actions</span>\n <c80-icon button icon=\"add\" [disabled]=\"creating()\" title=\"Agregar\" class=\"add-action-btn\"\n (iconClick)=\"startCreate()\"></c80-icon>\n </th>\n </tr>\n </thead>\n <tbody>\n @for (row of data(); track trackById(i, row); let i = $index) {\n <tr>\n @for (col of columns; track col) {\n @if (col.visible !== false) {\n @if (col.type === 'boolean') {\n <td class=\"text-center\">\n @if (editing() === row['id']) {\n <mat-checkbox [checked]=\"!!editRow()?.[col.accessor]\" (change)=\"onEditInput($event, col.accessor, col)\"\n [aria-label]=\"col.label\"></mat-checkbox>\n }\n @else {\n @if (row[col.accessor] === true) {\n <c80-icon icon=\"check\" [size]=\"1\"></c80-icon>\n <br />\n }\n @else if (row[col.accessor] === false) {\n <c80-icon icon=\"cancel\"></c80-icon>\n <br />\n }\n }\n </td>\n }\n @else {\n <td>\n @if (editing() === row['id']) {\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'number' ? 'number' : 'text'\"\n [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\"\n (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n @else {\n {{ row[col.accessor] }}\n }\n </td>\n }\n }\n }\n <td class=\"text-center\">\n @if (editing() === row['id']) {\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveEdit(row)\"></c80-icon>\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelEdit()\"></c80-icon>\n }\n @else {\n <c80-icon button icon=\"edit\" title=\"Editar\" (iconClick)=\"onEdit(row)\"></c80-icon>\n <c80-icon button icon=\"delete\" color=\"warn\" title=\"Borrar\" (iconClick)=\"onDelete(row)\"></c80-icon>\n }\n </td>\n </tr>\n }\n @if (creating()) {\n <tr>\n @for (col of columns; track col) {\n @if (col.visible !== false) {\n @if (col.type === 'boolean') {\n <td class=\"text-center\">\n <mat-checkbox [checked]=\"!!newRow()?.[col.accessor]\" (change)=\"onInput($event, col.accessor, col)\"\n [aria-label]=\"col.label\"></mat-checkbox>\n </td>\n } @else {\n <td>\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'number' ? 'number' : 'text'\"\n [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\"\n (input)=\"onInput($event, col.accessor, col)\" />\n </td>\n }\n }\n }\n <td class=\"text-center\">\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveCreate()\"></c80-icon>\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelCreate()\"></c80-icon>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (data().length === 0) {\n <div class=\"text-center text-muted py-3\">\n No hay datos para mostrar.\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";.table-responsive{width:100%;overflow-x:auto}.table-responsive .table{min-width:0px}.table-responsive .table .thead .table-actions-header{text-align:center;vertical-align:middle;display:flex;justify-content:center;align-items:center;gap:.5rem}.table-responsive .table .thead .table-actions-header .add-action-btn{margin-bottom:2px}.table-responsive .table .thead th{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .6rem!important}.table-responsive .table tbody td{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .8rem!important}.table-responsive .table tbody tr{height:35px!important;min-height:35px!important;max-height:35px!important;cursor:pointer}.table-responsive .table tbody tr:hover{background-color:#f5f5f5}.table-responsive .table tbody input{border:1px solid rgba(34,0,255,.37);height:35px!important}\n"], dependencies: [{ kind: "ngmodule", type: MatCheckboxModule }, { kind: "component", type: i1.MatCheckbox, selector: "mat-checkbox", inputs: ["aria-label", "aria-labelledby", "aria-describedby", "id", "required", "labelPosition", "name", "value", "disableRipple", "tabIndex", "color", "disabledInteractive", "checked", "disabled", "indeterminate"], outputs: ["change", "indeterminateChange"], exportAs: ["matCheckbox"] }, { kind: "component", type: C80IconComponent, selector: "c80-icon", inputs: ["icon", "color", "disabled", "size", "button", "type"], outputs: ["iconClick"] }] });
226
+ }
227
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: C80TableComponent, decorators: [{
228
+ type: Component,
229
+ args: [{ selector: 'c80-table', standalone: true, imports: [MatCheckboxModule, C80IconComponent], template: "<div class=\"table-responsive\">\n <table class=\"table table-bordered table-hover align-middle\">\n <thead class=\"thead table-light\">\n <tr>\n @for (col of columns; track col) {\n @if (col.visible !== false) {\n @if (col.type === 'boolean') {\n <th class=\"text-center\">{{ col.label }}</th>\n }\n @else {\n <th>{{ col.label }}</th>\n }\n }\n }\n <th class=\"table-actions-header\">\n <span>Actions</span>\n <c80-icon button icon=\"add\" [disabled]=\"creating()\" title=\"Agregar\" class=\"add-action-btn\"\n (iconClick)=\"startCreate()\"></c80-icon>\n </th>\n </tr>\n </thead>\n <tbody>\n @for (row of data(); track trackById(i, row); let i = $index) {\n <tr>\n @for (col of columns; track col) {\n @if (col.visible !== false) {\n @if (col.type === 'boolean') {\n <td class=\"text-center\">\n @if (editing() === row['id']) {\n <mat-checkbox [checked]=\"!!editRow()?.[col.accessor]\" (change)=\"onEditInput($event, col.accessor, col)\"\n [aria-label]=\"col.label\"></mat-checkbox>\n }\n @else {\n @if (row[col.accessor] === true) {\n <c80-icon icon=\"check\" [size]=\"1\"></c80-icon>\n <br />\n }\n @else if (row[col.accessor] === false) {\n <c80-icon icon=\"cancel\"></c80-icon>\n <br />\n }\n }\n </td>\n }\n @else {\n <td>\n @if (editing() === row['id']) {\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'number' ? 'number' : 'text'\"\n [value]=\"editRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\"\n (input)=\"onEditInput($event, col.accessor, col)\" />\n }\n @else {\n {{ row[col.accessor] }}\n }\n </td>\n }\n }\n }\n <td class=\"text-center\">\n @if (editing() === row['id']) {\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveEdit(row)\"></c80-icon>\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelEdit()\"></c80-icon>\n }\n @else {\n <c80-icon button icon=\"edit\" title=\"Editar\" (iconClick)=\"onEdit(row)\"></c80-icon>\n <c80-icon button icon=\"delete\" color=\"warn\" title=\"Borrar\" (iconClick)=\"onDelete(row)\"></c80-icon>\n }\n </td>\n </tr>\n }\n @if (creating()) {\n <tr>\n @for (col of columns; track col) {\n @if (col.visible !== false) {\n @if (col.type === 'boolean') {\n <td class=\"text-center\">\n <mat-checkbox [checked]=\"!!newRow()?.[col.accessor]\" (change)=\"onInput($event, col.accessor, col)\"\n [aria-label]=\"col.label\"></mat-checkbox>\n </td>\n } @else {\n <td>\n <input class=\"form-control form-control-sm\" [type]=\"col.type === 'number' ? 'number' : 'text'\"\n [value]=\"newRow()?.[col.accessor] ?? ''\" [placeholder]=\"col.label\"\n (input)=\"onInput($event, col.accessor, col)\" />\n </td>\n }\n }\n }\n <td class=\"text-center\">\n <c80-icon button icon=\"check\" title=\"Guardar\" (iconClick)=\"saveCreate()\"></c80-icon>\n <c80-icon button icon=\"cancel\" color=\"warn\" title=\"Cancelar\" (iconClick)=\"cancelCreate()\"></c80-icon>\n </td>\n </tr>\n }\n </tbody>\n </table>\n @if (data().length === 0) {\n <div class=\"text-center text-muted py-3\">\n No hay datos para mostrar.\n </div>\n }\n</div>", styles: ["@charset \"UTF-8\";.table-responsive{width:100%;overflow-x:auto}.table-responsive .table{min-width:0px}.table-responsive .table .thead .table-actions-header{text-align:center;vertical-align:middle;display:flex;justify-content:center;align-items:center;gap:.5rem}.table-responsive .table .thead .table-actions-header .add-action-btn{margin-bottom:2px}.table-responsive .table .thead th{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .6rem!important}.table-responsive .table tbody td{height:35px!important;min-height:35px!important;max-height:35px!important;vertical-align:middle!important;padding:.2rem .8rem!important}.table-responsive .table tbody tr{height:35px!important;min-height:35px!important;max-height:35px!important;cursor:pointer}.table-responsive .table tbody tr:hover{background-color:#f5f5f5}.table-responsive .table tbody input{border:1px solid rgba(34,0,255,.37);height:35px!important}\n"] }]
230
+ }], propDecorators: { service: [{
231
+ type: Input
232
+ }], columns: [{
233
+ type: Input
234
+ }], errorEvent: [{
235
+ type: Output
236
+ }] } });
237
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGFibGUuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy91aS9zcmMvbGliL3RhYmxlL3RhYmxlLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL2xpYnMvdWkvc3JjL2xpYi90YWJsZS90YWJsZS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBVSxNQUFNLEVBQUUsTUFBTSxFQUFFLFlBQVksRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN2RixPQUFPLEVBQWMsSUFBSSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDRCQUE0QixDQUFDO0FBRS9ELE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHdCQUF3QixDQUFDOzs7QUF3QjFELE1BQU0sT0FBTyxpQkFBaUI7SUFDbkIsT0FBTyxDQUFzQjtJQUM3QixPQUFPLEdBQXFCLEVBQUUsQ0FBQztJQUM5QixVQUFVLEdBQUcsSUFBSSxZQUFZLEVBQVUsQ0FBQztJQUV6QyxJQUFJLEdBQUcsTUFBTSxDQUFNLEVBQUUsQ0FBQyxDQUFDO0lBQ3ZCLElBQUksR0FBRyxNQUFNLENBQVcsRUFBRSxDQUFDLENBQUM7SUFDckMsUUFBUSxHQUFHLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN6QixNQUFNLEdBQUcsTUFBTSxDQUFvQixJQUFJLENBQUMsQ0FBQztJQUNoQyxPQUFPLEdBQUcsTUFBTSxDQUFnQixJQUFJLENBQUMsQ0FBQyxDQUFDLHlCQUF5QjtJQUNoRSxPQUFPLEdBQUcsTUFBTSxDQUFvQixJQUFJLENBQUMsQ0FBQztJQUVuRCxRQUFRO1FBQ04sSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPO1lBQUUsT0FBTztRQUMxQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQUVELE9BQU8sQ0FBQyxLQUFn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S0FBSyxDQUFDO0lBQ3pFLENBQUM7d0dBck5VLGlCQUFpQjs0RkFBakIsaUJBQWlCLGdLQzVCOUIscXJIQXFHTSx5Z0NEN0VNLGlCQUFpQixxWUFBRSxnQkFBZ0I7OzRGQUlsQyxpQkFBaUI7a0JBUDdCLFNBQVM7K0JBQ0UsV0FBVyxjQUNULElBQUksV0FDUCxDQUFDLGlCQUFpQixFQUFFLGdCQUFnQixDQUFDOzhCQUtyQyxPQUFPO3NCQUFmLEtBQUs7Z0JBQ0csT0FBTztzQkFBZixLQUFLO2dCQUNJLFVBQVU7c0JBQW5CLE1BQU0iLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb21wb25lbnQsIElucHV0LCBPbkluaXQsIE91dHB1dCwgc2lnbmFsLCBFdmVudEVtaXR0ZXIgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgT2JzZXJ2YWJsZSwgdGFrZSB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBNYXRDaGVja2JveE1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NoZWNrYm94JztcclxuaW1wb3J0IHR5cGUgeyBNYXRDaGVja2JveENoYW5nZSB9IGZyb20gJ0Bhbmd1bGFyL21hdGVyaWFsL2NoZWNrYm94JztcclxuaW1wb3J0IHsgQzgwSWNvbkNvbXBvbmVudCB9IGZyb20gJy4uL2ljb24vaWNvbi5jb21wb25lbnQnO1xyXG5cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQzgwVGFibGVTZXJ2aWNlPFQ+IHtcclxuICBnZXQ6ICgpID0+IE9ic2VydmFibGU8VFtdPjtcclxuICBjcmVhdGU6IChyb3c6IFQpID0+IE9ic2VydmFibGU8VD47XHJcbiAgZGVsZXRlOiAoaWQ6IG51bWJlcikgPT4gT2JzZXJ2YWJsZTx2b2lkPjtcclxuICB1cGRhdGU6IChpZDogbnVtYmVyLCByb3c6IFQpID0+IE9ic2VydmFibGU8VD47XHJcbn1cclxuXHJcbmV4cG9ydCBpbnRlcmZhY2UgQzgwVGFibGVDb2xEZWYge1xyXG4gIGFjY2Vzc29yOiBzdHJpbmc7XHJcbiAgbGFiZWw6IHN0cmluZztcclxuICB2aXNpYmxlPzogYm9vbGVhbjsgLy8gU2kgbm8gc2UgZXNwZWNpZmljYSwgc2UgYXN1bWUgdHJ1ZVxyXG4gIHR5cGU/OiAnc3RyaW5nJyB8ICdudW1iZXInIHwgJ2Jvb2xlYW4nOyAvLyBUaXBvIGRlIGRhdG8gcGFyYSBsYSBjb2x1bW5hXHJcbn1cclxuXHJcbkBDb21wb25lbnQoe1xyXG4gIHNlbGVjdG9yOiAnYzgwLXRhYmxlJyxcclxuICBzdGFuZGFsb25lOiB0cnVlLFxyXG4gIGltcG9ydHM6IFtNYXRDaGVja2JveE1vZHVsZSwgQzgwSWNvbkNvbXBvbmVudF0sXHJcbiAgdGVtcGxhdGVVcmw6ICcuL3RhYmxlLmNvbXBvbmVudC5odG1sJyxcclxuICBzdHlsZVVybDogJy4vdGFibGUuY29tcG9uZW50LnNjc3MnLFxyXG59KVxyXG5leHBvcnQgY2xhc3MgQzgwVGFibGVDb21wb25lbnQ8VCBleHRlbmRzIFJlY29yZDxzdHJpbmcsIHVua25vd24+PiBpbXBsZW1lbnRzIE9uSW5pdCB7XHJcbiAgQElucHV0KCkgc2VydmljZSE6IEM4MFRhYmxlU2VydmljZTxUPjtcclxuICBASW5wdXQoKSBjb2x1bW5zOiBDODBUYWJsZUNvbERlZltdID0gW107XHJcbiAgQE91dHB1dCgpIGVycm9yRXZlbnQgPSBuZXcgRXZlbnRFbWl0dGVyPHN0cmluZz4oKTtcclxuXHJcbiAgcmVhZG9ubHkgZGF0YSA9IHNpZ25hbDxUW10+KFtdKTtcclxuICByZWFkb25seSBrZXlzID0gc2lnbmFsPHN0cmluZ1tdPihbXSk7XHJcbiAgY3JlYXRpbmcgPSBzaWduYWwoZmFsc2UpO1xyXG4gIG5ld1JvdyA9IHNpZ25hbDxQYXJ0aWFsPFQ+IHwgbnVsbD4obnVsbCk7XHJcbiAgcmVhZG9ubHkgZWRpdGluZyA9IHNpZ25hbDxudW1iZXIgfCBudWxsPihudWxsKTsgLy8gaWQgb2Ygcm93IGJlaW5nIGVkaXRlZFxyXG4gIHJlYWRvbmx5IGVkaXRSb3cgPSBzaWduYWw8UGFydGlhbDxUPiB8IG51bGw+KG51bGwpO1xyXG5cclxuICBuZ09uSW5pdCgpIHtcclxuICAgIGlmICghdGhpcy5zZXJ2aWNlKSByZXR1cm47XHJcbiAgICB0aGlzLnJlZnJlc2goKTtcclxuICB9XHJcblxyXG4gIG9uSW5wdXQoZXZlbnQ6IEV2ZW50IHwgTWF0Q2hlY2tib3hDaGFuZ2UsIGtleTogc3RyaW5nLCBjb2w/OiBDODBUYWJsZUNvbERlZikge1xyXG4gICAgaWYgKGNvbD8udHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgIC8vIE1hdENoZWNrYm94Q2hhbmdlXHJcbiAgICAgIGNvbnN0IGNoZWNrZWQgPSAoZXZlbnQgYXMgTWF0Q2hlY2tib3hDaGFuZ2UpLmNoZWNrZWQ7XHJcbiAgICAgIHRoaXMudXBkYXRlTmV3Um93KGtleSwgY2hlY2tlZCk7XHJcbiAgICB9IGVsc2Uge1xyXG4gICAgICBjb25zdCB0YXJnZXQgPSAoZXZlbnQgYXMgRXZlbnQpLnRhcmdldDtcclxuICAgICAgaWYgKHRhcmdldCAmJiB0eXBlb2YgKHRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSA9PT0gJ3N0cmluZycpIHtcclxuICAgICAgICB0aGlzLnVwZGF0ZU5ld1JvdyhrZXksICh0YXJnZXQgYXMgSFRNTElucHV0RWxlbWVudCkudmFsdWUpO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICBvbkRlbGV0ZShyb3c6IFQpIHtcclxuICAgIGlmICghdGhpcy5zZXJ2aWNlLmRlbGV0ZSkgcmV0dXJuO1xyXG4gICAgY29uc3QgaWQgPSByb3dbJ2lkJ107XHJcbiAgICBpZiAodHlwZW9mIGlkICE9PSAnbnVtYmVyJykge1xyXG4gICAgICB0aGlzLmVycm9yRXZlbnQuZW1pdCgnTm8gc2UgcHVlZGUgYm9ycmFyOiBpZCBpbnbDoWxpZG8nKTtcclxuICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG4gICAgaWYgKGNvbmZpcm0oJ8K/RXN0w6Egc2VndXJvIGRlIHF1ZSBkZXNlYSBib3JyYXIgZXN0ZSBlbGVtZW50bz8nKSkge1xyXG4gICAgICB0aGlzLnNlcnZpY2UuZGVsZXRlKGlkKS5waXBlKHRha2UoMSkpLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKCkgPT4gdGhpcy5yZWZyZXNoKCksXHJcbiAgICAgICAgZXJyb3I6IChlcnIpID0+IHRoaXMuZXJyb3JFdmVudC5lbWl0KGVycj8ubWVzc2FnZSB8fCAnRXJyb3IgYWwgYm9ycmFyJylcclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICByZWZyZXNoKCkge1xyXG4gICAgdGhpcy5zZXJ2aWNlLmdldCgpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKChpdGVtcykgPT4ge1xyXG4gICAgICB0aGlzLmRhdGEudXBkYXRlKCgpID0+IGl0ZW1zKTtcclxuICAgICAgLy8gU29sbyBtb3N0cmFyIGxhcyBjb2x1bW5hcyB2aXNpYmxlc1xyXG4gICAgICBjb25zdCB2aXNpYmxlQ29sdW1ucyA9IHRoaXMuY29sdW1ucy5maWx0ZXIoY29sID0+IGNvbD8udmlzaWJsZSAhPT0gZmFsc2UpO1xyXG4gICAgICB0aGlzLmtleXMudXBkYXRlKCgpID0+IHZpc2libGVDb2x1bW5zLm1hcChjb2wgPT4gY29sLmFjY2Vzc29yKSk7XHJcbiAgICB9KTtcclxuICB9XHJcblxyXG4gIHN0YXJ0Q3JlYXRlKCkge1xyXG4gICAgdGhpcy5jcmVhdGluZy5zZXQodHJ1ZSk7XHJcbiAgICAvLyBJbmljaWFsaXphIG5ld1JvdyBzb2xvIGNvbiBsb3MgYWNjZXNzb3JzIGRlIGNvbHVtbmFzIHZpc2libGVzXHJcbiAgICBjb25zdCByb3c6IFBhcnRpYWw8VD4gPSB7fTtcclxuICAgIHRoaXMuY29sdW1ucy5maWx0ZXIoY29sID0+IGNvbC52aXNpYmxlICE9PSBmYWxzZSkuZm9yRWFjaChjb2wgPT4ge1xyXG4gICAgICAocm93IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KVtjb2wuYWNjZXNzb3JdID0gJyc7XHJcbiAgICB9KTtcclxuICAgIHRoaXMubmV3Um93LnNldChyb3cpO1xyXG4gIH1cclxuXHJcbiAgY2FuY2VsQ3JlYXRlKCkge1xyXG4gICAgdGhpcy5jcmVhdGluZy5zZXQoZmFsc2UpO1xyXG4gICAgdGhpcy5uZXdSb3cuc2V0KG51bGwpO1xyXG4gIH1cclxuXHJcbiAgdXBkYXRlTmV3Um93KGtleTogc3RyaW5nLCB2YWx1ZTogdW5rbm93bikge1xyXG4gICAgY29uc3QgY3VycmVudCA9IHRoaXMubmV3Um93KCk7XHJcbiAgICBpZiAoIWN1cnJlbnQpIHJldHVybjtcclxuICAgIHRoaXMubmV3Um93LnNldCh7IC4uLmN1cnJlbnQsIFtrZXldOiB2YWx1ZSB9KTtcclxuICB9XHJcblxyXG4gIHNhdmVDcmVhdGUoKSB7XHJcbiAgICBjb25zdCByb3cgPSB0aGlzLm5ld1JvdygpO1xyXG4gICAgaWYgKCFyb3cpIHJldHVybjtcclxuXHJcbiAgICBjb25zdCB2aXNpYmxlQ29sdW1ucyA9IHRoaXMuY29sdW1ucy5maWx0ZXIoY29sID0+IGNvbC52aXNpYmxlICE9PSBmYWxzZSk7XHJcbiAgICBjb25zdCBjb252ZXJ0ZWQgPSB2aXNpYmxlQ29sdW1ucy5yZWR1Y2UoKGFjYywgY29sKSA9PiB7XHJcbiAgICAgIGFjY1tjb2wuYWNjZXNzb3JdID0gdGhpcy5jb252ZXJ0Q2VsbFZhbHVlKHJvd1tjb2wuYWNjZXNzb3JdLCBjb2wpO1xyXG4gICAgICByZXR1cm4gYWNjO1xyXG4gICAgfSwge30gYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pIGFzIFBhcnRpYWw8VD47XHJcblxyXG4gICAgaWYgKHRoaXMuc2VydmljZS5jcmVhdGUpIHtcclxuICAgICAgKHRoaXMuc2VydmljZS5jcmVhdGUgYXMgKHJvdzogUGFydGlhbDxUPikgPT4gT2JzZXJ2YWJsZTxUPikoY29udmVydGVkKS5waXBlKHRha2UoMSkpLnN1YnNjcmliZSh7XHJcbiAgICAgICAgbmV4dDogKCkgPT4ge1xyXG4gICAgICAgICAgdGhpcy5jYW5jZWxDcmVhdGUoKTtcclxuICAgICAgICAgIHRoaXMucmVmcmVzaCgpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgZXJyb3I6IChlcnIpID0+IHtcclxuICAgICAgICAgIHRoaXMuZXJyb3JFdmVudC5lbWl0KGVycj8ubWVzc2FnZSB8fCAnRXJyb3IgYWwgY3JlYXInKTtcclxuICAgICAgICB9XHJcbiAgICAgIH0pO1xyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgLyoqXHJcbiAgICogQ29udmVydHMgYSBjZWxsIHZhbHVlIGJhc2VkIG9uIGNvbHVtbiB0eXBlIG9yIHNhbXBsZSBkYXRhLlxyXG4gICAqIEhhbmRsZXMgc3RyaW5naWZpY2F0aW9uIG9mIG9iamVjdHMgZm9yIHN0cmluZyBjb2x1bW5zLlxyXG4gICAqL1xyXG4gIC8qKlxyXG4gICAqIENvbnZlcnRzIGEgY2VsbCB2YWx1ZSBiYXNlZCBvbiBjb2x1bW4gdHlwZSBvciBzYW1wbGUgZGF0YS5cclxuICAgKiBEZWxlZ2F0ZXMgdG8gdHlwZS1zcGVjaWZpYyBoZWxwZXJzIGZvciBjbGFyaXR5IGFuZCBtYWludGFpbmFiaWxpdHkuXHJcbiAgICovXHJcbiAgcHJpdmF0ZSBjb252ZXJ0Q2VsbFZhbHVlKHZhbHVlOiB1bmtub3duLCBjb2w6IEM4MFRhYmxlQ29sRGVmKTogdW5rbm93biB7XHJcbiAgICBpZiAoY29sLnR5cGUgPT09ICdib29sZWFuJykgcmV0dXJuIHRoaXMudG9Cb29sZWFuKHZhbHVlKTtcclxuICAgIGlmIChjb2wudHlwZSA9PT0gJ251bWJlcicpIHJldHVybiB0aGlzLnRvTnVtYmVyKHZhbHVlKTtcclxuICAgIGlmIChjb2wudHlwZSA9PT0gJ3N0cmluZycpIHJldHVybiB0aGlzLnRvU3RyaW5nVmFsdWUodmFsdWUpO1xyXG5cclxuICAgIC8vIEZhbGxiYWNrOiB1c2Ugc2FtcGxlIGRhdGEgaWYgYXZhaWxhYmxlXHJcbiAgICBjb25zdCBzYW1wbGUgPSB0aGlzLmRhdGEoKVswXTtcclxuICAgIGlmIChzYW1wbGUgJiYgY29sLmFjY2Vzc29yIGluIHNhbXBsZSkge1xyXG4gICAgICBjb25zdCBzYW1wbGVWYWx1ZSA9IHNhbXBsZVtjb2wuYWNjZXNzb3JdO1xyXG4gICAgICBpZiAodHlwZW9mIHNhbXBsZVZhbHVlID09PSAnYm9vbGVhbicpIHJldHVybiB0aGlzLnRvQm9vbGVhbih2YWx1ZSk7XHJcbiAgICAgIGlmICh0eXBlb2Ygc2FtcGxlVmFsdWUgPT09ICdudW1iZXInKSByZXR1cm4gdGhpcy50b051bWJlcih2YWx1ZSk7XHJcbiAgICAgIGlmICh0eXBlb2Ygc2FtcGxlVmFsdWUgPT09ICdzdHJpbmcnKSByZXR1cm4gdGhpcy50b1N0cmluZ1ZhbHVlKHZhbHVlKTtcclxuICAgIH1cclxuICAgIHJldHVybiB2YWx1ZTtcclxuICB9XHJcblxyXG4gIC8qKiBDb252ZXJ0cyB2YWx1ZSB0byBib29sZWFuIHVzaW5nIGJlc3QgcHJhY3RpY2VzLiAqL1xyXG4gIHByaXZhdGUgdG9Cb29sZWFuKHZhbHVlOiB1bmtub3duKTogYm9vbGVhbiB7XHJcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHJldHVybiB2YWx1ZTtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSByZXR1cm4gdmFsdWUudHJpbSgpLnRvTG93ZXJDYXNlKCkgPT09ICd0cnVlJyB8fCB2YWx1ZS50cmltKCkgPT09ICcxJztcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInKSByZXR1cm4gdmFsdWUgPT09IDE7XHJcbiAgICByZXR1cm4gZmFsc2U7XHJcbiAgfVxyXG5cclxuICAvKiogQ29udmVydHMgdmFsdWUgdG8gbnVtYmVyIHVzaW5nIGJlc3QgcHJhY3RpY2VzLiAqL1xyXG4gIHByaXZhdGUgdG9OdW1iZXIodmFsdWU6IHVua25vd24pOiBudW1iZXIgfCB1bmRlZmluZWQge1xyXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ251bWJlcicpIHJldHVybiB2YWx1ZTtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdzdHJpbmcnKSByZXR1cm4gdmFsdWUudHJpbSgpID09PSAnJyA/IHVuZGVmaW5lZCA6IE51bWJlcih2YWx1ZSk7XHJcbiAgICBpZiAodHlwZW9mIHZhbHVlID09PSAnYm9vbGVhbicpIHJldHVybiB2YWx1ZSA/IDEgOiAwO1xyXG4gICAgcmV0dXJuIHVuZGVmaW5lZDtcclxuICB9XHJcblxyXG4gIC8qKiBDb252ZXJ0cyB2YWx1ZSB0byBzdHJpbmcgdXNpbmcgYmVzdCBwcmFjdGljZXMsIGFsd2F5cyBzdHJpbmdpZmllcyBvYmplY3RzLiAqL1xyXG4gIHByaXZhdGUgdG9TdHJpbmdWYWx1ZSh2YWx1ZTogdW5rbm93bik6IHN0cmluZyB7XHJcbiAgICBpZiAodmFsdWUgPT0gbnVsbCkgcmV0dXJuICcnO1xyXG4gICAgaWYgKHR5cGVvZiB2YWx1ZSA9PT0gJ3N0cmluZycpIHJldHVybiB2YWx1ZTtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdudW1iZXInIHx8IHR5cGVvZiB2YWx1ZSA9PT0gJ2Jvb2xlYW4nKSByZXR1cm4gU3RyaW5nKHZhbHVlKTtcclxuICAgIGlmICh0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSB7XHJcbiAgICAgIHRyeSB7XHJcbiAgICAgICAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KHZhbHVlKTtcclxuICAgICAgfSBjYXRjaCB7XHJcbiAgICAgICAgcmV0dXJuICdbb2JqZWN0IE9iamVjdF0nO1xyXG4gICAgICB9XHJcbiAgICB9XHJcbiAgICAvLyBGb3IgZnVuY3Rpb25zLCBzeW1ib2xzLCB1bmRlZmluZWQsIGV0Yy4sIHJldHVybiBlbXB0eSBzdHJpbmdcclxuICAgIHJldHVybiAnJztcclxuICB9XHJcblxyXG4gIG9uRWRpdChyb3c6IFQpIHtcclxuICAgIHRoaXMuZWRpdGluZy5zZXQocm93WydpZCddIGFzIG51bWJlcik7XHJcbiAgICBjb25zdCBlZGl0OiBQYXJ0aWFsPFQ+ID0ge307XHJcbiAgICB0aGlzLmNvbHVtbnMuZmlsdGVyKGNvbCA9PiBjb2wudmlzaWJsZSAhPT0gZmFsc2UpLmZvckVhY2goY29sID0+IHtcclxuICAgICAgKGVkaXQgYXMgUmVjb3JkPHN0cmluZywgdW5rbm93bj4pW2NvbC5hY2Nlc3Nvcl0gPSByb3dbY29sLmFjY2Vzc29yXTtcclxuICAgIH0pO1xyXG4gICAgdGhpcy5lZGl0Um93LnNldChlZGl0KTtcclxuICB9XHJcblxyXG4gIGNhbmNlbEVkaXQoKSB7XHJcbiAgICB0aGlzLmVkaXRpbmcuc2V0KG51bGwpO1xyXG4gICAgdGhpcy5lZGl0Um93LnNldChudWxsKTtcclxuICB9XHJcblxyXG4gIG9uRWRpdElucHV0KGV2ZW50OiBFdmVudCB8IE1hdENoZWNrYm94Q2hhbmdlLCBrZXk6IHN0cmluZywgY29sPzogQzgwVGFibGVDb2xEZWYpIHtcclxuICAgIGNvbnN0IGN1cnJlbnQgPSB0aGlzLmVkaXRSb3coKTtcclxuICAgIGlmICghY3VycmVudCkgcmV0dXJuO1xyXG4gICAgaWYgKGNvbD8udHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XHJcbiAgICAgIC8vIE1hdENoZWNrYm94Q2hhbmdlXHJcbiAgICAgIGNvbnN0IGNoZWNrZWQgPSAoZXZlbnQgYXMgTWF0Q2hlY2tib3hDaGFuZ2UpLmNoZWNrZWQ7XHJcbiAgICAgIHRoaXMuZWRpdFJvdy5zZXQoeyAuLi5jdXJyZW50LCBba2V5XTogY2hlY2tlZCB9KTtcclxuICAgIH0gZWxzZSB7XHJcbiAgICAgIGNvbnN0IHRhcmdldCA9IChldmVudCBhcyBFdmVudCkudGFyZ2V0O1xyXG4gICAgICBpZiAodGFyZ2V0ICYmIHR5cGVvZiAodGFyZ2V0IGFzIEhUTUxJbnB1dEVsZW1lbnQpLnZhbHVlID09PSAnc3RyaW5nJykge1xyXG4gICAgICAgIHRoaXMuZWRpdFJvdy5zZXQoeyAuLi5jdXJyZW50LCBba2V5XTogKHRhcmdldCBhcyBIVE1MSW5wdXRFbGVtZW50KS52YWx1ZSB9KTtcclxuICAgICAgfVxyXG4gICAgfVxyXG4gIH1cclxuXHJcbiAgc2F2ZUVkaXQocm93OiBUKSB7XHJcbiAgICBjb25zdCBpZCA9IHJvd1snaWQnXTtcclxuICAgIGlmICh0eXBlb2YgaWQgIT09ICdudW1iZXInIHx8ICF0aGlzLmVkaXRSb3coKSkgcmV0dXJuO1xyXG4gICAgY29uc3QgdmlzaWJsZUNvbHVtbnMgPSB0aGlzLmNvbHVtbnMuZmlsdGVyKGNvbCA9PiBjb2wudmlzaWJsZSAhPT0gZmFsc2UpO1xyXG4gICAgY29uc3QgY29udmVydGVkID0gdmlzaWJsZUNvbHVtbnMucmVkdWNlKChhY2MsIGNvbCkgPT4ge1xyXG4gICAgICBhY2NbY29sLmFjY2Vzc29yXSA9IHRoaXMuY29udmVydENlbGxWYWx1ZSh0aGlzLmVkaXRSb3coKSFbY29sLmFjY2Vzc29yXSwgY29sKTtcclxuICAgICAgcmV0dXJuIGFjYztcclxuICAgIH0sIHt9IGFzIFJlY29yZDxzdHJpbmcsIHVua25vd24+KSBhcyBQYXJ0aWFsPFQ+O1xyXG4gICAgLy8gVHlwZS1zYWZlIHVwZGF0ZSBtZXRob2QgZGV0ZWN0aW9uXHJcbiAgICBjb25zdCB1cGRhdGVGbiA9ICh0aGlzLnNlcnZpY2UgYXMgeyB1cGRhdGU/OiAoaWQ6IG51bWJlciwgcm93OiBUKSA9PiBPYnNlcnZhYmxlPFQ+IH0pLnVwZGF0ZTtcclxuICAgIGlmICh1cGRhdGVGbikge1xyXG4gICAgICB1cGRhdGVGbihpZCwgY29udmVydGVkIGFzIFQpLnBpcGUodGFrZSgxKSkuc3Vic2NyaWJlKHtcclxuICAgICAgICBuZXh0OiAoKSA9PiB7XHJcbiAgICAgICAgICB0aGlzLmNhbmNlbEVkaXQoKTtcclxuICAgICAgICAgIHRoaXMucmVmcmVzaCgpO1xyXG4gICAgICAgIH0sXHJcbiAgICAgICAgZXJyb3I6IChlcnI6IHVua25vd24pID0+IHtcclxuICAgICAgICAgIGNvbnN0IG1lc3NhZ2UgPSAodHlwZW9mIGVyciA9PT0gJ29iamVjdCcgJiYgZXJyICYmICdtZXNzYWdlJyBpbiBlcnIpID8gKGVyciBhcyB7IG1lc3NhZ2U/OiBzdHJpbmcgfSkubWVzc2FnZSA6IHVuZGVmaW5lZDtcclxuICAgICAgICAgIHRoaXMuZXJyb3JFdmVudC5lbWl0KG1lc3NhZ2UgfHwgJ0Vycm9yIGFsIGVkaXRhcicpO1xyXG4gICAgICAgIH1cclxuICAgICAgfSk7XHJcbiAgICB9XHJcbiAgfVxyXG5cclxuICAvKipcclxuICAgKiBUcmFja0J5IGZ1bmN0aW9uIGZvciBuZ0ZvciB0byBhdm9pZCBET00gcmUtY3JlYXRpb24gKE5HMDk1NiB3YXJuaW5nKS5cclxuICAgKi9cclxuICB0cmFja0J5SWQoaW5kZXg6IG51bWJlciwgcm93OiBUKTogbnVtYmVyIHwgc3RyaW5nIHtcclxuICAgIGNvbnN0IGlkID0gcm93ICYmIHR5cGVvZiByb3cgPT09ICdvYmplY3QnICYmICdpZCcgaW4gcm93ID8gKHJvdyBhcyBSZWNvcmQ8c3RyaW5nLCB1bmtub3duPilbJ2lkJ10gOiB1bmRlZmluZWQ7XHJcbiAgICByZXR1cm4gKHR5cGVvZiBpZCA9PT0gJ3N0cmluZycgfHwgdHlwZW9mIGlkID09PSAnbnVtYmVyJykgPyBpZCA6IGluZGV4O1xyXG4gIH1cclxufVxyXG4iLCI8ZGl2IGNsYXNzPVwidGFibGUtcmVzcG9uc2l2ZVwiPlxuICA8dGFibGUgY2xhc3M9XCJ0YWJsZSB0YWJsZS1ib3JkZXJlZCB0YWJsZS1ob3ZlciBhbGlnbi1taWRkbGVcIj5cbiAgICA8dGhlYWQgY2xhc3M9XCJ0aGVhZCB0YWJsZS1saWdodFwiPlxuICAgICAgPHRyPlxuICAgICAgICBAZm9yIChjb2wgb2YgY29sdW1uczsgdHJhY2sgY29sKSB7XG4gICAgICAgIEBpZiAoY29sLnZpc2libGUgIT09IGZhbHNlKSB7XG4gICAgICAgIEBpZiAoY29sLnR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgICA8dGggY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPnt7IGNvbC5sYWJlbCB9fTwvdGg+XG4gICAgICAgIH1cbiAgICAgICAgQGVsc2Uge1xuICAgICAgICA8dGg+e3sgY29sLmxhYmVsIH19PC90aD5cbiAgICAgICAgfVxuICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgPHRoIGNsYXNzPVwidGFibGUtYWN0aW9ucy1oZWFkZXJcIj5cbiAgICAgICAgICA8c3Bhbj5BY3Rpb25zPC9zcGFuPlxuICAgICAgICAgIDxjODAtaWNvbiBidXR0b24gaWNvbj1cImFkZFwiIFtkaXNhYmxlZF09XCJjcmVhdGluZygpXCIgdGl0bGU9XCJBZ3JlZ2FyXCIgY2xhc3M9XCJhZGQtYWN0aW9uLWJ0blwiXG4gICAgICAgICAgICAoaWNvbkNsaWNrKT1cInN0YXJ0Q3JlYXRlKClcIj48L2M4MC1pY29uPlxuICAgICAgICA8L3RoPlxuICAgICAgPC90cj5cbiAgICA8L3RoZWFkPlxuICAgIDx0Ym9keT5cbiAgICAgIEBmb3IgKHJvdyBvZiBkYXRhKCk7IHRyYWNrIHRyYWNrQnlJZChpLCByb3cpOyBsZXQgaSA9ICRpbmRleCkge1xuICAgICAgPHRyPlxuICAgICAgICBAZm9yIChjb2wgb2YgY29sdW1uczsgdHJhY2sgY29sKSB7XG4gICAgICAgIEBpZiAoY29sLnZpc2libGUgIT09IGZhbHNlKSB7XG4gICAgICAgIEBpZiAoY29sLnR5cGUgPT09ICdib29sZWFuJykge1xuICAgICAgICA8dGQgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxuICAgICAgICAgIEBpZiAoZWRpdGluZygpID09PSByb3dbJ2lkJ10pIHtcbiAgICAgICAgICA8bWF0LWNoZWNrYm94IFtjaGVja2VkXT1cIiEhZWRpdFJvdygpPy5bY29sLmFjY2Vzc29yXVwiIChjaGFuZ2UpPVwib25FZGl0SW5wdXQoJGV2ZW50LCBjb2wuYWNjZXNzb3IsIGNvbClcIlxuICAgICAgICAgICAgW2FyaWEtbGFiZWxdPVwiY29sLmxhYmVsXCI+PC9tYXQtY2hlY2tib3g+XG4gICAgICAgICAgfVxuICAgICAgICAgIEBlbHNlIHtcbiAgICAgICAgICBAaWYgKHJvd1tjb2wuYWNjZXNzb3JdID09PSB0cnVlKSB7XG4gICAgICAgICAgPGM4MC1pY29uIGljb249XCJjaGVja1wiIFtzaXplXT1cIjFcIj48L2M4MC1pY29uPlxuICAgICAgICAgIDxiciAvPlxuICAgICAgICAgIH1cbiAgICAgICAgICBAZWxzZSBpZiAocm93W2NvbC5hY2Nlc3Nvcl0gPT09IGZhbHNlKSB7XG4gICAgICAgICAgPGM4MC1pY29uIGljb249XCJjYW5jZWxcIj48L2M4MC1pY29uPlxuICAgICAgICAgIDxiciAvPlxuICAgICAgICAgIH1cbiAgICAgICAgICB9XG4gICAgICAgIDwvdGQ+XG4gICAgICAgIH1cbiAgICAgICAgQGVsc2Uge1xuICAgICAgICA8dGQ+XG4gICAgICAgICAgQGlmIChlZGl0aW5nKCkgPT09IHJvd1snaWQnXSkge1xuICAgICAgICAgIDxpbnB1dCBjbGFzcz1cImZvcm0tY29udHJvbCBmb3JtLWNvbnRyb2wtc21cIiBbdHlwZV09XCJjb2wudHlwZSA9PT0gJ251bWJlcicgPyAnbnVtYmVyJyA6ICd0ZXh0J1wiXG4gICAgICAgICAgICBbdmFsdWVdPVwiZWRpdFJvdygpPy5bY29sLmFjY2Vzc29yXSA/PyAnJ1wiIFtwbGFjZWhvbGRlcl09XCJjb2wubGFiZWxcIlxuICAgICAgICAgICAgKGlucHV0KT1cIm9uRWRpdElucHV0KCRldmVudCwgY29sLmFjY2Vzc29yLCBjb2wpXCIgLz5cbiAgICAgICAgICB9XG4gICAgICAgICAgQGVsc2Uge1xuICAgICAgICAgIHt7IHJvd1tjb2wuYWNjZXNzb3JdIH19XG4gICAgICAgICAgfVxuICAgICAgICA8L3RkPlxuICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICA8dGQgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxuICAgICAgICAgIEBpZiAoZWRpdGluZygpID09PSByb3dbJ2lkJ10pIHtcbiAgICAgICAgICA8YzgwLWljb24gYnV0dG9uIGljb249XCJjaGVja1wiIHRpdGxlPVwiR3VhcmRhclwiIChpY29uQ2xpY2spPVwic2F2ZUVkaXQocm93KVwiPjwvYzgwLWljb24+XG4gICAgICAgICAgPGM4MC1pY29uIGJ1dHRvbiBpY29uPVwiY2FuY2VsXCIgY29sb3I9XCJ3YXJuXCIgdGl0bGU9XCJDYW5jZWxhclwiIChpY29uQ2xpY2spPVwiY2FuY2VsRWRpdCgpXCI+PC9jODAtaWNvbj5cbiAgICAgICAgICB9XG4gICAgICAgICAgQGVsc2Uge1xuICAgICAgICAgIDxjODAtaWNvbiBidXR0b24gaWNvbj1cImVkaXRcIiB0aXRsZT1cIkVkaXRhclwiIChpY29uQ2xpY2spPVwib25FZGl0KHJvdylcIj48L2M4MC1pY29uPlxuICAgICAgICAgIDxjODAtaWNvbiBidXR0b24gaWNvbj1cImRlbGV0ZVwiIGNvbG9yPVwid2FyblwiIHRpdGxlPVwiQm9ycmFyXCIgKGljb25DbGljayk9XCJvbkRlbGV0ZShyb3cpXCI+PC9jODAtaWNvbj5cbiAgICAgICAgICB9XG4gICAgICAgIDwvdGQ+XG4gICAgICA8L3RyPlxuICAgICAgfVxuICAgICAgQGlmIChjcmVhdGluZygpKSB7XG4gICAgICA8dHI+XG4gICAgICAgIEBmb3IgKGNvbCBvZiBjb2x1bW5zOyB0cmFjayBjb2wpIHtcbiAgICAgICAgQGlmIChjb2wudmlzaWJsZSAhPT0gZmFsc2UpIHtcbiAgICAgICAgQGlmIChjb2wudHlwZSA9PT0gJ2Jvb2xlYW4nKSB7XG4gICAgICAgIDx0ZCBjbGFzcz1cInRleHQtY2VudGVyXCI+XG4gICAgICAgICAgPG1hdC1jaGVja2JveCBbY2hlY2tlZF09XCIhIW5ld1JvdygpPy5bY29sLmFjY2Vzc29yXVwiIChjaGFuZ2UpPVwib25JbnB1dCgkZXZlbnQsIGNvbC5hY2Nlc3NvciwgY29sKVwiXG4gICAgICAgICAgICBbYXJpYS1sYWJlbF09XCJjb2wubGFiZWxcIj48L21hdC1jaGVja2JveD5cbiAgICAgICAgPC90ZD5cbiAgICAgICAgfSBAZWxzZSB7XG4gICAgICAgIDx0ZD5cbiAgICAgICAgICA8aW5wdXQgY2xhc3M9XCJmb3JtLWNvbnRyb2wgZm9ybS1jb250cm9sLXNtXCIgW3R5cGVdPVwiY29sLnR5cGUgPT09ICdudW1iZXInID8gJ251bWJlcicgOiAndGV4dCdcIlxuICAgICAgICAgICAgW3ZhbHVlXT1cIm5ld1JvdygpPy5bY29sLmFjY2Vzc29yXSA/PyAnJ1wiIFtwbGFjZWhvbGRlcl09XCJjb2wubGFiZWxcIlxuICAgICAgICAgICAgKGlucHV0KT1cIm9uSW5wdXQoJGV2ZW50LCBjb2wuYWNjZXNzb3IsIGNvbClcIiAvPlxuICAgICAgICA8L3RkPlxuICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICA8dGQgY2xhc3M9XCJ0ZXh0LWNlbnRlclwiPlxuICAgICAgICAgIDxjODAtaWNvbiBidXR0b24gaWNvbj1cImNoZWNrXCIgdGl0bGU9XCJHdWFyZGFyXCIgKGljb25DbGljayk9XCJzYXZlQ3JlYXRlKClcIj48L2M4MC1pY29uPlxuICAgICAgICAgIDxjODAtaWNvbiBidXR0b24gaWNvbj1cImNhbmNlbFwiIGNvbG9yPVwid2FyblwiIHRpdGxlPVwiQ2FuY2VsYXJcIiAoaWNvbkNsaWNrKT1cImNhbmNlbENyZWF0ZSgpXCI+PC9jODAtaWNvbj5cbiAgICAgICAgPC90ZD5cbiAgICAgIDwvdHI+XG4gICAgICB9XG4gICAgPC90Ym9keT5cbiAgPC90YWJsZT5cbiAgQGlmIChkYXRhKCkubGVuZ3RoID09PSAwKSB7XG4gIDxkaXYgY2xhc3M9XCJ0ZXh0LWNlbnRlciB0ZXh0LW11dGVkIHB5LTNcIj5cbiAgICBObyBoYXkgZGF0b3MgcGFyYSBtb3N0cmFyLlxuICA8L2Rpdj5cbiAgfVxuPC9kaXY+Il19
package/index.d.ts CHANGED
@@ -1 +1,2 @@
1
- export * from './lib/ui/ui.component';
1
+ export * from './lib/table/table.component';
2
+ export * from './lib/icon/icon.component';
@@ -0,0 +1,31 @@
1
+ import { EventEmitter, TemplateRef } from '@angular/core';
2
+ import * as i0 from "@angular/core";
3
+ export type Icon = 'check' | 'cancel' | 'edit' | 'delete' | 'add';
4
+ export type Color = 'primary' | 'secondary' | 'warn';
5
+ export declare class C80IconComponent {
6
+ /** Tamaño base del icono (en px) */
7
+ get iconSize(): number;
8
+ icon: Icon;
9
+ color: Color;
10
+ disabled?: boolean;
11
+ size: number;
12
+ /** Si es true, renderiza como <button> nativo, si es false solo como icono */
13
+ private _button;
14
+ set button(val: boolean | string | null | undefined);
15
+ get button(): boolean;
16
+ /** Tipo de botón nativo (solo si button=true) */
17
+ type: 'button' | 'submit' | 'reset';
18
+ /** Output para click (solo si button=true) */
19
+ iconClick: EventEmitter<Event>;
20
+ checkIconTpl: TemplateRef<unknown>;
21
+ cancelIconTpl: TemplateRef<unknown>;
22
+ editIconTpl: TemplateRef<unknown>;
23
+ deleteIconTpl: TemplateRef<unknown>;
24
+ addIconTpl: TemplateRef<unknown>;
25
+ defaultIconTpl: TemplateRef<unknown>;
26
+ getIconTemplate(): TemplateRef<unknown>;
27
+ get iconColor(): string;
28
+ onButtonClick(event: Event): void;
29
+ static ɵfac: i0.ɵɵFactoryDeclaration<C80IconComponent, never>;
30
+ static ɵcmp: i0.ɵɵComponentDeclaration<C80IconComponent, "c80-icon", never, { "icon": { "alias": "icon"; "required": false; }; "color": { "alias": "color"; "required": false; }; "disabled": { "alias": "disabled"; "required": false; }; "size": { "alias": "size"; "required": false; }; "button": { "alias": "button"; "required": false; }; "type": { "alias": "type"; "required": false; }; }, { "iconClick": "iconClick"; }, never, never, true, never>;
31
+ }
@@ -0,0 +1,60 @@
1
+ import { OnInit, EventEmitter } from '@angular/core';
2
+ import { Observable } from 'rxjs';
3
+ import type { MatCheckboxChange } from '@angular/material/checkbox';
4
+ import * as i0 from "@angular/core";
5
+ export interface C80TableService<T> {
6
+ get: () => Observable<T[]>;
7
+ create: (row: T) => Observable<T>;
8
+ delete: (id: number) => Observable<void>;
9
+ update: (id: number, row: T) => Observable<T>;
10
+ }
11
+ export interface C80TableColDef {
12
+ accessor: string;
13
+ label: string;
14
+ visible?: boolean;
15
+ type?: 'string' | 'number' | 'boolean';
16
+ }
17
+ export declare class C80TableComponent<T extends Record<string, unknown>> implements OnInit {
18
+ service: C80TableService<T>;
19
+ columns: C80TableColDef[];
20
+ errorEvent: EventEmitter<string>;
21
+ readonly data: import("@angular/core").WritableSignal<T[]>;
22
+ readonly keys: import("@angular/core").WritableSignal<string[]>;
23
+ creating: import("@angular/core").WritableSignal<boolean>;
24
+ newRow: import("@angular/core").WritableSignal<Partial<T> | null>;
25
+ readonly editing: import("@angular/core").WritableSignal<number | null>;
26
+ readonly editRow: import("@angular/core").WritableSignal<Partial<T> | null>;
27
+ ngOnInit(): void;
28
+ onInput(event: Event | MatCheckboxChange, key: string, col?: C80TableColDef): void;
29
+ onDelete(row: T): void;
30
+ refresh(): void;
31
+ startCreate(): void;
32
+ cancelCreate(): void;
33
+ updateNewRow(key: string, value: unknown): void;
34
+ saveCreate(): void;
35
+ /**
36
+ * Converts a cell value based on column type or sample data.
37
+ * Handles stringification of objects for string columns.
38
+ */
39
+ /**
40
+ * Converts a cell value based on column type or sample data.
41
+ * Delegates to type-specific helpers for clarity and maintainability.
42
+ */
43
+ private convertCellValue;
44
+ /** Converts value to boolean using best practices. */
45
+ private toBoolean;
46
+ /** Converts value to number using best practices. */
47
+ private toNumber;
48
+ /** Converts value to string using best practices, always stringifies objects. */
49
+ private toStringValue;
50
+ onEdit(row: T): void;
51
+ cancelEdit(): void;
52
+ onEditInput(event: Event | MatCheckboxChange, key: string, col?: C80TableColDef): void;
53
+ saveEdit(row: T): void;
54
+ /**
55
+ * TrackBy function for ngFor to avoid DOM re-creation (NG0956 warning).
56
+ */
57
+ trackById(index: number, row: T): number | string;
58
+ static ɵfac: i0.ɵɵFactoryDeclaration<C80TableComponent<any>, never>;
59
+ static ɵcmp: i0.ɵɵComponentDeclaration<C80TableComponent<any>, "c80-table", never, { "service": { "alias": "service"; "required": false; }; "columns": { "alias": "columns"; "required": false; }; }, { "errorEvent": "errorEvent"; }, never, never, true, never>;
60
+ }
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@c80/ui",
3
- "version": "0.0.1",
3
+ "version": "1.0.1",
4
4
  "peerDependencies": {
5
- "@angular/common": "^18.2.0",
6
- "@angular/core": "^18.2.0"
5
+ "@angular/core": "^18.2.0",
6
+ "rxjs": "~7.8.0",
7
+ "@angular/material": "^18.2.14",
8
+ "@angular/common": "~18.2.0"
7
9
  },
8
10
  "sideEffects": false,
9
11
  "module": "esm2022/c80-ui.mjs",
@@ -1,12 +0,0 @@
1
- import { ChangeDetectionStrategy, Component } from '@angular/core';
2
- import { CommonModule } from '@angular/common';
3
- import * as i0 from "@angular/core";
4
- export class UiComponent {
5
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UiComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
6
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.13", type: UiComponent, isStandalone: true, selector: "lib-ui", ngImport: i0, template: "<p>Ui works!</p>\n", styles: [""], dependencies: [{ kind: "ngmodule", type: CommonModule }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
7
- }
8
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: UiComponent, decorators: [{
9
- type: Component,
10
- args: [{ selector: 'lib-ui', standalone: true, imports: [CommonModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<p>Ui works!</p>\n" }]
11
- }] });
12
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidWkuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vbGlicy91aS9zcmMvbGliL3VpL3VpLmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uL2xpYnMvdWkvc3JjL2xpYi91aS91aS5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQ25FLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQzs7QUFVL0MsTUFBTSxPQUFPLFdBQVc7d0dBQVgsV0FBVzs0RkFBWCxXQUFXLGtFQ1h4QixvQkFDQSx5RERLWSxZQUFZOzs0RkFLWCxXQUFXO2tCQVJ2QixTQUFTOytCQUNFLFFBQVEsY0FDTixJQUFJLFdBQ1AsQ0FBQyxZQUFZLENBQUMsbUJBR04sdUJBQXVCLENBQUMsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDb21wb25lbnQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2xpYi11aScsXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtDb21tb25Nb2R1bGVdLFxuICB0ZW1wbGF0ZVVybDogJy4vdWkuY29tcG9uZW50Lmh0bWwnLFxuICBzdHlsZVVybDogJy4vdWkuY29tcG9uZW50LmNzcycsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxufSlcbmV4cG9ydCBjbGFzcyBVaUNvbXBvbmVudCB7fVxuIiwiPHA+VWkgd29ya3MhPC9wPlxuIl19
@@ -1,5 +0,0 @@
1
- import * as i0 from "@angular/core";
2
- export declare class UiComponent {
3
- static ɵfac: i0.ɵɵFactoryDeclaration<UiComponent, never>;
4
- static ɵcmp: i0.ɵɵComponentDeclaration<UiComponent, "lib-ui", never, {}, {}, never, never, true, never>;
5
- }