@smilodon/core 1.4.3 → 1.4.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +31 -0
- package/dist/index.cjs +260 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +260 -8
- package/dist/index.js.map +1 -1
- package/dist/index.min.js +1 -1
- package/dist/index.min.js.map +1 -1
- package/dist/index.umd.js +260 -8
- package/dist/index.umd.js.map +1 -1
- package/dist/index.umd.min.js +1 -1
- package/dist/index.umd.min.js.map +1 -1
- package/dist/types/src/components/enhanced-select.d.ts +12 -1
- package/dist/types/src/config/global-config.d.ts +21 -0
- package/dist/types/src/index.d.ts +1 -1
- package/dist/types/src/types.d.ts +5 -0
- package/dist/types/src/utils/csp-styles.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -136,6 +136,31 @@ See the [main documentation](https://github.com/navidrezadoost/smilodon#readme)
|
|
|
136
136
|
|
|
137
137
|
## API Reference
|
|
138
138
|
|
|
139
|
+
### Clear Control (Selection/Search Reset)
|
|
140
|
+
|
|
141
|
+
```javascript
|
|
142
|
+
const select = document.querySelector('enhanced-select');
|
|
143
|
+
|
|
144
|
+
select.updateConfig({
|
|
145
|
+
clearControl: {
|
|
146
|
+
enabled: true,
|
|
147
|
+
clearSelection: true,
|
|
148
|
+
clearSearch: true,
|
|
149
|
+
hideWhenEmpty: true,
|
|
150
|
+
ariaLabel: 'Clear selected and searched values',
|
|
151
|
+
icon: '✕',
|
|
152
|
+
}
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
select.addEventListener('clear', (e) => {
|
|
156
|
+
console.log(e.detail); // { clearedSelection: boolean, clearedSearch: boolean }
|
|
157
|
+
});
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Style hooks:
|
|
161
|
+
- Parts: `::part(clear-button)`, `::part(clear-icon)`
|
|
162
|
+
- Tokens: `--select-clear-button-*`, `--select-clear-icon-*`, `--select-input-padding-with-clear`
|
|
163
|
+
|
|
139
164
|
### Properties
|
|
140
165
|
|
|
141
166
|
```typescript
|
|
@@ -560,6 +585,9 @@ enhanced-select {
|
|
|
560
585
|
/* Selected state */
|
|
561
586
|
--select-option-selected-bg: #e0e7ff;
|
|
562
587
|
--select-option-selected-color: #4338ca;
|
|
588
|
+
--select-option-selected-border: 1px solid #4338ca;
|
|
589
|
+
--select-option-selected-hover-bg: #c7d2fe;
|
|
590
|
+
--select-option-selected-hover-border: 1px solid #3730a3;
|
|
563
591
|
|
|
564
592
|
/* Active/focused state */
|
|
565
593
|
--select-option-active-bg: #f3f4f6;
|
|
@@ -610,6 +638,9 @@ enhanced-select.dark-mode {
|
|
|
610
638
|
--select-option-hover-color /* Hover text color (#1f2937) */
|
|
611
639
|
--select-option-selected-bg /* Selected background (#e0e7ff) */
|
|
612
640
|
--select-option-selected-color /* Selected text color (#4338ca) */
|
|
641
|
+
--select-option-selected-border /* Selected border (inherits option border by default) */
|
|
642
|
+
--select-option-selected-hover-bg /* Selected+hover background (inherits selected bg by default) */
|
|
643
|
+
--select-option-selected-hover-border /* Selected+hover border (inherits selected border by default) */
|
|
613
644
|
--select-option-active-bg /* Active background (#f3f4f6) */
|
|
614
645
|
--select-option-active-color /* Active text color (#1f2937) */
|
|
615
646
|
--select-dropdown-bg /* Dropdown background (white) */
|
package/dist/index.cjs
CHANGED
|
@@ -1394,6 +1394,14 @@ const defaultConfig = {
|
|
|
1394
1394
|
expandLabel: 'Show more',
|
|
1395
1395
|
collapseLabel: 'Show less',
|
|
1396
1396
|
},
|
|
1397
|
+
clearControl: {
|
|
1398
|
+
enabled: false,
|
|
1399
|
+
clearSelection: true,
|
|
1400
|
+
clearSearch: true,
|
|
1401
|
+
hideWhenEmpty: true,
|
|
1402
|
+
ariaLabel: 'Clear selection and search',
|
|
1403
|
+
icon: '×',
|
|
1404
|
+
},
|
|
1397
1405
|
callbacks: {},
|
|
1398
1406
|
enabled: true,
|
|
1399
1407
|
searchable: false,
|
|
@@ -1498,10 +1506,15 @@ class SelectOption extends HTMLElement {
|
|
|
1498
1506
|
display: flex;
|
|
1499
1507
|
align-items: center;
|
|
1500
1508
|
justify-content: space-between;
|
|
1501
|
-
padding: 8px 12px;
|
|
1509
|
+
padding: var(--select-option-padding, 8px 12px);
|
|
1502
1510
|
cursor: pointer;
|
|
1503
1511
|
user-select: none;
|
|
1504
|
-
transition: background-color 0.2s ease;
|
|
1512
|
+
transition: var(--select-option-transition, background-color 0.2s ease);
|
|
1513
|
+
border: var(--select-option-border, none);
|
|
1514
|
+
border-bottom: var(--select-option-border-bottom, none);
|
|
1515
|
+
border-radius: var(--select-option-border-radius, 0);
|
|
1516
|
+
box-shadow: var(--select-option-shadow, none);
|
|
1517
|
+
transform: var(--select-option-transform, none);
|
|
1505
1518
|
}
|
|
1506
1519
|
|
|
1507
1520
|
.option-container:hover {
|
|
@@ -1511,6 +1524,20 @@ class SelectOption extends HTMLElement {
|
|
|
1511
1524
|
.option-container.selected {
|
|
1512
1525
|
background-color: var(--select-option-selected-bg, #e3f2fd);
|
|
1513
1526
|
color: var(--select-option-selected-color, #1976d2);
|
|
1527
|
+
border: var(--select-option-selected-border, var(--select-option-border, none));
|
|
1528
|
+
border-bottom: var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none));
|
|
1529
|
+
border-radius: var(--select-option-selected-border-radius, var(--select-option-border-radius, 0));
|
|
1530
|
+
box-shadow: var(--select-option-selected-shadow, var(--select-option-shadow, none));
|
|
1531
|
+
transform: var(--select-option-selected-transform, var(--select-option-transform, none));
|
|
1532
|
+
}
|
|
1533
|
+
|
|
1534
|
+
.option-container.selected:hover {
|
|
1535
|
+
background-color: var(--select-option-selected-hover-bg, var(--select-option-selected-bg, #e3f2fd));
|
|
1536
|
+
color: var(--select-option-selected-hover-color, var(--select-option-selected-color, #1976d2));
|
|
1537
|
+
border: var(--select-option-selected-hover-border, var(--select-option-selected-border, var(--select-option-border, none)));
|
|
1538
|
+
border-bottom: var(--select-option-selected-hover-border-bottom, var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none)));
|
|
1539
|
+
box-shadow: var(--select-option-selected-hover-shadow, var(--select-option-selected-shadow, var(--select-option-shadow, none)));
|
|
1540
|
+
transform: var(--select-option-selected-hover-transform, var(--select-option-selected-transform, var(--select-option-transform, none)));
|
|
1514
1541
|
}
|
|
1515
1542
|
|
|
1516
1543
|
.option-container.active {
|
|
@@ -1818,6 +1845,16 @@ if (!customElements.get('select-option')) {
|
|
|
1818
1845
|
* server-side selection, and full customization
|
|
1819
1846
|
*/
|
|
1820
1847
|
class EnhancedSelect extends HTMLElement {
|
|
1848
|
+
get classMap() {
|
|
1849
|
+
return this._classMap;
|
|
1850
|
+
}
|
|
1851
|
+
set classMap(map) {
|
|
1852
|
+
this._classMap = map;
|
|
1853
|
+
this._setGlobalStylesMirroring(Boolean(this._optionRenderer || map));
|
|
1854
|
+
if (!this.isConnected)
|
|
1855
|
+
return;
|
|
1856
|
+
this._renderOptions();
|
|
1857
|
+
}
|
|
1821
1858
|
constructor() {
|
|
1822
1859
|
super();
|
|
1823
1860
|
this._pageCache = {};
|
|
@@ -1861,6 +1898,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1861
1898
|
this._inputContainer = this._createInputContainer();
|
|
1862
1899
|
this._input = this._createInput();
|
|
1863
1900
|
this._arrowContainer = this._createArrowContainer();
|
|
1901
|
+
this._clearControl = this._createClearControl();
|
|
1864
1902
|
this._dropdown = this._createDropdown();
|
|
1865
1903
|
this._optionsContainer = this._createOptionsContainer();
|
|
1866
1904
|
this._liveRegion = this._createLiveRegion();
|
|
@@ -2074,8 +2112,25 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2074
2112
|
`;
|
|
2075
2113
|
return container;
|
|
2076
2114
|
}
|
|
2115
|
+
_createClearControl() {
|
|
2116
|
+
const button = document.createElement('button');
|
|
2117
|
+
button.type = 'button';
|
|
2118
|
+
button.className = 'clear-control-button';
|
|
2119
|
+
button.setAttribute('part', 'clear-button');
|
|
2120
|
+
const icon = document.createElement('span');
|
|
2121
|
+
icon.className = 'clear-control-icon';
|
|
2122
|
+
icon.setAttribute('part', 'clear-icon');
|
|
2123
|
+
icon.textContent = this._config.clearControl.icon || '×';
|
|
2124
|
+
button.setAttribute('aria-label', this._config.clearControl.ariaLabel || 'Clear selection and search');
|
|
2125
|
+
button.appendChild(icon);
|
|
2126
|
+
this._clearControlIcon = icon;
|
|
2127
|
+
return button;
|
|
2128
|
+
}
|
|
2077
2129
|
_assembleDOM() {
|
|
2078
2130
|
this._inputContainer.appendChild(this._input);
|
|
2131
|
+
if (this._clearControl) {
|
|
2132
|
+
this._inputContainer.appendChild(this._clearControl);
|
|
2133
|
+
}
|
|
2079
2134
|
if (this._arrowContainer) {
|
|
2080
2135
|
this._inputContainer.appendChild(this._arrowContainer);
|
|
2081
2136
|
}
|
|
@@ -2091,6 +2146,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2091
2146
|
this._dropdown.id = listboxId;
|
|
2092
2147
|
this._input.setAttribute('aria-controls', listboxId);
|
|
2093
2148
|
this._input.setAttribute('aria-owns', listboxId);
|
|
2149
|
+
this._syncClearControlState();
|
|
2094
2150
|
}
|
|
2095
2151
|
_initializeStyles() {
|
|
2096
2152
|
const style = document.createElement('style');
|
|
@@ -2164,6 +2220,58 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2164
2220
|
border-radius: var(--select-arrow-border-radius, 0 4px 4px 0);
|
|
2165
2221
|
z-index: 2;
|
|
2166
2222
|
}
|
|
2223
|
+
|
|
2224
|
+
.input-container.has-clear-control {
|
|
2225
|
+
padding: var(--select-input-padding-with-clear, 6px 84px 6px 8px);
|
|
2226
|
+
}
|
|
2227
|
+
|
|
2228
|
+
.input-container.has-clear-control::after {
|
|
2229
|
+
right: var(--select-separator-position-with-clear, 72px);
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
.dropdown-arrow-container.with-clear-control {
|
|
2233
|
+
right: var(--select-arrow-right-with-clear, 32px);
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
.clear-control-button {
|
|
2237
|
+
position: absolute;
|
|
2238
|
+
top: 50%;
|
|
2239
|
+
right: var(--select-clear-button-right, 6px);
|
|
2240
|
+
transform: translateY(-50%);
|
|
2241
|
+
width: var(--select-clear-button-size, 24px);
|
|
2242
|
+
height: var(--select-clear-button-size, 24px);
|
|
2243
|
+
border: var(--select-clear-button-border, none);
|
|
2244
|
+
border-radius: var(--select-clear-button-radius, 999px);
|
|
2245
|
+
background: var(--select-clear-button-bg, transparent);
|
|
2246
|
+
color: var(--select-clear-button-color, #6b7280);
|
|
2247
|
+
display: inline-flex;
|
|
2248
|
+
align-items: center;
|
|
2249
|
+
justify-content: center;
|
|
2250
|
+
cursor: pointer;
|
|
2251
|
+
z-index: 3;
|
|
2252
|
+
transition: var(--select-clear-button-transition, all 0.2s ease);
|
|
2253
|
+
}
|
|
2254
|
+
|
|
2255
|
+
.clear-control-button:hover {
|
|
2256
|
+
background: var(--select-clear-button-hover-bg, rgba(0, 0, 0, 0.06));
|
|
2257
|
+
color: var(--select-clear-button-hover-color, #111827);
|
|
2258
|
+
}
|
|
2259
|
+
|
|
2260
|
+
.clear-control-button:focus-visible {
|
|
2261
|
+
outline: var(--select-clear-button-focus-outline, 2px solid rgba(102, 126, 234, 0.55));
|
|
2262
|
+
outline-offset: 1px;
|
|
2263
|
+
}
|
|
2264
|
+
|
|
2265
|
+
.clear-control-button[hidden] {
|
|
2266
|
+
display: none;
|
|
2267
|
+
}
|
|
2268
|
+
|
|
2269
|
+
.clear-control-icon {
|
|
2270
|
+
font-size: var(--select-clear-icon-size, 16px);
|
|
2271
|
+
line-height: 1;
|
|
2272
|
+
font-weight: var(--select-clear-icon-weight, 500);
|
|
2273
|
+
pointer-events: none;
|
|
2274
|
+
}
|
|
2167
2275
|
|
|
2168
2276
|
.dropdown-arrow-container:hover {
|
|
2169
2277
|
background-color: var(--select-arrow-hover-bg, rgba(102, 126, 234, 0.08));
|
|
@@ -2291,6 +2399,9 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2291
2399
|
line-height: var(--select-option-line-height, 1.5);
|
|
2292
2400
|
border: var(--select-option-border, none);
|
|
2293
2401
|
border-bottom: var(--select-option-border-bottom, none);
|
|
2402
|
+
border-radius: var(--select-option-border-radius, 0);
|
|
2403
|
+
box-shadow: var(--select-option-shadow, none);
|
|
2404
|
+
transform: var(--select-option-transform, none);
|
|
2294
2405
|
}
|
|
2295
2406
|
|
|
2296
2407
|
.option:hover {
|
|
@@ -2302,18 +2413,47 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2302
2413
|
background-color: var(--select-option-selected-bg, #e0e7ff);
|
|
2303
2414
|
color: var(--select-option-selected-color, #4338ca);
|
|
2304
2415
|
font-weight: var(--select-option-selected-weight, 500);
|
|
2416
|
+
border: var(--select-option-selected-border, var(--select-option-border, none));
|
|
2417
|
+
border-bottom: var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none));
|
|
2418
|
+
border-radius: var(--select-option-selected-border-radius, var(--select-option-border-radius, 0));
|
|
2419
|
+
box-shadow: var(--select-option-selected-shadow, var(--select-option-shadow, none));
|
|
2420
|
+
transform: var(--select-option-selected-transform, var(--select-option-transform, none));
|
|
2421
|
+
}
|
|
2422
|
+
|
|
2423
|
+
.option.selected:hover {
|
|
2424
|
+
background-color: var(--select-option-selected-hover-bg, var(--select-option-selected-bg, #e0e7ff));
|
|
2425
|
+
color: var(--select-option-selected-hover-color, var(--select-option-selected-color, #4338ca));
|
|
2426
|
+
border: var(--select-option-selected-hover-border, var(--select-option-selected-border, var(--select-option-border, none)));
|
|
2427
|
+
border-bottom: var(--select-option-selected-hover-border-bottom, var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none)));
|
|
2428
|
+
box-shadow: var(--select-option-selected-hover-shadow, var(--select-option-selected-shadow, var(--select-option-shadow, none)));
|
|
2429
|
+
transform: var(--select-option-selected-hover-transform, var(--select-option-selected-transform, var(--select-option-transform, none)));
|
|
2305
2430
|
}
|
|
2306
2431
|
|
|
2307
|
-
.option.active {
|
|
2432
|
+
.option.active:not(.selected) {
|
|
2308
2433
|
background-color: var(--select-option-active-bg, #f3f4f6);
|
|
2309
2434
|
color: var(--select-option-active-color, #1f2937);
|
|
2310
2435
|
outline: var(--select-option-active-outline, 2px solid rgba(99, 102, 241, 0.45));
|
|
2311
2436
|
outline-offset: -2px;
|
|
2312
2437
|
}
|
|
2313
2438
|
|
|
2314
|
-
.option
|
|
2439
|
+
.option.selected.active {
|
|
2440
|
+
background-color: var(--select-option-selected-active-bg, var(--select-option-selected-bg, #e0e7ff));
|
|
2441
|
+
color: var(--select-option-selected-active-color, var(--select-option-selected-color, #4338ca));
|
|
2442
|
+
border: var(--select-option-selected-active-border, var(--select-option-selected-border, var(--select-option-border, none)));
|
|
2443
|
+
border-bottom: var(--select-option-selected-active-border-bottom, var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none)));
|
|
2444
|
+
box-shadow: var(--select-option-selected-active-shadow, var(--select-option-selected-shadow, var(--select-option-shadow, none)));
|
|
2445
|
+
transform: var(--select-option-selected-active-transform, var(--select-option-selected-transform, var(--select-option-transform, none)));
|
|
2446
|
+
outline: var(--select-option-selected-active-outline, var(--select-option-active-outline, 2px solid rgba(99, 102, 241, 0.45)));
|
|
2447
|
+
outline-offset: -2px;
|
|
2448
|
+
}
|
|
2449
|
+
|
|
2450
|
+
.option:active:not(.selected) {
|
|
2315
2451
|
background-color: var(--select-option-pressed-bg, #e5e7eb);
|
|
2316
2452
|
}
|
|
2453
|
+
|
|
2454
|
+
.option.selected:active {
|
|
2455
|
+
background-color: var(--select-option-selected-pressed-bg, var(--select-option-selected-hover-bg, var(--select-option-selected-bg, #e0e7ff)));
|
|
2456
|
+
}
|
|
2317
2457
|
|
|
2318
2458
|
.load-more-container {
|
|
2319
2459
|
padding: var(--select-load-more-padding, 12px);
|
|
@@ -2459,14 +2599,38 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2459
2599
|
.option.selected {
|
|
2460
2600
|
background-color: var(--select-dark-option-selected-bg, #3730a3);
|
|
2461
2601
|
color: var(--select-dark-option-selected-text, #e0e7ff);
|
|
2602
|
+
border: var(--select-dark-option-selected-border, var(--select-option-selected-border, var(--select-option-border, none)));
|
|
2603
|
+
border-bottom: var(--select-dark-option-selected-border-bottom, var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none)));
|
|
2604
|
+
box-shadow: var(--select-dark-option-selected-shadow, var(--select-option-selected-shadow, var(--select-option-shadow, none)));
|
|
2605
|
+
transform: var(--select-dark-option-selected-transform, var(--select-option-selected-transform, var(--select-option-transform, none)));
|
|
2606
|
+
}
|
|
2607
|
+
|
|
2608
|
+
.option.selected:hover {
|
|
2609
|
+
background-color: var(--select-dark-option-selected-hover-bg, var(--select-dark-option-selected-bg, #3730a3));
|
|
2610
|
+
color: var(--select-dark-option-selected-hover-color, var(--select-dark-option-selected-text, #e0e7ff));
|
|
2611
|
+
border: var(--select-dark-option-selected-hover-border, var(--select-dark-option-selected-border, var(--select-option-selected-hover-border, var(--select-option-selected-border, var(--select-option-border, none)))));
|
|
2612
|
+
border-bottom: var(--select-dark-option-selected-hover-border-bottom, var(--select-dark-option-selected-border-bottom, var(--select-option-selected-hover-border-bottom, var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none)))));
|
|
2613
|
+
box-shadow: var(--select-dark-option-selected-hover-shadow, var(--select-dark-option-selected-shadow, var(--select-option-selected-hover-shadow, var(--select-option-selected-shadow, var(--select-option-shadow, none)))));
|
|
2614
|
+
transform: var(--select-dark-option-selected-hover-transform, var(--select-dark-option-selected-transform, var(--select-option-selected-hover-transform, var(--select-option-selected-transform, var(--select-option-transform, none)))));
|
|
2462
2615
|
}
|
|
2463
2616
|
|
|
2464
|
-
.option.active {
|
|
2617
|
+
.option.active:not(.selected) {
|
|
2465
2618
|
background-color: var(--select-dark-option-active-bg, #374151);
|
|
2466
2619
|
color: var(--select-dark-option-active-color, #f9fafb);
|
|
2467
2620
|
outline: var(--select-dark-option-active-outline, 2px solid rgba(129, 140, 248, 0.55));
|
|
2468
2621
|
}
|
|
2469
2622
|
|
|
2623
|
+
.option.selected.active {
|
|
2624
|
+
background-color: var(--select-dark-option-selected-active-bg, var(--select-dark-option-selected-bg, #3730a3));
|
|
2625
|
+
color: var(--select-dark-option-selected-active-color, var(--select-dark-option-selected-text, #e0e7ff));
|
|
2626
|
+
border: var(--select-dark-option-selected-active-border, var(--select-dark-option-selected-border, var(--select-option-selected-active-border, var(--select-option-selected-border, var(--select-option-border, none)))));
|
|
2627
|
+
border-bottom: var(--select-dark-option-selected-active-border-bottom, var(--select-dark-option-selected-border-bottom, var(--select-option-selected-active-border-bottom, var(--select-option-selected-border-bottom, var(--select-option-border-bottom, none)))));
|
|
2628
|
+
box-shadow: var(--select-dark-option-selected-active-shadow, var(--select-dark-option-selected-shadow, var(--select-option-selected-active-shadow, var(--select-option-selected-shadow, var(--select-option-shadow, none)))));
|
|
2629
|
+
transform: var(--select-dark-option-selected-active-transform, var(--select-dark-option-selected-transform, var(--select-option-selected-active-transform, var(--select-option-selected-transform, var(--select-option-transform, none)))));
|
|
2630
|
+
outline: var(--select-dark-option-selected-active-outline, var(--select-dark-option-active-outline, var(--select-option-selected-active-outline, var(--select-option-active-outline, 2px solid rgba(129, 140, 248, 0.55)))));
|
|
2631
|
+
outline-offset: -2px;
|
|
2632
|
+
}
|
|
2633
|
+
|
|
2470
2634
|
.selection-badge {
|
|
2471
2635
|
background: var(--select-dark-badge-bg, #4f46e5);
|
|
2472
2636
|
color: var(--select-dark-badge-color, #eef2ff);
|
|
@@ -2551,6 +2715,17 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2551
2715
|
};
|
|
2552
2716
|
this._arrowContainer.addEventListener('click', this._boundArrowClick);
|
|
2553
2717
|
}
|
|
2718
|
+
if (this._clearControl) {
|
|
2719
|
+
this._clearControl.addEventListener('pointerdown', (e) => {
|
|
2720
|
+
e.stopPropagation();
|
|
2721
|
+
e.preventDefault();
|
|
2722
|
+
});
|
|
2723
|
+
this._clearControl.addEventListener('click', (e) => {
|
|
2724
|
+
e.stopPropagation();
|
|
2725
|
+
e.preventDefault();
|
|
2726
|
+
this._handleClearControlClick();
|
|
2727
|
+
});
|
|
2728
|
+
}
|
|
2554
2729
|
// Input container click - focus input and open dropdown
|
|
2555
2730
|
this._inputContainer.addEventListener('pointerdown', (e) => {
|
|
2556
2731
|
const target = e.target;
|
|
@@ -2558,6 +2733,8 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2558
2733
|
return;
|
|
2559
2734
|
if (target && target.closest('.dropdown-arrow-container'))
|
|
2560
2735
|
return;
|
|
2736
|
+
if (target && target.closest('.clear-control-button'))
|
|
2737
|
+
return;
|
|
2561
2738
|
if (!this._state.isOpen) {
|
|
2562
2739
|
this._handleOpen();
|
|
2563
2740
|
}
|
|
@@ -2770,6 +2947,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2770
2947
|
}
|
|
2771
2948
|
_handleSearch(query) {
|
|
2772
2949
|
this._state.searchQuery = query;
|
|
2950
|
+
this._syncClearControlState();
|
|
2773
2951
|
if (query.length > 0) {
|
|
2774
2952
|
this._perfMark('smilodon-search-input-last');
|
|
2775
2953
|
this._pendingSearchRenderMark = true;
|
|
@@ -2947,7 +3125,9 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2947
3125
|
option.classList.add('smilodon-option--active');
|
|
2948
3126
|
option.setAttribute('aria-selected', 'true');
|
|
2949
3127
|
}
|
|
2950
|
-
option.scrollIntoView
|
|
3128
|
+
if (typeof option.scrollIntoView === 'function') {
|
|
3129
|
+
option.scrollIntoView({ block: 'nearest', behavior: 'smooth' });
|
|
3130
|
+
}
|
|
2951
3131
|
// Announce position for screen readers
|
|
2952
3132
|
const total = options.length;
|
|
2953
3133
|
this._announce(`Item ${index + 1} of ${total}`);
|
|
@@ -3074,6 +3254,10 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3074
3254
|
const item = this._state.loadedItems[index];
|
|
3075
3255
|
if (!item)
|
|
3076
3256
|
return;
|
|
3257
|
+
// Keep active/focus styling aligned with the most recently interacted option.
|
|
3258
|
+
// Without this, a previously selected item may retain active classes/styles
|
|
3259
|
+
// after selecting a different option.
|
|
3260
|
+
this._state.activeIndex = index;
|
|
3077
3261
|
const isCurrentlySelected = this._state.selectedIndices.has(index);
|
|
3078
3262
|
if (this._config.selection.mode === 'single') {
|
|
3079
3263
|
// Single select: clear previous and select new
|
|
@@ -3198,6 +3382,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3198
3382
|
this._inputContainer.insertBefore(badge, this._input);
|
|
3199
3383
|
});
|
|
3200
3384
|
}
|
|
3385
|
+
this._syncClearControlState();
|
|
3201
3386
|
}
|
|
3202
3387
|
_renderOptionsWithAnimation() {
|
|
3203
3388
|
// Add fade-out animation
|
|
@@ -3313,7 +3498,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3313
3498
|
}
|
|
3314
3499
|
set optionRenderer(renderer) {
|
|
3315
3500
|
this._optionRenderer = renderer;
|
|
3316
|
-
this._setGlobalStylesMirroring(Boolean(renderer));
|
|
3501
|
+
this._setGlobalStylesMirroring(Boolean(renderer || this._classMap));
|
|
3317
3502
|
this._renderOptions();
|
|
3318
3503
|
}
|
|
3319
3504
|
/**
|
|
@@ -3446,6 +3631,21 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3446
3631
|
this._renderOptions();
|
|
3447
3632
|
this._updateInputDisplay();
|
|
3448
3633
|
this._emitChange();
|
|
3634
|
+
this._syncClearControlState();
|
|
3635
|
+
}
|
|
3636
|
+
/**
|
|
3637
|
+
* Clear search query and restore full option list
|
|
3638
|
+
*/
|
|
3639
|
+
clearSearch() {
|
|
3640
|
+
this._state.searchQuery = '';
|
|
3641
|
+
if (this._config.searchable) {
|
|
3642
|
+
this._input.value = '';
|
|
3643
|
+
if (this._state.selectedIndices.size > 0) {
|
|
3644
|
+
this._updateInputDisplay();
|
|
3645
|
+
}
|
|
3646
|
+
}
|
|
3647
|
+
this._renderOptions();
|
|
3648
|
+
this._syncClearControlState();
|
|
3449
3649
|
}
|
|
3450
3650
|
/**
|
|
3451
3651
|
* Open dropdown
|
|
@@ -3472,6 +3672,12 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3472
3672
|
this._input.placeholder = this._config.placeholder || 'Select an option...';
|
|
3473
3673
|
}
|
|
3474
3674
|
}
|
|
3675
|
+
if (this._clearControl) {
|
|
3676
|
+
this._clearControl.setAttribute('aria-label', this._config.clearControl.ariaLabel || 'Clear selection and search');
|
|
3677
|
+
}
|
|
3678
|
+
if (this._clearControlIcon) {
|
|
3679
|
+
this._clearControlIcon.textContent = this._config.clearControl.icon || '×';
|
|
3680
|
+
}
|
|
3475
3681
|
if (this._dropdown) {
|
|
3476
3682
|
if (this._config.selection.mode === 'multi') {
|
|
3477
3683
|
this._dropdown.setAttribute('aria-multiselectable', 'true');
|
|
@@ -3482,8 +3688,47 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3482
3688
|
}
|
|
3483
3689
|
// Re-initialize observers in case infinite scroll was enabled/disabled
|
|
3484
3690
|
this._initializeObservers();
|
|
3691
|
+
this._syncClearControlState();
|
|
3485
3692
|
this._renderOptions();
|
|
3486
3693
|
}
|
|
3694
|
+
_handleClearControlClick() {
|
|
3695
|
+
const shouldClearSelection = this._config.clearControl.clearSelection !== false;
|
|
3696
|
+
const shouldClearSearch = this._config.clearControl.clearSearch !== false;
|
|
3697
|
+
const hadSelection = this._state.selectedIndices.size > 0;
|
|
3698
|
+
const hadSearch = this._state.searchQuery.length > 0;
|
|
3699
|
+
if (shouldClearSelection && hadSelection) {
|
|
3700
|
+
this.clear();
|
|
3701
|
+
}
|
|
3702
|
+
if (shouldClearSearch && hadSearch) {
|
|
3703
|
+
this.clearSearch();
|
|
3704
|
+
}
|
|
3705
|
+
this._emit('clear', {
|
|
3706
|
+
clearedSelection: shouldClearSelection && hadSelection,
|
|
3707
|
+
clearedSearch: shouldClearSearch && hadSearch,
|
|
3708
|
+
});
|
|
3709
|
+
this._config.callbacks.onClear?.({
|
|
3710
|
+
clearedSelection: shouldClearSelection && hadSelection,
|
|
3711
|
+
clearedSearch: shouldClearSearch && hadSearch,
|
|
3712
|
+
});
|
|
3713
|
+
this._input.focus();
|
|
3714
|
+
}
|
|
3715
|
+
_syncClearControlState() {
|
|
3716
|
+
if (!this._clearControl || !this._inputContainer || !this._arrowContainer)
|
|
3717
|
+
return;
|
|
3718
|
+
const enabled = this._config.clearControl.enabled === true;
|
|
3719
|
+
const hasSelection = this._state.selectedIndices.size > 0;
|
|
3720
|
+
const hasSearch = this._state.searchQuery.length > 0;
|
|
3721
|
+
const clearSelection = this._config.clearControl.clearSelection !== false;
|
|
3722
|
+
const clearSearch = this._config.clearControl.clearSearch !== false;
|
|
3723
|
+
const hasSomethingToClear = (clearSelection && hasSelection) || (clearSearch && hasSearch);
|
|
3724
|
+
const hideWhenEmpty = this._config.clearControl.hideWhenEmpty !== false;
|
|
3725
|
+
const visible = enabled && (!hideWhenEmpty || hasSomethingToClear);
|
|
3726
|
+
this._inputContainer.classList.toggle('has-clear-control', enabled);
|
|
3727
|
+
this._arrowContainer.classList.toggle('with-clear-control', enabled);
|
|
3728
|
+
this._clearControl.hidden = !visible;
|
|
3729
|
+
this._clearControl.disabled = !hasSomethingToClear;
|
|
3730
|
+
this._clearControl.setAttribute('aria-hidden', String(!visible));
|
|
3731
|
+
}
|
|
3487
3732
|
/**
|
|
3488
3733
|
* Set error state
|
|
3489
3734
|
*/
|
|
@@ -4771,10 +5016,17 @@ const shadowDOMStyles = `
|
|
|
4771
5016
|
color: var(--ns-item-selected-color, #0066cc);
|
|
4772
5017
|
}
|
|
4773
5018
|
|
|
4774
|
-
.ns-item[data-active="true"] {
|
|
5019
|
+
.ns-item[data-active="true"]:not([aria-selected="true"]) {
|
|
4775
5020
|
background: var(--ns-item-active-bg, rgba(0, 102, 204, 0.2));
|
|
4776
5021
|
}
|
|
4777
5022
|
|
|
5023
|
+
.ns-item[aria-selected="true"][data-active="true"] {
|
|
5024
|
+
background: var(--ns-item-selected-active-bg, var(--ns-item-selected-bg, rgba(0, 102, 204, 0.1)));
|
|
5025
|
+
color: var(--ns-item-selected-active-color, var(--ns-item-selected-color, #0066cc));
|
|
5026
|
+
outline: var(--ns-item-selected-active-outline, 2px solid #0066cc);
|
|
5027
|
+
outline-offset: -2px;
|
|
5028
|
+
}
|
|
5029
|
+
|
|
4778
5030
|
.ns-item[aria-disabled="true"] {
|
|
4779
5031
|
opacity: 0.5;
|
|
4780
5032
|
cursor: not-allowed;
|