@jasonshimmy/custom-elements-runtime 2.5.2 → 2.5.5
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 +115 -40
- package/dist/css/colors.d.ts +14 -0
- package/dist/custom-elements-runtime.cjs.js +6 -1
- package/dist/custom-elements-runtime.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.colors.cjs.js +2 -0
- package/dist/custom-elements-runtime.colors.cjs.js.map +1 -0
- package/dist/custom-elements-runtime.colors.es.js +279 -0
- package/dist/custom-elements-runtime.colors.es.js.map +1 -0
- package/dist/custom-elements-runtime.directive-enhancements.es.js +1 -1
- package/dist/custom-elements-runtime.es.js +258 -166
- package/dist/custom-elements-runtime.es.js.map +1 -1
- package/dist/custom-elements-runtime.event-bus.cjs.js +1 -1
- package/dist/custom-elements-runtime.event-bus.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.event-bus.es.js +28 -25
- package/dist/custom-elements-runtime.event-bus.es.js.map +1 -1
- package/dist/custom-elements-runtime.router.cjs.js +20 -20
- package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.router.es.js +549 -531
- package/dist/custom-elements-runtime.router.es.js.map +1 -1
- package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
- package/dist/custom-elements-runtime.ssr.es.js +12 -8
- package/dist/custom-elements-runtime.ssr.es.js.map +1 -1
- package/dist/custom-elements-runtime.store.cjs.js +1 -1
- package/dist/custom-elements-runtime.store.cjs.js.map +1 -1
- package/dist/custom-elements-runtime.store.es.js +5 -5
- package/dist/custom-elements-runtime.store.es.js.map +1 -1
- package/dist/custom-elements-runtime.transitions.cjs.js +1 -1
- package/dist/custom-elements-runtime.transitions.es.js +1 -1
- package/dist/event-bus.d.ts +17 -4
- package/dist/index.d.ts +13 -5
- package/dist/keep-alive.d.ts +50 -0
- package/dist/{logger-BuUYv7C_.js → logger-BvkEbVM4.js} +15 -11
- package/dist/logger-BvkEbVM4.js.map +1 -0
- package/dist/logger-CSALKaYm.cjs +2 -0
- package/dist/logger-CSALKaYm.cjs.map +1 -0
- package/dist/namespace-helpers-4qeKVqQw.cjs +5 -0
- package/dist/namespace-helpers-4qeKVqQw.cjs.map +1 -0
- package/dist/namespace-helpers-DcD_6_K1.js +989 -0
- package/dist/namespace-helpers-DcD_6_K1.js.map +1 -0
- package/dist/router/active-proxy.d.ts +5 -0
- package/dist/router/component-loader.d.ts +11 -0
- package/dist/router/instance.d.ts +11 -0
- package/dist/router/matcher.d.ts +14 -0
- package/dist/router/path-utils.d.ts +48 -0
- package/dist/router/types.d.ts +134 -0
- package/dist/router.d.ts +6 -208
- package/dist/runtime/builtin-components.d.ts +78 -0
- package/dist/runtime/component/element-class.d.ts +4 -0
- package/dist/runtime/component/factory.d.ts +39 -0
- package/dist/runtime/component/registry.d.ts +16 -0
- package/dist/runtime/component.d.ts +3 -50
- package/dist/runtime/discovery-state.d.ts +30 -0
- package/dist/runtime/hooks.d.ts +115 -0
- package/dist/runtime/logger.d.ts +19 -1
- package/dist/runtime/monitoring/health-monitor.d.ts +22 -65
- package/dist/runtime/reactive.d.ts +39 -7
- package/dist/runtime/render.d.ts +20 -4
- package/dist/runtime/scheduler.d.ts +69 -2
- package/dist/runtime/template-compiler/impl.d.ts +14 -0
- package/dist/runtime/template-compiler/lru-cache.d.ts +20 -0
- package/dist/runtime/template-compiler/props-parser.d.ts +15 -0
- package/dist/runtime/template-compiler/vnode-utils.d.ts +5 -0
- package/dist/runtime/template-compiler.d.ts +5 -28
- package/dist/runtime/types.d.ts +10 -0
- package/dist/runtime/vdom-directives.d.ts +71 -0
- package/dist/runtime/vdom-helpers.d.ts +126 -0
- package/dist/runtime/vdom-patch.d.ts +67 -0
- package/dist/runtime/vdom.d.ts +16 -140
- package/dist/ssr.d.ts +2 -1
- package/dist/teleport.d.ts +68 -0
- package/dist/template-compiler-CA4YRaBu.cjs +23 -0
- package/dist/template-compiler-CA4YRaBu.cjs.map +1 -0
- package/dist/template-compiler-CJFwjLCP.js +3981 -0
- package/dist/template-compiler-CJFwjLCP.js.map +1 -0
- package/dist/transitions-DPZiuXb9.cjs +330 -0
- package/dist/transitions-DPZiuXb9.cjs.map +1 -0
- package/dist/{transitions-Bx0Nc9zR.js → transitions-Di5wW9yc.js} +1072 -632
- package/dist/transitions-Di5wW9yc.js.map +1 -0
- package/dist/transitions.d.ts +1 -1
- package/package.json +18 -11
- package/dist/logger-BuUYv7C_.js.map +0 -1
- package/dist/logger-DiXdWaF-.cjs +0 -2
- package/dist/logger-DiXdWaF-.cjs.map +0 -1
- package/dist/namespace-helpers-BCVTzhAO.cjs +0 -5
- package/dist/namespace-helpers-BCVTzhAO.cjs.map +0 -1
- package/dist/namespace-helpers-CF28TyaG.js +0 -786
- package/dist/namespace-helpers-CF28TyaG.js.map +0 -1
- package/dist/template-compiler-CXHEnaBh.cjs +0 -17
- package/dist/template-compiler-CXHEnaBh.cjs.map +0 -1
- package/dist/template-compiler-DD_VZrte.js +0 -3729
- package/dist/template-compiler-DD_VZrte.js.map +0 -1
- package/dist/transitions-Bx0Nc9zR.js.map +0 -1
- package/dist/transitions-DfcqL-X4.cjs +0 -302
- package/dist/transitions-DfcqL-X4.cjs.map +0 -1
package/dist/router.d.ts
CHANGED
|
@@ -1,208 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export
|
|
7
|
-
new (...args: unknown[]): unknown;
|
|
8
|
-
} | ((...args: unknown[]) => unknown);
|
|
9
|
-
/**
|
|
10
|
-
* Represents the current state of the router.
|
|
11
|
-
*/
|
|
12
|
-
export interface RouteState {
|
|
13
|
-
/** The current path without base, query, or fragment */
|
|
14
|
-
path: string;
|
|
15
|
-
/** Route parameters extracted from dynamic path segments */
|
|
16
|
-
params: Record<string, string>;
|
|
17
|
-
/** Query parameters from the URL search string */
|
|
18
|
-
query: Record<string, string>;
|
|
19
|
-
/** Optional fragment (hash) portion of the URL, without the leading '#' */
|
|
20
|
-
fragment?: string;
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Result type for route guards.
|
|
24
|
-
* - `true`: Allow navigation
|
|
25
|
-
* - `false`: Block navigation
|
|
26
|
-
* - `string`: Redirect to the specified path
|
|
27
|
-
*/
|
|
28
|
-
export type GuardResult = boolean | string | Promise<boolean | string>;
|
|
29
|
-
/**
|
|
30
|
-
* Defines a route in the router configuration.
|
|
31
|
-
*/
|
|
32
|
-
export interface Route {
|
|
33
|
-
/** The path pattern for this route (e.g., '/users/:id') */
|
|
34
|
-
path: string;
|
|
35
|
-
/** Statically available component (already imported) */
|
|
36
|
-
component?: string | (() => unknown);
|
|
37
|
-
/** Lazy loader that resolves to something renderable */
|
|
38
|
-
load?: () => Promise<{
|
|
39
|
-
default: string | HTMLElement | ((...args: unknown[]) => unknown);
|
|
40
|
-
}>;
|
|
41
|
-
/** Guard that runs before matching — return false to cancel, or a string to redirect */
|
|
42
|
-
beforeEnter?: (to: RouteState, from: RouteState) => GuardResult;
|
|
43
|
-
/** Guard that runs right before navigation commits — can cancel or redirect */
|
|
44
|
-
onEnter?: (to: RouteState, from: RouteState) => GuardResult;
|
|
45
|
-
/** Hook that runs after navigation completes — cannot cancel */
|
|
46
|
-
afterEnter?: (to: RouteState, from: RouteState) => void;
|
|
47
|
-
}
|
|
48
|
-
/**
|
|
49
|
-
* Props interface for the router-link component.
|
|
50
|
-
*/
|
|
51
|
-
export interface RouterLinkProps {
|
|
52
|
-
/** Target path or URL to navigate to */
|
|
53
|
-
to: string;
|
|
54
|
-
/** HTML tag to render ('a' or 'button') */
|
|
55
|
-
tag: string;
|
|
56
|
-
/** Whether to use replace instead of push navigation */
|
|
57
|
-
replace: boolean;
|
|
58
|
-
/** Whether to use exact matching for active state */
|
|
59
|
-
exact: boolean;
|
|
60
|
-
/** CSS class applied when link is active */
|
|
61
|
-
activeClass: string;
|
|
62
|
-
/** CSS class applied when link is exactly active */
|
|
63
|
-
exactActiveClass: string;
|
|
64
|
-
/** Value for aria-current attribute when exactly active */
|
|
65
|
-
ariaCurrentValue: string;
|
|
66
|
-
/** Whether the link is disabled */
|
|
67
|
-
disabled: boolean;
|
|
68
|
-
/** Whether this is an external link */
|
|
69
|
-
external: boolean;
|
|
70
|
-
/** Additional CSS classes */
|
|
71
|
-
class?: string;
|
|
72
|
-
/** Additional inline styles */
|
|
73
|
-
style?: string;
|
|
74
|
-
}
|
|
75
|
-
export interface RouterLinkComputed {
|
|
76
|
-
current: RouteState;
|
|
77
|
-
isExactActive: boolean;
|
|
78
|
-
isActive: boolean;
|
|
79
|
-
className: string;
|
|
80
|
-
ariaCurrent: string;
|
|
81
|
-
isButton: boolean;
|
|
82
|
-
disabledAttr: string;
|
|
83
|
-
externalAttr: string;
|
|
84
|
-
}
|
|
85
|
-
/**
|
|
86
|
-
* Configuration object for initializing the router.
|
|
87
|
-
*/
|
|
88
|
-
export interface RouterConfig {
|
|
89
|
-
/** Array of route definitions */
|
|
90
|
-
routes: Route[];
|
|
91
|
-
/** Base path for all routes */
|
|
92
|
-
base?: string;
|
|
93
|
-
/** Initial URL for SSR mode */
|
|
94
|
-
initialUrl?: string;
|
|
95
|
-
/** Configure fragment (hash) scrolling behavior */
|
|
96
|
-
scrollToFragment?: boolean | {
|
|
97
|
-
/** Whether fragment scrolling is enabled */
|
|
98
|
-
enabled?: boolean;
|
|
99
|
-
/** Offset in pixels to account for fixed headers */
|
|
100
|
-
offset?: number;
|
|
101
|
-
/** Timeout in ms to wait for element to appear */
|
|
102
|
-
timeoutMs?: number;
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
/**
|
|
106
|
-
* Parse URL search string into query parameters object.
|
|
107
|
-
* @param search - The search string (with or without leading '?')
|
|
108
|
-
* @returns Object with query parameter key-value pairs
|
|
109
|
-
*/
|
|
110
|
-
export declare const parseQuery: (search: string) => Record<string, string>;
|
|
111
|
-
/**
|
|
112
|
-
* Serialize query parameters object into URL search string.
|
|
113
|
-
* @param q - Query parameters object
|
|
114
|
-
* @returns Search string with leading '?' or empty string
|
|
115
|
-
*/
|
|
116
|
-
export declare const serializeQuery: (q: Record<string, string> | undefined) => string;
|
|
117
|
-
/**
|
|
118
|
-
* Normalize a path for consistent route matching.
|
|
119
|
-
* Ensures leading slash, removes trailing slash, and collapses duplicate slashes.
|
|
120
|
-
* @param p - Path string to normalize
|
|
121
|
-
* @returns Normalized path string
|
|
122
|
-
*/
|
|
123
|
-
export declare function normalizePathForRoute(p: string): string;
|
|
124
|
-
export declare const matchRoute: (routes: Route[], path: string) => {
|
|
125
|
-
route: Route | null;
|
|
126
|
-
params: Record<string, string>;
|
|
127
|
-
};
|
|
128
|
-
/**
|
|
129
|
-
* Loads a route's component, supporting both static and async.
|
|
130
|
-
* @param route Route object
|
|
131
|
-
* @returns Promise resolving to the component
|
|
132
|
-
*/
|
|
133
|
-
export declare function resolveRouteComponent(route: Route): Promise<string | HTMLElement | ((...args: unknown[]) => unknown)>;
|
|
134
|
-
export declare function useRouter(config: RouterConfig): {
|
|
135
|
-
_cleanupScrollState: () => void;
|
|
136
|
-
store: Store<RouteState>;
|
|
137
|
-
push: (path: string) => Promise<void>;
|
|
138
|
-
replace: (path: string) => Promise<void>;
|
|
139
|
-
back: () => void;
|
|
140
|
-
subscribe: (listener: (state: RouteState) => void) => () => void;
|
|
141
|
-
matchRoute: (path: string) => {
|
|
142
|
-
route: Route | null;
|
|
143
|
-
params: Record<string, string>;
|
|
144
|
-
};
|
|
145
|
-
getCurrent: () => RouteState;
|
|
146
|
-
resolveRouteComponent: typeof resolveRouteComponent;
|
|
147
|
-
base: string;
|
|
148
|
-
scrollToFragment: (frag?: string) => Promise<boolean>;
|
|
149
|
-
};
|
|
150
|
-
/**
|
|
151
|
-
* Explicit Router instance type exported for clearer typing across the
|
|
152
|
-
* codebase and tests.
|
|
153
|
-
*/
|
|
154
|
-
/**
|
|
155
|
-
* Router instance interface providing navigation and state management.
|
|
156
|
-
*/
|
|
157
|
-
export interface Router {
|
|
158
|
-
/** Reactive store containing current route state */
|
|
159
|
-
store: Store<RouteState>;
|
|
160
|
-
/** Navigate to a path (adds to history) */
|
|
161
|
-
push: (path: string) => Promise<void>;
|
|
162
|
-
/** Navigate to a path (replaces current history entry) */
|
|
163
|
-
replace: (path: string) => Promise<void>;
|
|
164
|
-
/** Go back in browser history */
|
|
165
|
-
back: () => void;
|
|
166
|
-
/** Subscribe to route state changes */
|
|
167
|
-
subscribe: Store<RouteState>['subscribe'];
|
|
168
|
-
/** Match a path against configured routes */
|
|
169
|
-
matchRoute: (path: string) => {
|
|
170
|
-
route: Route | null;
|
|
171
|
-
params: Record<string, string>;
|
|
172
|
-
};
|
|
173
|
-
/** Get current route state */
|
|
174
|
-
getCurrent: () => RouteState;
|
|
175
|
-
/** Resolve a route's component */
|
|
176
|
-
resolveRouteComponent: typeof resolveRouteComponent;
|
|
177
|
-
/** Base path for the router */
|
|
178
|
-
base: string;
|
|
179
|
-
/** Scroll to a fragment/hash element */
|
|
180
|
-
scrollToFragment: (frag?: string) => Promise<boolean>;
|
|
181
|
-
}
|
|
182
|
-
export declare function matchRouteSSR(routes: Route[], path: string): {
|
|
183
|
-
route: Route | null;
|
|
184
|
-
params: Record<string, string>;
|
|
185
|
-
};
|
|
186
|
-
export declare const activeRouterProxy: Router;
|
|
187
|
-
/**
|
|
188
|
-
* Singleton router instance for global access.
|
|
189
|
-
*
|
|
190
|
-
* Define here to prevent circular dependency
|
|
191
|
-
* issue with component.
|
|
192
|
-
*/
|
|
193
|
-
export declare function initRouter(config: RouterConfig): {
|
|
194
|
-
_cleanupScrollState: () => void;
|
|
195
|
-
store: Store<RouteState>;
|
|
196
|
-
push: (path: string) => Promise<void>;
|
|
197
|
-
replace: (path: string) => Promise<void>;
|
|
198
|
-
back: () => void;
|
|
199
|
-
subscribe: (listener: (state: RouteState) => void) => () => void;
|
|
200
|
-
matchRoute: (path: string) => {
|
|
201
|
-
route: Route | null;
|
|
202
|
-
params: Record<string, string>;
|
|
203
|
-
};
|
|
204
|
-
getCurrent: () => RouteState;
|
|
205
|
-
resolveRouteComponent: typeof resolveRouteComponent;
|
|
206
|
-
base: string;
|
|
207
|
-
scrollToFragment: (frag?: string) => Promise<boolean>;
|
|
208
|
-
};
|
|
1
|
+
export type { RouteComponent, RouteState, GuardResult, Route, RouterLinkProps, RouterLinkComputed, RouterConfig, Router, } from './router/types';
|
|
2
|
+
export { parseQuery, serializeQuery, normalizePathForRoute, DEFAULT_SCROLL_CONFIG, isDangerousScheme, isAbsoluteUrl, safeDecode, canonicalizeBase, } from './router/path-utils';
|
|
3
|
+
export { matchRoute, matchRouteSSR, findMatchedRoute } from './router/matcher';
|
|
4
|
+
export { clearComponentCache, resolveRouteComponent, } from './router/component-loader';
|
|
5
|
+
export { activeRouterProxy } from './router/active-proxy';
|
|
6
|
+
export { useRouter, initRouter } from './router/instance';
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in utility components provided by the custom-elements runtime.
|
|
3
|
+
*
|
|
4
|
+
* These components are registered automatically when this module is imported.
|
|
5
|
+
* They are designed to be minimal, tree-shakeable, and zero-dependency.
|
|
6
|
+
*
|
|
7
|
+
* Included components:
|
|
8
|
+
* - `<cer-suspense>` — Shows a fallback while async work is pending
|
|
9
|
+
* - `<cer-error-boundary>` — Catches render errors and shows a fallback UI
|
|
10
|
+
* - `<cer-keep-alive>` — Preserves component state across DOM removal/re-insertion
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* A built-in component that conditionally renders either the default slot
|
|
14
|
+
* content or the `fallback` slot content, controlled by the `pending` prop.
|
|
15
|
+
*
|
|
16
|
+
* Use the `pending` attribute/property to signal that async work is in
|
|
17
|
+
* progress; the component will swap to the `fallback` slot until `pending`
|
|
18
|
+
* becomes falsy.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```html
|
|
22
|
+
* <cer-suspense pending>
|
|
23
|
+
* <!-- shown when pending=false -->
|
|
24
|
+
* <my-async-content></my-async-content>
|
|
25
|
+
*
|
|
26
|
+
* <!-- shown while pending=true -->
|
|
27
|
+
* <div slot="fallback">Loading…</div>
|
|
28
|
+
* </cer-suspense>
|
|
29
|
+
* ```
|
|
30
|
+
*
|
|
31
|
+
* @example Programmatic usage
|
|
32
|
+
* ```ts
|
|
33
|
+
* component('my-data-loader', () => {
|
|
34
|
+
* const pending = ref(true);
|
|
35
|
+
* useOnConnected(async () => {
|
|
36
|
+
* await fetchData();
|
|
37
|
+
* pending.value = false;
|
|
38
|
+
* });
|
|
39
|
+
* return html`
|
|
40
|
+
* <cer-suspense pending="${pending.value}">
|
|
41
|
+
* <my-data-view></my-data-view>
|
|
42
|
+
* <div slot="fallback">Loading data…</div>
|
|
43
|
+
* </cer-suspense>
|
|
44
|
+
* `;
|
|
45
|
+
* });
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
export declare function registerSuspense(): void;
|
|
49
|
+
/**
|
|
50
|
+
* A built-in component that catches errors thrown during child component
|
|
51
|
+
* rendering and displays a fallback UI instead of crashing the page.
|
|
52
|
+
*
|
|
53
|
+
* Errors are caught via the `useOnError` lifecycle hook. Once an error is
|
|
54
|
+
* caught the component switches to showing the `fallback` named slot (or a
|
|
55
|
+
* default "Something went wrong" message if no fallback slot is provided).
|
|
56
|
+
*
|
|
57
|
+
* Call the custom `reset()` method on the element to clear the error and
|
|
58
|
+
* attempt re-rendering the default slot.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* ```html
|
|
62
|
+
* <cer-error-boundary>
|
|
63
|
+
* <my-risky-component></my-risky-component>
|
|
64
|
+
*
|
|
65
|
+
* <div slot="fallback">
|
|
66
|
+
* <p>Something went wrong. <button onclick="this.closest('cer-error-boundary').reset()">Retry</button></p>
|
|
67
|
+
* </div>
|
|
68
|
+
* </cer-error-boundary>
|
|
69
|
+
* ```
|
|
70
|
+
*/
|
|
71
|
+
export declare function registerErrorBoundary(): void;
|
|
72
|
+
/**
|
|
73
|
+
* Register all built-in components (`cer-suspense`, `cer-error-boundary`,
|
|
74
|
+
* `cer-keep-alive`).
|
|
75
|
+
* Safe to call multiple times — each registration is guarded by a
|
|
76
|
+
* `customElements.get()` check.
|
|
77
|
+
*/
|
|
78
|
+
export declare function registerBuiltinComponents(): void;
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ComponentConfig } from '../types';
|
|
2
|
+
export declare function createElementClass<S extends object, C extends object, P extends object, T extends object = object>(tag: string, config: ComponentConfig<S, C, P, T>): CustomElementConstructor | {
|
|
3
|
+
new (): object;
|
|
4
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { VNode } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Streamlined functional component API with automatic reactive props and lifecycle hooks.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```ts
|
|
7
|
+
* // Simple component with no parameters
|
|
8
|
+
* component('simple-header', () => {
|
|
9
|
+
* return html`<h1>Hello World</h1>`;
|
|
10
|
+
* });
|
|
11
|
+
*
|
|
12
|
+
* // With props using useProps() hook
|
|
13
|
+
* component('with-props', () => {
|
|
14
|
+
* const { message } = useProps({ message: 'Hello' });
|
|
15
|
+
* return html`<div>${message}</div>`;
|
|
16
|
+
* });
|
|
17
|
+
*
|
|
18
|
+
* // With props and lifecycle hooks
|
|
19
|
+
* component('my-switch', () => {
|
|
20
|
+
* const { modelValue, label } = useProps({ modelValue: false, label: '' });
|
|
21
|
+
* const emit = useEmit();
|
|
22
|
+
*
|
|
23
|
+
* useOnConnected(() => console.log('Switch connected!'));
|
|
24
|
+
* useOnDisconnected(() => console.log('Switch disconnected!'));
|
|
25
|
+
*
|
|
26
|
+
* return html`
|
|
27
|
+
* <label>
|
|
28
|
+
* ${label}
|
|
29
|
+
* <input
|
|
30
|
+
* type="checkbox"
|
|
31
|
+
* :checked="${modelValue}"
|
|
32
|
+
* @change="${(e) => emit('update:modelValue', e.target.checked)}"
|
|
33
|
+
* />
|
|
34
|
+
* </label>
|
|
35
|
+
* `;
|
|
36
|
+
* });
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
export declare function component(tag: string, renderFn: () => VNode | VNode[] | Promise<VNode | VNode[]>): void;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { ComponentConfig } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* @internal
|
|
4
|
+
* Runtime registry of component configs.
|
|
5
|
+
* NOTE: This is an internal implementation detail. Do not import from the
|
|
6
|
+
* published package in consumer code — it is intended for runtime/HMR and
|
|
7
|
+
* internal tests only. Consumers should use the public `component` API.
|
|
8
|
+
*/
|
|
9
|
+
export declare const registry: Map<string, ComponentConfig<object, object, object>>;
|
|
10
|
+
/**
|
|
11
|
+
* Lazily initialize the global registry slot with SSR safety.
|
|
12
|
+
* This avoids performing a write to globalThis at module-import time
|
|
13
|
+
* (which is a side-effect that prevents bundlers from tree-shaking).
|
|
14
|
+
* Enhanced with SSR detection and multi-tenant safety.
|
|
15
|
+
*/
|
|
16
|
+
export declare function initGlobalRegistryIfNeeded(): void;
|
|
@@ -1,50 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
* Runtime registry of component configs.
|
|
5
|
-
* NOTE: This is an internal implementation detail. Do not import from the
|
|
6
|
-
* published package in consumer code — it is intended for runtime/HMR and
|
|
7
|
-
* internal tests only. Consumers should use the public `component` API.
|
|
8
|
-
*/
|
|
9
|
-
export declare const registry: Map<string, ComponentConfig<object, object, object>>;
|
|
10
|
-
export declare function createElementClass<S extends object, C extends object, P extends object, T extends object = object>(tag: string, config: ComponentConfig<S, C, P, T>): CustomElementConstructor | {
|
|
11
|
-
new (): object;
|
|
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 using useProps() hook
|
|
24
|
-
* component('with-props', () => {
|
|
25
|
-
* const { message } = useProps({ message: 'Hello' });
|
|
26
|
-
* return html`<div>${message}</div>`;
|
|
27
|
-
* });
|
|
28
|
-
*
|
|
29
|
-
* // With props and lifecycle hooks
|
|
30
|
-
* component('my-switch', () => {
|
|
31
|
-
* const { modelValue, label } = useProps({ modelValue: false, label: '' });
|
|
32
|
-
* const emit = useEmit();
|
|
33
|
-
*
|
|
34
|
-
* useOnConnected(() => console.log('Switch connected!'));
|
|
35
|
-
* useOnDisconnected(() => console.log('Switch disconnected!'));
|
|
36
|
-
*
|
|
37
|
-
* return html`
|
|
38
|
-
* <label>
|
|
39
|
-
* ${label}
|
|
40
|
-
* <input
|
|
41
|
-
* type="checkbox"
|
|
42
|
-
* :checked="${modelValue}"
|
|
43
|
-
* @change="${(e) => emit('update:modelValue', e.target.checked)}"
|
|
44
|
-
* />
|
|
45
|
-
* </label>
|
|
46
|
-
* `;
|
|
47
|
-
* });
|
|
48
|
-
* ```
|
|
49
|
-
*/
|
|
50
|
-
export declare function component(tag: string, renderFn: () => VNode | VNode[] | Promise<VNode | VNode[]>): void;
|
|
1
|
+
export { registry } from './component/registry';
|
|
2
|
+
export { createElementClass } from './component/element-class';
|
|
3
|
+
export { component } from './component/factory';
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* discovery-state.ts
|
|
3
|
+
*
|
|
4
|
+
* Isolated discovery-render flag. Extracted from hooks.ts to break the
|
|
5
|
+
* circular dependency between hooks.ts and reactive.ts — both modules need
|
|
6
|
+
* to check `isDiscoveryRender()`, but hooks.ts also imports from reactive.ts.
|
|
7
|
+
*
|
|
8
|
+
* All side-effectful hooks (watchEffect, watch, useOnConnected, useStyle,
|
|
9
|
+
* provide, inject, useEmit, …) must guard their setup with
|
|
10
|
+
* `isDiscoveryRender()` and return early / return no-ops when it is true.
|
|
11
|
+
*/
|
|
12
|
+
/**
|
|
13
|
+
* Returns `true` while a discovery render is in progress.
|
|
14
|
+
* Used by `html` tagged templates and hooks to short-circuit side effects.
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare function isDiscoveryRender(): boolean;
|
|
18
|
+
/**
|
|
19
|
+
* Mark the start of a discovery render pass.
|
|
20
|
+
* Call this immediately before invoking the render function for the first time
|
|
21
|
+
* (before `useProps` prop-name collection).
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
export declare function beginDiscoveryRender(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Mark the end of a discovery render pass.
|
|
27
|
+
* Call this in a `finally` block after the discovery render function returns.
|
|
28
|
+
* @internal
|
|
29
|
+
*/
|
|
30
|
+
export declare function endDiscoveryRender(): void;
|
package/dist/runtime/hooks.d.ts
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
* Context-based hooks for functional components
|
|
3
3
|
* Provides React-like hooks with perfect TypeScript inference
|
|
4
4
|
*/
|
|
5
|
+
export { beginDiscoveryRender, endDiscoveryRender } from './discovery-state';
|
|
6
|
+
/**
|
|
7
|
+
* Returns true while a discovery render is in progress.
|
|
8
|
+
* Used by `html` and other primitives to short-circuit side effects.
|
|
9
|
+
* @internal
|
|
10
|
+
*/
|
|
11
|
+
export declare function isDiscoveryRender(): boolean;
|
|
5
12
|
/**
|
|
6
13
|
* Set the current component context (called internally during render)
|
|
7
14
|
* @internal
|
|
@@ -12,6 +19,12 @@ export declare function setCurrentComponentContext(context: Record<string, unkno
|
|
|
12
19
|
* @internal
|
|
13
20
|
*/
|
|
14
21
|
export declare function clearCurrentComponentContext(): void;
|
|
22
|
+
/**
|
|
23
|
+
* Get the current component context. Useful for advanced composable patterns
|
|
24
|
+
* that need to access or pass the context explicitly.
|
|
25
|
+
* @internal
|
|
26
|
+
*/
|
|
27
|
+
export declare function getCurrentComponentContext(): Record<string, unknown> | null;
|
|
15
28
|
/**
|
|
16
29
|
* Get the emit function for the current component
|
|
17
30
|
* Must be called during component render
|
|
@@ -137,3 +150,105 @@ export declare function useProps<T extends Record<string, unknown>>(defaults: T)
|
|
|
137
150
|
* ```
|
|
138
151
|
*/
|
|
139
152
|
export declare function useStyle(callback: () => string): void;
|
|
153
|
+
/**
|
|
154
|
+
* Store a value under a key so that descendant components can retrieve it
|
|
155
|
+
* with `inject()`. Must be called during component render.
|
|
156
|
+
*
|
|
157
|
+
* @example
|
|
158
|
+
* ```ts
|
|
159
|
+
* component('theme-provider', () => {
|
|
160
|
+
* provide('theme', 'dark');
|
|
161
|
+
* return html`<slot></slot>`;
|
|
162
|
+
* });
|
|
163
|
+
* ```
|
|
164
|
+
*/
|
|
165
|
+
export declare function provide<T>(key: string | symbol, value: T): void;
|
|
166
|
+
/**
|
|
167
|
+
* Retrieve a value provided by an ancestor component. Traverses the shadow
|
|
168
|
+
* DOM tree upward through ShadowRoot host elements looking for the nearest
|
|
169
|
+
* `provide()` call with the matching key. Returns `defaultValue` (or
|
|
170
|
+
* `undefined`) when no provider is found. Must be called during render.
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* ```ts
|
|
174
|
+
* component('themed-button', () => {
|
|
175
|
+
* const theme = inject<string>('theme', 'light');
|
|
176
|
+
* return html`<button class="btn-${theme}">Click</button>`;
|
|
177
|
+
* });
|
|
178
|
+
* ```
|
|
179
|
+
*/
|
|
180
|
+
export declare function inject<T>(key: string | symbol, defaultValue?: T): T | undefined;
|
|
181
|
+
/**
|
|
182
|
+
* Execute a function that calls hooks (useOnConnected, useOnDisconnected, etc.)
|
|
183
|
+
* using an explicit component context rather than requiring the call to happen
|
|
184
|
+
* directly inside a render function. This enables composable utility functions
|
|
185
|
+
* that register lifecycle callbacks from outside the render body.
|
|
186
|
+
*
|
|
187
|
+
* @example
|
|
188
|
+
* ```ts
|
|
189
|
+
* function useLogger(label: string) {
|
|
190
|
+
* return createComposable(() => {
|
|
191
|
+
* useOnConnected(() => console.log(`${label} connected`));
|
|
192
|
+
* useOnDisconnected(() => console.log(`${label} disconnected`));
|
|
193
|
+
* });
|
|
194
|
+
* }
|
|
195
|
+
*
|
|
196
|
+
* component('my-comp', () => {
|
|
197
|
+
* const stopLogger = useLogger('my-comp');
|
|
198
|
+
* stopLogger(context); // pass the component context explicitly
|
|
199
|
+
* return html`<div>Hello</div>`;
|
|
200
|
+
* });
|
|
201
|
+
* ```
|
|
202
|
+
*
|
|
203
|
+
* More commonly, use it as a direct wrapper inside render:
|
|
204
|
+
* ```ts
|
|
205
|
+
* component('my-comp', () => {
|
|
206
|
+
* // Accepts context automatically from getCurrentComponentContext()
|
|
207
|
+
* createComposable(() => {
|
|
208
|
+
* useOnConnected(() => console.log('connected from composable'));
|
|
209
|
+
* })();
|
|
210
|
+
* return html`<div>Hello</div>`;
|
|
211
|
+
* });
|
|
212
|
+
* ```
|
|
213
|
+
*/
|
|
214
|
+
export declare function createComposable<T>(fn: () => T): (ctx?: Record<string, unknown>) => T;
|
|
215
|
+
/**
|
|
216
|
+
* Expose a public interface from the current component so that parent
|
|
217
|
+
* components holding a template ref to this element can call its methods
|
|
218
|
+
* or read its properties. Must be called during component render.
|
|
219
|
+
*
|
|
220
|
+
* @example
|
|
221
|
+
* ```ts
|
|
222
|
+
* component('my-counter', () => {
|
|
223
|
+
* const count = ref(0);
|
|
224
|
+
* useExpose({ increment: () => count.value++, get count() { return count.value; } });
|
|
225
|
+
* return html`<div>${count.value}</div>`;
|
|
226
|
+
* });
|
|
227
|
+
*
|
|
228
|
+
* // Parent: counterRef.value.increment()
|
|
229
|
+
* ```
|
|
230
|
+
*/
|
|
231
|
+
export declare function useExpose<T extends Record<string, unknown>>(exposed: T): void;
|
|
232
|
+
/**
|
|
233
|
+
* Access named slots provided to the current component. Returns helpers to
|
|
234
|
+
* check slot presence and retrieve slotted elements. Must be called during
|
|
235
|
+
* component render.
|
|
236
|
+
*
|
|
237
|
+
* @example
|
|
238
|
+
* ```ts
|
|
239
|
+
* component('my-card', () => {
|
|
240
|
+
* const slots = useSlots();
|
|
241
|
+
* return html`
|
|
242
|
+
* <div class="card">
|
|
243
|
+
* <slot></slot>
|
|
244
|
+
* ${slots.has('footer') ? html`<footer><slot name="footer"></slot></footer>` : ''}
|
|
245
|
+
* </div>
|
|
246
|
+
* `;
|
|
247
|
+
* });
|
|
248
|
+
* ```
|
|
249
|
+
*/
|
|
250
|
+
export declare function useSlots(): {
|
|
251
|
+
has(name?: string): boolean;
|
|
252
|
+
getNodes(name?: string): Element[];
|
|
253
|
+
names(): string[];
|
|
254
|
+
};
|
package/dist/runtime/logger.d.ts
CHANGED
|
@@ -6,6 +6,14 @@
|
|
|
6
6
|
* Programmatically toggle dev-mode logging at runtime.
|
|
7
7
|
* Prefer setting `globalThis.__CE_RUNTIME_DEV__ = true` before importing
|
|
8
8
|
* the runtime so logs are enabled as early as possible.
|
|
9
|
+
*
|
|
10
|
+
* @param v - `true` to enable dev logging, `false` to disable it.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* import { setDevMode } from '@jasonshimmy/custom-elements-runtime';
|
|
15
|
+
* setDevMode(true); // enable verbose dev logs
|
|
16
|
+
* ```
|
|
9
17
|
*/
|
|
10
18
|
export declare function setDevMode(v: boolean): void;
|
|
11
19
|
/**
|
|
@@ -17,6 +25,16 @@ export declare function devError(message: string, ...args: unknown[]): void;
|
|
|
17
25
|
*/
|
|
18
26
|
export declare function devWarn(message: string, ...args: unknown[]): void;
|
|
19
27
|
/**
|
|
20
|
-
* Log
|
|
28
|
+
* Log an informational message only in development mode.
|
|
29
|
+
* No-ops in production builds or when dev mode is disabled.
|
|
30
|
+
*
|
|
31
|
+
* @param message - Message to log.
|
|
32
|
+
* @param args - Additional values to pass to `console.log`.
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* ```ts
|
|
36
|
+
* import { devLog } from '@jasonshimmy/custom-elements-runtime';
|
|
37
|
+
* devLog('[my-component] mounted', { props });
|
|
38
|
+
* ```
|
|
21
39
|
*/
|
|
22
40
|
export declare function devLog(message: string, ...args: unknown[]): void;
|