@smilodon/core 1.0.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.
Files changed (34) hide show
  1. package/dist/index.cjs +3685 -0
  2. package/dist/index.cjs.map +1 -0
  3. package/dist/index.js +3643 -0
  4. package/dist/index.js.map +1 -0
  5. package/dist/index.min.js +2 -0
  6. package/dist/index.min.js.map +1 -0
  7. package/dist/index.umd.js +3691 -0
  8. package/dist/index.umd.js.map +1 -0
  9. package/dist/index.umd.min.js +2 -0
  10. package/dist/index.umd.min.js.map +1 -0
  11. package/dist/types/src/components/enhanced-select.d.ts +136 -0
  12. package/dist/types/src/components/native-select.d.ts +41 -0
  13. package/dist/types/src/components/select-option.d.ts +77 -0
  14. package/dist/types/src/config/global-config.d.ts +194 -0
  15. package/dist/types/src/index.d.ts +14 -0
  16. package/dist/types/src/renderers/contracts.d.ts +5 -0
  17. package/dist/types/src/themes/importer.d.ts +112 -0
  18. package/dist/types/src/types.d.ts +85 -0
  19. package/dist/types/src/utils/csp-styles.d.ts +74 -0
  20. package/dist/types/src/utils/data-source.d.ts +37 -0
  21. package/dist/types/src/utils/dom-pool.d.ts +79 -0
  22. package/dist/types/src/utils/fenwick-tree.d.ts +71 -0
  23. package/dist/types/src/utils/security.d.ts +131 -0
  24. package/dist/types/src/utils/telemetry.d.ts +95 -0
  25. package/dist/types/src/utils/virtualizer.d.ts +53 -0
  26. package/dist/types/src/utils/worker-manager.d.ts +106 -0
  27. package/dist/types/tests/csp.spec.d.ts +5 -0
  28. package/dist/types/tests/interaction.spec.d.ts +1 -0
  29. package/dist/types/tests/setup.d.ts +6 -0
  30. package/dist/types/tests/shadow-dom.spec.d.ts +5 -0
  31. package/dist/types/tests/smoke.spec.d.ts +1 -0
  32. package/dist/types/tests/stress.spec.d.ts +5 -0
  33. package/dist/types/tests/virtualizer.spec.d.ts +1 -0
  34. package/package.json +52 -0
@@ -0,0 +1,79 @@
1
+ /**
2
+ * DOM Node Pool with LRU eviction and aggressive cleanup.
3
+ * Reuses nodes to minimize GC pressure and layout thrashing.
4
+ *
5
+ * Features:
6
+ * - LRU eviction when pool exceeds maxSize
7
+ * - Style reset to avoid style pollution
8
+ * - Event listener cleanup
9
+ * - Performance telemetry integration
10
+ */
11
+ export interface DOMPoolOptions {
12
+ /** Maximum pool size (default: renderedNodes + 32) */
13
+ maxSize?: number;
14
+ /** Factory function to create new nodes */
15
+ factory: () => HTMLElement;
16
+ /** Reset function called before reuse */
17
+ reset?: (node: HTMLElement) => void;
18
+ /** Enable performance telemetry */
19
+ telemetry?: boolean;
20
+ }
21
+ export declare class DOMPool {
22
+ private pool;
23
+ private factory;
24
+ private reset;
25
+ private maxSize;
26
+ private telemetry;
27
+ private hits;
28
+ private misses;
29
+ private evictions;
30
+ constructor(options: DOMPoolOptions);
31
+ /**
32
+ * Acquire a node from pool or create new one
33
+ * Complexity: O(n) for LRU scan, amortized O(1) for small pools
34
+ */
35
+ acquire(): HTMLElement;
36
+ /**
37
+ * Release node back to pool
38
+ * Complexity: O(n) to find node
39
+ */
40
+ release(node: HTMLElement): void;
41
+ /**
42
+ * Evict least recently used node
43
+ * Complexity: O(n)
44
+ */
45
+ private evictLRU;
46
+ /**
47
+ * Default reset: clear content, remove inline styles, remove attributes
48
+ */
49
+ private defaultReset;
50
+ /**
51
+ * Deep cleanup before eviction/destruction
52
+ */
53
+ private deepCleanup;
54
+ /**
55
+ * Clear entire pool
56
+ */
57
+ clear(): void;
58
+ /**
59
+ * Adjust max pool size dynamically
60
+ */
61
+ setMaxSize(size: number): void;
62
+ /**
63
+ * Get pool statistics
64
+ */
65
+ getStats(): {
66
+ total: number;
67
+ available: number;
68
+ inUse: number;
69
+ maxSize: number;
70
+ hits: number;
71
+ misses: number;
72
+ evictions: number;
73
+ hitRate: number;
74
+ };
75
+ /**
76
+ * Reset telemetry counters
77
+ */
78
+ resetTelemetry(): void;
79
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Fenwick Tree (Binary Indexed Tree) for O(log n) prefix sum queries and updates.
3
+ * Used for cumulative height calculations in variable-height virtualization.
4
+ *
5
+ * Space: O(n)
6
+ * Time: O(log n) for both query and update
7
+ *
8
+ * @see https://en.wikipedia.org/wiki/Fenwick_tree
9
+ */
10
+ export declare class FenwickTree {
11
+ private tree;
12
+ private size;
13
+ constructor(size: number);
14
+ /**
15
+ * Add delta to index i (0-indexed input)
16
+ * Complexity: O(log n)
17
+ */
18
+ add(index: number, delta: number): void;
19
+ /**
20
+ * Get prefix sum from 0 to index (inclusive, 0-indexed input)
21
+ * Complexity: O(log n)
22
+ */
23
+ sum(index: number): number;
24
+ /**
25
+ * Get sum in range [left, right] (inclusive, 0-indexed)
26
+ * Complexity: O(log n)
27
+ */
28
+ rangeSum(left: number, right: number): number;
29
+ /**
30
+ * Update value at index to newValue (handles delta internally)
31
+ * Requires tracking current values externally or use add() directly
32
+ * Complexity: O(log n)
33
+ */
34
+ update(index: number, oldValue: number, newValue: number): void;
35
+ /**
36
+ * Binary search to find the smallest index where sum(index) >= target
37
+ * Useful for finding scroll position -> item index mapping
38
+ * Complexity: O(log² n) or O(log n) with optimization
39
+ *
40
+ * @returns index (0-indexed) or -1 if not found
41
+ */
42
+ lowerBound(target: number): number;
43
+ /**
44
+ * Reset all values to 0
45
+ * Complexity: O(n)
46
+ */
47
+ reset(): void;
48
+ /**
49
+ * Resize the tree (useful for dynamic item lists)
50
+ * Complexity: O(n)
51
+ */
52
+ resize(newSize: number): void;
53
+ /**
54
+ * Get current size
55
+ */
56
+ getSize(): number;
57
+ /**
58
+ * Export state for serialization (e.g., to SharedArrayBuffer)
59
+ */
60
+ exportState(): {
61
+ size: number;
62
+ tree: number[];
63
+ };
64
+ /**
65
+ * Import state from serialization
66
+ */
67
+ static fromState(state: {
68
+ size: number;
69
+ tree: number[];
70
+ }): FenwickTree;
71
+ }
@@ -0,0 +1,131 @@
1
+ /**
2
+ * Security utilities for CSP-compliant environments.
3
+ * All utilities are opt-in and do not run by default.
4
+ */
5
+ /**
6
+ * HTML Sanitizer interface - developers must provide their own implementation
7
+ * (e.g., DOMPurify) or use the no-op default.
8
+ */
9
+ export interface HTMLSanitizer {
10
+ sanitize(html: string): string;
11
+ }
12
+ /**
13
+ * Set a custom HTML sanitizer (e.g., DOMPurify).
14
+ *
15
+ * @example
16
+ * import DOMPurify from 'dompurify';
17
+ * setHTMLSanitizer({
18
+ * sanitize: (html) => DOMPurify.sanitize(html)
19
+ * });
20
+ */
21
+ export declare function setHTMLSanitizer(sanitizer: HTMLSanitizer): void;
22
+ /**
23
+ * Reset to the default no-op sanitizer.
24
+ * Mainly for testing purposes.
25
+ */
26
+ export declare function resetHTMLSanitizer(): void;
27
+ /**
28
+ * Get the current HTML sanitizer.
29
+ */
30
+ export declare function getHTMLSanitizer(): HTMLSanitizer;
31
+ /**
32
+ * Sanitize HTML using the registered sanitizer.
33
+ * WARNING: Default is no-op! Set a real sanitizer for untrusted content.
34
+ *
35
+ * @param html - HTML string to sanitize
36
+ * @returns Sanitized HTML string
37
+ */
38
+ export declare function sanitizeHTML(html: string): string;
39
+ /**
40
+ * Create a text node (CSP-safe alternative to innerHTML for text content).
41
+ *
42
+ * @param text - Text content
43
+ * @returns Text node
44
+ */
45
+ export declare function createTextNode(text: string): Text;
46
+ /**
47
+ * Set text content safely (CSP-compliant).
48
+ *
49
+ * @param element - Target element
50
+ * @param text - Text content
51
+ */
52
+ export declare function setTextContent(element: Element, text: string): void;
53
+ /**
54
+ * Create an element with attributes (CSP-safe).
55
+ * No inline styles or event handlers.
56
+ *
57
+ * @param tagName - HTML tag name
58
+ * @param attributes - Element attributes (excluding style and on* handlers)
59
+ * @param textContent - Optional text content
60
+ * @returns Created element
61
+ */
62
+ export declare function createElement(tagName: string, attributes?: Record<string, string>, textContent?: string): HTMLElement;
63
+ /**
64
+ * Set CSS custom properties (CSP-safe way to style elements).
65
+ *
66
+ * @param element - Target element
67
+ * @param properties - CSS custom properties (e.g., { '--color': 'red' })
68
+ */
69
+ export declare function setCSSProperties(element: HTMLElement, properties: Record<string, string>): void;
70
+ /**
71
+ * Feature detection utilities for CSP-restricted environments.
72
+ */
73
+ export declare const CSPFeatures: {
74
+ /**
75
+ * Check if inline scripts are allowed (CSP: script-src 'unsafe-inline').
76
+ */
77
+ hasInlineScripts(): boolean;
78
+ /**
79
+ * Check if eval is allowed (CSP: script-src 'unsafe-eval').
80
+ */
81
+ hasEval(): boolean;
82
+ /**
83
+ * Check if SharedArrayBuffer is available.
84
+ * Required for some Worker features, blocked without COOP/COEP headers.
85
+ */
86
+ hasSharedArrayBuffer(): boolean;
87
+ /**
88
+ * Check if Web Workers are available and functional.
89
+ */
90
+ hasWorkers(): boolean;
91
+ /**
92
+ * Check if we're in a sandboxed iframe.
93
+ */
94
+ isSandboxed(): boolean;
95
+ /**
96
+ * Check CSP policy via meta tag or SecurityPolicyViolationEvent.
97
+ */
98
+ getCSPDirectives(): string[];
99
+ };
100
+ /**
101
+ * Runtime environment checks for degraded features.
102
+ */
103
+ export interface EnvironmentCapabilities {
104
+ canUseWorkers: boolean;
105
+ canUseSharedArrayBuffer: boolean;
106
+ canUseInlineScripts: boolean;
107
+ canUseEval: boolean;
108
+ isSandboxed: boolean;
109
+ cspDirectives: string[];
110
+ }
111
+ /**
112
+ * Detect environment capabilities once at initialization.
113
+ */
114
+ export declare function detectEnvironment(): EnvironmentCapabilities;
115
+ /**
116
+ * Validation for untrusted HTML in templates.
117
+ * Logs warning if no sanitizer is configured.
118
+ */
119
+ export declare function validateTemplate(html: string, source: string): string;
120
+ /**
121
+ * Check if a string looks like it might contain executable code.
122
+ */
123
+ export declare function containsSuspiciousPatterns(str: string): boolean;
124
+ /**
125
+ * Escape HTML entities for text content.
126
+ */
127
+ export declare function escapeHTML(text: string): string;
128
+ /**
129
+ * Escape attribute values.
130
+ */
131
+ export declare function escapeAttribute(attr: string): string;
@@ -0,0 +1,95 @@
1
+ /**
2
+ * Performance telemetry module for tracking frame timing and performance metrics.
3
+ * Uses PerformanceObserver for precise measurements.
4
+ *
5
+ * Tracks:
6
+ * - Frame time (should be < 16.67ms for 60fps)
7
+ * - Main thread work per frame (target < 8ms, ideal 4-6ms)
8
+ * - Long tasks (> 50ms blocks)
9
+ * - Memory usage (if available)
10
+ */
11
+ export interface FrameMetrics {
12
+ frameTime: number;
13
+ fps: number;
14
+ longTasks: number;
15
+ droppedFrames: number;
16
+ }
17
+ export interface PerformanceMetrics {
18
+ frames: FrameMetrics;
19
+ mainThreadWork: number;
20
+ longTaskCount: number;
21
+ memory?: {
22
+ usedJSHeapSize: number;
23
+ totalJSHeapSize: number;
24
+ jsHeapSizeLimit: number;
25
+ };
26
+ }
27
+ export declare class PerformanceTelemetry {
28
+ private frameTimes;
29
+ private longTasks;
30
+ private lastFrameTime;
31
+ private rafId;
32
+ private measuring;
33
+ private observer;
34
+ private workTimes;
35
+ constructor();
36
+ /**
37
+ * Setup PerformanceObserver for long tasks
38
+ */
39
+ private setupObserver;
40
+ /**
41
+ * Start measuring frame performance
42
+ */
43
+ start(): void;
44
+ /**
45
+ * Stop measuring
46
+ */
47
+ stop(): void;
48
+ /**
49
+ * Measure frame timing via requestAnimationFrame
50
+ */
51
+ private measureFrame;
52
+ /**
53
+ * Mark start of work for custom measurement
54
+ */
55
+ markStart(label: string): void;
56
+ /**
57
+ * Mark end of work and measure duration
58
+ */
59
+ markEnd(label: string): number;
60
+ /**
61
+ * Get current metrics snapshot
62
+ */
63
+ getMetrics(): PerformanceMetrics;
64
+ /**
65
+ * Check if performance is acceptable
66
+ */
67
+ isPerformanceGood(): boolean;
68
+ /**
69
+ * Get detailed report as string
70
+ */
71
+ getReport(): string;
72
+ /**
73
+ * Reset all metrics
74
+ */
75
+ reset(): void;
76
+ /**
77
+ * Cleanup
78
+ */
79
+ destroy(): void;
80
+ }
81
+ export declare function getTelemetry(): PerformanceTelemetry;
82
+ /**
83
+ * Helper to measure async function execution
84
+ */
85
+ export declare function measureAsync<T>(label: string, fn: () => Promise<T>): Promise<{
86
+ result: T;
87
+ duration: number;
88
+ }>;
89
+ /**
90
+ * Helper to measure sync function execution
91
+ */
92
+ export declare function measureSync<T>(label: string, fn: () => T): {
93
+ result: T;
94
+ duration: number;
95
+ };
@@ -0,0 +1,53 @@
1
+ type ItemGetter = (index: number) => unknown;
2
+ export interface VirtualizerOptions {
3
+ estimatedItemHeight: number;
4
+ buffer: number;
5
+ maxPoolExtra?: number;
6
+ measurementThreshold?: number;
7
+ enableTelemetry?: boolean;
8
+ }
9
+ export declare class Virtualizer {
10
+ private container;
11
+ private itemsLength;
12
+ private options;
13
+ measuredHeights: Map<number, number>;
14
+ averageHeight: number;
15
+ private pool;
16
+ private itemGetter;
17
+ private fenwick?;
18
+ private activeNodes;
19
+ constructor(container: HTMLElement, itemsLength: number, itemGetter: ItemGetter, options: VirtualizerOptions);
20
+ computeWindow(scrollTop: number, viewportHeight: number): {
21
+ startIndex: number;
22
+ endIndex: number;
23
+ windowSize: number;
24
+ };
25
+ cumulativeOffset(index: number): number;
26
+ acquireNode(index: number): HTMLElement;
27
+ releaseNode(index: number): void;
28
+ releaseExcess(activeIndices: Set<number>): void;
29
+ render(startIndex: number, endIndex: number, updateNode: (node: HTMLElement, item: unknown, index: number) => void): void;
30
+ measureOnAppear(node: HTMLElement, index: number): void;
31
+ /**
32
+ * Get pool statistics (if telemetry enabled)
33
+ */
34
+ getPoolStats(): {
35
+ total: number;
36
+ available: number;
37
+ inUse: number;
38
+ maxSize: number;
39
+ hits: number;
40
+ misses: number;
41
+ evictions: number;
42
+ hitRate: number;
43
+ };
44
+ /**
45
+ * Update items length and resize Fenwick tree if needed
46
+ */
47
+ setItemsLength(newLength: number): void;
48
+ /**
49
+ * Cleanup resources
50
+ */
51
+ destroy(): void;
52
+ }
53
+ export {};
@@ -0,0 +1,106 @@
1
+ /**
2
+ * Web Worker protocol types for off-main-thread processing.
3
+ * Supports heavy transforms, fuzzy search, and data processing.
4
+ */
5
+ export interface WorkerRequest {
6
+ id: string;
7
+ type: 'transform' | 'search' | 'filter' | 'sort';
8
+ payload: unknown;
9
+ }
10
+ export interface WorkerResponse<T = unknown> {
11
+ id: string;
12
+ success: boolean;
13
+ data?: T;
14
+ error?: string;
15
+ duration?: number;
16
+ }
17
+ export interface TransformRequest {
18
+ items: unknown[];
19
+ transformer: string;
20
+ }
21
+ export interface SearchRequest {
22
+ items: unknown[];
23
+ query: string;
24
+ fuzzy?: boolean;
25
+ maxResults?: number;
26
+ }
27
+ export interface FilterRequest {
28
+ items: unknown[];
29
+ predicate: string;
30
+ }
31
+ export interface SortRequest {
32
+ items: unknown[];
33
+ comparator: string;
34
+ }
35
+ /**
36
+ * Worker manager for handling off-main-thread processing.
37
+ * Automatically falls back if workers not available or blocked by COOP/COEP.
38
+ */
39
+ export declare class WorkerManager {
40
+ private worker;
41
+ private pending;
42
+ private supportsWorkers;
43
+ private supportsSharedArrayBuffer;
44
+ private nextId;
45
+ constructor();
46
+ /**
47
+ * Detect browser capabilities
48
+ */
49
+ private detectFeatures;
50
+ /**
51
+ * Initialize worker (inline blob URL for simplicity)
52
+ */
53
+ private initWorker;
54
+ /**
55
+ * Generate worker code as string
56
+ */
57
+ private generateWorkerCode;
58
+ /**
59
+ * Handle worker message
60
+ */
61
+ private handleMessage;
62
+ /**
63
+ * Handle worker error
64
+ */
65
+ private handleError;
66
+ /**
67
+ * Execute operation (worker or fallback)
68
+ */
69
+ execute<T = unknown>(type: WorkerRequest['type'], payload: unknown, timeout?: number): Promise<T>;
70
+ /**
71
+ * Fallback to main thread execution
72
+ */
73
+ private executeFallback;
74
+ /**
75
+ * Transform items with custom function
76
+ */
77
+ transform<T, R>(items: T[], transformer: (item: T, index: number) => R): Promise<R[]>;
78
+ /**
79
+ * Search items with optional fuzzy matching
80
+ */
81
+ search<T>(items: T[], query: string, fuzzy?: boolean): Promise<{
82
+ item: T;
83
+ index: number;
84
+ }[]>;
85
+ /**
86
+ * Filter items with predicate
87
+ */
88
+ filter<T>(items: T[], predicate: (item: T, index: number) => boolean): Promise<T[]>;
89
+ /**
90
+ * Sort items with comparator
91
+ */
92
+ sort<T>(items: T[], comparator: (a: T, b: T) => number): Promise<T[]>;
93
+ /**
94
+ * Check if workers are supported
95
+ */
96
+ get hasWorkerSupport(): boolean;
97
+ /**
98
+ * Check if SharedArrayBuffer is supported
99
+ */
100
+ get hasSharedArrayBuffer(): boolean;
101
+ /**
102
+ * Terminate worker
103
+ */
104
+ destroy(): void;
105
+ }
106
+ export declare function getWorkerManager(): WorkerManager;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * CSP (Content Security Policy) compliance test suite.
3
+ * Verifies the library works in CSP-restricted environments.
4
+ */
5
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Test setup - runs before all tests
3
+ */
4
+ import '../src/components/native-select';
5
+ import '../src/components/enhanced-select';
6
+ import '../src/components/select-option';
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Shadow DOM security and isolation tests.
3
+ * Tests closed shadow roots, nested embeddings, and isolation boundaries.
4
+ */
5
+ export {};
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Stress tests for extreme scale performance validation.
3
+ * Tests 1M+ items, heavy transforms, worker offloading.
4
+ */
5
+ export {};
@@ -0,0 +1 @@
1
+ export {};
package/package.json ADDED
@@ -0,0 +1,52 @@
1
+ {
2
+ "name": "@smilodon/core",
3
+ "version": "1.0.0",
4
+ "description": "High-performance native select component with extreme-scale virtualization",
5
+ "type": "module",
6
+ "main": "./dist/index.cjs",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/types/src/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/types/src/index.d.ts",
12
+ "import": "./dist/index.js",
13
+ "require": "./dist/index.cjs"
14
+ },
15
+ "./package.json": "./package.json"
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md"
20
+ ],
21
+ "scripts": {
22
+ "build": "rollup -c && tsc --emitDeclarationOnly --outDir dist/types",
23
+ "dev": "rollup -c --watch",
24
+ "test": "vitest run",
25
+ "test:watch": "vitest",
26
+ "size": "gzip -c dist/index.js | wc -c"
27
+ },
28
+ "keywords": [
29
+ "select",
30
+ "dropdown",
31
+ "virtualization",
32
+ "web-components",
33
+ "custom-element",
34
+ "performance"
35
+ ],
36
+ "author": "",
37
+ "license": "MIT",
38
+ "devDependencies": {
39
+ "@rollup/plugin-node-resolve": "^15.2.3",
40
+ "@rollup/plugin-terser": "^0.4.4",
41
+ "@rollup/plugin-typescript": "^11.1.6",
42
+ "rollup": "^4.9.0",
43
+ "typescript": "^5.6.2",
44
+ "vitest": "^1.6.0",
45
+ "jsdom": "^24.0.0"
46
+ },
47
+ "sideEffects": [
48
+ "./src/components/enhanced-select.ts",
49
+ "./src/components/native-select.ts",
50
+ "./dist/**/*.js"
51
+ ]
52
+ }