@jasonshimmy/custom-elements-runtime 0.3.0 → 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.
- package/README.md +69 -57
- package/dist/custom-elements-runtime.cjs.js +36 -30
- package/dist/custom-elements-runtime.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.es.js +2534 -1373
- package/dist/custom-elements-runtime.es.js.map +1 -1
- package/dist/custom-elements-runtime.umd.js +35 -29
- package/dist/custom-elements-runtime.umd.js.map +1 -1
- package/dist/directive-enhancements.d.ts +138 -0
- package/dist/directives.d.ts +5 -0
- package/dist/index.d.ts +9 -6
- package/dist/runtime/component.d.ts +39 -2
- package/dist/runtime/event-manager.d.ts +58 -0
- package/dist/runtime/helpers.d.ts +19 -0
- package/dist/runtime/hooks.d.ts +113 -0
- package/dist/runtime/logger.d.ts +16 -0
- package/dist/runtime/props.d.ts +13 -1
- package/dist/runtime/reactive-proxy-cache.d.ts +51 -0
- package/dist/runtime/reactive.d.ts +118 -0
- package/dist/runtime/render.d.ts +2 -2
- package/dist/runtime/scheduler.d.ts +27 -0
- package/dist/runtime/secure-expression-evaluator.d.ts +30 -0
- package/dist/runtime/template-compiler.d.ts +4 -0
- package/dist/runtime/types.d.ts +2 -10
- package/dist/runtime/vdom.d.ts +10 -9
- package/package.json +1 -1
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
import type { VNode } from "./runtime/types";
|
|
2
|
+
/**
|
|
3
|
+
* Conditional rendering with negated condition (opposite of when)
|
|
4
|
+
* @param cond - Boolean condition to negate
|
|
5
|
+
* @param children - Content to render when condition is false
|
|
6
|
+
*/
|
|
7
|
+
export declare function unless(cond: boolean, children: VNode | VNode[]): VNode;
|
|
8
|
+
/**
|
|
9
|
+
* Render content only if array/collection is empty
|
|
10
|
+
* @param collection - Array or collection to check
|
|
11
|
+
* @param children - Content to render when empty
|
|
12
|
+
*/
|
|
13
|
+
export declare function whenEmpty(collection: any[] | null | undefined, children: VNode | VNode[]): VNode;
|
|
14
|
+
/**
|
|
15
|
+
* Render content only if array/collection has items
|
|
16
|
+
* @param collection - Array or collection to check
|
|
17
|
+
* @param children - Content to render when not empty
|
|
18
|
+
*/
|
|
19
|
+
export declare function whenNotEmpty(collection: any[] | null | undefined, children: VNode | VNode[]): VNode;
|
|
20
|
+
/**
|
|
21
|
+
* Enhanced each with filtering capability
|
|
22
|
+
* @param list - Array to iterate over
|
|
23
|
+
* @param predicate - Filter function (optional)
|
|
24
|
+
* @param render - Render function for each item
|
|
25
|
+
*/
|
|
26
|
+
export declare function eachWhere<T>(list: T[], predicate: (item: T, index: number) => boolean, render: (item: T, index: number, filteredIndex: number) => VNode | VNode[]): VNode[];
|
|
27
|
+
/**
|
|
28
|
+
* Render different content based on array length
|
|
29
|
+
* @param list - Array to check
|
|
30
|
+
* @param cases - Object with length-based cases
|
|
31
|
+
*/
|
|
32
|
+
export declare function switchOnLength<T>(list: T[], cases: {
|
|
33
|
+
empty?: VNode | VNode[];
|
|
34
|
+
one?: (item: T) => VNode | VNode[];
|
|
35
|
+
many?: (items: T[]) => VNode | VNode[];
|
|
36
|
+
exactly?: {
|
|
37
|
+
[count: number]: (items: T[]) => VNode | VNode[];
|
|
38
|
+
};
|
|
39
|
+
}): VNode;
|
|
40
|
+
/**
|
|
41
|
+
* Group array items and render each group
|
|
42
|
+
* @param list - Array to group
|
|
43
|
+
* @param groupBy - Function to determine group key
|
|
44
|
+
* @param renderGroup - Function to render each group
|
|
45
|
+
*/
|
|
46
|
+
export declare function eachGroup<T, K extends string | number>(list: T[], groupBy: (item: T) => K, renderGroup: (groupKey: K, items: T[], groupIndex: number) => VNode | VNode[]): VNode[];
|
|
47
|
+
/**
|
|
48
|
+
* Render with pagination/chunking
|
|
49
|
+
* @param list - Array to chunk
|
|
50
|
+
* @param pageSize - Items per page/chunk
|
|
51
|
+
* @param currentPage - Current page (0-based)
|
|
52
|
+
* @param render - Render function for visible items
|
|
53
|
+
*/
|
|
54
|
+
export declare function eachPage<T>(list: T[], pageSize: number, currentPage: number, render: (item: T, index: number, pageIndex: number) => VNode | VNode[]): VNode[];
|
|
55
|
+
/**
|
|
56
|
+
* Render content based on Promise state
|
|
57
|
+
* @param promiseState - Object with loading, data, error states
|
|
58
|
+
* @param cases - Render functions for each state
|
|
59
|
+
*/
|
|
60
|
+
export declare function switchOnPromise<T, E = Error>(promiseState: {
|
|
61
|
+
loading?: boolean;
|
|
62
|
+
data?: T;
|
|
63
|
+
error?: E;
|
|
64
|
+
}, cases: {
|
|
65
|
+
loading?: VNode | VNode[];
|
|
66
|
+
success?: (data: T) => VNode | VNode[];
|
|
67
|
+
error?: (error: E) => VNode | VNode[];
|
|
68
|
+
idle?: VNode | VNode[];
|
|
69
|
+
}): VNode;
|
|
70
|
+
/**
|
|
71
|
+
* Render content based on screen size/media query
|
|
72
|
+
* @param mediaQuery - CSS media query string
|
|
73
|
+
* @param children - Content to render when media query matches
|
|
74
|
+
*/
|
|
75
|
+
export declare function whenMedia(mediaQuery: string, children: VNode | VNode[]): VNode;
|
|
76
|
+
/**
|
|
77
|
+
* Media variants matching those in style.ts
|
|
78
|
+
*/
|
|
79
|
+
export declare const mediaVariants: {
|
|
80
|
+
readonly sm: "(min-width:640px)";
|
|
81
|
+
readonly md: "(min-width:768px)";
|
|
82
|
+
readonly lg: "(min-width:1024px)";
|
|
83
|
+
readonly xl: "(min-width:1280px)";
|
|
84
|
+
readonly "2xl": "(min-width:1536px)";
|
|
85
|
+
readonly dark: "(prefers-color-scheme: dark)";
|
|
86
|
+
};
|
|
87
|
+
/**
|
|
88
|
+
* Responsive order matching style.ts
|
|
89
|
+
*/
|
|
90
|
+
export declare const responsiveOrder: readonly ["sm", "md", "lg", "xl", "2xl"];
|
|
91
|
+
/**
|
|
92
|
+
* Individual responsive directives matching the style.ts breakpoint system
|
|
93
|
+
*/
|
|
94
|
+
export declare const responsive: {
|
|
95
|
+
readonly sm: (children: VNode | VNode[]) => VNode;
|
|
96
|
+
readonly md: (children: VNode | VNode[]) => VNode;
|
|
97
|
+
readonly lg: (children: VNode | VNode[]) => VNode;
|
|
98
|
+
readonly xl: (children: VNode | VNode[]) => VNode;
|
|
99
|
+
readonly "2xl": (children: VNode | VNode[]) => VNode;
|
|
100
|
+
readonly dark: (children: VNode | VNode[]) => VNode;
|
|
101
|
+
readonly light: (children: VNode | VNode[]) => VNode;
|
|
102
|
+
readonly touch: (children: VNode | VNode[]) => VNode;
|
|
103
|
+
readonly mouse: (children: VNode | VNode[]) => VNode;
|
|
104
|
+
readonly reducedMotion: (children: VNode | VNode[]) => VNode;
|
|
105
|
+
readonly highContrast: (children: VNode | VNode[]) => VNode;
|
|
106
|
+
readonly portrait: (children: VNode | VNode[]) => VNode;
|
|
107
|
+
readonly landscape: (children: VNode | VNode[]) => VNode;
|
|
108
|
+
};
|
|
109
|
+
/**
|
|
110
|
+
* Advanced responsive directive that matches the style.ts multi-variant processing
|
|
111
|
+
* Allows chaining responsive and dark mode conditions like in CSS classes
|
|
112
|
+
* @param variants - Array of variant keys (e.g., ['dark', 'lg'])
|
|
113
|
+
* @param children - Content to render when all variants match
|
|
114
|
+
*/
|
|
115
|
+
export declare function whenVariants(variants: Array<keyof typeof mediaVariants | 'light'>, children: VNode | VNode[]): VNode;
|
|
116
|
+
/**
|
|
117
|
+
* Responsive switch directive - render different content for different breakpoints
|
|
118
|
+
* Mirrors the responsive behavior from the style system
|
|
119
|
+
* @param content - Object with breakpoint keys and corresponding content
|
|
120
|
+
*/
|
|
121
|
+
export declare function responsiveSwitch(content: {
|
|
122
|
+
base?: VNode | VNode[];
|
|
123
|
+
sm?: VNode | VNode[];
|
|
124
|
+
md?: VNode | VNode[];
|
|
125
|
+
lg?: VNode | VNode[];
|
|
126
|
+
xl?: VNode | VNode[];
|
|
127
|
+
"2xl"?: VNode | VNode[];
|
|
128
|
+
}): VNode[];
|
|
129
|
+
/**
|
|
130
|
+
* Enhanced match directive with more fluent API
|
|
131
|
+
* @param value - Value to match against
|
|
132
|
+
*/
|
|
133
|
+
export declare function switchOn<T>(value: T): {
|
|
134
|
+
case(matcher: T | ((val: T) => boolean), content: VNode | VNode[]): /*elided*/ any;
|
|
135
|
+
when(predicate: (val: T) => boolean, content: VNode | VNode[]): /*elided*/ any;
|
|
136
|
+
otherwise(content: VNode | VNode[]): /*elided*/ any;
|
|
137
|
+
done(): VNode;
|
|
138
|
+
};
|
package/dist/directives.d.ts
CHANGED
|
@@ -9,3 +9,8 @@ export declare function match(): {
|
|
|
9
9
|
otherwise(content: VNode | VNode[]): /*elided*/ any;
|
|
10
10
|
done(): VNode[];
|
|
11
11
|
};
|
|
12
|
+
/**
|
|
13
|
+
* Create a stable anchor block with consistent boundaries.
|
|
14
|
+
* Always has start/end boundaries.
|
|
15
|
+
*/
|
|
16
|
+
export declare function anchorBlock(children: VNode | VNode[] | null | undefined, anchorKey: string): VNode;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Custom Elements Runtime
|
|
3
3
|
* Lightweight, strongly typed, functional custom element runtime for two-way binding, event, and prop support.
|
|
4
|
-
* Supports:
|
|
4
|
+
* Supports: reactive props, computed, events, style, render, lifecycle hooks, :model and @event attributes.
|
|
5
5
|
* No external dependencies. Mobile-first, secure, and developer friendly.
|
|
6
6
|
*/
|
|
7
|
-
export
|
|
7
|
+
export { component } from "./runtime/component";
|
|
8
|
+
export { useEmit, useOnConnected, useOnDisconnected, useOnAttributeChanged, useOnError, useStyle } from "./runtime/hooks";
|
|
9
|
+
export { ref, computed, watch } from "./runtime/reactive";
|
|
10
|
+
export { html } from "./runtime/template-compiler";
|
|
11
|
+
export { css } from "./runtime/style";
|
|
12
|
+
export { renderToString } from "./runtime/vdom";
|
|
13
|
+
export type { VNode } from "./runtime/types";
|
|
8
14
|
export * from "./directives";
|
|
15
|
+
export * from "./directive-enhancements";
|
|
9
16
|
export * from "./event-bus";
|
|
10
17
|
export * from "./store";
|
|
11
18
|
export * from "./router";
|
|
12
|
-
export { renderToString } from "./runtime/vdom";
|
|
13
|
-
export { component } from "./runtime/component";
|
|
14
|
-
export { css } from "./runtime/style";
|
|
15
|
-
export { html } from "./runtime/template-compiler";
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { ComponentConfig,
|
|
1
|
+
import type { ComponentConfig, VNode } from "./types";
|
|
2
2
|
/**
|
|
3
3
|
* @internal
|
|
4
4
|
* Runtime registry of component configs.
|
|
@@ -7,7 +7,44 @@ import type { ComponentConfig, ComponentContext } from "./types";
|
|
|
7
7
|
* internal tests only. Consumers should use the public `component` API.
|
|
8
8
|
*/
|
|
9
9
|
export declare const registry: Map<string, ComponentConfig<any, any, any>>;
|
|
10
|
-
export declare function component<S extends object = {}, C extends object = {}, P extends object = {}, T extends object = any>(tag: string, renderOrConfig: ((context: ComponentContext<S, C, P, T>) => any) | ComponentConfig<S, C, P, T>, config?: Partial<ComponentConfig<S, C, P, T>>): void;
|
|
11
10
|
export declare function createElementClass<S extends object, C extends object, P extends object, T extends object = any>(tag: string, config: ComponentConfig<S, C, P, T>): CustomElementConstructor | {
|
|
12
11
|
new (): object;
|
|
13
12
|
};
|
|
13
|
+
/**
|
|
14
|
+
* Streamlined functional component API with automatic reactive props and lifecycle hooks.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // Simple component with no parameters
|
|
19
|
+
* component('simple-header', () => {
|
|
20
|
+
* return html`<h1>Hello World</h1>`;
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* // With props only
|
|
24
|
+
* component('with-props', ({ message = 'Hello' }) => {
|
|
25
|
+
* return html`<div>${message}</div>`;
|
|
26
|
+
* });
|
|
27
|
+
*
|
|
28
|
+
* // With props and hooks
|
|
29
|
+
* component('my-switch', ({
|
|
30
|
+
* modelValue = false,
|
|
31
|
+
* label = ''
|
|
32
|
+
* }, { emit, onConnected, onDisconnected }) => {
|
|
33
|
+
* onConnected(() => console.log('Switch connected!'));
|
|
34
|
+
* onDisconnected(() => console.log('Switch disconnected!'));
|
|
35
|
+
*
|
|
36
|
+
* return html`
|
|
37
|
+
* <label>
|
|
38
|
+
* ${label}
|
|
39
|
+
* <input
|
|
40
|
+
* type="checkbox"
|
|
41
|
+
* :checked="${modelValue}"
|
|
42
|
+
* @change="${(e) => emit('update:modelValue', e.target.checked)}"
|
|
43
|
+
* />
|
|
44
|
+
* </label>
|
|
45
|
+
* `;
|
|
46
|
+
* });
|
|
47
|
+
* ```
|
|
48
|
+
*/
|
|
49
|
+
export declare function component(tag: string, renderFn: () => VNode | VNode[] | Promise<VNode | VNode[]>): void;
|
|
50
|
+
export declare function component<TProps extends Record<string, any> = {}>(tag: string, renderFn: (props: TProps) => VNode | VNode[] | Promise<VNode | VNode[]>): void;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event Manager for tracking and cleaning up event listeners
|
|
3
|
+
* Prevents memory leaks by maintaining cleanup functions
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Manages event listeners and their cleanup for elements
|
|
7
|
+
*/
|
|
8
|
+
declare class EventManager {
|
|
9
|
+
private static cleanupFunctions;
|
|
10
|
+
/**
|
|
11
|
+
* Add an event listener with automatic cleanup tracking
|
|
12
|
+
*/
|
|
13
|
+
static addListener(element: HTMLElement, event: string, handler: EventListener, options?: AddEventListenerOptions): void;
|
|
14
|
+
/**
|
|
15
|
+
* Remove a specific event listener
|
|
16
|
+
*/
|
|
17
|
+
static removeListener(element: HTMLElement, event: string, handler: EventListener, options?: EventListenerOptions): void;
|
|
18
|
+
/**
|
|
19
|
+
* Clean up all event listeners for an element
|
|
20
|
+
*/
|
|
21
|
+
static cleanup(element: HTMLElement): void;
|
|
22
|
+
/**
|
|
23
|
+
* Clean up all tracked event listeners (useful for testing)
|
|
24
|
+
*/
|
|
25
|
+
static cleanupAll(): void;
|
|
26
|
+
/**
|
|
27
|
+
* Check if an element has any tracked event listeners
|
|
28
|
+
*/
|
|
29
|
+
static hasListeners(element: HTMLElement): boolean;
|
|
30
|
+
/**
|
|
31
|
+
* Get the number of tracked event listeners for an element
|
|
32
|
+
*/
|
|
33
|
+
static getListenerCount(element: HTMLElement): number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Enhanced event listener tracker that stores more metadata
|
|
37
|
+
* for better debugging and cleanup
|
|
38
|
+
*/
|
|
39
|
+
interface EventListenerMetadata {
|
|
40
|
+
event: string;
|
|
41
|
+
handler: EventListener;
|
|
42
|
+
options?: AddEventListenerOptions;
|
|
43
|
+
cleanup: () => void;
|
|
44
|
+
addedAt: number;
|
|
45
|
+
}
|
|
46
|
+
declare class DetailedEventManager {
|
|
47
|
+
private static listeners;
|
|
48
|
+
static addListener(element: HTMLElement, event: string, handler: EventListener, options?: AddEventListenerOptions): void;
|
|
49
|
+
static removeListener(element: HTMLElement, event: string, handler: EventListener, options?: EventListenerOptions): boolean;
|
|
50
|
+
static cleanup(element: HTMLElement): void;
|
|
51
|
+
static getListenerInfo(element: HTMLElement): EventListenerMetadata[];
|
|
52
|
+
static findStaleListeners(_maxAge?: number): Array<{
|
|
53
|
+
element: HTMLElement;
|
|
54
|
+
listeners: EventListenerMetadata[];
|
|
55
|
+
}>;
|
|
56
|
+
}
|
|
57
|
+
export { EventManager, DetailedEventManager };
|
|
58
|
+
export type { EventListenerMetadata };
|
|
@@ -1,4 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert camelCase to kebab-case with caching
|
|
3
|
+
*/
|
|
1
4
|
export declare function toKebab(str: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Convert kebab-case to camelCase with caching
|
|
7
|
+
*/
|
|
8
|
+
export declare function toCamel(str: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* Clear string transformation caches (useful for testing)
|
|
11
|
+
*/
|
|
12
|
+
export declare function clearStringCaches(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Get cache statistics for debugging
|
|
15
|
+
*/
|
|
16
|
+
export declare function getStringCacheStats(): {
|
|
17
|
+
kebabCacheSize: number;
|
|
18
|
+
camelCacheSize: number;
|
|
19
|
+
htmlEscapeCacheSize: number;
|
|
20
|
+
};
|
|
2
21
|
export declare function escapeHTML(str: string | number | boolean): string | number | boolean;
|
|
3
22
|
/**
|
|
4
23
|
* Get nested property value from object using dot notation
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Context-based hooks for functional components
|
|
3
|
+
* Provides React-like hooks with perfect TypeScript inference
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Set the current component context (called internally during render)
|
|
7
|
+
* @internal
|
|
8
|
+
*/
|
|
9
|
+
export declare function setCurrentComponentContext(context: any): void;
|
|
10
|
+
/**
|
|
11
|
+
* Clear the current component context (called internally after render)
|
|
12
|
+
* @internal
|
|
13
|
+
*/
|
|
14
|
+
export declare function clearCurrentComponentContext(): void;
|
|
15
|
+
/**
|
|
16
|
+
* Get the emit function for the current component
|
|
17
|
+
* Must be called during component render
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```ts
|
|
21
|
+
* component('my-button', ({ label = 'Click me' }) => {
|
|
22
|
+
* const emit = useEmit();
|
|
23
|
+
*
|
|
24
|
+
* return html`
|
|
25
|
+
* <button @click="${() => emit('button-click', { label })}">
|
|
26
|
+
* ${label}
|
|
27
|
+
* </button>
|
|
28
|
+
* `;
|
|
29
|
+
* });
|
|
30
|
+
* ```
|
|
31
|
+
*/
|
|
32
|
+
export declare function useEmit(): (eventName: string, detail?: any) => boolean;
|
|
33
|
+
/**
|
|
34
|
+
* Register a callback to be called when component is connected to DOM
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* component('my-component', () => {
|
|
39
|
+
* useOnConnected(() => {
|
|
40
|
+
* console.log('Component mounted!');
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* return html`<div>Hello World</div>`;
|
|
44
|
+
* });
|
|
45
|
+
* ```
|
|
46
|
+
*/
|
|
47
|
+
export declare function useOnConnected(callback: () => void): void;
|
|
48
|
+
/**
|
|
49
|
+
* Register a callback to be called when component is disconnected from DOM
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* ```ts
|
|
53
|
+
* component('my-component', () => {
|
|
54
|
+
* useOnDisconnected(() => {
|
|
55
|
+
* console.log('Component unmounted!');
|
|
56
|
+
* });
|
|
57
|
+
*
|
|
58
|
+
* return html`<div>Goodbye World</div>`;
|
|
59
|
+
* });
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
export declare function useOnDisconnected(callback: () => void): void;
|
|
63
|
+
/**
|
|
64
|
+
* Register a callback to be called when an attribute changes
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```ts
|
|
68
|
+
* component('my-component', () => {
|
|
69
|
+
* useOnAttributeChanged((name, oldValue, newValue) => {
|
|
70
|
+
* console.log(`Attribute ${name} changed from ${oldValue} to ${newValue}`);
|
|
71
|
+
* });
|
|
72
|
+
*
|
|
73
|
+
* return html`<div>Attribute watcher</div>`;
|
|
74
|
+
* });
|
|
75
|
+
* ```
|
|
76
|
+
*/
|
|
77
|
+
export declare function useOnAttributeChanged(callback: (name: string, oldValue: string | null, newValue: string | null) => void): void;
|
|
78
|
+
/**
|
|
79
|
+
* Register a callback to be called when an error occurs
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* ```ts
|
|
83
|
+
* component('my-component', () => {
|
|
84
|
+
* useOnError((error) => {
|
|
85
|
+
* console.error('Component error:', error);
|
|
86
|
+
* });
|
|
87
|
+
*
|
|
88
|
+
* return html`<div>Error handler</div>`;
|
|
89
|
+
* });
|
|
90
|
+
* ```
|
|
91
|
+
*/
|
|
92
|
+
export declare function useOnError(callback: (error: Error) => void): void;
|
|
93
|
+
/**
|
|
94
|
+
* Register a style function that will be called during each render
|
|
95
|
+
* to provide reactive styles for the component
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* ```ts
|
|
99
|
+
* import { css } from '@lib/style';
|
|
100
|
+
*
|
|
101
|
+
* component('my-component', ({ theme = 'light' }) => {
|
|
102
|
+
* useStyle(() => css`
|
|
103
|
+
* :host {
|
|
104
|
+
* background: ${theme === 'light' ? 'white' : 'black'};
|
|
105
|
+
* color: ${theme === 'light' ? 'black' : 'white'};
|
|
106
|
+
* }
|
|
107
|
+
* `);
|
|
108
|
+
*
|
|
109
|
+
* return html`<div>Styled component</div>`;
|
|
110
|
+
* });
|
|
111
|
+
* ```
|
|
112
|
+
*/
|
|
113
|
+
export declare function useStyle(callback: () => string): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Development-only logging utilities
|
|
3
|
+
* These are stripped out in production builds via bundler configuration
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Log error only in development mode
|
|
7
|
+
*/
|
|
8
|
+
export declare function devError(message: string, ...args: any[]): void;
|
|
9
|
+
/**
|
|
10
|
+
* Log warning only in development mode
|
|
11
|
+
*/
|
|
12
|
+
export declare function devWarn(message: string, ...args: any[]): void;
|
|
13
|
+
/**
|
|
14
|
+
* Log info only in development mode
|
|
15
|
+
*/
|
|
16
|
+
export declare function devLog(message: string, ...args: any[]): void;
|
package/dist/runtime/props.d.ts
CHANGED
|
@@ -1,6 +1,18 @@
|
|
|
1
1
|
import type { ComponentConfig, ComponentContext } from "./types";
|
|
2
|
+
export type PropDefinition = {
|
|
3
|
+
type: StringConstructor | NumberConstructor | BooleanConstructor | FunctionConstructor;
|
|
4
|
+
default?: string | number | boolean;
|
|
5
|
+
};
|
|
2
6
|
/**
|
|
3
|
-
* Applies props to the component context.
|
|
7
|
+
* Applies props to the component context using a direct prop definitions object.
|
|
8
|
+
* @param element - The custom element instance.
|
|
9
|
+
* @param propDefinitions - Object mapping prop names to their definitions.
|
|
10
|
+
* @param context - The component context.
|
|
11
|
+
*/
|
|
12
|
+
export declare function applyPropsFromDefinitions(element: HTMLElement, propDefinitions: Record<string, PropDefinition>, context: any): void;
|
|
13
|
+
/**
|
|
14
|
+
* Legacy function for ComponentConfig compatibility.
|
|
15
|
+
* Applies props to the component context using a ComponentConfig.
|
|
4
16
|
* @param element - The custom element instance.
|
|
5
17
|
* @param cfg - The component config.
|
|
6
18
|
* @param context - The component context.
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reactive proxy cache to optimize proxy creation and reuse
|
|
3
|
+
* Uses WeakMap for automatic garbage collection when objects are no longer referenced
|
|
4
|
+
*/
|
|
5
|
+
declare class ReactiveProxyCache {
|
|
6
|
+
private static cache;
|
|
7
|
+
private static arrayHandlerCache;
|
|
8
|
+
private static objectHandlerCache;
|
|
9
|
+
/**
|
|
10
|
+
* Get or create a reactive proxy for an object
|
|
11
|
+
*/
|
|
12
|
+
static getOrCreateProxy<T extends object>(obj: T, reactiveState: any, isArray?: boolean): T;
|
|
13
|
+
/**
|
|
14
|
+
* Get or create a cached array handler
|
|
15
|
+
*/
|
|
16
|
+
private static getOrCreateArrayHandler;
|
|
17
|
+
/**
|
|
18
|
+
* Get or create a cached object handler
|
|
19
|
+
*/
|
|
20
|
+
private static getOrCreateObjectHandler;
|
|
21
|
+
/**
|
|
22
|
+
* Check if an object already has a cached proxy
|
|
23
|
+
*/
|
|
24
|
+
static hasProxy(obj: object): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Clear all cached proxies (useful for testing)
|
|
27
|
+
*/
|
|
28
|
+
static clear(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Get cache statistics (for debugging)
|
|
31
|
+
* Note: WeakMap doesn't provide size, so this is limited
|
|
32
|
+
*/
|
|
33
|
+
static getStats(): {
|
|
34
|
+
hasCachedProxies: boolean;
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Optimized proxy creation utilities
|
|
39
|
+
*/
|
|
40
|
+
declare class ProxyOptimizer {
|
|
41
|
+
private static contextCache;
|
|
42
|
+
/**
|
|
43
|
+
* Create an optimized reactive proxy with minimal overhead
|
|
44
|
+
*/
|
|
45
|
+
static createReactiveProxy<T extends object>(obj: T, onUpdate: () => void, makeReactive: (value: any) => any): T;
|
|
46
|
+
/**
|
|
47
|
+
* Mark an object as a proxy (for optimization)
|
|
48
|
+
*/
|
|
49
|
+
static markAsProxy(obj: any): void;
|
|
50
|
+
}
|
|
51
|
+
export { ReactiveProxyCache, ProxyOptimizer };
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Global reactive system for tracking dependencies and triggering updates
|
|
3
|
+
*/
|
|
4
|
+
declare class ReactiveSystem {
|
|
5
|
+
private currentComponent;
|
|
6
|
+
private componentDependencies;
|
|
7
|
+
private componentRenderFunctions;
|
|
8
|
+
private stateStorage;
|
|
9
|
+
private stateIndexCounter;
|
|
10
|
+
private trackingDisabled;
|
|
11
|
+
private lastWarningTime;
|
|
12
|
+
/**
|
|
13
|
+
* Set the current component being rendered for dependency tracking
|
|
14
|
+
*/
|
|
15
|
+
setCurrentComponent(componentId: string, renderFn: () => void): void;
|
|
16
|
+
/**
|
|
17
|
+
* Clear the current component after rendering
|
|
18
|
+
*/
|
|
19
|
+
clearCurrentComponent(): void;
|
|
20
|
+
/**
|
|
21
|
+
* Temporarily disable dependency tracking
|
|
22
|
+
*/
|
|
23
|
+
disableTracking(): void;
|
|
24
|
+
/**
|
|
25
|
+
* Re-enable dependency tracking
|
|
26
|
+
*/
|
|
27
|
+
enableTracking(): void;
|
|
28
|
+
/**
|
|
29
|
+
* Check if a component is currently rendering
|
|
30
|
+
*/
|
|
31
|
+
isRenderingComponent(): boolean;
|
|
32
|
+
/**
|
|
33
|
+
* Return whether we should emit a render-time warning for the current component.
|
|
34
|
+
* This throttles warnings to avoid spamming the console for legitimate rapid updates.
|
|
35
|
+
*/
|
|
36
|
+
shouldEmitRenderWarning(): boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Execute a function with tracking disabled
|
|
39
|
+
*/
|
|
40
|
+
withoutTracking<T>(fn: () => T): T;
|
|
41
|
+
/**
|
|
42
|
+
* Get or create a state instance for the current component
|
|
43
|
+
*/
|
|
44
|
+
getOrCreateState<T>(initialValue: T): ReactiveState<T>;
|
|
45
|
+
/**
|
|
46
|
+
* Track a dependency for the current component
|
|
47
|
+
*/
|
|
48
|
+
trackDependency(state: ReactiveState<any>): void;
|
|
49
|
+
/**
|
|
50
|
+
* Trigger updates for all components that depend on a state
|
|
51
|
+
*/
|
|
52
|
+
triggerUpdate(state: ReactiveState<any>): void;
|
|
53
|
+
/**
|
|
54
|
+
* Clean up component dependencies when component is destroyed
|
|
55
|
+
*/
|
|
56
|
+
cleanup(componentId: string): void;
|
|
57
|
+
}
|
|
58
|
+
declare const reactiveSystem: ReactiveSystem;
|
|
59
|
+
export { reactiveSystem };
|
|
60
|
+
/**
|
|
61
|
+
* Internal reactive state class
|
|
62
|
+
*/
|
|
63
|
+
export declare class ReactiveState<T> {
|
|
64
|
+
private _value;
|
|
65
|
+
private dependents;
|
|
66
|
+
constructor(initialValue: T);
|
|
67
|
+
get value(): T;
|
|
68
|
+
set value(newValue: T);
|
|
69
|
+
addDependent(componentId: string): void;
|
|
70
|
+
removeDependent(componentId: string): void;
|
|
71
|
+
getDependents(): Set<string>;
|
|
72
|
+
private makeReactive;
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Create reactive state that automatically triggers component re-renders
|
|
76
|
+
* when accessed during render and modified afterwards.
|
|
77
|
+
* Defaults to null if no initial value is provided (Vue-style ref).
|
|
78
|
+
*
|
|
79
|
+
* @example
|
|
80
|
+
* ```ts
|
|
81
|
+
* const counter = ref(0);
|
|
82
|
+
* const user = ref({ name: 'John', age: 30 });
|
|
83
|
+
* const emptyRef = ref(); // defaults to null
|
|
84
|
+
*
|
|
85
|
+
* // Usage in component
|
|
86
|
+
* counter.value++; // triggers re-render
|
|
87
|
+
* user.value.name = 'Jane'; // triggers re-render
|
|
88
|
+
* console.log(emptyRef.value); // null
|
|
89
|
+
* ```
|
|
90
|
+
*/
|
|
91
|
+
export declare function ref<T = null>(initialValue?: T): ReactiveState<T extends undefined ? null : T>;
|
|
92
|
+
/**
|
|
93
|
+
* Create computed state that derives from other reactive state
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* ```ts
|
|
97
|
+
* const firstName = ref('John');
|
|
98
|
+
* const lastName = ref('Doe');
|
|
99
|
+
* const fullName = computed(() => `${firstName.value} ${lastName.value}`);
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
export declare function computed<T>(fn: () => T): {
|
|
103
|
+
readonly value: T;
|
|
104
|
+
};
|
|
105
|
+
/**
|
|
106
|
+
* Create a watcher that runs when dependencies change
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const count = ref(0);
|
|
111
|
+
* watch(() => count.value, (newVal, oldVal) => {
|
|
112
|
+
* console.log(`Count changed from ${oldVal} to ${newVal}`);
|
|
113
|
+
* });
|
|
114
|
+
* ```
|
|
115
|
+
*/
|
|
116
|
+
export declare function watch<T>(source: () => T, callback: (newValue: T, oldValue: T) => void, options?: {
|
|
117
|
+
immediate?: boolean;
|
|
118
|
+
}): () => void;
|
package/dist/runtime/render.d.ts
CHANGED
|
@@ -9,10 +9,10 @@ export declare function renderComponent<S extends object, C extends object, P ex
|
|
|
9
9
|
*/
|
|
10
10
|
export declare function renderOutput<S extends object, C extends object, P extends object, T extends object>(shadowRoot: ShadowRoot | null, output: VNode | VNode[], context: ComponentContext<S, C, P, T>, refs: Refs["refs"], setHtmlString: (html: string) => void): void;
|
|
11
11
|
/**
|
|
12
|
-
* Debounced render request.
|
|
12
|
+
* Debounced render request with infinite loop protection.
|
|
13
13
|
*/
|
|
14
14
|
export declare function requestRender(renderFn: () => void, lastRenderTime: number, renderCount: number, setLastRenderTime: (t: number) => void, setRenderCount: (c: number) => void, renderTimeoutId: ReturnType<typeof setTimeout> | null, setRenderTimeoutId: (id: ReturnType<typeof setTimeout> | null) => void): void;
|
|
15
15
|
/**
|
|
16
16
|
* Applies styles to the shadowRoot.
|
|
17
17
|
*/
|
|
18
|
-
export declare function applyStyle<S extends object, C extends object, P extends object, T extends object>(shadowRoot: ShadowRoot | null,
|
|
18
|
+
export declare function applyStyle<S extends object, C extends object, P extends object, T extends object>(shadowRoot: ShadowRoot | null, context: ComponentContext<S, C, P, T>, htmlString: string, styleSheet: CSSStyleSheet | null, setStyleSheet: (sheet: CSSStyleSheet | null) => void): void;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Update Scheduler for batching DOM updates
|
|
3
|
+
* Prevents excessive re-renders and improves performance
|
|
4
|
+
*/
|
|
5
|
+
declare class UpdateScheduler {
|
|
6
|
+
private pendingUpdates;
|
|
7
|
+
private isFlushScheduled;
|
|
8
|
+
/**
|
|
9
|
+
* Schedule an update to be executed in the next microtask
|
|
10
|
+
* Uses component identity to deduplicate multiple render requests for the same component
|
|
11
|
+
*/
|
|
12
|
+
schedule(update: () => void, componentId?: string): void;
|
|
13
|
+
/**
|
|
14
|
+
* Execute all pending updates
|
|
15
|
+
*/
|
|
16
|
+
private flush;
|
|
17
|
+
/**
|
|
18
|
+
* Get the number of pending updates
|
|
19
|
+
*/
|
|
20
|
+
get pendingCount(): number;
|
|
21
|
+
}
|
|
22
|
+
export declare const updateScheduler: UpdateScheduler;
|
|
23
|
+
/**
|
|
24
|
+
* Schedule a DOM update to be batched with optional component identity
|
|
25
|
+
*/
|
|
26
|
+
export declare function scheduleDOMUpdate(update: () => void, componentId?: string): void;
|
|
27
|
+
export {};
|