@remix-run/ui 0.7.0 → 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.
Files changed (91) hide show
  1. package/README.md +90 -14
  2. package/dist/animation/demos/drag-release.js +5 -7
  3. package/dist/animation/demos/drag-release.js.map +1 -1
  4. package/dist/index.d.ts +2 -2
  5. package/dist/index.js +1 -1
  6. package/dist/index.js.map +1 -1
  7. package/dist/runtime/component.d.ts +9 -4
  8. package/dist/runtime/component.js +38 -9
  9. package/dist/runtime/component.js.map +1 -1
  10. package/dist/runtime/core/mix.d.ts +21 -0
  11. package/dist/runtime/core/mix.js +128 -0
  12. package/dist/runtime/core/mix.js.map +1 -0
  13. package/dist/runtime/diff-dom.js +15 -16
  14. package/dist/runtime/diff-dom.js.map +1 -1
  15. package/dist/runtime/document-reload.d.ts +2 -0
  16. package/dist/runtime/document-reload.js +14 -0
  17. package/dist/runtime/document-reload.js.map +1 -0
  18. package/dist/runtime/dom.d.ts +21 -11
  19. package/dist/runtime/event-types.d.ts +14 -0
  20. package/dist/runtime/event-types.js +2 -0
  21. package/dist/runtime/event-types.js.map +1 -0
  22. package/dist/runtime/frame-resolution.js +8 -0
  23. package/dist/runtime/frame-resolution.js.map +1 -1
  24. package/dist/runtime/frame.d.ts +24 -6
  25. package/dist/runtime/frame.js +187 -60
  26. package/dist/runtime/frame.js.map +1 -1
  27. package/dist/runtime/import-map-manager.d.ts +8 -0
  28. package/dist/runtime/import-map-manager.js +295 -0
  29. package/dist/runtime/import-map-manager.js.map +1 -0
  30. package/dist/runtime/mixins/link-mixin.js +4 -4
  31. package/dist/runtime/mixins/link-mixin.js.map +1 -1
  32. package/dist/runtime/mixins/mixin.d.ts +9 -4
  33. package/dist/runtime/mixins/mixin.js +18 -132
  34. package/dist/runtime/mixins/mixin.js.map +1 -1
  35. package/dist/runtime/mixins/on-mixin.d.ts +1 -1
  36. package/dist/runtime/module-preloader.d.ts +2 -1
  37. package/dist/runtime/module-preloader.js +6 -5
  38. package/dist/runtime/module-preloader.js.map +1 -1
  39. package/dist/runtime/navigation.js +211 -34
  40. package/dist/runtime/navigation.js.map +1 -1
  41. package/dist/runtime/reconcile.js +18 -3
  42. package/dist/runtime/reconcile.js.map +1 -1
  43. package/dist/runtime/run.d.ts +3 -0
  44. package/dist/runtime/run.js +8 -4
  45. package/dist/runtime/run.js.map +1 -1
  46. package/dist/runtime/scheduler.js +37 -11
  47. package/dist/runtime/scheduler.js.map +1 -1
  48. package/dist/runtime/spa-response.d.ts +30 -0
  49. package/dist/runtime/spa-response.js +47 -0
  50. package/dist/runtime/spa-response.js.map +1 -0
  51. package/dist/runtime/to-vnode.js +1 -1
  52. package/dist/runtime/to-vnode.js.map +1 -1
  53. package/dist/runtime/typed-event-target.d.ts +0 -4
  54. package/dist/runtime/typed-event-target.js.map +1 -1
  55. package/dist/server/stream.d.ts +25 -2
  56. package/dist/server/stream.js +382 -171
  57. package/dist/server/stream.js.map +1 -1
  58. package/dist/style/stylesheet.js +2 -2
  59. package/dist/style/stylesheet.js.map +1 -1
  60. package/package.json +1 -1
  61. package/src/animation/demos/drag-release.ts +5 -7
  62. package/src/index.ts +2 -2
  63. package/src/runtime/component.ts +52 -14
  64. package/src/runtime/core/mix.ts +157 -0
  65. package/src/runtime/demos/readme.demo.tsx +7 -17
  66. package/src/runtime/diff-dom.ts +13 -15
  67. package/src/runtime/document-reload.ts +14 -0
  68. package/src/runtime/dom.ts +21 -11
  69. package/src/runtime/event-types.ts +27 -0
  70. package/src/runtime/frame-resolution.ts +9 -0
  71. package/src/runtime/frame.ts +216 -65
  72. package/src/runtime/import-map-manager.ts +369 -0
  73. package/src/runtime/mixins/link-mixin.ts +4 -4
  74. package/src/runtime/mixins/mixin.ts +44 -149
  75. package/src/runtime/mixins/on-mixin.ts +1 -1
  76. package/src/runtime/module-preloader.ts +9 -6
  77. package/src/runtime/navigation.ts +257 -42
  78. package/src/runtime/reconcile.ts +20 -4
  79. package/src/runtime/run.ts +13 -4
  80. package/src/runtime/scheduler.ts +53 -13
  81. package/src/runtime/spa-response.ts +56 -0
  82. package/src/runtime/to-vnode.ts +1 -1
  83. package/src/runtime/typed-event-target.ts +1 -6
  84. package/src/server/README.md +25 -5
  85. package/src/server/stream.ts +506 -202
  86. package/src/style/stylesheet.ts +3 -3
  87. package/src/test/utils.ts +1 -6
  88. package/dist/runtime/event-listeners.d.ts +0 -50
  89. package/dist/runtime/event-listeners.js +0 -31
  90. package/dist/runtime/event-listeners.js.map +0 -1
  91. package/src/runtime/event-listeners.ts +0 -171
package/README.md CHANGED
@@ -79,10 +79,9 @@ function Actions() {
79
79
  }
80
80
  ```
81
81
 
82
- ## Frame Navigation
82
+ ## Client Entry Loading
83
83
 
84
- `run()` progressively enhances same-origin links and forms using a default `resolveFrame` that
85
- fetches the frame source:
84
+ `run()` hydrates client entries by calling `loadModule` for each component module:
86
85
 
87
86
  ```tsx
88
87
  import { run } from 'remix/ui'
@@ -97,6 +96,47 @@ let app = run({
97
96
  await app.ready()
98
97
  ```
99
98
 
99
+ Client entries introduced after the initial document may depend on import maps added at runtime.
100
+ When targeting browsers without native support for multiple import maps, use
101
+ `remix/multiple-import-maps-polyfill` to load these modules and process their preloads:
102
+
103
+ ```tsx
104
+ import {
105
+ detectMultipleImportMapSupport,
106
+ importModule,
107
+ preloadShim,
108
+ } from 'remix/multiple-import-maps-polyfill'
109
+
110
+ let app = run({
111
+ async loadModule(moduleUrl, exportName) {
112
+ let module = await importModule(moduleUrl)
113
+ let Component = module[exportName]
114
+ if (typeof Component !== 'function') {
115
+ throw new Error(`Unknown component: ${moduleUrl}#${exportName}`)
116
+ }
117
+ return Component
118
+ },
119
+ async processClientEntryPreloads(preloads) {
120
+ if (await detectMultipleImportMapSupport()) return preloads
121
+
122
+ preloadShim(preloads)
123
+ return []
124
+ },
125
+ })
126
+ ```
127
+
128
+ ## Frame Navigation
129
+
130
+ The same runtime represents the current document as `app.frames.top` and intercepts eligible
131
+ same-origin links and forms through the browser's Navigation API. Those navigations fetch HTML with
132
+ the frame resolver and update the existing document in place instead of loading a new document.
133
+ This soft-navigation behavior applies even when the page only uses `clientEntry()` and does not
134
+ render an explicit `<Frame>`.
135
+
136
+ Frame navigation requires both `window.navigation` and `NavigateEvent.sourceElement`. Browsers
137
+ missing either capability use document navigation for links, forms, and `navigate()`. Hydration and
138
+ explicit frame reloads still work.
139
+
100
140
  The default resolver is equivalent to:
101
141
 
102
142
  ```js
@@ -108,7 +148,8 @@ async function resolveFrame(src, options) {
108
148
  signal: options?.signal,
109
149
  })
110
150
 
111
- if (!response.ok) {
151
+ let isHtml = response.headers.get('Content-Type')?.toLowerCase().includes('text/html')
152
+ if (response.status >= 500 || (response.status >= 300 && !isHtml)) {
112
153
  throw new Error(`Failed to resolve frame: ${response.status} ${response.statusText}`.trimEnd())
113
154
  }
114
155
 
@@ -149,13 +190,20 @@ CRLF-delimited text, and `multipart/form-data` submissions use `FormData`. Pass
149
190
  `resolveFrame` when the server requires additional headers, another body encoding, or a different
150
191
  response policy.
151
192
 
152
- Add `rmx-document` to a link or form to leave its navigation to the browser.
193
+ Add `data-rmx-document` to a link or form to leave that navigation to the browser. To keep all links
194
+ and forms as document navigations while still hydrating client entries and using explicit frames,
195
+ register a listener before calling `run()`:
196
+
197
+ ```ts
198
+ window.navigation?.addEventListener('navigate', (e) => e.stopImmediatePropagation())
199
+ ```
200
+
201
+ This prevents Remix from intercepting Navigation API events. Explicit frame reloads such as
202
+ `handle.frame.reload()` continue to use the frame resolver.
153
203
 
154
- The default resolver rejects non-OK responses with an error containing their status and status text.
155
- A custom `resolveFrame` may return a `Response` with any status when it wants Remix UI to render the
156
- response body.
204
+ The default resolver accepts `2xx` responses and `3xx` or `4xx` responses whose `Content-Type` includes `text/html`, ignoring case. It rejects other `3xx` or `4xx` responses and all `5xx` responses with an error containing their status and status text. A custom `resolveFrame` may return a `Response` with any status when it wants Remix UI to render the response body.
157
205
 
158
- Forms remain ordinary HTML forms before the runtime starts. Add `rmx-target` to reload a named frame, or `rmx-document` to require a full-document submission:
206
+ Forms remain ordinary HTML forms before the runtime starts. Add `data-rmx-target` to reload a named frame, or `data-rmx-document` to require a full-document submission:
159
207
 
160
208
  ```tsx
161
209
  import { Frame } from 'remix/ui'
@@ -164,7 +212,7 @@ function AccountPage() {
164
212
  return () => (
165
213
  <>
166
214
  <Frame name="account" src="/account/edit" />
167
- <form action="/account/edit" method="post" rmx-target="account">
215
+ <form action="/account/edit" method="post" data-rmx-target="account">
168
216
  <label for="display-name">Display name</label>
169
217
  <input id="display-name" name="displayName" required />
170
218
  <button type="submit">Save</button>
@@ -176,19 +224,47 @@ function AccountPage() {
176
224
 
177
225
  Native constraint validation and submitter overrides still apply. GET form values arrive in `src`; non-GET forms provide `formData`, `method`, and `encType` to the resolver. See [Frames](https://github.com/remix-run/remix/blob/main/packages/ui/docs/frames.md#form-navigation) for targeting, history behavior, request encoding, opt-outs, and server response guidance.
178
226
 
179
- Use `rmx-history="push|replace"` on an enhanced anchor or form to control how the navigation updates history. This can override the automatic replacement used for non-GET form submissions to the current URL.
227
+ Use `data-rmx-history="push|replace"` on an enhanced anchor or form to control how the navigation updates history. This can override the automatic replacement used for non-GET form submissions to the current URL.
228
+
229
+ ## Single-page Applications
230
+
231
+ Use `render` and `run` from `remix/spa` when every route runs in the browser and returns a Remix UI
232
+ tree instead of an HTTP response body. The render middleware keeps the router's standard `Request`
233
+ to `Response` contract while associating the response with a node for the top frame to render:
234
+
235
+ ```tsx
236
+ import { createRouter } from 'remix/router'
237
+ import { render, run } from 'remix/spa'
238
+
239
+ let router = createRouter({ middleware: [render()] })
240
+
241
+ router.get('/', ({ render }) => render(<h1>Home</h1>))
242
+ router.get('/about', ({ render }) => render(<h1>About</h1>))
243
+
244
+ function LoadingPage() {
245
+ return () => <p role="status">Loading…</p>
246
+ }
247
+
248
+ let app = run(router, { fallback: <LoadingPage /> })
249
+ await app.ready()
250
+ ```
251
+
252
+ The optional `fallback` is a live Remix node displayed while the initial route loads.
253
+ `app.ready()` resolves after the initial URL has replaced it with the routed node. The runtime then
254
+ reuses frame navigation for same-origin links, forms, history traversal, redirects, cancellation,
255
+ and `rmx-target`.
180
256
 
181
257
  ## Preserving Client-Owned DOM
182
258
 
183
- Use `rmx-preserve-dom` on the smallest element whose live DOM should belong to client code after initial render, such as a custom element or third-party widget:
259
+ Use `data-rmx-preserve-dom` on the smallest element whose live DOM should belong to client code after initial render, such as a custom element or third-party widget:
184
260
 
185
261
  ```tsx
186
- <pagefind-ui data-key="search" rmx-preserve-dom>
262
+ <pagefind-ui data-rmx-key="search" data-rmx-preserve-dom>
187
263
  <button type="button">Search</button>
188
264
  </pagefind-ui>
189
265
  ```
190
266
 
191
- Remix UI still renders the element's children during SSR and still hydrates any initial client entries inside it. On later frame reloads, matched `rmx-preserve-dom` elements keep their current attributes and children instead of accepting incoming DOM updates. See [Preserving client-owned DOM](https://github.com/remix-run/remix/blob/main/packages/ui/docs/frames.md#preserving-client-owned-dom) for guidance and caveats.
267
+ Remix UI still renders the element's children during SSR and still hydrates any initial client entries inside it. On later frame reloads, matched `data-rmx-preserve-dom` elements keep their current attributes and children instead of accepting incoming DOM updates. See [Preserving client-owned DOM](https://github.com/remix-run/remix/blob/main/packages/ui/docs/frames.md#preserving-client-owned-dom) for guidance and caveats.
192
268
 
193
269
  ## Cascade Layers
194
270
 
@@ -1,4 +1,4 @@
1
- import { addEventListeners, createMixin } from '@remix-run/ui';
1
+ import { createMixin } from '@remix-run/ui';
2
2
  export const dragVelocityReleaseEventType = 'rmx:drag-velocity-release';
3
3
  export class DragVelocityEvent extends Event {
4
4
  clientX;
@@ -82,12 +82,10 @@ const baseDragVelocityEvents = createMixin((handle) => {
82
82
  };
83
83
  handle.addEventListener('insert', (event) => {
84
84
  target = event.node;
85
- addEventListeners(target, handle.signal, {
86
- pointerdown: onPointerDown,
87
- pointermove: onPointerMove,
88
- pointerup: onPointerUp,
89
- pointercancel: onPointerCancel,
90
- });
85
+ target.addEventListener('pointerdown', onPointerDown, { signal: handle.signal });
86
+ target.addEventListener('pointermove', onPointerMove, { signal: handle.signal });
87
+ target.addEventListener('pointerup', onPointerUp, { signal: handle.signal });
88
+ target.addEventListener('pointercancel', onPointerCancel, { signal: handle.signal });
91
89
  });
92
90
  });
93
91
  export const dragVelocityEvents = Object.assign(baseDragVelocityEvents, {
@@ -1 +1 @@
1
- {"version":3,"file":"drag-release.js","sourceRoot":"","sources":["../../../src/animation/demos/drag-release.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"drag-release.js","sourceRoot":"","sources":["../../../src/animation/demos/drag-release.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -9,14 +9,14 @@ export type { SerializablePrimitive, SerializableObject, SerializableArray, Seri
9
9
  export { Fragment, Frame } from './runtime/component.ts';
10
10
  export type { Task, Handle, Context, FrameHandleEventMap, FrameContent, FrameHandle, FrameProps, } from './runtime/component.ts';
11
11
  export type { LoadModule, ResolveFrame, ResolveFrameOptions } from './runtime/frame.ts';
12
+ export { spaResponse } from './runtime/spa-response.ts';
12
13
  export { createElement } from './runtime/create-element.ts';
13
14
  export type { ElementType, ElementProps, RemixElement, Renderable, RemixNode, Props, } from './runtime/jsx.ts';
14
15
  export type { HostProps, LayoutAnimationConfig } from './runtime/dom.ts';
15
16
  export { createMixin } from './runtime/mixins/mixin.ts';
16
17
  export type { MixinDescriptor, MixinFactory, MixinHandle, MixinType, MixInput, MixValue, } from './runtime/mixins/mixin.ts';
17
18
  export { TypedEventTarget } from './runtime/typed-event-target.ts';
18
- export { addEventListeners } from './runtime/event-listeners.ts';
19
- export type { Dispatched } from './runtime/event-listeners.ts';
19
+ export type { Dispatched } from './runtime/event-types.ts';
20
20
  export { on } from './runtime/mixins/on-mixin.ts';
21
21
  export { link } from './runtime/mixins/link-mixin.ts';
22
22
  export { ref } from './runtime/mixins/ref-mixin.ts';
package/dist/index.js CHANGED
@@ -6,11 +6,11 @@ export { createRoot, createRangeRoot, createScheduler } from './runtime/vdom.js'
6
6
  export { clientEntry } from './runtime/client-entries.js';
7
7
  // -- Components --
8
8
  export { Fragment, Frame } from './runtime/component.js';
9
+ export { spaResponse } from './runtime/spa-response.js';
9
10
  // -- Elements/JSX/Props --
10
11
  export { createElement } from './runtime/create-element.js';
11
12
  export { createMixin } from './runtime/mixins/mixin.js';
12
13
  export { TypedEventTarget } from './runtime/typed-event-target.js';
13
- export { addEventListeners } from './runtime/event-listeners.js';
14
14
  export { on } from './runtime/mixins/on-mixin.js';
15
15
  export { link } from './runtime/mixins/link-mixin.js';
16
16
  export { ref } from './runtime/mixins/ref-mixin.js';
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,cAAc;AACd,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAItC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAQhF,uBAAuB;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAUzD,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAYxD,2BAA2B;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAU3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AASvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAA;AAEhE,OAAO,EAAE,EAAE,EAAE,MAAM,8BAA8B,CAAA;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAA;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAA;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAG1C,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,wDAAwD;AAExD,cAAc;AACd,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAA;AAItC,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AAQhF,uBAAuB;AACvB,OAAO,EAAE,WAAW,EAAE,MAAM,6BAA6B,CAAA;AAUzD,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,MAAM,wBAAwB,CAAA;AAWxD,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AAEvD,2BAA2B;AAC3B,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAU3D,OAAO,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAA;AASvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAA;AAElE,OAAO,EAAE,EAAE,EAAE,MAAM,8BAA8B,CAAA;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,gCAAgC,CAAA;AACrD,OAAO,EAAE,GAAG,EAAE,MAAM,+BAA+B,CAAA;AAEnD,OAAO,EAAE,KAAK,EAAE,MAAM,iCAAiC,CAAA;AACvD,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAG1C,mBAAmB;AACnB,OAAO,EAAE,QAAQ,EAAE,MAAM,yBAAyB,CAAA"}
@@ -26,10 +26,14 @@ export interface Handle<Props = Record<string, never>, ContextValue = NoContext>
26
26
  context: Context<ContextValue>;
27
27
  /**
28
28
  * Schedules an update for the component to render again. Returns a promise
29
- * that resolves with an AbortSignal after the update completes. The signal
30
- * is aborted when the component re-renders or is removed.
29
+ * that resolves with an AbortSignal after the update completes. Call this
30
+ * from an event handler, queued task, or other work that runs after the
31
+ * component commits. The signal is aborted when the component re-renders or
32
+ * is removed. Calling this during setup warns and skips the extra render;
33
+ * the promise resolves after the initial commit.
31
34
  *
32
35
  * @returns A promise that resolves with an AbortSignal after the update
36
+ * @throws If called during rendering or before the initial commit outside setup
33
37
  */
34
38
  update(): Promise<AbortSignal>;
35
39
  /**
@@ -121,8 +125,9 @@ export type FrameContent = ReadableStream<Uint8Array> | string | RemixNode;
121
125
  * Value returned by a browser frame resolver.
122
126
  *
123
127
  * Response bodies are rendered as frame content regardless of status. The default browser resolver
124
- * rejects non-OK responses before returning them. When `fetch()` followed a redirect, the response's
125
- * final URL updates the frame source and browser URL for a top-frame navigation.
128
+ * accepts 2xx responses and 3xx or 4xx HTML responses. It rejects other 3xx or 4xx responses and all
129
+ * 5xx responses. When `fetch()` followed a redirect, the response's final URL updates the frame source
130
+ * and browser URL for a top-frame navigation.
126
131
  */
127
132
  export type FrameResolution = FrameContent | Response;
128
133
  /**
@@ -18,6 +18,7 @@ class ComponentRuntime {
18
18
  #renderController;
19
19
  #renderFn;
20
20
  #removed = false;
21
+ #phase = 'idle';
21
22
  // The schedule target is stored as fields (updated each render) rather than
22
23
  // a closure so re-renders don't allocate a new function per component.
23
24
  #updateQueue;
@@ -49,7 +50,14 @@ class ComponentRuntime {
49
50
  let renderFn = this.#renderFn;
50
51
  if (renderFn === undefined) {
51
52
  let initialize = this.#config.type;
52
- let result = initialize(this.#handle);
53
+ let result;
54
+ this.#phase = 'setup';
55
+ try {
56
+ result = initialize(this.#handle);
57
+ }
58
+ finally {
59
+ this.#phase = 'idle';
60
+ }
53
61
  if (!isRenderFn(result)) {
54
62
  let name = this.#config.type.name || 'Anonymous';
55
63
  throw new Error(`${name} must return a render function, received ${typeof result}`);
@@ -57,7 +65,15 @@ class ComponentRuntime {
57
65
  renderFn = result;
58
66
  this.#renderFn = renderFn;
59
67
  }
60
- return [renderFn(), this.#dequeueTasks()];
68
+ let element;
69
+ this.#phase = 'render';
70
+ try {
71
+ element = renderFn();
72
+ }
73
+ finally {
74
+ this.#phase = 'idle';
75
+ }
76
+ return [element, this.#dequeueTasks()];
61
77
  };
62
78
  remove = () => {
63
79
  if (this.#removed)
@@ -87,14 +103,27 @@ class ComponentRuntime {
87
103
  return {
88
104
  id: this.#config.id,
89
105
  props: this.#props,
90
- update: () => new Promise((resolve) => {
91
- if (component.#removed) {
92
- resolve(AbortSignal.abort());
93
- return;
106
+ update: () => {
107
+ if (component.#removed)
108
+ return Promise.resolve(AbortSignal.abort());
109
+ let name = component.#config.type.name || 'Anonymous';
110
+ if (component.#phase === 'setup') {
111
+ console.warn(`Ignored handle.update() while ${name} is running its setup function. The initial render includes setup changes.`);
112
+ return new Promise((resolve) => {
113
+ this.#tasks.push((signal) => resolve(signal));
114
+ });
94
115
  }
95
- this.#tasks.push((signal) => resolve(signal));
96
- this.#scheduleUpdate();
97
- }),
116
+ if (component.#phase !== 'idle') {
117
+ throw new Error(`Cannot call handle.update() while ${name} is running its ${component.#phase} function. Call it from an event handler or handle.queueTask() instead.`);
118
+ }
119
+ if (component.#updateQueue === undefined) {
120
+ throw new Error(`Cannot call handle.update() before ${name}'s initial render commits. Call it from an event handler or handle.queueTask() instead.`);
121
+ }
122
+ return new Promise((resolve) => {
123
+ this.#tasks.push((signal) => resolve(signal));
124
+ this.#scheduleUpdate();
125
+ });
126
+ },
98
127
  queueTask: (task) => {
99
128
  this.#tasks.push(task);
100
129
  },
@@ -1 +1 @@
1
- {"version":3,"file":"component.js","sourceRoot":"","sources":["../../src/runtime/component.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"component.js","sourceRoot":"","sources":["../../src/runtime/component.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ElementProps } from '../jsx.ts';
2
+ interface MixDescriptor {
3
+ type: (...args: any[]) => unknown;
4
+ args: readonly unknown[];
5
+ }
6
+ type MixDescriptorRunner = (descriptor: MixDescriptor, index: number, mixinProps: ElementProps) => unknown;
7
+ /**
8
+ * Composes an element's `mix` descriptors into its final props.
9
+ *
10
+ * @param hostType Host element tag name the mixins are composed for.
11
+ * @param props Original element props, including `mix`.
12
+ * @param runDescriptor Runs each mixin using the caller's state and error handling.
13
+ * @returns The composed props.
14
+ */
15
+ export declare function composeMixedProps(hostType: string, props: ElementProps, runDescriptor: MixDescriptorRunner): ElementProps;
16
+ export declare function resolveMixDescriptors(props: ElementProps): MixDescriptor[];
17
+ export declare function isMixinDescriptor(value: unknown): value is MixDescriptor;
18
+ export declare function isMixinElementFunction(value: unknown): value is ((...args: unknown[]) => unknown) & {
19
+ __rmxMixinElementType: string;
20
+ };
21
+ export {};
@@ -0,0 +1,128 @@
1
+ // Stop mixins that return themselves from expanding forever.
2
+ const MAX_MIX_DESCRIPTORS = 1024;
3
+ /**
4
+ * Composes an element's `mix` descriptors into its final props.
5
+ *
6
+ * @param hostType Host element tag name the mixins are composed for.
7
+ * @param props Original element props, including `mix`.
8
+ * @param runDescriptor Runs each mixin using the caller's state and error handling.
9
+ * @returns The composed props.
10
+ */
11
+ export function composeMixedProps(hostType, props, runDescriptor) {
12
+ let descriptors = resolveMixDescriptors(props);
13
+ let composedProps = withoutMix(props);
14
+ let mixinProps = withoutMixinTreeProps(composedProps);
15
+ for (let index = 0; index < descriptors.length && index < MAX_MIX_DESCRIPTORS; index++) {
16
+ let result = runDescriptor(descriptors[index], index, mixinProps);
17
+ if (!result)
18
+ continue;
19
+ if (isMixinElementFunction(result))
20
+ continue;
21
+ let returnedDescriptors = resolveReturnedMixDescriptors(result);
22
+ if (returnedDescriptors) {
23
+ for (let returned of returnedDescriptors)
24
+ descriptors.push(returned);
25
+ continue;
26
+ }
27
+ if (!isRemixElementResult(result)) {
28
+ console.error(new Error('mixins must return a remix element'));
29
+ continue;
30
+ }
31
+ let resultType = typeof result.type === 'string'
32
+ ? result.type
33
+ : isMixinElementFunction(result.type)
34
+ ? result.type.__rmxMixinElementType
35
+ : null;
36
+ if (resultType !== hostType) {
37
+ console.error(new Error('mixins must return an element with the same host type'));
38
+ continue;
39
+ }
40
+ let nextProps = sanitizeReturnedMixinProps(result.props);
41
+ for (let nested of resolveMixDescriptors(nextProps))
42
+ descriptors.push(nested);
43
+ composedProps = { ...composedProps, ...withoutMix(nextProps) };
44
+ mixinProps = withoutMixinTreeProps(composedProps);
45
+ }
46
+ let nextMix = props.mix;
47
+ return {
48
+ ...composedProps,
49
+ ...(nextMix === undefined ? {} : { mix: nextMix }),
50
+ };
51
+ }
52
+ // JSX creation flattens nested mix arrays before composition.
53
+ export function resolveMixDescriptors(props) {
54
+ let mix = props.mix;
55
+ if (!mix)
56
+ return [];
57
+ if (Array.isArray(mix)) {
58
+ if (mix.length === 0)
59
+ return [];
60
+ return mix.filter(Boolean);
61
+ }
62
+ return [mix];
63
+ }
64
+ function withoutMix(props) {
65
+ if (!('mix' in props))
66
+ return props;
67
+ let output = { ...props };
68
+ delete output.mix;
69
+ return output;
70
+ }
71
+ function withoutMixinTreeProps(props) {
72
+ if (!('children' in props) && !('innerHTML' in props))
73
+ return props;
74
+ let output = { ...props };
75
+ delete output.children;
76
+ delete output.innerHTML;
77
+ return output;
78
+ }
79
+ function sanitizeReturnedMixinProps(props) {
80
+ if (!('children' in props) && !('innerHTML' in props))
81
+ return props;
82
+ console.error(new Error('mixins must not return children or innerHTML'));
83
+ return withoutMixinTreeProps(props);
84
+ }
85
+ export function isMixinDescriptor(value) {
86
+ if (!value || typeof value !== 'object' || isRemixElementResult(value)) {
87
+ return false;
88
+ }
89
+ let descriptor = value;
90
+ return typeof descriptor.type === 'function' && Array.isArray(descriptor.args);
91
+ }
92
+ export function isMixinElementFunction(value) {
93
+ if (typeof value !== 'function')
94
+ return false;
95
+ return '__rmxMixinElementType' in value;
96
+ }
97
+ // The composition loop checks the returned element's host type separately.
98
+ function isRemixElementResult(value) {
99
+ if (!value || typeof value !== 'object')
100
+ return false;
101
+ return value.$rmx === true;
102
+ }
103
+ function resolveReturnedMixDescriptors(value) {
104
+ let descriptors = [];
105
+ if (!collectReturnedMixDescriptors(value, descriptors)) {
106
+ return null;
107
+ }
108
+ return descriptors;
109
+ }
110
+ function collectReturnedMixDescriptors(value, output) {
111
+ if (!value) {
112
+ return true;
113
+ }
114
+ if (Array.isArray(value)) {
115
+ for (let item of value) {
116
+ if (!collectReturnedMixDescriptors(item, output)) {
117
+ return false;
118
+ }
119
+ }
120
+ return true;
121
+ }
122
+ if (!isMixinDescriptor(value)) {
123
+ return false;
124
+ }
125
+ output.push(value);
126
+ return true;
127
+ }
128
+ //# sourceMappingURL=mix.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mix.js","sourceRoot":"","sources":["../../../src/runtime/core/mix.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { invariant } from './invariant.js';
2
2
  import { disposeClientEntryBoundary, getClientEntryBoundaryOwner } from './client-entry-boundary.js';
3
- const REMIX_PRESERVE_DOM_ATTRIBUTE = 'rmx-preserve-dom';
3
+ const REMIX_PRESERVE_DOM_ATTRIBUTE = 'data-rmx-preserve-dom';
4
4
  export function diffNodes(curr, next, context) {
5
5
  let parent = curr[0]?.parentNode ?? context.regionParent ?? null;
6
6
  invariant(parent, 'Parent node not found');
@@ -44,10 +44,15 @@ function diffNode(current, next, context) {
44
44
  if (nextMarkerData.status === 'resolved') {
45
45
  let nextEnd = findFrameEndMarker(next);
46
46
  let nextContent = collectFrameContentFragment(current.ownerDocument, next, nextEnd);
47
- void frame.renderMarkerContent({ ...nextMarkerData, id: getFrameId(next) }, nextContent, {
47
+ let render = frame.renderMarkerContent({ ...nextMarkerData, id: getFrameId(next) }, nextContent, {
48
48
  data: context.data,
49
49
  signal: context.signal,
50
+ reconciliationTracker: context.reconciliationTracker,
50
51
  });
52
+ if (context.reconciliationTracker)
53
+ context.reconciliationTracker.waitFor(render);
54
+ else
55
+ void render;
51
56
  return nextEnd;
52
57
  }
53
58
  if (frame.isDisplayingResolvedContent()) {
@@ -179,21 +184,15 @@ function isPopoverOpen(element) {
179
184
  }
180
185
  }
181
186
  function diffElementChildren(current, next, context) {
182
- let currentChildren;
183
- // Allow actively managed preload link tags in the head to stay in the document
184
- // during diffing rather than removing them which aborts the preload in Safari
185
- if (context.isActiveModulePreload && current === current.ownerDocument.head) {
186
- currentChildren = [];
187
- for (let node of current.childNodes) {
188
- if (!context.isActiveModulePreload(node))
189
- currentChildren.push(node);
190
- }
191
- }
192
- else {
193
- currentChildren = Array.from(current.childNodes);
187
+ let shouldPreserveHeadNode = context.shouldPreserveHeadNode;
188
+ let preservedHeadNodes = [];
189
+ let currentChildren = Array.from(current.childNodes);
190
+ if (current === current.ownerDocument.head && shouldPreserveHeadNode) {
191
+ preservedHeadNodes = currentChildren.filter(shouldPreserveHeadNode);
192
+ currentChildren = currentChildren.filter((node) => !shouldPreserveHeadNode(node));
194
193
  }
195
194
  let nextChildren = Array.from(next.childNodes);
196
- diffSiblingUnits(currentChildren, nextChildren, current, null, context);
195
+ diffSiblingUnits(currentChildren, nextChildren, current, preservedHeadNodes[0] ?? null, context);
197
196
  }
198
197
  function diffSiblingUnits(currentNodes, nextNodes, parent, regionTailRef, context) {
199
198
  let currentUnits = parseSiblingUnits(currentNodes);
@@ -346,7 +345,7 @@ function parseSiblingUnits(nodes) {
346
345
  function getSiblingUnitKey(unit) {
347
346
  if (unit.kind !== 'node' || !isElement(unit.node))
348
347
  return;
349
- return unit.node.getAttribute('data-key') ?? undefined;
348
+ return unit.node.getAttribute('data-rmx-key') ?? undefined;
350
349
  }
351
350
  function siblingUnitsComparable(current, next) {
352
351
  if (current.kind !== next.kind)