@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
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Static expressions, lit's `lit/static-html.js` under a WebJs path:
|
|
3
|
+
* `@webjsdev/core/static-html`.
|
|
4
|
+
*
|
|
5
|
+
* Portions derived from Lit, Copyright Google LLC, BSD-3-Clause.
|
|
6
|
+
*
|
|
7
|
+
* A static value is spliced into the template's STRINGS before the renderer
|
|
8
|
+
* ever sees them, so it can sit where an ordinary hole cannot: a tag name, an
|
|
9
|
+
* attribute name. The classic use is a component whose child tag is chosen at
|
|
10
|
+
* runtime.
|
|
11
|
+
*
|
|
12
|
+
* ```js
|
|
13
|
+
* import { html, literal, unsafeStatic } from '@webjsdev/core/static-html';
|
|
14
|
+
*
|
|
15
|
+
* const tag = literal`my-button`;
|
|
16
|
+
* html`<${tag} label="Save"></${tag}>`;
|
|
17
|
+
*
|
|
18
|
+
* // A string from data must go through unsafeStatic, which trusts it as markup.
|
|
19
|
+
* html`<${unsafeStatic(level)}>Title</${unsafeStatic(level)}>`;
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* The merged strings array is cached by its joined text, so every render of
|
|
23
|
+
* the same static shape hands the renderers the SAME array, which is what
|
|
24
|
+
* their template caches key on (identity). A static that changes between
|
|
25
|
+
* renders produces a different shape, and so a fresh template, exactly as in
|
|
26
|
+
* lit.
|
|
27
|
+
*
|
|
28
|
+
* NEVER pass user input to `unsafeStatic`: it is inserted as markup.
|
|
29
|
+
*
|
|
30
|
+
* @module static-html
|
|
31
|
+
*/
|
|
32
|
+
|
|
33
|
+
import { html as coreHtml, svg as coreSvg, mathml as coreMathml } from './html.js';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Brand on every static value. `Symbol.for` so a value made by one loaded copy
|
|
37
|
+
* of this module is recognised by another (the source module and a bundle).
|
|
38
|
+
*/
|
|
39
|
+
const STATIC = Symbol.for('webjs.static');
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* @typedef {{ _$webjsStatic: string, r: symbol }} StaticValue
|
|
43
|
+
*/
|
|
44
|
+
|
|
45
|
+
/** @param {unknown} value @returns {string | undefined} */
|
|
46
|
+
function unwrapStaticValue(value) {
|
|
47
|
+
if (value && typeof value === 'object' && /** @type {any} */ (value).r === STATIC) {
|
|
48
|
+
return /** @type {any} */ (value)._$webjsStatic;
|
|
49
|
+
}
|
|
50
|
+
return undefined;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Wrap a string so it is inserted as static markup, lit's `unsafeStatic`. The
|
|
55
|
+
* string is trusted: NEVER pass user input.
|
|
56
|
+
*
|
|
57
|
+
* @param {string} value
|
|
58
|
+
* @returns {StaticValue}
|
|
59
|
+
*/
|
|
60
|
+
export function unsafeStatic(value) {
|
|
61
|
+
return { _$webjsStatic: value, r: STATIC };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* A static value from a template literal, lit's `literal`. Every interpolated
|
|
66
|
+
* value must itself be a static value (another `literal` or `unsafeStatic`),
|
|
67
|
+
* so a literal can never carry untrusted text.
|
|
68
|
+
*
|
|
69
|
+
* @param {TemplateStringsArray} strings
|
|
70
|
+
* @param {...unknown} values
|
|
71
|
+
* @returns {StaticValue}
|
|
72
|
+
*/
|
|
73
|
+
export function literal(strings, ...values) {
|
|
74
|
+
let text = strings[0];
|
|
75
|
+
for (let i = 0; i < values.length; i++) {
|
|
76
|
+
const s = unwrapStaticValue(values[i]);
|
|
77
|
+
if (s === undefined) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Value passed to 'literal' function must be a 'literal' result: ${String(values[i])}. ` +
|
|
80
|
+
`Use 'unsafeStatic' to pass non-literal values, but take care to ensure page security.`,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
text += s + strings[i + 1];
|
|
84
|
+
}
|
|
85
|
+
return { _$webjsStatic: text, r: STATIC };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/**
|
|
89
|
+
* One strings array per static shape, kept for the life of the process as Lit
|
|
90
|
+
* keeps it: the renderers key their template caches on its identity, so a
|
|
91
|
+
* shape still in use must never get a new array. Only literal statics belong
|
|
92
|
+
* here; `unsafeStatic` over request data makes a new shape per value.
|
|
93
|
+
* @type {Map<string, string[]>}
|
|
94
|
+
*/
|
|
95
|
+
const stringsCache = new Map();
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Wrap a template tag so it accepts static values, lit's `withStatic`.
|
|
99
|
+
*
|
|
100
|
+
* @template R
|
|
101
|
+
* @param {(strings: TemplateStringsArray | string[], ...values: unknown[]) => R} coreTag
|
|
102
|
+
* @returns {(strings: TemplateStringsArray | string[], ...values: unknown[]) => R}
|
|
103
|
+
*/
|
|
104
|
+
export function withStatic(coreTag) {
|
|
105
|
+
return (strings, ...values) => {
|
|
106
|
+
const l = values.length;
|
|
107
|
+
/** @type {string[]} */
|
|
108
|
+
const staticStrings = [];
|
|
109
|
+
/** @type {unknown[]} */
|
|
110
|
+
const dynamicValues = [];
|
|
111
|
+
let hasStatics = false;
|
|
112
|
+
let i = 0;
|
|
113
|
+
while (i < l) {
|
|
114
|
+
let s = strings[i];
|
|
115
|
+
let staticValue;
|
|
116
|
+
while (i < l && (staticValue = unwrapStaticValue(values[i])) !== undefined) {
|
|
117
|
+
s += staticValue + strings[++i];
|
|
118
|
+
hasStatics = true;
|
|
119
|
+
}
|
|
120
|
+
if (i !== l) dynamicValues.push(values[i]);
|
|
121
|
+
staticStrings.push(s);
|
|
122
|
+
i++;
|
|
123
|
+
}
|
|
124
|
+
if (i === l) staticStrings.push(strings[l]);
|
|
125
|
+
if (!hasStatics) return coreTag(strings, ...values);
|
|
126
|
+
// A NUL separator cannot occur in template source, so two different
|
|
127
|
+
// shapes never share a key.
|
|
128
|
+
const key = staticStrings.join('\u0000');
|
|
129
|
+
let cached = stringsCache.get(key);
|
|
130
|
+
if (cached === undefined) {
|
|
131
|
+
/** @type {any} */ (staticStrings).raw = staticStrings;
|
|
132
|
+
cached = staticStrings;
|
|
133
|
+
stringsCache.set(key, cached);
|
|
134
|
+
}
|
|
135
|
+
return coreTag(cached, ...dynamicValues);
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** `html` that accepts static values (`literal` / `unsafeStatic`). */
|
|
140
|
+
export const html = withStatic(coreHtml);
|
|
141
|
+
/** `svg` that accepts static values. */
|
|
142
|
+
export const svg = withStatic(coreSvg);
|
|
143
|
+
/** `mathml` that accepts static values. */
|
|
144
|
+
export const mathml = withStatic(coreMathml);
|
package/src/task.d.ts
CHANGED
|
@@ -1,4 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Portions derived from Lit (`@lit/task`), Copyright Google LLC, BSD-3-Clause.
|
|
4
|
+
*/
|
|
5
|
+
import type { ReactiveController } from './component.js';
|
|
6
|
+
|
|
7
|
+
/** The host a Task attaches to: any ReactiveController host (a WebComponent). */
|
|
8
|
+
interface TaskHost {
|
|
9
|
+
addController(controller: ReactiveController): void;
|
|
10
|
+
requestUpdate(): void;
|
|
11
|
+
}
|
|
2
12
|
|
|
3
13
|
export const TaskStatus: {
|
|
4
14
|
readonly INITIAL: 0;
|
|
@@ -7,27 +17,60 @@ export const TaskStatus: {
|
|
|
7
17
|
readonly ERROR: 3;
|
|
8
18
|
};
|
|
9
19
|
|
|
10
|
-
export type
|
|
20
|
+
export type TaskStatus = (typeof TaskStatus)[keyof typeof TaskStatus];
|
|
21
|
+
|
|
22
|
+
/** Return it from a task function to put the task back into INITIAL. */
|
|
23
|
+
export const initialState: unique symbol;
|
|
24
|
+
export type InitialState = typeof initialState;
|
|
11
25
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
26
|
+
/** Called as `task(args, { signal })`, where `args` is the array `args()` returned. */
|
|
27
|
+
export type TaskFunction<D extends ReadonlyArray<unknown>, R = unknown> = (
|
|
28
|
+
args: D,
|
|
29
|
+
options: { signal: AbortSignal },
|
|
30
|
+
) => R | InitialState | Promise<R | InitialState>;
|
|
31
|
+
|
|
32
|
+
export type ArgsFunction<D extends ReadonlyArray<unknown>> = () => D;
|
|
33
|
+
|
|
34
|
+
export interface TaskConfig<T extends ReadonlyArray<unknown>, R> {
|
|
35
|
+
task: TaskFunction<T, R>;
|
|
36
|
+
args?: ArgsFunction<T>;
|
|
37
|
+
/** `true` runs in `hostUpdate`, `'afterUpdate'` in `hostUpdated`, `false` only on `run()`. */
|
|
38
|
+
autoRun?: boolean | 'afterUpdate';
|
|
39
|
+
argsEqual?: (oldArgs: T, newArgs: T) => boolean;
|
|
40
|
+
initialValue?: R;
|
|
41
|
+
onComplete?: (value: R) => unknown;
|
|
42
|
+
onError?: (error: unknown) => unknown;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export interface StatusRenderer<R> {
|
|
46
|
+
initial?: () => unknown;
|
|
47
|
+
pending?: () => unknown;
|
|
48
|
+
complete?: (value: R) => unknown;
|
|
49
|
+
error?: (error: unknown) => unknown;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export class Task<
|
|
53
|
+
const T extends ReadonlyArray<unknown> = ReadonlyArray<unknown>,
|
|
54
|
+
const R = unknown,
|
|
55
|
+
> implements ReactiveController {
|
|
56
|
+
autoRun: boolean | 'afterUpdate';
|
|
57
|
+
constructor(host: TaskHost, task: TaskFunction<T, R>, args?: ArgsFunction<T>);
|
|
58
|
+
constructor(host: TaskHost, config: TaskConfig<T, R>);
|
|
59
|
+
get taskComplete(): Promise<R>;
|
|
60
|
+
get status(): TaskStatus;
|
|
61
|
+
get value(): R | undefined;
|
|
20
62
|
get error(): unknown;
|
|
21
|
-
run(): Promise<void>;
|
|
22
|
-
abort(): void;
|
|
23
|
-
render(
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
complete?: (value: T) => unknown;
|
|
27
|
-
error?: (error: unknown) => unknown;
|
|
28
|
-
}): unknown;
|
|
63
|
+
run(args?: T): Promise<void>;
|
|
64
|
+
abort(reason?: unknown): void;
|
|
65
|
+
render<X extends StatusRenderer<R>>(
|
|
66
|
+
renderer: X,
|
|
67
|
+
): MaybeReturnType<X['initial']> | MaybeReturnType<X['pending']> | MaybeReturnType<X['complete']> | MaybeReturnType<X['error']>;
|
|
29
68
|
hostUpdate(): void;
|
|
30
69
|
hostUpdated(): void;
|
|
31
|
-
hostConnected(): void;
|
|
32
|
-
hostDisconnected(): void;
|
|
33
70
|
}
|
|
71
|
+
|
|
72
|
+
type MaybeReturnType<F> = F extends (...args: never[]) => infer R ? R : undefined;
|
|
73
|
+
|
|
74
|
+
export function shallowArrayEquals<T extends ReadonlyArray<unknown>>(oldArgs: T, newArgs: T): boolean;
|
|
75
|
+
export function deepArrayEquals<T extends ReadonlyArray<unknown>>(oldArgs: T, newArgs: T): boolean;
|
|
76
|
+
export function deepEquals(a: unknown, b: unknown): boolean;
|