@smilodon/core 1.4.9 → 1.4.10
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 +28 -0
- package/dist/index.cjs +78 -19
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +78 -19
- 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 +78 -19
- 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 +10 -0
- package/dist/types/src/types.d.ts +5 -0
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1873,7 +1873,22 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1873
1873
|
}
|
|
1874
1874
|
set classMap(map) {
|
|
1875
1875
|
this._classMap = map;
|
|
1876
|
-
this._setGlobalStylesMirroring(Boolean(this._optionRenderer || map));
|
|
1876
|
+
this._setGlobalStylesMirroring(Boolean(this._optionRenderer || map || this._groupHeaderRenderer));
|
|
1877
|
+
if (!this.isConnected)
|
|
1878
|
+
return;
|
|
1879
|
+
this._renderOptions();
|
|
1880
|
+
}
|
|
1881
|
+
/**
|
|
1882
|
+
* DOM-based renderer for group headers. When provided, the component will
|
|
1883
|
+
* call this function for each group during rendering. The returned element
|
|
1884
|
+
* will receive `.group-header` and `part="group-header"` automatically.
|
|
1885
|
+
*/
|
|
1886
|
+
get groupHeaderRenderer() {
|
|
1887
|
+
return this._groupHeaderRenderer;
|
|
1888
|
+
}
|
|
1889
|
+
set groupHeaderRenderer(renderer) {
|
|
1890
|
+
this._groupHeaderRenderer = renderer;
|
|
1891
|
+
this._setGlobalStylesMirroring(Boolean(this._optionRenderer || this._classMap || renderer));
|
|
1877
1892
|
if (!this.isConnected)
|
|
1878
1893
|
return;
|
|
1879
1894
|
this._renderOptions();
|
|
@@ -1932,6 +1947,8 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1932
1947
|
this._initializeObservers();
|
|
1933
1948
|
}
|
|
1934
1949
|
connectedCallback() {
|
|
1950
|
+
// register instance
|
|
1951
|
+
EnhancedSelect._instances.add(this);
|
|
1935
1952
|
// WORKAROUND: Force display style on host element for Angular compatibility
|
|
1936
1953
|
// Angular's rendering seems to not apply :host styles correctly in some cases
|
|
1937
1954
|
// Must be done in connectedCallback when element is attached to DOM
|
|
@@ -1950,6 +1967,8 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1950
1967
|
}
|
|
1951
1968
|
}
|
|
1952
1969
|
disconnectedCallback() {
|
|
1970
|
+
// unregister instance
|
|
1971
|
+
EnhancedSelect._instances.delete(this);
|
|
1953
1972
|
// Cleanup observers
|
|
1954
1973
|
this._resizeObserver?.disconnect();
|
|
1955
1974
|
this._intersectionObserver?.disconnect();
|
|
@@ -2235,6 +2254,8 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2235
2254
|
right: 0;
|
|
2236
2255
|
bottom: 0;
|
|
2237
2256
|
width: var(--select-arrow-width, 40px);
|
|
2257
|
+
/* allow explicit height override even though container normally stretches */
|
|
2258
|
+
height: var(--select-arrow-height, auto);
|
|
2238
2259
|
display: flex;
|
|
2239
2260
|
align-items: center;
|
|
2240
2261
|
justify-content: center;
|
|
@@ -2300,9 +2321,14 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2300
2321
|
background-color: var(--select-arrow-hover-bg, rgba(102, 126, 234, 0.08));
|
|
2301
2322
|
}
|
|
2302
2323
|
|
|
2324
|
+
.dropdown-arrow:hover {
|
|
2325
|
+
/* legacy alias --select-arrow-hover for icon color */
|
|
2326
|
+
color: var(--select-arrow-hover, var(--select-arrow-hover-color, #667eea));
|
|
2327
|
+
}
|
|
2328
|
+
|
|
2303
2329
|
.dropdown-arrow {
|
|
2304
|
-
width: var(--select-arrow-size, 16px);
|
|
2305
|
-
height: var(--select-arrow-size, 16px);
|
|
2330
|
+
width: var(--select-arrow-width, var(--select-arrow-size, 16px));
|
|
2331
|
+
height: var(--select-arrow-height, var(--select-arrow-size, 16px));
|
|
2306
2332
|
color: var(--select-arrow-color, #667eea);
|
|
2307
2333
|
transition: transform 0.2s ease, color 0.2s ease;
|
|
2308
2334
|
transform: translateY(0);
|
|
@@ -2656,6 +2682,13 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2656
2682
|
|
|
2657
2683
|
.option.active:not(.selected) {
|
|
2658
2684
|
background-color: var(--select-dark-option-active-bg, #374151);
|
|
2685
|
+
}
|
|
2686
|
+
|
|
2687
|
+
/* Group header in dark mode */
|
|
2688
|
+
.group-header {
|
|
2689
|
+
color: var(--select-dark-group-header-color, var(--select-group-header-color, #6b7280));
|
|
2690
|
+
background-color: var(--select-dark-group-header-bg, var(--select-group-header-bg, #374151));
|
|
2691
|
+
}
|
|
2659
2692
|
color: var(--select-dark-option-active-color, #f9fafb);
|
|
2660
2693
|
outline: var(--select-dark-option-active-outline, 2px solid rgba(129, 140, 248, 0.55));
|
|
2661
2694
|
}
|
|
@@ -2738,19 +2771,14 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2738
2771
|
this._boundArrowClick = (e) => {
|
|
2739
2772
|
e.stopPropagation();
|
|
2740
2773
|
e.preventDefault();
|
|
2741
|
-
|
|
2742
|
-
|
|
2743
|
-
|
|
2744
|
-
this.
|
|
2745
|
-
|
|
2746
|
-
this._config.callbacks.onOpen();
|
|
2747
|
-
}
|
|
2748
|
-
else if (!this._state.isOpen && this._config.callbacks.onClose) {
|
|
2749
|
-
this._config.callbacks.onClose();
|
|
2774
|
+
// delegate to the existing open/close helpers so we don't accidentally
|
|
2775
|
+
// drift out of sync with the logic in those methods (focus, events,
|
|
2776
|
+
// scroll-to-selected, etc.)
|
|
2777
|
+
if (this._state.isOpen) {
|
|
2778
|
+
this._handleClose();
|
|
2750
2779
|
}
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
setTimeout(() => this._scrollToSelected(), 50);
|
|
2780
|
+
else {
|
|
2781
|
+
this._handleOpen();
|
|
2754
2782
|
}
|
|
2755
2783
|
};
|
|
2756
2784
|
this._arrowContainer.addEventListener('click', this._boundArrowClick);
|
|
@@ -2784,6 +2812,10 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2784
2812
|
if (wasClosed) {
|
|
2785
2813
|
this._handleOpen();
|
|
2786
2814
|
}
|
|
2815
|
+
else {
|
|
2816
|
+
// clicking the input while open should close the dropdown too
|
|
2817
|
+
this._handleClose();
|
|
2818
|
+
}
|
|
2787
2819
|
// Focus the input (do not prevent default behavior)
|
|
2788
2820
|
this._input.focus();
|
|
2789
2821
|
// If we just opened the dropdown, transfer pointer capture to the
|
|
@@ -2959,6 +2991,16 @@ class EnhancedSelect extends HTMLElement {
|
|
|
2959
2991
|
_handleOpen() {
|
|
2960
2992
|
if (!this._config.enabled || this._state.isOpen)
|
|
2961
2993
|
return;
|
|
2994
|
+
// close any other open selects before proceeding
|
|
2995
|
+
EnhancedSelect._instances.forEach(inst => {
|
|
2996
|
+
if (inst !== this)
|
|
2997
|
+
inst._handleClose();
|
|
2998
|
+
});
|
|
2999
|
+
// Always focus the input when opening so callers (arrow click,
|
|
3000
|
+
// programmatic `open()`, etc.) get the keyboard cursor. This was a
|
|
3001
|
+
// frequent source of confusion in #14 where people opened the dropdown
|
|
3002
|
+
// but the text field never received focus.
|
|
3003
|
+
this._input.focus();
|
|
2962
3004
|
this._markOpenStart();
|
|
2963
3005
|
this._state.isOpen = true;
|
|
2964
3006
|
this._dropdown.style.display = 'block';
|
|
@@ -3932,10 +3974,25 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3932
3974
|
const query = this._state.searchQuery.toLowerCase();
|
|
3933
3975
|
// Handle Grouped Items Rendering (when no search query)
|
|
3934
3976
|
if (this._state.groupedItems.length > 0 && !query) {
|
|
3935
|
-
this._state.groupedItems.forEach(group => {
|
|
3936
|
-
|
|
3937
|
-
|
|
3938
|
-
|
|
3977
|
+
this._state.groupedItems.forEach((group, groupIndex) => {
|
|
3978
|
+
let header;
|
|
3979
|
+
if (this.groupHeaderRenderer) {
|
|
3980
|
+
header = this.groupHeaderRenderer(group, groupIndex);
|
|
3981
|
+
// make sure the returned element has the correct semantics so
|
|
3982
|
+
// people can style it. we add the class/part even if the renderer
|
|
3983
|
+
// returned something else to ensure backward compatibility.
|
|
3984
|
+
if (!(header instanceof HTMLElement)) {
|
|
3985
|
+
// fall back to default if API is misused
|
|
3986
|
+
header = document.createElement('div');
|
|
3987
|
+
header.textContent = String(group.label);
|
|
3988
|
+
}
|
|
3989
|
+
}
|
|
3990
|
+
else {
|
|
3991
|
+
header = document.createElement('div');
|
|
3992
|
+
header.textContent = group.label;
|
|
3993
|
+
}
|
|
3994
|
+
header.classList.add('group-header');
|
|
3995
|
+
header.setAttribute('part', 'group-header');
|
|
3939
3996
|
this._optionsContainer.appendChild(header);
|
|
3940
3997
|
group.options.forEach(item => {
|
|
3941
3998
|
// Find original index for correct ID generation and selection
|
|
@@ -4208,6 +4265,8 @@ class EnhancedSelect extends HTMLElement {
|
|
|
4208
4265
|
}
|
|
4209
4266
|
}
|
|
4210
4267
|
}
|
|
4268
|
+
/** live set of all connected instances; used to auto-close siblings */
|
|
4269
|
+
EnhancedSelect._instances = new Set();
|
|
4211
4270
|
// Register custom element
|
|
4212
4271
|
if (!customElements.get('enhanced-select')) {
|
|
4213
4272
|
customElements.define('enhanced-select', EnhancedSelect);
|