@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.
Files changed (94) hide show
  1. package/README.md +115 -40
  2. package/dist/css/colors.d.ts +14 -0
  3. package/dist/custom-elements-runtime.cjs.js +6 -1
  4. package/dist/custom-elements-runtime.cjs.js.map +1 -1
  5. package/dist/custom-elements-runtime.colors.cjs.js +2 -0
  6. package/dist/custom-elements-runtime.colors.cjs.js.map +1 -0
  7. package/dist/custom-elements-runtime.colors.es.js +279 -0
  8. package/dist/custom-elements-runtime.colors.es.js.map +1 -0
  9. package/dist/custom-elements-runtime.directive-enhancements.es.js +1 -1
  10. package/dist/custom-elements-runtime.es.js +258 -166
  11. package/dist/custom-elements-runtime.es.js.map +1 -1
  12. package/dist/custom-elements-runtime.event-bus.cjs.js +1 -1
  13. package/dist/custom-elements-runtime.event-bus.cjs.js.map +1 -1
  14. package/dist/custom-elements-runtime.event-bus.es.js +28 -25
  15. package/dist/custom-elements-runtime.event-bus.es.js.map +1 -1
  16. package/dist/custom-elements-runtime.router.cjs.js +20 -20
  17. package/dist/custom-elements-runtime.router.cjs.js.map +1 -1
  18. package/dist/custom-elements-runtime.router.es.js +549 -531
  19. package/dist/custom-elements-runtime.router.es.js.map +1 -1
  20. package/dist/custom-elements-runtime.ssr.cjs.js +1 -1
  21. package/dist/custom-elements-runtime.ssr.es.js +12 -8
  22. package/dist/custom-elements-runtime.ssr.es.js.map +1 -1
  23. package/dist/custom-elements-runtime.store.cjs.js +1 -1
  24. package/dist/custom-elements-runtime.store.cjs.js.map +1 -1
  25. package/dist/custom-elements-runtime.store.es.js +5 -5
  26. package/dist/custom-elements-runtime.store.es.js.map +1 -1
  27. package/dist/custom-elements-runtime.transitions.cjs.js +1 -1
  28. package/dist/custom-elements-runtime.transitions.es.js +1 -1
  29. package/dist/event-bus.d.ts +17 -4
  30. package/dist/index.d.ts +13 -5
  31. package/dist/keep-alive.d.ts +50 -0
  32. package/dist/{logger-BuUYv7C_.js → logger-BvkEbVM4.js} +15 -11
  33. package/dist/logger-BvkEbVM4.js.map +1 -0
  34. package/dist/logger-CSALKaYm.cjs +2 -0
  35. package/dist/logger-CSALKaYm.cjs.map +1 -0
  36. package/dist/namespace-helpers-4qeKVqQw.cjs +5 -0
  37. package/dist/namespace-helpers-4qeKVqQw.cjs.map +1 -0
  38. package/dist/namespace-helpers-DcD_6_K1.js +989 -0
  39. package/dist/namespace-helpers-DcD_6_K1.js.map +1 -0
  40. package/dist/router/active-proxy.d.ts +5 -0
  41. package/dist/router/component-loader.d.ts +11 -0
  42. package/dist/router/instance.d.ts +11 -0
  43. package/dist/router/matcher.d.ts +14 -0
  44. package/dist/router/path-utils.d.ts +48 -0
  45. package/dist/router/types.d.ts +134 -0
  46. package/dist/router.d.ts +6 -208
  47. package/dist/runtime/builtin-components.d.ts +78 -0
  48. package/dist/runtime/component/element-class.d.ts +4 -0
  49. package/dist/runtime/component/factory.d.ts +39 -0
  50. package/dist/runtime/component/registry.d.ts +16 -0
  51. package/dist/runtime/component.d.ts +3 -50
  52. package/dist/runtime/discovery-state.d.ts +30 -0
  53. package/dist/runtime/hooks.d.ts +115 -0
  54. package/dist/runtime/logger.d.ts +19 -1
  55. package/dist/runtime/monitoring/health-monitor.d.ts +22 -65
  56. package/dist/runtime/reactive.d.ts +39 -7
  57. package/dist/runtime/render.d.ts +20 -4
  58. package/dist/runtime/scheduler.d.ts +69 -2
  59. package/dist/runtime/template-compiler/impl.d.ts +14 -0
  60. package/dist/runtime/template-compiler/lru-cache.d.ts +20 -0
  61. package/dist/runtime/template-compiler/props-parser.d.ts +15 -0
  62. package/dist/runtime/template-compiler/vnode-utils.d.ts +5 -0
  63. package/dist/runtime/template-compiler.d.ts +5 -28
  64. package/dist/runtime/types.d.ts +10 -0
  65. package/dist/runtime/vdom-directives.d.ts +71 -0
  66. package/dist/runtime/vdom-helpers.d.ts +126 -0
  67. package/dist/runtime/vdom-patch.d.ts +67 -0
  68. package/dist/runtime/vdom.d.ts +16 -140
  69. package/dist/ssr.d.ts +2 -1
  70. package/dist/teleport.d.ts +68 -0
  71. package/dist/template-compiler-CA4YRaBu.cjs +23 -0
  72. package/dist/template-compiler-CA4YRaBu.cjs.map +1 -0
  73. package/dist/template-compiler-CJFwjLCP.js +3981 -0
  74. package/dist/template-compiler-CJFwjLCP.js.map +1 -0
  75. package/dist/transitions-DPZiuXb9.cjs +330 -0
  76. package/dist/transitions-DPZiuXb9.cjs.map +1 -0
  77. package/dist/{transitions-Bx0Nc9zR.js → transitions-Di5wW9yc.js} +1072 -632
  78. package/dist/transitions-Di5wW9yc.js.map +1 -0
  79. package/dist/transitions.d.ts +1 -1
  80. package/package.json +18 -11
  81. package/dist/logger-BuUYv7C_.js.map +0 -1
  82. package/dist/logger-DiXdWaF-.cjs +0 -2
  83. package/dist/logger-DiXdWaF-.cjs.map +0 -1
  84. package/dist/namespace-helpers-BCVTzhAO.cjs +0 -5
  85. package/dist/namespace-helpers-BCVTzhAO.cjs.map +0 -1
  86. package/dist/namespace-helpers-CF28TyaG.js +0 -786
  87. package/dist/namespace-helpers-CF28TyaG.js.map +0 -1
  88. package/dist/template-compiler-CXHEnaBh.cjs +0 -17
  89. package/dist/template-compiler-CXHEnaBh.cjs.map +0 -1
  90. package/dist/template-compiler-DD_VZrte.js +0 -3729
  91. package/dist/template-compiler-DD_VZrte.js.map +0 -1
  92. package/dist/transitions-Bx0Nc9zR.js.map +0 -1
  93. package/dist/transitions-DfcqL-X4.cjs +0 -302
  94. package/dist/transitions-DfcqL-X4.cjs.map +0 -1
package/dist/router.d.ts CHANGED
@@ -1,208 +1,6 @@
1
- import { type Store } from './store';
2
- /**
3
- * Represents a component that can be rendered by the router.
4
- * Can be either a class constructor or a function component.
5
- */
6
- export type RouteComponent = {
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
- import type { ComponentConfig, VNode } 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
- 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;
@@ -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
+ };
@@ -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 info only in development mode
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;