@smilodon/core 1.4.11 → 1.4.12
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.cjs +208 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +208 -1
- 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 +208 -1
- 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 +11 -1
- package/dist/types/src/config/global-config.d.ts +25 -0
- package/dist/types/src/types.d.ts +58 -0
- package/dist/types/tests/capabilities-tracking.spec.d.ts +1 -0
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -1403,6 +1403,18 @@ const defaultConfig = {
|
|
|
1403
1403
|
icon: '×',
|
|
1404
1404
|
},
|
|
1405
1405
|
callbacks: {},
|
|
1406
|
+
tracking: {
|
|
1407
|
+
enabled: false,
|
|
1408
|
+
events: true,
|
|
1409
|
+
styling: true,
|
|
1410
|
+
limitations: true,
|
|
1411
|
+
emitDiagnostics: false,
|
|
1412
|
+
maxEntries: 200,
|
|
1413
|
+
},
|
|
1414
|
+
limitations: {
|
|
1415
|
+
policies: {},
|
|
1416
|
+
autoMitigateRuntimeModeSwitch: true,
|
|
1417
|
+
},
|
|
1406
1418
|
enabled: true,
|
|
1407
1419
|
searchable: false,
|
|
1408
1420
|
placeholder: 'Select an option...',
|
|
@@ -1879,6 +1891,10 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1879
1891
|
set classMap(map) {
|
|
1880
1892
|
this._classMap = map;
|
|
1881
1893
|
this._setGlobalStylesMirroring(Boolean(this._optionRenderer || map || this._groupHeaderRenderer));
|
|
1894
|
+
this._track('style', 'classMapChanged', {
|
|
1895
|
+
hasClassMap: Boolean(map),
|
|
1896
|
+
keys: map ? Object.keys(map) : [],
|
|
1897
|
+
});
|
|
1882
1898
|
if (!this.isConnected)
|
|
1883
1899
|
return;
|
|
1884
1900
|
this._renderOptions();
|
|
@@ -1894,6 +1910,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1894
1910
|
set groupHeaderRenderer(renderer) {
|
|
1895
1911
|
this._groupHeaderRenderer = renderer;
|
|
1896
1912
|
this._setGlobalStylesMirroring(Boolean(this._optionRenderer || this._classMap || renderer));
|
|
1913
|
+
this._track('style', 'groupHeaderRendererChanged', { enabled: Boolean(renderer) });
|
|
1897
1914
|
if (!this.isConnected)
|
|
1898
1915
|
return;
|
|
1899
1916
|
this._renderOptions();
|
|
@@ -1912,6 +1929,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1912
1929
|
this._mirrorGlobalStylesForCustomOptions = false;
|
|
1913
1930
|
this._globalStylesObserver = null;
|
|
1914
1931
|
this._globalStylesContainer = null;
|
|
1932
|
+
this._tracking = { events: [], styles: [], limitations: [] };
|
|
1915
1933
|
this._shadow = this.attachShadow({ mode: 'open' });
|
|
1916
1934
|
this._uniqueId = `enhanced-select-${Math.random().toString(36).substr(2, 9)}`;
|
|
1917
1935
|
this._rendererHelpers = this._buildRendererHelpers();
|
|
@@ -1996,6 +2014,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
1996
2014
|
return;
|
|
1997
2015
|
}
|
|
1998
2016
|
this._mirrorGlobalStylesForCustomOptions = enabled;
|
|
2017
|
+
this._track('style', 'globalStylesMirroringChanged', { enabled });
|
|
1999
2018
|
if (enabled) {
|
|
2000
2019
|
this._setupGlobalStylesMirroring();
|
|
2001
2020
|
}
|
|
@@ -3676,6 +3695,162 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3676
3695
|
}
|
|
3677
3696
|
_emit(name, detail) {
|
|
3678
3697
|
this.dispatchEvent(new CustomEvent(name, { detail, bubbles: true, composed: true }));
|
|
3698
|
+
if (name !== 'diagnostic') {
|
|
3699
|
+
this._track('event', String(name), detail);
|
|
3700
|
+
}
|
|
3701
|
+
}
|
|
3702
|
+
_track(source, name, detail) {
|
|
3703
|
+
const cfg = this._config.tracking;
|
|
3704
|
+
if (!cfg?.enabled)
|
|
3705
|
+
return;
|
|
3706
|
+
if (source === 'event' && !cfg.events)
|
|
3707
|
+
return;
|
|
3708
|
+
if (source === 'style' && !cfg.styling)
|
|
3709
|
+
return;
|
|
3710
|
+
if (source === 'limitation' && !cfg.limitations)
|
|
3711
|
+
return;
|
|
3712
|
+
const entry = {
|
|
3713
|
+
timestamp: Date.now(),
|
|
3714
|
+
source,
|
|
3715
|
+
name,
|
|
3716
|
+
detail,
|
|
3717
|
+
};
|
|
3718
|
+
const bucket = source === 'event'
|
|
3719
|
+
? this._tracking.events
|
|
3720
|
+
: source === 'style'
|
|
3721
|
+
? this._tracking.styles
|
|
3722
|
+
: this._tracking.limitations;
|
|
3723
|
+
bucket.push(entry);
|
|
3724
|
+
const maxEntries = Math.max(10, cfg.maxEntries || 200);
|
|
3725
|
+
if (bucket.length > maxEntries) {
|
|
3726
|
+
bucket.splice(0, bucket.length - maxEntries);
|
|
3727
|
+
}
|
|
3728
|
+
if (cfg.emitDiagnostics) {
|
|
3729
|
+
this.dispatchEvent(new CustomEvent('diagnostic', {
|
|
3730
|
+
detail: entry,
|
|
3731
|
+
bubbles: true,
|
|
3732
|
+
composed: true,
|
|
3733
|
+
}));
|
|
3734
|
+
}
|
|
3735
|
+
}
|
|
3736
|
+
_getKnownLimitationDefinitions() {
|
|
3737
|
+
return [
|
|
3738
|
+
{
|
|
3739
|
+
id: 'variableItemHeight',
|
|
3740
|
+
title: 'Variable item height',
|
|
3741
|
+
description: 'Virtualization assumes fixed or estimated item heights; fully dynamic heights are not yet supported.',
|
|
3742
|
+
workaround: 'Use consistent item heights or set estimatedItemHeight to your dominant row size.',
|
|
3743
|
+
},
|
|
3744
|
+
{
|
|
3745
|
+
id: 'builtInFetchPaginationApi',
|
|
3746
|
+
title: 'Built-in fetch/pagination API',
|
|
3747
|
+
description: 'Core does not include a built-in fetchUrl/searchUrl pagination transport.',
|
|
3748
|
+
workaround: 'Use onSearch/onLoadMore callbacks and update data via setItems().',
|
|
3749
|
+
},
|
|
3750
|
+
{
|
|
3751
|
+
id: 'virtualizationOverheadSmallLists',
|
|
3752
|
+
title: 'Virtualization overhead for small lists',
|
|
3753
|
+
description: 'Virtualization can add slight overhead on very small lists.',
|
|
3754
|
+
workaround: 'Disable virtualization for tiny datasets when micro-latency is critical.',
|
|
3755
|
+
},
|
|
3756
|
+
{
|
|
3757
|
+
id: 'runtimeModeSwitching',
|
|
3758
|
+
title: 'Runtime single/multi mode switching',
|
|
3759
|
+
description: 'Switching between single and multi mode can require state reset for consistency.',
|
|
3760
|
+
workaround: 'Enable autoMitigateRuntimeModeSwitch or recreate/reset component state when toggling modes.',
|
|
3761
|
+
},
|
|
3762
|
+
{
|
|
3763
|
+
id: 'legacyBrowserSupport',
|
|
3764
|
+
title: 'Legacy browser support',
|
|
3765
|
+
description: 'Official support targets modern evergreen browsers.',
|
|
3766
|
+
},
|
|
3767
|
+
{
|
|
3768
|
+
id: 'webkitArchLinux',
|
|
3769
|
+
title: 'Playwright WebKit on Arch-based Linux',
|
|
3770
|
+
description: 'Native WebKit Playwright bundle depends on unavailable legacy system libraries on Arch-based distros.',
|
|
3771
|
+
workaround: 'Run WebKit E2E tests via Playwright Docker image.',
|
|
3772
|
+
},
|
|
3773
|
+
];
|
|
3774
|
+
}
|
|
3775
|
+
_evaluateLimitationStatus(id) {
|
|
3776
|
+
const policyMode = this._config.limitations?.policies?.[id]?.mode ?? 'default';
|
|
3777
|
+
if (policyMode === 'suppress')
|
|
3778
|
+
return 'suppressed';
|
|
3779
|
+
if (id === 'runtimeModeSwitching' && this._config.limitations?.autoMitigateRuntimeModeSwitch) {
|
|
3780
|
+
return 'mitigated';
|
|
3781
|
+
}
|
|
3782
|
+
return 'active';
|
|
3783
|
+
}
|
|
3784
|
+
getKnownLimitations() {
|
|
3785
|
+
return this._getKnownLimitationDefinitions().map((limitation) => {
|
|
3786
|
+
const mode = this._config.limitations?.policies?.[limitation.id]?.mode ?? 'default';
|
|
3787
|
+
return {
|
|
3788
|
+
...limitation,
|
|
3789
|
+
mode,
|
|
3790
|
+
status: this._evaluateLimitationStatus(limitation.id),
|
|
3791
|
+
};
|
|
3792
|
+
});
|
|
3793
|
+
}
|
|
3794
|
+
setLimitationPolicies(policies) {
|
|
3795
|
+
const next = {
|
|
3796
|
+
...(this._config.limitations?.policies || {}),
|
|
3797
|
+
...policies,
|
|
3798
|
+
};
|
|
3799
|
+
this.updateConfig({
|
|
3800
|
+
limitations: {
|
|
3801
|
+
...(this._config.limitations || { autoMitigateRuntimeModeSwitch: true, policies: {} }),
|
|
3802
|
+
policies: next,
|
|
3803
|
+
},
|
|
3804
|
+
});
|
|
3805
|
+
this._track('limitation', 'policiesUpdated', { policies: next });
|
|
3806
|
+
}
|
|
3807
|
+
getTrackingSnapshot() {
|
|
3808
|
+
return {
|
|
3809
|
+
events: [...this._tracking.events],
|
|
3810
|
+
styles: [...this._tracking.styles],
|
|
3811
|
+
limitations: [...this._tracking.limitations],
|
|
3812
|
+
};
|
|
3813
|
+
}
|
|
3814
|
+
clearTracking(source) {
|
|
3815
|
+
if (!source || source === 'all') {
|
|
3816
|
+
this._tracking.events = [];
|
|
3817
|
+
this._tracking.styles = [];
|
|
3818
|
+
this._tracking.limitations = [];
|
|
3819
|
+
return;
|
|
3820
|
+
}
|
|
3821
|
+
if (source === 'event')
|
|
3822
|
+
this._tracking.events = [];
|
|
3823
|
+
if (source === 'style')
|
|
3824
|
+
this._tracking.styles = [];
|
|
3825
|
+
if (source === 'limitation')
|
|
3826
|
+
this._tracking.limitations = [];
|
|
3827
|
+
}
|
|
3828
|
+
getCapabilities() {
|
|
3829
|
+
return {
|
|
3830
|
+
styling: {
|
|
3831
|
+
classMap: true,
|
|
3832
|
+
optionRenderer: true,
|
|
3833
|
+
groupHeaderRenderer: true,
|
|
3834
|
+
cssCustomProperties: true,
|
|
3835
|
+
shadowParts: true,
|
|
3836
|
+
globalStyleMirroring: true,
|
|
3837
|
+
},
|
|
3838
|
+
events: {
|
|
3839
|
+
emitted: ['select', 'open', 'close', 'search', 'change', 'loadMore', 'remove', 'clear', 'error', 'diagnostic'],
|
|
3840
|
+
diagnosticEvent: true,
|
|
3841
|
+
},
|
|
3842
|
+
functionality: {
|
|
3843
|
+
multiSelect: true,
|
|
3844
|
+
searchable: true,
|
|
3845
|
+
infiniteScroll: true,
|
|
3846
|
+
loadMore: true,
|
|
3847
|
+
clearControl: true,
|
|
3848
|
+
groupedItems: true,
|
|
3849
|
+
serverSideSelection: true,
|
|
3850
|
+
runtimeModeSwitchMitigation: Boolean(this._config.limitations?.autoMitigateRuntimeModeSwitch),
|
|
3851
|
+
},
|
|
3852
|
+
limitations: this.getKnownLimitations(),
|
|
3853
|
+
};
|
|
3679
3854
|
}
|
|
3680
3855
|
_emitChange() {
|
|
3681
3856
|
const selectedItems = Array.from(this._state.selectedItems.values());
|
|
@@ -3693,6 +3868,7 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3693
3868
|
set optionRenderer(renderer) {
|
|
3694
3869
|
this._optionRenderer = renderer;
|
|
3695
3870
|
this._setGlobalStylesMirroring(Boolean(renderer || this._classMap));
|
|
3871
|
+
this._track('style', 'optionRendererChanged', { enabled: Boolean(renderer) });
|
|
3696
3872
|
this._renderOptions();
|
|
3697
3873
|
}
|
|
3698
3874
|
/**
|
|
@@ -3857,7 +4033,22 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3857
4033
|
* Update component configuration
|
|
3858
4034
|
*/
|
|
3859
4035
|
updateConfig(config) {
|
|
3860
|
-
|
|
4036
|
+
const previousMode = this._config.selection.mode;
|
|
4037
|
+
this._config = this._mergeConfig(this._config, config);
|
|
4038
|
+
if (previousMode !== this._config.selection.mode &&
|
|
4039
|
+
this._config.limitations?.autoMitigateRuntimeModeSwitch) {
|
|
4040
|
+
this.clear();
|
|
4041
|
+
this._track('limitation', 'runtimeModeSwitchMitigated', {
|
|
4042
|
+
from: previousMode,
|
|
4043
|
+
to: this._config.selection.mode,
|
|
4044
|
+
});
|
|
4045
|
+
}
|
|
4046
|
+
else if (previousMode !== this._config.selection.mode) {
|
|
4047
|
+
this._track('limitation', 'runtimeModeSwitchDetected', {
|
|
4048
|
+
from: previousMode,
|
|
4049
|
+
to: this._config.selection.mode,
|
|
4050
|
+
});
|
|
4051
|
+
}
|
|
3861
4052
|
// Update input state based on new config
|
|
3862
4053
|
if (this._input) {
|
|
3863
4054
|
this._input.readOnly = !this._config.searchable;
|
|
@@ -3885,6 +4076,22 @@ class EnhancedSelect extends HTMLElement {
|
|
|
3885
4076
|
this._syncClearControlState();
|
|
3886
4077
|
this._renderOptions();
|
|
3887
4078
|
}
|
|
4079
|
+
_mergeConfig(target, source) {
|
|
4080
|
+
const result = { ...target };
|
|
4081
|
+
for (const key in source) {
|
|
4082
|
+
if (!Object.prototype.hasOwnProperty.call(source, key))
|
|
4083
|
+
continue;
|
|
4084
|
+
const sourceValue = source[key];
|
|
4085
|
+
const targetValue = result[key];
|
|
4086
|
+
if (sourceValue && typeof sourceValue === 'object' && !Array.isArray(sourceValue)) {
|
|
4087
|
+
result[key] = this._mergeConfig(targetValue && typeof targetValue === 'object' ? targetValue : {}, sourceValue);
|
|
4088
|
+
}
|
|
4089
|
+
else {
|
|
4090
|
+
result[key] = sourceValue;
|
|
4091
|
+
}
|
|
4092
|
+
}
|
|
4093
|
+
return result;
|
|
4094
|
+
}
|
|
3888
4095
|
_handleClearControlClick() {
|
|
3889
4096
|
const shouldClearSelection = this._config.clearControl.clearSelection !== false;
|
|
3890
4097
|
const shouldClearSearch = this._config.clearControl.clearSearch !== false;
|