@webjsdev/core 0.7.65 → 0.9.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 +5 -0
- package/dist/webjs-core-browser.js +6 -5
- package/dist/webjs-core-browser.js.map +3 -3
- package/dist/webjs-core-testing.js +22 -21
- package/dist/webjs-core-testing.js.map +3 -3
- package/dist/webjs-core.js +7 -6
- package/dist/webjs-core.js.map +3 -3
- package/index-browser.js +18 -9
- package/index.d.ts +26 -10
- package/index.js +21 -9
- package/package.json +15 -2
- package/src/action-effects-client.d.ts +5 -0
- package/src/action-effects-client.js +84 -0
- package/src/action-seed-client.js +5 -5
- package/src/asset-url.js +12 -13
- package/src/async-directive.d.ts +18 -0
- package/src/async-directive.js +88 -0
- package/src/attribute-directives.d.ts +6 -0
- package/src/attribute-directives.js +49 -0
- package/src/attribute-reader.js +213 -25
- package/src/binding-prefixes.js +10 -53
- package/src/component/lifecycle.js +921 -252
- package/src/component/reactive.js +7 -14
- package/src/component/server-element.js +23 -1
- package/src/component.d.ts +160 -44
- package/src/context.d.ts +94 -18
- package/src/context.js +341 -217
- package/src/converters.d.ts +7 -0
- package/src/converters.js +38 -0
- package/src/css.d.ts +32 -6
- package/src/css.js +178 -14
- package/src/directive.d.ts +58 -0
- package/src/directive.js +119 -0
- package/src/directives.d.ts +40 -1
- package/src/directives.js +160 -1
- package/src/form-action.d.ts +13 -0
- package/src/form-action.js +139 -4
- package/src/hot.js +23 -0
- package/src/html.d.ts +8 -0
- package/src/html.js +55 -2
- package/src/is-server.d.ts +2 -0
- package/src/is-server.js +18 -0
- package/src/jsx-guard.js +130 -0
- package/src/metadata.d.ts +22 -3
- package/src/nav.d.ts +4 -1
- package/src/nav.js +44 -11
- package/src/optimistic.js +2 -2
- package/src/refresh-header.js +52 -0
- package/src/registry.js +10 -1
- package/src/render-client/adopt-slots.js +250 -0
- package/src/render-client/parts.js +790 -42
- package/src/render-client/reconciler.js +84 -23
- package/src/render-client/template-compiler.js +152 -43
- package/src/render-client.d.ts +6 -1
- package/src/render-server/attrs.js +2 -2
- package/src/render-server/compile.js +50 -2
- package/src/render-server/errors.js +37 -0
- package/src/render-server/expand.js +100 -20
- package/src/render-server/served-attrs.js +78 -0
- package/src/render-server/walk.js +177 -5
- package/src/render-server.d.ts +3 -0
- package/src/render-server.js +2 -0
- package/src/repeat.d.ts +7 -2
- package/src/repeat.js +20 -6
- package/src/router-client/anchors.js +3 -1
- package/src/router-client/boundaries.js +15 -1
- package/src/router-client/constants.js +30 -0
- package/src/router-client/dom-differ.js +17 -0
- package/src/router-client/fetch-apply.js +107 -5
- package/src/router-client/frames.js +6 -3
- package/src/router-client/head-merge.js +58 -10
- package/src/router-client/navigator.js +49 -9
- package/src/router-client/owned-styles.js +372 -0
- package/src/router-client/prefetch.js +6 -4
- package/src/router-client/root-attrs.js +43 -0
- package/src/router-client/stream.js +7 -0
- package/src/router-client/stylesheets.js +191 -0
- package/src/router-client/swap.js +53 -10
- package/src/routes.d.ts +75 -18
- package/src/sentinels.d.ts +2 -0
- package/src/sentinels.js +4 -0
- package/src/serialize.d.ts +2 -0
- package/src/serialize.js +35 -4
- package/src/signal.d.ts +7 -0
- package/src/signal.js +26 -6
- package/src/slot/polyfills.js +3 -3
- package/src/slot.js +4 -8
- package/src/static-html.d.ts +22 -0
- package/src/static-html.js +144 -0
- package/src/task.d.ts +63 -20
- package/src/task.js +326 -293
- package/src/webjs-config.d.ts +2 -9
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import { tagOf } from '../registry.js';
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* Default change detection:
|
|
4
|
+
* Default change detection: Object.is inequality (NaN is stable; signed zero changes).
|
|
5
5
|
* @param {unknown} a
|
|
6
6
|
* @param {unknown} b
|
|
7
7
|
* @returns {boolean}
|
|
8
8
|
*/
|
|
9
9
|
export function defaultHasChanged(a, b) {
|
|
10
|
-
return a
|
|
10
|
+
return !Object.is(a, b);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -59,7 +59,7 @@ export function warnFunctionReflection(host, propName, attrName) {
|
|
|
59
59
|
if (typeof console === 'undefined' || !console.warn) return;
|
|
60
60
|
const tag = tagOf(/** @type any */ (host.constructor)) || host.tagName?.toLowerCase() || 'unknown';
|
|
61
61
|
console.warn(
|
|
62
|
-
`[webjs] reflect:true property "${propName}" on <${tag}> holds a function `
|
|
62
|
+
`[webjs] reflect:true property "${String(propName)}" on <${tag}> holds a function `
|
|
63
63
|
+ `(or an array carrying one), which has no HTML attribute representation. `
|
|
64
64
|
+ `Removing "${attrName}" instead of stringifying it (a stringified function `
|
|
65
65
|
+ `writes its source into the page, so a server action's body would ship to `
|
|
@@ -96,7 +96,7 @@ export function warnUnserializableReflection(host, propName, attrName, detail) {
|
|
|
96
96
|
if (typeof console === 'undefined' || !console.warn) return;
|
|
97
97
|
const tag = tagOf(/** @type any */ (host.constructor)) || host.tagName?.toLowerCase() || 'unknown';
|
|
98
98
|
console.warn(
|
|
99
|
-
`[webjs] reflect:true property "${propName}" on <${tag}> holds a value `
|
|
99
|
+
`[webjs] reflect:true property "${String(propName)}" on <${tag}> holds a value `
|
|
100
100
|
+ `JSON.stringify cannot serialize (a cycle, a BigInt, or a throwing `
|
|
101
101
|
+ `toJSON), so it has no HTML attribute representation. Removing `
|
|
102
102
|
+ `"${attrName}" instead. Detail: ${detail}`
|
|
@@ -108,8 +108,9 @@ export function warnUnserializableReflection(host, propName, attrName, detail) {
|
|
|
108
108
|
* while staying JSDoc-only and no-build.
|
|
109
109
|
*
|
|
110
110
|
* Subclasses declare:
|
|
111
|
-
* -
|
|
112
|
-
*
|
|
111
|
+
* - reactive properties, through the `WebComponent({ ... })` factory:
|
|
112
|
+
* attribute/property declarations with type info, reflection and custom
|
|
113
|
+
* converters (internal state is an instance signal, not a property)
|
|
113
114
|
* - `static styles`: CSSResult or array thereof (only meaningful with
|
|
114
115
|
* `static shadow = true`; light-DOM components inherit global CSS)
|
|
115
116
|
* - `static shadow`: set `true` to opt in to shadow DOM (default: `false`
|
|
@@ -132,14 +133,6 @@ export function warnUnserializableReflection(host, propName, attrName, detail) {
|
|
|
132
133
|
* `changedProperties` is a `Map<string, unknown>` where each entry maps
|
|
133
134
|
* a property name to its previous value.
|
|
134
135
|
*
|
|
135
|
-
* MAINTAINER NOTE. Adding a new overridable lifecycle hook here means
|
|
136
|
-
* the display-only component elision analyser must learn about it too,
|
|
137
|
-
* or it will wrongly elide a component that now does client work. Add
|
|
138
|
-
* the hook name to `CLIENT_LIFECYCLE_HOOKS` in
|
|
139
|
-
* `packages/server/src/component-elision.js`. The guard test at
|
|
140
|
-
* `packages/server/test/elision/lifecycle-coverage.test.js` introspects
|
|
141
|
-
* this prototype and fails until you do.
|
|
142
|
-
*
|
|
143
136
|
* Usage:
|
|
144
137
|
* ```js
|
|
145
138
|
* import { signal } from '@webjsdev/core';
|
|
@@ -44,7 +44,8 @@ export function makeServerInternals() {
|
|
|
44
44
|
* reflected/added attributes in the output. Event methods are no-ops (no
|
|
45
45
|
* server event loop), and `attachInternals()` returns the inert object
|
|
46
46
|
* above. The genuinely browser-only surface (`querySelector`, layout reads,
|
|
47
|
-
* `
|
|
47
|
+
* `focus`) is deliberately absent and still throws at SSR (`attachShadow`
|
|
48
|
+
* throws with the `static shadow = true` fix),
|
|
48
49
|
* which the `no-browser-globals-in-render` rule and the SSR crash hint flag.
|
|
49
50
|
*
|
|
50
51
|
* Deliberate deviation from lit: this shim lowercases attribute names so
|
|
@@ -209,6 +210,27 @@ export class ServerElement {
|
|
|
209
210
|
removeEventListener() {}
|
|
210
211
|
dispatchEvent() { return true; }
|
|
211
212
|
|
|
213
|
+
/**
|
|
214
|
+
* There is no shadow root at SSR: the server writes a shadow component's
|
|
215
|
+
* root as Declarative Shadow DOM from `static shadow = true`, and the
|
|
216
|
+
* browser attaches it while parsing.
|
|
217
|
+
* @returns {null}
|
|
218
|
+
*/
|
|
219
|
+
get shadowRoot() { return null; }
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* `attachShadow()` cannot run at SSR, which has no DOM. Called from a
|
|
223
|
+
* constructor or `render()` (Lit's habit of attaching in the constructor),
|
|
224
|
+
* it names the WebJs spelling instead of failing as an unknown method.
|
|
225
|
+
*/
|
|
226
|
+
attachShadow() {
|
|
227
|
+
throw new Error(
|
|
228
|
+
'[webjs] attachShadow() was called during SSR, which has no DOM. Declare `static shadow = true` ' +
|
|
229
|
+
'(and `static shadowRootOptions` for the attachShadow options) instead: the server writes the shadow root ' +
|
|
230
|
+
'as Declarative Shadow DOM and the browser attaches it.',
|
|
231
|
+
);
|
|
232
|
+
}
|
|
233
|
+
|
|
212
234
|
/** @returns {any} */
|
|
213
235
|
attachInternals() {
|
|
214
236
|
// Match the browser (and lit's shim): a second attach is an error.
|
package/src/component.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* cost: nothing in this file ships to the browser.
|
|
10
10
|
*/
|
|
11
11
|
|
|
12
|
-
import type {
|
|
12
|
+
import type { CSSResultGroup, CSSResultOrNative } from './css.js';
|
|
13
13
|
import type { TemplateResult } from './html.js';
|
|
14
14
|
|
|
15
15
|
/** Any constructor the framework accepts as the `type:` field of a property. */
|
|
@@ -22,23 +22,41 @@ export type PropertyConstructor<T = unknown> =
|
|
|
22
22
|
| (new (...args: any[]) => T)
|
|
23
23
|
| ((v: any) => T);
|
|
24
24
|
|
|
25
|
-
/** Runtime-level property declaration: one entry in `WebComponent({ … })`. */
|
|
25
|
+
/** Runtime-level property declaration: one entry in `WebComponent({ … })` or in Lit's `static properties`. */
|
|
26
26
|
export interface PropertyDeclaration<T = unknown> {
|
|
27
27
|
/** Constructor used for string → value coercion when the attribute changes. */
|
|
28
28
|
type?: PropertyConstructor<T>;
|
|
29
|
-
/** Write property changes back to the HTML attribute (
|
|
29
|
+
/** Write property changes back to the HTML attribute (the lowercased property name unless `attribute` names one). */
|
|
30
30
|
reflect?: boolean;
|
|
31
31
|
/** Internal-only: no attribute, no reflection, but still reactive. */
|
|
32
32
|
state?: boolean;
|
|
33
|
-
/** Rename the attribute,
|
|
34
|
-
attribute?: string |
|
|
35
|
-
/**
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
33
|
+
/** Rename the attribute (a string), keep the default name (`true`), or suppress it (`false`). */
|
|
34
|
+
attribute?: string | boolean;
|
|
35
|
+
/**
|
|
36
|
+
* Custom attribute ⇄ property serialisation. Takes precedence over `type`.
|
|
37
|
+
* A bare function is the `fromAttribute` half (reflection then uses the
|
|
38
|
+
* default serialisation), as in Lit.
|
|
39
|
+
*/
|
|
40
|
+
converter?:
|
|
41
|
+
| ((value: string | null, type?: PropertyConstructor<T>) => T)
|
|
42
|
+
| {
|
|
43
|
+
fromAttribute?: (value: string | null, type?: PropertyConstructor<T>) => T;
|
|
44
|
+
toAttribute?: (value: T, type?: PropertyConstructor<T>) => string | null;
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Install no accessor: the class's own get/set stays and must call
|
|
48
|
+
* `this.requestUpdate(name, oldValue)` itself (Lit's `noAccessor`).
|
|
49
|
+
*/
|
|
50
|
+
noAccessor?: boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Lit's `useDefault`: the first value is the default. It is not reflected,
|
|
53
|
+
* and removing the attribute restores it instead of `null`.
|
|
54
|
+
*/
|
|
55
|
+
useDefault?: boolean;
|
|
40
56
|
/** Custom dirty check. Return `true` to schedule an update. */
|
|
41
57
|
hasChanged?: (newValue: T, oldValue: T) => boolean;
|
|
58
|
+
/** Initial value, or a function called per instance for a fresh object / array. */
|
|
59
|
+
default?: T | (() => T);
|
|
42
60
|
}
|
|
43
61
|
|
|
44
62
|
/** Reactive controller protocol (Lit-compatible). */
|
|
@@ -49,12 +67,52 @@ export interface ReactiveController {
|
|
|
49
67
|
hostUpdated?(): void;
|
|
50
68
|
}
|
|
51
69
|
|
|
70
|
+
/**
|
|
71
|
+
* Lit's `ReactiveControllerHost`: what a controller may rely on from its host.
|
|
72
|
+
* Every `WebComponent` satisfies it, so a controller typed against it works
|
|
73
|
+
* with WebJs and Lit alike.
|
|
74
|
+
*/
|
|
75
|
+
export interface ReactiveControllerHost {
|
|
76
|
+
addController(controller: ReactiveController): void;
|
|
77
|
+
removeController(controller: ReactiveController): void;
|
|
78
|
+
requestUpdate(): void;
|
|
79
|
+
readonly updateComplete: Promise<boolean>;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/** Lit's `ComplexAttributeConverter`: the object form of a property `converter`. */
|
|
83
|
+
export interface ComplexAttributeConverter<Type = unknown, TypeHint = unknown> {
|
|
84
|
+
fromAttribute?(value: string | null, type?: TypeHint): Type;
|
|
85
|
+
toAttribute?(value: Type, type?: TypeHint): unknown;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Lit's `PropertyDeclarations`: the shape of a `static properties` block. */
|
|
89
|
+
export interface PropertyDeclarations {
|
|
90
|
+
readonly [key: string]: PropertyDeclaration | PropertyConstructor;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* Lit's `PropertyValueMap<T>`: a `changedProperties` Map whose keys and old
|
|
95
|
+
* values are typed against the component (`PropertyValues<this>`).
|
|
96
|
+
*/
|
|
97
|
+
export interface PropertyValueMap<T> extends Map<PropertyKey, unknown> {
|
|
98
|
+
get<K extends keyof T>(k: K): T[K] | undefined;
|
|
99
|
+
set<K extends keyof T>(key: K, value: T[K]): this;
|
|
100
|
+
has<K extends keyof T>(k: K): boolean;
|
|
101
|
+
delete<K extends keyof T>(k: K): boolean;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Lit's `PropertyValues`: the `changedProperties` argument of the lifecycle
|
|
106
|
+
* hooks. `PropertyValues<this>` types its keys against the component.
|
|
107
|
+
*/
|
|
108
|
+
export type PropertyValues<T = any> = T extends object ? PropertyValueMap<T> : Map<PropertyKey, unknown>;
|
|
109
|
+
|
|
52
110
|
/**
|
|
53
111
|
* Base class for interactive web components.
|
|
54
112
|
*
|
|
55
|
-
* Declare reactive properties
|
|
56
|
-
* factory
|
|
57
|
-
* you (no `declare
|
|
113
|
+
* Declare reactive properties in either of two equivalent ways. The
|
|
114
|
+
* `extends WebComponent({ … })` factory installs the reactive accessor AND
|
|
115
|
+
* types each field for you (no `declare` needed):
|
|
58
116
|
*
|
|
59
117
|
* class StudentCard extends WebComponent({ student: prop<Student>(Object) }) {
|
|
60
118
|
* render() { return html`<p>${this.student.name}</p>`; }
|
|
@@ -64,10 +122,18 @@ export interface ReactiveController {
|
|
|
64
122
|
* A bare constructor type covers the common case (`WebComponent({ count:
|
|
65
123
|
* Number })` gives `this.count: number`); use the `prop()` helper for
|
|
66
124
|
* options (`prop(Number, { reflect: true })`) or to narrow the type
|
|
67
|
-
* (`prop<Student>(Object)`).
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
125
|
+
* (`prop<Student>(Object)`). Lit's own spelling works too, with an erasable
|
|
126
|
+
* `declare` for the type:
|
|
127
|
+
*
|
|
128
|
+
* class Counter extends WebComponent {
|
|
129
|
+
* static properties = { count: { type: Number, reflect: true } };
|
|
130
|
+
* declare count: number;
|
|
131
|
+
* }
|
|
132
|
+
*
|
|
133
|
+
* Props merge down the class chain as in Lit, so a subclass's own
|
|
134
|
+
* `static properties` adds to its parent's. Set defaults via the `default`
|
|
135
|
+
* option or in the constructor, never a class-field initializer (it runs
|
|
136
|
+
* after super() and clobbers the reactive accessor).
|
|
71
137
|
*
|
|
72
138
|
* See the Editor Setup doc for tooling that gives attribute/tag
|
|
73
139
|
* intelligence inside `html\`…\`` templates.
|
|
@@ -85,13 +151,13 @@ interface WebComponentBase extends HTMLElement {
|
|
|
85
151
|
* Schedule a re-render. Optionally record a property change so lifecycle
|
|
86
152
|
* hooks can branch on what changed via `changedProperties`.
|
|
87
153
|
*
|
|
88
|
-
* For instance-local state,
|
|
89
|
-
*
|
|
90
|
-
* `@webjsdev/core`'s `signal()`. The framework's built-in
|
|
91
|
-
*
|
|
92
|
-
*
|
|
154
|
+
* For instance-local state, use a reactive property (`WebComponent({
|
|
155
|
+
* open: prop<boolean>({ state: true }) })`) or a signal from
|
|
156
|
+
* `@webjsdev/core`'s `signal()`. The framework's built-in SignalWatcher
|
|
157
|
+
* wires every signal the update cycle reads to a re-render automatically;
|
|
158
|
+
* explicit `requestUpdate()` is rarely needed.
|
|
93
159
|
*/
|
|
94
|
-
requestUpdate(name?:
|
|
160
|
+
requestUpdate(name?: PropertyKey, oldValue?: unknown, options?: PropertyDeclaration): void;
|
|
95
161
|
/** A Promise that resolves after the next render commit. */
|
|
96
162
|
readonly updateComplete: Promise<boolean>;
|
|
97
163
|
/** Override point for `updateComplete`. Default returns the internal promise. */
|
|
@@ -100,18 +166,40 @@ interface WebComponentBase extends HTMLElement {
|
|
|
100
166
|
addController(controller: ReactiveController): void;
|
|
101
167
|
/** Detach a reactive controller. */
|
|
102
168
|
removeController(controller: ReactiveController): void;
|
|
103
|
-
/** Returns the template for this render. May be async. */
|
|
104
|
-
render():
|
|
169
|
+
/** Returns the template for this render. May be async. The default returns `noChange`. */
|
|
170
|
+
render(): unknown;
|
|
171
|
+
/**
|
|
172
|
+
* The node `render()` commits into: the element itself for light DOM, its
|
|
173
|
+
* shadow root for `static shadow = true`. Undefined until the element
|
|
174
|
+
* connects, and at SSR.
|
|
175
|
+
*/
|
|
176
|
+
renderRoot: HTMLElement | ShadowRoot | DocumentFragment | undefined;
|
|
177
|
+
/** True once the first update has completed. */
|
|
178
|
+
readonly hasUpdated: boolean;
|
|
179
|
+
/** True while an update is queued or running. */
|
|
180
|
+
readonly isUpdatePending: boolean;
|
|
181
|
+
/**
|
|
182
|
+
* Create the render root, once per element. The default returns the element
|
|
183
|
+
* for light DOM, and for `static shadow = true` attaches the shadow root
|
|
184
|
+
* with `static shadowRootOptions` and adopts `static styles`.
|
|
185
|
+
*/
|
|
186
|
+
createRenderRoot(): HTMLElement | ShadowRoot | DocumentFragment;
|
|
187
|
+
/** Called from the update microtask; override to change when an update runs. */
|
|
188
|
+
scheduleUpdate(): void | Promise<unknown>;
|
|
189
|
+
/** Run the pending update now, synchronously. No-op when nothing is pending. */
|
|
190
|
+
performUpdate(): void;
|
|
191
|
+
/** Called on connect, right before the first update is queued. */
|
|
192
|
+
enableUpdating(requestedUpdate: boolean): void;
|
|
105
193
|
/** Decide whether to update. Default returns `true`. */
|
|
106
|
-
shouldUpdate(changedProperties:
|
|
194
|
+
shouldUpdate(changedProperties: PropertyValues): boolean;
|
|
107
195
|
/** Pre-render hook. Safe to set properties; folds into current cycle. */
|
|
108
|
-
willUpdate(changedProperties:
|
|
196
|
+
willUpdate(changedProperties: PropertyValues): void;
|
|
109
197
|
/** Render-and-commit step. Default calls `render()` and commits. */
|
|
110
|
-
update(changedProperties:
|
|
198
|
+
update(changedProperties: PropertyValues): void;
|
|
111
199
|
/** Post-render hook. Runs after every commit. */
|
|
112
|
-
updated(changedProperties:
|
|
200
|
+
updated(changedProperties: PropertyValues): void;
|
|
113
201
|
/** One-shot hook after the first render lands in the DOM. */
|
|
114
|
-
firstUpdated?(changedProperties:
|
|
202
|
+
firstUpdated?(changedProperties: PropertyValues): void;
|
|
115
203
|
/** Optional render-error boundary inside the component. */
|
|
116
204
|
renderError?(error: Error): TemplateResult | void;
|
|
117
205
|
/**
|
|
@@ -137,6 +225,11 @@ export type Infer<C> =
|
|
|
137
225
|
C extends BooleanConstructor ? boolean :
|
|
138
226
|
C extends NumberConstructor ? number :
|
|
139
227
|
C extends StringConstructor ? string :
|
|
228
|
+
// A bare Array / Object says nothing about the element type, so it is the
|
|
229
|
+
// open type an undeclared Lit property has, not unknown: a typed callback
|
|
230
|
+
// (`items.filter((m: Message) => ...)`) has to compile, as it would in Lit.
|
|
231
|
+
C extends ArrayConstructor ? any[] :
|
|
232
|
+
C extends ObjectConstructor ? any :
|
|
140
233
|
C extends new (...a: any[]) => infer T ? T :
|
|
141
234
|
C extends (v: any) => infer T ? T : unknown;
|
|
142
235
|
|
|
@@ -153,24 +246,34 @@ export type InferProps<S> = {
|
|
|
153
246
|
*/
|
|
154
247
|
interface WebComponentStatics {
|
|
155
248
|
shadow: boolean;
|
|
249
|
+
/** The `attachShadow()` options, also written onto the server's Declarative Shadow DOM template. */
|
|
250
|
+
shadowRootOptions: ShadowRootInit;
|
|
156
251
|
hydrate: 'visible' | undefined;
|
|
157
|
-
properties: Record<string, PropertyDeclaration>;
|
|
158
|
-
styles:
|
|
252
|
+
properties: Record<string, PropertyDeclaration | PropertyConstructor>;
|
|
253
|
+
styles: CSSResultGroup | null | undefined;
|
|
254
|
+
/** `static styles` flattened by `finalizeStyles()`: what the shadow root adopts. */
|
|
255
|
+
readonly elementStyles: CSSResultOrNative[];
|
|
256
|
+
/** Flatten and dedupe `static styles`; override to post-process. */
|
|
257
|
+
finalizeStyles(styles?: CSSResultGroup | null): CSSResultOrNative[];
|
|
159
258
|
lazy?: boolean;
|
|
160
|
-
/**
|
|
161
|
-
* Force this component to ship (hydrate) even when the elision analyser would
|
|
162
|
-
* drop it as display-only. The escape hatch for interactivity the analyser
|
|
163
|
-
* cannot see statically: an OBSERVER that computes the tag it waits for, a
|
|
164
|
-
* `:defined` rule in an external stylesheet outside the module graph, or a
|
|
165
|
-
* consumer reaching the element through a string selector. It
|
|
166
|
-
* cannot rescue a component whose OWN registration tag is computed, since
|
|
167
|
-
* the scanner requires a literal tag (invariant 3) and never sees that
|
|
168
|
-
* component at all. Leave unset for the automatic verdict; inspect it with
|
|
169
|
-
* `webjs elision`.
|
|
170
|
-
*/
|
|
171
|
-
interactive?: boolean;
|
|
172
259
|
register(tag: string): void;
|
|
173
260
|
readonly observedAttributes: string[];
|
|
261
|
+
/** Every declared reactive property, own and inherited, as name to declaration. */
|
|
262
|
+
readonly elementProperties: Map<PropertyKey, PropertyDeclaration>;
|
|
263
|
+
/** The declaration for `name`, or the default `{ type: String }`. */
|
|
264
|
+
getPropertyOptions(name: PropertyKey): PropertyDeclaration;
|
|
265
|
+
/** Declare a reactive property from code. Must run before the first instance. */
|
|
266
|
+
createProperty(name: PropertyKey, options?: PropertyDeclaration): void;
|
|
267
|
+
/**
|
|
268
|
+
* The accessor installed on the prototype for one reactive property.
|
|
269
|
+
* Override to wrap `super.getPropertyDescriptor(...)`; return `undefined`
|
|
270
|
+
* to install none.
|
|
271
|
+
*/
|
|
272
|
+
getPropertyDescriptor(name: PropertyKey, key: string | symbol, options: PropertyDeclaration): PropertyDescriptor | undefined;
|
|
273
|
+
/** Prepare the class metadata once. Called for you; idempotent. */
|
|
274
|
+
finalize(): void;
|
|
275
|
+
/** Run `initializer(element)` in the constructor of every instance of this class and its subclasses. */
|
|
276
|
+
addInitializer(initializer: (element: WebComponentBase) => void): void;
|
|
174
277
|
}
|
|
175
278
|
|
|
176
279
|
export interface WebComponentConstructor extends WebComponentStatics {
|
|
@@ -210,6 +313,19 @@ export declare function prop<T>(
|
|
|
210
313
|
opts?: Omit<PropertyDeclaration<T>, 'type'>
|
|
211
314
|
): PropertyDeclaration<T>;
|
|
212
315
|
|
|
316
|
+
// No type constructor and no attribute: nothing says what the value is, so it
|
|
317
|
+
// is `unknown` until narrowed (`prop<boolean>({ state: true })`). With a
|
|
318
|
+
// `default` it holds a `T` from the start; without one nothing fills it until
|
|
319
|
+
// the component sets it, so it is `T | undefined`, Lit's `@state() error?:
|
|
320
|
+
// string` (#1686: an agent clearing such a prop with `undefined` failed
|
|
321
|
+
// typecheck against a type that said it was never undefined).
|
|
322
|
+
export declare function prop<T = unknown>(
|
|
323
|
+
opts: PropertyDeclaration<T> & ({ state: true } | { attribute: false }) & { default: T | (() => T) }
|
|
324
|
+
): PropertyDeclaration<T>;
|
|
325
|
+
export declare function prop<T = unknown>(
|
|
326
|
+
opts: PropertyDeclaration<T> & ({ state: true } | { attribute: false })
|
|
327
|
+
): PropertyDeclaration<T | undefined>;
|
|
328
|
+
|
|
213
329
|
export declare function prop<T = string>(
|
|
214
330
|
opts?: PropertyDeclaration<T>
|
|
215
331
|
): PropertyDeclaration<T>;
|
package/src/context.d.ts
CHANGED
|
@@ -1,34 +1,110 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Portions derived from Lit (`@lit/context`), Copyright Google LLC, BSD-3-Clause.
|
|
4
|
+
*/
|
|
5
|
+
import type { ReactiveController } from './component.js';
|
|
2
6
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
7
|
+
/** Any element that hosts reactive controllers (a WebComponent). */
|
|
8
|
+
interface ContextHost extends HTMLElement {
|
|
9
|
+
addController(controller: ReactiveController): void;
|
|
10
|
+
requestUpdate(): void;
|
|
6
11
|
}
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
/**
|
|
14
|
+
* A context key carrying its value type. At runtime it is the key itself (a
|
|
15
|
+
* string, a Symbol, an object), and the key IS the identity.
|
|
16
|
+
*/
|
|
17
|
+
export type Context<KeyType, ValueType> = KeyType & { __context__: ValueType };
|
|
9
18
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
19
|
+
/** The value type a context carries. */
|
|
20
|
+
export type ContextType<Key extends Context<unknown, unknown>> =
|
|
21
|
+
Key extends Context<unknown, infer ValueType> ? ValueType : never;
|
|
22
|
+
|
|
23
|
+
/** Returns `key`, typed as a context of `ValueType`. */
|
|
24
|
+
export function createContext<ValueType, K = unknown>(key: K): Context<K, ValueType>;
|
|
25
|
+
|
|
26
|
+
export type ContextCallback<ValueType> = (value: ValueType, unsubscribe?: () => void) => void;
|
|
27
|
+
|
|
28
|
+
export class ContextRequestEvent<C extends Context<unknown, unknown>> extends Event {
|
|
29
|
+
readonly context: C;
|
|
30
|
+
readonly contextTarget: Element;
|
|
31
|
+
readonly callback: ContextCallback<ContextType<C>>;
|
|
32
|
+
readonly subscribe: boolean;
|
|
14
33
|
constructor(
|
|
15
|
-
context:
|
|
16
|
-
|
|
34
|
+
context: C,
|
|
35
|
+
contextTarget: Element,
|
|
36
|
+
callback: ContextCallback<ContextType<C>>,
|
|
17
37
|
subscribe?: boolean,
|
|
18
38
|
);
|
|
19
39
|
}
|
|
20
40
|
|
|
21
|
-
export class
|
|
22
|
-
|
|
41
|
+
export class ContextProviderEvent<C extends Context<unknown, unknown>> extends Event {
|
|
42
|
+
readonly context: C;
|
|
43
|
+
readonly contextTarget: Element;
|
|
44
|
+
constructor(context: C, contextTarget: Element);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
declare global {
|
|
48
|
+
interface HTMLElementEventMap {
|
|
49
|
+
'context-request': ContextRequestEvent<Context<unknown, unknown>>;
|
|
50
|
+
'context-provider': ContextProviderEvent<Context<unknown, unknown>>;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export class ValueNotifier<T> {
|
|
55
|
+
protected readonly subscriptions: Map<ContextCallback<T>, { disposer: () => void; consumerHost: Element }>;
|
|
56
|
+
constructor(defaultValue?: T);
|
|
23
57
|
get value(): T;
|
|
24
|
-
|
|
58
|
+
set value(v: T);
|
|
59
|
+
setValue(v: T, force?: boolean): void;
|
|
60
|
+
updateObservers: () => void;
|
|
61
|
+
addCallback(callback: ContextCallback<T>, consumerHost: Element, subscribe?: boolean): void;
|
|
62
|
+
clearCallbacks(): void;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface ContextProviderOptions<C extends Context<unknown, unknown>> {
|
|
66
|
+
context: C;
|
|
67
|
+
initialValue?: ContextType<C>;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export class ContextProvider<
|
|
71
|
+
T extends Context<unknown, unknown>,
|
|
72
|
+
HostElement extends ContextHost = ContextHost,
|
|
73
|
+
> extends ValueNotifier<ContextType<T>> implements ReactiveController {
|
|
74
|
+
protected readonly host: HostElement;
|
|
75
|
+
constructor(host: HostElement, options: ContextProviderOptions<T>);
|
|
76
|
+
constructor(host: HostElement, context: T, initialValue?: ContextType<T>);
|
|
77
|
+
onContextRequest: (ev: ContextRequestEvent<Context<unknown, unknown>>) => void;
|
|
78
|
+
onProviderRequest: (ev: ContextProviderEvent<Context<unknown, unknown>>) => void;
|
|
25
79
|
hostConnected(): void;
|
|
26
|
-
hostDisconnected(): void;
|
|
27
80
|
}
|
|
28
81
|
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
82
|
+
export interface ContextConsumerOptions<C extends Context<unknown, unknown>> {
|
|
83
|
+
context: C;
|
|
84
|
+
callback?: (value: ContextType<C>, dispose?: () => void) => void;
|
|
85
|
+
/** Keep receiving changes. Default `false`, a one-time read per connection. */
|
|
86
|
+
subscribe?: boolean;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
export class ContextConsumer<
|
|
90
|
+
C extends Context<unknown, unknown>,
|
|
91
|
+
HostElement extends ContextHost = ContextHost,
|
|
92
|
+
> implements ReactiveController {
|
|
93
|
+
protected host: HostElement;
|
|
94
|
+
value?: ContextType<C>;
|
|
95
|
+
constructor(host: HostElement, options: ContextConsumerOptions<C>);
|
|
96
|
+
constructor(
|
|
97
|
+
host: HostElement,
|
|
98
|
+
context: C,
|
|
99
|
+
callback?: (value: ContextType<C>, dispose?: () => void) => void,
|
|
100
|
+
subscribe?: boolean,
|
|
101
|
+
);
|
|
32
102
|
hostConnected(): void;
|
|
33
103
|
hostDisconnected(): void;
|
|
34
104
|
}
|
|
105
|
+
|
|
106
|
+
/** Buffers unanswered subscribing requests and replays them when a provider connects. */
|
|
107
|
+
export class ContextRoot {
|
|
108
|
+
attach(element: HTMLElement): void;
|
|
109
|
+
detach(element: HTMLElement): void;
|
|
110
|
+
}
|