@smilodon/core 1.1.9 → 1.2.1
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 +14 -5
- package/dist/index.cjs +540 -940
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +539 -940
- 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 +540 -940
- 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 +2 -0
- package/dist/types/src/components/native-select.d.ts +19 -0
- package/dist/types/src/index.d.ts +3 -1
- package/dist/types/src/types/custom-option.d.ts +135 -0
- package/dist/types/src/utils/custom-option-pool.d.ts +78 -0
- package/dist/types/src/utils/option-renderer.d.ts +76 -0
- package/package.json +1 -1
|
@@ -29,6 +29,7 @@ export declare class EnhancedSelect extends HTMLElement {
|
|
|
29
29
|
private _errorMessage;
|
|
30
30
|
private _boundArrowClick;
|
|
31
31
|
private _arrowContainer?;
|
|
32
|
+
private _optionRenderer?;
|
|
32
33
|
constructor();
|
|
33
34
|
connectedCallback(): void;
|
|
34
35
|
disconnectedCallback(): void;
|
|
@@ -43,6 +44,7 @@ export declare class EnhancedSelect extends HTMLElement {
|
|
|
43
44
|
private _initializeStyles;
|
|
44
45
|
private _attachEventListeners;
|
|
45
46
|
private _initializeObservers;
|
|
47
|
+
private _initializeOptionRenderer;
|
|
46
48
|
private _loadInitialSelectedItems;
|
|
47
49
|
private _handleOpen;
|
|
48
50
|
private _handleClose;
|
|
@@ -26,6 +26,25 @@ export declare class NativeSelectElement extends HTMLElement {
|
|
|
26
26
|
get selectedItems(): unknown[];
|
|
27
27
|
set optionTemplate(template: OptionTemplate | undefined);
|
|
28
28
|
set optionRenderer(renderer: OptionRenderer | undefined);
|
|
29
|
+
/**
|
|
30
|
+
* Public API: setItems() method for compatibility with EnhancedSelect
|
|
31
|
+
* Accepts an array of items which can be:
|
|
32
|
+
* - Simple primitives (string, number)
|
|
33
|
+
* - Objects with {label, value} structure
|
|
34
|
+
* - Objects with {label, value, optionComponent} for custom rendering (v1.2.0+)
|
|
35
|
+
*/
|
|
36
|
+
setItems(items: unknown[]): void;
|
|
37
|
+
/**
|
|
38
|
+
* Public API: setValue() method to programmatically select an item
|
|
39
|
+
* For single select: clears selection and selects the item matching the value
|
|
40
|
+
* For multi-select: adds to selection if not already selected
|
|
41
|
+
*/
|
|
42
|
+
setValue(value: unknown): void;
|
|
43
|
+
/**
|
|
44
|
+
* Public API: getValue() method to get currently selected value(s)
|
|
45
|
+
* Returns single value for single-select, array for multi-select
|
|
46
|
+
*/
|
|
47
|
+
getValue(): unknown | unknown[];
|
|
29
48
|
render(): void;
|
|
30
49
|
private _applyOptionAttrs;
|
|
31
50
|
private _applyAriaToAll;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export * from './types.js';
|
|
2
2
|
export type { SelectEventDetail, OpenEventDetail, CloseEventDetail, SearchEventDetail, ChangeEventDetail, LoadMoreEventDetail, RemoveEventDetail, ErrorEventDetail, PageLoadedEventDetail, GroupedItem, RemoteConfig, Placement, Strategy, NativeSelectOptions, RendererHelpers, SelectEventsDetailMap, SelectEventName } from './types.js';
|
|
3
|
+
export type { CustomOptionContract, CustomOptionContext, CustomOptionFactory, ExtendedSelectItem, OptionRendererMode, CustomOptionConfig, CustomOptionEvents } from './types/custom-option.js';
|
|
3
4
|
export * from './renderers/contracts.js';
|
|
4
5
|
export * from './components/native-select.js';
|
|
5
6
|
export * from './components/enhanced-select.js';
|
|
6
|
-
export { AngularEnhancedSelect } from './components/angular-enhanced-select.js';
|
|
7
7
|
export * from './components/select-option.js';
|
|
8
8
|
export * from './config/global-config.js';
|
|
9
9
|
export { FenwickTree } from './utils/fenwick-tree.js';
|
|
@@ -11,6 +11,8 @@ export { DOMPool } from './utils/dom-pool.js';
|
|
|
11
11
|
export { WorkerManager, getWorkerManager } from './utils/worker-manager.js';
|
|
12
12
|
export { PerformanceTelemetry, getTelemetry, measureAsync, measureSync } from './utils/telemetry.js';
|
|
13
13
|
export { Virtualizer } from './utils/virtualizer.js';
|
|
14
|
+
export { OptionRenderer } from './utils/option-renderer.js';
|
|
15
|
+
export { CustomOptionPool } from './utils/custom-option-pool.js';
|
|
14
16
|
export { setHTMLSanitizer, getHTMLSanitizer, sanitizeHTML, createElement, setCSSProperties, CSPFeatures, detectEnvironment, containsSuspiciousPatterns, escapeHTML, escapeAttribute, validateTemplate, createTextNode, setTextContent } from './utils/security.js';
|
|
15
17
|
export { applyClasses, toggleClass, setCustomProperties, getCustomProperty, removeCustomProperty, defaultTheme, applyDefaultTheme, shadowDOMStyles, injectShadowStyles, hasOverflowHiddenAncestor, warnCSPViolation } from './utils/csp-styles.js';
|
|
16
18
|
export type { HTMLSanitizer, EnvironmentCapabilities } from './utils/security.js';
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Option Rendering System
|
|
3
|
+
*
|
|
4
|
+
* This module provides types and contracts for rendering custom framework components
|
|
5
|
+
* as select options, enabling deep customization while maintaining performance and cohesion.
|
|
6
|
+
*/
|
|
7
|
+
/**
|
|
8
|
+
* Contract that custom option components must implement
|
|
9
|
+
*
|
|
10
|
+
* Custom components must expose these methods to integrate with the select system:
|
|
11
|
+
* - `mountOption()`: Called when the option is added to DOM
|
|
12
|
+
* - `unmountOption()`: Called when the option is removed from DOM
|
|
13
|
+
* - `updateSelected()`: Called when selection state changes
|
|
14
|
+
* - `getElement()`: Returns the root DOM element
|
|
15
|
+
*/
|
|
16
|
+
export interface CustomOptionContract {
|
|
17
|
+
/**
|
|
18
|
+
* Mount the component into the provided container
|
|
19
|
+
* @param container - The DOM element to mount into
|
|
20
|
+
* @param context - Context data including selection state and callbacks
|
|
21
|
+
*/
|
|
22
|
+
mountOption(container: HTMLElement, context: CustomOptionContext): void;
|
|
23
|
+
/**
|
|
24
|
+
* Unmount and cleanup the component
|
|
25
|
+
*/
|
|
26
|
+
unmountOption(): void;
|
|
27
|
+
/**
|
|
28
|
+
* Update the component when selection state changes
|
|
29
|
+
* @param selected - Whether this option is currently selected
|
|
30
|
+
*/
|
|
31
|
+
updateSelected(selected: boolean): void;
|
|
32
|
+
/**
|
|
33
|
+
* Get the root DOM element of the component
|
|
34
|
+
* @returns The root element that receives click events
|
|
35
|
+
*/
|
|
36
|
+
getElement(): HTMLElement;
|
|
37
|
+
/**
|
|
38
|
+
* Optional: Handle when the option becomes focused (keyboard navigation)
|
|
39
|
+
* @param focused - Whether this option has keyboard focus
|
|
40
|
+
*/
|
|
41
|
+
updateFocused?(focused: boolean): void;
|
|
42
|
+
/**
|
|
43
|
+
* Optional: Handle when the option becomes disabled
|
|
44
|
+
* @param disabled - Whether this option is disabled
|
|
45
|
+
*/
|
|
46
|
+
updateDisabled?(disabled: boolean): void;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Context provided to custom option components
|
|
50
|
+
*/
|
|
51
|
+
export interface CustomOptionContext {
|
|
52
|
+
/** The item data */
|
|
53
|
+
item: unknown;
|
|
54
|
+
/** The index of this option in the list */
|
|
55
|
+
index: number;
|
|
56
|
+
/** The value extracted from the item */
|
|
57
|
+
value: unknown;
|
|
58
|
+
/** The label extracted from the item */
|
|
59
|
+
label: string;
|
|
60
|
+
/** Whether this option is currently selected */
|
|
61
|
+
isSelected: boolean;
|
|
62
|
+
/** Whether this option currently has keyboard focus */
|
|
63
|
+
isFocused: boolean;
|
|
64
|
+
/** Whether the option is disabled */
|
|
65
|
+
isDisabled: boolean;
|
|
66
|
+
/** Callback to notify the select that this option was clicked */
|
|
67
|
+
onSelect: (index: number) => void;
|
|
68
|
+
/** Callback to notify custom events from the option */
|
|
69
|
+
onCustomEvent?: (eventName: string, data: unknown) => void;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Factory function signature for creating custom option instances
|
|
73
|
+
*
|
|
74
|
+
* @param item - The data item for this option
|
|
75
|
+
* @param index - The index in the list
|
|
76
|
+
* @returns A new instance implementing CustomOptionContract
|
|
77
|
+
*/
|
|
78
|
+
export type CustomOptionFactory = (item: unknown, index: number) => CustomOptionContract;
|
|
79
|
+
/**
|
|
80
|
+
* Extended item type supporting custom components
|
|
81
|
+
*
|
|
82
|
+
* Items can now include:
|
|
83
|
+
* - Traditional: { label: string, value: any }
|
|
84
|
+
* - Custom Component: { label: string, value: any, optionComponent: CustomOptionFactory }
|
|
85
|
+
*/
|
|
86
|
+
export interface ExtendedSelectItem {
|
|
87
|
+
/** Display label (still required for accessibility and fallback) */
|
|
88
|
+
label: string;
|
|
89
|
+
/** Value used for selection */
|
|
90
|
+
value: unknown;
|
|
91
|
+
/** Optional: Custom component factory for rendering this option */
|
|
92
|
+
optionComponent?: CustomOptionFactory;
|
|
93
|
+
/** Optional: Whether this option is disabled */
|
|
94
|
+
disabled?: boolean;
|
|
95
|
+
/** Any additional data */
|
|
96
|
+
[key: string]: unknown;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Renderer mode for the select component
|
|
100
|
+
*/
|
|
101
|
+
export type OptionRendererMode = 'lightweight' | 'component';
|
|
102
|
+
/**
|
|
103
|
+
* Configuration for custom option rendering
|
|
104
|
+
*/
|
|
105
|
+
export interface CustomOptionConfig {
|
|
106
|
+
/** Default renderer mode when no component specified */
|
|
107
|
+
defaultMode: OptionRendererMode;
|
|
108
|
+
/** Enable performance optimizations for component rendering */
|
|
109
|
+
enableVirtualization: boolean;
|
|
110
|
+
/** Recycle component instances when scrolling (for large lists) */
|
|
111
|
+
enableComponentRecycling: boolean;
|
|
112
|
+
/** Maximum component instances to keep in pool */
|
|
113
|
+
maxComponentPoolSize: number;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Events emitted by custom option components
|
|
117
|
+
*/
|
|
118
|
+
export interface CustomOptionEvents {
|
|
119
|
+
/** Custom component emitted an event */
|
|
120
|
+
'option:custom-event': {
|
|
121
|
+
index: number;
|
|
122
|
+
eventName: string;
|
|
123
|
+
data: unknown;
|
|
124
|
+
};
|
|
125
|
+
/** Component failed to mount */
|
|
126
|
+
'option:mount-error': {
|
|
127
|
+
index: number;
|
|
128
|
+
error: Error;
|
|
129
|
+
};
|
|
130
|
+
/** Component lifecycle event for debugging */
|
|
131
|
+
'option:lifecycle': {
|
|
132
|
+
index: number;
|
|
133
|
+
phase: 'mount' | 'unmount' | 'update';
|
|
134
|
+
};
|
|
135
|
+
}
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom Option Component Pool
|
|
3
|
+
*
|
|
4
|
+
* Manages lifecycle and recycling of custom option components for optimal performance.
|
|
5
|
+
* Uses object pooling pattern to minimize allocation/deallocation overhead.
|
|
6
|
+
*/
|
|
7
|
+
import type { CustomOptionContract, CustomOptionContext, CustomOptionFactory } from '../types/custom-option';
|
|
8
|
+
/**
|
|
9
|
+
* Manages a pool of reusable custom option component instances
|
|
10
|
+
*/
|
|
11
|
+
export declare class CustomOptionPool {
|
|
12
|
+
private _pool;
|
|
13
|
+
private _maxPoolSize;
|
|
14
|
+
private _activeComponents;
|
|
15
|
+
constructor(maxPoolSize?: number);
|
|
16
|
+
/**
|
|
17
|
+
* Get or create a component instance for the given index
|
|
18
|
+
*
|
|
19
|
+
* @param factory - Factory function to create new instances
|
|
20
|
+
* @param item - The data item
|
|
21
|
+
* @param index - The option index
|
|
22
|
+
* @param context - Context for mounting
|
|
23
|
+
* @param container - DOM container for mounting
|
|
24
|
+
* @returns Component instance
|
|
25
|
+
*/
|
|
26
|
+
acquire(factory: CustomOptionFactory, item: unknown, index: number, context: CustomOptionContext, container: HTMLElement): CustomOptionContract;
|
|
27
|
+
/**
|
|
28
|
+
* Release a component back to the pool
|
|
29
|
+
*
|
|
30
|
+
* @param index - The index of the component to release
|
|
31
|
+
*/
|
|
32
|
+
release(index: number): void;
|
|
33
|
+
/**
|
|
34
|
+
* Release all active components
|
|
35
|
+
*/
|
|
36
|
+
releaseAll(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Update selection state for a component
|
|
39
|
+
*
|
|
40
|
+
* @param index - The index of the component
|
|
41
|
+
* @param selected - Whether it's selected
|
|
42
|
+
*/
|
|
43
|
+
updateSelection(index: number, selected: boolean): void;
|
|
44
|
+
/**
|
|
45
|
+
* Update focused state for a component
|
|
46
|
+
*
|
|
47
|
+
* @param index - The index of the component
|
|
48
|
+
* @param focused - Whether it has keyboard focus
|
|
49
|
+
*/
|
|
50
|
+
updateFocused(index: number, focused: boolean): void;
|
|
51
|
+
/**
|
|
52
|
+
* Get active component at index
|
|
53
|
+
*
|
|
54
|
+
* @param index - The option index
|
|
55
|
+
* @returns The component instance or undefined
|
|
56
|
+
*/
|
|
57
|
+
getComponent(index: number): CustomOptionContract | undefined;
|
|
58
|
+
/**
|
|
59
|
+
* Clear the entire pool
|
|
60
|
+
*/
|
|
61
|
+
clear(): void;
|
|
62
|
+
/**
|
|
63
|
+
* Get pool statistics for debugging
|
|
64
|
+
*/
|
|
65
|
+
getStats(): {
|
|
66
|
+
totalPooled: number;
|
|
67
|
+
activeComponents: number;
|
|
68
|
+
availableComponents: number;
|
|
69
|
+
};
|
|
70
|
+
/**
|
|
71
|
+
* Find an available component in the pool
|
|
72
|
+
*/
|
|
73
|
+
private _findAvailableComponent;
|
|
74
|
+
/**
|
|
75
|
+
* Generate a unique key for a factory function
|
|
76
|
+
*/
|
|
77
|
+
private _getFactoryKey;
|
|
78
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Option Renderer
|
|
3
|
+
*
|
|
4
|
+
* Unified renderer that handles both lightweight (label/value) and
|
|
5
|
+
* custom component rendering with consistent performance characteristics.
|
|
6
|
+
*/
|
|
7
|
+
export interface OptionRendererConfig {
|
|
8
|
+
enableRecycling: boolean;
|
|
9
|
+
maxPoolSize: number;
|
|
10
|
+
getValue: (item: unknown) => unknown;
|
|
11
|
+
getLabel: (item: unknown) => string;
|
|
12
|
+
getDisabled?: (item: unknown) => boolean;
|
|
13
|
+
onSelect: (index: number) => void;
|
|
14
|
+
onCustomEvent?: (index: number, eventName: string, data: unknown) => void;
|
|
15
|
+
onError?: (index: number, error: Error) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Manages rendering of both lightweight and custom component options
|
|
19
|
+
*/
|
|
20
|
+
export declare class OptionRenderer {
|
|
21
|
+
private _config;
|
|
22
|
+
private _pool;
|
|
23
|
+
private _mountedElements;
|
|
24
|
+
constructor(config: OptionRendererConfig);
|
|
25
|
+
/**
|
|
26
|
+
* Render an option (lightweight or custom component)
|
|
27
|
+
*
|
|
28
|
+
* @param item - The data item
|
|
29
|
+
* @param index - The option index
|
|
30
|
+
* @param isSelected - Whether the option is selected
|
|
31
|
+
* @param isFocused - Whether the option has keyboard focus
|
|
32
|
+
* @param uniqueId - Unique ID for the select instance
|
|
33
|
+
* @returns The rendered DOM element
|
|
34
|
+
*/
|
|
35
|
+
render(item: unknown, index: number, isSelected: boolean, isFocused: boolean, uniqueId: string): HTMLElement;
|
|
36
|
+
/**
|
|
37
|
+
* Update selection state for an option
|
|
38
|
+
*
|
|
39
|
+
* @param index - The option index
|
|
40
|
+
* @param selected - Whether it's selected
|
|
41
|
+
*/
|
|
42
|
+
updateSelection(index: number, selected: boolean): void;
|
|
43
|
+
/**
|
|
44
|
+
* Update focused state for an option
|
|
45
|
+
*
|
|
46
|
+
* @param index - The option index
|
|
47
|
+
* @param focused - Whether it has keyboard focus
|
|
48
|
+
*/
|
|
49
|
+
updateFocused(index: number, focused: boolean): void;
|
|
50
|
+
/**
|
|
51
|
+
* Unmount and cleanup an option
|
|
52
|
+
*
|
|
53
|
+
* @param index - The option index
|
|
54
|
+
*/
|
|
55
|
+
unmount(index: number): void;
|
|
56
|
+
/**
|
|
57
|
+
* Unmount all options
|
|
58
|
+
*/
|
|
59
|
+
unmountAll(): void;
|
|
60
|
+
/**
|
|
61
|
+
* Get pool statistics
|
|
62
|
+
*/
|
|
63
|
+
getStats(): {
|
|
64
|
+
totalPooled: number;
|
|
65
|
+
activeComponents: number;
|
|
66
|
+
availableComponents: number;
|
|
67
|
+
};
|
|
68
|
+
/**
|
|
69
|
+
* Render a lightweight option (traditional label/value)
|
|
70
|
+
*/
|
|
71
|
+
private _renderLightweightOption;
|
|
72
|
+
/**
|
|
73
|
+
* Render a custom component option
|
|
74
|
+
*/
|
|
75
|
+
private _renderCustomComponent;
|
|
76
|
+
}
|