@patter/ngx-components 0.5.6 → 0.5.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (29) hide show
  1. package/esm2022/lib/dialog/ptr-dialog/ptr-dialog.component.mjs +4 -4
  2. package/esm2022/lib/dialog/ptr-dialog.service.mjs +3 -3
  3. package/esm2022/lib/dialog/ptr-tooltip/ptr-tooltip.component.mjs +5 -4
  4. package/esm2022/lib/forms/form/form.component.mjs +11 -31
  5. package/esm2022/lib/forms/input/ptr-input/ptr-input.component.mjs +128 -0
  6. package/esm2022/lib/forms/input/select/select.component.mjs +124 -0
  7. package/esm2022/lib/forms/interfaces.mjs +1 -1
  8. package/esm2022/lib/forms/shared/ptr-dialog-list/ptr-dialog-list.component.mjs +173 -0
  9. package/esm2022/lib/loading-spinner/loading-spinner.component.mjs +3 -3
  10. package/esm2022/lib/loading-spinner/loading-spinner.directive.mjs +3 -3
  11. package/esm2022/lib/menu/menu.component.mjs +5 -5
  12. package/esm2022/lib/ptr-button/ptr-button.component.mjs +4 -4
  13. package/esm2022/lib/ptr-title/ptr-title.component.mjs +27 -8
  14. package/esm2022/lib/services/loading.service.mjs +3 -3
  15. package/esm2022/public-api.mjs +3 -1
  16. package/fesm2022/patter-ngx-components.mjs +475 -66
  17. package/fesm2022/patter-ngx-components.mjs.map +1 -1
  18. package/lib/dialog/ptr-dialog/ptr-dialog.component.d.ts +2 -2
  19. package/lib/forms/form/form.component.d.ts +1 -8
  20. package/lib/forms/input/ptr-input/ptr-input.component.d.ts +37 -0
  21. package/lib/forms/input/select/select.component.d.ts +31 -0
  22. package/lib/forms/interfaces.d.ts +9 -8
  23. package/lib/forms/shared/ptr-dialog-list/ptr-dialog-list.component.d.ts +40 -0
  24. package/lib/ptr-button/ptr-button.component.d.ts +2 -2
  25. package/lib/ptr-title/ptr-title.component.d.ts +2 -1
  26. package/package.json +3 -3
  27. package/patter-ngx-components-0.5.8.tgz +0 -0
  28. package/public-api.d.ts +2 -0
  29. package/patter-ngx-components-0.5.6.tgz +0 -0
@@ -1,22 +1,21 @@
1
1
  import * as i0 from '@angular/core';
2
- import { Component, ChangeDetectionStrategy, Input, signal, EventEmitter, computed, HostBinding, Output, inject, ChangeDetectorRef, DestroyRef, ElementRef, ViewContainerRef, Renderer2, Directive, Injectable, ViewChild, createComponent } from '@angular/core';
2
+ import { Component, ChangeDetectionStrategy, Input, signal, EventEmitter, computed, HostBinding, Output, ViewChild, forwardRef, HostListener, inject, ChangeDetectorRef, DestroyRef, ElementRef, ViewContainerRef, Renderer2, Directive, Injectable, createComponent } from '@angular/core';
3
3
  import * as i1 from '@angular/router';
4
4
  import { RouterModule, RouterLink, Router, ActivatedRoute, TitleStrategy, NavigationEnd } from '@angular/router';
5
5
  import * as i1$1 from '@angular/common';
6
6
  import { CommonModule } from '@angular/common';
7
- import * as i2 from '@angular/forms';
8
- import { FormBuilder, ReactiveFormsModule } from '@angular/forms';
9
- import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
10
- import { Observable, filter, map, Subject } from 'rxjs';
7
+ import * as i1$2 from '@angular/forms';
8
+ import { FormsModule, NG_VALUE_ACCESSOR, ReactiveFormsModule, FormBuilder } from '@angular/forms';
9
+ import { Subject, debounceTime, distinctUntilChanged, switchMap, of, filter, map } from 'rxjs';
11
10
 
12
11
  class PtrMenuComponent {
13
12
  menuItems = [];
14
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
15
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.4", type: PtrMenuComponent, isStandalone: true, selector: "ptr-menu", inputs: { menuItems: "menuItems" }, ngImport: i0, template: "<nav class=\"ptr-menu\">\n <ul class=\"menu\">\n @for (item of menuItems; track item) {\n <li class=\"menu-item\" routerLinkActive=\"current_page_item\"\n [routerLinkActiveOptions]=\"{exact: true}\">\n <a [routerLink]=\"item.link || '#'\">{{item.label}}</a>\n </li>\n }\n </ul>\n</nav>\n", styles: [".menu{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu>ul{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu--vertical{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu--vertical>ul{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu li.current-menu-item>a,.menu li.current_page_item>a,.menu li.current-menu-parent>a{opacity:1;font-weight:700}.menu a{transition:color .33s}.menu a:hover,.menu a:focus{text-decoration:none}.menu a{position:relative;text-decoration:none;padding:8px 0;font-family:var(--wp--preset--font-family--heading-font);letter-spacing:-.72px;color:var(--ptr-menu-color, var(--wp--preset--color--black))}.menu a:before,.menu a:after{content:\"\";position:absolute;bottom:2px;left:0;right:0;height:2px;background-color:var(--wp--preset--color--primary)}.menu a:before{opacity:0;transform:translateY(-8px);transition:transform 0s cubic-bezier(.175,.885,.32,1.275),opacity 0s}.menu a:after{opacity:0;transform:translateY(4px);transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:before,.menu a:hover:after,.menu a:focus:before,.menu a:focus:after{opacity:1;transform:translateY(0)}.menu a:hover:before,.menu a:focus:before{transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:after,.menu a:focus:after{transition:transform 0s .2s cubic-bezier(.175,.885,.32,1.275),opacity 0s .2s}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
13
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrMenuComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
14
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PtrMenuComponent, isStandalone: true, selector: "ptr-menu", inputs: { menuItems: "menuItems" }, ngImport: i0, template: "<nav class=\"ptr-menu\">\n <ul class=\"menu\">\n @for (item of menuItems; track item.label) {\n <li class=\"menu-item\" routerLinkActive=\"current_page_item\" [routerLinkActiveOptions]=\"{exact: true}\">\n <a [routerLink]=\"item.link || '#'\">{{item.label}}</a>\n </li>\n }\n </ul>\n</nav>\n", styles: [".menu{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu>ul{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu--vertical{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu--vertical>ul{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu li.current-menu-item>a,.menu li.current_page_item>a,.menu li.current-menu-parent>a{opacity:1;font-weight:700}.menu a{transition:color .33s}.menu a:hover,.menu a:focus{text-decoration:none}.menu a{position:relative;text-decoration:none;padding:8px 0;font-family:var(--wp--preset--font-family--heading-font);letter-spacing:-.72px;color:var(--ptr-menu-color, var(--wp--preset--color--black))}.menu a:before,.menu a:after{content:\"\";position:absolute;bottom:2px;left:0;right:0;height:2px;background-color:var(--wp--preset--color--primary)}.menu a:before{opacity:0;transform:translateY(-8px);transition:transform 0s cubic-bezier(.175,.885,.32,1.275),opacity 0s}.menu a:after{opacity:0;transform:translateY(4px);transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:before,.menu a:hover:after,.menu a:focus:before,.menu a:focus:after{opacity:1;transform:translateY(0)}.menu a:hover:before,.menu a:focus:before{transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:after,.menu a:focus:after{transition:transform 0s .2s cubic-bezier(.175,.885,.32,1.275),opacity 0s .2s}\n"], dependencies: [{ kind: "ngmodule", type: RouterModule }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: i1.RouterLinkActive, selector: "[routerLinkActive]", inputs: ["routerLinkActiveOptions", "ariaCurrentWhenActive", "routerLinkActive"], outputs: ["isActiveChange"], exportAs: ["routerLinkActive"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
16
15
  }
17
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrMenuComponent, decorators: [{
16
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrMenuComponent, decorators: [{
18
17
  type: Component,
19
- args: [{ selector: 'ptr-menu', standalone: true, imports: [RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"ptr-menu\">\n <ul class=\"menu\">\n @for (item of menuItems; track item) {\n <li class=\"menu-item\" routerLinkActive=\"current_page_item\"\n [routerLinkActiveOptions]=\"{exact: true}\">\n <a [routerLink]=\"item.link || '#'\">{{item.label}}</a>\n </li>\n }\n </ul>\n</nav>\n", styles: [".menu{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu>ul{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu--vertical{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu--vertical>ul{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu li.current-menu-item>a,.menu li.current_page_item>a,.menu li.current-menu-parent>a{opacity:1;font-weight:700}.menu a{transition:color .33s}.menu a:hover,.menu a:focus{text-decoration:none}.menu a{position:relative;text-decoration:none;padding:8px 0;font-family:var(--wp--preset--font-family--heading-font);letter-spacing:-.72px;color:var(--ptr-menu-color, var(--wp--preset--color--black))}.menu a:before,.menu a:after{content:\"\";position:absolute;bottom:2px;left:0;right:0;height:2px;background-color:var(--wp--preset--color--primary)}.menu a:before{opacity:0;transform:translateY(-8px);transition:transform 0s cubic-bezier(.175,.885,.32,1.275),opacity 0s}.menu a:after{opacity:0;transform:translateY(4px);transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:before,.menu a:hover:after,.menu a:focus:before,.menu a:focus:after{opacity:1;transform:translateY(0)}.menu a:hover:before,.menu a:focus:before{transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:after,.menu a:focus:after{transition:transform 0s .2s cubic-bezier(.175,.885,.32,1.275),opacity 0s .2s}\n"] }]
18
+ args: [{ selector: 'ptr-menu', standalone: true, imports: [RouterModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<nav class=\"ptr-menu\">\n <ul class=\"menu\">\n @for (item of menuItems; track item.label) {\n <li class=\"menu-item\" routerLinkActive=\"current_page_item\" [routerLinkActiveOptions]=\"{exact: true}\">\n <a [routerLink]=\"item.link || '#'\">{{item.label}}</a>\n </li>\n }\n </ul>\n</nav>\n", styles: [".menu{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu>ul{display:flex;flex-direction:row;gap:var(--wp--custom--content--gap, 40px);align-items:center}.menu--vertical{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu--vertical>ul{flex-direction:column;align-items:flex-start;gap:calc(var(--wp--custom--content--gap, 40px) / 2)}.menu li.current-menu-item>a,.menu li.current_page_item>a,.menu li.current-menu-parent>a{opacity:1;font-weight:700}.menu a{transition:color .33s}.menu a:hover,.menu a:focus{text-decoration:none}.menu a{position:relative;text-decoration:none;padding:8px 0;font-family:var(--wp--preset--font-family--heading-font);letter-spacing:-.72px;color:var(--ptr-menu-color, var(--wp--preset--color--black))}.menu a:before,.menu a:after{content:\"\";position:absolute;bottom:2px;left:0;right:0;height:2px;background-color:var(--wp--preset--color--primary)}.menu a:before{opacity:0;transform:translateY(-8px);transition:transform 0s cubic-bezier(.175,.885,.32,1.275),opacity 0s}.menu a:after{opacity:0;transform:translateY(4px);transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:before,.menu a:hover:after,.menu a:focus:before,.menu a:focus:after{opacity:1;transform:translateY(0)}.menu a:hover:before,.menu a:focus:before{transition:transform .2s cubic-bezier(.175,.885,.32,1.275),opacity .2s}.menu a:hover:after,.menu a:focus:after{transition:transform 0s .2s cubic-bezier(.175,.885,.32,1.275),opacity 0s .2s}\n"] }]
20
19
  }], propDecorators: { menuItems: [{
21
20
  type: Input
22
21
  }] } });
@@ -95,10 +94,10 @@ class PtrButtonComponent {
95
94
  }
96
95
  this.clicked.emit(event);
97
96
  }
98
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
99
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.4", type: PtrButtonComponent, isStandalone: true, selector: "ptr-button", inputs: { buttonStyle: "buttonStyle", buttonType: "buttonType", isDisabled: "isDisabled", hrefLink: "hrefLink", routerLinkValue: "routerLinkValue", extraClasses: "extraClasses", isSmallSize: "isSmallSize", isIconButton: "isIconButton" }, outputs: { clicked: "clicked" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<ng-template #contentTpl>\r\n <ng-content></ng-content>\r\n</ng-template>\r\n\r\n@if (isLink()) {\r\n<a [attr.href]=\"href()\" [routerLink]=\"routerLink()\" [class]=\"buttonClasses()\" [attr.disabled]=\"disabled() ? '' : null\"\r\n (click)=\"onClick($event)\">\r\n <ng-container [ngTemplateOutlet]=\"contentTpl\"></ng-container>\r\n</a>\r\n} @else {\r\n<button [type]=\"type()\" [class]=\"buttonClasses()\" [disabled]=\"disabled()\" (click)=\"onClick($event)\">\r\n <ng-container [ngTemplateOutlet]=\"contentTpl\"></ng-container>\r\n</button>\r\n}", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
97
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrButtonComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
98
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PtrButtonComponent, isStandalone: true, selector: "ptr-button", inputs: { buttonStyle: "buttonStyle", buttonType: "buttonType", isDisabled: "isDisabled", hrefLink: "hrefLink", routerLinkValue: "routerLinkValue", extraClasses: "extraClasses", isSmallSize: "isSmallSize", isIconButton: "isIconButton" }, outputs: { clicked: "clicked" }, host: { properties: { "class": "this.hostClasses" } }, ngImport: i0, template: "<ng-template #contentTpl>\r\n <ng-content></ng-content>\r\n</ng-template>\r\n\r\n@if (isLink()) {\r\n<a [attr.href]=\"href()\" [routerLink]=\"routerLink()\" [class]=\"buttonClasses()\" [attr.disabled]=\"disabled() ? '' : null\"\r\n (click)=\"onClick($event)\">\r\n <ng-container [ngTemplateOutlet]=\"contentTpl\"></ng-container>\r\n</a>\r\n} @else {\r\n<button [type]=\"type()\" [class]=\"buttonClasses()\" [disabled]=\"disabled()\" (click)=\"onClick($event)\">\r\n <ng-container [ngTemplateOutlet]=\"contentTpl\"></ng-container>\r\n</button>\r\n}", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1$1.NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
100
99
  }
101
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrButtonComponent, decorators: [{
100
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrButtonComponent, decorators: [{
102
101
  type: Component,
103
102
  args: [{ selector: 'ptr-button', standalone: true, imports: [CommonModule, RouterLink], changeDetection: ChangeDetectionStrategy.OnPush, template: "<ng-template #contentTpl>\r\n <ng-content></ng-content>\r\n</ng-template>\r\n\r\n@if (isLink()) {\r\n<a [attr.href]=\"href()\" [routerLink]=\"routerLink()\" [class]=\"buttonClasses()\" [attr.disabled]=\"disabled() ? '' : null\"\r\n (click)=\"onClick($event)\">\r\n <ng-container [ngTemplateOutlet]=\"contentTpl\"></ng-container>\r\n</a>\r\n} @else {\r\n<button [type]=\"type()\" [class]=\"buttonClasses()\" [disabled]=\"disabled()\" (click)=\"onClick($event)\">\r\n <ng-container [ngTemplateOutlet]=\"contentTpl\"></ng-container>\r\n</button>\r\n}" }]
104
103
  }], propDecorators: { hostClasses: [{
@@ -124,34 +123,430 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImpor
124
123
  type: Output
125
124
  }] } });
126
125
 
126
+ class PtrDialogListComponent {
127
+ set options(value) {
128
+ this._options.set(this.processOptions(value));
129
+ }
130
+ showSearch = false;
131
+ searchPlaceholder = 'Search...';
132
+ dialogTitle = '';
133
+ selectionChange = new EventEmitter();
134
+ dialogClosed = new EventEmitter();
135
+ searchTermChanged = new EventEmitter();
136
+ dialog;
137
+ _options = signal([]);
138
+ value = signal(null);
139
+ searchTerm = signal('');
140
+ highlightedIndex = signal(-1);
141
+ isOpen = signal(false);
142
+ componentId = Math.random().toString(36).substring(2);
143
+ listId = `${this.componentId}-list`;
144
+ filteredOptions = computed(() => {
145
+ const term = this.searchTerm().toLowerCase();
146
+ return this._options().flatMap(item => {
147
+ if (item.type === 'group') {
148
+ const filteredOptions = item.options.filter(option => option.label.toLowerCase().includes(term));
149
+ return filteredOptions.length > 0 ? [{ ...item, options: filteredOptions }] : [];
150
+ }
151
+ else {
152
+ return item.label.toLowerCase().includes(term) ? [item] : [];
153
+ }
154
+ });
155
+ });
156
+ openDialog() {
157
+ this.dialog.nativeElement.show();
158
+ this.isOpen.set(true);
159
+ }
160
+ closeDialog() {
161
+ this.dialog.nativeElement.close();
162
+ this.isOpen.set(false);
163
+ this.searchTerm.set('');
164
+ this.highlightedIndex.set(-1);
165
+ this.dialogClosed.emit();
166
+ }
167
+ updateSearchTerm(term) {
168
+ this.searchTerm.set(term);
169
+ this.highlightedIndex.set(-1);
170
+ this.searchTermChanged.emit(term);
171
+ }
172
+ onDialogKeyDown(event) {
173
+ if (event.key === 'Escape') {
174
+ this.closeDialog();
175
+ event.preventDefault();
176
+ }
177
+ // When there is no search input and there are options, move input into the first option
178
+ if (!this.showSearch && this.filteredOptions().length > 0 && this.highlightedIndex() === -1) {
179
+ if (event.key === 'Tab' || event.key === 'ArrowDown') {
180
+ this.highlightedIndex.update(i => Math.min(i + 1, this.getTotalOptionsCount() - 1));
181
+ this.focusOption();
182
+ event.preventDefault();
183
+ }
184
+ }
185
+ }
186
+ onInputKeyDown(event) {
187
+ switch (event.key) {
188
+ case 'ArrowDown':
189
+ this.highlightedIndex.update(i => Math.min(i + 1, this.getTotalOptionsCount() - 1));
190
+ this.focusOption();
191
+ event.preventDefault();
192
+ break;
193
+ case 'Escape':
194
+ this.closeDialog();
195
+ event.preventDefault();
196
+ break;
197
+ }
198
+ }
199
+ onOptionKeyDown(event, optionValue) {
200
+ switch (event.key) {
201
+ case 'ArrowDown':
202
+ this.highlightedIndex.update(i => Math.min(i + 1, this.getTotalOptionsCount() - 1));
203
+ this.focusOption();
204
+ event.preventDefault();
205
+ break;
206
+ case 'ArrowUp':
207
+ this.highlightedIndex.update(i => Math.max(i - 1, -1));
208
+ this.focusOption();
209
+ event.preventDefault();
210
+ break;
211
+ case 'Enter':
212
+ case ' ':
213
+ this.selectOption(optionValue);
214
+ event.preventDefault();
215
+ break;
216
+ }
217
+ }
218
+ focusOption() {
219
+ if (this.highlightedIndex() >= 0) {
220
+ const options = this.dialog.nativeElement.querySelectorAll('li[role="option"]');
221
+ options[this.highlightedIndex()].focus();
222
+ }
223
+ }
224
+ selectOption(optionValue) {
225
+ this.value.set(optionValue);
226
+ this.selectionChange.emit(optionValue);
227
+ this.closeDialog();
228
+ }
229
+ getTotalOptionsCount() {
230
+ return this.filteredOptions().reduce((count, item) => {
231
+ if (item.type === 'group') {
232
+ return count + item.options.length;
233
+ }
234
+ return count + 1;
235
+ }, 0);
236
+ }
237
+ processOptions(options) {
238
+ if (!options)
239
+ return [];
240
+ return options.map(option => {
241
+ if (typeof option === 'string') {
242
+ return {
243
+ type: 'option',
244
+ label: option,
245
+ value: option
246
+ };
247
+ }
248
+ else if ('groupLabel' in option) {
249
+ return {
250
+ type: 'group',
251
+ label: option.groupLabel,
252
+ options: option.options.map(subOption => ({
253
+ type: 'option',
254
+ label: typeof subOption === 'string' ? subOption : subOption.label,
255
+ value: typeof subOption === 'string' ? subOption : subOption.value
256
+ }))
257
+ };
258
+ }
259
+ else {
260
+ return {
261
+ type: 'option',
262
+ label: option.label,
263
+ value: option.value
264
+ };
265
+ }
266
+ });
267
+ }
268
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogListComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
269
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PtrDialogListComponent, isStandalone: true, selector: "ptr-dialog-list", inputs: { options: "options", showSearch: "showSearch", searchPlaceholder: "searchPlaceholder", dialogTitle: "dialogTitle" }, outputs: { selectionChange: "selectionChange", dialogClosed: "dialogClosed", searchTermChanged: "searchTermChanged" }, viewQueries: [{ propertyName: "dialog", first: true, predicate: ["dialog"], descendants: true }], ngImport: i0, template: "<dialog #dialog class=\"ptr-dialog-list\" (keydown)=\"onDialogKeyDown($event)\" [attr.aria-label]=\"'Options'\">\r\n\r\n @if(dialogTitle) {\r\n <p class=\"dialog-title\">{{dialogTitle}}</p>\r\n }\r\n\r\n @if (showSearch) {\r\n <div>\r\n <input #searchInput [ngModel]=\"searchTerm()\" (ngModelChange)=\"updateSearchTerm($event)\"\r\n [attr.aria-expanded]=\"isOpen()\" [attr.aria-owns]=\"listId\" (keydown)=\"onInputKeyDown($event)\"\r\n [attr.aria-autocomplete]=\"'list'\" role=\"combobox\" [attr.aria-controls]=\"listId\" [placeholder]=\"searchPlaceholder\"\r\n class=\"search-input\">\r\n </div>\r\n }\r\n\r\n <ul [attr.id]=\"listId\" role=\"listbox\" class=\"option-list\">\r\n @for (item of filteredOptions(); track item.label) {\r\n @if (item.type === 'option') {\r\n <li role=\"option\" [attr.id]=\"item.value\" [attr.aria-selected]=\"item.value === value()\"\r\n [class.selected]=\"item.value === value()\" [class.highlighted]=\"item === filteredOptions()[highlightedIndex()]\"\r\n (click)=\"selectOption(item.value!)\" (keydown)=\"onOptionKeyDown($event, item.value!)\"\r\n [attr.tabindex]=\"item === filteredOptions()[highlightedIndex()] ? 0 : -1\">\r\n {{ item.label }}\r\n </li>\r\n } @else {\r\n <li role=\"group\" [attr.aria-label]=\"item.label\">\r\n {{ item.label }}\r\n </li>\r\n @for (option of item.options!; track option.value) {\r\n <li role=\"option\" [attr.id]=\"option.value\" [attr.aria-selected]=\"option.value === value()\"\r\n [class.selected]=\"option.value === value()\" [class.highlighted]=\"option === filteredOptions()[highlightedIndex()]\"\r\n (click)=\"selectOption(option.value!)\" (keydown)=\"onOptionKeyDown($event, option.value!)\"\r\n [attr.tabindex]=\"option === filteredOptions()[highlightedIndex()] ? 0 : -1\">\r\n {{ option.label }}\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n\r\n</dialog>\r\n", styles: [".ptr-dialog-list{margin:0;padding:0;border:1px solid var(--wp--custom--color--border);width:100%;max-height:350px;overflow-y:auto;z-index:5;border-radius:calc(var(--wp--custom--default-border-radius) / 2);border-top-left-radius:0;border-top-right-radius:0;scrollbar-width:thin}.ptr-dialog-list:focus{outline:none}input.search-input{padding:calc(var(--wp--custom--content--button-input-padding-y, 12px) / 1.5) var(--wp--custom--content--button-input-padding-x, 16px)!important;border:none!important;border-bottom:1px solid var(--wp--custom--color--border)!important;outline:0;font-size:var(--wp--preset--font-size--small, inherit);border-radius:0!important}.dialog-title{padding:5px 10px;border:none!important;border-bottom:1px solid var(--wp--custom--color--border)!important;font-size:var(--wp--preset--font-size--small, inherit);font-weight:500;margin:0}.option-list{list-style-type:none;padding:0;margin:0}li[role=option],li[role=group]{padding:5px 10px}li[role=group]{font-weight:700;margin-top:6px}li[role=option]{cursor:pointer;font-size:var(--wp--preset--font-size--small, inherit)}li[role=option]:hover,li[role=option].selected,li[role=option].highlighted{background-color:#f0f0f0}li[role=option]:focus-within{outline:2px solid var(--wp--custom--color--border)}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
270
+ }
271
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogListComponent, decorators: [{
272
+ type: Component,
273
+ args: [{ selector: 'ptr-dialog-list', standalone: true, imports: [
274
+ FormsModule
275
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<dialog #dialog class=\"ptr-dialog-list\" (keydown)=\"onDialogKeyDown($event)\" [attr.aria-label]=\"'Options'\">\r\n\r\n @if(dialogTitle) {\r\n <p class=\"dialog-title\">{{dialogTitle}}</p>\r\n }\r\n\r\n @if (showSearch) {\r\n <div>\r\n <input #searchInput [ngModel]=\"searchTerm()\" (ngModelChange)=\"updateSearchTerm($event)\"\r\n [attr.aria-expanded]=\"isOpen()\" [attr.aria-owns]=\"listId\" (keydown)=\"onInputKeyDown($event)\"\r\n [attr.aria-autocomplete]=\"'list'\" role=\"combobox\" [attr.aria-controls]=\"listId\" [placeholder]=\"searchPlaceholder\"\r\n class=\"search-input\">\r\n </div>\r\n }\r\n\r\n <ul [attr.id]=\"listId\" role=\"listbox\" class=\"option-list\">\r\n @for (item of filteredOptions(); track item.label) {\r\n @if (item.type === 'option') {\r\n <li role=\"option\" [attr.id]=\"item.value\" [attr.aria-selected]=\"item.value === value()\"\r\n [class.selected]=\"item.value === value()\" [class.highlighted]=\"item === filteredOptions()[highlightedIndex()]\"\r\n (click)=\"selectOption(item.value!)\" (keydown)=\"onOptionKeyDown($event, item.value!)\"\r\n [attr.tabindex]=\"item === filteredOptions()[highlightedIndex()] ? 0 : -1\">\r\n {{ item.label }}\r\n </li>\r\n } @else {\r\n <li role=\"group\" [attr.aria-label]=\"item.label\">\r\n {{ item.label }}\r\n </li>\r\n @for (option of item.options!; track option.value) {\r\n <li role=\"option\" [attr.id]=\"option.value\" [attr.aria-selected]=\"option.value === value()\"\r\n [class.selected]=\"option.value === value()\" [class.highlighted]=\"option === filteredOptions()[highlightedIndex()]\"\r\n (click)=\"selectOption(option.value!)\" (keydown)=\"onOptionKeyDown($event, option.value!)\"\r\n [attr.tabindex]=\"option === filteredOptions()[highlightedIndex()] ? 0 : -1\">\r\n {{ option.label }}\r\n </li>\r\n }\r\n }\r\n }\r\n </ul>\r\n\r\n</dialog>\r\n", styles: [".ptr-dialog-list{margin:0;padding:0;border:1px solid var(--wp--custom--color--border);width:100%;max-height:350px;overflow-y:auto;z-index:5;border-radius:calc(var(--wp--custom--default-border-radius) / 2);border-top-left-radius:0;border-top-right-radius:0;scrollbar-width:thin}.ptr-dialog-list:focus{outline:none}input.search-input{padding:calc(var(--wp--custom--content--button-input-padding-y, 12px) / 1.5) var(--wp--custom--content--button-input-padding-x, 16px)!important;border:none!important;border-bottom:1px solid var(--wp--custom--color--border)!important;outline:0;font-size:var(--wp--preset--font-size--small, inherit);border-radius:0!important}.dialog-title{padding:5px 10px;border:none!important;border-bottom:1px solid var(--wp--custom--color--border)!important;font-size:var(--wp--preset--font-size--small, inherit);font-weight:500;margin:0}.option-list{list-style-type:none;padding:0;margin:0}li[role=option],li[role=group]{padding:5px 10px}li[role=group]{font-weight:700;margin-top:6px}li[role=option]{cursor:pointer;font-size:var(--wp--preset--font-size--small, inherit)}li[role=option]:hover,li[role=option].selected,li[role=option].highlighted{background-color:#f0f0f0}li[role=option]:focus-within{outline:2px solid var(--wp--custom--color--border)}\n"] }]
276
+ }], propDecorators: { options: [{
277
+ type: Input
278
+ }], showSearch: [{
279
+ type: Input
280
+ }], searchPlaceholder: [{
281
+ type: Input
282
+ }], dialogTitle: [{
283
+ type: Input
284
+ }], selectionChange: [{
285
+ type: Output
286
+ }], dialogClosed: [{
287
+ type: Output
288
+ }], searchTermChanged: [{
289
+ type: Output
290
+ }], dialog: [{
291
+ type: ViewChild,
292
+ args: ['dialog']
293
+ }] } });
294
+
295
+ /* eslint-disable @typescript-eslint/no-empty-function */
296
+ class PtrSelectComponent {
297
+ options;
298
+ showSearch = true;
299
+ placeholder = 'Select an option';
300
+ label = '';
301
+ selectionChange = new EventEmitter();
302
+ selectButton;
303
+ dialogList;
304
+ value = signal(null);
305
+ isOpen = signal(false);
306
+ displayValue = computed(() => {
307
+ const currentValue = this.value();
308
+ if (currentValue === null)
309
+ return null;
310
+ const allOptions = this.flattenOptions(this.options);
311
+ const selectedOption = allOptions?.find(option => option.value === currentValue);
312
+ return selectedOption ? selectedOption.label : null;
313
+ });
314
+ componentId = Math.random().toString(36).substring(2);
315
+ labelId = `${this.componentId}-label`;
316
+ inputId = `${this.componentId}-input`;
317
+ onChange = () => { };
318
+ onTouched = () => { };
319
+ onDocumentClick(event) {
320
+ if (!this.dialogList.dialog.nativeElement.contains(event.target) &&
321
+ !event.target.closest('.select-button') &&
322
+ this.isOpen()) {
323
+ this.dialogList.closeDialog();
324
+ this.isOpen.set(false);
325
+ }
326
+ }
327
+ toggleDialog() {
328
+ if (this.isOpen()) {
329
+ this.dialogList.closeDialog();
330
+ }
331
+ else {
332
+ this.dialogList.openDialog();
333
+ }
334
+ this.isOpen.update(v => !v);
335
+ }
336
+ onOptionSelected(optionValue) {
337
+ this.value.set(optionValue);
338
+ this.onChange(optionValue);
339
+ this.onTouched();
340
+ this.selectionChange.emit(optionValue);
341
+ this.isOpen.set(false);
342
+ }
343
+ writeValue(value) {
344
+ this.value.set(value);
345
+ }
346
+ registerOnChange(fn) {
347
+ this.onChange = fn;
348
+ }
349
+ registerOnTouched(fn) {
350
+ this.onTouched = fn;
351
+ }
352
+ setDisabledState(isDisabled) {
353
+ if (this.selectButton?.nativeElement) {
354
+ this.selectButton.nativeElement.disabled = isDisabled;
355
+ }
356
+ }
357
+ flattenOptions(options) {
358
+ if (!options)
359
+ return [];
360
+ return options.flatMap(option => {
361
+ if (typeof option === 'string') {
362
+ return { value: option, label: option };
363
+ }
364
+ else if ('groupLabel' in option) {
365
+ return option.options;
366
+ }
367
+ else {
368
+ return option;
369
+ }
370
+ });
371
+ }
372
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrSelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
373
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PtrSelectComponent, isStandalone: true, selector: "ptr-select", inputs: { options: "options", showSearch: "showSearch", placeholder: "placeholder", label: "label" }, outputs: { selectionChange: "selectionChange" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
374
+ {
375
+ provide: NG_VALUE_ACCESSOR,
376
+ useExisting: forwardRef(() => PtrSelectComponent),
377
+ multi: true
378
+ }
379
+ ], viewQueries: [{ propertyName: "selectButton", first: true, predicate: ["selectButton"], descendants: true }, { propertyName: "dialogList", first: true, predicate: ["dialogList"], descendants: true }], ngImport: i0, template: "<label class=\"gfield_label gform-field-label\" [attr.for]=\"inputId\">{{ label }}</label>\r\n<div class=\"select-container\">\r\n\r\n <button #selectButton type=\"button\" class=\"select-button\" [attr.id]=\"inputId\" [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"isOpen()\" [attr.aria-labelledby]=\"labelId\" (click)=\"toggleDialog()\">\r\n <span [attr.id]=\"labelId\">@if (displayValue(); as dValue) { {{dValue}} } @else { {{placeholder}} }</span>\r\n </button>\r\n\r\n <ptr-dialog-list #dialogList [options]=\"options\" (selectionChange)=\"onOptionSelected($event)\"\r\n [showSearch]=\"showSearch\" />\r\n\r\n</div>\r\n", styles: [".select-container{position:relative}.select-button{appearance:none;background-color:#fff;text-align:left;cursor:pointer;border:1px solid var(--wp--custom--color--border);width:100%;padding:var(--wp--custom--content--button-input-padding-y, 12px) var(--wp--custom--content--button-input-padding-x, 16px);margin:0;font-size:var(--wp--preset--font-size--small, inherit);font-family:Arial,Helvetica,sans-serif;z-index:5;color:#000;border-radius:calc(var(--wp--custom--default-border-radius) / 2);transition:border-color .3s,color .3s,background-color .3s;transition-timing-function:cubic-bezier(.2,1,.3,1);background-position:calc(100% - 4px) 50%;background-repeat:no-repeat;background-image:url(data:image/png;base64,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)}.select-button[aria-expanded=true]{border-bottom-left-radius:0;border-bottom-right-radius:0}\n"], dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: PtrDialogListComponent, selector: "ptr-dialog-list", inputs: ["options", "showSearch", "searchPlaceholder", "dialogTitle"], outputs: ["selectionChange", "dialogClosed", "searchTermChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
380
+ }
381
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrSelectComponent, decorators: [{
382
+ type: Component,
383
+ args: [{ selector: 'ptr-select', standalone: true, imports: [
384
+ FormsModule,
385
+ ReactiveFormsModule,
386
+ PtrDialogListComponent
387
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
388
+ {
389
+ provide: NG_VALUE_ACCESSOR,
390
+ useExisting: forwardRef(() => PtrSelectComponent),
391
+ multi: true
392
+ }
393
+ ], template: "<label class=\"gfield_label gform-field-label\" [attr.for]=\"inputId\">{{ label }}</label>\r\n<div class=\"select-container\">\r\n\r\n <button #selectButton type=\"button\" class=\"select-button\" [attr.id]=\"inputId\" [attr.aria-haspopup]=\"'listbox'\"\r\n [attr.aria-expanded]=\"isOpen()\" [attr.aria-labelledby]=\"labelId\" (click)=\"toggleDialog()\">\r\n <span [attr.id]=\"labelId\">@if (displayValue(); as dValue) { {{dValue}} } @else { {{placeholder}} }</span>\r\n </button>\r\n\r\n <ptr-dialog-list #dialogList [options]=\"options\" (selectionChange)=\"onOptionSelected($event)\"\r\n [showSearch]=\"showSearch\" />\r\n\r\n</div>\r\n", styles: [".select-container{position:relative}.select-button{appearance:none;background-color:#fff;text-align:left;cursor:pointer;border:1px solid var(--wp--custom--color--border);width:100%;padding:var(--wp--custom--content--button-input-padding-y, 12px) var(--wp--custom--content--button-input-padding-x, 16px);margin:0;font-size:var(--wp--preset--font-size--small, inherit);font-family:Arial,Helvetica,sans-serif;z-index:5;color:#000;border-radius:calc(var(--wp--custom--default-border-radius) / 2);transition:border-color .3s,color .3s,background-color .3s;transition-timing-function:cubic-bezier(.2,1,.3,1);background-position:calc(100% - 4px) 50%;background-repeat:no-repeat;background-image:url(data:image/png;base64,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)}.select-button[aria-expanded=true]{border-bottom-left-radius:0;border-bottom-right-radius:0}\n"] }]
394
+ }], propDecorators: { options: [{
395
+ type: Input
396
+ }], showSearch: [{
397
+ type: Input
398
+ }], placeholder: [{
399
+ type: Input
400
+ }], label: [{
401
+ type: Input
402
+ }], selectionChange: [{
403
+ type: Output
404
+ }], selectButton: [{
405
+ type: ViewChild,
406
+ args: ['selectButton']
407
+ }], dialogList: [{
408
+ type: ViewChild,
409
+ args: ['dialogList']
410
+ }], onDocumentClick: [{
411
+ type: HostListener,
412
+ args: ['document:click', ['$event']]
413
+ }] } });
414
+
415
+ /* eslint-disable @typescript-eslint/no-empty-function */
416
+ class PtrInputComponent {
417
+ type = 'text';
418
+ label = '';
419
+ placeholder = '';
420
+ autocomplete = '';
421
+ dialogHelpText = '';
422
+ searchFn;
423
+ input;
424
+ dialogList;
425
+ componentId = Math.random().toString(36).substring(2);
426
+ minChars = 3;
427
+ searchTerms = new Subject();
428
+ hasSelectedOption = false;
429
+ inputId = `${this.componentId}-input`;
430
+ inputValue = signal('');
431
+ searchResultOptions = signal([]);
432
+ onChange = () => { };
433
+ onTouched = () => { };
434
+ onDocumentClick(event) {
435
+ if (!this.dialogList.dialog.nativeElement.contains(event.target) && this.dialogList.isOpen()) {
436
+ this.dialogList.closeDialog();
437
+ }
438
+ }
439
+ ngOnInit() {
440
+ this.setupSearch();
441
+ }
442
+ setupSearch() {
443
+ if (this.searchFn) {
444
+ this.searchTerms.pipe(debounceTime(300), distinctUntilChanged(), switchMap(term => term.length >= this.minChars ? this.searchFn(term) : of([]))).subscribe(results => {
445
+ this.searchResultOptions.set(results);
446
+ if (results.length > 0 && this.dialogList) {
447
+ this.dialogList.openDialog();
448
+ }
449
+ });
450
+ }
451
+ }
452
+ onInputChange(value) {
453
+ this.inputValue.set(value);
454
+ this.onChange(value);
455
+ if (!this.hasSelectedOption && this.searchFn && value.length >= this.minChars) {
456
+ this.searchTerms.next(value);
457
+ }
458
+ this.hasSelectedOption = false;
459
+ }
460
+ onOptionSelected(optionValue) {
461
+ this.hasSelectedOption = true;
462
+ this.inputValue.set(optionValue ?? '');
463
+ this.onChange(optionValue ?? '');
464
+ if (this.dialogList) {
465
+ this.dialogList.closeDialog();
466
+ }
467
+ }
468
+ onFocus() {
469
+ if (this.searchResultOptions().length > 0 && this.dialogList && !this.hasSelectedOption) {
470
+ this.dialogList.openDialog();
471
+ }
472
+ }
473
+ onBlur() {
474
+ this.onTouched();
475
+ }
476
+ writeValue(value) {
477
+ this.inputValue.set(value ?? '');
478
+ }
479
+ registerOnChange(fn) {
480
+ this.onChange = fn;
481
+ }
482
+ registerOnTouched(fn) {
483
+ this.onTouched = fn;
484
+ }
485
+ setDisabledState(isDisabled) {
486
+ if (this.input?.nativeElement) {
487
+ this.input.nativeElement.disabled = isDisabled;
488
+ }
489
+ }
490
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrInputComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
491
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: PtrInputComponent, isStandalone: true, selector: "ptr-input", inputs: { type: "type", label: "label", placeholder: "placeholder", autocomplete: "autocomplete", dialogHelpText: "dialogHelpText", searchFn: "searchFn" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, providers: [
492
+ {
493
+ provide: NG_VALUE_ACCESSOR,
494
+ useExisting: forwardRef(() => PtrInputComponent),
495
+ multi: true
496
+ }
497
+ ], viewQueries: [{ propertyName: "input", first: true, predicate: ["input"], descendants: true }, { propertyName: "dialogList", first: true, predicate: ["dialogList"], descendants: true }], ngImport: i0, template: "<label class=\"gfield_label gform-field-label\" [attr.for]=\"inputId\">{{ label }}</label>\r\n<div class=\"gfield--input-wrapper\">\r\n\r\n <input #input [id]=\"inputId\" [type]=\"type\" [attr.autocomplete]=\"autocomplete || null\"\r\n [attr.placeholder]=\"placeholder || null\" [ngModel]=\"inputValue()\" (ngModelChange)=\"onInputChange($event)\"\r\n (focus)=\"onFocus()\" (blur)=\"onBlur()\" />\r\n\r\n <ptr-dialog-list #dialogList [options]=\"searchResultOptions()\" (selectionChange)=\"onOptionSelected($event)\"\r\n [dialogTitle]=\"dialogHelpText\" />\r\n\r\n</div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "component", type: PtrDialogListComponent, selector: "ptr-dialog-list", inputs: ["options", "showSearch", "searchPlaceholder", "dialogTitle"], outputs: ["selectionChange", "dialogClosed", "searchTermChanged"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
498
+ }
499
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrInputComponent, decorators: [{
500
+ type: Component,
501
+ args: [{ selector: 'ptr-input', standalone: true, imports: [
502
+ CommonModule,
503
+ FormsModule,
504
+ ReactiveFormsModule,
505
+ PtrDialogListComponent
506
+ ], changeDetection: ChangeDetectionStrategy.OnPush, providers: [
507
+ {
508
+ provide: NG_VALUE_ACCESSOR,
509
+ useExisting: forwardRef(() => PtrInputComponent),
510
+ multi: true
511
+ }
512
+ ], template: "<label class=\"gfield_label gform-field-label\" [attr.for]=\"inputId\">{{ label }}</label>\r\n<div class=\"gfield--input-wrapper\">\r\n\r\n <input #input [id]=\"inputId\" [type]=\"type\" [attr.autocomplete]=\"autocomplete || null\"\r\n [attr.placeholder]=\"placeholder || null\" [ngModel]=\"inputValue()\" (ngModelChange)=\"onInputChange($event)\"\r\n (focus)=\"onFocus()\" (blur)=\"onBlur()\" />\r\n\r\n <ptr-dialog-list #dialogList [options]=\"searchResultOptions()\" (selectionChange)=\"onOptionSelected($event)\"\r\n [dialogTitle]=\"dialogHelpText\" />\r\n\r\n</div>\r\n" }]
513
+ }], propDecorators: { type: [{
514
+ type: Input
515
+ }], label: [{
516
+ type: Input
517
+ }], placeholder: [{
518
+ type: Input
519
+ }], autocomplete: [{
520
+ type: Input
521
+ }], dialogHelpText: [{
522
+ type: Input
523
+ }], searchFn: [{
524
+ type: Input
525
+ }], input: [{
526
+ type: ViewChild,
527
+ args: ['input']
528
+ }], dialogList: [{
529
+ type: ViewChild,
530
+ args: ['dialogList']
531
+ }], onDocumentClick: [{
532
+ type: HostListener,
533
+ args: ['document:click', ['$event']]
534
+ }] } });
535
+
127
536
  class PtrFormComponent {
128
537
  config;
129
538
  loading = false;
130
539
  error = null;
540
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
131
541
  formSubmit = new EventEmitter();
132
542
  formGroupCreated = new EventEmitter();
133
543
  formGroup;
134
- flatOptions = {};
135
- groupedOptions = {};
136
544
  fb = inject(FormBuilder);
137
545
  cdr = inject(ChangeDetectorRef);
138
546
  destroyRef = inject(DestroyRef);
139
547
  ngOnInit() {
140
548
  this.buildForm();
141
549
  this.formGroupCreated.emit(this.formGroup);
142
- this.config.fields.forEach(field => {
143
- if (field.type === 'select' && field.options instanceof Observable) {
144
- field.options
145
- .pipe(takeUntilDestroyed(this.destroyRef))
146
- .subscribe(options => {
147
- this.processOptions(field.name, options);
148
- this.cdr.markForCheck(); // Trigger change detection after options are loaded
149
- });
150
- }
151
- else if (field.type === 'select' && Array.isArray(field.options)) {
152
- this.processOptions(field.name, field.options);
153
- }
154
- });
155
550
  }
156
551
  buildForm() {
157
552
  const group = {};
@@ -173,24 +568,18 @@ class PtrFormComponent {
173
568
  });
174
569
  this.cdr.markForCheck();
175
570
  }
176
- processOptions(fieldName, options) {
177
- if (options.length > 0 && 'options' in options[0]) {
178
- this.groupedOptions[fieldName] = options;
179
- }
180
- else {
181
- this.flatOptions[fieldName] = options;
182
- }
183
- }
184
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
185
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.4", type: PtrFormComponent, isStandalone: true, selector: "ptr-form", inputs: { config: "config", loading: "loading", error: "error" }, outputs: { formSubmit: "formSubmit", formGroupCreated: "formGroupCreated" }, ngImport: i0, template: "<div [class]=\"'gform_wrapper ' + config.formClass\">\n\n @if (error) {\n <div class=\"gform_validation_errors\">\n <h2 class=\"gform_submission_error hide_summary\">{{error}}</h2>\n </div>\n }\n\n @if (config.title) {\n <div class=\"gform_heading\">\n <h2 class=\"gform_title\">{{ config.title }}</h2>\n </div>\n }\n\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n\n <div class=\"gform_fields\">\n\n @for (field of config.fields; track field.name) {\n <div class=\"gfield gfield--width-{{field.size}}\" [class.gform_hidden]=\"field.type === 'hidden'\"\n [class.gfield_error]=\"formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched\">\n <label class=\"gfield_label gform-field-label\" [for]=\"field.name\">{{ field.label }}</label>\n @switch (field.type) {\n @case ('textarea') {\n <textarea [id]=\"field.name\" [formControlName]=\"field.name\"></textarea>\n }\n @case ('select') {\n <select [formControlName]=\"field.name\" [id]=\"field.name\">\n <!-- Render grouped options -->\n @for (group of groupedOptions[field.name]; track group) {\n <optgroup [label]=\"group.groupLabel\">\n @for (option of group.options; track option) {\n <option [value]=\"option.value\">\n {{ option.label }}\n </option>\n }\n </optgroup>\n }\n <!-- Render flat options -->\n @for (option of flatOptions[field.name]; track option) {\n <option [value]=\"option.value\">\n {{ option.label }}\n </option>\n }\n </select>\n }\n @default {\n <input [formControlName]=\"field.name\" [id]=\"field.name\" [type]=\"field.type\"\n [autocomplete]=\"field.autocomplete ?? ''\" />\n }\n }\n @if (formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\n <div class=\"gfield_description validation_message gfield_validation_message\"\n >\n @if (formGroup.get(field.name)?.errors?.['required']) {\n This field is required.\n }\n @if (formGroup.get(field.name)?.errors?.['email']) {\n Please enter a valid email\n address.\n }\n @if (formGroup.get(field.name)?.errors?.['minlength']) {\n Minimum length is {{ formGroup.get(field.name)?.errors?.['minlength'].requiredLength }} characters.\n }\n @if (formGroup.get(field.name)?.errors?.['maxlength']) {\n Maximum length is {{ formGroup.get(field.name)?.errors?.['maxlength'].requiredLength }} characters.\n }\n @if (formGroup.get(field.name)?.errors?.['pattern']) {\n Please match the required format.\n }\n </div>\n }\n @if (field.validationMessages && formGroup.invalid && !formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\n @for (error of formGroup.errors | keyvalue; track error) {\n @if (field.validationMessages[error.key]) {\n <div\n class=\"gfield_description validation_message gfield_validation_message\">\n {{ field.validationMessages[error.key] }}\n </div>\n }\n }\n }\n </div>\n }\n </div>\n\n <div class=\"gform_footer\">\n <ptr-button buttonType=\"submit\" [isDisabled]=\"loading || !formGroup.valid\">{{config.submitText}}</ptr-button>\n </div>\n\n </form>\n </div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i2.NgSelectOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.ɵNgSelectMultipleOption, selector: "option", inputs: ["ngValue", "value"] }, { kind: "directive", type: i2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i2.SelectControlValueAccessor, selector: "select:not([multiple])[formControlName],select:not([multiple])[formControl],select:not([multiple])[ngModel]", inputs: ["compareWith"] }, { kind: "directive", type: i2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PtrButtonComponent, selector: "ptr-button", inputs: ["buttonStyle", "buttonType", "isDisabled", "hrefLink", "routerLinkValue", "extraClasses", "isSmallSize", "isIconButton"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
571
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrFormComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
572
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PtrFormComponent, isStandalone: true, selector: "ptr-form", inputs: { config: "config", loading: "loading", error: "error" }, outputs: { formSubmit: "formSubmit", formGroupCreated: "formGroupCreated" }, ngImport: i0, template: "<div [class]=\"'gform_wrapper ' + config.formClass\">\r\n\r\n @if (error) {\r\n <div class=\"gform_validation_errors\">\r\n <h2 class=\"gform_submission_error hide_summary\">{{error}}</h2>\r\n </div>\r\n }\r\n\r\n @if (config.title) {\r\n <div class=\"gform_heading\">\r\n <h2 class=\"gform_title\">{{ config.title }}</h2>\r\n </div>\r\n }\r\n\r\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\r\n\r\n <div class=\"gform_fields\">\r\n\r\n @for (field of config.fields; track field.name) {\r\n <div class=\"gfield gfield--width-{{field.size}}\" [class.gform_hidden]=\"field.type === 'hidden'\"\r\n [class.gfield_error]=\"formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched\">\r\n\r\n @switch (field.type) {\r\n @case ('textarea') {\r\n <label class=\"gfield_label gform-field-label\" [for]=\"field.name\">{{ field.label }}</label>\r\n <textarea [id]=\"field.name\" [formControlName]=\"field.name\" [attr.placeholder]=\"field.placeholder || null\"></textarea>\r\n }\r\n @case ('select') {\r\n <ptr-select [label]=\"field.label\" [formControlName]=\"field.name\" [options]=\"field.options\" [placeholder]=\"field.placeholder\"></ptr-select>\r\n }\r\n @default {\r\n <ptr-input [label]=\"field.label\" [formControlName]=\"field.name\" [type]=\"field.type\" [placeholder]=\"field.placeholder\"\r\n [autocomplete]=\"field.autocomplete\" [searchFn]=\"field.searchFn\" [dialogHelpText]=\"field.dialogHelpText\" />\r\n }\r\n }\r\n\r\n @if (formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\r\n <div class=\"gfield_description validation_message gfield_validation_message\"\r\n >\r\n @if (formGroup.get(field.name)?.errors?.['required']) {\r\n This field is required.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['email']) {\r\n Please enter a valid email address.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['minlength']) {\r\n Minimum length is {{ formGroup.get(field.name)?.errors?.['minlength'].requiredLength }} characters.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['maxlength']) {\r\n Maximum length is {{ formGroup.get(field.name)?.errors?.['maxlength'].requiredLength }} characters.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['pattern']) {\r\n Please match the required format.\r\n }\r\n </div>\r\n }\r\n @if (field.validationMessages && formGroup.invalid && !formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\r\n @for (error of formGroup.errors | keyvalue; track error) {\r\n @if (field.validationMessages[error.key]) {\r\n <div\r\n class=\"gfield_description validation_message gfield_validation_message\">\r\n {{ field.validationMessages[error.key] }}\r\n </div>\r\n }\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if(config.submitText){\r\n <div class=\"gform_footer\">\r\n <ptr-button buttonType=\"submit\" [isDisabled]=\"loading || !formGroup.valid\">{{config.submitText}}</ptr-button>\r\n </div>\r\n }\r\n\r\n </form>\r\n </div>\r\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.KeyValuePipe, name: "keyvalue" }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "directive", type: i1$2.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1$2.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1$2.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1$2.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1$2.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1$2.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "component", type: PtrButtonComponent, selector: "ptr-button", inputs: ["buttonStyle", "buttonType", "isDisabled", "hrefLink", "routerLinkValue", "extraClasses", "isSmallSize", "isIconButton"], outputs: ["clicked"] }, { kind: "component", type: PtrSelectComponent, selector: "ptr-select", inputs: ["options", "showSearch", "placeholder", "label"], outputs: ["selectionChange"] }, { kind: "component", type: PtrInputComponent, selector: "ptr-input", inputs: ["type", "label", "placeholder", "autocomplete", "dialogHelpText", "searchFn"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
186
573
  }
187
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrFormComponent, decorators: [{
574
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrFormComponent, decorators: [{
188
575
  type: Component,
189
576
  args: [{ selector: 'ptr-form', standalone: true, imports: [
190
577
  CommonModule,
191
578
  ReactiveFormsModule,
192
- PtrButtonComponent
193
- ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"'gform_wrapper ' + config.formClass\">\n\n @if (error) {\n <div class=\"gform_validation_errors\">\n <h2 class=\"gform_submission_error hide_summary\">{{error}}</h2>\n </div>\n }\n\n @if (config.title) {\n <div class=\"gform_heading\">\n <h2 class=\"gform_title\">{{ config.title }}</h2>\n </div>\n }\n\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\n\n <div class=\"gform_fields\">\n\n @for (field of config.fields; track field.name) {\n <div class=\"gfield gfield--width-{{field.size}}\" [class.gform_hidden]=\"field.type === 'hidden'\"\n [class.gfield_error]=\"formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched\">\n <label class=\"gfield_label gform-field-label\" [for]=\"field.name\">{{ field.label }}</label>\n @switch (field.type) {\n @case ('textarea') {\n <textarea [id]=\"field.name\" [formControlName]=\"field.name\"></textarea>\n }\n @case ('select') {\n <select [formControlName]=\"field.name\" [id]=\"field.name\">\n <!-- Render grouped options -->\n @for (group of groupedOptions[field.name]; track group) {\n <optgroup [label]=\"group.groupLabel\">\n @for (option of group.options; track option) {\n <option [value]=\"option.value\">\n {{ option.label }}\n </option>\n }\n </optgroup>\n }\n <!-- Render flat options -->\n @for (option of flatOptions[field.name]; track option) {\n <option [value]=\"option.value\">\n {{ option.label }}\n </option>\n }\n </select>\n }\n @default {\n <input [formControlName]=\"field.name\" [id]=\"field.name\" [type]=\"field.type\"\n [autocomplete]=\"field.autocomplete ?? ''\" />\n }\n }\n @if (formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\n <div class=\"gfield_description validation_message gfield_validation_message\"\n >\n @if (formGroup.get(field.name)?.errors?.['required']) {\n This field is required.\n }\n @if (formGroup.get(field.name)?.errors?.['email']) {\n Please enter a valid email\n address.\n }\n @if (formGroup.get(field.name)?.errors?.['minlength']) {\n Minimum length is {{ formGroup.get(field.name)?.errors?.['minlength'].requiredLength }} characters.\n }\n @if (formGroup.get(field.name)?.errors?.['maxlength']) {\n Maximum length is {{ formGroup.get(field.name)?.errors?.['maxlength'].requiredLength }} characters.\n }\n @if (formGroup.get(field.name)?.errors?.['pattern']) {\n Please match the required format.\n }\n </div>\n }\n @if (field.validationMessages && formGroup.invalid && !formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\n @for (error of formGroup.errors | keyvalue; track error) {\n @if (field.validationMessages[error.key]) {\n <div\n class=\"gfield_description validation_message gfield_validation_message\">\n {{ field.validationMessages[error.key] }}\n </div>\n }\n }\n }\n </div>\n }\n </div>\n\n <div class=\"gform_footer\">\n <ptr-button buttonType=\"submit\" [isDisabled]=\"loading || !formGroup.valid\">{{config.submitText}}</ptr-button>\n </div>\n\n </form>\n </div>\n" }]
579
+ PtrButtonComponent,
580
+ PtrSelectComponent,
581
+ PtrInputComponent
582
+ ], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div [class]=\"'gform_wrapper ' + config.formClass\">\r\n\r\n @if (error) {\r\n <div class=\"gform_validation_errors\">\r\n <h2 class=\"gform_submission_error hide_summary\">{{error}}</h2>\r\n </div>\r\n }\r\n\r\n @if (config.title) {\r\n <div class=\"gform_heading\">\r\n <h2 class=\"gform_title\">{{ config.title }}</h2>\r\n </div>\r\n }\r\n\r\n <form [formGroup]=\"formGroup\" (ngSubmit)=\"onSubmit()\">\r\n\r\n <div class=\"gform_fields\">\r\n\r\n @for (field of config.fields; track field.name) {\r\n <div class=\"gfield gfield--width-{{field.size}}\" [class.gform_hidden]=\"field.type === 'hidden'\"\r\n [class.gfield_error]=\"formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched\">\r\n\r\n @switch (field.type) {\r\n @case ('textarea') {\r\n <label class=\"gfield_label gform-field-label\" [for]=\"field.name\">{{ field.label }}</label>\r\n <textarea [id]=\"field.name\" [formControlName]=\"field.name\" [attr.placeholder]=\"field.placeholder || null\"></textarea>\r\n }\r\n @case ('select') {\r\n <ptr-select [label]=\"field.label\" [formControlName]=\"field.name\" [options]=\"field.options\" [placeholder]=\"field.placeholder\"></ptr-select>\r\n }\r\n @default {\r\n <ptr-input [label]=\"field.label\" [formControlName]=\"field.name\" [type]=\"field.type\" [placeholder]=\"field.placeholder\"\r\n [autocomplete]=\"field.autocomplete\" [searchFn]=\"field.searchFn\" [dialogHelpText]=\"field.dialogHelpText\" />\r\n }\r\n }\r\n\r\n @if (formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\r\n <div class=\"gfield_description validation_message gfield_validation_message\"\r\n >\r\n @if (formGroup.get(field.name)?.errors?.['required']) {\r\n This field is required.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['email']) {\r\n Please enter a valid email address.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['minlength']) {\r\n Minimum length is {{ formGroup.get(field.name)?.errors?.['minlength'].requiredLength }} characters.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['maxlength']) {\r\n Maximum length is {{ formGroup.get(field.name)?.errors?.['maxlength'].requiredLength }} characters.\r\n }\r\n @if (formGroup.get(field.name)?.errors?.['pattern']) {\r\n Please match the required format.\r\n }\r\n </div>\r\n }\r\n @if (field.validationMessages && formGroup.invalid && !formGroup.get(field.name)?.invalid && formGroup.get(field.name)?.touched) {\r\n @for (error of formGroup.errors | keyvalue; track error) {\r\n @if (field.validationMessages[error.key]) {\r\n <div\r\n class=\"gfield_description validation_message gfield_validation_message\">\r\n {{ field.validationMessages[error.key] }}\r\n </div>\r\n }\r\n }\r\n }\r\n </div>\r\n }\r\n </div>\r\n\r\n @if(config.submitText){\r\n <div class=\"gform_footer\">\r\n <ptr-button buttonType=\"submit\" [isDisabled]=\"loading || !formGroup.valid\">{{config.submitText}}</ptr-button>\r\n </div>\r\n }\r\n\r\n </form>\r\n </div>\r\n" }]
194
583
  }], propDecorators: { config: [{
195
584
  type: Input
196
585
  }], loading: [{
@@ -207,16 +596,25 @@ class PtrTitleComponent {
207
596
  router = inject(Router);
208
597
  activatedRoute = inject(ActivatedRoute);
209
598
  titleStrategy = inject(TitleStrategy);
210
- title$;
599
+ displayTitle$;
211
600
  hideTitle$;
212
601
  ngOnInit() {
213
602
  const routeEvents$ = this.router.events.pipe(filter((event) => event instanceof NavigationEnd), map(() => this.getRoute(this.activatedRoute)));
214
603
  this.hideTitle$ = routeEvents$.pipe(map(route => !!route.snapshot.data['hideTitle']));
215
- this.title$ = routeEvents$.pipe(map(route => {
604
+ this.displayTitle$ = routeEvents$.pipe(map(route => {
216
605
  if (route.snapshot.data['hideTitle']) {
217
606
  return '';
218
607
  }
219
- return this.titleStrategy.getResolvedTitleForRoute(route.snapshot) || '';
608
+ // Check for a custom display title in the route data
609
+ const customDisplayTitle = route.snapshot.data['displayTitle'];
610
+ if (customDisplayTitle) {
611
+ return customDisplayTitle;
612
+ }
613
+ // If no custom display title, use the resolved title from TitleStrategy
614
+ const resolvedTitle = this.titleStrategy.getResolvedTitleForRoute(route.snapshot) || '';
615
+ return resolvedTitle;
616
+ // Remove any common suffix (checking for both ' | ' and ' - ' separators)
617
+ // return this.removeCommonSuffix(resolvedTitle);
220
618
  }));
221
619
  }
222
620
  getRoute(route) {
@@ -225,25 +623,35 @@ class PtrTitleComponent {
225
623
  }
226
624
  return route;
227
625
  }
228
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
229
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.4", type: PtrTitleComponent, isStandalone: true, selector: "ptr-title", ngImport: i0, template: '@if (!(hideTitle$ | async)) {<header class="entry-header is-layout-constrained my-3"><h1 class="entry-title">{{ title$ | async }}</h1></header>}', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
626
+ removeCommonSuffix(title) {
627
+ const separators = [' | ', ' - '];
628
+ for (const separator of separators) {
629
+ const parts = title.split(separator);
630
+ if (parts.length > 1) {
631
+ return parts[0].trim();
632
+ }
633
+ }
634
+ return title.trim();
635
+ }
636
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrTitleComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
637
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.0", type: PtrTitleComponent, isStandalone: true, selector: "ptr-title", ngImport: i0, template: '@if ((hideTitle$|async) === false) {<header class="entry-header is-layout-constrained my-3"><h1 class="entry-title">{{ displayTitle$ | async }}</h1></header>}', isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "pipe", type: i1$1.AsyncPipe, name: "async" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
230
638
  }
231
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrTitleComponent, decorators: [{
639
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrTitleComponent, decorators: [{
232
640
  type: Component,
233
641
  args: [{
234
642
  selector: 'ptr-title',
235
643
  standalone: true,
236
644
  imports: [CommonModule],
237
- template: '@if (!(hideTitle$ | async)) {<header class="entry-header is-layout-constrained my-3"><h1 class="entry-title">{{ title$ | async }}</h1></header>}',
645
+ template: '@if ((hideTitle$|async) === false) {<header class="entry-header is-layout-constrained my-3"><h1 class="entry-title">{{ displayTitle$ | async }}</h1></header>}',
238
646
  changeDetection: ChangeDetectionStrategy.OnPush
239
647
  }]
240
648
  }] });
241
649
 
242
650
  class PtrLoadingSpinnerComponent {
243
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
244
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.4", type: PtrLoadingSpinnerComponent, isStandalone: true, selector: "ptr-loading-spinner", ngImport: i0, template: `<div class="vdx-progress-spinner"></div>`, isInline: true, styles: [":host{display:inline-block;line-height:0}.vdx-progress-spinner{display:inline-block;width:25px;height:25px;transform:scaleZ(1)}.vdx-progress-spinner:before{position:absolute;content:\"\";background-image:url(\"data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 40 40' style='enable-background:new 0 0 40 40;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23272e3e;%7D%0A%3C/style%3E%3Ccircle class='st0' cx='34' cy='6' r='6'/%3E%3Ccircle class='st0' cx='6' cy='6' r='6'/%3E%3Ccircle class='st0' cx='6' cy='34' r='6'/%3E%3Ccircle class='st0' cx='34' cy='34' r='6'/%3E%3C/svg%3E\");height:40px;width:40px;left:-8px;top:-8px;border:none;display:block;animation:loader-anim 1.5s 0s ease-in-out infinite}.vdx-progress-spinner:after{content:\"\";position:absolute;height:12px;width:12px;border:none;border-radius:12px;display:block;left:6px;top:6px;background-color:#272e3e;animation:loader-anim-dot 1.5s 0s ease-in-out infinite}@keyframes loader-anim{0%{transform:rotate(0) scale(0);opacity:.5}50%{transform:rotate(180deg) scale(1);opacity:1}to{transform:rotate(360deg) scale(0);opacity:.2}}@keyframes loader-anim-dot{0%{opacity:1}50%{opacity:0}to{opacity:1}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
651
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingSpinnerComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
652
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: PtrLoadingSpinnerComponent, isStandalone: true, selector: "ptr-loading-spinner", ngImport: i0, template: `<div class="vdx-progress-spinner"></div>`, isInline: true, styles: [":host{display:inline-block;line-height:0}.vdx-progress-spinner{display:inline-block;width:25px;height:25px;transform:scaleZ(1)}.vdx-progress-spinner:before{position:absolute;content:\"\";background-image:url(\"data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 40 40' style='enable-background:new 0 0 40 40;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23272e3e;%7D%0A%3C/style%3E%3Ccircle class='st0' cx='34' cy='6' r='6'/%3E%3Ccircle class='st0' cx='6' cy='6' r='6'/%3E%3Ccircle class='st0' cx='6' cy='34' r='6'/%3E%3Ccircle class='st0' cx='34' cy='34' r='6'/%3E%3C/svg%3E\");height:40px;width:40px;left:-8px;top:-8px;border:none;display:block;animation:loader-anim 1.5s 0s ease-in-out infinite}.vdx-progress-spinner:after{content:\"\";position:absolute;height:12px;width:12px;border:none;border-radius:12px;display:block;left:6px;top:6px;background-color:#272e3e;animation:loader-anim-dot 1.5s 0s ease-in-out infinite}@keyframes loader-anim{0%{transform:rotate(0) scale(0);opacity:.5}50%{transform:rotate(180deg) scale(1);opacity:1}to{transform:rotate(360deg) scale(0);opacity:.2}}@keyframes loader-anim-dot{0%{opacity:1}50%{opacity:0}to{opacity:1}}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
245
653
  }
246
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingSpinnerComponent, decorators: [{
654
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingSpinnerComponent, decorators: [{
247
655
  type: Component,
248
656
  args: [{ selector: 'ptr-loading-spinner', standalone: true, imports: [], template: `<div class="vdx-progress-spinner"></div>`, changeDetection: ChangeDetectionStrategy.OnPush, styles: [":host{display:inline-block;line-height:0}.vdx-progress-spinner{display:inline-block;width:25px;height:25px;transform:scaleZ(1)}.vdx-progress-spinner:before{position:absolute;content:\"\";background-image:url(\"data:image/svg+xml,%3Csvg version='1.1' id='Layer_1' xmlns='http://www.w3.org/2000/svg' xmlns:xlink='http://www.w3.org/1999/xlink' x='0px' y='0px' viewBox='0 0 40 40' style='enable-background:new 0 0 40 40;' xml:space='preserve'%3E%3Cstyle type='text/css'%3E .st0%7Bfill:%23272e3e;%7D%0A%3C/style%3E%3Ccircle class='st0' cx='34' cy='6' r='6'/%3E%3Ccircle class='st0' cx='6' cy='6' r='6'/%3E%3Ccircle class='st0' cx='6' cy='34' r='6'/%3E%3Ccircle class='st0' cx='34' cy='34' r='6'/%3E%3C/svg%3E\");height:40px;width:40px;left:-8px;top:-8px;border:none;display:block;animation:loader-anim 1.5s 0s ease-in-out infinite}.vdx-progress-spinner:after{content:\"\";position:absolute;height:12px;width:12px;border:none;border-radius:12px;display:block;left:6px;top:6px;background-color:#272e3e;animation:loader-anim-dot 1.5s 0s ease-in-out infinite}@keyframes loader-anim{0%{transform:rotate(0) scale(0);opacity:.5}50%{transform:rotate(180deg) scale(1);opacity:1}to{transform:rotate(360deg) scale(0);opacity:.2}}@keyframes loader-anim-dot{0%{opacity:1}50%{opacity:0}to{opacity:1}}\n"] }]
249
657
  }] });
@@ -311,10 +719,10 @@ class PtrLoadingSpinnerDirective {
311
719
  removeBlurEffect() {
312
720
  this.renderer.removeClass(this.targetEl.nativeElement, 'ptr-loading-blur');
313
721
  }
314
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingSpinnerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
315
- static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.1.4", type: PtrLoadingSpinnerDirective, isStandalone: true, selector: "[ptrLoadingSpinner]", inputs: { ptrLoadingSpinner: "ptrLoadingSpinner" }, host: { properties: { "style.position": "this.hostPosition" } }, ngImport: i0 });
722
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingSpinnerDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive });
723
+ static ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "18.2.0", type: PtrLoadingSpinnerDirective, isStandalone: true, selector: "[ptrLoadingSpinner]", inputs: { ptrLoadingSpinner: "ptrLoadingSpinner" }, host: { properties: { "style.position": "this.hostPosition" } }, ngImport: i0 });
316
724
  }
317
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingSpinnerDirective, decorators: [{
725
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingSpinnerDirective, decorators: [{
318
726
  type: Directive,
319
727
  args: [{
320
728
  selector: '[ptrLoadingSpinner]',
@@ -399,10 +807,10 @@ class PtrLoadingService {
399
807
  updateTaskCount(taskCount, increment) {
400
808
  taskCount.update(count => increment ? count + 1 : Math.max(0, count - 1));
401
809
  }
402
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
403
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingService, providedIn: 'root' });
810
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingService, deps: [], target: i0.ɵɵFactoryTarget.Injectable });
811
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingService, providedIn: 'root' });
404
812
  }
405
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrLoadingService, decorators: [{
813
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrLoadingService, decorators: [{
406
814
  type: Injectable,
407
815
  args: [{
408
816
  providedIn: 'root'
@@ -428,10 +836,10 @@ class PtrDialogComponent {
428
836
  onClose() {
429
837
  this.closed.emit(null);
430
838
  }
431
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
432
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.4", type: PtrDialogComponent, isStandalone: true, selector: "ptr-dialog", inputs: { message: "message", buttonText: "buttonText", buttonStyle: "buttonStyle" }, outputs: { closed: "closed" }, viewQueries: [{ propertyName: "dialogElement", first: true, predicate: ["dialogElement"], descendants: true }], ngImport: i0, template: "<dialog #dialogElement class=\"ptr-modal\" (close)=\"onClose()\">\r\n <div class=\"ptr-modal__content\">\r\n <button class=\"ptr-modal__close\" (click)=\"close()\" aria-label=\"Close dialog\">\r\n &times;\r\n </button>\r\n <p>{{ message }}</p>\r\n <div class=\"ptr-modal__actions\">\r\n <ptr-button [buttonStyle]=\"buttonStyle\" (clicked)=\"confirm()\" [isSmallSize]=\"true\">{{buttonText}}</ptr-button>\r\n </div>\r\n </div>\r\n</dialog>", styles: [".ptr-modal{border-radius:var(--wp--custom--default-border-radius);border:none;padding:1rem}.ptr-modal__content{padding:1rem;position:relative}.ptr-modal__close{position:absolute;right:0;top:0;background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;line-height:1rem}.ptr-modal__actions{margin-top:20px;text-align:right}dialog.ptr-modal{opacity:0;transition:all .7s allow-discrete}dialog.ptr-modal[open]{opacity:1}dialog.ptr-modal::backdrop{background-color:#0000;transition:all .7s allow-discrete;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}dialog.ptr-modal[open]::backdrop{background-color:#0006}@starting-style{dialog[open]{opacity:0}}@starting-style{dialog[open]::backdrop{background-color:#0000}}\n"], dependencies: [{ kind: "component", type: PtrButtonComponent, selector: "ptr-button", inputs: ["buttonStyle", "buttonType", "isDisabled", "hrefLink", "routerLinkValue", "extraClasses", "isSmallSize", "isIconButton"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
839
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
840
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: PtrDialogComponent, isStandalone: true, selector: "ptr-dialog", inputs: { message: "message", buttonText: "buttonText", buttonStyle: "buttonStyle" }, outputs: { closed: "closed" }, viewQueries: [{ propertyName: "dialogElement", first: true, predicate: ["dialogElement"], descendants: true }], ngImport: i0, template: "<dialog #dialogElement class=\"ptr-modal\" (close)=\"onClose()\">\r\n <div class=\"ptr-modal__content\">\r\n <button class=\"ptr-modal__close\" (click)=\"close()\" aria-label=\"Close dialog\">\r\n &times;\r\n </button>\r\n <p>{{ message }}</p>\r\n <div class=\"ptr-modal__actions\">\r\n <ptr-button [buttonStyle]=\"buttonStyle\" (clicked)=\"confirm()\" [isSmallSize]=\"true\">{{buttonText}}</ptr-button>\r\n </div>\r\n </div>\r\n</dialog>", styles: [".ptr-modal{border-radius:var(--wp--custom--default-border-radius);border:none;padding:1rem}.ptr-modal__content{padding:1rem;position:relative}.ptr-modal__close{position:absolute;right:0;top:0;background:none;border:none;font-size:1.5rem;cursor:pointer;padding:0;line-height:1rem}.ptr-modal__actions{margin-top:20px;text-align:right}dialog.ptr-modal{opacity:0;transition:all .7s allow-discrete}dialog.ptr-modal[open]{opacity:1}dialog.ptr-modal::backdrop{background-color:#0000;transition:all .7s allow-discrete;-webkit-backdrop-filter:blur(2px);backdrop-filter:blur(2px)}dialog.ptr-modal[open]::backdrop{background-color:#0006}@starting-style{dialog[open]{opacity:0}}@starting-style{dialog[open]::backdrop{background-color:#0000}}\n"], dependencies: [{ kind: "component", type: PtrButtonComponent, selector: "ptr-button", inputs: ["buttonStyle", "buttonType", "isDisabled", "hrefLink", "routerLinkValue", "extraClasses", "isSmallSize", "isIconButton"], outputs: ["clicked"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
433
841
  }
434
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrDialogComponent, decorators: [{
842
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogComponent, decorators: [{
435
843
  type: Component,
436
844
  args: [{ selector: 'ptr-dialog', standalone: true, imports: [
437
845
  PtrButtonComponent
@@ -482,16 +890,17 @@ class PtrDialogService {
482
890
  this.dialogComponentRef = null;
483
891
  }
484
892
  }
485
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrDialogService, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable });
486
- static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrDialogService, providedIn: 'root' });
893
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogService, deps: [{ token: i0.ApplicationRef }, { token: i0.EnvironmentInjector }], target: i0.ɵɵFactoryTarget.Injectable });
894
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogService, providedIn: 'root' });
487
895
  }
488
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrDialogService, decorators: [{
896
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrDialogService, decorators: [{
489
897
  type: Injectable,
490
898
  args: [{
491
899
  providedIn: 'root'
492
900
  }]
493
901
  }], ctorParameters: () => [{ type: i0.ApplicationRef }, { type: i0.EnvironmentInjector }] });
494
902
 
903
+ /* eslint-disable @typescript-eslint/no-explicit-any */
495
904
  class PtrTooltipComponent {
496
905
  content = '';
497
906
  tooltipDialog;
@@ -508,10 +917,10 @@ class PtrTooltipComponent {
508
917
  this.tooltipDialog.nativeElement.close();
509
918
  }, 200); // Small delay to allow moving mouse to tooltip
510
919
  }
511
- static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
512
- static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.1.4", type: PtrTooltipComponent, isStandalone: true, selector: "ptr-tooltip", inputs: { content: "content" }, viewQueries: [{ propertyName: "tooltipDialog", first: true, predicate: ["tooltipDialog"], descendants: true }], ngImport: i0, template: "<span (mouseenter)=\"showTooltip()\" (mouseleave)=\"hideTooltip()\" class=\"tooltip-trigger\">\r\n <ng-content></ng-content>\r\n</span>\r\n<dialog #tooltipDialog class=\"ptr-tooltip\">\r\n <div class=\"ptr-tooltip__content\">{{ content }}</div>\r\n</dialog>", styles: [":host{display:inline-block;position:relative}.tooltip-trigger{cursor:help}.ptr-tooltip{position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:none;border-radius:3px;padding:.5rem .75rem;background-color:#212121;border:0;color:#fff;font-size:.875rem;max-width:15.5rem;min-width:12.5rem;z-index:1000;margin:0 0 8px;box-shadow:0 3px 6px #00000029,0 3px 6px #0000003b}.ptr-tooltip:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #212121}.ptr-tooltip__content{white-space:pre-wrap;text-align:center;line-height:1.5}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
920
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrTooltipComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
921
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.2.0", type: PtrTooltipComponent, isStandalone: true, selector: "ptr-tooltip", inputs: { content: "content" }, viewQueries: [{ propertyName: "tooltipDialog", first: true, predicate: ["tooltipDialog"], descendants: true }], ngImport: i0, template: "<span (mouseenter)=\"showTooltip()\" (mouseleave)=\"hideTooltip()\" class=\"tooltip-trigger\">\r\n <ng-content></ng-content>\r\n</span>\r\n<dialog #tooltipDialog class=\"ptr-tooltip\">\r\n <div class=\"ptr-tooltip__content\">{{ content }}</div>\r\n</dialog>", styles: [":host{display:inline-block;position:relative}.tooltip-trigger{cursor:help}.ptr-tooltip{position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:none;border-radius:3px;padding:.5rem .75rem;background-color:#212121;border:0;color:#fff;font-size:.875rem;max-width:15.5rem;min-width:12.5rem;z-index:1000;margin:0 0 8px;box-shadow:0 3px 6px #00000029,0 3px 6px #0000003b}.ptr-tooltip:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #212121}.ptr-tooltip__content{white-space:pre-wrap;text-align:center;line-height:1.5}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
513
922
  }
514
- i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImport: i0, type: PtrTooltipComponent, decorators: [{
923
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.0", ngImport: i0, type: PtrTooltipComponent, decorators: [{
515
924
  type: Component,
516
925
  args: [{ selector: 'ptr-tooltip', standalone: true, imports: [], changeDetection: ChangeDetectionStrategy.OnPush, template: "<span (mouseenter)=\"showTooltip()\" (mouseleave)=\"hideTooltip()\" class=\"tooltip-trigger\">\r\n <ng-content></ng-content>\r\n</span>\r\n<dialog #tooltipDialog class=\"ptr-tooltip\">\r\n <div class=\"ptr-tooltip__content\">{{ content }}</div>\r\n</dialog>", styles: [":host{display:inline-block;position:relative}.tooltip-trigger{cursor:help}.ptr-tooltip{position:absolute;bottom:100%;left:50%;transform:translate(-50%);border:none;border-radius:3px;padding:.5rem .75rem;background-color:#212121;border:0;color:#fff;font-size:.875rem;max-width:15.5rem;min-width:12.5rem;z-index:1000;margin:0 0 8px;box-shadow:0 3px 6px #00000029,0 3px 6px #0000003b}.ptr-tooltip:before{content:\"\";position:absolute;top:100%;left:50%;transform:translate(-50%);border-left:6px solid transparent;border-right:6px solid transparent;border-top:6px solid #212121}.ptr-tooltip__content{white-space:pre-wrap;text-align:center;line-height:1.5}\n"] }]
517
926
  }], propDecorators: { content: [{
@@ -529,5 +938,5 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.4", ngImpor
529
938
  * Generated bundle index. Do not edit.
530
939
  */
531
940
 
532
- export { PtrButtonComponent, PtrDialogComponent, PtrDialogService, PtrFormComponent, PtrLoadingService, PtrLoadingSpinnerComponent, PtrLoadingSpinnerDirective, PtrMenuComponent, PtrTitleComponent, PtrTooltipComponent };
941
+ export { PtrButtonComponent, PtrDialogComponent, PtrDialogService, PtrFormComponent, PtrInputComponent, PtrLoadingService, PtrLoadingSpinnerComponent, PtrLoadingSpinnerDirective, PtrMenuComponent, PtrSelectComponent, PtrTitleComponent, PtrTooltipComponent };
533
942
  //# sourceMappingURL=patter-ngx-components.mjs.map