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