@shival99/z-ui 1.8.13 → 1.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/assets/css/tailwind.css +7 -11
  2. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs +45 -71
  3. package/fesm2022/shival99-z-ui-components-z-autocomplete.mjs.map +1 -1
  4. package/fesm2022/shival99-z-ui-components-z-button.mjs +21 -11
  5. package/fesm2022/shival99-z-ui-components-z-button.mjs.map +1 -1
  6. package/fesm2022/shival99-z-ui-components-z-calendar.mjs +61 -32
  7. package/fesm2022/shival99-z-ui-components-z-calendar.mjs.map +1 -1
  8. package/fesm2022/shival99-z-ui-components-z-card.mjs +1 -1
  9. package/fesm2022/shival99-z-ui-components-z-card.mjs.map +1 -1
  10. package/fesm2022/shival99-z-ui-components-z-chat.mjs +429 -0
  11. package/fesm2022/shival99-z-ui-components-z-chat.mjs.map +1 -0
  12. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs +1 -1
  13. package/fesm2022/shival99-z-ui-components-z-checkbox.mjs.map +1 -1
  14. package/fesm2022/shival99-z-ui-components-z-code.mjs +51 -21
  15. package/fesm2022/shival99-z-ui-components-z-code.mjs.map +1 -1
  16. package/fesm2022/shival99-z-ui-components-z-drawer.mjs +8 -3
  17. package/fesm2022/shival99-z-ui-components-z-drawer.mjs.map +1 -1
  18. package/fesm2022/shival99-z-ui-components-z-editor.mjs +3 -3
  19. package/fesm2022/shival99-z-ui-components-z-editor.mjs.map +1 -1
  20. package/fesm2022/shival99-z-ui-components-z-empty.mjs.map +1 -1
  21. package/fesm2022/shival99-z-ui-components-z-filter.mjs +3 -3
  22. package/fesm2022/shival99-z-ui-components-z-filter.mjs.map +1 -1
  23. package/fesm2022/shival99-z-ui-components-z-gallery.mjs +169 -90
  24. package/fesm2022/shival99-z-ui-components-z-gallery.mjs.map +1 -1
  25. package/fesm2022/shival99-z-ui-components-z-icon.mjs +143 -360
  26. package/fesm2022/shival99-z-ui-components-z-icon.mjs.map +1 -1
  27. package/fesm2022/shival99-z-ui-components-z-input.mjs +131 -8
  28. package/fesm2022/shival99-z-ui-components-z-input.mjs.map +1 -1
  29. package/fesm2022/shival99-z-ui-components-z-loading.mjs +2 -2
  30. package/fesm2022/shival99-z-ui-components-z-loading.mjs.map +1 -1
  31. package/fesm2022/shival99-z-ui-components-z-menu.mjs +2 -2
  32. package/fesm2022/shival99-z-ui-components-z-menu.mjs.map +1 -1
  33. package/fesm2022/shival99-z-ui-components-z-modal.mjs +8 -3
  34. package/fesm2022/shival99-z-ui-components-z-modal.mjs.map +1 -1
  35. package/fesm2022/shival99-z-ui-components-z-pagination.mjs +1 -1
  36. package/fesm2022/shival99-z-ui-components-z-pagination.mjs.map +1 -1
  37. package/fesm2022/shival99-z-ui-components-z-popover.mjs +3 -3
  38. package/fesm2022/shival99-z-ui-components-z-popover.mjs.map +1 -1
  39. package/fesm2022/shival99-z-ui-components-z-select.mjs +31 -7
  40. package/fesm2022/shival99-z-ui-components-z-select.mjs.map +1 -1
  41. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs +3 -3
  42. package/fesm2022/shival99-z-ui-components-z-skeleton.mjs.map +1 -1
  43. package/fesm2022/shival99-z-ui-components-z-steps.mjs +31 -29
  44. package/fesm2022/shival99-z-ui-components-z-steps.mjs.map +1 -1
  45. package/fesm2022/shival99-z-ui-components-z-switch.mjs +131 -15
  46. package/fesm2022/shival99-z-ui-components-z-switch.mjs.map +1 -1
  47. package/fesm2022/shival99-z-ui-components-z-table.mjs +57 -13
  48. package/fesm2022/shival99-z-ui-components-z-table.mjs.map +1 -1
  49. package/fesm2022/shival99-z-ui-components-z-tabs.mjs +6 -6
  50. package/fesm2022/shival99-z-ui-components-z-tabs.mjs.map +1 -1
  51. package/fesm2022/shival99-z-ui-components-z-tags.mjs +1 -1
  52. package/fesm2022/shival99-z-ui-components-z-tags.mjs.map +1 -1
  53. package/fesm2022/shival99-z-ui-components-z-timeline.mjs +6 -6
  54. package/fesm2022/shival99-z-ui-components-z-timeline.mjs.map +1 -1
  55. package/fesm2022/shival99-z-ui-components-z-tooltip.mjs +4 -4
  56. package/fesm2022/shival99-z-ui-components-z-tooltip.mjs.map +1 -1
  57. package/fesm2022/shival99-z-ui-components-z-upload.mjs +5 -4
  58. package/fesm2022/shival99-z-ui-components-z-upload.mjs.map +1 -1
  59. package/fesm2022/shival99-z-ui-i18n.mjs +12 -0
  60. package/fesm2022/shival99-z-ui-i18n.mjs.map +1 -1
  61. package/fesm2022/shival99-z-ui-pipes.mjs +18 -0
  62. package/fesm2022/shival99-z-ui-pipes.mjs.map +1 -1
  63. package/fesm2022/shival99-z-ui-providers.mjs +30 -13
  64. package/fesm2022/shival99-z-ui-providers.mjs.map +1 -1
  65. package/fesm2022/shival99-z-ui-services.mjs +53 -29
  66. package/fesm2022/shival99-z-ui-services.mjs.map +1 -1
  67. package/fesm2022/z-ui.mjs +0 -4
  68. package/fesm2022/z-ui.mjs.map +1 -1
  69. package/package.json +6 -1
  70. package/types/shival99-z-ui-components-z-autocomplete.d.ts +25 -38
  71. package/types/shival99-z-ui-components-z-breadcrumb.d.ts +4 -4
  72. package/types/shival99-z-ui-components-z-button.d.ts +5 -4
  73. package/types/shival99-z-ui-components-z-chat.d.ts +148 -0
  74. package/types/shival99-z-ui-components-z-drawer.d.ts +3 -1
  75. package/types/shival99-z-ui-components-z-dropdown-menu.d.ts +2 -2
  76. package/types/shival99-z-ui-components-z-empty.d.ts +3 -3
  77. package/types/shival99-z-ui-components-z-filter.d.ts +2 -2
  78. package/types/shival99-z-ui-components-z-gallery.d.ts +6 -3
  79. package/types/shival99-z-ui-components-z-icon.d.ts +18 -304
  80. package/types/shival99-z-ui-components-z-input.d.ts +42 -1
  81. package/types/shival99-z-ui-components-z-modal.d.ts +4 -2
  82. package/types/shival99-z-ui-components-z-select.d.ts +5 -2
  83. package/types/shival99-z-ui-components-z-steps.d.ts +4 -4
  84. package/types/shival99-z-ui-components-z-switch.d.ts +25 -4
  85. package/types/shival99-z-ui-components-z-table.d.ts +2 -0
  86. package/types/shival99-z-ui-pipes.d.ts +2 -0
  87. package/types/shival99-z-ui-providers.d.ts +10 -16
  88. package/types/shival99-z-ui-services.d.ts +6 -1
  89. package/types/z-ui.d.ts +1 -2
@@ -456,7 +456,7 @@ const zFilterContainerVariants = cva('flex flex-wrap items-center gap-2', {
456
456
  size: 'md',
457
457
  },
458
458
  });
459
- const zFilterItemVariants = cva('inline-flex items-stretch rounded-[4px] border border-input bg-background shadow-xs overflow-hidden', {
459
+ const zFilterItemVariants = cva('inline-flex items-stretch rounded-[0.25rem] border border-input bg-background shadow-xs overflow-hidden', {
460
460
  variants: {
461
461
  size: {
462
462
  sm: 'h-8',
@@ -770,14 +770,14 @@ class ZFilterComponent {
770
770
  return field.key || `field-${index}`;
771
771
  }
772
772
  static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
773
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZFilterComponent, isStandalone: true, selector: "z-filter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zFilters: { classPropertyName: "zFilters", publicName: "zFilters", isSignal: true, isRequired: true, transformFunction: null }, zFields: { classPropertyName: "zFields", publicName: "zFields", isSignal: true, isRequired: true, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zI18n: { classPropertyName: "zI18n", publicName: "zI18n", isSignal: true, isRequired: false, transformFunction: null }, zShowAddButton: { classPropertyName: "zShowAddButton", publicName: "zShowAddButton", isSignal: true, isRequired: false, transformFunction: null }, zAllowMultiple: { classPropertyName: "zAllowMultiple", publicName: "zAllowMultiple", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonIcon: { classPropertyName: "zAddButtonIcon", publicName: "zAddButtonIcon", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonText: { classPropertyName: "zAddButtonText", publicName: "zAddButtonText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zFiltersChange: "zFiltersChange", zFilterAdd: "zFilterAdd", zFilterRemove: "zFilterRemove", zFilterUpdate: "zFilterUpdate" }, host: { attributes: { "data-slot": "z-filter" }, properties: { "class": "hostClasses()" } }, queries: [{ propertyName: "addButtonTemplate", first: true, predicate: ["addButton"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "addFilterSearchInput", first: true, predicate: ["addFilterSearchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n @if (addButtonTemplate()) {\n <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n } @else {\n <button\n z-button\n zType=\"outline\"\n [zSize]=\"buttonSize()\"\n z-popover\n [zPopoverContent]=\"addFilterPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"6\"\n (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n {{ zAddButtonText() || i18n().addFilter }}\n </button>\n }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n <div class=\"w-[200px]\">\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n #addFilterSearchInput\n type=\"text\"\n [placeholder]=\"i18n().searchFields\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n </div>\n <div class=\"flex max-h-[300px] flex-col gap-0.5 overflow-y-auto p-1\">\n @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n @if (group.group) {\n <div\n class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n [class.border-border]=\"groupIndex > 0\"\n [class.mt-2]=\"groupIndex > 0\"\n [class.border-t]=\"groupIndex > 0\"\n [class.ml-1]=\"groupIndex > 0\">\n {{ group.group }}\n </div>\n }\n @for (field of group.fields; track trackByFieldKey($index, field)) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onFieldSelect(field); close()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ field.label }}</span>\n </button>\n }\n } @empty {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noFieldsFound }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n @if (filter | zFilterField: $any(zFields()); as field) {\n <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n <!-- Field Label -->\n <div [class]=\"getLabelClasses()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n }\n {{ field.label }}\n </div>\n\n <!-- Operator Dropdown -->\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"operatorDropdown\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n (zHide)=\"operatorPopoverOpen.set(null)\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n </button>\n\n <ng-template #operatorDropdown let-close=\"close\">\n <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n (click)=\"updateFilterOperator(filter, op.value); close()\">\n <span>{{ op.label }}</span>\n @if (op.value === filter.operator) {\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n }\n </button>\n }\n </div>\n </ng-template>\n\n <!-- Value Selector -->\n @if (!(filter | zFilterIsValueHidden)) {\n <!-- Boolean Field -->\n @if (field.type === 'boolean') {\n <div class=\"flex items-center gap-2 px-2.5\">\n <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n @if (field.onLabel && field.offLabel) {\n <span class=\"text-muted-foreground text-xs\">\n {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n </span>\n }\n </div>\n }\n\n <!-- Text/Email/URL/Tel Input -->\n @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"{{\n field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n }}\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [pattern]=\"field | zFilterInputPattern\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n\n <!-- Number Input -->\n @else if (field.type === 'number') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"i18n().min\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n <input\n type=\"number\"\n [value]=\"filter.values[1] || ''\"\n [placeholder]=\"i18n().max\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 1)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-24\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n }\n\n <!-- Date Input -->\n @else if (field.type === 'date') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- Select/Multiselect -->\n @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"selectPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n (zHide)=\"valuePopoverOpen.set(null)\"\n class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n @if (selectedOpts.length > 0) {\n <div class=\"flex items-center -space-x-1.5\">\n @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n }\n </div>\n @if (selectedOpts.length === 1) {\n {{ selectedOpts[0].label }}\n } @else {\n {{ selectedOpts.length }} {{ i18n().selectedCount }}\n }\n } @else {\n <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n }\n }\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n </button>\n\n <ng-template #selectPopover let-close=\"close\">\n <div class=\"w-[200px]\">\n @if (field.searchable !== false) {\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n [id]=\"'select-search-' + filter.id\"\n type=\"text\"\n [placeholder]=\"i18n().placeholders.searchField\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n </div>\n }\n <div class=\"flex max-h-[200px] flex-col gap-0.5 overflow-y-auto p-1\">\n <!-- Selected Options -->\n @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n </button>\n }\n\n <!-- Separator -->\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n ) {\n <div class=\"bg-border my-1 ml-1 h-px\"></div>\n }\n\n <!-- Unselected Options -->\n @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n </button>\n }\n\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n ) {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noResultsFound }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n }\n }\n\n <!-- Remove Button -->\n <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n </div>\n }\n}\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZSwitchComponent, selector: "z-switch", inputs: ["class", "zSize", "zLabel", "zText", "zDisabled", "zLoading", "zTextPosition", "zChecked"], outputs: ["zChange", "zOnBlur", "zOnFocus", "zEvent", "zCheckedChange"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zManualClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange"], exportAs: ["zPopover"] }, { kind: "pipe", type: ZFilterFieldPipe, name: "zFilterField" }, { kind: "pipe", type: ZFilterOperatorLabelPipe, name: "zFilterOperatorLabel" }, { kind: "pipe", type: ZFilterOperatorsPipe, name: "zFilterOperators" }, { kind: "pipe", type: ZFilterSelectedOptionsPipe, name: "zFilterSelectedOptions" }, { kind: "pipe", type: ZFilterUnselectedOptionsPipe, name: "zFilterUnselectedOptions" }, { kind: "pipe", type: ZFilterInputPatternPipe, name: "zFilterInputPattern" }, { kind: "pipe", type: ZFilterIsValueHiddenPipe, name: "zFilterIsValueHidden" }, { kind: "pipe", type: ZFilterIsBetweenOperatorPipe, name: "zFilterIsBetweenOperator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
773
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.0.6", type: ZFilterComponent, isStandalone: true, selector: "z-filter", inputs: { class: { classPropertyName: "class", publicName: "class", isSignal: true, isRequired: false, transformFunction: null }, zFilters: { classPropertyName: "zFilters", publicName: "zFilters", isSignal: true, isRequired: true, transformFunction: null }, zFields: { classPropertyName: "zFields", publicName: "zFields", isSignal: true, isRequired: true, transformFunction: null }, zSize: { classPropertyName: "zSize", publicName: "zSize", isSignal: true, isRequired: false, transformFunction: null }, zI18n: { classPropertyName: "zI18n", publicName: "zI18n", isSignal: true, isRequired: false, transformFunction: null }, zShowAddButton: { classPropertyName: "zShowAddButton", publicName: "zShowAddButton", isSignal: true, isRequired: false, transformFunction: null }, zAllowMultiple: { classPropertyName: "zAllowMultiple", publicName: "zAllowMultiple", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonIcon: { classPropertyName: "zAddButtonIcon", publicName: "zAddButtonIcon", isSignal: true, isRequired: false, transformFunction: null }, zAddButtonText: { classPropertyName: "zAddButtonText", publicName: "zAddButtonText", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { zFiltersChange: "zFiltersChange", zFilterAdd: "zFilterAdd", zFilterRemove: "zFilterRemove", zFilterUpdate: "zFilterUpdate" }, host: { attributes: { "data-slot": "z-filter" }, properties: { "class": "hostClasses()" } }, queries: [{ propertyName: "addButtonTemplate", first: true, predicate: ["addButton"], descendants: true, isSignal: true }], viewQueries: [{ propertyName: "addFilterSearchInput", first: true, predicate: ["addFilterSearchInput"], descendants: true, isSignal: true }], ngImport: i0, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n @if (addButtonTemplate()) {\n <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n } @else {\n <button\n z-button\n zType=\"outline\"\n [zSize]=\"buttonSize()\"\n z-popover\n [zPopoverContent]=\"addFilterPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"6\"\n (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n {{ zAddButtonText() || i18n().addFilter }}\n </button>\n }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n #addFilterSearchInput\n type=\"text\"\n [placeholder]=\"i18n().searchFields\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n </div>\n <div class=\"flex max-h-[18.75rem] flex-col gap-0.5 overflow-y-auto p-1\">\n @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n @if (group.group) {\n <div\n class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n [class.border-border]=\"groupIndex > 0\"\n [class.mt-2]=\"groupIndex > 0\"\n [class.border-t]=\"groupIndex > 0\"\n [class.ml-1]=\"groupIndex > 0\">\n {{ group.group }}\n </div>\n }\n @for (field of group.fields; track trackByFieldKey($index, field)) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onFieldSelect(field); close()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ field.label }}</span>\n </button>\n }\n } @empty {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noFieldsFound }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n @if (filter | zFilterField: $any(zFields()); as field) {\n <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n <!-- Field Label -->\n <div [class]=\"getLabelClasses()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n }\n {{ field.label }}\n </div>\n\n <!-- Operator Dropdown -->\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"operatorDropdown\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n (zHide)=\"operatorPopoverOpen.set(null)\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n </button>\n\n <ng-template #operatorDropdown let-close=\"close\">\n <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n (click)=\"updateFilterOperator(filter, op.value); close()\">\n <span>{{ op.label }}</span>\n @if (op.value === filter.operator) {\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n }\n </button>\n }\n </div>\n </ng-template>\n\n <!-- Value Selector -->\n @if (!(filter | zFilterIsValueHidden)) {\n <!-- Boolean Field -->\n @if (field.type === 'boolean') {\n <div class=\"flex items-center gap-2 px-2.5\">\n <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n @if (field.onLabel && field.offLabel) {\n <span class=\"text-muted-foreground text-xs\">\n {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n </span>\n }\n </div>\n }\n\n <!-- Text/Email/URL/Tel Input -->\n @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"{{\n field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n }}\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [pattern]=\"field | zFilterInputPattern\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n\n <!-- Number Input -->\n @else if (field.type === 'number') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"i18n().min\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n <input\n type=\"number\"\n [value]=\"filter.values[1] || ''\"\n [placeholder]=\"i18n().max\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 1)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-24\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n }\n\n <!-- Date Input -->\n @else if (field.type === 'date') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- Select/Multiselect -->\n @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"selectPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n (zHide)=\"valuePopoverOpen.set(null)\"\n class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n @if (selectedOpts.length > 0) {\n <div class=\"flex items-center -space-x-1.5\">\n @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n }\n </div>\n @if (selectedOpts.length === 1) {\n {{ selectedOpts[0].label }}\n } @else {\n {{ selectedOpts.length }} {{ i18n().selectedCount }}\n }\n } @else {\n <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n }\n }\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n </button>\n\n <ng-template #selectPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n @if (field.searchable !== false) {\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n [id]=\"'select-search-' + filter.id\"\n type=\"text\"\n [placeholder]=\"i18n().placeholders.searchField\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n </div>\n }\n <div class=\"flex max-h-[12.5rem] flex-col gap-0.5 overflow-y-auto p-1\">\n <!-- Selected Options -->\n @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n </button>\n }\n\n <!-- Separator -->\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n ) {\n <div class=\"bg-border my-1 ml-1 h-px\"></div>\n }\n\n <!-- Unselected Options -->\n @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n </button>\n }\n\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n ) {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noResultsFound }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n }\n }\n\n <!-- Remove Button -->\n <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n </div>\n }\n}\n", styles: [":host{display:block}\n"], dependencies: [{ kind: "component", type: ZIconComponent, selector: "z-icon, [z-icon]", inputs: ["class", "zType", "zSize", "zStrokeWidth", "zSvg"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "component", type: ZSwitchComponent, selector: "z-switch", inputs: ["class", "zSize", "zMode", "zLabel", "zText", "zCheckedText", "zUncheckedText", "zDisabled", "zLoading", "zTextPosition", "zWave", "zChecked"], outputs: ["zChange", "zOnBlur", "zOnFocus", "zEvent", "zCheckedChange"] }, { kind: "component", type: ZButtonComponent, selector: "z-button, button[z-button], a[z-button]", inputs: ["class", "zType", "zSize", "zShape", "zLabel", "zLoading", "zDisabled", "zTypeIcon", "zSizeIcon", "zStrokeWidthIcon", "zWave"], exportAs: ["zButton"] }, { kind: "directive", type: ZPopoverDirective, selector: "[z-popover]", inputs: ["zPopoverContent", "zPosition", "zTrigger", "zClass", "zShowDelay", "zHideDelay", "zDisabled", "zOffset", "zPopoverWidth", "zManualClose", "zScrollClose", "zShowArrow"], outputs: ["zShow", "zHide", "zHideStart", "zControl", "zPositionChange"], exportAs: ["zPopover"] }, { kind: "pipe", type: ZFilterFieldPipe, name: "zFilterField" }, { kind: "pipe", type: ZFilterOperatorLabelPipe, name: "zFilterOperatorLabel" }, { kind: "pipe", type: ZFilterOperatorsPipe, name: "zFilterOperators" }, { kind: "pipe", type: ZFilterSelectedOptionsPipe, name: "zFilterSelectedOptions" }, { kind: "pipe", type: ZFilterUnselectedOptionsPipe, name: "zFilterUnselectedOptions" }, { kind: "pipe", type: ZFilterInputPatternPipe, name: "zFilterInputPattern" }, { kind: "pipe", type: ZFilterIsValueHiddenPipe, name: "zFilterIsValueHidden" }, { kind: "pipe", type: ZFilterIsBetweenOperatorPipe, name: "zFilterIsBetweenOperator" }], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None });
774
774
  }
775
775
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.0.6", ngImport: i0, type: ZFilterComponent, decorators: [{
776
776
  type: Component,
777
777
  args: [{ selector: 'z-filter', imports: [ZIconComponent, NgTemplateOutlet, ZSwitchComponent, ZButtonComponent, ZPopoverDirective, ...Z_FILTER_PIPES], standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, encapsulation: ViewEncapsulation.None, host: {
778
778
  '[class]': 'hostClasses()',
779
779
  'data-slot': 'z-filter',
780
- }, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n @if (addButtonTemplate()) {\n <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n } @else {\n <button\n z-button\n zType=\"outline\"\n [zSize]=\"buttonSize()\"\n z-popover\n [zPopoverContent]=\"addFilterPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"6\"\n (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n {{ zAddButtonText() || i18n().addFilter }}\n </button>\n }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n <div class=\"w-[200px]\">\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n #addFilterSearchInput\n type=\"text\"\n [placeholder]=\"i18n().searchFields\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n </div>\n <div class=\"flex max-h-[300px] flex-col gap-0.5 overflow-y-auto p-1\">\n @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n @if (group.group) {\n <div\n class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n [class.border-border]=\"groupIndex > 0\"\n [class.mt-2]=\"groupIndex > 0\"\n [class.border-t]=\"groupIndex > 0\"\n [class.ml-1]=\"groupIndex > 0\">\n {{ group.group }}\n </div>\n }\n @for (field of group.fields; track trackByFieldKey($index, field)) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onFieldSelect(field); close()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ field.label }}</span>\n </button>\n }\n } @empty {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noFieldsFound }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n @if (filter | zFilterField: $any(zFields()); as field) {\n <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n <!-- Field Label -->\n <div [class]=\"getLabelClasses()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n }\n {{ field.label }}\n </div>\n\n <!-- Operator Dropdown -->\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"operatorDropdown\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n (zHide)=\"operatorPopoverOpen.set(null)\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n </button>\n\n <ng-template #operatorDropdown let-close=\"close\">\n <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n (click)=\"updateFilterOperator(filter, op.value); close()\">\n <span>{{ op.label }}</span>\n @if (op.value === filter.operator) {\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n }\n </button>\n }\n </div>\n </ng-template>\n\n <!-- Value Selector -->\n @if (!(filter | zFilterIsValueHidden)) {\n <!-- Boolean Field -->\n @if (field.type === 'boolean') {\n <div class=\"flex items-center gap-2 px-2.5\">\n <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n @if (field.onLabel && field.offLabel) {\n <span class=\"text-muted-foreground text-xs\">\n {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n </span>\n }\n </div>\n }\n\n <!-- Text/Email/URL/Tel Input -->\n @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"{{\n field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n }}\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [pattern]=\"field | zFilterInputPattern\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n\n <!-- Number Input -->\n @else if (field.type === 'number') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"i18n().min\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n <input\n type=\"number\"\n [value]=\"filter.values[1] || ''\"\n [placeholder]=\"i18n().max\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 1)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-24\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n }\n\n <!-- Date Input -->\n @else if (field.type === 'date') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- Select/Multiselect -->\n @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"selectPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n (zHide)=\"valuePopoverOpen.set(null)\"\n class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n @if (selectedOpts.length > 0) {\n <div class=\"flex items-center -space-x-1.5\">\n @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n }\n </div>\n @if (selectedOpts.length === 1) {\n {{ selectedOpts[0].label }}\n } @else {\n {{ selectedOpts.length }} {{ i18n().selectedCount }}\n }\n } @else {\n <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n }\n }\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n </button>\n\n <ng-template #selectPopover let-close=\"close\">\n <div class=\"w-[200px]\">\n @if (field.searchable !== false) {\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n [id]=\"'select-search-' + filter.id\"\n type=\"text\"\n [placeholder]=\"i18n().placeholders.searchField\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n </div>\n }\n <div class=\"flex max-h-[200px] flex-col gap-0.5 overflow-y-auto p-1\">\n <!-- Selected Options -->\n @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n </button>\n }\n\n <!-- Separator -->\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n ) {\n <div class=\"bg-border my-1 ml-1 h-px\"></div>\n }\n\n <!-- Unselected Options -->\n @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n </button>\n }\n\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n ) {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noResultsFound }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n }\n }\n\n <!-- Remove Button -->\n <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n </div>\n }\n}\n", styles: [":host{display:block}\n"] }]
780
+ }, template: "<!-- Add Filter Button -->\n@if (zShowAddButton() && selectableFields().length > 0) {\n @if (addButtonTemplate()) {\n <ng-container [ngTemplateOutlet]=\"addButtonTemplate()!\" />\n } @else {\n <button\n z-button\n zType=\"outline\"\n [zSize]=\"buttonSize()\"\n z-popover\n [zPopoverContent]=\"addFilterPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"6\"\n (zShow)=\"addFilterOpen.set(true); focusSearchInput()\"\n (zHide)=\"addFilterOpen.set(false); searchQuery.set('')\">\n <z-icon [zType]=\"zAddButtonIcon()\" zSize=\"14\" />\n {{ zAddButtonText() || i18n().addFilter }}\n </button>\n }\n}\n\n<ng-template #addFilterPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n #addFilterSearchInput\n type=\"text\"\n [placeholder]=\"i18n().searchFields\"\n [value]=\"searchQuery()\"\n (input)=\"onSearchInput($event)\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-10 w-full bg-transparent py-3 text-sm outline-none\" />\n </div>\n <div class=\"flex max-h-[18.75rem] flex-col gap-0.5 overflow-y-auto p-1\">\n @for (group of groupedFields(); track group.group; let groupIndex = $index) {\n @if (group.group) {\n <div\n class=\"text-muted-foreground px-2 py-1.5 text-xs font-medium\"\n [class.border-border]=\"groupIndex > 0\"\n [class.mt-2]=\"groupIndex > 0\"\n [class.border-t]=\"groupIndex > 0\"\n [class.ml-1]=\"groupIndex > 0\">\n {{ group.group }}\n </div>\n }\n @for (field of group.fields; track trackByFieldKey($index, field)) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onFieldSelect(field); close()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" class=\"text-muted-foreground\" />\n }\n <span>{{ field.label }}</span>\n </button>\n }\n } @empty {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noFieldsFound }}\n </div>\n }\n </div>\n </div>\n</ng-template>\n\n<!-- Filter Items -->\n@for (filter of zFilters(); track trackByFilterId($index, filter)) {\n @if (filter | zFilterField: $any(zFields()); as field) {\n <div [class]=\"getItemClasses()\" data-slot=\"filter-item\">\n <!-- Field Label -->\n <div [class]=\"getLabelClasses()\">\n @if (field.icon) {\n <z-icon [zType]=\"field.icon\" zSize=\"14\" />\n }\n {{ field.label }}\n </div>\n\n <!-- Operator Dropdown -->\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"operatorDropdown\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"operatorPopoverOpen.set(filter.id)\"\n (zHide)=\"operatorPopoverOpen.set(null)\"\n class=\"text-muted-foreground hover:text-foreground hover:bg-muted flex cursor-pointer items-center px-2.5 text-sm transition-colors\"\n [class.text-foreground]=\"operatorPopoverOpen() === filter.id\"\n [class.bg-muted]=\"operatorPopoverOpen() === filter.id\">\n {{ filter | zFilterOperatorLabel: $any(zFields()) : i18n() }}\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"ml-1\" />\n </button>\n\n <ng-template #operatorDropdown let-close=\"close\">\n <div class=\"flex w-fit min-w-32 flex-col gap-0.5 p-1\">\n @for (op of filter | zFilterOperators: $any(zFields()) : i18n(); track op.value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center justify-between gap-4 rounded-sm px-2 py-1.5 text-sm transition-colors outline-none\"\n (click)=\"updateFilterOperator(filter, op.value); close()\">\n <span>{{ op.label }}</span>\n @if (op.value === filter.operator) {\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary\" />\n }\n </button>\n }\n </div>\n </ng-template>\n\n <!-- Value Selector -->\n @if (!(filter | zFilterIsValueHidden)) {\n <!-- Boolean Field -->\n @if (field.type === 'boolean') {\n <div class=\"flex items-center gap-2 px-2.5\">\n <z-switch [zChecked]=\"filter.values[0] === true\" (zChange)=\"onBooleanChange(filter, $event)\" zSize=\"sm\" />\n @if (field.onLabel && field.offLabel) {\n <span class=\"text-muted-foreground text-xs\">\n {{ filter.values[0] === true ? field.onLabel : field.offLabel }}\n </span>\n }\n </div>\n }\n\n <!-- Text/Email/URL/Tel Input -->\n @else if (field.type === 'text' || field.type === 'email' || field.type === 'url' || field.type === 'tel') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"{{\n field.type === 'email' ? 'email' : field.type === 'url' ? 'url' : field.type === 'tel' ? 'tel' : 'text'\n }}\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [pattern]=\"field | zFilterInputPattern\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n\n <!-- Number Input -->\n @else if (field.type === 'number') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"i18n().min\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-20\">\n <input\n type=\"number\"\n [value]=\"filter.values[1] || ''\"\n [placeholder]=\"i18n().max\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event, 1)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-24\">\n @if (field.prefix) {\n <span class=\"text-muted-foreground mr-1\">{{ field.prefix }}</span>\n }\n <input\n type=\"number\"\n [value]=\"filter.values[0] || ''\"\n [placeholder]=\"field.placeholder || i18n().placeholders.enterField\"\n [min]=\"field.min\"\n [max]=\"field.max\"\n [step]=\"field.step\"\n class=\"w-full bg-transparent outline-none\"\n (blur)=\"onInputChange(filter, $event)\" />\n @if (field.suffix) {\n <span class=\"text-muted-foreground ml-1\">{{ field.suffix }}</span>\n }\n </div>\n }\n }\n\n <!-- Date Input -->\n @else if (field.type === 'date') {\n <div [class]=\"getInputClasses()\" class=\"w-36\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n\n <!-- Date Range Input -->\n @else if (field.type === 'daterange') {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-32\">\n <input\n type=\"date\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n }\n\n <!-- Time Input -->\n @else if (field.type === 'time') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-28\">\n <input\n type=\"time\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- DateTime Input -->\n @else if (field.type === 'datetime') {\n @if (filter | zFilterIsBetweenOperator) {\n <div class=\"flex items-center\">\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 0)\" />\n </div>\n <div [class]=\"getBetweenClasses()\">{{ i18n().to }}</div>\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[1] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event, 1)\" />\n </div>\n </div>\n } @else {\n <div [class]=\"getInputClasses()\" class=\"w-44\">\n <input\n type=\"datetime-local\"\n [value]=\"filter.values[0] || ''\"\n class=\"w-full bg-transparent outline-none\"\n (change)=\"onInputChange(filter, $event)\" />\n </div>\n }\n }\n\n <!-- Select/Multiselect -->\n @else if (field.type === 'select' || field.type === 'multiselect' || field.options) {\n <button\n type=\"button\"\n z-popover\n [zPopoverContent]=\"selectPopover\"\n zTrigger=\"click\"\n zPosition=\"bottom-left\"\n [zOffset]=\"4\"\n (zShow)=\"valuePopoverOpen.set(filter.id); focusSelectSearch(filter.id)\"\n (zHide)=\"valuePopoverOpen.set(null)\"\n class=\"hover:bg-muted flex cursor-pointer items-center gap-1.5 px-2.5 text-sm transition-colors\"\n [class.bg-muted]=\"valuePopoverOpen() === filter.id\">\n @if (filter | zFilterSelectedOptions: $any(zFields()); as selectedOpts) {\n @if (selectedOpts.length > 0) {\n <div class=\"flex items-center -space-x-1.5\">\n @for (opt of selectedOpts.slice(0, 3); track $any(opt).value) {\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n }\n </div>\n @if (selectedOpts.length === 1) {\n {{ selectedOpts[0].label }}\n } @else {\n {{ selectedOpts.length }} {{ i18n().selectedCount }}\n }\n } @else {\n <span class=\"text-muted-foreground\">{{ i18n().select }}</span>\n }\n }\n <z-icon zType=\"lucideChevronDown\" zSize=\"12\" class=\"text-muted-foreground ml-1\" />\n </button>\n\n <ng-template #selectPopover let-close=\"close\">\n <div class=\"w-[12.5rem]\">\n @if (field.searchable !== false) {\n <div class=\"border-border flex items-center border-b px-3\">\n <z-icon zType=\"lucideSearch\" zSize=\"16\" class=\"text-muted-foreground/50 mr-2 shrink-0\" />\n <input\n [id]=\"'select-search-' + filter.id\"\n type=\"text\"\n [placeholder]=\"i18n().placeholders.searchField\"\n class=\"placeholder:text-muted-foreground text-foreground flex h-9 w-full bg-transparent py-2 text-sm outline-none\" />\n </div>\n }\n <div class=\"flex max-h-[12.5rem] flex-col gap-0.5 overflow-y-auto p-1\">\n <!-- Selected Options -->\n @for (opt of filter | zFilterSelectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n <z-icon zType=\"lucideCheck\" zSize=\"14\" class=\"text-primary ml-auto\" />\n </button>\n }\n\n <!-- Separator -->\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length > 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length > 0\n ) {\n <div class=\"bg-border my-1 ml-1 h-px\"></div>\n }\n\n <!-- Unselected Options -->\n @for (opt of filter | zFilterUnselectedOptions: $any(zFields()); track $any(opt).value) {\n <button\n type=\"button\"\n class=\"hover:bg-accent flex w-full cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm transition-colors\"\n (click)=\"onSelectValueChange(filter, $any(opt)); field.type !== 'multiselect' && close()\">\n @if (opt.icon) {\n <z-icon [zType]=\"opt.icon\" zSize=\"14\" />\n }\n <span class=\"truncate\">{{ opt.label }}</span>\n </button>\n }\n\n @if (\n (filter | zFilterSelectedOptions: $any(zFields())).length === 0 &&\n (filter | zFilterUnselectedOptions: $any(zFields())).length === 0\n ) {\n <div class=\"text-muted-foreground py-6 text-center text-sm\">\n {{ i18n().noResultsFound }}\n </div>\n }\n </div>\n </div>\n </ng-template>\n }\n }\n\n <!-- Remove Button -->\n <button type=\"button\" [class]=\"getRemoveButtonClasses()\" data-slot=\"filter-remove\" (click)=\"removeFilter(filter)\">\n <z-icon zType=\"lucideX\" zSize=\"14\" />\n </button>\n </div>\n }\n}\n", styles: [":host{display:block}\n"] }]
781
781
  }], propDecorators: { addButtonTemplate: [{ type: i0.ContentChild, args: ['addButton', { isSignal: true }] }], zFiltersChange: [{ type: i0.Output, args: ["zFiltersChange"] }], zFilterAdd: [{ type: i0.Output, args: ["zFilterAdd"] }], zFilterRemove: [{ type: i0.Output, args: ["zFilterRemove"] }], zFilterUpdate: [{ type: i0.Output, args: ["zFilterUpdate"] }], class: [{ type: i0.Input, args: [{ isSignal: true, alias: "class", required: false }] }], zFilters: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFilters", required: true }] }], zFields: [{ type: i0.Input, args: [{ isSignal: true, alias: "zFields", required: true }] }], zSize: [{ type: i0.Input, args: [{ isSignal: true, alias: "zSize", required: false }] }], zI18n: [{ type: i0.Input, args: [{ isSignal: true, alias: "zI18n", required: false }] }], zShowAddButton: [{ type: i0.Input, args: [{ isSignal: true, alias: "zShowAddButton", required: false }] }], zAllowMultiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAllowMultiple", required: false }] }], zAddButtonIcon: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAddButtonIcon", required: false }] }], zAddButtonText: [{ type: i0.Input, args: [{ isSignal: true, alias: "zAddButtonText", required: false }] }], addFilterSearchInput: [{ type: i0.ViewChild, args: ['addFilterSearchInput', { isSignal: true }] }] } });
782
782
 
783
783
  /**