@smilodon/core 1.4.13 → 1.5.0

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/dist/index.umd.js CHANGED
@@ -1354,9 +1354,21 @@
1354
1354
  allowDeselect: false,
1355
1355
  maxSelections: 0,
1356
1356
  showRemoveButton: true,
1357
+ removeButtonIcon: '×',
1357
1358
  closeOnSelect: true,
1358
1359
  toggleOnTriggerClick: true,
1359
1360
  },
1361
+ direction: 'ltr',
1362
+ dropdownPlacement: {
1363
+ mode: 'bottom',
1364
+ },
1365
+ multiSelectDisplay: {
1366
+ mode: 'wrap',
1367
+ maxHeight: '160px',
1368
+ overflowX: 'hidden',
1369
+ overflowY: 'auto',
1370
+ dragScroll: true,
1371
+ },
1360
1372
  scrollToSelected: {
1361
1373
  enabled: true,
1362
1374
  multiSelectTarget: 'first',
@@ -1517,6 +1529,8 @@
1517
1529
  :host {
1518
1530
  display: block;
1519
1531
  position: relative;
1532
+ font: inherit;
1533
+ color: inherit;
1520
1534
  }
1521
1535
 
1522
1536
  /* Allow authors to style selected state from outside the shadow root
@@ -1548,7 +1562,7 @@
1548
1562
  display: flex;
1549
1563
  align-items: center;
1550
1564
  justify-content: space-between;
1551
- padding: var(--select-option-padding, 8px 12px);
1565
+ padding: var(--select-option-padding, 10px 14px);
1552
1566
  cursor: pointer;
1553
1567
  user-select: none;
1554
1568
  color: var(--select-option-color, var(--select-text-color, #1f2937));
@@ -1556,13 +1570,19 @@
1556
1570
  transition: var(--select-option-transition, background-color 0.2s ease);
1557
1571
  border: var(--select-option-border, none);
1558
1572
  border-bottom: var(--select-option-border-bottom, none);
1559
- border-radius: var(--select-option-border-radius, 0);
1573
+ border-radius: var(--select-option-border-radius, var(--select-radius-sm, 6px));
1560
1574
  box-shadow: var(--select-option-shadow, none);
1561
1575
  transform: var(--select-option-transform, none);
1576
+ font: inherit;
1562
1577
  }
1563
1578
 
1564
1579
  .option-container:hover {
1565
1580
  background: var(--select-option-hover-bg, #f0f0f0);
1581
+ color: var(--select-option-hover-color, var(--select-option-color, var(--select-text-color, #1f2937)));
1582
+ border: var(--select-option-hover-border, var(--select-option-border, none));
1583
+ border-bottom: var(--select-option-hover-border-bottom, var(--select-option-border-bottom, none));
1584
+ box-shadow: var(--select-option-hover-shadow, var(--select-option-shadow, none));
1585
+ transform: var(--select-option-hover-transform, var(--select-option-transform, none));
1566
1586
  }
1567
1587
 
1568
1588
  .option-container.selected {
@@ -1585,13 +1605,22 @@
1585
1605
  }
1586
1606
 
1587
1607
  .option-container.active {
1588
- outline: 2px solid var(--select-option-active-outline, #1976d2);
1589
- outline-offset: -2px;
1608
+ background: var(--select-option-active-bg, var(--select-option-hover-bg, #f0f0f0));
1609
+ color: var(--select-option-active-color, var(--select-option-hover-color, var(--select-option-color, var(--select-text-color, #1f2937))));
1610
+ border: var(--select-option-active-border, var(--select-option-hover-border, var(--select-option-border, none)));
1611
+ box-shadow: var(--select-option-active-shadow, var(--select-option-shadow, none));
1612
+ transform: var(--select-option-active-transform, var(--select-option-transform, none));
1613
+ outline: var(--select-option-active-outline, 2px solid #1976d2);
1614
+ outline-offset: var(--select-option-active-outline-offset, -2px);
1590
1615
  }
1591
1616
 
1592
1617
  .option-container.disabled {
1593
- opacity: 0.5;
1594
- cursor: not-allowed;
1618
+ background: var(--select-option-disabled-bg, var(--select-option-bg, var(--select-dropdown-bg, var(--select-bg, white))));
1619
+ color: var(--select-option-disabled-color, var(--select-option-color, var(--select-text-color, #1f2937)));
1620
+ border: var(--select-option-disabled-border, var(--select-option-border, none));
1621
+ border-bottom: var(--select-option-disabled-border-bottom, var(--select-option-border-bottom, none));
1622
+ opacity: var(--select-option-disabled-opacity, 0.5);
1623
+ cursor: var(--select-option-disabled-cursor, not-allowed);
1595
1624
  pointer-events: none;
1596
1625
  }
1597
1626
 
@@ -1608,6 +1637,12 @@
1608
1637
  color: var(--select-checkmark-color, currentColor);
1609
1638
  }
1610
1639
 
1640
+ :host([dir="rtl"]) .checkmark-icon,
1641
+ :host-context([dir="rtl"]) .checkmark-icon {
1642
+ margin-left: 0;
1643
+ margin-right: var(--select-checkmark-margin-left, 8px);
1644
+ }
1645
+
1611
1646
  :host([aria-selected="true"]) .checkmark-icon,
1612
1647
  .option-container.selected .checkmark-icon {
1613
1648
  display: inline-flex;
@@ -1615,20 +1650,49 @@
1615
1650
 
1616
1651
  .remove-button {
1617
1652
  margin-left: 8px;
1618
- padding: 2px 6px;
1653
+ width: var(--select-badge-remove-size, 18px);
1654
+ height: var(--select-badge-remove-size, 18px);
1655
+ min-width: var(--select-badge-remove-min-width, var(--select-badge-remove-size, 18px));
1656
+ min-height: var(--select-badge-remove-min-height, var(--select-badge-remove-size, 18px));
1657
+ padding: 0;
1619
1658
  border: none;
1620
- background-color: var(--select-remove-btn-bg, transparent);
1621
- color: var(--select-remove-btn-color, #666);
1659
+ background-color: var(--select-badge-remove-bg, rgba(255, 255, 255, 0.2));
1660
+ color: var(--select-badge-remove-color, currentColor);
1622
1661
  cursor: pointer;
1623
- border-radius: 3px;
1624
- font-size: 16px;
1662
+ border-radius: var(--select-badge-remove-radius, 50%);
1663
+ font-size: var(--select-badge-remove-font-size, 0.7333em);
1664
+ font-weight: var(--select-badge-remove-font-weight, 600);
1625
1665
  line-height: 1;
1666
+ display: inline-flex;
1667
+ align-items: center;
1668
+ justify-content: center;
1626
1669
  transition: all 0.2s ease;
1627
1670
  }
1671
+
1672
+ :host([dir="rtl"]) .remove-button,
1673
+ :host-context([dir="rtl"]) .remove-button {
1674
+ margin-left: 0;
1675
+ margin-right: 8px;
1676
+ }
1677
+
1678
+ .remove-button-icon {
1679
+ display: inline-flex;
1680
+ align-items: center;
1681
+ justify-content: center;
1682
+ width: var(--select-badge-remove-icon-size, 10px);
1683
+ height: var(--select-badge-remove-icon-size, 10px);
1684
+ pointer-events: none;
1685
+ }
1686
+
1687
+ .remove-button-icon svg {
1688
+ width: 100%;
1689
+ height: 100%;
1690
+ display: block;
1691
+ }
1628
1692
 
1629
1693
  .remove-button:hover {
1630
- background-color: var(--select-remove-btn-hover-bg, #ffebee);
1631
- color: var(--select-remove-btn-hover-color, #c62828);
1694
+ background-color: var(--select-badge-remove-hover-bg, #ffebee);
1695
+ color: var(--select-badge-remove-hover-color, #c62828);
1632
1696
  }
1633
1697
 
1634
1698
  .remove-button:focus {
@@ -1715,10 +1779,22 @@
1715
1779
  if (showRemoveButton && selected) {
1716
1780
  this._removeButton = document.createElement('button');
1717
1781
  this._removeButton.className = 'remove-button';
1718
- this._removeButton.innerHTML = '×';
1719
1782
  this._removeButton.setAttribute('part', 'chip-remove');
1720
1783
  this._removeButton.setAttribute('aria-label', 'Remove option');
1721
1784
  this._removeButton.setAttribute('type', 'button');
1785
+ const removeIcon = document.createElement('span');
1786
+ removeIcon.className = 'remove-button-icon';
1787
+ removeIcon.setAttribute('part', 'chip-remove-icon');
1788
+ const iconMarkup = this._config.removeButtonIcon && this._config.removeButtonIcon.trim()
1789
+ ? this._config.removeButtonIcon
1790
+ : '×';
1791
+ if (iconMarkup.trim().startsWith('<')) {
1792
+ removeIcon.innerHTML = iconMarkup;
1793
+ }
1794
+ else {
1795
+ removeIcon.textContent = iconMarkup;
1796
+ }
1797
+ this._removeButton.appendChild(removeIcon);
1722
1798
  this._container.appendChild(this._removeButton);
1723
1799
  }
1724
1800
  // Set ARIA attributes and State attributes on Host
@@ -1939,6 +2015,16 @@
1939
2015
  this._tracking = { events: [], styles: [], limitations: [] };
1940
2016
  this._suppressBlurClose = false;
1941
2017
  this._renderCycleId = 0;
2018
+ this._suppressNextOpenClick = false;
2019
+ this._resolvedDropdownPlacement = 'bottom';
2020
+ this._multiScrollDrag = {
2021
+ active: false,
2022
+ moved: false,
2023
+ pointerId: -1,
2024
+ startX: 0,
2025
+ startScrollLeft: 0,
2026
+ };
2027
+ this._liftedAncestors = [];
1942
2028
  this._shadow = this.attachShadow({ mode: 'open' });
1943
2029
  this._uniqueId = `enhanced-select-${Math.random().toString(36).substr(2, 9)}`;
1944
2030
  this._rendererHelpers = this._buildRendererHelpers();
@@ -1966,6 +2052,7 @@
1966
2052
  // Create DOM structure
1967
2053
  this._container = this._createContainer();
1968
2054
  this._inputContainer = this._createInputContainer();
2055
+ this._inputContent = this._createInputContent();
1969
2056
  this._input = this._createInput();
1970
2057
  this._arrowContainer = this._createArrowContainer();
1971
2058
  this._clearControl = this._createClearControl();
@@ -1974,6 +2061,8 @@
1974
2061
  this._liveRegion = this._createLiveRegion();
1975
2062
  // Initialize styles BEFORE assembling DOM (order matters in shadow DOM)
1976
2063
  this._initializeStyles();
2064
+ this._syncStyleConfigVariables();
2065
+ this._syncDirectionConfig();
1977
2066
  this._assembleDOM();
1978
2067
  this._attachEventListeners();
1979
2068
  this._initializeObservers();
@@ -2009,6 +2098,7 @@
2009
2098
  clearTimeout(this._typeTimeout);
2010
2099
  if (this._searchTimeout)
2011
2100
  clearTimeout(this._searchTimeout);
2101
+ this._endMultiScrollDrag();
2012
2102
  // Cleanup arrow click listener
2013
2103
  if (this._boundArrowClick && this._arrowContainer) {
2014
2104
  this._arrowContainer.removeEventListener('click', this._boundArrowClick);
@@ -2142,6 +2232,203 @@
2142
2232
  }
2143
2233
  return container;
2144
2234
  }
2235
+ _createInputContent() {
2236
+ const content = document.createElement('div');
2237
+ content.className = 'input-content';
2238
+ return content;
2239
+ }
2240
+ _setCssVariable(name, value) {
2241
+ if (value == null || value === '') {
2242
+ this.style.removeProperty(name);
2243
+ return;
2244
+ }
2245
+ this.style.setProperty(name, String(value));
2246
+ }
2247
+ _applyStyleVariableMap(styleConfig, variableMap) {
2248
+ Object.entries(variableMap).forEach(([styleKey, variableName]) => {
2249
+ this._setCssVariable(variableName, styleConfig?.[styleKey]);
2250
+ });
2251
+ }
2252
+ _syncStyleConfigVariables() {
2253
+ const styles = this._config.styles;
2254
+ this._applyStyleVariableMap(styles.option, {
2255
+ background: '--select-option-bg',
2256
+ backgroundColor: '--select-option-bg',
2257
+ color: '--select-option-color',
2258
+ border: '--select-option-border',
2259
+ borderBottom: '--select-option-border-bottom',
2260
+ borderRadius: '--select-option-border-radius',
2261
+ boxShadow: '--select-option-shadow',
2262
+ transform: '--select-option-transform',
2263
+ padding: '--select-option-padding',
2264
+ margin: '--select-option-margin',
2265
+ fontSize: '--select-option-font-size',
2266
+ fontWeight: '--select-option-font-weight',
2267
+ lineHeight: '--select-option-line-height',
2268
+ textAlign: '--select-option-text-align',
2269
+ });
2270
+ this._applyStyleVariableMap(styles.selectedOption, {
2271
+ background: '--select-option-selected-bg',
2272
+ backgroundColor: '--select-option-selected-bg',
2273
+ color: '--select-option-selected-color',
2274
+ border: '--select-option-selected-border',
2275
+ borderBottom: '--select-option-selected-border-bottom',
2276
+ borderRadius: '--select-option-selected-border-radius',
2277
+ boxShadow: '--select-option-selected-shadow',
2278
+ transform: '--select-option-selected-transform',
2279
+ fontWeight: '--select-option-selected-weight',
2280
+ });
2281
+ this._applyStyleVariableMap(styles.hoverOption, {
2282
+ background: '--select-option-hover-bg',
2283
+ backgroundColor: '--select-option-hover-bg',
2284
+ color: '--select-option-hover-color',
2285
+ border: '--select-option-hover-border',
2286
+ borderBottom: '--select-option-hover-border-bottom',
2287
+ boxShadow: '--select-option-hover-shadow',
2288
+ transform: '--select-option-hover-transform',
2289
+ });
2290
+ this._applyStyleVariableMap(styles.activeOption, {
2291
+ background: '--select-option-active-bg',
2292
+ backgroundColor: '--select-option-active-bg',
2293
+ color: '--select-option-active-color',
2294
+ border: '--select-option-active-border',
2295
+ outline: '--select-option-active-outline',
2296
+ outlineOffset: '--select-option-active-outline-offset',
2297
+ boxShadow: '--select-option-active-shadow',
2298
+ transform: '--select-option-active-transform',
2299
+ });
2300
+ this._applyStyleVariableMap(styles.disabledOption, {
2301
+ background: '--select-option-disabled-bg',
2302
+ backgroundColor: '--select-option-disabled-bg',
2303
+ color: '--select-option-disabled-color',
2304
+ border: '--select-option-disabled-border',
2305
+ borderBottom: '--select-option-disabled-border-bottom',
2306
+ opacity: '--select-option-disabled-opacity',
2307
+ cursor: '--select-option-disabled-cursor',
2308
+ });
2309
+ this._applyStyleVariableMap(styles.badge, {
2310
+ width: '--select-badge-width',
2311
+ minWidth: '--select-badge-min-width',
2312
+ maxWidth: '--select-badge-max-width',
2313
+ height: '--select-badge-height',
2314
+ minHeight: '--select-badge-min-height',
2315
+ padding: '--select-badge-padding',
2316
+ margin: '--select-badge-margin',
2317
+ gap: '--select-badge-gap',
2318
+ background: '--select-badge-bg',
2319
+ backgroundColor: '--select-badge-bg',
2320
+ color: '--select-badge-color',
2321
+ border: '--select-badge-border',
2322
+ borderRadius: '--select-badge-border-radius',
2323
+ boxShadow: '--select-badge-shadow',
2324
+ fontSize: '--select-badge-font-size',
2325
+ fontWeight: '--select-badge-font-weight',
2326
+ lineHeight: '--select-badge-line-height',
2327
+ letterSpacing: '--select-badge-letter-spacing',
2328
+ });
2329
+ this._applyStyleVariableMap(styles.badgeHover, {
2330
+ background: '--select-badge-hover-bg',
2331
+ backgroundColor: '--select-badge-hover-bg',
2332
+ color: '--select-badge-hover-color',
2333
+ border: '--select-badge-hover-border',
2334
+ boxShadow: '--select-badge-hover-shadow',
2335
+ transform: '--select-badge-hover-transform',
2336
+ });
2337
+ this._applyStyleVariableMap(styles.badgeActive, {
2338
+ background: '--select-badge-active-bg',
2339
+ backgroundColor: '--select-badge-active-bg',
2340
+ color: '--select-badge-active-color',
2341
+ border: '--select-badge-active-border',
2342
+ boxShadow: '--select-badge-active-shadow',
2343
+ transform: '--select-badge-active-transform',
2344
+ });
2345
+ this._applyStyleVariableMap(styles.badgeLabel, {
2346
+ color: '--select-badge-label-color',
2347
+ fontSize: '--select-badge-label-font-size',
2348
+ fontWeight: '--select-badge-label-font-weight',
2349
+ lineHeight: '--select-badge-label-line-height',
2350
+ letterSpacing: '--select-badge-label-letter-spacing',
2351
+ textAlign: '--select-badge-label-text-align',
2352
+ });
2353
+ this._applyStyleVariableMap(styles.badgeRemove, {
2354
+ width: '--select-badge-remove-size',
2355
+ height: '--select-badge-remove-size',
2356
+ minWidth: '--select-badge-remove-min-width',
2357
+ minHeight: '--select-badge-remove-min-height',
2358
+ marginLeft: '--select-badge-remove-margin-left',
2359
+ background: '--select-badge-remove-bg',
2360
+ backgroundColor: '--select-badge-remove-bg',
2361
+ border: '--select-badge-remove-border',
2362
+ borderRadius: '--select-badge-remove-radius',
2363
+ color: '--select-badge-remove-color',
2364
+ fontSize: '--select-badge-remove-font-size',
2365
+ fontWeight: '--select-badge-remove-font-weight',
2366
+ });
2367
+ this._applyStyleVariableMap(styles.badgeRemoveHover, {
2368
+ background: '--select-badge-remove-hover-bg',
2369
+ backgroundColor: '--select-badge-remove-hover-bg',
2370
+ color: '--select-badge-remove-hover-color',
2371
+ border: '--select-badge-remove-hover-border',
2372
+ boxShadow: '--select-badge-remove-hover-shadow',
2373
+ transform: '--select-badge-remove-hover-transform',
2374
+ });
2375
+ this._applyStyleVariableMap(styles.badgeRemoveActive, {
2376
+ background: '--select-badge-remove-active-bg',
2377
+ backgroundColor: '--select-badge-remove-active-bg',
2378
+ color: '--select-badge-remove-active-color',
2379
+ border: '--select-badge-remove-active-border',
2380
+ boxShadow: '--select-badge-remove-active-shadow',
2381
+ transform: '--select-badge-remove-active-transform',
2382
+ });
2383
+ this._applyStyleVariableMap(styles.groupHeader, {
2384
+ padding: '--select-group-header-padding',
2385
+ margin: '--select-group-header-margin',
2386
+ color: '--select-group-header-color',
2387
+ background: '--select-group-header-bg',
2388
+ backgroundColor: '--select-group-header-bg',
2389
+ border: '--select-group-header-border',
2390
+ borderBottom: '--select-group-header-border-bottom',
2391
+ borderRadius: '--select-group-header-border-radius',
2392
+ boxShadow: '--select-group-header-shadow',
2393
+ textAlign: '--select-group-header-text-align',
2394
+ fontSize: '--select-group-header-font-size',
2395
+ fontWeight: '--select-group-header-weight',
2396
+ textTransform: '--select-group-header-text-transform',
2397
+ letterSpacing: '--select-group-header-letter-spacing',
2398
+ });
2399
+ }
2400
+ _resolveDropdownPlacement() {
2401
+ const placementMode = this._config.dropdownPlacement?.mode ?? 'bottom';
2402
+ if (placementMode === 'bottom' || placementMode === 'top') {
2403
+ return placementMode;
2404
+ }
2405
+ const hostRect = this._container.getBoundingClientRect();
2406
+ const availableBelow = window.innerHeight - hostRect.bottom;
2407
+ const computedDropdown = window.getComputedStyle(this._dropdown);
2408
+ const maxHeight = Number.parseFloat(computedDropdown.maxHeight || '0');
2409
+ const desiredHeight = Number.isFinite(maxHeight) && maxHeight > 0
2410
+ ? Math.min(this._dropdown.scrollHeight, maxHeight)
2411
+ : this._dropdown.scrollHeight;
2412
+ return availableBelow >= desiredHeight ? 'bottom' : 'top';
2413
+ }
2414
+ _syncDropdownPlacement() {
2415
+ if (!this._dropdown)
2416
+ return;
2417
+ this._resolvedDropdownPlacement = this._resolveDropdownPlacement();
2418
+ this._dropdown.setAttribute('data-placement', this._resolvedDropdownPlacement);
2419
+ }
2420
+ _syncDirectionConfig() {
2421
+ this.setAttribute('dir', this._config.direction ?? 'ltr');
2422
+ }
2423
+ _setIconContent(target, markup, fallback) {
2424
+ const content = markup && markup.trim() ? markup : fallback;
2425
+ target.innerHTML = '';
2426
+ if (content.trim().startsWith('<')) {
2427
+ target.innerHTML = content;
2428
+ return;
2429
+ }
2430
+ target.textContent = content;
2431
+ }
2145
2432
  _syncInputContainerMode() {
2146
2433
  if (!this._inputContainer || !this._input)
2147
2434
  return;
@@ -2158,6 +2445,121 @@
2158
2445
  this._input.style.width = '100%';
2159
2446
  this._input.style.minWidth = '0';
2160
2447
  }
2448
+ this._syncMultiSelectDisplayConfig();
2449
+ }
2450
+ _syncMultiSelectDisplayConfig() {
2451
+ if (!this._inputContainer || !this._input)
2452
+ return;
2453
+ const isMulti = this._config.selection.mode === 'multi';
2454
+ const mode = this._config.multiSelectDisplay?.mode ?? 'wrap';
2455
+ const dragEnabled = this._config.multiSelectDisplay?.dragScroll !== false;
2456
+ if (!isMulti) {
2457
+ this._inputContainer.removeAttribute('data-multi-scroll-mode');
2458
+ this._inputContainer.removeAttribute('data-drag-scroll');
2459
+ this._inputContainer.classList.remove('is-dragging-scroll');
2460
+ this._inputContainer.style.removeProperty('--select-multi-input-max-height');
2461
+ this._inputContainer.style.removeProperty('--select-multi-input-overflow-x');
2462
+ this._inputContainer.style.removeProperty('--select-multi-input-overflow-y');
2463
+ this._inputContainer.style.removeProperty('--select-multi-input-flex-wrap');
2464
+ this._inputContainer.style.removeProperty('--select-multi-input-align-content');
2465
+ return;
2466
+ }
2467
+ const maxHeight = this._config.multiSelectDisplay?.maxHeight ?? '160px';
2468
+ const overflowX = this._config.multiSelectDisplay?.overflowX ?? (mode === 'horizontal' ? 'auto' : 'hidden');
2469
+ const overflowY = this._config.multiSelectDisplay?.overflowY ?? (mode === 'horizontal' ? 'hidden' : 'auto');
2470
+ const flexWrap = mode === 'horizontal' ? 'nowrap' : 'wrap';
2471
+ const alignContent = mode === 'horizontal' ? 'center' : 'flex-start';
2472
+ this._inputContainer.setAttribute('data-multi-scroll-mode', mode);
2473
+ this._inputContainer.setAttribute('data-drag-scroll', String(dragEnabled && mode === 'horizontal'));
2474
+ this._inputContainer.style.setProperty('--select-multi-input-max-height', maxHeight);
2475
+ this._inputContainer.style.setProperty('--select-multi-input-overflow-x', overflowX);
2476
+ this._inputContainer.style.setProperty('--select-multi-input-overflow-y', overflowY);
2477
+ this._inputContainer.style.setProperty('--select-multi-input-flex-wrap', flexWrap);
2478
+ this._inputContainer.style.setProperty('--select-multi-input-align-content', alignContent);
2479
+ }
2480
+ _canUseHorizontalMultiScroll(target) {
2481
+ if (this._config.selection.mode !== 'multi')
2482
+ return false;
2483
+ if ((this._config.multiSelectDisplay?.mode ?? 'wrap') !== 'horizontal')
2484
+ return false;
2485
+ if (this._config.multiSelectDisplay?.dragScroll === false)
2486
+ return false;
2487
+ if (!target)
2488
+ return true;
2489
+ if (target.closest('.dropdown-arrow-container, .clear-control-button, .badge-remove'))
2490
+ return false;
2491
+ if (target.matches('.select-input'))
2492
+ return false;
2493
+ return true;
2494
+ }
2495
+ _isScrollableMultiSelectMode() {
2496
+ if (this._config.selection.mode !== 'multi')
2497
+ return false;
2498
+ const mode = this._config.multiSelectDisplay?.mode ?? 'wrap';
2499
+ return mode === 'vertical' || mode === 'horizontal';
2500
+ }
2501
+ _isPointerOnInputScrollbar(event) {
2502
+ if (!this._isScrollableMultiSelectMode())
2503
+ return false;
2504
+ const rect = this._inputContent.getBoundingClientRect();
2505
+ const verticalScrollbarWidth = this._inputContent.offsetWidth - this._inputContent.clientWidth;
2506
+ const horizontalScrollbarHeight = this._inputContent.offsetHeight - this._inputContent.clientHeight;
2507
+ if (verticalScrollbarWidth > 0
2508
+ && event.clientX >= rect.right - verticalScrollbarWidth
2509
+ && event.clientX <= rect.right
2510
+ && event.clientY >= rect.top
2511
+ && event.clientY <= rect.bottom) {
2512
+ return true;
2513
+ }
2514
+ if (horizontalScrollbarHeight > 0
2515
+ && event.clientY >= rect.bottom - horizontalScrollbarHeight
2516
+ && event.clientY <= rect.bottom
2517
+ && event.clientX >= rect.left
2518
+ && event.clientX <= rect.right) {
2519
+ return true;
2520
+ }
2521
+ return false;
2522
+ }
2523
+ _beginMultiScrollDrag(e) {
2524
+ const scrollHost = this._inputContent;
2525
+ this._multiScrollDrag.active = true;
2526
+ this._multiScrollDrag.moved = false;
2527
+ this._multiScrollDrag.pointerId = e.pointerId;
2528
+ this._multiScrollDrag.startX = e.clientX;
2529
+ this._multiScrollDrag.startScrollLeft = scrollHost.scrollLeft;
2530
+ this._inputContainer.classList.add('is-dragging-scroll');
2531
+ try {
2532
+ scrollHost.setPointerCapture(e.pointerId);
2533
+ }
2534
+ catch (_error) {
2535
+ // ignore pointer capture issues
2536
+ }
2537
+ }
2538
+ _updateMultiScrollDrag(e) {
2539
+ if (!this._multiScrollDrag.active || this._multiScrollDrag.pointerId !== e.pointerId)
2540
+ return;
2541
+ const deltaX = e.clientX - this._multiScrollDrag.startX;
2542
+ if (Math.abs(deltaX) > 3) {
2543
+ this._multiScrollDrag.moved = true;
2544
+ }
2545
+ this._inputContent.scrollLeft = this._multiScrollDrag.startScrollLeft - deltaX;
2546
+ }
2547
+ _endMultiScrollDrag(pointerId) {
2548
+ if (!this._multiScrollDrag.active)
2549
+ return;
2550
+ if (pointerId != null && this._multiScrollDrag.pointerId !== pointerId)
2551
+ return;
2552
+ try {
2553
+ if (this._multiScrollDrag.pointerId >= 0) {
2554
+ this._inputContent.releasePointerCapture(this._multiScrollDrag.pointerId);
2555
+ }
2556
+ }
2557
+ catch (_error) {
2558
+ // ignore pointer capture issues
2559
+ }
2560
+ this._multiScrollDrag.active = false;
2561
+ this._multiScrollDrag.pointerId = -1;
2562
+ this._inputContainer.classList.remove('is-dragging-scroll');
2161
2563
  }
2162
2564
  _createInput() {
2163
2565
  const input = document.createElement('input');
@@ -2286,7 +2688,8 @@
2286
2688
  return button;
2287
2689
  }
2288
2690
  _assembleDOM() {
2289
- this._inputContainer.appendChild(this._input);
2691
+ this._inputContent.appendChild(this._input);
2692
+ this._inputContainer.appendChild(this._inputContent);
2290
2693
  if (this._clearControl) {
2291
2694
  this._inputContainer.appendChild(this._clearControl);
2292
2695
  }
@@ -2343,9 +2746,11 @@
2343
2746
  --select-badge-enter-from-transform: scale(0.8) translateY(-4px);
2344
2747
  --select-badge-enter-to-opacity: 1;
2345
2748
  --select-badge-enter-to-transform: scale(1) translateY(0);
2749
+ --select-badge-active-transform: scale(0.98);
2346
2750
  --select-badge-hover-transform: scale(1.02);
2347
2751
  --select-badge-letter-spacing: 0.01em;
2348
2752
  --select-badge-hover-shadow: var(--select-shadow-md), inset 0 1px 0 rgba(255, 255, 255, 0.15);
2753
+ --select-badge-remove-icon-size: 10px;
2349
2754
  --select-badge-remove-focus-outline: 2px solid rgba(255, 255, 255, 0.5);
2350
2755
  --select-badge-remove-focus-offset: 1px;
2351
2756
  --select-badge-remove-hover-transform: scale(1.15) rotate(90deg);
@@ -2355,8 +2760,25 @@
2355
2760
  --select-input-font-weight: 450;
2356
2761
  --select-input-letter-spacing: 0.01em;
2357
2762
  --select-input-disabled-opacity: 0.6;
2763
+ --select-input-overflow-x: hidden;
2764
+ --select-input-align-items: center;
2765
+ --select-input-align-content: center;
2766
+ --select-input-align-self: center;
2767
+ --select-multi-input-max-height: 160px;
2768
+ --select-multi-input-overflow-x: hidden;
2769
+ --select-multi-input-overflow-y: auto;
2770
+ --select-multi-input-flex-wrap: wrap;
2771
+ --select-multi-input-align-content: flex-start;
2772
+ --select-multi-input-horizontal-input-flex: 0 0 var(--select-multi-input-min-width, 96px);
2773
+ --select-multi-input-horizontal-cursor: grab;
2774
+ --select-multi-input-horizontal-active-cursor: grabbing;
2775
+ --select-multi-separator-inset-block: 10px;
2776
+ --select-multi-action-surface-bg: var(--select-input-bg, var(--select-surface));
2777
+ --select-multi-action-divider: 1px solid var(--select-border);
2358
2778
  --select-separator-opacity: 0.6;
2359
2779
  --select-separator-active-opacity: 1;
2780
+ --select-separator-position: var(--select-arrow-width, 42px);
2781
+ --select-separator-position-with-clear: calc(var(--select-arrow-right-with-clear, 34px) + var(--select-arrow-width, 42px));
2360
2782
  --select-separator-dark-bg: linear-gradient(
2361
2783
  to bottom,
2362
2784
  transparent 0%,
@@ -2370,11 +2792,15 @@
2370
2792
  --select-clear-button-focus-offset: 2px;
2371
2793
  --select-clear-icon-size: 14px;
2372
2794
  --select-dropdown-top: calc(100% + 6px);
2795
+ --select-dropdown-bottom: calc(100% + 6px);
2373
2796
  --select-dropdown-animation: dropdownEnter 200ms cubic-bezier(0.4, 0, 0.2, 1) forwards;
2374
2797
  --select-dropdown-enter-from-opacity: 0;
2375
2798
  --select-dropdown-enter-from-transform: translateY(-8px) scale(0.98);
2376
2799
  --select-dropdown-enter-to-opacity: 1;
2377
2800
  --select-dropdown-enter-to-transform: translateY(0) scale(1);
2801
+ --select-dropdown-top-transform-origin: bottom center;
2802
+ --select-dropdown-top-enter-from-transform: translateY(8px) scale(0.98);
2803
+ --select-dropdown-padding: 6px;
2378
2804
  --select-dropdown-scroll-behavior: smooth;
2379
2805
  --select-dropdown-transform-origin: top center;
2380
2806
  --select-scrollbar-width: 6px;
@@ -2382,6 +2808,8 @@
2382
2808
  --select-option-hover-transform: translateX(2px);
2383
2809
  --select-option-font-weight: 450;
2384
2810
  --select-option-margin: 2px 0;
2811
+ --select-option-disabled-opacity: 0.5;
2812
+ --select-option-disabled-cursor: not-allowed;
2385
2813
  --select-option-active-outline-offset: -2px;
2386
2814
  --select-option-selected-active-outline-offset: -2px;
2387
2815
  --select-option-selected-indicator-width: 3px;
@@ -2423,12 +2851,31 @@
2423
2851
  --select-high-contrast-focus-outline-color: Highlight;
2424
2852
  --select-touch-target-min-height: 44px;
2425
2853
  --select-badge-dark-bg: linear-gradient(135deg, var(--select-accent) 0%, #4f46e5 100%);
2854
+ --select-host-z-index: auto;
2855
+ --select-host-open-z-index: var(--select-dropdown-z-index, 1000);
2856
+ --select-ancestor-open-z-index: var(--select-host-open-z-index, var(--select-dropdown-z-index, 1000));
2426
2857
 
2427
2858
  display: block;
2428
2859
  position: relative;
2860
+ z-index: var(--select-host-z-index, auto);
2429
2861
  width: var(--select-width, 100%);
2430
2862
  height: var(--select-height, auto);
2431
- font-family: var(--select-font-family, 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif);
2863
+ font-family: var(--select-font-family, inherit);
2864
+ font-size: var(--select-font-size, inherit);
2865
+ line-height: var(--select-line-height, inherit);
2866
+ color: var(--select-color, inherit);
2867
+ }
2868
+
2869
+ :host([data-open="true"]) {
2870
+ z-index: var(--select-host-open-z-index, var(--select-dropdown-z-index, 1000));
2871
+ }
2872
+
2873
+ :host([dir="ltr"]) {
2874
+ direction: ltr;
2875
+ }
2876
+
2877
+ :host([dir="rtl"]) {
2878
+ direction: rtl;
2432
2879
  }
2433
2880
 
2434
2881
  /* ─────────────────────────────────────────────────────────────────────────
@@ -2440,6 +2887,9 @@
2440
2887
  align-items: center;
2441
2888
  gap: var(--select-badge-gap, 6px);
2442
2889
  flex: 0 1 auto;
2890
+ width: var(--select-badge-width, auto);
2891
+ min-width: var(--select-badge-min-width, 0);
2892
+ height: var(--select-badge-height, auto);
2443
2893
  min-height: var(--select-badge-min-height, 26px);
2444
2894
  padding: var(--select-badge-padding, 4px 10px 4px 12px);
2445
2895
  margin: var(--select-badge-margin, 3px);
@@ -2449,7 +2899,7 @@
2449
2899
  border-radius: var(--select-badge-border-radius, 999px);
2450
2900
  box-shadow: var(--select-badge-shadow, var(--select-shadow-sm), inset 0 1px 0 rgba(255, 255, 255, 0.1));
2451
2901
  box-sizing: border-box;
2452
- font-size: var(--select-badge-font-size, 13px);
2902
+ font-size: var(--select-badge-font-size, 0.8667em);
2453
2903
  font-weight: var(--select-badge-font-weight, 500);
2454
2904
  line-height: var(--select-badge-line-height, 1.2);
2455
2905
  letter-spacing: var(--select-badge-letter-spacing);
@@ -2475,17 +2925,33 @@
2475
2925
  }
2476
2926
 
2477
2927
  .selection-badge:hover {
2928
+ background: var(--select-badge-hover-bg, var(--select-badge-bg, linear-gradient(135deg, var(--select-accent) 0%, var(--select-primary-light) 100%)));
2929
+ color: var(--select-badge-hover-color, var(--select-badge-color, #ffffff));
2930
+ border: var(--select-badge-hover-border, var(--select-badge-border, none));
2478
2931
  box-shadow: var(--select-badge-hover-shadow);
2479
2932
  transform: var(--select-badge-hover-transform);
2480
2933
  }
2481
2934
 
2935
+ .selection-badge:active {
2936
+ background: var(--select-badge-active-bg, var(--select-badge-hover-bg, var(--select-badge-bg, linear-gradient(135deg, var(--select-accent) 0%, var(--select-primary-light) 100%))));
2937
+ color: var(--select-badge-active-color, var(--select-badge-hover-color, var(--select-badge-color, #ffffff)));
2938
+ border: var(--select-badge-active-border, var(--select-badge-hover-border, var(--select-badge-border, none)));
2939
+ box-shadow: var(--select-badge-active-shadow, var(--select-badge-hover-shadow));
2940
+ transform: var(--select-badge-active-transform);
2941
+ }
2942
+
2482
2943
  .selection-badge-label {
2483
2944
  display: block;
2484
2945
  min-width: 0;
2485
2946
  overflow: hidden;
2486
2947
  text-overflow: ellipsis;
2487
2948
  white-space: nowrap;
2488
- line-height: var(--select-badge-line-height, 1.2);
2949
+ color: var(--select-badge-label-color, inherit);
2950
+ font-size: var(--select-badge-label-font-size, inherit);
2951
+ font-weight: var(--select-badge-label-font-weight, inherit);
2952
+ line-height: var(--select-badge-label-line-height, var(--select-badge-line-height, 1.2));
2953
+ letter-spacing: var(--select-badge-label-letter-spacing, inherit);
2954
+ text-align: var(--select-badge-label-text-align, start);
2489
2955
  }
2490
2956
 
2491
2957
  .badge-remove {
@@ -2494,24 +2960,47 @@
2494
2960
  justify-content: center;
2495
2961
  width: var(--select-badge-remove-size, 18px);
2496
2962
  height: var(--select-badge-remove-size, 18px);
2963
+ min-width: var(--select-badge-remove-min-width, var(--select-badge-remove-size, 18px));
2964
+ min-height: var(--select-badge-remove-min-height, var(--select-badge-remove-size, 18px));
2497
2965
  padding: 0;
2498
2966
  margin-left: var(--select-badge-remove-margin-left);
2499
2967
  background: var(--select-badge-remove-bg, rgba(255, 255, 255, 0.2));
2500
2968
  border: var(--select-badge-remove-border, none);
2501
2969
  border-radius: var(--select-badge-remove-radius);
2502
2970
  color: var(--select-badge-remove-color, #ffffff);
2503
- font-size: var(--select-badge-remove-font-size, 11px);
2971
+ font-size: var(--select-badge-remove-font-size, 0.7333em);
2504
2972
  font-weight: var(--select-badge-remove-font-weight);
2505
2973
  line-height: 1;
2506
2974
  cursor: pointer;
2507
2975
  flex: 0 0 auto;
2508
2976
  transition:
2509
2977
  background var(--select-transition-fast),
2978
+ color var(--select-transition-fast),
2979
+ border-color var(--select-transition-fast),
2980
+ box-shadow var(--select-transition-fast),
2510
2981
  transform var(--select-transition-bounce);
2511
2982
  }
2983
+
2984
+ .badge-remove-icon {
2985
+ display: inline-flex;
2986
+ align-items: center;
2987
+ justify-content: center;
2988
+ width: var(--select-badge-remove-icon-size, 10px);
2989
+ height: var(--select-badge-remove-icon-size, 10px);
2990
+ pointer-events: none;
2991
+ }
2992
+
2993
+ .badge-remove-icon svg {
2994
+ width: 100%;
2995
+ height: 100%;
2996
+ display: block;
2997
+ }
2512
2998
 
2513
2999
  .badge-remove:hover {
2514
3000
  background: var(--select-badge-remove-hover-bg, rgba(233, 69, 96, 0.9));
3001
+ color: var(--select-badge-remove-hover-color, var(--select-badge-remove-color, #ffffff));
3002
+ border: var(--select-badge-remove-hover-border, var(--select-badge-remove-border, none));
3003
+ box-shadow: var(--select-badge-remove-hover-shadow, none);
2515
3004
  transform: var(--select-badge-remove-hover-transform);
2516
3005
  }
2517
3006
 
@@ -2521,8 +3010,17 @@
2521
3010
  }
2522
3011
 
2523
3012
  .badge-remove:active {
3013
+ background: var(--select-badge-remove-active-bg, var(--select-badge-remove-hover-bg, rgba(233, 69, 96, 0.9)));
3014
+ color: var(--select-badge-remove-active-color, var(--select-badge-remove-hover-color, var(--select-badge-remove-color, #ffffff)));
3015
+ border: var(--select-badge-remove-active-border, var(--select-badge-remove-hover-border, var(--select-badge-remove-border, none)));
3016
+ box-shadow: var(--select-badge-remove-active-shadow, var(--select-badge-remove-hover-shadow, none));
2524
3017
  transform: var(--select-badge-remove-active-transform);
2525
3018
  }
3019
+
3020
+ :host([dir="rtl"]) .badge-remove {
3021
+ margin-left: 0;
3022
+ margin-right: var(--select-badge-remove-margin-left);
3023
+ }
2526
3024
 
2527
3025
  /* ─────────────────────────────────────────────────────────────────────────
2528
3026
  Input Container — Sophisticated control shell
@@ -2537,15 +3035,17 @@
2537
3035
  position: relative;
2538
3036
  width: 100%;
2539
3037
  display: flex;
2540
- align-items: center;
3038
+ align-items: var(--select-input-align-items, center);
2541
3039
  flex-wrap: nowrap;
3040
+ justify-content: var(--select-input-justify-content, flex-start);
2542
3041
  gap: var(--select-input-gap, 6px);
2543
3042
  padding: var(--select-input-padding, 10px 52px 10px 14px);
2544
3043
  height: var(--select-input-height, auto);
2545
3044
  min-height: var(--select-input-min-height, 48px);
2546
3045
  max-height: var(--select-input-max-height, 160px);
2547
- overflow-y: var(--select-input-overflow-y, auto);
2548
- align-content: center;
3046
+ overflow: hidden;
3047
+ align-content: var(--select-input-align-content, center);
3048
+ text-align: var(--select-input-text-align, start);
2549
3049
  background: var(--select-input-bg, var(--select-surface));
2550
3050
  border: var(--select-input-border, 1.5px solid var(--select-border));
2551
3051
  border-radius: var(--select-input-border-radius, var(--select-radius-md));
@@ -2556,6 +3056,25 @@
2556
3056
  box-shadow var(--select-transition-smooth),
2557
3057
  transform var(--select-transition-fast);
2558
3058
  }
3059
+
3060
+ .input-content {
3061
+ position: relative;
3062
+ display: flex;
3063
+ flex: 1 1 auto;
3064
+ width: 100%;
3065
+ min-width: 0;
3066
+ min-height: 0;
3067
+ align-self: stretch;
3068
+ align-items: var(--select-input-align-items, center);
3069
+ align-content: var(--select-input-align-content, center);
3070
+ justify-content: var(--select-input-justify-content, flex-start);
3071
+ flex-wrap: nowrap;
3072
+ gap: var(--select-input-gap, 6px);
3073
+ overflow-x: var(--select-input-overflow-x, hidden);
3074
+ overflow-y: var(--select-input-overflow-y, hidden);
3075
+ scrollbar-width: thin;
3076
+ box-sizing: border-box;
3077
+ }
2559
3078
 
2560
3079
  .input-container:hover {
2561
3080
  border-color: var(--select-input-hover-border);
@@ -2568,8 +3087,75 @@
2568
3087
  }
2569
3088
 
2570
3089
  .input-container.input-container--multi {
2571
- flex-wrap: wrap;
2572
- align-content: flex-start;
3090
+ max-height: var(--select-multi-input-max-height, var(--select-input-max-height, 160px));
3091
+ }
3092
+
3093
+ .input-container.input-container--multi .input-content {
3094
+ flex-wrap: var(--select-multi-input-flex-wrap, wrap);
3095
+ align-content: var(--select-multi-input-align-content, flex-start);
3096
+ overflow-x: var(--select-multi-input-overflow-x, hidden);
3097
+ overflow-y: var(--select-multi-input-overflow-y, auto);
3098
+ }
3099
+
3100
+ .input-container.input-container--multi::after {
3101
+ top: var(--select-multi-separator-inset-block, 10px);
3102
+ bottom: var(--select-multi-separator-inset-block, 10px);
3103
+ height: auto;
3104
+ transform: none;
3105
+ }
3106
+
3107
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] {
3108
+ align-items: stretch;
3109
+ }
3110
+
3111
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .input-content {
3112
+ cursor: var(--select-multi-input-horizontal-cursor, grab);
3113
+ overflow-y: hidden;
3114
+ overscroll-behavior-x: contain;
3115
+ }
3116
+
3117
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"]::after {
3118
+ display: none;
3119
+ }
3120
+
3121
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"].is-dragging-scroll .input-content {
3122
+ cursor: var(--select-multi-input-horizontal-active-cursor, grabbing);
3123
+ user-select: none;
3124
+ }
3125
+
3126
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .input-content .selection-badge {
3127
+ flex: 0 0 auto;
3128
+ }
3129
+
3130
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .input-content > .select-input,
3131
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .input-content > input.select-input,
3132
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .input-content > .select-input[type="text"] {
3133
+ flex: var(--select-multi-input-horizontal-input-flex, 0 0 var(--select-multi-input-min-width, 96px));
3134
+ }
3135
+
3136
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .dropdown-arrow-container {
3137
+ background: var(--select-multi-action-surface-bg, var(--select-input-bg, var(--select-surface)));
3138
+ border-left: var(--select-multi-action-divider, 1px solid var(--select-border));
3139
+ z-index: 4;
3140
+ }
3141
+
3142
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .dropdown-arrow-container.with-clear-control {
3143
+ right: var(--select-arrow-right-with-clear, 34px);
3144
+ }
3145
+
3146
+ :host([dir="rtl"]) .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .dropdown-arrow-container {
3147
+ border-left: none;
3148
+ border-right: var(--select-multi-action-divider, 1px solid var(--select-border));
3149
+ }
3150
+
3151
+ :host([dir="rtl"]) .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .dropdown-arrow-container.with-clear-control {
3152
+ right: auto;
3153
+ left: var(--select-arrow-right-with-clear, 34px);
3154
+ }
3155
+
3156
+ .input-container.input-container--multi[data-multi-scroll-mode="horizontal"] .clear-control-button {
3157
+ background: var(--select-multi-action-surface-bg, var(--select-input-bg, var(--select-surface)));
3158
+ z-index: 4;
2573
3159
  }
2574
3160
 
2575
3161
  .input-container:focus-within {
@@ -2582,7 +3168,7 @@
2582
3168
  content: '';
2583
3169
  position: absolute;
2584
3170
  top: 50%;
2585
- right: var(--select-separator-position, 42px);
3171
+ right: var(--select-separator-position, var(--select-arrow-width, 42px));
2586
3172
  transform: translateY(-50%);
2587
3173
  width: var(--select-separator-width, 1px);
2588
3174
  height: var(--select-separator-height, 50%);
@@ -2603,6 +3189,11 @@
2603
3189
  .input-container:focus-within::after {
2604
3190
  opacity: var(--select-separator-active-opacity);
2605
3191
  }
3192
+
3193
+ :host([dir="rtl"]) .input-container::after {
3194
+ right: auto;
3195
+ left: var(--select-separator-position, var(--select-arrow-width, 42px));
3196
+ }
2606
3197
 
2607
3198
  /* ─────────────────────────────────────────────────────────────────────────
2608
3199
  Dropdown Arrow — Smooth rotation with refined styling
@@ -2629,13 +3220,29 @@
2629
3220
  }
2630
3221
 
2631
3222
  .input-container.has-clear-control::after {
2632
- right: var(--select-separator-position-with-clear, 74px);
3223
+ right: var(--select-separator-position-with-clear, calc(var(--select-arrow-right-with-clear, 34px) + var(--select-arrow-width, 42px)));
2633
3224
  }
2634
3225
 
2635
3226
  .dropdown-arrow-container.with-clear-control {
2636
3227
  right: var(--select-arrow-right-with-clear, 34px);
2637
3228
  }
2638
3229
 
3230
+ :host([dir="rtl"]) .dropdown-arrow-container {
3231
+ right: auto;
3232
+ left: 0;
3233
+ border-radius: var(--select-arrow-border-radius-rtl, var(--select-radius-md) 0 0 var(--select-radius-md));
3234
+ }
3235
+
3236
+ :host([dir="rtl"]) .input-container.has-clear-control::after {
3237
+ right: auto;
3238
+ left: var(--select-separator-position-with-clear, calc(var(--select-arrow-right-with-clear, 34px) + var(--select-arrow-width, 42px)));
3239
+ }
3240
+
3241
+ :host([dir="rtl"]) .dropdown-arrow-container.with-clear-control {
3242
+ right: auto;
3243
+ left: var(--select-arrow-right-with-clear, 34px);
3244
+ }
3245
+
2639
3246
  /* ─────────────────────────────────────────────────────────────────────────
2640
3247
  Clear Control — Minimal and elegant dismiss button
2641
3248
  ───────────────────────────────────────────────────────────────────────── */
@@ -2681,6 +3288,11 @@
2681
3288
  display: none;
2682
3289
  }
2683
3290
 
3291
+ :host([dir="rtl"]) .clear-control-button {
3292
+ right: auto;
3293
+ left: var(--select-clear-button-right, 8px);
3294
+ }
3295
+
2684
3296
  .clear-control-icon {
2685
3297
  width: var(--select-clear-icon-size);
2686
3298
  height: var(--select-clear-icon-size);
@@ -2735,7 +3347,7 @@
2735
3347
  padding: var(--select-input-field-padding, 0) !important;
2736
3348
  margin: 0 !important;
2737
3349
  border: 0 !important;
2738
- font-size: var(--select-input-font-size, 15px);
3350
+ font-size: var(--select-input-font-size, inherit);
2739
3351
  line-height: var(--select-input-line-height, 1.5);
2740
3352
  color: var(--select-input-color, var(--select-text));
2741
3353
  background: transparent !important;
@@ -2743,13 +3355,16 @@
2743
3355
  outline: none !important;
2744
3356
  font-weight: var(--select-input-font-weight);
2745
3357
  letter-spacing: var(--select-input-letter-spacing);
2746
- align-self: center;
3358
+ font-family: var(--select-input-font-family, inherit);
3359
+ font-style: var(--select-input-font-style, normal);
3360
+ align-self: var(--select-input-align-self, center);
2747
3361
  appearance: none !important;
2748
3362
  -webkit-appearance: none !important;
2749
3363
  box-shadow: none !important;
2750
3364
  border-radius: 0 !important;
2751
3365
  overflow: hidden;
2752
3366
  text-overflow: ellipsis;
3367
+ text-align: var(--select-input-text-align, inherit);
2753
3368
  white-space: nowrap;
2754
3369
  }
2755
3370
 
@@ -2758,6 +3373,14 @@
2758
3373
  font-weight: 400;
2759
3374
  }
2760
3375
 
3376
+ :host([dir="rtl"]) .input-container {
3377
+ padding: var(--select-input-padding-rtl, 10px 14px 10px 52px);
3378
+ }
3379
+
3380
+ :host([dir="rtl"]) .input-container.has-clear-control {
3381
+ padding: var(--select-input-padding-with-clear-rtl, 10px 14px 10px 84px);
3382
+ }
3383
+
2761
3384
  .input-container.input-container--multi > .select-input,
2762
3385
  .input-container.input-container--multi > input.select-input,
2763
3386
  .input-container.input-container--multi > .select-input[type="text"] {
@@ -2788,10 +3411,12 @@
2788
3411
  position: absolute;
2789
3412
  scroll-behavior: var(--select-dropdown-scroll-behavior);
2790
3413
  top: var(--select-dropdown-top);
3414
+ bottom: auto;
2791
3415
  left: 0;
2792
3416
  right: 0;
2793
3417
  max-height: var(--select-dropdown-max-height, 320px);
2794
3418
  overflow: hidden;
3419
+ box-sizing: border-box;
2795
3420
  background: var(--select-dropdown-bg, var(--select-surface));
2796
3421
  border: 1px solid var(--select-dropdown-border, var(--select-border));
2797
3422
  border-radius: var(--select-dropdown-border-radius, var(--select-radius-lg));
@@ -2800,6 +3425,16 @@
2800
3425
  transform-origin: var(--select-dropdown-transform-origin);
2801
3426
  animation: var(--select-dropdown-animation);
2802
3427
  }
3428
+
3429
+ .select-dropdown[data-placement="top"] {
3430
+ top: auto;
3431
+ bottom: var(--select-dropdown-bottom, calc(100% + 6px));
3432
+ transform-origin: var(--select-dropdown-top-transform-origin, bottom center);
3433
+ }
3434
+
3435
+ .select-dropdown[data-placement="top"] {
3436
+ --select-dropdown-enter-from-transform: var(--select-dropdown-top-enter-from-transform, translateY(8px) scale(0.98));
3437
+ }
2803
3438
 
2804
3439
  @keyframes dropdownEnter {
2805
3440
  0% {
@@ -2816,8 +3451,9 @@
2816
3451
  position: relative;
2817
3452
  max-height: var(--select-options-max-height, 320px);
2818
3453
  overflow: auto;
2819
- padding: var(--select-options-padding, 6px);
2820
- background: var(--select-options-bg, var(--select-surface));
3454
+ box-sizing: border-box;
3455
+ padding: var(--select-options-padding, var(--select-dropdown-padding, 6px));
3456
+ background: var(--select-options-bg, var(--select-dropdown-bg, var(--select-surface)));
2821
3457
 
2822
3458
  /* Custom scrollbar styling */
2823
3459
  scrollbar-width: thin;
@@ -2847,17 +3483,21 @@
2847
3483
 
2848
3484
  .group-header {
2849
3485
  padding: var(--select-group-header-padding, 10px 12px 6px);
3486
+ margin: var(--select-group-header-margin, 0);
2850
3487
  font-weight: var(--select-group-header-weight, 600);
2851
3488
  color: var(--select-group-header-color, var(--select-text-muted));
2852
3489
  background-color: var(--select-group-header-bg, var(--select-surface));
2853
3490
  text-align: var(--select-group-header-text-align, left);
2854
- font-size: var(--select-group-header-font-size, 11px);
3491
+ font-size: var(--select-group-header-font-size, 0.7333em);
2855
3492
  text-transform: var(--select-group-header-text-transform, uppercase);
2856
3493
  letter-spacing: var(--select-group-header-letter-spacing, 0.08em);
2857
3494
  position: sticky;
2858
3495
  top: 0;
2859
3496
  z-index: 1;
3497
+ border: var(--select-group-header-border, none);
2860
3498
  border-bottom: var(--select-group-header-border-bottom, none);
3499
+ border-radius: var(--select-group-header-border-radius, 0);
3500
+ box-shadow: var(--select-group-header-shadow, none);
2861
3501
  }
2862
3502
 
2863
3503
  .group-header:not(:first-child) {
@@ -2876,13 +3516,16 @@
2876
3516
  cursor: pointer;
2877
3517
  color: var(--select-option-color, var(--select-text));
2878
3518
  background: var(--select-option-bg, transparent);
3519
+ border: var(--select-option-border, none);
3520
+ text-align: var(--select-option-text-align, start);
2879
3521
  transition:
2880
3522
  background var(--select-transition-fast),
2881
3523
  color var(--select-transition-fast),
3524
+ border-color var(--select-transition-fast),
2882
3525
  transform var(--select-transition-fast),
2883
3526
  box-shadow var(--select-transition-fast);
2884
3527
  user-select: none;
2885
- font-size: var(--select-option-font-size, 14px);
3528
+ font-size: var(--select-option-font-size, inherit);
2886
3529
  font-weight: var(--select-option-font-weight);
2887
3530
  line-height: var(--select-option-line-height, 1.5);
2888
3531
  border-radius: var(--select-option-border-radius, var(--select-radius-sm));
@@ -2891,12 +3534,14 @@
2891
3534
 
2892
3535
  .option:hover {
2893
3536
  background: var(--select-option-hover-bg, var(--select-surface-elevated));
3537
+ border: var(--select-option-hover-border, var(--select-option-border, none));
2894
3538
  color: var(--select-option-hover-color, var(--select-text));
2895
3539
  transform: var(--select-option-hover-transform);
2896
3540
  }
2897
3541
 
2898
3542
  .option.selected {
2899
3543
  background: var(--select-option-selected-bg, linear-gradient(135deg, rgba(15, 52, 96, 0.08) 0%, rgba(15, 52, 96, 0.04) 100%));
3544
+ border: var(--select-option-selected-border, var(--select-option-border, none));
2900
3545
  color: var(--select-option-selected-color, var(--select-accent));
2901
3546
  font-weight: var(--select-option-selected-weight, 550);
2902
3547
  }
@@ -2913,6 +3558,12 @@
2913
3558
  border-radius: var(--select-option-selected-indicator-radius);
2914
3559
  animation: var(--select-option-selected-indicator-animation);
2915
3560
  }
3561
+
3562
+ :host([dir="rtl"]) .option.selected::before {
3563
+ left: auto;
3564
+ right: var(--select-option-selected-indicator-right, var(--select-option-selected-indicator-left));
3565
+ border-radius: var(--select-option-selected-indicator-radius-rtl, 2px 0 0 2px);
3566
+ }
2916
3567
 
2917
3568
  @keyframes selectedIndicator {
2918
3569
  0% {
@@ -2926,13 +3577,19 @@
2926
3577
  }
2927
3578
 
2928
3579
  .option.selected:hover {
2929
- background: var(--select-option-selected-hover-bg, linear-gradient(135deg, rgba(15, 52, 96, 0.12) 0%, rgba(15, 52, 96, 0.06) 100%));
3580
+ background: var(--select-option-selected-hover-bg, var(--select-option-selected-bg, linear-gradient(135deg, rgba(15, 52, 96, 0.12) 0%, rgba(15, 52, 96, 0.06) 100%)));
3581
+ border: var(--select-option-selected-hover-border, var(--select-option-selected-border, var(--select-option-hover-border, var(--select-option-border, none))));
3582
+ color: var(--select-option-selected-hover-color, var(--select-option-selected-color, var(--select-accent)));
2930
3583
  }
2931
3584
 
2932
3585
  .option.active:not(.selected) {
2933
3586
  background: var(--select-option-active-bg, var(--select-surface-elevated));
3587
+ color: var(--select-option-active-color, var(--select-option-hover-color, var(--select-option-color, var(--select-text))));
3588
+ border: var(--select-option-active-border, var(--select-option-hover-border, var(--select-option-border, none)));
2934
3589
  outline: var(--select-option-active-outline, 2px solid rgba(15, 52, 96, 0.3));
2935
3590
  outline-offset: var(--select-option-active-outline-offset);
3591
+ box-shadow: var(--select-option-active-shadow, none);
3592
+ transform: var(--select-option-active-transform, none);
2936
3593
  }
2937
3594
 
2938
3595
  .option.selected.active {
@@ -2940,6 +3597,14 @@
2940
3597
  outline-offset: var(--select-option-selected-active-outline-offset);
2941
3598
  }
2942
3599
 
3600
+ .option.disabled {
3601
+ background: var(--select-option-disabled-bg, var(--select-option-bg, transparent));
3602
+ color: var(--select-option-disabled-color, var(--select-text-muted));
3603
+ border: var(--select-option-disabled-border, var(--select-option-border, none));
3604
+ opacity: var(--select-option-disabled-opacity, 0.5);
3605
+ cursor: var(--select-option-disabled-cursor, not-allowed);
3606
+ }
3607
+
2943
3608
  .option:active:not(.selected) {
2944
3609
  background: var(--select-option-pressed-bg, rgba(15, 52, 96, 0.08));
2945
3610
  transform: var(--select-option-pressed-transform);
@@ -2965,7 +3630,7 @@
2965
3630
  color: var(--select-button-color, var(--select-accent));
2966
3631
  border-radius: var(--select-button-border-radius, var(--select-radius-md));
2967
3632
  cursor: pointer;
2968
- font-size: var(--select-button-font-size, 13px);
3633
+ font-size: var(--select-button-font-size, 0.8667em);
2969
3634
  font-weight: var(--select-button-font-weight);
2970
3635
  letter-spacing: var(--select-button-letter-spacing);
2971
3636
  transition:
@@ -2997,7 +3662,7 @@
2997
3662
  text-align: center;
2998
3663
  color: var(--select-busy-color, var(--select-text-muted));
2999
3664
  background: var(--select-busy-bg, transparent);
3000
- font-size: var(--select-busy-font-size, 13px);
3665
+ font-size: var(--select-busy-font-size, 0.8667em);
3001
3666
  }
3002
3667
 
3003
3668
  .spinner {
@@ -3018,7 +3683,7 @@
3018
3683
  padding: var(--select-empty-padding, 32px 24px);
3019
3684
  text-align: center;
3020
3685
  color: var(--select-empty-color, var(--select-text-muted));
3021
- font-size: var(--select-empty-font-size, 14px);
3686
+ font-size: var(--select-empty-font-size, 0.9333em);
3022
3687
  background: var(--select-empty-bg, transparent);
3023
3688
  display: flex;
3024
3689
  flex-direction: column;
@@ -3031,7 +3696,7 @@
3031
3696
  padding: var(--select-searching-padding, 32px 24px);
3032
3697
  text-align: center;
3033
3698
  color: var(--select-searching-color, var(--select-accent));
3034
- font-size: var(--select-searching-font-size, 14px);
3699
+ font-size: var(--select-searching-font-size, 0.9333em);
3035
3700
  background: var(--select-searching-bg, transparent);
3036
3701
  display: flex;
3037
3702
  flex-direction: column;
@@ -3121,24 +3786,28 @@
3121
3786
  --select-primary-light: #2a2a3e;
3122
3787
  --select-accent: #6366f1;
3123
3788
  --select-accent-hover: #f43f5e;
3124
- --select-surface: #1a1a2e;
3789
+ --select-surface: var(--select-dark-bg, #1a1a2e);
3125
3790
  --select-surface-elevated: #252540;
3126
- --select-border: #3f3f5a;
3791
+ --select-border: var(--select-dark-border, #3f3f5a);
3127
3792
  --select-border-focus: #6366f1;
3128
- --select-text: #f5f5f5;
3793
+ --select-text: var(--select-dark-text, #f5f5f5);
3129
3794
  --select-text-muted: #9ca3af;
3130
3795
  --select-text-placeholder: #6b7280;
3131
3796
  --select-shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.2);
3132
3797
  --select-shadow-md: 0 4px 12px rgba(0, 0, 0, 0.3);
3133
3798
  --select-shadow-lg: 0 8px 24px rgba(0, 0, 0, 0.4);
3134
3799
  --select-shadow-focus: 0 0 0 3px rgba(99, 102, 241, 0.25);
3800
+
3801
+ --select-dropdown-bg: var(--select-dark-dropdown-bg, var(--select-surface));
3135
3802
 
3136
- --select-option-bg: transparent;
3137
- --select-option-color: var(--select-text);
3138
- --select-option-hover-bg: var(--select-surface-elevated);
3139
- --select-option-hover-color: var(--select-text);
3140
- --select-option-selected-bg: linear-gradient(135deg, rgba(99, 102, 241, 0.15) 0%, rgba(99, 102, 241, 0.08) 100%);
3141
- --select-option-selected-color: #a5b4fc;
3803
+ --select-option-bg: var(--select-dark-option-bg, transparent);
3804
+ --select-option-color: var(--select-dark-option-color, var(--select-text));
3805
+ --select-option-hover-bg: var(--select-dark-option-hover-bg, var(--select-surface-elevated));
3806
+ --select-option-hover-color: var(--select-dark-option-hover-color, var(--select-text));
3807
+ --select-option-selected-bg: var(--select-dark-option-selected-bg, linear-gradient(135deg, rgba(99, 102, 241, 0.15) 0%, rgba(99, 102, 241, 0.08) 100%));
3808
+ --select-option-selected-color: var(--select-dark-option-selected-color, #a5b4fc);
3809
+ --select-option-selected-hover-bg: var(--select-dark-option-selected-hover-bg, var(--select-option-selected-bg));
3810
+ --select-option-selected-hover-color: var(--select-dark-option-selected-hover-color, var(--select-option-selected-color));
3142
3811
  }
3143
3812
 
3144
3813
  :host(.dark-mode) .input-container,
@@ -3181,7 +3850,7 @@
3181
3850
  :host-context([darkmode]) .select-dropdown,
3182
3851
  :host-context([data-theme="dark"]) .select-dropdown,
3183
3852
  :host-context([theme="dark"]) .select-dropdown {
3184
- background: var(--select-surface);
3853
+ background: var(--select-dropdown-bg, var(--select-surface));
3185
3854
  border-color: var(--select-border);
3186
3855
  }
3187
3856
 
@@ -3196,7 +3865,7 @@
3196
3865
  :host-context([darkmode]) .options-container,
3197
3866
  :host-context([data-theme="dark"]) .options-container,
3198
3867
  :host-context([theme="dark"]) .options-container {
3199
- background: var(--select-surface);
3868
+ background: var(--select-dropdown-bg, var(--select-surface));
3200
3869
  scrollbar-color: var(--select-border) transparent;
3201
3870
  }
3202
3871
 
@@ -3293,6 +3962,19 @@
3293
3962
  return;
3294
3963
  if (target && target.closest('.clear-control-button'))
3295
3964
  return;
3965
+ if (this._isPointerOnInputScrollbar(e)) {
3966
+ this._suppressNextOpenClick = true;
3967
+ return;
3968
+ }
3969
+ const isHorizontalMultiMode = this._config.selection.mode === 'multi'
3970
+ && (this._config.multiSelectDisplay?.mode ?? 'wrap') === 'horizontal';
3971
+ const enableHorizontalDrag = this._canUseHorizontalMultiScroll(target);
3972
+ if (enableHorizontalDrag && e.button === 0) {
3973
+ this._beginMultiScrollDrag(e);
3974
+ this._suppressNextOpenClick = false;
3975
+ e.preventDefault();
3976
+ return;
3977
+ }
3296
3978
  // If we clicked the container, but not the input itself, we must prevent default
3297
3979
  // otherwise the browser moves focus from our input to the body, immediately triggering blur.
3298
3980
  if (target && !target.matches('.select-input')) {
@@ -3301,6 +3983,8 @@
3301
3983
  const clickedInput = Boolean(target && target.matches('.select-input'));
3302
3984
  if (this._state.isOpen &&
3303
3985
  this._config.selection.toggleOnTriggerClick !== false &&
3986
+ !isHorizontalMultiMode &&
3987
+ !enableHorizontalDrag &&
3304
3988
  !(clickedInput && this._config.searchable)) {
3305
3989
  this._handleClose();
3306
3990
  return;
@@ -3323,6 +4007,47 @@
3323
4007
  }
3324
4008
  }
3325
4009
  });
4010
+ this._inputContainer.addEventListener('click', (e) => {
4011
+ const target = e.target;
4012
+ const isHorizontalMultiMode = this._config.selection.mode === 'multi'
4013
+ && (this._config.multiSelectDisplay?.mode ?? 'wrap') === 'horizontal';
4014
+ if (!this._config.enabled || !isHorizontalMultiMode) {
4015
+ this._suppressNextOpenClick = false;
4016
+ this._multiScrollDrag.moved = false;
4017
+ return;
4018
+ }
4019
+ if (target && target.closest('.dropdown-arrow-container, .clear-control-button')) {
4020
+ this._suppressNextOpenClick = false;
4021
+ this._multiScrollDrag.moved = false;
4022
+ return;
4023
+ }
4024
+ if (this._suppressNextOpenClick || this._multiScrollDrag.moved || this._isPointerOnInputScrollbar(e)) {
4025
+ this._suppressNextOpenClick = false;
4026
+ this._multiScrollDrag.moved = false;
4027
+ return;
4028
+ }
4029
+ this._suppressNextOpenClick = false;
4030
+ this._multiScrollDrag.moved = false;
4031
+ if (!this._state.isOpen) {
4032
+ this._handleOpen();
4033
+ }
4034
+ this._input.focus();
4035
+ });
4036
+ this._inputContent.addEventListener('pointermove', (e) => {
4037
+ this._updateMultiScrollDrag(e);
4038
+ });
4039
+ this._inputContent.addEventListener('pointerup', (e) => {
4040
+ this._endMultiScrollDrag(e.pointerId);
4041
+ });
4042
+ this._inputContent.addEventListener('pointercancel', (e) => {
4043
+ this._endMultiScrollDrag(e.pointerId);
4044
+ });
4045
+ this._inputContent.addEventListener('wheel', (e) => {
4046
+ if (this._config.selection.mode === 'multi'
4047
+ && (this._config.multiSelectDisplay?.mode ?? 'wrap') === 'horizontal') {
4048
+ e.preventDefault();
4049
+ }
4050
+ }, { passive: false });
3326
4051
  // Input container click - prevent event from reaching document listener
3327
4052
  this._container.addEventListener('click', (e) => {
3328
4053
  e.stopPropagation();
@@ -3493,11 +4218,14 @@
3493
4218
  this._input.focus();
3494
4219
  this._markOpenStart();
3495
4220
  this._state.isOpen = true;
4221
+ this.setAttribute('data-open', 'true');
4222
+ this._liftStackingAncestors();
3496
4223
  this._dropdown.style.display = 'block';
3497
4224
  this._input.setAttribute('aria-expanded', 'true');
3498
4225
  this._updateArrowRotation();
3499
4226
  // Render options when opening
3500
4227
  this._renderOptions();
4228
+ this._syncDropdownPlacement();
3501
4229
  this._setInitialActiveOption();
3502
4230
  this._emit('open', {});
3503
4231
  this._config.callbacks.onOpen?.();
@@ -3517,7 +4245,10 @@
3517
4245
  if (!this._state.isOpen)
3518
4246
  return;
3519
4247
  this._state.isOpen = false;
4248
+ this.removeAttribute('data-open');
4249
+ this._restoreLiftedAncestors();
3520
4250
  this._dropdown.style.display = 'none';
4251
+ this._dropdown.setAttribute('data-placement', this._resolvedDropdownPlacement);
3521
4252
  this._input.setAttribute('aria-expanded', 'false');
3522
4253
  this._input.removeAttribute('aria-activedescendant');
3523
4254
  this._updateArrowRotation();
@@ -3527,14 +4258,76 @@
3527
4258
  }
3528
4259
  _updateDropdownVisibility() {
3529
4260
  if (this._state.isOpen) {
4261
+ this.setAttribute('data-open', 'true');
4262
+ this._liftStackingAncestors();
3530
4263
  this._dropdown.style.display = 'block';
4264
+ this._syncDropdownPlacement();
3531
4265
  this._input.setAttribute('aria-expanded', 'true');
3532
4266
  }
3533
4267
  else {
4268
+ this.removeAttribute('data-open');
4269
+ this._restoreLiftedAncestors();
3534
4270
  this._dropdown.style.display = 'none';
3535
4271
  this._input.setAttribute('aria-expanded', 'false');
3536
4272
  }
3537
4273
  }
4274
+ _liftStackingAncestors() {
4275
+ this._restoreLiftedAncestors();
4276
+ let ancestor = this.parentElement;
4277
+ while (ancestor && ancestor !== document.body) {
4278
+ if (this._createsStackingContext(ancestor)) {
4279
+ const hadMarker = ancestor.hasAttribute('data-smilodon-open-ancestor');
4280
+ this._liftedAncestors.push({
4281
+ element: ancestor,
4282
+ position: ancestor.style.position,
4283
+ zIndex: ancestor.style.zIndex,
4284
+ hadMarker,
4285
+ });
4286
+ if (getComputedStyle(ancestor).position === 'static') {
4287
+ ancestor.style.position = 'relative';
4288
+ }
4289
+ ancestor.style.zIndex = 'var(--select-ancestor-open-z-index, var(--select-host-open-z-index, var(--select-dropdown-z-index, 1000)))';
4290
+ ancestor.setAttribute('data-smilodon-open-ancestor', 'true');
4291
+ }
4292
+ ancestor = ancestor.parentElement;
4293
+ }
4294
+ }
4295
+ _restoreLiftedAncestors() {
4296
+ for (const lifted of this._liftedAncestors) {
4297
+ lifted.element.style.position = lifted.position;
4298
+ lifted.element.style.zIndex = lifted.zIndex;
4299
+ if (!lifted.hadMarker) {
4300
+ lifted.element.removeAttribute('data-smilodon-open-ancestor');
4301
+ }
4302
+ }
4303
+ this._liftedAncestors = [];
4304
+ }
4305
+ _createsStackingContext(element) {
4306
+ const style = getComputedStyle(element);
4307
+ if (style.position === 'fixed' || style.position === 'sticky')
4308
+ return true;
4309
+ if (style.zIndex !== 'auto' && style.position !== 'static')
4310
+ return true;
4311
+ if (style.opacity !== '1')
4312
+ return true;
4313
+ if (style.transform !== 'none')
4314
+ return true;
4315
+ if (style.filter !== 'none')
4316
+ return true;
4317
+ if (style.backdropFilter && style.backdropFilter !== 'none')
4318
+ return true;
4319
+ if (style.perspective !== 'none')
4320
+ return true;
4321
+ if (style.mixBlendMode !== 'normal')
4322
+ return true;
4323
+ if (style.isolation === 'isolate')
4324
+ return true;
4325
+ if (style.contain.includes('paint') || style.contain.includes('layout'))
4326
+ return true;
4327
+ if (style.willChange.includes('transform') || style.willChange.includes('opacity') || style.willChange.includes('filter'))
4328
+ return true;
4329
+ return false;
4330
+ }
3538
4331
  _updateArrowRotation() {
3539
4332
  if (this._arrowContainer) {
3540
4333
  const arrow = this._arrowContainer.querySelector('.dropdown-arrow');
@@ -4006,7 +4799,7 @@
4006
4799
  this._input.value = '';
4007
4800
  this._input.placeholder = this._config.placeholder || 'Select an option...';
4008
4801
  // Clear any badges
4009
- const existingBadges = this._inputContainer.querySelectorAll('.selection-badge');
4802
+ const existingBadges = this._inputContent.querySelectorAll('.selection-badge');
4010
4803
  existingBadges.forEach(badge => badge.remove());
4011
4804
  }
4012
4805
  else if (this._config.selection.mode === 'single') {
@@ -4017,16 +4810,23 @@
4017
4810
  this._input.value = '';
4018
4811
  this._input.placeholder = '';
4019
4812
  // Clear existing badges
4020
- const existingBadges = this._inputContainer.querySelectorAll('.selection-badge');
4813
+ const existingBadges = this._inputContent.querySelectorAll('.selection-badge');
4021
4814
  existingBadges.forEach(badge => badge.remove());
4022
4815
  // Create badges for each selected item
4023
4816
  const selectedEntries = Array.from(this._state.selectedItems.entries());
4024
4817
  selectedEntries.forEach(([index, item]) => {
4025
4818
  const badge = document.createElement('span');
4026
4819
  badge.className = 'selection-badge';
4820
+ if (this._config.styles.classNames?.badge) {
4821
+ badge.classList.add(...this._config.styles.classNames.badge.split(' ').filter(Boolean));
4822
+ }
4027
4823
  badge.setAttribute('part', 'chip');
4028
4824
  const badgeLabel = document.createElement('span');
4029
4825
  badgeLabel.className = 'selection-badge-label';
4826
+ if (this._config.styles.classNames?.badgeLabel) {
4827
+ badgeLabel.classList.add(...this._config.styles.classNames.badgeLabel.split(' ').filter(Boolean));
4828
+ }
4829
+ badgeLabel.setAttribute('part', 'chip-label');
4030
4830
  badgeLabel.textContent = getLabel(item);
4031
4831
  badge.appendChild(badgeLabel);
4032
4832
  // Add remove button to badge
@@ -4034,9 +4834,19 @@
4034
4834
  const removeBtn = document.createElement('button');
4035
4835
  removeBtn.type = 'button';
4036
4836
  removeBtn.className = 'badge-remove';
4837
+ if (this._config.styles.classNames?.removeButton) {
4838
+ removeBtn.classList.add(...this._config.styles.classNames.removeButton.split(' ').filter(Boolean));
4839
+ }
4840
+ if (this._config.styles.classNames?.badgeRemove) {
4841
+ removeBtn.classList.add(...this._config.styles.classNames.badgeRemove.split(' ').filter(Boolean));
4842
+ }
4037
4843
  removeBtn.setAttribute('part', 'chip-remove');
4038
- removeBtn.innerHTML = '×';
4039
4844
  removeBtn.setAttribute('aria-label', `Remove ${getLabel(item)}`);
4845
+ const removeIcon = document.createElement('span');
4846
+ removeIcon.className = 'badge-remove-icon';
4847
+ removeIcon.setAttribute('part', 'chip-remove-icon');
4848
+ this._setIconContent(removeIcon, this._config.selection.removeButtonIcon, '×');
4849
+ removeBtn.appendChild(removeIcon);
4040
4850
  removeBtn.addEventListener('pointerdown', (e) => {
4041
4851
  e.stopPropagation();
4042
4852
  e.preventDefault();
@@ -4048,7 +4858,7 @@
4048
4858
  });
4049
4859
  badge.appendChild(removeBtn);
4050
4860
  }
4051
- this._inputContainer.insertBefore(badge, this._input);
4861
+ this._inputContent.insertBefore(badge, this._input);
4052
4862
  });
4053
4863
  }
4054
4864
  this._syncClearControlState();
@@ -4521,6 +5331,7 @@
4521
5331
  if (this._clearControlIcon) {
4522
5332
  this._clearControlIcon.innerHTML = `<svg viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M12 4L4 12M4 4L12 12" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/></svg>`;
4523
5333
  }
5334
+ this._syncStyleConfigVariables();
4524
5335
  if (this._dropdown) {
4525
5336
  if (this._config.selection.mode === 'multi') {
4526
5337
  this._dropdown.setAttribute('aria-multiselectable', 'true');
@@ -4529,10 +5340,14 @@
4529
5340
  this._dropdown.removeAttribute('aria-multiselectable');
4530
5341
  }
4531
5342
  }
5343
+ this._syncDirectionConfig();
4532
5344
  this._syncInputContainerMode();
5345
+ this._syncMultiSelectDisplayConfig();
5346
+ this._syncDropdownPlacement();
4533
5347
  // Re-initialize observers in case infinite scroll was enabled/disabled
4534
5348
  this._initializeObservers();
4535
5349
  this._syncClearControlState();
5350
+ this._updateInputDisplay();
4536
5351
  this._renderOptions();
4537
5352
  }
4538
5353
  _mergeConfig(target, source) {
@@ -4688,6 +5503,9 @@
4688
5503
  header.textContent = group.label;
4689
5504
  }
4690
5505
  header.classList.add('group-header');
5506
+ if (this._config.styles.classNames?.groupHeader) {
5507
+ header.classList.add(...this._config.styles.classNames.groupHeader.split(' ').filter(Boolean));
5508
+ }
4691
5509
  header.setAttribute('part', 'group-header');
4692
5510
  this._optionsContainer.appendChild(header);
4693
5511
  group.options.forEach(item => {
@@ -4815,6 +5633,7 @@
4815
5633
  disabled: isDisabled,
4816
5634
  id: optionId,
4817
5635
  });
5636
+ optionElement.setAttribute('dir', this._config.direction ?? 'ltr');
4818
5637
  targetContainer.appendChild(optionElement);
4819
5638
  return;
4820
5639
  }
@@ -4828,8 +5647,23 @@
4828
5647
  getValue,
4829
5648
  getLabel,
4830
5649
  showRemoveButton: this._config.selection.mode === 'multi' && this._config.selection.showRemoveButton,
5650
+ removeButtonIcon: this._config.selection.removeButtonIcon,
4831
5651
  classMap: this.classMap,
5652
+ className: this._config.styles.classNames?.option,
4832
5653
  });
5654
+ if (this._config.styles.classNames?.option) {
5655
+ option.classList.add(...this._config.styles.classNames.option.split(' ').filter(Boolean));
5656
+ }
5657
+ option.setAttribute('dir', this._config.direction ?? 'ltr');
5658
+ if (isSelected && this._config.styles.classNames?.selectedOption) {
5659
+ option.classList.add(...this._config.styles.classNames.selectedOption.split(' ').filter(Boolean));
5660
+ }
5661
+ if (this._state.activeIndex === index && this._config.styles.classNames?.activeOption) {
5662
+ option.classList.add(...this._config.styles.classNames.activeOption.split(' ').filter(Boolean));
5663
+ }
5664
+ if (isDisabled && this._config.styles.classNames?.disabledOption) {
5665
+ option.classList.add(...this._config.styles.classNames.disabledOption.split(' ').filter(Boolean));
5666
+ }
4833
5667
  // Valid part attribute on the web component host itself
4834
5668
  option.setAttribute('part', 'option');
4835
5669
  option.dataset.index = String(index);
@@ -4863,6 +5697,9 @@
4863
5697
  }
4864
5698
  // Add both semantic namespaced classes and the legacy internal classes that CSS uses
4865
5699
  optionEl.classList.add('smilodon-option', 'option');
5700
+ if (this._config.styles.classNames?.option) {
5701
+ optionEl.classList.add(...this._config.styles.classNames.option.split(' ').filter(Boolean));
5702
+ }
4866
5703
  // Toggle state classes using classMap if available
4867
5704
  const isSelected = meta.selected;
4868
5705
  const isActive = meta.active;
@@ -4874,26 +5711,44 @@
4874
5711
  if (isSelected) {
4875
5712
  optionEl.classList.add(...selectedClasses);
4876
5713
  optionEl.classList.add('smilodon-option--selected');
5714
+ if (this._config.styles.classNames?.selectedOption) {
5715
+ optionEl.classList.add(...this._config.styles.classNames.selectedOption.split(' ').filter(Boolean));
5716
+ }
4877
5717
  }
4878
5718
  else {
4879
5719
  optionEl.classList.remove(...selectedClasses);
4880
5720
  optionEl.classList.remove('smilodon-option--selected');
5721
+ if (this._config.styles.classNames?.selectedOption) {
5722
+ optionEl.classList.remove(...this._config.styles.classNames.selectedOption.split(' ').filter(Boolean));
5723
+ }
4881
5724
  }
4882
5725
  if (isActive) {
4883
5726
  optionEl.classList.add(...activeClasses);
4884
5727
  optionEl.classList.add('smilodon-option--active');
5728
+ if (this._config.styles.classNames?.activeOption) {
5729
+ optionEl.classList.add(...this._config.styles.classNames.activeOption.split(' ').filter(Boolean));
5730
+ }
4885
5731
  }
4886
5732
  else {
4887
5733
  optionEl.classList.remove(...activeClasses);
4888
5734
  optionEl.classList.remove('smilodon-option--active');
5735
+ if (this._config.styles.classNames?.activeOption) {
5736
+ optionEl.classList.remove(...this._config.styles.classNames.activeOption.split(' ').filter(Boolean));
5737
+ }
4889
5738
  }
4890
5739
  if (isDisabled) {
4891
5740
  optionEl.classList.add(...disabledClasses);
4892
5741
  optionEl.classList.add('smilodon-option--disabled');
5742
+ if (this._config.styles.classNames?.disabledOption) {
5743
+ optionEl.classList.add(...this._config.styles.classNames.disabledOption.split(' ').filter(Boolean));
5744
+ }
4893
5745
  }
4894
5746
  else {
4895
5747
  optionEl.classList.remove(...disabledClasses);
4896
5748
  optionEl.classList.remove('smilodon-option--disabled');
5749
+ if (this._config.styles.classNames?.disabledOption) {
5750
+ optionEl.classList.remove(...this._config.styles.classNames.disabledOption.split(' ').filter(Boolean));
5751
+ }
4897
5752
  }
4898
5753
  // Data Attributes Contract
4899
5754
  const state = [];