pdm-ui-kit 0.1.50 → 0.2.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 (46) hide show
  1. package/README.md +189 -2
  2. package/esm2020/lib/components/alert-dialog/alert-dialog.component.mjs +3 -3
  3. package/esm2020/lib/components/breadcrumb/breadcrumb.component.mjs +37 -4
  4. package/esm2020/lib/components/calendar/calendar.component.mjs +3 -3
  5. package/esm2020/lib/components/card/card.component.mjs +36 -53
  6. package/esm2020/lib/components/command/command.component.mjs +3 -3
  7. package/esm2020/lib/components/context-menu/context-menu.component.mjs +3 -3
  8. package/esm2020/lib/components/data-table/data-table.component.mjs +214 -16
  9. package/esm2020/lib/components/dialog/dialog.component.mjs +133 -17
  10. package/esm2020/lib/components/draggable-table/draggable-table.component.mjs +300 -0
  11. package/esm2020/lib/components/drawer/drawer.component.mjs +123 -16
  12. package/esm2020/lib/components/dropdown-menu/dropdown-menu.component.mjs +3 -2
  13. package/esm2020/lib/components/hover-card/hover-card.component.mjs +3 -3
  14. package/esm2020/lib/components/menubar/menubar.component.mjs +3 -3
  15. package/esm2020/lib/components/navigation-menu/navigation-menu.component.mjs +25 -3
  16. package/esm2020/lib/components/pagination/pagination.component.mjs +3 -3
  17. package/esm2020/lib/components/popover/popover.component.mjs +5 -3
  18. package/esm2020/lib/components/select/select.component.mjs +5 -3
  19. package/esm2020/lib/components/sheet/sheet.component.mjs +68 -12
  20. package/esm2020/lib/components/sidebar/sidebar.component.mjs +52 -5
  21. package/esm2020/lib/components/table/table.component.mjs +152 -188
  22. package/esm2020/lib/components/tabs/tabs.component.mjs +3 -3
  23. package/esm2020/lib/components/tooltip/tooltip.component.mjs +3 -3
  24. package/esm2020/lib/pdm-ui-kit.module.mjs +5 -1
  25. package/esm2020/lib/utils/responsive.mjs +143 -0
  26. package/esm2020/lib/utils/z-index.mjs +93 -0
  27. package/esm2020/public-api.mjs +4 -1
  28. package/fesm2015/pdm-ui-kit.mjs +1430 -371
  29. package/fesm2015/pdm-ui-kit.mjs.map +1 -1
  30. package/fesm2020/pdm-ui-kit.mjs +1428 -369
  31. package/fesm2020/pdm-ui-kit.mjs.map +1 -1
  32. package/lib/components/breadcrumb/breadcrumb.component.d.ts +23 -1
  33. package/lib/components/card/card.component.d.ts +32 -19
  34. package/lib/components/data-table/data-table.component.d.ts +172 -14
  35. package/lib/components/dialog/dialog.component.d.ts +35 -1
  36. package/lib/components/draggable-table/draggable-table.component.d.ts +74 -0
  37. package/lib/components/drawer/drawer.component.d.ts +65 -7
  38. package/lib/components/navigation-menu/navigation-menu.component.d.ts +22 -1
  39. package/lib/components/sheet/sheet.component.d.ts +30 -3
  40. package/lib/components/sidebar/sidebar.component.d.ts +39 -1
  41. package/lib/components/table/table.component.d.ts +46 -25
  42. package/lib/pdm-ui-kit.module.d.ts +42 -41
  43. package/lib/utils/responsive.d.ts +107 -0
  44. package/lib/utils/z-index.d.ts +73 -0
  45. package/package.json +5 -3
  46. package/public-api.d.ts +3 -0
@@ -131,10 +131,10 @@ class PdmAlertDialogComponent {
131
131
  }
132
132
  }
133
133
  PdmAlertDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmAlertDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
134
- PdmAlertDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmAlertDialogComponent, selector: "pdm-alert-dialog", inputs: { open: "open", showTrigger: "showTrigger", triggerText: "triggerText", title: "title", description: "description", confirmText: "confirmText", cancelText: "cancelText", className: "className", closeOnEsc: "closeOnEsc" }, outputs: { openChange: "openChange", confirm: "confirm", cancel: "cancel" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<button\n *ngIf=\"showTrigger && !open\"\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onTriggerClick()\"\n>\n {{ triggerText }}\n</button>\n\n<div *ngIf=\"open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-5\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onCancel()\"></div>\n <section\n role=\"alertdialog\"\n aria-modal=\"true\"\n [ngClass]=\"[\n 'relative z-10 w-full max-w-lg rounded-lg border border-border bg-background p-6 text-foreground shadow-lg',\n className\n ]\"\n >\n <div class=\"flex flex-col gap-2\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <div class=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onCancel()\"\n >\n {{ cancelText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onConfirm()\"\n >\n {{ confirmText }}\n </button>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
134
+ PdmAlertDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmAlertDialogComponent, selector: "pdm-alert-dialog", inputs: { open: "open", showTrigger: "showTrigger", triggerText: "triggerText", title: "title", description: "description", confirmText: "confirmText", cancelText: "cancelText", className: "className", closeOnEsc: "closeOnEsc" }, outputs: { openChange: "openChange", confirm: "confirm", cancel: "cancel" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<button\n *ngIf=\"showTrigger && !open\"\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onTriggerClick()\"\n>\n {{ triggerText }}\n</button>\n\n<div *ngIf=\"open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-5\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onCancel()\"></div>\n <section\n role=\"alertdialog\"\n aria-modal=\"true\"\n [ngClass]=\"[\n 'relative z-[60] w-full max-w-lg rounded-lg border border-border bg-background p-6 text-foreground shadow-lg',\n className\n ]\"\n >\n <div class=\"flex flex-col gap-2\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <div class=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onCancel()\"\n >\n {{ cancelText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onConfirm()\"\n >\n {{ confirmText }}\n </button>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
135
135
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmAlertDialogComponent, decorators: [{
136
136
  type: Component,
137
- args: [{ selector: 'pdm-alert-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n *ngIf=\"showTrigger && !open\"\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onTriggerClick()\"\n>\n {{ triggerText }}\n</button>\n\n<div *ngIf=\"open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-5\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onCancel()\"></div>\n <section\n role=\"alertdialog\"\n aria-modal=\"true\"\n [ngClass]=\"[\n 'relative z-10 w-full max-w-lg rounded-lg border border-border bg-background p-6 text-foreground shadow-lg',\n className\n ]\"\n >\n <div class=\"flex flex-col gap-2\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <div class=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onCancel()\"\n >\n {{ cancelText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onConfirm()\"\n >\n {{ confirmText }}\n </button>\n </div>\n </section>\n</div>\n" }]
137
+ args: [{ selector: 'pdm-alert-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n *ngIf=\"showTrigger && !open\"\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onTriggerClick()\"\n>\n {{ triggerText }}\n</button>\n\n<div *ngIf=\"open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-5\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onCancel()\"></div>\n <section\n role=\"alertdialog\"\n aria-modal=\"true\"\n [ngClass]=\"[\n 'relative z-[60] w-full max-w-lg rounded-lg border border-border bg-background p-6 text-foreground shadow-lg',\n className\n ]\"\n >\n <div class=\"flex flex-col gap-2\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <div class=\"mt-4 flex items-center justify-end gap-2\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onCancel()\"\n >\n {{ cancelText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onConfirm()\"\n >\n {{ confirmText }}\n </button>\n </div>\n </section>\n</div>\n" }]
138
138
  }], propDecorators: { open: [{
139
139
  type: Input
140
140
  }], showTrigger: [{
@@ -255,30 +255,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
255
255
  type: Input
256
256
  }] } });
257
257
 
258
+ /**
259
+ * Breadcrumb component con soporte responsive
260
+ *
261
+ * MEJORADO en v0.2.0:
262
+ * - Modo responsive real con overflow-x-auto
263
+ * - Collapse inteligente en mobile
264
+ *
265
+ * @example
266
+ * <pdm-breadcrumb
267
+ * mode="responsive"
268
+ * [items]="['Home', 'Products', 'Electronics', 'Laptops']">
269
+ * </pdm-breadcrumb>
270
+ */
258
271
  class PdmBreadcrumbComponent {
259
272
  constructor() {
260
273
  this.mode = 'link-component';
261
274
  this.items = ['Home', 'Components', 'Breadcrumb'];
262
275
  this.className = '';
276
+ /**
277
+ * Cantidad mínima de items para mostrar en mobile cuando mode="responsive"
278
+ * Default: 2 (primer y último item)
279
+ */
280
+ this.minItemsMobile = 2;
263
281
  }
264
282
  get renderedItems() {
265
- if ((this.mode === 'collapsed' || this.mode === 'responsive') && this.items.length > 3) {
283
+ if (this.mode === 'collapsed' && this.items.length > 3) {
266
284
  return [this.items[0], '...', this.items[this.items.length - 2], this.items[this.items.length - 1]];
267
285
  }
286
+ // Responsive mode: no collapse en el TS, se maneja en el template con CSS
268
287
  return this.items;
269
288
  }
289
+ /**
290
+ * Determina si un item debe estar visible en mobile (modo responsive)
291
+ */
292
+ shouldShowInMobile(index) {
293
+ if (this.mode !== 'responsive')
294
+ return true;
295
+ const totalItems = this.items.length;
296
+ if (totalItems <= this.minItemsMobile)
297
+ return true;
298
+ // Siempre mostrar primero y último
299
+ return index === 0 || index === totalItems - 1;
300
+ }
270
301
  }
271
302
  PdmBreadcrumbComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmBreadcrumbComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
272
- PdmBreadcrumbComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmBreadcrumbComponent, selector: "pdm-breadcrumb", inputs: { mode: "mode", items: "items", className: "className" }, ngImport: i0, template: "<nav\n aria-label=\"breadcrumb\"\n [ngClass]=\"['inline-flex items-center gap-1.5 text-sm', className]\"\n>\n <ng-container *ngFor=\"let item of renderedItems; let i = index; let last = last\">\n <span [ngClass]=\"[last ? 'text-foreground' : 'text-muted-foreground']\">{{ item }}</span>\n\n <ng-container *ngIf=\"!last\">\n <span class=\"inline-flex h-6 w-6 items-center justify-center text-muted-foreground\" aria-hidden=\"true\">\n <svg\n *ngIf=\"mode === 'custom-separator' && item !== '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M8 20L16 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <svg\n *ngIf=\"(mode !== 'custom-separator' && item !== '...') || item === '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n </ng-container>\n\n <ng-container *ngIf=\"mode === 'dropdown' && i === 1 && item !== '...' && !last\">\n <span class=\"-ml-2 inline-flex h-6 w-6 items-center justify-center text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n </ng-container>\n </ng-container>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
303
+ PdmBreadcrumbComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmBreadcrumbComponent, selector: "pdm-breadcrumb", inputs: { mode: "mode", items: "items", className: "className", minItemsMobile: "minItemsMobile" }, ngImport: i0, template: "<nav\n aria-label=\"breadcrumb\"\n [ngClass]=\"[\n 'inline-flex items-center gap-1.5 text-sm',\n mode === 'responsive' ? 'overflow-x-auto max-w-full pb-1 scrollbar-thin' : '',\n className\n ]\"\n>\n <ng-container *ngFor=\"let item of renderedItems; let i = index; let last = last\">\n <!-- Item text -->\n <span \n [ngClass]=\"[\n last ? 'text-foreground font-medium' : 'text-muted-foreground hover:text-foreground transition-colors cursor-pointer',\n mode === 'responsive' && !shouldShowInMobile(i) ? 'hidden sm:inline' : '',\n 'whitespace-nowrap'\n ]\">\n {{ item }}\n </span>\n\n <!-- Separator -->\n <ng-container *ngIf=\"!last\">\n <span \n [ngClass]=\"[\n 'inline-flex h-6 w-6 flex-shrink-0 items-center justify-center text-muted-foreground',\n mode === 'responsive' && !shouldShowInMobile(i) && !shouldShowInMobile(i + 1) ? 'hidden sm:inline-flex' : ''\n ]\" \n aria-hidden=\"true\">\n <!-- Custom separator (slash) -->\n <svg\n *ngIf=\"mode === 'custom-separator' && item !== '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M8 20L16 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n \n <!-- Default separator (chevron) -->\n <svg\n *ngIf=\"(mode !== 'custom-separator' && item !== '...') || item === '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n \n <!-- Ellipsis indicator for responsive mode (only shown when items are hidden) -->\n <span \n *ngIf=\"mode === 'responsive' && !shouldShowInMobile(i) && i === 0\"\n class=\"inline-flex sm:hidden text-muted-foreground\">\n ...\n </span>\n </ng-container>\n\n <!-- Dropdown indicator -->\n <ng-container *ngIf=\"mode === 'dropdown' && i === 1 && item !== '...' && !last\">\n <span class=\"-ml-2 inline-flex h-6 w-6 items-center justify-center text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n </ng-container>\n </ng-container>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
273
304
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmBreadcrumbComponent, decorators: [{
274
305
  type: Component,
275
- args: [{ selector: 'pdm-breadcrumb', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n aria-label=\"breadcrumb\"\n [ngClass]=\"['inline-flex items-center gap-1.5 text-sm', className]\"\n>\n <ng-container *ngFor=\"let item of renderedItems; let i = index; let last = last\">\n <span [ngClass]=\"[last ? 'text-foreground' : 'text-muted-foreground']\">{{ item }}</span>\n\n <ng-container *ngIf=\"!last\">\n <span class=\"inline-flex h-6 w-6 items-center justify-center text-muted-foreground\" aria-hidden=\"true\">\n <svg\n *ngIf=\"mode === 'custom-separator' && item !== '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M8 20L16 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n <svg\n *ngIf=\"(mode !== 'custom-separator' && item !== '...') || item === '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n </ng-container>\n\n <ng-container *ngIf=\"mode === 'dropdown' && i === 1 && item !== '...' && !last\">\n <span class=\"-ml-2 inline-flex h-6 w-6 items-center justify-center text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n </ng-container>\n </ng-container>\n</nav>\n" }]
306
+ args: [{ selector: 'pdm-breadcrumb', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n aria-label=\"breadcrumb\"\n [ngClass]=\"[\n 'inline-flex items-center gap-1.5 text-sm',\n mode === 'responsive' ? 'overflow-x-auto max-w-full pb-1 scrollbar-thin' : '',\n className\n ]\"\n>\n <ng-container *ngFor=\"let item of renderedItems; let i = index; let last = last\">\n <!-- Item text -->\n <span \n [ngClass]=\"[\n last ? 'text-foreground font-medium' : 'text-muted-foreground hover:text-foreground transition-colors cursor-pointer',\n mode === 'responsive' && !shouldShowInMobile(i) ? 'hidden sm:inline' : '',\n 'whitespace-nowrap'\n ]\">\n {{ item }}\n </span>\n\n <!-- Separator -->\n <ng-container *ngIf=\"!last\">\n <span \n [ngClass]=\"[\n 'inline-flex h-6 w-6 flex-shrink-0 items-center justify-center text-muted-foreground',\n mode === 'responsive' && !shouldShowInMobile(i) && !shouldShowInMobile(i + 1) ? 'hidden sm:inline-flex' : ''\n ]\" \n aria-hidden=\"true\">\n <!-- Custom separator (slash) -->\n <svg\n *ngIf=\"mode === 'custom-separator' && item !== '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M8 20L16 4\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" />\n </svg>\n \n <!-- Default separator (chevron) -->\n <svg\n *ngIf=\"(mode !== 'custom-separator' && item !== '...') || item === '...'\"\n viewBox=\"0 0 24 24\"\n class=\"h-4 w-4\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n \n <!-- Ellipsis indicator for responsive mode (only shown when items are hidden) -->\n <span \n *ngIf=\"mode === 'responsive' && !shouldShowInMobile(i) && i === 0\"\n class=\"inline-flex sm:hidden text-muted-foreground\">\n ...\n </span>\n </ng-container>\n\n <!-- Dropdown indicator -->\n <ng-container *ngIf=\"mode === 'dropdown' && i === 1 && item !== '...' && !last\">\n <span class=\"-ml-2 inline-flex h-6 w-6 items-center justify-center text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\" />\n </svg>\n </span>\n </ng-container>\n </ng-container>\n</nav>\n" }]
276
307
  }], propDecorators: { mode: [{
277
308
  type: Input
278
309
  }], items: [{
279
310
  type: Input
280
311
  }], className: [{
281
312
  type: Input
313
+ }], minItemsMobile: [{
314
+ type: Input
282
315
  }] } });
283
316
 
284
317
  class PdmButtonGroupComponent {
@@ -1058,10 +1091,10 @@ class PdmCalendarComponent {
1058
1091
  }
1059
1092
  }
1060
1093
  PdmCalendarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCalendarComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
1061
- PdmCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: { variant: "variant", className: "className", disabledDates: "disabledDates", minDate: "minDate", maxDate: "maxDate", minYear: "minYear", maxYear: "maxYear", isDateDisabled: "isDateDisabled", allowSameDayRange: "allowSameDayRange", readonly: "readonly", value: "value", rangeValue: "rangeValue", month: "month" }, outputs: { valueChange: "valueChange", rangeValueChange: "rangeValueChange", monthChange: "monthChange", dateClick: "dateClick", disabledDateClick: "disabledDateClick" }, ngImport: i0, template: "<div [ngClass]=\"rootClasses\" [ngStyle]=\"rootStyle\">\n <div *ngFor=\"let month of visibleMonths; let monthIndex = index; trackBy: trackByIndex\" [ngClass]=\"monthPanelClasses(monthIndex)\">\n <div [ngClass]=\"headerClasses(month)\">\n <button\n *ngIf=\"month.showPrevButton; else prevPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Previous month\"\n (click)=\"goToPreviousMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #prevPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container *ngIf=\"month.titleStyle === 'dropdowns'; else plainTitle\">\n <div [ngClass]=\"dropdownWrapClasses()\">\n <div [ngClass]=\"dropdownClasses('w-[72px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderMonth\"\n aria-label=\"Month\"\n (change)=\"onSingleMonthChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let monthOption of monthOptions\"\n [value]=\"monthOption.value\"\n [selected]=\"monthOption.value === singleHeaderMonth\"\n >\n {{ monthOption.label }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n <div [ngClass]=\"dropdownClasses('w-[82px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderYear\"\n aria-label=\"Year\"\n (change)=\"onSingleYearChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let year of yearOptions\"\n [value]=\"year\"\n [selected]=\"year === singleHeaderYear\"\n >\n {{ year }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n </div>\n </ng-container>\n\n <ng-template #plainTitle>\n <div class=\"flex min-w-0 flex-1 items-center justify-center\">\n <p class=\"m-0 text-foreground text-center text-sm font-medium leading-5\">\n {{ month.title }}\n </p>\n </div>\n </ng-template>\n\n <button\n *ngIf=\"month.showNextButton; else nextPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #nextPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n </div>\n\n <div [ngClass]=\"calendarGridWrapClasses()\">\n <div [ngClass]=\"weekdayRowClasses()\">\n <div *ngFor=\"let day of weekdays; trackBy: trackByIndex\" [ngClass]=\"weekdayCellClasses()\">\n <span>{{ day }}</span>\n </div>\n </div>\n\n <div *ngFor=\"let week of month.weeks; trackBy: trackByIndex\" [ngClass]=\"weekRowClasses()\">\n <div *ngFor=\"let cell of week; trackBy: trackByDate\" [ngClass]=\"dayCellClasses(cell)\">\n <button\n type=\"button\"\n [ngClass]=\"dayButtonClasses(cell)\"\n [disabled]=\"readonly\"\n [attr.aria-selected]=\"cell.selected\"\n [attr.aria-disabled]=\"cell.disabled || readonly\"\n [attr.title]=\"cell.date | date : 'yyyy-MM-dd'\"\n (click)=\"onDatePressed(cell)\"\n >\n <span [ngClass]=\"dayLabelClasses(cell)\">{{ cell.label }}</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1094
+ PdmCalendarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: { variant: "variant", className: "className", disabledDates: "disabledDates", minDate: "minDate", maxDate: "maxDate", minYear: "minYear", maxYear: "maxYear", isDateDisabled: "isDateDisabled", allowSameDayRange: "allowSameDayRange", readonly: "readonly", value: "value", rangeValue: "rangeValue", month: "month" }, outputs: { valueChange: "valueChange", rangeValueChange: "rangeValueChange", monthChange: "monthChange", dateClick: "dateClick", disabledDateClick: "disabledDateClick" }, ngImport: i0, template: "<div [ngClass]=\"rootClasses\" [ngStyle]=\"rootStyle\">\n <div *ngFor=\"let month of visibleMonths; let monthIndex = index; trackBy: trackByIndex\" [ngClass]=\"monthPanelClasses(monthIndex)\">\n <div [ngClass]=\"headerClasses(month)\">\n <button\n *ngIf=\"month.showPrevButton; else prevPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Previous month\"\n (click)=\"goToPreviousMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #prevPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container *ngIf=\"month.titleStyle === 'dropdowns'; else plainTitle\">\n <div [ngClass]=\"dropdownWrapClasses()\">\n <div [ngClass]=\"dropdownClasses('w-16 sm:w-[72px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderMonth\"\n aria-label=\"Month\"\n (change)=\"onSingleMonthChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let monthOption of monthOptions\"\n [value]=\"monthOption.value\"\n [selected]=\"monthOption.value === singleHeaderMonth\"\n >\n {{ monthOption.label }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n <div [ngClass]=\"dropdownClasses('w-16 sm:w-[82px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderYear\"\n aria-label=\"Year\"\n (change)=\"onSingleYearChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let year of yearOptions\"\n [value]=\"year\"\n [selected]=\"year === singleHeaderYear\"\n >\n {{ year }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n </div>\n </ng-container>\n\n <ng-template #plainTitle>\n <div class=\"flex min-w-0 flex-1 items-center justify-center\">\n <p class=\"m-0 text-foreground text-center text-sm font-medium leading-5\">\n {{ month.title }}\n </p>\n </div>\n </ng-template>\n\n <button\n *ngIf=\"month.showNextButton; else nextPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #nextPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n </div>\n\n <div [ngClass]=\"calendarGridWrapClasses()\">\n <div [ngClass]=\"weekdayRowClasses()\">\n <div *ngFor=\"let day of weekdays; trackBy: trackByIndex\" [ngClass]=\"weekdayCellClasses()\">\n <span>{{ day }}</span>\n </div>\n </div>\n\n <div *ngFor=\"let week of month.weeks; trackBy: trackByIndex\" [ngClass]=\"weekRowClasses()\">\n <div *ngFor=\"let cell of week; trackBy: trackByDate\" [ngClass]=\"dayCellClasses(cell)\">\n <button\n type=\"button\"\n [ngClass]=\"dayButtonClasses(cell)\"\n [disabled]=\"readonly\"\n [attr.aria-selected]=\"cell.selected\"\n [attr.aria-disabled]=\"cell.disabled || readonly\"\n [attr.title]=\"cell.date | date : 'yyyy-MM-dd'\"\n (click)=\"onDatePressed(cell)\"\n >\n <span [ngClass]=\"dayLabelClasses(cell)\">{{ cell.label }}</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i1.DatePipe, name: "date" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1062
1095
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCalendarComponent, decorators: [{
1063
1096
  type: Component,
1064
- args: [{ selector: 'pdm-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"rootClasses\" [ngStyle]=\"rootStyle\">\n <div *ngFor=\"let month of visibleMonths; let monthIndex = index; trackBy: trackByIndex\" [ngClass]=\"monthPanelClasses(monthIndex)\">\n <div [ngClass]=\"headerClasses(month)\">\n <button\n *ngIf=\"month.showPrevButton; else prevPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Previous month\"\n (click)=\"goToPreviousMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #prevPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container *ngIf=\"month.titleStyle === 'dropdowns'; else plainTitle\">\n <div [ngClass]=\"dropdownWrapClasses()\">\n <div [ngClass]=\"dropdownClasses('w-[72px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderMonth\"\n aria-label=\"Month\"\n (change)=\"onSingleMonthChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let monthOption of monthOptions\"\n [value]=\"monthOption.value\"\n [selected]=\"monthOption.value === singleHeaderMonth\"\n >\n {{ monthOption.label }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n <div [ngClass]=\"dropdownClasses('w-[82px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderYear\"\n aria-label=\"Year\"\n (change)=\"onSingleYearChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let year of yearOptions\"\n [value]=\"year\"\n [selected]=\"year === singleHeaderYear\"\n >\n {{ year }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n </div>\n </ng-container>\n\n <ng-template #plainTitle>\n <div class=\"flex min-w-0 flex-1 items-center justify-center\">\n <p class=\"m-0 text-foreground text-center text-sm font-medium leading-5\">\n {{ month.title }}\n </p>\n </div>\n </ng-template>\n\n <button\n *ngIf=\"month.showNextButton; else nextPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #nextPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n </div>\n\n <div [ngClass]=\"calendarGridWrapClasses()\">\n <div [ngClass]=\"weekdayRowClasses()\">\n <div *ngFor=\"let day of weekdays; trackBy: trackByIndex\" [ngClass]=\"weekdayCellClasses()\">\n <span>{{ day }}</span>\n </div>\n </div>\n\n <div *ngFor=\"let week of month.weeks; trackBy: trackByIndex\" [ngClass]=\"weekRowClasses()\">\n <div *ngFor=\"let cell of week; trackBy: trackByDate\" [ngClass]=\"dayCellClasses(cell)\">\n <button\n type=\"button\"\n [ngClass]=\"dayButtonClasses(cell)\"\n [disabled]=\"readonly\"\n [attr.aria-selected]=\"cell.selected\"\n [attr.aria-disabled]=\"cell.disabled || readonly\"\n [attr.title]=\"cell.date | date : 'yyyy-MM-dd'\"\n (click)=\"onDatePressed(cell)\"\n >\n <span [ngClass]=\"dayLabelClasses(cell)\">{{ cell.label }}</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
1097
+ args: [{ selector: 'pdm-calendar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"rootClasses\" [ngStyle]=\"rootStyle\">\n <div *ngFor=\"let month of visibleMonths; let monthIndex = index; trackBy: trackByIndex\" [ngClass]=\"monthPanelClasses(monthIndex)\">\n <div [ngClass]=\"headerClasses(month)\">\n <button\n *ngIf=\"month.showPrevButton; else prevPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Previous month\"\n (click)=\"goToPreviousMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m15 18-6-6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #prevPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n\n <ng-container *ngIf=\"month.titleStyle === 'dropdowns'; else plainTitle\">\n <div [ngClass]=\"dropdownWrapClasses()\">\n <div [ngClass]=\"dropdownClasses('w-16 sm:w-[72px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderMonth\"\n aria-label=\"Month\"\n (change)=\"onSingleMonthChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let monthOption of monthOptions\"\n [value]=\"monthOption.value\"\n [selected]=\"monthOption.value === singleHeaderMonth\"\n >\n {{ monthOption.label }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n <div [ngClass]=\"dropdownClasses('w-16 sm:w-[82px]')\">\n <select\n [ngClass]=\"dropdownSelectClasses()\"\n [ngStyle]=\"dropdownSelectStyle\"\n [value]=\"singleHeaderYear\"\n aria-label=\"Year\"\n (change)=\"onSingleYearChange($any($event.target).value)\"\n >\n <option\n *ngFor=\"let year of yearOptions\"\n [value]=\"year\"\n [selected]=\"year === singleHeaderYear\"\n >\n {{ year }}\n </option>\n </select>\n <svg viewBox=\"0 0 24 24\" class=\"h-3 w-3 text-foreground\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m6 9 6 6 6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </div>\n </div>\n </ng-container>\n\n <ng-template #plainTitle>\n <div class=\"flex min-w-0 flex-1 items-center justify-center\">\n <p class=\"m-0 text-foreground text-center text-sm font-medium leading-5\">\n {{ month.title }}\n </p>\n </div>\n </ng-template>\n\n <button\n *ngIf=\"month.showNextButton; else nextPlaceholder\"\n type=\"button\"\n [ngClass]=\"navButtonClasses()\"\n aria-label=\"Next month\"\n (click)=\"goToNextMonth()\"\n [disabled]=\"readonly\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\" aria-hidden=\"true\">\n <path d=\"m9 18 6-6-6-6\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n <ng-template #nextPlaceholder>\n <div [ngClass]=\"navPlaceholderClasses()\" aria-hidden=\"true\"></div>\n </ng-template>\n </div>\n\n <div [ngClass]=\"calendarGridWrapClasses()\">\n <div [ngClass]=\"weekdayRowClasses()\">\n <div *ngFor=\"let day of weekdays; trackBy: trackByIndex\" [ngClass]=\"weekdayCellClasses()\">\n <span>{{ day }}</span>\n </div>\n </div>\n\n <div *ngFor=\"let week of month.weeks; trackBy: trackByIndex\" [ngClass]=\"weekRowClasses()\">\n <div *ngFor=\"let cell of week; trackBy: trackByDate\" [ngClass]=\"dayCellClasses(cell)\">\n <button\n type=\"button\"\n [ngClass]=\"dayButtonClasses(cell)\"\n [disabled]=\"readonly\"\n [attr.aria-selected]=\"cell.selected\"\n [attr.aria-disabled]=\"cell.disabled || readonly\"\n [attr.title]=\"cell.date | date : 'yyyy-MM-dd'\"\n (click)=\"onDatePressed(cell)\"\n >\n <span [ngClass]=\"dayLabelClasses(cell)\">{{ cell.label }}</span>\n </button>\n </div>\n </div>\n </div>\n </div>\n</div>\n" }]
1065
1098
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { variant: [{
1066
1099
  type: Input
1067
1100
  }], className: [{
@@ -1199,66 +1232,49 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1199
1232
  type: Output
1200
1233
  }] } });
1201
1234
 
1235
+ /**
1236
+ * Card component - Visual container primitivo
1237
+ *
1238
+ * BREAKING CHANGE en v0.2.0: variant="login" eliminado.
1239
+ * Card es ahora un componente UI puro sin lógica de negocio.
1240
+ *
1241
+ * Para crear un login form, componer con primitivos:
1242
+ *
1243
+ * @example
1244
+ * <pdm-card>
1245
+ * <div pdmCardHeader>
1246
+ * <h3 class="text-lg font-semibold">Login</h3>
1247
+ * <p class="text-sm text-muted-foreground">Enter your credentials</p>
1248
+ * </div>
1249
+ * <div pdmCardContent>
1250
+ * <form [formGroup]="form">
1251
+ * <pdm-field>
1252
+ * <pdm-label>Email</pdm-label>
1253
+ * <pdm-input type="email" formControlName="email" />
1254
+ * </pdm-field>
1255
+ * <pdm-field>
1256
+ * <pdm-label>Password</pdm-label>
1257
+ * <pdm-input-password formControlName="password" />
1258
+ * </pdm-field>
1259
+ * </form>
1260
+ * </div>
1261
+ * <div pdmCardFooter>
1262
+ * <pdm-button (click)="onLogin()">Login</pdm-button>
1263
+ * </div>
1264
+ * </pdm-card>
1265
+ */
1202
1266
  class PdmCardComponent {
1203
1267
  constructor() {
1204
- this.variant = 'default';
1205
1268
  this.className = '';
1206
- this.title = 'Login to your account';
1207
- this.description = 'Enter your email below to login to your account';
1208
- this.actionText = 'Sign up';
1209
- this.emailLabel = 'Email';
1210
- this.emailPlaceholder = 'm@example.com';
1211
- this.passwordLabel = 'Password';
1212
- this.passwordHint = 'Forgot password?';
1213
- this.primaryActionText = 'Login';
1214
- this.secondaryActionText = 'Login with Google';
1215
- this.primaryAction = new EventEmitter();
1216
- this.secondaryAction = new EventEmitter();
1217
- this.actionPressed = new EventEmitter();
1218
- }
1219
- onPrimaryAction() {
1220
- this.primaryAction.emit();
1221
- }
1222
- onSecondaryAction() {
1223
- this.secondaryAction.emit();
1224
- }
1225
- onActionPressed() {
1226
- this.actionPressed.emit();
1227
1269
  }
1228
1270
  }
1229
1271
  PdmCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1230
- PdmCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCardComponent, selector: "pdm-card", inputs: { variant: "variant", className: "className", title: "title", description: "description", actionText: "actionText", emailLabel: "emailLabel", emailPlaceholder: "emailPlaceholder", passwordLabel: "passwordLabel", passwordHint: "passwordHint", primaryActionText: "primaryActionText", secondaryActionText: "secondaryActionText" }, outputs: { primaryAction: "primaryAction", secondaryAction: "secondaryAction", actionPressed: "actionPressed" }, ngImport: i0, template: "<section\n [ngClass]=\"[\n 'w-full rounded-lg border border-border bg-background py-6 shadow-sm',\n className\n ]\"\n>\n <ng-container *ngIf=\"variant === 'login'; else defaultCard\">\n <div class=\"flex w-full items-start gap-1.5 px-6\">\n <div class=\"min-w-0 flex-1\">\n <h3 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ title }}</h3>\n <p class=\"m-0 mt-1.5 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border-0 bg-transparent px-4 py-2 text-sm font-medium text-foreground\"\n (click)=\"onActionPressed()\"\n >\n {{ actionText }}\n </button>\n </div>\n\n <div class=\"mt-6 flex flex-col gap-4 px-6\">\n <div class=\"w-full\">\n <label class=\"mb-3 block text-sm font-medium text-foreground\">{{ emailLabel }}</label>\n <input\n type=\"email\"\n [placeholder]=\"emailPlaceholder\"\n class=\"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n </div>\n\n <div class=\"w-full\">\n <div class=\"mb-3 flex w-full items-center justify-between gap-4\">\n <label class=\"text-sm font-medium text-foreground\">{{ passwordLabel }}</label>\n <button type=\"button\" class=\"appearance-none border-0 bg-transparent p-0 text-sm text-foreground\">\n {{ passwordHint }}\n </button>\n </div>\n <input\n type=\"password\"\n class=\"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n </div>\n </div>\n\n <div class=\"mt-6 flex w-full flex-col gap-2 px-6\">\n <button\n type=\"button\"\n class=\"flex h-9 w-full appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onPrimaryAction()\"\n >\n {{ primaryActionText }}\n </button>\n <button\n type=\"button\"\n class=\"flex h-9 w-full appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n </div>\n </ng-container>\n\n <ng-template #defaultCard>\n <div class=\"flex w-full flex-col gap-6\">\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardHeader]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardContent]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardFooter]\"></ng-content>\n </div>\n </div>\n </ng-template>\n</section>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1272
+ PdmCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCardComponent, selector: "pdm-card", inputs: { className: "className" }, ngImport: i0, template: "<section\n [ngClass]=\"[\n 'w-full rounded-lg border border-border bg-background py-6 shadow-sm',\n className\n ]\"\n>\n <div class=\"flex w-full flex-col gap-6\">\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardHeader]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardContent]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardFooter]\"></ng-content>\n </div>\n </div>\n</section>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1231
1273
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCardComponent, decorators: [{
1232
1274
  type: Component,
1233
- args: [{ selector: 'pdm-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<section\n [ngClass]=\"[\n 'w-full rounded-lg border border-border bg-background py-6 shadow-sm',\n className\n ]\"\n>\n <ng-container *ngIf=\"variant === 'login'; else defaultCard\">\n <div class=\"flex w-full items-start gap-1.5 px-6\">\n <div class=\"min-w-0 flex-1\">\n <h3 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ title }}</h3>\n <p class=\"m-0 mt-1.5 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border-0 bg-transparent px-4 py-2 text-sm font-medium text-foreground\"\n (click)=\"onActionPressed()\"\n >\n {{ actionText }}\n </button>\n </div>\n\n <div class=\"mt-6 flex flex-col gap-4 px-6\">\n <div class=\"w-full\">\n <label class=\"mb-3 block text-sm font-medium text-foreground\">{{ emailLabel }}</label>\n <input\n type=\"email\"\n [placeholder]=\"emailPlaceholder\"\n class=\"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n </div>\n\n <div class=\"w-full\">\n <div class=\"mb-3 flex w-full items-center justify-between gap-4\">\n <label class=\"text-sm font-medium text-foreground\">{{ passwordLabel }}</label>\n <button type=\"button\" class=\"appearance-none border-0 bg-transparent p-0 text-sm text-foreground\">\n {{ passwordHint }}\n </button>\n </div>\n <input\n type=\"password\"\n class=\"h-9 w-full rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n </div>\n </div>\n\n <div class=\"mt-6 flex w-full flex-col gap-2 px-6\">\n <button\n type=\"button\"\n class=\"flex h-9 w-full appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onPrimaryAction()\"\n >\n {{ primaryActionText }}\n </button>\n <button\n type=\"button\"\n class=\"flex h-9 w-full appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n </div>\n </ng-container>\n\n <ng-template #defaultCard>\n <div class=\"flex w-full flex-col gap-6\">\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardHeader]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardContent]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardFooter]\"></ng-content>\n </div>\n </div>\n </ng-template>\n</section>\n" }]
1234
- }], propDecorators: { variant: [{
1235
- type: Input
1236
- }], className: [{
1237
- type: Input
1238
- }], title: [{
1239
- type: Input
1240
- }], description: [{
1241
- type: Input
1242
- }], actionText: [{
1243
- type: Input
1244
- }], emailLabel: [{
1245
- type: Input
1246
- }], emailPlaceholder: [{
1247
- type: Input
1248
- }], passwordLabel: [{
1249
- type: Input
1250
- }], passwordHint: [{
1251
- type: Input
1252
- }], primaryActionText: [{
1253
- type: Input
1254
- }], secondaryActionText: [{
1275
+ args: [{ selector: 'pdm-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<section\n [ngClass]=\"[\n 'w-full rounded-lg border border-border bg-background py-6 shadow-sm',\n className\n ]\"\n>\n <div class=\"flex w-full flex-col gap-6\">\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardHeader]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardContent]\"></ng-content>\n </div>\n <div class=\"px-6\">\n <ng-content select=\"[pdmCardFooter]\"></ng-content>\n </div>\n </div>\n</section>\n" }]
1276
+ }], propDecorators: { className: [{
1255
1277
  type: Input
1256
- }], primaryAction: [{
1257
- type: Output
1258
- }], secondaryAction: [{
1259
- type: Output
1260
- }], actionPressed: [{
1261
- type: Output
1262
1278
  }] } });
1263
1279
 
1264
1280
  class PdmChartComponent {
@@ -1753,10 +1769,10 @@ class PdmCommandComponent {
1753
1769
  }
1754
1770
  }
1755
1771
  PdmCommandComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCommandComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1756
- PdmCommandComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCommandComponent, selector: "pdm-command", inputs: { open: "open", hintLabel: "hintLabel", hintKey: "hintKey", placeholder: "placeholder", emptyMessage: "emptyMessage", items: "items", className: "className" }, outputs: { itemSelect: "itemSelect", openChange: "openChange" }, ngImport: i0, template: "<div [ngClass]=\"['w-full', className]\">\n <div *ngIf=\"!open\" class=\"flex items-center gap-1\">\n <span class=\"text-sm font-medium text-muted-foreground\">{{ hintLabel }}</span>\n <button\n type=\"button\"\n class=\"inline-flex h-5 appearance-none items-center gap-0.5 rounded-sm border border-border bg-muted px-1.5\"\n (click)=\"toggleOpen()\"\n >\n <pdm-icon name=\"command\" [size]=\"12\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <span class=\"text-xs text-muted-foreground\">{{ hintKey }}</span>\n </button>\n </div>\n\n <section\n *ngIf=\"open\"\n class=\"flex w-full flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md\"\n >\n <div class=\"flex items-center gap-2 border-b border-border px-3\">\n <pdm-icon name=\"search\" [size]=\"16\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n [value]=\"query\"\n (input)=\"onQueryChange($event)\"\n class=\"h-10 w-full bg-transparent py-3 text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n <div class=\"max-h-72 overflow-y-auto p-1\">\n <ng-container *ngFor=\"let group of groupedItems; let groupIndex = index\">\n <div *ngIf=\"group.name\" class=\"px-2 py-1.5 text-xs text-muted-foreground\">{{ group.name }}</div>\n <button\n *ngFor=\"let item of group.items\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"flex w-full appearance-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground\"\n [ngClass]=\"[\n item.disabled ? 'opacity-50' : '',\n item.label === 'Calendar' ? 'bg-accent text-accent-foreground' : ''\n ]\"\n (click)=\"select(item.value)\"\n >\n <span class=\"inline-flex h-4 w-4 items-center justify-center text-foreground\">\n <pdm-icon *ngIf=\"item.icon\" [name]=\"item.icon\" [size]=\"16\" [decorative]=\"true\"></pdm-icon>\n </span>\n <span class=\"min-w-0 flex-1 text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n </button>\n <div *ngIf=\"groupIndex === 0 && groupedItems.length > 1\" class=\"my-1 border-t border-border\"></div>\n </ng-container>\n\n <p *ngIf=\"filteredItems.length === 0\" class=\"m-0 py-6 text-center text-sm text-muted-foreground\">{{ emptyMessage }}</p>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1772
+ PdmCommandComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmCommandComponent, selector: "pdm-command", inputs: { open: "open", hintLabel: "hintLabel", hintKey: "hintKey", placeholder: "placeholder", emptyMessage: "emptyMessage", items: "items", className: "className" }, outputs: { itemSelect: "itemSelect", openChange: "openChange" }, ngImport: i0, template: "<div [ngClass]=\"['w-full', className]\">\n <div *ngIf=\"!open\" class=\"flex items-center gap-1\">\n <span class=\"text-sm font-medium text-muted-foreground\">{{ hintLabel }}</span>\n <button\n type=\"button\"\n class=\"inline-flex h-5 appearance-none items-center gap-0.5 rounded-sm border border-border bg-muted px-1.5\"\n (click)=\"toggleOpen()\"\n >\n <pdm-icon name=\"command\" [size]=\"12\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <span class=\"text-xs text-muted-foreground\">{{ hintKey }}</span>\n </button>\n </div>\n\n <section\n *ngIf=\"open\"\n class=\"flex w-full flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md\"\n >\n <div class=\"flex items-center gap-2 border-b border-border px-3\">\n <pdm-icon name=\"search\" [size]=\"16\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n [value]=\"query\"\n (input)=\"onQueryChange($event)\"\n class=\"h-10 w-full bg-transparent py-3 text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n <div class=\"max-h-[50vh] overflow-y-auto p-1 md:max-h-72\">\n <ng-container *ngFor=\"let group of groupedItems; let groupIndex = index\">\n <div *ngIf=\"group.name\" class=\"px-2 py-1.5 text-xs text-muted-foreground\">{{ group.name }}</div>\n <button\n *ngFor=\"let item of group.items\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"flex w-full appearance-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground\"\n [ngClass]=\"[\n item.disabled ? 'opacity-50' : '',\n item.label === 'Calendar' ? 'bg-accent text-accent-foreground' : ''\n ]\"\n (click)=\"select(item.value)\"\n >\n <span class=\"inline-flex h-4 w-4 items-center justify-center text-foreground\">\n <pdm-icon *ngIf=\"item.icon\" [name]=\"item.icon\" [size]=\"16\" [decorative]=\"true\"></pdm-icon>\n </span>\n <span class=\"min-w-0 flex-1 text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n </button>\n <div *ngIf=\"groupIndex === 0 && groupedItems.length > 1\" class=\"my-1 border-t border-border\"></div>\n </ng-container>\n\n <p *ngIf=\"filteredItems.length === 0\" class=\"m-0 py-6 text-center text-sm text-muted-foreground\">{{ emptyMessage }}</p>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1757
1773
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmCommandComponent, decorators: [{
1758
1774
  type: Component,
1759
- args: [{ selector: 'pdm-command', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"['w-full', className]\">\n <div *ngIf=\"!open\" class=\"flex items-center gap-1\">\n <span class=\"text-sm font-medium text-muted-foreground\">{{ hintLabel }}</span>\n <button\n type=\"button\"\n class=\"inline-flex h-5 appearance-none items-center gap-0.5 rounded-sm border border-border bg-muted px-1.5\"\n (click)=\"toggleOpen()\"\n >\n <pdm-icon name=\"command\" [size]=\"12\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <span class=\"text-xs text-muted-foreground\">{{ hintKey }}</span>\n </button>\n </div>\n\n <section\n *ngIf=\"open\"\n class=\"flex w-full flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md\"\n >\n <div class=\"flex items-center gap-2 border-b border-border px-3\">\n <pdm-icon name=\"search\" [size]=\"16\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n [value]=\"query\"\n (input)=\"onQueryChange($event)\"\n class=\"h-10 w-full bg-transparent py-3 text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n <div class=\"max-h-72 overflow-y-auto p-1\">\n <ng-container *ngFor=\"let group of groupedItems; let groupIndex = index\">\n <div *ngIf=\"group.name\" class=\"px-2 py-1.5 text-xs text-muted-foreground\">{{ group.name }}</div>\n <button\n *ngFor=\"let item of group.items\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"flex w-full appearance-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground\"\n [ngClass]=\"[\n item.disabled ? 'opacity-50' : '',\n item.label === 'Calendar' ? 'bg-accent text-accent-foreground' : ''\n ]\"\n (click)=\"select(item.value)\"\n >\n <span class=\"inline-flex h-4 w-4 items-center justify-center text-foreground\">\n <pdm-icon *ngIf=\"item.icon\" [name]=\"item.icon\" [size]=\"16\" [decorative]=\"true\"></pdm-icon>\n </span>\n <span class=\"min-w-0 flex-1 text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n </button>\n <div *ngIf=\"groupIndex === 0 && groupedItems.length > 1\" class=\"my-1 border-t border-border\"></div>\n </ng-container>\n\n <p *ngIf=\"filteredItems.length === 0\" class=\"m-0 py-6 text-center text-sm text-muted-foreground\">{{ emptyMessage }}</p>\n </div>\n </section>\n</div>\n" }]
1775
+ args: [{ selector: 'pdm-command', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"['w-full', className]\">\n <div *ngIf=\"!open\" class=\"flex items-center gap-1\">\n <span class=\"text-sm font-medium text-muted-foreground\">{{ hintLabel }}</span>\n <button\n type=\"button\"\n class=\"inline-flex h-5 appearance-none items-center gap-0.5 rounded-sm border border-border bg-muted px-1.5\"\n (click)=\"toggleOpen()\"\n >\n <pdm-icon name=\"command\" [size]=\"12\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <span class=\"text-xs text-muted-foreground\">{{ hintKey }}</span>\n </button>\n </div>\n\n <section\n *ngIf=\"open\"\n class=\"flex w-full flex-col overflow-hidden rounded-lg border border-border bg-popover text-popover-foreground shadow-md\"\n >\n <div class=\"flex items-center gap-2 border-b border-border px-3\">\n <pdm-icon name=\"search\" [size]=\"16\" className=\"text-muted-foreground\" [decorative]=\"true\"></pdm-icon>\n <input\n type=\"text\"\n [placeholder]=\"placeholder\"\n [value]=\"query\"\n (input)=\"onQueryChange($event)\"\n class=\"h-10 w-full bg-transparent py-3 text-sm text-foreground outline-none placeholder:text-muted-foreground\"\n />\n </div>\n\n <div class=\"max-h-[50vh] overflow-y-auto p-1 md:max-h-72\">\n <ng-container *ngFor=\"let group of groupedItems; let groupIndex = index\">\n <div *ngIf=\"group.name\" class=\"px-2 py-1.5 text-xs text-muted-foreground\">{{ group.name }}</div>\n <button\n *ngFor=\"let item of group.items\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"flex w-full appearance-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground\"\n [ngClass]=\"[\n item.disabled ? 'opacity-50' : '',\n item.label === 'Calendar' ? 'bg-accent text-accent-foreground' : ''\n ]\"\n (click)=\"select(item.value)\"\n >\n <span class=\"inline-flex h-4 w-4 items-center justify-center text-foreground\">\n <pdm-icon *ngIf=\"item.icon\" [name]=\"item.icon\" [size]=\"16\" [decorative]=\"true\"></pdm-icon>\n </span>\n <span class=\"min-w-0 flex-1 text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n </button>\n <div *ngIf=\"groupIndex === 0 && groupedItems.length > 1\" class=\"my-1 border-t border-border\"></div>\n </ng-container>\n\n <p *ngIf=\"filteredItems.length === 0\" class=\"m-0 py-6 text-center text-sm text-muted-foreground\">{{ emptyMessage }}</p>\n </div>\n </section>\n</div>\n" }]
1760
1776
  }], propDecorators: { open: [{
1761
1777
  type: Input
1762
1778
  }], hintLabel: [{
@@ -1839,10 +1855,10 @@ class PdmContextMenuComponent {
1839
1855
  }
1840
1856
  }
1841
1857
  PdmContextMenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmContextMenuComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
1842
- PdmContextMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmContextMenuComponent, selector: "pdm-context-menu", inputs: { items: "items", className: "className", triggerLabel: "triggerLabel", width: "width", height: "height" }, outputs: { itemSelect: "itemSelect" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div class=\"relative\" [ngClass]=\"className\" (contextmenu)=\"onContextMenu($event)\">\n <div\n class=\"flex items-center justify-center rounded-md border border-dashed border-border\"\n [style.width.px]=\"width\"\n [style.height.px]=\"height\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ triggerLabel }}</span>\n </div>\n\n <div\n *ngIf=\"open\"\n class=\"fixed z-50 w-52 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n [style.left.px]=\"x + 4\"\n [style.top.px]=\"y + 2\"\n >\n <div>\n <ng-container *ngFor=\"let item of items\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div *ngIf=\"item.type === 'label'\" class=\"px-2 py-1.5 text-sm font-semibold text-foreground\">\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent py-1.5 pr-2 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n [ngClass]=\"item.inset ? 'pl-8' : 'px-2'\"\n (click)=\"select(item)\"\n >\n <span class=\"mr-2 inline-flex w-4 shrink-0 items-center justify-center text-foreground\">\n <svg *ngIf=\"item.checked\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.selectedDot\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <svg *ngIf=\"item.showChevron\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5 text-muted-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </ng-container>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1858
+ PdmContextMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmContextMenuComponent, selector: "pdm-context-menu", inputs: { items: "items", className: "className", triggerLabel: "triggerLabel", width: "width", height: "height" }, outputs: { itemSelect: "itemSelect" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div class=\"relative\" [ngClass]=\"className\" (contextmenu)=\"onContextMenu($event)\">\n <div\n class=\"flex items-center justify-center rounded-md border border-dashed border-border\"\n [style.width.px]=\"width\"\n [style.height.px]=\"height\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ triggerLabel }}</span>\n </div>\n\n <div\n *ngIf=\"open\"\n class=\"fixed z-[70] min-w-48 max-w-xs rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md sm:min-w-52\"\n [style.left.px]=\"x + 4\"\n [style.top.px]=\"y + 2\"\n >\n <div>\n <ng-container *ngFor=\"let item of items\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div *ngIf=\"item.type === 'label'\" class=\"px-2 py-1.5 text-sm font-semibold text-foreground\">\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent py-1.5 pr-2 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n [ngClass]=\"item.inset ? 'pl-8' : 'px-2'\"\n (click)=\"select(item)\"\n >\n <span class=\"mr-2 inline-flex w-4 shrink-0 items-center justify-center text-foreground\">\n <svg *ngIf=\"item.checked\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.selectedDot\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <svg *ngIf=\"item.showChevron\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5 text-muted-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </ng-container>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1843
1859
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmContextMenuComponent, decorators: [{
1844
1860
  type: Component,
1845
- args: [{ selector: 'pdm-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative\" [ngClass]=\"className\" (contextmenu)=\"onContextMenu($event)\">\n <div\n class=\"flex items-center justify-center rounded-md border border-dashed border-border\"\n [style.width.px]=\"width\"\n [style.height.px]=\"height\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ triggerLabel }}</span>\n </div>\n\n <div\n *ngIf=\"open\"\n class=\"fixed z-50 w-52 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n [style.left.px]=\"x + 4\"\n [style.top.px]=\"y + 2\"\n >\n <div>\n <ng-container *ngFor=\"let item of items\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div *ngIf=\"item.type === 'label'\" class=\"px-2 py-1.5 text-sm font-semibold text-foreground\">\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent py-1.5 pr-2 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n [ngClass]=\"item.inset ? 'pl-8' : 'px-2'\"\n (click)=\"select(item)\"\n >\n <span class=\"mr-2 inline-flex w-4 shrink-0 items-center justify-center text-foreground\">\n <svg *ngIf=\"item.checked\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.selectedDot\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <svg *ngIf=\"item.showChevron\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5 text-muted-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </ng-container>\n </div>\n </div>\n</div>\n" }]
1861
+ args: [{ selector: 'pdm-context-menu', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative\" [ngClass]=\"className\" (contextmenu)=\"onContextMenu($event)\">\n <div\n class=\"flex items-center justify-center rounded-md border border-dashed border-border\"\n [style.width.px]=\"width\"\n [style.height.px]=\"height\"\n >\n <span class=\"text-sm font-medium text-foreground\">{{ triggerLabel }}</span>\n </div>\n\n <div\n *ngIf=\"open\"\n class=\"fixed z-[70] min-w-48 max-w-xs rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md sm:min-w-52\"\n [style.left.px]=\"x + 4\"\n [style.top.px]=\"y + 2\"\n >\n <div>\n <ng-container *ngFor=\"let item of items\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div *ngIf=\"item.type === 'label'\" class=\"px-2 py-1.5 text-sm font-semibold text-foreground\">\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent py-1.5 pr-2 text-left text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n [ngClass]=\"item.inset ? 'pl-8' : 'px-2'\"\n (click)=\"select(item)\"\n >\n <span class=\"mr-2 inline-flex w-4 shrink-0 items-center justify-center text-foreground\">\n <svg *ngIf=\"item.checked\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.selectedDot\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate text-foreground\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <svg *ngIf=\"item.showChevron\" viewBox=\"0 0 24 24\" class=\"h-3.5 w-3.5 text-muted-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M9 6L15 12L9 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </ng-container>\n </div>\n </div>\n</div>\n" }]
1846
1862
  }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { items: [{
1847
1863
  type: Input
1848
1864
  }], className: [{
@@ -1860,31 +1876,459 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1860
1876
  args: ['document:keydown.escape']
1861
1877
  }] } });
1862
1878
 
1879
+ /**
1880
+ * Sistema de responsive utilities para PDM UI Kit
1881
+ *
1882
+ * Proporciona constantes, tipos y helpers para manejar responsive design
1883
+ * de forma consistente en todos los componentes.
1884
+ */
1885
+ /**
1886
+ * Breakpoints estándar de Tailwind CSS
1887
+ * Mobile-first approach: los estilos base son para mobile, los breakpoints son MIN-WIDTH
1888
+ */
1889
+ const BREAKPOINTS = {
1890
+ sm: '640px',
1891
+ md: '768px',
1892
+ lg: '1024px',
1893
+ xl: '1280px',
1894
+ '2xl': '1536px' // extra large desktop
1895
+ };
1896
+ /**
1897
+ * Helper para generar clases responsive de forma programática
1898
+ *
1899
+ * @example
1900
+ * responsive({ default: 'block', sm: 'flex', lg: 'grid' })
1901
+ * // Returns: 'block sm:flex lg:grid'
1902
+ */
1903
+ function responsive(config) {
1904
+ const classes = [];
1905
+ if (config.default) {
1906
+ classes.push(config.default);
1907
+ }
1908
+ ['sm', 'md', 'lg', 'xl', '2xl'].forEach(bp => {
1909
+ if (config[bp]) {
1910
+ classes.push(`${bp}:${config[bp]}`);
1911
+ }
1912
+ });
1913
+ return classes.join(' ');
1914
+ }
1915
+ /**
1916
+ * Helper para overflow responsive
1917
+ * Maneja el caso común de scroll en mobile, auto en desktop
1918
+ *
1919
+ * @example
1920
+ * overflowResponsive('x', 'scroll', 'auto')
1921
+ * // Returns: 'overflow-x-scroll sm:overflow-x-auto'
1922
+ */
1923
+ function overflowResponsive(axis, mobile, desktop) {
1924
+ const axisClass = axis === 'both' ? 'overflow' : `overflow-${axis}`;
1925
+ const mobileClass = `${axisClass}-${mobile}`;
1926
+ if (!desktop || desktop === mobile) {
1927
+ return mobileClass;
1928
+ }
1929
+ return `${mobileClass} sm:${axisClass}-${desktop}`;
1930
+ }
1931
+ /**
1932
+ * Helper para spacing responsive
1933
+ * Útil para padding/margin que necesita ajustarse por breakpoint
1934
+ *
1935
+ * @example
1936
+ * spacingResponsive('px', { default: '4', sm: '6', lg: '8' })
1937
+ * // Returns: 'px-4 sm:px-6 lg:px-8'
1938
+ */
1939
+ function spacingResponsive(property, values) {
1940
+ return responsive(Object.entries(values).reduce((acc, [key, value]) => {
1941
+ acc[key] = `${property}-${value}`;
1942
+ return acc;
1943
+ }, {}));
1944
+ }
1945
+ /**
1946
+ * Helper para width responsive
1947
+ *
1948
+ * @example
1949
+ * widthResponsive({ default: 'full', sm: 'auto', lg: '1/2' })
1950
+ * // Returns: 'w-full sm:w-auto lg:w-1/2'
1951
+ */
1952
+ function widthResponsive(values) {
1953
+ return responsive(Object.entries(values).reduce((acc, [key, value]) => {
1954
+ acc[key] = `w-${value}`;
1955
+ return acc;
1956
+ }, {}));
1957
+ }
1958
+ /**
1959
+ * Clases comunes para containers responsive
1960
+ * Pensadas para wrappers que contienen contenido que puede desbordar
1961
+ */
1962
+ const RESPONSIVE_CONTAINER = {
1963
+ // Container con scroll horizontal en mobile, contenido visible en desktop
1964
+ tableWrapper: 'relative w-full overflow-x-auto sm:overflow-x-visible',
1965
+ // Container con padding negativo en mobile para scroll edge-to-edge
1966
+ tableWrapperFullBleed: 'relative w-full -mx-4 px-4 overflow-x-auto sm:mx-0 sm:px-0 sm:overflow-x-visible',
1967
+ // Container con max-width responsive
1968
+ contentWrapper: 'w-full mx-auto px-4 sm:px-6 lg:px-8 max-w-screen-2xl',
1969
+ // Container para modals/dialogs
1970
+ modalWrapper: 'w-full max-w-lg mx-auto px-4 sm:px-0',
1971
+ // Container para forms
1972
+ formWrapper: 'w-full max-w-md mx-auto space-y-4'
1973
+ };
1974
+ /**
1975
+ * Clases comunes para display responsive
1976
+ */
1977
+ const RESPONSIVE_DISPLAY = {
1978
+ // Ocultar en mobile, mostrar en desktop
1979
+ hideOnMobile: 'hidden sm:block',
1980
+ // Mostrar solo en mobile
1981
+ showOnMobile: 'block sm:hidden',
1982
+ // Stack en mobile, flex en desktop
1983
+ stackToFlex: 'flex flex-col sm:flex-row',
1984
+ // Stack en mobile, grid en desktop
1985
+ stackToGrid: 'grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3'
1986
+ };
1987
+ /**
1988
+ * Clases para table responsive strategies
1989
+ */
1990
+ const TABLE_RESPONSIVE = {
1991
+ // Scroll horizontal (default, más simple)
1992
+ scroll: {
1993
+ wrapper: 'relative w-full overflow-x-auto',
1994
+ table: 'w-full min-w-full',
1995
+ cell: 'whitespace-nowrap'
1996
+ },
1997
+ // Permitir wrap del contenido
1998
+ wrap: {
1999
+ wrapper: 'relative w-full overflow-x-auto',
2000
+ table: 'w-full',
2001
+ cell: 'whitespace-normal break-words'
2002
+ },
2003
+ // Stack en mobile (cada fila se convierte en card)
2004
+ // Requiere lógica adicional en el componente
2005
+ stack: {
2006
+ wrapper: 'relative w-full',
2007
+ table: 'w-full',
2008
+ row: 'block sm:table-row border-b sm:border-b-0',
2009
+ cell: 'block sm:table-cell py-2 sm:py-0 before:content-[attr(data-label)] before:font-medium before:inline-block before:w-32 sm:before:content-none'
2010
+ },
2011
+ // Collapse: ocultar columnas menos importantes en mobile
2012
+ // Se usa con clases de visibility en las columnas específicas
2013
+ collapse: {
2014
+ wrapper: 'relative w-full overflow-x-auto',
2015
+ table: 'w-full',
2016
+ cell: 'whitespace-nowrap',
2017
+ // Estas clases se aplican a columnas opcionales
2018
+ optionalColumn: 'hidden md:table-cell'
2019
+ }
2020
+ };
2021
+
2022
+ /**
2023
+ * Componente base de tabla con soporte responsive
2024
+ *
2025
+ * SIMPLIFICADO: Ya no incluye drag & drop (usar pdm-draggable-table para eso)
2026
+ *
2027
+ * @example
2028
+ * // Tabla simple con scroll horizontal
2029
+ * <pdm-table variant="default">
2030
+ * <thead><tr><th>Name</th><th>Email</th></tr></thead>
2031
+ * <tbody><tr><td>John</td><td>john@example.com</td></tr></tbody>
2032
+ * </pdm-table>
2033
+ *
2034
+ * @example
2035
+ * // Tabla interactiva con wrap en mobile
2036
+ * <pdm-table variant="interactive" responsiveStrategy="wrap">
2037
+ * ...
2038
+ * </pdm-table>
2039
+ */
2040
+ class PdmTableComponent {
2041
+ constructor() {
2042
+ /**
2043
+ * Variante visual de la tabla
2044
+ * - default: tabla básica sin estilos extra
2045
+ * - data: tabla con bordes y espaciado para data
2046
+ * - interactive: tabla con hover, sticky header y estilos interactivos
2047
+ */
2048
+ this.variant = 'default';
2049
+ /**
2050
+ * Estrategia responsive para la tabla
2051
+ * - scroll: scroll horizontal en mobile (default, más simple)
2052
+ * - wrap: permite que el contenido haga wrap
2053
+ * - stack: convierte filas en cards en mobile (requiere data-label en celdas)
2054
+ * - collapse: oculta columnas menos importantes en mobile
2055
+ */
2056
+ this.responsiveStrategy = 'scroll';
2057
+ /**
2058
+ * Clases CSS adicionales para el wrapper
2059
+ */
2060
+ this.className = '';
2061
+ /**
2062
+ * Si es true, aplica padding negativo en mobile para scroll edge-to-edge
2063
+ * Útil cuando la tabla está dentro de un container con padding
2064
+ */
2065
+ this.fullBleed = false;
2066
+ }
2067
+ get wrapperClasses() {
2068
+ const baseClasses = ['relative', 'w-full'];
2069
+ const strategyClasses = this.getResponsiveStrategyClasses();
2070
+ const variantClasses = this.getVariantWrapperClasses();
2071
+ // Full bleed: scroll edge-to-edge en mobile
2072
+ if (this.fullBleed && this.responsiveStrategy === 'scroll') {
2073
+ baseClasses.push('-mx-4', 'px-4', 'sm:mx-0', 'sm:px-0');
2074
+ }
2075
+ return [
2076
+ ...baseClasses,
2077
+ ...strategyClasses,
2078
+ ...variantClasses,
2079
+ this.className
2080
+ ].filter(Boolean);
2081
+ }
2082
+ get tableClasses() {
2083
+ const baseClasses = ['w-full', 'caption-bottom', 'text-sm'];
2084
+ const variantClasses = this.getVariantTableClasses();
2085
+ const cellClasses = this.getCellClasses();
2086
+ return [...baseClasses, ...variantClasses, ...cellClasses].filter(Boolean);
2087
+ }
2088
+ getResponsiveStrategyClasses() {
2089
+ const strategy = TABLE_RESPONSIVE[this.responsiveStrategy];
2090
+ if (this.responsiveStrategy === 'scroll') {
2091
+ return ['overflow-x-auto'];
2092
+ }
2093
+ if (this.responsiveStrategy === 'wrap') {
2094
+ return ['overflow-x-auto'];
2095
+ }
2096
+ if (this.responsiveStrategy === 'stack') {
2097
+ // Stack requiere lógica en el template, aquí solo el wrapper
2098
+ return [];
2099
+ }
2100
+ if (this.responsiveStrategy === 'collapse') {
2101
+ return ['overflow-x-auto'];
2102
+ }
2103
+ return ['overflow-auto'];
2104
+ }
2105
+ getVariantWrapperClasses() {
2106
+ if (this.variant === 'interactive') {
2107
+ return ['rounded-xl', 'border', 'border-border', 'bg-background'];
2108
+ }
2109
+ if (this.variant === 'data') {
2110
+ return ['rounded-md', 'border', 'border-border', 'bg-background'];
2111
+ }
2112
+ return [];
2113
+ }
2114
+ getVariantTableClasses() {
2115
+ if (this.variant === 'data') {
2116
+ return [
2117
+ 'border-collapse',
2118
+ 'text-foreground',
2119
+ '[&_thead_tr]:border-b',
2120
+ '[&_thead_tr]:border-border',
2121
+ '[&_tbody_tr]:border-b',
2122
+ '[&_tbody_tr]:border-border',
2123
+ '[&_tbody_tr:last-child]:border-b-0',
2124
+ '[&_th]:h-10',
2125
+ '[&_th]:px-2',
2126
+ '[&_th]:text-left',
2127
+ '[&_th]:align-middle',
2128
+ '[&_th]:font-medium',
2129
+ '[&_td]:p-2',
2130
+ '[&_td]:align-middle'
2131
+ ];
2132
+ }
2133
+ if (this.variant === 'interactive') {
2134
+ return [
2135
+ 'text-foreground',
2136
+ '[&_thead]:sticky',
2137
+ '[&_thead]:top-0',
2138
+ '[&_thead]:z-10',
2139
+ '[&_thead]:bg-muted/70',
2140
+ '[&_thead_tr]:border-b',
2141
+ '[&_thead_tr]:border-border',
2142
+ '[&_th]:h-12',
2143
+ '[&_th]:px-4',
2144
+ '[&_th]:text-left',
2145
+ '[&_th]:align-middle',
2146
+ '[&_th]:text-sm',
2147
+ '[&_th]:font-medium',
2148
+ '[&_tbody_tr]:border-b',
2149
+ '[&_tbody_tr]:border-border',
2150
+ '[&_tbody_tr]:transition-colors',
2151
+ '[&_tbody_tr:hover]:bg-muted/50',
2152
+ '[&_tbody_tr:last-child]:border-b-0',
2153
+ '[&_td]:h-14',
2154
+ '[&_td]:px-4',
2155
+ '[&_td]:align-middle',
2156
+ '[&_td]:text-sm',
2157
+ '[&_svg]:text-muted-foreground'
2158
+ ];
2159
+ }
2160
+ return [];
2161
+ }
2162
+ getCellClasses() {
2163
+ // Manejo responsive de whitespace
2164
+ if (this.responsiveStrategy === 'scroll') {
2165
+ // En scroll, permitir wrap en mobile, nowrap en desktop
2166
+ return ['[&_td]:whitespace-normal', '[&_th]:whitespace-normal', 'sm:[&_td]:whitespace-nowrap', 'sm:[&_th]:whitespace-nowrap'];
2167
+ }
2168
+ if (this.responsiveStrategy === 'wrap') {
2169
+ // En wrap, siempre permitir wrap
2170
+ return ['[&_td]:whitespace-normal', '[&_td]:break-words', '[&_th]:whitespace-normal'];
2171
+ }
2172
+ // Default: nowrap (comportamiento anterior para backward compatibility)
2173
+ return [];
2174
+ }
2175
+ }
2176
+ PdmTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2177
+ PdmTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmTableComponent, selector: "pdm-table", inputs: { variant: "variant", responsiveStrategy: "responsiveStrategy", className: "className", fullBleed: "fullBleed" }, ngImport: i0, template: "<div [ngClass]=\"wrapperClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table-container' : null\">\n <table #tableElement [ngClass]=\"tableClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table' : null\">\n <ng-content></ng-content>\n </table>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2178
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTableComponent, decorators: [{
2179
+ type: Component,
2180
+ args: [{ selector: 'pdm-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"wrapperClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table-container' : null\">\n <table #tableElement [ngClass]=\"tableClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table' : null\">\n <ng-content></ng-content>\n </table>\n</div>\n" }]
2181
+ }], propDecorators: { variant: [{
2182
+ type: Input
2183
+ }], responsiveStrategy: [{
2184
+ type: Input
2185
+ }], className: [{
2186
+ type: Input
2187
+ }], fullBleed: [{
2188
+ type: Input
2189
+ }] } });
2190
+
2191
+ /**
2192
+ * Data-table genérico con paginación, filtrado y selección
2193
+ *
2194
+ * NUEVO: Ahora es genérico y configurable via columnas
2195
+ *
2196
+ * @example
2197
+ * // Definir columnas
2198
+ * columns: PdmDataTableColumn<User>[] = [
2199
+ * { key: 'name', label: 'Name', sortable: true },
2200
+ * { key: 'email', label: 'Email', sortable: true },
2201
+ * { key: 'role', label: 'Role', hideOnMobile: true },
2202
+ * { key: 'createdAt', label: 'Created', render: (val) => formatDate(val) }
2203
+ * ];
2204
+ *
2205
+ * // En el template
2206
+ * <pdm-data-table
2207
+ * [columns]="columns"
2208
+ * [rows]="users"
2209
+ * [selectable]="true"
2210
+ * (selectionChange)="onSelect($event)">
2211
+ * </pdm-data-table>
2212
+ */
1863
2213
  class PdmDataTableComponent {
1864
2214
  constructor() {
1865
2215
  this.className = '';
2216
+ /**
2217
+ * Columnas a mostrar
2218
+ * Si no se provee, intenta inferir del primer row (legacy mode)
2219
+ */
2220
+ this.columns = [];
2221
+ /**
2222
+ * Estrategia responsive de la tabla
2223
+ */
2224
+ this.responsiveStrategy = 'scroll';
2225
+ /**
2226
+ * Si es true, muestra checkbox de selección en cada fila
2227
+ */
2228
+ this.selectable = false;
2229
+ /**
2230
+ * Si es true, muestra botón de acciones (tres puntos) en cada fila
2231
+ */
2232
+ this.showActions = false;
2233
+ /**
2234
+ * Si es true, muestra filtro de búsqueda
2235
+ */
2236
+ this.showFilter = true;
2237
+ /**
2238
+ * Si es true, muestra controles de paginación
2239
+ */
2240
+ this.showPagination = true;
2241
+ /**
2242
+ * Si es true, muestra selector de columnas
2243
+ */
2244
+ this.showColumnSelector = false;
2245
+ // Labels i18n
1866
2246
  this.filterPlaceholder = 'Filter...';
1867
2247
  this.columnsLabel = 'Columns';
1868
- this.statusLabel = 'Status';
1869
- this.emailLabel = 'Email';
1870
- this.amountLabel = 'Amount';
1871
2248
  this.previousLabel = 'Previous';
1872
2249
  this.nextLabel = 'Next';
1873
2250
  this.emptyLabel = 'No results.';
2251
+ this.rowsSelectedLabel = 'row(s) selected';
2252
+ // DEPRECATED: Labels hardcodeados para backward compatibility
2253
+ /**
2254
+ * @deprecated Use columns configuration instead
2255
+ */
2256
+ this.statusLabel = 'Status';
2257
+ /**
2258
+ * @deprecated Use columns configuration instead
2259
+ */
2260
+ this.emailLabel = 'Email';
2261
+ /**
2262
+ * @deprecated Use columns configuration instead
2263
+ */
2264
+ this.amountLabel = 'Amount';
2265
+ /**
2266
+ * Datos a mostrar
2267
+ */
1874
2268
  this.rows = [];
2269
+ /**
2270
+ * Página actual (1-indexed)
2271
+ */
1875
2272
  this.page = 1;
1876
- this.pageSize = 5;
2273
+ /**
2274
+ * Cantidad de filas por página
2275
+ */
2276
+ this.pageSize = 10;
2277
+ /**
2278
+ * Query de filtrado
2279
+ */
1877
2280
  this.query = '';
1878
2281
  this.queryChange = new EventEmitter();
1879
2282
  this.rowAction = new EventEmitter();
1880
2283
  this.pageChange = new EventEmitter();
1881
2284
  this.selectionChange = new EventEmitter();
2285
+ this.columnSort = new EventEmitter();
2286
+ // Estado interno
2287
+ this.selectedRows = new Set();
2288
+ this.sortDirection = 'asc';
2289
+ }
2290
+ /**
2291
+ * Backward compatibility: si no hay columnas definidas, inferir del primer row
2292
+ */
2293
+ get effectiveColumns() {
2294
+ if (this.columns.length > 0) {
2295
+ return this.columns;
2296
+ }
2297
+ // Legacy mode: inferir columnas del primer row (solo para PdmDataTableRow)
2298
+ if (this.rows.length > 0) {
2299
+ const firstRow = this.rows[0];
2300
+ return Object.keys(firstRow)
2301
+ .filter(key => key !== 'selected')
2302
+ .map(key => ({
2303
+ key: key,
2304
+ label: this.getLegacyLabel(key),
2305
+ align: key === 'amount' ? 'right' : 'left'
2306
+ }));
2307
+ }
2308
+ return [];
2309
+ }
2310
+ /**
2311
+ * LEGACY: mapeo de keys a labels hardcodeados
2312
+ */
2313
+ getLegacyLabel(key) {
2314
+ const map = {
2315
+ status: this.statusLabel,
2316
+ email: this.emailLabel,
2317
+ amount: this.amountLabel
2318
+ };
2319
+ return map[key] || key.charAt(0).toUpperCase() + key.slice(1);
1882
2320
  }
1883
2321
  get filteredRows() {
1884
2322
  const q = this.query.trim().toLowerCase();
1885
2323
  if (!q)
1886
2324
  return this.rows;
1887
- return this.rows.filter((r) => r.email.toLowerCase().includes(q));
2325
+ if (this.filterFn) {
2326
+ return this.rows.filter(row => this.filterFn(row, q));
2327
+ }
2328
+ // Filtrado default: buscar en todos los campos string
2329
+ return this.rows.filter(row => {
2330
+ return Object.values(row).some(val => typeof val === 'string' && val.toLowerCase().includes(q));
2331
+ });
1888
2332
  }
1889
2333
  get pagedRows() {
1890
2334
  const start = (this.page - 1) * this.pageSize;
@@ -1894,14 +2338,33 @@ class PdmDataTableComponent {
1894
2338
  return Math.max(1, Math.ceil(this.filteredRows.length / this.pageSize));
1895
2339
  }
1896
2340
  get selectedCount() {
1897
- return this.rows.filter((row) => row.selected).length;
2341
+ return this.selectedRows.size;
1898
2342
  }
1899
2343
  onQueryInput(event) {
1900
2344
  const value = event.target.value;
1901
2345
  this.queryChange.emit(value);
1902
2346
  }
1903
2347
  onToggleRow(row, event) {
1904
- this.selectionChange.emit({ id: row.id, selected: event.target.checked });
2348
+ const checked = event.target.checked;
2349
+ if (checked) {
2350
+ this.selectedRows.add(row);
2351
+ }
2352
+ else {
2353
+ this.selectedRows.delete(row);
2354
+ }
2355
+ this.selectionChange.emit({ row, selected: checked });
2356
+ }
2357
+ onToggleAll(event) {
2358
+ const checked = event.target.checked;
2359
+ if (checked) {
2360
+ this.pagedRows.forEach(row => this.selectedRows.add(row));
2361
+ }
2362
+ else {
2363
+ this.pagedRows.forEach(row => this.selectedRows.delete(row));
2364
+ }
2365
+ }
2366
+ isSelected(row) {
2367
+ return this.selectedRows.has(row);
1905
2368
  }
1906
2369
  previous() {
1907
2370
  if (this.page <= 1)
@@ -1914,25 +2377,75 @@ class PdmDataTableComponent {
1914
2377
  this.pageChange.emit(this.page + 1);
1915
2378
  }
1916
2379
  onAction(row) {
1917
- this.rowAction.emit(row.id);
2380
+ this.rowAction.emit(row);
2381
+ }
2382
+ onSort(column) {
2383
+ if (!column.sortable)
2384
+ return;
2385
+ if (this.sortColumn === column) {
2386
+ this.sortDirection = this.sortDirection === 'asc' ? 'desc' : 'asc';
2387
+ }
2388
+ else {
2389
+ this.sortColumn = column;
2390
+ this.sortDirection = 'asc';
2391
+ }
2392
+ this.columnSort.emit({ column, direction: this.sortDirection });
2393
+ }
2394
+ getCellValue(row, column) {
2395
+ const value = row[column.key];
2396
+ if (column.render) {
2397
+ return column.render(value, row);
2398
+ }
2399
+ return value != null ? String(value) : '';
2400
+ }
2401
+ getCellClass(column) {
2402
+ const classes = ['px-2', 'py-2'];
2403
+ if (column.align === 'center')
2404
+ classes.push('text-center');
2405
+ if (column.align === 'right')
2406
+ classes.push('text-right');
2407
+ if (column.hideOnMobile)
2408
+ classes.push('hidden', 'md:table-cell');
2409
+ if (column.cellClass)
2410
+ classes.push(column.cellClass);
2411
+ return classes.join(' ');
2412
+ }
2413
+ getHeaderClass(column) {
2414
+ const classes = ['px-2', 'py-2', 'text-left', 'font-medium'];
2415
+ if (column.hideOnMobile)
2416
+ classes.push('hidden', 'md:table-cell');
2417
+ if (column.headerClass)
2418
+ classes.push(column.headerClass);
2419
+ return classes.join(' ');
2420
+ }
2421
+ getColumnStyle(column) {
2422
+ return column.width ? { width: column.width } : {};
1918
2423
  }
1919
2424
  }
1920
2425
  PdmDataTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDataTableComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
1921
- PdmDataTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDataTableComponent, selector: "pdm-data-table", inputs: { className: "className", filterPlaceholder: "filterPlaceholder", columnsLabel: "columnsLabel", statusLabel: "statusLabel", emailLabel: "emailLabel", amountLabel: "amountLabel", previousLabel: "previousLabel", nextLabel: "nextLabel", emptyLabel: "emptyLabel", rows: "rows", page: "page", pageSize: "pageSize", query: "query" }, outputs: { queryChange: "queryChange", rowAction: "rowAction", pageChange: "pageChange", selectionChange: "selectionChange" }, ngImport: i0, template: "<section [ngClass]=\"['flex w-full max-w-3xl flex-col items-end', className]\">\n <div class=\"flex w-full items-center justify-between py-4\">\n <input\n type=\"text\"\n [placeholder]=\"filterPlaceholder\"\n [value]=\"query\"\n (input)=\"onQueryInput($event)\"\n class=\"h-9 flex-1 rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm placeholder:text-muted-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n\n <button type=\"button\" class=\"inline-flex h-9 appearance-none items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm font-medium text-foreground shadow-sm\">\n <span>{{ columnsLabel }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"w-full overflow-hidden rounded-md border border-border bg-background\">\n <table class=\"w-full border-collapse text-sm text-foreground\">\n <thead>\n <tr class=\"border-b border-border\">\n <th class=\"w-10 px-2 text-left font-medium\"><input type=\"checkbox\" class=\"h-4 w-4 rounded-sm border border-input\" /></th>\n <th class=\"w-32 px-2 py-2 text-left font-medium\">{{ statusLabel }}</th>\n <th class=\"px-2 py-2 text-left font-medium\">\n <button type=\"button\" class=\"inline-flex appearance-none items-center gap-1 rounded-sm border-0 bg-transparent px-3 py-2 text-sm\">\n <span>{{ emailLabel }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8 6L4 10L8 14M16 18L20 14L16 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </th>\n <th class=\"w-24 px-2 py-2 text-right font-medium\">{{ amountLabel }}</th>\n <th class=\"px-2 py-2\"></th>\n </tr>\n </thead>\n\n <tbody>\n <tr *ngFor=\"let row of pagedRows\" class=\"border-b border-border last:border-b-0\">\n <td class=\"px-2 py-2\"><input type=\"checkbox\" [checked]=\"row.selected\" (change)=\"onToggleRow(row, $event)\" class=\"h-4 w-4 rounded-sm border border-input\" /></td>\n <td class=\"px-2 py-2\">{{ row.status }}</td>\n <td class=\"px-2 py-2\">{{ row.email }}</td>\n <td class=\"px-2 py-2 text-right\">{{ row.amount }}</td>\n <td class=\"px-2 py-2\">\n <button type=\"button\" class=\"inline-flex h-8 w-8 appearance-none items-center justify-center border-0 bg-transparent p-0\" (click)=\"onAction(row)\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"18\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n </svg>\n </button>\n </td>\n </tr>\n <tr *ngIf=\"pagedRows.length === 0\">\n <td colspan=\"5\" class=\"px-3 py-6 text-center text-sm text-muted-foreground\">{{ emptyLabel }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div class=\"flex w-full items-center gap-2 py-4\">\n <p class=\"m-0 flex-1 pr-2 text-sm text-muted-foreground\">{{ selectedCount }} of {{ rows.length }} row(s) selected.</p>\n <button type=\"button\" class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50\" [disabled]=\"page <= 1\" (click)=\"previous()\">{{ previousLabel }}</button>\n <button type=\"button\" class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50\" [disabled]=\"page >= totalPages\" (click)=\"next()\">{{ nextLabel }}</button>\n </div>\n</section>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2426
+ PdmDataTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDataTableComponent, selector: "pdm-data-table", inputs: { className: "className", columns: "columns", responsiveStrategy: "responsiveStrategy", selectable: "selectable", showActions: "showActions", showFilter: "showFilter", showPagination: "showPagination", showColumnSelector: "showColumnSelector", filterPlaceholder: "filterPlaceholder", columnsLabel: "columnsLabel", previousLabel: "previousLabel", nextLabel: "nextLabel", emptyLabel: "emptyLabel", rowsSelectedLabel: "rowsSelectedLabel", statusLabel: "statusLabel", emailLabel: "emailLabel", amountLabel: "amountLabel", rows: "rows", page: "page", pageSize: "pageSize", query: "query", filterFn: "filterFn" }, outputs: { queryChange: "queryChange", rowAction: "rowAction", pageChange: "pageChange", selectionChange: "selectionChange", columnSort: "columnSort" }, ngImport: i0, template: "<section [ngClass]=\"['flex w-full flex-col', className]\">\n <!-- Toolbar: Filtro + Selector de columnas -->\n <div *ngIf=\"showFilter || showColumnSelector\" class=\"flex w-full items-center justify-between gap-2 py-4\">\n <input\n *ngIf=\"showFilter\"\n type=\"text\"\n [placeholder]=\"filterPlaceholder\"\n [value]=\"query\"\n (input)=\"onQueryInput($event)\"\n class=\"h-9 flex-1 rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm placeholder:text-muted-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n\n <button \n *ngIf=\"showColumnSelector\"\n type=\"button\" \n class=\"inline-flex h-9 appearance-none items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm font-medium text-foreground shadow-sm whitespace-nowrap\">\n <span>{{ columnsLabel }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <!-- Tabla con responsive -->\n <pdm-table \n variant=\"data\"\n [responsiveStrategy]=\"responsiveStrategy\"\n [fullBleed]=\"false\">\n <thead>\n <tr>\n <!-- Columna de selecci\u00F3n -->\n <th *ngIf=\"selectable\" class=\"w-10 px-2 py-2 text-left font-medium\">\n <input \n type=\"checkbox\" \n (change)=\"onToggleAll($event)\"\n class=\"h-4 w-4 rounded-sm border border-input\" \n />\n </th>\n\n <!-- Columnas din\u00E1micas -->\n <th \n *ngFor=\"let column of effectiveColumns\"\n [ngClass]=\"getHeaderClass(column)\"\n [ngStyle]=\"getColumnStyle(column)\">\n \n <!-- Header sortable -->\n <button \n *ngIf=\"column.sortable\"\n type=\"button\" \n (click)=\"onSort(column)\"\n class=\"inline-flex appearance-none items-center gap-1 rounded-sm border-0 bg-transparent px-3 py-2 text-sm hover:underline\">\n <span>{{ column.label }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8 6L4 10L8 14M16 18L20 14L16 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n\n <!-- Header no sortable -->\n <span *ngIf=\"!column.sortable\">{{ column.label }}</span>\n </th>\n\n <!-- Columna de acciones -->\n <th *ngIf=\"showActions\" class=\"w-10 px-2 py-2\"></th>\n </tr>\n </thead>\n\n <tbody>\n <!-- Filas con datos -->\n <tr *ngFor=\"let row of pagedRows\">\n <!-- Celda de selecci\u00F3n -->\n <td *ngIf=\"selectable\" class=\"px-2 py-2\">\n <input \n type=\"checkbox\" \n [checked]=\"isSelected(row)\" \n (change)=\"onToggleRow(row, $event)\" \n class=\"h-4 w-4 rounded-sm border border-input\" \n />\n </td>\n\n <!-- Celdas din\u00E1micas -->\n <td \n *ngFor=\"let column of effectiveColumns\"\n [ngClass]=\"getCellClass(column)\">\n \n <!-- Template personalizado si existe -->\n <ng-container *ngIf=\"column.cellTemplate; else defaultCell\">\n <ng-container \n *ngTemplateOutlet=\"column.cellTemplate; context: { $implicit: row, value: row[column.key] }\">\n </ng-container>\n </ng-container>\n\n <!-- Renderizado default -->\n <ng-template #defaultCell>\n {{ getCellValue(row, column) }}\n </ng-template>\n </td>\n\n <!-- Celda de acciones -->\n <td *ngIf=\"showActions\" class=\"px-2 py-2\">\n <button \n type=\"button\" \n class=\"inline-flex h-8 w-8 appearance-none items-center justify-center border-0 bg-transparent p-0 hover:text-foreground\" \n (click)=\"onAction(row)\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"18\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n </svg>\n </button>\n </td>\n </tr>\n\n <!-- Fila vac\u00EDa -->\n <tr *ngIf=\"pagedRows.length === 0\">\n <td \n [attr.colspan]=\"effectiveColumns.length + (selectable ? 1 : 0) + (showActions ? 1 : 0)\" \n class=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {{ emptyLabel }}\n </td>\n </tr>\n </tbody>\n </pdm-table>\n\n <!-- Footer: Info + Paginaci\u00F3n -->\n <div *ngIf=\"showPagination || selectable\" class=\"flex w-full items-center gap-2 py-4 flex-wrap sm:flex-nowrap\">\n <p *ngIf=\"selectable\" class=\"m-0 flex-1 pr-2 text-sm text-muted-foreground whitespace-nowrap\">\n {{ selectedCount }} of {{ rows.length }} {{ rowsSelectedLabel }}\n </p>\n\n <div *ngIf=\"showPagination\" class=\"flex items-center gap-2 ml-auto\">\n <span class=\"text-sm text-muted-foreground whitespace-nowrap\">\n Page {{ page }} of {{ totalPages }}\n </span>\n <button \n type=\"button\" \n class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\" \n [disabled]=\"page <= 1\" \n (click)=\"previous()\">\n {{ previousLabel }}\n </button>\n <button \n type=\"button\" \n class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\" \n [disabled]=\"page >= totalPages\" \n (click)=\"next()\">\n {{ nextLabel }}\n </button>\n </div>\n </div>\n</section>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: PdmTableComponent, selector: "pdm-table", inputs: ["variant", "responsiveStrategy", "className", "fullBleed"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
1922
2427
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDataTableComponent, decorators: [{
1923
2428
  type: Component,
1924
- args: [{ selector: 'pdm-data-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<section [ngClass]=\"['flex w-full max-w-3xl flex-col items-end', className]\">\n <div class=\"flex w-full items-center justify-between py-4\">\n <input\n type=\"text\"\n [placeholder]=\"filterPlaceholder\"\n [value]=\"query\"\n (input)=\"onQueryInput($event)\"\n class=\"h-9 flex-1 rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm placeholder:text-muted-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n\n <button type=\"button\" class=\"inline-flex h-9 appearance-none items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm font-medium text-foreground shadow-sm\">\n <span>{{ columnsLabel }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <div class=\"w-full overflow-hidden rounded-md border border-border bg-background\">\n <table class=\"w-full border-collapse text-sm text-foreground\">\n <thead>\n <tr class=\"border-b border-border\">\n <th class=\"w-10 px-2 text-left font-medium\"><input type=\"checkbox\" class=\"h-4 w-4 rounded-sm border border-input\" /></th>\n <th class=\"w-32 px-2 py-2 text-left font-medium\">{{ statusLabel }}</th>\n <th class=\"px-2 py-2 text-left font-medium\">\n <button type=\"button\" class=\"inline-flex appearance-none items-center gap-1 rounded-sm border-0 bg-transparent px-3 py-2 text-sm\">\n <span>{{ emailLabel }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8 6L4 10L8 14M16 18L20 14L16 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </th>\n <th class=\"w-24 px-2 py-2 text-right font-medium\">{{ amountLabel }}</th>\n <th class=\"px-2 py-2\"></th>\n </tr>\n </thead>\n\n <tbody>\n <tr *ngFor=\"let row of pagedRows\" class=\"border-b border-border last:border-b-0\">\n <td class=\"px-2 py-2\"><input type=\"checkbox\" [checked]=\"row.selected\" (change)=\"onToggleRow(row, $event)\" class=\"h-4 w-4 rounded-sm border border-input\" /></td>\n <td class=\"px-2 py-2\">{{ row.status }}</td>\n <td class=\"px-2 py-2\">{{ row.email }}</td>\n <td class=\"px-2 py-2 text-right\">{{ row.amount }}</td>\n <td class=\"px-2 py-2\">\n <button type=\"button\" class=\"inline-flex h-8 w-8 appearance-none items-center justify-center border-0 bg-transparent p-0\" (click)=\"onAction(row)\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"18\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n </svg>\n </button>\n </td>\n </tr>\n <tr *ngIf=\"pagedRows.length === 0\">\n <td colspan=\"5\" class=\"px-3 py-6 text-center text-sm text-muted-foreground\">{{ emptyLabel }}</td>\n </tr>\n </tbody>\n </table>\n </div>\n\n <div class=\"flex w-full items-center gap-2 py-4\">\n <p class=\"m-0 flex-1 pr-2 text-sm text-muted-foreground\">{{ selectedCount }} of {{ rows.length }} row(s) selected.</p>\n <button type=\"button\" class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50\" [disabled]=\"page <= 1\" (click)=\"previous()\">{{ previousLabel }}</button>\n <button type=\"button\" class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50\" [disabled]=\"page >= totalPages\" (click)=\"next()\">{{ nextLabel }}</button>\n </div>\n</section>\n" }]
2429
+ args: [{ selector: 'pdm-data-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<section [ngClass]=\"['flex w-full flex-col', className]\">\n <!-- Toolbar: Filtro + Selector de columnas -->\n <div *ngIf=\"showFilter || showColumnSelector\" class=\"flex w-full items-center justify-between gap-2 py-4\">\n <input\n *ngIf=\"showFilter\"\n type=\"text\"\n [placeholder]=\"filterPlaceholder\"\n [value]=\"query\"\n (input)=\"onQueryInput($event)\"\n class=\"h-9 flex-1 rounded-md border border-input bg-transparent px-3 py-1 text-sm text-foreground shadow-sm placeholder:text-muted-foreground outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\"\n />\n\n <button \n *ngIf=\"showColumnSelector\"\n type=\"button\" \n class=\"inline-flex h-9 appearance-none items-center gap-2 rounded-md border border-input bg-background px-3 py-2 text-sm font-medium text-foreground shadow-sm whitespace-nowrap\">\n <span>{{ columnsLabel }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4 text-foreground\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M7 10L12 15L17 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <!-- Tabla con responsive -->\n <pdm-table \n variant=\"data\"\n [responsiveStrategy]=\"responsiveStrategy\"\n [fullBleed]=\"false\">\n <thead>\n <tr>\n <!-- Columna de selecci\u00F3n -->\n <th *ngIf=\"selectable\" class=\"w-10 px-2 py-2 text-left font-medium\">\n <input \n type=\"checkbox\" \n (change)=\"onToggleAll($event)\"\n class=\"h-4 w-4 rounded-sm border border-input\" \n />\n </th>\n\n <!-- Columnas din\u00E1micas -->\n <th \n *ngFor=\"let column of effectiveColumns\"\n [ngClass]=\"getHeaderClass(column)\"\n [ngStyle]=\"getColumnStyle(column)\">\n \n <!-- Header sortable -->\n <button \n *ngIf=\"column.sortable\"\n type=\"button\" \n (click)=\"onSort(column)\"\n class=\"inline-flex appearance-none items-center gap-1 rounded-sm border-0 bg-transparent px-3 py-2 text-sm hover:underline\">\n <span>{{ column.label }}</span>\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M8 6L4 10L8 14M16 18L20 14L16 10\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </button>\n\n <!-- Header no sortable -->\n <span *ngIf=\"!column.sortable\">{{ column.label }}</span>\n </th>\n\n <!-- Columna de acciones -->\n <th *ngIf=\"showActions\" class=\"w-10 px-2 py-2\"></th>\n </tr>\n </thead>\n\n <tbody>\n <!-- Filas con datos -->\n <tr *ngFor=\"let row of pagedRows\">\n <!-- Celda de selecci\u00F3n -->\n <td *ngIf=\"selectable\" class=\"px-2 py-2\">\n <input \n type=\"checkbox\" \n [checked]=\"isSelected(row)\" \n (change)=\"onToggleRow(row, $event)\" \n class=\"h-4 w-4 rounded-sm border border-input\" \n />\n </td>\n\n <!-- Celdas din\u00E1micas -->\n <td \n *ngFor=\"let column of effectiveColumns\"\n [ngClass]=\"getCellClass(column)\">\n \n <!-- Template personalizado si existe -->\n <ng-container *ngIf=\"column.cellTemplate; else defaultCell\">\n <ng-container \n *ngTemplateOutlet=\"column.cellTemplate; context: { $implicit: row, value: row[column.key] }\">\n </ng-container>\n </ng-container>\n\n <!-- Renderizado default -->\n <ng-template #defaultCell>\n {{ getCellValue(row, column) }}\n </ng-template>\n </td>\n\n <!-- Celda de acciones -->\n <td *ngIf=\"showActions\" class=\"px-2 py-2\">\n <button \n type=\"button\" \n class=\"inline-flex h-8 w-8 appearance-none items-center justify-center border-0 bg-transparent p-0 hover:text-foreground\" \n (click)=\"onAction(row)\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <circle cx=\"6\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"12\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n <circle cx=\"18\" cy=\"12\" r=\"1.5\" fill=\"currentColor\"></circle>\n </svg>\n </button>\n </td>\n </tr>\n\n <!-- Fila vac\u00EDa -->\n <tr *ngIf=\"pagedRows.length === 0\">\n <td \n [attr.colspan]=\"effectiveColumns.length + (selectable ? 1 : 0) + (showActions ? 1 : 0)\" \n class=\"px-3 py-6 text-center text-sm text-muted-foreground\">\n {{ emptyLabel }}\n </td>\n </tr>\n </tbody>\n </pdm-table>\n\n <!-- Footer: Info + Paginaci\u00F3n -->\n <div *ngIf=\"showPagination || selectable\" class=\"flex w-full items-center gap-2 py-4 flex-wrap sm:flex-nowrap\">\n <p *ngIf=\"selectable\" class=\"m-0 flex-1 pr-2 text-sm text-muted-foreground whitespace-nowrap\">\n {{ selectedCount }} of {{ rows.length }} {{ rowsSelectedLabel }}\n </p>\n\n <div *ngIf=\"showPagination\" class=\"flex items-center gap-2 ml-auto\">\n <span class=\"text-sm text-muted-foreground whitespace-nowrap\">\n Page {{ page }} of {{ totalPages }}\n </span>\n <button \n type=\"button\" \n class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\" \n [disabled]=\"page <= 1\" \n (click)=\"previous()\">\n {{ previousLabel }}\n </button>\n <button \n type=\"button\" \n class=\"h-9 appearance-none rounded-md border border-input bg-background px-4 text-sm font-medium text-foreground shadow-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:opacity-50 disabled:cursor-not-allowed\" \n [disabled]=\"page >= totalPages\" \n (click)=\"next()\">\n {{ nextLabel }}\n </button>\n </div>\n </div>\n</section>\n" }]
1925
2430
  }], propDecorators: { className: [{
1926
2431
  type: Input
1927
- }], filterPlaceholder: [{
2432
+ }], columns: [{
1928
2433
  type: Input
1929
- }], columnsLabel: [{
2434
+ }], responsiveStrategy: [{
1930
2435
  type: Input
1931
- }], statusLabel: [{
2436
+ }], selectable: [{
1932
2437
  type: Input
1933
- }], emailLabel: [{
2438
+ }], showActions: [{
1934
2439
  type: Input
1935
- }], amountLabel: [{
2440
+ }], showFilter: [{
2441
+ type: Input
2442
+ }], showPagination: [{
2443
+ type: Input
2444
+ }], showColumnSelector: [{
2445
+ type: Input
2446
+ }], filterPlaceholder: [{
2447
+ type: Input
2448
+ }], columnsLabel: [{
1936
2449
  type: Input
1937
2450
  }], previousLabel: [{
1938
2451
  type: Input
@@ -1940,6 +2453,14 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1940
2453
  type: Input
1941
2454
  }], emptyLabel: [{
1942
2455
  type: Input
2456
+ }], rowsSelectedLabel: [{
2457
+ type: Input
2458
+ }], statusLabel: [{
2459
+ type: Input
2460
+ }], emailLabel: [{
2461
+ type: Input
2462
+ }], amountLabel: [{
2463
+ type: Input
1943
2464
  }], rows: [{
1944
2465
  type: Input
1945
2466
  }], page: [{
@@ -1948,6 +2469,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1948
2469
  type: Input
1949
2470
  }], query: [{
1950
2471
  type: Input
2472
+ }], filterFn: [{
2473
+ type: Input
1951
2474
  }], queryChange: [{
1952
2475
  type: Output
1953
2476
  }], rowAction: [{
@@ -1956,6 +2479,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1956
2479
  type: Output
1957
2480
  }], selectionChange: [{
1958
2481
  type: Output
2482
+ }], columnSort: [{
2483
+ type: Output
1959
2484
  }] } });
1960
2485
 
1961
2486
  /**
@@ -2373,30 +2898,152 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2373
2898
  args: ['document:keydown.escape']
2374
2899
  }] } });
2375
2900
 
2376
- class PdmDialogComponent {
2377
- constructor() {
2378
- this.open = false;
2379
- this.variant = 'default';
2380
- this.size = 'desktop';
2381
- this.title = 'Edit profile';
2382
- this.description = '';
2383
- this.closeOnBackdrop = true;
2384
- this.closeOnEsc = true;
2385
- this.showCloseButton = true;
2386
- this.showHeader = true;
2387
- this.showFooter = true;
2388
- this.primaryActionText = 'Save changes';
2389
- this.secondaryActionText = 'Cancel';
2390
- this.alignFooter = 'right';
2391
- this.headerClassName = '';
2392
- this.bodyClassName = '';
2393
- this.footerClassName = '';
2394
- this.className = '';
2395
- this.openChange = new EventEmitter();
2396
- this.primaryAction = new EventEmitter();
2397
- this.secondaryAction = new EventEmitter();
2398
- }
2399
- onEsc() {
2901
+ /**
2902
+ * Z-Index Scale - Sistema centralizado de z-index
2903
+ *
2904
+ * JERARQUÍA (de menor a mayor):
2905
+ * 1. base (z-0) - Elementos normales del DOM
2906
+ * 2. dropdown (z-10) - Selects, combobox, date-pickers
2907
+ * 3. sticky (z-20) - Headers, navigation bars
2908
+ * 4. overlay (z-30) - Popovers, hover cards, context menus
2909
+ * 5. drawer (z-40) - Sidebar drawer, sheets laterales
2910
+ * 6. modal (z-50) - Dialogs, alert-dialogs
2911
+ * 7. modal-backdrop (z-40) - Backdrop de modals
2912
+ * 8. popover (z-60) - Tooltips, dropdowns DENTRO de modals
2913
+ * 9. toast (z-[100]) - Notificaciones que deben estar sobre TODO
2914
+ *
2915
+ * REGLA CRÍTICA:
2916
+ * - Componentes overlay (select options, dropdown menu, tooltip) SIEMPRE z-60 o mayor
2917
+ * - Esto permite que funcionen DENTRO de modals (z-50)
2918
+ * - Backdrop de modal debe ser z-40 para estar DEBAJO del contenido del modal (z-50)
2919
+ */
2920
+ const Z_INDEX = {
2921
+ /**
2922
+ * Base - contenido normal del DOM
2923
+ */
2924
+ base: 'z-0',
2925
+ /**
2926
+ * Dropdown - Selects, combobox, date-pickers
2927
+ * Debe estar SOBRE contenido normal pero BAJO modals
2928
+ */
2929
+ dropdown: 'z-10',
2930
+ /**
2931
+ * Sticky - Headers, navigation fija
2932
+ */
2933
+ sticky: 'z-20',
2934
+ /**
2935
+ * Overlay - Popovers, hover cards, context menus
2936
+ * Debe estar SOBRE sticky pero BAJO modals
2937
+ */
2938
+ overlay: 'z-30',
2939
+ /**
2940
+ * Drawer backdrop - Backdrop de sidebar drawer
2941
+ * Debe estar DEBAJO del drawer panel
2942
+ */
2943
+ drawerBackdrop: 'z-40',
2944
+ /**
2945
+ * Drawer - Sidebar drawer, sheets laterales
2946
+ * Debe estar SOBRE su backdrop pero BAJO modals
2947
+ */
2948
+ drawer: 'z-50',
2949
+ /**
2950
+ * Modal backdrop - Backdrop de dialogs
2951
+ * Debe estar SOBRE drawers pero DEBAJO del contenido del modal
2952
+ */
2953
+ modalBackdrop: 'z-50',
2954
+ /**
2955
+ * Modal - Dialogs, alert-dialogs, sheets
2956
+ * Debe estar SOBRE su backdrop
2957
+ */
2958
+ modal: 'z-[60]',
2959
+ /**
2960
+ * Popover - Tooltips, dropdowns, selects options DENTRO de modals
2961
+ * CRÍTICO: Debe ser MAYOR que modal (z-50) para aparecer sobre modals
2962
+ */
2963
+ popover: 'z-[70]',
2964
+ /**
2965
+ * Toast - Notificaciones globales
2966
+ * Debe estar sobre TODO
2967
+ */
2968
+ toast: 'z-[100]'
2969
+ };
2970
+ /**
2971
+ * Helper para debugging z-index issues
2972
+ */
2973
+ function logZIndexStack(element) {
2974
+ if (typeof window === 'undefined')
2975
+ return;
2976
+ let current = element;
2977
+ const stack = [];
2978
+ while (current && current !== document.body) {
2979
+ const computed = window.getComputedStyle(current);
2980
+ const zIndex = computed.zIndex;
2981
+ const position = computed.position;
2982
+ if (zIndex !== 'auto') {
2983
+ stack.push({
2984
+ element: current.tagName + (current.className ? `.${current.className.split(' ')[0]}` : ''),
2985
+ zIndex,
2986
+ position
2987
+ });
2988
+ }
2989
+ current = current.parentElement;
2990
+ }
2991
+ console.table(stack);
2992
+ }
2993
+
2994
+ /**
2995
+ * Modal/Dialog component con soporte responsive
2996
+ *
2997
+ * MEJORADO en v0.2.0:
2998
+ * - Modo 'responsive' (default): fullscreen en mobile, modal en desktop
2999
+ * - Tamaños predefinidos: sm, md, lg, xl
3000
+ * - Mejor manejo de scroll en mobile
3001
+ *
3002
+ * @example
3003
+ * // Responsive (recomendado)
3004
+ * <pdm-dialog [open]="isOpen" size="responsive">
3005
+ * <p>Content</p>
3006
+ * </pdm-dialog>
3007
+ *
3008
+ * @example
3009
+ * // Tamaño fijo
3010
+ * <pdm-dialog [open]="isOpen" size="lg">
3011
+ * <p>Content</p>
3012
+ * </pdm-dialog>
3013
+ */
3014
+ class PdmDialogComponent {
3015
+ constructor() {
3016
+ this.open = false;
3017
+ this.variant = 'default';
3018
+ /**
3019
+ * Tamaño del dialog
3020
+ * - responsive: fullscreen mobile, modal desktop (recomendado)
3021
+ * - sm: 400px max
3022
+ * - md: 500px max
3023
+ * - lg: 640px max (default)
3024
+ * - xl: 800px max
3025
+ * - desktop/mobile/mobile-fullscreen: legacy, deprecado
3026
+ */
3027
+ this.size = 'responsive';
3028
+ this.title = 'Edit profile';
3029
+ this.description = '';
3030
+ this.closeOnBackdrop = true;
3031
+ this.closeOnEsc = true;
3032
+ this.showCloseButton = true;
3033
+ this.showHeader = true;
3034
+ this.showFooter = true;
3035
+ this.primaryActionText = 'Save changes';
3036
+ this.secondaryActionText = 'Cancel';
3037
+ this.alignFooter = 'right';
3038
+ this.headerClassName = '';
3039
+ this.bodyClassName = '';
3040
+ this.footerClassName = '';
3041
+ this.className = '';
3042
+ this.openChange = new EventEmitter();
3043
+ this.primaryAction = new EventEmitter();
3044
+ this.secondaryAction = new EventEmitter();
3045
+ }
3046
+ onEsc() {
2400
3047
  if (this.open && this.closeOnEsc) {
2401
3048
  this.close();
2402
3049
  }
@@ -2416,47 +3063,132 @@ class PdmDialogComponent {
2416
3063
  }
2417
3064
  }
2418
3065
  get panelClassName() {
3066
+ // Legacy sizes (backward compatibility)
3067
+ if (this.size === 'desktop') {
3068
+ return this.buildClasses(['max-w-[640px]', 'max-h-[calc(100vh-2rem)]', 'rounded-[10px]']);
3069
+ }
3070
+ if (this.size === 'mobile') {
3071
+ return this.buildClasses(['max-w-[320px]', 'min-h-[240px]', 'rounded-[10px]']);
3072
+ }
3073
+ if (this.size === 'mobile-fullscreen') {
3074
+ return this.buildClasses(['max-w-[320px]', 'h-[min(100dvh,640px)]', 'rounded-none', 'sm:rounded-[10px]']);
3075
+ }
3076
+ // New responsive mode (recomendado)
3077
+ if (this.size === 'responsive') {
3078
+ return this.buildClasses([
3079
+ // Mobile: fullscreen con bordes redondeados solo arriba
3080
+ 'w-full',
3081
+ 'h-full',
3082
+ 'max-h-[100dvh]',
3083
+ 'rounded-t-[10px]',
3084
+ 'sm:rounded-[10px]',
3085
+ // Desktop: modal centrado
3086
+ 'sm:w-auto',
3087
+ 'sm:h-auto',
3088
+ 'sm:max-w-[640px]',
3089
+ 'sm:max-h-[calc(100vh-4rem)]'
3090
+ ]);
3091
+ }
3092
+ // New size options
3093
+ const sizeMap = {
3094
+ sm: 'sm:max-w-[400px]',
3095
+ md: 'sm:max-w-[500px]',
3096
+ lg: 'sm:max-w-[640px]',
3097
+ xl: 'sm:max-w-[800px]'
3098
+ };
3099
+ const maxWidth = sizeMap[this.size] || sizeMap.lg;
3100
+ return this.buildClasses([
3101
+ // Mobile: fullscreen
3102
+ 'w-full',
3103
+ 'h-full',
3104
+ 'max-h-[100dvh]',
3105
+ 'rounded-t-[10px]',
3106
+ // Desktop: modal
3107
+ 'sm:rounded-[10px]',
3108
+ 'sm:w-auto',
3109
+ 'sm:h-auto',
3110
+ maxWidth,
3111
+ 'sm:max-h-[calc(100vh-4rem)]'
3112
+ ]);
3113
+ }
3114
+ buildClasses(sizeClasses) {
2419
3115
  const base = [
2420
- 'relative z-10 w-full border border-border bg-background text-foreground shadow-lg',
2421
- this.size === 'desktop' ? 'max-w-[640px] max-h-[calc(100vh-2rem)] rounded-[10px] overflow-visible' : '',
2422
- this.size === 'mobile' ? 'max-w-[320px] min-h-[240px] rounded-[10px] overflow-visible' : '',
2423
- this.size === 'mobile-fullscreen'
2424
- ? 'max-w-[320px] h-[min(100dvh,640px)] rounded-none sm:rounded-[10px] overflow-visible'
2425
- : '',
3116
+ 'relative',
3117
+ Z_INDEX.modal,
3118
+ 'flex',
3119
+ 'flex-col',
3120
+ 'border',
3121
+ 'border-border',
3122
+ 'bg-background',
3123
+ 'text-foreground',
3124
+ 'shadow-lg',
3125
+ 'overflow-hidden',
3126
+ ...sizeClasses,
2426
3127
  this.className
2427
3128
  ];
2428
3129
  return base.filter(Boolean).join(' ');
2429
3130
  }
2430
3131
  get bodyWrapperClassName() {
2431
3132
  const base = [
2432
- 'min-h-0 flex-1',
2433
- this.size === 'mobile-fullscreen' ? 'overflow-y-auto px-4 py-6' : 'px-6 py-6',
3133
+ 'flex-1',
3134
+ 'overflow-y-auto',
3135
+ 'px-4',
3136
+ 'py-6',
3137
+ 'sm:px-6',
2434
3138
  this.bodyClassName
2435
3139
  ];
2436
3140
  return base.filter(Boolean).join(' ');
2437
3141
  }
2438
3142
  get headerWrapperClassName() {
2439
- return ['flex items-start justify-between gap-3 p-4', this.headerClassName].filter(Boolean).join(' ');
3143
+ const base = [
3144
+ 'flex',
3145
+ 'items-start',
3146
+ 'justify-between',
3147
+ 'gap-3',
3148
+ 'p-4',
3149
+ 'sm:p-6',
3150
+ 'border-b',
3151
+ 'border-border',
3152
+ this.headerClassName
3153
+ ];
3154
+ return base.filter(Boolean).join(' ');
2440
3155
  }
2441
3156
  get footerWrapperClassName() {
2442
3157
  const effectiveAlign = this.alignFooter === 'right' && this.variant === 'custom-close' ? 'left' : this.alignFooter;
2443
3158
  const base = [
2444
3159
  'p-4',
3160
+ 'sm:p-6',
3161
+ 'border-t',
3162
+ 'border-border',
3163
+ // Mobile: siempre full-width
3164
+ 'flex',
3165
+ 'flex-col',
3166
+ 'gap-2',
3167
+ // Desktop: según alignFooter
2445
3168
  effectiveAlign === 'full-width'
2446
- ? 'flex flex-col gap-2'
2447
- : effectiveAlign === 'left'
2448
- ? 'flex items-center gap-2 justify-start'
2449
- : 'flex items-center gap-2 justify-end',
3169
+ ? 'sm:flex-col'
3170
+ : 'sm:flex-row sm:items-center',
3171
+ effectiveAlign === 'left' ? 'sm:justify-start' : '',
3172
+ effectiveAlign === 'right' ? 'sm:justify-end' : '',
2450
3173
  this.footerClassName
2451
3174
  ];
2452
3175
  return base.filter(Boolean).join(' ');
2453
3176
  }
3177
+ get containerClassName() {
3178
+ // Container con backdrop z-50
3179
+ // Mobile: fullscreen desde el bottom
3180
+ // Desktop: centrado
3181
+ return responsive({
3182
+ default: `fixed inset-x-0 bottom-0 ${Z_INDEX.modalBackdrop} flex items-end justify-center`,
3183
+ sm: `fixed inset-0 ${Z_INDEX.modalBackdrop} flex items-center justify-center p-4`
3184
+ });
3185
+ }
2454
3186
  }
2455
3187
  PdmDialogComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2456
- PdmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDialogComponent, selector: "pdm-dialog", inputs: { open: "open", variant: "variant", size: "size", title: "title", description: "description", closeOnBackdrop: "closeOnBackdrop", closeOnEsc: "closeOnEsc", showCloseButton: "showCloseButton", showHeader: "showHeader", showFooter: "showFooter", primaryActionText: "primaryActionText", secondaryActionText: "secondaryActionText", alignFooter: "alignFooter", headerClassName: "headerClassName", bodyClassName: "bodyClassName", footerClassName: "footerClassName", className: "className" }, outputs: { openChange: "openChange", primaryAction: "primaryAction", secondaryAction: "secondaryAction" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onBackdropClick()\"></div>\n <section role=\"dialog\" aria-modal=\"true\" [ngClass]=\"panelClassName\">\n <div *ngIf=\"showHeader\" [ngClass]=\"headerWrapperClassName\">\n <div class=\"min-w-0\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 mt-2 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-sm border-0 bg-transparent p-0 text-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 6L18 18M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <div [ngClass]=\"bodyWrapperClassName\">\n <ng-content></ng-content>\n </div>\n\n <div *ngIf=\"showFooter\" [ngClass]=\"footerWrapperClassName\">\n <ng-container *ngIf=\"variant === 'custom-close'; else defaultActions\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n </ng-container>\n\n <ng-template #defaultActions>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onPrimaryAction()\"\n >\n {{ primaryActionText }}\n </button>\n </ng-template>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3188
+ PdmDialogComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDialogComponent, selector: "pdm-dialog", inputs: { open: "open", variant: "variant", size: "size", title: "title", description: "description", closeOnBackdrop: "closeOnBackdrop", closeOnEsc: "closeOnEsc", showCloseButton: "showCloseButton", showHeader: "showHeader", showFooter: "showFooter", primaryActionText: "primaryActionText", secondaryActionText: "secondaryActionText", alignFooter: "alignFooter", headerClassName: "headerClassName", bodyClassName: "bodyClassName", footerClassName: "footerClassName", className: "className" }, outputs: { openChange: "openChange", primaryAction: "primaryAction", secondaryAction: "secondaryAction" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div *ngIf=\"open\" [ngClass]=\"containerClassName\">\n <!-- Backdrop -->\n <div class=\"absolute inset-0 bg-foreground/30 backdrop-blur-sm\" (click)=\"onBackdropClick()\"></div>\n \n <!-- Dialog Panel -->\n <section role=\"dialog\" aria-modal=\"true\" [ngClass]=\"panelClassName\">\n <!-- Header -->\n <div *ngIf=\"showHeader\" [ngClass]=\"headerWrapperClassName\">\n <div class=\"min-w-0 flex-1\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 mt-2 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n class=\"inline-flex h-6 w-6 flex-shrink-0 appearance-none items-center justify-center rounded-sm border-0 bg-transparent p-0 text-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 6L18 18M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <!-- Body -->\n <div [ngClass]=\"bodyWrapperClassName\">\n <ng-content></ng-content>\n </div>\n\n <!-- Footer -->\n <div *ngIf=\"showFooter\" [ngClass]=\"footerWrapperClassName\">\n <ng-container *ngIf=\"variant === 'custom-close'; else defaultActions\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 w-full appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm sm:w-auto\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n </ng-container>\n\n <ng-template #defaultActions>\n <button\n type=\"button\"\n class=\"inline-flex h-9 w-full appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm sm:w-auto\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 w-full appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm sm:w-auto\"\n (click)=\"onPrimaryAction()\"\n >\n {{ primaryActionText }}\n </button>\n </ng-template>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2457
3189
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDialogComponent, decorators: [{
2458
3190
  type: Component,
2459
- args: [{ selector: 'pdm-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50 flex items-center justify-center p-4\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onBackdropClick()\"></div>\n <section role=\"dialog\" aria-modal=\"true\" [ngClass]=\"panelClassName\">\n <div *ngIf=\"showHeader\" [ngClass]=\"headerWrapperClassName\">\n <div class=\"min-w-0\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 mt-2 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-sm border-0 bg-transparent p-0 text-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 6L18 18M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <div [ngClass]=\"bodyWrapperClassName\">\n <ng-content></ng-content>\n </div>\n\n <div *ngIf=\"showFooter\" [ngClass]=\"footerWrapperClassName\">\n <ng-container *ngIf=\"variant === 'custom-close'; else defaultActions\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n </ng-container>\n\n <ng-template #defaultActions>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm\"\n (click)=\"onPrimaryAction()\"\n >\n {{ primaryActionText }}\n </button>\n </ng-template>\n </div>\n </section>\n</div>\n" }]
3191
+ args: [{ selector: 'pdm-dialog', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"open\" [ngClass]=\"containerClassName\">\n <!-- Backdrop -->\n <div class=\"absolute inset-0 bg-foreground/30 backdrop-blur-sm\" (click)=\"onBackdropClick()\"></div>\n \n <!-- Dialog Panel -->\n <section role=\"dialog\" aria-modal=\"true\" [ngClass]=\"panelClassName\">\n <!-- Header -->\n <div *ngIf=\"showHeader\" [ngClass]=\"headerWrapperClassName\">\n <div class=\"min-w-0 flex-1\">\n <h2 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ title }}</h2>\n <p *ngIf=\"description\" class=\"m-0 mt-2 text-sm text-muted-foreground\">{{ description }}</p>\n </div>\n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n class=\"inline-flex h-6 w-6 flex-shrink-0 appearance-none items-center justify-center rounded-sm border-0 bg-transparent p-0 text-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\"\n (click)=\"close()\"\n aria-label=\"Close dialog\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 6L18 18M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <!-- Body -->\n <div [ngClass]=\"bodyWrapperClassName\">\n <ng-content></ng-content>\n </div>\n\n <!-- Footer -->\n <div *ngIf=\"showFooter\" [ngClass]=\"footerWrapperClassName\">\n <ng-container *ngIf=\"variant === 'custom-close'; else defaultActions\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 w-full appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm sm:w-auto\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n </ng-container>\n\n <ng-template #defaultActions>\n <button\n type=\"button\"\n class=\"inline-flex h-9 w-full appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm sm:w-auto\"\n (click)=\"onSecondaryAction()\"\n >\n {{ secondaryActionText }}\n </button>\n <button\n type=\"button\"\n class=\"inline-flex h-9 w-full appearance-none items-center justify-center rounded-md bg-primary px-4 py-2 text-sm font-medium text-primary-foreground shadow-sm sm:w-auto\"\n (click)=\"onPrimaryAction()\"\n >\n {{ primaryActionText }}\n </button>\n </ng-template>\n </div>\n </section>\n</div>\n" }]
2460
3192
  }], propDecorators: { open: [{
2461
3193
  type: Input
2462
3194
  }], variant: [{
@@ -2502,6 +3234,303 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2502
3234
  args: ['document:keydown.escape']
2503
3235
  }] } });
2504
3236
 
3237
+ /**
3238
+ * Tabla con funcionalidad de reordenamiento de filas mediante drag & drop
3239
+ *
3240
+ * Extiende pdm-table agregando la capacidad de reordenar filas.
3241
+ * Si no necesitás drag & drop, usá pdm-table directamente (más simple y liviano).
3242
+ *
3243
+ * @example
3244
+ * <pdm-draggable-table
3245
+ * variant="interactive"
3246
+ * [reorderRows]="true"
3247
+ * (rowOrderChange)="onOrderChange($event)">
3248
+ * <tbody>
3249
+ * <tr data-row-id="1"><td>Row 1</td></tr>
3250
+ * <tr data-row-id="2"><td>Row 2</td></tr>
3251
+ * </tbody>
3252
+ * </pdm-draggable-table>
3253
+ *
3254
+ * IMPORTANTE: Cada <tr> debe tener un atributo data-row-id único
3255
+ */
3256
+ class PdmDraggableTableComponent {
3257
+ constructor(renderer) {
3258
+ this.renderer = renderer;
3259
+ this.variant = 'default';
3260
+ this.responsiveStrategy = 'scroll';
3261
+ this.className = '';
3262
+ this.fullBleed = false;
3263
+ /**
3264
+ * Habilita el reordenamiento de filas mediante drag & drop
3265
+ */
3266
+ this.reorderRows = false;
3267
+ /**
3268
+ * Selector CSS para identificar los handles de drag
3269
+ * Por defecto busca: [data-drag-handle], [data-slot=row-drag-handle], .row-drag-handle
3270
+ * Si no encuentra ninguno, inserta un handle automático
3271
+ */
3272
+ this.dragHandleSelector = '[data-drag-handle],[data-slot=row-drag-handle],.row-drag-handle,[data-auto-drag-handle]';
3273
+ /**
3274
+ * Emite el nuevo orden de las filas cuando el usuario termina de arrastrar
3275
+ * Array de data-row-id en el nuevo orden
3276
+ */
3277
+ this.rowOrderChange = new EventEmitter();
3278
+ this.cleanupListeners = [];
3279
+ this.draggedRow = null;
3280
+ }
3281
+ ngAfterViewInit() {
3282
+ this.syncReorderBehavior();
3283
+ }
3284
+ // Getters para clases CSS (mismo comportamiento que pdm-table)
3285
+ get wrapperClasses() {
3286
+ const baseClasses = ['relative', 'w-full'];
3287
+ const strategyClasses = this.getResponsiveStrategyClasses();
3288
+ const variantClasses = this.getVariantWrapperClasses();
3289
+ if (this.fullBleed && this.responsiveStrategy === 'scroll') {
3290
+ baseClasses.push('-mx-4', 'px-4', 'sm:mx-0', 'sm:px-0');
3291
+ }
3292
+ return [
3293
+ ...baseClasses,
3294
+ ...strategyClasses,
3295
+ ...variantClasses,
3296
+ this.className
3297
+ ].filter(Boolean);
3298
+ }
3299
+ get tableClasses() {
3300
+ const baseClasses = ['w-full', 'caption-bottom', 'text-sm'];
3301
+ const variantClasses = this.getVariantTableClasses();
3302
+ const cellClasses = this.getCellClasses();
3303
+ return [...baseClasses, ...variantClasses, ...cellClasses].filter(Boolean);
3304
+ }
3305
+ getResponsiveStrategyClasses() {
3306
+ if (this.responsiveStrategy === 'scroll' || this.responsiveStrategy === 'wrap' || this.responsiveStrategy === 'collapse') {
3307
+ return ['overflow-x-auto'];
3308
+ }
3309
+ return [];
3310
+ }
3311
+ getVariantWrapperClasses() {
3312
+ if (this.variant === 'interactive') {
3313
+ return ['rounded-xl', 'border', 'border-border', 'bg-background'];
3314
+ }
3315
+ if (this.variant === 'data') {
3316
+ return ['rounded-md', 'border', 'border-border', 'bg-background'];
3317
+ }
3318
+ return [];
3319
+ }
3320
+ getVariantTableClasses() {
3321
+ if (this.variant === 'data') {
3322
+ return [
3323
+ 'border-collapse', 'text-foreground',
3324
+ '[&_thead_tr]:border-b', '[&_thead_tr]:border-border',
3325
+ '[&_tbody_tr]:border-b', '[&_tbody_tr]:border-border',
3326
+ '[&_tbody_tr:last-child]:border-b-0',
3327
+ '[&_th]:h-10', '[&_th]:px-2', '[&_th]:text-left', '[&_th]:align-middle', '[&_th]:font-medium',
3328
+ '[&_td]:p-2', '[&_td]:align-middle'
3329
+ ];
3330
+ }
3331
+ if (this.variant === 'interactive') {
3332
+ return [
3333
+ 'text-foreground',
3334
+ '[&_thead]:sticky', '[&_thead]:top-0', '[&_thead]:z-10', '[&_thead]:bg-muted/70',
3335
+ '[&_thead_tr]:border-b', '[&_thead_tr]:border-border',
3336
+ '[&_th]:h-12', '[&_th]:px-4', '[&_th]:text-left', '[&_th]:align-middle', '[&_th]:text-sm', '[&_th]:font-medium',
3337
+ '[&_tbody_tr]:border-b', '[&_tbody_tr]:border-border',
3338
+ '[&_tbody_tr]:transition-colors', '[&_tbody_tr:hover]:bg-muted/50',
3339
+ '[&_tbody_tr:last-child]:border-b-0',
3340
+ '[&_td]:h-14', '[&_td]:px-4', '[&_td]:align-middle', '[&_td]:text-sm',
3341
+ '[&_svg]:text-muted-foreground'
3342
+ ];
3343
+ }
3344
+ return [];
3345
+ }
3346
+ getCellClasses() {
3347
+ if (this.responsiveStrategy === 'scroll') {
3348
+ return ['[&_td]:whitespace-normal', '[&_th]:whitespace-normal', 'sm:[&_td]:whitespace-nowrap', 'sm:[&_th]:whitespace-nowrap'];
3349
+ }
3350
+ if (this.responsiveStrategy === 'wrap') {
3351
+ return ['[&_td]:whitespace-normal', '[&_td]:break-words', '[&_th]:whitespace-normal'];
3352
+ }
3353
+ return [];
3354
+ }
3355
+ ngOnChanges(changes) {
3356
+ if (changes['reorderRows'] || changes['variant']) {
3357
+ this.syncReorderBehavior();
3358
+ }
3359
+ }
3360
+ ngOnDestroy() {
3361
+ this.cleanupReorderBehavior();
3362
+ }
3363
+ syncReorderBehavior() {
3364
+ this.cleanupReorderBehavior();
3365
+ if (!this.reorderRows) {
3366
+ return;
3367
+ }
3368
+ const tbody = this.getTbody();
3369
+ if (!tbody) {
3370
+ return;
3371
+ }
3372
+ this.setRowsDraggable(tbody, true);
3373
+ this.cleanupListeners.push(this.renderer.listen(tbody, 'mousedown', (event) => this.armDragFromHandle(event)), this.renderer.listen(tbody, 'dragstart', (event) => this.onDragStart(event)), this.renderer.listen(tbody, 'dragover', (event) => this.onDragOver(event, tbody)), this.renderer.listen(tbody, 'drop', (event) => this.onDrop(event)), this.renderer.listen(tbody, 'dragend', () => this.onDragEnd()));
3374
+ // Observer para detectar cambios en el DOM (filas agregadas/removidas)
3375
+ this.observer = new MutationObserver(() => this.setRowsDraggable(tbody, true));
3376
+ this.observer.observe(tbody, { childList: true });
3377
+ }
3378
+ cleanupReorderBehavior() {
3379
+ this.cleanupListeners.forEach((dispose) => dispose());
3380
+ this.cleanupListeners = [];
3381
+ if (this.observer) {
3382
+ this.observer.disconnect();
3383
+ this.observer = undefined;
3384
+ }
3385
+ const tbody = this.getTbody();
3386
+ if (tbody) {
3387
+ this.setRowsDraggable(tbody, false);
3388
+ }
3389
+ this.draggedRow = null;
3390
+ }
3391
+ getTbody() {
3392
+ return this.tableElement?.nativeElement.tBodies.item(0) ?? null;
3393
+ }
3394
+ setRowsDraggable(tbody, enabled) {
3395
+ const rows = Array.from(tbody.rows);
3396
+ rows.forEach((row) => {
3397
+ this.syncAutoDragHandle(row, enabled);
3398
+ row.draggable = false;
3399
+ if (!enabled) {
3400
+ delete row.dataset['dragging'];
3401
+ delete row.dataset['dragArmed'];
3402
+ }
3403
+ });
3404
+ }
3405
+ /**
3406
+ * Inserta un handle de drag automático si no existe uno custom
3407
+ */
3408
+ syncAutoDragHandle(row, enabled) {
3409
+ const firstCell = row.cells.item(0);
3410
+ if (!firstCell) {
3411
+ return;
3412
+ }
3413
+ const existingAutoHandle = firstCell.querySelector('[data-auto-drag-handle]');
3414
+ if (!enabled) {
3415
+ existingAutoHandle?.remove();
3416
+ return;
3417
+ }
3418
+ const hasCustomHandle = !!firstCell.querySelector('[data-drag-handle],[data-slot=row-drag-handle],.row-drag-handle');
3419
+ if (hasCustomHandle || existingAutoHandle) {
3420
+ return;
3421
+ }
3422
+ // Crear handle automático
3423
+ const button = this.renderer.createElement('button');
3424
+ this.renderer.setAttribute(button, 'type', 'button');
3425
+ this.renderer.setAttribute(button, 'aria-label', 'Drag row');
3426
+ this.renderer.setAttribute(button, 'data-auto-drag-handle', 'true');
3427
+ this.renderer.addClass(button, 'inline-flex');
3428
+ this.renderer.addClass(button, 'h-7');
3429
+ this.renderer.addClass(button, 'w-7');
3430
+ this.renderer.addClass(button, 'items-center');
3431
+ this.renderer.addClass(button, 'justify-center');
3432
+ this.renderer.addClass(button, 'cursor-grab');
3433
+ this.renderer.addClass(button, 'active:cursor-grabbing');
3434
+ this.renderer.addClass(button, 'text-muted-foreground');
3435
+ const dots = this.renderer.createElement('span');
3436
+ this.renderer.addClass(dots, 'text-sm');
3437
+ this.renderer.addClass(dots, 'leading-none');
3438
+ this.renderer.setProperty(dots, 'textContent', '⋮⋮');
3439
+ this.renderer.appendChild(button, dots);
3440
+ this.renderer.insertBefore(firstCell, button, firstCell.firstChild);
3441
+ }
3442
+ onDragStart(event) {
3443
+ const target = event.target;
3444
+ const row = target?.closest('tr');
3445
+ if (!row) {
3446
+ return;
3447
+ }
3448
+ const handle = target?.closest(this.dragHandleSelector);
3449
+ const isArmed = row.dataset['dragArmed'] === 'true';
3450
+ if ((!handle || !row.contains(handle)) && !isArmed) {
3451
+ event.preventDefault();
3452
+ return;
3453
+ }
3454
+ this.draggedRow = row;
3455
+ this.draggedRow.dataset['dragging'] = 'true';
3456
+ if (event.dataTransfer) {
3457
+ event.dataTransfer.effectAllowed = 'move';
3458
+ event.dataTransfer.setData('text/plain', '');
3459
+ }
3460
+ }
3461
+ onDragOver(event, tbody) {
3462
+ if (!this.draggedRow) {
3463
+ return;
3464
+ }
3465
+ event.preventDefault();
3466
+ const target = event.target;
3467
+ const targetRow = target?.closest('tr');
3468
+ if (!targetRow || targetRow === this.draggedRow) {
3469
+ return;
3470
+ }
3471
+ const rect = targetRow.getBoundingClientRect();
3472
+ const shouldInsertBefore = event.clientY < rect.top + rect.height / 2;
3473
+ tbody.insertBefore(this.draggedRow, shouldInsertBefore ? targetRow : targetRow.nextSibling);
3474
+ }
3475
+ onDrop(event) {
3476
+ event.preventDefault();
3477
+ }
3478
+ onDragEnd() {
3479
+ const tbody = this.getTbody();
3480
+ if (tbody) {
3481
+ Array.from(tbody.rows).forEach((row) => {
3482
+ row.draggable = false;
3483
+ delete row.dataset['dragArmed'];
3484
+ });
3485
+ }
3486
+ if (this.draggedRow) {
3487
+ delete this.draggedRow.dataset['dragging'];
3488
+ this.draggedRow = null;
3489
+ }
3490
+ if (!tbody) {
3491
+ return;
3492
+ }
3493
+ const order = Array.from(tbody.rows).map((row, index) => row.getAttribute('data-row-id') || String(index));
3494
+ this.rowOrderChange.emit(order);
3495
+ }
3496
+ armDragFromHandle(event) {
3497
+ const target = event.target;
3498
+ const handle = target?.closest(this.dragHandleSelector);
3499
+ if (!handle) {
3500
+ return;
3501
+ }
3502
+ const row = handle.closest('tr');
3503
+ if (!row) {
3504
+ return;
3505
+ }
3506
+ row.draggable = true;
3507
+ row.dataset['dragArmed'] = 'true';
3508
+ }
3509
+ }
3510
+ PdmDraggableTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDraggableTableComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
3511
+ PdmDraggableTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDraggableTableComponent, selector: "pdm-draggable-table", inputs: { variant: "variant", responsiveStrategy: "responsiveStrategy", className: "className", fullBleed: "fullBleed", reorderRows: "reorderRows", dragHandleSelector: "dragHandleSelector" }, outputs: { rowOrderChange: "rowOrderChange" }, viewQueries: [{ propertyName: "tableElement", first: true, predicate: ["tableElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [ngClass]=\"wrapperClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table-container' : null\">\n <table #tableElement [ngClass]=\"tableClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table' : null\">\n <ng-content></ng-content>\n </table>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3512
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDraggableTableComponent, decorators: [{
3513
+ type: Component,
3514
+ args: [{ selector: 'pdm-draggable-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"wrapperClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table-container' : null\">\n <table #tableElement [ngClass]=\"tableClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table' : null\">\n <ng-content></ng-content>\n </table>\n</div>\n" }]
3515
+ }], ctorParameters: function () { return [{ type: i0.Renderer2 }]; }, propDecorators: { variant: [{
3516
+ type: Input
3517
+ }], responsiveStrategy: [{
3518
+ type: Input
3519
+ }], className: [{
3520
+ type: Input
3521
+ }], fullBleed: [{
3522
+ type: Input
3523
+ }], reorderRows: [{
3524
+ type: Input
3525
+ }], dragHandleSelector: [{
3526
+ type: Input
3527
+ }], rowOrderChange: [{
3528
+ type: Output
3529
+ }], tableElement: [{
3530
+ type: ViewChild,
3531
+ args: ['tableElement']
3532
+ }] } });
3533
+
2505
3534
  class PdmDropdownMenuComponent {
2506
3535
  constructor(elementRef, cdr, overlay, viewContainerRef) {
2507
3536
  this.elementRef = elementRef;
@@ -2616,7 +3645,7 @@ class PdmDropdownMenuComponent {
2616
3645
  const positionStrategy = createFlexiblePositionStrategy(this.overlay, triggerEl, 8);
2617
3646
  // Resolve panelClass: overlayOptions.panelClass wins; otherwise map panelClassName.
2618
3647
  const resolvedPanelClass = this.overlayOptions?.panelClass
2619
- ?? (this.panelClassName ? ['block', this.panelClassName] : ['block']);
3648
+ ?? (this.panelClassName ? [Z_INDEX.popover, this.panelClassName] : [Z_INDEX.popover]);
2620
3649
  this.overlayRef = this.overlay.create({
2621
3650
  positionStrategy,
2622
3651
  scrollStrategy: this.overlay.scrollStrategies.reposition(),
@@ -2687,13 +3716,67 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2687
3716
  args: ['document:keydown.escape']
2688
3717
  }] } });
2689
3718
 
3719
+ /**
3720
+ * Drawer/Sheet component con soporte responsive
3721
+ *
3722
+ * MEJORADO en v0.2.0:
3723
+ * - Posicionamiento configurable (bottom, left, right, top)
3724
+ * - Tamaños predefinidos
3725
+ * - Responsive: bottom sheet en mobile, side panel en desktop
3726
+ * - Contenido genérico via ng-content
3727
+ *
3728
+ * @example
3729
+ * // Drawer simple desde el bottom
3730
+ * <pdm-drawer [open]="isOpen" position="bottom">
3731
+ * <h3>Title</h3>
3732
+ * <p>Content</p>
3733
+ * </pdm-drawer>
3734
+ *
3735
+ * @example
3736
+ * // Side panel desde la right
3737
+ * <pdm-drawer [open]="isOpen" position="right" size="md">
3738
+ * <p>Content</p>
3739
+ * </pdm-drawer>
3740
+ */
2690
3741
  class PdmDrawerComponent {
2691
3742
  constructor() {
2692
3743
  this.open = false;
3744
+ /**
3745
+ * Posición del drawer
3746
+ * - bottom: desde abajo (default, mejor para mobile)
3747
+ * - left: side panel desde izquierda
3748
+ * - right: side panel desde derecha
3749
+ * - top: desde arriba (poco común)
3750
+ */
3751
+ this.position = 'bottom';
3752
+ /**
3753
+ * Tamaño del drawer
3754
+ * - sm: 400px (side) / 50vh (bottom/top)
3755
+ * - md: 500px (side) / 66vh (bottom/top) (default)
3756
+ * - lg: 640px (side) / 80vh (bottom/top)
3757
+ * - full: 100% ancho/alto
3758
+ */
3759
+ this.size = 'md';
3760
+ /**
3761
+ * @deprecated Use position="bottom" instead
3762
+ */
2693
3763
  this.variant = 'drawer';
2694
3764
  this.className = '';
2695
3765
  this.title = '';
2696
3766
  this.description = '';
3767
+ /**
3768
+ * Mostrar handle visual (línea para arrastrar)
3769
+ * Solo tiene sentido en position="bottom"
3770
+ */
3771
+ this.showHandle = true;
3772
+ /**
3773
+ * Mostrar botón de cerrar
3774
+ */
3775
+ this.showCloseButton = true;
3776
+ this.closeOnEsc = true;
3777
+ this.closeOnBackdropClick = true;
3778
+ this.openChange = new EventEmitter();
3779
+ // DEPRECATED: contenido específico que se movió a ng-content
2697
3780
  this.value = '';
2698
3781
  this.unit = '';
2699
3782
  this.decrementLabel = '-';
@@ -2707,14 +3790,9 @@ class PdmDrawerComponent {
2707
3790
  this.usernameLabel = 'Username';
2708
3791
  this.usernameValue = '';
2709
3792
  this.responsivePrimaryLabel = '';
2710
- /** Close when the ESC key is pressed. Default: `true`. */
2711
- this.closeOnEsc = true;
2712
- /** Close when the backdrop is clicked. Default: `true`. */
2713
- this.closeOnBackdropClick = true;
2714
- this.openChange = new EventEmitter();
3793
+ this.bars = [];
2715
3794
  this.primaryAction = new EventEmitter();
2716
3795
  this.secondaryAction = new EventEmitter();
2717
- this.bars = [];
2718
3796
  }
2719
3797
  onEsc() {
2720
3798
  if (this.open && this.closeOnEsc) {
@@ -2735,14 +3813,67 @@ class PdmDrawerComponent {
2735
3813
  onSecondaryAction() {
2736
3814
  this.secondaryAction.emit();
2737
3815
  }
3816
+ get containerClassName() {
3817
+ return `fixed inset-0 ${Z_INDEX.drawer} ${this.className}`;
3818
+ }
3819
+ get panelClassName() {
3820
+ const base = [
3821
+ 'absolute',
3822
+ 'bg-background',
3823
+ 'border',
3824
+ 'border-border',
3825
+ 'shadow-lg',
3826
+ 'overflow-auto'
3827
+ ];
3828
+ // Posicionamiento
3829
+ const positionClasses = this.getPositionClasses();
3830
+ // Tamaño
3831
+ const sizeClasses = this.getSizeClasses();
3832
+ return [...base, ...positionClasses, ...sizeClasses].filter(Boolean).join(' ');
3833
+ }
3834
+ getPositionClasses() {
3835
+ const map = {
3836
+ bottom: ['inset-x-0', 'bottom-0', 'rounded-t-xl'],
3837
+ top: ['inset-x-0', 'top-0', 'rounded-b-xl'],
3838
+ left: ['inset-y-0', 'left-0', 'rounded-r-xl'],
3839
+ right: ['inset-y-0', 'right-0', 'rounded-l-xl']
3840
+ };
3841
+ return map[this.position] || map.bottom;
3842
+ }
3843
+ getSizeClasses() {
3844
+ const isVertical = this.position === 'bottom' || this.position === 'top';
3845
+ if (this.size === 'full') {
3846
+ return ['w-full', 'h-full'];
3847
+ }
3848
+ const sizeMap = {
3849
+ sm: isVertical ? 'max-h-[50vh]' : 'max-w-[400px]',
3850
+ md: isVertical ? 'max-h-[66vh]' : 'max-w-[500px]',
3851
+ lg: isVertical ? 'max-h-[80vh]' : 'max-w-[640px]'
3852
+ };
3853
+ const maxDimension = sizeMap[this.size] || sizeMap.md;
3854
+ if (isVertical) {
3855
+ return ['w-full', maxDimension];
3856
+ }
3857
+ else {
3858
+ return ['h-full', maxDimension];
3859
+ }
3860
+ }
3861
+ get showLegacyContent() {
3862
+ // Mostrar contenido legacy si variant está siendo usado
3863
+ return this.variant === 'drawer' || this.variant === 'responsive-dialog';
3864
+ }
2738
3865
  }
2739
3866
  PdmDrawerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDrawerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2740
- PdmDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDrawerComponent, selector: "pdm-drawer", inputs: { open: "open", variant: "variant", className: "className", title: "title", description: "description", value: "value", unit: "unit", decrementLabel: "decrementLabel", incrementLabel: "incrementLabel", primaryLabel: "primaryLabel", secondaryLabel: "secondaryLabel", profileTitle: "profileTitle", profileDescription: "profileDescription", nameLabel: "nameLabel", nameValue: "nameValue", usernameLabel: "usernameLabel", usernameValue: "usernameValue", responsivePrimaryLabel: "responsivePrimaryLabel", closeOnEsc: "closeOnEsc", closeOnBackdropClick: "closeOnBackdropClick", bars: "bars" }, outputs: { openChange: "openChange", primaryAction: "primaryAction", secondaryAction: "secondaryAction" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50\" [ngClass]=\"className\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onBackdropClick()\"></div>\n\n <section\n *ngIf=\"variant === 'drawer'; else responsiveDialog\"\n class=\"absolute inset-x-0 bottom-0 mx-auto w-full max-w-6xl rounded-t-lg border border-border bg-background p-6 shadow-lg\"\n >\n <div class=\"mx-auto mb-4 h-1 w-10 rounded-full bg-border\"></div>\n\n <div class=\"mx-auto flex max-w-sm flex-col items-center\">\n <h3 class=\"m-0 text-sm font-semibold text-foreground\">{{ title }}</h3>\n <p class=\"m-0 mt-1 text-xs text-muted-foreground\">{{ description }}</p>\n\n <div class=\"mt-3 flex w-full items-center justify-center gap-4\">\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ decrementLabel }}</button>\n <div class=\"text-center\">\n <div class=\"text-5xl font-semibold leading-none text-foreground\">{{ value }}</div>\n <div class=\"mt-1 text-xs tracking-wide text-muted-foreground\">{{ unit }}</div>\n </div>\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ incrementLabel }}</button>\n </div>\n\n <div *ngIf=\"bars.length\" class=\"mt-3 flex h-14 w-full items-end gap-1\">\n <div *ngFor=\"let bar of bars\" class=\"flex-1 bg-foreground\" [style.height.px]=\"bar\"></div>\n </div>\n\n <button *ngIf=\"primaryLabel\" type=\"button\" class=\"mt-3 h-9 w-full appearance-none rounded-md bg-primary text-sm font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ primaryLabel }}</button>\n <button *ngIf=\"secondaryLabel\" type=\"button\" class=\"mt-2 h-9 w-full appearance-none rounded-md border border-input bg-background text-sm font-medium text-foreground\" (click)=\"onSecondaryAction()\">{{ secondaryLabel }}</button>\n </div>\n </section>\n\n <ng-template #responsiveDialog>\n <section class=\"absolute left-1/2 top-1/2 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-lg border border-border bg-background p-6 shadow-lg\">\n <div class=\"flex items-start justify-between\">\n <div>\n <h3 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ profileTitle }}</h3>\n <p class=\"m-0 mt-1 text-sm text-muted-foreground\">{{ profileDescription }}</p>\n </div>\n <button type=\"button\" class=\"h-5 w-5 appearance-none border-0 bg-transparent p-0 text-muted-foreground\" (click)=\"close()\">\u00D7</button>\n </div>\n\n <div class=\"mt-3 flex flex-col gap-3\">\n <div>\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ nameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ nameValue }}</div>\n </div>\n <div>\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ usernameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ usernameValue }}</div>\n </div>\n </div>\n\n <button *ngIf=\"responsivePrimaryLabel\" type=\"button\" class=\"mt-3 h-8 w-full appearance-none rounded-md bg-primary text-xs font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ responsivePrimaryLabel }}</button>\n </section>\n </ng-template>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3867
+ PdmDrawerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDrawerComponent, selector: "pdm-drawer", inputs: { open: "open", position: "position", size: "size", variant: "variant", className: "className", title: "title", description: "description", showHandle: "showHandle", showCloseButton: "showCloseButton", closeOnEsc: "closeOnEsc", closeOnBackdropClick: "closeOnBackdropClick", value: "value", unit: "unit", decrementLabel: "decrementLabel", incrementLabel: "incrementLabel", primaryLabel: "primaryLabel", secondaryLabel: "secondaryLabel", profileTitle: "profileTitle", profileDescription: "profileDescription", nameLabel: "nameLabel", nameValue: "nameValue", usernameLabel: "usernameLabel", usernameValue: "usernameValue", responsivePrimaryLabel: "responsivePrimaryLabel", bars: "bars" }, outputs: { openChange: "openChange", primaryAction: "primaryAction", secondaryAction: "secondaryAction" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div *ngIf=\"open\" [ngClass]=\"containerClassName\">\n <!-- Backdrop -->\n <div class=\"absolute inset-0 bg-foreground/30 backdrop-blur-sm\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Panel -->\n <section [ngClass]=\"panelClassName\">\n <!-- Handle visual (solo para bottom) -->\n <div \n *ngIf=\"showHandle && position === 'bottom'\" \n class=\"mx-auto mb-4 mt-2 h-1 w-10 rounded-full bg-border\">\n </div>\n\n <!-- Header (opcional) -->\n <div *ngIf=\"title || description || showCloseButton\" class=\"flex items-start justify-between gap-4 p-6 pb-4\">\n <div *ngIf=\"title || description\" class=\"flex-1 min-w-0\">\n <h3 *ngIf=\"title\" class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">\n {{ title }}\n </h3>\n <p *ngIf=\"description\" class=\"m-0 mt-1 text-sm text-muted-foreground\">\n {{ description }}\n </p>\n </div>\n \n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n class=\"inline-flex h-6 w-6 flex-shrink-0 appearance-none items-center justify-center rounded-sm border-0 bg-transparent p-0 text-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n (click)=\"close()\"\n aria-label=\"Close drawer\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 6L18 18M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"px-6 pb-6\">\n <!-- Contenido gen\u00E9rico -->\n <ng-container *ngIf=\"!showLegacyContent\">\n <ng-content></ng-content>\n </ng-container>\n\n <!-- LEGACY: contenido espec\u00EDfico hardcodeado (backward compatibility) -->\n <ng-container *ngIf=\"showLegacyContent\">\n <!-- Variant: drawer -->\n <div *ngIf=\"variant === 'drawer'\" class=\"mx-auto flex max-w-sm flex-col items-center\">\n <div *ngIf=\"value !== ''\" class=\"mt-3 flex w-full items-center justify-center gap-4\">\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ decrementLabel }}</button>\n <div class=\"text-center\">\n <div class=\"text-5xl font-semibold leading-none text-foreground\">{{ value }}</div>\n <div *ngIf=\"unit\" class=\"mt-1 text-xs tracking-wide text-muted-foreground\">{{ unit }}</div>\n </div>\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ incrementLabel }}</button>\n </div>\n\n <div *ngIf=\"bars.length\" class=\"mt-3 flex h-14 w-full items-end gap-1\">\n <div *ngFor=\"let bar of bars\" class=\"flex-1 bg-foreground\" [style.height.px]=\"bar\"></div>\n </div>\n\n <button *ngIf=\"primaryLabel\" type=\"button\" class=\"mt-3 h-9 w-full appearance-none rounded-md bg-primary text-sm font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ primaryLabel }}</button>\n <button *ngIf=\"secondaryLabel\" type=\"button\" class=\"mt-2 h-9 w-full appearance-none rounded-md border border-input bg-background text-sm font-medium text-foreground\" (click)=\"onSecondaryAction()\">{{ secondaryLabel }}</button>\n </div>\n\n <!-- Variant: responsive-dialog -->\n <div *ngIf=\"variant === 'responsive-dialog'\" class=\"flex flex-col gap-3\">\n <div *ngIf=\"nameLabel && nameValue\">\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ nameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ nameValue }}</div>\n </div>\n <div *ngIf=\"usernameLabel && usernameValue\">\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ usernameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ usernameValue }}</div>\n </div>\n\n <button *ngIf=\"responsivePrimaryLabel\" type=\"button\" class=\"mt-3 h-8 w-full appearance-none rounded-md bg-primary text-xs font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ responsivePrimaryLabel }}</button>\n </div>\n </ng-container>\n </div>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2741
3868
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDrawerComponent, decorators: [{
2742
3869
  type: Component,
2743
- args: [{ selector: 'pdm-drawer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50\" [ngClass]=\"className\">\n <div class=\"absolute inset-0 bg-foreground/30\" (click)=\"onBackdropClick()\"></div>\n\n <section\n *ngIf=\"variant === 'drawer'; else responsiveDialog\"\n class=\"absolute inset-x-0 bottom-0 mx-auto w-full max-w-6xl rounded-t-lg border border-border bg-background p-6 shadow-lg\"\n >\n <div class=\"mx-auto mb-4 h-1 w-10 rounded-full bg-border\"></div>\n\n <div class=\"mx-auto flex max-w-sm flex-col items-center\">\n <h3 class=\"m-0 text-sm font-semibold text-foreground\">{{ title }}</h3>\n <p class=\"m-0 mt-1 text-xs text-muted-foreground\">{{ description }}</p>\n\n <div class=\"mt-3 flex w-full items-center justify-center gap-4\">\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ decrementLabel }}</button>\n <div class=\"text-center\">\n <div class=\"text-5xl font-semibold leading-none text-foreground\">{{ value }}</div>\n <div class=\"mt-1 text-xs tracking-wide text-muted-foreground\">{{ unit }}</div>\n </div>\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ incrementLabel }}</button>\n </div>\n\n <div *ngIf=\"bars.length\" class=\"mt-3 flex h-14 w-full items-end gap-1\">\n <div *ngFor=\"let bar of bars\" class=\"flex-1 bg-foreground\" [style.height.px]=\"bar\"></div>\n </div>\n\n <button *ngIf=\"primaryLabel\" type=\"button\" class=\"mt-3 h-9 w-full appearance-none rounded-md bg-primary text-sm font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ primaryLabel }}</button>\n <button *ngIf=\"secondaryLabel\" type=\"button\" class=\"mt-2 h-9 w-full appearance-none rounded-md border border-input bg-background text-sm font-medium text-foreground\" (click)=\"onSecondaryAction()\">{{ secondaryLabel }}</button>\n </div>\n </section>\n\n <ng-template #responsiveDialog>\n <section class=\"absolute left-1/2 top-1/2 w-full max-w-lg -translate-x-1/2 -translate-y-1/2 rounded-lg border border-border bg-background p-6 shadow-lg\">\n <div class=\"flex items-start justify-between\">\n <div>\n <h3 class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">{{ profileTitle }}</h3>\n <p class=\"m-0 mt-1 text-sm text-muted-foreground\">{{ profileDescription }}</p>\n </div>\n <button type=\"button\" class=\"h-5 w-5 appearance-none border-0 bg-transparent p-0 text-muted-foreground\" (click)=\"close()\">\u00D7</button>\n </div>\n\n <div class=\"mt-3 flex flex-col gap-3\">\n <div>\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ nameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ nameValue }}</div>\n </div>\n <div>\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ usernameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ usernameValue }}</div>\n </div>\n </div>\n\n <button *ngIf=\"responsivePrimaryLabel\" type=\"button\" class=\"mt-3 h-8 w-full appearance-none rounded-md bg-primary text-xs font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ responsivePrimaryLabel }}</button>\n </section>\n </ng-template>\n</div>\n" }]
3870
+ args: [{ selector: 'pdm-drawer', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"open\" [ngClass]=\"containerClassName\">\n <!-- Backdrop -->\n <div class=\"absolute inset-0 bg-foreground/30 backdrop-blur-sm\" (click)=\"onBackdropClick()\"></div>\n\n <!-- Panel -->\n <section [ngClass]=\"panelClassName\">\n <!-- Handle visual (solo para bottom) -->\n <div \n *ngIf=\"showHandle && position === 'bottom'\" \n class=\"mx-auto mb-4 mt-2 h-1 w-10 rounded-full bg-border\">\n </div>\n\n <!-- Header (opcional) -->\n <div *ngIf=\"title || description || showCloseButton\" class=\"flex items-start justify-between gap-4 p-6 pb-4\">\n <div *ngIf=\"title || description\" class=\"flex-1 min-w-0\">\n <h3 *ngIf=\"title\" class=\"m-0 text-lg font-semibold leading-none tracking-tight text-foreground\">\n {{ title }}\n </h3>\n <p *ngIf=\"description\" class=\"m-0 mt-1 text-sm text-muted-foreground\">\n {{ description }}\n </p>\n </div>\n \n <button\n *ngIf=\"showCloseButton\"\n type=\"button\"\n class=\"inline-flex h-6 w-6 flex-shrink-0 appearance-none items-center justify-center rounded-sm border-0 bg-transparent p-0 text-foreground opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2\"\n (click)=\"close()\"\n aria-label=\"Close drawer\"\n >\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n <path d=\"M6 6L18 18M18 6L6 18\" stroke=\"currentColor\" stroke-width=\"1.5\" stroke-linecap=\"round\"></path>\n </svg>\n </button>\n </div>\n\n <!-- Content -->\n <div class=\"px-6 pb-6\">\n <!-- Contenido gen\u00E9rico -->\n <ng-container *ngIf=\"!showLegacyContent\">\n <ng-content></ng-content>\n </ng-container>\n\n <!-- LEGACY: contenido espec\u00EDfico hardcodeado (backward compatibility) -->\n <ng-container *ngIf=\"showLegacyContent\">\n <!-- Variant: drawer -->\n <div *ngIf=\"variant === 'drawer'\" class=\"mx-auto flex max-w-sm flex-col items-center\">\n <div *ngIf=\"value !== ''\" class=\"mt-3 flex w-full items-center justify-center gap-4\">\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ decrementLabel }}</button>\n <div class=\"text-center\">\n <div class=\"text-5xl font-semibold leading-none text-foreground\">{{ value }}</div>\n <div *ngIf=\"unit\" class=\"mt-1 text-xs tracking-wide text-muted-foreground\">{{ unit }}</div>\n </div>\n <button type=\"button\" class=\"inline-flex h-6 w-6 appearance-none items-center justify-center rounded-full border border-border bg-transparent p-0 text-muted-foreground\">{{ incrementLabel }}</button>\n </div>\n\n <div *ngIf=\"bars.length\" class=\"mt-3 flex h-14 w-full items-end gap-1\">\n <div *ngFor=\"let bar of bars\" class=\"flex-1 bg-foreground\" [style.height.px]=\"bar\"></div>\n </div>\n\n <button *ngIf=\"primaryLabel\" type=\"button\" class=\"mt-3 h-9 w-full appearance-none rounded-md bg-primary text-sm font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ primaryLabel }}</button>\n <button *ngIf=\"secondaryLabel\" type=\"button\" class=\"mt-2 h-9 w-full appearance-none rounded-md border border-input bg-background text-sm font-medium text-foreground\" (click)=\"onSecondaryAction()\">{{ secondaryLabel }}</button>\n </div>\n\n <!-- Variant: responsive-dialog -->\n <div *ngIf=\"variant === 'responsive-dialog'\" class=\"flex flex-col gap-3\">\n <div *ngIf=\"nameLabel && nameValue\">\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ nameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ nameValue }}</div>\n </div>\n <div *ngIf=\"usernameLabel && usernameValue\">\n <label class=\"mb-1 block text-xs font-medium text-foreground\">{{ usernameLabel }}</label>\n <div class=\"h-8 rounded-md border border-border bg-background px-2 py-1 text-xs text-foreground\">{{ usernameValue }}</div>\n </div>\n\n <button *ngIf=\"responsivePrimaryLabel\" type=\"button\" class=\"mt-3 h-8 w-full appearance-none rounded-md bg-primary text-xs font-medium text-primary-foreground\" (click)=\"onPrimaryAction()\">{{ responsivePrimaryLabel }}</button>\n </div>\n </ng-container>\n </div>\n </section>\n</div>\n" }]
2744
3871
  }], propDecorators: { open: [{
2745
3872
  type: Input
3873
+ }], position: [{
3874
+ type: Input
3875
+ }], size: [{
3876
+ type: Input
2746
3877
  }], variant: [{
2747
3878
  type: Input
2748
3879
  }], className: [{
@@ -2751,6 +3882,16 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2751
3882
  type: Input
2752
3883
  }], description: [{
2753
3884
  type: Input
3885
+ }], showHandle: [{
3886
+ type: Input
3887
+ }], showCloseButton: [{
3888
+ type: Input
3889
+ }], closeOnEsc: [{
3890
+ type: Input
3891
+ }], closeOnBackdropClick: [{
3892
+ type: Input
3893
+ }], openChange: [{
3894
+ type: Output
2754
3895
  }], value: [{
2755
3896
  type: Input
2756
3897
  }], unit: [{
@@ -2777,18 +3918,12 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2777
3918
  type: Input
2778
3919
  }], responsivePrimaryLabel: [{
2779
3920
  type: Input
2780
- }], closeOnEsc: [{
2781
- type: Input
2782
- }], closeOnBackdropClick: [{
3921
+ }], bars: [{
2783
3922
  type: Input
2784
- }], openChange: [{
2785
- type: Output
2786
3923
  }], primaryAction: [{
2787
3924
  type: Output
2788
3925
  }], secondaryAction: [{
2789
3926
  type: Output
2790
- }], bars: [{
2791
- type: Input
2792
3927
  }], onEsc: [{
2793
3928
  type: HostListener,
2794
3929
  args: ['document:keydown.escape']
@@ -2933,10 +4068,10 @@ class PdmHoverCardComponent {
2933
4068
  }
2934
4069
  }
2935
4070
  PdmHoverCardComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmHoverCardComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
2936
- PdmHoverCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmHoverCardComponent, selector: "pdm-hover-card", inputs: { className: "className", panelClassName: "panelClassName", side: "side", align: "align", panelWidth: "panelWidth" }, ngImport: i0, template: "<div\n class=\"relative inline-flex\"\n [ngClass]=\"className\"\n (mouseenter)=\"open = true\"\n (mouseleave)=\"open = false\"\n (focusin)=\"open = true\"\n (focusout)=\"open = false\"\n>\n <div>\n <ng-content select=\"[pdmHoverTrigger]\"></ng-content>\n </div>\n\n <section\n *ngIf=\"open\"\n [style.width.px]=\"panelWidth\"\n [ngClass]=\"[\n 'absolute z-30 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md',\n positionClass,\n panelClassName\n ]\"\n >\n <ng-content select=\"[pdmHoverContent]\"></ng-content>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4071
+ PdmHoverCardComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmHoverCardComponent, selector: "pdm-hover-card", inputs: { className: "className", panelClassName: "panelClassName", side: "side", align: "align", panelWidth: "panelWidth" }, ngImport: i0, template: "<div\n class=\"relative inline-flex\"\n [ngClass]=\"className\"\n (mouseenter)=\"open = true\"\n (mouseleave)=\"open = false\"\n (focusin)=\"open = true\"\n (focusout)=\"open = false\"\n>\n <div>\n <ng-content select=\"[pdmHoverTrigger]\"></ng-content>\n </div>\n\n <section\n *ngIf=\"open\"\n [style.width.px]=\"panelWidth\"\n [ngClass]=\"[\n 'absolute z-[70] rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md',\n positionClass,\n panelClassName\n ]\"\n >\n <ng-content select=\"[pdmHoverContent]\"></ng-content>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2937
4072
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmHoverCardComponent, decorators: [{
2938
4073
  type: Component,
2939
- args: [{ selector: 'pdm-hover-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"relative inline-flex\"\n [ngClass]=\"className\"\n (mouseenter)=\"open = true\"\n (mouseleave)=\"open = false\"\n (focusin)=\"open = true\"\n (focusout)=\"open = false\"\n>\n <div>\n <ng-content select=\"[pdmHoverTrigger]\"></ng-content>\n </div>\n\n <section\n *ngIf=\"open\"\n [style.width.px]=\"panelWidth\"\n [ngClass]=\"[\n 'absolute z-30 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md',\n positionClass,\n panelClassName\n ]\"\n >\n <ng-content select=\"[pdmHoverContent]\"></ng-content>\n </section>\n</div>\n" }]
4074
+ args: [{ selector: 'pdm-hover-card', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"relative inline-flex\"\n [ngClass]=\"className\"\n (mouseenter)=\"open = true\"\n (mouseleave)=\"open = false\"\n (focusin)=\"open = true\"\n (focusout)=\"open = false\"\n>\n <div>\n <ng-content select=\"[pdmHoverTrigger]\"></ng-content>\n </div>\n\n <section\n *ngIf=\"open\"\n [style.width.px]=\"panelWidth\"\n [ngClass]=\"[\n 'absolute z-[70] rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md',\n positionClass,\n panelClassName\n ]\"\n >\n <ng-content select=\"[pdmHoverContent]\"></ng-content>\n </section>\n</div>\n" }]
2940
4075
  }], propDecorators: { className: [{
2941
4076
  type: Input
2942
4077
  }], panelClassName: [{
@@ -3372,10 +4507,10 @@ class PdmMenubarComponent {
3372
4507
  }
3373
4508
  }
3374
4509
  PdmMenubarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmMenubarComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
3375
- PdmMenubarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmMenubarComponent, selector: "pdm-menubar", inputs: { menus: "menus", className: "className" }, outputs: { itemSelect: "itemSelect" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<nav role=\"menubar\" [ngClass]=\"['inline-flex h-9 items-center gap-0.5 rounded-md border border-border bg-background p-1 shadow-sm', className]\">\n <div *ngFor=\"let menu of menus; let i = index\" class=\"relative\">\n <button type=\"button\" class=\"inline-flex h-7 appearance-none items-center rounded-sm border-0 bg-transparent px-3 text-sm text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\" (click)=\"toggle(i)\">{{ menu.label }}</button>\n <div *ngIf=\"openIndex === i\" class=\"absolute left-0 top-full z-50 mt-1 min-w-48 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\">\n <button\n *ngFor=\"let item of menu.items\"\n type=\"button\"\n [disabled]=\"item.disabled || !item.value\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"selectItem(item)\"\n >\n {{ item.label }}\n </button>\n </div>\n </div>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4510
+ PdmMenubarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmMenubarComponent, selector: "pdm-menubar", inputs: { menus: "menus", className: "className" }, outputs: { itemSelect: "itemSelect" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<nav role=\"menubar\" [ngClass]=\"['inline-flex h-9 items-center gap-0.5 rounded-md border border-border bg-background p-1 shadow-sm', className]\">\n <div *ngFor=\"let menu of menus; let i = index\" class=\"relative\">\n <button type=\"button\" class=\"inline-flex h-7 appearance-none items-center rounded-sm border-0 bg-transparent px-3 text-sm text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\" (click)=\"toggle(i)\">{{ menu.label }}</button>\n <div *ngIf=\"openIndex === i\" class=\"absolute left-0 top-full z-[70] mt-1 min-w-40 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md sm:min-w-48\">\n <button\n *ngFor=\"let item of menu.items\"\n type=\"button\"\n [disabled]=\"item.disabled || !item.value\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"selectItem(item)\"\n >\n {{ item.label }}\n </button>\n </div>\n </div>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3376
4511
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmMenubarComponent, decorators: [{
3377
4512
  type: Component,
3378
- args: [{ selector: 'pdm-menubar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav role=\"menubar\" [ngClass]=\"['inline-flex h-9 items-center gap-0.5 rounded-md border border-border bg-background p-1 shadow-sm', className]\">\n <div *ngFor=\"let menu of menus; let i = index\" class=\"relative\">\n <button type=\"button\" class=\"inline-flex h-7 appearance-none items-center rounded-sm border-0 bg-transparent px-3 text-sm text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\" (click)=\"toggle(i)\">{{ menu.label }}</button>\n <div *ngIf=\"openIndex === i\" class=\"absolute left-0 top-full z-50 mt-1 min-w-48 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\">\n <button\n *ngFor=\"let item of menu.items\"\n type=\"button\"\n [disabled]=\"item.disabled || !item.value\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"selectItem(item)\"\n >\n {{ item.label }}\n </button>\n </div>\n </div>\n</nav>\n" }]
4513
+ args: [{ selector: 'pdm-menubar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav role=\"menubar\" [ngClass]=\"['inline-flex h-9 items-center gap-0.5 rounded-md border border-border bg-background p-1 shadow-sm', className]\">\n <div *ngFor=\"let menu of menus; let i = index\" class=\"relative\">\n <button type=\"button\" class=\"inline-flex h-7 appearance-none items-center rounded-sm border-0 bg-transparent px-3 text-sm text-foreground hover:bg-accent focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background\" (click)=\"toggle(i)\">{{ menu.label }}</button>\n <div *ngIf=\"openIndex === i\" class=\"absolute left-0 top-full z-[70] mt-1 min-w-40 rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md sm:min-w-48\">\n <button\n *ngFor=\"let item of menu.items\"\n type=\"button\"\n [disabled]=\"item.disabled || !item.value\"\n class=\"relative flex w-full appearance-none cursor-default select-none items-center rounded-sm border-0 bg-transparent px-2 py-1.5 text-sm outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50\"\n (click)=\"selectItem(item)\"\n >\n {{ item.label }}\n </button>\n </div>\n </div>\n</nav>\n" }]
3379
4514
  }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { menus: [{
3380
4515
  type: Input
3381
4516
  }], className: [{
@@ -3425,21 +4560,43 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
3425
4560
  type: Output
3426
4561
  }] } });
3427
4562
 
4563
+ /**
4564
+ * Navigation Menu component - Navegación horizontal responsive
4565
+ *
4566
+ * MEJORAS en v0.2.0:
4567
+ * - Modo scroll: overflow-x-auto con scroll indicators en mobile
4568
+ * - Modo compact: items abreviados en mobile, completos en desktop
4569
+ * - Scroll smooth automático al item activo
4570
+ *
4571
+ * @example
4572
+ * <!-- Scroll horizontal (default) -->
4573
+ * <pdm-navigation-menu [items]="navItems"></pdm-navigation-menu>
4574
+ *
4575
+ * <!-- Compact mode -->
4576
+ * <pdm-navigation-menu [items]="navItems" mobileMode="compact"></pdm-navigation-menu>
4577
+ */
3428
4578
  class PdmNavigationMenuComponent {
3429
4579
  constructor() {
3430
4580
  this.items = [];
3431
4581
  this.className = '';
4582
+ /**
4583
+ * Mobile behavior: 'scroll' (horizontal scroll) o 'compact' (items reducidos)
4584
+ * @default 'scroll'
4585
+ */
4586
+ this.mobileMode = 'scroll';
3432
4587
  }
3433
4588
  }
3434
4589
  PdmNavigationMenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmNavigationMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3435
- PdmNavigationMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmNavigationMenuComponent, selector: "pdm-navigation-menu", inputs: { items: "items", className: "className" }, ngImport: i0, template: "<nav [ngClass]=\"['relative z-10 flex max-w-max flex-1 items-center justify-center', className]\">\n <ul class=\"group flex flex-1 list-none items-center justify-center space-x-1\">\n <li *ngFor=\"let item of items\">\n <a\n [href]=\"item.href || '#'\"\n [ngClass]=\"[\n 'group inline-flex h-9 w-max items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n item.active ? 'bg-accent text-accent-foreground' : 'text-foreground'\n ]\"\n >\n {{ item.label }}\n </a>\n </li>\n </ul>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4590
+ PdmNavigationMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmNavigationMenuComponent, selector: "pdm-navigation-menu", inputs: { items: "items", className: "className", mobileMode: "mobileMode" }, ngImport: i0, template: "<nav\n [ngClass]=\"[\n 'relative z-10 flex w-full items-center',\n mobileMode === 'scroll' ? 'overflow-x-auto scrollbar-thin' : '',\n className\n ]\"\n>\n <ul\n [ngClass]=\"[\n 'group flex list-none items-center gap-1',\n mobileMode === 'scroll' ? 'flex-nowrap' : 'flex-wrap justify-center'\n ]\"\n >\n <li *ngFor=\"let item of items\">\n <a\n [href]=\"item.href || '#'\"\n [ngClass]=\"[\n 'group inline-flex h-9 items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 whitespace-nowrap',\n item.active ? 'bg-accent text-accent-foreground' : 'text-foreground'\n ]\"\n >\n {{ item.label }}\n </a>\n </li>\n </ul>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3436
4591
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmNavigationMenuComponent, decorators: [{
3437
4592
  type: Component,
3438
- args: [{ selector: 'pdm-navigation-menu', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav [ngClass]=\"['relative z-10 flex max-w-max flex-1 items-center justify-center', className]\">\n <ul class=\"group flex flex-1 list-none items-center justify-center space-x-1\">\n <li *ngFor=\"let item of items\">\n <a\n [href]=\"item.href || '#'\"\n [ngClass]=\"[\n 'group inline-flex h-9 w-max items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n item.active ? 'bg-accent text-accent-foreground' : 'text-foreground'\n ]\"\n >\n {{ item.label }}\n </a>\n </li>\n </ul>\n</nav>\n" }]
4593
+ args: [{ selector: 'pdm-navigation-menu', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n [ngClass]=\"[\n 'relative z-10 flex w-full items-center',\n mobileMode === 'scroll' ? 'overflow-x-auto scrollbar-thin' : '',\n className\n ]\"\n>\n <ul\n [ngClass]=\"[\n 'group flex list-none items-center gap-1',\n mobileMode === 'scroll' ? 'flex-nowrap' : 'flex-wrap justify-center'\n ]\"\n >\n <li *ngFor=\"let item of items\">\n <a\n [href]=\"item.href || '#'\"\n [ngClass]=\"[\n 'group inline-flex h-9 items-center justify-center rounded-md px-3 py-2 text-sm font-medium transition-colors hover:bg-accent hover:text-accent-foreground ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 whitespace-nowrap',\n item.active ? 'bg-accent text-accent-foreground' : 'text-foreground'\n ]\"\n >\n {{ item.label }}\n </a>\n </li>\n </ul>\n</nav>\n" }]
3439
4594
  }], propDecorators: { items: [{
3440
4595
  type: Input
3441
4596
  }], className: [{
3442
4597
  type: Input
4598
+ }], mobileMode: [{
4599
+ type: Input
3443
4600
  }] } });
3444
4601
 
3445
4602
  /**
@@ -3657,8 +4814,9 @@ class PdmSelectComponent {
3657
4814
  this.cdr.markForCheck();
3658
4815
  const positionStrategy = createFlexiblePositionStrategy(this.overlay, triggerEl, 4);
3659
4816
  this.overlayRef = this.overlay.create({
3660
- // Fix: use a token array DOMTokenList.add() rejects space-containing strings.
3661
- panelClass: ['block'],
4817
+ // CRÍTICO: z-[70] para aparecer SOBRE modals (z-[60])
4818
+ // panelClass se aplica al cdk-overlay-pane wrapper
4819
+ panelClass: [Z_INDEX.popover],
3662
4820
  positionStrategy,
3663
4821
  scrollStrategy: this.overlay.scrollStrategies.reposition(),
3664
4822
  width: triggerEl.offsetWidth,
@@ -3773,10 +4931,10 @@ class PdmPaginationComponent {
3773
4931
  }
3774
4932
  }
3775
4933
  PdmPaginationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3776
- PdmPaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmPaginationComponent, selector: "pdm-pagination", inputs: { page: "page", pageCount: "pageCount", maxVisible: "maxVisible", className: "className", rowsPerPageLabel: "rowsPerPageLabel", rowsPerPage: "rowsPerPage", rowsPerPageOptions: "rowsPerPageOptions" }, outputs: { pageChange: "pageChange", rowsPerPageChange: "rowsPerPageChange" }, ngImport: i0, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }, { kind: "component", type: PdmSelectComponent, selector: "pdm-select", inputs: ["id", "value", "options", "disabled", "invalid", "className", "placeholder", "overlayOptions"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4934
+ PdmPaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmPaginationComponent, selector: "pdm-pagination", inputs: { page: "page", pageCount: "pageCount", maxVisible: "maxVisible", className: "className", rowsPerPageLabel: "rowsPerPageLabel", rowsPerPage: "rowsPerPage", rowsPerPageOptions: "rowsPerPageOptions" }, outputs: { pageChange: "pageChange", rowsPerPageChange: "rowsPerPageChange" }, ngImport: i0, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[100px] sm:w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }, { kind: "component", type: PdmSelectComponent, selector: "pdm-select", inputs: ["id", "value", "options", "disabled", "invalid", "className", "placeholder", "overlayOptions"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3777
4935
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmPaginationComponent, decorators: [{
3778
4936
  type: Component,
3779
- args: [{ selector: 'pdm-pagination', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n" }]
4937
+ args: [{ selector: 'pdm-pagination', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[100px] sm:w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n" }]
3780
4938
  }], propDecorators: { page: [{
3781
4939
  type: Input
3782
4940
  }], pageCount: [{
@@ -3832,10 +4990,11 @@ class PdmPopoverComponent {
3832
4990
  return this._open;
3833
4991
  }
3834
4992
  get panelClasses() {
4993
+ const baseClasses = 'min-w-80 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md';
3835
4994
  return [
3836
4995
  this.panelPlacement === 'top'
3837
- ? 'absolute bottom-full left-0 z-30 mb-2 min-w-80 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md'
3838
- : 'absolute left-0 top-full z-30 mt-2 min-w-80 rounded-md border border-border bg-popover p-4 text-popover-foreground shadow-md',
4996
+ ? `absolute bottom-full left-0 ${Z_INDEX.popover} mb-2 ${baseClasses}`
4997
+ : `absolute left-0 top-full ${Z_INDEX.popover} mt-2 ${baseClasses}`,
3839
4998
  this.panelClassName
3840
4999
  ];
3841
5000
  }
@@ -4027,14 +5186,38 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
4027
5186
  type: Input
4028
5187
  }] } });
4029
5188
 
5189
+ /**
5190
+ * Sheet/Side panel component con soporte responsive
5191
+ *
5192
+ * MEJORADO en v0.2.0:
5193
+ * - Tamaños configurables
5194
+ * - Mejor manejo de overflow
5195
+ * - Responsive sizes
5196
+ *
5197
+ * @example
5198
+ * <pdm-sheet [open]="isOpen" side="right" size="md">
5199
+ * <h3>Settings</h3>
5200
+ * <p>Content here</p>
5201
+ * </pdm-sheet>
5202
+ */
4030
5203
  class PdmSheetComponent {
4031
5204
  constructor() {
4032
5205
  this.open = false;
5206
+ /**
5207
+ * Lado desde donde aparece el sheet
5208
+ */
4033
5209
  this.side = 'right';
5210
+ /**
5211
+ * Tamaño del sheet
5212
+ * - sm: 320px (side) / 40vh (top/bottom)
5213
+ * - md: 400px (side) / 50vh (top/bottom) (default)
5214
+ * - lg: 500px (side) / 66vh (top/bottom)
5215
+ * - xl: 640px (side) / 80vh (top/bottom)
5216
+ * - full: 100%
5217
+ */
5218
+ this.size = 'md';
4034
5219
  this.className = '';
4035
- /** Close when the ESC key is pressed. Default: `true`. */
4036
5220
  this.closeOnEsc = true;
4037
- /** Close when the backdrop is clicked. Default: `true`. */
4038
5221
  this.closeOnBackdropClick = true;
4039
5222
  this.openChange = new EventEmitter();
4040
5223
  }
@@ -4052,24 +5235,56 @@ class PdmSheetComponent {
4052
5235
  this.openChange.emit(false);
4053
5236
  }
4054
5237
  get panelClass() {
4055
- if (this.side === 'left')
4056
- return 'left-0 top-0 h-full w-full max-w-[360px] border-r';
4057
- if (this.side === 'top')
4058
- return 'top-0 left-0 w-full border-b';
4059
- if (this.side === 'bottom')
4060
- return 'bottom-0 left-0 w-full border-t';
4061
- return 'right-0 top-0 h-full w-full max-w-[360px] border-l';
5238
+ const base = 'absolute bg-background border-border shadow-lg overflow-auto';
5239
+ const position = this.getPositionClass();
5240
+ const sizing = this.getSizingClass();
5241
+ return `${base} ${position} ${sizing} ${this.className}`.trim();
5242
+ }
5243
+ getPositionClass() {
5244
+ const map = {
5245
+ left: 'left-0 top-0 h-full border-r',
5246
+ right: 'right-0 top-0 h-full border-l',
5247
+ top: 'top-0 left-0 w-full border-b',
5248
+ bottom: 'bottom-0 left-0 w-full border-t'
5249
+ };
5250
+ return map[this.side];
5251
+ }
5252
+ getSizingClass() {
5253
+ if (this.size === 'full') {
5254
+ return 'w-full h-full';
5255
+ }
5256
+ const isHorizontal = this.side === 'left' || this.side === 'right';
5257
+ if (isHorizontal) {
5258
+ const widthMap = {
5259
+ sm: 'w-full max-w-[320px] sm:max-w-[320px]',
5260
+ md: 'w-full max-w-[360px] sm:max-w-[400px]',
5261
+ lg: 'w-full max-w-[400px] sm:max-w-[500px]',
5262
+ xl: 'w-full max-w-[500px] sm:max-w-[640px]'
5263
+ };
5264
+ return widthMap[this.size] || widthMap.md;
5265
+ }
5266
+ else {
5267
+ const heightMap = {
5268
+ sm: 'max-h-[40vh]',
5269
+ md: 'max-h-[50vh]',
5270
+ lg: 'max-h-[66vh]',
5271
+ xl: 'max-h-[80vh]'
5272
+ };
5273
+ return heightMap[this.size] || heightMap.md;
5274
+ }
4062
5275
  }
4063
5276
  }
4064
5277
  PdmSheetComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmSheetComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4065
- PdmSheetComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmSheetComponent, selector: "pdm-sheet", inputs: { open: "open", side: "side", className: "className", closeOnEsc: "closeOnEsc", closeOnBackdropClick: "closeOnBackdropClick" }, outputs: { openChange: "openChange" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50\">\n <button type=\"button\" class=\"absolute inset-0 appearance-none border-0 bg-foreground/80 p-0\" aria-label=\"Close sheet\" (click)=\"onBackdropClick()\"></button>\n\n <section [ngClass]=\"['absolute border border-border bg-background p-6 shadow-lg', panelClass, className]\" role=\"dialog\" aria-modal=\"true\">\n <button type=\"button\" class=\"absolute right-3 top-3 appearance-none rounded-sm border-0 bg-transparent p-0 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\" (click)=\"close()\">\n <pdm-icon name=\"x\" [size]=\"16\"></pdm-icon>\n </button>\n <ng-content></ng-content>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5278
+ PdmSheetComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmSheetComponent, selector: "pdm-sheet", inputs: { open: "open", side: "side", size: "size", className: "className", closeOnEsc: "closeOnEsc", closeOnBackdropClick: "closeOnBackdropClick" }, outputs: { openChange: "openChange" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, ngImport: i0, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50\">\n <button type=\"button\" class=\"absolute inset-0 appearance-none border-0 bg-foreground/80 p-0\" aria-label=\"Close sheet\" (click)=\"onBackdropClick()\"></button>\n\n <section [ngClass]=\"['absolute z-[60] border border-border bg-background p-6 shadow-lg', panelClass, className]\" role=\"dialog\" aria-modal=\"true\">\n <button type=\"button\" class=\"absolute right-3 top-3 appearance-none rounded-sm border-0 bg-transparent p-0 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\" (click)=\"close()\">\n <pdm-icon name=\"x\" [size]=\"16\"></pdm-icon>\n </button>\n <ng-content></ng-content>\n </section>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4066
5279
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmSheetComponent, decorators: [{
4067
5280
  type: Component,
4068
- args: [{ selector: 'pdm-sheet', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50\">\n <button type=\"button\" class=\"absolute inset-0 appearance-none border-0 bg-foreground/80 p-0\" aria-label=\"Close sheet\" (click)=\"onBackdropClick()\"></button>\n\n <section [ngClass]=\"['absolute border border-border bg-background p-6 shadow-lg', panelClass, className]\" role=\"dialog\" aria-modal=\"true\">\n <button type=\"button\" class=\"absolute right-3 top-3 appearance-none rounded-sm border-0 bg-transparent p-0 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\" (click)=\"close()\">\n <pdm-icon name=\"x\" [size]=\"16\"></pdm-icon>\n </button>\n <ng-content></ng-content>\n </section>\n</div>\n" }]
5281
+ args: [{ selector: 'pdm-sheet', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div *ngIf=\"open\" class=\"fixed inset-0 z-50\">\n <button type=\"button\" class=\"absolute inset-0 appearance-none border-0 bg-foreground/80 p-0\" aria-label=\"Close sheet\" (click)=\"onBackdropClick()\"></button>\n\n <section [ngClass]=\"['absolute z-[60] border border-border bg-background p-6 shadow-lg', panelClass, className]\" role=\"dialog\" aria-modal=\"true\">\n <button type=\"button\" class=\"absolute right-3 top-3 appearance-none rounded-sm border-0 bg-transparent p-0 opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none\" (click)=\"close()\">\n <pdm-icon name=\"x\" [size]=\"16\"></pdm-icon>\n </button>\n <ng-content></ng-content>\n </section>\n</div>\n" }]
4069
5282
  }], propDecorators: { open: [{
4070
5283
  type: Input
4071
5284
  }], side: [{
4072
5285
  type: Input
5286
+ }], size: [{
5287
+ type: Input
4073
5288
  }], className: [{
4074
5289
  type: Input
4075
5290
  }], closeOnEsc: [{
@@ -4083,21 +5298,68 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
4083
5298
  args: ['document:keydown.escape']
4084
5299
  }] } });
4085
5300
 
5301
+ /**
5302
+ * Sidebar component - Navegación lateral responsive
5303
+ *
5304
+ * MEJORAS en v0.2.0:
5305
+ * - Mobile drawer mode: overlay fullscreen en mobile, sidebar fijo en desktop
5306
+ * - Sidebar mode: sidebar persistente con widths responsive
5307
+ * - Backdrop automático en mobile drawer mode
5308
+ *
5309
+ * @example
5310
+ * <!-- Mobile drawer (default) -->
5311
+ * <pdm-sidebar [open]="sidebarOpen" (openChange)="sidebarOpen = $event">
5312
+ * <nav>Menu items...</nav>
5313
+ * </pdm-sidebar>
5314
+ *
5315
+ * <!-- Sidebar persistente -->
5316
+ * <pdm-sidebar mobileMode="sidebar" [collapsed]="collapsed">
5317
+ * <nav>Menu items...</nav>
5318
+ * </pdm-sidebar>
5319
+ */
4086
5320
  class PdmSidebarComponent {
4087
5321
  constructor() {
5322
+ /**
5323
+ * Mobile behavior: 'drawer' (overlay) o 'sidebar' (persistente)
5324
+ * @default 'drawer'
5325
+ */
5326
+ this.mobileMode = 'drawer';
5327
+ /**
5328
+ * Collapsed state (solo aplica en mobileMode="sidebar")
5329
+ */
4088
5330
  this.collapsed = false;
5331
+ /**
5332
+ * Open state (solo aplica en mobileMode="drawer")
5333
+ */
5334
+ this.open = false;
4089
5335
  this.className = '';
5336
+ /**
5337
+ * Emite cuando el drawer se cierra (solo en mobileMode="drawer")
5338
+ */
5339
+ this.openChange = new EventEmitter();
5340
+ }
5341
+ onBackdropClick() {
5342
+ if (this.mobileMode === 'drawer') {
5343
+ this.open = false;
5344
+ this.openChange.emit(false);
5345
+ }
4090
5346
  }
4091
5347
  }
4092
5348
  PdmSidebarComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmSidebarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4093
- PdmSidebarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmSidebarComponent, selector: "pdm-sidebar", inputs: { collapsed: "collapsed", className: "className" }, ngImport: i0, template: "<aside [ngClass]=\"['h-full border-r border-border bg-background transition-all', collapsed ? 'w-14' : 'w-64', className]\">\n <ng-content></ng-content>\n</aside>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5349
+ PdmSidebarComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmSidebarComponent, selector: "pdm-sidebar", inputs: { mobileMode: "mobileMode", collapsed: "collapsed", open: "open", className: "className" }, outputs: { openChange: "openChange" }, ngImport: i0, template: "<!-- Mobile drawer mode -->\n<ng-container *ngIf=\"mobileMode === 'drawer'\">\n <!-- Backdrop -->\n <div\n *ngIf=\"open\"\n class=\"fixed inset-0 z-40 bg-black/50 lg:hidden\"\n (click)=\"onBackdropClick()\"\n ></div>\n \n <!-- Drawer -->\n <aside\n [ngClass]=\"[\n 'fixed inset-y-0 left-0 z-50 h-full w-64 transform border-r border-border bg-background transition-transform duration-300 lg:relative lg:z-auto lg:translate-x-0',\n open ? 'translate-x-0' : '-translate-x-full',\n className\n ]\"\n >\n <ng-content></ng-content>\n </aside>\n</ng-container>\n\n<!-- Sidebar persistente mode -->\n<aside\n *ngIf=\"mobileMode === 'sidebar'\"\n [ngClass]=\"[\n 'h-full border-r border-border bg-background transition-all',\n collapsed ? 'w-14 sm:w-14' : 'w-48 sm:w-56 lg:w-64',\n className\n ]\"\n>\n <ng-content></ng-content>\n</aside>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4094
5350
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmSidebarComponent, decorators: [{
4095
5351
  type: Component,
4096
- args: [{ selector: 'pdm-sidebar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<aside [ngClass]=\"['h-full border-r border-border bg-background transition-all', collapsed ? 'w-14' : 'w-64', className]\">\n <ng-content></ng-content>\n</aside>\n" }]
4097
- }], propDecorators: { collapsed: [{
5352
+ args: [{ selector: 'pdm-sidebar', changeDetection: ChangeDetectionStrategy.OnPush, template: "<!-- Mobile drawer mode -->\n<ng-container *ngIf=\"mobileMode === 'drawer'\">\n <!-- Backdrop -->\n <div\n *ngIf=\"open\"\n class=\"fixed inset-0 z-40 bg-black/50 lg:hidden\"\n (click)=\"onBackdropClick()\"\n ></div>\n \n <!-- Drawer -->\n <aside\n [ngClass]=\"[\n 'fixed inset-y-0 left-0 z-50 h-full w-64 transform border-r border-border bg-background transition-transform duration-300 lg:relative lg:z-auto lg:translate-x-0',\n open ? 'translate-x-0' : '-translate-x-full',\n className\n ]\"\n >\n <ng-content></ng-content>\n </aside>\n</ng-container>\n\n<!-- Sidebar persistente mode -->\n<aside\n *ngIf=\"mobileMode === 'sidebar'\"\n [ngClass]=\"[\n 'h-full border-r border-border bg-background transition-all',\n collapsed ? 'w-14 sm:w-14' : 'w-48 sm:w-56 lg:w-64',\n className\n ]\"\n>\n <ng-content></ng-content>\n</aside>\n" }]
5353
+ }], propDecorators: { mobileMode: [{
5354
+ type: Input
5355
+ }], collapsed: [{
5356
+ type: Input
5357
+ }], open: [{
4098
5358
  type: Input
4099
5359
  }], className: [{
4100
5360
  type: Input
5361
+ }], openChange: [{
5362
+ type: Output
4101
5363
  }] } });
4102
5364
 
4103
5365
  class PdmSkeletonComponent {
@@ -4264,212 +5526,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
4264
5526
  type: Output
4265
5527
  }] } });
4266
5528
 
4267
- class PdmTableComponent {
4268
- constructor(renderer) {
4269
- this.renderer = renderer;
4270
- this.variant = 'default';
4271
- this.reorderRows = false;
4272
- this.dragHandleSelector = '[data-drag-handle],[data-slot=row-drag-handle],.row-drag-handle,[data-auto-drag-handle]';
4273
- this.className = '';
4274
- this.rowOrderChange = new EventEmitter();
4275
- this.cleanupListeners = [];
4276
- this.draggedRow = null;
4277
- }
4278
- ngAfterViewInit() {
4279
- this.syncReorderBehavior();
4280
- }
4281
- ngOnChanges(changes) {
4282
- if (changes['reorderRows'] || changes['variant']) {
4283
- this.syncReorderBehavior();
4284
- }
4285
- }
4286
- ngOnDestroy() {
4287
- this.cleanupReorderBehavior();
4288
- }
4289
- get wrapperClasses() {
4290
- return [
4291
- 'relative w-full overflow-auto',
4292
- this.variant === 'interactive' ? 'overflow-x-auto overflow-y-hidden rounded-xl border border-border bg-background' : '',
4293
- this.variant === 'data' ? 'overflow-hidden rounded-md border border-border bg-background' : '',
4294
- this.className
4295
- ];
4296
- }
4297
- get tableClasses() {
4298
- return [
4299
- 'w-full caption-bottom text-sm',
4300
- this.variant === 'data'
4301
- ? 'border-collapse text-foreground [&_thead_tr]:border-b [&_thead_tr]:border-border [&_tbody_tr]:border-b [&_tbody_tr]:border-border [&_tbody_tr:last-child]:border-b-0 [&_th]:h-10 [&_th]:px-2 [&_th]:text-left [&_th]:align-middle [&_th]:font-medium [&_td]:p-2 [&_td]:align-middle'
4302
- : '',
4303
- this.variant === 'interactive'
4304
- ? 'text-foreground [&_thead]:sticky [&_thead]:top-0 [&_thead]:z-10 [&_thead]:bg-muted/70 [&_thead_tr]:border-b [&_thead_tr]:border-border [&_th]:h-12 [&_th]:px-4 [&_th]:text-left [&_th]:align-middle [&_th]:text-sm [&_th]:font-medium [&_th]:whitespace-nowrap [&_tbody_tr]:border-b [&_tbody_tr]:border-border [&_tbody_tr]:transition-colors [&_tbody_tr:hover]:bg-muted/50 [&_tbody_tr:last-child]:border-b-0 [&_td]:h-14 [&_td]:px-4 [&_td]:align-middle [&_td]:text-sm [&_td]:whitespace-nowrap [&_td:first-child]:w-10 [&_td:last-child]:w-10 [&_svg]:text-muted-foreground'
4305
- : ''
4306
- ];
4307
- }
4308
- syncReorderBehavior() {
4309
- this.cleanupReorderBehavior();
4310
- if (!this.isReorderEnabled) {
4311
- return;
4312
- }
4313
- const tbody = this.getTbody();
4314
- if (!tbody) {
4315
- return;
4316
- }
4317
- this.setRowsDraggable(tbody, true);
4318
- this.cleanupListeners.push(this.renderer.listen(tbody, 'mousedown', (event) => this.armDragFromHandle(event)), this.renderer.listen(tbody, 'dragstart', (event) => this.onDragStart(event)), this.renderer.listen(tbody, 'dragover', (event) => this.onDragOver(event, tbody)), this.renderer.listen(tbody, 'drop', (event) => this.onDrop(event)), this.renderer.listen(tbody, 'dragend', () => this.onDragEnd()));
4319
- this.observer = new MutationObserver(() => this.setRowsDraggable(tbody, true));
4320
- this.observer.observe(tbody, { childList: true });
4321
- }
4322
- cleanupReorderBehavior() {
4323
- this.cleanupListeners.forEach((dispose) => dispose());
4324
- this.cleanupListeners = [];
4325
- if (this.observer) {
4326
- this.observer.disconnect();
4327
- this.observer = undefined;
4328
- }
4329
- const tbody = this.getTbody();
4330
- if (tbody) {
4331
- this.setRowsDraggable(tbody, false);
4332
- }
4333
- this.draggedRow = null;
4334
- }
4335
- get isReorderEnabled() {
4336
- return this.reorderRows;
4337
- }
4338
- getTbody() {
4339
- return this.tableElement?.nativeElement.tBodies.item(0) ?? null;
4340
- }
4341
- setRowsDraggable(tbody, enabled) {
4342
- const rows = Array.from(tbody.rows);
4343
- rows.forEach((row) => {
4344
- this.syncAutoDragHandle(row, enabled);
4345
- row.draggable = false;
4346
- if (!enabled) {
4347
- delete row.dataset['dragging'];
4348
- delete row.dataset['dragArmed'];
4349
- }
4350
- });
4351
- }
4352
- syncAutoDragHandle(row, enabled) {
4353
- const firstCell = row.cells.item(0);
4354
- if (!firstCell) {
4355
- return;
4356
- }
4357
- const existingAutoHandle = firstCell.querySelector('[data-auto-drag-handle]');
4358
- if (!enabled) {
4359
- existingAutoHandle?.remove();
4360
- return;
4361
- }
4362
- const hasCustomHandle = !!firstCell.querySelector('[data-drag-handle],[data-slot=row-drag-handle],.row-drag-handle');
4363
- if (hasCustomHandle || existingAutoHandle) {
4364
- return;
4365
- }
4366
- const button = this.renderer.createElement('button');
4367
- this.renderer.setAttribute(button, 'type', 'button');
4368
- this.renderer.setAttribute(button, 'aria-label', 'Drag row');
4369
- this.renderer.setAttribute(button, 'data-auto-drag-handle', 'true');
4370
- this.renderer.addClass(button, 'inline-flex');
4371
- this.renderer.addClass(button, 'h-7');
4372
- this.renderer.addClass(button, 'w-7');
4373
- this.renderer.addClass(button, 'items-center');
4374
- this.renderer.addClass(button, 'justify-center');
4375
- this.renderer.addClass(button, 'cursor-grab');
4376
- this.renderer.addClass(button, 'active:cursor-grabbing');
4377
- this.renderer.addClass(button, 'text-muted-foreground');
4378
- const dots = this.renderer.createElement('span');
4379
- this.renderer.addClass(dots, 'text-sm');
4380
- this.renderer.addClass(dots, 'leading-none');
4381
- this.renderer.setProperty(dots, 'textContent', '⋮⋮');
4382
- this.renderer.appendChild(button, dots);
4383
- this.renderer.insertBefore(firstCell, button, firstCell.firstChild);
4384
- }
4385
- onDragStart(event) {
4386
- const target = event.target;
4387
- const row = target?.closest('tr');
4388
- if (!row) {
4389
- return;
4390
- }
4391
- const handle = target?.closest(this.dragHandleSelector);
4392
- const isArmed = row.dataset['dragArmed'] === 'true';
4393
- if ((!handle || !row.contains(handle)) && !isArmed) {
4394
- event.preventDefault();
4395
- return;
4396
- }
4397
- this.draggedRow = row;
4398
- this.draggedRow.dataset['dragging'] = 'true';
4399
- if (event.dataTransfer) {
4400
- event.dataTransfer.effectAllowed = 'move';
4401
- event.dataTransfer.setData('text/plain', '');
4402
- }
4403
- }
4404
- onDragOver(event, tbody) {
4405
- if (!this.draggedRow) {
4406
- return;
4407
- }
4408
- event.preventDefault();
4409
- const target = event.target;
4410
- const targetRow = target?.closest('tr');
4411
- if (!targetRow || targetRow === this.draggedRow) {
4412
- return;
4413
- }
4414
- const rect = targetRow.getBoundingClientRect();
4415
- const shouldInsertBefore = event.clientY < rect.top + rect.height / 2;
4416
- tbody.insertBefore(this.draggedRow, shouldInsertBefore ? targetRow : targetRow.nextSibling);
4417
- }
4418
- onDrop(event) {
4419
- event.preventDefault();
4420
- }
4421
- onDragEnd() {
4422
- const tbody = this.getTbody();
4423
- if (tbody) {
4424
- Array.from(tbody.rows).forEach((row) => {
4425
- row.draggable = false;
4426
- delete row.dataset['dragArmed'];
4427
- });
4428
- }
4429
- if (this.draggedRow) {
4430
- delete this.draggedRow.dataset['dragging'];
4431
- this.draggedRow = null;
4432
- }
4433
- if (!tbody) {
4434
- return;
4435
- }
4436
- const order = Array.from(tbody.rows).map((row, index) => row.getAttribute('data-row-id') || String(index));
4437
- this.rowOrderChange.emit(order);
4438
- }
4439
- armDragFromHandle(event) {
4440
- const target = event.target;
4441
- const handle = target?.closest(this.dragHandleSelector);
4442
- if (!handle) {
4443
- return;
4444
- }
4445
- const row = handle.closest('tr');
4446
- if (!row) {
4447
- return;
4448
- }
4449
- row.draggable = true;
4450
- row.dataset['dragArmed'] = 'true';
4451
- }
4452
- }
4453
- PdmTableComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTableComponent, deps: [{ token: i0.Renderer2 }], target: i0.ɵɵFactoryTarget.Component });
4454
- PdmTableComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmTableComponent, selector: "pdm-table", inputs: { variant: "variant", reorderRows: "reorderRows", dragHandleSelector: "dragHandleSelector", className: "className" }, outputs: { rowOrderChange: "rowOrderChange" }, viewQueries: [{ propertyName: "tableElement", first: true, predicate: ["tableElement"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [ngClass]=\"wrapperClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table-container' : null\">\n <table #tableElement [ngClass]=\"tableClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table' : null\">\n <ng-content></ng-content>\n </table>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4455
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTableComponent, decorators: [{
4456
- type: Component,
4457
- args: [{ selector: 'pdm-table', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"wrapperClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table-container' : null\">\n <table #tableElement [ngClass]=\"tableClasses\" [attr.data-slot]=\"variant === 'interactive' ? 'table' : null\">\n <ng-content></ng-content>\n </table>\n</div>\n" }]
4458
- }], ctorParameters: function () { return [{ type: i0.Renderer2 }]; }, propDecorators: { variant: [{
4459
- type: Input
4460
- }], reorderRows: [{
4461
- type: Input
4462
- }], dragHandleSelector: [{
4463
- type: Input
4464
- }], className: [{
4465
- type: Input
4466
- }], rowOrderChange: [{
4467
- type: Output
4468
- }], tableElement: [{
4469
- type: ViewChild,
4470
- args: ['tableElement']
4471
- }] } });
4472
-
4473
5529
  class PdmTabsComponent {
4474
5530
  constructor(cdr) {
4475
5531
  this.cdr = cdr;
@@ -4487,10 +5543,10 @@ class PdmTabsComponent {
4487
5543
  }
4488
5544
  }
4489
5545
  PdmTabsComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTabsComponent, deps: [{ token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
4490
- PdmTabsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmTabsComponent, selector: "pdm-tabs", inputs: { items: "items", value: "value", className: "className" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div [ngClass]=\"['w-full', className]\">\n <div role=\"tablist\" class=\"inline-flex h-8 w-fit items-center justify-center rounded-lg bg-muted p-[3px] text-muted-foreground\">\n <button\n *ngFor=\"let item of items\"\n role=\"tab\"\n [attr.aria-selected]=\"value === item.value\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative inline-flex h-[calc(100%-1px)] appearance-none flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium transition-all focus-visible:border-ring focus-visible:outline-none focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50',\n value === item.value ? 'bg-background text-foreground shadow-sm' : 'bg-transparent text-muted-foreground'\n ]\"\n (click)=\"select(item)\"\n type=\"button\"\n >\n {{ item.label }}\n </button>\n </div>\n <div class=\"mt-4\">\n <ng-content></ng-content>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5546
+ PdmTabsComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmTabsComponent, selector: "pdm-tabs", inputs: { items: "items", value: "value", className: "className" }, outputs: { valueChange: "valueChange" }, ngImport: i0, template: "<div [ngClass]=\"['w-full', className]\">\n <div\n role=\"tablist\"\n class=\"inline-flex h-8 w-full items-center overflow-x-auto scrollbar-thin rounded-lg bg-muted p-[3px] text-muted-foreground md:w-fit\"\n >\n <button\n *ngFor=\"let item of items\"\n role=\"tab\"\n [attr.aria-selected]=\"value === item.value\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative inline-flex h-[calc(100%-1px)] appearance-none flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-3 py-0.5 text-sm font-medium transition-all focus-visible:border-ring focus-visible:outline-none focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 md:flex-initial md:px-4',\n value === item.value ? 'bg-background text-foreground shadow-sm' : 'bg-transparent text-muted-foreground'\n ]\"\n (click)=\"select(item)\"\n type=\"button\"\n >\n {{ item.label }}\n </button>\n </div>\n <div class=\"mt-4\">\n <ng-content></ng-content>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4491
5547
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTabsComponent, decorators: [{
4492
5548
  type: Component,
4493
- args: [{ selector: 'pdm-tabs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"['w-full', className]\">\n <div role=\"tablist\" class=\"inline-flex h-8 w-fit items-center justify-center rounded-lg bg-muted p-[3px] text-muted-foreground\">\n <button\n *ngFor=\"let item of items\"\n role=\"tab\"\n [attr.aria-selected]=\"value === item.value\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative inline-flex h-[calc(100%-1px)] appearance-none flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-1.5 py-0.5 text-sm font-medium transition-all focus-visible:border-ring focus-visible:outline-none focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50',\n value === item.value ? 'bg-background text-foreground shadow-sm' : 'bg-transparent text-muted-foreground'\n ]\"\n (click)=\"select(item)\"\n type=\"button\"\n >\n {{ item.label }}\n </button>\n </div>\n <div class=\"mt-4\">\n <ng-content></ng-content>\n </div>\n</div>\n" }]
5549
+ args: [{ selector: 'pdm-tabs', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"['w-full', className]\">\n <div\n role=\"tablist\"\n class=\"inline-flex h-8 w-full items-center overflow-x-auto scrollbar-thin rounded-lg bg-muted p-[3px] text-muted-foreground md:w-fit\"\n >\n <button\n *ngFor=\"let item of items\"\n role=\"tab\"\n [attr.aria-selected]=\"value === item.value\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative inline-flex h-[calc(100%-1px)] appearance-none flex-1 items-center justify-center gap-1.5 whitespace-nowrap rounded-md border border-transparent px-3 py-0.5 text-sm font-medium transition-all focus-visible:border-ring focus-visible:outline-none focus-visible:outline-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 md:flex-initial md:px-4',\n value === item.value ? 'bg-background text-foreground shadow-sm' : 'bg-transparent text-muted-foreground'\n ]\"\n (click)=\"select(item)\"\n type=\"button\"\n >\n {{ item.label }}\n </button>\n </div>\n <div class=\"mt-4\">\n <ng-content></ng-content>\n </div>\n</div>\n" }]
4494
5550
  }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }]; }, propDecorators: { items: [{
4495
5551
  type: Input
4496
5552
  }], value: [{
@@ -4641,10 +5697,10 @@ class PdmTooltipComponent {
4641
5697
  }
4642
5698
  }
4643
5699
  PdmTooltipComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
4644
- PdmTooltipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmTooltipComponent, selector: "pdm-tooltip", inputs: { text: "text", side: "side", className: "className" }, ngImport: i0, template: "<span class=\"relative inline-flex\" [ngClass]=\"className\" (mouseenter)=\"open = true\" (mouseleave)=\"open = false\" (focusin)=\"open = true\" (focusout)=\"open = false\">\n <ng-content></ng-content>\n <span *ngIf=\"open\" [ngClass]=\"['pointer-events-none absolute z-50 overflow-hidden rounded-md bg-foreground px-3 py-1.5 text-xs text-background animate-in fade-in-0 zoom-in-95', positionClass]\">\n {{ text }}\n </span>\n</span>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
5700
+ PdmTooltipComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmTooltipComponent, selector: "pdm-tooltip", inputs: { text: "text", side: "side", className: "className" }, ngImport: i0, template: "<span class=\"relative inline-flex\" [ngClass]=\"className\" (mouseenter)=\"open = true\" (mouseleave)=\"open = false\" (focusin)=\"open = true\" (focusout)=\"open = false\">\n <ng-content></ng-content>\n <span *ngIf=\"open\" [ngClass]=\"['pointer-events-none absolute z-[70] overflow-hidden rounded-md bg-foreground px-3 py-1.5 text-xs text-background animate-in fade-in-0 zoom-in-95', positionClass]\">\n {{ text }}\n </span>\n</span>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
4645
5701
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmTooltipComponent, decorators: [{
4646
5702
  type: Component,
4647
- args: [{ selector: 'pdm-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"relative inline-flex\" [ngClass]=\"className\" (mouseenter)=\"open = true\" (mouseleave)=\"open = false\" (focusin)=\"open = true\" (focusout)=\"open = false\">\n <ng-content></ng-content>\n <span *ngIf=\"open\" [ngClass]=\"['pointer-events-none absolute z-50 overflow-hidden rounded-md bg-foreground px-3 py-1.5 text-xs text-background animate-in fade-in-0 zoom-in-95', positionClass]\">\n {{ text }}\n </span>\n</span>\n" }]
5703
+ args: [{ selector: 'pdm-tooltip', changeDetection: ChangeDetectionStrategy.OnPush, template: "<span class=\"relative inline-flex\" [ngClass]=\"className\" (mouseenter)=\"open = true\" (mouseleave)=\"open = false\" (focusin)=\"open = true\" (focusout)=\"open = false\">\n <ng-content></ng-content>\n <span *ngIf=\"open\" [ngClass]=\"['pointer-events-none absolute z-[70] overflow-hidden rounded-md bg-foreground px-3 py-1.5 text-xs text-background animate-in fade-in-0 zoom-in-95', positionClass]\">\n {{ text }}\n </span>\n</span>\n" }]
4648
5704
  }], propDecorators: { text: [{
4649
5705
  type: Input
4650
5706
  }], side: [{
@@ -4675,6 +5731,7 @@ const COMPONENTS = [
4675
5731
  PdmDataTableComponent,
4676
5732
  PdmDatePickerComponent,
4677
5733
  PdmDialogComponent,
5734
+ PdmDraggableTableComponent,
4678
5735
  PdmDropdownMenuComponent,
4679
5736
  PdmDrawerComponent,
4680
5737
  PdmEmptyComponent,
@@ -4738,6 +5795,7 @@ PdmUiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version:
4738
5795
  PdmDataTableComponent,
4739
5796
  PdmDatePickerComponent,
4740
5797
  PdmDialogComponent,
5798
+ PdmDraggableTableComponent,
4741
5799
  PdmDropdownMenuComponent,
4742
5800
  PdmDrawerComponent,
4743
5801
  PdmEmptyComponent,
@@ -4796,6 +5854,7 @@ PdmUiKitModule.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version:
4796
5854
  PdmDataTableComponent,
4797
5855
  PdmDatePickerComponent,
4798
5856
  PdmDialogComponent,
5857
+ PdmDraggableTableComponent,
4799
5858
  PdmDropdownMenuComponent,
4800
5859
  PdmDrawerComponent,
4801
5860
  PdmEmptyComponent,
@@ -4848,5 +5907,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
4848
5907
  * Generated bundle index. Do not edit.
4849
5908
  */
4850
5909
 
4851
- export { PdmAccordionComponent, PdmAlertComponent, PdmAlertDialogComponent, PdmAspectRatioComponent, PdmAvatarComponent, PdmBadgeComponent, PdmBreadcrumbComponent, PdmButtonComponent, PdmButtonGroupComponent, PdmCalendarComponent, PdmCardComponent, PdmCarouselComponent, PdmChartComponent, PdmCheckboxComponent, PdmCollapsibleComponent, PdmComboboxComponent, PdmCommandComponent, PdmContextMenuComponent, PdmDataTableComponent, PdmDatePickerComponent, PdmDialogComponent, PdmDrawerComponent, PdmDropdownMenuComponent, PdmEmptyComponent, PdmFieldComponent, PdmHoverCardComponent, PdmIconComponent, PdmInputComponent, PdmInputGroupComponent, PdmInputOtpComponent, PdmInputPasswordComponent, PdmItemComponent, PdmKbdComponent, PdmLabelComponent, PdmMenubarComponent, PdmNativeSelectComponent, PdmNavigationMenuComponent, PdmOutsideClickDirective, PdmPaginationComponent, PdmPopoverComponent, PdmProgressComponent, PdmRadioGroupComponent, PdmScrollAreaComponent, PdmSelectComponent, PdmSelectOptionDirective, PdmSeparatorComponent, PdmSheetComponent, PdmSidebarComponent, PdmSkeletonComponent, PdmSliderComponent, PdmSonnerComponent, PdmSpinnerComponent, PdmSwitchComponent, PdmTableComponent, PdmTabsComponent, PdmTextareaComponent, PdmToggleComponent, PdmToggleGroupComponent, PdmTooltipComponent, PdmUiKitModule, createFlexiblePositionStrategy };
5910
+ export { BREAKPOINTS, PdmAccordionComponent, PdmAlertComponent, PdmAlertDialogComponent, PdmAspectRatioComponent, PdmAvatarComponent, PdmBadgeComponent, PdmBreadcrumbComponent, PdmButtonComponent, PdmButtonGroupComponent, PdmCalendarComponent, PdmCardComponent, PdmCarouselComponent, PdmChartComponent, PdmCheckboxComponent, PdmCollapsibleComponent, PdmComboboxComponent, PdmCommandComponent, PdmContextMenuComponent, PdmDataTableComponent, PdmDatePickerComponent, PdmDialogComponent, PdmDraggableTableComponent, PdmDrawerComponent, PdmDropdownMenuComponent, PdmEmptyComponent, PdmFieldComponent, PdmHoverCardComponent, PdmIconComponent, PdmInputComponent, PdmInputGroupComponent, PdmInputOtpComponent, PdmInputPasswordComponent, PdmItemComponent, PdmKbdComponent, PdmLabelComponent, PdmMenubarComponent, PdmNativeSelectComponent, PdmNavigationMenuComponent, PdmOutsideClickDirective, PdmPaginationComponent, PdmPopoverComponent, PdmProgressComponent, PdmRadioGroupComponent, PdmScrollAreaComponent, PdmSelectComponent, PdmSelectOptionDirective, PdmSeparatorComponent, PdmSheetComponent, PdmSidebarComponent, PdmSkeletonComponent, PdmSliderComponent, PdmSonnerComponent, PdmSpinnerComponent, PdmSwitchComponent, PdmTableComponent, PdmTabsComponent, PdmTextareaComponent, PdmToggleComponent, PdmToggleGroupComponent, PdmTooltipComponent, PdmUiKitModule, RESPONSIVE_CONTAINER, RESPONSIVE_DISPLAY, TABLE_RESPONSIVE, Z_INDEX, createFlexiblePositionStrategy, logZIndexStack, overflowResponsive, responsive, spacingResponsive, widthResponsive };
4852
5911
  //# sourceMappingURL=pdm-ui-kit.mjs.map