@webjsdev/core 0.7.1
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 +55 -0
- package/index.d.ts +28 -0
- package/index.js +39 -0
- package/package.json +46 -0
- package/src/component.d.ts +120 -0
- package/src/component.js +1061 -0
- package/src/context.js +327 -0
- package/src/css.js +54 -0
- package/src/directives.js +454 -0
- package/src/escape.js +15 -0
- package/src/expose.js +90 -0
- package/src/html.js +30 -0
- package/src/lazy-loader.js +107 -0
- package/src/nav.js +45 -0
- package/src/registry.js +190 -0
- package/src/render-client.js +1717 -0
- package/src/render-server.js +1128 -0
- package/src/repeat.js +37 -0
- package/src/rich-fetch.js +70 -0
- package/src/router-client.js +1434 -0
- package/src/serialize.js +452 -0
- package/src/signal.js +684 -0
- package/src/slot.js +860 -0
- package/src/suspense.js +46 -0
- package/src/task.js +386 -0
- package/src/testing.js +157 -0
- package/src/webjs-frame.js +65 -0
- package/src/websocket-client.js +111 -0
package/README.md
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# @webjsdev/core
|
|
2
|
+
|
|
3
|
+
Isomorphic core runtime for [webjs](https://github.com/vivek7405/webjs), the
|
|
4
|
+
AI-first, web-components-first, no-build web framework.
|
|
5
|
+
|
|
6
|
+
This package ships the tagged-template `html` / `css` helpers, the
|
|
7
|
+
`WebComponent` base class, the client and server renderers (with Declarative
|
|
8
|
+
Shadow DOM support), directives, context protocol, the `Task` controller, and
|
|
9
|
+
the client-side navigation router.
|
|
10
|
+
|
|
11
|
+
Not intended for direct install. You'll usually get it as a transitive dep
|
|
12
|
+
when you scaffold an app with [`@webjsdev/cli`](https://www.npmjs.com/package/@webjsdev/cli).
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
```sh
|
|
17
|
+
npm install @webjsdev/core
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Use
|
|
21
|
+
|
|
22
|
+
```js
|
|
23
|
+
import { html, css, WebComponent } from '@webjsdev/core';
|
|
24
|
+
|
|
25
|
+
class Counter extends WebComponent {
|
|
26
|
+
static properties = { count: { type: Number } };
|
|
27
|
+
static styles = css`button { padding: 8px 12px; }`;
|
|
28
|
+
|
|
29
|
+
render() {
|
|
30
|
+
return html`<button @click=${() => this.count++}>${this.count}</button>`;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
Counter.register('x-counter');
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
`Class.register('tag-name')` is the webjs idiom. It calls
|
|
37
|
+
`customElements.define()` under the hood and adds tag validation,
|
|
38
|
+
registry bookkeeping (needed for lazy-loading), and a dev-time
|
|
39
|
+
double-register warning. Plain `customElements.define('x-counter',
|
|
40
|
+
Counter)` works identically.
|
|
41
|
+
|
|
42
|
+
Side-channel imports for optional features:
|
|
43
|
+
|
|
44
|
+
```js
|
|
45
|
+
import '@webjsdev/core/client-router'; // SPA-style link interception
|
|
46
|
+
import { unsafeHTML } from '@webjsdev/core/directives';
|
|
47
|
+
import { createContext } from '@webjsdev/core/context';
|
|
48
|
+
import { Task } from '@webjsdev/core/task';
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
See the full framework docs at https://github.com/vivek7405/webjs.
|
|
52
|
+
|
|
53
|
+
## License
|
|
54
|
+
|
|
55
|
+
MIT
|
package/index.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public type surface for `webjs`.
|
|
3
|
+
*
|
|
4
|
+
* The runtime is packages/core/index.js (JSDoc-annotated JavaScript); this
|
|
5
|
+
* overlay exists so TypeScript-based editors (tsserver under VS Code,
|
|
6
|
+
* Neovim, Zed, WebStorm) resolve richer types than JSDoc alone can express
|
|
7
|
+
* - specifically the generic component factory and property-descriptor
|
|
8
|
+
* inference helpers. Zero runtime cost.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export * from './src/component.d.ts';
|
|
12
|
+
|
|
13
|
+
export { html, isTemplate, MARKER } from './src/html.js';
|
|
14
|
+
export { css, isCSS, adoptStyles, stylesToString } from './src/css.js';
|
|
15
|
+
export { register, lookup, lookupModuleUrl, isLazy, allTags, primeModuleUrl, tagOf } from './src/registry.js';
|
|
16
|
+
export { renderToString, renderToStream } from './src/render-server.js';
|
|
17
|
+
export { render } from './src/render-client.js';
|
|
18
|
+
export { escapeText, escapeAttr } from './src/escape.js';
|
|
19
|
+
export { notFound, redirect, isNotFound, isRedirect } from './src/nav.js';
|
|
20
|
+
export { expose, getExposed } from './src/expose.js';
|
|
21
|
+
export { repeat, isRepeat } from './src/repeat.js';
|
|
22
|
+
export { Suspense, isSuspense } from './src/suspense.js';
|
|
23
|
+
export { connectWS } from './src/websocket-client.js';
|
|
24
|
+
export { richFetch } from './src/rich-fetch.js';
|
|
25
|
+
export { enableClientRouter, disableClientRouter, navigate } from './src/router-client.js';
|
|
26
|
+
export { unsafeHTML, isUnsafeHTML, live, isLive } from './src/directives.js';
|
|
27
|
+
export { createContext, ContextProvider, ContextConsumer, ContextRequestEvent } from './src/context.js';
|
|
28
|
+
export { Task, TaskStatus } from './src/task.js';
|
package/index.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* webjs/core public surface.
|
|
3
|
+
*
|
|
4
|
+
* Isomorphic: this module is safe to import on both server and client.
|
|
5
|
+
* The client renderer is lazy-loaded by the WebComponent base. The server
|
|
6
|
+
* renderer is only reached on the server.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
export { html, isTemplate, MARKER } from './src/html.js';
|
|
10
|
+
export { css, isCSS, adoptStyles, stylesToString } from './src/css.js';
|
|
11
|
+
export { WebComponent } from './src/component.js';
|
|
12
|
+
export { register, lookup, lookupModuleUrl, isLazy, allTags, primeModuleUrl, tagOf } from './src/registry.js';
|
|
13
|
+
export { renderToString, renderToStream } from './src/render-server.js';
|
|
14
|
+
export { render } from './src/render-client.js';
|
|
15
|
+
export { escapeText, escapeAttr } from './src/escape.js';
|
|
16
|
+
export { notFound, redirect, isNotFound, isRedirect } from './src/nav.js';
|
|
17
|
+
export { expose, getExposed } from './src/expose.js';
|
|
18
|
+
export { repeat, isRepeat } from './src/repeat.js';
|
|
19
|
+
export { Suspense, isSuspense } from './src/suspense.js';
|
|
20
|
+
export { connectWS } from './src/websocket-client.js';
|
|
21
|
+
export { richFetch } from './src/rich-fetch.js';
|
|
22
|
+
export {
|
|
23
|
+
stringify, parse,
|
|
24
|
+
serialize, deserialize,
|
|
25
|
+
} from './src/serialize.js';
|
|
26
|
+
export { enableClientRouter, disableClientRouter, navigate, revalidate } from './src/router-client.js';
|
|
27
|
+
export { WebjsFrame } from './src/webjs-frame.js';
|
|
28
|
+
|
|
29
|
+
// Signals (TC39 Stage-1 shape), also available via '@webjsdev/core/signals'
|
|
30
|
+
export { signal, computed, effect, batch, isSignal, Signal } from './src/signal.js';
|
|
31
|
+
|
|
32
|
+
// Directives, also available via '@webjsdev/core/directives'
|
|
33
|
+
export { unsafeHTML, isUnsafeHTML, live, isLive } from './src/directives.js';
|
|
34
|
+
|
|
35
|
+
// Context Protocol, also available via '@webjsdev/core/context'
|
|
36
|
+
export { createContext, ContextProvider, ContextConsumer, ContextRequestEvent } from './src/context.js';
|
|
37
|
+
|
|
38
|
+
// Task controller, also available via '@webjsdev/core/task'
|
|
39
|
+
export { Task, TaskStatus } from './src/task.js';
|
package/package.json
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@webjsdev/core",
|
|
3
|
+
"version": "0.7.1",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"description": "webjs core runtime - html/css tags, WebComponent base, isomorphic renderers",
|
|
6
|
+
"types": "./index.d.ts",
|
|
7
|
+
"exports": {
|
|
8
|
+
".": {
|
|
9
|
+
"types": "./index.d.ts",
|
|
10
|
+
"default": "./index.js"
|
|
11
|
+
},
|
|
12
|
+
"./client": "./src/render-client.js",
|
|
13
|
+
"./server": "./src/render-server.js",
|
|
14
|
+
"./component": {
|
|
15
|
+
"types": "./src/component.d.ts",
|
|
16
|
+
"default": "./src/component.js"
|
|
17
|
+
},
|
|
18
|
+
"./registry": "./src/registry.js",
|
|
19
|
+
"./client-router": "./src/router-client.js",
|
|
20
|
+
"./signals": "./src/signal.js"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"index.js",
|
|
24
|
+
"index.d.ts",
|
|
25
|
+
"src",
|
|
26
|
+
"README.md"
|
|
27
|
+
],
|
|
28
|
+
"publishConfig": {
|
|
29
|
+
"access": "public"
|
|
30
|
+
},
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/vivek7405/webjs.git",
|
|
34
|
+
"directory": "packages/core"
|
|
35
|
+
},
|
|
36
|
+
"homepage": "https://github.com/vivek7405/webjs#readme",
|
|
37
|
+
"bugs": "https://github.com/vivek7405/webjs/issues",
|
|
38
|
+
"license": "MIT",
|
|
39
|
+
"keywords": [
|
|
40
|
+
"webjs",
|
|
41
|
+
"web-components",
|
|
42
|
+
"ssr",
|
|
43
|
+
"framework",
|
|
44
|
+
"no-build"
|
|
45
|
+
]
|
|
46
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript overlay for packages/core/src/component.js.
|
|
3
|
+
*
|
|
4
|
+
* The runtime is JSDoc-authored JavaScript; this file exists so editors
|
|
5
|
+
* (tsserver: used by VS Code, Neovim, Zed, WebStorm) resolve imports
|
|
6
|
+
* with full type information. Without this overlay, `declare foo: Foo`
|
|
7
|
+
* would type the field but the surrounding class (`this.requestUpdate`,
|
|
8
|
+
* lifecycle hooks, controllers) would be weakly typed. Zero runtime
|
|
9
|
+
* cost: nothing in this file ships to the browser.
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
import type { CSSResult } from './css.js';
|
|
13
|
+
import type { TemplateResult } from './html.js';
|
|
14
|
+
|
|
15
|
+
/** Any constructor the framework accepts as the `type:` field of a property. */
|
|
16
|
+
export type PropertyConstructor<T = unknown> =
|
|
17
|
+
| StringConstructor
|
|
18
|
+
| NumberConstructor
|
|
19
|
+
| BooleanConstructor
|
|
20
|
+
| ObjectConstructor
|
|
21
|
+
| ArrayConstructor
|
|
22
|
+
| (new (...args: any[]) => T)
|
|
23
|
+
| ((v: any) => T);
|
|
24
|
+
|
|
25
|
+
/** Runtime-level property declaration: matches `static properties = { … }`. */
|
|
26
|
+
export interface PropertyDeclaration<T = unknown> {
|
|
27
|
+
/** Constructor used for string → value coercion when the attribute changes. */
|
|
28
|
+
type?: PropertyConstructor<T>;
|
|
29
|
+
/** Write property changes back to the HTML attribute (kebab-cased). */
|
|
30
|
+
reflect?: boolean;
|
|
31
|
+
/** Internal-only: no attribute, no reflection, but still reactive. */
|
|
32
|
+
state?: boolean;
|
|
33
|
+
/** Rename the attribute, or pass `false` to suppress it entirely. */
|
|
34
|
+
attribute?: string | false;
|
|
35
|
+
/** Custom attribute ⇄ property serialisation. Takes precedence over `type`. */
|
|
36
|
+
converter?: {
|
|
37
|
+
fromAttribute?: (value: string | null, type?: PropertyConstructor<T>) => T;
|
|
38
|
+
toAttribute?: (value: T, type?: PropertyConstructor<T>) => string | null;
|
|
39
|
+
};
|
|
40
|
+
/** Custom dirty check. Return `true` to schedule an update. */
|
|
41
|
+
hasChanged?: (newValue: T, oldValue: T) => boolean;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/** Reactive controller protocol (Lit-compatible). */
|
|
45
|
+
export interface ReactiveController {
|
|
46
|
+
hostConnected?(): void;
|
|
47
|
+
hostDisconnected?(): void;
|
|
48
|
+
hostUpdate?(): void;
|
|
49
|
+
hostUpdated?(): void;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Base class for interactive web components.
|
|
54
|
+
*
|
|
55
|
+
* Declare runtime behaviour via `static properties = { … }` and type
|
|
56
|
+
* each field with a sibling `declare foo: Foo`:
|
|
57
|
+
*
|
|
58
|
+
* class StudentCard extends WebComponent {
|
|
59
|
+
* static properties = { student: { type: Object } };
|
|
60
|
+
* declare student: Student;
|
|
61
|
+
* render() { return html`<p>${this.student.name}</p>`; }
|
|
62
|
+
* }
|
|
63
|
+
* StudentCard.register('student-card');
|
|
64
|
+
*
|
|
65
|
+
* The `declare` field has no runtime cost: it tells TypeScript the
|
|
66
|
+
* field's type without emitting a class-field initializer that would
|
|
67
|
+
* clobber the reactive accessor the framework installs via
|
|
68
|
+
* `Object.defineProperty` in the constructor.
|
|
69
|
+
*
|
|
70
|
+
* See the Editor Setup doc for tooling that gives attribute/tag
|
|
71
|
+
* intelligence inside `html\`…\`` templates.
|
|
72
|
+
*/
|
|
73
|
+
export abstract class WebComponent extends HTMLElement {
|
|
74
|
+
static shadow: boolean;
|
|
75
|
+
static hydrate: 'visible' | undefined;
|
|
76
|
+
static properties: Record<string, PropertyDeclaration>;
|
|
77
|
+
static styles: CSSResult | CSSResult[] | null;
|
|
78
|
+
static lazy?: boolean;
|
|
79
|
+
/** Register this class as a custom element under `tag`. Tag must contain a hyphen. */
|
|
80
|
+
static register(tag: string): void;
|
|
81
|
+
static readonly observedAttributes: string[];
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Schedule a re-render. Optionally record a property change so lifecycle
|
|
85
|
+
* hooks can branch on what changed via `changedProperties`.
|
|
86
|
+
*
|
|
87
|
+
* For instance-local state, prefer a reactive property (`static
|
|
88
|
+
* properties = { foo: { state: true } }`) or a signal from
|
|
89
|
+
* `@webjsdev/core`'s `signal()`. The framework's built-in
|
|
90
|
+
* SignalWatcher wires every signal read in `render()` to a re-render
|
|
91
|
+
* automatically; explicit `requestUpdate()` is rarely needed.
|
|
92
|
+
*/
|
|
93
|
+
requestUpdate(name?: string, oldValue?: unknown): void;
|
|
94
|
+
/** A Promise that resolves after the next render commit. */
|
|
95
|
+
readonly updateComplete: Promise<boolean>;
|
|
96
|
+
/** Override point for `updateComplete`. Default returns the internal promise. */
|
|
97
|
+
getUpdateComplete(): Promise<boolean>;
|
|
98
|
+
/** Attach a reactive controller. */
|
|
99
|
+
addController(controller: ReactiveController): void;
|
|
100
|
+
/** Detach a reactive controller. */
|
|
101
|
+
removeController(controller: ReactiveController): void;
|
|
102
|
+
/** Returns the template for this render. May be async. */
|
|
103
|
+
render(): TemplateResult | Promise<TemplateResult> | void;
|
|
104
|
+
/** Decide whether to update. Default returns `true`. */
|
|
105
|
+
shouldUpdate(changedProperties: Map<string, unknown>): boolean;
|
|
106
|
+
/** Pre-render hook. Safe to set properties; folds into current cycle. */
|
|
107
|
+
willUpdate(changedProperties: Map<string, unknown>): void;
|
|
108
|
+
/** Render-and-commit step. Default calls `render()` and commits. */
|
|
109
|
+
update(changedProperties: Map<string, unknown>): void;
|
|
110
|
+
/** Post-render hook. Runs after every commit. */
|
|
111
|
+
updated(changedProperties: Map<string, unknown>): void;
|
|
112
|
+
/** One-shot hook after the first render lands in the DOM. */
|
|
113
|
+
firstUpdated?(changedProperties: Map<string, unknown>): void;
|
|
114
|
+
/** Optional render-error boundary inside the component. */
|
|
115
|
+
renderError?(error: Error): TemplateResult | void;
|
|
116
|
+
|
|
117
|
+
connectedCallback?(): void;
|
|
118
|
+
disconnectedCallback?(): void;
|
|
119
|
+
attributeChangedCallback?(name: string, oldValue: string | null, newValue: string | null): void;
|
|
120
|
+
}
|