@webjsdev/core 0.8.0 → 0.9.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.
Files changed (85) hide show
  1. package/README.md +5 -0
  2. package/dist/webjs-core-browser.js +6 -5
  3. package/dist/webjs-core-browser.js.map +3 -3
  4. package/dist/webjs-core-testing.js +20 -19
  5. package/dist/webjs-core-testing.js.map +3 -3
  6. package/dist/webjs-core.js +7 -6
  7. package/dist/webjs-core.js.map +3 -3
  8. package/index-browser.js +14 -9
  9. package/index.d.ts +53 -10
  10. package/index.js +17 -9
  11. package/package.json +15 -2
  12. package/src/action-effects-client.d.ts +5 -0
  13. package/src/action-effects-client.js +84 -0
  14. package/src/action-seed-client.js +5 -5
  15. package/src/asset-url.d.ts +18 -0
  16. package/src/asset-url.js +12 -13
  17. package/src/async-directive.d.ts +18 -0
  18. package/src/async-directive.js +88 -0
  19. package/src/attribute-reader.js +197 -23
  20. package/src/binding-prefixes.js +0 -12
  21. package/src/component/lifecycle.js +760 -209
  22. package/src/component/reactive.js +2 -10
  23. package/src/component/server-element.js +23 -1
  24. package/src/component.d.ts +151 -41
  25. package/src/context.d.ts +94 -18
  26. package/src/context.js +341 -217
  27. package/src/converters.d.ts +7 -0
  28. package/src/converters.js +38 -0
  29. package/src/csp-nonce.d.ts +18 -0
  30. package/src/css.d.ts +32 -6
  31. package/src/css.js +178 -14
  32. package/src/directive.d.ts +58 -0
  33. package/src/directive.js +119 -0
  34. package/src/directives.d.ts +38 -1
  35. package/src/directives.js +158 -1
  36. package/src/form-action.d.ts +13 -0
  37. package/src/form-action.js +139 -4
  38. package/src/hot.js +23 -0
  39. package/src/html.d.ts +4 -0
  40. package/src/html.js +35 -3
  41. package/src/is-server.d.ts +2 -0
  42. package/src/is-server.js +18 -0
  43. package/src/jsx-guard.js +130 -0
  44. package/src/metadata.d.ts +22 -3
  45. package/src/nav.d.ts +4 -1
  46. package/src/nav.js +44 -11
  47. package/src/optimistic.js +2 -2
  48. package/src/refresh-header.js +52 -0
  49. package/src/registry.js +10 -1
  50. package/src/render-client/adopt-slots.js +8 -3
  51. package/src/render-client/parts.js +745 -31
  52. package/src/render-client/reconciler.js +56 -11
  53. package/src/render-client/template-compiler.js +139 -44
  54. package/src/render-client.d.ts +5 -1
  55. package/src/render-server/attrs.js +2 -2
  56. package/src/render-server/compile.js +34 -0
  57. package/src/render-server/errors.js +37 -0
  58. package/src/render-server/expand.js +61 -8
  59. package/src/render-server/served-attrs.js +1 -2
  60. package/src/render-server/walk.js +135 -3
  61. package/src/render-server.d.ts +3 -0
  62. package/src/render-server.js +2 -0
  63. package/src/repeat.d.ts +7 -2
  64. package/src/repeat.js +20 -6
  65. package/src/router-client/dom-differ.js +17 -0
  66. package/src/router-client/fetch-apply.js +86 -5
  67. package/src/router-client/navigator.js +45 -9
  68. package/src/router-client/prefetch.js +3 -4
  69. package/src/router-client/root-attrs.js +43 -0
  70. package/src/router-client/stream.js +7 -0
  71. package/src/router-client/swap.js +4 -1
  72. package/src/routes.d.ts +75 -18
  73. package/src/serialize.d.ts +2 -0
  74. package/src/serialize.js +35 -4
  75. package/src/signal.d.ts +7 -0
  76. package/src/signal.js +26 -6
  77. package/src/slot/polyfills.js +3 -3
  78. package/src/slot.js +4 -8
  79. package/src/static-html.d.ts +22 -0
  80. package/src/static-html.js +144 -0
  81. package/src/task.d.ts +63 -20
  82. package/src/task.js +326 -293
  83. package/src/testing.d.ts +42 -0
  84. package/src/webjs-config.d.ts +1 -8
  85. package/src/websocket-client.d.ts +24 -0
package/src/testing.d.ts CHANGED
@@ -1,6 +1,48 @@
1
1
  import type { TemplateResult } from './html.js';
2
2
 
3
+ /**
4
+ * Server-render a template (or an HTML string) into a container in the test
5
+ * page, wait two macrotasks for the element to upgrade, and resolve its first
6
+ * element. A quick mount; use `ssrFixture` when the hydration round trip matters.
7
+ *
8
+ * @example
9
+ * ```js
10
+ * // modules/todos/components/browser/todo-item.test.js, run with `webjs test --browser`
11
+ * import { html } from '@webjsdev/core';
12
+ * import { fixture } from '@webjsdev/core/testing';
13
+ * import '../todo-item.ts';
14
+ *
15
+ * suite('<todo-item>', () => { // the runner's UI is tdd (suite / test), and a test throws to fail
16
+ * test('renders its title', async () => {
17
+ * const el = await fixture(html`<todo-item title="Buy milk"></todo-item>`);
18
+ * if (!el.textContent?.includes('Buy milk')) throw new Error('the title is missing');
19
+ * });
20
+ * });
21
+ * ```
22
+ */
3
23
  export function fixture(template: TemplateResult | string): Promise<Element>;
24
+ /**
25
+ * Server-render a template, hydrate it in the real browser, and resolve once
26
+ * the element's `updateComplete` settles, so the post-hydration DOM is what the
27
+ * test reads. The component module must be imported first.
28
+ *
29
+ * @example
30
+ * ```js
31
+ * // modules/counter/components/browser/counter-card.test.js, run with `webjs test --browser`
32
+ * import { html } from '@webjsdev/core';
33
+ * import { ssrFixture, waitForUpdate } from '@webjsdev/core/testing';
34
+ * import '../counter-card.ts';
35
+ *
36
+ * suite('<counter-card>', () => {
37
+ * test('counts a click after hydration', async () => {
38
+ * const el = await ssrFixture(html`<counter-card></counter-card>`);
39
+ * el.querySelector('button')?.click();
40
+ * await waitForUpdate(el);
41
+ * if (!el.textContent?.includes('1')) throw new Error('the count did not advance');
42
+ * });
43
+ * });
44
+ * ```
45
+ */
4
46
  export function ssrFixture(template: TemplateResult | string): Promise<Element>;
5
47
  export function waitForUpdate(el: Element): Promise<void>;
6
48
  export function assertNoA11yViolations(el: Element, opts?: Record<string, unknown>): Promise<void>;
@@ -220,7 +220,7 @@ export type WebjsDoctorSeverity = 'off' | 'warn' | 'error';
220
220
  export interface WebjsDoctorConfig {
221
221
  /**
222
222
  * Per-check severity, keyed by the stable doctor code (`NODE_VERSION`,
223
- * `UNMARKED_ASSET_LINKS`, `ELISION_CARRIERS`, and so on; `webjs doctor --json`
223
+ * `UNMARKED_ASSET_LINKS`, `ROUTE_BROWSER_CODE`, and so on; `webjs doctor --json`
224
224
  * carries the code on every result). A code with no entry keeps its default:
225
225
  * `error` for a hard toolchain failure, `warn` otherwise. This is how CI gates
226
226
  * on a chosen subset without `--strict` making every warning fatal.
@@ -277,13 +277,6 @@ export interface WebjsCspConfig {
277
277
  * Next.js superset.
278
278
  */
279
279
  export interface WebjsConfig {
280
- /**
281
- * Display-only and inert-route dead-JS elision switch. Default `true`.
282
- * Set to `false` to ship every module's JS app-wide. The `WEBJS_ELIDE`
283
- * env override wins over this.
284
- */
285
- elide?: boolean;
286
-
287
280
  /**
288
281
  * SSR action-result seeding switch (#472). Default `true`. When on, a
289
282
  * `'use server'` action's SSR result is serialized into the page so an
@@ -19,4 +19,28 @@ export interface WSConnection {
19
19
  readonly readyState: 0 | 1 | 2 | 3;
20
20
  }
21
21
 
22
+ /**
23
+ * Open a managed WebSocket: a relative path is promoted to ws:// or wss://, it
24
+ * reconnects with backoff unless `reconnect: false`, a string message that is
25
+ * JSON arrives parsed, `send()` JSON-encodes an object and queues while
26
+ * disconnected, and `close()` stops for good.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // modules/chat/components/chat-feed.ts, fed by app/api/chat/route.ts (its WS export)
31
+ * import { WebComponent, html, signal, connectWS, type WSConnection } from '@webjsdev/core';
32
+ *
33
+ * export class ChatFeed extends WebComponent {
34
+ * readonly #lines = signal<string[]>([]);
35
+ * #conn: WSConnection | null = null;
36
+ * connectedCallback() { // browser only, so no socket opens during SSR
37
+ * super.connectedCallback();
38
+ * this.#conn = connectWS('/api/chat', { onMessage: (msg) => this.#lines.set([...this.#lines.get(), String(msg)]) });
39
+ * }
40
+ * disconnectedCallback() { super.disconnectedCallback(); this.#conn?.close(); }
41
+ * render() { return html`<ul>${this.#lines.get().map((line) => html`<li>${line}</li>`)}</ul>`; }
42
+ * }
43
+ * ChatFeed.register('chat-feed');
44
+ * ```
45
+ */
22
46
  export function connectWS(url: string, opts?: ConnectOptions): WSConnection;