ripple 0.4.2 → 0.4.4

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 (98) hide show
  1. package/CHANGELOG.md +164 -0
  2. package/package.json +10 -4
  3. package/src/constants.js +6 -0
  4. package/src/jsx-runtime.d.ts +2 -1
  5. package/src/runtime/array.js +15 -9
  6. package/src/runtime/index-client.js +25 -7
  7. package/src/runtime/index-server.js +1 -0
  8. package/src/runtime/internal/client/attributes.js +439 -0
  9. package/src/runtime/internal/client/blocks.js +20 -20
  10. package/src/runtime/internal/client/component.js +2 -5
  11. package/src/runtime/internal/client/composite.js +295 -95
  12. package/src/runtime/internal/client/constants.js +14 -6
  13. package/src/runtime/internal/client/context.js +3 -2
  14. package/src/runtime/internal/client/css.js +11 -26
  15. package/src/runtime/internal/client/errors.js +188 -0
  16. package/src/runtime/internal/client/events.js +79 -34
  17. package/src/runtime/internal/client/expression.js +25 -120
  18. package/src/runtime/internal/client/for.js +113 -262
  19. package/src/runtime/internal/client/head.js +4 -3
  20. package/src/runtime/internal/client/html.js +5 -3
  21. package/src/runtime/internal/client/hydrate.js +484 -0
  22. package/src/runtime/internal/client/hydration-enabled.js +7 -0
  23. package/src/runtime/internal/client/hydration.js +16 -81
  24. package/src/runtime/internal/client/if.js +69 -10
  25. package/src/runtime/internal/client/index.js +18 -10
  26. package/src/runtime/internal/client/operations.js +11 -7
  27. package/src/runtime/internal/client/portal.js +3 -2
  28. package/src/runtime/internal/client/render.js +42 -325
  29. package/src/runtime/internal/client/root-boundary-enabled.js +7 -0
  30. package/src/runtime/internal/client/runtime.js +157 -371
  31. package/src/runtime/internal/client/template-ns.js +88 -0
  32. package/src/runtime/internal/client/template.js +118 -139
  33. package/src/runtime/internal/client/track-async.js +356 -0
  34. package/src/runtime/internal/client/try.js +133 -319
  35. package/src/runtime/internal/client/types.d.ts +48 -24
  36. package/src/runtime/internal/server/index.js +31 -29
  37. package/src/runtime/internal/server/prerender.js +27 -0
  38. package/src/server/index.js +1 -0
  39. package/src/utils/class-name.js +28 -0
  40. package/tests/client/basic/basic.errors.test.tsrx +3 -3
  41. package/tests/client/compiler/__snapshots__/compiler.typescript.test.tsrx.snap +0 -2
  42. package/tests/client/compiler/compiler.basic.test.tsrx +2 -2
  43. package/tests/client/compiler/compiler.tracked-access.test.tsrx +3 -3
  44. package/tests/client/composite/composite.dynamic-components.test.tsrx +40 -0
  45. package/tests/client/composite/composite.props.test.tsrx +10 -10
  46. package/tests/client/css/scoped-styles.test.tsrx +3 -1
  47. package/tests/client/derived-release.test.tsrx +3 -3
  48. package/tests/client/for-item.test.tsrx +39 -0
  49. package/tests/client/for-selector.test.tsrx +95 -0
  50. package/tests/client/svg.test.tsrx +273 -1
  51. package/tests/hydration/compiled/client/basic.js +88 -87
  52. package/tests/hydration/compiled/client/composite.js +15 -6
  53. package/tests/hydration/compiled/client/events.js +40 -48
  54. package/tests/hydration/compiled/client/for.js +191 -199
  55. package/tests/hydration/compiled/client/fragment-cursor.js +633 -334
  56. package/tests/hydration/compiled/client/head.js +22 -22
  57. package/tests/hydration/compiled/client/hmr.js +14 -5
  58. package/tests/hydration/compiled/client/html-in-template.js +5 -5
  59. package/tests/hydration/compiled/client/html.js +195 -177
  60. package/tests/hydration/compiled/client/if-children.js +136 -63
  61. package/tests/hydration/compiled/client/if-fragment-controlflow.js +63 -43
  62. package/tests/hydration/compiled/client/if.js +78 -30
  63. package/tests/hydration/compiled/client/mixed-control-flow.js +90 -72
  64. package/tests/hydration/compiled/client/nested-control-flow.js +266 -307
  65. package/tests/hydration/compiled/client/portal.js +20 -11
  66. package/tests/hydration/compiled/client/reactivity.js +29 -29
  67. package/tests/hydration/compiled/client/return.js +2 -2
  68. package/tests/hydration/compiled/client/streaming.js +33 -35
  69. package/tests/hydration/compiled/client/switch.js +25 -25
  70. package/tests/hydration/compiled/client/track-async-serialization.js +41 -41
  71. package/tests/hydration/compiled/client/try.js +15 -15
  72. package/tests/hydration/compiled/client/typed-text.js +8 -7
  73. package/tests/hydration/compiled/server/basic.js +6 -6
  74. package/tests/hydration/compiled/server/events.js +8 -8
  75. package/tests/hydration/compiled/server/for.js +22 -22
  76. package/tests/hydration/compiled/server/fragment-cursor.js +188 -52
  77. package/tests/hydration/compiled/server/head.js +6 -6
  78. package/tests/hydration/compiled/server/hmr.js +1 -1
  79. package/tests/hydration/compiled/server/html.js +1 -1
  80. package/tests/hydration/compiled/server/if-children.js +9 -9
  81. package/tests/hydration/compiled/server/if.js +5 -5
  82. package/tests/hydration/compiled/server/mixed-control-flow.js +4 -4
  83. package/tests/hydration/compiled/server/portal.js +1 -1
  84. package/tests/hydration/compiled/server/reactivity.js +9 -9
  85. package/tests/hydration/compiled/server/streaming.js +9 -9
  86. package/tests/hydration/compiled/server/switch.js +4 -4
  87. package/tests/hydration/compiled/server/track-async-serialization.js +16 -16
  88. package/tests/hydration/compiled/server/try.js +4 -4
  89. package/tests/hydration/compiled/server/typed-text.js +1 -1
  90. package/tests/hydration/components/fragment-cursor.tsrx +60 -0
  91. package/tests/hydration/components/track-async-serialization.tsrx +2 -2
  92. package/tests/hydration/fragment-cursor.test.js +34 -1
  93. package/tests/hydration/track-async-serialization.test.js +1 -1
  94. package/tests/server/basic.components.test.tsrx +3 -3
  95. package/tests/server/track-async-serialization.test.tsrx +6 -6
  96. package/tests/utils/tracked-types.test.js +3 -3
  97. package/types/index.d.ts +8 -8
  98. package/types/server.d.ts +17 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,169 @@
1
1
  # ripple
2
2
 
3
+ ## 0.4.4
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1496](https://github.com/Ripple-TS/ripple/pull/1496)
8
+ [`0473e93`](https://github.com/Ripple-TS/ripple/commit/0473e93006e53cd15fcf6d851443d427ccf13e8b)
9
+ Thanks [@leonidaz](https://github.com/leonidaz)! - Update `@tsrx/core` to ^0.2.3
10
+ and use its SVG and MathML tag-name predicates for dynamic class handling,
11
+ removing the compiler's duplicate tag-name list.
12
+
13
+ - [#1490](https://github.com/Ripple-TS/ripple/pull/1490)
14
+ [`ff3a26a`](https://github.com/Ripple-TS/ripple/commit/ff3a26acef0c9584cf41d32bc8cbcc39d863d74c)
15
+ Thanks [@leonidaz](https://github.com/leonidaz)! - Blocks keep the namespace
16
+ they were created in when they rerun. A dynamic element whose tag changes, an
17
+ `@if` that toggles, or an `@for` that grows inside an SVG that is only known at
18
+ runtime (children rendered into a component's `<svg>`, a leaf component rendered
19
+ there) now creates its elements in the SVG namespace instead of HTML, and a
20
+ nested template cloned in that context no longer throws before a namespaced
21
+ template has been parsed. A dynamic element whose tag becomes `foreignObject`
22
+ renders its children as HTML.
23
+
24
+ - [#1488](https://github.com/Ripple-TS/ripple/pull/1488)
25
+ [`b3bf787`](https://github.com/Ripple-TS/ripple/commit/b3bf78756d9235412a2af264e42897652e8f911e)
26
+ Thanks [@leonidaz](https://github.com/leonidaz)! - Build a template that is one
27
+ element with static attributes and at most a text child with DOM calls instead
28
+ of parsing it. Parsing a `<template>` has a fixed cost that dwarfs such an
29
+ element, and an app's first render pays it once per distinct template; a chain
30
+ of 100 single-element components mounts about 35% faster.
31
+
32
+ - [#1495](https://github.com/Ripple-TS/ripple/pull/1495)
33
+ [`1b8381f`](https://github.com/Ripple-TS/ripple/commit/1b8381f31f98f84049764ca56676fc320721e844)
34
+ Thanks [@leonidaz](https://github.com/leonidaz)! - Faster element spreads,
35
+ dynamic elements and list items. An element spread is applied from the element's
36
+ own render function instead of a render block of its own, and a spread object
37
+ identical to the one applied last is skipped without a diff (a spread of a
38
+ tracked object or of tracked values is always diffed). A dynamic element
39
+ (`<{tag}>`) is one block that owns its element and applies its attributes
40
+ itself; a tag that does not change keeps its element and diffs the attributes,
41
+ so a swap between variants with the same tag no longer recreates the element. An
42
+ `@if` whose condition reads tracked state is evaluated by the render function of
43
+ the enclosing content (a list item's, an element's), so the if keeps a block for
44
+ its branch but not one that runs the condition. A dynamic element or component
45
+ called inside an `<svg>` or `<math>` template receives the namespace as an
46
+ argument instead of a `with_ns` closure. A dynamic element without children is
47
+ driven by the render function of the content it sits in, with no block or
48
+ closures of its own (`_$_.dynamic`); a build that can hydrate lets a composite
49
+ block claim the server element while hydrating. With `textTypes`, an attribute
50
+ value TypeScript proves to be a string is set with a direct `setAttribute` call,
51
+ and a proven `class` takes the string-only path. On the SVG dashboard benchmark,
52
+ mounting is about 20% faster and swapping 150 dynamic icons 40% faster.
53
+ - Updated dependencies
54
+ [[`0473e93`](https://github.com/Ripple-TS/ripple/commit/0473e93006e53cd15fcf6d851443d427ccf13e8b),
55
+ [`b3bf787`](https://github.com/Ripple-TS/ripple/commit/b3bf78756d9235412a2af264e42897652e8f911e),
56
+ [`1b8381f`](https://github.com/Ripple-TS/ripple/commit/1b8381f31f98f84049764ca56676fc320721e844),
57
+ [`ff3a26a`](https://github.com/Ripple-TS/ripple/commit/ff3a26acef0c9584cf41d32bc8cbcc39d863d74c)]:
58
+ - @tsrx/ripple@0.2.3
59
+
60
+ ## 0.4.3
61
+
62
+ ### Patch Changes
63
+
64
+ - [#1486](https://github.com/Ripple-TS/ripple/pull/1486)
65
+ [`304ba6c`](https://github.com/Ripple-TS/ripple/commit/304ba6c2d9098752396fff6c2545e3ef2546381c)
66
+ Thanks [@leonidaz](https://github.com/leonidaz)! - perf: a static component,
67
+ template `@if`, or template `@for` followed by a static element sibling inserts
68
+ before that element instead of before a `<!>` placeholder of its own: the
69
+ element is part of the template and never moves, so the compiled template holds
70
+ no comment node for it and the client reuses the element's variable where
71
+ hydration steps to the sibling. The `RippleArray` statics (`from`, `of`,
72
+ `fromAsync`) lower to standalone runtime functions, so a bundle that never
73
+ constructs a `RippleArray` drops the array proxy instead of keeping it through
74
+ property assignments on the constructor's compiled form (the server's
75
+ `fromAsync` lowering previously named a function that did not exist).
76
+
77
+ - [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
78
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
79
+ Thanks [@leonidaz](https://github.com/leonidaz)! - perf: smaller production
80
+ bundles without a runtime cost. The compiler lowers a static `onBlur`-style
81
+ handler (an event its name keeps off delegation) to a direct `listen` call with
82
+ the DOM name and phase resolved at compile time, packs the locals a hoisted
83
+ `@if`/`@switch` captures under positional keys, writes template strings without
84
+ attribute quotes or implied end tags where the parser reads them back the same,
85
+ gives a plain function no `_$_.scope()` call when its body never reads the
86
+ block, and omits `set_class`'s default trailing arguments. The runtime keeps its
87
+ hydration paths (template adoption, expression text, append cursor, streamed
88
+ boundaries) in a module `hydrate()` installs and its `trackAsync` machinery in a
89
+ module that registers with the runtime on first use, and the catch routing is
90
+ registered by the first boundary, so a client-only mount without `trackAsync`
91
+ ships neither and the core runtime no longer imports the boundary module; the
92
+ try boundary state, the root event ref and the template cache use short keys,
93
+ the keyed and reference list diffs share one patch helper, and symbol constants
94
+ carry no descriptions. The runtime's errors are thrown as in Svelte: the message
95
+ and a link to `https://ripple-ts.com/e/<code>` in development, the link alone in
96
+ production, so the message text stays out of production bundles; `set_class`
97
+ composes non-string values with its own clsx-style joiner instead of importing
98
+ `clsx`; hoisted render blocks store captured locals under positional keys; a
99
+ `template()` with no flags passes none; and the hash a `track()` call carries
100
+ encodes the same 32 bits in base 36. The Vite plugin leaves Vite's modulepreload
101
+ polyfill out of production builds unless `build.modulePreload` is configured.
102
+
103
+ - [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
104
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
105
+ Thanks [@leonidaz](https://github.com/leonidaz)! - feat: build shapes.
106
+ `ripple({ ssr: false })` builds a client-only app: components compile without
107
+ the hydration cursor or `track()` serialization hashes (`hydration: false` on
108
+ the compiler), the runtime's hydration paths are compiled out through its
109
+ `HYDRATION` build constant, and `hydrate()` throws; `ssr: true` compiles every
110
+ module for the server. `prerender()` on `ripple/server` renders a component to
111
+ static HTML with every boundary settled and the CSS as text, and a `RenderRoute`
112
+ marked `prerender: true` is rendered through the built server entry at build
113
+ time into `<outDir>/client<path>/index.html`, which the node and bun adapters
114
+ now serve for a directory request before the server renders. The client build's
115
+ `index.html` template moves to the server output so a static handler never
116
+ serves its placeholders.
117
+
118
+ - [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
119
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
120
+ Thanks [@leonidaz](https://github.com/leonidaz)! - perf: a `class` expression
121
+ the compiler can prove to be a string writes through a string-only `set_class`,
122
+ so the clsx-style joiner ships only with a bundle that composes classes from
123
+ arrays or objects; templates in the SVG or MathML namespace parse through a
124
+ `template_ns` entry that an HTML-only bundle never loads; and the class joiner
125
+ is one module shared by the client and server renderers, so `ripple` no longer
126
+ depends on `clsx`. `ripple({ rootBoundary: false })` builds an app that renders
127
+ without the default root try/pending/catch boundary and leaves the boundary
128
+ runtime out of the bundle; a `rootBoundary` option on `mount()` or `hydrate()`
129
+ then throws. The `ripple` package declares `sideEffects: false`, and dynamic
130
+ attribute, style and spread helpers live in their own runtime module, so a
131
+ bundle that never sets an attribute dynamically drops them along with the
132
+ attribute tables they consult. The plugin's `ssr: false` and
133
+ `rootBoundary: false` rewrite the runtime's build-constant imports to literals
134
+ at transform time, which every bundler folds while tree-shaking.
135
+
136
+ - [#1484](https://github.com/Ripple-TS/ripple/pull/1484)
137
+ [`1ea71f1`](https://github.com/Ripple-TS/ripple/commit/1ea71f14fcee5a976ea81e2bedf5010251eaa70c)
138
+ Thanks [@leonidaz](https://github.com/leonidaz)! - perf: a template `@if` that
139
+ closes the trailing run of an element's children (nothing rendered follows it)
140
+ never materializes an anchor node: the element's tail is its position for its
141
+ whole life. An `@if (outer === item.key)` in a `@for` body lowers to the loop's
142
+ selector like an attribute comparison, and a comparison against the item's key
143
+ reads the block's key (fixed for its life) rather than the item, so a change of
144
+ the outer value re-runs the ifs of its previous and next key alone and a
145
+ replaced item leaves its ifs untouched; comparisons against the same outer value
146
+ share one selector per loop. Event delegation reads the composed path only for a
147
+ nested root and looks the handler property up by one string, and `checked` is
148
+ compared against the element instead of a cached write.
149
+
150
+ - [#1487](https://github.com/Ripple-TS/ripple/pull/1487)
151
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)
152
+ Thanks [@leonidaz](https://github.com/leonidaz)! - `trackReadOnly(value)`
153
+ replaces the `readOnly()` method on tracked and derived values: it returns a
154
+ derived that follows a tracked or writable derived, or a read-only derived as it
155
+ is. The method is removed, so `count.readOnly()` becomes `trackReadOnly(count)`,
156
+ imported from `ripple`. Dropping the prototype methods lets a bundle that never
157
+ takes a read-only view leave the code out.
158
+ - Updated dependencies
159
+ [[`304ba6c`](https://github.com/Ripple-TS/ripple/commit/304ba6c2d9098752396fff6c2545e3ef2546381c),
160
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1),
161
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1),
162
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1),
163
+ [`1ea71f1`](https://github.com/Ripple-TS/ripple/commit/1ea71f14fcee5a976ea81e2bedf5010251eaa70c),
164
+ [`b4abea0`](https://github.com/Ripple-TS/ripple/commit/b4abea0ab4830eed99adf14dc95a0ef214b24af1)]:
165
+ - @tsrx/ripple@0.2.2
166
+
3
167
  ## 0.4.2
4
168
 
5
169
  ### Patch Changes
package/package.json CHANGED
@@ -3,8 +3,9 @@
3
3
  "description": "Ripple is an elegant TypeScript UI framework",
4
4
  "license": "MIT",
5
5
  "author": "Dominic Gannaway",
6
- "version": "0.4.2",
6
+ "version": "0.4.4",
7
7
  "type": "module",
8
+ "sideEffects": false,
8
9
  "module": "src/runtime/index-client.js",
9
10
  "main": "src/runtime/index-client.js",
10
11
  "repository": {
@@ -54,6 +55,12 @@
54
55
  "./internal/client": {
55
56
  "default": "./src/runtime/internal/client/index.js"
56
57
  },
58
+ "./internal/client/hydration-enabled": {
59
+ "default": "./src/runtime/internal/client/hydration-enabled.js"
60
+ },
61
+ "./internal/client/root-boundary-enabled": {
62
+ "default": "./src/runtime/internal/client/root-boundary-enabled.js"
63
+ },
57
64
  "./internal/client-types": {
58
65
  "types": "./src/runtime/internal/client/types.d.ts"
59
66
  },
@@ -76,12 +83,11 @@
76
83
  "#public": "./types/index.d.ts"
77
84
  },
78
85
  "dependencies": {
79
- "clsx": "^2.1.1",
80
86
  "csstype": "^3.2.3",
81
87
  "devalue": "^5.9.2",
82
88
  "esm-env": "^1.2.2",
83
- "@tsrx/core": "^0.2.0",
84
- "@tsrx/ripple": "0.2.1"
89
+ "@tsrx/core": "^0.2.3",
90
+ "@tsrx/ripple": "0.2.3"
85
91
  },
86
92
  "devDependencies": {
87
93
  "@types/estree": "^1.0.8",
package/src/constants.js CHANGED
@@ -38,3 +38,9 @@ export const ELEMENT_NODE = 1;
38
38
  export const TEXT_NODE = 3;
39
39
  export const COMMENT_NODE = 8;
40
40
  export const DOCUMENT_FRAGMENT_NODE = 11;
41
+
42
+ // `if_static` flags (see the runtime's if module): the if renders directly
43
+ // before the component's `__anchor`, and the compiler proved its condition
44
+ // reads tracked state.
45
+ export const IF_ROOT_CONTROLLED = 1;
46
+ export const IF_TRACKED = 1 << 1;
@@ -55,7 +55,8 @@ type NullableStyleProperties<T> = { [Property in keyof T]: T[Property] | null };
55
55
 
56
56
  /** JSX attributes live under Ripple so editor hovers identify their framework. */
57
57
  declare namespace Ripple {
58
- type ClassValue = string | import('clsx').ClassArray | import('clsx').ClassDictionary;
58
+ type ClassValue =
59
+ string | number | boolean | null | undefined | ClassValue[] | { [key: string]: unknown };
59
60
 
60
61
  /** Inline CSS styles. Values keep their units; null and undefined remove a property. */
61
62
  interface CSSProperties
@@ -24,7 +24,7 @@ export class RippleArray {
24
24
  * @returns {RippleArray<U>}
25
25
  */
26
26
  static from(arrayLike, mapFn, thisArg) {
27
- return ripple_array.from(safe_scope(), arrayLike, mapFn, thisArg);
27
+ return ripple_array_from(safe_scope(), arrayLike, mapFn, thisArg);
28
28
  }
29
29
 
30
30
  /**
@@ -33,7 +33,7 @@ export class RippleArray {
33
33
  * @returns {RippleArray<U>}
34
34
  */
35
35
  static of(...items) {
36
- return ripple_array.of(safe_scope(), ...items);
36
+ return ripple_array_of(safe_scope(), ...items);
37
37
  }
38
38
 
39
39
  /**
@@ -44,11 +44,14 @@ export class RippleArray {
44
44
  * @returns {Promise<RippleArray<U>>}
45
45
  */
46
46
  static async fromAsync(arrayLike, mapFn, thisArg) {
47
- return ripple_array.fromAsync(safe_scope(), arrayLike, mapFn, thisArg);
47
+ return ripple_array_from_async(safe_scope(), arrayLike, mapFn, thisArg);
48
48
  }
49
49
  }
50
50
 
51
51
  /**
52
+ * The compiled form of `new RippleArray(...)`. Each static below is its own
53
+ * function so a bundle that never uses one drops it (and the proxy it would
54
+ * create) instead of keeping a function that carries them all.
52
55
  * @template T
53
56
  * @param {Block} block
54
57
  * @param {...T} elements
@@ -59,6 +62,7 @@ export function ripple_array(block, ...elements) {
59
62
  }
60
63
 
61
64
  /**
65
+ * `RippleArray.from(...)`
62
66
  * @template T
63
67
  * @param {Block} block
64
68
  * @param {ArrayLike<T> | Iterable<T>} arrayLike
@@ -66,23 +70,25 @@ export function ripple_array(block, ...elements) {
66
70
  * @param {*} [thisArg]
67
71
  * @returns {RippleArray<T>}
68
72
  */
69
- ripple_array.from = function (block, arrayLike, mapFn, thisArg) {
73
+ export function ripple_array_from(block, arrayLike, mapFn, thisArg) {
70
74
  var elements = mapFn ? Array.from(arrayLike, mapFn, thisArg) : Array.from(arrayLike);
71
75
  return array_proxy({ elements, block, from_static: true });
72
- };
76
+ }
73
77
 
74
78
  /**
79
+ * `RippleArray.of(...)`
75
80
  * @template T
76
81
  * @param {Block} block
77
82
  * @param {...T} items
78
83
  * @returns {RippleArray<T>}
79
84
  */
80
- ripple_array.of = function (block, ...items) {
85
+ export function ripple_array_of(block, ...items) {
81
86
  var elements = Array.of(...items);
82
87
  return array_proxy({ elements, block, from_static: true });
83
- };
88
+ }
84
89
 
85
90
  /**
91
+ * `RippleArray.fromAsync(...)`
86
92
  * @template T
87
93
  * @param {Block} block
88
94
  * @param {ArrayLike<T> | Iterable<T>} arrayLike
@@ -90,9 +96,9 @@ ripple_array.of = function (block, ...items) {
90
96
  * @param {any} [thisArg]
91
97
  * @returns {Promise<RippleArray<T>>}
92
98
  */
93
- ripple_array.fromAsync = async function (block, arrayLike, mapFn, thisArg) {
99
+ export async function ripple_array_from_async(block, arrayLike, mapFn, thisArg) {
94
100
  var elements = mapFn
95
101
  ? await Array.fromAsync(arrayLike, mapFn, thisArg)
96
102
  : await Array.fromAsync(arrayLike);
97
103
  return array_proxy({ elements, block, from_static: true });
98
- };
104
+ }
@@ -6,6 +6,9 @@ import { init_operations } from './internal/client/operations.js';
6
6
  import { render_component } from './internal/client/component.js';
7
7
  import { try_block } from './internal/client/try.js';
8
8
  import { remove_styles } from './internal/client/css.js';
9
+ import { install_hydration } from './internal/client/hydrate.js';
10
+ import { hydration_disabled, root_boundary_disabled } from './internal/client/errors.js';
11
+ import { ROOT_BOUNDARY } from 'ripple/internal/client/root-boundary-enabled';
9
12
  import { normalize_children } from './element.js';
10
13
  import {
11
14
  hydrate_next,
@@ -82,8 +85,10 @@ export function mount(component, options) {
82
85
  // Requesting a frame otherwise makes the browser attach layout to the
83
86
  // mounted tree before the app's next update, which slows a teardown that
84
87
  // would have preceded the first paint.
85
- if (document.querySelector('style[data-ripple-ssr]') !== null) {
86
- requestAnimationFrame(remove_styles);
88
+ if (HYDRATION) {
89
+ if (document.querySelector('style[data-ripple-ssr]') !== null) {
90
+ requestAnimationFrame(remove_styles);
91
+ }
87
92
  }
88
93
 
89
94
  let props = options.props ?? {};
@@ -100,15 +105,18 @@ export function mount(component, options) {
100
105
  // The app appends into the emptied target; a root that keeps inserting
101
106
  // relative to its anchor materializes one (see `resolve_anchor`).
102
107
  /** @type {AppendIntoAnchor} */
103
- const anchor = { parent: target, into: true };
108
+ const anchor = { parent: target, into: true, tail: false };
104
109
 
105
110
  /** @type {import('./internal/client/events.js').RootTargetRef | null} */
106
111
  let events_ref = handle_root_events(target);
107
112
 
108
113
  const root_boundary = options.rootBoundary;
114
+ if (!ROOT_BOUNDARY && root_boundary != null && root_boundary !== false) {
115
+ root_boundary_disabled();
116
+ }
109
117
 
110
118
  const _root = root(() => {
111
- if (root_boundary === false) {
119
+ if (!ROOT_BOUNDARY || root_boundary === false) {
112
120
  render_component(component, anchor, props);
113
121
  return;
114
122
  }
@@ -144,7 +152,11 @@ export function mount(component, options) {
144
152
  * @returns {() => void}
145
153
  */
146
154
  export function hydrate(component, options) {
155
+ if (!HYDRATION) {
156
+ hydration_disabled();
157
+ }
147
158
  init_operations();
159
+ install_hydration();
148
160
  requestAnimationFrame(remove_styles);
149
161
 
150
162
  let props = options.props ?? {};
@@ -152,7 +164,7 @@ export function hydrate(component, options) {
152
164
  props = normalize_props(props);
153
165
  }
154
166
  const target = options.target;
155
- const was_hydrating = hydrating;
167
+ const was_hydrating = HYDRATION && hydrating;
156
168
  const previous_hydrate_node = hydrate_node;
157
169
  let anchor = target.firstChild;
158
170
 
@@ -176,9 +188,12 @@ export function hydrate(component, options) {
176
188
 
177
189
  const root_boundary = options.rootBoundary;
178
190
  const marker = /** @type {Comment} */ (anchor);
191
+ if (!ROOT_BOUNDARY && root_boundary != null && root_boundary !== false) {
192
+ root_boundary_disabled();
193
+ }
179
194
 
180
195
  _root = root(() => {
181
- if (root_boundary === false && marker.data === HYDRATION_START) {
196
+ if ((!ROOT_BOUNDARY || root_boundary === false) && marker.data === HYDRATION_START) {
182
197
  // The root boundary's own hydration walk: consume the `<!--[-->`
183
198
  // marker and render against it, as `try_block` does for the root.
184
199
  hydrate_next();
@@ -215,13 +230,15 @@ export { Context } from './internal/client/context.js';
215
230
  export {
216
231
  flush_sync as flushSync,
217
232
  track,
218
- track_async as trackAsync,
233
+ track_read_only as trackReadOnly,
219
234
  untrack,
220
235
  tick,
221
236
  is_tracked_pending as trackPending,
222
237
  peek_tracked as peek,
223
238
  } from './internal/client/runtime.js';
224
239
 
240
+ export { track_async as trackAsync } from './internal/client/track-async.js';
241
+
225
242
  export { snapshot } from './proxy.js';
226
243
 
227
244
  export { RippleArray } from './array.js';
@@ -271,3 +288,4 @@ export {
271
288
  bindOffsetWidth,
272
289
  bindOffsetHeight,
273
290
  } from './internal/client/bindings.js';
291
+ import { HYDRATION } from 'ripple/internal/client/hydration-enabled';
@@ -6,6 +6,7 @@ export { Context } from './internal/server/context.js';
6
6
  export {
7
7
  untrack,
8
8
  track,
9
+ track_read_only as trackReadOnly,
9
10
  track_async as trackAsync,
10
11
  is_tracked_pending as trackPending,
11
12
  peek_tracked as peek,