@m1z23r/ngx-ui 1.0.4 → 1.0.6
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/fesm2022/m1z23r-ngx-ui.mjs +202 -11
- package/fesm2022/m1z23r-ngx-ui.mjs.map +1 -1
- package/package.json +1 -1
- package/types/m1z23r-ngx-ui.d.ts +20 -3
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as i0 from '@angular/core';
|
|
2
|
-
import { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, contentChildren, TemplateRef, contentChild, viewChild } from '@angular/core';
|
|
2
|
+
import { inject, PLATFORM_ID, signal, Injectable, computed, InjectionToken, ApplicationRef, EnvironmentInjector, createComponent, Injector, input, output, ChangeDetectionStrategy, Component, ElementRef, HostListener, effect, Directive, model, contentChildren, ViewChild, TemplateRef, contentChild, viewChild } from '@angular/core';
|
|
3
3
|
import { isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
4
4
|
import * as i1 from '@angular/forms';
|
|
5
5
|
import { FormsModule } from '@angular/forms';
|
|
@@ -935,11 +935,15 @@ class SelectComponent {
|
|
|
935
935
|
closed = output();
|
|
936
936
|
// Content children
|
|
937
937
|
options = contentChildren(OptionComponent, ...(ngDevMode ? [{ debugName: "options" }] : []));
|
|
938
|
+
// View children for dropdown portal
|
|
939
|
+
triggerRef;
|
|
940
|
+
dropdownRef;
|
|
938
941
|
// Internal state
|
|
939
942
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
940
943
|
searchQuery = signal('', ...(ngDevMode ? [{ debugName: "searchQuery" }] : []));
|
|
941
944
|
focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : []));
|
|
942
945
|
elementRef = inject(ElementRef);
|
|
946
|
+
positionCleanup = null;
|
|
943
947
|
constructor() {
|
|
944
948
|
// Sync selected state to options
|
|
945
949
|
effect(() => {
|
|
@@ -984,6 +988,13 @@ class SelectComponent {
|
|
|
984
988
|
});
|
|
985
989
|
});
|
|
986
990
|
}
|
|
991
|
+
ngOnDestroy() {
|
|
992
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
993
|
+
if (dropdown?.parentElement === document.body) {
|
|
994
|
+
document.body.removeChild(dropdown);
|
|
995
|
+
}
|
|
996
|
+
this.removePositionListeners();
|
|
997
|
+
}
|
|
987
998
|
triggerClasses = computed(() => {
|
|
988
999
|
return `ui-select__trigger--${this.variant()} ui-select__trigger--${this.size()}`;
|
|
989
1000
|
}, ...(ngDevMode ? [{ debugName: "triggerClasses" }] : []));
|
|
@@ -1022,7 +1033,9 @@ class SelectComponent {
|
|
|
1022
1033
|
});
|
|
1023
1034
|
}, ...(ngDevMode ? [{ debugName: "visibleOptions" }] : []));
|
|
1024
1035
|
onDocumentClick(event) {
|
|
1025
|
-
|
|
1036
|
+
const target = event.target;
|
|
1037
|
+
if (!this.elementRef.nativeElement.contains(target) &&
|
|
1038
|
+
!this.dropdownRef?.nativeElement?.contains(target)) {
|
|
1026
1039
|
this.close();
|
|
1027
1040
|
}
|
|
1028
1041
|
}
|
|
@@ -1043,10 +1056,12 @@ class SelectComponent {
|
|
|
1043
1056
|
this.searchQuery.set('');
|
|
1044
1057
|
this.focusedIndex.set(-1);
|
|
1045
1058
|
this.opened.emit();
|
|
1059
|
+
this.portalDropdown();
|
|
1046
1060
|
}
|
|
1047
1061
|
close() {
|
|
1048
1062
|
if (!this.isOpen())
|
|
1049
1063
|
return;
|
|
1064
|
+
this.unportalDropdown();
|
|
1050
1065
|
this.isOpen.set(false);
|
|
1051
1066
|
this.searchQuery.set('');
|
|
1052
1067
|
this.focusedIndex.set(-1);
|
|
@@ -1177,13 +1192,90 @@ class SelectComponent {
|
|
|
1177
1192
|
focused.elementRef.nativeElement.scrollIntoView({ block: 'nearest' });
|
|
1178
1193
|
}
|
|
1179
1194
|
}
|
|
1195
|
+
portalDropdown() {
|
|
1196
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
1197
|
+
if (!dropdown)
|
|
1198
|
+
return;
|
|
1199
|
+
dropdown.style.display = 'block';
|
|
1200
|
+
document.body.appendChild(dropdown);
|
|
1201
|
+
this.updateDropdownPosition();
|
|
1202
|
+
this.addPositionListeners();
|
|
1203
|
+
}
|
|
1204
|
+
unportalDropdown() {
|
|
1205
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
1206
|
+
if (!dropdown)
|
|
1207
|
+
return;
|
|
1208
|
+
if (dropdown.parentElement === document.body) {
|
|
1209
|
+
const wrapper = this.elementRef.nativeElement.querySelector('.ui-select-wrapper');
|
|
1210
|
+
if (wrapper) {
|
|
1211
|
+
wrapper.appendChild(dropdown);
|
|
1212
|
+
}
|
|
1213
|
+
}
|
|
1214
|
+
dropdown.style.display = '';
|
|
1215
|
+
dropdown.style.position = '';
|
|
1216
|
+
dropdown.style.top = '';
|
|
1217
|
+
dropdown.style.left = '';
|
|
1218
|
+
dropdown.style.bottom = '';
|
|
1219
|
+
dropdown.style.width = '';
|
|
1220
|
+
dropdown.style.zIndex = '';
|
|
1221
|
+
dropdown.style.margin = '';
|
|
1222
|
+
this.removePositionListeners();
|
|
1223
|
+
}
|
|
1224
|
+
updateDropdownPosition() {
|
|
1225
|
+
const trigger = this.triggerRef?.nativeElement;
|
|
1226
|
+
const dropdown = this.dropdownRef?.nativeElement;
|
|
1227
|
+
if (!trigger || !dropdown)
|
|
1228
|
+
return;
|
|
1229
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
1230
|
+
const dropdownHeight = dropdown.scrollHeight;
|
|
1231
|
+
const gap = 4;
|
|
1232
|
+
const spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
1233
|
+
const spaceAbove = triggerRect.top;
|
|
1234
|
+
const openAbove = spaceBelow < dropdownHeight + gap && spaceAbove > spaceBelow;
|
|
1235
|
+
dropdown.style.position = 'fixed';
|
|
1236
|
+
dropdown.style.width = `${triggerRect.width}px`;
|
|
1237
|
+
dropdown.style.left = `${triggerRect.left}px`;
|
|
1238
|
+
dropdown.style.zIndex = '99999';
|
|
1239
|
+
dropdown.style.margin = '0';
|
|
1240
|
+
if (openAbove) {
|
|
1241
|
+
dropdown.style.top = 'auto';
|
|
1242
|
+
dropdown.style.bottom = `${window.innerHeight - triggerRect.top + gap}px`;
|
|
1243
|
+
}
|
|
1244
|
+
else {
|
|
1245
|
+
dropdown.style.top = `${triggerRect.bottom + gap}px`;
|
|
1246
|
+
dropdown.style.bottom = 'auto';
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
addPositionListeners() {
|
|
1250
|
+
const update = () => {
|
|
1251
|
+
if (this.isOpen()) {
|
|
1252
|
+
this.updateDropdownPosition();
|
|
1253
|
+
}
|
|
1254
|
+
};
|
|
1255
|
+
window.addEventListener('scroll', update, true);
|
|
1256
|
+
window.addEventListener('resize', update);
|
|
1257
|
+
this.positionCleanup = () => {
|
|
1258
|
+
window.removeEventListener('scroll', update, true);
|
|
1259
|
+
window.removeEventListener('resize', update);
|
|
1260
|
+
};
|
|
1261
|
+
}
|
|
1262
|
+
removePositionListeners() {
|
|
1263
|
+
this.positionCleanup?.();
|
|
1264
|
+
this.positionCleanup = null;
|
|
1265
|
+
}
|
|
1180
1266
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: SelectComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1181
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: SelectComponent, isStandalone: true, selector: "ui-select", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "options", predicate: OptionComponent, isSignal: true }], ngImport: i0, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n @if (searchable()) {\n <div class=\"ui-select__search\">\n <input\n type=\"text\"\n class=\"ui-select__search-input\"\n placeholder=\"Search...\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"searchQuery.set($event)\"\n (keydown)=\"handleSearchKeydown($event)\"\n #searchInput\n />\n </div>\n }\n <div class=\"ui-select__options\">\n <ng-content />\n </div>\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;
|
|
1267
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.1.1", type: SelectComponent, isStandalone: true, selector: "ui-select", inputs: { variant: { classPropertyName: "variant", publicName: "variant", isSignal: true, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, hint: { classPropertyName: "hint", publicName: "hint", isSignal: true, isRequired: false, transformFunction: null }, error: { classPropertyName: "error", publicName: "error", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, multiple: { classPropertyName: "multiple", publicName: "multiple", isSignal: true, isRequired: false, transformFunction: null }, searchable: { classPropertyName: "searchable", publicName: "searchable", isSignal: true, isRequired: false, transformFunction: null }, clearable: { classPropertyName: "clearable", publicName: "clearable", isSignal: true, isRequired: false, transformFunction: null }, value: { classPropertyName: "value", publicName: "value", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { value: "valueChange", opened: "opened", closed: "closed" }, host: { listeners: { "document:click": "onDocumentClick($event)" } }, queries: [{ propertyName: "options", predicate: OptionComponent, isSignal: true }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, static: true }, { propertyName: "dropdownRef", first: true, predicate: ["dropdownRef"], descendants: true, static: true }], ngImport: i0, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n #triggerRef\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n #dropdownRef\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n @if (searchable()) {\n <div class=\"ui-select__search\">\n <input\n type=\"text\"\n class=\"ui-select__search-input\"\n placeholder=\"Search...\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"searchQuery.set($event)\"\n (keydown)=\"handleSearchKeydown($event)\"\n #searchInput\n />\n </div>\n }\n <div class=\"ui-select__options\">\n <ng-content />\n </div>\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast)}.ui-select__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-select__search{padding:var(--ui-spacing-sm);border-bottom:1px solid var(--ui-border)}.ui-select__search-input{width:100%;padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-family:inherit;font-size:var(--ui-font-sm);color:var(--ui-text);background-color:var(--ui-bg-secondary);border:1px solid var(--ui-border);border-radius:var(--ui-radius-sm);outline:none}.ui-select__search-input:focus{border-color:var(--ui-border-focus)}.ui-select__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-select__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select-wrapper--error .ui-select__trigger{border-color:var(--ui-danger)}.ui-select-wrapper--error .ui-select__trigger:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-select__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-select__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"], 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"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1182
1268
|
}
|
|
1183
1269
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: SelectComponent, decorators: [{
|
|
1184
1270
|
type: Component,
|
|
1185
|
-
args: [{ selector: 'ui-select', standalone: true, imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n @if (searchable()) {\n <div class=\"ui-select__search\">\n <input\n type=\"text\"\n class=\"ui-select__search-input\"\n placeholder=\"Search...\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"searchQuery.set($event)\"\n (keydown)=\"handleSearchKeydown($event)\"\n #searchInput\n />\n </div>\n }\n <div class=\"ui-select__options\">\n <ng-content />\n </div>\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;
|
|
1186
|
-
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], options: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => OptionComponent), { isSignal: true }] }],
|
|
1271
|
+
args: [{ selector: 'ui-select', standalone: true, imports: [FormsModule], changeDetection: ChangeDetectionStrategy.OnPush, template: "<div\n class=\"ui-select-wrapper\"\n [class.ui-select-wrapper--error]=\"error()\"\n [class.ui-select-wrapper--disabled]=\"disabled()\"\n [class.ui-select-wrapper--open]=\"isOpen()\"\n>\n @if (label()) {\n <label class=\"ui-select__label\">\n {{ label() }}\n </label>\n }\n\n <div\n #triggerRef\n class=\"ui-select__trigger\"\n [class]=\"triggerClasses()\"\n [attr.role]=\"'combobox'\"\n [attr.aria-expanded]=\"isOpen()\"\n [attr.aria-haspopup]=\"'listbox'\"\n [attr.aria-disabled]=\"disabled()\"\n [attr.tabindex]=\"disabled() ? -1 : 0\"\n (click)=\"toggle()\"\n (keydown)=\"handleTriggerKeydown($event)\"\n >\n <span class=\"ui-select__value\">\n @if (displayValue()) {\n {{ displayValue() }}\n } @else {\n <span class=\"ui-select__placeholder\">{{ placeholder() }}</span>\n }\n </span>\n\n <div class=\"ui-select__icons\">\n @if (clearable() && hasValue() && !disabled()) {\n <button\n type=\"button\"\n class=\"ui-select__clear\"\n (click)=\"clear($event)\"\n aria-label=\"Clear selection\"\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <line x1=\"18\" y1=\"6\" x2=\"6\" y2=\"18\"></line>\n <line x1=\"6\" y1=\"6\" x2=\"18\" y2=\"18\"></line>\n </svg>\n </button>\n }\n <svg\n class=\"ui-select__arrow\"\n [class.ui-select__arrow--open]=\"isOpen()\"\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n >\n <polyline points=\"6 9 12 15 18 9\"></polyline>\n </svg>\n </div>\n </div>\n\n <div\n #dropdownRef\n class=\"ui-select__dropdown\"\n [class.ui-select__dropdown--open]=\"isOpen()\"\n [attr.role]=\"'listbox'\"\n [attr.aria-multiselectable]=\"multiple()\"\n >\n @if (searchable()) {\n <div class=\"ui-select__search\">\n <input\n type=\"text\"\n class=\"ui-select__search-input\"\n placeholder=\"Search...\"\n [ngModel]=\"searchQuery()\"\n (ngModelChange)=\"searchQuery.set($event)\"\n (keydown)=\"handleSearchKeydown($event)\"\n #searchInput\n />\n </div>\n }\n <div class=\"ui-select__options\">\n <ng-content />\n </div>\n </div>\n\n @if (error()) {\n <span class=\"ui-select__error\">{{ error() }}</span>\n }\n @if (hint() && !error()) {\n <span class=\"ui-select__hint\">{{ hint() }}</span>\n }\n</div>\n", styles: [":host{display:block;position:relative}.ui-select-wrapper{display:flex;flex-direction:column;gap:var(--ui-spacing-xs)}.ui-select__label{font-size:var(--ui-font-sm);font-weight:500;color:var(--ui-text)}.ui-select__trigger{display:flex;align-items:center;justify-content:space-between;gap:var(--ui-spacing-sm);width:100%;background-color:var(--ui-bg);border:1px solid var(--ui-border);border-radius:var(--ui-radius-md);cursor:pointer;transition:border-color var(--ui-transition-fast),box-shadow var(--ui-transition-fast)}.ui-select__trigger:hover:not([aria-disabled=true]){border-color:var(--ui-border-hover)}.ui-select__trigger:focus{outline:none;border-color:var(--ui-border-focus);box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-primary) 20%,transparent)}.ui-select__trigger[aria-disabled=true]{background-color:var(--ui-bg-secondary);color:var(--ui-text-disabled);cursor:not-allowed}.ui-select__trigger--sm{padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-size:var(--ui-font-sm)}.ui-select__trigger--md{padding:var(--ui-spacing-sm) var(--ui-spacing-md);font-size:var(--ui-font-md)}.ui-select__trigger--lg{padding:var(--ui-spacing-md) var(--ui-spacing-lg);font-size:var(--ui-font-lg)}.ui-select__trigger--outlined{background-color:transparent}.ui-select__trigger--filled{background-color:var(--ui-bg-secondary);border-color:transparent}.ui-select__trigger--filled:hover:not([aria-disabled=true]){background-color:var(--ui-bg-tertiary)}.ui-select__trigger--filled:focus{border-color:var(--ui-border-focus)}.ui-select__value{flex:1;min-width:0;text-align:left;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.ui-select__placeholder{color:var(--ui-text-muted)}.ui-select__icons{display:flex;align-items:center;gap:var(--ui-spacing-xs);flex-shrink:0}.ui-select__clear{display:flex;align-items:center;justify-content:center;padding:2px;background:none;border:none;cursor:pointer;color:var(--ui-text-muted);border-radius:var(--ui-radius-sm);transition:color var(--ui-transition-fast),background-color var(--ui-transition-fast)}.ui-select__clear:hover{color:var(--ui-text);background-color:var(--ui-bg-hover)}.ui-select__arrow{color:var(--ui-text-muted);transition:transform var(--ui-transition-fast)}.ui-select__arrow--open{transform:rotate(180deg)}.ui-select__dropdown{position:absolute;top:100%;left:0;right:0;z-index:1000;margin-top:var(--ui-spacing-xs);background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast)}.ui-select__dropdown--open{display:block;opacity:1;transform:translateY(0)}.ui-select__search{padding:var(--ui-spacing-sm);border-bottom:1px solid var(--ui-border)}.ui-select__search-input{width:100%;padding:var(--ui-spacing-xs) var(--ui-spacing-sm);font-family:inherit;font-size:var(--ui-font-sm);color:var(--ui-text);background-color:var(--ui-bg-secondary);border:1px solid var(--ui-border);border-radius:var(--ui-radius-sm);outline:none}.ui-select__search-input:focus{border-color:var(--ui-border-focus)}.ui-select__options{max-height:var(--ui-dropdown-max-height, 300px);overflow-y:auto}.ui-select__empty{padding:var(--ui-spacing-md);text-align:center;color:var(--ui-text-muted);font-size:var(--ui-font-sm)}.ui-select-wrapper--error .ui-select__trigger{border-color:var(--ui-danger)}.ui-select-wrapper--error .ui-select__trigger:focus{box-shadow:0 0 0 3px color-mix(in srgb,var(--ui-danger) 20%,transparent)}.ui-select__error{font-size:var(--ui-font-sm);color:var(--ui-danger)}.ui-select__hint{font-size:var(--ui-font-sm);color:var(--ui-text-muted)}\n"] }]
|
|
1272
|
+
}], ctorParameters: () => [], propDecorators: { variant: [{ type: i0.Input, args: [{ isSignal: true, alias: "variant", required: false }] }], size: [{ type: i0.Input, args: [{ isSignal: true, alias: "size", required: false }] }], placeholder: [{ type: i0.Input, args: [{ isSignal: true, alias: "placeholder", required: false }] }], label: [{ type: i0.Input, args: [{ isSignal: true, alias: "label", required: false }] }], hint: [{ type: i0.Input, args: [{ isSignal: true, alias: "hint", required: false }] }], error: [{ type: i0.Input, args: [{ isSignal: true, alias: "error", required: false }] }], disabled: [{ type: i0.Input, args: [{ isSignal: true, alias: "disabled", required: false }] }], multiple: [{ type: i0.Input, args: [{ isSignal: true, alias: "multiple", required: false }] }], searchable: [{ type: i0.Input, args: [{ isSignal: true, alias: "searchable", required: false }] }], clearable: [{ type: i0.Input, args: [{ isSignal: true, alias: "clearable", required: false }] }], value: [{ type: i0.Input, args: [{ isSignal: true, alias: "value", required: false }] }, { type: i0.Output, args: ["valueChange"] }], opened: [{ type: i0.Output, args: ["opened"] }], closed: [{ type: i0.Output, args: ["closed"] }], options: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => OptionComponent), { isSignal: true }] }], triggerRef: [{
|
|
1273
|
+
type: ViewChild,
|
|
1274
|
+
args: ['triggerRef', { static: true }]
|
|
1275
|
+
}], dropdownRef: [{
|
|
1276
|
+
type: ViewChild,
|
|
1277
|
+
args: ['dropdownRef', { static: true }]
|
|
1278
|
+
}], onDocumentClick: [{
|
|
1187
1279
|
type: HostListener,
|
|
1188
1280
|
args: ['document:click', ['$event']]
|
|
1189
1281
|
}] } });
|
|
@@ -1259,7 +1351,10 @@ class DropdownComponent {
|
|
|
1259
1351
|
closeOnSelect = input(true, ...(ngDevMode ? [{ debugName: "closeOnSelect" }] : []));
|
|
1260
1352
|
isOpen = signal(false, ...(ngDevMode ? [{ debugName: "isOpen" }] : []));
|
|
1261
1353
|
focusedIndex = signal(-1, ...(ngDevMode ? [{ debugName: "focusedIndex" }] : []));
|
|
1354
|
+
triggerRef;
|
|
1355
|
+
menuRef;
|
|
1262
1356
|
elementRef = inject(ElementRef);
|
|
1357
|
+
positionCleanup = null;
|
|
1263
1358
|
trigger = contentChild(DropdownTriggerDirective, ...(ngDevMode ? [{ debugName: "trigger" }] : []));
|
|
1264
1359
|
items = contentChildren(DropdownItemComponent, ...(ngDevMode ? [{ debugName: "items" }] : []));
|
|
1265
1360
|
constructor() {
|
|
@@ -1291,11 +1386,17 @@ class DropdownComponent {
|
|
|
1291
1386
|
});
|
|
1292
1387
|
});
|
|
1293
1388
|
}
|
|
1294
|
-
|
|
1295
|
-
|
|
1389
|
+
ngOnDestroy() {
|
|
1390
|
+
const menu = this.menuRef?.nativeElement;
|
|
1391
|
+
if (menu?.parentElement === document.body) {
|
|
1392
|
+
document.body.removeChild(menu);
|
|
1393
|
+
}
|
|
1394
|
+
this.removePositionListeners();
|
|
1296
1395
|
}
|
|
1297
1396
|
onDocumentClick(event) {
|
|
1298
|
-
|
|
1397
|
+
const target = event.target;
|
|
1398
|
+
if (!this.elementRef.nativeElement.contains(target) &&
|
|
1399
|
+
!this.menuRef?.nativeElement?.contains(target)) {
|
|
1299
1400
|
this.close();
|
|
1300
1401
|
}
|
|
1301
1402
|
}
|
|
@@ -1341,10 +1442,12 @@ class DropdownComponent {
|
|
|
1341
1442
|
return;
|
|
1342
1443
|
this.isOpen.set(true);
|
|
1343
1444
|
this.focusedIndex.set(-1);
|
|
1445
|
+
this.portalMenu();
|
|
1344
1446
|
}
|
|
1345
1447
|
close() {
|
|
1346
1448
|
if (!this.isOpen())
|
|
1347
1449
|
return;
|
|
1450
|
+
this.unportalMenu();
|
|
1348
1451
|
this.isOpen.set(false);
|
|
1349
1452
|
this.focusedIndex.set(-1);
|
|
1350
1453
|
}
|
|
@@ -1370,13 +1473,101 @@ class DropdownComponent {
|
|
|
1370
1473
|
this.focusedIndex.set(prev);
|
|
1371
1474
|
}
|
|
1372
1475
|
}
|
|
1476
|
+
portalMenu() {
|
|
1477
|
+
const menu = this.menuRef?.nativeElement;
|
|
1478
|
+
if (!menu)
|
|
1479
|
+
return;
|
|
1480
|
+
menu.style.display = 'block';
|
|
1481
|
+
document.body.appendChild(menu);
|
|
1482
|
+
this.updateMenuPosition();
|
|
1483
|
+
this.addPositionListeners();
|
|
1484
|
+
}
|
|
1485
|
+
unportalMenu() {
|
|
1486
|
+
const menu = this.menuRef?.nativeElement;
|
|
1487
|
+
if (!menu)
|
|
1488
|
+
return;
|
|
1489
|
+
if (menu.parentElement === document.body) {
|
|
1490
|
+
const wrapper = this.elementRef.nativeElement.querySelector('.ui-dropdown');
|
|
1491
|
+
if (wrapper) {
|
|
1492
|
+
wrapper.appendChild(menu);
|
|
1493
|
+
}
|
|
1494
|
+
}
|
|
1495
|
+
menu.style.display = '';
|
|
1496
|
+
menu.style.position = '';
|
|
1497
|
+
menu.style.top = '';
|
|
1498
|
+
menu.style.left = '';
|
|
1499
|
+
menu.style.right = '';
|
|
1500
|
+
menu.style.bottom = '';
|
|
1501
|
+
menu.style.width = '';
|
|
1502
|
+
menu.style.zIndex = '';
|
|
1503
|
+
menu.style.margin = '';
|
|
1504
|
+
this.removePositionListeners();
|
|
1505
|
+
}
|
|
1506
|
+
updateMenuPosition() {
|
|
1507
|
+
const trigger = this.triggerRef?.nativeElement;
|
|
1508
|
+
const menu = this.menuRef?.nativeElement;
|
|
1509
|
+
if (!trigger || !menu)
|
|
1510
|
+
return;
|
|
1511
|
+
const triggerRect = trigger.getBoundingClientRect();
|
|
1512
|
+
const menuHeight = menu.scrollHeight;
|
|
1513
|
+
const gap = 4;
|
|
1514
|
+
const spaceBelow = window.innerHeight - triggerRect.bottom;
|
|
1515
|
+
const spaceAbove = triggerRect.top;
|
|
1516
|
+
const preferTop = this.position().startsWith('top');
|
|
1517
|
+
const openAbove = preferTop
|
|
1518
|
+
? spaceAbove >= menuHeight + gap || spaceAbove > spaceBelow
|
|
1519
|
+
: spaceBelow < menuHeight + gap && spaceAbove > spaceBelow;
|
|
1520
|
+
const alignEnd = this.position().endsWith('end');
|
|
1521
|
+
menu.style.position = 'fixed';
|
|
1522
|
+
menu.style.zIndex = '99999';
|
|
1523
|
+
menu.style.margin = '0';
|
|
1524
|
+
if (openAbove) {
|
|
1525
|
+
menu.style.top = 'auto';
|
|
1526
|
+
menu.style.bottom = `${window.innerHeight - triggerRect.top + gap}px`;
|
|
1527
|
+
}
|
|
1528
|
+
else {
|
|
1529
|
+
menu.style.top = `${triggerRect.bottom + gap}px`;
|
|
1530
|
+
menu.style.bottom = 'auto';
|
|
1531
|
+
}
|
|
1532
|
+
if (alignEnd) {
|
|
1533
|
+
menu.style.left = 'auto';
|
|
1534
|
+
menu.style.right = `${window.innerWidth - triggerRect.right}px`;
|
|
1535
|
+
}
|
|
1536
|
+
else {
|
|
1537
|
+
menu.style.left = `${triggerRect.left}px`;
|
|
1538
|
+
menu.style.right = 'auto';
|
|
1539
|
+
}
|
|
1540
|
+
}
|
|
1541
|
+
addPositionListeners() {
|
|
1542
|
+
const update = () => {
|
|
1543
|
+
if (this.isOpen()) {
|
|
1544
|
+
this.updateMenuPosition();
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1547
|
+
window.addEventListener('scroll', update, true);
|
|
1548
|
+
window.addEventListener('resize', update);
|
|
1549
|
+
this.positionCleanup = () => {
|
|
1550
|
+
window.removeEventListener('scroll', update, true);
|
|
1551
|
+
window.removeEventListener('resize', update);
|
|
1552
|
+
};
|
|
1553
|
+
}
|
|
1554
|
+
removePositionListeners() {
|
|
1555
|
+
this.positionCleanup?.();
|
|
1556
|
+
this.positionCleanup = null;
|
|
1557
|
+
}
|
|
1373
1558
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DropdownComponent, deps: [], target: i0.ɵɵFactoryTarget.Component });
|
|
1374
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.
|
|
1559
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.2.0", version: "21.1.1", type: DropdownComponent, isStandalone: true, selector: "ui-dropdown", inputs: { position: { classPropertyName: "position", publicName: "position", isSignal: true, isRequired: false, transformFunction: null }, closeOnSelect: { classPropertyName: "closeOnSelect", publicName: "closeOnSelect", isSignal: true, isRequired: false, transformFunction: null } }, host: { listeners: { "document:click": "onDocumentClick($event)", "keydown": "onKeydown($event)" } }, queries: [{ propertyName: "trigger", first: true, predicate: DropdownTriggerDirective, descendants: true, isSignal: true }, { propertyName: "items", predicate: DropdownItemComponent, isSignal: true }], viewQueries: [{ propertyName: "triggerRef", first: true, predicate: ["triggerRef"], descendants: true, static: true }, { propertyName: "menuRef", first: true, predicate: ["menuRef"], descendants: true, static: true }], ngImport: i0, template: "<div class=\"ui-dropdown\">\n <div #triggerRef class=\"ui-dropdown__trigger\">\n <ng-content select=\"[uiDropdownTrigger]\" />\n </div>\n\n <div\n #menuRef\n class=\"ui-dropdown__menu\"\n [class.ui-dropdown__menu--open]=\"isOpen()\"\n [attr.role]=\"'menu'\"\n >\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:inline-block;position:relative}.ui-dropdown{position:relative}.ui-dropdown__trigger{display:inline-block}.ui-dropdown__menu{position:absolute;top:100%;left:0;z-index:1000;min-width:160px;margin-top:var(--ui-spacing-xs);padding:var(--ui-spacing-xs) 0;background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast)}.ui-dropdown__menu--open{display:block;opacity:1;transform:translateY(0)}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
1375
1560
|
}
|
|
1376
1561
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.1.1", ngImport: i0, type: DropdownComponent, decorators: [{
|
|
1377
1562
|
type: Component,
|
|
1378
|
-
args: [{ selector: 'ui-dropdown', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-dropdown\">\n <div class=\"ui-dropdown__trigger\">\n <ng-content select=\"[uiDropdownTrigger]\" />\n </div>\n\n
|
|
1379
|
-
}], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], closeOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnSelect", required: false }] }],
|
|
1563
|
+
args: [{ selector: 'ui-dropdown', standalone: true, changeDetection: ChangeDetectionStrategy.OnPush, template: "<div class=\"ui-dropdown\">\n <div #triggerRef class=\"ui-dropdown__trigger\">\n <ng-content select=\"[uiDropdownTrigger]\" />\n </div>\n\n <div\n #menuRef\n class=\"ui-dropdown__menu\"\n [class.ui-dropdown__menu--open]=\"isOpen()\"\n [attr.role]=\"'menu'\"\n >\n <ng-content />\n </div>\n</div>\n", styles: [":host{display:inline-block;position:relative}.ui-dropdown{position:relative}.ui-dropdown__trigger{display:inline-block}.ui-dropdown__menu{position:absolute;top:100%;left:0;z-index:1000;min-width:160px;margin-top:var(--ui-spacing-xs);padding:var(--ui-spacing-xs) 0;background-color:var(--ui-dropdown-bg, var(--ui-bg));border:1px solid var(--ui-dropdown-border, var(--ui-border));border-radius:var(--ui-dropdown-radius, var(--ui-radius-md));box-shadow:var(--ui-dropdown-shadow, var(--ui-shadow-lg));overflow:hidden;display:none;opacity:0;transform:translateY(-8px);transition:opacity var(--ui-transition-fast),transform var(--ui-transition-fast)}.ui-dropdown__menu--open{display:block;opacity:1;transform:translateY(0)}\n"] }]
|
|
1564
|
+
}], ctorParameters: () => [], propDecorators: { position: [{ type: i0.Input, args: [{ isSignal: true, alias: "position", required: false }] }], closeOnSelect: [{ type: i0.Input, args: [{ isSignal: true, alias: "closeOnSelect", required: false }] }], triggerRef: [{
|
|
1565
|
+
type: ViewChild,
|
|
1566
|
+
args: ['triggerRef', { static: true }]
|
|
1567
|
+
}], menuRef: [{
|
|
1568
|
+
type: ViewChild,
|
|
1569
|
+
args: ['menuRef', { static: true }]
|
|
1570
|
+
}], trigger: [{ type: i0.ContentChild, args: [i0.forwardRef(() => DropdownTriggerDirective), { isSignal: true }] }], items: [{ type: i0.ContentChildren, args: [i0.forwardRef(() => DropdownItemComponent), { isSignal: true }] }], onDocumentClick: [{
|
|
1380
1571
|
type: HostListener,
|
|
1381
1572
|
args: ['document:click', ['$event']]
|
|
1382
1573
|
}], onKeydown: [{
|