ng-zenduit 2.3.0 → 2.3.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.
@@ -4007,11 +4007,11 @@ class ZenduSelectComponent {
4007
4007
  this.isSelectedAll = this.options.every(opt => opt.checked);
4008
4008
  }
4009
4009
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ZenduSelectComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
4010
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ZenduSelectComponent, isStandalone: false, selector: "zen-select", inputs: { selectModel: "selectModel", options: "options", label: "label", supportingText: "supportingText", hintText: "hintText", placeholder: "placeholder", leadingType: "leadingType", leadingIcon: "leadingIcon", leadingAvatar: "leadingAvatar", leadingDotColor: "leadingDotColor", displayProp: "displayProp", idProp: "idProp", hasSearch: "hasSearch", isMultiselect: "isMultiselect", multiselect: "multiselect", hideSelectAll: "hideSelectAll", hideTreeSearch: "hideTreeSearch", required: "required", disabled: "disabled", error: "error", errorMessage: "errorMessage", destructive: "destructive", size: "size", returnOption: "returnOption", isTruncate: "isTruncate", enableAddNewOption: "enableAddNewOption", showDefaultAddOption: "showDefaultAddOption", newOptionText: "newOptionText", enableRemoveOption: "enableRemoveOption", removeOptionText: "removeOptionText", isLazyLoading: "isLazyLoading", lazyLoader: "lazyLoader", preferredOpenDirection: "preferredOpenDirection" }, outputs: { selectModelChange: "selectModelChange", addNewOption: "addNewOption", removeOption: "removeOption", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "optionTemplate", first: true, predicate: ZenduSelectOptionDirective, descendants: true }, { propertyName: "valueTemplate", first: true, predicate: ZenduSelectValueDirective, descendants: true }, { propertyName: "buttonTemplate", first: true, predicate: ZenduSelectButtonDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [class]=\"getStateClasses()\">\n <!-- Label -->\n @if (label) {\n <label class=\"app-select-label text text-sm text-weight-medium\"\n [ngClass]=\"{'required': required, 'disabled': disabled, 'destructive': destructive}\">\n {{ label | translate }}\n @if (required) {\n <span class=\"required-indicator\">*</span>\n }\n </label>\n }\n\n <!-- Select Input -->\n <div class=\"app-select-wrapper\">\n <!-- Custom Trigger Template (overrides built-in trigger) -->\n @if (buttonTemplate) {\n <div\n class=\"app-select-custom-trigger\"\n (click)=\"toggleDropdown()\">\n <ng-template [ngTemplateOutlet]=\"buttonTemplate.template\"\n [ngTemplateOutletContext]=\"{ isOpen: isOpen, selected: getSelectedOption(), display: selectedDisplay, disabled: disabled }\">\n </ng-template>\n </div>\n }\n\n <!-- Built-in Trigger (when no custom button template provided) -->\n @if (!buttonTemplate) {\n @switch (leadingType) {\n <!-- Default Select (no leading element) -->\n @case ('default') {\n <ng-container *ngTemplateOutlet=\"defaultSelectTemplate\"></ng-container>\n }\n <!-- Icon Leading Select -->\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconSelectTemplate\"></ng-container>\n }\n <!-- Avatar Leading Select -->\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarSelectTemplate\"></ng-container>\n }\n <!-- Dot Leading Select -->\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotSelectTemplate\"></ng-container>\n }\n <!-- Search Input Select -->\n @case ('search') {\n <ng-container *ngTemplateOutlet=\"searchInputTemplate\"></ng-container>\n }\n }\n }\n\n <!-- Dropdown Menu -->\n @if (isOpen) {\n <div class=\"app-select-dropdown\"\n [ngClass]=\"getDropdownDirectionClass()\"\n >\n <!-- Tree Mode: embed zen-groups inline -->\n @if (isTreeMode && isMultiselect) {\n <zen-groups [inline]=\"true\"\n [dataSource]=\"$any(options)\"\n [filteredDataSource]=\"treeFilteredDataSource\"\n [hideSelectAll]=\"hideSelectAll\"\n [hideSearch]=\"hideTreeSearch\"\n [idProp]=\"idProp\"\n [displayProp]=\"displayProp\"\n [(isSelectedAll)]=\"isSelectedAll\"\n (isSelectedAllChange)=\"onTreeSelectAllChange($event)\"\n (checkedChange)=\"onTreeCheckedChange($event)\">\n </zen-groups>\n } @else {\n <!-- Search Box for hasSearch (not for search type as it has inline search) -->\n @if (leadingType !== 'search' && hasSearch && !disabled) {\n <div class=\"app-select-search\">\n <zen-icon [name]=\"'search'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n <input type=\"text\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"onSearchChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n placeholder=\"Search\"\n class=\"app-select-search-input\">\n @if (searchText) {\n <zen-icon\n class=\"app-select-search-clear\"\n [name]=\"'x'\"\n [customColor]=\"'#667085'\"\n (click)=\"clearSearch(); $event.stopPropagation()\">\n </zen-icon>\n }\n </div>\n }\n <!-- Options List -->\n <div class=\"app-select-options\" (scroll)=\"onOptionsScroll($event)\">\n <!-- Select All Option for Multiselect -->\n @if (isMultiselect && !hideSelectAll && !isLazyLoading && filteredOptions.length > 0) {\n <button\n class=\"app-select-option select-all\"\n (click)=\"toggleSelectAll()\">\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isAllSelected()\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n <span class=\"app-select-option-text\">\n Select All\n </span>\n </button>\n }\n <!-- Add New Option -->\n @if (enableAddNewOption && (showDefaultAddOption || searchText)) {\n <button\n class=\"app-select-option add-new-option\"\n (click)=\"handleAddNewOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'plus'\" [customColor]=\"'#136AB6'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ (newOptionText || 'Add New Option') + (searchText ? ': \"' + searchText + '\"' : '') }}\n </span>\n </button>\n }\n <!-- Remove Option -->\n @if (enableRemoveOption) {\n <button\n class=\"app-select-option remove-option\"\n (click)=\"handleRemoveOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'user-x'\" [customColor]=\"'#344054'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ removeOptionText || 'Remove' }}\n </span>\n </button>\n }\n @if (filteredOptions.length === 0 && !enableAddNewOption && !isLoadingNow) {\n <div class=\"app-select-no-options\">\n No matching options found\n </div>\n }\n @for (option of filteredOptions; track option) {\n <button\n class=\"app-select-option\"\n [class.selected]=\"isSelected(option)\"\n (click)=\"selectOption(option)\">\n <!-- Checkbox for Multiselect -->\n @if (isMultiselect) {\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isSelected(option)\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n }\n <!-- Option Leading Element -->\n @if (leadingType !== 'default') {\n <div class=\"app-select-option-leading\">\n @switch (leadingType) {\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: option }\"></ng-container>\n }\n }\n </div>\n }\n <!-- Option Text -->\n <div class=\"app-select-option-text-wrapper\">\n <!-- Use custom template if provided -->\n @if (!isMultiselect && optionTemplate) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-template>\n } @else {\n <span class=\"app-select-option-text\" [class.app-select-option-truncate]=\"isTruncate\">\n {{ getName(option) | translate }}\n </span>\n @if (option.secondaryText) {\n <span class=\"app-select-option-secondary\">\n {{ option.secondaryText }}\n </span>\n }\n }\n </div>\n <!-- Check Icon for Single Select -->\n @if (!isMultiselect && isSelected(option)) {\n <zen-icon\n class=\"app-select-option-check\"\n [name]=\"'check'\"\n [customColor]=\"'#136AB6'\">\n </zen-icon>\n }\n </button>\n }\n <!-- Lazy loading spinner -->\n @if (isLazyLoading && isLoadingNow) {\n <div class=\"app-select-loading\">\n <zen-spinner size=\"small\"></zen-spinner>\n </div>\n }\n </div>\n }\n <!-- Flat List Mode (default) -->\n </div>\n }\n </div>\n\n <!-- Hint text / Error message -->\n @if ((destructive && errorMessage) || hintText) {\n <div\n class=\"app-select-hint text text-sm text-weight-regular\"\n [ngClass]=\"{'destructive': destructive}\">\n @if (destructive) {\n <i class=\"material-icons-outlined hint-icon\">error_outline</i>\n }\n <span>{{ ((destructive && errorMessage) ? errorMessage : hintText) | translate }}</span>\n </div>\n }\n</div>\n\n<!-- ============================================= -->\n<!-- MAIN SELECT INPUT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Default Select Template (No Leading Element) -->\n<ng-template #defaultSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Icon Select Template -->\n<ng-template #iconSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: getSelectedOption(), icon: leadingIcon }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Avatar Select Template -->\n<ng-template #avatarSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: getSelectedOption(), avatar: leadingAvatar }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Dot Select Template -->\n<ng-template #dotSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: getSelectedOption(), color: leadingDotColor }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Search Input Template -->\n<ng-template #searchInputTemplate>\n <div class=\"app-select-input app-select-search-input\"\n [class.focused]=\"isOpen || searchFocused\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <!-- Search Icon -->\n <zen-icon [name]=\"'search'\"\n [customColor]=\"disabled ? '#9CA3AF' : '#667085'\">\n </zen-icon>\n\n <!-- Search Input Field -->\n <input type=\"text\"\n class=\"app-select-search-field\"\n [(ngModel)]=\"searchInputValue\"\n (ngModelChange)=\"onSearchInputChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur($event)\"\n [placeholder]=\"selectedDisplay || placeholder\"\n [disabled]=\"disabled\">\n </div>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- SHARED COMPONENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Select Value Display -->\n<ng-template #selectValueDisplay>\n <div class=\"app-select-value-wrapper\">\n @if (valueTemplate && !isModelEmpty()) {\n <ng-template [ngTemplateOutlet]=\"valueTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: getSelectedOption(), display: selectedDisplay }\">\n </ng-template>\n } @else {\n <span class=\"app-select-value\" [class.placeholder]=\"isModelEmpty()\">\n {{ selectedDisplay || placeholder | translate }}\n </span>\n @if (getSelectedSecondaryText() && !isModelEmpty()) {\n <span class=\"app-select-secondary\">\n {{ getSelectedSecondaryText() }}\n </span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Dropdown Arrow -->\n<ng-template #dropdownArrow>\n <zen-icon class=\"app-select-arrow\"\n [class.rotated]=\"isOpen\"\n [name]=\"'chevron-down'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- LEADING ELEMENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Icon Leading Element (with smart resolution) -->\n<ng-template #iconLeadingElement let-option=\"option\" let-icon=\"icon\">\n @if (icon || option?.icon || option?.iconName) {\n @if (getIconPath(option, icon); as iconPath) {\n <!-- If icon contains / or . treat as SVG path -->\n @if ((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.')))) {\n <!-- Use img tag for Excel to preserve colors -->\n @if (iconPath.includes('excel')) {\n <img\n [src]=\"iconPath\"\n alt=\"\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Use zen-icon with src for other SVG files -->\n @if (!iconPath.includes('excel')) {\n <zen-icon\n [src]=\"iconPath\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n <!-- Otherwise treat as Material icon name or special cases -->\n @if (!((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.'))))) {\n <!-- Special case for Excel icon - use img to preserve colors -->\n @if ((icon === 'excel') || (option?.icon === 'excel') || (option?.iconName === 'excel')) {\n <img\n src=\"assets/ng-zenduit/icons/excel.svg\"\n alt=\"Excel\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Material icon names -->\n @if ((icon !== 'excel') && (option?.icon !== 'excel') && (option?.iconName !== 'excel')) {\n <zen-icon\n [name]=\"icon || option?.icon || option?.iconName\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n }\n }\n</ng-template>\n\n<!-- Avatar Leading Element -->\n<ng-template #avatarLeadingElement let-option=\"option\" let-avatar=\"avatar\">\n @if (avatar || option?.avatar) {\n <div class=\"app-select-avatar\" >\n <img [src]=\"avatar || option?.avatar\" alt=\"\">\n </div>\n }\n</ng-template>\n\n<!-- Dot Leading Element -->\n<ng-template #dotLeadingElement let-option=\"option\" let-color=\"color\">\n <div class=\"app-select-dot\"\n [style.background-color]=\"color || option?.dotColor || '#10B981'\">\n </div>\n</ng-template>", styles: [".text{margin:0;padding:0;color:#101828}.text-display-2xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:72px;line-height:90px;letter-spacing:-.02em}.text-display-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:60px;line-height:72px;letter-spacing:-.02em}.text-display-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:48px;line-height:60px;letter-spacing:-.02em}.text-display-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:36px;line-height:44px;letter-spacing:-.02em}.text-display-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:30px;line-height:38px;letter-spacing:0}.text-display-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:24px;line-height:32px;letter-spacing:0}.text-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:20px;line-height:30px;letter-spacing:0}.text-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:18px;line-height:28px;letter-spacing:0}.text-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0}.text-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.text-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0}.text-weight-regular{font-weight:400;font-style:normal}.text-weight-medium{font-weight:500;font-style:normal}.text-weight-semibold{font-weight:600;font-style:normal}.text-weight-bold{font-weight:700;font-style:normal}@media(max-width:768px){.text-display-2xl{font-size:48px;line-height:56px}.text-display-xl{font-size:40px;line-height:48px}.text-display-lg{font-size:32px;line-height:40px}}.app-select-container{width:100%;position:relative}.app-select-label{display:flex;align-items:center;gap:4px;margin-bottom:6px;color:#344054}.app-select-label .required-indicator{color:#f04438}.app-select-label.disabled{color:#d0d5dd}.app-select-wrapper{position:relative;width:100%}.app-select-custom-trigger{display:inline-flex;cursor:pointer;-webkit-user-select:none;user-select:none}.app-select-input{width:100%;min-height:44px;padding:10px 14px;box-sizing:border-box;display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;color:#101828;text-align:left;cursor:pointer;transition:all .2s ease}.app-select-input.app-select-search-input{cursor:text}.app-select-input.app-select-search-input .app-select-search-field{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;background:transparent;color:#101828;min-width:0}.app-select-input.app-select-search-input .app-select-search-field::placeholder{color:#667085}.app-select-input.app-select-search-input .app-select-search-field:disabled{cursor:not-allowed;color:#667085}.app-select-input:hover:not(:disabled){border-color:#d0d5dd}.app-select-input.focused,.app-select-input:focus{outline:none;border-color:#88c1f1;box-shadow:0 1px 2px #1018280d,0 0 0 4px #e3eefb}.app-select-input:disabled{background:#f9fafb;border-color:#d0d5dd;cursor:not-allowed;opacity:.6}.app-select-container.error .app-select-input:focus{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-leading,.app-select-option-leading{display:flex;align-items:center;flex-shrink:0}.app-select-avatar,.app-select-option-avatar{width:24px;height:24px;border-radius:50%;overflow:hidden;flex-shrink:0}.app-select-avatar img,.app-select-option-avatar img{width:100%;height:100%;object-fit:cover}.app-select-avatar .avatar-placeholder,.app-select-option-avatar .avatar-placeholder{width:100%;height:100%;background:#f2f4f7;color:#667085;display:flex;align-items:center;justify-content:center;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0;font-weight:600;font-style:normal}.app-select-dot,.app-select-option-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.app-select-value-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-value-wrapper .app-select-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085}.app-select-value{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-value.placeholder{color:#667085}.app-select-secondary,.app-select-option-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085;white-space:nowrap;flex-shrink:0}.app-select-arrow{margin-left:auto;flex-shrink:0;transition:transform .2s ease}.app-select-arrow.rotated{transform:rotate(180deg)}.app-select-dropdown{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:1000;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 4px 6px -2px #10182808,0 12px 16px -4px #10182814;overflow:hidden;max-height:320px;display:flex;flex-direction:column}.app-select-dropdown.dropdown-up{top:auto;bottom:calc(100% + 4px)}.app-select-dropdown.dropdown-down,.app-select-dropdown.dropdown-auto{top:calc(100% + 4px);bottom:auto}.app-select-search{padding:12px;border-bottom:1px solid #EAECF0;display:flex;align-items:center;gap:8px}.app-select-search .app-select-search-input{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;color:#101828}.app-select-search .app-select-search-input::placeholder{color:#667085}.app-select-search .app-select-search-clear{cursor:pointer}.app-select-loading{display:flex;justify-content:center;align-items:center;padding:8px 0}.app-select-options{flex:1;overflow-y:auto;padding:4px 0}.app-select-options::-webkit-scrollbar{width:6px}.app-select-options::-webkit-scrollbar-track{background:transparent}.app-select-options::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-no-options{padding:32px 24px;text-align:center;color:#667085;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.app-select-option{width:100%;padding:10px 14px;display:flex;align-items:center;gap:8px;background:transparent;border:none;text-align:left;cursor:pointer;transition:background .15s ease}.app-select-option:hover,.app-select-option.selected{background:#f9fafb}.app-select-option-text-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-option-text{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#344054;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-option-text.app-select-option-truncate{max-width:200px}.app-select-option-check{margin-left:auto;flex-shrink:0}.app-select-checkbox{display:flex;align-items:center;flex-shrink:0;margin-right:8px}.app-select-checkbox .checkbox-wrapper{margin-bottom:0}.app-select-checkbox .checkbox-content{display:none}.app-select-checkbox .checkbox-input{margin-right:0}.app-select-supporting{margin-top:6px;color:#667085}.app-select-supporting .error-text{color:#f04438}.app-select-container.size-sm .app-select-input{min-height:36px;padding:8px 12px}.app-select-container.error .app-select-input{border-color:#fda29b}.app-select-container.error .app-select-supporting{color:#f04438}.app-select-container.destructive .app-select-input{border-color:#fda29b}.app-select-container.destructive .app-select-input:focus,.app-select-container.destructive .app-select-input.focused{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-container.disabled .app-select-label,.app-select-container.disabled .app-select-value,.app-select-container.disabled .app-select-arrow,.app-select-container.disabled .app-select-leading zen-icon,.app-select-container.disabled .app-select-search-input zen-icon,.app-select-container.disabled .app-select-secondary,.app-select-container.disabled .app-select-search-field{opacity:.6}.app-select-container.disabled .app-select-input,.app-select-container.disabled .app-select-search-input{background:#f9fafb;cursor:not-allowed}.app-select-hint{display:flex;align-items:center;gap:4px;margin-top:6px;color:#667085}.app-select-hint .hint-icon{font-size:16px;color:#f04438}.app-select-hint.destructive{color:#f04438}.app-select-option.select-all{border-bottom:1px solid #F2F4F7;margin-bottom:4px;padding-bottom:14px}.app-select-option.add-new-option{color:#136ab6;font-weight:500}.app-select-option.add-new-option:hover{background:#eff8ff}.app-select-option.remove-option{background:#f9fafb;color:#344054}.app-select-option.remove-option .app-select-option-text{color:#344054}.app-select-spinner{display:flex;justify-content:center;padding:16px}.app-select-spinner .spinner-small{width:20px;height:20px;border:2px solid #F2F4F7;border-top-color:#136ab6;border-radius:50%;animation:spin .6s linear infinite}.app-select-load-more{padding:8px 14px}.app-select-load-more .app-select-load-more-btn{width:100%;padding:8px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:6px;color:#344054;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0;font-weight:500;font-style:normal;cursor:pointer;transition:all .15s ease}.app-select-load-more .app-select-load-more-btn:hover{background:#f9fafb;border-color:#667085}@keyframes spin{to{transform:rotate(360deg)}}.app-select-dropdown ::ng-deep zen-groups .zen-groups-inline{display:flex;flex-direction:column;max-height:310px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree{flex:1;overflow-y:auto;padding:4px 0}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar{width:6px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-track{background:transparent}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox{padding:10px 14px;font-weight:400;font-size:14px;line-height:20px;color:#344054}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox:hover{background:#f9fafb}.app-select-dropdown ::ng-deep zen-groups .select-all{border-bottom:none;margin-bottom:0;font-weight:500}.app-select-dropdown ::ng-deep zen-groups .tree-item[style*=padding-left]{padding-right:14px}.app-select-dropdown ::ng-deep zen-groups .tree-item-badge{background:#f1f7fe;color:#105494}.app-select-dropdown ::ng-deep zen-groups .checkbox-component .app-checkbox-label{font-weight:400;color:#344054}.app-select-dropdown ::ng-deep zen-groups .zen-groups-no-results{padding:32px 24px;text-align:center;color:#667085}@media(max-width:640px){.app-select-dropdown{position:fixed;inset:auto 0 0;max-height:70vh;border-radius:16px 16px 0 0}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZenduCheckboxComponent, selector: "zen-checkbox", inputs: ["checked", "label", "labelColor", "disabled", "disableValueChange", "indeterminate", "imageUrl", "size", "supportingText"], outputs: ["checkedChange"] }, { kind: "component", type: ZenduGroupsComponent, selector: "zen-groups", inputs: ["dataSource", "filteredDataSource", "hideSelectAll", "isSelectedAll", "inline", "width", "placeholder", "hideSearch", "idProp", "displayProp"], outputs: ["isSelectedAllChange", "checkedChange"] }, { kind: "component", type: ZenduIconComponent, selector: "zen-icon", inputs: ["src", "name", "size", "color", "theme", "customColor"] }, { kind: "component", type: ZenduSpinner, selector: "zen-spinner", inputs: ["size"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
4010
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ZenduSelectComponent, isStandalone: false, selector: "zen-select", inputs: { selectModel: "selectModel", options: "options", label: "label", supportingText: "supportingText", hintText: "hintText", placeholder: "placeholder", leadingType: "leadingType", leadingIcon: "leadingIcon", leadingAvatar: "leadingAvatar", leadingDotColor: "leadingDotColor", displayProp: "displayProp", idProp: "idProp", hasSearch: "hasSearch", isMultiselect: "isMultiselect", multiselect: "multiselect", hideSelectAll: "hideSelectAll", hideTreeSearch: "hideTreeSearch", required: "required", disabled: "disabled", error: "error", errorMessage: "errorMessage", destructive: "destructive", size: "size", returnOption: "returnOption", isTruncate: "isTruncate", enableAddNewOption: "enableAddNewOption", showDefaultAddOption: "showDefaultAddOption", newOptionText: "newOptionText", enableRemoveOption: "enableRemoveOption", removeOptionText: "removeOptionText", isLazyLoading: "isLazyLoading", lazyLoader: "lazyLoader", preferredOpenDirection: "preferredOpenDirection" }, outputs: { selectModelChange: "selectModelChange", addNewOption: "addNewOption", removeOption: "removeOption", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "optionTemplate", first: true, predicate: ZenduSelectOptionDirective, descendants: true }, { propertyName: "valueTemplate", first: true, predicate: ZenduSelectValueDirective, descendants: true }, { propertyName: "buttonTemplate", first: true, predicate: ZenduSelectButtonDirective, descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div [class]=\"getStateClasses()\">\n <!-- Label -->\n @if (label) {\n <label class=\"app-select-label text text-sm text-weight-medium\"\n [ngClass]=\"{'required': required, 'disabled': disabled, 'destructive': destructive}\">\n {{ label | translate }}\n @if (required) {\n <span class=\"required-indicator\">*</span>\n }\n </label>\n }\n\n <!-- Select Input -->\n <div class=\"app-select-wrapper\">\n <!-- Custom Trigger Template (overrides built-in trigger) -->\n @if (buttonTemplate) {\n <div\n class=\"app-select-custom-trigger\"\n (click)=\"toggleDropdown()\">\n <ng-template [ngTemplateOutlet]=\"buttonTemplate.template\"\n [ngTemplateOutletContext]=\"{ isOpen: isOpen, selected: getSelectedOption(), display: selectedDisplay, disabled: disabled }\">\n </ng-template>\n </div>\n }\n\n <!-- Built-in Trigger (when no custom button template provided) -->\n @if (!buttonTemplate) {\n @switch (leadingType) {\n <!-- Default Select (no leading element) -->\n @case ('default') {\n <ng-container *ngTemplateOutlet=\"defaultSelectTemplate\"></ng-container>\n }\n <!-- Icon Leading Select -->\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconSelectTemplate\"></ng-container>\n }\n <!-- Avatar Leading Select -->\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarSelectTemplate\"></ng-container>\n }\n <!-- Dot Leading Select -->\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotSelectTemplate\"></ng-container>\n }\n <!-- Search Input Select -->\n @case ('search') {\n <ng-container *ngTemplateOutlet=\"searchInputTemplate\"></ng-container>\n }\n }\n }\n\n <!-- Dropdown Menu -->\n @if (isOpen) {\n <div class=\"app-select-dropdown\"\n [ngClass]=\"getDropdownDirectionClass()\"\n >\n <!-- Tree Mode: embed zen-groups inline -->\n @if (isTreeMode && isMultiselect) {\n <zen-groups [inline]=\"true\"\n [dataSource]=\"$any(options)\"\n [filteredDataSource]=\"treeFilteredDataSource\"\n [hideSelectAll]=\"hideSelectAll\"\n [hideSearch]=\"hideTreeSearch\"\n [idProp]=\"idProp\"\n [displayProp]=\"displayProp\"\n [(isSelectedAll)]=\"isSelectedAll\"\n (isSelectedAllChange)=\"onTreeSelectAllChange($event)\"\n (checkedChange)=\"onTreeCheckedChange($event)\">\n </zen-groups>\n } @else {\n <!-- Search Box for hasSearch (not for search type as it has inline search) -->\n @if (leadingType !== 'search' && hasSearch && !disabled) {\n <div class=\"app-select-search\">\n <zen-icon [name]=\"'search'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n <input type=\"text\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"onSearchChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n placeholder=\"Search\"\n class=\"app-select-search-input\">\n @if (searchText) {\n <zen-icon\n class=\"app-select-search-clear\"\n [name]=\"'x'\"\n [customColor]=\"'#667085'\"\n (click)=\"clearSearch(); $event.stopPropagation()\">\n </zen-icon>\n }\n </div>\n }\n <!-- Options List -->\n <div class=\"app-select-options\" (scroll)=\"onOptionsScroll($event)\">\n <!-- Select All Option for Multiselect -->\n @if (isMultiselect && !hideSelectAll && !isLazyLoading && filteredOptions.length > 0) {\n <button\n class=\"app-select-option select-all\"\n (click)=\"toggleSelectAll()\">\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isAllSelected()\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n <span class=\"app-select-option-text\">\n Select All\n </span>\n </button>\n }\n <!-- Add New Option -->\n @if (enableAddNewOption && (showDefaultAddOption || searchText)) {\n <button\n class=\"app-select-option add-new-option\"\n (click)=\"handleAddNewOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'plus'\" [customColor]=\"'#136AB6'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ (newOptionText || 'Add New Option') + (searchText ? ': \"' + searchText + '\"' : '') }}\n </span>\n </button>\n }\n <!-- Remove Option -->\n @if (enableRemoveOption) {\n <button\n class=\"app-select-option remove-option\"\n (click)=\"handleRemoveOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'user-x'\" [customColor]=\"'#344054'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ removeOptionText || 'Remove' }}\n </span>\n </button>\n }\n @if (filteredOptions.length === 0 && !enableAddNewOption && !isLoadingNow) {\n <div class=\"app-select-no-options\">\n No matching options found\n </div>\n }\n @for (option of filteredOptions; track option) {\n <button\n class=\"app-select-option\"\n [class.selected]=\"isSelected(option)\"\n (click)=\"selectOption(option)\">\n <!-- Checkbox for Multiselect -->\n @if (isMultiselect) {\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isSelected(option)\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n }\n <!-- Option Leading Element -->\n @if (leadingType !== 'default') {\n <div class=\"app-select-option-leading\">\n @switch (leadingType) {\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: option }\"></ng-container>\n }\n }\n </div>\n }\n <!-- Option Text -->\n <div class=\"app-select-option-text-wrapper\">\n <!-- Use custom template if provided -->\n @if (!isMultiselect && optionTemplate) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-template>\n } @else {\n <span class=\"app-select-option-text\" [class.app-select-option-truncate]=\"isTruncate\">\n {{ getName(option) | translate }}\n </span>\n @if (option.secondaryText) {\n <span class=\"app-select-option-secondary\">\n {{ option.secondaryText }}\n </span>\n }\n }\n </div>\n <!-- Check Icon for Single Select -->\n @if (!isMultiselect && isSelected(option)) {\n <zen-icon\n class=\"app-select-option-check\"\n [name]=\"'check'\"\n [customColor]=\"'#136AB6'\">\n </zen-icon>\n }\n </button>\n }\n <!-- Lazy loading spinner -->\n @if (isLazyLoading && isLoadingNow) {\n <div class=\"app-select-loading\">\n <zen-spinner size=\"small\"></zen-spinner>\n </div>\n }\n </div>\n }\n <!-- Flat List Mode (default) -->\n </div>\n }\n </div>\n\n <!-- Hint text / Error message -->\n @if ((destructive && errorMessage) || hintText) {\n <div\n class=\"app-select-hint text text-sm text-weight-regular\"\n [ngClass]=\"{'destructive': destructive}\">\n @if (destructive) {\n <i class=\"material-icons-outlined hint-icon\">error_outline</i>\n }\n <span>{{ ((destructive && errorMessage) ? errorMessage : hintText) | translate }}</span>\n </div>\n }\n</div>\n\n<!-- ============================================= -->\n<!-- MAIN SELECT INPUT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Default Select Template (No Leading Element) -->\n<ng-template #defaultSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Icon Select Template -->\n<ng-template #iconSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: getSelectedOption(), icon: leadingIcon }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Avatar Select Template -->\n<ng-template #avatarSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: getSelectedOption(), avatar: leadingAvatar }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Dot Select Template -->\n<ng-template #dotSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: getSelectedOption(), color: leadingDotColor }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Search Input Template -->\n<ng-template #searchInputTemplate>\n <div class=\"app-select-input app-select-search-input\"\n [class.focused]=\"isOpen || searchFocused\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <!-- Search Icon -->\n <zen-icon [name]=\"'search'\"\n [customColor]=\"disabled ? '#9CA3AF' : '#667085'\">\n </zen-icon>\n\n <!-- Search Input Field -->\n <input type=\"text\"\n class=\"app-select-search-field\"\n [(ngModel)]=\"searchInputValue\"\n (ngModelChange)=\"onSearchInputChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur($event)\"\n [placeholder]=\"selectedDisplay || placeholder\"\n [disabled]=\"disabled\">\n </div>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- SHARED COMPONENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Select Value Display -->\n<ng-template #selectValueDisplay>\n <div class=\"app-select-value-wrapper\">\n @if (valueTemplate && !isModelEmpty()) {\n <ng-template [ngTemplateOutlet]=\"valueTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: getSelectedOption(), display: selectedDisplay }\">\n </ng-template>\n } @else {\n <span class=\"app-select-value\" [class.placeholder]=\"isModelEmpty()\">\n {{ selectedDisplay || placeholder | translate }}\n </span>\n @if (getSelectedSecondaryText() && !isModelEmpty()) {\n <span class=\"app-select-secondary\">\n {{ getSelectedSecondaryText() }}\n </span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Dropdown Arrow -->\n<ng-template #dropdownArrow>\n <zen-icon class=\"app-select-arrow\"\n [class.rotated]=\"isOpen\"\n [name]=\"'chevron-down'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- LEADING ELEMENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Icon Leading Element (with smart resolution) -->\n<ng-template #iconLeadingElement let-option=\"option\" let-icon=\"icon\">\n @if (icon || option?.icon || option?.iconName) {\n @if (getIconPath(option, icon); as iconPath) {\n <!-- If icon contains / or . treat as SVG path -->\n @if ((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.')))) {\n <!-- Use img tag for Excel to preserve colors -->\n @if (iconPath.includes('excel')) {\n <img\n [src]=\"iconPath\"\n alt=\"\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Use zen-icon with src for other SVG files -->\n @if (!iconPath.includes('excel')) {\n <zen-icon\n [src]=\"iconPath\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n <!-- Otherwise treat as Material icon name or special cases -->\n @if (!((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.'))))) {\n <!-- Special case for Excel icon - use img to preserve colors -->\n @if ((icon === 'excel') || (option?.icon === 'excel') || (option?.iconName === 'excel')) {\n <img\n src=\"assets/ng-zenduit/icons/excel.svg\"\n alt=\"Excel\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Material icon names -->\n @if ((icon !== 'excel') && (option?.icon !== 'excel') && (option?.iconName !== 'excel')) {\n <zen-icon\n [name]=\"icon || option?.icon || option?.iconName\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n }\n }\n</ng-template>\n\n<!-- Avatar Leading Element -->\n<ng-template #avatarLeadingElement let-option=\"option\" let-avatar=\"avatar\">\n @if (avatar || option?.avatar) {\n <div class=\"app-select-avatar\" >\n <img [src]=\"avatar || option?.avatar\" alt=\"\">\n </div>\n }\n</ng-template>\n\n<!-- Dot Leading Element -->\n<ng-template #dotLeadingElement let-option=\"option\" let-color=\"color\">\n <div class=\"app-select-dot\"\n [style.background-color]=\"color || option?.dotColor || '#10B981'\">\n </div>\n</ng-template>", styles: [".text{margin:0;padding:0;color:#101828}.text-display-2xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:72px;line-height:90px;letter-spacing:-.02em}.text-display-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:60px;line-height:72px;letter-spacing:-.02em}.text-display-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:48px;line-height:60px;letter-spacing:-.02em}.text-display-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:36px;line-height:44px;letter-spacing:-.02em}.text-display-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:30px;line-height:38px;letter-spacing:0}.text-display-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:24px;line-height:32px;letter-spacing:0}.text-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:20px;line-height:30px;letter-spacing:0}.text-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:18px;line-height:28px;letter-spacing:0}.text-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0}.text-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.text-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0}.text-weight-regular{font-weight:400;font-style:normal}.text-weight-medium{font-weight:500;font-style:normal}.text-weight-semibold{font-weight:600;font-style:normal}.text-weight-bold{font-weight:700;font-style:normal}@media(max-width:768px){.text-display-2xl{font-size:48px;line-height:56px}.text-display-xl{font-size:40px;line-height:48px}.text-display-lg{font-size:32px;line-height:40px}}.app-select-container{width:100%;position:relative}.app-select-label{display:flex;align-items:center;gap:4px;margin-bottom:6px;color:#344054}.app-select-label .required-indicator{color:#f04438}.app-select-label.disabled{color:#d0d5dd}.app-select-wrapper{position:relative;width:100%}.app-select-custom-trigger{display:inline-flex;cursor:pointer;-webkit-user-select:none;user-select:none}.app-select-input{width:100%;min-height:44px;padding:10px 14px;box-sizing:border-box;display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;color:#101828;text-align:left;cursor:pointer;transition:all .2s ease}.app-select-input.app-select-search-input{cursor:text}.app-select-input.app-select-search-input .app-select-search-field{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;background:transparent;color:#101828;min-width:0}.app-select-input.app-select-search-input .app-select-search-field::placeholder{color:#667085}.app-select-input.app-select-search-input .app-select-search-field:disabled{cursor:not-allowed;color:#667085}.app-select-input:hover:not(:disabled){border-color:#98a2b3}.app-select-input.focused,.app-select-input:focus{outline:none;border-color:#88c1f1;box-shadow:0 1px 2px #1018280d,0 0 0 4px #e3eefb}.app-select-input:disabled{background:#f9fafb;border-color:#d0d5dd;cursor:not-allowed;opacity:.6}.app-select-container.error .app-select-input:focus{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-leading,.app-select-option-leading{display:flex;align-items:center;flex-shrink:0}.app-select-avatar,.app-select-option-avatar{width:24px;height:24px;border-radius:50%;overflow:hidden;flex-shrink:0}.app-select-avatar img,.app-select-option-avatar img{width:100%;height:100%;object-fit:cover}.app-select-avatar .avatar-placeholder,.app-select-option-avatar .avatar-placeholder{width:100%;height:100%;background:#f2f4f7;color:#667085;display:flex;align-items:center;justify-content:center;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0;font-weight:600;font-style:normal}.app-select-dot,.app-select-option-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.app-select-value-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-value-wrapper .app-select-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085}.app-select-value{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-value.placeholder{color:#667085}.app-select-secondary,.app-select-option-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085;white-space:nowrap;flex-shrink:0}.app-select-arrow{margin-left:auto;flex-shrink:0;transition:transform .2s ease}.app-select-arrow.rotated{transform:rotate(180deg)}.app-select-dropdown{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:1000;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 4px 6px -2px #10182808,0 12px 16px -4px #10182814;overflow:hidden;max-height:320px;display:flex;flex-direction:column}.app-select-dropdown.dropdown-up{top:auto;bottom:calc(100% + 4px)}.app-select-dropdown.dropdown-down,.app-select-dropdown.dropdown-auto{top:calc(100% + 4px);bottom:auto}.app-select-search{padding:12px;border-bottom:1px solid #EAECF0;display:flex;align-items:center;gap:8px}.app-select-search .app-select-search-input{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;color:#101828}.app-select-search .app-select-search-input::placeholder{color:#667085}.app-select-search .app-select-search-clear{cursor:pointer}.app-select-loading{display:flex;justify-content:center;align-items:center;padding:8px 0}.app-select-options{flex:1;overflow-y:auto;padding:4px 0}.app-select-options::-webkit-scrollbar{width:6px}.app-select-options::-webkit-scrollbar-track{background:transparent}.app-select-options::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-no-options{padding:32px 24px;text-align:center;color:#667085;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.app-select-option{width:100%;padding:10px 14px;display:flex;align-items:center;gap:8px;background:transparent;border:none;text-align:left;cursor:pointer;transition:background .15s ease}.app-select-option:hover,.app-select-option.selected{background:#f9fafb}.app-select-option-text-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-option-text{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#344054;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-option-text.app-select-option-truncate{max-width:200px}.app-select-option-check{margin-left:auto;flex-shrink:0}.app-select-checkbox{display:flex;align-items:center;flex-shrink:0;margin-right:8px}.app-select-checkbox .checkbox-wrapper{margin-bottom:0}.app-select-checkbox .checkbox-content{display:none}.app-select-checkbox .checkbox-input{margin-right:0}.app-select-supporting{margin-top:6px;color:#667085}.app-select-supporting .error-text{color:#f04438}.app-select-container.size-sm .app-select-input{min-height:36px;padding:8px 12px}.app-select-container.error .app-select-input{border-color:#fda29b}.app-select-container.error .app-select-supporting{color:#f04438}.app-select-container.destructive .app-select-input{border-color:#fda29b}.app-select-container.destructive .app-select-input:focus,.app-select-container.destructive .app-select-input.focused{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-container.disabled .app-select-label,.app-select-container.disabled .app-select-value,.app-select-container.disabled .app-select-arrow,.app-select-container.disabled .app-select-leading zen-icon,.app-select-container.disabled .app-select-search-input zen-icon,.app-select-container.disabled .app-select-secondary,.app-select-container.disabled .app-select-search-field{opacity:.6}.app-select-container.disabled .app-select-input,.app-select-container.disabled .app-select-search-input{background:#f9fafb;cursor:not-allowed}.app-select-hint{display:flex;align-items:center;gap:4px;margin-top:6px;color:#667085}.app-select-hint .hint-icon{font-size:16px;color:#f04438}.app-select-hint.destructive{color:#f04438}.app-select-option.select-all{border-bottom:1px solid #F2F4F7;margin-bottom:4px;padding-bottom:14px}.app-select-option.add-new-option{color:#136ab6;font-weight:500}.app-select-option.add-new-option:hover{background:#eff8ff}.app-select-option.remove-option{background:#f9fafb;color:#344054}.app-select-option.remove-option .app-select-option-text{color:#344054}.app-select-spinner{display:flex;justify-content:center;padding:16px}.app-select-spinner .spinner-small{width:20px;height:20px;border:2px solid #F2F4F7;border-top-color:#136ab6;border-radius:50%;animation:spin .6s linear infinite}.app-select-load-more{padding:8px 14px}.app-select-load-more .app-select-load-more-btn{width:100%;padding:8px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:6px;color:#344054;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0;font-weight:500;font-style:normal;cursor:pointer;transition:all .15s ease}.app-select-load-more .app-select-load-more-btn:hover{background:#f9fafb;border-color:#667085}@keyframes spin{to{transform:rotate(360deg)}}.app-select-dropdown ::ng-deep zen-groups .zen-groups-inline{display:flex;flex-direction:column;max-height:310px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree{flex:1;overflow-y:auto;padding:4px 0}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar{width:6px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-track{background:transparent}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox{padding:10px 14px;font-weight:400;font-size:14px;line-height:20px;color:#344054}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox:hover{background:#f9fafb}.app-select-dropdown ::ng-deep zen-groups .select-all{border-bottom:none;margin-bottom:0;font-weight:500}.app-select-dropdown ::ng-deep zen-groups .tree-item[style*=padding-left]{padding-right:14px}.app-select-dropdown ::ng-deep zen-groups .tree-item-badge{background:#f1f7fe;color:#105494}.app-select-dropdown ::ng-deep zen-groups .checkbox-component .app-checkbox-label{font-weight:400;color:#344054}.app-select-dropdown ::ng-deep zen-groups .zen-groups-no-results{padding:32px 24px;text-align:center;color:#667085}@media(max-width:640px){.app-select-dropdown{position:fixed;inset:auto 0 0;max-height:70vh;border-radius:16px 16px 0 0}}\n"], dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i2$1.DefaultValueAccessor, selector: "input:not([type=checkbox]):not([ngNoCva])[formControlName],textarea:not([ngNoCva])[formControlName],input:not([type=checkbox]):not([ngNoCva])[formControl],textarea:not([ngNoCva])[formControl],input:not([type=checkbox]):not([ngNoCva])[ngModel],textarea:not([ngNoCva])[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2$1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2$1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "component", type: ZenduCheckboxComponent, selector: "zen-checkbox", inputs: ["checked", "label", "labelColor", "disabled", "disableValueChange", "indeterminate", "imageUrl", "size", "supportingText"], outputs: ["checkedChange"] }, { kind: "component", type: ZenduGroupsComponent, selector: "zen-groups", inputs: ["dataSource", "filteredDataSource", "hideSelectAll", "isSelectedAll", "inline", "width", "placeholder", "hideSearch", "idProp", "displayProp"], outputs: ["isSelectedAllChange", "checkedChange"] }, { kind: "component", type: ZenduIconComponent, selector: "zen-icon", inputs: ["src", "name", "size", "color", "theme", "customColor"] }, { kind: "component", type: ZenduSpinner, selector: "zen-spinner", inputs: ["size"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
4011
4011
  }
4012
4012
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ZenduSelectComponent, decorators: [{
4013
4013
  type: Component,
4014
- args: [{ selector: 'zen-select', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div [class]=\"getStateClasses()\">\n <!-- Label -->\n @if (label) {\n <label class=\"app-select-label text text-sm text-weight-medium\"\n [ngClass]=\"{'required': required, 'disabled': disabled, 'destructive': destructive}\">\n {{ label | translate }}\n @if (required) {\n <span class=\"required-indicator\">*</span>\n }\n </label>\n }\n\n <!-- Select Input -->\n <div class=\"app-select-wrapper\">\n <!-- Custom Trigger Template (overrides built-in trigger) -->\n @if (buttonTemplate) {\n <div\n class=\"app-select-custom-trigger\"\n (click)=\"toggleDropdown()\">\n <ng-template [ngTemplateOutlet]=\"buttonTemplate.template\"\n [ngTemplateOutletContext]=\"{ isOpen: isOpen, selected: getSelectedOption(), display: selectedDisplay, disabled: disabled }\">\n </ng-template>\n </div>\n }\n\n <!-- Built-in Trigger (when no custom button template provided) -->\n @if (!buttonTemplate) {\n @switch (leadingType) {\n <!-- Default Select (no leading element) -->\n @case ('default') {\n <ng-container *ngTemplateOutlet=\"defaultSelectTemplate\"></ng-container>\n }\n <!-- Icon Leading Select -->\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconSelectTemplate\"></ng-container>\n }\n <!-- Avatar Leading Select -->\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarSelectTemplate\"></ng-container>\n }\n <!-- Dot Leading Select -->\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotSelectTemplate\"></ng-container>\n }\n <!-- Search Input Select -->\n @case ('search') {\n <ng-container *ngTemplateOutlet=\"searchInputTemplate\"></ng-container>\n }\n }\n }\n\n <!-- Dropdown Menu -->\n @if (isOpen) {\n <div class=\"app-select-dropdown\"\n [ngClass]=\"getDropdownDirectionClass()\"\n >\n <!-- Tree Mode: embed zen-groups inline -->\n @if (isTreeMode && isMultiselect) {\n <zen-groups [inline]=\"true\"\n [dataSource]=\"$any(options)\"\n [filteredDataSource]=\"treeFilteredDataSource\"\n [hideSelectAll]=\"hideSelectAll\"\n [hideSearch]=\"hideTreeSearch\"\n [idProp]=\"idProp\"\n [displayProp]=\"displayProp\"\n [(isSelectedAll)]=\"isSelectedAll\"\n (isSelectedAllChange)=\"onTreeSelectAllChange($event)\"\n (checkedChange)=\"onTreeCheckedChange($event)\">\n </zen-groups>\n } @else {\n <!-- Search Box for hasSearch (not for search type as it has inline search) -->\n @if (leadingType !== 'search' && hasSearch && !disabled) {\n <div class=\"app-select-search\">\n <zen-icon [name]=\"'search'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n <input type=\"text\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"onSearchChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n placeholder=\"Search\"\n class=\"app-select-search-input\">\n @if (searchText) {\n <zen-icon\n class=\"app-select-search-clear\"\n [name]=\"'x'\"\n [customColor]=\"'#667085'\"\n (click)=\"clearSearch(); $event.stopPropagation()\">\n </zen-icon>\n }\n </div>\n }\n <!-- Options List -->\n <div class=\"app-select-options\" (scroll)=\"onOptionsScroll($event)\">\n <!-- Select All Option for Multiselect -->\n @if (isMultiselect && !hideSelectAll && !isLazyLoading && filteredOptions.length > 0) {\n <button\n class=\"app-select-option select-all\"\n (click)=\"toggleSelectAll()\">\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isAllSelected()\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n <span class=\"app-select-option-text\">\n Select All\n </span>\n </button>\n }\n <!-- Add New Option -->\n @if (enableAddNewOption && (showDefaultAddOption || searchText)) {\n <button\n class=\"app-select-option add-new-option\"\n (click)=\"handleAddNewOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'plus'\" [customColor]=\"'#136AB6'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ (newOptionText || 'Add New Option') + (searchText ? ': \"' + searchText + '\"' : '') }}\n </span>\n </button>\n }\n <!-- Remove Option -->\n @if (enableRemoveOption) {\n <button\n class=\"app-select-option remove-option\"\n (click)=\"handleRemoveOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'user-x'\" [customColor]=\"'#344054'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ removeOptionText || 'Remove' }}\n </span>\n </button>\n }\n @if (filteredOptions.length === 0 && !enableAddNewOption && !isLoadingNow) {\n <div class=\"app-select-no-options\">\n No matching options found\n </div>\n }\n @for (option of filteredOptions; track option) {\n <button\n class=\"app-select-option\"\n [class.selected]=\"isSelected(option)\"\n (click)=\"selectOption(option)\">\n <!-- Checkbox for Multiselect -->\n @if (isMultiselect) {\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isSelected(option)\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n }\n <!-- Option Leading Element -->\n @if (leadingType !== 'default') {\n <div class=\"app-select-option-leading\">\n @switch (leadingType) {\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: option }\"></ng-container>\n }\n }\n </div>\n }\n <!-- Option Text -->\n <div class=\"app-select-option-text-wrapper\">\n <!-- Use custom template if provided -->\n @if (!isMultiselect && optionTemplate) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-template>\n } @else {\n <span class=\"app-select-option-text\" [class.app-select-option-truncate]=\"isTruncate\">\n {{ getName(option) | translate }}\n </span>\n @if (option.secondaryText) {\n <span class=\"app-select-option-secondary\">\n {{ option.secondaryText }}\n </span>\n }\n }\n </div>\n <!-- Check Icon for Single Select -->\n @if (!isMultiselect && isSelected(option)) {\n <zen-icon\n class=\"app-select-option-check\"\n [name]=\"'check'\"\n [customColor]=\"'#136AB6'\">\n </zen-icon>\n }\n </button>\n }\n <!-- Lazy loading spinner -->\n @if (isLazyLoading && isLoadingNow) {\n <div class=\"app-select-loading\">\n <zen-spinner size=\"small\"></zen-spinner>\n </div>\n }\n </div>\n }\n <!-- Flat List Mode (default) -->\n </div>\n }\n </div>\n\n <!-- Hint text / Error message -->\n @if ((destructive && errorMessage) || hintText) {\n <div\n class=\"app-select-hint text text-sm text-weight-regular\"\n [ngClass]=\"{'destructive': destructive}\">\n @if (destructive) {\n <i class=\"material-icons-outlined hint-icon\">error_outline</i>\n }\n <span>{{ ((destructive && errorMessage) ? errorMessage : hintText) | translate }}</span>\n </div>\n }\n</div>\n\n<!-- ============================================= -->\n<!-- MAIN SELECT INPUT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Default Select Template (No Leading Element) -->\n<ng-template #defaultSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Icon Select Template -->\n<ng-template #iconSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: getSelectedOption(), icon: leadingIcon }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Avatar Select Template -->\n<ng-template #avatarSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: getSelectedOption(), avatar: leadingAvatar }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Dot Select Template -->\n<ng-template #dotSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: getSelectedOption(), color: leadingDotColor }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Search Input Template -->\n<ng-template #searchInputTemplate>\n <div class=\"app-select-input app-select-search-input\"\n [class.focused]=\"isOpen || searchFocused\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <!-- Search Icon -->\n <zen-icon [name]=\"'search'\"\n [customColor]=\"disabled ? '#9CA3AF' : '#667085'\">\n </zen-icon>\n\n <!-- Search Input Field -->\n <input type=\"text\"\n class=\"app-select-search-field\"\n [(ngModel)]=\"searchInputValue\"\n (ngModelChange)=\"onSearchInputChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur($event)\"\n [placeholder]=\"selectedDisplay || placeholder\"\n [disabled]=\"disabled\">\n </div>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- SHARED COMPONENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Select Value Display -->\n<ng-template #selectValueDisplay>\n <div class=\"app-select-value-wrapper\">\n @if (valueTemplate && !isModelEmpty()) {\n <ng-template [ngTemplateOutlet]=\"valueTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: getSelectedOption(), display: selectedDisplay }\">\n </ng-template>\n } @else {\n <span class=\"app-select-value\" [class.placeholder]=\"isModelEmpty()\">\n {{ selectedDisplay || placeholder | translate }}\n </span>\n @if (getSelectedSecondaryText() && !isModelEmpty()) {\n <span class=\"app-select-secondary\">\n {{ getSelectedSecondaryText() }}\n </span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Dropdown Arrow -->\n<ng-template #dropdownArrow>\n <zen-icon class=\"app-select-arrow\"\n [class.rotated]=\"isOpen\"\n [name]=\"'chevron-down'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- LEADING ELEMENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Icon Leading Element (with smart resolution) -->\n<ng-template #iconLeadingElement let-option=\"option\" let-icon=\"icon\">\n @if (icon || option?.icon || option?.iconName) {\n @if (getIconPath(option, icon); as iconPath) {\n <!-- If icon contains / or . treat as SVG path -->\n @if ((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.')))) {\n <!-- Use img tag for Excel to preserve colors -->\n @if (iconPath.includes('excel')) {\n <img\n [src]=\"iconPath\"\n alt=\"\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Use zen-icon with src for other SVG files -->\n @if (!iconPath.includes('excel')) {\n <zen-icon\n [src]=\"iconPath\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n <!-- Otherwise treat as Material icon name or special cases -->\n @if (!((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.'))))) {\n <!-- Special case for Excel icon - use img to preserve colors -->\n @if ((icon === 'excel') || (option?.icon === 'excel') || (option?.iconName === 'excel')) {\n <img\n src=\"assets/ng-zenduit/icons/excel.svg\"\n alt=\"Excel\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Material icon names -->\n @if ((icon !== 'excel') && (option?.icon !== 'excel') && (option?.iconName !== 'excel')) {\n <zen-icon\n [name]=\"icon || option?.icon || option?.iconName\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n }\n }\n</ng-template>\n\n<!-- Avatar Leading Element -->\n<ng-template #avatarLeadingElement let-option=\"option\" let-avatar=\"avatar\">\n @if (avatar || option?.avatar) {\n <div class=\"app-select-avatar\" >\n <img [src]=\"avatar || option?.avatar\" alt=\"\">\n </div>\n }\n</ng-template>\n\n<!-- Dot Leading Element -->\n<ng-template #dotLeadingElement let-option=\"option\" let-color=\"color\">\n <div class=\"app-select-dot\"\n [style.background-color]=\"color || option?.dotColor || '#10B981'\">\n </div>\n</ng-template>", styles: [".text{margin:0;padding:0;color:#101828}.text-display-2xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:72px;line-height:90px;letter-spacing:-.02em}.text-display-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:60px;line-height:72px;letter-spacing:-.02em}.text-display-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:48px;line-height:60px;letter-spacing:-.02em}.text-display-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:36px;line-height:44px;letter-spacing:-.02em}.text-display-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:30px;line-height:38px;letter-spacing:0}.text-display-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:24px;line-height:32px;letter-spacing:0}.text-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:20px;line-height:30px;letter-spacing:0}.text-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:18px;line-height:28px;letter-spacing:0}.text-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0}.text-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.text-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0}.text-weight-regular{font-weight:400;font-style:normal}.text-weight-medium{font-weight:500;font-style:normal}.text-weight-semibold{font-weight:600;font-style:normal}.text-weight-bold{font-weight:700;font-style:normal}@media(max-width:768px){.text-display-2xl{font-size:48px;line-height:56px}.text-display-xl{font-size:40px;line-height:48px}.text-display-lg{font-size:32px;line-height:40px}}.app-select-container{width:100%;position:relative}.app-select-label{display:flex;align-items:center;gap:4px;margin-bottom:6px;color:#344054}.app-select-label .required-indicator{color:#f04438}.app-select-label.disabled{color:#d0d5dd}.app-select-wrapper{position:relative;width:100%}.app-select-custom-trigger{display:inline-flex;cursor:pointer;-webkit-user-select:none;user-select:none}.app-select-input{width:100%;min-height:44px;padding:10px 14px;box-sizing:border-box;display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;color:#101828;text-align:left;cursor:pointer;transition:all .2s ease}.app-select-input.app-select-search-input{cursor:text}.app-select-input.app-select-search-input .app-select-search-field{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;background:transparent;color:#101828;min-width:0}.app-select-input.app-select-search-input .app-select-search-field::placeholder{color:#667085}.app-select-input.app-select-search-input .app-select-search-field:disabled{cursor:not-allowed;color:#667085}.app-select-input:hover:not(:disabled){border-color:#d0d5dd}.app-select-input.focused,.app-select-input:focus{outline:none;border-color:#88c1f1;box-shadow:0 1px 2px #1018280d,0 0 0 4px #e3eefb}.app-select-input:disabled{background:#f9fafb;border-color:#d0d5dd;cursor:not-allowed;opacity:.6}.app-select-container.error .app-select-input:focus{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-leading,.app-select-option-leading{display:flex;align-items:center;flex-shrink:0}.app-select-avatar,.app-select-option-avatar{width:24px;height:24px;border-radius:50%;overflow:hidden;flex-shrink:0}.app-select-avatar img,.app-select-option-avatar img{width:100%;height:100%;object-fit:cover}.app-select-avatar .avatar-placeholder,.app-select-option-avatar .avatar-placeholder{width:100%;height:100%;background:#f2f4f7;color:#667085;display:flex;align-items:center;justify-content:center;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0;font-weight:600;font-style:normal}.app-select-dot,.app-select-option-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.app-select-value-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-value-wrapper .app-select-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085}.app-select-value{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-value.placeholder{color:#667085}.app-select-secondary,.app-select-option-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085;white-space:nowrap;flex-shrink:0}.app-select-arrow{margin-left:auto;flex-shrink:0;transition:transform .2s ease}.app-select-arrow.rotated{transform:rotate(180deg)}.app-select-dropdown{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:1000;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 4px 6px -2px #10182808,0 12px 16px -4px #10182814;overflow:hidden;max-height:320px;display:flex;flex-direction:column}.app-select-dropdown.dropdown-up{top:auto;bottom:calc(100% + 4px)}.app-select-dropdown.dropdown-down,.app-select-dropdown.dropdown-auto{top:calc(100% + 4px);bottom:auto}.app-select-search{padding:12px;border-bottom:1px solid #EAECF0;display:flex;align-items:center;gap:8px}.app-select-search .app-select-search-input{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;color:#101828}.app-select-search .app-select-search-input::placeholder{color:#667085}.app-select-search .app-select-search-clear{cursor:pointer}.app-select-loading{display:flex;justify-content:center;align-items:center;padding:8px 0}.app-select-options{flex:1;overflow-y:auto;padding:4px 0}.app-select-options::-webkit-scrollbar{width:6px}.app-select-options::-webkit-scrollbar-track{background:transparent}.app-select-options::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-no-options{padding:32px 24px;text-align:center;color:#667085;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.app-select-option{width:100%;padding:10px 14px;display:flex;align-items:center;gap:8px;background:transparent;border:none;text-align:left;cursor:pointer;transition:background .15s ease}.app-select-option:hover,.app-select-option.selected{background:#f9fafb}.app-select-option-text-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-option-text{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#344054;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-option-text.app-select-option-truncate{max-width:200px}.app-select-option-check{margin-left:auto;flex-shrink:0}.app-select-checkbox{display:flex;align-items:center;flex-shrink:0;margin-right:8px}.app-select-checkbox .checkbox-wrapper{margin-bottom:0}.app-select-checkbox .checkbox-content{display:none}.app-select-checkbox .checkbox-input{margin-right:0}.app-select-supporting{margin-top:6px;color:#667085}.app-select-supporting .error-text{color:#f04438}.app-select-container.size-sm .app-select-input{min-height:36px;padding:8px 12px}.app-select-container.error .app-select-input{border-color:#fda29b}.app-select-container.error .app-select-supporting{color:#f04438}.app-select-container.destructive .app-select-input{border-color:#fda29b}.app-select-container.destructive .app-select-input:focus,.app-select-container.destructive .app-select-input.focused{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-container.disabled .app-select-label,.app-select-container.disabled .app-select-value,.app-select-container.disabled .app-select-arrow,.app-select-container.disabled .app-select-leading zen-icon,.app-select-container.disabled .app-select-search-input zen-icon,.app-select-container.disabled .app-select-secondary,.app-select-container.disabled .app-select-search-field{opacity:.6}.app-select-container.disabled .app-select-input,.app-select-container.disabled .app-select-search-input{background:#f9fafb;cursor:not-allowed}.app-select-hint{display:flex;align-items:center;gap:4px;margin-top:6px;color:#667085}.app-select-hint .hint-icon{font-size:16px;color:#f04438}.app-select-hint.destructive{color:#f04438}.app-select-option.select-all{border-bottom:1px solid #F2F4F7;margin-bottom:4px;padding-bottom:14px}.app-select-option.add-new-option{color:#136ab6;font-weight:500}.app-select-option.add-new-option:hover{background:#eff8ff}.app-select-option.remove-option{background:#f9fafb;color:#344054}.app-select-option.remove-option .app-select-option-text{color:#344054}.app-select-spinner{display:flex;justify-content:center;padding:16px}.app-select-spinner .spinner-small{width:20px;height:20px;border:2px solid #F2F4F7;border-top-color:#136ab6;border-radius:50%;animation:spin .6s linear infinite}.app-select-load-more{padding:8px 14px}.app-select-load-more .app-select-load-more-btn{width:100%;padding:8px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:6px;color:#344054;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0;font-weight:500;font-style:normal;cursor:pointer;transition:all .15s ease}.app-select-load-more .app-select-load-more-btn:hover{background:#f9fafb;border-color:#667085}@keyframes spin{to{transform:rotate(360deg)}}.app-select-dropdown ::ng-deep zen-groups .zen-groups-inline{display:flex;flex-direction:column;max-height:310px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree{flex:1;overflow-y:auto;padding:4px 0}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar{width:6px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-track{background:transparent}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox{padding:10px 14px;font-weight:400;font-size:14px;line-height:20px;color:#344054}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox:hover{background:#f9fafb}.app-select-dropdown ::ng-deep zen-groups .select-all{border-bottom:none;margin-bottom:0;font-weight:500}.app-select-dropdown ::ng-deep zen-groups .tree-item[style*=padding-left]{padding-right:14px}.app-select-dropdown ::ng-deep zen-groups .tree-item-badge{background:#f1f7fe;color:#105494}.app-select-dropdown ::ng-deep zen-groups .checkbox-component .app-checkbox-label{font-weight:400;color:#344054}.app-select-dropdown ::ng-deep zen-groups .zen-groups-no-results{padding:32px 24px;text-align:center;color:#667085}@media(max-width:640px){.app-select-dropdown{position:fixed;inset:auto 0 0;max-height:70vh;border-radius:16px 16px 0 0}}\n"] }]
4014
+ args: [{ selector: 'zen-select', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div [class]=\"getStateClasses()\">\n <!-- Label -->\n @if (label) {\n <label class=\"app-select-label text text-sm text-weight-medium\"\n [ngClass]=\"{'required': required, 'disabled': disabled, 'destructive': destructive}\">\n {{ label | translate }}\n @if (required) {\n <span class=\"required-indicator\">*</span>\n }\n </label>\n }\n\n <!-- Select Input -->\n <div class=\"app-select-wrapper\">\n <!-- Custom Trigger Template (overrides built-in trigger) -->\n @if (buttonTemplate) {\n <div\n class=\"app-select-custom-trigger\"\n (click)=\"toggleDropdown()\">\n <ng-template [ngTemplateOutlet]=\"buttonTemplate.template\"\n [ngTemplateOutletContext]=\"{ isOpen: isOpen, selected: getSelectedOption(), display: selectedDisplay, disabled: disabled }\">\n </ng-template>\n </div>\n }\n\n <!-- Built-in Trigger (when no custom button template provided) -->\n @if (!buttonTemplate) {\n @switch (leadingType) {\n <!-- Default Select (no leading element) -->\n @case ('default') {\n <ng-container *ngTemplateOutlet=\"defaultSelectTemplate\"></ng-container>\n }\n <!-- Icon Leading Select -->\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconSelectTemplate\"></ng-container>\n }\n <!-- Avatar Leading Select -->\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarSelectTemplate\"></ng-container>\n }\n <!-- Dot Leading Select -->\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotSelectTemplate\"></ng-container>\n }\n <!-- Search Input Select -->\n @case ('search') {\n <ng-container *ngTemplateOutlet=\"searchInputTemplate\"></ng-container>\n }\n }\n }\n\n <!-- Dropdown Menu -->\n @if (isOpen) {\n <div class=\"app-select-dropdown\"\n [ngClass]=\"getDropdownDirectionClass()\"\n >\n <!-- Tree Mode: embed zen-groups inline -->\n @if (isTreeMode && isMultiselect) {\n <zen-groups [inline]=\"true\"\n [dataSource]=\"$any(options)\"\n [filteredDataSource]=\"treeFilteredDataSource\"\n [hideSelectAll]=\"hideSelectAll\"\n [hideSearch]=\"hideTreeSearch\"\n [idProp]=\"idProp\"\n [displayProp]=\"displayProp\"\n [(isSelectedAll)]=\"isSelectedAll\"\n (isSelectedAllChange)=\"onTreeSelectAllChange($event)\"\n (checkedChange)=\"onTreeCheckedChange($event)\">\n </zen-groups>\n } @else {\n <!-- Search Box for hasSearch (not for search type as it has inline search) -->\n @if (leadingType !== 'search' && hasSearch && !disabled) {\n <div class=\"app-select-search\">\n <zen-icon [name]=\"'search'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n <input type=\"text\"\n [(ngModel)]=\"searchText\"\n (ngModelChange)=\"onSearchChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n placeholder=\"Search\"\n class=\"app-select-search-input\">\n @if (searchText) {\n <zen-icon\n class=\"app-select-search-clear\"\n [name]=\"'x'\"\n [customColor]=\"'#667085'\"\n (click)=\"clearSearch(); $event.stopPropagation()\">\n </zen-icon>\n }\n </div>\n }\n <!-- Options List -->\n <div class=\"app-select-options\" (scroll)=\"onOptionsScroll($event)\">\n <!-- Select All Option for Multiselect -->\n @if (isMultiselect && !hideSelectAll && !isLazyLoading && filteredOptions.length > 0) {\n <button\n class=\"app-select-option select-all\"\n (click)=\"toggleSelectAll()\">\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isAllSelected()\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n <span class=\"app-select-option-text\">\n Select All\n </span>\n </button>\n }\n <!-- Add New Option -->\n @if (enableAddNewOption && (showDefaultAddOption || searchText)) {\n <button\n class=\"app-select-option add-new-option\"\n (click)=\"handleAddNewOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'plus'\" [customColor]=\"'#136AB6'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ (newOptionText || 'Add New Option') + (searchText ? ': \"' + searchText + '\"' : '') }}\n </span>\n </button>\n }\n <!-- Remove Option -->\n @if (enableRemoveOption) {\n <button\n class=\"app-select-option remove-option\"\n (click)=\"handleRemoveOption(); $event.stopPropagation()\">\n <zen-icon [name]=\"'user-x'\" [customColor]=\"'#344054'\"></zen-icon>\n <span class=\"app-select-option-text\">\n {{ removeOptionText || 'Remove' }}\n </span>\n </button>\n }\n @if (filteredOptions.length === 0 && !enableAddNewOption && !isLoadingNow) {\n <div class=\"app-select-no-options\">\n No matching options found\n </div>\n }\n @for (option of filteredOptions; track option) {\n <button\n class=\"app-select-option\"\n [class.selected]=\"isSelected(option)\"\n (click)=\"selectOption(option)\">\n <!-- Checkbox for Multiselect -->\n @if (isMultiselect) {\n <zen-checkbox class=\"app-select-checkbox\"\n [checked]=\"isSelected(option)\"\n [disableValueChange]=\"true\"\n [label]=\"''\"\n size=\"sm\">\n </zen-checkbox>\n }\n <!-- Option Leading Element -->\n @if (leadingType !== 'default') {\n <div class=\"app-select-option-leading\">\n @switch (leadingType) {\n @case ('icon') {\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('avatar') {\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: option }\"></ng-container>\n }\n @case ('dot') {\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: option }\"></ng-container>\n }\n }\n </div>\n }\n <!-- Option Text -->\n <div class=\"app-select-option-text-wrapper\">\n <!-- Use custom template if provided -->\n @if (!isMultiselect && optionTemplate) {\n <ng-template [ngTemplateOutlet]=\"optionTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: option }\">\n </ng-template>\n } @else {\n <span class=\"app-select-option-text\" [class.app-select-option-truncate]=\"isTruncate\">\n {{ getName(option) | translate }}\n </span>\n @if (option.secondaryText) {\n <span class=\"app-select-option-secondary\">\n {{ option.secondaryText }}\n </span>\n }\n }\n </div>\n <!-- Check Icon for Single Select -->\n @if (!isMultiselect && isSelected(option)) {\n <zen-icon\n class=\"app-select-option-check\"\n [name]=\"'check'\"\n [customColor]=\"'#136AB6'\">\n </zen-icon>\n }\n </button>\n }\n <!-- Lazy loading spinner -->\n @if (isLazyLoading && isLoadingNow) {\n <div class=\"app-select-loading\">\n <zen-spinner size=\"small\"></zen-spinner>\n </div>\n }\n </div>\n }\n <!-- Flat List Mode (default) -->\n </div>\n }\n </div>\n\n <!-- Hint text / Error message -->\n @if ((destructive && errorMessage) || hintText) {\n <div\n class=\"app-select-hint text text-sm text-weight-regular\"\n [ngClass]=\"{'destructive': destructive}\">\n @if (destructive) {\n <i class=\"material-icons-outlined hint-icon\">error_outline</i>\n }\n <span>{{ ((destructive && errorMessage) ? errorMessage : hintText) | translate }}</span>\n </div>\n }\n</div>\n\n<!-- ============================================= -->\n<!-- MAIN SELECT INPUT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Default Select Template (No Leading Element) -->\n<ng-template #defaultSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Icon Select Template -->\n<ng-template #iconSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"iconLeadingElement; context: { option: getSelectedOption(), icon: leadingIcon }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Avatar Select Template -->\n<ng-template #avatarSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"avatarLeadingElement; context: { option: getSelectedOption(), avatar: leadingAvatar }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Dot Select Template -->\n<ng-template #dotSelectTemplate>\n <button class=\"app-select-input\"\n [disabled]=\"disabled\"\n (click)=\"toggleDropdown()\"\n [class.focused]=\"isOpen\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <div class=\"app-select-leading\">\n <ng-container *ngTemplateOutlet=\"dotLeadingElement; context: { option: getSelectedOption(), color: leadingDotColor }\"></ng-container>\n </div>\n\n <ng-container *ngTemplateOutlet=\"selectValueDisplay\"></ng-container>\n <ng-container *ngTemplateOutlet=\"dropdownArrow\"></ng-container>\n </button>\n</ng-template>\n\n<!-- Search Input Template -->\n<ng-template #searchInputTemplate>\n <div class=\"app-select-input app-select-search-input\"\n [class.focused]=\"isOpen || searchFocused\"\n [class.has-value]=\"!isModelEmpty()\">\n\n <!-- Search Icon -->\n <zen-icon [name]=\"'search'\"\n [customColor]=\"disabled ? '#9CA3AF' : '#667085'\">\n </zen-icon>\n\n <!-- Search Input Field -->\n <input type=\"text\"\n class=\"app-select-search-field\"\n [(ngModel)]=\"searchInputValue\"\n (ngModelChange)=\"onSearchInputChange()\"\n (keydown.enter)=\"onSearchEnter($event)\"\n (focus)=\"onSearchFocus()\"\n (blur)=\"onSearchBlur($event)\"\n [placeholder]=\"selectedDisplay || placeholder\"\n [disabled]=\"disabled\">\n </div>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- SHARED COMPONENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Select Value Display -->\n<ng-template #selectValueDisplay>\n <div class=\"app-select-value-wrapper\">\n @if (valueTemplate && !isModelEmpty()) {\n <ng-template [ngTemplateOutlet]=\"valueTemplate.template\"\n [ngTemplateOutletContext]=\"{ option: getSelectedOption(), display: selectedDisplay }\">\n </ng-template>\n } @else {\n <span class=\"app-select-value\" [class.placeholder]=\"isModelEmpty()\">\n {{ selectedDisplay || placeholder | translate }}\n </span>\n @if (getSelectedSecondaryText() && !isModelEmpty()) {\n <span class=\"app-select-secondary\">\n {{ getSelectedSecondaryText() }}\n </span>\n }\n }\n </div>\n</ng-template>\n\n<!-- Dropdown Arrow -->\n<ng-template #dropdownArrow>\n <zen-icon class=\"app-select-arrow\"\n [class.rotated]=\"isOpen\"\n [name]=\"'chevron-down'\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n</ng-template>\n\n<!-- ============================================= -->\n<!-- LEADING ELEMENT TEMPLATES -->\n<!-- ============================================= -->\n\n<!-- Icon Leading Element (with smart resolution) -->\n<ng-template #iconLeadingElement let-option=\"option\" let-icon=\"icon\">\n @if (icon || option?.icon || option?.iconName) {\n @if (getIconPath(option, icon); as iconPath) {\n <!-- If icon contains / or . treat as SVG path -->\n @if ((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.')))) {\n <!-- Use img tag for Excel to preserve colors -->\n @if (iconPath.includes('excel')) {\n <img\n [src]=\"iconPath\"\n alt=\"\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Use zen-icon with src for other SVG files -->\n @if (!iconPath.includes('excel')) {\n <zen-icon\n [src]=\"iconPath\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n <!-- Otherwise treat as Material icon name or special cases -->\n @if (!((icon && (icon.includes('/') || icon.includes('.'))) ||\n (option?.icon && (option.icon.includes('/') || option.icon.includes('.'))) ||\n (option?.iconName && (option.iconName.includes('/') || option.iconName.includes('.'))))) {\n <!-- Special case for Excel icon - use img to preserve colors -->\n @if ((icon === 'excel') || (option?.icon === 'excel') || (option?.iconName === 'excel')) {\n <img\n src=\"assets/ng-zenduit/icons/excel.svg\"\n alt=\"Excel\"\n style=\"width: 20px; height: 20px;\">\n }\n <!-- Material icon names -->\n @if ((icon !== 'excel') && (option?.icon !== 'excel') && (option?.iconName !== 'excel')) {\n <zen-icon\n [name]=\"icon || option?.icon || option?.iconName\"\n [customColor]=\"'#667085'\">\n </zen-icon>\n }\n }\n }\n }\n</ng-template>\n\n<!-- Avatar Leading Element -->\n<ng-template #avatarLeadingElement let-option=\"option\" let-avatar=\"avatar\">\n @if (avatar || option?.avatar) {\n <div class=\"app-select-avatar\" >\n <img [src]=\"avatar || option?.avatar\" alt=\"\">\n </div>\n }\n</ng-template>\n\n<!-- Dot Leading Element -->\n<ng-template #dotLeadingElement let-option=\"option\" let-color=\"color\">\n <div class=\"app-select-dot\"\n [style.background-color]=\"color || option?.dotColor || '#10B981'\">\n </div>\n</ng-template>", styles: [".text{margin:0;padding:0;color:#101828}.text-display-2xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:72px;line-height:90px;letter-spacing:-.02em}.text-display-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:60px;line-height:72px;letter-spacing:-.02em}.text-display-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:48px;line-height:60px;letter-spacing:-.02em}.text-display-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:36px;line-height:44px;letter-spacing:-.02em}.text-display-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:30px;line-height:38px;letter-spacing:0}.text-display-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:24px;line-height:32px;letter-spacing:0}.text-xl{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:20px;line-height:30px;letter-spacing:0}.text-lg{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:18px;line-height:28px;letter-spacing:0}.text-md{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0}.text-sm{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.text-xs{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0}.text-weight-regular{font-weight:400;font-style:normal}.text-weight-medium{font-weight:500;font-style:normal}.text-weight-semibold{font-weight:600;font-style:normal}.text-weight-bold{font-weight:700;font-style:normal}@media(max-width:768px){.text-display-2xl{font-size:48px;line-height:56px}.text-display-xl{font-size:40px;line-height:48px}.text-display-lg{font-size:32px;line-height:40px}}.app-select-container{width:100%;position:relative}.app-select-label{display:flex;align-items:center;gap:4px;margin-bottom:6px;color:#344054}.app-select-label .required-indicator{color:#f04438}.app-select-label.disabled{color:#d0d5dd}.app-select-wrapper{position:relative;width:100%}.app-select-custom-trigger{display:inline-flex;cursor:pointer;-webkit-user-select:none;user-select:none}.app-select-input{width:100%;min-height:44px;padding:10px 14px;box-sizing:border-box;display:flex;align-items:center;gap:8px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;color:#101828;text-align:left;cursor:pointer;transition:all .2s ease}.app-select-input.app-select-search-input{cursor:text}.app-select-input.app-select-search-input .app-select-search-field{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;background:transparent;color:#101828;min-width:0}.app-select-input.app-select-search-input .app-select-search-field::placeholder{color:#667085}.app-select-input.app-select-search-input .app-select-search-field:disabled{cursor:not-allowed;color:#667085}.app-select-input:hover:not(:disabled){border-color:#98a2b3}.app-select-input.focused,.app-select-input:focus{outline:none;border-color:#88c1f1;box-shadow:0 1px 2px #1018280d,0 0 0 4px #e3eefb}.app-select-input:disabled{background:#f9fafb;border-color:#d0d5dd;cursor:not-allowed;opacity:.6}.app-select-container.error .app-select-input:focus{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-leading,.app-select-option-leading{display:flex;align-items:center;flex-shrink:0}.app-select-avatar,.app-select-option-avatar{width:24px;height:24px;border-radius:50%;overflow:hidden;flex-shrink:0}.app-select-avatar img,.app-select-option-avatar img{width:100%;height:100%;object-fit:cover}.app-select-avatar .avatar-placeholder,.app-select-option-avatar .avatar-placeholder{width:100%;height:100%;background:#f2f4f7;color:#667085;display:flex;align-items:center;justify-content:center;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:12px;line-height:18px;letter-spacing:0;font-weight:600;font-style:normal}.app-select-dot,.app-select-option-dot{width:8px;height:8px;border-radius:50%;flex-shrink:0}.app-select-value-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-value-wrapper .app-select-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085}.app-select-value{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-value.placeholder{color:#667085}.app-select-secondary,.app-select-option-secondary{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#667085;white-space:nowrap;flex-shrink:0}.app-select-arrow{margin-left:auto;flex-shrink:0;transition:transform .2s ease}.app-select-arrow.rotated{transform:rotate(180deg)}.app-select-dropdown{position:absolute;top:calc(100% + 4px);left:0;right:0;z-index:1000;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 4px 6px -2px #10182808,0 12px 16px -4px #10182814;overflow:hidden;max-height:320px;display:flex;flex-direction:column}.app-select-dropdown.dropdown-up{top:auto;bottom:calc(100% + 4px)}.app-select-dropdown.dropdown-down,.app-select-dropdown.dropdown-auto{top:calc(100% + 4px);bottom:auto}.app-select-search{padding:12px;border-bottom:1px solid #EAECF0;display:flex;align-items:center;gap:8px}.app-select-search .app-select-search-input{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;flex:1;border:none;outline:none;color:#101828}.app-select-search .app-select-search-input::placeholder{color:#667085}.app-select-search .app-select-search-clear{cursor:pointer}.app-select-loading{display:flex;justify-content:center;align-items:center;padding:8px 0}.app-select-options{flex:1;overflow-y:auto;padding:4px 0}.app-select-options::-webkit-scrollbar{width:6px}.app-select-options::-webkit-scrollbar-track{background:transparent}.app-select-options::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-no-options{padding:32px 24px;text-align:center;color:#667085;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0}.app-select-option{width:100%;padding:10px 14px;display:flex;align-items:center;gap:8px;background:transparent;border:none;text-align:left;cursor:pointer;transition:background .15s ease}.app-select-option:hover,.app-select-option.selected{background:#f9fafb}.app-select-option-text-wrapper{flex:1;display:flex;align-items:center;gap:8px;overflow:hidden}.app-select-option-text{font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:16px;line-height:24px;letter-spacing:0;font-weight:400;font-style:normal;color:#344054;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.app-select-option-text.app-select-option-truncate{max-width:200px}.app-select-option-check{margin-left:auto;flex-shrink:0}.app-select-checkbox{display:flex;align-items:center;flex-shrink:0;margin-right:8px}.app-select-checkbox .checkbox-wrapper{margin-bottom:0}.app-select-checkbox .checkbox-content{display:none}.app-select-checkbox .checkbox-input{margin-right:0}.app-select-supporting{margin-top:6px;color:#667085}.app-select-supporting .error-text{color:#f04438}.app-select-container.size-sm .app-select-input{min-height:36px;padding:8px 12px}.app-select-container.error .app-select-input{border-color:#fda29b}.app-select-container.error .app-select-supporting{color:#f04438}.app-select-container.destructive .app-select-input{border-color:#fda29b}.app-select-container.destructive .app-select-input:focus,.app-select-container.destructive .app-select-input.focused{box-shadow:0 1px 2px #1018280d,0 0 0 4px #fee4e2}.app-select-container.disabled .app-select-label,.app-select-container.disabled .app-select-value,.app-select-container.disabled .app-select-arrow,.app-select-container.disabled .app-select-leading zen-icon,.app-select-container.disabled .app-select-search-input zen-icon,.app-select-container.disabled .app-select-secondary,.app-select-container.disabled .app-select-search-field{opacity:.6}.app-select-container.disabled .app-select-input,.app-select-container.disabled .app-select-search-input{background:#f9fafb;cursor:not-allowed}.app-select-hint{display:flex;align-items:center;gap:4px;margin-top:6px;color:#667085}.app-select-hint .hint-icon{font-size:16px;color:#f04438}.app-select-hint.destructive{color:#f04438}.app-select-option.select-all{border-bottom:1px solid #F2F4F7;margin-bottom:4px;padding-bottom:14px}.app-select-option.add-new-option{color:#136ab6;font-weight:500}.app-select-option.add-new-option:hover{background:#eff8ff}.app-select-option.remove-option{background:#f9fafb;color:#344054}.app-select-option.remove-option .app-select-option-text{color:#344054}.app-select-spinner{display:flex;justify-content:center;padding:16px}.app-select-spinner .spinner-small{width:20px;height:20px;border:2px solid #F2F4F7;border-top-color:#136ab6;border-radius:50%;animation:spin .6s linear infinite}.app-select-load-more{padding:8px 14px}.app-select-load-more .app-select-load-more-btn{width:100%;padding:8px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:6px;color:#344054;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,sans-serif;font-size:14px;line-height:20px;letter-spacing:0;font-weight:500;font-style:normal;cursor:pointer;transition:all .15s ease}.app-select-load-more .app-select-load-more-btn:hover{background:#f9fafb;border-color:#667085}@keyframes spin{to{transform:rotate(360deg)}}.app-select-dropdown ::ng-deep zen-groups .zen-groups-inline{display:flex;flex-direction:column;max-height:310px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree{flex:1;overflow-y:auto;padding:4px 0}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar{width:6px}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-track{background:transparent}.app-select-dropdown ::ng-deep zen-groups .zen-groups-tree::-webkit-scrollbar-thumb{background:#d0d5dd;border-radius:3px}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox{padding:10px 14px;font-weight:400;font-size:14px;line-height:20px;color:#344054}.app-select-dropdown ::ng-deep zen-groups .action-item-checkbox:hover{background:#f9fafb}.app-select-dropdown ::ng-deep zen-groups .select-all{border-bottom:none;margin-bottom:0;font-weight:500}.app-select-dropdown ::ng-deep zen-groups .tree-item[style*=padding-left]{padding-right:14px}.app-select-dropdown ::ng-deep zen-groups .tree-item-badge{background:#f1f7fe;color:#105494}.app-select-dropdown ::ng-deep zen-groups .checkbox-component .app-checkbox-label{font-weight:400;color:#344054}.app-select-dropdown ::ng-deep zen-groups .zen-groups-no-results{padding:32px 24px;text-align:center;color:#667085}@media(max-width:640px){.app-select-dropdown{position:fixed;inset:auto 0 0;max-height:70vh;border-radius:16px 16px 0 0}}\n"] }]
4015
4015
  }], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { selectModel: [{
4016
4016
  type: Input
4017
4017
  }], selectModelChange: [{
@@ -4170,11 +4170,11 @@ class ZenduPaginationBarComponent {
4170
4170
  return result;
4171
4171
  }
4172
4172
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ZenduPaginationBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
4173
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ZenduPaginationBarComponent, isStandalone: false, selector: "zen-pagination-bar", inputs: { page: "page", perPage: "perPage", count: "count", perPageOptions: "perPageOptions" }, outputs: { pageChange: "pageChange", perPageChange: "perPageChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"pagination-component\">\n <p class=\"results-text\">\n {{ \"Showing\" | translate }} {{ rangeStart }} - {{ rangeEnd }}\n {{ \"of\" | translate }} {{ count }} {{ \"results\" | translate }}\n </p>\n\n <div class=\"page-navigation\">\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-left\"\n [disabled]=\"page <= 1\"\n (click)=\"goToPage(page - 1)\">\n </zen-button>\n\n <div class=\"pages\">\n @for (item of pages; track item; let i = $index) {\n @if (item.kind === 'page') {\n <button\n type=\"button\"\n class=\"page-btn\"\n [class.is-active]=\"item.active\"\n (click)=\"goToPage(item.page)\">\n {{ item.page }}\n </button>\n }\n @if (item.kind === 'ellipsis') {\n <span class=\"page-ellipsis\">\u2026</span>\n }\n }\n </div>\n\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-right\"\n [disabled]=\"page >= totalPages\"\n (click)=\"goToPage(page + 1)\">\n </zen-button>\n </div>\n\n <div class=\"rows-per-page\">\n <span class=\"rows-label\">{{ \"Rows per page\" | translate }}</span>\n <zen-select\n size=\"sm\"\n [options]=\"perPageOptions\"\n [(selectModel)]=\"perPage\"\n (selectModelChange)=\"onPerPageChange($event)\"\n preferredOpenDirection=\"up\">\n </zen-select>\n </div>\n</div>\n", styles: [".pagination-component{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;border-top:1px solid #EAECF0;padding:11px 24px 16px;font-family:Inter,sans-serif}.pagination-component .results-text{justify-self:start;margin:0;font-size:14px;line-height:20px;color:#667085;white-space:nowrap}.pagination-component .page-navigation{justify-self:center;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page{justify-self:end;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page .rows-label{font-size:14px;font-weight:500;line-height:20px;color:#344054;white-space:nowrap}.pagination-component .pages{display:flex;flex-direction:row;align-items:center;gap:2px}.pagination-component .page-btn,.pagination-component .page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;font-weight:500;font-size:14px;line-height:20px;color:#667085;background:transparent;border:0;padding:0;box-sizing:border-box}.pagination-component .page-btn{cursor:pointer;transition:background-color .1s,color .1s}.pagination-component .page-btn:hover:not(.is-active){background:#f9fafb}.pagination-component .page-btn.is-active{background:#f1f7fe;color:#136ab6;cursor:default}.pagination-component .page-ellipsis{cursor:default}\n"], dependencies: [{ kind: "component", type: ZenduSelectComponent, selector: "zen-select", inputs: ["selectModel", "options", "label", "supportingText", "hintText", "placeholder", "leadingType", "leadingIcon", "leadingAvatar", "leadingDotColor", "displayProp", "idProp", "hasSearch", "isMultiselect", "multiselect", "hideSelectAll", "hideTreeSearch", "required", "disabled", "error", "errorMessage", "destructive", "size", "returnOption", "isTruncate", "enableAddNewOption", "showDefaultAddOption", "newOptionText", "enableRemoveOption", "removeOptionText", "isLazyLoading", "lazyLoader", "preferredOpenDirection"], outputs: ["selectModelChange", "addNewOption", "removeOption", "closed"] }, { kind: "component", type: ZenButtonComponent, selector: "zen-button", inputs: ["variant", "buttonType", "icon", "iconRotated", "size", "destructive", "disabled", "fullWidth", "type"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
4173
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ZenduPaginationBarComponent, isStandalone: false, selector: "zen-pagination-bar", inputs: { page: "page", perPage: "perPage", count: "count", perPageOptions: "perPageOptions" }, outputs: { pageChange: "pageChange", perPageChange: "perPageChange" }, usesOnChanges: true, ngImport: i0, template: "<div class=\"pagination-component\">\n <p class=\"results-text\">\n {{ \"Showing\" | translate }} {{ rangeStart }} - {{ rangeEnd }}\n {{ \"of\" | translate }} {{ count }} {{ \"results\" | translate }}\n </p>\n\n <div class=\"page-navigation\">\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-left\"\n [disabled]=\"page <= 1\"\n (click)=\"goToPage(page - 1)\">\n </zen-button>\n\n <div class=\"pages\">\n @for (item of pages; track item; let i = $index) {\n @if (item.kind === 'page') {\n <button\n type=\"button\"\n class=\"page-btn\"\n [class.is-active]=\"item.active\"\n (click)=\"goToPage(item.page)\">\n {{ item.page }}\n </button>\n }\n @if (item.kind === 'ellipsis') {\n <span class=\"page-ellipsis\">\u2026</span>\n }\n }\n </div>\n\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-right\"\n [disabled]=\"page >= totalPages\"\n (click)=\"goToPage(page + 1)\">\n </zen-button>\n </div>\n\n <div class=\"rows-per-page\">\n <span class=\"rows-label\">{{ \"Rows per page\" | translate }}</span>\n <zen-select\n size=\"sm\"\n [options]=\"perPageOptions\"\n [(selectModel)]=\"perPage\"\n (selectModelChange)=\"onPerPageChange($event)\"\n preferredOpenDirection=\"up\">\n </zen-select>\n </div>\n</div>\n", styles: [".pagination-component{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;border-top:1px solid #EAECF0;padding:11px 24px 16px;font-family:Inter,sans-serif}.pagination-component .results-text{justify-self:start;margin:0;font-size:14px;line-height:20px;color:#667085;white-space:nowrap}.pagination-component .page-navigation{justify-self:center;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page{justify-self:end;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page .rows-label{font-size:14px;font-weight:500;line-height:20px;color:#344054;white-space:nowrap}.pagination-component .rows-per-page zen-select{min-width:80px}.pagination-component .pages{display:flex;flex-direction:row;align-items:center;gap:2px}.pagination-component .page-btn,.pagination-component .page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;font-weight:500;font-size:14px;line-height:20px;color:#667085;background:transparent;border:0;padding:0;box-sizing:border-box}.pagination-component .page-btn{cursor:pointer;transition:background-color .1s,color .1s}.pagination-component .page-btn:hover:not(.is-active){background:#f9fafb}.pagination-component .page-btn.is-active{background:#f1f7fe;color:#136ab6;cursor:default}.pagination-component .page-ellipsis{cursor:default}\n"], dependencies: [{ kind: "component", type: ZenduSelectComponent, selector: "zen-select", inputs: ["selectModel", "options", "label", "supportingText", "hintText", "placeholder", "leadingType", "leadingIcon", "leadingAvatar", "leadingDotColor", "displayProp", "idProp", "hasSearch", "isMultiselect", "multiselect", "hideSelectAll", "hideTreeSearch", "required", "disabled", "error", "errorMessage", "destructive", "size", "returnOption", "isTruncate", "enableAddNewOption", "showDefaultAddOption", "newOptionText", "enableRemoveOption", "removeOptionText", "isLazyLoading", "lazyLoader", "preferredOpenDirection"], outputs: ["selectModelChange", "addNewOption", "removeOption", "closed"] }, { kind: "component", type: ZenButtonComponent, selector: "zen-button", inputs: ["variant", "buttonType", "icon", "iconRotated", "size", "destructive", "disabled", "fullWidth", "type"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
4174
4174
  }
4175
4175
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ZenduPaginationBarComponent, decorators: [{
4176
4176
  type: Component,
4177
- args: [{ selector: 'zen-pagination-bar', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div class=\"pagination-component\">\n <p class=\"results-text\">\n {{ \"Showing\" | translate }} {{ rangeStart }} - {{ rangeEnd }}\n {{ \"of\" | translate }} {{ count }} {{ \"results\" | translate }}\n </p>\n\n <div class=\"page-navigation\">\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-left\"\n [disabled]=\"page <= 1\"\n (click)=\"goToPage(page - 1)\">\n </zen-button>\n\n <div class=\"pages\">\n @for (item of pages; track item; let i = $index) {\n @if (item.kind === 'page') {\n <button\n type=\"button\"\n class=\"page-btn\"\n [class.is-active]=\"item.active\"\n (click)=\"goToPage(item.page)\">\n {{ item.page }}\n </button>\n }\n @if (item.kind === 'ellipsis') {\n <span class=\"page-ellipsis\">\u2026</span>\n }\n }\n </div>\n\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-right\"\n [disabled]=\"page >= totalPages\"\n (click)=\"goToPage(page + 1)\">\n </zen-button>\n </div>\n\n <div class=\"rows-per-page\">\n <span class=\"rows-label\">{{ \"Rows per page\" | translate }}</span>\n <zen-select\n size=\"sm\"\n [options]=\"perPageOptions\"\n [(selectModel)]=\"perPage\"\n (selectModelChange)=\"onPerPageChange($event)\"\n preferredOpenDirection=\"up\">\n </zen-select>\n </div>\n</div>\n", styles: [".pagination-component{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;border-top:1px solid #EAECF0;padding:11px 24px 16px;font-family:Inter,sans-serif}.pagination-component .results-text{justify-self:start;margin:0;font-size:14px;line-height:20px;color:#667085;white-space:nowrap}.pagination-component .page-navigation{justify-self:center;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page{justify-self:end;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page .rows-label{font-size:14px;font-weight:500;line-height:20px;color:#344054;white-space:nowrap}.pagination-component .pages{display:flex;flex-direction:row;align-items:center;gap:2px}.pagination-component .page-btn,.pagination-component .page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;font-weight:500;font-size:14px;line-height:20px;color:#667085;background:transparent;border:0;padding:0;box-sizing:border-box}.pagination-component .page-btn{cursor:pointer;transition:background-color .1s,color .1s}.pagination-component .page-btn:hover:not(.is-active){background:#f9fafb}.pagination-component .page-btn.is-active{background:#f1f7fe;color:#136ab6;cursor:default}.pagination-component .page-ellipsis{cursor:default}\n"] }]
4177
+ args: [{ selector: 'zen-pagination-bar', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div class=\"pagination-component\">\n <p class=\"results-text\">\n {{ \"Showing\" | translate }} {{ rangeStart }} - {{ rangeEnd }}\n {{ \"of\" | translate }} {{ count }} {{ \"results\" | translate }}\n </p>\n\n <div class=\"page-navigation\">\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-left\"\n [disabled]=\"page <= 1\"\n (click)=\"goToPage(page - 1)\">\n </zen-button>\n\n <div class=\"pages\">\n @for (item of pages; track item; let i = $index) {\n @if (item.kind === 'page') {\n <button\n type=\"button\"\n class=\"page-btn\"\n [class.is-active]=\"item.active\"\n (click)=\"goToPage(item.page)\">\n {{ item.page }}\n </button>\n }\n @if (item.kind === 'ellipsis') {\n <span class=\"page-ellipsis\">\u2026</span>\n }\n }\n </div>\n\n <zen-button\n buttonType=\"button-icon-only\"\n variant=\"tertiary-gray\"\n size=\"md\"\n icon=\"chevron-right\"\n [disabled]=\"page >= totalPages\"\n (click)=\"goToPage(page + 1)\">\n </zen-button>\n </div>\n\n <div class=\"rows-per-page\">\n <span class=\"rows-label\">{{ \"Rows per page\" | translate }}</span>\n <zen-select\n size=\"sm\"\n [options]=\"perPageOptions\"\n [(selectModel)]=\"perPage\"\n (selectModelChange)=\"onPerPageChange($event)\"\n preferredOpenDirection=\"up\">\n </zen-select>\n </div>\n</div>\n", styles: [".pagination-component{display:grid;grid-template-columns:1fr auto 1fr;align-items:center;border-top:1px solid #EAECF0;padding:11px 24px 16px;font-family:Inter,sans-serif}.pagination-component .results-text{justify-self:start;margin:0;font-size:14px;line-height:20px;color:#667085;white-space:nowrap}.pagination-component .page-navigation{justify-self:center;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page{justify-self:end;display:flex;flex-direction:row;align-items:center;gap:8px}.pagination-component .rows-per-page .rows-label{font-size:14px;font-weight:500;line-height:20px;color:#344054;white-space:nowrap}.pagination-component .rows-per-page zen-select{min-width:80px}.pagination-component .pages{display:flex;flex-direction:row;align-items:center;gap:2px}.pagination-component .page-btn,.pagination-component .page-ellipsis{display:inline-flex;align-items:center;justify-content:center;width:40px;height:40px;border-radius:8px;font-weight:500;font-size:14px;line-height:20px;color:#667085;background:transparent;border:0;padding:0;box-sizing:border-box}.pagination-component .page-btn{cursor:pointer;transition:background-color .1s,color .1s}.pagination-component .page-btn:hover:not(.is-active){background:#f9fafb}.pagination-component .page-btn.is-active{background:#f1f7fe;color:#136ab6;cursor:default}.pagination-component .page-ellipsis{cursor:default}\n"] }]
4178
4178
  }], propDecorators: { page: [{
4179
4179
  type: Input
4180
4180
  }], perPage: [{
@@ -7327,6 +7327,11 @@ class ZenduDatePickerDropdownComponent {
7327
7327
  this.mobileBreakpoint = MOBILE_BREAKPOINT;
7328
7328
  this.timePicker = false;
7329
7329
  this.autoApply = false;
7330
+ /**
7331
+ * Hide the built-in trigger button. The popup then anchors to the host
7332
+ * element, so an external control (e.g. a select) can drive it via open().
7333
+ */
7334
+ this.hideTrigger = false;
7330
7335
  this.mobile = false;
7331
7336
  this.isOpen = false;
7332
7337
  this.dropdownStyle = {};
@@ -7543,35 +7548,44 @@ class ZenduDatePickerDropdownComponent {
7543
7548
  this.updateDropdownPosition();
7544
7549
  }
7545
7550
  updateDropdownPosition() {
7546
- if (!this.triggerBtn)
7551
+ // Anchor to the trigger button, or to the host element when the trigger
7552
+ // is hidden (external control drives the popup).
7553
+ const anchorEl = this.triggerBtn?.nativeElement
7554
+ ?? this._element.nativeElement;
7555
+ if (!anchorEl)
7547
7556
  return;
7548
- // Place below the trigger synchronously so the panel opens without a flash
7549
- const rect = this.triggerBtn.nativeElement.getBoundingClientRect();
7557
+ // Place below the anchor synchronously so the panel opens without a flash
7558
+ const rect = anchorEl.getBoundingClientRect();
7550
7559
  this.dropdownStyle = {
7551
7560
  left: `${rect.left}px`,
7552
7561
  top: `${rect.bottom + 8}px`
7553
7562
  };
7554
- // Once rendered, flip above or pin to the viewport if it overflows
7563
+ // Once rendered, clamp to the viewport (horizontal + vertical) so the
7564
+ // panel never overflows off-screen.
7555
7565
  requestAnimationFrame(() => {
7556
7566
  const dropdownEl = this._element.nativeElement.querySelector('.dropdown-menu');
7557
7567
  if (!dropdownEl)
7558
7568
  return;
7559
- const r = this.triggerBtn.nativeElement.getBoundingClientRect();
7560
- const dropdownHeight = dropdownEl.scrollHeight;
7561
- const spaceBelow = window.innerHeight - r.bottom - 8;
7562
- const spaceAbove = r.top - 8;
7569
+ const r = anchorEl.getBoundingClientRect();
7563
7570
  const margin = 16;
7564
7571
  const viewportHeight = window.innerHeight;
7572
+ const viewportWidth = window.innerWidth;
7573
+ const dropdownHeight = dropdownEl.scrollHeight;
7574
+ const dropdownWidth = dropdownEl.offsetWidth;
7575
+ const spaceBelow = viewportHeight - r.bottom - 8;
7576
+ const spaceAbove = r.top - 8;
7577
+ const style = {};
7578
+ // Horizontal: keep the panel within the viewport.
7579
+ const left = Math.max(margin, Math.min(r.left, viewportWidth - dropdownWidth - margin));
7580
+ style['left'] = `${left}px`;
7581
+ // Vertical: below, else above, else pin to the viewport.
7565
7582
  if (spaceBelow >= dropdownHeight) {
7566
- return;
7583
+ style['top'] = `${r.bottom + 8}px`;
7567
7584
  }
7568
- const style = { left: `${r.left}px` };
7569
- if (spaceAbove >= dropdownHeight) {
7570
- // Fits above the trigger
7585
+ else if (spaceAbove >= dropdownHeight) {
7571
7586
  style['bottom'] = `${viewportHeight - r.top + 8}px`;
7572
7587
  }
7573
7588
  else {
7574
- // Doesn't fit either way — pin to viewport so full content is visible
7575
7589
  const top = Math.max(margin, viewportHeight - dropdownHeight - margin);
7576
7590
  style['top'] = `${top}px`;
7577
7591
  style['max-height'] = `${viewportHeight - top - margin}px`;
@@ -7932,11 +7946,11 @@ class ZenduDatePickerDropdownComponent {
7932
7946
  return moment(day.date).isSame(moment(this._selectedEnd), 'day');
7933
7947
  }
7934
7948
  static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ZenduDatePickerDropdownComponent, deps: [{ token: i0.ElementRef }, { token: i2.TranslateService }, { token: ZEN_DATE_PICKER_DEFAULT_PRESETS, optional: true }], target: i0.ɵɵFactoryTarget.Component }); }
7935
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ZenduDatePickerDropdownComponent, isStandalone: false, selector: "zen-date-picker-dropdown", inputs: { type: "type", date: "date", startDate: "startDate", endDate: "endDate", presets: "presets", minDate: "minDate", maxDate: "maxDate", disabled: "disabled", dateMarkers: "dateMarkers", placeholder: "placeholder", mobileBreakpoint: "mobileBreakpoint", timePicker: "timePicker", autoApply: "autoApply" }, outputs: { dateChange: "dateChange", startDateChange: "startDateChange", endDateChange: "endDateChange", rangeChange: "rangeChange" }, host: { listeners: { "window:resize": "onResize()", "window:mousedown": "outsideHandling($event)" } }, viewQueries: [{ propertyName: "triggerBtn", first: true, predicate: ["triggerBtn"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"zen-dpd\">\n <!-- Trigger Button -->\n <button class=\"dropdown-trigger\"\n #triggerBtn\n [disabled]=\"disabled\"\n [class.active]=\"isOpen\"\n [class.has-value]=\"hasValue\"\n (click)=\"toggle()\">\n <zen-icon class=\"trigger-icon\"\n src=\"assets/ng-zenduit/icons/calendar.svg\">\n </zen-icon>\n <span class=\"trigger-label\">{{ triggerLabel }}</span>\n </button>\n\n <!-- Dropdown Panel -->\n @if (isOpen) {\n <div class=\"dropdown-menu\" [class.mobile]=\"mobile\" [ngStyle]=\"dropdownStyle\">\n <!-- RANGE DESKTOP: presets sidebar + dual calendar -->\n @if (type === 'range' && !mobile) {\n <!-- Presets sidebar -->\n <div class=\"presets-sidebar\">\n @for (preset of activePresets; track preset) {\n <div class=\"preset-item\"\n [class.active]=\"_activePreset === preset.label\"\n (click)=\"selectPreset(preset)\">\n {{ preset.label | translate }}\n </div>\n }\n </div>\n <div class=\"sidebar-divider\"></div>\n <!-- Calendars + bottom panel -->\n <div class=\"calendars-container\">\n <div class=\"dual-calendars\">\n <!-- Left calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"leftPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"leftNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n </div>\n <div class=\"calendar-divider\"></div>\n <!-- Right calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"rightPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ rightDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"rightNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: rightDayRows }\"></ng-container>\n </div>\n </div>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n <div class=\"bottom-divider\"></div>\n <!-- Bottom panel: inputs (or legend) + actions -->\n <div class=\"bottom-panel\">\n @if (legendMarkers.length) {\n <div class=\"marker-legend\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"input-fields\">\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Start date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('End date' | translate) }}\n </span>\n </div>\n </div>\n }\n <div class=\"actions\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- RANGE MOBILE: single calendar with dual inputs on top -->\n @if (type === 'range' && mobile) {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Range inputs -->\n <div class=\"mobile-range-inputs\">\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Select date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('Select date' | translate) }}\n </span>\n </div>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- SINGLE DATE: single calendar + input + today button -->\n @if (type === 'single') {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Date input + Today button -->\n <div class=\"single-actions-row\">\n <div class=\"date-input flex-1\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedDate\">\n {{ _selectedDate ? formattedSelectedDate : ('Select date' | translate) }}\n </span>\n </div>\n <button class=\"btn-today\" (click)=\"goToToday()\">{{ 'Today' | translate }}</button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone single\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n @if (!autoApply) {\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Shared time picker template -->\n<ng-template #timePickerSection>\n <div class=\"time-picker-container\">\n <div class=\"time-picker-content\">\n <span class=\"time-picker-label\">{{ 'Select a time' | translate }}</span>\n <div class=\"time-picker-row\">\n <div class=\"time-fields\">\n <!-- Hours -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Hours\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_hoursDisplay\"\n (input)=\"onHoursInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampHours()\"\n (keydown)=\"onTimeKeydown($event, 'hours')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'HRS' | translate }}</span>\n </div>\n\n <!-- Colon separator -->\n <div class=\"time-colon\">:</div>\n\n <!-- Minutes -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Minutes\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_minutesDisplay\"\n (input)=\"onMinutesInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampMinutes()\"\n (keydown)=\"onTimeKeydown($event, 'minutes')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'MIN' | translate }}</span>\n </div>\n </div>\n\n <!-- AM/PM toggle -->\n <div class=\"time-period-toggle\">\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'AM'\"\n (click)=\"setPeriod('AM')\">\n AM\n </button>\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'PM'\"\n (click)=\"setPeriod('PM')\">\n PM\n </button>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- Shared calendar grid template -->\n<ng-template #calendarGrid let-dayRows>\n <div class=\"dates-grid\">\n <!-- Week day headers -->\n <div class=\"week-header\">\n @for (wd of weekDays; track wd) {\n <div class=\"cell header-cell\">{{ wd | translate }}</div>\n }\n </div>\n <!-- Day rows -->\n @for (row of dayRows; track row) {\n <div class=\"day-row\">\n @for (day of row.days; track day) {\n <div class=\"cell day-cell\"\n [class.outside]=\"day.isOutside\"\n [class.selected]=\"day.selected\"\n [class.today]=\"isToday(day)\"\n [class.disabled]=\"day.isDisabled\"\n [class.in-range]=\"isInRange(day)\"\n [class.range-start]=\"isRangeStart(day)\"\n [class.range-end]=\"isRangeEnd(day)\"\n (click)=\"selectDay(day)\">\n <span class=\"day-number\">{{ day.lbl }}</span>\n @if (day.markerColors?.length) {\n <div class=\"marker-dots\">\n @for (c of day.markerColors; track c) {\n <span class=\"marker-dot\"\n [style.background]=\"c || null\"></span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;position:relative;width:100%}.zen-dpd{position:relative;width:100%}.dropdown-trigger{display:flex;width:100%;align-items:center;justify-content:center;gap:8px;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;cursor:pointer;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#667085;white-space:nowrap;transition:.2s;appearance:none;outline:none}.dropdown-trigger:hover{border-color:#98a2b3}.dropdown-trigger.active{box-shadow:0 1px 2px #1018280d,0 0 0 4px #f2f4f7}.dropdown-trigger.has-value{color:#344054}.dropdown-trigger:disabled{cursor:not-allowed;opacity:.5}.dropdown-trigger .trigger-icon{width:20px;height:20px;background-color:#667085}.dropdown-trigger.has-value .trigger-icon{background-color:#344054}.dropdown-menu{position:fixed;z-index:1200;display:inline-flex;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 20px 24px -4px #10182814,0 8px 8px -4px #10182808;font-family:Inter,sans-serif;overflow-y:auto;overflow-x:hidden;width:max-content}.presets-sidebar{display:flex;flex-direction:column;gap:4px;padding:12px 16px;min-width:160px}.presets-sidebar .preset-item{padding:10px 16px;border-radius:6px;font-size:14px;font-weight:400;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;transition:.15s}.presets-sidebar .preset-item:hover{background:#f1f7fe;color:#105494}.presets-sidebar .preset-item.active{background:#f1f7fe;color:#105494;font-weight:500}.sidebar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendars-container{display:flex;flex-direction:column}.dual-calendars{display:flex}.calendar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendar-panel{width:328px;overflow:hidden}.calendar-content{display:flex;flex-direction:column;padding:20px 24px;gap:12px}.single-calendar-container{display:flex;flex-direction:column;width:328px}.month-header{display:flex;align-items:center;justify-content:space-between;width:280px}.nav-btn{display:flex;align-items:center;justify-content:center;padding:10px;border-radius:8px;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;transition:.15s}.nav-btn:hover{background:#f9fafb}.nav-btn zen-icon{width:20px;height:20px;background-color:#344054}.month-title{font-size:16px;font-weight:500;line-height:24px;color:#344054;text-align:center}.single-actions-row{display:flex;gap:12px;align-items:flex-start;width:280px}.flex-1{flex:1}.btn-today{display:flex;align-items:center;justify-content:center;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;appearance:none;outline:none;transition:.15s}.btn-today:hover{background:#f9fafb}.mobile-range-inputs{display:flex;align-items:center;gap:8px;height:40px;width:280px}.date-input{display:flex;align-items:center;padding:8px 14px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;min-width:0}.date-input.compact{flex:1}.date-input .date-input-text{font-size:16px;font-weight:400;line-height:24px;color:#101828;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.date-input .date-input-text.placeholder{color:#667085}.date-separator{font-size:16px;font-weight:400;line-height:24px;color:#667085}.dates-grid{display:flex;flex-direction:column;gap:4px}.week-header{display:flex;width:280px}.day-row{display:flex;border-radius:20px;overflow:hidden}.cell{position:relative;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:20px}.cell .day-number{font-size:14px;font-weight:400;line-height:20px;text-align:center;color:#344054;width:24px}.cell.header-cell .day-number{font-weight:500}.header-cell{font-size:14px;font-weight:500;line-height:20px;color:#344054}.day-cell{cursor:pointer;transition:.1s}.day-cell:hover:not(.disabled):not(.selected){background:#f1f7fe}.day-cell:hover:not(.disabled):not(.selected) .day-number{color:#105494;font-weight:500}.day-cell.outside{cursor:default;pointer-events:none}.day-cell.today{background:#f2f4f7}.day-cell.today .day-number{font-weight:500}.day-cell.selected{background:#136ab6}.day-cell.selected .day-number{color:#fff;font-weight:500}.day-cell.in-range{background:#f1f7fe;border-radius:0}.day-cell.in-range .day-number{color:#105494}.day-cell.range-start{border-radius:20px 0 0 20px}.day-cell.range-end{border-radius:0 20px 20px 0}.day-cell.range-start.range-end{border-radius:20px}.day-cell.disabled{cursor:not-allowed}.day-cell.disabled .day-number{color:#d0d5dd}.day-cell .marker-dots{position:absolute;bottom:4px;left:50%;transform:translate(-50%);display:flex;gap:3px}.day-cell .marker-dots .marker-dot{width:5px;height:5px;border-radius:50%;background:#105494}.day-cell.outside .marker-dots .marker-dot{opacity:.4}.day-cell.selected .marker-dots .marker-dot{background:#fff!important}.time-picker-container{display:flex;flex-direction:column;padding:16px;background:#fff;width:100%}.time-picker-content{display:flex;flex-direction:column;gap:16px}.time-picker-label{font-size:14px;font-weight:500;line-height:20px;color:#1d2939}.time-picker-row{display:flex;align-items:flex-start;gap:16px}.time-fields{display:flex;gap:8px;align-items:flex-start}.time-input-group{display:flex;flex-direction:column;align-items:center;gap:4px}.time-input-box{display:flex;align-items:center;justify-content:center;gap:6px;height:44px;min-width:72px;padding:6px 6px 6px 12px;background:#f2f4f7;border:1px solid #E5E7EB;border-radius:8px;box-sizing:border-box}.time-input{width:24px;border:none;background:transparent;font-size:16px;font-weight:500;line-height:24px;color:#1d2939;text-align:center;outline:none;padding:0;font-family:Inter,sans-serif;-moz-appearance:textfield}.time-input::-webkit-outer-spin-button,.time-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.time-arrows{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:20px;height:100%}.time-arrow-btn{display:flex;align-items:center;justify-content:center;width:14px;height:14px;padding:0;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;border-radius:2px;transition:.15s}.time-arrow-btn:hover{background:#6670851f}.time-arrow-btn zen-icon{width:14px;height:14px;background-color:#667085}.time-input-label{font-size:10px;font-weight:500;line-height:normal;color:#667085;text-transform:uppercase;letter-spacing:.02em}.time-colon{display:flex;flex-direction:column;align-items:center;justify-content:center;width:4px;height:44px;font-size:14px;font-weight:500;line-height:20px;color:#667085}.time-period-toggle{display:flex;gap:8px;align-items:center;height:44px;align-self:flex-start}.time-period-btn{display:flex;align-items:center;justify-content:center;padding:10px 14px;height:36px;box-sizing:border-box;border-radius:8px;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap;background:#fff;border:1px solid #D0D5DD;box-shadow:0 1px 2px #1018280d;color:#344054}.time-period-btn.active{background:#f1f7fe;border-color:#f1f7fe;color:#105494}.time-period-btn:hover:not(.active){background:#f9fafb}.bottom-divider{height:1px;min-height:1px;background:#eaecf0;width:100%;flex-shrink:0}.bottom-panel{display:flex;align-items:flex-start;justify-content:space-between;padding:16px 24px}.bottom-panel.compact{justify-content:flex-end}.marker-legend{display:flex;flex-wrap:wrap;gap:16px;align-items:center}.marker-legend.standalone{padding:12px 24px 16px}.marker-legend.standalone.single{padding-top:0}.marker-legend .legend-item{display:flex;align-items:center;gap:6px}.marker-legend .legend-dot{width:8px;height:8px;border-radius:50%;background:#105494}.marker-legend .legend-title{font-size:14px;font-weight:400;line-height:20px;color:#344054}.input-fields{display:flex;gap:12px;align-items:center}.input-fields .date-input{width:128px}.actions{display:flex;gap:12px}.actions.full-width,.actions.full-width .btn-cancel,.actions.full-width .btn-apply{flex:1}.btn-cancel{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-cancel:hover{background:#f9fafb}.btn-apply{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#136ab6;border:1px solid #136AB6;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#fff;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-apply:hover{background:#105494}.btn-apply:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ZenduIconComponent, selector: "zen-icon", inputs: ["src", "name", "size", "color", "theme", "customColor"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
7949
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "22.0.0", type: ZenduDatePickerDropdownComponent, isStandalone: false, selector: "zen-date-picker-dropdown", inputs: { type: "type", date: "date", startDate: "startDate", endDate: "endDate", presets: "presets", minDate: "minDate", maxDate: "maxDate", disabled: "disabled", dateMarkers: "dateMarkers", placeholder: "placeholder", mobileBreakpoint: "mobileBreakpoint", timePicker: "timePicker", autoApply: "autoApply", hideTrigger: "hideTrigger" }, outputs: { dateChange: "dateChange", startDateChange: "startDateChange", endDateChange: "endDateChange", rangeChange: "rangeChange" }, host: { listeners: { "window:resize": "onResize()", "window:mousedown": "outsideHandling($event)" } }, viewQueries: [{ propertyName: "triggerBtn", first: true, predicate: ["triggerBtn"], descendants: true }], usesOnChanges: true, ngImport: i0, template: "<div class=\"zen-dpd\">\n <!-- Trigger Button -->\n @if (!hideTrigger) {\n <button class=\"dropdown-trigger\"\n #triggerBtn\n [disabled]=\"disabled\"\n [class.active]=\"isOpen\"\n [class.has-value]=\"hasValue\"\n (click)=\"toggle()\">\n <zen-icon class=\"trigger-icon\"\n src=\"assets/ng-zenduit/icons/calendar.svg\">\n </zen-icon>\n <span class=\"trigger-label\">{{ triggerLabel }}</span>\n </button>\n }\n\n <!-- Dropdown Panel -->\n @if (isOpen) {\n <div class=\"dropdown-menu\" [class.mobile]=\"mobile\" [ngStyle]=\"dropdownStyle\">\n <!-- RANGE DESKTOP: presets sidebar + dual calendar -->\n @if (type === 'range' && !mobile) {\n <!-- Presets sidebar -->\n <div class=\"presets-sidebar\">\n @for (preset of activePresets; track preset) {\n <div class=\"preset-item\"\n [class.active]=\"_activePreset === preset.label\"\n (click)=\"selectPreset(preset)\">\n {{ preset.label | translate }}\n </div>\n }\n </div>\n <div class=\"sidebar-divider\"></div>\n <!-- Calendars + bottom panel -->\n <div class=\"calendars-container\">\n <div class=\"dual-calendars\">\n <!-- Left calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"leftPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"leftNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n </div>\n <div class=\"calendar-divider\"></div>\n <!-- Right calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"rightPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ rightDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"rightNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: rightDayRows }\"></ng-container>\n </div>\n </div>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n <div class=\"bottom-divider\"></div>\n <!-- Bottom panel: inputs (or legend) + actions -->\n <div class=\"bottom-panel\">\n @if (legendMarkers.length) {\n <div class=\"marker-legend\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"input-fields\">\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Start date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('End date' | translate) }}\n </span>\n </div>\n </div>\n }\n <div class=\"actions\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- RANGE MOBILE: single calendar with dual inputs on top -->\n @if (type === 'range' && mobile) {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Range inputs -->\n <div class=\"mobile-range-inputs\">\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Select date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('Select date' | translate) }}\n </span>\n </div>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- SINGLE DATE: single calendar + input + today button -->\n @if (type === 'single') {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Date input + Today button -->\n <div class=\"single-actions-row\">\n <div class=\"date-input flex-1\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedDate\">\n {{ _selectedDate ? formattedSelectedDate : ('Select date' | translate) }}\n </span>\n </div>\n <button class=\"btn-today\" (click)=\"goToToday()\">{{ 'Today' | translate }}</button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone single\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n @if (!autoApply) {\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Shared time picker template -->\n<ng-template #timePickerSection>\n <div class=\"time-picker-container\">\n <div class=\"time-picker-content\">\n <span class=\"time-picker-label\">{{ 'Select a time' | translate }}</span>\n <div class=\"time-picker-row\">\n <div class=\"time-fields\">\n <!-- Hours -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Hours\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_hoursDisplay\"\n (input)=\"onHoursInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampHours()\"\n (keydown)=\"onTimeKeydown($event, 'hours')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'HRS' | translate }}</span>\n </div>\n\n <!-- Colon separator -->\n <div class=\"time-colon\">:</div>\n\n <!-- Minutes -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Minutes\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_minutesDisplay\"\n (input)=\"onMinutesInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampMinutes()\"\n (keydown)=\"onTimeKeydown($event, 'minutes')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'MIN' | translate }}</span>\n </div>\n </div>\n\n <!-- AM/PM toggle -->\n <div class=\"time-period-toggle\">\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'AM'\"\n (click)=\"setPeriod('AM')\">\n AM\n </button>\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'PM'\"\n (click)=\"setPeriod('PM')\">\n PM\n </button>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- Shared calendar grid template -->\n<ng-template #calendarGrid let-dayRows>\n <div class=\"dates-grid\">\n <!-- Week day headers -->\n <div class=\"week-header\">\n @for (wd of weekDays; track wd) {\n <div class=\"cell header-cell\">{{ wd | translate }}</div>\n }\n </div>\n <!-- Day rows -->\n @for (row of dayRows; track row) {\n <div class=\"day-row\">\n @for (day of row.days; track day) {\n <div class=\"cell day-cell\"\n [class.outside]=\"day.isOutside\"\n [class.selected]=\"day.selected\"\n [class.today]=\"isToday(day)\"\n [class.disabled]=\"day.isDisabled\"\n [class.in-range]=\"isInRange(day)\"\n [class.range-start]=\"isRangeStart(day)\"\n [class.range-end]=\"isRangeEnd(day)\"\n (click)=\"selectDay(day)\">\n <span class=\"day-number\">{{ day.lbl }}</span>\n @if (day.markerColors?.length) {\n <div class=\"marker-dots\">\n @for (c of day.markerColors; track c) {\n <span class=\"marker-dot\"\n [style.background]=\"c || null\"></span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;position:relative;width:100%}.zen-dpd{position:relative;width:100%}.dropdown-trigger{display:flex;width:100%;align-items:center;justify-content:center;gap:8px;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;cursor:pointer;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#667085;white-space:nowrap;transition:.2s;appearance:none;outline:none}.dropdown-trigger:hover{border-color:#98a2b3}.dropdown-trigger.active{box-shadow:0 1px 2px #1018280d,0 0 0 4px #f2f4f7}.dropdown-trigger.has-value{color:#344054}.dropdown-trigger:disabled{cursor:not-allowed;opacity:.5}.dropdown-trigger .trigger-icon{width:20px;height:20px;background-color:#667085}.dropdown-trigger.has-value .trigger-icon{background-color:#344054}.dropdown-menu{position:fixed;z-index:1200;display:inline-flex;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 20px 24px -4px #10182814,0 8px 8px -4px #10182808;font-family:Inter,sans-serif;overflow-y:auto;overflow-x:hidden;width:max-content}.presets-sidebar{display:flex;flex-direction:column;gap:4px;padding:12px 16px;min-width:160px}.presets-sidebar .preset-item{padding:10px 16px;border-radius:6px;font-size:14px;font-weight:400;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;transition:.15s}.presets-sidebar .preset-item:hover{background:#f1f7fe;color:#105494}.presets-sidebar .preset-item.active{background:#f1f7fe;color:#105494;font-weight:500}.sidebar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendars-container{display:flex;flex-direction:column}.dual-calendars{display:flex}.calendar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendar-panel{width:328px;overflow:hidden}.calendar-content{display:flex;flex-direction:column;padding:20px 24px;gap:12px}.single-calendar-container{display:flex;flex-direction:column;width:328px}.month-header{display:flex;align-items:center;justify-content:space-between;width:280px}.nav-btn{display:flex;align-items:center;justify-content:center;padding:10px;border-radius:8px;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;transition:.15s}.nav-btn:hover{background:#f9fafb}.nav-btn zen-icon{width:20px;height:20px;background-color:#344054}.month-title{font-size:16px;font-weight:500;line-height:24px;color:#344054;text-align:center}.single-actions-row{display:flex;gap:12px;align-items:flex-start;width:280px}.flex-1{flex:1}.btn-today{display:flex;align-items:center;justify-content:center;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;appearance:none;outline:none;transition:.15s}.btn-today:hover{background:#f9fafb}.mobile-range-inputs{display:flex;align-items:center;gap:8px;height:40px;width:280px}.date-input{display:flex;align-items:center;padding:8px 14px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;min-width:0}.date-input.compact{flex:1}.date-input .date-input-text{font-size:16px;font-weight:400;line-height:24px;color:#101828;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.date-input .date-input-text.placeholder{color:#667085}.date-separator{font-size:16px;font-weight:400;line-height:24px;color:#667085}.dates-grid{display:flex;flex-direction:column;gap:4px}.week-header{display:flex;width:280px}.day-row{display:flex;border-radius:20px;overflow:hidden}.cell{position:relative;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:20px}.cell .day-number{font-size:14px;font-weight:400;line-height:20px;text-align:center;color:#344054;width:24px}.cell.header-cell .day-number{font-weight:500}.header-cell{font-size:14px;font-weight:500;line-height:20px;color:#344054}.day-cell{cursor:pointer;transition:.1s}.day-cell:hover:not(.disabled):not(.selected){background:#f1f7fe}.day-cell:hover:not(.disabled):not(.selected) .day-number{color:#105494;font-weight:500}.day-cell.outside{cursor:default;pointer-events:none}.day-cell.today{background:#f2f4f7}.day-cell.today .day-number{font-weight:500}.day-cell.selected{background:#136ab6}.day-cell.selected .day-number{color:#fff;font-weight:500}.day-cell.in-range{background:#f1f7fe;border-radius:0}.day-cell.in-range .day-number{color:#105494}.day-cell.range-start{border-radius:20px 0 0 20px}.day-cell.range-end{border-radius:0 20px 20px 0}.day-cell.range-start.range-end{border-radius:20px}.day-cell.disabled{cursor:not-allowed}.day-cell.disabled .day-number{color:#d0d5dd}.day-cell .marker-dots{position:absolute;bottom:4px;left:50%;transform:translate(-50%);display:flex;gap:3px}.day-cell .marker-dots .marker-dot{width:5px;height:5px;border-radius:50%;background:#105494}.day-cell.outside .marker-dots .marker-dot{opacity:.4}.day-cell.selected .marker-dots .marker-dot{background:#fff!important}.time-picker-container{display:flex;flex-direction:column;padding:16px;background:#fff;width:100%}.time-picker-content{display:flex;flex-direction:column;gap:16px}.time-picker-label{font-size:14px;font-weight:500;line-height:20px;color:#1d2939}.time-picker-row{display:flex;align-items:flex-start;gap:16px}.time-fields{display:flex;gap:8px;align-items:flex-start}.time-input-group{display:flex;flex-direction:column;align-items:center;gap:4px}.time-input-box{display:flex;align-items:center;justify-content:center;gap:6px;height:44px;min-width:72px;padding:6px 6px 6px 12px;background:#f2f4f7;border:1px solid #E5E7EB;border-radius:8px;box-sizing:border-box}.time-input{width:24px;border:none;background:transparent;font-size:16px;font-weight:500;line-height:24px;color:#1d2939;text-align:center;outline:none;padding:0;font-family:Inter,sans-serif;-moz-appearance:textfield}.time-input::-webkit-outer-spin-button,.time-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.time-arrows{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:20px;height:100%}.time-arrow-btn{display:flex;align-items:center;justify-content:center;width:14px;height:14px;padding:0;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;border-radius:2px;transition:.15s}.time-arrow-btn:hover{background:#6670851f}.time-arrow-btn zen-icon{width:14px;height:14px;background-color:#667085}.time-input-label{font-size:10px;font-weight:500;line-height:normal;color:#667085;text-transform:uppercase;letter-spacing:.02em}.time-colon{display:flex;flex-direction:column;align-items:center;justify-content:center;width:4px;height:44px;font-size:14px;font-weight:500;line-height:20px;color:#667085}.time-period-toggle{display:flex;gap:8px;align-items:center;height:44px;align-self:flex-start}.time-period-btn{display:flex;align-items:center;justify-content:center;padding:10px 14px;height:36px;box-sizing:border-box;border-radius:8px;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap;background:#fff;border:1px solid #D0D5DD;box-shadow:0 1px 2px #1018280d;color:#344054}.time-period-btn.active{background:#f1f7fe;border-color:#f1f7fe;color:#105494}.time-period-btn:hover:not(.active){background:#f9fafb}.bottom-divider{height:1px;min-height:1px;background:#eaecf0;width:100%;flex-shrink:0}.bottom-panel{display:flex;align-items:flex-start;justify-content:space-between;padding:16px 24px}.bottom-panel.compact{justify-content:flex-end}.marker-legend{display:flex;flex-wrap:wrap;gap:16px;align-items:center}.marker-legend.standalone{padding:12px 24px 16px}.marker-legend.standalone.single{padding-top:0}.marker-legend .legend-item{display:flex;align-items:center;gap:6px}.marker-legend .legend-dot{width:8px;height:8px;border-radius:50%;background:#105494}.marker-legend .legend-title{font-size:14px;font-weight:400;line-height:20px;color:#344054}.input-fields{display:flex;gap:12px;align-items:center}.input-fields .date-input{width:auto;min-width:128px}.actions{display:flex;gap:12px}.actions.full-width,.actions.full-width .btn-cancel,.actions.full-width .btn-apply{flex:1}.btn-cancel{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-cancel:hover{background:#f9fafb}.btn-apply{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#136ab6;border:1px solid #136AB6;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#fff;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-apply:hover{background:#105494}.btn-apply:disabled{opacity:.5;cursor:not-allowed}\n"], dependencies: [{ kind: "directive", type: i1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: i1.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "component", type: ZenduIconComponent, selector: "zen-icon", inputs: ["src", "name", "size", "color", "theme", "customColor"] }, { kind: "pipe", type: i2.TranslatePipe, name: "translate" }], changeDetection: i0.ChangeDetectionStrategy.Eager }); }
7936
7950
  }
7937
7951
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImport: i0, type: ZenduDatePickerDropdownComponent, decorators: [{
7938
7952
  type: Component,
7939
- args: [{ selector: 'zen-date-picker-dropdown', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div class=\"zen-dpd\">\n <!-- Trigger Button -->\n <button class=\"dropdown-trigger\"\n #triggerBtn\n [disabled]=\"disabled\"\n [class.active]=\"isOpen\"\n [class.has-value]=\"hasValue\"\n (click)=\"toggle()\">\n <zen-icon class=\"trigger-icon\"\n src=\"assets/ng-zenduit/icons/calendar.svg\">\n </zen-icon>\n <span class=\"trigger-label\">{{ triggerLabel }}</span>\n </button>\n\n <!-- Dropdown Panel -->\n @if (isOpen) {\n <div class=\"dropdown-menu\" [class.mobile]=\"mobile\" [ngStyle]=\"dropdownStyle\">\n <!-- RANGE DESKTOP: presets sidebar + dual calendar -->\n @if (type === 'range' && !mobile) {\n <!-- Presets sidebar -->\n <div class=\"presets-sidebar\">\n @for (preset of activePresets; track preset) {\n <div class=\"preset-item\"\n [class.active]=\"_activePreset === preset.label\"\n (click)=\"selectPreset(preset)\">\n {{ preset.label | translate }}\n </div>\n }\n </div>\n <div class=\"sidebar-divider\"></div>\n <!-- Calendars + bottom panel -->\n <div class=\"calendars-container\">\n <div class=\"dual-calendars\">\n <!-- Left calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"leftPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"leftNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n </div>\n <div class=\"calendar-divider\"></div>\n <!-- Right calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"rightPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ rightDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"rightNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: rightDayRows }\"></ng-container>\n </div>\n </div>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n <div class=\"bottom-divider\"></div>\n <!-- Bottom panel: inputs (or legend) + actions -->\n <div class=\"bottom-panel\">\n @if (legendMarkers.length) {\n <div class=\"marker-legend\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"input-fields\">\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Start date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('End date' | translate) }}\n </span>\n </div>\n </div>\n }\n <div class=\"actions\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- RANGE MOBILE: single calendar with dual inputs on top -->\n @if (type === 'range' && mobile) {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Range inputs -->\n <div class=\"mobile-range-inputs\">\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Select date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('Select date' | translate) }}\n </span>\n </div>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- SINGLE DATE: single calendar + input + today button -->\n @if (type === 'single') {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Date input + Today button -->\n <div class=\"single-actions-row\">\n <div class=\"date-input flex-1\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedDate\">\n {{ _selectedDate ? formattedSelectedDate : ('Select date' | translate) }}\n </span>\n </div>\n <button class=\"btn-today\" (click)=\"goToToday()\">{{ 'Today' | translate }}</button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone single\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n @if (!autoApply) {\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Shared time picker template -->\n<ng-template #timePickerSection>\n <div class=\"time-picker-container\">\n <div class=\"time-picker-content\">\n <span class=\"time-picker-label\">{{ 'Select a time' | translate }}</span>\n <div class=\"time-picker-row\">\n <div class=\"time-fields\">\n <!-- Hours -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Hours\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_hoursDisplay\"\n (input)=\"onHoursInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampHours()\"\n (keydown)=\"onTimeKeydown($event, 'hours')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'HRS' | translate }}</span>\n </div>\n\n <!-- Colon separator -->\n <div class=\"time-colon\">:</div>\n\n <!-- Minutes -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Minutes\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_minutesDisplay\"\n (input)=\"onMinutesInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampMinutes()\"\n (keydown)=\"onTimeKeydown($event, 'minutes')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'MIN' | translate }}</span>\n </div>\n </div>\n\n <!-- AM/PM toggle -->\n <div class=\"time-period-toggle\">\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'AM'\"\n (click)=\"setPeriod('AM')\">\n AM\n </button>\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'PM'\"\n (click)=\"setPeriod('PM')\">\n PM\n </button>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- Shared calendar grid template -->\n<ng-template #calendarGrid let-dayRows>\n <div class=\"dates-grid\">\n <!-- Week day headers -->\n <div class=\"week-header\">\n @for (wd of weekDays; track wd) {\n <div class=\"cell header-cell\">{{ wd | translate }}</div>\n }\n </div>\n <!-- Day rows -->\n @for (row of dayRows; track row) {\n <div class=\"day-row\">\n @for (day of row.days; track day) {\n <div class=\"cell day-cell\"\n [class.outside]=\"day.isOutside\"\n [class.selected]=\"day.selected\"\n [class.today]=\"isToday(day)\"\n [class.disabled]=\"day.isDisabled\"\n [class.in-range]=\"isInRange(day)\"\n [class.range-start]=\"isRangeStart(day)\"\n [class.range-end]=\"isRangeEnd(day)\"\n (click)=\"selectDay(day)\">\n <span class=\"day-number\">{{ day.lbl }}</span>\n @if (day.markerColors?.length) {\n <div class=\"marker-dots\">\n @for (c of day.markerColors; track c) {\n <span class=\"marker-dot\"\n [style.background]=\"c || null\"></span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;position:relative;width:100%}.zen-dpd{position:relative;width:100%}.dropdown-trigger{display:flex;width:100%;align-items:center;justify-content:center;gap:8px;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;cursor:pointer;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#667085;white-space:nowrap;transition:.2s;appearance:none;outline:none}.dropdown-trigger:hover{border-color:#98a2b3}.dropdown-trigger.active{box-shadow:0 1px 2px #1018280d,0 0 0 4px #f2f4f7}.dropdown-trigger.has-value{color:#344054}.dropdown-trigger:disabled{cursor:not-allowed;opacity:.5}.dropdown-trigger .trigger-icon{width:20px;height:20px;background-color:#667085}.dropdown-trigger.has-value .trigger-icon{background-color:#344054}.dropdown-menu{position:fixed;z-index:1200;display:inline-flex;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 20px 24px -4px #10182814,0 8px 8px -4px #10182808;font-family:Inter,sans-serif;overflow-y:auto;overflow-x:hidden;width:max-content}.presets-sidebar{display:flex;flex-direction:column;gap:4px;padding:12px 16px;min-width:160px}.presets-sidebar .preset-item{padding:10px 16px;border-radius:6px;font-size:14px;font-weight:400;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;transition:.15s}.presets-sidebar .preset-item:hover{background:#f1f7fe;color:#105494}.presets-sidebar .preset-item.active{background:#f1f7fe;color:#105494;font-weight:500}.sidebar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendars-container{display:flex;flex-direction:column}.dual-calendars{display:flex}.calendar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendar-panel{width:328px;overflow:hidden}.calendar-content{display:flex;flex-direction:column;padding:20px 24px;gap:12px}.single-calendar-container{display:flex;flex-direction:column;width:328px}.month-header{display:flex;align-items:center;justify-content:space-between;width:280px}.nav-btn{display:flex;align-items:center;justify-content:center;padding:10px;border-radius:8px;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;transition:.15s}.nav-btn:hover{background:#f9fafb}.nav-btn zen-icon{width:20px;height:20px;background-color:#344054}.month-title{font-size:16px;font-weight:500;line-height:24px;color:#344054;text-align:center}.single-actions-row{display:flex;gap:12px;align-items:flex-start;width:280px}.flex-1{flex:1}.btn-today{display:flex;align-items:center;justify-content:center;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;appearance:none;outline:none;transition:.15s}.btn-today:hover{background:#f9fafb}.mobile-range-inputs{display:flex;align-items:center;gap:8px;height:40px;width:280px}.date-input{display:flex;align-items:center;padding:8px 14px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;min-width:0}.date-input.compact{flex:1}.date-input .date-input-text{font-size:16px;font-weight:400;line-height:24px;color:#101828;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.date-input .date-input-text.placeholder{color:#667085}.date-separator{font-size:16px;font-weight:400;line-height:24px;color:#667085}.dates-grid{display:flex;flex-direction:column;gap:4px}.week-header{display:flex;width:280px}.day-row{display:flex;border-radius:20px;overflow:hidden}.cell{position:relative;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:20px}.cell .day-number{font-size:14px;font-weight:400;line-height:20px;text-align:center;color:#344054;width:24px}.cell.header-cell .day-number{font-weight:500}.header-cell{font-size:14px;font-weight:500;line-height:20px;color:#344054}.day-cell{cursor:pointer;transition:.1s}.day-cell:hover:not(.disabled):not(.selected){background:#f1f7fe}.day-cell:hover:not(.disabled):not(.selected) .day-number{color:#105494;font-weight:500}.day-cell.outside{cursor:default;pointer-events:none}.day-cell.today{background:#f2f4f7}.day-cell.today .day-number{font-weight:500}.day-cell.selected{background:#136ab6}.day-cell.selected .day-number{color:#fff;font-weight:500}.day-cell.in-range{background:#f1f7fe;border-radius:0}.day-cell.in-range .day-number{color:#105494}.day-cell.range-start{border-radius:20px 0 0 20px}.day-cell.range-end{border-radius:0 20px 20px 0}.day-cell.range-start.range-end{border-radius:20px}.day-cell.disabled{cursor:not-allowed}.day-cell.disabled .day-number{color:#d0d5dd}.day-cell .marker-dots{position:absolute;bottom:4px;left:50%;transform:translate(-50%);display:flex;gap:3px}.day-cell .marker-dots .marker-dot{width:5px;height:5px;border-radius:50%;background:#105494}.day-cell.outside .marker-dots .marker-dot{opacity:.4}.day-cell.selected .marker-dots .marker-dot{background:#fff!important}.time-picker-container{display:flex;flex-direction:column;padding:16px;background:#fff;width:100%}.time-picker-content{display:flex;flex-direction:column;gap:16px}.time-picker-label{font-size:14px;font-weight:500;line-height:20px;color:#1d2939}.time-picker-row{display:flex;align-items:flex-start;gap:16px}.time-fields{display:flex;gap:8px;align-items:flex-start}.time-input-group{display:flex;flex-direction:column;align-items:center;gap:4px}.time-input-box{display:flex;align-items:center;justify-content:center;gap:6px;height:44px;min-width:72px;padding:6px 6px 6px 12px;background:#f2f4f7;border:1px solid #E5E7EB;border-radius:8px;box-sizing:border-box}.time-input{width:24px;border:none;background:transparent;font-size:16px;font-weight:500;line-height:24px;color:#1d2939;text-align:center;outline:none;padding:0;font-family:Inter,sans-serif;-moz-appearance:textfield}.time-input::-webkit-outer-spin-button,.time-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.time-arrows{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:20px;height:100%}.time-arrow-btn{display:flex;align-items:center;justify-content:center;width:14px;height:14px;padding:0;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;border-radius:2px;transition:.15s}.time-arrow-btn:hover{background:#6670851f}.time-arrow-btn zen-icon{width:14px;height:14px;background-color:#667085}.time-input-label{font-size:10px;font-weight:500;line-height:normal;color:#667085;text-transform:uppercase;letter-spacing:.02em}.time-colon{display:flex;flex-direction:column;align-items:center;justify-content:center;width:4px;height:44px;font-size:14px;font-weight:500;line-height:20px;color:#667085}.time-period-toggle{display:flex;gap:8px;align-items:center;height:44px;align-self:flex-start}.time-period-btn{display:flex;align-items:center;justify-content:center;padding:10px 14px;height:36px;box-sizing:border-box;border-radius:8px;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap;background:#fff;border:1px solid #D0D5DD;box-shadow:0 1px 2px #1018280d;color:#344054}.time-period-btn.active{background:#f1f7fe;border-color:#f1f7fe;color:#105494}.time-period-btn:hover:not(.active){background:#f9fafb}.bottom-divider{height:1px;min-height:1px;background:#eaecf0;width:100%;flex-shrink:0}.bottom-panel{display:flex;align-items:flex-start;justify-content:space-between;padding:16px 24px}.bottom-panel.compact{justify-content:flex-end}.marker-legend{display:flex;flex-wrap:wrap;gap:16px;align-items:center}.marker-legend.standalone{padding:12px 24px 16px}.marker-legend.standalone.single{padding-top:0}.marker-legend .legend-item{display:flex;align-items:center;gap:6px}.marker-legend .legend-dot{width:8px;height:8px;border-radius:50%;background:#105494}.marker-legend .legend-title{font-size:14px;font-weight:400;line-height:20px;color:#344054}.input-fields{display:flex;gap:12px;align-items:center}.input-fields .date-input{width:128px}.actions{display:flex;gap:12px}.actions.full-width,.actions.full-width .btn-cancel,.actions.full-width .btn-apply{flex:1}.btn-cancel{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-cancel:hover{background:#f9fafb}.btn-apply{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#136ab6;border:1px solid #136AB6;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#fff;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-apply:hover{background:#105494}.btn-apply:disabled{opacity:.5;cursor:not-allowed}\n"] }]
7953
+ args: [{ selector: 'zen-date-picker-dropdown', changeDetection: ChangeDetectionStrategy.Eager, standalone: false, template: "<div class=\"zen-dpd\">\n <!-- Trigger Button -->\n @if (!hideTrigger) {\n <button class=\"dropdown-trigger\"\n #triggerBtn\n [disabled]=\"disabled\"\n [class.active]=\"isOpen\"\n [class.has-value]=\"hasValue\"\n (click)=\"toggle()\">\n <zen-icon class=\"trigger-icon\"\n src=\"assets/ng-zenduit/icons/calendar.svg\">\n </zen-icon>\n <span class=\"trigger-label\">{{ triggerLabel }}</span>\n </button>\n }\n\n <!-- Dropdown Panel -->\n @if (isOpen) {\n <div class=\"dropdown-menu\" [class.mobile]=\"mobile\" [ngStyle]=\"dropdownStyle\">\n <!-- RANGE DESKTOP: presets sidebar + dual calendar -->\n @if (type === 'range' && !mobile) {\n <!-- Presets sidebar -->\n <div class=\"presets-sidebar\">\n @for (preset of activePresets; track preset) {\n <div class=\"preset-item\"\n [class.active]=\"_activePreset === preset.label\"\n (click)=\"selectPreset(preset)\">\n {{ preset.label | translate }}\n </div>\n }\n </div>\n <div class=\"sidebar-divider\"></div>\n <!-- Calendars + bottom panel -->\n <div class=\"calendars-container\">\n <div class=\"dual-calendars\">\n <!-- Left calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"leftPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"leftNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n </div>\n <div class=\"calendar-divider\"></div>\n <!-- Right calendar -->\n <div class=\"calendar-panel\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"rightPrevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ rightDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"rightNextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: rightDayRows }\"></ng-container>\n </div>\n </div>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n <div class=\"bottom-divider\"></div>\n <!-- Bottom panel: inputs (or legend) + actions -->\n <div class=\"bottom-panel\">\n @if (legendMarkers.length) {\n <div class=\"marker-legend\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n } @else {\n <div class=\"input-fields\">\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Start date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('End date' | translate) }}\n </span>\n </div>\n </div>\n }\n <div class=\"actions\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- RANGE MOBILE: single calendar with dual inputs on top -->\n @if (type === 'range' && mobile) {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Range inputs -->\n <div class=\"mobile-range-inputs\">\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedStart\">\n {{ _selectedStart ? formattedStartDate : ('Select date' | translate) }}\n </span>\n </div>\n <span class=\"date-separator\">&ndash;</span>\n <div class=\"date-input compact\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedEnd\">\n {{ _selectedEnd ? formattedEndDate : ('Select date' | translate) }}\n </span>\n </div>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n </div>\n }\n <!-- SINGLE DATE: single calendar + input + today button -->\n @if (type === 'single') {\n <div class=\"single-calendar-container\">\n <div class=\"calendar-content\">\n <div class=\"month-header\">\n <button class=\"nav-btn\" (click)=\"prevMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-left.svg\"></zen-icon>\n </button>\n <span class=\"month-title\">{{ leftDaysTitle }}</span>\n <button class=\"nav-btn\" (click)=\"nextMonth()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-right.svg\"></zen-icon>\n </button>\n </div>\n <!-- Date input + Today button -->\n <div class=\"single-actions-row\">\n <div class=\"date-input flex-1\">\n <span class=\"date-input-text\" [class.placeholder]=\"!_selectedDate\">\n {{ _selectedDate ? formattedSelectedDate : ('Select date' | translate) }}\n </span>\n </div>\n <button class=\"btn-today\" (click)=\"goToToday()\">{{ 'Today' | translate }}</button>\n </div>\n <ng-container *ngTemplateOutlet=\"calendarGrid; context: { $implicit: leftDayRows }\"></ng-container>\n </div>\n <!-- Time Picker -->\n @if (timePicker) {\n <div class=\"bottom-divider\"></div>\n <ng-container *ngTemplateOutlet=\"timePickerSection\"></ng-container>\n }\n @if (legendMarkers.length) {\n <div class=\"marker-legend standalone single\">\n @for (m of legendMarkers; track m) {\n <div class=\"legend-item\">\n <span class=\"legend-dot\" [style.background]=\"m.color || null\"></span>\n <span class=\"legend-title\">{{ m.title | translate }}</span>\n </div>\n }\n </div>\n }\n @if (!autoApply) {\n <div class=\"bottom-divider\"></div>\n <div class=\"bottom-panel compact\">\n <div class=\"actions full-width\">\n <button class=\"btn-cancel\" (click)=\"cancel()\">{{ 'Cancel' | translate }}</button>\n <button class=\"btn-apply\" [disabled]=\"!canApply\" (click)=\"apply()\">{{ 'Apply' | translate }}</button>\n </div>\n </div>\n }\n </div>\n }\n </div>\n }\n</div>\n\n<!-- Shared time picker template -->\n<ng-template #timePickerSection>\n <div class=\"time-picker-container\">\n <div class=\"time-picker-content\">\n <span class=\"time-picker-label\">{{ 'Select a time' | translate }}</span>\n <div class=\"time-picker-row\">\n <div class=\"time-fields\">\n <!-- Hours -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Hours\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_hoursDisplay\"\n (input)=\"onHoursInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampHours()\"\n (keydown)=\"onTimeKeydown($event, 'hours')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementHours()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'HRS' | translate }}</span>\n </div>\n\n <!-- Colon separator -->\n <div class=\"time-colon\">:</div>\n\n <!-- Minutes -->\n <div class=\"time-input-group\">\n <div class=\"time-input-box\">\n <input class=\"time-input\"\n type=\"text\"\n aria-label=\"Minutes\"\n inputmode=\"numeric\"\n autocomplete=\"off\"\n [value]=\"_minutesDisplay\"\n (input)=\"onMinutesInput($event)\"\n (focus)=\"onTimeFocus($event)\"\n (blur)=\"clampMinutes()\"\n (keydown)=\"onTimeKeydown($event, 'minutes')\"\n maxlength=\"2\" />\n <div class=\"time-arrows\">\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"incrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-up-small.svg\"></zen-icon>\n </button>\n <button class=\"time-arrow-btn\" type=\"button\" tabindex=\"-1\" (click)=\"decrementMinutes()\">\n <zen-icon src=\"assets/ng-zenduit/icons/arrow-down-small.svg\"></zen-icon>\n </button>\n </div>\n </div>\n <span class=\"time-input-label\">{{ 'MIN' | translate }}</span>\n </div>\n </div>\n\n <!-- AM/PM toggle -->\n <div class=\"time-period-toggle\">\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'AM'\"\n (click)=\"setPeriod('AM')\">\n AM\n </button>\n <button class=\"time-period-btn\"\n [class.active]=\"_period === 'PM'\"\n (click)=\"setPeriod('PM')\">\n PM\n </button>\n </div>\n </div>\n </div>\n </div>\n</ng-template>\n\n<!-- Shared calendar grid template -->\n<ng-template #calendarGrid let-dayRows>\n <div class=\"dates-grid\">\n <!-- Week day headers -->\n <div class=\"week-header\">\n @for (wd of weekDays; track wd) {\n <div class=\"cell header-cell\">{{ wd | translate }}</div>\n }\n </div>\n <!-- Day rows -->\n @for (row of dayRows; track row) {\n <div class=\"day-row\">\n @for (day of row.days; track day) {\n <div class=\"cell day-cell\"\n [class.outside]=\"day.isOutside\"\n [class.selected]=\"day.selected\"\n [class.today]=\"isToday(day)\"\n [class.disabled]=\"day.isDisabled\"\n [class.in-range]=\"isInRange(day)\"\n [class.range-start]=\"isRangeStart(day)\"\n [class.range-end]=\"isRangeEnd(day)\"\n (click)=\"selectDay(day)\">\n <span class=\"day-number\">{{ day.lbl }}</span>\n @if (day.markerColors?.length) {\n <div class=\"marker-dots\">\n @for (c of day.markerColors; track c) {\n <span class=\"marker-dot\"\n [style.background]=\"c || null\"></span>\n }\n </div>\n }\n </div>\n }\n </div>\n }\n </div>\n</ng-template>\n", styles: [":host{display:block;position:relative;width:100%}.zen-dpd{position:relative;width:100%}.dropdown-trigger{display:flex;width:100%;align-items:center;justify-content:center;gap:8px;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;cursor:pointer;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#667085;white-space:nowrap;transition:.2s;appearance:none;outline:none}.dropdown-trigger:hover{border-color:#98a2b3}.dropdown-trigger.active{box-shadow:0 1px 2px #1018280d,0 0 0 4px #f2f4f7}.dropdown-trigger.has-value{color:#344054}.dropdown-trigger:disabled{cursor:not-allowed;opacity:.5}.dropdown-trigger .trigger-icon{width:20px;height:20px;background-color:#667085}.dropdown-trigger.has-value .trigger-icon{background-color:#344054}.dropdown-menu{position:fixed;z-index:1200;display:inline-flex;background:#fff;border:1px solid #EAECF0;border-radius:8px;box-shadow:0 20px 24px -4px #10182814,0 8px 8px -4px #10182808;font-family:Inter,sans-serif;overflow-y:auto;overflow-x:hidden;width:max-content}.presets-sidebar{display:flex;flex-direction:column;gap:4px;padding:12px 16px;min-width:160px}.presets-sidebar .preset-item{padding:10px 16px;border-radius:6px;font-size:14px;font-weight:400;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;transition:.15s}.presets-sidebar .preset-item:hover{background:#f1f7fe;color:#105494}.presets-sidebar .preset-item.active{background:#f1f7fe;color:#105494;font-weight:500}.sidebar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendars-container{display:flex;flex-direction:column}.dual-calendars{display:flex}.calendar-divider{width:1px;background:#eaecf0;align-self:stretch}.calendar-panel{width:328px;overflow:hidden}.calendar-content{display:flex;flex-direction:column;padding:20px 24px;gap:12px}.single-calendar-container{display:flex;flex-direction:column;width:328px}.month-header{display:flex;align-items:center;justify-content:space-between;width:280px}.nav-btn{display:flex;align-items:center;justify-content:center;padding:10px;border-radius:8px;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;transition:.15s}.nav-btn:hover{background:#f9fafb}.nav-btn zen-icon{width:20px;height:20px;background-color:#344054}.month-title{font-size:16px;font-weight:500;line-height:24px;color:#344054;text-align:center}.single-actions-row{display:flex;gap:12px;align-items:flex-start;width:280px}.flex-1{flex:1}.btn-today{display:flex;align-items:center;justify-content:center;padding:10px 16px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;white-space:nowrap;appearance:none;outline:none;transition:.15s}.btn-today:hover{background:#f9fafb}.mobile-range-inputs{display:flex;align-items:center;gap:8px;height:40px;width:280px}.date-input{display:flex;align-items:center;padding:8px 14px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;min-width:0}.date-input.compact{flex:1}.date-input .date-input-text{font-size:16px;font-weight:400;line-height:24px;color:#101828;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.date-input .date-input-text.placeholder{color:#667085}.date-separator{font-size:16px;font-weight:400;line-height:24px;color:#667085}.dates-grid{display:flex;flex-direction:column;gap:4px}.week-header{display:flex;width:280px}.day-row{display:flex;border-radius:20px;overflow:hidden}.cell{position:relative;width:40px;height:40px;display:flex;align-items:center;justify-content:center;border-radius:20px}.cell .day-number{font-size:14px;font-weight:400;line-height:20px;text-align:center;color:#344054;width:24px}.cell.header-cell .day-number{font-weight:500}.header-cell{font-size:14px;font-weight:500;line-height:20px;color:#344054}.day-cell{cursor:pointer;transition:.1s}.day-cell:hover:not(.disabled):not(.selected){background:#f1f7fe}.day-cell:hover:not(.disabled):not(.selected) .day-number{color:#105494;font-weight:500}.day-cell.outside{cursor:default;pointer-events:none}.day-cell.today{background:#f2f4f7}.day-cell.today .day-number{font-weight:500}.day-cell.selected{background:#136ab6}.day-cell.selected .day-number{color:#fff;font-weight:500}.day-cell.in-range{background:#f1f7fe;border-radius:0}.day-cell.in-range .day-number{color:#105494}.day-cell.range-start{border-radius:20px 0 0 20px}.day-cell.range-end{border-radius:0 20px 20px 0}.day-cell.range-start.range-end{border-radius:20px}.day-cell.disabled{cursor:not-allowed}.day-cell.disabled .day-number{color:#d0d5dd}.day-cell .marker-dots{position:absolute;bottom:4px;left:50%;transform:translate(-50%);display:flex;gap:3px}.day-cell .marker-dots .marker-dot{width:5px;height:5px;border-radius:50%;background:#105494}.day-cell.outside .marker-dots .marker-dot{opacity:.4}.day-cell.selected .marker-dots .marker-dot{background:#fff!important}.time-picker-container{display:flex;flex-direction:column;padding:16px;background:#fff;width:100%}.time-picker-content{display:flex;flex-direction:column;gap:16px}.time-picker-label{font-size:14px;font-weight:500;line-height:20px;color:#1d2939}.time-picker-row{display:flex;align-items:flex-start;gap:16px}.time-fields{display:flex;gap:8px;align-items:flex-start}.time-input-group{display:flex;flex-direction:column;align-items:center;gap:4px}.time-input-box{display:flex;align-items:center;justify-content:center;gap:6px;height:44px;min-width:72px;padding:6px 6px 6px 12px;background:#f2f4f7;border:1px solid #E5E7EB;border-radius:8px;box-sizing:border-box}.time-input{width:24px;border:none;background:transparent;font-size:16px;font-weight:500;line-height:24px;color:#1d2939;text-align:center;outline:none;padding:0;font-family:Inter,sans-serif;-moz-appearance:textfield}.time-input::-webkit-outer-spin-button,.time-input::-webkit-inner-spin-button{-webkit-appearance:none;margin:0}.time-arrows{display:flex;flex-direction:column;align-items:center;justify-content:center;gap:4px;width:20px;height:100%}.time-arrow-btn{display:flex;align-items:center;justify-content:center;width:14px;height:14px;padding:0;border:none;background:transparent;cursor:pointer;appearance:none;outline:none;border-radius:2px;transition:.15s}.time-arrow-btn:hover{background:#6670851f}.time-arrow-btn zen-icon{width:14px;height:14px;background-color:#667085}.time-input-label{font-size:10px;font-weight:500;line-height:normal;color:#667085;text-transform:uppercase;letter-spacing:.02em}.time-colon{display:flex;flex-direction:column;align-items:center;justify-content:center;width:4px;height:44px;font-size:14px;font-weight:500;line-height:20px;color:#667085}.time-period-toggle{display:flex;gap:8px;align-items:center;height:44px;align-self:flex-start}.time-period-btn{display:flex;align-items:center;justify-content:center;padding:10px 14px;height:36px;box-sizing:border-box;border-radius:8px;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap;background:#fff;border:1px solid #D0D5DD;box-shadow:0 1px 2px #1018280d;color:#344054}.time-period-btn.active{background:#f1f7fe;border-color:#f1f7fe;color:#105494}.time-period-btn:hover:not(.active){background:#f9fafb}.bottom-divider{height:1px;min-height:1px;background:#eaecf0;width:100%;flex-shrink:0}.bottom-panel{display:flex;align-items:flex-start;justify-content:space-between;padding:16px 24px}.bottom-panel.compact{justify-content:flex-end}.marker-legend{display:flex;flex-wrap:wrap;gap:16px;align-items:center}.marker-legend.standalone{padding:12px 24px 16px}.marker-legend.standalone.single{padding-top:0}.marker-legend .legend-item{display:flex;align-items:center;gap:6px}.marker-legend .legend-dot{width:8px;height:8px;border-radius:50%;background:#105494}.marker-legend .legend-title{font-size:14px;font-weight:400;line-height:20px;color:#344054}.input-fields{display:flex;gap:12px;align-items:center}.input-fields .date-input{width:auto;min-width:128px}.actions{display:flex;gap:12px}.actions.full-width,.actions.full-width .btn-cancel,.actions.full-width .btn-apply{flex:1}.btn-cancel{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#fff;border:1px solid #D0D5DD;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#344054;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-cancel:hover{background:#f9fafb}.btn-apply{display:flex;align-items:center;justify-content:center;padding:10px 16px;min-width:109px;background:#136ab6;border:1px solid #136AB6;border-radius:8px;box-shadow:0 1px 2px #1018280d;font-family:Inter,sans-serif;font-size:14px;font-weight:500;line-height:20px;color:#fff;cursor:pointer;appearance:none;outline:none;transition:.15s;white-space:nowrap}.btn-apply:hover{background:#105494}.btn-apply:disabled{opacity:.5;cursor:not-allowed}\n"] }]
7940
7954
  }], ctorParameters: () => [{ type: i0.ElementRef }, { type: i2.TranslateService }, { type: undefined, decorators: [{
7941
7955
  type: Optional
7942
7956
  }, {
@@ -7976,6 +7990,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "22.0.0", ngImpor
7976
7990
  type: Input
7977
7991
  }], autoApply: [{
7978
7992
  type: Input
7993
+ }], hideTrigger: [{
7994
+ type: Input
7979
7995
  }], triggerBtn: [{
7980
7996
  type: ViewChild,
7981
7997
  args: ['triggerBtn']