cloud-ide-element 1.1.159 → 1.1.160
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/cloud-ide-element.mjs +214 -45
- package/fesm2022/cloud-ide-element.mjs.map +1 -1
- package/index.d.ts +4 -6
- package/package.json +1 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import * as i1 from '@angular/common';
|
|
2
2
|
import { CommonModule, isPlatformBrowser, NgTemplateOutlet } from '@angular/common';
|
|
3
3
|
import * as i0 from '@angular/core';
|
|
4
|
-
import { Pipe, Injectable, inject, ChangeDetectorRef, EventEmitter, ViewContainerRef, forwardRef, ViewChild, Output, Input, Component, input,
|
|
4
|
+
import { Pipe, Injectable, inject, ChangeDetectorRef, EventEmitter, ViewContainerRef, forwardRef, ViewChild, Output, Input, Component, input, effect, ContentChildren, signal, DestroyRef, computed, HostListener, ChangeDetectionStrategy, Directive, PLATFORM_ID, ElementRef, viewChild } from '@angular/core';
|
|
5
5
|
import * as i2 from '@angular/forms';
|
|
6
|
-
import { FormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS
|
|
6
|
+
import { FormsModule, NG_VALUE_ACCESSOR, NG_VALIDATORS } from '@angular/forms';
|
|
7
7
|
import { BehaviorSubject, Subject, debounceTime, distinctUntilChanged, takeUntil, Observable, retry, catchError, finalize, throwError, map, of } from 'rxjs';
|
|
8
8
|
import * as i1$1 from '@angular/common/http';
|
|
9
9
|
import { HttpClient, HttpEventType, HttpParams, HttpRequest } from '@angular/common/http';
|
|
@@ -1971,33 +1971,34 @@ class CideSelectComponent {
|
|
|
1971
1971
|
// Debug tracking properties
|
|
1972
1972
|
debugId = Math.random().toString(36).substr(2, 9);
|
|
1973
1973
|
timeoutIds = [];
|
|
1974
|
-
// Dependencies
|
|
1975
|
-
el = inject(ElementRef);
|
|
1976
|
-
cdr = inject(ChangeDetectorRef);
|
|
1977
|
-
ngControl = inject(NgControl, { optional: true, self: true });
|
|
1978
1974
|
interactionCount = 0;
|
|
1979
1975
|
maxInteractionCount = 10; // Prevent infinite loops
|
|
1980
1976
|
constructor(elementRef) {
|
|
1981
1977
|
this.elementRef = elementRef;
|
|
1982
|
-
if (this.ngControl) {
|
|
1983
|
-
this.ngControl.valueAccessor = this;
|
|
1984
|
-
}
|
|
1985
1978
|
// Watch for options changes (input signal) - effects must be in constructor
|
|
1986
1979
|
effect(() => {
|
|
1987
1980
|
const opts = this.options();
|
|
1988
1981
|
if (opts && opts.length >= 0) {
|
|
1989
1982
|
this.filterOptions();
|
|
1990
1983
|
// Update portal context if dropdown is open
|
|
1991
|
-
if (this.isOpen && this.
|
|
1992
|
-
|
|
1984
|
+
if (this.isOpen && this.dropdownPortalId) {
|
|
1985
|
+
setTimeout(() => {
|
|
1986
|
+
this.updatePortalContext();
|
|
1987
|
+
}, 0);
|
|
1993
1988
|
}
|
|
1989
|
+
// // Update portal context if dropdown is open
|
|
1990
|
+
// if (this.isOpen && this.portalContext) {
|
|
1991
|
+
// this.portalContext.options = this.filteredOptions;
|
|
1992
|
+
// }
|
|
1994
1993
|
}
|
|
1995
1994
|
});
|
|
1996
1995
|
// Watch for loading changes
|
|
1997
1996
|
effect(() => {
|
|
1998
1997
|
const loading = this.loading();
|
|
1999
|
-
if (this.isOpen && this.
|
|
2000
|
-
|
|
1998
|
+
if (this.isOpen && this.dropdownPortalId) {
|
|
1999
|
+
setTimeout(() => {
|
|
2000
|
+
this.updatePortalContext();
|
|
2001
|
+
}, 0);
|
|
2001
2002
|
}
|
|
2002
2003
|
});
|
|
2003
2004
|
}
|
|
@@ -2158,8 +2159,6 @@ class CideSelectComponent {
|
|
|
2158
2159
|
window.removeEventListener('resize', this.onWindowResize.bind(this));
|
|
2159
2160
|
this.logDebug('Component destroyed, timeouts cleared');
|
|
2160
2161
|
}
|
|
2161
|
-
// Portal context property
|
|
2162
|
-
portalContext = {};
|
|
2163
2162
|
createDropdownPortal() {
|
|
2164
2163
|
try {
|
|
2165
2164
|
const triggerElement = this.elementRef?.nativeElement;
|
|
@@ -2174,27 +2173,25 @@ class CideSelectComponent {
|
|
|
2174
2173
|
// Generate unique portal ID
|
|
2175
2174
|
this.dropdownPortalId = `select-dropdown-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
2176
2175
|
console.log('🔍 Creating new portal with ID:', this.dropdownPortalId);
|
|
2177
|
-
// Initialize shared context object
|
|
2178
|
-
this.portalContext = {
|
|
2179
|
-
options: this.filteredOptions,
|
|
2180
|
-
isOpen: this.isOpen,
|
|
2181
|
-
searchTerm: this.searchTerm,
|
|
2182
|
-
searchable: this.searchable(),
|
|
2183
|
-
multiple: this.multiple(),
|
|
2184
|
-
loading: this.loading(),
|
|
2185
|
-
dropdownPosition: this.dropdownPosition,
|
|
2186
|
-
treeView: this.treeView(),
|
|
2187
|
-
onSearchInput: this.onSearchInput.bind(this),
|
|
2188
|
-
selectOption: this.selectOption.bind(this),
|
|
2189
|
-
isOptionSelected: this.isOptionSelected.bind(this),
|
|
2190
|
-
trackByValue: this.trackByValue.bind(this),
|
|
2191
|
-
getOptionLabel: this.getOptionLabel.bind(this)
|
|
2192
|
-
};
|
|
2193
2176
|
const portalConfig = {
|
|
2194
2177
|
triggerElement,
|
|
2195
2178
|
template: this.dropdownTemplate,
|
|
2196
2179
|
viewContainerRef: this.dropdownContainer,
|
|
2197
|
-
context:
|
|
2180
|
+
context: {
|
|
2181
|
+
options: this.filteredOptions,
|
|
2182
|
+
isOpen: this.isOpen,
|
|
2183
|
+
searchTerm: this.searchTerm,
|
|
2184
|
+
searchable: this.searchable(),
|
|
2185
|
+
multiple: this.multiple(),
|
|
2186
|
+
loading: this.loading(),
|
|
2187
|
+
dropdownPosition: this.dropdownPosition,
|
|
2188
|
+
treeView: this.treeView(),
|
|
2189
|
+
onSearchInput: this.onSearchInput.bind(this),
|
|
2190
|
+
selectOption: this.selectOption.bind(this),
|
|
2191
|
+
isOptionSelected: this.isOptionSelected.bind(this),
|
|
2192
|
+
trackByValue: this.trackByValue.bind(this),
|
|
2193
|
+
getOptionLabel: this.getOptionLabel.bind(this)
|
|
2194
|
+
},
|
|
2198
2195
|
className: 'cide-select-dropdown-portal',
|
|
2199
2196
|
position: this.dropdownPosition,
|
|
2200
2197
|
align: 'left',
|
|
@@ -2238,6 +2235,165 @@ class CideSelectComponent {
|
|
|
2238
2235
|
console.error(`💥 SELECT [${this.debugId}] destroyDropdownPortal error:`, error);
|
|
2239
2236
|
}
|
|
2240
2237
|
}
|
|
2238
|
+
updatePortalContext() {
|
|
2239
|
+
try {
|
|
2240
|
+
if (!this.dropdownPortalId) {
|
|
2241
|
+
return; // Portal not created yet
|
|
2242
|
+
}
|
|
2243
|
+
// Set flag to prevent blur during update
|
|
2244
|
+
this.isUpdatingOptions = true;
|
|
2245
|
+
// Store reference to search input before destroying portal
|
|
2246
|
+
console.log('🔍 Looking for search input with portal ID:', this.dropdownPortalId);
|
|
2247
|
+
const searchInput = document.querySelector(`#${this.dropdownPortalId} input[type="text"]`);
|
|
2248
|
+
console.log('🔍 searchInput found:', searchInput);
|
|
2249
|
+
// Try alternative selectors if the first one fails
|
|
2250
|
+
let searchInputAlt = null;
|
|
2251
|
+
if (!searchInput) {
|
|
2252
|
+
searchInputAlt = document.querySelector(`[id*="${this.dropdownPortalId}"] input[type="text"]`);
|
|
2253
|
+
console.log('🔍 searchInputAlt found:', searchInputAlt);
|
|
2254
|
+
}
|
|
2255
|
+
const finalSearchInput = searchInput || searchInputAlt;
|
|
2256
|
+
const wasSearchInputFocused = finalSearchInput && document.activeElement === finalSearchInput;
|
|
2257
|
+
const searchInputValue = finalSearchInput ? finalSearchInput.value : '';
|
|
2258
|
+
const cursorPosition = finalSearchInput ? finalSearchInput.selectionStart || 0 : 0;
|
|
2259
|
+
// Since the portal service doesn't have an update context method,
|
|
2260
|
+
// we need to recreate the portal with updated context
|
|
2261
|
+
this.destroyDropdownPortal();
|
|
2262
|
+
this.createDropdownPortal();
|
|
2263
|
+
// Restore focus and value to search input after recreation
|
|
2264
|
+
if (wasSearchInputFocused && searchInputValue) {
|
|
2265
|
+
// Use multiple timing strategies to ensure focus restoration works
|
|
2266
|
+
const restoreFocus = () => {
|
|
2267
|
+
let newSearchInput = document.querySelector(`#${this.dropdownPortalId} input[type="text"]`);
|
|
2268
|
+
console.log('🔍 newSearchInput', newSearchInput);
|
|
2269
|
+
// Try alternative selectors if the first one fails
|
|
2270
|
+
if (!newSearchInput) {
|
|
2271
|
+
newSearchInput = document.querySelector(`[id*="${this.dropdownPortalId}"] input[type="text"]`);
|
|
2272
|
+
console.log('🔍 newSearchInputAlt', newSearchInput);
|
|
2273
|
+
}
|
|
2274
|
+
if (newSearchInput) {
|
|
2275
|
+
newSearchInput.value = searchInputValue;
|
|
2276
|
+
newSearchInput.focus();
|
|
2277
|
+
// Set cursor position to the original position
|
|
2278
|
+
newSearchInput.setSelectionRange(cursorPosition, cursorPosition);
|
|
2279
|
+
return true;
|
|
2280
|
+
}
|
|
2281
|
+
return false;
|
|
2282
|
+
};
|
|
2283
|
+
// Try immediate restoration
|
|
2284
|
+
if (!restoreFocus()) {
|
|
2285
|
+
// Try with requestAnimationFrame
|
|
2286
|
+
requestAnimationFrame(() => {
|
|
2287
|
+
if (!restoreFocus()) {
|
|
2288
|
+
// Try with setTimeout as fallback
|
|
2289
|
+
setTimeout(() => {
|
|
2290
|
+
restoreFocus();
|
|
2291
|
+
// Clear the flag after restoration
|
|
2292
|
+
this.isUpdatingOptions = false;
|
|
2293
|
+
}, 10);
|
|
2294
|
+
}
|
|
2295
|
+
else {
|
|
2296
|
+
// Clear the flag after successful restoration
|
|
2297
|
+
this.isUpdatingOptions = false;
|
|
2298
|
+
}
|
|
2299
|
+
});
|
|
2300
|
+
}
|
|
2301
|
+
else {
|
|
2302
|
+
// Clear the flag after successful restoration
|
|
2303
|
+
this.isUpdatingOptions = false;
|
|
2304
|
+
}
|
|
2305
|
+
}
|
|
2306
|
+
else {
|
|
2307
|
+
// Clear the flag if no focus restoration needed
|
|
2308
|
+
this.isUpdatingOptions = false;
|
|
2309
|
+
}
|
|
2310
|
+
this.logDebug('Portal context updated', {
|
|
2311
|
+
filteredOptionsCount: this.filteredOptions.length,
|
|
2312
|
+
searchTerm: this.searchTerm
|
|
2313
|
+
});
|
|
2314
|
+
}
|
|
2315
|
+
catch (error) {
|
|
2316
|
+
console.error(`💥 SELECT [${this.debugId}] updatePortalContext error:`, error);
|
|
2317
|
+
this.isUpdatingOptions = false;
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
updateOptionsInDOM() {
|
|
2321
|
+
try {
|
|
2322
|
+
if (!this.dropdownPortalId) {
|
|
2323
|
+
return false; // Portal not created yet
|
|
2324
|
+
}
|
|
2325
|
+
// Find the options container in the DOM
|
|
2326
|
+
console.log('🔍 Looking for options container with portal ID:', this.dropdownPortalId);
|
|
2327
|
+
let optionsContainer = document.querySelector(`#${this.dropdownPortalId} .tw-py-1`);
|
|
2328
|
+
console.log('🔍 optionsContainer (.tw-py-1):', optionsContainer);
|
|
2329
|
+
// Try alternative selectors if the first one fails
|
|
2330
|
+
if (!optionsContainer) {
|
|
2331
|
+
optionsContainer = document.querySelector(`#${this.dropdownPortalId}`);
|
|
2332
|
+
console.log('🔍 optionsContainer (main):', optionsContainer);
|
|
2333
|
+
}
|
|
2334
|
+
if (!optionsContainer) {
|
|
2335
|
+
optionsContainer = document.querySelector(`[id*="${this.dropdownPortalId}"] .tw-py-1`);
|
|
2336
|
+
console.log('🔍 optionsContainer (alt .tw-py-1):', optionsContainer);
|
|
2337
|
+
}
|
|
2338
|
+
if (!optionsContainer) {
|
|
2339
|
+
optionsContainer = document.querySelector(`[id*="${this.dropdownPortalId}"]`);
|
|
2340
|
+
console.log('🔍 optionsContainer (alt main):', optionsContainer);
|
|
2341
|
+
}
|
|
2342
|
+
if (!optionsContainer) {
|
|
2343
|
+
console.log('🔍 No options container found, returning false');
|
|
2344
|
+
return false;
|
|
2345
|
+
}
|
|
2346
|
+
console.log('🔍 optionsContainer found, clearing and updating with', this.filteredOptions.length, 'options');
|
|
2347
|
+
console.log('🔍 Current optionsContainer HTML before clear:', optionsContainer.innerHTML);
|
|
2348
|
+
// Find and clear only the option buttons and loading states, not the entire container
|
|
2349
|
+
const existingOptions = optionsContainer.querySelectorAll('.cide-select-option, .tw-px-3.tw-py-2, .tw-px-3.tw-py-4');
|
|
2350
|
+
console.log('🔍 Found existing options to remove:', existingOptions.length);
|
|
2351
|
+
existingOptions.forEach(option => option.remove());
|
|
2352
|
+
// Add filtered options directly to DOM
|
|
2353
|
+
this.filteredOptions.forEach((option) => {
|
|
2354
|
+
const button = document.createElement('button');
|
|
2355
|
+
button.type = 'button';
|
|
2356
|
+
button.className = `cide-select-option tw-w-full tw-text-left tw-px-3 tw-py-2 tw-text-sm tw-cursor-pointer tw-transition-colors hover:tw-bg-gray-100 tw-border-none tw-bg-transparent tw-outline-none ${this.isOptionSelected(option) ? 'tw-bg-blue-50 tw-text-blue-700' : ''} ${option.disabled ? 'tw-text-gray-400 tw-cursor-not-allowed' : ''}`;
|
|
2357
|
+
button.textContent = this.getOptionLabel(option);
|
|
2358
|
+
button.disabled = option.disabled || false;
|
|
2359
|
+
// Add event listeners
|
|
2360
|
+
button.addEventListener('mousedown', (e) => {
|
|
2361
|
+
e.preventDefault(); // Prevent blur from closing dropdown before click
|
|
2362
|
+
this.onDropdownMouseDown();
|
|
2363
|
+
});
|
|
2364
|
+
button.addEventListener('click', (e) => {
|
|
2365
|
+
e.preventDefault();
|
|
2366
|
+
e.stopPropagation();
|
|
2367
|
+
this.selectOption(option);
|
|
2368
|
+
});
|
|
2369
|
+
button.addEventListener('keyup', (e) => {
|
|
2370
|
+
if (e.key === 'Enter' || e.key === ' ') {
|
|
2371
|
+
e.preventDefault();
|
|
2372
|
+
this.selectOption(option);
|
|
2373
|
+
}
|
|
2374
|
+
});
|
|
2375
|
+
optionsContainer.appendChild(button);
|
|
2376
|
+
});
|
|
2377
|
+
// Add "No options" message if no options
|
|
2378
|
+
if (this.filteredOptions.length === 0) {
|
|
2379
|
+
const noOptionsDiv = document.createElement('div');
|
|
2380
|
+
noOptionsDiv.className = 'tw-px-3 tw-py-2 tw-text-sm tw-text-gray-500 tw-italic';
|
|
2381
|
+
noOptionsDiv.textContent = this.searchable() && this.searchTerm ? 'No options found' : 'No options available';
|
|
2382
|
+
optionsContainer.appendChild(noOptionsDiv);
|
|
2383
|
+
}
|
|
2384
|
+
console.log('🔍 Options added, final optionsContainer HTML:', optionsContainer.innerHTML);
|
|
2385
|
+
console.log('🔍 Number of child elements in optionsContainer:', optionsContainer.children.length);
|
|
2386
|
+
this.logDebug('Options updated directly in DOM', {
|
|
2387
|
+
filteredOptionsCount: this.filteredOptions.length,
|
|
2388
|
+
searchTerm: this.searchTerm
|
|
2389
|
+
});
|
|
2390
|
+
return true; // Success
|
|
2391
|
+
}
|
|
2392
|
+
catch (error) {
|
|
2393
|
+
console.error(`💥 SELECT [${this.debugId}] updateOptionsInDOM error:`, error);
|
|
2394
|
+
return false; // Failed
|
|
2395
|
+
}
|
|
2396
|
+
}
|
|
2241
2397
|
setupDebouncedSearch() {
|
|
2242
2398
|
this.searchSubject
|
|
2243
2399
|
.pipe(debounceTime(300), // 300ms debounce
|
|
@@ -2679,26 +2835,17 @@ class CideSelectComponent {
|
|
|
2679
2835
|
this.searchTerm = event.target.value;
|
|
2680
2836
|
console.log(`🔍 SELECT [${this.debugId}] Search input changed:`, `"${this.searchTerm}"`);
|
|
2681
2837
|
// If search term is empty, emit immediately without debounce
|
|
2682
|
-
// If search term is empty, emit immediately without debounce
|
|
2683
2838
|
if (this.searchTerm === '' || this.searchTerm === null || this.searchTerm === undefined) {
|
|
2684
2839
|
console.log(`🔍 SELECT [${this.debugId}] Empty search - emitting immediately`);
|
|
2685
2840
|
// Update local filtering immediately
|
|
2686
2841
|
this.filterOptions();
|
|
2687
|
-
|
|
2688
|
-
if (this.portalContext) {
|
|
2689
|
-
this.portalContext.searchTerm = this.searchTerm;
|
|
2690
|
-
this.portalContext.options = this.filteredOptions;
|
|
2691
|
-
}
|
|
2842
|
+
this.updateOptionsInDOM();
|
|
2692
2843
|
this.performSearch('');
|
|
2693
2844
|
}
|
|
2694
2845
|
else {
|
|
2695
2846
|
// Update local filtering immediately for better UX
|
|
2696
2847
|
this.filterOptions();
|
|
2697
|
-
|
|
2698
|
-
if (this.portalContext) {
|
|
2699
|
-
this.portalContext.searchTerm = this.searchTerm;
|
|
2700
|
-
this.portalContext.options = this.filteredOptions;
|
|
2701
|
-
}
|
|
2848
|
+
this.updateOptionsInDOM();
|
|
2702
2849
|
// For non-empty values, use debounced search for API calls
|
|
2703
2850
|
this.searchSubject.next(this.searchTerm);
|
|
2704
2851
|
}
|
|
@@ -2788,11 +2935,33 @@ class CideSelectComponent {
|
|
|
2788
2935
|
return timeoutId;
|
|
2789
2936
|
}
|
|
2790
2937
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CideSelectComponent, deps: [{ token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component });
|
|
2791
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: CideSelectComponent, isStandalone: true, selector: "cide-ele-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelHide: { classPropertyName: "labelHide", publicName: "labelHide", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ngModel: { classPropertyName: "ngModel", publicName: "ngModel", isSignal: false, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, labelPlacement: { classPropertyName: "labelPlacement", publicName: "labelPlacement", isSignal: true, isRequired: false, transformFunction: null }, labelDir: { classPropertyName: "labelDir", publicName: "labelDir", isSignal: true, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: true, isRequired: false, transformFunction: null }, trailingIcon: { classPropertyName: "trailingIcon", publicName: "trailingIcon", isSignal: true, isRequired: false, transformFunction: null }, clearInput: { classPropertyName: "clearInput", publicName: "clearInput", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", 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 }, showSearchInput: { classPropertyName: "showSearchInput", publicName: "showSearchInput", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, valueKey: { classPropertyName: "valueKey", publicName: "valueKey", isSignal: true, isRequired: false, transformFunction: null }, labelKey: { classPropertyName: "labelKey", publicName: "labelKey", isSignal: true, isRequired: false, transformFunction: null }, treeView: { classPropertyName: "treeView", publicName: "treeView", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ngModelChange: "ngModelChange", selectionChange: "change", searchChange: "searchChange" }, queries: [{ propertyName: "optionComponents", predicate: CideSelectOptionComponent }], viewQueries: [{ propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "dropdownTemplate", first: true, predicate: ["dropdownTemplate"], descendants: true }, { propertyName: "dropdownContainer", first: true, predicate: ["dropdownContainer"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cide-select\" [ngClass]=\"{\n 'cide-element-size-xxs': (size() === '2xs'),\n 'cide-element-size-xs': (size() === 'xs'),\n 'cide-element-size-sm': (size() === 'sm'),\n 'cide-element-size-md': (size() === 'md'),\n 'cide-element-size-lg': (size() === 'lg'),\n 'cide-element-leading-icon': leadingIcon(),\n 'cide-element-input-label-floating': (labelPlacement() === 'floating'),\n 'cide-element-input-label-start': (labelDir() === 'start'),\n 'cide-element-input-label-end': (labelDir() === 'end'),\n 'cide-element-input-label-fixed': (labelPlacement() === 'fixed'),\n 'cide-element-input-label-less': (!label() || labelHide()),\n 'cide-element-style-outline': (fill() === 'outline'),\n 'cide-element-style-solid': (fill() === 'solid'),\n 'cide-element-style-standard': (fill() === 'standard'),\n}\">\n @if (label() && !labelHide()) {\n <label [for]=\"id()\" class=\"cide-select-label\">\n {{ label() }}\n @if (required()) {\n <span class=\"tw-text-red-500 tw-ml-1\">*</span>\n }\n </label>\n }\n\n <div class=\"cide-element-select-wrapper tw-relative\">\n <!-- Leading Icon -->\n @if (leadingIcon()) {\n <span class=\"cide-input-leading-icon-wrapper\">\n <span class=\"cide-input-leading-icon material-symbols-outlined tw-text-center\">{{leadingIcon()}}</span>\n </span>\n }\n\n <!-- Select Button -->\n <button type=\"button\" [id]=\"id()\" [disabled]=\"isDisabled()\" (click)=\"toggleDropdown()\" (blur)=\"onBlur()\" [ngClass]=\"{\n 'tw-rounded-e-md tw-rounded-es-md': label() && labelPlacement() === 'fixed',\n 'tw-rounded-md': !(label() && labelPlacement() === 'fixed'),\n 'tw-pl-1': !leadingIcon(),\n 'tw-pr-8': trailingIcon() || clearInput() || loading(),\n 'tw-pr-1': !trailingIcon() && !clearInput() && !loading(),\n 'tw-h-8 tw-pt-0.5 tw-pb-0': size() === 'md',\n 'tw-h-7': size() === 'sm',\n '!tw-mt-0': labelHide(),\n 'tw-opacity-50 tw-cursor-not-allowed': isDisabled(),\n 'cide-select-button tw-m-0 tw-w-full tw-bg-transparent tw-overflow-hidden tw-border-solid tw-p-0 tw-outline-none tw-text-left tw-cursor-pointer': true\n }\" class=\"cide-select-button\">\n\n <span class=\"cide-select-value\" [ngClass]=\"{'tw-text-gray-400': !ngModel}\">\n {{ ngModel ? getSelectedOptionLabel() : placeholder() }}\n </span>\n </button>\n\n <!-- Trailing Icon (Dropdown Arrow or Loading Spinner) -->\n @if (!clearInput() || !ngModel || loading()) {\n <span class=\"tw-absolute tw-top-1/2 tw-right-0 tw-transform -tw-translate-y-1/2 tw-select-none tw-z-10\">\n <!-- Loading Spinner -->\n @if (loading()) {\n <span class=\"tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center tw-text-gray-500\">\n <svg class=\"tw-animate-spin tw-h-4 tw-w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"tw-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"tw-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n </span>\n }\n <!-- Dropdown Arrow -->\n @if (!loading()) {\n <span\n class=\"material-symbols-outlined tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center !tw-text-2xl tw-transition-transform tw-text-gray-500\"\n [ngClass]=\"{'tw-rotate-180': isOpen}\">\n expand_more\n </span>\n }\n </span>\n }\n\n <!-- Clear Button -->\n @if (clearInput() && ngModel) {\n <button class=\"cide-input-clear\" (click)=\"clearSelection()\" type=\"button\">\n <span class=\"cide-input-clear-icon material-symbols-outlined\">close</span>\n </button>\n }\n\n\n </div>\n\n <!-- Error/Helper Text -->\n @if ((errorText() || helperText()) && !isValid) {\n <span class=\"cide-select-help-error-text\">\n {{ errorText() || helperText() }}\n </span>\n }\n @if (helperText() && isValid) {\n <span class=\"cide-select-help-error-text\">\n {{ helperText() }}\n </span>\n }\n\n <!-- Portal Container -->\n <div #dropdownContainer></div>\n</div>\n\n<!-- Portal Template for Dropdown -->\n<ng-template #dropdownTemplate let-context=\"context\">\n <div\n class=\"cide-select-dropdown-portal tw-bg-white tw-border tw-border-gray-300 tw-rounded-md tw-shadow-lg tw-max-h-60 tw-overflow-y-auto tw-z-50\">\n <!-- Search Input (if searchable and showSearchInput is true) -->\n @if (context?.searchable && showSearchInput()) {\n <div class=\"tw-p-2 tw-border-b tw-border-gray-200 tw-sticky tw-top-0 tw-z-20 tw-bg-white\">\n <input #searchInput type=\"text\" placeholder=\"Search options...\" [value]=\"context?.searchTerm\"\n (input)=\"context?.onSearchInput($event)\" (mousedown)=\"onDropdownMouseDown()\" (focus)=\"onDropdownMouseDown()\"\n (click)=\"$event.stopPropagation()\" (blur)=\"onSearchInputBlur($event)\"\n class=\"tw-w-full tw-px-2 tw-py-1 tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-outline-none focus:tw-border-blue-500\">\n </div>\n }\n\n <!-- Options List -->\n <div class=\"tw-py-1\">\n <!-- Loading State -->\n @if (context?.loading) {\n <div class=\"tw-px-3 tw-py-4 tw-text-center\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-space-x-2\">\n <svg class=\"tw-animate-spin tw-h-4 tw-w-4 tw-text-gray-500\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"tw-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"tw-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"tw-text-sm tw-text-gray-500\">Loading...</span>\n </div>\n </div>\n }\n <!-- Options -->\n @if (!context?.loading) {\n @for (option of context?.options; track $index) {\n <button type=\"button\" (mousedown)=\"onDropdownMouseDown()\" (click)=\"context?.selectOption(option)\"\n (keyup.enter)=\"context?.selectOption(option)\" (keyup.space)=\"context?.selectOption(option)\"\n [disabled]=\"option.disabled\" [ngClass]=\"{\n 'cide-select-option tw-w-full tw-text-left tw-px-3 tw-py-2 tw-text-sm tw-cursor-pointer tw-transition-colors hover:tw-bg-gray-100 tw-border-none tw-bg-transparent tw-outline-none': true,\n 'tw-bg-blue-50 tw-text-blue-700': context?.isOptionSelected(option),\n 'tw-text-gray-400 tw-cursor-not-allowed': option.disabled,\n 'cide-select-tree-option': context?.treeView?.enabled\n }\" class=\"cide-select-option\" [style.white-space]=\"context?.treeView?.enabled ? 'pre' : 'normal'\"\n [style.font-family]=\"context?.treeView?.enabled ? 'monospace' : 'inherit'\">\n {{ context?.getOptionLabel(option) }}\n </button>\n }\n }\n\n <!-- No options message -->\n @if (!context?.loading && context?.options.length === 0) {\n <div class=\"tw-px-3 tw-py-2 tw-text-sm tw-text-gray-500 tw-italic\">\n {{ context?.searchable && context?.searchTerm ? 'No options found' : 'No options available' }}\n </div>\n }\n </div>\n </div>\n</ng-template>", styles: [".cide-select{position:relative;width:100%}.cide-select .cide-select-button{display:flex;align-items:center;justify-content:space-between;width:100%;background-color:transparent;transition:all .2s ease-in-out;cursor:pointer;outline:none}.cide-select .cide-select-button:disabled{cursor:not-allowed}.cide-select .cide-select-value{flex:1;text-align:left}.cide-select .cide-select-dropdown{position:absolute;left:0;right:0;z-index:1000;background-color:#fff;border:1px solid var(--cide-input-border);border-radius:.375rem;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;max-height:15rem;overflow-y:auto}.cide-select .cide-select-dropdown .cide-select-option{display:block;width:100%;text-align:left;padding:.5rem .75rem;font-size:.875rem;cursor:pointer;transition:background-color .15s ease-in-out;border:none;background:transparent;outline:none}.cide-select .cide-select-dropdown .cide-select-option:hover:not(:disabled){background-color:#f3f4f6}.cide-select .cide-select-dropdown .cide-select-option:focus{background-color:#f3f4f6}.cide-select .cide-select-dropdown .cide-select-option:disabled{cursor:not-allowed}.cide-select-dropdown-portal{width:auto!important;min-width:200px;max-width:80vw;word-wrap:break-word;overflow-wrap:break-word}.cide-select-dropdown-portal .tw-py-1{min-width:0}.cide-select-dropdown-portal .cide-select-option{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }] });
|
|
2938
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "20.3.15", type: CideSelectComponent, isStandalone: true, selector: "cide-ele-select", inputs: { label: { classPropertyName: "label", publicName: "label", isSignal: true, isRequired: false, transformFunction: null }, labelHide: { classPropertyName: "labelHide", publicName: "labelHide", isSignal: true, isRequired: false, transformFunction: null }, placeholder: { classPropertyName: "placeholder", publicName: "placeholder", isSignal: true, isRequired: false, transformFunction: null }, helperText: { classPropertyName: "helperText", publicName: "helperText", isSignal: true, isRequired: false, transformFunction: null }, errorText: { classPropertyName: "errorText", publicName: "errorText", isSignal: true, isRequired: false, transformFunction: null }, required: { classPropertyName: "required", publicName: "required", isSignal: true, isRequired: false, transformFunction: null }, disabled: { classPropertyName: "disabled", publicName: "disabled", isSignal: true, isRequired: false, transformFunction: null }, id: { classPropertyName: "id", publicName: "id", isSignal: true, isRequired: false, transformFunction: null }, ngModel: { classPropertyName: "ngModel", publicName: "ngModel", isSignal: false, isRequired: false, transformFunction: null }, size: { classPropertyName: "size", publicName: "size", isSignal: true, isRequired: false, transformFunction: null }, fill: { classPropertyName: "fill", publicName: "fill", isSignal: true, isRequired: false, transformFunction: null }, labelPlacement: { classPropertyName: "labelPlacement", publicName: "labelPlacement", isSignal: true, isRequired: false, transformFunction: null }, labelDir: { classPropertyName: "labelDir", publicName: "labelDir", isSignal: true, isRequired: false, transformFunction: null }, leadingIcon: { classPropertyName: "leadingIcon", publicName: "leadingIcon", isSignal: true, isRequired: false, transformFunction: null }, trailingIcon: { classPropertyName: "trailingIcon", publicName: "trailingIcon", isSignal: true, isRequired: false, transformFunction: null }, clearInput: { classPropertyName: "clearInput", publicName: "clearInput", isSignal: true, isRequired: false, transformFunction: null }, options: { classPropertyName: "options", publicName: "options", 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 }, showSearchInput: { classPropertyName: "showSearchInput", publicName: "showSearchInput", isSignal: true, isRequired: false, transformFunction: null }, loading: { classPropertyName: "loading", publicName: "loading", isSignal: true, isRequired: false, transformFunction: null }, valueKey: { classPropertyName: "valueKey", publicName: "valueKey", isSignal: true, isRequired: false, transformFunction: null }, labelKey: { classPropertyName: "labelKey", publicName: "labelKey", isSignal: true, isRequired: false, transformFunction: null }, treeView: { classPropertyName: "treeView", publicName: "treeView", isSignal: true, isRequired: false, transformFunction: null } }, outputs: { ngModelChange: "ngModelChange", selectionChange: "change", searchChange: "searchChange" }, providers: [
|
|
2939
|
+
{
|
|
2940
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2941
|
+
useExisting: forwardRef(() => CideSelectComponent),
|
|
2942
|
+
multi: true
|
|
2943
|
+
},
|
|
2944
|
+
{
|
|
2945
|
+
provide: NG_VALIDATORS,
|
|
2946
|
+
multi: true,
|
|
2947
|
+
useExisting: forwardRef(() => CideSelectComponent),
|
|
2948
|
+
}
|
|
2949
|
+
], queries: [{ propertyName: "optionComponents", predicate: CideSelectOptionComponent }], viewQueries: [{ propertyName: "searchInputRef", first: true, predicate: ["searchInput"], descendants: true }, { propertyName: "dropdownTemplate", first: true, predicate: ["dropdownTemplate"], descendants: true }, { propertyName: "dropdownContainer", first: true, predicate: ["dropdownContainer"], descendants: true, read: ViewContainerRef }], usesOnChanges: true, ngImport: i0, template: "<div class=\"cide-select\" [ngClass]=\"{\n 'cide-element-size-xxs': (size() === '2xs'),\n 'cide-element-size-xs': (size() === 'xs'),\n 'cide-element-size-sm': (size() === 'sm'),\n 'cide-element-size-md': (size() === 'md'),\n 'cide-element-size-lg': (size() === 'lg'),\n 'cide-element-leading-icon': leadingIcon(),\n 'cide-element-input-label-floating': (labelPlacement() === 'floating'),\n 'cide-element-input-label-start': (labelDir() === 'start'),\n 'cide-element-input-label-end': (labelDir() === 'end'),\n 'cide-element-input-label-fixed': (labelPlacement() === 'fixed'),\n 'cide-element-input-label-less': (!label() || labelHide()),\n 'cide-element-style-outline': (fill() === 'outline'),\n 'cide-element-style-solid': (fill() === 'solid'),\n 'cide-element-style-standard': (fill() === 'standard'),\n}\">\n @if (label() && !labelHide()) {\n <label [for]=\"id()\" class=\"cide-select-label\">\n {{ label() }}\n @if (required()) {\n <span class=\"tw-text-red-500 tw-ml-1\">*</span>\n }\n </label>\n }\n\n <div class=\"cide-element-select-wrapper tw-relative\">\n <!-- Leading Icon -->\n @if (leadingIcon()) {\n <span class=\"cide-input-leading-icon-wrapper\">\n <span class=\"cide-input-leading-icon material-symbols-outlined tw-text-center\">{{leadingIcon()}}</span>\n </span>\n }\n\n <!-- Select Button -->\n <button type=\"button\" [id]=\"id()\" [disabled]=\"isDisabled()\" (click)=\"toggleDropdown()\" (blur)=\"onBlur()\" [ngClass]=\"{\n 'tw-rounded-e-md tw-rounded-es-md': label() && labelPlacement() === 'fixed',\n 'tw-rounded-md': !(label() && labelPlacement() === 'fixed'),\n 'tw-pl-1': !leadingIcon(),\n 'tw-pr-8': trailingIcon() || clearInput() || loading(),\n 'tw-pr-1': !trailingIcon() && !clearInput() && !loading(),\n 'tw-h-8 tw-pt-0.5 tw-pb-0': size() === 'md',\n 'tw-h-7': size() === 'sm',\n '!tw-mt-0': labelHide(),\n 'tw-opacity-50 tw-cursor-not-allowed': isDisabled(),\n 'cide-select-button tw-m-0 tw-w-full tw-bg-transparent tw-overflow-hidden tw-border-solid tw-p-0 tw-outline-none tw-text-left tw-cursor-pointer': true\n }\" class=\"cide-select-button\">\n\n <span class=\"cide-select-value\" [ngClass]=\"{'tw-text-gray-400': !ngModel}\">\n {{ ngModel ? getSelectedOptionLabel() : placeholder() }}\n </span>\n </button>\n\n <!-- Trailing Icon (Dropdown Arrow or Loading Spinner) -->\n @if (!clearInput() || !ngModel || loading()) {\n <span class=\"tw-absolute tw-top-1/2 tw-right-0 tw-transform -tw-translate-y-1/2 tw-select-none tw-z-10\">\n <!-- Loading Spinner -->\n @if (loading()) {\n <span class=\"tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center tw-text-gray-500\">\n <svg class=\"tw-animate-spin tw-h-4 tw-w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"tw-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"tw-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n </span>\n }\n <!-- Dropdown Arrow -->\n @if (!loading()) {\n <span\n class=\"material-symbols-outlined tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center !tw-text-2xl tw-transition-transform tw-text-gray-500\"\n [ngClass]=\"{'tw-rotate-180': isOpen}\">\n expand_more\n </span>\n }\n </span>\n }\n\n <!-- Clear Button -->\n @if (clearInput() && ngModel) {\n <button class=\"cide-input-clear\" (click)=\"clearSelection()\" type=\"button\">\n <span class=\"cide-input-clear-icon material-symbols-outlined\">close</span>\n </button>\n }\n\n\n </div>\n\n <!-- Error/Helper Text -->\n @if ((errorText() || helperText()) && !isValid) {\n <span class=\"cide-select-help-error-text\">\n {{ errorText() || helperText() }}\n </span>\n }\n @if (helperText() && isValid) {\n <span class=\"cide-select-help-error-text\">\n {{ helperText() }}\n </span>\n }\n\n <!-- Portal Container -->\n <div #dropdownContainer></div>\n</div>\n\n<!-- Portal Template for Dropdown -->\n<ng-template #dropdownTemplate let-context=\"context\">\n <div\n class=\"cide-select-dropdown-portal tw-bg-white tw-border tw-border-gray-300 tw-rounded-md tw-shadow-lg tw-max-h-60 tw-overflow-y-auto tw-z-50\">\n <!-- Search Input (if searchable and showSearchInput is true) -->\n @if (context?.searchable && showSearchInput()) {\n <div class=\"tw-p-2 tw-border-b tw-border-gray-200 tw-sticky tw-top-0 tw-z-20 tw-bg-white\">\n <input #searchInput type=\"text\" placeholder=\"Search options...\" [value]=\"context?.searchTerm\"\n (input)=\"context?.onSearchInput($event)\" (mousedown)=\"onDropdownMouseDown()\" (focus)=\"onDropdownMouseDown()\"\n (click)=\"$event.stopPropagation()\" (blur)=\"onSearchInputBlur($event)\"\n class=\"tw-w-full tw-px-2 tw-py-1 tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-outline-none focus:tw-border-blue-500\">\n </div>\n }\n\n <!-- Options List -->\n <div class=\"tw-py-1\">\n <!-- Loading State -->\n @if (context?.loading) {\n <div class=\"tw-px-3 tw-py-4 tw-text-center\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-space-x-2\">\n <svg class=\"tw-animate-spin tw-h-4 tw-w-4 tw-text-gray-500\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"tw-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"tw-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"tw-text-sm tw-text-gray-500\">Loading...</span>\n </div>\n </div>\n }\n <!-- Options -->\n @if (!context?.loading) {\n @for (option of context?.options; track $index) {\n <button type=\"button\" (mousedown)=\"onDropdownMouseDown()\" (click)=\"context?.selectOption(option)\"\n (keyup.enter)=\"context?.selectOption(option)\" (keyup.space)=\"context?.selectOption(option)\"\n [disabled]=\"option.disabled\" [ngClass]=\"{\n 'cide-select-option tw-w-full tw-text-left tw-px-3 tw-py-2 tw-text-sm tw-cursor-pointer tw-transition-colors hover:tw-bg-gray-100 tw-border-none tw-bg-transparent tw-outline-none': true,\n 'tw-bg-blue-50 tw-text-blue-700': context?.isOptionSelected(option),\n 'tw-text-gray-400 tw-cursor-not-allowed': option.disabled,\n 'cide-select-tree-option': context?.treeView?.enabled\n }\" class=\"cide-select-option\" [style.white-space]=\"context?.treeView?.enabled ? 'pre' : 'normal'\"\n [style.font-family]=\"context?.treeView?.enabled ? 'monospace' : 'inherit'\">\n {{ context?.getOptionLabel(option) }}\n </button>\n }\n }\n\n <!-- No options message -->\n @if (!context?.loading && context?.options.length === 0) {\n <div class=\"tw-px-3 tw-py-2 tw-text-sm tw-text-gray-500 tw-italic\">\n {{ context?.searchable && context?.searchTerm ? 'No options found' : 'No options available' }}\n </div>\n }\n </div>\n </div>\n</ng-template>", styles: [".cide-select{position:relative;width:100%}.cide-select .cide-select-button{display:flex;align-items:center;justify-content:space-between;width:100%;background-color:transparent;transition:all .2s ease-in-out;cursor:pointer;outline:none}.cide-select .cide-select-button:disabled{cursor:not-allowed}.cide-select .cide-select-value{flex:1;text-align:left}.cide-select .cide-select-dropdown{position:absolute;left:0;right:0;z-index:1000;background-color:#fff;border:1px solid var(--cide-input-border);border-radius:.375rem;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;max-height:15rem;overflow-y:auto}.cide-select .cide-select-dropdown .cide-select-option{display:block;width:100%;text-align:left;padding:.5rem .75rem;font-size:.875rem;cursor:pointer;transition:background-color .15s ease-in-out;border:none;background:transparent;outline:none}.cide-select .cide-select-dropdown .cide-select-option:hover:not(:disabled){background-color:#f3f4f6}.cide-select .cide-select-dropdown .cide-select-option:focus{background-color:#f3f4f6}.cide-select .cide-select-dropdown .cide-select-option:disabled{cursor:not-allowed}.cide-select-dropdown-portal{width:auto!important;min-width:200px;max-width:80vw;word-wrap:break-word;overflow-wrap:break-word}.cide-select-dropdown-portal .tw-py-1{min-width:0}.cide-select-dropdown-portal .cide-select-option{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}\n"], dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i1.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "ngmodule", type: FormsModule }] });
|
|
2792
2950
|
}
|
|
2793
2951
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.3.15", ngImport: i0, type: CideSelectComponent, decorators: [{
|
|
2794
2952
|
type: Component,
|
|
2795
|
-
args: [{ selector: 'cide-ele-select', standalone: true, imports: [CommonModule, FormsModule],
|
|
2953
|
+
args: [{ selector: 'cide-ele-select', standalone: true, imports: [CommonModule, FormsModule], providers: [
|
|
2954
|
+
{
|
|
2955
|
+
provide: NG_VALUE_ACCESSOR,
|
|
2956
|
+
useExisting: forwardRef(() => CideSelectComponent),
|
|
2957
|
+
multi: true
|
|
2958
|
+
},
|
|
2959
|
+
{
|
|
2960
|
+
provide: NG_VALIDATORS,
|
|
2961
|
+
multi: true,
|
|
2962
|
+
useExisting: forwardRef(() => CideSelectComponent),
|
|
2963
|
+
}
|
|
2964
|
+
], template: "<div class=\"cide-select\" [ngClass]=\"{\n 'cide-element-size-xxs': (size() === '2xs'),\n 'cide-element-size-xs': (size() === 'xs'),\n 'cide-element-size-sm': (size() === 'sm'),\n 'cide-element-size-md': (size() === 'md'),\n 'cide-element-size-lg': (size() === 'lg'),\n 'cide-element-leading-icon': leadingIcon(),\n 'cide-element-input-label-floating': (labelPlacement() === 'floating'),\n 'cide-element-input-label-start': (labelDir() === 'start'),\n 'cide-element-input-label-end': (labelDir() === 'end'),\n 'cide-element-input-label-fixed': (labelPlacement() === 'fixed'),\n 'cide-element-input-label-less': (!label() || labelHide()),\n 'cide-element-style-outline': (fill() === 'outline'),\n 'cide-element-style-solid': (fill() === 'solid'),\n 'cide-element-style-standard': (fill() === 'standard'),\n}\">\n @if (label() && !labelHide()) {\n <label [for]=\"id()\" class=\"cide-select-label\">\n {{ label() }}\n @if (required()) {\n <span class=\"tw-text-red-500 tw-ml-1\">*</span>\n }\n </label>\n }\n\n <div class=\"cide-element-select-wrapper tw-relative\">\n <!-- Leading Icon -->\n @if (leadingIcon()) {\n <span class=\"cide-input-leading-icon-wrapper\">\n <span class=\"cide-input-leading-icon material-symbols-outlined tw-text-center\">{{leadingIcon()}}</span>\n </span>\n }\n\n <!-- Select Button -->\n <button type=\"button\" [id]=\"id()\" [disabled]=\"isDisabled()\" (click)=\"toggleDropdown()\" (blur)=\"onBlur()\" [ngClass]=\"{\n 'tw-rounded-e-md tw-rounded-es-md': label() && labelPlacement() === 'fixed',\n 'tw-rounded-md': !(label() && labelPlacement() === 'fixed'),\n 'tw-pl-1': !leadingIcon(),\n 'tw-pr-8': trailingIcon() || clearInput() || loading(),\n 'tw-pr-1': !trailingIcon() && !clearInput() && !loading(),\n 'tw-h-8 tw-pt-0.5 tw-pb-0': size() === 'md',\n 'tw-h-7': size() === 'sm',\n '!tw-mt-0': labelHide(),\n 'tw-opacity-50 tw-cursor-not-allowed': isDisabled(),\n 'cide-select-button tw-m-0 tw-w-full tw-bg-transparent tw-overflow-hidden tw-border-solid tw-p-0 tw-outline-none tw-text-left tw-cursor-pointer': true\n }\" class=\"cide-select-button\">\n\n <span class=\"cide-select-value\" [ngClass]=\"{'tw-text-gray-400': !ngModel}\">\n {{ ngModel ? getSelectedOptionLabel() : placeholder() }}\n </span>\n </button>\n\n <!-- Trailing Icon (Dropdown Arrow or Loading Spinner) -->\n @if (!clearInput() || !ngModel || loading()) {\n <span class=\"tw-absolute tw-top-1/2 tw-right-0 tw-transform -tw-translate-y-1/2 tw-select-none tw-z-10\">\n <!-- Loading Spinner -->\n @if (loading()) {\n <span class=\"tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center tw-text-gray-500\">\n <svg class=\"tw-animate-spin tw-h-4 tw-w-4\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\" viewBox=\"0 0 24 24\">\n <circle class=\"tw-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"tw-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n </span>\n }\n <!-- Dropdown Arrow -->\n @if (!loading()) {\n <span\n class=\"material-symbols-outlined tw-w-8 tw-h-8 tw-flex tw-items-center tw-justify-center !tw-text-2xl tw-transition-transform tw-text-gray-500\"\n [ngClass]=\"{'tw-rotate-180': isOpen}\">\n expand_more\n </span>\n }\n </span>\n }\n\n <!-- Clear Button -->\n @if (clearInput() && ngModel) {\n <button class=\"cide-input-clear\" (click)=\"clearSelection()\" type=\"button\">\n <span class=\"cide-input-clear-icon material-symbols-outlined\">close</span>\n </button>\n }\n\n\n </div>\n\n <!-- Error/Helper Text -->\n @if ((errorText() || helperText()) && !isValid) {\n <span class=\"cide-select-help-error-text\">\n {{ errorText() || helperText() }}\n </span>\n }\n @if (helperText() && isValid) {\n <span class=\"cide-select-help-error-text\">\n {{ helperText() }}\n </span>\n }\n\n <!-- Portal Container -->\n <div #dropdownContainer></div>\n</div>\n\n<!-- Portal Template for Dropdown -->\n<ng-template #dropdownTemplate let-context=\"context\">\n <div\n class=\"cide-select-dropdown-portal tw-bg-white tw-border tw-border-gray-300 tw-rounded-md tw-shadow-lg tw-max-h-60 tw-overflow-y-auto tw-z-50\">\n <!-- Search Input (if searchable and showSearchInput is true) -->\n @if (context?.searchable && showSearchInput()) {\n <div class=\"tw-p-2 tw-border-b tw-border-gray-200 tw-sticky tw-top-0 tw-z-20 tw-bg-white\">\n <input #searchInput type=\"text\" placeholder=\"Search options...\" [value]=\"context?.searchTerm\"\n (input)=\"context?.onSearchInput($event)\" (mousedown)=\"onDropdownMouseDown()\" (focus)=\"onDropdownMouseDown()\"\n (click)=\"$event.stopPropagation()\" (blur)=\"onSearchInputBlur($event)\"\n class=\"tw-w-full tw-px-2 tw-py-1 tw-text-sm tw-border tw-border-gray-300 tw-rounded tw-outline-none focus:tw-border-blue-500\">\n </div>\n }\n\n <!-- Options List -->\n <div class=\"tw-py-1\">\n <!-- Loading State -->\n @if (context?.loading) {\n <div class=\"tw-px-3 tw-py-4 tw-text-center\">\n <div class=\"tw-flex tw-items-center tw-justify-center tw-space-x-2\">\n <svg class=\"tw-animate-spin tw-h-4 tw-w-4 tw-text-gray-500\" xmlns=\"http://www.w3.org/2000/svg\" fill=\"none\"\n viewBox=\"0 0 24 24\">\n <circle class=\"tw-opacity-25\" cx=\"12\" cy=\"12\" r=\"10\" stroke=\"currentColor\" stroke-width=\"4\"></circle>\n <path class=\"tw-opacity-75\" fill=\"currentColor\"\n d=\"M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z\">\n </path>\n </svg>\n <span class=\"tw-text-sm tw-text-gray-500\">Loading...</span>\n </div>\n </div>\n }\n <!-- Options -->\n @if (!context?.loading) {\n @for (option of context?.options; track $index) {\n <button type=\"button\" (mousedown)=\"onDropdownMouseDown()\" (click)=\"context?.selectOption(option)\"\n (keyup.enter)=\"context?.selectOption(option)\" (keyup.space)=\"context?.selectOption(option)\"\n [disabled]=\"option.disabled\" [ngClass]=\"{\n 'cide-select-option tw-w-full tw-text-left tw-px-3 tw-py-2 tw-text-sm tw-cursor-pointer tw-transition-colors hover:tw-bg-gray-100 tw-border-none tw-bg-transparent tw-outline-none': true,\n 'tw-bg-blue-50 tw-text-blue-700': context?.isOptionSelected(option),\n 'tw-text-gray-400 tw-cursor-not-allowed': option.disabled,\n 'cide-select-tree-option': context?.treeView?.enabled\n }\" class=\"cide-select-option\" [style.white-space]=\"context?.treeView?.enabled ? 'pre' : 'normal'\"\n [style.font-family]=\"context?.treeView?.enabled ? 'monospace' : 'inherit'\">\n {{ context?.getOptionLabel(option) }}\n </button>\n }\n }\n\n <!-- No options message -->\n @if (!context?.loading && context?.options.length === 0) {\n <div class=\"tw-px-3 tw-py-2 tw-text-sm tw-text-gray-500 tw-italic\">\n {{ context?.searchable && context?.searchTerm ? 'No options found' : 'No options available' }}\n </div>\n }\n </div>\n </div>\n</ng-template>", styles: [".cide-select{position:relative;width:100%}.cide-select .cide-select-button{display:flex;align-items:center;justify-content:space-between;width:100%;background-color:transparent;transition:all .2s ease-in-out;cursor:pointer;outline:none}.cide-select .cide-select-button:disabled{cursor:not-allowed}.cide-select .cide-select-value{flex:1;text-align:left}.cide-select .cide-select-dropdown{position:absolute;left:0;right:0;z-index:1000;background-color:#fff;border:1px solid var(--cide-input-border);border-radius:.375rem;box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;max-height:15rem;overflow-y:auto}.cide-select .cide-select-dropdown .cide-select-option{display:block;width:100%;text-align:left;padding:.5rem .75rem;font-size:.875rem;cursor:pointer;transition:background-color .15s ease-in-out;border:none;background:transparent;outline:none}.cide-select .cide-select-dropdown .cide-select-option:hover:not(:disabled){background-color:#f3f4f6}.cide-select .cide-select-dropdown .cide-select-option:focus{background-color:#f3f4f6}.cide-select .cide-select-dropdown .cide-select-option:disabled{cursor:not-allowed}.cide-select-dropdown-portal{width:auto!important;min-width:200px;max-width:80vw;word-wrap:break-word;overflow-wrap:break-word}.cide-select-dropdown-portal .tw-py-1{min-width:0}.cide-select-dropdown-portal .cide-select-option{white-space:nowrap;overflow:hidden;text-overflow:ellipsis;max-width:100%}\n"] }]
|
|
2796
2965
|
}], ctorParameters: () => [{ type: i0.ElementRef }], propDecorators: { optionComponents: [{
|
|
2797
2966
|
type: ContentChildren,
|
|
2798
2967
|
args: [CideSelectOptionComponent]
|