pdm-ui-kit 0.1.46 → 0.1.48

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.
@@ -6,8 +6,8 @@ import * as i1$2 from '@angular/cdk/overlay';
6
6
  import { OverlayModule } from '@angular/cdk/overlay';
7
7
  import { icons } from 'lucide';
8
8
  import * as i1$1 from '@angular/platform-browser';
9
- import { format } from 'date-fns';
10
9
  import { TemplatePortal } from '@angular/cdk/portal';
10
+ import { format } from 'date-fns';
11
11
 
12
12
  class PdmAccordionComponent {
13
13
  constructor() {
@@ -1932,6 +1932,60 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1932
1932
  type: Output
1933
1933
  }] } });
1934
1934
 
1935
+ /**
1936
+ * Creates a flexible position strategy that automatically adjusts
1937
+ * to keep the overlay within the viewport edges.
1938
+ *
1939
+ * The strategy tries positions in this order:
1940
+ * 1. Bottom-left (origin bottom edge, aligns to left)
1941
+ * 2. Top-left (origin top edge, aligns to left)
1942
+ * 3. Bottom-right (origin bottom edge, aligns to right)
1943
+ * 4. Top-right (origin top edge, aligns to right)
1944
+ *
1945
+ * CDK Overlay will use the first position that fits within the viewport.
1946
+ */
1947
+ function createFlexiblePositionStrategy(overlay, triggerElement, offset = 4) {
1948
+ return overlay
1949
+ .position()
1950
+ .flexibleConnectedTo(triggerElement)
1951
+ .withPositions([
1952
+ // Bottom-left (default) - opens downward from left edge
1953
+ {
1954
+ originX: 'start',
1955
+ originY: 'bottom',
1956
+ overlayX: 'start',
1957
+ overlayY: 'top',
1958
+ offsetY: offset
1959
+ },
1960
+ // Top-left - opens upward from left edge
1961
+ {
1962
+ originX: 'start',
1963
+ originY: 'top',
1964
+ overlayX: 'start',
1965
+ overlayY: 'bottom',
1966
+ offsetY: -offset
1967
+ },
1968
+ // Bottom-right - opens downward from right edge
1969
+ {
1970
+ originX: 'end',
1971
+ originY: 'bottom',
1972
+ overlayX: 'end',
1973
+ overlayY: 'top',
1974
+ offsetY: offset
1975
+ },
1976
+ // Top-right - opens upward from right edge
1977
+ {
1978
+ originX: 'end',
1979
+ originY: 'top',
1980
+ overlayX: 'end',
1981
+ overlayY: 'bottom',
1982
+ offsetY: -offset
1983
+ }
1984
+ ])
1985
+ .withFlexibleDimensions(false)
1986
+ .withPush(true);
1987
+ }
1988
+
1935
1989
  class PdmLabelComponent {
1936
1990
  constructor() {
1937
1991
  this.forId = '';
@@ -1954,21 +2008,29 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
1954
2008
 
1955
2009
  let nextDatePickerId = 0;
1956
2010
  class PdmDatePickerComponent {
1957
- constructor(elementRef, cdr) {
2011
+ constructor(elementRef, cdr, overlay, viewContainerRef) {
1958
2012
  this.elementRef = elementRef;
1959
2013
  this.cdr = cdr;
2014
+ this.overlay = overlay;
2015
+ this.viewContainerRef = viewContainerRef;
1960
2016
  this._value = null;
1961
2017
  this._rangeValue = null;
1962
2018
  this._open = false;
1963
2019
  this.instanceId = `pdm-date-picker-${++nextDatePickerId}`;
1964
2020
  this.triggerFocused = false;
1965
- this.panelPlacement = 'bottom';
2021
+ this.overlayRef = null;
2022
+ this.backdropSub = null;
1966
2023
  this.id = '';
1967
2024
  this.variant = 'single';
1968
2025
  this.label = '';
1969
2026
  this.labelClassName = '';
1970
2027
  this.className = '';
1971
2028
  this.triggerClassName = '';
2029
+ /**
2030
+ * Additional CSS classes applied to the overlay panel.
2031
+ * Backward-compatible: mapped to `overlayOptions.panelClass` when `overlayOptions` is not set.
2032
+ * When both are supplied, `overlayOptions.panelClass` takes precedence.
2033
+ */
1972
2034
  this.panelClassName = '';
1973
2035
  this.placeholder = 'Pick a date';
1974
2036
  this.rangePlaceholder = 'Pick a date range';
@@ -1991,14 +2053,14 @@ class PdmDatePickerComponent {
1991
2053
  this.monthChange = new EventEmitter();
1992
2054
  }
1993
2055
  set open(value) {
1994
- this._open = !!value;
1995
- if (this._open) {
1996
- this.schedulePanelPlacementUpdate();
2056
+ if (this._open === !!value)
2057
+ return;
2058
+ if (!!value) {
2059
+ this.openPanel();
1997
2060
  }
1998
2061
  else {
1999
- this.panelPlacement = 'bottom';
2062
+ this.closePanel();
2000
2063
  }
2001
- this.cdr.markForCheck();
2002
2064
  }
2003
2065
  get open() {
2004
2066
  return this._open;
@@ -2022,6 +2084,9 @@ class PdmDatePickerComponent {
2022
2084
  get rangeValue() {
2023
2085
  return this._rangeValue;
2024
2086
  }
2087
+ ngOnDestroy() {
2088
+ this.destroyOverlay();
2089
+ }
2025
2090
  get resolvedVariant() {
2026
2091
  return this.variant === 'range' ? 'range' : 'single';
2027
2092
  }
@@ -2066,7 +2131,7 @@ class PdmDatePickerComponent {
2066
2131
  ];
2067
2132
  }
2068
2133
  get triggerClasses() {
2069
- const focusStyle = this.open || this.triggerFocused;
2134
+ const focusStyle = this._open || this.triggerFocused;
2070
2135
  return [
2071
2136
  'border-input focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 aria-invalid:ring-2 aria-invalid:ring-destructive aria-invalid:border-destructive relative flex w-full appearance-none items-center gap-2 overflow-hidden rounded-lg border bg-background px-3 py-[7.5px] text-left text-sm shadow-sm outline-none transition-colors',
2072
2137
  'min-h-[36px] disabled:pointer-events-none disabled:cursor-not-allowed disabled:opacity-50',
@@ -2077,19 +2142,11 @@ class PdmDatePickerComponent {
2077
2142
  this.triggerClassName
2078
2143
  ];
2079
2144
  }
2080
- get panelClasses() {
2081
- return [
2082
- this.panelPlacement === 'top'
2083
- ? 'absolute bottom-full left-0 z-50 mb-2'
2084
- : 'absolute left-0 top-full z-50 mt-2',
2085
- this.panelClassName
2086
- ];
2087
- }
2088
2145
  toggleOpen() {
2089
2146
  if (this.disabled || this.readonly) {
2090
2147
  return;
2091
2148
  }
2092
- this.setOpen(!this.open);
2149
+ this.setOpen(!this._open);
2093
2150
  }
2094
2151
  onTriggerFocus() {
2095
2152
  this.triggerFocused = true;
@@ -2132,58 +2189,68 @@ class PdmDatePickerComponent {
2132
2189
  this.monthChange.emit(this.cloneDate(month));
2133
2190
  }
2134
2191
  onEscape() {
2135
- if (this.open) {
2136
- this.setOpen(false);
2137
- }
2138
- }
2139
- onDocumentClick(event) {
2140
- if (!this.open) {
2141
- return;
2142
- }
2143
- const target = event.target;
2144
- if (target && !this.elementRef.nativeElement.contains(target)) {
2192
+ if (this._open) {
2145
2193
  this.setOpen(false);
2146
2194
  }
2147
2195
  }
2148
- onViewportChange() {
2149
- this.updatePanelPlacement();
2150
- }
2151
2196
  setOpen(nextOpen) {
2152
2197
  if (this._open === nextOpen) {
2153
2198
  return;
2154
2199
  }
2155
- this._open = nextOpen;
2156
- this.openChange.emit(this._open);
2157
- if (this._open) {
2158
- this.schedulePanelPlacementUpdate();
2200
+ if (nextOpen) {
2201
+ this.openPanel();
2159
2202
  }
2160
2203
  else {
2161
- this.panelPlacement = 'bottom';
2204
+ this.closePanel();
2162
2205
  }
2163
- this.cdr.markForCheck();
2164
2206
  }
2165
- schedulePanelPlacementUpdate() {
2166
- setTimeout(() => this.updatePanelPlacement());
2167
- }
2168
- updatePanelPlacement() {
2169
- if (!this._open) {
2207
+ openPanel() {
2208
+ if (this.overlayRef)
2170
2209
  return;
2171
- }
2172
2210
  const triggerEl = this.triggerRef?.nativeElement;
2173
- const panelEl = this.panelRef?.nativeElement;
2174
- if (!triggerEl || !panelEl || typeof window === 'undefined') {
2211
+ if (!triggerEl)
2175
2212
  return;
2213
+ this._open = true;
2214
+ this.openChange.emit(true);
2215
+ this.cdr.markForCheck();
2216
+ const positionStrategy = createFlexiblePositionStrategy(this.overlay, triggerEl, 8);
2217
+ // Resolve panelClass: overlayOptions.panelClass wins; otherwise map panelClassName.
2218
+ const resolvedPanelClass = this.overlayOptions?.panelClass
2219
+ ?? (this.panelClassName ? ['block', this.panelClassName] : ['block']);
2220
+ this.overlayRef = this.overlay.create({
2221
+ positionStrategy,
2222
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
2223
+ // Consumer overrides are spread last — they win over every default above.
2224
+ ...this.overlayOptions,
2225
+ // panelClass always overrides last: it already merges panelClassName + overlayOptions.
2226
+ panelClass: resolvedPanelClass
2227
+ });
2228
+ const portal = new TemplatePortal(this.panelTemplateRef, this.viewContainerRef);
2229
+ this.overlayRef.attach(portal);
2230
+ this.backdropSub = this.overlayRef.outsidePointerEvents().subscribe((event) => {
2231
+ const target = event.target;
2232
+ if (!triggerEl.contains(target)) {
2233
+ this.closePanel();
2234
+ }
2235
+ });
2236
+ this.cdr.markForCheck();
2237
+ }
2238
+ closePanel() {
2239
+ if (!this.overlayRef && !this._open)
2240
+ return;
2241
+ this._open = false;
2242
+ this.openChange.emit(false);
2243
+ this.destroyOverlay();
2244
+ this.cdr.markForCheck();
2245
+ }
2246
+ destroyOverlay() {
2247
+ if (this.backdropSub) {
2248
+ this.backdropSub.unsubscribe();
2249
+ this.backdropSub = null;
2176
2250
  }
2177
- const viewportHeight = window.innerHeight;
2178
- const gap = 8;
2179
- const triggerRect = triggerEl.getBoundingClientRect();
2180
- const panelHeight = panelEl.offsetHeight;
2181
- const spaceBelow = Math.max(0, viewportHeight - triggerRect.bottom - gap);
2182
- const spaceAbove = Math.max(0, triggerRect.top - gap);
2183
- const nextPlacement = spaceBelow < panelHeight && spaceAbove > spaceBelow ? 'top' : 'bottom';
2184
- if (this.panelPlacement !== nextPlacement) {
2185
- this.panelPlacement = nextPlacement;
2186
- this.cdr.markForCheck();
2251
+ if (this.overlayRef) {
2252
+ this.overlayRef.dispose();
2253
+ this.overlayRef = null;
2187
2254
  }
2188
2255
  }
2189
2256
  formatDate(date) {
@@ -2204,17 +2271,17 @@ class PdmDatePickerComponent {
2204
2271
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
2205
2272
  }
2206
2273
  }
2207
- PdmDatePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDatePickerComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }], target: i0.ɵɵFactoryTarget.Component });
2208
- PdmDatePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDatePickerComponent, selector: "pdm-date-picker", inputs: { id: "id", variant: "variant", label: "label", labelClassName: "labelClassName", className: "className", triggerClassName: "triggerClassName", panelClassName: "panelClassName", placeholder: "placeholder", rangePlaceholder: "rangePlaceholder", format: "format", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", allowSameDayRange: "allowSameDayRange", closeOnSelect: "closeOnSelect", minDate: "minDate", maxDate: "maxDate", minYear: "minYear", maxYear: "maxYear", disabledDates: "disabledDates", isDateDisabled: "isDateDisabled", open: "open", value: "value", rangeValue: "rangeValue" }, outputs: { valueChange: "valueChange", rangeValueChange: "rangeValueChange", openChange: "openChange", monthChange: "monthChange" }, host: { listeners: { "document:keydown.escape": "onEscape()", "document:click": "onDocumentClick($event)", "window:resize": "onViewportChange()", "window:scroll": "onViewportChange()" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true }, { propertyName: "panelRef", first: true, predicate: ["panelEl"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"rootClasses\">\n <pdm-label *ngIf=\"label\" [forId]=\"triggerId\" [required]=\"required\" [className]=\"labelClassName\">\n {{ label }}\n </pdm-label>\n\n <div class=\"relative inline-block w-full\">\n <button\n #triggerEl\n type=\"button\"\n [id]=\"triggerId\"\n [disabled]=\"disabled\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"invalid\"\n [ngClass]=\"triggerClasses\"\n [attr.title]=\"displayText\"\n (click)=\"toggleOpen()\"\n (focus)=\"onTriggerFocus()\"\n (blur)=\"onTriggerBlur()\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center p-0.5 text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\">\n <path d=\"M8 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M16 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"16.5\" rx=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></rect>\n <path d=\"M3 9.5h18\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </span>\n\n <span [ngClass]=\"textClasses\">{{ displayText }}</span>\n </button>\n\n <div *ngIf=\"open\" #panelEl [id]=\"panelId\" [ngClass]=\"panelClasses\" role=\"dialog\" [attr.aria-labelledby]=\"label ? triggerId : null\">\n <pdm-calendar\n [variant]=\"resolvedVariant\"\n [value]=\"value\"\n [rangeValue]=\"rangeValue\"\n [readonly]=\"readonly\"\n [allowSameDayRange]=\"allowSameDayRange\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [minYear]=\"minYear\"\n [maxYear]=\"maxYear\"\n [disabledDates]=\"disabledDates\"\n [isDateDisabled]=\"isDateDisabled\"\n (valueChange)=\"onCalendarValueChange($event)\"\n (rangeValueChange)=\"onCalendarRangeValueChange($event)\"\n (monthChange)=\"onCalendarMonthChange($event)\"\n ></pdm-calendar>\n </div>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: ["variant", "className", "disabledDates", "minDate", "maxDate", "minYear", "maxYear", "isDateDisabled", "allowSameDayRange", "readonly", "value", "rangeValue", "month"], outputs: ["valueChange", "rangeValueChange", "monthChange", "dateClick", "disabledDateClick"] }, { kind: "component", type: PdmLabelComponent, selector: "pdm-label", inputs: ["forId", "required", "className"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2274
+ PdmDatePickerComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDatePickerComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1$2.Overlay }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
2275
+ PdmDatePickerComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDatePickerComponent, selector: "pdm-date-picker", inputs: { id: "id", variant: "variant", label: "label", labelClassName: "labelClassName", className: "className", triggerClassName: "triggerClassName", panelClassName: "panelClassName", overlayOptions: "overlayOptions", placeholder: "placeholder", rangePlaceholder: "rangePlaceholder", format: "format", disabled: "disabled", readonly: "readonly", required: "required", invalid: "invalid", allowSameDayRange: "allowSameDayRange", closeOnSelect: "closeOnSelect", minDate: "minDate", maxDate: "maxDate", minYear: "minYear", maxYear: "maxYear", disabledDates: "disabledDates", isDateDisabled: "isDateDisabled", open: "open", value: "value", rangeValue: "rangeValue" }, outputs: { valueChange: "valueChange", rangeValueChange: "rangeValueChange", openChange: "openChange", monthChange: "monthChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"rootClasses\">\n <pdm-label *ngIf=\"label\" [forId]=\"triggerId\" [required]=\"required\" [className]=\"labelClassName\">\n {{ label }}\n </pdm-label>\n\n <button\n #triggerEl\n type=\"button\"\n [id]=\"triggerId\"\n [disabled]=\"disabled\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"invalid\"\n [ngClass]=\"triggerClasses\"\n [attr.title]=\"displayText\"\n (click)=\"toggleOpen()\"\n (focus)=\"onTriggerFocus()\"\n (blur)=\"onTriggerBlur()\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center p-0.5 text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\">\n <path d=\"M8 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M16 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"16.5\" rx=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></rect>\n <path d=\"M3 9.5h18\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </span>\n\n <span [ngClass]=\"textClasses\">{{ displayText }}</span>\n </button>\n</div>\n\n<ng-template #panelTemplate>\n <div [id]=\"panelId\" role=\"dialog\" [attr.aria-labelledby]=\"label ? triggerId : null\">\n <pdm-calendar\n [variant]=\"resolvedVariant\"\n [value]=\"value\"\n [rangeValue]=\"rangeValue\"\n [readonly]=\"readonly\"\n [allowSameDayRange]=\"allowSameDayRange\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [minYear]=\"minYear\"\n [maxYear]=\"maxYear\"\n [disabledDates]=\"disabledDates\"\n [isDateDisabled]=\"isDateDisabled\"\n (valueChange)=\"onCalendarValueChange($event)\"\n (rangeValueChange)=\"onCalendarRangeValueChange($event)\"\n (monthChange)=\"onCalendarMonthChange($event)\"\n ></pdm-calendar>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmCalendarComponent, selector: "pdm-calendar", inputs: ["variant", "className", "disabledDates", "minDate", "maxDate", "minYear", "maxYear", "isDateDisabled", "allowSameDayRange", "readonly", "value", "rangeValue", "month"], outputs: ["valueChange", "rangeValueChange", "monthChange", "dateClick", "disabledDateClick"] }, { kind: "component", type: PdmLabelComponent, selector: "pdm-label", inputs: ["forId", "required", "className"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2209
2276
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDatePickerComponent, decorators: [{
2210
2277
  type: Component,
2211
- args: [{ selector: 'pdm-date-picker', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"rootClasses\">\n <pdm-label *ngIf=\"label\" [forId]=\"triggerId\" [required]=\"required\" [className]=\"labelClassName\">\n {{ label }}\n </pdm-label>\n\n <div class=\"relative inline-block w-full\">\n <button\n #triggerEl\n type=\"button\"\n [id]=\"triggerId\"\n [disabled]=\"disabled\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"invalid\"\n [ngClass]=\"triggerClasses\"\n [attr.title]=\"displayText\"\n (click)=\"toggleOpen()\"\n (focus)=\"onTriggerFocus()\"\n (blur)=\"onTriggerBlur()\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center p-0.5 text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\">\n <path d=\"M8 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M16 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"16.5\" rx=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></rect>\n <path d=\"M3 9.5h18\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </span>\n\n <span [ngClass]=\"textClasses\">{{ displayText }}</span>\n </button>\n\n <div *ngIf=\"open\" #panelEl [id]=\"panelId\" [ngClass]=\"panelClasses\" role=\"dialog\" [attr.aria-labelledby]=\"label ? triggerId : null\">\n <pdm-calendar\n [variant]=\"resolvedVariant\"\n [value]=\"value\"\n [rangeValue]=\"rangeValue\"\n [readonly]=\"readonly\"\n [allowSameDayRange]=\"allowSameDayRange\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [minYear]=\"minYear\"\n [maxYear]=\"maxYear\"\n [disabledDates]=\"disabledDates\"\n [isDateDisabled]=\"isDateDisabled\"\n (valueChange)=\"onCalendarValueChange($event)\"\n (rangeValueChange)=\"onCalendarRangeValueChange($event)\"\n (monthChange)=\"onCalendarMonthChange($event)\"\n ></pdm-calendar>\n </div>\n </div>\n</div>\n" }]
2212
- }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }]; }, propDecorators: { triggerRef: [{
2278
+ args: [{ selector: 'pdm-date-picker', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"rootClasses\">\n <pdm-label *ngIf=\"label\" [forId]=\"triggerId\" [required]=\"required\" [className]=\"labelClassName\">\n {{ label }}\n </pdm-label>\n\n <button\n #triggerEl\n type=\"button\"\n [id]=\"triggerId\"\n [disabled]=\"disabled\"\n [attr.aria-expanded]=\"open\"\n [attr.aria-controls]=\"panelId\"\n [attr.aria-haspopup]=\"'dialog'\"\n [attr.aria-invalid]=\"invalid\"\n [ngClass]=\"triggerClasses\"\n [attr.title]=\"displayText\"\n (click)=\"toggleOpen()\"\n (focus)=\"onTriggerFocus()\"\n (blur)=\"onTriggerBlur()\"\n >\n <span class=\"flex h-5 w-5 shrink-0 items-center justify-center p-0.5 text-muted-foreground\" aria-hidden=\"true\">\n <svg viewBox=\"0 0 24 24\" class=\"h-4 w-4\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.8\">\n <path d=\"M8 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <path d=\"M16 2v4\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n <rect x=\"3\" y=\"4.5\" width=\"18\" height=\"16.5\" rx=\"2\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></rect>\n <path d=\"M3 9.5h18\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n </span>\n\n <span [ngClass]=\"textClasses\">{{ displayText }}</span>\n </button>\n</div>\n\n<ng-template #panelTemplate>\n <div [id]=\"panelId\" role=\"dialog\" [attr.aria-labelledby]=\"label ? triggerId : null\">\n <pdm-calendar\n [variant]=\"resolvedVariant\"\n [value]=\"value\"\n [rangeValue]=\"rangeValue\"\n [readonly]=\"readonly\"\n [allowSameDayRange]=\"allowSameDayRange\"\n [minDate]=\"minDate\"\n [maxDate]=\"maxDate\"\n [minYear]=\"minYear\"\n [maxYear]=\"maxYear\"\n [disabledDates]=\"disabledDates\"\n [isDateDisabled]=\"isDateDisabled\"\n (valueChange)=\"onCalendarValueChange($event)\"\n (rangeValueChange)=\"onCalendarRangeValueChange($event)\"\n (monthChange)=\"onCalendarMonthChange($event)\"\n ></pdm-calendar>\n </div>\n</ng-template>\n" }]
2279
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1$2.Overlay }, { type: i0.ViewContainerRef }]; }, propDecorators: { triggerRef: [{
2213
2280
  type: ViewChild,
2214
2281
  args: ['triggerEl']
2215
- }], panelRef: [{
2282
+ }], panelTemplateRef: [{
2216
2283
  type: ViewChild,
2217
- args: ['panelEl']
2284
+ args: ['panelTemplate']
2218
2285
  }], id: [{
2219
2286
  type: Input
2220
2287
  }], variant: [{
@@ -2229,6 +2296,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2229
2296
  type: Input
2230
2297
  }], panelClassName: [{
2231
2298
  type: Input
2299
+ }], overlayOptions: [{
2300
+ type: Input
2232
2301
  }], placeholder: [{
2233
2302
  type: Input
2234
2303
  }], rangePlaceholder: [{
@@ -2276,15 +2345,6 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2276
2345
  }], onEscape: [{
2277
2346
  type: HostListener,
2278
2347
  args: ['document:keydown.escape']
2279
- }], onDocumentClick: [{
2280
- type: HostListener,
2281
- args: ['document:click', ['$event']]
2282
- }], onViewportChange: [{
2283
- type: HostListener,
2284
- args: ['window:resize']
2285
- }, {
2286
- type: HostListener,
2287
- args: ['window:scroll']
2288
2348
  }] } });
2289
2349
 
2290
2350
  class PdmDialogComponent {
@@ -2417,20 +2477,42 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2417
2477
  }] } });
2418
2478
 
2419
2479
  class PdmDropdownMenuComponent {
2420
- constructor(elementRef) {
2480
+ constructor(elementRef, cdr, overlay, viewContainerRef) {
2421
2481
  this.elementRef = elementRef;
2482
+ this.cdr = cdr;
2483
+ this.overlay = overlay;
2484
+ this.viewContainerRef = viewContainerRef;
2422
2485
  this.triggerText = 'Open';
2423
2486
  this.variant = 'default';
2424
2487
  this.items = [];
2425
2488
  this.closeOnSelect = true;
2426
- this.panelClassName = '';
2489
+ /**
2490
+ * Additional CSS classes applied to the trigger wrapper element.
2491
+ * Preserved for backward compatibility.
2492
+ */
2427
2493
  this.className = '';
2494
+ /**
2495
+ * Additional CSS classes applied to the overlay panel.
2496
+ * Backward-compatible: mapped to `overlayOptions.panelClass` when `overlayOptions` is not set.
2497
+ * When both are supplied, `overlayOptions.panelClass` takes precedence.
2498
+ */
2499
+ this.panelClassName = '';
2428
2500
  this.itemSelect = new EventEmitter();
2429
2501
  this.itemsChange = new EventEmitter();
2430
2502
  this.open = false;
2503
+ this.overlayRef = null;
2504
+ this.backdropSub = null;
2505
+ }
2506
+ ngOnDestroy() {
2507
+ this.destroyOverlay();
2431
2508
  }
2432
2509
  toggle() {
2433
- this.open = !this.open;
2510
+ if (this.open) {
2511
+ this.closePanel();
2512
+ }
2513
+ else {
2514
+ this.openPanel();
2515
+ }
2434
2516
  }
2435
2517
  get resolvedItems() {
2436
2518
  if (this.items.length) {
@@ -2489,27 +2571,66 @@ class PdmDropdownMenuComponent {
2489
2571
  this.itemSelect.emit(item.value);
2490
2572
  const shouldClose = this.variant === 'default' ? this.closeOnSelect : false;
2491
2573
  if (shouldClose) {
2492
- this.open = false;
2574
+ this.closePanel();
2493
2575
  }
2494
2576
  }
2495
2577
  onEsc() {
2496
- this.open = false;
2578
+ this.closePanel();
2497
2579
  }
2498
- onDocumentClick(event) {
2499
- if (!this.open)
2580
+ openPanel() {
2581
+ if (this.overlayRef)
2500
2582
  return;
2501
- const target = event.target;
2502
- if (target && !this.elementRef.nativeElement.contains(target)) {
2503
- this.open = false;
2583
+ const triggerEl = this.triggerRef?.nativeElement;
2584
+ if (!triggerEl)
2585
+ return;
2586
+ this.open = true;
2587
+ this.cdr.markForCheck();
2588
+ const positionStrategy = createFlexiblePositionStrategy(this.overlay, triggerEl, 8);
2589
+ // Resolve panelClass: overlayOptions.panelClass wins; otherwise map panelClassName.
2590
+ const resolvedPanelClass = this.overlayOptions?.panelClass
2591
+ ?? (this.panelClassName ? ['block', this.panelClassName] : ['block']);
2592
+ this.overlayRef = this.overlay.create({
2593
+ positionStrategy,
2594
+ scrollStrategy: this.overlay.scrollStrategies.reposition(),
2595
+ // Consumer overrides are spread last — they win over every default above.
2596
+ ...this.overlayOptions,
2597
+ // panelClass always overrides last: it already merges panelClassName + overlayOptions.
2598
+ panelClass: resolvedPanelClass
2599
+ });
2600
+ const portal = new TemplatePortal(this.panelTemplateRef, this.viewContainerRef);
2601
+ this.overlayRef.attach(portal);
2602
+ this.backdropSub = this.overlayRef.outsidePointerEvents().subscribe((event) => {
2603
+ const target = event.target;
2604
+ if (!triggerEl.contains(target)) {
2605
+ this.closePanel();
2606
+ }
2607
+ });
2608
+ this.cdr.markForCheck();
2609
+ }
2610
+ closePanel() {
2611
+ if (!this.overlayRef)
2612
+ return;
2613
+ this.open = false;
2614
+ this.destroyOverlay();
2615
+ this.cdr.markForCheck();
2616
+ }
2617
+ destroyOverlay() {
2618
+ if (this.backdropSub) {
2619
+ this.backdropSub.unsubscribe();
2620
+ this.backdropSub = null;
2621
+ }
2622
+ if (this.overlayRef) {
2623
+ this.overlayRef.dispose();
2624
+ this.overlayRef = null;
2504
2625
  }
2505
2626
  }
2506
2627
  }
2507
- PdmDropdownMenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDropdownMenuComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
2508
- PdmDropdownMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDropdownMenuComponent, selector: "pdm-dropdown-menu", inputs: { triggerText: "triggerText", variant: "variant", items: "items", closeOnSelect: "closeOnSelect", panelClassName: "panelClassName", className: "className" }, outputs: { itemSelect: "itemSelect", itemsChange: "itemsChange" }, host: { listeners: { "document:keydown.escape": "onEsc()", "document:click": "onDocumentClick($event)" } }, ngImport: i0, template: "<div class=\"relative inline-block\" [ngClass]=\"className\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [attr.aria-expanded]=\"open\"\n (click)=\"toggle()\"\n >\n {{ triggerText }}\n </button>\n\n <div\n *ngIf=\"open\"\n [ngClass]=\"[\n 'absolute left-0 top-full z-50 mt-2 min-w-32 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md',\n panelClassName\n ]\"\n >\n <ng-container *ngFor=\"let item of resolvedItems\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div\n *ngIf=\"item.type === 'label'\"\n [ngClass]=\"['px-2 py-1.5 text-sm font-semibold text-foreground', item.inset ? 'pl-8' : '']\"\n >\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative flex w-full appearance-none cursor-default select-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm text-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50',\n item.inset ? 'pl-8' : ''\n ]\"\n (click)=\"select(item)\"\n >\n <span class=\"inline-flex h-4 w-4 shrink-0 items-center justify-center\">\n <svg\n *ngIf=\"item.checked\"\n viewBox=\"0 0 24 24\"\n class=\"h-3.5 w-3.5 text-foreground\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.radioSelected\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <span *ngIf=\"item.showChevron\" class=\"text-sm text-muted-foreground\">\u203A</span>\n </button>\n </ng-container>\n </div>\n</div>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2628
+ PdmDropdownMenuComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDropdownMenuComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1$2.Overlay }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
2629
+ PdmDropdownMenuComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmDropdownMenuComponent, selector: "pdm-dropdown-menu", inputs: { triggerText: "triggerText", variant: "variant", items: "items", closeOnSelect: "closeOnSelect", className: "className", panelClassName: "panelClassName", overlayOptions: "overlayOptions" }, outputs: { itemSelect: "itemSelect", itemsChange: "itemsChange" }, host: { listeners: { "document:keydown.escape": "onEsc()" } }, viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true }], ngImport: i0, template: "<button\n #triggerEl\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n ]\"\n [attr.aria-expanded]=\"open\"\n (click)=\"toggle()\"\n>\n {{ triggerText }}\n</button>\n\n<ng-template #panelTemplate>\n <div\n class=\"min-w-32 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n <ng-container *ngFor=\"let item of resolvedItems\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div\n *ngIf=\"item.type === 'label'\"\n [ngClass]=\"['px-2 py-1.5 text-sm font-semibold text-foreground', item.inset ? 'pl-8' : '']\"\n >\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative flex w-full appearance-none cursor-default select-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm text-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50',\n item.inset ? 'pl-8' : ''\n ]\"\n (click)=\"select(item)\"\n >\n <span class=\"inline-flex h-4 w-4 shrink-0 items-center justify-center\">\n <svg\n *ngIf=\"item.checked\"\n viewBox=\"0 0 24 24\"\n class=\"h-3.5 w-3.5 text-foreground\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.radioSelected\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <span *ngIf=\"item.showChevron\" class=\"text-sm text-muted-foreground\">\u203A</span>\n </button>\n </ng-container>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
2509
2630
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmDropdownMenuComponent, decorators: [{
2510
2631
  type: Component,
2511
- args: [{ selector: 'pdm-dropdown-menu', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"relative inline-block\" [ngClass]=\"className\">\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [attr.aria-expanded]=\"open\"\n (click)=\"toggle()\"\n >\n {{ triggerText }}\n </button>\n\n <div\n *ngIf=\"open\"\n [ngClass]=\"[\n 'absolute left-0 top-full z-50 mt-2 min-w-32 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md',\n panelClassName\n ]\"\n >\n <ng-container *ngFor=\"let item of resolvedItems\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div\n *ngIf=\"item.type === 'label'\"\n [ngClass]=\"['px-2 py-1.5 text-sm font-semibold text-foreground', item.inset ? 'pl-8' : '']\"\n >\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative flex w-full appearance-none cursor-default select-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm text-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50',\n item.inset ? 'pl-8' : ''\n ]\"\n (click)=\"select(item)\"\n >\n <span class=\"inline-flex h-4 w-4 shrink-0 items-center justify-center\">\n <svg\n *ngIf=\"item.checked\"\n viewBox=\"0 0 24 24\"\n class=\"h-3.5 w-3.5 text-foreground\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.radioSelected\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <span *ngIf=\"item.showChevron\" class=\"text-sm text-muted-foreground\">\u203A</span>\n </button>\n </ng-container>\n </div>\n</div>\n" }]
2512
- }], ctorParameters: function () { return [{ type: i0.ElementRef }]; }, propDecorators: { triggerText: [{
2632
+ args: [{ selector: 'pdm-dropdown-menu', changeDetection: ChangeDetectionStrategy.OnPush, template: "<button\n #triggerEl\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 appearance-none items-center justify-center rounded-md border border-input bg-background px-4 py-2 text-sm font-medium text-foreground shadow-sm ring-offset-background transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n className\n ]\"\n [attr.aria-expanded]=\"open\"\n (click)=\"toggle()\"\n>\n {{ triggerText }}\n</button>\n\n<ng-template #panelTemplate>\n <div\n class=\"min-w-32 overflow-hidden rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md\"\n >\n <ng-container *ngFor=\"let item of resolvedItems\">\n <div *ngIf=\"item.type === 'separator'\" class=\"-mx-1 my-1 h-px bg-muted\"></div>\n\n <div\n *ngIf=\"item.type === 'label'\"\n [ngClass]=\"['px-2 py-1.5 text-sm font-semibold text-foreground', item.inset ? 'pl-8' : '']\"\n >\n {{ item.label }}\n </div>\n\n <button\n *ngIf=\"!item.type || item.type === 'item'\"\n type=\"button\"\n [disabled]=\"item.disabled\"\n [ngClass]=\"[\n 'relative flex w-full appearance-none cursor-default select-none items-center gap-2 rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm text-foreground outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground disabled:pointer-events-none disabled:opacity-50',\n item.inset ? 'pl-8' : ''\n ]\"\n (click)=\"select(item)\"\n >\n <span class=\"inline-flex h-4 w-4 shrink-0 items-center justify-center\">\n <svg\n *ngIf=\"item.checked\"\n viewBox=\"0 0 24 24\"\n class=\"h-3.5 w-3.5 text-foreground\"\n fill=\"none\"\n xmlns=\"http://www.w3.org/2000/svg\"\n >\n <path d=\"M5 12.5L9.2 16.7L19 7\" stroke=\"currentColor\" stroke-width=\"1.8\" stroke-linecap=\"round\" stroke-linejoin=\"round\"></path>\n </svg>\n <span *ngIf=\"item.radioSelected\" class=\"h-2 w-2 rounded-full bg-foreground\"></span>\n </span>\n <span class=\"min-w-0 flex-1 truncate\">{{ item.label }}</span>\n <span *ngIf=\"item.shortcut\" class=\"text-xs text-muted-foreground\">{{ item.shortcut }}</span>\n <span *ngIf=\"item.showChevron\" class=\"text-sm text-muted-foreground\">\u203A</span>\n </button>\n </ng-container>\n </div>\n</ng-template>\n" }]
2633
+ }], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i1$2.Overlay }, { type: i0.ViewContainerRef }]; }, propDecorators: { triggerText: [{
2513
2634
  type: Input
2514
2635
  }], variant: [{
2515
2636
  type: Input
@@ -2517,20 +2638,25 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
2517
2638
  type: Input
2518
2639
  }], closeOnSelect: [{
2519
2640
  type: Input
2641
+ }], className: [{
2642
+ type: Input
2520
2643
  }], panelClassName: [{
2521
2644
  type: Input
2522
- }], className: [{
2645
+ }], overlayOptions: [{
2523
2646
  type: Input
2524
2647
  }], itemSelect: [{
2525
2648
  type: Output
2526
2649
  }], itemsChange: [{
2527
2650
  type: Output
2651
+ }], triggerRef: [{
2652
+ type: ViewChild,
2653
+ args: ['triggerEl']
2654
+ }], panelTemplateRef: [{
2655
+ type: ViewChild,
2656
+ args: ['panelTemplate']
2528
2657
  }], onEsc: [{
2529
2658
  type: HostListener,
2530
2659
  args: ['document:keydown.escape']
2531
- }], onDocumentClick: [{
2532
- type: HostListener,
2533
- args: ['document:click', ['$event']]
2534
2660
  }] } });
2535
2661
 
2536
2662
  class PdmDrawerComponent {
@@ -3365,33 +3491,15 @@ class PdmSelectComponent {
3365
3491
  return;
3366
3492
  this.open = true;
3367
3493
  this.cdr.markForCheck();
3368
- const positionStrategy = this.overlay
3369
- .position()
3370
- .flexibleConnectedTo(triggerEl)
3371
- .withPositions([
3372
- {
3373
- originX: 'start',
3374
- originY: 'bottom',
3375
- overlayX: 'start',
3376
- overlayY: 'top',
3377
- offsetY: 4
3378
- },
3379
- {
3380
- originX: 'start',
3381
- originY: 'top',
3382
- overlayX: 'start',
3383
- overlayY: 'bottom',
3384
- offsetY: -4
3385
- }
3386
- ])
3387
- .withFlexibleDimensions(false)
3388
- .withPush(true);
3494
+ const positionStrategy = createFlexiblePositionStrategy(this.overlay, triggerEl, 4);
3389
3495
  this.overlayRef = this.overlay.create({
3390
3496
  // Fix: use a token array — DOMTokenList.add() rejects space-containing strings.
3391
3497
  panelClass: ['block'],
3392
3498
  positionStrategy,
3393
3499
  scrollStrategy: this.overlay.scrollStrategies.reposition(),
3394
- width: triggerEl.offsetWidth
3500
+ width: triggerEl.offsetWidth,
3501
+ // Consumer overrides are spread last — they win over every default above.
3502
+ ...this.overlayOptions
3395
3503
  });
3396
3504
  const portal = new TemplatePortal(this.panelTemplateRef, this.viewContainerRef);
3397
3505
  this.overlayRef.attach(portal);
@@ -3422,7 +3530,7 @@ class PdmSelectComponent {
3422
3530
  }
3423
3531
  }
3424
3532
  PdmSelectComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmSelectComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i1$2.Overlay }, { token: i0.ViewContainerRef }], target: i0.ɵɵFactoryTarget.Component });
3425
- PdmSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmSelectComponent, selector: "pdm-select", inputs: { id: "id", value: "value", options: "options", disabled: "disabled", invalid: "invalid", className: "className", placeholder: "placeholder" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "projectedOptions", predicate: PdmSelectOptionDirective }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"['relative', className || 'w-full']\">\n <button\n #triggerEl\n type=\"button\"\n [id]=\"id\"\n [disabled]=\"disabled\"\n [attr.aria-invalid]=\"invalid\"\n [attr.aria-expanded]=\"open\"\n [attr.data-state]=\"open ? 'open' : 'closed'\"\n aria-haspopup=\"listbox\"\n (click)=\"toggle()\"\n [ngClass]=\"[\n 'border-input focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 aria-invalid:ring-2 aria-invalid:ring-destructive aria-invalid:border-destructive flex h-9 w-full appearance-none items-center justify-between rounded-md border bg-background px-3 py-2 text-sm shadow-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',\n ]\"\n >\n <span\n [ngClass]=\"[\n 'min-w-0 flex-1 truncate text-left leading-5',\n selectedOption\n ? 'font-medium text-foreground'\n : 'font-normal text-muted-foreground',\n ]\"\n >\n {{ selectedLabel }}\n </span>\n <pdm-icon\n name=\"chevron-down\"\n [size]=\"16\"\n className=\"shrink-0 text-muted-foreground\"\n ></pdm-icon>\n </button>\n\n <!-- Hidden native select kept for screen-reader / form fallback -->\n <select\n class=\"sr-only\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [value]=\"value\"\n (change)=\"onChange($event)\"\n >\n <option\n *ngFor=\"let option of resolvedOptions\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n\n <!-- Slot for content-projected pdm-select-option elements (hidden from layout) -->\n <span class=\"hidden\">\n <ng-content select=\"pdm-select-option\"></ng-content>\n </span>\n</div>\n\n<ng-template #panelTemplate>\n <div\n role=\"listbox\"\n [attr.aria-labelledby]=\"id || null\"\n class=\"overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md max-h-96\"\n >\n <button\n *ngFor=\"let option of resolvedOptions\"\n type=\"button\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value\"\n [disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n [ngClass]=\"[\n 'flex w-full appearance-none items-center justify-between rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors',\n option.disabled\n ? 'cursor-not-allowed opacity-50'\n : 'hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground',\n option.value === value ? 'text-foreground' : '',\n ]\"\n >\n <span class=\"min-w-0 flex-1 truncate leading-5\">{{ option.label }}</span>\n <span\n *ngIf=\"option.value === value\"\n class=\"ml-2 flex shrink-0 items-center justify-end\"\n >\n <pdm-icon\n name=\"check\"\n [size]=\"16\"\n className=\"shrink-0 text-current\"\n ></pdm-icon>\n </span>\n </button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3533
+ PdmSelectComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmSelectComponent, selector: "pdm-select", inputs: { id: "id", value: "value", options: "options", disabled: "disabled", invalid: "invalid", className: "className", placeholder: "placeholder", overlayOptions: "overlayOptions" }, outputs: { valueChange: "valueChange" }, host: { listeners: { "document:keydown.escape": "onEscape()" } }, queries: [{ propertyName: "projectedOptions", predicate: PdmSelectOptionDirective }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerEl"], descendants: true }, { propertyName: "panelTemplateRef", first: true, predicate: ["panelTemplate"], descendants: true }], ngImport: i0, template: "<div [ngClass]=\"['relative', className || 'w-full']\">\n <button\n #triggerEl\n type=\"button\"\n [id]=\"id\"\n [disabled]=\"disabled\"\n [attr.aria-invalid]=\"invalid\"\n [attr.aria-expanded]=\"open\"\n [attr.data-state]=\"open ? 'open' : 'closed'\"\n aria-haspopup=\"listbox\"\n (click)=\"toggle()\"\n [ngClass]=\"[\n 'border-input focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 aria-invalid:ring-2 aria-invalid:ring-destructive aria-invalid:border-destructive flex h-9 w-full appearance-none items-center justify-between rounded-md border bg-background px-3 py-2 text-sm shadow-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',\n ]\"\n >\n <span\n [ngClass]=\"[\n 'min-w-0 flex-1 truncate text-left leading-5',\n selectedOption\n ? 'font-medium text-foreground'\n : 'font-normal text-muted-foreground',\n ]\"\n >\n {{ selectedLabel }}\n </span>\n <pdm-icon\n name=\"chevron-down\"\n [size]=\"16\"\n className=\"shrink-0 text-muted-foreground\"\n ></pdm-icon>\n </button>\n\n <!-- Hidden native select kept for screen-reader / form fallback -->\n <select\n class=\"sr-only\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [value]=\"value\"\n (change)=\"onChange($event)\"\n >\n <option\n *ngFor=\"let option of resolvedOptions\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n\n <!-- Slot for content-projected pdm-select-option elements (hidden from layout) -->\n <span class=\"hidden\">\n <ng-content select=\"pdm-select-option\"></ng-content>\n </span>\n</div>\n\n<ng-template #panelTemplate>\n <div\n role=\"listbox\"\n [attr.aria-labelledby]=\"id || null\"\n class=\"overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md max-h-96\"\n >\n <button\n *ngFor=\"let option of resolvedOptions\"\n type=\"button\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value\"\n [disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n [ngClass]=\"[\n 'flex w-full appearance-none items-center justify-between rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors',\n option.disabled\n ? 'cursor-not-allowed opacity-50'\n : 'hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground',\n option.value === value ? 'text-foreground' : '',\n ]\"\n >\n <span class=\"min-w-0 flex-1 truncate leading-5\">{{ option.label }}</span>\n <span\n *ngIf=\"option.value === value\"\n class=\"ml-2 flex shrink-0 items-center justify-end\"\n >\n <pdm-icon\n name=\"check\"\n [size]=\"16\"\n className=\"shrink-0 text-current\"\n ></pdm-icon>\n </span>\n </button>\n </div>\n</ng-template>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3426
3534
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmSelectComponent, decorators: [{
3427
3535
  type: Component,
3428
3536
  args: [{ selector: 'pdm-select', changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [ngClass]=\"['relative', className || 'w-full']\">\n <button\n #triggerEl\n type=\"button\"\n [id]=\"id\"\n [disabled]=\"disabled\"\n [attr.aria-invalid]=\"invalid\"\n [attr.aria-expanded]=\"open\"\n [attr.data-state]=\"open ? 'open' : 'closed'\"\n aria-haspopup=\"listbox\"\n (click)=\"toggle()\"\n [ngClass]=\"[\n 'border-input focus-visible:border-ring focus-visible:ring-2 focus-visible:ring-ring/50 aria-invalid:ring-2 aria-invalid:ring-destructive aria-invalid:border-destructive flex h-9 w-full appearance-none items-center justify-between rounded-md border bg-background px-3 py-2 text-sm shadow-sm outline-none disabled:cursor-not-allowed disabled:opacity-50',\n ]\"\n >\n <span\n [ngClass]=\"[\n 'min-w-0 flex-1 truncate text-left leading-5',\n selectedOption\n ? 'font-medium text-foreground'\n : 'font-normal text-muted-foreground',\n ]\"\n >\n {{ selectedLabel }}\n </span>\n <pdm-icon\n name=\"chevron-down\"\n [size]=\"16\"\n className=\"shrink-0 text-muted-foreground\"\n ></pdm-icon>\n </button>\n\n <!-- Hidden native select kept for screen-reader / form fallback -->\n <select\n class=\"sr-only\"\n tabindex=\"-1\"\n aria-hidden=\"true\"\n [value]=\"value\"\n (change)=\"onChange($event)\"\n >\n <option\n *ngFor=\"let option of resolvedOptions\"\n [value]=\"option.value\"\n [disabled]=\"option.disabled\"\n >\n {{ option.label }}\n </option>\n </select>\n\n <!-- Slot for content-projected pdm-select-option elements (hidden from layout) -->\n <span class=\"hidden\">\n <ng-content select=\"pdm-select-option\"></ng-content>\n </span>\n</div>\n\n<ng-template #panelTemplate>\n <div\n role=\"listbox\"\n [attr.aria-labelledby]=\"id || null\"\n class=\"overflow-y-auto rounded-md border border-border bg-popover p-1 text-popover-foreground shadow-md max-h-96\"\n >\n <button\n *ngFor=\"let option of resolvedOptions\"\n type=\"button\"\n role=\"option\"\n [attr.aria-selected]=\"option.value === value\"\n [disabled]=\"option.disabled\"\n (click)=\"selectOption(option)\"\n [ngClass]=\"[\n 'flex w-full appearance-none items-center justify-between rounded-sm border-0 bg-transparent px-2 py-1.5 text-left text-sm outline-none transition-colors',\n option.disabled\n ? 'cursor-not-allowed opacity-50'\n : 'hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground',\n option.value === value ? 'text-foreground' : '',\n ]\"\n >\n <span class=\"min-w-0 flex-1 truncate leading-5\">{{ option.label }}</span>\n <span\n *ngIf=\"option.value === value\"\n class=\"ml-2 flex shrink-0 items-center justify-end\"\n >\n <pdm-icon\n name=\"check\"\n [size]=\"16\"\n className=\"shrink-0 text-current\"\n ></pdm-icon>\n </span>\n </button>\n </div>\n</ng-template>\n" }]
@@ -3440,6 +3548,8 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
3440
3548
  type: Input
3441
3549
  }], placeholder: [{
3442
3550
  type: Input
3551
+ }], overlayOptions: [{
3552
+ type: Input
3443
3553
  }], valueChange: [{
3444
3554
  type: Output
3445
3555
  }], triggerRef: [{
@@ -3499,7 +3609,7 @@ class PdmPaginationComponent {
3499
3609
  }
3500
3610
  }
3501
3611
  PdmPaginationComponent.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmPaginationComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
3502
- PdmPaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmPaginationComponent, selector: "pdm-pagination", inputs: { page: "page", pageCount: "pageCount", maxVisible: "maxVisible", className: "className", rowsPerPageLabel: "rowsPerPageLabel", rowsPerPage: "rowsPerPage", rowsPerPageOptions: "rowsPerPageOptions" }, outputs: { pageChange: "pageChange", rowsPerPageChange: "rowsPerPageChange" }, ngImport: i0, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }, { kind: "component", type: PdmSelectComponent, selector: "pdm-select", inputs: ["id", "value", "options", "disabled", "invalid", "className", "placeholder"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3612
+ PdmPaginationComponent.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.3.0", type: PdmPaginationComponent, selector: "pdm-pagination", inputs: { page: "page", pageCount: "pageCount", maxVisible: "maxVisible", className: "className", rowsPerPageLabel: "rowsPerPageLabel", rowsPerPage: "rowsPerPage", rowsPerPageOptions: "rowsPerPageOptions" }, outputs: { pageChange: "pageChange", rowsPerPageChange: "rowsPerPageChange" }, ngImport: i0, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n", dependencies: [{ kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i1.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i1.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: PdmIconComponent, selector: "pdm-icon", inputs: ["name", "library", "assetUrl", "size", "strokeWidth", "className", "ariaLabel", "decorative"] }, { kind: "component", type: PdmSelectComponent, selector: "pdm-select", inputs: ["id", "value", "options", "disabled", "invalid", "className", "placeholder", "overlayOptions"], outputs: ["valueChange"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
3503
3613
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImport: i0, type: PdmPaginationComponent, decorators: [{
3504
3614
  type: Component,
3505
3615
  args: [{ selector: 'pdm-pagination', changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav\n aria-label=\"Pagination\"\n [ngClass]=\"[\n 'mx-auto flex w-full flex-wrap items-center justify-center gap-4',\n className,\n ]\"\n>\n <div class=\"flex items-center gap-3\" *ngIf=\"rowsPerPageOptions.length > 0\">\n <span class=\"text-sm font-medium text-foreground\">{{\n rowsPerPageLabel\n }}</span>\n <pdm-select\n [value]=\"rowsPerPageValue\"\n [options]=\"rowsPerPageSelectOptions\"\n [placeholder]=\"rowsPerPageValue\"\n className=\"w-[120px]\"\n (valueChange)=\"onRowsPerPageChangeValue($event)\"\n ></pdm-select>\n </div>\n\n <ul class=\"m-0 flex list-none items-center gap-1 p-0\">\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page <= 1\"\n (click)=\"setPage(page - 1)\"\n >\n <pdm-icon name=\"chevron-left\" [size]=\"14\"></pdm-icon>\n Previous\n </button>\n </li>\n <li *ngFor=\"let pageNumber of visiblePages\">\n <ng-container *ngIf=\"pageNumber === 'ellipsis'; else pageButton\">\n <span\n class=\"inline-flex h-9 min-w-9 items-center justify-center px-2 text-sm text-muted-foreground\"\n >...</span\n >\n </ng-container>\n <ng-template #pageButton>\n <button\n type=\"button\"\n [ngClass]=\"[\n 'inline-flex h-9 min-w-9 items-center justify-center rounded-md px-2 text-sm ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2',\n pageNumber === page\n ? 'appearance-none border border-border bg-muted text-foreground shadow-sm'\n : 'appearance-none border-0 bg-transparent text-foreground hover:bg-accent hover:text-accent-foreground',\n ]\"\n (click)=\"setPage(+pageNumber)\"\n >\n {{ pageNumber }}\n </button>\n </ng-template>\n </li>\n <li>\n <button\n type=\"button\"\n class=\"inline-flex h-9 appearance-none items-center justify-center gap-1 rounded-md border-0 bg-transparent px-2 text-sm text-foreground hover:bg-accent disabled:opacity-50 ring-offset-background focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2\"\n [disabled]=\"page >= pageCount\"\n (click)=\"setPage(page + 1)\"\n >\n Next\n <pdm-icon name=\"chevron-right\" [size]=\"14\"></pdm-icon>\n </button>\n </li>\n </ul>\n</nav>\n" }]
@@ -4544,5 +4654,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.3.0", ngImpor
4544
4654
  * Generated bundle index. Do not edit.
4545
4655
  */
4546
4656
 
4547
- export { PdmAccordionComponent, PdmAlertComponent, PdmAlertDialogComponent, PdmAspectRatioComponent, PdmAvatarComponent, PdmBadgeComponent, PdmBreadcrumbComponent, PdmButtonComponent, PdmButtonGroupComponent, PdmCalendarComponent, PdmCardComponent, PdmCarouselComponent, PdmChartComponent, PdmCheckboxComponent, PdmCollapsibleComponent, PdmComboboxComponent, PdmCommandComponent, PdmContextMenuComponent, PdmDataTableComponent, PdmDatePickerComponent, PdmDialogComponent, PdmDrawerComponent, PdmDropdownMenuComponent, PdmEmptyComponent, PdmFieldComponent, PdmHoverCardComponent, PdmIconComponent, PdmInputComponent, PdmInputGroupComponent, PdmInputOtpComponent, PdmInputPasswordComponent, PdmItemComponent, PdmKbdComponent, PdmLabelComponent, PdmMenubarComponent, PdmNativeSelectComponent, PdmNavigationMenuComponent, PdmPaginationComponent, PdmPopoverComponent, PdmProgressComponent, PdmRadioGroupComponent, PdmScrollAreaComponent, PdmSelectComponent, PdmSelectOptionDirective, PdmSeparatorComponent, PdmSheetComponent, PdmSidebarComponent, PdmSkeletonComponent, PdmSliderComponent, PdmSonnerComponent, PdmSpinnerComponent, PdmSwitchComponent, PdmTableComponent, PdmTabsComponent, PdmTextareaComponent, PdmToggleComponent, PdmToggleGroupComponent, PdmTooltipComponent, PdmUiKitModule };
4657
+ export { PdmAccordionComponent, PdmAlertComponent, PdmAlertDialogComponent, PdmAspectRatioComponent, PdmAvatarComponent, PdmBadgeComponent, PdmBreadcrumbComponent, PdmButtonComponent, PdmButtonGroupComponent, PdmCalendarComponent, PdmCardComponent, PdmCarouselComponent, PdmChartComponent, PdmCheckboxComponent, PdmCollapsibleComponent, PdmComboboxComponent, PdmCommandComponent, PdmContextMenuComponent, PdmDataTableComponent, PdmDatePickerComponent, PdmDialogComponent, PdmDrawerComponent, PdmDropdownMenuComponent, PdmEmptyComponent, PdmFieldComponent, PdmHoverCardComponent, PdmIconComponent, PdmInputComponent, PdmInputGroupComponent, PdmInputOtpComponent, PdmInputPasswordComponent, PdmItemComponent, PdmKbdComponent, PdmLabelComponent, PdmMenubarComponent, PdmNativeSelectComponent, PdmNavigationMenuComponent, PdmPaginationComponent, PdmPopoverComponent, PdmProgressComponent, PdmRadioGroupComponent, PdmScrollAreaComponent, PdmSelectComponent, PdmSelectOptionDirective, PdmSeparatorComponent, PdmSheetComponent, PdmSidebarComponent, PdmSkeletonComponent, PdmSliderComponent, PdmSonnerComponent, PdmSpinnerComponent, PdmSwitchComponent, PdmTableComponent, PdmTabsComponent, PdmTextareaComponent, PdmToggleComponent, PdmToggleGroupComponent, PdmTooltipComponent, PdmUiKitModule, createFlexiblePositionStrategy };
4548
4658
  //# sourceMappingURL=pdm-ui-kit.mjs.map