ripple 0.4.2 → 0.4.3

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/CHANGELOG.md +107 -0
  2. package/package.json +9 -3
  3. package/src/jsx-runtime.d.ts +2 -1
  4. package/src/runtime/array.js +15 -9
  5. package/src/runtime/index-client.js +25 -7
  6. package/src/runtime/index-server.js +1 -0
  7. package/src/runtime/internal/client/attributes.js +313 -0
  8. package/src/runtime/internal/client/blocks.js +4 -14
  9. package/src/runtime/internal/client/component.js +2 -5
  10. package/src/runtime/internal/client/composite.js +14 -6
  11. package/src/runtime/internal/client/constants.js +6 -6
  12. package/src/runtime/internal/client/context.js +3 -2
  13. package/src/runtime/internal/client/css.js +11 -26
  14. package/src/runtime/internal/client/errors.js +188 -0
  15. package/src/runtime/internal/client/events.js +79 -34
  16. package/src/runtime/internal/client/expression.js +21 -116
  17. package/src/runtime/internal/client/for.js +108 -232
  18. package/src/runtime/internal/client/head.js +4 -3
  19. package/src/runtime/internal/client/html.js +5 -3
  20. package/src/runtime/internal/client/hydrate.js +484 -0
  21. package/src/runtime/internal/client/hydration-enabled.js +7 -0
  22. package/src/runtime/internal/client/hydration.js +16 -81
  23. package/src/runtime/internal/client/if.js +13 -9
  24. package/src/runtime/internal/client/index.js +14 -6
  25. package/src/runtime/internal/client/operations.js +11 -7
  26. package/src/runtime/internal/client/portal.js +3 -2
  27. package/src/runtime/internal/client/render.js +42 -325
  28. package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
  29. package/src/runtime/internal/client/runtime.js +87 -363
  30. package/src/runtime/internal/client/template-ns.js +47 -0
  31. package/src/runtime/internal/client/template.js +63 -140
  32. package/src/runtime/internal/client/track-async.js +356 -0
  33. package/src/runtime/internal/client/try.js +133 -319
  34. package/src/runtime/internal/client/types.d.ts +48 -24
  35. package/src/runtime/internal/server/index.js +31 -29
  36. package/src/runtime/internal/server/prerender.js +27 -0
  37. package/src/server/index.js +1 -0
  38. package/src/utils/class-name.js +28 -0
  39. package/tests/client/basic/basic.errors.test.tsrx +3 -3
  40. package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
  41. package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
  42. package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
  43. package/tests/client/composite/composite.props.test.tsrx +10 -10
  44. package/tests/client/derived-release.test.tsrx +3 -3
  45. package/tests/client/for-item.test.tsrx +39 -0
  46. package/tests/client/for-selector.test.tsrx +95 -0
  47. package/tests/hydration/compiled/client/basic.js +87 -87
  48. package/tests/hydration/compiled/client/composite.js +5 -5
  49. package/tests/hydration/compiled/client/events.js +40 -48
  50. package/tests/hydration/compiled/client/for.js +162 -181
  51. package/tests/hydration/compiled/client/fragment-cursor.js +521 -289
  52. package/tests/hydration/compiled/client/head.js +22 -22
  53. package/tests/hydration/compiled/client/hmr.js +4 -4
  54. package/tests/hydration/compiled/client/html-in-template.js +5 -5
  55. package/tests/hydration/compiled/client/html.js +152 -162
  56. package/tests/hydration/compiled/client/if-children.js +58 -53
  57. package/tests/hydration/compiled/client/if-fragment-controlflow.js +39 -39
  58. package/tests/hydration/compiled/client/if.js +26 -26
  59. package/tests/hydration/compiled/client/mixed-control-flow.js +56 -68
  60. package/tests/hydration/compiled/client/nested-control-flow.js +139 -271
  61. package/tests/hydration/compiled/client/portal.js +10 -10
  62. package/tests/hydration/compiled/client/reactivity.js +29 -29
  63. package/tests/hydration/compiled/client/return.js +2 -2
  64. package/tests/hydration/compiled/client/streaming.js +33 -35
  65. package/tests/hydration/compiled/client/switch.js +25 -25
  66. package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
  67. package/tests/hydration/compiled/client/try.js +15 -15
  68. package/tests/hydration/compiled/client/typed-text.js +7 -7
  69. package/tests/hydration/compiled/server/basic.js +6 -6
  70. package/tests/hydration/compiled/server/events.js +8 -8
  71. package/tests/hydration/compiled/server/for.js +22 -22
  72. package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
  73. package/tests/hydration/compiled/server/head.js +6 -6
  74. package/tests/hydration/compiled/server/hmr.js +1 -1
  75. package/tests/hydration/compiled/server/html.js +1 -1
  76. package/tests/hydration/compiled/server/if-children.js +9 -9
  77. package/tests/hydration/compiled/server/if.js +5 -5
  78. package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
  79. package/tests/hydration/compiled/server/portal.js +1 -1
  80. package/tests/hydration/compiled/server/reactivity.js +9 -9
  81. package/tests/hydration/compiled/server/streaming.js +9 -9
  82. package/tests/hydration/compiled/server/switch.js +4 -4
  83. package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
  84. package/tests/hydration/compiled/server/try.js +4 -4
  85. package/tests/hydration/compiled/server/typed-text.js +1 -1
  86. package/tests/hydration/components/fragment-cursor.tsrx +60 -0
  87. package/tests/hydration/components/track-async-serialization.tsrx +2 -2
  88. package/tests/hydration/fragment-cursor.test.js +34 -1
  89. package/tests/hydration/track-async-serialization.test.js +1 -1
  90. package/tests/server/basic.components.test.tsrx +3 -3
  91. package/tests/server/track-async-serialization.test.tsrx +6 -6
  92. package/tests/utils/tracked-types.test.js +3 -3
  93. package/types/index.d.ts +8 -8
  94. package/types/server.d.ts +17 -0
@@ -1,5 +1,5 @@
1
1
  import { DEV } from 'esm-env';
2
- import { setTransport, track, trackAsync } from 'ripple';
2
+ import { setTransport, track, trackAsync, trackReadOnly } from 'ripple';
3
3
  import * as devalue from 'devalue';
4
4
 
5
5
  const TRACK_ASYNC_PUBLIC_ERROR_MESSAGE = 'An error occurred during async rendering';
@@ -147,7 +147,7 @@ describe('trackAsync serialization (server)', () => {
147
147
  async function deps_for(read: 'direct' | 'view') {
148
148
  function App() @{
149
149
  const count = track(3);
150
- const view = count.readOnly();
150
+ const view = trackReadOnly(count);
151
151
  @try {
152
152
  const data = trackAsync(
153
153
  () => Promise.resolve(`count-${read === 'view' ? view.value : count.value}`),
@@ -160,7 +160,7 @@ describe('trackAsync serialization (server)', () => {
160
160
 
161
161
  const { body } = await render(App);
162
162
  const match = body.match(
163
- /<script id="__ripple_ta_[a-f0-9]+" type="application\/json">(.*?)<\/script>/s,
163
+ /<script id="__ripple_ta_[a-z0-9]+" type="application\/json">(.*?)<\/script>/s,
164
164
  );
165
165
  expect(match).not.toBeNull();
166
166
  return JSON.parse(/** @type {RegExpMatchArray} */ (match)[1]).deps;
@@ -170,7 +170,7 @@ describe('trackAsync serialization (server)', () => {
170
170
  expect(await deps_for('direct')).toHaveLength(1);
171
171
  });
172
172
 
173
- it('records the tracked behind a readOnly() view a trackAsync read', async () => {
173
+ it('records the tracked behind a trackReadOnly() view a trackAsync read', async () => {
174
174
  // The view itself has no hash; the client must still re-subscribe to
175
175
  // the source after hydration, so its hash is what gets recorded.
176
176
  expect(await deps_for('view')).toEqual(await deps_for('direct'));
@@ -190,7 +190,7 @@ describe('trackAsync serialization (server)', () => {
190
190
 
191
191
  const { body } = await render(App);
192
192
  const match = body.match(
193
- /<script id="__ripple_ta_[a-f0-9]+" type="application\/json">(.*?)<\/script>/s,
193
+ /<script id="__ripple_ta_[a-z0-9]+" type="application\/json">(.*?)<\/script>/s,
194
194
  );
195
195
  expect(match).not.toBeNull();
196
196
  const text = /** @type {RegExpMatchArray} */ (match)[1];
@@ -362,7 +362,7 @@ describe('trackAsync serialization (server)', () => {
362
362
 
363
363
  const { body } = await render(App);
364
364
  // Find all script tag IDs
365
- const matches = [...body.matchAll(/id="(__ripple_ta_[a-f0-9]+)"/g)];
365
+ const matches = [...body.matchAll(/id="(__ripple_ta_[a-z0-9]+)"/g)];
366
366
  expect(matches.length).toBe(2);
367
367
  // Hashes should be different
368
368
  expect(matches[0][1]).not.toBe(matches[1][1]);
@@ -44,7 +44,7 @@ function create_service(source) {
44
44
  describe('Ripple tracked types', () => {
45
45
  it('shows public names in value property hovers', () => {
46
46
  const source = `
47
- import { track } from 'ripple';
47
+ import { track, trackReadOnly } from 'ripple';
48
48
  const count = track(0);
49
49
  const derived = track(() => count.value * 2);
50
50
  const writable = track(() => count.value, undefined, true);
@@ -75,12 +75,12 @@ describe('Ripple tracked types', () => {
75
75
 
76
76
  it('preserves writes, read-only views, and tracked component props', () => {
77
77
  const source = `
78
- import { track, type Component, type Derived, type Tracked } from 'ripple';
78
+ import { track, type Component, type Derived, type Tracked, trackReadOnly } from 'ripple';
79
79
  const count = track(0);
80
80
  count.value = 1;
81
81
  const tracked: Tracked<number> = track(count);
82
82
  const derived: Derived<number> = tracked;
83
- const view = count.readOnly();
83
+ const view = trackReadOnly(count);
84
84
  // @ts-expect-error Read-only views reject writes.
85
85
  view.value = 2;
86
86
  const computed = track(() => count.value * 2);
package/types/index.d.ts CHANGED
@@ -225,12 +225,6 @@ export const SUSPENSE_REJECTED: unique symbol;
225
225
  export interface Tracked<V> extends TrackedCallable<V> {
226
226
  '#v': V;
227
227
  value: V;
228
- /**
229
- * A read-only view of this value: a `Derived<V>` that follows it, for a
230
- * receiver that should read but not write it. Equivalent to
231
- * `track(() => tracked.value)`.
232
- */
233
- readOnly(): Derived<V>;
234
228
  }
235
229
  // Augment Tracked to be callable when V is a Component.
236
230
  // This allows tracked component values to continue flowing through JSX checks.
@@ -242,8 +236,6 @@ interface TrackedCallable<V> {
242
236
  export interface Derived<V> extends TrackedCallable<V> {
243
237
  '#v': V;
244
238
  readonly value: V;
245
- /** A derived is already read-only: returns itself. */
246
- readOnly(): Derived<V>;
247
239
  }
248
240
  // A computed value created with a setter (`track(fn, get, set)`) or with
249
241
  // `true` in the setter position: writes land as a temporary value until the
@@ -284,6 +276,14 @@ export function track<V>(
284
276
  // Overload for non-function values
285
277
  export function track<V>(value?: V, get?: (v: V) => V, set?: (next: V, prev: V) => V): Tracked<V>;
286
278
 
279
+ /**
280
+ * A read-only view of a tracked or derived value, for a receiver that should
281
+ * read but not write it: a `Derived<V>` that follows a `Tracked<V>` or a
282
+ * writable derived (equivalent to `track(() => value.value)`), or a read-only
283
+ * derived as it is.
284
+ */
285
+ export function trackReadOnly<V>(value: Tracked<V> | Derived<V>): Derived<V>;
286
+
287
287
  export function trackAsync<V>(
288
288
  value: () => PromiseLike<V> | { promise: PromiseLike<V>; abortController: AbortController },
289
289
  ): Tracked<V>;
package/types/server.d.ts CHANGED
@@ -94,3 +94,20 @@ export declare function render(
94
94
  component: Component,
95
95
  options: StreamingRenderOptions,
96
96
  ): Promise<RenderStreamResult>;
97
+
98
+ export interface PrerenderResult {
99
+ head: string;
100
+ body: string;
101
+ /** the scoped CSS text — emit it in a `<style data-ripple-ssr>` tag */
102
+ css: string;
103
+ topLevelError: Error | null;
104
+ }
105
+
106
+ /**
107
+ * Renders a component to static HTML: buffered, every boundary settled, the
108
+ * scoped CSS as text. The static-generation counterpart of `render()`.
109
+ */
110
+ export declare function prerender(
111
+ component: Component,
112
+ options?: { rootBoundary?: RootBoundaryOptions },
113
+ ): Promise<PrerenderResult>;