ng-prime-tools 1.1.6 → 1.1.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1460,24 +1460,22 @@ class PTAdvancedPrimeTableComponent {
1460
1460
  }
1461
1461
  const height = this.getCellHeight();
1462
1462
  if (height) {
1463
- styles['height'] = height;
1464
- styles['max-height'] = height;
1465
- styles['line-height'] = height;
1463
+ styles['min-height'] = height;
1466
1464
  }
1467
1465
  styles['padding'] = this.getColumnCellPadding(col);
1468
1466
  styles['box-sizing'] = 'border-box';
1467
+ styles['vertical-align'] = 'top';
1469
1468
  return styles;
1470
1469
  }
1471
1470
  getHeaderCellStyle(col) {
1472
1471
  const styles = {
1473
1472
  padding: this.getColumnCellPadding(col),
1474
1473
  boxSizing: 'border-box',
1474
+ verticalAlign: 'middle',
1475
1475
  };
1476
1476
  const height = this.getCellHeight();
1477
1477
  if (height) {
1478
- styles['height'] = height;
1479
- styles['max-height'] = height;
1480
- styles['line-height'] = height;
1478
+ styles['min-height'] = height;
1481
1479
  }
1482
1480
  return styles;
1483
1481
  }
@@ -1485,21 +1483,20 @@ class PTAdvancedPrimeTableComponent {
1485
1483
  const styles = {
1486
1484
  padding: this.cellPadding?.trim() || '0px',
1487
1485
  boxSizing: 'border-box',
1486
+ verticalAlign: 'top',
1488
1487
  };
1489
1488
  const height = this.getCellHeight();
1490
1489
  if (height) {
1491
- styles['height'] = height;
1492
- styles['max-height'] = height;
1493
- styles['line-height'] = height;
1490
+ styles['min-height'] = height;
1494
1491
  }
1495
1492
  return styles;
1496
1493
  }
1497
1494
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTAdvancedPrimeTableComponent, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
1498
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTAdvancedPrimeTableComponent, isStandalone: false, selector: "pt-advanced-prime-table", inputs: { data: "data", columns: "columns", totalRecords: "totalRecords", rowsPerPage: "rowsPerPage", hasSearchFilter: "hasSearchFilter", hasExportExcel: "hasExportExcel", hasExportPDF: "hasExportPDF", hasColumnFilter: "hasColumnFilter", cellPadding: "cellPadding", isPaginated: "isPaginated", isLazy: "isLazy", actions: "actions", isSortable: "isSortable", loading: "loading", maxHeight: "maxHeight", isRowReorderable: "isRowReorderable", showRowMoveArrows: "showRowMoveArrows", rowReorderIdField: "rowReorderIdField", rowOrderStartAt: "rowOrderStartAt", selectionDataKey: "selectionDataKey", selectionMode: "selectionMode", selection: "selection", cellHeight: "cellHeight" }, outputs: { selectionChange: "selectionChange", rowSelect: "rowSelect", rowUnselect: "rowUnselect", lazyLoad: "lazyLoad", search: "search", exportExcelEvent: "exportExcelEvent", exportPdfEvent: "exportPdfEvent", onPageChange: "onPageChange", onSortColumn: "onSortColumn", onFilterColumn: "onFilterColumn", rowReorderChange: "rowReorderChange", filteredData: "filteredData" }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }, { propertyName: "tableContainer", first: true, predicate: ["tableContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #tableContainer class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"tableData\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isLazy\"\n [filterDelay]=\"0\"\n [dataKey]=\"selectionDataKey || rowReorderIdField || 'id'\"\n [rowTrackBy]=\"rowTrackBy\"\n paginatorDropdownAppendTo=\"body\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n (onFilter)=\"filterColumn($event)\"\n [selectionMode]=\"selectionMode\"\n [(selection)]=\"selection\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (onRowSelect)=\"rowSelect.emit($event.data)\"\n (onRowUnselect)=\"rowUnselect.emit($event.data)\"\n >\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n @if (canUseRowReorder()) {\n <col [style.width]=\"getRowReorderColumnWidth()\" />\n }\n @for (col of columns; track col) {\n <col [style.width]=\"col.width || getHeaderWidth(col)\" />\n }\n </colgroup>\n </ng-template>\n\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n @if (hasSearchFilter) {\n <button\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n }\n @if (hasExportExcel) {\n <button\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n }\n @if (hasExportPDF) {\n <button\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n }\n </div>\n\n @if (hasSearchFilter) {\n <div class=\"ml-auto\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n @for (col of columns; track col) {\n @if (!col.children) {\n <th\n [pSortableColumn]=\"col.code\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n colspan=\"1\"\n >\n @if (isSortable && col.isSortable !== false) {\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getCellInnerStyle(col, '10px')\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon [field]=\"col.code\" />\n\n @if (hasColumnFilter && col.isFilter !== false) {\n @if (col.type === TableTypeEnum.COMPOSED) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"false\"\n [showOperator]=\"false\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n >\n @for (\n composedName of col.composedNames;\n track composedName\n ) {\n <div>\n @if (\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n ) {\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n filters[composedName]?.value ?? []\n \"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event\n );\n filter($event ?? [])\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n display=\"chip\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n @if (item.image) {\n <img\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n }\n\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n }\n </div>\n }\n </ng-template>\n </p-columnFilter>\n }\n @if (col.type !== TableTypeEnum.COMPOSED) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [showOperator]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [matchMode]=\"\n col.type === TableTypeEnum.MULTISELECT\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n @if (\n col.type === TableTypeEnum.NUMBER ||\n col.type === TableTypeEnum.AMOUNT;\n as value\n ) {\n <ng-template pTemplate=\"filter\" let-value>\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value\n \"\n (ngModelChange)=\"\n onNumberFilterChange(col.code!, $event)\n \"\n placeholder=\"Enter a number\"\n />\n </ng-template>\n }\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-datepicker\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event)\n \"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n ></p-datepicker>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value ?? []\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event ?? [])\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n }\n }\n </div>\n </div>\n } @else {\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getCellInnerStyle(col, '10px')\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n @if (hasColumnFilter && col.isFilter !== false) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n getColumnFilterType(col) !== 'multiSelect'\n \"\n [showOperator]=\"\n getColumnFilterType(col) !== 'multiSelect'\n \"\n [matchMode]=\"\n getColumnFilterType(col) === 'multiSelect'\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-value\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-datepicker\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event)\n \"\n dateFormat=\"dd/mm/yy\"\n ></p-datepicker>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-value\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value ?? []\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event ?? [])\n \"\n display=\"chip\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n }\n </div>\n }\n </th>\n } @else {\n <th\n [attr.colspan]=\"col?.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n }\n }\n </tr>\n\n @if (hasGroupedColumns) {\n <tr>\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n @for (col of columns; track col) {\n @if (col.children) {\n @for (child of col.children; track child) {\n <th\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngStyle]=\"getHeaderCellStyle(child)\"\n ></th>\n }\n }\n }\n </tr>\n }\n </ng-template>\n\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <td\n class=\"empty-message-cell\"\n [attr.colspan]=\"columns.length + (canUseRowReorder() ? 1 : 0)\"\n >\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-data let-editing=\"editing\">\n @if (!loading) {\n <tr\n [pEditableRow]=\"isEdit ? data : null\"\n [pSelectableRow]=\"selectionMode ? data : null\"\n [attr.data-row-reorder-target]=\"canUseRowReorder() ? 'true' : null\"\n >\n @if (canUseRowReorder()) {\n <td\n [style.width]=\"getRowReorderColumnWidth()\"\n [style.text-align]=\"'center'\"\n [ngStyle]=\"getStaticCellStyle()\"\n >\n <div\n style=\"\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.25rem;\n white-space: nowrap;\n \"\n >\n <span\n class=\"row-drag-handle\"\n (pointerdown)=\"onRowPointerDown($event, data)\"\n style=\"display: inline-flex; align-items: center\"\n title=\"D\u00E9placer la ligne\"\n >\n <i class=\"pi pi-bars\"></i>\n </span>\n\n @if (showRowMoveArrows) {\n <div\n style=\"display: inline-flex; flex-direction: column; gap: 0\"\n >\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-up\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Monter la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowUp(data)\"\n (click)=\"moveRowUp(data); $event.stopPropagation()\"\n ></button>\n\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-down\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Descendre la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowDown(data)\"\n (click)=\"moveRowDown(data); $event.stopPropagation()\"\n ></button>\n </div>\n }\n </div>\n </td>\n }\n @for (col of columns; track col) {\n @if (!col.children) {\n @if (isEditable(col.code!) && col.type !== TableTypeEnum.ACTION) {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isMultiSelect(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n @for (\n rec of getMultiSelectValues(data[col.code!]);\n track rec\n ) {\n <p-tag [value]=\"rec\"></p-tag>\n }\n </div>\n </ng-template>\n </p-cellEditor>\n } @else {\n @if (isDatePicker(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-datepicker\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-datepicker>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n } @else {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n @if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else {\n {{ data[col.code!] }}\n }\n </ng-template>\n </p-cellEditor>\n }\n }\n </div>\n </td>\n } @else {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n @if (col.type === TableTypeEnum.ACTION) {\n <div\n class=\"action-buttons-container\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isDelete) {\n <button\n pButton\n pRipple\n pTooltip=\"Supprimer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n @if (isEdit) {\n <div>\n @if (!editing) {\n <button\n pInitEditableRow\n pButton\n pRipple\n pTooltip=\"Modifier\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n @if (editing) {\n <button\n pSaveEditableRow\n pButton\n pRipple\n pTooltip=\"Enregistrer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n @if (editing) {\n <button\n pCancelEditableRow\n pButton\n pRipple\n pTooltip=\"Annuler\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n </div>\n }\n @for (act of customActions; track act) {\n @if (isActionVisible(act, data)) {\n <button\n pButton\n pRipple\n [pTooltip]=\"act.tooltip || ''\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n [disabled]=\"isActionDisabled(act, data)\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n }\n }\n </div>\n } @else {\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (col.type === TableTypeEnum.COMPOSED) {\n <div class=\"composed-cell\">\n @for (\n composedName of col.composedNames;\n track composedName;\n let i = $index\n ) {\n @if (\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n ) {\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getMergedComposedImageStyle(\n col,\n composedName,\n data\n )\n \"\n />\n }\n @if (\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n ) {\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getMergedComposedTextStyle(\n col,\n composedName,\n data\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n }\n }\n </div>\n } @else {\n @if (col.type === TableTypeEnum.PROGRESS) {\n <div class=\"progress-cell\">\n <p-progressBar\n [value]=\"getProgressValue(col, data)\"\n [showValue]=\"false\"\n [ngClass]=\"\n 'pt-progress-' + getProgressSeverity(col, data)\n \"\n ></p-progressBar>\n\n @if (isProgressShowValue(col)) {\n <span class=\"progress-cell-value\">\n {{ getProgressValue(col, data)\n }}{{ getProgressUnit(col) }}\n </span>\n }\n </div>\n } @else {\n @if (col.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(col, data)\"\n [severity]=\"$any(getTagSeverity(col, data))\"\n [icon]=\"getTagIcon(col, data)\"\n [rounded]=\"isTagRounded(col)\"\n ></p-tag>\n } @else {\n @if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else {\n @if (col.type === TableTypeEnum.NUMBER) {\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n } @else {\n @if (\n col.type === TableTypeEnum.DATE ||\n col.type === TableTypeEnum.DATETIME\n ) {\n @if (col.type === TableTypeEnum.DATE) {\n {{\n formatDateWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n }\n @if (col.type === TableTypeEnum.DATETIME) {\n {{\n formatDateTimeWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n }\n } @else {\n @if (\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT,\n ].includes(col.type!)\n ) {\n {{ data[col.code!] }}\n }\n }\n }\n }\n }\n }\n }\n </div>\n }\n </td>\n }\n } @else {\n @for (child of col.children; track child) {\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n [ngStyle]=\"getCellStyle(child, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(child)\"\n [ngStyle]=\"getCellInnerStyle(child)\"\n >\n @if (isEditable(child.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n } @else {\n @if (child.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(child, data)\"\n [severity]=\"$any(getTagSeverity(child, data))\"\n [icon]=\"getTagIcon(child, data)\"\n [rounded]=\"isTagRounded(child)\"\n ></p-tag>\n } @else {\n {{ child.code ? data[child.code] : \"\" }}\n }\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </ng-template>\n </p-table>\n</div>\n", styles: [":host{display:block;width:100%;min-width:0;max-width:100%;box-sizing:border-box}:host *,:host *:before,:host *:after{box-sizing:border-box}.pt-advanced-prime-table{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{display:grid;align-items:center;justify-items:start;width:100%;min-width:0;height:5rem}.pt-advanced-prime-table .filter-container{display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .settings{display:flex;align-items:center;gap:1rem;min-width:0}.pt-advanced-prime-table .multi-select-container{display:flex;align-items:center;gap:.3rem;min-width:0}.pt-advanced-prime-table .table-container{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep p-table{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper{display:block;width:100%;min-width:0;max-width:100%;overflow-x:auto!important;overflow-y:visible!important;overscroll-behavior-x:contain;scrollbar-gutter:stable;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{width:100%;min-width:var(--pt-advanced-table-min-width, 95rem);max-width:none;table-layout:auto;border-collapse:separate;border-spacing:0}.pt-advanced-prime-table ::ng-deep .p-datatable-header,.pt-advanced-prime-table ::ng-deep .p-datatable-caption{width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-caption>.flex,.pt-advanced-prime-table ::ng-deep .p-datatable-header>.flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;align-items:center;justify-content:space-between;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{flex:1 1 auto;min-width:0}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield{position:relative;display:inline-flex;align-items:center;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep p-inputicon,.pt-advanced-prime-table ::ng-deep .p-inputicon,.pt-advanced-prime-table ::ng-deep .p-input-icon{position:absolute;top:50%;left:.85rem;z-index:2;display:inline-flex;align-items:center;justify-content:center;margin:0;transform:translateY(-50%);pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-iconfield .p-inputtext{width:100%;max-width:100%;padding-left:2.5rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{margin-left:1rem;cursor:pointer}.pt-advanced-prime-table .table-row{display:flex;justify-content:center;gap:1rem;min-width:0;text-align:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{color:green;font-size:1.25em}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{color:red;font-size:1.25em}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:180px}.pt-advanced-prime-table .empty-message{color:#888;font-size:1.2rem;text-align:center}.pt-advanced-prime-table .empty-message i{display:block;margin-bottom:.5rem;font-size:2rem}.pt-advanced-prime-table th{white-space:normal;overflow-wrap:break-word}.pt-advanced-prime-table td{white-space:nowrap}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table .cell-inner-left,.pt-advanced-prime-table .cell-inner-center,.pt-advanced-prime-table .cell-inner-right{display:flex;align-items:center;width:100%;min-width:0}.pt-advanced-prime-table .cell-inner-left{justify-content:flex-start;text-align:left}.pt-advanced-prime-table .cell-inner-center{justify-content:center;text-align:center}.pt-advanced-prime-table .cell-inner-right{justify-content:flex-end;text-align:right}.pt-advanced-prime-table ::ng-deep .p-tag{padding:.2rem .55rem;font-size:.72rem;font-weight:800;line-height:1.2;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .p-tag .p-tag-icon{margin-right:.25rem}.pt-advanced-prime-table .progress-cell{display:flex;align-items:center;gap:.5rem;width:100%;min-width:160px}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar{flex:1 1 auto;width:100%;min-width:120px;height:.75rem!important;overflow:hidden;border-radius:999px;background:#e5e7eb!important}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar-value{display:block!important;height:100%!important;border-radius:999px}.pt-advanced-prime-table .progress-cell-value{min-width:38px;color:#334155;font-size:.72rem;font-weight:800;text-align:right}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{align-items:center;justify-content:center;padding:0;overflow:hidden;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .action-buttons-container{display:flex;align-items:center!important;justify-content:center!important;gap:.35rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{min-width:22px!important;height:22px!important;padding:.25rem!important}.pt-advanced-prime-table ::ng-deep .pt-progress-success .p-progressbar-value{background:#22c55e!important}.pt-advanced-prime-table ::ng-deep .pt-progress-warning .p-progressbar-value{background:#f59e0b!important}.pt-advanced-prime-table ::ng-deep .pt-progress-danger .p-progressbar-value{background:#ef4444!important}.pt-advanced-prime-table ::ng-deep .pt-progress-info .p-progressbar-value{background:#3b82f6!important}.pt-advanced-prime-table ::ng-deep .composed-cell{display:flex;align-items:center;gap:.5rem;min-width:0}.pt-advanced-prime-table ::ng-deep .composed-image{display:block;flex:0 0 auto;object-fit:contain}.pt-advanced-prime-table ::ng-deep .composed-text{min-width:0}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{transition:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging{cursor:grabbing!important;opacity:.55}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:5;box-shadow:inset 0 0 0 1px #3b82f673}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before:before{position:absolute;z-index:30;top:-2px;right:0;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after:after{position:absolute;z-index:30;right:0;bottom:-2px;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td{border-top:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{border-bottom:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-drag-handle{display:inline-flex;align-items:center;justify-content:center;width:2rem;min-width:2rem;height:2rem;border-radius:6px;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pt-advanced-prime-table ::ng-deep .row-drag-handle:hover{background:#3b82f61a}.pt-advanced-prime-table ::ng-deep .row-drag-handle:active{cursor:grabbing}.pt-advanced-prime-table ::ng-deep .row-drag-handle .pi{color:#64748b;font-size:.95rem}.pt-advanced-prime-table ::ng-deep td.row-reorder-column,.pt-advanced-prime-table ::ng-deep th.row-reorder-column{width:7rem;min-width:7rem;padding:.25rem .4rem!important;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .row-reorder-actions{display:inline-flex;align-items:center;justify-content:center;gap:.15rem;width:100%}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text{width:1.75rem!important;min-width:1.75rem!important;height:1.75rem!important;padding:0!important;border-radius:6px!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text .p-button-icon{font-size:.75rem}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:not(:disabled):hover{background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:disabled{cursor:not-allowed;opacity:.35}.pt-advanced-prime-table.dragging-active,.pt-advanced-prime-table.dragging-active *{-webkit-user-select:none!important;user-select:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:10}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-after>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar{width:10px;height:10px}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-track,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-track{border-radius:999px;background:var(--pt-advanced-table-scrollbar-track, #f1f5f9)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb{border:2px solid var(--pt-advanced-table-scrollbar-track, #f1f5f9);border-radius:999px;background:var(--pt-advanced-table-scrollbar-thumb, #94a3b8)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb:hover,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb:hover{background:var(--pt-advanced-table-scrollbar-thumb-hover, #64748b)}@media(max-width:768px){.pt-advanced-prime-table .filter-container,.pt-advanced-prime-table .flex{align-items:stretch;flex-direction:column}.pt-advanced-prime-table .settings{flex-wrap:wrap}.pt-advanced-prime-table .ml-auto{width:100%;margin-left:0}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield,.pt-advanced-prime-table ::ng-deep .p-inputtext{width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{min-width:var(--pt-advanced-table-mobile-min-width, 78rem)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i3.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i3.SelectableRow, selector: "[pSelectableRow]", inputs: ["pSelectableRow", "pSelectableRowIndex", "pSelectableRowDisabled"] }, { kind: "component", type: i3.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i3.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i3.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i3.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i3.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i3.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i3.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i7.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i10.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "directive", type: i12.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: i13.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "pipe", type: CustomCurrencyPipe, name: "customCurrency" }, { kind: "pipe", type: CustomDatePipe, name: "customDate" }] }); }
1495
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTAdvancedPrimeTableComponent, isStandalone: false, selector: "pt-advanced-prime-table", inputs: { data: "data", columns: "columns", totalRecords: "totalRecords", rowsPerPage: "rowsPerPage", hasSearchFilter: "hasSearchFilter", hasExportExcel: "hasExportExcel", hasExportPDF: "hasExportPDF", hasColumnFilter: "hasColumnFilter", cellPadding: "cellPadding", isPaginated: "isPaginated", isLazy: "isLazy", actions: "actions", isSortable: "isSortable", loading: "loading", maxHeight: "maxHeight", isRowReorderable: "isRowReorderable", showRowMoveArrows: "showRowMoveArrows", rowReorderIdField: "rowReorderIdField", rowOrderStartAt: "rowOrderStartAt", selectionDataKey: "selectionDataKey", selectionMode: "selectionMode", selection: "selection", cellHeight: "cellHeight" }, outputs: { selectionChange: "selectionChange", rowSelect: "rowSelect", rowUnselect: "rowUnselect", lazyLoad: "lazyLoad", search: "search", exportExcelEvent: "exportExcelEvent", exportPdfEvent: "exportPdfEvent", onPageChange: "onPageChange", onSortColumn: "onSortColumn", onFilterColumn: "onFilterColumn", rowReorderChange: "rowReorderChange", filteredData: "filteredData" }, viewQueries: [{ propertyName: "dt", first: true, predicate: ["dt"], descendants: true }, { propertyName: "tableContainer", first: true, predicate: ["tableContainer"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div #tableContainer class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"tableData\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isLazy\"\n [filterDelay]=\"0\"\n [dataKey]=\"selectionDataKey || rowReorderIdField || 'id'\"\n [rowTrackBy]=\"rowTrackBy\"\n paginatorDropdownAppendTo=\"body\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n [selectionMode]=\"selectionMode\"\n [(selection)]=\"selection\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n (onFilter)=\"filterColumn($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (onRowSelect)=\"rowSelect.emit($event.data)\"\n (onRowUnselect)=\"rowUnselect.emit($event.data)\"\n >\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n @if (canUseRowReorder()) {\n <col [style.width]=\"getRowReorderColumnWidth()\" />\n }\n\n @for (col of columns; track col) {\n <col [style.width]=\"col.width || getHeaderWidth(col)\" />\n }\n </colgroup>\n </ng-template>\n\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n @if (hasSearchFilter) {\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n title=\"Clear filters\"\n (click)=\"clear(dt)\"\n ></button>\n }\n\n @if (hasExportExcel) {\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n title=\"Export to Excel\"\n (click)=\"exportExcel()\"\n ></button>\n }\n\n @if (hasExportPDF) {\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n title=\"Export to PDF\"\n (click)=\"exportPdf()\"\n ></button>\n }\n </div>\n\n @if (hasSearchFilter) {\n <div class=\"ml-auto\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n placeholder=\"Search keyword\"\n (input)=\"filterGlobal($event)\"\n />\n </p-iconField>\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n\n @for (col of columns; track col) {\n @if (!col.children) {\n <th\n [pSortableColumn]=\"col.code\"\n [pSortableColumnDisabled]=\"\n !isSortable || col.isSortable === false\n \"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n colspan=\"1\"\n >\n <div class=\"header-container\" [ngStyle]=\"getCellInnerStyle(col)\">\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n @if (\n (isSortable && col.isSortable !== false) ||\n (hasColumnFilter && col.isFilter !== false)\n ) {\n <div class=\"icons\">\n @if (isSortable && col.isSortable !== false) {\n <p-sortIcon [field]=\"col.code\" />\n }\n\n @if (hasColumnFilter && col.isFilter !== false) {\n @if (col.type === TableTypeEnum.COMPOSED) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"false\"\n [showOperator]=\"false\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n >\n @for (\n composedName of col.composedNames;\n track composedName\n ) {\n @if (\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n ) {\n <div>\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n filters[composedName]?.value ?? []\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n display=\"chip\"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event\n );\n filter($event ?? [])\n \"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n @if (item.image) {\n <img\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n }\n\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </div>\n }\n }\n </ng-template>\n </p-columnFilter>\n } @else {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [showOperator]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [matchMode]=\"\n col.type === TableTypeEnum.MULTISELECT\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n @if (\n col.type === TableTypeEnum.NUMBER ||\n col.type === TableTypeEnum.AMOUNT\n ) {\n <ng-template pTemplate=\"filter\" let-value>\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value\n \"\n placeholder=\"Enter a number\"\n (ngModelChange)=\"\n onNumberFilterChange(col.code!, $event)\n \"\n />\n </ng-template>\n }\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-datepicker\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event)\n \"\n ></p-datepicker>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value ?? []\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event ?? [])\n \"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n }\n }\n </div>\n }\n </div>\n </th>\n } @else {\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n }\n }\n </tr>\n\n @if (hasGroupedColumns) {\n <tr>\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n\n @for (col of columns; track col) {\n @if (col.children) {\n @for (child of col.children; track child) {\n <th\n [pSortableColumn]=\"child.code\"\n [pSortableColumnDisabled]=\"\n !isSortable || child.isSortable === false\n \"\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngStyle]=\"getHeaderCellStyle(child)\"\n [ngClass]=\"getHeaderAlignClass(child)\"\n >\n <div\n class=\"header-container\"\n [ngStyle]=\"getCellInnerStyle(child)\"\n >\n <span [ngClass]=\"getHeaderTitleClass(child)\">\n {{ child.title }}\n </span>\n\n @if (\n (isSortable && child.isSortable !== false) ||\n (hasColumnFilter && child.isFilter !== false)\n ) {\n <div class=\"icons\">\n @if (isSortable && child.isSortable !== false) {\n <p-sortIcon [field]=\"child.code\" />\n }\n\n @if (hasColumnFilter && child.isFilter !== false) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"child.code\"\n [type]=\"getColumnFilterType(child)\"\n [currency]=\"getCurrencySymbol(child)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n child.type !== TableTypeEnum.MULTISELECT\n \"\n [showOperator]=\"\n child.type !== TableTypeEnum.MULTISELECT\n \"\n [matchMode]=\"\n child.type === TableTypeEnum.MULTISELECT\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(child.code!)\"\n ></p-columnFilter>\n }\n </div>\n }\n </div>\n </th>\n }\n }\n }\n </tr>\n }\n </ng-template>\n\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <td\n class=\"empty-message-cell\"\n [attr.colspan]=\"columns.length + (canUseRowReorder() ? 1 : 0)\"\n >\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-data let-editing=\"editing\">\n @if (!loading) {\n <tr\n [pEditableRow]=\"isEdit ? data : null\"\n [pSelectableRow]=\"selectionMode ? data : null\"\n [attr.data-row-reorder-target]=\"canUseRowReorder() ? 'true' : null\"\n >\n @if (canUseRowReorder()) {\n <td\n class=\"row-reorder-column\"\n [style.width]=\"getRowReorderColumnWidth()\"\n [style.text-align]=\"'center'\"\n [ngStyle]=\"getStaticCellStyle()\"\n >\n <div class=\"row-reorder-actions\">\n <span\n class=\"row-drag-handle\"\n title=\"D\u00E9placer la ligne\"\n (pointerdown)=\"onRowPointerDown($event, data)\"\n >\n <i class=\"pi pi-bars\"></i>\n </span>\n\n @if (showRowMoveArrows) {\n <div class=\"row-reorder-arrow-buttons\">\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-up\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Monter la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowUp(data)\"\n (click)=\"moveRowUp(data); $event.stopPropagation()\"\n ></button>\n\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-down\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Descendre la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowDown(data)\"\n (click)=\"moveRowDown(data); $event.stopPropagation()\"\n ></button>\n </div>\n }\n </div>\n </td>\n }\n\n @for (col of columns; track col) {\n @if (!col.children) {\n @if (isEditable(col.code!) && col.type !== TableTypeEnum.ACTION) {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isMultiSelect(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n [options]=\"optionValues\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n ></p-multiSelect>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n @for (\n rec of getMultiSelectValues(data[col.code!]);\n track rec\n ) {\n <p-tag [value]=\"rec\"></p-tag>\n }\n </div>\n </ng-template>\n </p-cellEditor>\n } @else if (isDatePicker(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-datepicker\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n [dateFormat]=\"'dd/mm/yy'\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n ></p-datepicker>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n } @else {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n @if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else {\n {{ data[col.code!] }}\n }\n </ng-template>\n </p-cellEditor>\n }\n </div>\n </td>\n } @else {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n @if (col.type === TableTypeEnum.ACTION) {\n <div\n class=\"action-buttons-container\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isDelete) {\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Supprimer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"Delete(data)\"\n ></button>\n }\n\n @if (isEdit) {\n <div>\n @if (!editing) {\n <button\n pInitEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Modifier\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"initEditableRow(data)\"\n ></button>\n }\n\n @if (editing) {\n <button\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Enregistrer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"saveEditableRow(data)\"\n ></button>\n\n <button\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Annuler\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"cancelEditableRow(data)\"\n ></button>\n }\n </div>\n }\n\n @for (act of customActions; track act) {\n @if (isActionVisible(act, data)) {\n <button\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n [disabled]=\"isActionDisabled(act, data)\"\n [pTooltip]=\"act.tooltip || ''\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n }\n }\n </div>\n } @else {\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (col.type === TableTypeEnum.COMPOSED) {\n <div class=\"composed-cell\">\n @for (\n composedName of col.composedNames;\n track composedName;\n let i = $index\n ) {\n @if (\n col.composedTypes?.[i] === TableTypeEnum.IMAGE\n ) {\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getMergedComposedImageStyle(\n col,\n composedName,\n data\n )\n \"\n />\n }\n\n @if (\n col.composedTypes?.[i] === TableTypeEnum.STRING\n ) {\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getMergedComposedTextStyle(\n col,\n composedName,\n data\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n }\n }\n </div>\n } @else if (col.type === TableTypeEnum.PROGRESS) {\n <div class=\"progress-cell\">\n <p-progressBar\n [value]=\"getProgressValue(col, data)\"\n [showValue]=\"false\"\n [ngClass]=\"\n 'pt-progress-' + getProgressSeverity(col, data)\n \"\n ></p-progressBar>\n\n @if (isProgressShowValue(col)) {\n <span class=\"progress-cell-value\">\n {{ getProgressValue(col, data)\n }}{{ getProgressUnit(col) }}\n </span>\n }\n </div>\n } @else if (col.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(col, data)\"\n [severity]=\"$any(getTagSeverity(col, data))\"\n [icon]=\"getTagIcon(col, data)\"\n [rounded]=\"isTagRounded(col)\"\n ></p-tag>\n } @else if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else if (col.type === TableTypeEnum.NUMBER) {\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n } @else if (col.type === TableTypeEnum.DATE) {\n {{\n formatDateWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n } @else if (col.type === TableTypeEnum.DATETIME) {\n {{\n formatDateTimeWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n } @else if (\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT,\n ].includes(col.type!)\n ) {\n {{ data[col.code!] }}\n }\n </div>\n }\n </td>\n }\n } @else {\n @for (child of col.children; track child) {\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n [ngStyle]=\"getCellStyle(child, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(child)\"\n [ngStyle]=\"getCellInnerStyle(child)\"\n >\n @if (isEditable(child.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n } @else if (child.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(child, data)\"\n [severity]=\"$any(getTagSeverity(child, data))\"\n [icon]=\"getTagIcon(child, data)\"\n [rounded]=\"isTagRounded(child)\"\n ></p-tag>\n } @else {\n {{ child.code ? data[child.code] : \"\" }}\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </ng-template>\n </p-table>\n</div>\n", styles: [":host{display:block;width:100%;min-width:0;max-width:100%;box-sizing:border-box}:host *,:host *:before,:host *:after{box-sizing:border-box}.pt-advanced-prime-table{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{display:grid;align-items:center;justify-items:start;width:100%;min-width:0;height:5rem}.pt-advanced-prime-table .filter-container{display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .settings{display:flex;align-items:center;gap:1rem;min-width:0}.pt-advanced-prime-table .multi-select-container{display:flex;align-items:center;gap:.3rem;min-width:0}.pt-advanced-prime-table .table-container{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep p-table{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper{display:block;width:100%;min-width:0;max-width:100%;overflow-x:auto!important;overflow-y:visible!important;overscroll-behavior-x:contain;scrollbar-gutter:stable;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{width:100%;min-width:var(--pt-advanced-table-min-width, 95rem);max-width:none;table-layout:fixed;border-collapse:separate;border-spacing:0}.pt-advanced-prime-table ::ng-deep .p-datatable-header,.pt-advanced-prime-table ::ng-deep .p-datatable-caption{width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-caption>.flex,.pt-advanced-prime-table ::ng-deep .p-datatable-header>.flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{position:relative;display:flex;align-items:center;gap:.25rem;width:100%!important;min-width:0;max-width:100%;margin:0!important;padding:0!important}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{display:block;flex:1 1 auto;width:auto;min-width:0;max-width:100%;padding:0;line-height:1.2;white-space:normal;overflow-wrap:break-word;word-break:normal}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-container>.icons{position:static!important;top:auto!important;right:auto!important;display:inline-flex;align-items:center;justify-content:flex-end;flex:0 0 auto;gap:.15rem;width:auto!important;min-width:1.5rem;max-width:none;margin-left:auto;padding:0;transform:none!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .header-container>.icons p-sorticon,.pt-advanced-prime-table ::ng-deep .header-container>.icons p-columnfilter{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;margin:0}.pt-advanced-prime-table ::ng-deep .header-container>p-columnfilter:last-child{position:static!important;top:auto!important;right:auto!important;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;margin:0 0 0 auto!important;transform:none!important}.pt-advanced-prime-table ::ng-deep .p-sortable-column-icon,.pt-advanced-prime-table ::ng-deep .p-column-filter-menu-button{flex:0 0 auto;margin:0!important}.pt-advanced-prime-table ::ng-deep .p-column-filter-menu-button{width:1.75rem;height:1.75rem;padding:0}.pt-advanced-prime-table ::ng-deep p-sorticon{width:1.25rem;min-width:1.25rem}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:0}.pt-advanced-prime-table .flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield{position:relative;display:inline-flex;align-items:center;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep p-inputicon,.pt-advanced-prime-table ::ng-deep .p-inputicon,.pt-advanced-prime-table ::ng-deep .p-input-icon{position:absolute;top:50%;left:.85rem;z-index:2;display:inline-flex;align-items:center;justify-content:center;margin:0;transform:translateY(-50%);pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-iconfield .p-inputtext{width:100%;max-width:100%;padding-left:2.5rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{margin-left:1rem;cursor:pointer}.pt-advanced-prime-table .table-row{display:flex;justify-content:center;gap:1rem;min-width:0;text-align:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{color:green;font-size:1.25em}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{color:red;font-size:1.25em}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:180px}.pt-advanced-prime-table .empty-message{color:#888;font-size:1.2rem;text-align:center}.pt-advanced-prime-table .empty-message i{display:block;margin-bottom:.5rem;font-size:2rem}.pt-advanced-prime-table th,.pt-advanced-prime-table td{min-width:0;overflow:hidden;white-space:normal;overflow-wrap:anywhere;word-break:break-word}.pt-advanced-prime-table ::ng-deep .p-datatable-thead>tr>th,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td{min-width:0;overflow:hidden;white-space:normal;overflow-wrap:anywhere;word-break:break-word}.pt-advanced-prime-table ::ng-deep .p-datatable-thead>tr>th{vertical-align:middle}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td{vertical-align:top}.pt-advanced-prime-table .cell-inner-left,.pt-advanced-prime-table .cell-inner-center,.pt-advanced-prime-table .cell-inner-right,.pt-advanced-prime-table ::ng-deep .composed-cell,.pt-advanced-prime-table ::ng-deep .composed-text{min-width:0;max-width:100%;white-space:normal;overflow-wrap:anywhere;word-break:break-word}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table .cell-inner-left,.pt-advanced-prime-table .cell-inner-center,.pt-advanced-prime-table .cell-inner-right{display:flex;align-items:flex-start;width:100%;min-width:0}.pt-advanced-prime-table .cell-inner-left{justify-content:flex-start;text-align:left}.pt-advanced-prime-table .cell-inner-center{justify-content:center;text-align:center}.pt-advanced-prime-table .cell-inner-right{justify-content:flex-end;text-align:right}.pt-advanced-prime-table ::ng-deep .p-tag{padding:.2rem .55rem;font-size:.72rem;font-weight:800;line-height:1.2;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .p-tag .p-tag-icon{margin-right:.25rem}.pt-advanced-prime-table .progress-cell{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar{flex:1 1 auto;width:100%;min-width:0;height:.75rem!important;overflow:hidden;border-radius:999px;background:#e5e7eb!important}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar-value{display:block!important;height:100%!important;border-radius:999px}.pt-advanced-prime-table .progress-cell-value{flex:0 0 auto;min-width:38px;color:#334155;font-size:.72rem;font-weight:800;text-align:right}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{align-items:center;justify-content:center;padding:0;overflow:hidden;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .action-buttons-container{display:flex;align-items:center!important;justify-content:center!important;flex-wrap:wrap;gap:.35rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{min-width:22px!important;height:22px!important;padding:.25rem!important}.pt-advanced-prime-table ::ng-deep .pt-progress-success .p-progressbar-value{background:#22c55e!important}.pt-advanced-prime-table ::ng-deep .pt-progress-warning .p-progressbar-value{background:#f59e0b!important}.pt-advanced-prime-table ::ng-deep .pt-progress-danger .p-progressbar-value{background:#ef4444!important}.pt-advanced-prime-table ::ng-deep .pt-progress-info .p-progressbar-value{background:#3b82f6!important}.pt-advanced-prime-table ::ng-deep .composed-cell{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .composed-image{display:block;flex:0 0 auto;object-fit:contain}.pt-advanced-prime-table ::ng-deep .composed-text{flex:1 1 auto;min-width:0}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{transition:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging{cursor:grabbing!important;opacity:.55}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:5;box-shadow:inset 0 0 0 1px #3b82f673}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before:before{position:absolute;z-index:30;top:-2px;right:0;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after:after{position:absolute;z-index:30;right:0;bottom:-2px;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td{border-top:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{border-bottom:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-drag-handle{display:inline-flex;align-items:center;justify-content:center;width:2rem;min-width:2rem;height:2rem;border-radius:6px;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pt-advanced-prime-table ::ng-deep .row-drag-handle:hover{background:#3b82f61a}.pt-advanced-prime-table ::ng-deep .row-drag-handle:active{cursor:grabbing}.pt-advanced-prime-table ::ng-deep .row-drag-handle .pi{color:#64748b;font-size:.95rem}.pt-advanced-prime-table ::ng-deep td.row-reorder-column,.pt-advanced-prime-table ::ng-deep th.row-reorder-column{width:7rem;min-width:7rem;padding:.25rem .4rem!important;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .row-reorder-actions{display:inline-flex;align-items:center;justify-content:center;gap:.15rem;width:100%}.pt-advanced-prime-table ::ng-deep .row-reorder-arrow-buttons{display:inline-flex;flex-direction:column;gap:0}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text{width:1.75rem!important;min-width:1.75rem!important;height:1.75rem!important;padding:0!important;border-radius:6px!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text .p-button-icon{font-size:.75rem}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:not(:disabled):hover{background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:disabled{cursor:not-allowed;opacity:.35}.pt-advanced-prime-table.dragging-active,.pt-advanced-prime-table.dragging-active *{-webkit-user-select:none!important;user-select:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:10}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-after>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar{width:10px;height:10px}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-track,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-track{border-radius:999px;background:var(--pt-advanced-table-scrollbar-track, #f1f5f9)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb{border:2px solid var(--pt-advanced-table-scrollbar-track, #f1f5f9);border-radius:999px;background:var(--pt-advanced-table-scrollbar-thumb, #94a3b8)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb:hover,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb:hover{background:var(--pt-advanced-table-scrollbar-thumb-hover, #64748b)}@media(max-width:768px){.pt-advanced-prime-table .filter-container,.pt-advanced-prime-table .flex{align-items:stretch;flex-direction:column}.pt-advanced-prime-table .settings{flex-wrap:wrap}.pt-advanced-prime-table .ml-auto{width:100%;margin-left:0}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield,.pt-advanced-prime-table ::ng-deep .p-inputtext{width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{min-width:var(--pt-advanced-table-mobile-min-width, 78rem)}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: i3.Table, selector: "p-table", inputs: ["frozenColumns", "frozenValue", "styleClass", "tableStyle", "tableStyleClass", "paginator", "pageLinks", "rowsPerPageOptions", "alwaysShowPaginator", "paginatorPosition", "paginatorStyleClass", "paginatorDropdownAppendTo", "paginatorDropdownScrollHeight", "currentPageReportTemplate", "showCurrentPageReport", "showJumpToPageDropdown", "showJumpToPageInput", "showFirstLastIcon", "showPageLinks", "defaultSortOrder", "sortMode", "resetPageOnSort", "selectionMode", "selectionPageOnly", "contextMenuSelection", "contextMenuSelectionMode", "dataKey", "metaKeySelection", "rowSelectable", "rowTrackBy", "lazy", "lazyLoadOnInit", "compareSelectionBy", "csvSeparator", "exportFilename", "filters", "globalFilterFields", "filterDelay", "filterLocale", "expandedRowKeys", "editingRowKeys", "rowExpandMode", "scrollable", "rowGroupMode", "scrollHeight", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "virtualScrollDelay", "frozenWidth", "contextMenu", "resizableColumns", "columnResizeMode", "reorderableColumns", "loading", "loadingIcon", "showLoader", "rowHover", "customSort", "showInitialSortBadge", "exportFunction", "exportHeader", "stateKey", "stateStorage", "editMode", "groupRowsBy", "size", "showGridlines", "stripedRows", "groupRowsByOrder", "responsiveLayout", "breakpoint", "paginatorLocale", "value", "columns", "first", "rows", "totalRecords", "sortField", "sortOrder", "multiSortMeta", "selection", "selectAll"], outputs: ["contextMenuSelectionChange", "selectAllChange", "selectionChange", "onRowSelect", "onRowUnselect", "onPage", "onSort", "onFilter", "onLazyLoad", "onRowExpand", "onRowCollapse", "onContextMenuSelect", "onColResize", "onColReorder", "onRowReorder", "onEditInit", "onEditComplete", "onEditCancel", "onHeaderCheckboxToggle", "sortFunction", "firstChange", "rowsChange", "onStateSave", "onStateRestore"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "directive", type: i3.SortableColumn, selector: "[pSortableColumn]", inputs: ["pSortableColumn", "pSortableColumnDisabled"] }, { kind: "directive", type: i3.SelectableRow, selector: "[pSelectableRow]", inputs: ["pSelectableRow", "pSelectableRowIndex", "pSelectableRowDisabled"] }, { kind: "component", type: i3.CellEditor, selector: "p-cellEditor" }, { kind: "component", type: i3.SortIcon, selector: "p-sortIcon", inputs: ["field"] }, { kind: "directive", type: i3.EditableRow, selector: "[pEditableRow]", inputs: ["pEditableRow", "pEditableRowDisabled"] }, { kind: "directive", type: i3.InitEditableRow, selector: "[pInitEditableRow]" }, { kind: "directive", type: i3.SaveEditableRow, selector: "[pSaveEditableRow]" }, { kind: "directive", type: i3.CancelEditableRow, selector: "[pCancelEditableRow]" }, { kind: "component", type: i3.ColumnFilter, selector: "p-columnFilter, p-column-filter, p-columnfilter", inputs: ["field", "type", "display", "showMenu", "matchMode", "operator", "showOperator", "showClearButton", "showApplyButton", "showMatchModes", "showAddButton", "hideOnClear", "placeholder", "matchModeOptions", "maxConstraints", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "locale", "localeMatcher", "currency", "currencyDisplay", "filterOn", "useGrouping", "showButtons", "ariaLabel", "filterButtonProps", "motionOptions"], outputs: ["onShow", "onHide"] }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: i7.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }, { kind: "component", type: i9.Tag, selector: "p-tag", inputs: ["styleClass", "severity", "value", "icon", "rounded"] }, { kind: "component", type: i10.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "directive", type: i12.Tooltip, selector: "[pTooltip]", inputs: ["tooltipPosition", "tooltipEvent", "positionStyle", "tooltipStyleClass", "tooltipZIndex", "escape", "showDelay", "hideDelay", "life", "positionTop", "positionLeft", "autoHide", "fitContent", "hideOnEscape", "showOnEllipsis", "pTooltip", "tooltipDisabled", "tooltipOptions", "appendTo", "ptTooltip", "pTooltipPT", "pTooltipUnstyled"] }, { kind: "component", type: i13.ProgressBar, selector: "p-progressBar, p-progressbar, p-progress-bar", inputs: ["value", "showValue", "styleClass", "valueStyleClass", "unit", "mode", "color"] }, { kind: "pipe", type: CustomCurrencyPipe, name: "customCurrency" }, { kind: "pipe", type: CustomDatePipe, name: "customDate" }] }); }
1499
1496
  }
1500
1497
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTAdvancedPrimeTableComponent, decorators: [{
1501
1498
  type: Component,
1502
- args: [{ selector: 'pt-advanced-prime-table', standalone: false, template: "<div #tableContainer class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"tableData\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isLazy\"\n [filterDelay]=\"0\"\n [dataKey]=\"selectionDataKey || rowReorderIdField || 'id'\"\n [rowTrackBy]=\"rowTrackBy\"\n paginatorDropdownAppendTo=\"body\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n (onFilter)=\"filterColumn($event)\"\n [selectionMode]=\"selectionMode\"\n [(selection)]=\"selection\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (onRowSelect)=\"rowSelect.emit($event.data)\"\n (onRowUnselect)=\"rowUnselect.emit($event.data)\"\n >\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n @if (canUseRowReorder()) {\n <col [style.width]=\"getRowReorderColumnWidth()\" />\n }\n @for (col of columns; track col) {\n <col [style.width]=\"col.width || getHeaderWidth(col)\" />\n }\n </colgroup>\n </ng-template>\n\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n @if (hasSearchFilter) {\n <button\n pButton\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"clear(dt)\"\n title=\"Clear filters\"\n ></button>\n }\n @if (hasExportExcel) {\n <button\n pButton\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportExcel()\"\n title=\"Export to Excel\"\n ></button>\n }\n @if (hasExportPDF) {\n <button\n pButton\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n (click)=\"exportPdf()\"\n title=\"Export to PDF\"\n ></button>\n }\n </div>\n\n @if (hasSearchFilter) {\n <div class=\"ml-auto\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n (input)=\"filterGlobal($event)\"\n placeholder=\"Search keyword\"\n />\n </p-iconField>\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n @for (col of columns; track col) {\n @if (!col.children) {\n <th\n [pSortableColumn]=\"col.code\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n colspan=\"1\"\n >\n @if (isSortable && col.isSortable !== false) {\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getCellInnerStyle(col, '10px')\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n <div\n class=\"icons d-flex align-items-center\"\n [style.width]=\"'77px'\"\n >\n <p-sortIcon [field]=\"col.code\" />\n\n @if (hasColumnFilter && col.isFilter !== false) {\n @if (col.type === TableTypeEnum.COMPOSED) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"false\"\n [showOperator]=\"false\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n >\n @for (\n composedName of col.composedNames;\n track composedName\n ) {\n <div>\n @if (\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n ) {\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n filters[composedName]?.value ?? []\n \"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event\n );\n filter($event ?? [])\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n display=\"chip\"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n @if (item.image) {\n <img\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n }\n\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n }\n </div>\n }\n </ng-template>\n </p-columnFilter>\n }\n @if (col.type !== TableTypeEnum.COMPOSED) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [showOperator]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [matchMode]=\"\n col.type === TableTypeEnum.MULTISELECT\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n @if (\n col.type === TableTypeEnum.NUMBER ||\n col.type === TableTypeEnum.AMOUNT;\n as value\n ) {\n <ng-template pTemplate=\"filter\" let-value>\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value\n \"\n (ngModelChange)=\"\n onNumberFilterChange(col.code!, $event)\n \"\n placeholder=\"Enter a number\"\n />\n </ng-template>\n }\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-datepicker\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event)\n \"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n ></p-datepicker>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value ?? []\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event ?? [])\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n }\n }\n </div>\n </div>\n } @else {\n <div\n class=\"header-container d-flex align-items-center justify-content-between\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getCellInnerStyle(col, '10px')\"\n >\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n @if (hasColumnFilter && col.isFilter !== false) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n getColumnFilterType(col) !== 'multiSelect'\n \"\n [showOperator]=\"\n getColumnFilterType(col) !== 'multiSelect'\n \"\n [matchMode]=\"\n getColumnFilterType(col) === 'multiSelect'\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-value\n *ngIf=\"getColumnFilterType(col) === 'date'\"\n >\n <p-datepicker\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event)\n \"\n dateFormat=\"dd/mm/yy\"\n ></p-datepicker>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n let-value\n *ngIf=\"getColumnFilterType(col) === 'multiSelect'\"\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value ?? []\n \"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event ?? [])\n \"\n display=\"chip\"\n placeholder=\"Select\"\n class=\"custom-multiselect\"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n }\n </div>\n }\n </th>\n } @else {\n <th\n [attr.colspan]=\"col?.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n }\n }\n </tr>\n\n @if (hasGroupedColumns) {\n <tr>\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n @for (col of columns; track col) {\n @if (col.children) {\n @for (child of col.children; track child) {\n <th\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngStyle]=\"getHeaderCellStyle(child)\"\n ></th>\n }\n }\n }\n </tr>\n }\n </ng-template>\n\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <td\n class=\"empty-message-cell\"\n [attr.colspan]=\"columns.length + (canUseRowReorder() ? 1 : 0)\"\n >\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-data let-editing=\"editing\">\n @if (!loading) {\n <tr\n [pEditableRow]=\"isEdit ? data : null\"\n [pSelectableRow]=\"selectionMode ? data : null\"\n [attr.data-row-reorder-target]=\"canUseRowReorder() ? 'true' : null\"\n >\n @if (canUseRowReorder()) {\n <td\n [style.width]=\"getRowReorderColumnWidth()\"\n [style.text-align]=\"'center'\"\n [ngStyle]=\"getStaticCellStyle()\"\n >\n <div\n style=\"\n display: inline-flex;\n align-items: center;\n justify-content: center;\n gap: 0.25rem;\n white-space: nowrap;\n \"\n >\n <span\n class=\"row-drag-handle\"\n (pointerdown)=\"onRowPointerDown($event, data)\"\n style=\"display: inline-flex; align-items: center\"\n title=\"D\u00E9placer la ligne\"\n >\n <i class=\"pi pi-bars\"></i>\n </span>\n\n @if (showRowMoveArrows) {\n <div\n style=\"display: inline-flex; flex-direction: column; gap: 0\"\n >\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-up\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Monter la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowUp(data)\"\n (click)=\"moveRowUp(data); $event.stopPropagation()\"\n ></button>\n\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-down\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Descendre la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowDown(data)\"\n (click)=\"moveRowDown(data); $event.stopPropagation()\"\n ></button>\n </div>\n }\n </div>\n </td>\n }\n @for (col of columns; track col) {\n @if (!col.children) {\n @if (isEditable(col.code!) && col.type !== TableTypeEnum.ACTION) {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isMultiSelect(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [options]=\"optionValues\"\n ></p-multiSelect>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n @for (\n rec of getMultiSelectValues(data[col.code!]);\n track rec\n ) {\n <p-tag [value]=\"rec\"></p-tag>\n }\n </div>\n </ng-template>\n </p-cellEditor>\n } @else {\n @if (isDatePicker(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-datepicker\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n [dateFormat]=\"'dd/mm/yy'\"\n ></p-datepicker>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n } @else {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n @if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else {\n {{ data[col.code!] }}\n }\n </ng-template>\n </p-cellEditor>\n }\n }\n </div>\n </td>\n } @else {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n @if (col.type === TableTypeEnum.ACTION) {\n <div\n class=\"action-buttons-container\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isDelete) {\n <button\n pButton\n pRipple\n pTooltip=\"Supprimer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-trash\"\n (click)=\"Delete(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n @if (isEdit) {\n <div>\n @if (!editing) {\n <button\n pInitEditableRow\n pButton\n pRipple\n pTooltip=\"Modifier\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-pencil\"\n (click)=\"initEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n @if (editing) {\n <button\n pSaveEditableRow\n pButton\n pRipple\n pTooltip=\"Enregistrer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-check\"\n (click)=\"saveEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n @if (editing) {\n <button\n pCancelEditableRow\n pButton\n pRipple\n pTooltip=\"Annuler\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n icon=\"pi pi-times\"\n (click)=\"cancelEditableRow(data)\"\n class=\"p-button-rounded p-button-text\"\n ></button>\n }\n </div>\n }\n @for (act of customActions; track act) {\n @if (isActionVisible(act, data)) {\n <button\n pButton\n pRipple\n [pTooltip]=\"act.tooltip || ''\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n [disabled]=\"isActionDisabled(act, data)\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n }\n }\n </div>\n } @else {\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (col.type === TableTypeEnum.COMPOSED) {\n <div class=\"composed-cell\">\n @for (\n composedName of col.composedNames;\n track composedName;\n let i = $index\n ) {\n @if (\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.IMAGE\n ) {\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getMergedComposedImageStyle(\n col,\n composedName,\n data\n )\n \"\n />\n }\n @if (\n col.composedTypes &&\n col.composedTypes[i] === TableTypeEnum.STRING\n ) {\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getMergedComposedTextStyle(\n col,\n composedName,\n data\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n }\n }\n </div>\n } @else {\n @if (col.type === TableTypeEnum.PROGRESS) {\n <div class=\"progress-cell\">\n <p-progressBar\n [value]=\"getProgressValue(col, data)\"\n [showValue]=\"false\"\n [ngClass]=\"\n 'pt-progress-' + getProgressSeverity(col, data)\n \"\n ></p-progressBar>\n\n @if (isProgressShowValue(col)) {\n <span class=\"progress-cell-value\">\n {{ getProgressValue(col, data)\n }}{{ getProgressUnit(col) }}\n </span>\n }\n </div>\n } @else {\n @if (col.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(col, data)\"\n [severity]=\"$any(getTagSeverity(col, data))\"\n [icon]=\"getTagIcon(col, data)\"\n [rounded]=\"isTagRounded(col)\"\n ></p-tag>\n } @else {\n @if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else {\n @if (col.type === TableTypeEnum.NUMBER) {\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n } @else {\n @if (\n col.type === TableTypeEnum.DATE ||\n col.type === TableTypeEnum.DATETIME\n ) {\n @if (col.type === TableTypeEnum.DATE) {\n {{\n formatDateWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n }\n @if (col.type === TableTypeEnum.DATETIME) {\n {{\n formatDateTimeWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n }\n } @else {\n @if (\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT,\n ].includes(col.type!)\n ) {\n {{ data[col.code!] }}\n }\n }\n }\n }\n }\n }\n }\n </div>\n }\n </td>\n }\n } @else {\n @for (child of col.children; track child) {\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n [ngStyle]=\"getCellStyle(child, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(child)\"\n [ngStyle]=\"getCellInnerStyle(child)\"\n >\n @if (isEditable(child.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n } @else {\n @if (child.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(child, data)\"\n [severity]=\"$any(getTagSeverity(child, data))\"\n [icon]=\"getTagIcon(child, data)\"\n [rounded]=\"isTagRounded(child)\"\n ></p-tag>\n } @else {\n {{ child.code ? data[child.code] : \"\" }}\n }\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </ng-template>\n </p-table>\n</div>\n", styles: [":host{display:block;width:100%;min-width:0;max-width:100%;box-sizing:border-box}:host *,:host *:before,:host *:after{box-sizing:border-box}.pt-advanced-prime-table{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{display:grid;align-items:center;justify-items:start;width:100%;min-width:0;height:5rem}.pt-advanced-prime-table .filter-container{display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .settings{display:flex;align-items:center;gap:1rem;min-width:0}.pt-advanced-prime-table .multi-select-container{display:flex;align-items:center;gap:.3rem;min-width:0}.pt-advanced-prime-table .table-container{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep p-table{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper{display:block;width:100%;min-width:0;max-width:100%;overflow-x:auto!important;overflow-y:visible!important;overscroll-behavior-x:contain;scrollbar-gutter:stable;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{width:100%;min-width:var(--pt-advanced-table-min-width, 95rem);max-width:none;table-layout:auto;border-collapse:separate;border-spacing:0}.pt-advanced-prime-table ::ng-deep .p-datatable-header,.pt-advanced-prime-table ::ng-deep .p-datatable-caption{width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-caption>.flex,.pt-advanced-prime-table ::ng-deep .p-datatable-header>.flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{display:flex;align-items:center;justify-content:space-between;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{flex:1 1 auto;min-width:0}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:4px}.pt-advanced-prime-table .flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield{position:relative;display:inline-flex;align-items:center;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep p-inputicon,.pt-advanced-prime-table ::ng-deep .p-inputicon,.pt-advanced-prime-table ::ng-deep .p-input-icon{position:absolute;top:50%;left:.85rem;z-index:2;display:inline-flex;align-items:center;justify-content:center;margin:0;transform:translateY(-50%);pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-iconfield .p-inputtext{width:100%;max-width:100%;padding-left:2.5rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{margin-left:1rem;cursor:pointer}.pt-advanced-prime-table .table-row{display:flex;justify-content:center;gap:1rem;min-width:0;text-align:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{color:green;font-size:1.25em}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{color:red;font-size:1.25em}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:180px}.pt-advanced-prime-table .empty-message{color:#888;font-size:1.2rem;text-align:center}.pt-advanced-prime-table .empty-message i{display:block;margin-bottom:.5rem;font-size:2rem}.pt-advanced-prime-table th{white-space:normal;overflow-wrap:break-word}.pt-advanced-prime-table td{white-space:nowrap}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table .cell-inner-left,.pt-advanced-prime-table .cell-inner-center,.pt-advanced-prime-table .cell-inner-right{display:flex;align-items:center;width:100%;min-width:0}.pt-advanced-prime-table .cell-inner-left{justify-content:flex-start;text-align:left}.pt-advanced-prime-table .cell-inner-center{justify-content:center;text-align:center}.pt-advanced-prime-table .cell-inner-right{justify-content:flex-end;text-align:right}.pt-advanced-prime-table ::ng-deep .p-tag{padding:.2rem .55rem;font-size:.72rem;font-weight:800;line-height:1.2;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .p-tag .p-tag-icon{margin-right:.25rem}.pt-advanced-prime-table .progress-cell{display:flex;align-items:center;gap:.5rem;width:100%;min-width:160px}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar{flex:1 1 auto;width:100%;min-width:120px;height:.75rem!important;overflow:hidden;border-radius:999px;background:#e5e7eb!important}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar-value{display:block!important;height:100%!important;border-radius:999px}.pt-advanced-prime-table .progress-cell-value{min-width:38px;color:#334155;font-size:.72rem;font-weight:800;text-align:right}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{align-items:center;justify-content:center;padding:0;overflow:hidden;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .action-buttons-container{display:flex;align-items:center!important;justify-content:center!important;gap:.35rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{min-width:22px!important;height:22px!important;padding:.25rem!important}.pt-advanced-prime-table ::ng-deep .pt-progress-success .p-progressbar-value{background:#22c55e!important}.pt-advanced-prime-table ::ng-deep .pt-progress-warning .p-progressbar-value{background:#f59e0b!important}.pt-advanced-prime-table ::ng-deep .pt-progress-danger .p-progressbar-value{background:#ef4444!important}.pt-advanced-prime-table ::ng-deep .pt-progress-info .p-progressbar-value{background:#3b82f6!important}.pt-advanced-prime-table ::ng-deep .composed-cell{display:flex;align-items:center;gap:.5rem;min-width:0}.pt-advanced-prime-table ::ng-deep .composed-image{display:block;flex:0 0 auto;object-fit:contain}.pt-advanced-prime-table ::ng-deep .composed-text{min-width:0}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{transition:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging{cursor:grabbing!important;opacity:.55}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:5;box-shadow:inset 0 0 0 1px #3b82f673}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before:before{position:absolute;z-index:30;top:-2px;right:0;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after:after{position:absolute;z-index:30;right:0;bottom:-2px;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td{border-top:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{border-bottom:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-drag-handle{display:inline-flex;align-items:center;justify-content:center;width:2rem;min-width:2rem;height:2rem;border-radius:6px;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pt-advanced-prime-table ::ng-deep .row-drag-handle:hover{background:#3b82f61a}.pt-advanced-prime-table ::ng-deep .row-drag-handle:active{cursor:grabbing}.pt-advanced-prime-table ::ng-deep .row-drag-handle .pi{color:#64748b;font-size:.95rem}.pt-advanced-prime-table ::ng-deep td.row-reorder-column,.pt-advanced-prime-table ::ng-deep th.row-reorder-column{width:7rem;min-width:7rem;padding:.25rem .4rem!important;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .row-reorder-actions{display:inline-flex;align-items:center;justify-content:center;gap:.15rem;width:100%}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text{width:1.75rem!important;min-width:1.75rem!important;height:1.75rem!important;padding:0!important;border-radius:6px!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text .p-button-icon{font-size:.75rem}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:not(:disabled):hover{background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:disabled{cursor:not-allowed;opacity:.35}.pt-advanced-prime-table.dragging-active,.pt-advanced-prime-table.dragging-active *{-webkit-user-select:none!important;user-select:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:10}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-after>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar{width:10px;height:10px}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-track,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-track{border-radius:999px;background:var(--pt-advanced-table-scrollbar-track, #f1f5f9)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb{border:2px solid var(--pt-advanced-table-scrollbar-track, #f1f5f9);border-radius:999px;background:var(--pt-advanced-table-scrollbar-thumb, #94a3b8)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb:hover,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb:hover{background:var(--pt-advanced-table-scrollbar-thumb-hover, #64748b)}@media(max-width:768px){.pt-advanced-prime-table .filter-container,.pt-advanced-prime-table .flex{align-items:stretch;flex-direction:column}.pt-advanced-prime-table .settings{flex-wrap:wrap}.pt-advanced-prime-table .ml-auto{width:100%;margin-left:0}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield,.pt-advanced-prime-table ::ng-deep .p-inputtext{width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{min-width:var(--pt-advanced-table-mobile-min-width, 78rem)}}\n"] }]
1499
+ args: [{ selector: 'pt-advanced-prime-table', standalone: false, template: "<div #tableContainer class=\"pt-advanced-prime-table table-container\">\n <p-table\n #dt\n [value]=\"tableData\"\n [loading]=\"loading\"\n [rows]=\"rows\"\n [paginator]=\"isPaginated\"\n [globalFilterFields]=\"globalFilterFields\"\n [rowsPerPageOptions]=\"rowsPerPage\"\n [totalRecords]=\"totalRecords\"\n [lazy]=\"isLazy\"\n [filterDelay]=\"0\"\n [dataKey]=\"selectionDataKey || rowReorderIdField || 'id'\"\n [rowTrackBy]=\"rowTrackBy\"\n paginatorDropdownAppendTo=\"body\"\n styleClass=\"p-datatable-gridlines p-datatable-striped\"\n [scrollable]=\"true\"\n [scrollHeight]=\"maxHeight !== null ? maxHeight : undefined\"\n [selectionMode]=\"selectionMode\"\n [(selection)]=\"selection\"\n (onPage)=\"changePage($event)\"\n (onSort)=\"sortColumn($event)\"\n (onFilter)=\"filterColumn($event)\"\n (selectionChange)=\"selectionChange.emit($event)\"\n (onRowSelect)=\"rowSelect.emit($event.data)\"\n (onRowUnselect)=\"rowUnselect.emit($event.data)\"\n >\n <ng-template pTemplate=\"colgroup\" let-columns>\n <colgroup>\n @if (canUseRowReorder()) {\n <col [style.width]=\"getRowReorderColumnWidth()\" />\n }\n\n @for (col of columns; track col) {\n <col [style.width]=\"col.width || getHeaderWidth(col)\" />\n }\n </colgroup>\n </ng-template>\n\n <ng-template pTemplate=\"caption\">\n <div class=\"flex\">\n <div>\n <h3>Total: {{ totalRecords }}</h3>\n </div>\n\n <div>\n @if (hasSearchFilter) {\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-filter-slash\"\n class=\"p-button-rounded p-button-text\"\n title=\"Clear filters\"\n (click)=\"clear(dt)\"\n ></button>\n }\n\n @if (hasExportExcel) {\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-file-excel\"\n class=\"p-button-rounded p-button-text\"\n title=\"Export to Excel\"\n (click)=\"exportExcel()\"\n ></button>\n }\n\n @if (hasExportPDF) {\n <button\n pButton\n type=\"button\"\n icon=\"pi pi-file-pdf\"\n class=\"p-button-rounded p-button-text\"\n title=\"Export to PDF\"\n (click)=\"exportPdf()\"\n ></button>\n }\n </div>\n\n @if (hasSearchFilter) {\n <div class=\"ml-auto\">\n <p-iconField iconPosition=\"left\" class=\"ml-auto\">\n <p-inputIcon>\n <i class=\"pi pi-search\"></i>\n </p-inputIcon>\n\n <input\n pInputText\n type=\"text\"\n [(ngModel)]=\"searchValue\"\n placeholder=\"Search keyword\"\n (input)=\"filterGlobal($event)\"\n />\n </p-iconField>\n </div>\n }\n </div>\n </ng-template>\n\n <ng-template pTemplate=\"header\">\n <tr class=\"sticky-header\">\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n\n @for (col of columns; track col) {\n @if (!col.children) {\n <th\n [pSortableColumn]=\"col.code\"\n [pSortableColumnDisabled]=\"\n !isSortable || col.isSortable === false\n \"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"[\n getHeaderAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n colspan=\"1\"\n >\n <div class=\"header-container\" [ngStyle]=\"getCellInnerStyle(col)\">\n <span [ngClass]=\"getHeaderTitleClass(col)\">\n {{ col.title }}\n </span>\n\n @if (\n (isSortable && col.isSortable !== false) ||\n (hasColumnFilter && col.isFilter !== false)\n ) {\n <div class=\"icons\">\n @if (isSortable && col.isSortable !== false) {\n <p-sortIcon [field]=\"col.code\" />\n }\n\n @if (hasColumnFilter && col.isFilter !== false) {\n @if (col.type === TableTypeEnum.COMPOSED) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n type=\"text\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"false\"\n [showOperator]=\"false\"\n (onClear)=\"onComposedColumnClear(col)\"\n >\n <ng-template\n pTemplate=\"filter\"\n let-filter=\"filterCallback\"\n >\n @for (\n composedName of col.composedNames;\n track composedName\n ) {\n @if (\n getComposedFieldType(col, composedName) ===\n TableTypeEnum.STRING\n ) {\n <div>\n <p-multiSelect\n [options]=\"filters[composedName]?.options\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n filters[composedName]?.value ?? []\n \"\n [placeholder]=\"\n filters[composedName]?.placeholder\n \"\n display=\"chip\"\n (ngModelChange)=\"\n onComposedFilterValueChange(\n col,\n composedName,\n $event\n );\n filter($event ?? [])\n \"\n >\n <ng-template let-item pTemplate=\"item\">\n <div class=\"custom-multiselect-item\">\n @if (item.image) {\n <img\n [src]=\"item.image\"\n alt=\"icon\"\n class=\"filter-image\"\n />\n }\n\n <span>{{ item.label }}</span>\n </div>\n </ng-template>\n </p-multiSelect>\n </div>\n }\n }\n </ng-template>\n </p-columnFilter>\n } @else {\n <p-columnFilter\n display=\"menu\"\n [field]=\"col.code\"\n [type]=\"getColumnFilterType(col)\"\n [currency]=\"getCurrencySymbol(col)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [showOperator]=\"\n col.type !== TableTypeEnum.MULTISELECT\n \"\n [matchMode]=\"\n col.type === TableTypeEnum.MULTISELECT\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(col.code!)\"\n >\n @if (\n col.type === TableTypeEnum.NUMBER ||\n col.type === TableTypeEnum.AMOUNT\n ) {\n <ng-template pTemplate=\"filter\" let-value>\n <input\n pInputText\n type=\"text\"\n inputmode=\"decimal\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value\n \"\n placeholder=\"Enter a number\"\n (ngModelChange)=\"\n onNumberFilterChange(col.code!, $event)\n \"\n />\n </ng-template>\n }\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"col.type === TableTypeEnum.DATE\"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-datepicker\n [ngModel]=\"latestFilterValues[col.code!] ?? value\"\n dateFormat=\"dd/mm/yy\"\n placeholder=\"Choose a date\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event)\n \"\n ></p-datepicker>\n </ng-template>\n\n <ng-template\n pTemplate=\"filter\"\n *ngIf=\"\n col.type === TableTypeEnum.MULTISELECT &&\n col.filterOptions &&\n col.filterOptions.length > 0\n \"\n let-filter=\"filterCallback\"\n let-value\n >\n <p-multiSelect\n [options]=\"col.filterOptions\"\n optionLabel=\"label\"\n optionValue=\"value\"\n [ngModel]=\"\n latestFilterValues[col.code!] ?? value ?? []\n \"\n display=\"chip\"\n placeholder=\"Choose option\"\n class=\"custom-multiselect\"\n (ngModelChange)=\"\n onFilterValueChange(col.code!, null, $event);\n filter($event ?? [])\n \"\n ></p-multiSelect>\n </ng-template>\n </p-columnFilter>\n }\n }\n </div>\n }\n </div>\n </th>\n } @else {\n <th\n [attr.colspan]=\"col.children?.length\"\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngStyle]=\"getHeaderCellStyle(col)\"\n [ngClass]=\"getHeaderAlignClass(col)\"\n >\n <span>{{ col.title }}</span>\n </th>\n }\n }\n </tr>\n\n @if (hasGroupedColumns) {\n <tr>\n @if (canUseRowReorder()) {\n <th\n [style.width]=\"getRowReorderColumnWidth()\"\n [ngStyle]=\"getStaticCellStyle()\"\n ></th>\n }\n\n @for (col of columns; track col) {\n @if (col.children) {\n @for (child of col.children; track child) {\n <th\n [pSortableColumn]=\"child.code\"\n [pSortableColumnDisabled]=\"\n !isSortable || child.isSortable === false\n \"\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngStyle]=\"getHeaderCellStyle(child)\"\n [ngClass]=\"getHeaderAlignClass(child)\"\n >\n <div\n class=\"header-container\"\n [ngStyle]=\"getCellInnerStyle(child)\"\n >\n <span [ngClass]=\"getHeaderTitleClass(child)\">\n {{ child.title }}\n </span>\n\n @if (\n (isSortable && child.isSortable !== false) ||\n (hasColumnFilter && child.isFilter !== false)\n ) {\n <div class=\"icons\">\n @if (isSortable && child.isSortable !== false) {\n <p-sortIcon [field]=\"child.code\" />\n }\n\n @if (hasColumnFilter && child.isFilter !== false) {\n <p-columnFilter\n display=\"menu\"\n [field]=\"child.code\"\n [type]=\"getColumnFilterType(child)\"\n [currency]=\"getCurrencySymbol(child)\"\n [showApplyButton]=\"true\"\n [showClearButton]=\"true\"\n [showMatchModes]=\"\n child.type !== TableTypeEnum.MULTISELECT\n \"\n [showOperator]=\"\n child.type !== TableTypeEnum.MULTISELECT\n \"\n [matchMode]=\"\n child.type === TableTypeEnum.MULTISELECT\n ? 'in'\n : undefined\n \"\n (onClear)=\"onFilterClear(child.code!)\"\n ></p-columnFilter>\n }\n </div>\n }\n </div>\n </th>\n }\n }\n }\n </tr>\n }\n </ng-template>\n\n <ng-template pTemplate=\"emptymessage\">\n <tr class=\"p-datatable-emptymessage\">\n <td\n class=\"empty-message-cell\"\n [attr.colspan]=\"columns.length + (canUseRowReorder() ? 1 : 0)\"\n >\n <div class=\"empty-message-wrapper\">\n <div class=\"empty-message\">\n <i class=\"pi pi-info-circle\"></i>\n <p>No records available to display.</p>\n </div>\n </div>\n </td>\n </tr>\n </ng-template>\n\n <ng-template pTemplate=\"body\" let-data let-editing=\"editing\">\n @if (!loading) {\n <tr\n [pEditableRow]=\"isEdit ? data : null\"\n [pSelectableRow]=\"selectionMode ? data : null\"\n [attr.data-row-reorder-target]=\"canUseRowReorder() ? 'true' : null\"\n >\n @if (canUseRowReorder()) {\n <td\n class=\"row-reorder-column\"\n [style.width]=\"getRowReorderColumnWidth()\"\n [style.text-align]=\"'center'\"\n [ngStyle]=\"getStaticCellStyle()\"\n >\n <div class=\"row-reorder-actions\">\n <span\n class=\"row-drag-handle\"\n title=\"D\u00E9placer la ligne\"\n (pointerdown)=\"onRowPointerDown($event, data)\"\n >\n <i class=\"pi pi-bars\"></i>\n </span>\n\n @if (showRowMoveArrows) {\n <div class=\"row-reorder-arrow-buttons\">\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-up\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Monter la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowUp(data)\"\n (click)=\"moveRowUp(data); $event.stopPropagation()\"\n ></button>\n\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-chevron-down\"\n class=\"p-button-rounded p-button-text p-button-sm\"\n pTooltip=\"Descendre la ligne\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n [disabled]=\"!canMoveRowDown(data)\"\n (click)=\"moveRowDown(data); $event.stopPropagation()\"\n ></button>\n </div>\n }\n </div>\n </td>\n }\n\n @for (col of columns; track col) {\n @if (!col.children) {\n @if (isEditable(col.code!) && col.type !== TableTypeEnum.ACTION) {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"getDataAlignClass(col)\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isMultiSelect(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-multiSelect\n appendTo=\"body\"\n [ngModel]=\"data[col.code!]\"\n [style]=\"{ width: '100%' }\"\n [options]=\"optionValues\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n ></p-multiSelect>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n <div class=\"multi-select-container\">\n @for (\n rec of getMultiSelectValues(data[col.code!]);\n track rec\n ) {\n <p-tag [value]=\"rec\"></p-tag>\n }\n </div>\n </ng-template>\n </p-cellEditor>\n } @else if (isDatePicker(col.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <p-datepicker\n [inputId]=\"data[col.code!]\"\n [ngModel]=\"data[col.code!]\"\n [dateFormat]=\"'dd/mm/yy'\"\n (ngModelChange)=\"\n changeHandler(data.id, col.code, $event)\n \"\n ></p-datepicker>\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ data[col.code!] | customDate }}\n </ng-template>\n </p-cellEditor>\n } @else {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"data[col.code!]\"\n (change)=\"onChange($event, data.id, col.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n @if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else {\n {{ data[col.code!] }}\n }\n </ng-template>\n </p-cellEditor>\n }\n </div>\n </td>\n } @else {\n <td\n [style.width]=\"col.width || getHeaderWidth(col)\"\n [ngClass]=\"[\n getDataAlignClass(col),\n col.type === TableTypeEnum.ACTION ? 'action-column' : '',\n ]\"\n [ngStyle]=\"getCellStyle(col, data)\"\n >\n @if (col.type === TableTypeEnum.ACTION) {\n <div\n class=\"action-buttons-container\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (isDelete) {\n <button\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-trash\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Supprimer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"Delete(data)\"\n ></button>\n }\n\n @if (isEdit) {\n <div>\n @if (!editing) {\n <button\n pInitEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-pencil\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Modifier\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"initEditableRow(data)\"\n ></button>\n }\n\n @if (editing) {\n <button\n pSaveEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-check\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Enregistrer\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"saveEditableRow(data)\"\n ></button>\n\n <button\n pCancelEditableRow\n pButton\n pRipple\n type=\"button\"\n icon=\"pi pi-times\"\n class=\"p-button-rounded p-button-text\"\n pTooltip=\"Annuler\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"cancelEditableRow(data)\"\n ></button>\n }\n </div>\n }\n\n @for (act of customActions; track act) {\n @if (isActionVisible(act, data)) {\n <button\n pButton\n pRipple\n type=\"button\"\n class=\"p-button-rounded p-button-text\"\n [icon]=\"act.icon || 'pi pi-ellipsis-h'\"\n [ngClass]=\"act.styleClass\"\n [disabled]=\"isActionDisabled(act, data)\"\n [pTooltip]=\"act.tooltip || ''\"\n tooltipPosition=\"top\"\n appendTo=\"body\"\n (click)=\"onCustomActionClick(act, data)\"\n ></button>\n }\n }\n </div>\n } @else {\n <div\n [ngClass]=\"getCellInnerAlignClass(col)\"\n [ngStyle]=\"getCellInnerStyle(col)\"\n >\n @if (col.type === TableTypeEnum.COMPOSED) {\n <div class=\"composed-cell\">\n @for (\n composedName of col.composedNames;\n track composedName;\n let i = $index\n ) {\n @if (\n col.composedTypes?.[i] === TableTypeEnum.IMAGE\n ) {\n <img\n [src]=\"data[col.code!]?.[composedName]\"\n alt=\"composed-img\"\n class=\"composed-image\"\n [ngStyle]=\"\n getMergedComposedImageStyle(\n col,\n composedName,\n data\n )\n \"\n />\n }\n\n @if (\n col.composedTypes?.[i] === TableTypeEnum.STRING\n ) {\n <span\n class=\"composed-text\"\n [ngStyle]=\"\n getMergedComposedTextStyle(\n col,\n composedName,\n data\n )\n \"\n >\n {{ data[col.code!]?.[composedName] }}\n </span>\n }\n }\n </div>\n } @else if (col.type === TableTypeEnum.PROGRESS) {\n <div class=\"progress-cell\">\n <p-progressBar\n [value]=\"getProgressValue(col, data)\"\n [showValue]=\"false\"\n [ngClass]=\"\n 'pt-progress-' + getProgressSeverity(col, data)\n \"\n ></p-progressBar>\n\n @if (isProgressShowValue(col)) {\n <span class=\"progress-cell-value\">\n {{ getProgressValue(col, data)\n }}{{ getProgressUnit(col) }}\n </span>\n }\n </div>\n } @else if (col.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(col, data)\"\n [severity]=\"$any(getTagSeverity(col, data))\"\n [icon]=\"getTagIcon(col, data)\"\n [rounded]=\"isTagRounded(col)\"\n ></p-tag>\n } @else if (col.type === TableTypeEnum.AMOUNT) {\n {{\n data[col.code!]\n | customCurrency\n : getCurrencySymbol(col)\n : col.decimalPlaces\n : col.thousandSeparator\n : col.decimalSeparator\n }}\n } @else if (col.type === TableTypeEnum.NUMBER) {\n {{\n formatNumber(\n data[col.code!],\n col.decimalPlaces,\n col.thousandSeparator,\n col.decimalSeparator\n )\n }}\n } @else if (col.type === TableTypeEnum.DATE) {\n {{\n formatDateWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n } @else if (col.type === TableTypeEnum.DATETIME) {\n {{\n formatDateTimeWithColumn(\n parseAnyDate(data[col.code!]),\n col\n )\n }}\n } @else if (\n [\n TableTypeEnum.STRING,\n TableTypeEnum.MULTISELECT,\n ].includes(col.type!)\n ) {\n {{ data[col.code!] }}\n }\n </div>\n }\n </td>\n }\n } @else {\n @for (child of col.children; track child) {\n <td\n [style.width]=\"child.width || getHeaderWidth(child)\"\n [ngClass]=\"getDataAlignClass(child)\"\n [ngStyle]=\"getCellStyle(child, data)\"\n >\n <div\n [ngClass]=\"getCellInnerAlignClass(child)\"\n [ngStyle]=\"getCellInnerStyle(child)\"\n >\n @if (isEditable(child.code)) {\n <p-cellEditor>\n <ng-template pTemplate=\"input\">\n <input\n pInputText\n type=\"text\"\n [ngModel]=\"child.code ? data[child.code] : null\"\n (change)=\"onChange($event, data.id, child.code)\"\n />\n </ng-template>\n\n <ng-template pTemplate=\"output\">\n {{ child.code ? data[child.code] : \"\" }}\n </ng-template>\n </p-cellEditor>\n } @else if (child.type === TableTypeEnum.TAG) {\n <p-tag\n [value]=\"getTagValue(child, data)\"\n [severity]=\"$any(getTagSeverity(child, data))\"\n [icon]=\"getTagIcon(child, data)\"\n [rounded]=\"isTagRounded(child)\"\n ></p-tag>\n } @else {\n {{ child.code ? data[child.code] : \"\" }}\n }\n </div>\n </td>\n }\n }\n }\n </tr>\n }\n </ng-template>\n </p-table>\n</div>\n", styles: [":host{display:block;width:100%;min-width:0;max-width:100%;box-sizing:border-box}:host *,:host *:before,:host *:after{box-sizing:border-box}.pt-advanced-prime-table{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table .bread-crumb{margin-bottom:15px}.pt-advanced-prime-table .date{display:grid;align-items:center;justify-items:start;width:100%;min-width:0;height:5rem}.pt-advanced-prime-table .filter-container{display:flex;align-items:center;justify-content:space-between;gap:1rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .settings{display:flex;align-items:center;gap:1rem;min-width:0}.pt-advanced-prime-table .multi-select-container{display:flex;align-items:center;gap:.3rem;min-width:0}.pt-advanced-prime-table .table-container{display:block;width:100%;min-width:0;max-width:100%;overflow:hidden}.pt-advanced-prime-table ::ng-deep p-table{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable{display:block;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper{display:block;width:100%;min-width:0;max-width:100%;overflow-x:auto!important;overflow-y:visible!important;overscroll-behavior-x:contain;scrollbar-gutter:stable;-webkit-overflow-scrolling:touch;scrollbar-width:thin}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{width:100%;min-width:var(--pt-advanced-table-min-width, 95rem);max-width:none;table-layout:fixed;border-collapse:separate;border-spacing:0}.pt-advanced-prime-table ::ng-deep .p-datatable-header,.pt-advanced-prime-table ::ng-deep .p-datatable-caption{width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-caption>.flex,.pt-advanced-prime-table ::ng-deep .p-datatable-header>.flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep .custom-multiselect .p-hidden-accessible input{display:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column.p-highlight:hover{background:none}.pt-advanced-prime-table ::ng-deep .p-datatable .p-sortable-column:focus{box-shadow:none;outline:0 none}.pt-advanced-prime-table ::ng-deep .header-container{position:relative;display:flex;align-items:center;gap:.25rem;width:100%!important;min-width:0;max-width:100%;margin:0!important;padding:0!important}.pt-advanced-prime-table ::ng-deep .header-title-left,.pt-advanced-prime-table ::ng-deep .header-title-center,.pt-advanced-prime-table ::ng-deep .header-title-right{display:block;flex:1 1 auto;width:auto;min-width:0;max-width:100%;padding:0;line-height:1.2;white-space:normal;overflow-wrap:break-word;word-break:normal}.pt-advanced-prime-table ::ng-deep .header-title-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-title-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-title-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-align-left{text-align:left}.pt-advanced-prime-table ::ng-deep .header-align-center{text-align:center}.pt-advanced-prime-table ::ng-deep .header-align-right{text-align:right}.pt-advanced-prime-table ::ng-deep .header-container>.icons{position:static!important;top:auto!important;right:auto!important;display:inline-flex;align-items:center;justify-content:flex-end;flex:0 0 auto;gap:.15rem;width:auto!important;min-width:1.5rem;max-width:none;margin-left:auto;padding:0;transform:none!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .header-container>.icons p-sorticon,.pt-advanced-prime-table ::ng-deep .header-container>.icons p-columnfilter{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;margin:0}.pt-advanced-prime-table ::ng-deep .header-container>p-columnfilter:last-child{position:static!important;top:auto!important;right:auto!important;display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto;margin:0 0 0 auto!important;transform:none!important}.pt-advanced-prime-table ::ng-deep .p-sortable-column-icon,.pt-advanced-prime-table ::ng-deep .p-column-filter-menu-button{flex:0 0 auto;margin:0!important}.pt-advanced-prime-table ::ng-deep .p-column-filter-menu-button{width:1.75rem;height:1.75rem;padding:0}.pt-advanced-prime-table ::ng-deep p-sorticon{width:1.25rem;min-width:1.25rem}.pt-advanced-prime-table ::ng-deep p-columnfilter.p-element.ng-star-inserted{margin-top:0}.pt-advanced-prime-table .flex{display:flex;align-items:center;justify-content:space-between;flex-wrap:wrap;gap:.75rem;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table .ml-auto{margin-left:auto}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield{position:relative;display:inline-flex;align-items:center;width:100%;min-width:0;max-width:100%}.pt-advanced-prime-table ::ng-deep p-inputicon,.pt-advanced-prime-table ::ng-deep .p-inputicon,.pt-advanced-prime-table ::ng-deep .p-input-icon{position:absolute;top:50%;left:.85rem;z-index:2;display:inline-flex;align-items:center;justify-content:center;margin:0;transform:translateY(-50%);pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-iconfield .p-inputtext{width:100%;max-width:100%;padding-left:2.5rem}.pt-advanced-prime-table ::ng-deep .bt-filter-btn button{margin-left:1rem;cursor:pointer}.pt-advanced-prime-table .table-row{display:flex;justify-content:center;gap:1rem;min-width:0;text-align:center}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-excel{color:green;font-size:1.25em}.pt-advanced-prime-table ::ng-deep span.p-button-icon.pi.pi-file-pdf{color:red;font-size:1.25em}.pt-advanced-prime-table ::ng-deep .p-datatable-emptymessage>td.empty-message-cell{padding:0!important}.pt-advanced-prime-table .empty-message-wrapper{display:flex;align-items:center;justify-content:center;width:100%;height:100%;min-height:180px}.pt-advanced-prime-table .empty-message{color:#888;font-size:1.2rem;text-align:center}.pt-advanced-prime-table .empty-message i{display:block;margin-bottom:.5rem;font-size:2rem}.pt-advanced-prime-table th,.pt-advanced-prime-table td{min-width:0;overflow:hidden;white-space:normal;overflow-wrap:anywhere;word-break:break-word}.pt-advanced-prime-table ::ng-deep .p-datatable-thead>tr>th,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td{min-width:0;overflow:hidden;white-space:normal;overflow-wrap:anywhere;word-break:break-word}.pt-advanced-prime-table ::ng-deep .p-datatable-thead>tr>th{vertical-align:middle}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td{vertical-align:top}.pt-advanced-prime-table .cell-inner-left,.pt-advanced-prime-table .cell-inner-center,.pt-advanced-prime-table .cell-inner-right,.pt-advanced-prime-table ::ng-deep .composed-cell,.pt-advanced-prime-table ::ng-deep .composed-text{min-width:0;max-width:100%;white-space:normal;overflow-wrap:anywhere;word-break:break-word}.filter-image{width:22px;height:14px;margin-right:5px}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-left{text-align:left!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-center{text-align:center!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr>td.cell-align-right{text-align:right!important}.pt-advanced-prime-table .cell-inner-left,.pt-advanced-prime-table .cell-inner-center,.pt-advanced-prime-table .cell-inner-right{display:flex;align-items:flex-start;width:100%;min-width:0}.pt-advanced-prime-table .cell-inner-left{justify-content:flex-start;text-align:left}.pt-advanced-prime-table .cell-inner-center{justify-content:center;text-align:center}.pt-advanced-prime-table .cell-inner-right{justify-content:flex-end;text-align:right}.pt-advanced-prime-table ::ng-deep .p-tag{padding:.2rem .55rem;font-size:.72rem;font-weight:800;line-height:1.2;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .p-tag .p-tag-icon{margin-right:.25rem}.pt-advanced-prime-table .progress-cell{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar{flex:1 1 auto;width:100%;min-width:0;height:.75rem!important;overflow:hidden;border-radius:999px;background:#e5e7eb!important}.pt-advanced-prime-table ::ng-deep .progress-cell .p-progressbar-value{display:block!important;height:100%!important;border-radius:999px}.pt-advanced-prime-table .progress-cell-value{flex:0 0 auto;min-width:38px;color:#334155;font-size:.72rem;font-weight:800;text-align:right}.pt-advanced-prime-table ::ng-deep th.action-column,.pt-advanced-prime-table ::ng-deep td.action-column{align-items:center;justify-content:center;padding:0;overflow:hidden;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .action-buttons-container{display:flex;align-items:center!important;justify-content:center!important;flex-wrap:wrap;gap:.35rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .action-buttons-container .p-button.p-button-rounded.p-button-text{min-width:22px!important;height:22px!important;padding:.25rem!important}.pt-advanced-prime-table ::ng-deep .pt-progress-success .p-progressbar-value{background:#22c55e!important}.pt-advanced-prime-table ::ng-deep .pt-progress-warning .p-progressbar-value{background:#f59e0b!important}.pt-advanced-prime-table ::ng-deep .pt-progress-danger .p-progressbar-value{background:#ef4444!important}.pt-advanced-prime-table ::ng-deep .pt-progress-info .p-progressbar-value{background:#3b82f6!important}.pt-advanced-prime-table ::ng-deep .composed-cell{display:flex;align-items:center;flex-wrap:wrap;gap:.5rem;width:100%;min-width:0}.pt-advanced-prime-table ::ng-deep .composed-image{display:block;flex:0 0 auto;object-fit:contain}.pt-advanced-prime-table ::ng-deep .composed-text{flex:1 1 auto;min-width:0}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{transition:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging{cursor:grabbing!important;opacity:.55}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:5;box-shadow:inset 0 0 0 1px #3b82f673}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before:before{position:absolute;z-index:30;top:-2px;right:0;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after:after{position:absolute;z-index:30;right:0;bottom:-2px;left:0;height:3px;border-radius:999px;background:var(--primary-color, #3b82f6);content:\"\";pointer-events:none}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-before>td{border-top:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-drop-after>td{border-bottom:3px solid var(--primary-color, #3b82f6)!important;background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-drag-handle{display:inline-flex;align-items:center;justify-content:center;width:2rem;min-width:2rem;height:2rem;border-radius:6px;cursor:grab;-webkit-user-select:none;user-select:none;touch-action:none}.pt-advanced-prime-table ::ng-deep .row-drag-handle:hover{background:#3b82f61a}.pt-advanced-prime-table ::ng-deep .row-drag-handle:active{cursor:grabbing}.pt-advanced-prime-table ::ng-deep .row-drag-handle .pi{color:#64748b;font-size:.95rem}.pt-advanced-prime-table ::ng-deep td.row-reorder-column,.pt-advanced-prime-table ::ng-deep th.row-reorder-column{width:7rem;min-width:7rem;padding:.25rem .4rem!important;text-align:center!important;white-space:nowrap}.pt-advanced-prime-table ::ng-deep .row-reorder-actions{display:inline-flex;align-items:center;justify-content:center;gap:.15rem;width:100%}.pt-advanced-prime-table ::ng-deep .row-reorder-arrow-buttons{display:inline-flex;flex-direction:column;gap:0}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text{width:1.75rem!important;min-width:1.75rem!important;height:1.75rem!important;padding:0!important;border-radius:6px!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text .p-button-icon{font-size:.75rem}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:not(:disabled):hover{background:#3b82f61a!important}.pt-advanced-prime-table ::ng-deep .row-reorder-actions .p-button.p-button-rounded.p-button-text:disabled{cursor:not-allowed;opacity:.35}.pt-advanced-prime-table.dragging-active,.pt-advanced-prime-table.dragging-active *{-webkit-user-select:none!important;user-select:none!important}.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-before,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table .p-datatable-tbody>tr.pt-row-drop-after{position:relative;z-index:10}.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-before>td,.pt-advanced-prime-table ::ng-deep .p-datatable-tbody>tr.pt-row-dragging.pt-row-drop-after>td{background:#3b82f60f!important}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar{width:10px;height:10px}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-track,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-track{border-radius:999px;background:var(--pt-advanced-table-scrollbar-track, #f1f5f9)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb{border:2px solid var(--pt-advanced-table-scrollbar-track, #f1f5f9);border-radius:999px;background:var(--pt-advanced-table-scrollbar-thumb, #94a3b8)}.pt-advanced-prime-table ::ng-deep .p-datatable-table-container::-webkit-scrollbar-thumb:hover,.pt-advanced-prime-table ::ng-deep .p-datatable-wrapper::-webkit-scrollbar-thumb:hover{background:var(--pt-advanced-table-scrollbar-thumb-hover, #64748b)}@media(max-width:768px){.pt-advanced-prime-table .filter-container,.pt-advanced-prime-table .flex{align-items:stretch;flex-direction:column}.pt-advanced-prime-table .settings{flex-wrap:wrap}.pt-advanced-prime-table .ml-auto{width:100%;margin-left:0}.pt-advanced-prime-table ::ng-deep p-iconfield,.pt-advanced-prime-table ::ng-deep .p-iconfield,.pt-advanced-prime-table ::ng-deep .p-inputtext{width:100%}.pt-advanced-prime-table ::ng-deep .p-datatable-table,.pt-advanced-prime-table ::ng-deep .p-datatable-scrollable-table{min-width:var(--pt-advanced-table-mobile-min-width, 78rem)}}\n"] }]
1503
1500
  }], ctorParameters: () => [{ type: i0.NgZone }], propDecorators: { data: [{
1504
1501
  type: Input
1505
1502
  }], columns: [{
@@ -1580,9 +1577,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
1580
1577
 
1581
1578
  class PTMultiSelectComponent {
1582
1579
  constructor() {
1583
- /**
1584
- * Two-way standalone value.
1585
- */
1586
1580
  this.value = [];
1587
1581
  this.valueChange = new EventEmitter();
1588
1582
  this.selectionChange = new EventEmitter();
@@ -1612,7 +1606,8 @@ class PTMultiSelectComponent {
1612
1606
  return `pt-multiselect-${this.controlName}`;
1613
1607
  }
1614
1608
  get resolvedHidden() {
1615
- return this.formField?.hidden ?? this.config?.hidden ?? false;
1609
+ const hidden = this.formField?.hidden ?? this.config?.hidden;
1610
+ return this.resolveHiddenValue(hidden);
1616
1611
  }
1617
1612
  get resolvedLabel() {
1618
1613
  return this.formField?.label || this.config?.label;
@@ -1629,10 +1624,10 @@ class PTMultiSelectComponent {
1629
1624
  'Select options');
1630
1625
  }
1631
1626
  get resolvedOptionLabel() {
1632
- return this.config?.optionLabel || 'label';
1627
+ return this.formField?.optionLabel || this.config?.optionLabel || 'label';
1633
1628
  }
1634
1629
  get resolvedOptionValue() {
1635
- return this.config?.optionValue || 'value';
1630
+ return this.formField?.optionValue || this.config?.optionValue || 'value';
1636
1631
  }
1637
1632
  get resolvedRequired() {
1638
1633
  return this.formField?.required ?? this.config?.required ?? false;
@@ -1644,19 +1639,45 @@ class PTMultiSelectComponent {
1644
1639
  return this.formField?.errorText || this.config?.errorText;
1645
1640
  }
1646
1641
  get resolvedFilter() {
1647
- return this.config?.filter === true;
1642
+ return this.formField?.filter === true || this.config?.filter === true;
1648
1643
  }
1649
1644
  get resolvedFilterBy() {
1650
- return this.config?.filterBy || this.resolvedOptionLabel;
1645
+ return (this.formField?.filterBy ||
1646
+ this.config?.filterBy ||
1647
+ this.resolvedOptionLabel);
1651
1648
  }
1652
1649
  get resolvedDisplay() {
1653
- return this.config?.display || 'comma';
1650
+ return this.formField?.display || this.config?.display || 'comma';
1654
1651
  }
1655
1652
  get resolvedMaxSelectedLabels() {
1656
- return this.config?.maxSelectedLabels ?? 3;
1653
+ return (this.formField?.maxSelectedLabels ?? this.config?.maxSelectedLabels ?? 3);
1657
1654
  }
1658
1655
  get resolvedSelectedItemsLabel() {
1659
- return this.config?.selectedItemsLabel || '{0} items selected';
1656
+ return (this.formField?.selectedItemsLabel ||
1657
+ this.config?.selectedItemsLabel ||
1658
+ '{0} items selected');
1659
+ }
1660
+ getErrorMessage() {
1661
+ const control = this.activeFormGroup.get(this.controlName);
1662
+ if (!control?.errors) {
1663
+ return '';
1664
+ }
1665
+ const errorKey = Object.keys(control.errors)[0];
1666
+ if (!errorKey) {
1667
+ return '';
1668
+ }
1669
+ const customMessage = this.formField?.validationMessages?.[errorKey];
1670
+ if (customMessage) {
1671
+ return customMessage;
1672
+ }
1673
+ if (this.resolvedErrorText) {
1674
+ return this.resolvedErrorText;
1675
+ }
1676
+ const label = this.resolvedLabel || this.controlName;
1677
+ if (control.hasError('required')) {
1678
+ return `${label} is required`;
1679
+ }
1680
+ return `${label} is invalid`;
1660
1681
  }
1661
1682
  setupControl(forceValueFromConfig) {
1662
1683
  const name = this.controlName;
@@ -1665,23 +1686,35 @@ class PTMultiSelectComponent {
1665
1686
  }
1666
1687
  let control = this.activeFormGroup.get(name);
1667
1688
  if (!control) {
1668
- control = new FormControl(this.getInitialValue());
1689
+ control = new FormControl(this.getInitialValue(), {
1690
+ nonNullable: true,
1691
+ });
1669
1692
  this.activeFormGroup.addControl(name, control);
1670
1693
  }
1671
1694
  else if (forceValueFromConfig) {
1672
- control.setValue(this.getInitialValue(), { emitEvent: false });
1695
+ control.setValue(this.getInitialValue(), {
1696
+ emitEvent: false,
1697
+ });
1673
1698
  }
1674
1699
  else if (!this.formGroup && this.value !== undefined) {
1675
- control.setValue(this.normalizeValue(this.value), { emitEvent: false });
1700
+ control.setValue(this.normalizeValue(this.value), {
1701
+ emitEvent: false,
1702
+ });
1676
1703
  }
1677
1704
  control.setValidators(this.getValidators());
1678
1705
  if (this.resolvedDisabled) {
1679
- control.disable({ emitEvent: false });
1706
+ control.disable({
1707
+ emitEvent: false,
1708
+ });
1680
1709
  }
1681
1710
  else {
1682
- control.enable({ emitEvent: false });
1711
+ control.enable({
1712
+ emitEvent: false,
1713
+ });
1683
1714
  }
1684
- control.updateValueAndValidity({ emitEvent: false });
1715
+ control.updateValueAndValidity({
1716
+ emitEvent: false,
1717
+ });
1685
1718
  this.valueChangesSubscription?.unsubscribe();
1686
1719
  this.valueChangesSubscription = control.valueChanges.subscribe((selectedValues) => {
1687
1720
  const normalizedValues = this.normalizeValue(selectedValues);
@@ -1693,7 +1726,7 @@ class PTMultiSelectComponent {
1693
1726
  if (this.formField?.value !== undefined) {
1694
1727
  return this.normalizeValue(this.formField.value);
1695
1728
  }
1696
- if (this.value !== undefined && Array.isArray(this.value)) {
1729
+ if (Array.isArray(this.value)) {
1697
1730
  return this.normalizeValue(this.value);
1698
1731
  }
1699
1732
  return this.normalizeValue(this.config?.value);
@@ -1703,39 +1736,42 @@ class PTMultiSelectComponent {
1703
1736
  if (this.resolvedRequired) {
1704
1737
  validators.push(Validators.required);
1705
1738
  }
1739
+ if (Array.isArray(this.formField?.validators) &&
1740
+ this.formField.validators.length > 0) {
1741
+ validators.push(...this.formField.validators);
1742
+ }
1706
1743
  return validators;
1707
1744
  }
1708
- /**
1709
- * Le MultiSelect doit manipuler un tableau d'identifiants primitifs,
1710
- * pas des objets complets, pour éviter les problèmes de référence.
1711
- */
1712
1745
  normalizeValue(value) {
1713
- if (!Array.isArray(value)) {
1746
+ if (!Array.isArray(value) || value.length === 0) {
1714
1747
  return [];
1715
1748
  }
1716
- if (value.length === 0) {
1717
- return [];
1718
- }
1719
- if (typeof value[0] === 'number' || typeof value[0] === 'string') {
1720
- return value;
1749
+ if (value.every((item) => typeof item === 'number' ||
1750
+ typeof item === 'string' ||
1751
+ typeof item === 'boolean')) {
1752
+ return [...value];
1721
1753
  }
1754
+ const optionValue = this.resolvedOptionValue;
1722
1755
  return value
1723
1756
  .map((item) => {
1724
- const optionValue = this.resolvedOptionValue;
1725
- if (item?.[optionValue] !== undefined) {
1757
+ if (item === null || item === undefined) {
1758
+ return null;
1759
+ }
1760
+ if (typeof item !== 'object') {
1761
+ return item;
1762
+ }
1763
+ if (item[optionValue] !== undefined) {
1726
1764
  return item[optionValue];
1727
1765
  }
1728
- return item?.value ?? item?.id ?? null;
1766
+ return item.value ?? item.id ?? null;
1729
1767
  })
1730
1768
  .filter((item) => item !== null && item !== undefined);
1731
1769
  }
1732
- getErrorMessage() {
1733
- const control = this.activeFormGroup.get(this.controlName);
1734
- if (control?.hasError('required')) {
1735
- return (this.resolvedErrorText ||
1736
- `${this.resolvedLabel || this.controlName} is required`);
1770
+ resolveHiddenValue(hidden) {
1771
+ if (typeof hidden === 'function') {
1772
+ return Boolean(hidden(this.activeFormGroup.getRawValue()));
1737
1773
  }
1738
- return '';
1774
+ return Boolean(hidden);
1739
1775
  }
1740
1776
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTMultiSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
1741
1777
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTMultiSelectComponent, isStandalone: false, selector: "pt-multi-select", inputs: { formGroup: "formGroup", formField: "formField", config: "config", value: "value" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!resolvedHidden) {\n <div\n [formGroup]=\"activeFormGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: resolvedWidth }\"\n >\n @if (resolvedLabel) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ resolvedLabel }}\n </label>\n }\n\n <p-multiSelect\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [options]=\"resolvedOptions\"\n [placeholder]=\"resolvedPlaceholder\"\n [optionLabel]=\"resolvedOptionLabel\"\n [optionValue]=\"resolvedOptionValue\"\n [filter]=\"resolvedFilter\"\n [filterBy]=\"resolvedFilterBy\"\n [display]=\"resolvedDisplay\"\n [maxSelectedLabels]=\"resolvedMaxSelectedLabels\"\n [selectedItemsLabel]=\"resolvedSelectedItemsLabel\"\n [appendTo]=\"'body'\"\n [overlayOptions]=\"{ baseZIndex: 11000 }\"\n ></p-multiSelect>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-multiselect{width:100%}.form-field ::ng-deep .p-multiselect.ng-invalid.ng-touched,.form-field ::ng-deep .p-multiselect.ng-invalid.ng-dirty{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i8.MultiSelect, selector: "p-multiSelect, p-multiselect, p-multi-select", inputs: ["id", "ariaLabel", "styleClass", "panelStyle", "panelStyleClass", "inputId", "readonly", "group", "filter", "filterPlaceHolder", "filterLocale", "overlayVisible", "tabindex", "dataKey", "ariaLabelledBy", "displaySelectedLabel", "maxSelectedLabels", "selectionLimit", "selectedItemsLabel", "showToggleAll", "emptyFilterMessage", "emptyMessage", "resetFilterOnHide", "dropdownIcon", "chipIcon", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "showHeader", "filterBy", "scrollHeight", "lazy", "virtualScroll", "loading", "virtualScrollItemSize", "loadingIcon", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "autofocusFilter", "display", "autocomplete", "showClear", "autofocus", "placeholder", "options", "filterValue", "selectAll", "focusOnHover", "filterFields", "selectOnFocus", "autoOptionFocus", "highlightOnSelect", "size", "variant", "fluid", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onClear", "onPanelShow", "onPanelHide", "onLazyLoad", "onRemove", "onSelectAllChange"] }] }); }
@@ -2360,56 +2396,109 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
2360
2396
  }]
2361
2397
  }] });
2362
2398
 
2399
+ // projects/ng-prime-tools/src/lib/pt-check-box-input/pt-check-box-input.component.ts
2363
2400
  class PTCheckBoxInputComponent {
2364
2401
  ngOnInit() {
2365
2402
  this.setupControl();
2366
2403
  }
2404
+ ngOnChanges(changes) {
2405
+ if (changes['formGroup'] || changes['formField']) {
2406
+ this.setupControl();
2407
+ }
2408
+ }
2367
2409
  get inputId() {
2368
2410
  return `pt-checkbox-${this.formField?.name || 'field'}`;
2369
2411
  }
2412
+ get errorId() {
2413
+ return `pt-checkbox-error-${this.formField?.name || 'field'}`;
2414
+ }
2415
+ get isInvalid() {
2416
+ const control = this.formGroup?.get(this.formField?.name);
2417
+ return Boolean(control &&
2418
+ control.enabled &&
2419
+ control.invalid &&
2420
+ (control.touched || control.dirty));
2421
+ }
2422
+ getErrorMessage() {
2423
+ const control = this.formGroup?.get(this.formField?.name);
2424
+ if (!control?.errors) {
2425
+ return '';
2426
+ }
2427
+ const errorKey = this.resolveFirstErrorKey(control.errors);
2428
+ if (!errorKey) {
2429
+ return '';
2430
+ }
2431
+ const customMessage = this.formField.validationMessages?.[errorKey];
2432
+ if (customMessage) {
2433
+ return customMessage;
2434
+ }
2435
+ if (this.formField.errorText) {
2436
+ return this.formField.errorText;
2437
+ }
2438
+ const label = this.formField.label?.trim() || this.formField.name;
2439
+ switch (errorKey) {
2440
+ case 'required':
2441
+ return `${label} is required`;
2442
+ default:
2443
+ return `${label} is invalid`;
2444
+ }
2445
+ }
2370
2446
  setupControl() {
2371
- let control = this.formGroup.get(this.formField.name);
2447
+ const name = this.formField?.name;
2448
+ if (!name || !this.formGroup) {
2449
+ return;
2450
+ }
2451
+ let control = this.formGroup.get(name);
2372
2452
  if (!control) {
2373
- control = new FormControl(null);
2374
- this.formGroup.addControl(this.formField.name, control);
2453
+ control = new FormControl(this.resolveInitialValue(), {
2454
+ nonNullable: true,
2455
+ });
2456
+ this.formGroup.addControl(name, control);
2375
2457
  }
2376
- const validators = this.getValidators();
2377
- control.setValidators(validators);
2458
+ control.setValidators(this.getValidators());
2378
2459
  if (this.formField.disabled) {
2379
- control.disable({ emitEvent: false });
2460
+ control.disable({
2461
+ emitEvent: false,
2462
+ });
2380
2463
  }
2381
2464
  else {
2382
- control.enable({ emitEvent: false });
2465
+ control.enable({
2466
+ emitEvent: false,
2467
+ });
2383
2468
  }
2384
- control.updateValueAndValidity({ emitEvent: false });
2469
+ control.updateValueAndValidity({
2470
+ emitEvent: false,
2471
+ });
2472
+ }
2473
+ resolveInitialValue() {
2474
+ const value = this.formField.value;
2475
+ if (typeof value === 'boolean') {
2476
+ return value;
2477
+ }
2478
+ return false;
2385
2479
  }
2386
2480
  getValidators() {
2387
2481
  const validators = [];
2388
2482
  if (this.formField.required) {
2389
- validators.push(this.requireChoiceValidator());
2483
+ validators.push(Validators.requiredTrue);
2484
+ }
2485
+ if (Array.isArray(this.formField.validators) &&
2486
+ this.formField.validators.length > 0) {
2487
+ validators.push(...this.formField.validators);
2390
2488
  }
2391
2489
  return validators;
2392
2490
  }
2393
- requireChoiceValidator() {
2394
- return (control) => {
2395
- return control.value !== null && control.value !== undefined
2396
- ? null
2397
- : { requiredChoice: true };
2398
- };
2399
- }
2400
- getErrorMessage() {
2401
- const control = this.formGroup.get(this.formField.name);
2402
- if (control?.errors?.['requiredChoice']) {
2403
- return this.formField.errorText || `${this.formField.label} is required`;
2404
- }
2405
- return '';
2491
+ resolveFirstErrorKey(errors) {
2492
+ const priority = ['required'];
2493
+ return (priority.find((key) => errors[key] !== undefined) ||
2494
+ Object.keys(errors)[0]);
2406
2495
  }
2407
2496
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTCheckBoxInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2408
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTCheckBoxInputComponent, isStandalone: false, selector: "pt-check-box-input", inputs: { formGroup: "formGroup", formField: "formField" }, ngImport: i0, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: formField.width || '100%' }\"\n >\n <div class=\"checkbox-container\">\n <p-checkbox\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n [binary]=\"true\"\n ></p-checkbox>\n\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"checkbox-label\">\n {{ formField.label }}\n </label>\n }\n </div>\n\n @if (\n formGroup.get(formField.name)?.errors &&\n (formGroup.get(formField.name)?.touched ||\n formGroup.get(formField.name)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"p-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem}.checkbox-container{display:flex;align-items:center;gap:.5rem;min-height:2.75rem}.checkbox-container .checkbox-label{display:inline-flex;align-items:center;margin:0;padding:0;font-weight:600;font-size:1rem;line-height:1;cursor:pointer}.checkbox-container ::ng-deep .p-checkbox{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.checkbox-container ::ng-deep .p-checkbox-box{width:1.25rem;height:1.25rem}.error-container{margin-top:.25rem}.p-error{font-size:.8rem;color:#f44336}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }] }); }
2497
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTCheckBoxInputComponent, isStandalone: false, selector: "pt-check-box-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-check-box-input/pt-check-box-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n 'max-width': formField.width || '100%',\n }\"\n>\n <div class=\"checkbox-container\">\n <p-checkbox\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n [binary]=\"true\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></p-checkbox>\n\n @if (formField.label) {\n <label class=\"checkbox-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n </div>\n\n @if (isInvalid) {\n <div class=\"error-container\" role=\"alert\" [id]=\"errorId\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"p-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{display:flex;flex-direction:column;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.checkbox-container{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.checkbox-label{min-width:0;cursor:pointer;font-size:1rem;font-weight:600;overflow-wrap:anywhere}.required-indicator{margin-left:.2rem;color:#ef4444}.form-field-invalid ::ng-deep .p-checkbox-box{border-color:#ef4444!important}.error-container{display:flex;align-items:flex-start;gap:.35rem;width:100%;min-width:0;margin-top:.35rem;color:#ef4444}.error-container .pi{flex:0 0 auto;margin-top:.1rem;font-size:.8rem}.p-error{min-width:0;color:inherit;font-size:.8rem;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$1.Checkbox, selector: "p-checkbox, p-checkBox, p-check-box", inputs: ["hostName", "value", "binary", "ariaLabelledBy", "ariaLabel", "tabindex", "inputId", "inputStyle", "styleClass", "inputClass", "indeterminate", "formControl", "checkboxIcon", "readonly", "autofocus", "trueValue", "falseValue", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }] }); }
2409
2498
  }
2410
2499
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTCheckBoxInputComponent, decorators: [{
2411
2500
  type: Component,
2412
- args: [{ selector: 'pt-check-box-input', standalone: false, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: formField.width || '100%' }\"\n >\n <div class=\"checkbox-container\">\n <p-checkbox\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n [binary]=\"true\"\n ></p-checkbox>\n\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"checkbox-label\">\n {{ formField.label }}\n </label>\n }\n </div>\n\n @if (\n formGroup.get(formField.name)?.errors &&\n (formGroup.get(formField.name)?.touched ||\n formGroup.get(formField.name)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"p-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem}.checkbox-container{display:flex;align-items:center;gap:.5rem;min-height:2.75rem}.checkbox-container .checkbox-label{display:inline-flex;align-items:center;margin:0;padding:0;font-weight:600;font-size:1rem;line-height:1;cursor:pointer}.checkbox-container ::ng-deep .p-checkbox{display:inline-flex;align-items:center;justify-content:center;flex:0 0 auto}.checkbox-container ::ng-deep .p-checkbox-box{width:1.25rem;height:1.25rem}.error-container{margin-top:.25rem}.p-error{font-size:.8rem;color:#f44336}\n"] }]
2501
+ args: [{ selector: 'pt-check-box-input', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-check-box-input/pt-check-box-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n 'max-width': formField.width || '100%',\n }\"\n>\n <div class=\"checkbox-container\">\n <p-checkbox\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n [binary]=\"true\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></p-checkbox>\n\n @if (formField.label) {\n <label class=\"checkbox-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n </div>\n\n @if (isInvalid) {\n <div class=\"error-container\" role=\"alert\" [id]=\"errorId\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"p-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{display:flex;flex-direction:column;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.checkbox-container{display:flex;align-items:center;gap:.5rem;width:100%;min-width:0}.checkbox-label{min-width:0;cursor:pointer;font-size:1rem;font-weight:600;overflow-wrap:anywhere}.required-indicator{margin-left:.2rem;color:#ef4444}.form-field-invalid ::ng-deep .p-checkbox-box{border-color:#ef4444!important}.error-container{display:flex;align-items:flex-start;gap:.35rem;width:100%;min-width:0;margin-top:.35rem;color:#ef4444}.error-container .pi{flex:0 0 auto;margin-top:.1rem;font-size:.8rem}.p-error{min-width:0;color:inherit;font-size:.8rem;overflow-wrap:anywhere}\n"] }]
2413
2502
  }], propDecorators: { formGroup: [{
2414
2503
  type: Input
2415
2504
  }], formField: [{
@@ -2544,12 +2633,10 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
2544
2633
  }]
2545
2634
  }], ctorParameters: () => [] });
2546
2635
 
2636
+ // projects/ng-prime-tools/src/lib/pt-date-input/pt-date-input.component.ts
2547
2637
  class PTDateInputComponent {
2548
2638
  constructor(dateService) {
2549
2639
  this.dateService = dateService;
2550
- /**
2551
- * Two-way standalone value.
2552
- */
2553
2640
  this.value = null;
2554
2641
  this.valueChange = new EventEmitter();
2555
2642
  this.dateChange = new EventEmitter();
@@ -2582,8 +2669,15 @@ class PTDateInputComponent {
2582
2669
  get inputId() {
2583
2670
  return `pt-date-${this.controlName}`;
2584
2671
  }
2672
+ get labelId() {
2673
+ return `pt-date-label-${this.controlName}`;
2674
+ }
2675
+ get errorId() {
2676
+ return `pt-date-error-${this.controlName}`;
2677
+ }
2585
2678
  get resolvedHidden() {
2586
- return this.formField?.hidden ?? this.config?.hidden ?? false;
2679
+ const hidden = this.formField?.hidden ?? this.config?.hidden;
2680
+ return this.resolveHiddenValue(hidden);
2587
2681
  }
2588
2682
  get resolvedLabel() {
2589
2683
  return this.formField?.label || this.config?.label;
@@ -2629,12 +2723,47 @@ class PTDateInputComponent {
2629
2723
  get resolvedErrorText() {
2630
2724
  return this.formField?.errorText || this.config?.errorText;
2631
2725
  }
2726
+ get isInvalid() {
2727
+ const control = this.activeFormGroup.get(this.controlName);
2728
+ return Boolean(control &&
2729
+ control.enabled &&
2730
+ control.invalid &&
2731
+ (control.touched || control.dirty));
2732
+ }
2733
+ getErrorMessage() {
2734
+ const control = this.activeFormGroup.get(this.controlName);
2735
+ if (!control?.errors) {
2736
+ return '';
2737
+ }
2738
+ const errorKey = this.resolveFirstErrorKey(control.errors);
2739
+ if (!errorKey) {
2740
+ return '';
2741
+ }
2742
+ const customMessage = this.formField?.validationMessages?.[errorKey];
2743
+ if (customMessage) {
2744
+ return customMessage;
2745
+ }
2746
+ if (this.resolvedErrorText) {
2747
+ return this.resolvedErrorText;
2748
+ }
2749
+ const label = this.resolvedLabel || this.controlName;
2750
+ switch (errorKey) {
2751
+ case 'required':
2752
+ return `${label} is required`;
2753
+ case 'minDate':
2754
+ return `${label} must be on or after ${this.resolvedMinValue}`;
2755
+ case 'maxDate':
2756
+ return `${label} must be on or before ${this.resolvedMaxValue}`;
2757
+ default:
2758
+ return `${label} is invalid`;
2759
+ }
2760
+ }
2632
2761
  initializeComponent() {
2633
2762
  this.defaultDateFormat = this.dateService.assignDefaultDateFormat(this.resolvedDateInputType, this.formField?.dateFormat || this.config?.dateFormat);
2634
- this.setupControl();
2763
+ this.defaultPlaceholder = getDefaultPlaceholder(this.resolvedDateInputType);
2635
2764
  this.initializeDateLimits();
2636
2765
  this.validateConfiguration();
2637
- this.defaultPlaceholder = getDefaultPlaceholder(this.resolvedDateInputType);
2766
+ this.setupControl();
2638
2767
  }
2639
2768
  setupControl() {
2640
2769
  const name = this.controlName;
@@ -2646,19 +2775,27 @@ class PTDateInputComponent {
2646
2775
  control = new FormControl(this.getInitialValue());
2647
2776
  this.activeFormGroup.addControl(name, control);
2648
2777
  }
2649
- if (!this.formGroup &&
2778
+ else if (!this.formGroup &&
2650
2779
  this.value !== undefined &&
2651
2780
  control.value !== this.value) {
2652
- control.setValue(this.value, { emitEvent: false });
2781
+ control.setValue(this.value, {
2782
+ emitEvent: false,
2783
+ });
2653
2784
  }
2654
2785
  control.setValidators(this.getValidators());
2655
2786
  if (this.resolvedDisabled) {
2656
- control.disable({ emitEvent: false });
2787
+ control.disable({
2788
+ emitEvent: false,
2789
+ });
2657
2790
  }
2658
2791
  else {
2659
- control.enable({ emitEvent: false });
2792
+ control.enable({
2793
+ emitEvent: false,
2794
+ });
2660
2795
  }
2661
- control.updateValueAndValidity({ emitEvent: false });
2796
+ control.updateValueAndValidity({
2797
+ emitEvent: false,
2798
+ });
2662
2799
  this.valueChangesSubscription?.unsubscribe();
2663
2800
  this.valueChangesSubscription = control.valueChanges.subscribe((selectedValue) => {
2664
2801
  this.valueChange.emit(selectedValue);
@@ -2689,10 +2826,9 @@ class PTDateInputComponent {
2689
2826
  catch (error) {
2690
2827
  if (error instanceof Error) {
2691
2828
  console.error(error.message);
2829
+ return;
2692
2830
  }
2693
- else {
2694
- console.error('An unknown error occurred.');
2695
- }
2831
+ console.error('An unknown error occurred.');
2696
2832
  }
2697
2833
  }
2698
2834
  getValidators() {
@@ -2700,22 +2836,90 @@ class PTDateInputComponent {
2700
2836
  if (this.resolvedRequired) {
2701
2837
  validators.push(Validators.required);
2702
2838
  }
2839
+ if (this.minDate) {
2840
+ validators.push(this.minDateValidator(this.minDate));
2841
+ }
2842
+ if (this.maxDate) {
2843
+ validators.push(this.maxDateValidator(this.maxDate));
2844
+ }
2845
+ if (Array.isArray(this.formField?.validators) &&
2846
+ this.formField.validators.length > 0) {
2847
+ validators.push(...this.formField.validators);
2848
+ }
2703
2849
  return validators;
2704
2850
  }
2705
- getErrorMessage() {
2706
- const control = this.activeFormGroup.get(this.controlName);
2707
- if (control?.hasError('required')) {
2708
- return (this.resolvedErrorText ||
2709
- `${this.resolvedLabel || this.controlName} is required`);
2851
+ minDateValidator(minDate) {
2852
+ return (control) => {
2853
+ const dates = this.extractDates(control.value);
2854
+ if (dates.length === 0) {
2855
+ return null;
2856
+ }
2857
+ const hasInvalidDate = dates.some((date) => date.getTime() < minDate.getTime());
2858
+ return hasInvalidDate
2859
+ ? {
2860
+ minDate: {
2861
+ requiredMinDate: minDate,
2862
+ actualValue: control.value,
2863
+ },
2864
+ }
2865
+ : null;
2866
+ };
2867
+ }
2868
+ maxDateValidator(maxDate) {
2869
+ return (control) => {
2870
+ const dates = this.extractDates(control.value);
2871
+ if (dates.length === 0) {
2872
+ return null;
2873
+ }
2874
+ const hasInvalidDate = dates.some((date) => date.getTime() > maxDate.getTime());
2875
+ return hasInvalidDate
2876
+ ? {
2877
+ maxDate: {
2878
+ requiredMaxDate: maxDate,
2879
+ actualValue: control.value,
2880
+ },
2881
+ }
2882
+ : null;
2883
+ };
2884
+ }
2885
+ extractDates(value) {
2886
+ if (value === null || value === undefined || value === '') {
2887
+ return [];
2710
2888
  }
2711
- return '';
2889
+ const values = Array.isArray(value) ? value : [value];
2890
+ return values
2891
+ .map((item) => this.convertToDate(item))
2892
+ .filter((date) => date !== null);
2893
+ }
2894
+ convertToDate(value) {
2895
+ if (value === null || value === undefined || value === '') {
2896
+ return null;
2897
+ }
2898
+ if (value instanceof Date) {
2899
+ return Number.isNaN(value.getTime()) ? null : value;
2900
+ }
2901
+ const parsedDate = parseDate(value, this.resolvedDateFormat);
2902
+ return parsedDate && !Number.isNaN(parsedDate.getTime())
2903
+ ? parsedDate
2904
+ : null;
2905
+ }
2906
+ resolveFirstErrorKey(errors) {
2907
+ const priority = ['required', 'minDate', 'maxDate'];
2908
+ const prioritizedError = priority.find((key) => errors[key] !== undefined);
2909
+ return prioritizedError || Object.keys(errors)[0];
2910
+ }
2911
+ resolveHiddenValue(hidden) {
2912
+ if (typeof hidden === 'function') {
2913
+ return Boolean(hidden(this.activeFormGroup.getRawValue()));
2914
+ }
2915
+ return Boolean(hidden);
2712
2916
  }
2713
2917
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTDateInputComponent, deps: [{ token: PTDateService }], target: i0.ɵɵFactoryTarget.Component }); }
2714
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTDateInputComponent, isStandalone: false, selector: "pt-date-input", inputs: { formGroup: "formGroup", formField: "formField", config: "config", value: "value" }, outputs: { valueChange: "valueChange", dateChange: "dateChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!resolvedHidden) {\n <div\n [formGroup]=\"activeFormGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: resolvedWidth }\"\n >\n @if (resolvedLabel) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ resolvedLabel }}\n </label>\n }\n\n <p-datepicker\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [placeholder]=\"resolvedPlaceholder\"\n [dateFormat]=\"resolvedDateFormat\"\n [showIcon]=\"resolvedShowIcon\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [showTime]=\"\n resolvedDateInputType === 'datetime' || resolvedDateInputType === 'time'\n \"\n [timeOnly]=\"resolvedDateInputType === 'time'\"\n [hourFormat]=\"resolvedHourFormat\"\n [selectionMode]=\"resolvedDateInputType === 'range' ? 'range' : 'single'\"\n appendTo=\"body\"\n [panelStyle]=\"{ zIndex: 99999 }\"\n ></p-datepicker>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem;overflow:visible}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-datepicker.ng-invalid.ng-touched .p-inputtext,.form-field ::ng-deep .p-datepicker.ng-invalid.ng-dirty .p-inputtext{border-color:#dc2626}.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-touched,.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-dirty{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }] }); }
2918
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTDateInputComponent, isStandalone: false, selector: "pt-date-input", inputs: { formGroup: "formGroup", formField: "formField", config: "config", value: "value" }, outputs: { valueChange: "valueChange", dateChange: "dateChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!resolvedHidden) {\n <div\n class=\"form-field\"\n [formGroup]=\"activeFormGroup\"\n [ngClass]=\"{\n 'form-field-invalid':\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty),\n }\"\n [ngStyle]=\"{\n width: resolvedWidth,\n 'max-width': resolvedWidth,\n }\"\n >\n @if (resolvedLabel) {\n <label class=\"field-label\" [id]=\"labelId\" [for]=\"inputId\">\n {{ resolvedLabel }}\n\n @if (resolvedRequired) {\n <span class=\"required-indicator\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n <p-datepicker\n class=\"date-input\"\n styleClass=\"date-input-control\"\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [placeholder]=\"resolvedPlaceholder\"\n [dateFormat]=\"resolvedDateFormat\"\n [showIcon]=\"resolvedShowIcon\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [showTime]=\"\n resolvedDateInputType === 'datetime' || resolvedDateInputType === 'time'\n \"\n [timeOnly]=\"resolvedDateInputType === 'time'\"\n [hourFormat]=\"resolvedHourFormat\"\n [selectionMode]=\"resolvedDateInputType === 'range' ? 'range' : 'single'\"\n [readonlyInput]=\"false\"\n [showButtonBar]=\"true\"\n [appendTo]=\"'body'\"\n [panelStyle]=\"{\n 'z-index': 99999,\n }\"\n [attr.aria-labelledby]=\"resolvedLabel ? labelId : null\"\n [attr.aria-describedby]=\"\n activeFormGroup.get(controlName)?.invalid\n ? controlName + '-error'\n : null\n \"\n [attr.aria-invalid]=\"\n activeFormGroup.get(controlName)?.invalid ? 'true' : 'false'\n \"\n ></p-datepicker>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\" role=\"alert\" [id]=\"controlName + '-error'\">\n <i class=\"pi pi-exclamation-circle\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem;overflow:visible}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-datepicker.ng-invalid.ng-touched .p-inputtext,.form-field ::ng-deep .p-datepicker.ng-invalid.ng-dirty .p-inputtext{border-color:#dc2626}.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-touched,.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-dirty{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i7.DatePicker, selector: "p-datePicker, p-datepicker, p-date-picker", inputs: ["iconDisplay", "styleClass", "inputStyle", "inputId", "inputStyleClass", "placeholder", "ariaLabelledBy", "ariaLabel", "iconAriaLabel", "dateFormat", "multipleSeparator", "rangeSeparator", "inline", "showOtherMonths", "selectOtherMonths", "showIcon", "icon", "readonlyInput", "shortYearCutoff", "hourFormat", "timeOnly", "stepHour", "stepMinute", "stepSecond", "showSeconds", "showOnFocus", "showWeek", "startWeekFromFirstDayOfYear", "showClear", "dataType", "selectionMode", "maxDateCount", "showButtonBar", "todayButtonStyleClass", "clearButtonStyleClass", "autofocus", "autoZIndex", "baseZIndex", "panelStyleClass", "panelStyle", "keepInvalid", "hideOnDateTimeSelect", "touchUI", "timeSeparator", "focusTrap", "showTransitionOptions", "hideTransitionOptions", "tabindex", "minDate", "maxDate", "disabledDates", "disabledDays", "showTime", "responsiveOptions", "numberOfMonths", "firstDayOfWeek", "view", "defaultDate", "appendTo", "motionOptions"], outputs: ["onFocus", "onBlur", "onClose", "onSelect", "onClear", "onInput", "onTodayClick", "onClearClick", "onMonthChange", "onYearChange", "onClickOutside", "onShow"] }] }); }
2715
2919
  }
2716
2920
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTDateInputComponent, decorators: [{
2717
2921
  type: Component,
2718
- args: [{ selector: 'pt-date-input', standalone: false, template: "@if (!resolvedHidden) {\n <div\n [formGroup]=\"activeFormGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: resolvedWidth }\"\n >\n @if (resolvedLabel) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ resolvedLabel }}\n </label>\n }\n\n <p-datepicker\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [placeholder]=\"resolvedPlaceholder\"\n [dateFormat]=\"resolvedDateFormat\"\n [showIcon]=\"resolvedShowIcon\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [showTime]=\"\n resolvedDateInputType === 'datetime' || resolvedDateInputType === 'time'\n \"\n [timeOnly]=\"resolvedDateInputType === 'time'\"\n [hourFormat]=\"resolvedHourFormat\"\n [selectionMode]=\"resolvedDateInputType === 'range' ? 'range' : 'single'\"\n appendTo=\"body\"\n [panelStyle]=\"{ zIndex: 99999 }\"\n ></p-datepicker>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem;overflow:visible}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-datepicker.ng-invalid.ng-touched .p-inputtext,.form-field ::ng-deep .p-datepicker.ng-invalid.ng-dirty .p-inputtext{border-color:#dc2626}.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-touched,.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-dirty{border-color:#dc2626}\n"] }]
2922
+ args: [{ selector: 'pt-date-input', standalone: false, template: "@if (!resolvedHidden) {\n <div\n class=\"form-field\"\n [formGroup]=\"activeFormGroup\"\n [ngClass]=\"{\n 'form-field-invalid':\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty),\n }\"\n [ngStyle]=\"{\n width: resolvedWidth,\n 'max-width': resolvedWidth,\n }\"\n >\n @if (resolvedLabel) {\n <label class=\"field-label\" [id]=\"labelId\" [for]=\"inputId\">\n {{ resolvedLabel }}\n\n @if (resolvedRequired) {\n <span class=\"required-indicator\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n <p-datepicker\n class=\"date-input\"\n styleClass=\"date-input-control\"\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [placeholder]=\"resolvedPlaceholder\"\n [dateFormat]=\"resolvedDateFormat\"\n [showIcon]=\"resolvedShowIcon\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [showTime]=\"\n resolvedDateInputType === 'datetime' || resolvedDateInputType === 'time'\n \"\n [timeOnly]=\"resolvedDateInputType === 'time'\"\n [hourFormat]=\"resolvedHourFormat\"\n [selectionMode]=\"resolvedDateInputType === 'range' ? 'range' : 'single'\"\n [readonlyInput]=\"false\"\n [showButtonBar]=\"true\"\n [appendTo]=\"'body'\"\n [panelStyle]=\"{\n 'z-index': 99999,\n }\"\n [attr.aria-labelledby]=\"resolvedLabel ? labelId : null\"\n [attr.aria-describedby]=\"\n activeFormGroup.get(controlName)?.invalid\n ? controlName + '-error'\n : null\n \"\n [attr.aria-invalid]=\"\n activeFormGroup.get(controlName)?.invalid ? 'true' : 'false'\n \"\n ></p-datepicker>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\" role=\"alert\" [id]=\"controlName + '-error'\">\n <i class=\"pi pi-exclamation-circle\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem;overflow:visible}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-datepicker.ng-invalid.ng-touched .p-inputtext,.form-field ::ng-deep .p-datepicker.ng-invalid.ng-dirty .p-inputtext{border-color:#dc2626}.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-touched,.form-field ::ng-deep .p-datepicker-input.ng-invalid.ng-dirty{border-color:#dc2626}\n"] }]
2719
2923
  }], ctorParameters: () => [{ type: PTDateService }], propDecorators: { formGroup: [{
2720
2924
  type: Input
2721
2925
  }], formField: [{
@@ -2730,18 +2934,63 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
2730
2934
  type: Output
2731
2935
  }] } });
2732
2936
 
2937
+ // projects/ng-prime-tools/src/lib/pt-number-input/pt-number-input.component.ts
2733
2938
  class PTNumberInputComponent {
2734
2939
  ngOnInit() {
2735
2940
  this.setupControl();
2736
2941
  }
2737
2942
  ngOnChanges(changes) {
2738
- if (changes['formField'] && !changes['formField'].firstChange) {
2943
+ if (changes['formGroup'] || changes['formField']) {
2739
2944
  this.setupControl();
2740
2945
  }
2741
2946
  }
2742
2947
  get inputId() {
2743
2948
  return `pt-number-${this.formField?.name || 'field'}`;
2744
2949
  }
2950
+ get errorId() {
2951
+ return `pt-number-error-${this.formField?.name || 'field'}`;
2952
+ }
2953
+ get isInvalid() {
2954
+ const control = this.formGroup?.get(this.formField?.name);
2955
+ return Boolean(control &&
2956
+ control.enabled &&
2957
+ control.invalid &&
2958
+ (control.touched || control.dirty));
2959
+ }
2960
+ getErrorMessage() {
2961
+ const control = this.formGroup.get(this.formField.name);
2962
+ if (!control?.errors) {
2963
+ return '';
2964
+ }
2965
+ const errorKey = this.resolveFirstErrorKey(control.errors);
2966
+ if (!errorKey) {
2967
+ return '';
2968
+ }
2969
+ const customMessage = this.formField.validationMessages?.[errorKey];
2970
+ if (customMessage) {
2971
+ return customMessage;
2972
+ }
2973
+ if (this.formField.errorText) {
2974
+ return this.formField.errorText;
2975
+ }
2976
+ const label = this.formField.label?.trim() || this.formField.name;
2977
+ switch (errorKey) {
2978
+ case 'required':
2979
+ return `${label} is required`;
2980
+ case 'min': {
2981
+ const minValue = control.getError('min')?.min ?? this.formField.minValue;
2982
+ return `${label} must be at least ${minValue}`;
2983
+ }
2984
+ case 'max': {
2985
+ const maxValue = control.getError('max')?.max ?? this.formField.maxValue;
2986
+ return `${label} must be at most ${maxValue}`;
2987
+ }
2988
+ case 'pattern':
2989
+ return `${label} is invalid`;
2990
+ default:
2991
+ return `${label} is invalid`;
2992
+ }
2993
+ }
2745
2994
  setupControl() {
2746
2995
  const name = this.formField?.name;
2747
2996
  if (!name || !this.formGroup) {
@@ -2749,24 +2998,30 @@ class PTNumberInputComponent {
2749
2998
  }
2750
2999
  let control = this.formGroup.get(name);
2751
3000
  if (!control) {
2752
- control = new FormControl(this.formField?.value ?? null);
3001
+ control = new FormControl(this.formField.value ?? null);
2753
3002
  this.formGroup.addControl(name, control);
2754
3003
  }
2755
3004
  control.setValidators(this.getValidators());
2756
- if (this.formField?.disabled) {
2757
- control.disable({ emitEvent: false });
3005
+ if (this.formField.disabled) {
3006
+ control.disable({
3007
+ emitEvent: false,
3008
+ });
2758
3009
  }
2759
3010
  else {
2760
- control.enable({ emitEvent: false });
3011
+ control.enable({
3012
+ emitEvent: false,
3013
+ });
2761
3014
  }
2762
- control.updateValueAndValidity({ emitEvent: false });
3015
+ control.updateValueAndValidity({
3016
+ emitEvent: false,
3017
+ });
2763
3018
  }
2764
3019
  getValidators() {
2765
3020
  const validators = [];
2766
- if (this.formField?.required) {
3021
+ if (this.formField.required) {
2767
3022
  validators.push(Validators.required);
2768
3023
  }
2769
- if (this.formField?.minValue !== undefined &&
3024
+ if (this.formField.minValue !== undefined &&
2770
3025
  this.formField.minValue !== null) {
2771
3026
  const minValue = Number(this.formField.minValue);
2772
3027
  if (!Number.isNaN(minValue)) {
@@ -2776,7 +3031,7 @@ class PTNumberInputComponent {
2776
3031
  console.error(`Invalid minValue: ${this.formField.minValue} is not a number.`);
2777
3032
  }
2778
3033
  }
2779
- if (this.formField?.maxValue !== undefined &&
3034
+ if (this.formField.maxValue !== undefined &&
2780
3035
  this.formField.maxValue !== null) {
2781
3036
  const maxValue = Number(this.formField.maxValue);
2782
3037
  if (!Number.isNaN(maxValue)) {
@@ -2786,47 +3041,41 @@ class PTNumberInputComponent {
2786
3041
  console.error(`Invalid maxValue: ${this.formField.maxValue} is not a number.`);
2787
3042
  }
2788
3043
  }
2789
- if (this.formField?.inputValidation) {
3044
+ if (this.formField.inputValidation) {
2790
3045
  validators.push(this.validateWithInputValidation(this.formField.inputValidation));
2791
3046
  }
3047
+ else if (this.formField.pattern) {
3048
+ validators.push(Validators.pattern(this.formField.pattern));
3049
+ }
3050
+ if (Array.isArray(this.formField.validators) &&
3051
+ this.formField.validators.length > 0) {
3052
+ validators.push(...this.formField.validators);
3053
+ }
2792
3054
  return validators;
2793
3055
  }
2794
3056
  validateWithInputValidation(inputValidation) {
2795
3057
  return Validators.pattern(new RegExp(inputValidation));
2796
3058
  }
2797
- getErrorMessage() {
2798
- const control = this.formGroup.get(this.formField.name);
2799
- if (control?.hasError('required')) {
2800
- return this.formField.errorText || `${this.formField.label} is required`;
2801
- }
2802
- if (control?.hasError('min')) {
2803
- return `${this.formField.label} must be at least ${this.formField.minValue}`;
2804
- }
2805
- if (control?.hasError('max')) {
2806
- return `${this.formField.label} must be at most ${this.formField.maxValue}`;
2807
- }
2808
- if (control?.hasError('pattern')) {
2809
- return `${this.formField.label} is invalid`;
2810
- }
2811
- return '';
3059
+ resolveFirstErrorKey(errors) {
3060
+ const priority = ['required', 'min', 'max', 'pattern'];
3061
+ return (priority.find((key) => errors[key] !== undefined) ||
3062
+ Object.keys(errors)[0]);
2812
3063
  }
2813
3064
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTNumberInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2814
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTNumberInputComponent, isStandalone: false, selector: "pt-number-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: formField.width || '100%' }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n <p-inputGroup>\n @if (!formField.iconPosition || formField.iconPosition === \"left\") {\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n\n <p-inputNumber\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits || 0\"\n [maxFractionDigits]=\"formField.decimalDigits || 0\"\n [placeholder]=\"formField.placeholder || ''\"\n ></p-inputNumber>\n }\n\n @if (formField.iconPosition === \"right\") {\n <p-inputNumber\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits || 0\"\n [maxFractionDigits]=\"formField.decimalDigits || 0\"\n [placeholder]=\"formField.placeholder || ''\"\n ></p-inputNumber>\n\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n\n @if (\n formGroup.get(formField.name)?.invalid &&\n (formGroup.get(formField.name)?.touched ||\n formGroup.get(formField.name)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-field ::ng-deep .p-inputnumber{width:100%}.form-field ::ng-deep .p-inputnumber-input{width:100%}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-inputnumber.ng-invalid.ng-touched .p-inputnumber-input,.form-field ::ng-deep .p-inputnumber.ng-invalid.ng-dirty .p-inputnumber-input{border-color:#dc2626}.form-field ::ng-deep .p-inputnumber-input.ng-invalid.ng-touched,.form-field ::ng-deep .p-inputnumber-input.ng-invalid.ng-dirty{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$2.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "component", type: i4.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "component", type: i8$1.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }] }); }
3065
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTNumberInputComponent, isStandalone: false, selector: "pt-number-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-number-input/pt-number-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n 'max-width': formField.width || '100%',\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n <p-inputGroup class=\"number-input-group\">\n @if (!formField.iconPosition || formField.iconPosition === \"left\") {\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\" aria-hidden=\"true\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n\n <p-inputNumber\n class=\"number-input\"\n styleClass=\"number-input-control\"\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits ?? 0\"\n [maxFractionDigits]=\"formField.decimalDigits ?? 0\"\n [min]=\"\n formField.minValue !== undefined && formField.minValue !== null\n ? +formField.minValue\n : undefined\n \"\n [max]=\"\n formField.maxValue !== undefined && formField.maxValue !== null\n ? +formField.maxValue\n : undefined\n \"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></p-inputNumber>\n }\n\n @if (formField.iconPosition === \"right\") {\n <p-inputNumber\n class=\"number-input\"\n styleClass=\"number-input-control\"\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits ?? 0\"\n [maxFractionDigits]=\"formField.decimalDigits ?? 0\"\n [min]=\"\n formField.minValue !== undefined && formField.minValue !== null\n ? +formField.minValue\n : undefined\n \"\n [max]=\"\n formField.maxValue !== undefined && formField.maxValue !== null\n ? +formField.maxValue\n : undefined\n \"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></p-inputNumber>\n\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\" aria-hidden=\"true\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n\n @if (isInvalid) {\n <div class=\"error-container\" role=\"alert\" [id]=\"errorId\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{display:flex;flex-direction:column;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.field-label{display:block;margin-bottom:.5rem;font-size:1rem;font-weight:600}.required-indicator{margin-left:.2rem;color:#ef4444}.number-input-group{display:flex;width:100%;min-width:0;max-width:100%}:host ::ng-deep .number-input-group.p-inputgroup,:host ::ng-deep .number-input-group .p-inputgroup{display:flex;width:100%;min-width:0;max-width:100%}.number-input{display:block;flex:1 1 auto;width:100%;min-width:0;max-width:100%}:host ::ng-deep .number-input-control,:host ::ng-deep .number-input.p-inputnumber,:host ::ng-deep .number-input .p-inputnumber{flex:1 1 auto;width:100%;min-width:0;max-width:100%}:host ::ng-deep .number-input .p-inputnumber-input{width:100%;min-width:0}:host ::ng-deep .p-inputgroup-addon{flex:0 0 auto}.form-field-invalid ::ng-deep .p-inputnumber-input{border-color:#ef4444!important}.error-container{display:flex;align-items:flex-start;gap:.35rem;margin-top:.35rem;color:#ef4444}.error-container .pi{flex:0 0 auto;margin-top:.1rem;font-size:.8rem}.field-error{min-width:0;color:inherit;font-size:.8rem;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$2.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "component", type: i4.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }, { kind: "component", type: i8$1.InputNumber, selector: "p-inputNumber, p-inputnumber, p-input-number", inputs: ["showButtons", "format", "buttonLayout", "inputId", "styleClass", "placeholder", "tabindex", "title", "ariaLabelledBy", "ariaDescribedBy", "ariaLabel", "ariaRequired", "autocomplete", "incrementButtonClass", "decrementButtonClass", "incrementButtonIcon", "decrementButtonIcon", "readonly", "allowEmpty", "locale", "localeMatcher", "mode", "currency", "currencyDisplay", "useGrouping", "minFractionDigits", "maxFractionDigits", "prefix", "suffix", "inputStyle", "inputStyleClass", "showClear", "autofocus"], outputs: ["onInput", "onFocus", "onBlur", "onKeyDown", "onClear"] }] }); }
2815
3066
  }
2816
3067
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTNumberInputComponent, decorators: [{
2817
3068
  type: Component,
2818
- args: [{ selector: 'pt-number-input', standalone: false, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: formField.width || '100%' }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n <p-inputGroup>\n @if (!formField.iconPosition || formField.iconPosition === \"left\") {\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n\n <p-inputNumber\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits || 0\"\n [maxFractionDigits]=\"formField.decimalDigits || 0\"\n [placeholder]=\"formField.placeholder || ''\"\n ></p-inputNumber>\n }\n\n @if (formField.iconPosition === \"right\") {\n <p-inputNumber\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits || 0\"\n [maxFractionDigits]=\"formField.decimalDigits || 0\"\n [placeholder]=\"formField.placeholder || ''\"\n ></p-inputNumber>\n\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n\n @if (\n formGroup.get(formField.name)?.invalid &&\n (formGroup.get(formField.name)?.touched ||\n formGroup.get(formField.name)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-field ::ng-deep .p-inputnumber{width:100%}.form-field ::ng-deep .p-inputnumber-input{width:100%}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-inputnumber.ng-invalid.ng-touched .p-inputnumber-input,.form-field ::ng-deep .p-inputnumber.ng-invalid.ng-dirty .p-inputnumber-input{border-color:#dc2626}.form-field ::ng-deep .p-inputnumber-input.ng-invalid.ng-touched,.form-field ::ng-deep .p-inputnumber-input.ng-invalid.ng-dirty{border-color:#dc2626}\n"] }]
3069
+ args: [{ selector: 'pt-number-input', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-number-input/pt-number-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n 'max-width': formField.width || '100%',\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n <p-inputGroup class=\"number-input-group\">\n @if (!formField.iconPosition || formField.iconPosition === \"left\") {\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\" aria-hidden=\"true\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n\n <p-inputNumber\n class=\"number-input\"\n styleClass=\"number-input-control\"\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits ?? 0\"\n [maxFractionDigits]=\"formField.decimalDigits ?? 0\"\n [min]=\"\n formField.minValue !== undefined && formField.minValue !== null\n ? +formField.minValue\n : undefined\n \"\n [max]=\"\n formField.maxValue !== undefined && formField.maxValue !== null\n ? +formField.maxValue\n : undefined\n \"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></p-inputNumber>\n }\n\n @if (formField.iconPosition === \"right\") {\n <p-inputNumber\n class=\"number-input\"\n styleClass=\"number-input-control\"\n [inputId]=\"inputId\"\n [name]=\"formField.name\"\n [formControlName]=\"formField.name\"\n mode=\"decimal\"\n [locale]=\"formField.numberFormat || undefined\"\n [useGrouping]=\"!!formField.numberFormat\"\n [minFractionDigits]=\"formField.decimalDigits ?? 0\"\n [maxFractionDigits]=\"formField.decimalDigits ?? 0\"\n [min]=\"\n formField.minValue !== undefined && formField.minValue !== null\n ? +formField.minValue\n : undefined\n \"\n [max]=\"\n formField.maxValue !== undefined && formField.maxValue !== null\n ? +formField.maxValue\n : undefined\n \"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></p-inputNumber>\n\n @if (formField.iconClass || formField.currency) {\n <p-inputGroupAddon>\n @if (formField.iconClass) {\n <i [ngClass]=\"formField.iconClass\" aria-hidden=\"true\"></i>\n }\n\n @if (!formField.iconClass && formField.currency) {\n <span>\n {{ formField.currency }}\n </span>\n }\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n\n @if (isInvalid) {\n <div class=\"error-container\" role=\"alert\" [id]=\"errorId\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{display:flex;flex-direction:column;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.field-label{display:block;margin-bottom:.5rem;font-size:1rem;font-weight:600}.required-indicator{margin-left:.2rem;color:#ef4444}.number-input-group{display:flex;width:100%;min-width:0;max-width:100%}:host ::ng-deep .number-input-group.p-inputgroup,:host ::ng-deep .number-input-group .p-inputgroup{display:flex;width:100%;min-width:0;max-width:100%}.number-input{display:block;flex:1 1 auto;width:100%;min-width:0;max-width:100%}:host ::ng-deep .number-input-control,:host ::ng-deep .number-input.p-inputnumber,:host ::ng-deep .number-input .p-inputnumber{flex:1 1 auto;width:100%;min-width:0;max-width:100%}:host ::ng-deep .number-input .p-inputnumber-input{width:100%;min-width:0}:host ::ng-deep .p-inputgroup-addon{flex:0 0 auto}.form-field-invalid ::ng-deep .p-inputnumber-input{border-color:#ef4444!important}.error-container{display:flex;align-items:flex-start;gap:.35rem;margin-top:.35rem;color:#ef4444}.error-container .pi{flex:0 0 auto;margin-top:.1rem;font-size:.8rem}.field-error{min-width:0;color:inherit;font-size:.8rem;overflow-wrap:anywhere}\n"] }]
2819
3070
  }], propDecorators: { formGroup: [{
2820
3071
  type: Input
2821
3072
  }], formField: [{
2822
3073
  type: Input
2823
3074
  }] } });
2824
3075
 
3076
+ // projects/ng-prime-tools/src/lib/pt-switch-input/pt-switch-input.component.ts
2825
3077
  class PTSwitchInputComponent {
2826
3078
  constructor() {
2827
- /**
2828
- * Two-way standalone value.
2829
- */
2830
3079
  this.value = null;
2831
3080
  this.valueChange = new EventEmitter();
2832
3081
  this.switchChange = new EventEmitter();
@@ -2859,7 +3108,8 @@ class PTSwitchInputComponent {
2859
3108
  return `pt-switch-label-${this.controlName}`;
2860
3109
  }
2861
3110
  get resolvedHidden() {
2862
- return this.formField?.hidden ?? this.config?.hidden ?? false;
3111
+ const hidden = this.formField?.hidden ?? this.config?.hidden;
3112
+ return this.resolveHiddenValue(hidden);
2863
3113
  }
2864
3114
  get resolvedLabel() {
2865
3115
  return this.formField?.label || this.config?.label;
@@ -2876,6 +3126,28 @@ class PTSwitchInputComponent {
2876
3126
  get resolvedErrorText() {
2877
3127
  return this.formField?.errorText || this.config?.errorText;
2878
3128
  }
3129
+ getErrorMessage() {
3130
+ const control = this.activeFormGroup.get(this.controlName);
3131
+ if (!control?.errors) {
3132
+ return '';
3133
+ }
3134
+ const errorKey = Object.keys(control.errors)[0];
3135
+ if (!errorKey) {
3136
+ return '';
3137
+ }
3138
+ const customMessage = this.formField?.validationMessages?.[errorKey];
3139
+ if (customMessage) {
3140
+ return customMessage;
3141
+ }
3142
+ if (this.resolvedErrorText) {
3143
+ return this.resolvedErrorText;
3144
+ }
3145
+ const label = this.resolvedLabel || this.controlName;
3146
+ if (control.hasError('requiredChoice')) {
3147
+ return `${label} is required`;
3148
+ }
3149
+ return `${label} is invalid`;
3150
+ }
2879
3151
  setupControl() {
2880
3152
  const name = this.controlName;
2881
3153
  if (!name) {
@@ -2889,16 +3161,24 @@ class PTSwitchInputComponent {
2889
3161
  this.activeFormGroup.addControl(name, control);
2890
3162
  }
2891
3163
  else if (!this.formGroup && this.hasExplicitFieldValue(this.value)) {
2892
- control.setValue(this.value, { emitEvent: false });
3164
+ control.setValue(this.value, {
3165
+ emitEvent: false,
3166
+ });
2893
3167
  }
2894
3168
  control.setValidators(this.getValidators());
2895
3169
  if (this.resolvedDisabled) {
2896
- control.disable({ emitEvent: false });
3170
+ control.disable({
3171
+ emitEvent: false,
3172
+ });
2897
3173
  }
2898
3174
  else {
2899
- control.enable({ emitEvent: false });
3175
+ control.enable({
3176
+ emitEvent: false,
3177
+ });
2900
3178
  }
2901
- control.updateValueAndValidity({ emitEvent: false });
3179
+ control.updateValueAndValidity({
3180
+ emitEvent: false,
3181
+ });
2902
3182
  this.valueChangesSubscription?.unsubscribe();
2903
3183
  this.valueChangesSubscription = control.valueChanges.subscribe((selectedValue) => {
2904
3184
  this.valueChange.emit(selectedValue);
@@ -2922,22 +3202,26 @@ class PTSwitchInputComponent {
2922
3202
  if (this.resolvedRequired) {
2923
3203
  validators.push(this.requireChoiceValidator());
2924
3204
  }
3205
+ if (Array.isArray(this.formField?.validators) &&
3206
+ this.formField.validators.length > 0) {
3207
+ validators.push(...this.formField.validators);
3208
+ }
2925
3209
  return validators;
2926
3210
  }
2927
3211
  requireChoiceValidator() {
2928
3212
  return (control) => {
2929
3213
  return control.value !== null && control.value !== undefined
2930
3214
  ? null
2931
- : { requiredChoice: true };
3215
+ : {
3216
+ requiredChoice: true,
3217
+ };
2932
3218
  };
2933
3219
  }
2934
- getErrorMessage() {
2935
- const control = this.activeFormGroup.get(this.controlName);
2936
- if (control?.errors?.['requiredChoice']) {
2937
- return (this.resolvedErrorText ||
2938
- `${this.resolvedLabel || this.controlName} is required`);
3220
+ resolveHiddenValue(hidden) {
3221
+ if (typeof hidden === 'function') {
3222
+ return Boolean(hidden(this.activeFormGroup.getRawValue()));
2939
3223
  }
2940
- return '';
3224
+ return Boolean(hidden);
2941
3225
  }
2942
3226
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTSwitchInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
2943
3227
  static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTSwitchInputComponent, isStandalone: false, selector: "pt-switch-input", inputs: { formGroup: "formGroup", formField: "formField", config: "config", value: "value" }, outputs: { valueChange: "valueChange", switchChange: "switchChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!resolvedHidden) {\n <div\n [formGroup]=\"activeFormGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: resolvedWidth }\"\n >\n <div class=\"switch-container\">\n <p-toggleswitch\n [inputId]=\"inputId\"\n [formControlName]=\"controlName\"\n [ariaLabelledBy]=\"labelId\"\n ></p-toggleswitch>\n\n @if (resolvedLabel) {\n <label [id]=\"labelId\" [for]=\"inputId\" class=\"switch-label\">\n {{ resolvedLabel }}\n </label>\n }\n </div>\n\n @if (\n activeFormGroup.get(controlName)?.errors &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{margin-bottom:1rem}.switch-container{display:flex;align-items:center;gap:.5rem;min-height:2.75rem}.switch-label{display:inline-flex;align-items:center;margin:0;padding:0;font-weight:600;font-size:1rem;line-height:1;cursor:pointer}.error-container{margin-top:.25rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-toggleswitch.ng-invalid.ng-touched .p-toggleswitch-slider,.form-field ::ng-deep .p-toggleswitch.ng-invalid.ng-dirty .p-toggleswitch-slider{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$3.ToggleSwitch, selector: "p-toggleswitch, p-toggleSwitch, p-toggle-switch", inputs: ["styleClass", "tabindex", "inputId", "readonly", "trueValue", "falseValue", "ariaLabel", "size", "ariaLabelledBy", "autofocus"], outputs: ["onChange"] }] }); }
@@ -2959,6 +3243,7 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
2959
3243
  type: Output
2960
3244
  }] } });
2961
3245
 
3246
+ // projects/ng-prime-tools/src/lib/pt-text-area-input/pt-text-area-input.component.ts
2962
3247
  class PTTextAreaInputComponent {
2963
3248
  constructor() {
2964
3249
  this.characterCount = 0;
@@ -2968,14 +3253,63 @@ class PTTextAreaInputComponent {
2968
3253
  this.updateCharacterCount();
2969
3254
  }
2970
3255
  ngOnChanges(changes) {
2971
- if (changes['formField'] && !changes['formField'].firstChange) {
3256
+ if (changes['formGroup'] || changes['formField']) {
2972
3257
  this.setupControl();
2973
3258
  this.updateCharacterCount();
2974
3259
  }
2975
3260
  }
3261
+ ngOnDestroy() {
3262
+ this.valueChangesSubscription?.unsubscribe();
3263
+ }
2976
3264
  get inputId() {
2977
3265
  return `pt-textarea-${this.formField?.name || 'field'}`;
2978
3266
  }
3267
+ get errorId() {
3268
+ return `pt-textarea-error-${this.formField?.name || 'field'}`;
3269
+ }
3270
+ get isInvalid() {
3271
+ const control = this.formGroup?.get(this.formField?.name);
3272
+ return Boolean(control &&
3273
+ control.enabled &&
3274
+ control.invalid &&
3275
+ (control.touched || control.dirty));
3276
+ }
3277
+ getErrorMessage() {
3278
+ const control = this.formGroup.get(this.formField.name);
3279
+ if (!control?.errors) {
3280
+ return '';
3281
+ }
3282
+ const errorKey = this.resolveFirstErrorKey(control.errors);
3283
+ if (!errorKey) {
3284
+ return '';
3285
+ }
3286
+ const customMessage = this.formField.validationMessages?.[errorKey];
3287
+ if (customMessage) {
3288
+ return customMessage;
3289
+ }
3290
+ if (this.formField.errorText) {
3291
+ return this.formField.errorText;
3292
+ }
3293
+ const label = this.formField.label?.trim() || this.formField.name;
3294
+ switch (errorKey) {
3295
+ case 'required':
3296
+ return `${label} is required`;
3297
+ case 'minlength': {
3298
+ const requiredLength = control.getError('minlength')?.requiredLength ??
3299
+ this.formField.minLength;
3300
+ return `${label} must be at least ${requiredLength} characters long`;
3301
+ }
3302
+ case 'maxlength': {
3303
+ const requiredLength = control.getError('maxlength')?.requiredLength ??
3304
+ this.formField.maxLength;
3305
+ return `${label} must be at most ${requiredLength} characters long`;
3306
+ }
3307
+ case 'pattern':
3308
+ return `${label} is invalid`;
3309
+ default:
3310
+ return `${label} is invalid`;
3311
+ }
3312
+ }
2979
3313
  setupControl() {
2980
3314
  const name = this.formField?.name;
2981
3315
  if (!name || !this.formGroup) {
@@ -2983,18 +3317,25 @@ class PTTextAreaInputComponent {
2983
3317
  }
2984
3318
  let control = this.formGroup.get(name);
2985
3319
  if (!control) {
2986
- control = new FormControl(this.formField?.value ?? null);
3320
+ control = new FormControl(this.formField.value ?? null);
2987
3321
  this.formGroup.addControl(name, control);
2988
3322
  }
2989
3323
  control.setValidators(this.getValidators());
2990
- if (this.formField?.disabled) {
2991
- control.disable({ emitEvent: false });
3324
+ if (this.formField.disabled) {
3325
+ control.disable({
3326
+ emitEvent: false,
3327
+ });
2992
3328
  }
2993
3329
  else {
2994
- control.enable({ emitEvent: false });
3330
+ control.enable({
3331
+ emitEvent: false,
3332
+ });
2995
3333
  }
2996
- control.updateValueAndValidity({ emitEvent: false });
2997
- control.valueChanges.subscribe(() => {
3334
+ control.updateValueAndValidity({
3335
+ emitEvent: false,
3336
+ });
3337
+ this.valueChangesSubscription?.unsubscribe();
3338
+ this.valueChangesSubscription = control.valueChanges.subscribe(() => {
2998
3339
  this.updateCharacterCount();
2999
3340
  });
3000
3341
  }
@@ -3005,55 +3346,55 @@ class PTTextAreaInputComponent {
3005
3346
  return;
3006
3347
  }
3007
3348
  const value = control.value;
3008
- this.characterCount = value ? String(value).length : 0;
3349
+ this.characterCount =
3350
+ value === null || value === undefined ? 0 : String(value).length;
3009
3351
  }
3010
3352
  getValidators() {
3011
3353
  const validators = [];
3012
- if (this.formField?.required) {
3354
+ if (this.formField.required) {
3013
3355
  validators.push(Validators.required);
3014
3356
  }
3015
- if (this.formField?.minLength !== undefined) {
3357
+ if (this.formField.minLength !== undefined &&
3358
+ this.formField.minLength !== null) {
3016
3359
  validators.push(Validators.minLength(this.formField.minLength));
3017
3360
  }
3018
- if (this.formField?.maxLength !== undefined) {
3361
+ if (this.formField.maxLength !== undefined &&
3362
+ this.formField.maxLength !== null) {
3019
3363
  validators.push(Validators.maxLength(this.formField.maxLength));
3020
3364
  }
3021
- if (this.formField?.inputValidation) {
3365
+ if (this.formField.inputValidation) {
3022
3366
  validators.push(this.validateWithInputValidation(this.formField.inputValidation));
3023
3367
  }
3368
+ else if (this.formField.pattern) {
3369
+ validators.push(Validators.pattern(this.formField.pattern));
3370
+ }
3371
+ if (Array.isArray(this.formField.validators) &&
3372
+ this.formField.validators.length > 0) {
3373
+ validators.push(...this.formField.validators);
3374
+ }
3024
3375
  return validators;
3025
3376
  }
3026
3377
  validateWithInputValidation(inputValidation) {
3027
3378
  return Validators.pattern(new RegExp(inputValidation));
3028
3379
  }
3029
- getErrorMessage() {
3030
- const control = this.formGroup.get(this.formField.name);
3031
- if (control?.hasError('required')) {
3032
- return this.formField.errorText || `${this.formField.label} is required`;
3033
- }
3034
- if (control?.hasError('minlength')) {
3035
- return `${this.formField.label} must be at least ${this.formField.minLength} characters long`;
3036
- }
3037
- if (control?.hasError('maxlength')) {
3038
- return `${this.formField.label} must be at most ${this.formField.maxLength} characters long`;
3039
- }
3040
- if (control?.hasError('pattern')) {
3041
- return `${this.formField.label} is invalid`;
3042
- }
3043
- return '';
3380
+ resolveFirstErrorKey(errors) {
3381
+ const priority = ['required', 'minlength', 'maxlength', 'pattern'];
3382
+ return (priority.find((key) => errors[key] !== undefined) ||
3383
+ Object.keys(errors)[0]);
3044
3384
  }
3045
3385
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTTextAreaInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3046
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTTextAreaInputComponent, isStandalone: false, selector: "pt-text-area-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: formField.width || '100%' }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\">{{ formField.label }}</label>\n }\n <p-inputGroup>\n @if (!formField.iconPosition || formField.iconPosition === 'left') {\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n <textarea\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [cols]=\"formField.cols || 30\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n ></textarea>\n }\n @if (formField.iconPosition === 'right') {\n <textarea\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [cols]=\"formField.cols || 30\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n ></textarea>\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n <div class=\"form-info-row\">\n @if (\n formGroup.get(formField.name)?.invalid &&\n (formGroup.get(formField.name)?.touched ||\n formGroup.get(formField.name)?.dirty)\n ) {\n <small\n class=\"p-error\"\n >\n {{ getErrorMessage() }}\n </small>\n }\n <div class=\"spacer\"></div>\n @if (!formField.disabled && formField.maxLength !== undefined) {\n <div\n class=\"character-counter\"\n >\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n </div>\n}\n", styles: [".form-field{position:relative;margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700;font-size:1rem}.form-info-row{display:flex;justify-content:space-between;align-items:center;margin-top:.5rem}.spacer{flex-grow:1}.character-counter{font-size:.8rem;color:#888;text-align:right;margin-left:auto}.p-error{font-size:.8rem;color:#f44336}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i3$4.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "component", type: i3$2.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "component", type: i4.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }] }); }
3386
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTTextAreaInputComponent, isStandalone: false, selector: "pt-text-area-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-text-area-input/pt-text-area-input.component.html -->\n\n<div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n }\"\n>\n @if (formField.label) {\n <label [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n <p-inputGroup class=\"textarea-input-group\">\n @if (!formField.iconPosition || formField.iconPosition === \"left\") {\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n\n <textarea\n class=\"textarea-control\"\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></textarea>\n }\n\n @if (formField.iconPosition === \"right\") {\n <textarea\n class=\"textarea-control\"\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></textarea>\n\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n\n <div class=\"form-info-row\">\n @if (isInvalid) {\n <small class=\"p-error\" role=\"alert\" [id]=\"errorId\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (!formField.disabled && formField.maxLength !== undefined) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}:host *,:host *:before,:host *:after{box-sizing:border-box}.form-field{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.form-field label{display:block;width:100%;margin-bottom:.5rem;font-size:1rem;font-weight:700}.textarea-input-group{display:flex;width:100%;min-width:0;max-width:100%}:host ::ng-deep .textarea-input-group.p-inputgroup,:host ::ng-deep .textarea-input-group .p-inputgroup{display:flex;width:100%;min-width:0;max-width:100%}.textarea-control{display:block;flex:1 1 auto;width:100%;min-width:0;max-width:100%;resize:vertical}:host ::ng-deep .textarea-control.p-textarea,:host ::ng-deep textarea.textarea-control{display:block;flex:1 1 auto;width:100%!important;min-width:0;max-width:100%}:host ::ng-deep .p-inputgroup textarea{flex:1 1 auto;width:100%!important;min-width:0}:host ::ng-deep .p-inputgroup-addon{flex:0 0 auto}.form-info-row{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem;width:100%;min-width:0;margin-top:.5rem}.spacer{flex:1 1 auto;min-width:0}.character-counter{flex:0 0 auto;margin-left:auto;color:#888;font-size:.8rem;text-align:right;white-space:nowrap}.p-error{min-width:0;color:#f44336;font-size:.8rem;overflow-wrap:anywhere}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i3$4.Textarea, selector: "[pTextarea], [pInputTextarea]", inputs: ["pTextareaPT", "pTextareaUnstyled", "autoResize", "pSize", "variant", "fluid", "invalid"], outputs: ["onResize"] }, { kind: "component", type: i3$2.InputGroup, selector: "p-inputgroup, p-inputGroup, p-input-group", inputs: ["styleClass"] }, { kind: "component", type: i4.InputGroupAddon, selector: "p-inputgroup-addon, p-inputGroupAddon", inputs: ["style", "styleClass"] }] }); }
3047
3387
  }
3048
3388
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTTextAreaInputComponent, decorators: [{
3049
3389
  type: Component,
3050
- args: [{ selector: 'pt-text-area-input', standalone: false, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: formField.width || '100%' }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\">{{ formField.label }}</label>\n }\n <p-inputGroup>\n @if (!formField.iconPosition || formField.iconPosition === 'left') {\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n <textarea\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [cols]=\"formField.cols || 30\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n ></textarea>\n }\n @if (formField.iconPosition === 'right') {\n <textarea\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [cols]=\"formField.cols || 30\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n ></textarea>\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n <div class=\"form-info-row\">\n @if (\n formGroup.get(formField.name)?.invalid &&\n (formGroup.get(formField.name)?.touched ||\n formGroup.get(formField.name)?.dirty)\n ) {\n <small\n class=\"p-error\"\n >\n {{ getErrorMessage() }}\n </small>\n }\n <div class=\"spacer\"></div>\n @if (!formField.disabled && formField.maxLength !== undefined) {\n <div\n class=\"character-counter\"\n >\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n </div>\n}\n", styles: [".form-field{position:relative;margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700;font-size:1rem}.form-info-row{display:flex;justify-content:space-between;align-items:center;margin-top:.5rem}.spacer{flex-grow:1}.character-counter{font-size:.8rem;color:#888;text-align:right;margin-left:auto}.p-error{font-size:.8rem;color:#f44336}\n"] }]
3390
+ args: [{ selector: 'pt-text-area-input', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-text-area-input/pt-text-area-input.component.html -->\n\n<div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n }\"\n>\n @if (formField.label) {\n <label [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n <p-inputGroup class=\"textarea-input-group\">\n @if (!formField.iconPosition || formField.iconPosition === \"left\") {\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n\n <textarea\n class=\"textarea-control\"\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></textarea>\n }\n\n @if (formField.iconPosition === \"right\") {\n <textarea\n class=\"textarea-control\"\n [id]=\"inputId\"\n pTextarea\n [formControlName]=\"formField.name\"\n [rows]=\"formField.rows || 5\"\n [autoResize]=\"formField.autoResize || false\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [placeholder]=\"formField.placeholder || ''\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n ></textarea>\n\n @if (formField.iconClass) {\n <p-inputGroupAddon>\n <i [ngClass]=\"formField.iconClass\"></i>\n </p-inputGroupAddon>\n }\n }\n </p-inputGroup>\n\n <div class=\"form-info-row\">\n @if (isInvalid) {\n <small class=\"p-error\" role=\"alert\" [id]=\"errorId\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (!formField.disabled && formField.maxLength !== undefined) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}:host *,:host *:before,:host *:after{box-sizing:border-box}.form-field{position:relative;display:flex;flex-direction:column;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.form-field label{display:block;width:100%;margin-bottom:.5rem;font-size:1rem;font-weight:700}.textarea-input-group{display:flex;width:100%;min-width:0;max-width:100%}:host ::ng-deep .textarea-input-group.p-inputgroup,:host ::ng-deep .textarea-input-group .p-inputgroup{display:flex;width:100%;min-width:0;max-width:100%}.textarea-control{display:block;flex:1 1 auto;width:100%;min-width:0;max-width:100%;resize:vertical}:host ::ng-deep .textarea-control.p-textarea,:host ::ng-deep textarea.textarea-control{display:block;flex:1 1 auto;width:100%!important;min-width:0;max-width:100%}:host ::ng-deep .p-inputgroup textarea{flex:1 1 auto;width:100%!important;min-width:0}:host ::ng-deep .p-inputgroup-addon{flex:0 0 auto}.form-info-row{display:flex;align-items:flex-start;justify-content:space-between;gap:.5rem;width:100%;min-width:0;margin-top:.5rem}.spacer{flex:1 1 auto;min-width:0}.character-counter{flex:0 0 auto;margin-left:auto;color:#888;font-size:.8rem;text-align:right;white-space:nowrap}.p-error{min-width:0;color:#f44336;font-size:.8rem;overflow-wrap:anywhere}\n"] }]
3051
3391
  }], propDecorators: { formGroup: [{
3052
3392
  type: Input
3053
3393
  }], formField: [{
3054
3394
  type: Input
3055
3395
  }] } });
3056
3396
 
3397
+ // projects/ng-prime-tools/src/lib/pt-text-input/pt-text-input.component.ts
3057
3398
  class PTTextInputComponent {
3058
3399
  constructor() {
3059
3400
  this.characterCount = 0;
@@ -3062,38 +3403,27 @@ class PTTextInputComponent {
3062
3403
  this.setupControl();
3063
3404
  this.updateCharacterCount();
3064
3405
  }
3406
+ ngOnChanges(changes) {
3407
+ if (changes['formGroup'] || changes['formField']) {
3408
+ this.setupControl();
3409
+ this.updateCharacterCount();
3410
+ }
3411
+ }
3065
3412
  ngOnDestroy() {
3066
3413
  this.valueChangesSubscription?.unsubscribe();
3067
3414
  }
3068
3415
  get inputId() {
3069
3416
  return `pt-input-${this.formField?.name || 'field'}`;
3070
3417
  }
3071
- setupControl() {
3072
- const control = this.formGroup.get(this.formField.name);
3073
- if (!control) {
3074
- return;
3075
- }
3076
- control.setValidators(this.getValidators());
3077
- this.valueChangesSubscription?.unsubscribe();
3078
- if (this.formField.disabled) {
3079
- control.disable({ emitEvent: false });
3080
- }
3081
- else {
3082
- control.enable({ emitEvent: false });
3083
- this.valueChangesSubscription = control.valueChanges.subscribe(() => {
3084
- this.updateCharacterCount();
3085
- });
3086
- }
3087
- control.updateValueAndValidity({ emitEvent: false });
3418
+ get errorId() {
3419
+ return `pt-input-error-${this.formField?.name || 'field'}`;
3088
3420
  }
3089
- updateCharacterCount() {
3090
- const control = this.formGroup.get(this.formField.name);
3091
- if (!control) {
3092
- this.characterCount = 0;
3093
- return;
3094
- }
3095
- const value = control.value;
3096
- this.characterCount = value != null ? String(value).length : 0;
3421
+ get isInvalid() {
3422
+ const control = this.formGroup?.get(this.formField?.name);
3423
+ return Boolean(control &&
3424
+ control.enabled &&
3425
+ control.invalid &&
3426
+ (control.touched || control.dirty));
3097
3427
  }
3098
3428
  getInputType() {
3099
3429
  switch (this.formField.type) {
@@ -3116,15 +3446,100 @@ class PTTextInputComponent {
3116
3446
  getPasswordFeedback() {
3117
3447
  return this.formField.feedback ?? false;
3118
3448
  }
3449
+ hasCharacterCounter() {
3450
+ return !this.formField.disabled && this.formField.maxLength !== undefined;
3451
+ }
3452
+ hasInfoRow() {
3453
+ return this.isInvalid || this.hasCharacterCounter();
3454
+ }
3455
+ getErrorMessage() {
3456
+ const control = this.formGroup?.get(this.formField?.name);
3457
+ if (!control?.errors) {
3458
+ return '';
3459
+ }
3460
+ const errorKey = this.resolveFirstErrorKey(control.errors);
3461
+ if (!errorKey) {
3462
+ return '';
3463
+ }
3464
+ const customMessage = this.formField.validationMessages?.[errorKey];
3465
+ if (customMessage) {
3466
+ return customMessage;
3467
+ }
3468
+ if (this.formField.errorText) {
3469
+ return this.formField.errorText;
3470
+ }
3471
+ const label = this.formField.label?.trim() || this.formField.name;
3472
+ switch (errorKey) {
3473
+ case 'required':
3474
+ return `${label} is required`;
3475
+ case 'email':
3476
+ return `${label} is not a valid email`;
3477
+ case 'minlength': {
3478
+ const requiredLength = control.getError('minlength')?.requiredLength ??
3479
+ this.formField.minLength;
3480
+ return `${label} must be at least ${requiredLength} characters`;
3481
+ }
3482
+ case 'maxlength': {
3483
+ const requiredLength = control.getError('maxlength')?.requiredLength ??
3484
+ this.formField.maxLength;
3485
+ return `${label} must be at most ${requiredLength} characters`;
3486
+ }
3487
+ case 'pattern':
3488
+ return `${label} is invalid`;
3489
+ default:
3490
+ return `${label} is invalid`;
3491
+ }
3492
+ }
3493
+ setupControl() {
3494
+ const name = this.formField?.name;
3495
+ if (!name || !this.formGroup) {
3496
+ return;
3497
+ }
3498
+ let control = this.formGroup.get(name);
3499
+ if (!control) {
3500
+ control = new FormControl(this.formField.value ?? null);
3501
+ this.formGroup.addControl(name, control);
3502
+ }
3503
+ control.setValidators(this.getValidators());
3504
+ if (this.formField.disabled) {
3505
+ control.disable({
3506
+ emitEvent: false,
3507
+ });
3508
+ }
3509
+ else {
3510
+ control.enable({
3511
+ emitEvent: false,
3512
+ });
3513
+ }
3514
+ control.updateValueAndValidity({
3515
+ emitEvent: false,
3516
+ });
3517
+ this.valueChangesSubscription?.unsubscribe();
3518
+ this.valueChangesSubscription = control.valueChanges.subscribe(() => {
3519
+ this.updateCharacterCount();
3520
+ });
3521
+ }
3522
+ updateCharacterCount() {
3523
+ const control = this.formGroup?.get(this.formField?.name);
3524
+ if (!control) {
3525
+ this.characterCount = 0;
3526
+ return;
3527
+ }
3528
+ const value = control.value;
3529
+ this.characterCount =
3530
+ value === null || value === undefined ? 0 : String(value).length;
3531
+ }
3119
3532
  getValidators() {
3120
3533
  const validators = [];
3121
3534
  if (this.formField.required) {
3122
3535
  validators.push(Validators.required);
3123
3536
  }
3124
- if (this.formField.minLength !== undefined) {
3537
+ if (this.formField.minLength !== undefined &&
3538
+ this.formField.minLength !== null) {
3125
3539
  validators.push(Validators.minLength(this.formField.minLength));
3126
3540
  }
3127
- if (this.formField.maxLength !== undefined) {
3541
+ if (this.formField.maxLength !== undefined &&
3542
+ this.formField.maxLength !== null) {
3128
3543
  validators.push(Validators.maxLength(this.formField.maxLength));
3129
3544
  }
3130
3545
  if (this.formField.type === FormInputTypeEnum.EMAIL) {
@@ -3133,46 +3548,29 @@ class PTTextInputComponent {
3133
3548
  if (this.formField.inputValidation) {
3134
3549
  validators.push(this.validateWithInputValidation(this.formField.inputValidation));
3135
3550
  }
3551
+ else if (this.formField.pattern) {
3552
+ validators.push(Validators.pattern(this.formField.pattern));
3553
+ }
3554
+ if (Array.isArray(this.formField.validators) &&
3555
+ this.formField.validators.length > 0) {
3556
+ validators.push(...this.formField.validators);
3557
+ }
3136
3558
  return validators;
3137
3559
  }
3138
3560
  validateWithInputValidation(inputValidation) {
3139
3561
  return Validators.pattern(new RegExp(inputValidation));
3140
3562
  }
3141
- getErrorMessage() {
3142
- const control = this.formGroup.get(this.formField.name);
3143
- if (control?.hasError('required')) {
3144
- return `${this.formField.label} is required`;
3145
- }
3146
- if (control?.hasError('email')) {
3147
- return `${this.formField.label} is not a valid email`;
3148
- }
3149
- if (control?.hasError('minlength')) {
3150
- return `${this.formField.label} must be at least ${this.formField.minLength} characters`;
3151
- }
3152
- if (control?.hasError('maxlength')) {
3153
- return `${this.formField.label} must be at most ${this.formField.maxLength} characters`;
3154
- }
3155
- if (control?.hasError('pattern')) {
3156
- return `${this.formField.label} is invalid`;
3157
- }
3158
- return '';
3159
- }
3160
- hasError() {
3161
- const control = this.formGroup.get(this.formField.name);
3162
- return !!(control?.invalid && (control.touched || control.dirty));
3163
- }
3164
- hasCharacterCounter() {
3165
- return !this.formField.disabled && this.formField.maxLength !== undefined;
3166
- }
3167
- hasInfoRow() {
3168
- return this.hasError() || this.hasCharacterCounter();
3563
+ resolveFirstErrorKey(errors) {
3564
+ const priority = ['required', 'email', 'minlength', 'maxlength', 'pattern'];
3565
+ return (priority.find((key) => errors[key] !== undefined) ||
3566
+ Object.keys(errors)[0]);
3169
3567
  }
3170
3568
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTTextInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3171
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTTextInputComponent, isStandalone: false, selector: "pt-text-input", inputs: { formGroup: "formGroup", formField: "formField" }, ngImport: i0, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField [iconPosition]=\"formField.iconPosition || 'left'\">\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n pInputText\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n </p-iconField>\n } @else {\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n pInputText\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (hasError()) {\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.character-counter{font-size:.8rem;font-weight:500;color:#64748b;white-space:nowrap}.form-field input.ng-invalid.ng-touched,.form-field input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input{width:100%!important;display:block!important}::ng-deep .pt-password-input .p-password{width:100%!important;display:block!important}::ng-deep .pt-password-input .p-password-input{width:100%!important}::ng-deep .pt-password-input input{width:100%!important;box-sizing:border-box}::ng-deep .pt-password-input.ng-invalid.ng-touched input,::ng-deep .pt-password-input.ng-invalid.ng-dirty input,::ng-deep .pt-password-input input.ng-invalid.ng-touched,::ng-deep .pt-password-input input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input .p-password-toggle-mask-icon,::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i10.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "component", type: i6$1.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }] }); }
3569
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTTextInputComponent, isStandalone: false, selector: "pt-text-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-text-input/pt-text-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField\n class=\"text-icon-field\"\n [iconPosition]=\"formField.iconPosition || 'left'\"\n >\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n pInputText\n class=\"pt-text-input\"\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [ngStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n </p-iconField>\n } @else {\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n pInputText\n class=\"pt-text-input\"\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [ngStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (isInvalid) {\n <small class=\"field-error\" role=\"alert\" [id]=\"errorId\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{width:100%;min-width:0}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.required-indicator{margin-left:.2rem;color:#dc2626}.text-icon-field{display:block;width:100%;min-width:0}.pt-text-input{width:100%;min-width:0;box-sizing:border-box}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;min-width:0;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2;overflow-wrap:anywhere}.character-counter{flex:0 0 auto;color:#64748b;font-size:.8rem;font-weight:500;white-space:nowrap}.form-field-invalid .pt-text-input{border-color:#dc2626}:host ::ng-deep .text-icon-field.p-iconfield,:host ::ng-deep .text-icon-field .p-iconfield{display:block;width:100%;min-width:0}:host ::ng-deep .pt-password-input{display:block;width:100%;min-width:0}:host ::ng-deep .pt-password-input.p-password,:host ::ng-deep .pt-password-input .p-password{display:block;width:100%;min-width:0}:host ::ng-deep .pt-password-input .p-password-input,:host ::ng-deep .pt-password-input input{width:100%;min-width:0;box-sizing:border-box}.form-field-invalid ::ng-deep .pt-password-input .p-password-input{border-color:#dc2626}:host ::ng-deep .pt-password-input .p-password-toggle-mask-icon,:host ::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i5.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pInputTextPT", "pInputTextUnstyled", "pSize", "variant", "fluid", "invalid"] }, { kind: "component", type: i10.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "component", type: i6$1.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }] }); }
3172
3570
  }
3173
3571
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTTextInputComponent, decorators: [{
3174
3572
  type: Component,
3175
- args: [{ selector: 'pt-text-input', standalone: false, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField [iconPosition]=\"formField.iconPosition || 'left'\">\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n pInputText\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n </p-iconField>\n } @else {\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n pInputText\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (hasError()) {\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.character-counter{font-size:.8rem;font-weight:500;color:#64748b;white-space:nowrap}.form-field input.ng-invalid.ng-touched,.form-field input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input{width:100%!important;display:block!important}::ng-deep .pt-password-input .p-password{width:100%!important;display:block!important}::ng-deep .pt-password-input .p-password-input{width:100%!important}::ng-deep .pt-password-input input{width:100%!important;box-sizing:border-box}::ng-deep .pt-password-input.ng-invalid.ng-touched input,::ng-deep .pt-password-input.ng-invalid.ng-dirty input,::ng-deep .pt-password-input input.ng-invalid.ng-touched,::ng-deep .pt-password-input input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input .p-password-toggle-mask-icon,::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"] }]
3573
+ args: [{ selector: 'pt-text-input', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-text-input/pt-text-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField\n class=\"text-icon-field\"\n [iconPosition]=\"formField.iconPosition || 'left'\"\n >\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n pInputText\n class=\"pt-text-input\"\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [ngStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n </p-iconField>\n } @else {\n @if (isPasswordInput()) {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n } @else {\n <input\n pInputText\n class=\"pt-text-input\"\n [id]=\"inputId\"\n [attr.name]=\"formField.name\"\n [type]=\"getInputType()\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [attr.minlength]=\"formField.minLength\"\n [attr.maxlength]=\"formField.maxLength\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [ngStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n />\n }\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (isInvalid) {\n <small class=\"field-error\" role=\"alert\" [id]=\"errorId\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{width:100%;min-width:0}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.required-indicator{margin-left:.2rem;color:#dc2626}.text-icon-field{display:block;width:100%;min-width:0}.pt-text-input{width:100%;min-width:0;box-sizing:border-box}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;min-width:0;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2;overflow-wrap:anywhere}.character-counter{flex:0 0 auto;color:#64748b;font-size:.8rem;font-weight:500;white-space:nowrap}.form-field-invalid .pt-text-input{border-color:#dc2626}:host ::ng-deep .text-icon-field.p-iconfield,:host ::ng-deep .text-icon-field .p-iconfield{display:block;width:100%;min-width:0}:host ::ng-deep .pt-password-input{display:block;width:100%;min-width:0}:host ::ng-deep .pt-password-input.p-password,:host ::ng-deep .pt-password-input .p-password{display:block;width:100%;min-width:0}:host ::ng-deep .pt-password-input .p-password-input,:host ::ng-deep .pt-password-input input{width:100%;min-width:0;box-sizing:border-box}.form-field-invalid ::ng-deep .pt-password-input .p-password-input{border-color:#dc2626}:host ::ng-deep .pt-password-input .p-password-toggle-mask-icon,:host ::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"] }]
3176
3574
  }], propDecorators: { formGroup: [{
3177
3575
  type: Input
3178
3576
  }], formField: [{
@@ -3216,7 +3614,11 @@ class PTDropdownComponent {
3216
3614
  return `pt-dropdown-label-${this.controlName}`;
3217
3615
  }
3218
3616
  get resolvedHidden() {
3219
- return this.formField?.hidden ?? this.config?.hidden ?? false;
3617
+ const hidden = this.formField?.hidden;
3618
+ if (typeof hidden === 'function') {
3619
+ return Boolean(hidden(this.activeFormGroup.getRawValue()));
3620
+ }
3621
+ return hidden ?? this.config?.hidden ?? false;
3220
3622
  }
3221
3623
  get resolvedLabel() {
3222
3624
  return this.formField?.label || this.config?.label;
@@ -3428,11 +3830,11 @@ class PTDropdownComponent {
3428
3830
  return 'left';
3429
3831
  }
3430
3832
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTDropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3431
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTDropdownComponent, isStandalone: false, selector: "pt-dropdown", inputs: { formGroup: "formGroup", formField: "formField", config: "config", value: "value" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!resolvedHidden) {\n <div\n [formGroup]=\"activeFormGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: resolvedWidth }\"\n >\n @if (resolvedLabel) {\n <label [id]=\"labelId\" class=\"field-label\">\n {{ resolvedLabel }}\n </label>\n }\n\n <p-select\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [options]=\"resolvedOptions\"\n [placeholder]=\"resolvedPlaceholder\"\n [optionLabel]=\"resolvedOptionLabel\"\n [optionValue]=\"resolvedOptionValue\"\n [optionDisabled]=\"resolvedOptionDisabled\"\n [dataKey]=\"resolvedOptionValue\"\n [filter]=\"resolvedFilter\"\n [filterBy]=\"resolvedFilterBy\"\n [appendTo]=\"'body'\"\n [overlayOptions]=\"{ baseZIndex: 11000 }\"\n [ariaLabelledBy]=\"labelId\"\n >\n <ng-template pTemplate=\"selectedItem\" let-option>\n @if (option) {\n <div class=\"pt-dropdown-item\">\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n class=\"pt-dropdown-icon-image\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n class=\"pt-dropdown-icon-font\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n } @else {\n <span>{{ resolvedPlaceholder }}</span>\n }\n </ng-template>\n\n <ng-template pTemplate=\"item\" let-option>\n <div\n class=\"pt-dropdown-item\"\n [class.pt-dropdown-parent-option]=\"option?.isParent\"\n [class.pt-dropdown-child-option]=\"option?.isChild\"\n [class.pt-dropdown-disabled-option]=\"option?.disabled\"\n [ngStyle]=\"{ 'padding-left': option?.indent || '0rem' }\"\n >\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n class=\"pt-dropdown-icon-image\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n class=\"pt-dropdown-icon-font\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n </ng-template>\n </p-select>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{display:flex;flex-direction:column;margin-bottom:1rem;gap:.25rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700;font-size:1rem}.pt-dropdown-item{display:flex;align-items:center;gap:.55rem}.pt-dropdown-label{display:inline-block}.pt-dropdown-parent-option{font-weight:700}.pt-dropdown-child-option{font-weight:400}.pt-dropdown-disabled-option{opacity:.65;cursor:not-allowed}.pt-dropdown-icon-font{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;text-align:center}.pt-dropdown-icon-image{object-fit:cover}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-select.ng-invalid.ng-touched{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] }); }
3833
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTDropdownComponent, isStandalone: false, selector: "pt-dropdown", inputs: { formGroup: "formGroup", formField: "formField", config: "config", value: "value" }, outputs: { valueChange: "valueChange", selectionChange: "selectionChange" }, usesOnChanges: true, ngImport: i0, template: "@if (!resolvedHidden) {\n <div\n class=\"form-field\"\n [formGroup]=\"activeFormGroup\"\n [ngClass]=\"{\n 'form-field-invalid':\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty),\n }\"\n [ngStyle]=\"{\n width: resolvedWidth,\n 'max-width': resolvedWidth,\n }\"\n >\n @if (resolvedLabel) {\n <label class=\"field-label\" [id]=\"labelId\" [for]=\"inputId\">\n {{ resolvedLabel }}\n\n @if (resolvedRequired) {\n <span class=\"required-indicator\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n <p-select\n class=\"dropdown-input\"\n styleClass=\"dropdown-input-control\"\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [options]=\"resolvedOptions\"\n [placeholder]=\"resolvedPlaceholder\"\n [optionLabel]=\"resolvedOptionLabel\"\n [optionValue]=\"resolvedOptionValue\"\n [optionDisabled]=\"resolvedOptionDisabled\"\n [dataKey]=\"resolvedOptionValue\"\n [filter]=\"resolvedFilter\"\n [filterBy]=\"resolvedFilterBy\"\n [appendTo]=\"'body'\"\n [overlayOptions]=\"{\n baseZIndex: 11000,\n }\"\n [ariaLabelledBy]=\"resolvedLabel ? labelId : undefined\"\n [attr.aria-describedby]=\"\n activeFormGroup.get(controlName)?.invalid\n ? controlName + '-error'\n : null\n \"\n [attr.aria-invalid]=\"\n activeFormGroup.get(controlName)?.invalid ? 'true' : 'false'\n \"\n >\n <ng-template pTemplate=\"selectedItem\" let-option>\n @if (option) {\n <div class=\"pt-dropdown-item\">\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n class=\"pt-dropdown-icon-image\"\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n alt=\"\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n class=\"pt-dropdown-icon-font\"\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n aria-hidden=\"true\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n } @else {\n <span class=\"pt-dropdown-placeholder\">\n {{ resolvedPlaceholder }}\n </span>\n }\n </ng-template>\n\n <ng-template pTemplate=\"item\" let-option>\n <div\n class=\"pt-dropdown-item\"\n [class.pt-dropdown-parent-option]=\"option?.isParent\"\n [class.pt-dropdown-child-option]=\"option?.isChild\"\n [class.pt-dropdown-disabled-option]=\"option?.[resolvedOptionDisabled]\"\n [ngStyle]=\"{\n 'padding-left': option?.indent || '0rem',\n }\"\n >\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n class=\"pt-dropdown-icon-image\"\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n alt=\"\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n class=\"pt-dropdown-icon-font\"\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n aria-hidden=\"true\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n </ng-template>\n </p-select>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\" role=\"alert\" [id]=\"controlName + '-error'\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{display:flex;flex-direction:column;margin-bottom:1rem;gap:.25rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700;font-size:1rem}.pt-dropdown-item{display:flex;align-items:center;gap:.55rem}.pt-dropdown-label{display:inline-block}.pt-dropdown-parent-option{font-weight:700}.pt-dropdown-child-option{font-weight:400}.pt-dropdown-disabled-option{opacity:.65;cursor:not-allowed}.pt-dropdown-icon-font{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;text-align:center}.pt-dropdown-icon-image{object-fit:cover}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-select.ng-invalid.ng-touched{border-color:#dc2626}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo", "motionOptions"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "directive", type: i1$1.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }] }); }
3432
3834
  }
3433
3835
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTDropdownComponent, decorators: [{
3434
3836
  type: Component,
3435
- args: [{ selector: 'pt-dropdown', standalone: false, template: "@if (!resolvedHidden) {\n <div\n [formGroup]=\"activeFormGroup\"\n class=\"form-field\"\n [ngStyle]=\"{ width: resolvedWidth }\"\n >\n @if (resolvedLabel) {\n <label [id]=\"labelId\" class=\"field-label\">\n {{ resolvedLabel }}\n </label>\n }\n\n <p-select\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [options]=\"resolvedOptions\"\n [placeholder]=\"resolvedPlaceholder\"\n [optionLabel]=\"resolvedOptionLabel\"\n [optionValue]=\"resolvedOptionValue\"\n [optionDisabled]=\"resolvedOptionDisabled\"\n [dataKey]=\"resolvedOptionValue\"\n [filter]=\"resolvedFilter\"\n [filterBy]=\"resolvedFilterBy\"\n [appendTo]=\"'body'\"\n [overlayOptions]=\"{ baseZIndex: 11000 }\"\n [ariaLabelledBy]=\"labelId\"\n >\n <ng-template pTemplate=\"selectedItem\" let-option>\n @if (option) {\n <div class=\"pt-dropdown-item\">\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n class=\"pt-dropdown-icon-image\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n class=\"pt-dropdown-icon-font\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n } @else {\n <span>{{ resolvedPlaceholder }}</span>\n }\n </ng-template>\n\n <ng-template pTemplate=\"item\" let-option>\n <div\n class=\"pt-dropdown-item\"\n [class.pt-dropdown-parent-option]=\"option?.isParent\"\n [class.pt-dropdown-child-option]=\"option?.isChild\"\n [class.pt-dropdown-disabled-option]=\"option?.disabled\"\n [ngStyle]=\"{ 'padding-left': option?.indent || '0rem' }\"\n >\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n class=\"pt-dropdown-icon-image\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n class=\"pt-dropdown-icon-font\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n </ng-template>\n </p-select>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\">\n <small class=\"field-error\">{{ getErrorMessage() }}</small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{display:flex;flex-direction:column;margin-bottom:1rem;gap:.25rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700;font-size:1rem}.pt-dropdown-item{display:flex;align-items:center;gap:.55rem}.pt-dropdown-label{display:inline-block}.pt-dropdown-parent-option{font-weight:700}.pt-dropdown-child-option{font-weight:400}.pt-dropdown-disabled-option{opacity:.65;cursor:not-allowed}.pt-dropdown-icon-font{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;text-align:center}.pt-dropdown-icon-image{object-fit:cover}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-select.ng-invalid.ng-touched{border-color:#dc2626}\n"] }]
3837
+ args: [{ selector: 'pt-dropdown', standalone: false, template: "@if (!resolvedHidden) {\n <div\n class=\"form-field\"\n [formGroup]=\"activeFormGroup\"\n [ngClass]=\"{\n 'form-field-invalid':\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty),\n }\"\n [ngStyle]=\"{\n width: resolvedWidth,\n 'max-width': resolvedWidth,\n }\"\n >\n @if (resolvedLabel) {\n <label class=\"field-label\" [id]=\"labelId\" [for]=\"inputId\">\n {{ resolvedLabel }}\n\n @if (resolvedRequired) {\n <span class=\"required-indicator\" aria-hidden=\"true\">*</span>\n }\n </label>\n }\n\n <p-select\n class=\"dropdown-input\"\n styleClass=\"dropdown-input-control\"\n [inputId]=\"inputId\"\n [name]=\"controlName\"\n [formControlName]=\"controlName\"\n [options]=\"resolvedOptions\"\n [placeholder]=\"resolvedPlaceholder\"\n [optionLabel]=\"resolvedOptionLabel\"\n [optionValue]=\"resolvedOptionValue\"\n [optionDisabled]=\"resolvedOptionDisabled\"\n [dataKey]=\"resolvedOptionValue\"\n [filter]=\"resolvedFilter\"\n [filterBy]=\"resolvedFilterBy\"\n [appendTo]=\"'body'\"\n [overlayOptions]=\"{\n baseZIndex: 11000,\n }\"\n [ariaLabelledBy]=\"resolvedLabel ? labelId : undefined\"\n [attr.aria-describedby]=\"\n activeFormGroup.get(controlName)?.invalid\n ? controlName + '-error'\n : null\n \"\n [attr.aria-invalid]=\"\n activeFormGroup.get(controlName)?.invalid ? 'true' : 'false'\n \"\n >\n <ng-template pTemplate=\"selectedItem\" let-option>\n @if (option) {\n <div class=\"pt-dropdown-item\">\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n class=\"pt-dropdown-icon-image\"\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n alt=\"\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n class=\"pt-dropdown-icon-font\"\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n aria-hidden=\"true\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n } @else {\n <span class=\"pt-dropdown-placeholder\">\n {{ resolvedPlaceholder }}\n </span>\n }\n </ng-template>\n\n <ng-template pTemplate=\"item\" let-option>\n <div\n class=\"pt-dropdown-item\"\n [class.pt-dropdown-parent-option]=\"option?.isParent\"\n [class.pt-dropdown-child-option]=\"option?.isChild\"\n [class.pt-dropdown-disabled-option]=\"option?.[resolvedOptionDisabled]\"\n [ngStyle]=\"{\n 'padding-left': option?.indent || '0rem',\n }\"\n >\n @if (getResolvedIcon(option); as iconMeta) {\n @if (iconMeta.type === \"image\") {\n <img\n class=\"pt-dropdown-icon-image\"\n [src]=\"iconMeta.imageUrl\"\n [ngStyle]=\"iconMeta.imageStyle\"\n alt=\"\"\n />\n }\n\n @if (iconMeta.type === \"font\") {\n <i\n class=\"pt-dropdown-icon-font\"\n [ngClass]=\"iconMeta.fontIconClass\"\n [ngStyle]=\"iconMeta.fontIconStyle\"\n aria-hidden=\"true\"\n ></i>\n }\n }\n\n <span class=\"pt-dropdown-label\">\n {{ option[resolvedOptionLabel] }}\n </span>\n </div>\n </ng-template>\n </p-select>\n\n @if (\n activeFormGroup.get(controlName)?.invalid &&\n (activeFormGroup.get(controlName)?.touched ||\n activeFormGroup.get(controlName)?.dirty)\n ) {\n <div class=\"error-container\" role=\"alert\" [id]=\"controlName + '-error'\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n </div>\n}\n", styles: [".form-field{display:flex;flex-direction:column;margin-bottom:1rem;gap:.25rem}.field-label{display:block;margin-bottom:.5rem;font-weight:700;font-size:1rem}.pt-dropdown-item{display:flex;align-items:center;gap:.55rem}.pt-dropdown-label{display:inline-block}.pt-dropdown-parent-option{font-weight:700}.pt-dropdown-child-option{font-weight:400}.pt-dropdown-disabled-option{opacity:.65;cursor:not-allowed}.pt-dropdown-icon-font{display:inline-flex;align-items:center;justify-content:center;width:1.25rem;text-align:center}.pt-dropdown-icon-image{object-fit:cover}.error-container{margin-top:.35rem}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.form-field ::ng-deep .p-select.ng-invalid.ng-touched{border-color:#dc2626}\n"] }]
3436
3838
  }], propDecorators: { formGroup: [{
3437
3839
  type: Input
3438
3840
  }], formField: [{
@@ -3545,18 +3947,25 @@ class PTOtpInputComponent {
3545
3947
  control.setValue(normalizedValue, { emitEvent: false });
3546
3948
  }
3547
3949
  }
3950
+ get labelId() {
3951
+ return `pt-otp-label-${this.formField?.name || 'field'}`;
3952
+ }
3953
+ get errorId() {
3954
+ return `pt-otp-error-${this.formField?.name || 'field'}`;
3955
+ }
3548
3956
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTOtpInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3549
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTOtpInputComponent, isStandalone: false, selector: "pt-otp-input", inputs: { formGroup: "formGroup", formField: "formField" }, ngImport: i0, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n >\n @if (formField.label) {\n <label class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n <div class=\"otp-input-wrapper\">\n <p-inputOtp\n [formControlName]=\"formField.name\"\n [length]=\"resolvedLength\"\n [integerOnly]=\"resolvedIntegerOnly\"\n [mask]=\"resolvedMask\"\n [readonly]=\"formField.disabled ?? false\"\n styleClass=\"pt-otp-input\"\n ></p-inputOtp>\n </div>\n\n @if (hasError()) {\n <div class=\"form-info-row\">\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n </div>\n}\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.85rem;color:#172554;font-size:1.1rem;font-weight:700;letter-spacing:.01em}.otp-input-wrapper{display:flex;width:100%;justify-content:center}.form-info-row{display:flex;min-height:1.35rem;margin-top:.65rem;justify-content:center}.field-error{color:#fca5a5;font-size:.82rem;font-weight:600;text-align:center}:host ::ng-deep .pt-otp-input{display:flex;width:100%;justify-content:center;gap:.7rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:3.7rem;height:4rem;border:2px solid rgba(255,255,255,.62);border-radius:.85rem;background:#fffffff0;box-shadow:0 6px 14px #0f172a29,inset 0 1px #ffffffe6;color:#172554;font-size:1.75rem;font-weight:800;text-align:center;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease}:host ::ng-deep .pt-otp-input .p-inputotp-input:hover{border-color:#60a5fa;transform:translateY(-2px)}:host ::ng-deep .pt-otp-input .p-inputotp-input:focus{border-color:#2563eb;box-shadow:0 0 0 4px #2563eb33,0 8px 18px #0f172a33;outline:none}@media(max-width:480px){:host ::ng-deep .pt-otp-input{gap:.42rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:2.85rem;height:3.3rem;font-size:1.4rem}}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$6.InputOtp, selector: "p-inputOtp, p-inputotp, p-input-otp", inputs: ["readonly", "tabindex", "length", "styleClass", "mask", "integerOnly", "autofocus", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }] }); }
3957
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTOtpInputComponent, isStandalone: false, selector: "pt-otp-input", inputs: { formGroup: "formGroup", formField: "formField" }, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-otp-input/pt-otp-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': hasError(),\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [id]=\"labelId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n <div class=\"otp-input-wrapper\">\n <p-inputOtp\n [formControlName]=\"formField.name\"\n [length]=\"resolvedLength\"\n [integerOnly]=\"resolvedIntegerOnly\"\n [mask]=\"resolvedMask\"\n [readonly]=\"formField.disabled ?? false\"\n [attr.aria-labelledby]=\"formField.label ? labelId : null\"\n [attr.aria-describedby]=\"hasError() ? errorId : null\"\n [attr.aria-invalid]=\"hasError() ? 'true' : 'false'\"\n styleClass=\"pt-otp-input\"\n ></p-inputOtp>\n </div>\n\n @if (hasError()) {\n <div class=\"form-info-row\" role=\"alert\" [id]=\"errorId\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{width:100%;min-width:0}.field-label{display:block;margin-bottom:.85rem;color:#172554;font-size:1.1rem;font-weight:700;letter-spacing:.01em}.required-indicator{margin-left:.2rem;color:#ef4444}.otp-input-wrapper{display:flex;width:100%;min-width:0;justify-content:center}.form-info-row{display:flex;align-items:center;min-height:1.35rem;margin-top:.65rem;justify-content:center;gap:.35rem;color:#fca5a5}.form-info-row .pi{font-size:.8rem}.field-error{color:inherit;font-size:.82rem;font-weight:600;text-align:center}:host ::ng-deep .pt-otp-input{display:flex;width:100%;min-width:0;justify-content:center;gap:.7rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:3.7rem;height:4rem;border:2px solid rgba(255,255,255,.62);border-radius:.85rem;background:#fffffff0;box-shadow:0 6px 14px #0f172a29,inset 0 1px #ffffffe6;color:#172554;font-size:1.75rem;font-weight:800;text-align:center;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease}:host ::ng-deep .pt-otp-input .p-inputotp-input:hover{border-color:#60a5fa;transform:translateY(-2px)}:host ::ng-deep .pt-otp-input .p-inputotp-input:focus{border-color:#2563eb;box-shadow:0 0 0 4px #2563eb33,0 8px 18px #0f172a33;outline:none}.form-field-invalid ::ng-deep .pt-otp-input .p-inputotp-input{border-color:#ef4444}@media(max-width:480px){:host ::ng-deep .pt-otp-input{gap:.42rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:2.85rem;height:3.3rem;font-size:1.4rem}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i3$6.InputOtp, selector: "p-inputOtp, p-inputotp, p-input-otp", inputs: ["readonly", "tabindex", "length", "styleClass", "mask", "integerOnly", "autofocus", "variant", "size"], outputs: ["onChange", "onFocus", "onBlur"] }] }); }
3550
3958
  }
3551
3959
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTOtpInputComponent, decorators: [{
3552
3960
  type: Component,
3553
- args: [{ selector: 'pt-otp-input', standalone: false, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n >\n @if (formField.label) {\n <label class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n <div class=\"otp-input-wrapper\">\n <p-inputOtp\n [formControlName]=\"formField.name\"\n [length]=\"resolvedLength\"\n [integerOnly]=\"resolvedIntegerOnly\"\n [mask]=\"resolvedMask\"\n [readonly]=\"formField.disabled ?? false\"\n styleClass=\"pt-otp-input\"\n ></p-inputOtp>\n </div>\n\n @if (hasError()) {\n <div class=\"form-info-row\">\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n </div>\n}\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.85rem;color:#172554;font-size:1.1rem;font-weight:700;letter-spacing:.01em}.otp-input-wrapper{display:flex;width:100%;justify-content:center}.form-info-row{display:flex;min-height:1.35rem;margin-top:.65rem;justify-content:center}.field-error{color:#fca5a5;font-size:.82rem;font-weight:600;text-align:center}:host ::ng-deep .pt-otp-input{display:flex;width:100%;justify-content:center;gap:.7rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:3.7rem;height:4rem;border:2px solid rgba(255,255,255,.62);border-radius:.85rem;background:#fffffff0;box-shadow:0 6px 14px #0f172a29,inset 0 1px #ffffffe6;color:#172554;font-size:1.75rem;font-weight:800;text-align:center;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease}:host ::ng-deep .pt-otp-input .p-inputotp-input:hover{border-color:#60a5fa;transform:translateY(-2px)}:host ::ng-deep .pt-otp-input .p-inputotp-input:focus{border-color:#2563eb;box-shadow:0 0 0 4px #2563eb33,0 8px 18px #0f172a33;outline:none}@media(max-width:480px){:host ::ng-deep .pt-otp-input{gap:.42rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:2.85rem;height:3.3rem;font-size:1.4rem}}\n"] }]
3961
+ args: [{ selector: 'pt-otp-input', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-otp-input/pt-otp-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': hasError(),\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [id]=\"labelId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n <div class=\"otp-input-wrapper\">\n <p-inputOtp\n [formControlName]=\"formField.name\"\n [length]=\"resolvedLength\"\n [integerOnly]=\"resolvedIntegerOnly\"\n [mask]=\"resolvedMask\"\n [readonly]=\"formField.disabled ?? false\"\n [attr.aria-labelledby]=\"formField.label ? labelId : null\"\n [attr.aria-describedby]=\"hasError() ? errorId : null\"\n [attr.aria-invalid]=\"hasError() ? 'true' : 'false'\"\n styleClass=\"pt-otp-input\"\n ></p-inputOtp>\n </div>\n\n @if (hasError()) {\n <div class=\"form-info-row\" role=\"alert\" [id]=\"errorId\">\n <i class=\"pi pi-exclamation-circle\" aria-hidden=\"true\"></i>\n\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0}.form-field{width:100%;min-width:0}.field-label{display:block;margin-bottom:.85rem;color:#172554;font-size:1.1rem;font-weight:700;letter-spacing:.01em}.required-indicator{margin-left:.2rem;color:#ef4444}.otp-input-wrapper{display:flex;width:100%;min-width:0;justify-content:center}.form-info-row{display:flex;align-items:center;min-height:1.35rem;margin-top:.65rem;justify-content:center;gap:.35rem;color:#fca5a5}.form-info-row .pi{font-size:.8rem}.field-error{color:inherit;font-size:.82rem;font-weight:600;text-align:center}:host ::ng-deep .pt-otp-input{display:flex;width:100%;min-width:0;justify-content:center;gap:.7rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:3.7rem;height:4rem;border:2px solid rgba(255,255,255,.62);border-radius:.85rem;background:#fffffff0;box-shadow:0 6px 14px #0f172a29,inset 0 1px #ffffffe6;color:#172554;font-size:1.75rem;font-weight:800;text-align:center;transition:border-color .2s ease,box-shadow .2s ease,transform .2s ease}:host ::ng-deep .pt-otp-input .p-inputotp-input:hover{border-color:#60a5fa;transform:translateY(-2px)}:host ::ng-deep .pt-otp-input .p-inputotp-input:focus{border-color:#2563eb;box-shadow:0 0 0 4px #2563eb33,0 8px 18px #0f172a33;outline:none}.form-field-invalid ::ng-deep .pt-otp-input .p-inputotp-input{border-color:#ef4444}@media(max-width:480px){:host ::ng-deep .pt-otp-input{gap:.42rem}:host ::ng-deep .pt-otp-input .p-inputotp-input{width:2.85rem;height:3.3rem;font-size:1.4rem}}\n"] }]
3554
3962
  }], propDecorators: { formGroup: [{
3555
3963
  type: Input
3556
3964
  }], formField: [{
3557
3965
  type: Input
3558
3966
  }] } });
3559
3967
 
3968
+ // projects/ng-prime-tools/src/lib/pt-password-input/pt-password-input.component.ts
3560
3969
  class PTPasswordInputComponent {
3561
3970
  constructor() {
3562
3971
  this.characterCount = 0;
@@ -3565,96 +3974,154 @@ class PTPasswordInputComponent {
3565
3974
  this.setupControl();
3566
3975
  this.updateCharacterCount();
3567
3976
  }
3977
+ ngOnChanges(changes) {
3978
+ if (changes['formGroup'] || changes['formField']) {
3979
+ this.setupControl();
3980
+ this.updateCharacterCount();
3981
+ }
3982
+ }
3568
3983
  ngOnDestroy() {
3569
3984
  this.valueChangesSubscription?.unsubscribe();
3570
3985
  }
3571
3986
  get inputId() {
3572
3987
  return `pt-password-${this.formField?.name || 'field'}`;
3573
3988
  }
3989
+ get errorId() {
3990
+ return `pt-password-error-${this.formField?.name || 'field'}`;
3991
+ }
3992
+ get isInvalid() {
3993
+ const control = this.formGroup?.get(this.formField?.name);
3994
+ return Boolean(control &&
3995
+ control.enabled &&
3996
+ control.invalid &&
3997
+ (control.touched || control.dirty));
3998
+ }
3999
+ getPasswordToggleMask() {
4000
+ return this.formField?.toggleMask ?? true;
4001
+ }
4002
+ getPasswordFeedback() {
4003
+ return this.formField?.feedback ?? false;
4004
+ }
4005
+ hasCharacterCounter() {
4006
+ return !this.formField?.disabled && this.formField?.maxLength !== undefined;
4007
+ }
4008
+ hasInfoRow() {
4009
+ return this.isInvalid || this.hasCharacterCounter();
4010
+ }
4011
+ getErrorMessage() {
4012
+ const control = this.formGroup?.get(this.formField?.name);
4013
+ if (!control?.errors) {
4014
+ return '';
4015
+ }
4016
+ const errorKey = this.resolveFirstErrorKey(control.errors);
4017
+ if (!errorKey) {
4018
+ return '';
4019
+ }
4020
+ const customMessage = this.formField.validationMessages?.[errorKey];
4021
+ if (customMessage) {
4022
+ return customMessage;
4023
+ }
4024
+ if (this.formField.errorText) {
4025
+ return this.formField.errorText;
4026
+ }
4027
+ const label = this.formField.label?.trim() || this.formField.name;
4028
+ switch (errorKey) {
4029
+ case 'required':
4030
+ return `${label} is required`;
4031
+ case 'minlength': {
4032
+ const requiredLength = control.getError('minlength')?.requiredLength ??
4033
+ this.formField.minLength;
4034
+ return `${label} must be at least ${requiredLength} characters`;
4035
+ }
4036
+ case 'maxlength': {
4037
+ const requiredLength = control.getError('maxlength')?.requiredLength ??
4038
+ this.formField.maxLength;
4039
+ return `${label} must be at most ${requiredLength} characters`;
4040
+ }
4041
+ case 'pattern':
4042
+ return `${label} is invalid`;
4043
+ default:
4044
+ return `${label} is invalid`;
4045
+ }
4046
+ }
3574
4047
  setupControl() {
3575
- const control = this.formGroup.get(this.formField.name);
3576
- if (!control) {
4048
+ const name = this.formField?.name;
4049
+ if (!name || !this.formGroup) {
3577
4050
  return;
3578
4051
  }
4052
+ let control = this.formGroup.get(name);
4053
+ if (!control) {
4054
+ control = new FormControl(this.formField.value ?? null);
4055
+ this.formGroup.addControl(name, control);
4056
+ }
3579
4057
  control.setValidators(this.getValidators());
3580
- this.valueChangesSubscription?.unsubscribe();
3581
4058
  if (this.formField.disabled) {
3582
- control.disable({ emitEvent: false });
4059
+ control.disable({
4060
+ emitEvent: false,
4061
+ });
3583
4062
  }
3584
4063
  else {
3585
- control.enable({ emitEvent: false });
3586
- this.valueChangesSubscription = control.valueChanges.subscribe(() => {
3587
- this.updateCharacterCount();
4064
+ control.enable({
4065
+ emitEvent: false,
3588
4066
  });
3589
4067
  }
3590
- control.updateValueAndValidity({ emitEvent: false });
4068
+ control.updateValueAndValidity({
4069
+ emitEvent: false,
4070
+ });
4071
+ this.valueChangesSubscription?.unsubscribe();
4072
+ this.valueChangesSubscription = control.valueChanges.subscribe(() => {
4073
+ this.updateCharacterCount();
4074
+ });
3591
4075
  }
3592
4076
  updateCharacterCount() {
3593
- const control = this.formGroup.get(this.formField.name);
4077
+ const control = this.formGroup?.get(this.formField?.name);
3594
4078
  if (!control) {
3595
4079
  this.characterCount = 0;
3596
4080
  return;
3597
4081
  }
3598
4082
  const value = control.value;
3599
- this.characterCount = value != null ? String(value).length : 0;
3600
- }
3601
- getPasswordToggleMask() {
3602
- return this.formField.toggleMask ?? true;
3603
- }
3604
- getPasswordFeedback() {
3605
- return this.formField.feedback ?? false;
4083
+ this.characterCount =
4084
+ value === null || value === undefined ? 0 : String(value).length;
3606
4085
  }
3607
4086
  getValidators() {
3608
4087
  const validators = [];
3609
4088
  if (this.formField.required) {
3610
4089
  validators.push(Validators.required);
3611
4090
  }
3612
- if (this.formField.minLength !== undefined) {
4091
+ if (this.formField.minLength !== undefined &&
4092
+ this.formField.minLength !== null) {
3613
4093
  validators.push(Validators.minLength(this.formField.minLength));
3614
4094
  }
3615
- if (this.formField.maxLength !== undefined) {
4095
+ if (this.formField.maxLength !== undefined &&
4096
+ this.formField.maxLength !== null) {
3616
4097
  validators.push(Validators.maxLength(this.formField.maxLength));
3617
4098
  }
3618
4099
  if (this.formField.inputValidation) {
3619
4100
  validators.push(this.validateWithInputValidation(this.formField.inputValidation));
3620
4101
  }
4102
+ else if (this.formField.pattern) {
4103
+ validators.push(Validators.pattern(this.formField.pattern));
4104
+ }
4105
+ if (Array.isArray(this.formField.validators) &&
4106
+ this.formField.validators.length > 0) {
4107
+ validators.push(...this.formField.validators);
4108
+ }
3621
4109
  return validators;
3622
4110
  }
3623
4111
  validateWithInputValidation(inputValidation) {
3624
4112
  return Validators.pattern(new RegExp(inputValidation));
3625
4113
  }
3626
- getErrorMessage() {
3627
- const control = this.formGroup.get(this.formField.name);
3628
- if (control?.hasError('required')) {
3629
- return this.formField.errorText ?? `${this.formField.label} is required`;
3630
- }
3631
- if (control?.hasError('minlength')) {
3632
- return `${this.formField.label} must be at least ${this.formField.minLength} characters`;
3633
- }
3634
- if (control?.hasError('maxlength')) {
3635
- return `${this.formField.label} must be at most ${this.formField.maxLength} characters`;
3636
- }
3637
- if (control?.hasError('pattern')) {
3638
- return this.formField.errorText ?? `${this.formField.label} is invalid`;
3639
- }
3640
- return '';
3641
- }
3642
- hasError() {
3643
- const control = this.formGroup.get(this.formField.name);
3644
- return !!(control?.invalid && (control.touched || control.dirty));
3645
- }
3646
- hasCharacterCounter() {
3647
- return !this.formField.disabled && this.formField.maxLength !== undefined;
3648
- }
3649
- hasInfoRow() {
3650
- return this.hasError() || this.hasCharacterCounter();
4114
+ resolveFirstErrorKey(errors) {
4115
+ const priority = ['required', 'minlength', 'maxlength', 'pattern'];
4116
+ return (priority.find((key) => errors[key] !== undefined) ||
4117
+ Object.keys(errors)[0]);
3651
4118
  }
3652
4119
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTPasswordInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3653
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTPasswordInputComponent, isStandalone: false, selector: "pt-password-input", inputs: { formGroup: "formGroup", formField: "formField" }, ngImport: i0, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField [iconPosition]=\"formField.iconPosition || 'left'\">\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n </p-iconField>\n } @else {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (hasError()) {\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.character-counter{font-size:.8rem;font-weight:500;color:#64748b;white-space:nowrap}::ng-deep .pt-password-input{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password-input{width:100%!important}::ng-deep .pt-password-input input{box-sizing:border-box;width:100%!important}::ng-deep .pt-password-input.ng-invalid.ng-touched input,::ng-deep .pt-password-input.ng-invalid.ng-dirty input,::ng-deep .pt-password-input input.ng-invalid.ng-touched,::ng-deep .pt-password-input input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input .p-password-toggle-mask-icon,::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i10.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "component", type: i6$1.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }] }); }
4120
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTPasswordInputComponent, isStandalone: false, selector: "pt-password-input", inputs: { formGroup: "formGroup", formField: "formField" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-password-input/pt-password-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField\n class=\"password-icon-field\"\n [iconPosition]=\"formField.iconPosition || 'left'\"\n >\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n </p-iconField>\n } @else {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (isInvalid) {\n <small class=\"field-error\" role=\"alert\" [id]=\"errorId\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.character-counter{font-size:.8rem;font-weight:500;color:#64748b;white-space:nowrap}::ng-deep .pt-password-input{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password-input{width:100%!important}::ng-deep .pt-password-input input{box-sizing:border-box;width:100%!important}::ng-deep .pt-password-input.ng-invalid.ng-touched input,::ng-deep .pt-password-input.ng-invalid.ng-dirty input,::ng-deep .pt-password-input input.ng-invalid.ng-touched,::ng-deep .pt-password-input input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input .p-password-toggle-mask-icon,::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: i10.IconField, selector: "p-iconfield, p-iconField, p-icon-field", inputs: ["hostName", "iconPosition", "styleClass"] }, { kind: "component", type: i11.InputIcon, selector: "p-inputicon, p-inputIcon", inputs: ["hostName", "styleClass"] }, { kind: "component", type: i6$1.Password, selector: "p-password", inputs: ["ariaLabel", "ariaLabelledBy", "label", "promptLabel", "mediumRegex", "strongRegex", "weakLabel", "mediumLabel", "maxLength", "strongLabel", "inputId", "feedback", "toggleMask", "inputStyleClass", "styleClass", "inputStyle", "showTransitionOptions", "hideTransitionOptions", "autocomplete", "placeholder", "showClear", "autofocus", "tabindex", "appendTo", "motionOptions", "overlayOptions"], outputs: ["onFocus", "onBlur", "onClear"] }] }); }
3654
4121
  }
3655
4122
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTPasswordInputComponent, decorators: [{
3656
4123
  type: Component,
3657
- args: [{ selector: 'pt-password-input', standalone: false, template: "@if (!formField.hidden) {\n <div\n [formGroup]=\"formGroup\"\n class=\"form-field\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n >\n @if (formField.label) {\n <label [for]=\"inputId\" class=\"field-label\">\n {{ formField.label }}\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField [iconPosition]=\"formField.iconPosition || 'left'\">\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n </p-iconField>\n } @else {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [inputStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (hasError()) {\n <small class=\"field-error\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n </div>\n}\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.character-counter{font-size:.8rem;font-weight:500;color:#64748b;white-space:nowrap}::ng-deep .pt-password-input{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password-input{width:100%!important}::ng-deep .pt-password-input input{box-sizing:border-box;width:100%!important}::ng-deep .pt-password-input.ng-invalid.ng-touched input,::ng-deep .pt-password-input.ng-invalid.ng-dirty input,::ng-deep .pt-password-input input.ng-invalid.ng-touched,::ng-deep .pt-password-input input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input .p-password-toggle-mask-icon,::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"] }]
4124
+ args: [{ selector: 'pt-password-input', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-password-input/pt-password-input.component.html -->\n\n<div\n class=\"form-field\"\n [formGroup]=\"formGroup\"\n [ngClass]=\"{\n 'form-field-invalid': isInvalid,\n }\"\n [ngStyle]=\"{\n width: formField.width || '100%',\n height: formField.height || 'auto',\n margin: formField.margin || null,\n }\"\n>\n @if (formField.label) {\n <label class=\"field-label\" [for]=\"inputId\">\n {{ formField.label }}\n\n @if (formField.required) {\n <span class=\"required-indicator\" aria-hidden=\"true\"> * </span>\n }\n </label>\n }\n\n @if (formField.iconClass) {\n <p-iconField\n class=\"password-icon-field\"\n [iconPosition]=\"formField.iconPosition || 'left'\"\n >\n <p-inputIcon [styleClass]=\"formField.iconClass\"></p-inputIcon>\n\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n </p-iconField>\n } @else {\n <p-password\n [inputId]=\"inputId\"\n [formControlName]=\"formField.name\"\n [placeholder]=\"formField.placeholder ?? ''\"\n [toggleMask]=\"getPasswordToggleMask()\"\n [feedback]=\"getPasswordFeedback()\"\n [attr.name]=\"formField.name\"\n [attr.aria-invalid]=\"isInvalid ? 'true' : 'false'\"\n [attr.aria-describedby]=\"isInvalid ? errorId : null\"\n [inputStyle]=\"{\n width: '100%',\n height: formField.height || 'auto',\n }\"\n styleClass=\"pt-password-input\"\n ></p-password>\n }\n\n @if (hasInfoRow()) {\n <div class=\"form-info-row\">\n @if (isInvalid) {\n <small class=\"field-error\" role=\"alert\" [id]=\"errorId\">\n {{ getErrorMessage() }}\n </small>\n }\n\n <div class=\"spacer\"></div>\n\n @if (hasCharacterCounter()) {\n <div class=\"character-counter\">\n {{ characterCount }}/{{ formField.maxLength }} characters\n </div>\n }\n </div>\n }\n</div>\n", styles: [":host{display:block;width:100%}.form-field{width:100%}.field-label{display:block;margin-bottom:.5rem;font-weight:700}.form-info-row{display:flex;align-items:center;gap:.5rem;min-height:1.25rem;margin-top:.35rem}.spacer{flex:1 1 auto}.field-error{display:block;color:#dc2626;font-size:.8rem;font-weight:500;line-height:1.2}.character-counter{font-size:.8rem;font-weight:500;color:#64748b;white-space:nowrap}::ng-deep .pt-password-input{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password{display:block!important;width:100%!important}::ng-deep .pt-password-input .p-password-input{width:100%!important}::ng-deep .pt-password-input input{box-sizing:border-box;width:100%!important}::ng-deep .pt-password-input.ng-invalid.ng-touched input,::ng-deep .pt-password-input.ng-invalid.ng-dirty input,::ng-deep .pt-password-input input.ng-invalid.ng-touched,::ng-deep .pt-password-input input.ng-invalid.ng-dirty{border-color:#dc2626}::ng-deep .pt-password-input .p-password-toggle-mask-icon,::ng-deep .pt-password-input .p-password-toggle-mask{right:1rem}\n"] }]
3658
4125
  }], propDecorators: { formGroup: [{
3659
4126
  type: Input
3660
4127
  }], formField: [{
@@ -3693,11 +4160,11 @@ class PTDynamicFormFieldComponent {
3693
4160
  return field;
3694
4161
  }
3695
4162
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTDynamicFormFieldComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
3696
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTDynamicFormFieldComponent, isStandalone: false, selector: "pt-dynamic-form-field", inputs: { field: "field", form: "form", inputWidth: "inputWidth" }, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-form-builder/pt-dynamic-form-field/pt-dynamic-form-field.component.html -->\n\n<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX\n ? field.width || inputWidth\n : 'auto',\n }\"\n>\n @switch (field.type) {\n <!-- TEXT -->\n @case (FormInputTypeEnum.TEXT) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- EMAIL -->\n @case (FormInputTypeEnum.EMAIL) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- PASSWORD -->\n @case (FormInputTypeEnum.PASSWORD) {\n <pt-password-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-password-input>\n }\n\n <!-- NUMBER -->\n @case (FormInputTypeEnum.NUMBER) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- AMOUNT -->\n @case (FormInputTypeEnum.AMOUNT) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- TEXTAREA -->\n @case (FormInputTypeEnum.TEXTAREA) {\n <pt-text-area-input\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n }\n\n <!-- DATE -->\n @case (FormInputTypeEnum.DATE) {\n <pt-date-input\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n }\n\n <!-- MULTISELECT -->\n @case (FormInputTypeEnum.MULTISELECT) {\n <pt-multi-select\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n }\n\n <!-- SELECT -->\n @case (FormInputTypeEnum.SELECT) {\n <pt-dropdown\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n }\n\n <!-- OTP -->\n @case (FormInputTypeEnum.OTP) {\n <pt-otp-input\n [formGroup]=\"form\"\n [formField]=\"asOtpField(field)\"\n ></pt-otp-input>\n }\n\n <!-- CHECKBOX -->\n @case (FormInputTypeEnum.CHECKBOX) {\n <pt-check-box-input\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n }\n\n <!-- SWITCH -->\n @case (FormInputTypeEnum.SWITCH) {\n <pt-switch-input\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n }\n }\n</div>\n", styles: [".form-field{margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PTCheckBoxInputComponent, selector: "pt-check-box-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDateInputComponent, selector: "pt-date-input", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "dateChange"] }, { kind: "component", type: PTNumberInputComponent, selector: "pt-number-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTSwitchInputComponent, selector: "pt-switch-input", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "switchChange"] }, { kind: "component", type: PTTextAreaInputComponent, selector: "pt-text-area-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTTextInputComponent, selector: "pt-text-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDropdownComponent, selector: "pt-dropdown", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "selectionChange"] }, { kind: "component", type: PTMultiSelectComponent, selector: "pt-multi-select", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "selectionChange"] }, { kind: "component", type: PTOtpInputComponent, selector: "pt-otp-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTPasswordInputComponent, selector: "pt-password-input", inputs: ["formGroup", "formField"] }] }); }
4163
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTDynamicFormFieldComponent, isStandalone: false, selector: "pt-dynamic-form-field", inputs: { field: "field", form: "form", inputWidth: "inputWidth" }, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/pt-form-builder/pt-dynamic-form-field/pt-dynamic-form-field.component.html -->\n\n<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX\n ? field.width || inputWidth\n : 'auto',\n }\"\n>\n @switch (field.type) {\n <!-- TEXT -->\n @case (FormInputTypeEnum.TEXT) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- EMAIL -->\n @case (FormInputTypeEnum.EMAIL) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- PASSWORD -->\n @case (FormInputTypeEnum.PASSWORD) {\n <pt-password-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-password-input>\n }\n\n <!-- NUMBER -->\n @case (FormInputTypeEnum.NUMBER) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- AMOUNT -->\n @case (FormInputTypeEnum.AMOUNT) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- TEXTAREA -->\n @case (FormInputTypeEnum.TEXTAREA) {\n <pt-text-area-input\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n }\n\n <!-- DATE -->\n @case (FormInputTypeEnum.DATE) {\n <pt-date-input\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n }\n\n <!-- MULTISELECT -->\n @case (FormInputTypeEnum.MULTISELECT) {\n <pt-multi-select\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n }\n\n <!-- SELECT -->\n @case (FormInputTypeEnum.SELECT) {\n <pt-dropdown\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n }\n\n <!-- OTP -->\n @case (FormInputTypeEnum.OTP) {\n <pt-otp-input\n [formGroup]=\"form\"\n [formField]=\"asOtpField(field)\"\n ></pt-otp-input>\n }\n\n <!-- CHECKBOX -->\n @case (FormInputTypeEnum.CHECKBOX) {\n <pt-check-box-input\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n }\n\n <!-- SWITCH -->\n @case (FormInputTypeEnum.SWITCH) {\n <pt-switch-input\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n }\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0;max-width:100%}.form-field{display:block;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.form-field>pt-text-input,.form-field>pt-password-input,.form-field>pt-number-input,.form-field>pt-text-area-input,.form-field>pt-date-input,.form-field>pt-multi-select,.form-field>pt-dropdown,.form-field>pt-otp-input,.form-field>pt-switch-input{display:block;width:100%;min-width:0;max-width:100%}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "component", type: PTCheckBoxInputComponent, selector: "pt-check-box-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDateInputComponent, selector: "pt-date-input", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "dateChange"] }, { kind: "component", type: PTNumberInputComponent, selector: "pt-number-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTSwitchInputComponent, selector: "pt-switch-input", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "switchChange"] }, { kind: "component", type: PTTextAreaInputComponent, selector: "pt-text-area-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTTextInputComponent, selector: "pt-text-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTDropdownComponent, selector: "pt-dropdown", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "selectionChange"] }, { kind: "component", type: PTMultiSelectComponent, selector: "pt-multi-select", inputs: ["formGroup", "formField", "config", "value"], outputs: ["valueChange", "selectionChange"] }, { kind: "component", type: PTOtpInputComponent, selector: "pt-otp-input", inputs: ["formGroup", "formField"] }, { kind: "component", type: PTPasswordInputComponent, selector: "pt-password-input", inputs: ["formGroup", "formField"] }] }); }
3697
4164
  }
3698
4165
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTDynamicFormFieldComponent, decorators: [{
3699
4166
  type: Component,
3700
- args: [{ selector: 'pt-dynamic-form-field', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-form-builder/pt-dynamic-form-field/pt-dynamic-form-field.component.html -->\n\n<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX\n ? field.width || inputWidth\n : 'auto',\n }\"\n>\n @switch (field.type) {\n <!-- TEXT -->\n @case (FormInputTypeEnum.TEXT) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- EMAIL -->\n @case (FormInputTypeEnum.EMAIL) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- PASSWORD -->\n @case (FormInputTypeEnum.PASSWORD) {\n <pt-password-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-password-input>\n }\n\n <!-- NUMBER -->\n @case (FormInputTypeEnum.NUMBER) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- AMOUNT -->\n @case (FormInputTypeEnum.AMOUNT) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- TEXTAREA -->\n @case (FormInputTypeEnum.TEXTAREA) {\n <pt-text-area-input\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n }\n\n <!-- DATE -->\n @case (FormInputTypeEnum.DATE) {\n <pt-date-input\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n }\n\n <!-- MULTISELECT -->\n @case (FormInputTypeEnum.MULTISELECT) {\n <pt-multi-select\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n }\n\n <!-- SELECT -->\n @case (FormInputTypeEnum.SELECT) {\n <pt-dropdown\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n }\n\n <!-- OTP -->\n @case (FormInputTypeEnum.OTP) {\n <pt-otp-input\n [formGroup]=\"form\"\n [formField]=\"asOtpField(field)\"\n ></pt-otp-input>\n }\n\n <!-- CHECKBOX -->\n @case (FormInputTypeEnum.CHECKBOX) {\n <pt-check-box-input\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n }\n\n <!-- SWITCH -->\n @case (FormInputTypeEnum.SWITCH) {\n <pt-switch-input\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n }\n }\n</div>\n", styles: [".form-field{margin-bottom:1rem}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"] }]
4167
+ args: [{ selector: 'pt-dynamic-form-field', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/pt-form-builder/pt-dynamic-form-field/pt-dynamic-form-field.component.html -->\n\n<div\n [formGroup]=\"form\"\n class=\"form-field\"\n [ngStyle]=\"{\n width:\n field.type !== FormInputTypeEnum.CHECKBOX\n ? field.width || inputWidth\n : 'auto',\n }\"\n>\n @switch (field.type) {\n <!-- TEXT -->\n @case (FormInputTypeEnum.TEXT) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- EMAIL -->\n @case (FormInputTypeEnum.EMAIL) {\n <pt-text-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-text-input>\n }\n\n <!-- PASSWORD -->\n @case (FormInputTypeEnum.PASSWORD) {\n <pt-password-input\n [formGroup]=\"form\"\n [formField]=\"asTextField(field)\"\n ></pt-password-input>\n }\n\n <!-- NUMBER -->\n @case (FormInputTypeEnum.NUMBER) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- AMOUNT -->\n @case (FormInputTypeEnum.AMOUNT) {\n <pt-number-input\n [formGroup]=\"form\"\n [formField]=\"asNumberField(field)\"\n ></pt-number-input>\n }\n\n <!-- TEXTAREA -->\n @case (FormInputTypeEnum.TEXTAREA) {\n <pt-text-area-input\n [formGroup]=\"form\"\n [formField]=\"asTextAreaField(field)\"\n ></pt-text-area-input>\n }\n\n <!-- DATE -->\n @case (FormInputTypeEnum.DATE) {\n <pt-date-input\n [formGroup]=\"form\"\n [formField]=\"asDateField(field)\"\n ></pt-date-input>\n }\n\n <!-- MULTISELECT -->\n @case (FormInputTypeEnum.MULTISELECT) {\n <pt-multi-select\n [formGroup]=\"form\"\n [formField]=\"asMultiSelectField(field)\"\n ></pt-multi-select>\n }\n\n <!-- SELECT -->\n @case (FormInputTypeEnum.SELECT) {\n <pt-dropdown\n [formGroup]=\"form\"\n [formField]=\"asSelectField(field)\"\n ></pt-dropdown>\n }\n\n <!-- OTP -->\n @case (FormInputTypeEnum.OTP) {\n <pt-otp-input\n [formGroup]=\"form\"\n [formField]=\"asOtpField(field)\"\n ></pt-otp-input>\n }\n\n <!-- CHECKBOX -->\n @case (FormInputTypeEnum.CHECKBOX) {\n <pt-check-box-input\n [formGroup]=\"form\"\n [formField]=\"asCheckboxField(field)\"\n ></pt-check-box-input>\n }\n\n <!-- SWITCH -->\n @case (FormInputTypeEnum.SWITCH) {\n <pt-switch-input\n [formGroup]=\"form\"\n [formField]=\"asSwitchField(field)\"\n ></pt-switch-input>\n }\n }\n</div>\n", styles: [":host{display:block;width:100%;min-width:0;max-width:100%}.form-field{display:block;width:100%;min-width:0;max-width:100%;margin-bottom:1rem}.form-field>pt-text-input,.form-field>pt-password-input,.form-field>pt-number-input,.form-field>pt-text-area-input,.form-field>pt-date-input,.form-field>pt-multi-select,.form-field>pt-dropdown,.form-field>pt-otp-input,.form-field>pt-switch-input{display:block;width:100%;min-width:0;max-width:100%}.form-field label{display:block;margin-bottom:.5rem;font-weight:700}\n"] }]
3701
4168
  }], propDecorators: { field: [{
3702
4169
  type: Input
3703
4170
  }], form: [{
@@ -3711,7 +4178,10 @@ class PTFormBuilderComponent {
3711
4178
  constructor(fb, cdr) {
3712
4179
  this.fb = fb;
3713
4180
  this.cdr = cdr;
3714
- this.mainGroup = { fields: [], groups: [] };
4181
+ this.mainGroup = {
4182
+ fields: [],
4183
+ groups: [],
4184
+ };
3715
4185
  this.buttons = [];
3716
4186
  this.inputWidth = '100%';
3717
4187
  this.formWidth = '100%';
@@ -3725,8 +4195,12 @@ class PTFormBuilderComponent {
3725
4195
  required: 'is required',
3726
4196
  email: 'is not a valid email address',
3727
4197
  pattern: 'is invalid',
3728
- minlength: 'must be at least',
3729
- maxlength: 'must be at most',
4198
+ minlength: 'must contain at least',
4199
+ maxlength: 'must contain at most',
4200
+ min: 'must be greater than or equal to',
4201
+ max: 'must be less than or equal to',
4202
+ invalid: 'is invalid',
4203
+ characters: 'characters',
3730
4204
  },
3731
4205
  fr: {
3732
4206
  required: 'est requis',
@@ -3734,6 +4208,10 @@ class PTFormBuilderComponent {
3734
4208
  pattern: 'est invalide',
3735
4209
  minlength: 'doit contenir au moins',
3736
4210
  maxlength: 'doit contenir au plus',
4211
+ min: 'doit être supérieur ou égal à',
4212
+ max: 'doit être inférieur ou égal à',
4213
+ invalid: 'est invalide',
4214
+ characters: 'caractères',
3737
4215
  },
3738
4216
  };
3739
4217
  this.form = this.fb.group({});
@@ -3756,6 +4234,74 @@ class PTFormBuilderComponent {
3756
4234
  }
3757
4235
  return Boolean(hidden);
3758
4236
  }
4237
+ isInvalid(field) {
4238
+ const control = this.form.get(field.name);
4239
+ return Boolean(control &&
4240
+ control.enabled &&
4241
+ control.invalid &&
4242
+ (control.touched || control.dirty));
4243
+ }
4244
+ getErrorMessage(field) {
4245
+ const control = this.form.get(field.name);
4246
+ if (!control?.errors) {
4247
+ return '';
4248
+ }
4249
+ const errorKey = this.resolveFirstErrorKey(control);
4250
+ if (!errorKey) {
4251
+ return '';
4252
+ }
4253
+ const customMessage = field.validationMessages?.[errorKey];
4254
+ if (customMessage) {
4255
+ return customMessage;
4256
+ }
4257
+ if (field.errorText) {
4258
+ return field.errorText;
4259
+ }
4260
+ const fieldLabel = field.label?.trim() || field.name;
4261
+ const messages = this.errorMessages[this.language];
4262
+ switch (errorKey) {
4263
+ case 'required':
4264
+ return `${fieldLabel} ${messages.required}`;
4265
+ case 'email':
4266
+ return `${fieldLabel} ${messages.email}`;
4267
+ case 'pattern':
4268
+ return `${fieldLabel} ${messages.pattern}`;
4269
+ case 'minlength': {
4270
+ const requiredLength = control.getError('minlength')?.requiredLength ?? '';
4271
+ return `${fieldLabel} ${messages.minlength} ${requiredLength} ${messages.characters}`;
4272
+ }
4273
+ case 'maxlength': {
4274
+ const requiredLength = control.getError('maxlength')?.requiredLength ?? '';
4275
+ return `${fieldLabel} ${messages.maxlength} ${requiredLength} ${messages.characters}`;
4276
+ }
4277
+ case 'min': {
4278
+ const minimum = control.getError('min')?.min ?? '';
4279
+ return `${fieldLabel} ${messages.min} ${minimum}`;
4280
+ }
4281
+ case 'max': {
4282
+ const maximum = control.getError('max')?.max ?? '';
4283
+ return `${fieldLabel} ${messages.max} ${maximum}`;
4284
+ }
4285
+ default:
4286
+ return `${fieldLabel} ${messages.invalid}`;
4287
+ }
4288
+ }
4289
+ onSubmit() {
4290
+ this.form.markAllAsTouched();
4291
+ this.form.updateValueAndValidity({
4292
+ emitEvent: false,
4293
+ });
4294
+ if (this.form.invalid) {
4295
+ this.cdr.markForCheck();
4296
+ return;
4297
+ }
4298
+ this.formSubmit.emit(this.form.getRawValue());
4299
+ }
4300
+ onClear() {
4301
+ this.form.reset();
4302
+ this.formChange.emit(this.form.getRawValue());
4303
+ this.cdr.markForCheck();
4304
+ }
3759
4305
  rebuildForm() {
3760
4306
  this.formValueChangesSub?.unsubscribe();
3761
4307
  this.form = this.fb.group({});
@@ -3768,14 +4314,17 @@ class PTFormBuilderComponent {
3768
4314
  }
3769
4315
  buildFormGroup(group) {
3770
4316
  (group?.fields ?? []).forEach((field) => {
3771
- const validators = this.buildValidators(field);
3772
- const anyField = field;
3773
4317
  this.form.addControl(field.name, this.fb.control({
3774
4318
  value: this.resolveInitialValue(field),
3775
- disabled: Boolean(anyField.disabled),
3776
- }, validators));
4319
+ disabled: Boolean(field.disabled),
4320
+ }, {
4321
+ validators: this.buildValidators(field),
4322
+ updateOn: 'change',
4323
+ }));
4324
+ });
4325
+ (group?.groups ?? []).forEach((subGroup) => {
4326
+ this.buildFormGroup(subGroup);
3777
4327
  });
3778
- (group?.groups ?? []).forEach((subGroup) => this.buildFormGroup(subGroup));
3779
4328
  }
3780
4329
  resolveInitialValue(field) {
3781
4330
  if (field.value !== undefined && field.value !== null) {
@@ -3791,31 +4340,29 @@ class PTFormBuilderComponent {
3791
4340
  }
3792
4341
  buildValidators(field) {
3793
4342
  const validators = [];
3794
- const anyField = field;
3795
4343
  if (field.required) {
3796
4344
  validators.push(Validators.required);
3797
4345
  }
3798
- if (anyField.minLength != null) {
3799
- validators.push(Validators.minLength(Number(anyField.minLength)));
4346
+ if (field.minLength !== undefined && field.minLength !== null) {
4347
+ validators.push(Validators.minLength(Number(field.minLength)));
3800
4348
  }
3801
- if (anyField.maxLength != null) {
3802
- validators.push(Validators.maxLength(Number(anyField.maxLength)));
4349
+ if (field.maxLength !== undefined && field.maxLength !== null) {
4350
+ validators.push(Validators.maxLength(Number(field.maxLength)));
3803
4351
  }
3804
- if (anyField.inputValidation) {
3805
- validators.push(Validators.pattern(new RegExp(anyField.inputValidation)));
4352
+ if (field.inputValidation) {
4353
+ validators.push(Validators.pattern(new RegExp(field.inputValidation)));
3806
4354
  }
3807
- else if (anyField.pattern) {
3808
- validators.push(Validators.pattern(anyField.pattern));
4355
+ else if (field.pattern) {
4356
+ validators.push(Validators.pattern(field.pattern));
3809
4357
  }
3810
- switch (field.type) {
3811
- case FormInputTypeEnum.EMAIL:
3812
- validators.push(Validators.email);
3813
- break;
3814
- case FormInputTypeEnum.OTP:
3815
- validators.push(Validators.pattern(this.buildOtpPattern(field)));
3816
- break;
3817
- default:
3818
- break;
4358
+ if (field.type === FormInputTypeEnum.EMAIL) {
4359
+ validators.push(Validators.email);
4360
+ }
4361
+ if (field.type === FormInputTypeEnum.OTP) {
4362
+ validators.push(Validators.pattern(this.buildOtpPattern(field)));
4363
+ }
4364
+ if (Array.isArray(field.validators) && field.validators.length > 0) {
4365
+ validators.push(...field.validators);
3819
4366
  }
3820
4367
  return validators;
3821
4368
  }
@@ -3827,55 +4374,32 @@ class PTFormBuilderComponent {
3827
4374
  }
3828
4375
  return new RegExp(`^[A-Za-z0-9]{${length}}$`);
3829
4376
  }
3830
- isInvalid(field) {
3831
- const control = this.form.get(field.name);
3832
- return Boolean(control && control.invalid && (control.touched || control.dirty));
3833
- }
3834
- getErrorMessage(field) {
3835
- const control = this.form.get(field.name);
3836
- if (!control) {
3837
- return '';
3838
- }
3839
- const lang = this.language;
3840
- if (control.hasError('required')) {
3841
- return (field.errorText ||
3842
- `${field.label} ${this.errorMessages[lang].required}`);
3843
- }
3844
- if (control.hasError('email')) {
3845
- return (field.errorText ||
3846
- `${field.label} ${this.errorMessages[lang].email}`);
3847
- }
3848
- if (control.hasError('pattern')) {
3849
- return (field.errorText ||
3850
- `${field.label} ${this.errorMessages[lang].pattern}`);
3851
- }
3852
- if (control.hasError('minlength')) {
3853
- const requiredLength = control.getError('minlength')?.requiredLength;
3854
- return `${field.label} ${this.errorMessages[lang].minlength} ${requiredLength} ${lang === 'fr' ? 'caractères' : 'characters'}`;
3855
- }
3856
- if (control.hasError('maxlength')) {
3857
- const requiredLength = control.getError('maxlength')?.requiredLength;
3858
- return `${field.label} ${this.errorMessages[lang].maxlength} ${requiredLength} ${lang === 'fr' ? 'caractères' : 'characters'}`;
4377
+ resolveFirstErrorKey(control) {
4378
+ const errors = control.errors;
4379
+ if (!errors) {
4380
+ return undefined;
3859
4381
  }
3860
- return '';
3861
- }
3862
- onSubmit() {
3863
- this.form.markAllAsTouched();
3864
- if (this.form.valid) {
3865
- this.formSubmit.emit(this.form.getRawValue());
4382
+ const priority = [
4383
+ 'required',
4384
+ 'email',
4385
+ 'minlength',
4386
+ 'maxlength',
4387
+ 'min',
4388
+ 'max',
4389
+ 'pattern',
4390
+ ];
4391
+ const priorityError = priority.find((key) => errors[key] !== undefined);
4392
+ if (priorityError) {
4393
+ return priorityError;
3866
4394
  }
3867
- }
3868
- onClear() {
3869
- this.form.reset();
3870
- this.formChange.emit(this.form.getRawValue());
3871
- this.cdr.markForCheck();
4395
+ return Object.keys(errors)[0];
3872
4396
  }
3873
4397
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTFormBuilderComponent, deps: [{ token: i2.FormBuilder }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component }); }
3874
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTFormBuilderComponent, isStandalone: false, selector: "pt-form-builder", inputs: { mainGroup: "mainGroup", buttons: "buttons", title: "title", titleStyle: "titleStyle", inputWidth: "inputWidth", formWidth: "formWidth", language: "language" }, outputs: { formSubmit: "formSubmit", formReady: "formReady", formChange: "formChange" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/components/pt-form-builder/pt-form-builder.component.html -->\n\n<div\n class=\"pt-form-builder-wrapper\"\n [ngStyle]=\"{ width: formWidth, maxWidth: formWidth }\"\n>\n @if (title) {\n <div [ngStyle]=\"titleStyle\" class=\"form-title\">{{ title }}</div>\n }\n\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n @for (field of mainGroup.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n ></pt-dynamic-form-field>\n }\n }\n\n @for (group of mainGroup.groups; track $index) {\n <div\n class=\"form-field-group\"\n [ngStyle]=\"{ width: group.width || '100%' }\"\n >\n @for (field of group.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n class=\"flex-item\"\n ></pt-dynamic-form-field>\n }\n }\n </div>\n }\n\n @if (buttons.length) {\n <div class=\"button-group\">\n @for (button of buttons; track button.text) {\n <button\n type=\"button\"\n pButton\n [label]=\"button.text\"\n [icon]=\"button.icon || ''\"\n [class]=\"button.color || ''\"\n [disabled]=\"button.disabled || false\"\n [ngStyle]=\"{\n color: button.fontColor || null,\n 'background-color': button.backgroundColor || null,\n 'border-color':\n button.borderColor || button.backgroundColor || null,\n }\"\n (click)=\"\n button.isSubmit\n ? onSubmit()\n : button.isClear\n ? onClear()\n : button.action\n ? button.action()\n : null\n \"\n ></button>\n }\n </div>\n }\n </form>\n</div>\n", styles: [".pt-form-builder-wrapper{width:100%;margin:0 auto;color:var(--pt-form-builder-text, inherit)}.form-title{text-align:center;margin-bottom:1rem;font-size:1.5rem;font-weight:700;color:var(--pt-form-builder-title, #333333)}.form-field{margin-bottom:1rem;color:var(--pt-form-builder-text, inherit)}.form-field label{display:block;margin-bottom:.5rem;font-weight:700;color:var(--pt-form-builder-label, #333333)}::ng-deep .p-inputtext,::ng-deep .p-inputtextarea,::ng-deep .p-calendar,::ng-deep .p-inputnumber,::ng-deep .p-multiselect,::ng-deep .p-dropdown{width:100%!important}::ng-deep .p-inputnumber,::ng-deep p-inputnumber{display:flex!important}.button-group{display:flex;gap:1rem;margin-top:1rem;justify-content:space-between}.button-group button{flex:1;display:flex;align-items:center;justify-content:center}.button-group button i{margin-right:.5rem}.button-group button.p-button-primary{background-color:var(--pt-form-builder-button-primary-bg, #007bff);color:var(--pt-form-builder-button-primary-text, #ffffff)}.button-group button.p-button-secondary{background-color:var(--pt-form-builder-button-secondary-bg, #6c757d);color:var(--pt-form-builder-button-secondary-text, #ffffff)}.button-group button.p-button-success{background-color:var(--pt-form-builder-button-success-bg, #28a745);color:var(--pt-form-builder-button-success-text, #ffffff)}.button-group button:hover{opacity:.9}.form-field-group{display:flex;gap:1rem}.form-field-group .flex-item{flex:1}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: PTDynamicFormFieldComponent, selector: "pt-dynamic-form-field", inputs: ["field", "form", "inputWidth"] }] }); }
4398
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.14", type: PTFormBuilderComponent, isStandalone: false, selector: "pt-form-builder", inputs: { mainGroup: "mainGroup", buttons: "buttons", title: "title", titleStyle: "titleStyle", inputWidth: "inputWidth", formWidth: "formWidth", language: "language" }, outputs: { formSubmit: "formSubmit", formReady: "formReady", formChange: "formChange" }, usesOnChanges: true, ngImport: i0, template: "<!-- projects/ng-prime-tools/src/lib/components/pt-form-builder/pt-form-builder.component.html -->\n\n<div\n class=\"pt-form-builder-wrapper\"\n [ngStyle]=\"{\n width: formWidth,\n 'max-width': formWidth,\n }\"\n>\n @if (title) {\n <div class=\"form-title\" [ngStyle]=\"titleStyle\">\n {{ title }}\n </div>\n }\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"onSubmit()\">\n @for (field of mainGroup.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n ></pt-dynamic-form-field>\n }\n }\n\n @for (group of mainGroup.groups; track $index) {\n <div\n class=\"form-field-group\"\n [ngStyle]=\"{\n width: group.width || '100%',\n }\"\n >\n @for (field of group.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n class=\"flex-item\"\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n ></pt-dynamic-form-field>\n }\n }\n </div>\n }\n\n @if (buttons.length > 0) {\n <div class=\"button-group\">\n @for (button of buttons; track button.text) {\n <button\n pButton\n [type]=\"button.isSubmit ? 'submit' : 'button'\"\n [label]=\"button.text\"\n [icon]=\"button.icon || ''\"\n [class]=\"button.color || ''\"\n [disabled]=\"button.disabled || false\"\n [ngStyle]=\"{\n color: button.fontColor || null,\n 'background-color': button.backgroundColor || null,\n 'border-color':\n button.borderColor || button.backgroundColor || null,\n }\"\n (click)=\"\n button.isSubmit\n ? null\n : button.isClear\n ? onClear()\n : button.action\n ? button.action()\n : null\n \"\n ></button>\n }\n </div>\n }\n </form>\n</div>\n", styles: [".pt-form-builder-wrapper{width:100%;margin:0 auto;color:var(--pt-form-builder-text, inherit)}.form-title{text-align:center;margin-bottom:1rem;font-size:1.5rem;font-weight:700;color:var(--pt-form-builder-title, #333333)}.form-field{margin-bottom:1rem;color:var(--pt-form-builder-text, inherit)}.form-field label{display:block;margin-bottom:.5rem;font-weight:700;color:var(--pt-form-builder-label, #333333)}::ng-deep .p-inputtext,::ng-deep .p-inputtextarea,::ng-deep .p-calendar,::ng-deep .p-inputnumber,::ng-deep .p-multiselect,::ng-deep .p-dropdown{width:100%!important}::ng-deep .p-inputnumber,::ng-deep p-inputnumber{display:flex!important}.button-group{display:flex;gap:1rem;margin-top:1rem;justify-content:space-between}.button-group button{flex:1;display:flex;align-items:center;justify-content:center}.button-group button i{margin-right:.5rem}.button-group button.p-button-primary{background-color:var(--pt-form-builder-button-primary-bg, #007bff);color:var(--pt-form-builder-button-primary-text, #ffffff)}.button-group button.p-button-secondary{background-color:var(--pt-form-builder-button-secondary-bg, #6c757d);color:var(--pt-form-builder-button-secondary-text, #ffffff)}.button-group button.p-button-success{background-color:var(--pt-form-builder-button-success-bg, #28a745);color:var(--pt-form-builder-button-success-text, #ffffff)}.button-group button:hover{opacity:.9}.form-field-group{display:flex;gap:1rem}.form-field-group .flex-item{flex:1}\n"], dependencies: [{ kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],[formArray],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i6.ButtonDirective, selector: "[pButton]", inputs: ["ptButtonDirective", "pButtonPT", "pButtonUnstyled", "hostName", "text", "plain", "raised", "size", "outlined", "rounded", "iconPos", "loadingIcon", "fluid", "label", "icon", "loading", "buttonProps", "severity"] }, { kind: "component", type: PTDynamicFormFieldComponent, selector: "pt-dynamic-form-field", inputs: ["field", "form", "inputWidth"] }] }); }
3875
4399
  }
3876
4400
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImport: i0, type: PTFormBuilderComponent, decorators: [{
3877
4401
  type: Component,
3878
- args: [{ selector: 'pt-form-builder', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/components/pt-form-builder/pt-form-builder.component.html -->\n\n<div\n class=\"pt-form-builder-wrapper\"\n [ngStyle]=\"{ width: formWidth, maxWidth: formWidth }\"\n>\n @if (title) {\n <div [ngStyle]=\"titleStyle\" class=\"form-title\">{{ title }}</div>\n }\n\n <form [formGroup]=\"form\" (ngSubmit)=\"onSubmit()\">\n @for (field of mainGroup.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n ></pt-dynamic-form-field>\n }\n }\n\n @for (group of mainGroup.groups; track $index) {\n <div\n class=\"form-field-group\"\n [ngStyle]=\"{ width: group.width || '100%' }\"\n >\n @for (field of group.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n class=\"flex-item\"\n ></pt-dynamic-form-field>\n }\n }\n </div>\n }\n\n @if (buttons.length) {\n <div class=\"button-group\">\n @for (button of buttons; track button.text) {\n <button\n type=\"button\"\n pButton\n [label]=\"button.text\"\n [icon]=\"button.icon || ''\"\n [class]=\"button.color || ''\"\n [disabled]=\"button.disabled || false\"\n [ngStyle]=\"{\n color: button.fontColor || null,\n 'background-color': button.backgroundColor || null,\n 'border-color':\n button.borderColor || button.backgroundColor || null,\n }\"\n (click)=\"\n button.isSubmit\n ? onSubmit()\n : button.isClear\n ? onClear()\n : button.action\n ? button.action()\n : null\n \"\n ></button>\n }\n </div>\n }\n </form>\n</div>\n", styles: [".pt-form-builder-wrapper{width:100%;margin:0 auto;color:var(--pt-form-builder-text, inherit)}.form-title{text-align:center;margin-bottom:1rem;font-size:1.5rem;font-weight:700;color:var(--pt-form-builder-title, #333333)}.form-field{margin-bottom:1rem;color:var(--pt-form-builder-text, inherit)}.form-field label{display:block;margin-bottom:.5rem;font-weight:700;color:var(--pt-form-builder-label, #333333)}::ng-deep .p-inputtext,::ng-deep .p-inputtextarea,::ng-deep .p-calendar,::ng-deep .p-inputnumber,::ng-deep .p-multiselect,::ng-deep .p-dropdown{width:100%!important}::ng-deep .p-inputnumber,::ng-deep p-inputnumber{display:flex!important}.button-group{display:flex;gap:1rem;margin-top:1rem;justify-content:space-between}.button-group button{flex:1;display:flex;align-items:center;justify-content:center}.button-group button i{margin-right:.5rem}.button-group button.p-button-primary{background-color:var(--pt-form-builder-button-primary-bg, #007bff);color:var(--pt-form-builder-button-primary-text, #ffffff)}.button-group button.p-button-secondary{background-color:var(--pt-form-builder-button-secondary-bg, #6c757d);color:var(--pt-form-builder-button-secondary-text, #ffffff)}.button-group button.p-button-success{background-color:var(--pt-form-builder-button-success-bg, #28a745);color:var(--pt-form-builder-button-success-text, #ffffff)}.button-group button:hover{opacity:.9}.form-field-group{display:flex;gap:1rem}.form-field-group .flex-item{flex:1}\n"] }]
4402
+ args: [{ selector: 'pt-form-builder', standalone: false, template: "<!-- projects/ng-prime-tools/src/lib/components/pt-form-builder/pt-form-builder.component.html -->\n\n<div\n class=\"pt-form-builder-wrapper\"\n [ngStyle]=\"{\n width: formWidth,\n 'max-width': formWidth,\n }\"\n>\n @if (title) {\n <div class=\"form-title\" [ngStyle]=\"titleStyle\">\n {{ title }}\n </div>\n }\n\n <form [formGroup]=\"form\" novalidate (ngSubmit)=\"onSubmit()\">\n @for (field of mainGroup.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n ></pt-dynamic-form-field>\n }\n }\n\n @for (group of mainGroup.groups; track $index) {\n <div\n class=\"form-field-group\"\n [ngStyle]=\"{\n width: group.width || '100%',\n }\"\n >\n @for (field of group.fields; track field.name) {\n @if (!isFieldHidden(field)) {\n <pt-dynamic-form-field\n class=\"flex-item\"\n [field]=\"field\"\n [form]=\"form\"\n [inputWidth]=\"inputWidth\"\n ></pt-dynamic-form-field>\n }\n }\n </div>\n }\n\n @if (buttons.length > 0) {\n <div class=\"button-group\">\n @for (button of buttons; track button.text) {\n <button\n pButton\n [type]=\"button.isSubmit ? 'submit' : 'button'\"\n [label]=\"button.text\"\n [icon]=\"button.icon || ''\"\n [class]=\"button.color || ''\"\n [disabled]=\"button.disabled || false\"\n [ngStyle]=\"{\n color: button.fontColor || null,\n 'background-color': button.backgroundColor || null,\n 'border-color':\n button.borderColor || button.backgroundColor || null,\n }\"\n (click)=\"\n button.isSubmit\n ? null\n : button.isClear\n ? onClear()\n : button.action\n ? button.action()\n : null\n \"\n ></button>\n }\n </div>\n }\n </form>\n</div>\n", styles: [".pt-form-builder-wrapper{width:100%;margin:0 auto;color:var(--pt-form-builder-text, inherit)}.form-title{text-align:center;margin-bottom:1rem;font-size:1.5rem;font-weight:700;color:var(--pt-form-builder-title, #333333)}.form-field{margin-bottom:1rem;color:var(--pt-form-builder-text, inherit)}.form-field label{display:block;margin-bottom:.5rem;font-weight:700;color:var(--pt-form-builder-label, #333333)}::ng-deep .p-inputtext,::ng-deep .p-inputtextarea,::ng-deep .p-calendar,::ng-deep .p-inputnumber,::ng-deep .p-multiselect,::ng-deep .p-dropdown{width:100%!important}::ng-deep .p-inputnumber,::ng-deep p-inputnumber{display:flex!important}.button-group{display:flex;gap:1rem;margin-top:1rem;justify-content:space-between}.button-group button{flex:1;display:flex;align-items:center;justify-content:center}.button-group button i{margin-right:.5rem}.button-group button.p-button-primary{background-color:var(--pt-form-builder-button-primary-bg, #007bff);color:var(--pt-form-builder-button-primary-text, #ffffff)}.button-group button.p-button-secondary{background-color:var(--pt-form-builder-button-secondary-bg, #6c757d);color:var(--pt-form-builder-button-secondary-text, #ffffff)}.button-group button.p-button-success{background-color:var(--pt-form-builder-button-success-bg, #28a745);color:var(--pt-form-builder-button-success-text, #ffffff)}.button-group button:hover{opacity:.9}.form-field-group{display:flex;gap:1rem}.form-field-group .flex-item{flex:1}\n"] }]
3879
4403
  }], ctorParameters: () => [{ type: i2.FormBuilder }, { type: i0.ChangeDetectorRef }], propDecorators: { mainGroup: [{
3880
4404
  type: Input
3881
4405
  }], buttons: [{
@@ -9464,6 +9988,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.14", ngImpo
9464
9988
  }]
9465
9989
  }] });
9466
9990
 
9991
+ // projects/ng-prime-tools/src/lib/models/form-multi-select.model.ts
9992
+
9467
9993
  // projects/ng-prime-tools/src/lib/models/pt-accordion-config.model.ts
9468
9994
 
9469
9995
  // nav-bar-menu-config.model.ts