@es.framework/ng.ui.core 2.0.65 → 2.0.66
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.
- package/README.md +3 -3
- package/attachments/README.md +3 -3
- package/base-crud/README.md +3 -3
- package/breadcrumb/README.md +3 -3
- package/checkbox/README.md +3 -3
- package/collapsible/README.md +3 -3
- package/color-picker/README.md +3 -3
- package/column-settings-popover/README.md +3 -3
- package/custom-switch/README.md +3 -3
- package/datepicker/README.md +3 -3
- package/deactivation-reason/README.md +3 -3
- package/excel-import/README.md +3 -3
- package/fesm2022/es.framework-ng.ui.core-attachments.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-attachments.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-base-crud.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-breadcrumb.mjs +108 -108
- package/fesm2022/es.framework-ng.ui.core-breadcrumb.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-checkbox.mjs +54 -54
- package/fesm2022/es.framework-ng.ui.core-checkbox.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-collapsible.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-color-picker.mjs +44 -44
- package/fesm2022/es.framework-ng.ui.core-color-picker.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-column-settings-popover.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-column-settings-popover.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-custom-switch.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-datepicker.mjs +178 -178
- package/fesm2022/es.framework-ng.ui.core-datepicker.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-deactivation-reason.mjs +46 -46
- package/fesm2022/es.framework-ng.ui.core-deactivation-reason.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-excel-import.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-filter-templates.mjs +624 -624
- package/fesm2022/es.framework-ng.ui.core-filter-templates.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-form-button.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-form-field.mjs +80 -80
- package/fesm2022/es.framework-ng.ui.core-form-field.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-form-template.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-image.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-label.mjs +44 -44
- package/fesm2022/es.framework-ng.ui.core-formly-avatar-label.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-button-selector.mjs +92 -92
- package/fesm2022/es.framework-ng.ui.core-formly-button-selector.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-button.mjs +24 -24
- package/fesm2022/es.framework-ng.ui.core-formly-button.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-presets.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-prime-icon-picker.mjs +366 -366
- package/fesm2022/es.framework-ng.ui.core-formly-prime-icon-picker.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-split-button.mjs +16 -16
- package/fesm2022/es.framework-ng.ui.core-formly-split-button.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-ui-all.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-ui.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-formly-username-with-domain.mjs +16 -16
- package/fesm2022/es.framework-ng.ui.core-formly-username-with-domain.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-assets.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-autocomplete.mjs +38 -38
- package/fesm2022/es.framework-ng.ui.core-generic-autocomplete.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-button.mjs +8 -2
- package/fesm2022/es.framework-ng.ui.core-generic-button.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-card.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-card.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-crud-table.mjs +14 -3
- package/fesm2022/es.framework-ng.ui.core-generic-crud-table.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-dialog.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-dialog.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-errormessage.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-errormessage.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-formly-fields.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-formly-fields.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-listbox.mjs +64 -64
- package/fesm2022/es.framework-ng.ui.core-generic-listbox.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-loadingspinner.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-loadingspinner.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-report-tabs.mjs +68 -68
- package/fesm2022/es.framework-ng.ui.core-generic-report-tabs.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-report.mjs +19 -3
- package/fesm2022/es.framework-ng.ui.core-generic-report.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-search-advanced.mjs +442 -442
- package/fesm2022/es.framework-ng.ui.core-generic-search-advanced.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-search.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-search.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-selector.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-table.mjs +16 -8
- package/fesm2022/es.framework-ng.ui.core-generic-table.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-generic-view.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-generic-view.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-header-wrapper.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-header-wrapper.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-icon-picker.mjs +106 -106
- package/fesm2022/es.framework-ng.ui.core-icon-picker.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-input-switch.mjs +58 -58
- package/fesm2022/es.framework-ng.ui.core-input-switch.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-input-with-icon.mjs +26 -26
- package/fesm2022/es.framework-ng.ui.core-input-with-icon.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-input.mjs +64 -64
- package/fesm2022/es.framework-ng.ui.core-input.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-label-type.mjs +16 -16
- package/fesm2022/es.framework-ng.ui.core-label-type.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-loading-skeletons.mjs +22 -22
- package/fesm2022/es.framework-ng.ui.core-loading-skeletons.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-odata-query-builder.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-odata-query-builder.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-query-type.mjs +14 -14
- package/fesm2022/es.framework-ng.ui.core-query-type.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-radio.mjs +30 -30
- package/fesm2022/es.framework-ng.ui.core-radio.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-repeat.mjs +354 -354
- package/fesm2022/es.framework-ng.ui.core-repeat.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-select.mjs +84 -84
- package/fesm2022/es.framework-ng.ui.core-select.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-sidebar-cards.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-sidebar-cards.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-sidebar-toggles.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core-sidebar-toggles.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-tabs.mjs +14 -14
- package/fesm2022/es.framework-ng.ui.core-tabs.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-tag-type.mjs +80 -80
- package/fesm2022/es.framework-ng.ui.core-tag-type.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-text-editor.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-textarea.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core-wrappers.mjs +118 -118
- package/fesm2022/es.framework-ng.ui.core-wrappers.mjs.map +1 -1
- package/fesm2022/es.framework-ng.ui.core.mjs +2 -2
- package/fesm2022/es.framework-ng.ui.core.mjs.map +1 -1
- package/filter-templates/README.md +3 -3
- package/form-button/README.md +3 -3
- package/form-field/README.md +3 -3
- package/form-template/README.md +3 -3
- package/formly-avatar-image/README.md +3 -3
- package/formly-avatar-label/README.md +3 -3
- package/formly-button/README.md +3 -3
- package/formly-button-selector/README.md +3 -3
- package/formly-presets/README.md +3 -3
- package/formly-prime-icon-picker/README.md +3 -3
- package/formly-split-button/README.md +3 -3
- package/formly-ui/README.md +3 -3
- package/formly-ui-all/README.md +3 -3
- package/formly-username-with-domain/README.md +3 -3
- package/generic-assets/README.md +3 -3
- package/generic-autocomplete/README.md +3 -3
- package/generic-button/README.md +3 -3
- package/generic-card/README.md +3 -3
- package/generic-crud-table/README.md +3 -3
- package/generic-dialog/README.md +3 -3
- package/generic-errormessage/README.md +3 -3
- package/generic-formly-fields/README.md +3 -3
- package/generic-loadingspinner/README.md +3 -3
- package/generic-report/README.md +3 -3
- package/generic-search/README.md +3 -3
- package/generic-search-advanced/README.md +3 -3
- package/generic-selector/README.md +3 -3
- package/generic-table/README.md +3 -3
- package/generic-view/README.md +3 -3
- package/header-wrapper/README.md +3 -3
- package/icon-picker/README.md +3 -3
- package/input/README.md +3 -3
- package/input-switch/README.md +3 -3
- package/input-with-icon/README.md +3 -3
- package/label-type/README.md +3 -3
- package/loading-skeletons/README.md +3 -3
- package/odata-query-builder/README.md +3 -3
- package/package.json +1 -1
- package/query-type/README.md +3 -3
- package/radio/README.md +3 -3
- package/repeat/README.md +3 -3
- package/select/README.md +3 -3
- package/sidebar-cards/README.md +3 -3
- package/sidebar-toggles/README.md +3 -3
- package/styles.css +0 -0
- package/tabs/README.md +3 -3
- package/tag-type/README.md +3 -3
- package/text-editor/README.md +3 -3
- package/textarea/README.md +3 -3
- package/types/es.framework-ng.ui.core-generic-button.d.ts +3 -1
- package/types/es.framework-ng.ui.core-generic-crud-table.d.ts +1 -0
- package/types/es.framework-ng.ui.core-generic-report.d.ts +1 -0
- package/types/es.framework-ng.ui.core-generic-table.d.ts +1 -1
- package/wrappers/README.md +3 -3
|
@@ -144,189 +144,189 @@ class PrimeIconPickerComponent extends FieldType {
|
|
|
144
144
|
trackIcon = (_, icon) => icon.class;
|
|
145
145
|
trackCategory = (_, cat) => cat.value || 'all';
|
|
146
146
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PrimeIconPickerComponent, deps: null, target: i0.ɵɵFactoryTarget.Component });
|
|
147
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: PrimeIconPickerComponent, isStandalone: true, selector: "formly-field-prime-icon-picker", viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
148
|
-
<div class="relative inline-block w-full max-w-[320px]">
|
|
149
|
-
<!-- Trigger -->
|
|
150
|
-
<button
|
|
151
|
-
type="button"
|
|
152
|
-
class="group w-full flex items-center gap-2 px-3 py-2.5 border rounded-lg shadow-sm
|
|
153
|
-
bg-white dark:bg-gray-800 dark:border-gray-700
|
|
154
|
-
hover:bg-gray-50 dark:hover:bg-gray-700
|
|
155
|
-
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
156
|
-
(click)="togglePopover($event)"
|
|
157
|
-
>
|
|
158
|
-
<span class="w-9 h-9 flex items-center justify-center rounded-md
|
|
159
|
-
bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700">
|
|
160
|
-
<i [ngClass]="selectedIconClass" class="text-lg"></i>
|
|
161
|
-
</span>
|
|
162
|
-
|
|
163
|
-
<div class="min-w-0 flex-1 text-left">
|
|
164
|
-
<div class="text-sm font-semibold text-gray-800 dark:text-gray-100 truncate">
|
|
165
|
-
{{ selectedIconName }}
|
|
166
|
-
</div>
|
|
167
|
-
<div class="text-[11px] text-gray-500 dark:text-gray-400 truncate">
|
|
168
|
-
{{ selectedIconClass }}
|
|
169
|
-
</div>
|
|
170
|
-
</div>
|
|
171
|
-
|
|
172
|
-
<i class="pi pi-chevron-down text-xs text-gray-500 dark:text-gray-300 transition-transform"
|
|
173
|
-
></i>
|
|
174
|
-
</button>
|
|
175
|
-
|
|
176
|
-
<!-- Popover -->
|
|
177
|
-
<p-popover
|
|
178
|
-
#popover
|
|
179
|
-
[appendTo]="'body'"
|
|
180
|
-
[style]="{ width: '420px', maxWidth: '95vw' }"
|
|
181
|
-
styleClass="shadow-2xl border border-gray-200 dark:border-gray-700 rounded-xl overflow-hidden"
|
|
182
|
-
>
|
|
183
|
-
<ng-template pTemplate="content">
|
|
184
|
-
<!-- Header -->
|
|
185
|
-
<div class="p-4 bg-white dark:bg-gray-800">
|
|
186
|
-
<div class="flex items-start justify-between gap-3">
|
|
187
|
-
<div>
|
|
188
|
-
<div class="text-sm font-bold text-gray-800 dark:text-gray-100">
|
|
189
|
-
Pick an icon
|
|
190
|
-
</div>
|
|
191
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
192
|
-
Search or choose a category
|
|
193
|
-
</div>
|
|
194
|
-
</div>
|
|
195
|
-
|
|
196
|
-
<button type="button"
|
|
197
|
-
class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
198
|
-
(click)="popover.hide()">
|
|
199
|
-
<i class="pi pi-times text-sm text-gray-600 dark:text-gray-300"></i>
|
|
200
|
-
</button>
|
|
201
|
-
</div>
|
|
202
|
-
|
|
203
|
-
<!-- Search + Select -->
|
|
204
|
-
<div class="mt-3 flex gap-2">
|
|
205
|
-
<div class="relative flex-1">
|
|
206
|
-
<i class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
|
|
207
|
-
|
|
208
|
-
<input
|
|
209
|
-
pInputText
|
|
210
|
-
type="text"
|
|
211
|
-
autocomplete="off"
|
|
212
|
-
placeholder="Search icons…"
|
|
213
|
-
[(ngModel)]="searchQuery"
|
|
214
|
-
(ngModelChange)="applyFilters()"
|
|
215
|
-
class="w-full pl-9 pr-9"
|
|
216
|
-
/>
|
|
217
|
-
|
|
218
|
-
<button *ngIf="searchQuery"
|
|
219
|
-
type="button"
|
|
220
|
-
class="absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
221
|
-
(click)="searchQuery=''; applyFilters()">
|
|
222
|
-
<i class="pi pi-times text-xs text-gray-500"></i>
|
|
223
|
-
</button>
|
|
224
|
-
</div>
|
|
225
|
-
|
|
226
|
-
<p-select
|
|
227
|
-
[options]="categories"
|
|
228
|
-
optionLabel="label"
|
|
229
|
-
optionValue="value"
|
|
230
|
-
[(ngModel)]="selectedCategory"
|
|
231
|
-
(ngModelChange)="applyFilters()"
|
|
232
|
-
placeholder="All"
|
|
233
|
-
[style]="{ width: '160px' }"
|
|
234
|
-
></p-select>
|
|
235
|
-
</div>
|
|
236
|
-
|
|
237
|
-
<!-- Category Chips -->
|
|
238
|
-
<div class="mt-3 flex flex-wrap gap-2">
|
|
239
|
-
<button
|
|
240
|
-
type="button"
|
|
241
|
-
*ngFor="let cat of categories; trackBy: trackCategory"
|
|
242
|
-
(click)="selectCategory(cat.value)"
|
|
243
|
-
class="px-3 py-1.5 text-xs rounded-full border transition
|
|
244
|
-
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
245
|
-
[ngClass]="{
|
|
246
|
-
'bg-blue-50 border-blue-300 text-blue-700 dark:bg-blue-900/40 dark:border-blue-700 dark:text-blue-200': selectedCategory === cat.value,
|
|
247
|
-
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-200': selectedCategory !== cat.value
|
|
248
|
-
}"
|
|
249
|
-
>
|
|
250
|
-
{{ cat.label }}
|
|
251
|
-
</button>
|
|
252
|
-
</div>
|
|
253
|
-
</div>
|
|
254
|
-
|
|
255
|
-
<!-- Divider -->
|
|
256
|
-
<div class="h-px bg-gray-200 dark:bg-gray-700"></div>
|
|
257
|
-
|
|
258
|
-
<!-- Grid -->
|
|
259
|
-
<div class="p-3 bg-gray-50 dark:bg-gray-900 max-h-[360px] overflow-y-auto">
|
|
260
|
-
<div *ngIf="filtered.length === 0" class="text-center py-10 text-gray-500">
|
|
261
|
-
<div class="text-sm font-semibold">No icons found</div>
|
|
262
|
-
<div class="text-xs">Try another keyword</div>
|
|
263
|
-
</div>
|
|
264
|
-
|
|
265
|
-
<div class="grid grid-cols-6 sm:grid-cols-7 gap-2">
|
|
266
|
-
<button
|
|
267
|
-
type="button"
|
|
268
|
-
*ngFor="let icon of filtered; trackBy: trackIcon"
|
|
269
|
-
(click)="onIconClick(icon, $event)"
|
|
270
|
-
class="relative group flex flex-col items-center justify-center gap-1.5
|
|
271
|
-
p-2.5 rounded-xl border transition
|
|
272
|
-
hover:shadow-sm hover:-translate-y-[1px]
|
|
273
|
-
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
274
|
-
[ngClass]="{
|
|
275
|
-
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700': formControl.value !== icon.class,
|
|
276
|
-
'bg-blue-50 dark:bg-blue-900/40 border-blue-400 dark:border-blue-700 ring-2 ring-blue-500/30': formControl.value === icon.class
|
|
277
|
-
}"
|
|
278
|
-
[title]="icon.name"
|
|
279
|
-
>
|
|
280
|
-
<i [ngClass]="icon.class" class="text-xl"></i>
|
|
281
|
-
|
|
282
|
-
<span class="text-[10px] text-gray-600 dark:text-gray-300 truncate w-full text-center">
|
|
283
|
-
{{ icon.name }}
|
|
284
|
-
</span>
|
|
285
|
-
|
|
286
|
-
<!-- Tooltip-like hover -->
|
|
287
|
-
<span
|
|
288
|
-
class="pointer-events-none absolute -top-2 left-1/2 -translate-x-1/2 -translate-y-full
|
|
289
|
-
opacity-0 group-hover:opacity-100 transition
|
|
290
|
-
px-2 py-1 text-[11px] rounded-md
|
|
291
|
-
bg-gray-900 text-white shadow-lg whitespace-nowrap"
|
|
292
|
-
>
|
|
293
|
-
{{ icon.class }}
|
|
294
|
-
</span>
|
|
295
|
-
</button>
|
|
296
|
-
</div>
|
|
297
|
-
</div>
|
|
298
|
-
|
|
299
|
-
<!-- Footer -->
|
|
300
|
-
<div class="px-4 py-3 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700">
|
|
301
|
-
<div class="flex items-center justify-between">
|
|
302
|
-
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
303
|
-
Showing <b class="text-gray-700 dark:text-gray-200">{{ filtered.length }}</b> icons
|
|
304
|
-
</span>
|
|
305
|
-
|
|
306
|
-
<div class="flex items-center gap-2">
|
|
307
|
-
<button
|
|
308
|
-
type="button"
|
|
309
|
-
class="px-3 py-1.5 text-xs rounded-md border border-gray-200 dark:border-gray-700
|
|
310
|
-
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
311
|
-
(click)="selectCategory(''); searchQuery=''; applyFilters()"
|
|
312
|
-
>
|
|
313
|
-
Reset
|
|
314
|
-
</button>
|
|
315
|
-
|
|
316
|
-
<button
|
|
317
|
-
type="button"
|
|
318
|
-
class="px-3 py-1.5 text-xs rounded-md bg-blue-600 text-white
|
|
319
|
-
hover:bg-blue-700"
|
|
320
|
-
(click)="popover.hide()"
|
|
321
|
-
>
|
|
322
|
-
Done
|
|
323
|
-
</button>
|
|
324
|
-
</div>
|
|
325
|
-
</div>
|
|
326
|
-
</div>
|
|
327
|
-
</ng-template>
|
|
328
|
-
</p-popover>
|
|
329
|
-
</div>
|
|
147
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.1.3", type: PrimeIconPickerComponent, isStandalone: true, selector: "formly-field-prime-icon-picker", viewQueries: [{ propertyName: "popover", first: true, predicate: ["popover"], descendants: true }], usesInheritance: true, ngImport: i0, template: `
|
|
148
|
+
<div class="relative inline-block w-full max-w-[320px]">
|
|
149
|
+
<!-- Trigger -->
|
|
150
|
+
<button
|
|
151
|
+
type="button"
|
|
152
|
+
class="group w-full flex items-center gap-2 px-3 py-2.5 border rounded-lg shadow-sm
|
|
153
|
+
bg-white dark:bg-gray-800 dark:border-gray-700
|
|
154
|
+
hover:bg-gray-50 dark:hover:bg-gray-700
|
|
155
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
156
|
+
(click)="togglePopover($event)"
|
|
157
|
+
>
|
|
158
|
+
<span class="w-9 h-9 flex items-center justify-center rounded-md
|
|
159
|
+
bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700">
|
|
160
|
+
<i [ngClass]="selectedIconClass" class="text-lg"></i>
|
|
161
|
+
</span>
|
|
162
|
+
|
|
163
|
+
<div class="min-w-0 flex-1 text-left">
|
|
164
|
+
<div class="text-sm font-semibold text-gray-800 dark:text-gray-100 truncate">
|
|
165
|
+
{{ selectedIconName }}
|
|
166
|
+
</div>
|
|
167
|
+
<div class="text-[11px] text-gray-500 dark:text-gray-400 truncate">
|
|
168
|
+
{{ selectedIconClass }}
|
|
169
|
+
</div>
|
|
170
|
+
</div>
|
|
171
|
+
|
|
172
|
+
<i class="pi pi-chevron-down text-xs text-gray-500 dark:text-gray-300 transition-transform"
|
|
173
|
+
></i>
|
|
174
|
+
</button>
|
|
175
|
+
|
|
176
|
+
<!-- Popover -->
|
|
177
|
+
<p-popover
|
|
178
|
+
#popover
|
|
179
|
+
[appendTo]="'body'"
|
|
180
|
+
[style]="{ width: '420px', maxWidth: '95vw' }"
|
|
181
|
+
styleClass="shadow-2xl border border-gray-200 dark:border-gray-700 rounded-xl overflow-hidden"
|
|
182
|
+
>
|
|
183
|
+
<ng-template pTemplate="content">
|
|
184
|
+
<!-- Header -->
|
|
185
|
+
<div class="p-4 bg-white dark:bg-gray-800">
|
|
186
|
+
<div class="flex items-start justify-between gap-3">
|
|
187
|
+
<div>
|
|
188
|
+
<div class="text-sm font-bold text-gray-800 dark:text-gray-100">
|
|
189
|
+
Pick an icon
|
|
190
|
+
</div>
|
|
191
|
+
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
192
|
+
Search or choose a category
|
|
193
|
+
</div>
|
|
194
|
+
</div>
|
|
195
|
+
|
|
196
|
+
<button type="button"
|
|
197
|
+
class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
198
|
+
(click)="popover.hide()">
|
|
199
|
+
<i class="pi pi-times text-sm text-gray-600 dark:text-gray-300"></i>
|
|
200
|
+
</button>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<!-- Search + Select -->
|
|
204
|
+
<div class="mt-3 flex gap-2">
|
|
205
|
+
<div class="relative flex-1">
|
|
206
|
+
<i class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
|
|
207
|
+
|
|
208
|
+
<input
|
|
209
|
+
pInputText
|
|
210
|
+
type="text"
|
|
211
|
+
autocomplete="off"
|
|
212
|
+
placeholder="Search icons…"
|
|
213
|
+
[(ngModel)]="searchQuery"
|
|
214
|
+
(ngModelChange)="applyFilters()"
|
|
215
|
+
class="w-full pl-9 pr-9"
|
|
216
|
+
/>
|
|
217
|
+
|
|
218
|
+
<button *ngIf="searchQuery"
|
|
219
|
+
type="button"
|
|
220
|
+
class="absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
221
|
+
(click)="searchQuery=''; applyFilters()">
|
|
222
|
+
<i class="pi pi-times text-xs text-gray-500"></i>
|
|
223
|
+
</button>
|
|
224
|
+
</div>
|
|
225
|
+
|
|
226
|
+
<p-select
|
|
227
|
+
[options]="categories"
|
|
228
|
+
optionLabel="label"
|
|
229
|
+
optionValue="value"
|
|
230
|
+
[(ngModel)]="selectedCategory"
|
|
231
|
+
(ngModelChange)="applyFilters()"
|
|
232
|
+
placeholder="All"
|
|
233
|
+
[style]="{ width: '160px' }"
|
|
234
|
+
></p-select>
|
|
235
|
+
</div>
|
|
236
|
+
|
|
237
|
+
<!-- Category Chips -->
|
|
238
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
239
|
+
<button
|
|
240
|
+
type="button"
|
|
241
|
+
*ngFor="let cat of categories; trackBy: trackCategory"
|
|
242
|
+
(click)="selectCategory(cat.value)"
|
|
243
|
+
class="px-3 py-1.5 text-xs rounded-full border transition
|
|
244
|
+
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
245
|
+
[ngClass]="{
|
|
246
|
+
'bg-blue-50 border-blue-300 text-blue-700 dark:bg-blue-900/40 dark:border-blue-700 dark:text-blue-200': selectedCategory === cat.value,
|
|
247
|
+
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-200': selectedCategory !== cat.value
|
|
248
|
+
}"
|
|
249
|
+
>
|
|
250
|
+
{{ cat.label }}
|
|
251
|
+
</button>
|
|
252
|
+
</div>
|
|
253
|
+
</div>
|
|
254
|
+
|
|
255
|
+
<!-- Divider -->
|
|
256
|
+
<div class="h-px bg-gray-200 dark:bg-gray-700"></div>
|
|
257
|
+
|
|
258
|
+
<!-- Grid -->
|
|
259
|
+
<div class="p-3 bg-gray-50 dark:bg-gray-900 max-h-[360px] overflow-y-auto">
|
|
260
|
+
<div *ngIf="filtered.length === 0" class="text-center py-10 text-gray-500">
|
|
261
|
+
<div class="text-sm font-semibold">No icons found</div>
|
|
262
|
+
<div class="text-xs">Try another keyword</div>
|
|
263
|
+
</div>
|
|
264
|
+
|
|
265
|
+
<div class="grid grid-cols-6 sm:grid-cols-7 gap-2">
|
|
266
|
+
<button
|
|
267
|
+
type="button"
|
|
268
|
+
*ngFor="let icon of filtered; trackBy: trackIcon"
|
|
269
|
+
(click)="onIconClick(icon, $event)"
|
|
270
|
+
class="relative group flex flex-col items-center justify-center gap-1.5
|
|
271
|
+
p-2.5 rounded-xl border transition
|
|
272
|
+
hover:shadow-sm hover:-translate-y-[1px]
|
|
273
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
274
|
+
[ngClass]="{
|
|
275
|
+
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700': formControl.value !== icon.class,
|
|
276
|
+
'bg-blue-50 dark:bg-blue-900/40 border-blue-400 dark:border-blue-700 ring-2 ring-blue-500/30': formControl.value === icon.class
|
|
277
|
+
}"
|
|
278
|
+
[title]="icon.name"
|
|
279
|
+
>
|
|
280
|
+
<i [ngClass]="icon.class" class="text-xl"></i>
|
|
281
|
+
|
|
282
|
+
<span class="text-[10px] text-gray-600 dark:text-gray-300 truncate w-full text-center">
|
|
283
|
+
{{ icon.name }}
|
|
284
|
+
</span>
|
|
285
|
+
|
|
286
|
+
<!-- Tooltip-like hover -->
|
|
287
|
+
<span
|
|
288
|
+
class="pointer-events-none absolute -top-2 left-1/2 -translate-x-1/2 -translate-y-full
|
|
289
|
+
opacity-0 group-hover:opacity-100 transition
|
|
290
|
+
px-2 py-1 text-[11px] rounded-md
|
|
291
|
+
bg-gray-900 text-white shadow-lg whitespace-nowrap"
|
|
292
|
+
>
|
|
293
|
+
{{ icon.class }}
|
|
294
|
+
</span>
|
|
295
|
+
</button>
|
|
296
|
+
</div>
|
|
297
|
+
</div>
|
|
298
|
+
|
|
299
|
+
<!-- Footer -->
|
|
300
|
+
<div class="px-4 py-3 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700">
|
|
301
|
+
<div class="flex items-center justify-between">
|
|
302
|
+
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
303
|
+
Showing <b class="text-gray-700 dark:text-gray-200">{{ filtered.length }}</b> icons
|
|
304
|
+
</span>
|
|
305
|
+
|
|
306
|
+
<div class="flex items-center gap-2">
|
|
307
|
+
<button
|
|
308
|
+
type="button"
|
|
309
|
+
class="px-3 py-1.5 text-xs rounded-md border border-gray-200 dark:border-gray-700
|
|
310
|
+
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
311
|
+
(click)="selectCategory(''); searchQuery=''; applyFilters()"
|
|
312
|
+
>
|
|
313
|
+
Reset
|
|
314
|
+
</button>
|
|
315
|
+
|
|
316
|
+
<button
|
|
317
|
+
type="button"
|
|
318
|
+
class="px-3 py-1.5 text-xs rounded-md bg-blue-600 text-white
|
|
319
|
+
hover:bg-blue-700"
|
|
320
|
+
(click)="popover.hide()"
|
|
321
|
+
>
|
|
322
|
+
Done
|
|
323
|
+
</button>
|
|
324
|
+
</div>
|
|
325
|
+
</div>
|
|
326
|
+
</div>
|
|
327
|
+
</ng-template>
|
|
328
|
+
</p-popover>
|
|
329
|
+
</div>
|
|
330
330
|
`, isInline: true, dependencies: [{ kind: "ngmodule", type: FormsModule }, { kind: "directive", type: i1.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.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgModel, selector: "[ngModel]:not([formControlName]):not([formControl])", inputs: ["name", "disabled", "ngModel", "ngModelOptions"], outputs: ["ngModelChange"], exportAs: ["ngModel"] }, { kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "ngmodule", type: ReactiveFormsModule }, { kind: "ngmodule", type: ButtonModule }, { kind: "directive", type: i3.PrimeTemplate, selector: "[pTemplate]", inputs: ["type", "pTemplate"] }, { kind: "ngmodule", type: InputTextModule }, { kind: "directive", type: i4.InputText, selector: "[pInputText]", inputs: ["hostName", "ptInputText", "pSize", "variant", "fluid", "invalid"] }, { kind: "ngmodule", type: SelectModule }, { kind: "component", type: i5.Select, selector: "p-select", inputs: ["id", "scrollHeight", "filter", "panelStyle", "styleClass", "panelStyleClass", "readonly", "editable", "tabindex", "placeholder", "loadingIcon", "filterPlaceholder", "filterLocale", "inputId", "dataKey", "filterBy", "filterFields", "autofocus", "resetFilterOnHide", "checkmark", "dropdownIcon", "loading", "optionLabel", "optionValue", "optionDisabled", "optionGroupLabel", "optionGroupChildren", "group", "showClear", "emptyFilterMessage", "emptyMessage", "lazy", "virtualScroll", "virtualScrollItemSize", "virtualScrollOptions", "overlayOptions", "ariaFilterLabel", "ariaLabel", "ariaLabelledBy", "filterMatchMode", "tooltip", "tooltipPosition", "tooltipPositionStyle", "tooltipStyleClass", "focusOnHover", "selectOnFocus", "autoOptionFocus", "autofocusFilter", "filterValue", "options", "appendTo"], outputs: ["onChange", "onFilter", "onFocus", "onBlur", "onClick", "onShow", "onHide", "onClear", "onLazyLoad"] }, { kind: "ngmodule", type: PopoverModule }, { kind: "component", type: i6.Popover, selector: "p-popover", inputs: ["ariaLabel", "ariaLabelledBy", "dismissable", "style", "styleClass", "appendTo", "autoZIndex", "ariaCloseLabel", "baseZIndex", "focusOnShow", "showTransitionOptions", "hideTransitionOptions"], outputs: ["onShow", "onHide"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
331
331
|
}
|
|
332
332
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImport: i0, type: PrimeIconPickerComponent, decorators: [{
|
|
@@ -344,189 +344,189 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.3", ngImpor
|
|
|
344
344
|
SelectModule,
|
|
345
345
|
PopoverModule,
|
|
346
346
|
],
|
|
347
|
-
template: `
|
|
348
|
-
<div class="relative inline-block w-full max-w-[320px]">
|
|
349
|
-
<!-- Trigger -->
|
|
350
|
-
<button
|
|
351
|
-
type="button"
|
|
352
|
-
class="group w-full flex items-center gap-2 px-3 py-2.5 border rounded-lg shadow-sm
|
|
353
|
-
bg-white dark:bg-gray-800 dark:border-gray-700
|
|
354
|
-
hover:bg-gray-50 dark:hover:bg-gray-700
|
|
355
|
-
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
356
|
-
(click)="togglePopover($event)"
|
|
357
|
-
>
|
|
358
|
-
<span class="w-9 h-9 flex items-center justify-center rounded-md
|
|
359
|
-
bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700">
|
|
360
|
-
<i [ngClass]="selectedIconClass" class="text-lg"></i>
|
|
361
|
-
</span>
|
|
362
|
-
|
|
363
|
-
<div class="min-w-0 flex-1 text-left">
|
|
364
|
-
<div class="text-sm font-semibold text-gray-800 dark:text-gray-100 truncate">
|
|
365
|
-
{{ selectedIconName }}
|
|
366
|
-
</div>
|
|
367
|
-
<div class="text-[11px] text-gray-500 dark:text-gray-400 truncate">
|
|
368
|
-
{{ selectedIconClass }}
|
|
369
|
-
</div>
|
|
370
|
-
</div>
|
|
371
|
-
|
|
372
|
-
<i class="pi pi-chevron-down text-xs text-gray-500 dark:text-gray-300 transition-transform"
|
|
373
|
-
></i>
|
|
374
|
-
</button>
|
|
375
|
-
|
|
376
|
-
<!-- Popover -->
|
|
377
|
-
<p-popover
|
|
378
|
-
#popover
|
|
379
|
-
[appendTo]="'body'"
|
|
380
|
-
[style]="{ width: '420px', maxWidth: '95vw' }"
|
|
381
|
-
styleClass="shadow-2xl border border-gray-200 dark:border-gray-700 rounded-xl overflow-hidden"
|
|
382
|
-
>
|
|
383
|
-
<ng-template pTemplate="content">
|
|
384
|
-
<!-- Header -->
|
|
385
|
-
<div class="p-4 bg-white dark:bg-gray-800">
|
|
386
|
-
<div class="flex items-start justify-between gap-3">
|
|
387
|
-
<div>
|
|
388
|
-
<div class="text-sm font-bold text-gray-800 dark:text-gray-100">
|
|
389
|
-
Pick an icon
|
|
390
|
-
</div>
|
|
391
|
-
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
392
|
-
Search or choose a category
|
|
393
|
-
</div>
|
|
394
|
-
</div>
|
|
395
|
-
|
|
396
|
-
<button type="button"
|
|
397
|
-
class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
398
|
-
(click)="popover.hide()">
|
|
399
|
-
<i class="pi pi-times text-sm text-gray-600 dark:text-gray-300"></i>
|
|
400
|
-
</button>
|
|
401
|
-
</div>
|
|
402
|
-
|
|
403
|
-
<!-- Search + Select -->
|
|
404
|
-
<div class="mt-3 flex gap-2">
|
|
405
|
-
<div class="relative flex-1">
|
|
406
|
-
<i class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
|
|
407
|
-
|
|
408
|
-
<input
|
|
409
|
-
pInputText
|
|
410
|
-
type="text"
|
|
411
|
-
autocomplete="off"
|
|
412
|
-
placeholder="Search icons…"
|
|
413
|
-
[(ngModel)]="searchQuery"
|
|
414
|
-
(ngModelChange)="applyFilters()"
|
|
415
|
-
class="w-full pl-9 pr-9"
|
|
416
|
-
/>
|
|
417
|
-
|
|
418
|
-
<button *ngIf="searchQuery"
|
|
419
|
-
type="button"
|
|
420
|
-
class="absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
421
|
-
(click)="searchQuery=''; applyFilters()">
|
|
422
|
-
<i class="pi pi-times text-xs text-gray-500"></i>
|
|
423
|
-
</button>
|
|
424
|
-
</div>
|
|
425
|
-
|
|
426
|
-
<p-select
|
|
427
|
-
[options]="categories"
|
|
428
|
-
optionLabel="label"
|
|
429
|
-
optionValue="value"
|
|
430
|
-
[(ngModel)]="selectedCategory"
|
|
431
|
-
(ngModelChange)="applyFilters()"
|
|
432
|
-
placeholder="All"
|
|
433
|
-
[style]="{ width: '160px' }"
|
|
434
|
-
></p-select>
|
|
435
|
-
</div>
|
|
436
|
-
|
|
437
|
-
<!-- Category Chips -->
|
|
438
|
-
<div class="mt-3 flex flex-wrap gap-2">
|
|
439
|
-
<button
|
|
440
|
-
type="button"
|
|
441
|
-
*ngFor="let cat of categories; trackBy: trackCategory"
|
|
442
|
-
(click)="selectCategory(cat.value)"
|
|
443
|
-
class="px-3 py-1.5 text-xs rounded-full border transition
|
|
444
|
-
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
445
|
-
[ngClass]="{
|
|
446
|
-
'bg-blue-50 border-blue-300 text-blue-700 dark:bg-blue-900/40 dark:border-blue-700 dark:text-blue-200': selectedCategory === cat.value,
|
|
447
|
-
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-200': selectedCategory !== cat.value
|
|
448
|
-
}"
|
|
449
|
-
>
|
|
450
|
-
{{ cat.label }}
|
|
451
|
-
</button>
|
|
452
|
-
</div>
|
|
453
|
-
</div>
|
|
454
|
-
|
|
455
|
-
<!-- Divider -->
|
|
456
|
-
<div class="h-px bg-gray-200 dark:bg-gray-700"></div>
|
|
457
|
-
|
|
458
|
-
<!-- Grid -->
|
|
459
|
-
<div class="p-3 bg-gray-50 dark:bg-gray-900 max-h-[360px] overflow-y-auto">
|
|
460
|
-
<div *ngIf="filtered.length === 0" class="text-center py-10 text-gray-500">
|
|
461
|
-
<div class="text-sm font-semibold">No icons found</div>
|
|
462
|
-
<div class="text-xs">Try another keyword</div>
|
|
463
|
-
</div>
|
|
464
|
-
|
|
465
|
-
<div class="grid grid-cols-6 sm:grid-cols-7 gap-2">
|
|
466
|
-
<button
|
|
467
|
-
type="button"
|
|
468
|
-
*ngFor="let icon of filtered; trackBy: trackIcon"
|
|
469
|
-
(click)="onIconClick(icon, $event)"
|
|
470
|
-
class="relative group flex flex-col items-center justify-center gap-1.5
|
|
471
|
-
p-2.5 rounded-xl border transition
|
|
472
|
-
hover:shadow-sm hover:-translate-y-[1px]
|
|
473
|
-
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
474
|
-
[ngClass]="{
|
|
475
|
-
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700': formControl.value !== icon.class,
|
|
476
|
-
'bg-blue-50 dark:bg-blue-900/40 border-blue-400 dark:border-blue-700 ring-2 ring-blue-500/30': formControl.value === icon.class
|
|
477
|
-
}"
|
|
478
|
-
[title]="icon.name"
|
|
479
|
-
>
|
|
480
|
-
<i [ngClass]="icon.class" class="text-xl"></i>
|
|
481
|
-
|
|
482
|
-
<span class="text-[10px] text-gray-600 dark:text-gray-300 truncate w-full text-center">
|
|
483
|
-
{{ icon.name }}
|
|
484
|
-
</span>
|
|
485
|
-
|
|
486
|
-
<!-- Tooltip-like hover -->
|
|
487
|
-
<span
|
|
488
|
-
class="pointer-events-none absolute -top-2 left-1/2 -translate-x-1/2 -translate-y-full
|
|
489
|
-
opacity-0 group-hover:opacity-100 transition
|
|
490
|
-
px-2 py-1 text-[11px] rounded-md
|
|
491
|
-
bg-gray-900 text-white shadow-lg whitespace-nowrap"
|
|
492
|
-
>
|
|
493
|
-
{{ icon.class }}
|
|
494
|
-
</span>
|
|
495
|
-
</button>
|
|
496
|
-
</div>
|
|
497
|
-
</div>
|
|
498
|
-
|
|
499
|
-
<!-- Footer -->
|
|
500
|
-
<div class="px-4 py-3 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700">
|
|
501
|
-
<div class="flex items-center justify-between">
|
|
502
|
-
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
503
|
-
Showing <b class="text-gray-700 dark:text-gray-200">{{ filtered.length }}</b> icons
|
|
504
|
-
</span>
|
|
505
|
-
|
|
506
|
-
<div class="flex items-center gap-2">
|
|
507
|
-
<button
|
|
508
|
-
type="button"
|
|
509
|
-
class="px-3 py-1.5 text-xs rounded-md border border-gray-200 dark:border-gray-700
|
|
510
|
-
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
511
|
-
(click)="selectCategory(''); searchQuery=''; applyFilters()"
|
|
512
|
-
>
|
|
513
|
-
Reset
|
|
514
|
-
</button>
|
|
515
|
-
|
|
516
|
-
<button
|
|
517
|
-
type="button"
|
|
518
|
-
class="px-3 py-1.5 text-xs rounded-md bg-blue-600 text-white
|
|
519
|
-
hover:bg-blue-700"
|
|
520
|
-
(click)="popover.hide()"
|
|
521
|
-
>
|
|
522
|
-
Done
|
|
523
|
-
</button>
|
|
524
|
-
</div>
|
|
525
|
-
</div>
|
|
526
|
-
</div>
|
|
527
|
-
</ng-template>
|
|
528
|
-
</p-popover>
|
|
529
|
-
</div>
|
|
347
|
+
template: `
|
|
348
|
+
<div class="relative inline-block w-full max-w-[320px]">
|
|
349
|
+
<!-- Trigger -->
|
|
350
|
+
<button
|
|
351
|
+
type="button"
|
|
352
|
+
class="group w-full flex items-center gap-2 px-3 py-2.5 border rounded-lg shadow-sm
|
|
353
|
+
bg-white dark:bg-gray-800 dark:border-gray-700
|
|
354
|
+
hover:bg-gray-50 dark:hover:bg-gray-700
|
|
355
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
356
|
+
(click)="togglePopover($event)"
|
|
357
|
+
>
|
|
358
|
+
<span class="w-9 h-9 flex items-center justify-center rounded-md
|
|
359
|
+
bg-gray-50 dark:bg-gray-900 border border-gray-200 dark:border-gray-700">
|
|
360
|
+
<i [ngClass]="selectedIconClass" class="text-lg"></i>
|
|
361
|
+
</span>
|
|
362
|
+
|
|
363
|
+
<div class="min-w-0 flex-1 text-left">
|
|
364
|
+
<div class="text-sm font-semibold text-gray-800 dark:text-gray-100 truncate">
|
|
365
|
+
{{ selectedIconName }}
|
|
366
|
+
</div>
|
|
367
|
+
<div class="text-[11px] text-gray-500 dark:text-gray-400 truncate">
|
|
368
|
+
{{ selectedIconClass }}
|
|
369
|
+
</div>
|
|
370
|
+
</div>
|
|
371
|
+
|
|
372
|
+
<i class="pi pi-chevron-down text-xs text-gray-500 dark:text-gray-300 transition-transform"
|
|
373
|
+
></i>
|
|
374
|
+
</button>
|
|
375
|
+
|
|
376
|
+
<!-- Popover -->
|
|
377
|
+
<p-popover
|
|
378
|
+
#popover
|
|
379
|
+
[appendTo]="'body'"
|
|
380
|
+
[style]="{ width: '420px', maxWidth: '95vw' }"
|
|
381
|
+
styleClass="shadow-2xl border border-gray-200 dark:border-gray-700 rounded-xl overflow-hidden"
|
|
382
|
+
>
|
|
383
|
+
<ng-template pTemplate="content">
|
|
384
|
+
<!-- Header -->
|
|
385
|
+
<div class="p-4 bg-white dark:bg-gray-800">
|
|
386
|
+
<div class="flex items-start justify-between gap-3">
|
|
387
|
+
<div>
|
|
388
|
+
<div class="text-sm font-bold text-gray-800 dark:text-gray-100">
|
|
389
|
+
Pick an icon
|
|
390
|
+
</div>
|
|
391
|
+
<div class="text-xs text-gray-500 dark:text-gray-400">
|
|
392
|
+
Search or choose a category
|
|
393
|
+
</div>
|
|
394
|
+
</div>
|
|
395
|
+
|
|
396
|
+
<button type="button"
|
|
397
|
+
class="p-2 rounded-md hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
398
|
+
(click)="popover.hide()">
|
|
399
|
+
<i class="pi pi-times text-sm text-gray-600 dark:text-gray-300"></i>
|
|
400
|
+
</button>
|
|
401
|
+
</div>
|
|
402
|
+
|
|
403
|
+
<!-- Search + Select -->
|
|
404
|
+
<div class="mt-3 flex gap-2">
|
|
405
|
+
<div class="relative flex-1">
|
|
406
|
+
<i class="pi pi-search absolute left-3 top-1/2 -translate-y-1/2 text-gray-400 text-sm"></i>
|
|
407
|
+
|
|
408
|
+
<input
|
|
409
|
+
pInputText
|
|
410
|
+
type="text"
|
|
411
|
+
autocomplete="off"
|
|
412
|
+
placeholder="Search icons…"
|
|
413
|
+
[(ngModel)]="searchQuery"
|
|
414
|
+
(ngModelChange)="applyFilters()"
|
|
415
|
+
class="w-full pl-9 pr-9"
|
|
416
|
+
/>
|
|
417
|
+
|
|
418
|
+
<button *ngIf="searchQuery"
|
|
419
|
+
type="button"
|
|
420
|
+
class="absolute right-2 top-1/2 -translate-y-1/2 p-1 rounded hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
421
|
+
(click)="searchQuery=''; applyFilters()">
|
|
422
|
+
<i class="pi pi-times text-xs text-gray-500"></i>
|
|
423
|
+
</button>
|
|
424
|
+
</div>
|
|
425
|
+
|
|
426
|
+
<p-select
|
|
427
|
+
[options]="categories"
|
|
428
|
+
optionLabel="label"
|
|
429
|
+
optionValue="value"
|
|
430
|
+
[(ngModel)]="selectedCategory"
|
|
431
|
+
(ngModelChange)="applyFilters()"
|
|
432
|
+
placeholder="All"
|
|
433
|
+
[style]="{ width: '160px' }"
|
|
434
|
+
></p-select>
|
|
435
|
+
</div>
|
|
436
|
+
|
|
437
|
+
<!-- Category Chips -->
|
|
438
|
+
<div class="mt-3 flex flex-wrap gap-2">
|
|
439
|
+
<button
|
|
440
|
+
type="button"
|
|
441
|
+
*ngFor="let cat of categories; trackBy: trackCategory"
|
|
442
|
+
(click)="selectCategory(cat.value)"
|
|
443
|
+
class="px-3 py-1.5 text-xs rounded-full border transition
|
|
444
|
+
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
445
|
+
[ngClass]="{
|
|
446
|
+
'bg-blue-50 border-blue-300 text-blue-700 dark:bg-blue-900/40 dark:border-blue-700 dark:text-blue-200': selectedCategory === cat.value,
|
|
447
|
+
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700 text-gray-700 dark:text-gray-200': selectedCategory !== cat.value
|
|
448
|
+
}"
|
|
449
|
+
>
|
|
450
|
+
{{ cat.label }}
|
|
451
|
+
</button>
|
|
452
|
+
</div>
|
|
453
|
+
</div>
|
|
454
|
+
|
|
455
|
+
<!-- Divider -->
|
|
456
|
+
<div class="h-px bg-gray-200 dark:bg-gray-700"></div>
|
|
457
|
+
|
|
458
|
+
<!-- Grid -->
|
|
459
|
+
<div class="p-3 bg-gray-50 dark:bg-gray-900 max-h-[360px] overflow-y-auto">
|
|
460
|
+
<div *ngIf="filtered.length === 0" class="text-center py-10 text-gray-500">
|
|
461
|
+
<div class="text-sm font-semibold">No icons found</div>
|
|
462
|
+
<div class="text-xs">Try another keyword</div>
|
|
463
|
+
</div>
|
|
464
|
+
|
|
465
|
+
<div class="grid grid-cols-6 sm:grid-cols-7 gap-2">
|
|
466
|
+
<button
|
|
467
|
+
type="button"
|
|
468
|
+
*ngFor="let icon of filtered; trackBy: trackIcon"
|
|
469
|
+
(click)="onIconClick(icon, $event)"
|
|
470
|
+
class="relative group flex flex-col items-center justify-center gap-1.5
|
|
471
|
+
p-2.5 rounded-xl border transition
|
|
472
|
+
hover:shadow-sm hover:-translate-y-[1px]
|
|
473
|
+
focus:outline-none focus:ring-2 focus:ring-blue-500/40"
|
|
474
|
+
[ngClass]="{
|
|
475
|
+
'bg-white dark:bg-gray-800 border-gray-200 dark:border-gray-700': formControl.value !== icon.class,
|
|
476
|
+
'bg-blue-50 dark:bg-blue-900/40 border-blue-400 dark:border-blue-700 ring-2 ring-blue-500/30': formControl.value === icon.class
|
|
477
|
+
}"
|
|
478
|
+
[title]="icon.name"
|
|
479
|
+
>
|
|
480
|
+
<i [ngClass]="icon.class" class="text-xl"></i>
|
|
481
|
+
|
|
482
|
+
<span class="text-[10px] text-gray-600 dark:text-gray-300 truncate w-full text-center">
|
|
483
|
+
{{ icon.name }}
|
|
484
|
+
</span>
|
|
485
|
+
|
|
486
|
+
<!-- Tooltip-like hover -->
|
|
487
|
+
<span
|
|
488
|
+
class="pointer-events-none absolute -top-2 left-1/2 -translate-x-1/2 -translate-y-full
|
|
489
|
+
opacity-0 group-hover:opacity-100 transition
|
|
490
|
+
px-2 py-1 text-[11px] rounded-md
|
|
491
|
+
bg-gray-900 text-white shadow-lg whitespace-nowrap"
|
|
492
|
+
>
|
|
493
|
+
{{ icon.class }}
|
|
494
|
+
</span>
|
|
495
|
+
</button>
|
|
496
|
+
</div>
|
|
497
|
+
</div>
|
|
498
|
+
|
|
499
|
+
<!-- Footer -->
|
|
500
|
+
<div class="px-4 py-3 bg-white dark:bg-gray-800 border-t border-gray-200 dark:border-gray-700">
|
|
501
|
+
<div class="flex items-center justify-between">
|
|
502
|
+
<span class="text-xs text-gray-500 dark:text-gray-400">
|
|
503
|
+
Showing <b class="text-gray-700 dark:text-gray-200">{{ filtered.length }}</b> icons
|
|
504
|
+
</span>
|
|
505
|
+
|
|
506
|
+
<div class="flex items-center gap-2">
|
|
507
|
+
<button
|
|
508
|
+
type="button"
|
|
509
|
+
class="px-3 py-1.5 text-xs rounded-md border border-gray-200 dark:border-gray-700
|
|
510
|
+
hover:bg-gray-100 dark:hover:bg-gray-700"
|
|
511
|
+
(click)="selectCategory(''); searchQuery=''; applyFilters()"
|
|
512
|
+
>
|
|
513
|
+
Reset
|
|
514
|
+
</button>
|
|
515
|
+
|
|
516
|
+
<button
|
|
517
|
+
type="button"
|
|
518
|
+
class="px-3 py-1.5 text-xs rounded-md bg-blue-600 text-white
|
|
519
|
+
hover:bg-blue-700"
|
|
520
|
+
(click)="popover.hide()"
|
|
521
|
+
>
|
|
522
|
+
Done
|
|
523
|
+
</button>
|
|
524
|
+
</div>
|
|
525
|
+
</div>
|
|
526
|
+
</div>
|
|
527
|
+
</ng-template>
|
|
528
|
+
</p-popover>
|
|
529
|
+
</div>
|
|
530
530
|
`,
|
|
531
531
|
}]
|
|
532
532
|
}], propDecorators: { popover: [{
|