@qwik.dev/react 2.0.0-beta.28 → 2.0.0-beta.29

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.
@@ -1,9 +1,9 @@
1
1
  var __defProp = Object.defineProperty;
2
2
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
3
3
  var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
4
- import { jsx, jsxs, Fragment } from "@qwik.dev/core/jsx-runtime";
5
- import { useSignal, $, isServer, useOn, useOnDocument, Slot, component$, useStylesScoped$, useStore, useTask$, isBrowser, noSerialize, RenderOnce, SkipRender, implicit$FirstArg } from "@qwik.dev/core";
6
- import { SSRStream, SSRComment, SSRRaw } from "@qwik.dev/core/internal";
4
+ import { useSignal, isServer, useOn, useOnDocument, inlinedQrl, _captures, _jsxSorted, _jsxSplit, _wrapProp, Slot, jsx, componentQrl, useStylesScopedQrl, useStore, useTaskQrl, isBrowser, noSerialize, RenderOnce, SkipRender, implicit$FirstArg } from "@qwik.dev/core";
5
+ import { Fragment } from "@qwik.dev/core/jsx-runtime";
6
+ import { SSRStream, SSRComment, SSRRaw, _getContextContainer, _getContextHostElement, _addProjection, _setProjectionTarget, _removeProjection, _updateProjectionProps } from "@qwik.dev/core/internal";
7
7
  import { renderToString } from "react-dom/server";
8
8
  import { createElement, createContext, Component, createRef } from "react";
9
9
  import { createRoot, hydrateRoot } from "react-dom/client";
@@ -11,23 +11,7 @@ import { flushSync } from "react-dom";
11
11
  const SlotCtx = createContext({
12
12
  scopeId: ""
13
13
  });
14
- function main(slotEl, scopeId, RootCmp, props) {
15
- const newProps = getReactProps(props);
16
- return mainExactProps(slotEl, scopeId, RootCmp, newProps);
17
- }
18
- function mainExactProps(slotEl, scopeId, RootCmp, props) {
19
- return createElement(SlotCtx.Provider, {
20
- value: {
21
- el: slotEl,
22
- scopeId,
23
- attachedEl: void 0
24
- },
25
- children: createElement(RootCmp, {
26
- ...props,
27
- children: createElement(SlotElement, null)
28
- })
29
- });
30
- }
14
+ const QwikProjectionCtx = createContext(null);
31
15
  class SlotElement extends Component {
32
16
  constructor() {
33
17
  super(...arguments);
@@ -61,28 +45,34 @@ class SlotElement extends Component {
61
45
  }
62
46
  }
63
47
  __publicField(SlotElement, "contextType", SlotCtx);
64
- const getReactProps = (props) => {
65
- const obj = {};
66
- Object.keys(props).forEach((key) => {
67
- if (!key.startsWith("client:") && !key.startsWith("qwik:") && !key.startsWith(HOST_PREFIX)) {
68
- const normalizedKey = key.endsWith("$") ? key.slice(0, -1) : key;
69
- obj[normalizedKey] = props[key];
70
- }
71
- });
72
- return obj;
73
- };
74
- const getHostProps = (props) => {
75
- const obj = {};
76
- Object.keys(props).forEach((key) => {
77
- if (key.startsWith(HOST_PREFIX)) {
78
- obj[key.slice(HOST_PREFIX.length)] = props[key];
79
- }
48
+ function mainExactProps(slotEl, scopeId, RootCmp, props, projectionState) {
49
+ let tree = createElement(SlotCtx.Provider, {
50
+ value: {
51
+ el: slotEl,
52
+ scopeId,
53
+ attachedEl: void 0
54
+ },
55
+ children: createElement(RootCmp, {
56
+ ...props,
57
+ children: createElement(SlotElement, null)
58
+ })
80
59
  });
81
- return obj;
82
- };
60
+ if (projectionState) {
61
+ tree = createElement(QwikProjectionCtx.Provider, {
62
+ value: projectionState,
63
+ children: tree
64
+ });
65
+ }
66
+ return tree;
67
+ }
83
68
  const useWakeupSignal = (props, opts = {}) => {
84
69
  const signal = useSignal(false);
85
- const activate = $(() => signal.value = true);
70
+ const activate = /* @__PURE__ */ inlinedQrl(() => {
71
+ const signal2 = _captures[0];
72
+ return signal2.value = true;
73
+ }, "useWakeupSignal_activate_bbwdFkXhIMU", [
74
+ signal
75
+ ]);
86
76
  const clientOnly = !!(props["client:only"] || props["qwik:only"] || opts?.clientOnly);
87
77
  const clientVisible = props["client:visible"] || props["qwik:visible"] || opts?.eagerness === "visible";
88
78
  const clientIdle = props["client:idle"] || props["qwik:idle"] || opts?.eagerness === "idle";
@@ -116,157 +106,353 @@ const useWakeupSignal = (props, opts = {}) => {
116
106
  ];
117
107
  };
118
108
  const HOST_PREFIX = "host:";
109
+ const getReactProps = (props) => {
110
+ const obj = {};
111
+ Object.keys(props).forEach((key) => {
112
+ if (!key.startsWith("client:") && !key.startsWith("qwik:") && !key.startsWith(HOST_PREFIX)) {
113
+ const normalizedKey = key.endsWith("$") ? key.slice(0, -1) : key;
114
+ obj[normalizedKey] = props[key];
115
+ }
116
+ });
117
+ return obj;
118
+ };
119
+ function main(slotEl, scopeId, RootCmp, props, projectionState) {
120
+ const newProps = getReactProps(props);
121
+ return mainExactProps(slotEl, scopeId, RootCmp, newProps, projectionState);
122
+ }
123
+ const getHostProps = (props) => {
124
+ const obj = {};
125
+ Object.keys(props).forEach((key) => {
126
+ if (key.startsWith(HOST_PREFIX)) {
127
+ obj[key.slice(HOST_PREFIX.length)] = props[key];
128
+ }
129
+ });
130
+ return obj;
131
+ };
132
+ let _ssrProjectionRegistry = null;
133
+ function setSSRProjectionRegistry(registry) {
134
+ _ssrProjectionRegistry = registry;
135
+ }
136
+ function getSSRProjectionRegistry() {
137
+ return _ssrProjectionRegistry;
138
+ }
139
+ const SLOT_MARKER = "<!--SLOT-->";
140
+ function splitHtmlAtMarkers(html) {
141
+ const MARKER_RE = /<!--(?:SLOT|QWIK-PROJ:(.*?))-->/g;
142
+ const segments = [];
143
+ let lastIndex = 0;
144
+ let match;
145
+ while ((match = MARKER_RE.exec(html)) !== null) {
146
+ if (match.index > lastIndex) {
147
+ segments.push({
148
+ type: "html",
149
+ content: html.slice(lastIndex, match.index)
150
+ });
151
+ }
152
+ if (match[1] !== void 0) {
153
+ segments.push({
154
+ type: "proj",
155
+ slotName: match[1]
156
+ });
157
+ } else {
158
+ segments.push({
159
+ type: "slot"
160
+ });
161
+ }
162
+ lastIndex = match.index + match[0].length;
163
+ }
164
+ if (lastIndex < html.length) {
165
+ segments.push({
166
+ type: "html",
167
+ content: html.slice(lastIndex)
168
+ });
169
+ }
170
+ return segments;
171
+ }
119
172
  async function renderFromServer(Host, reactCmp$, scopeId, props, ref, slotRef, hydrationProps) {
120
173
  if (isServer) {
121
174
  const Cmp = await reactCmp$.resolve();
122
175
  const newProps = getReactProps(props);
123
176
  Object.assign(hydrationProps, newProps);
177
+ const registry = {
178
+ entries: /* @__PURE__ */ new Map()
179
+ };
180
+ setSSRProjectionRegistry(registry);
124
181
  const html = renderToString(mainExactProps(void 0, scopeId, Cmp, newProps));
125
- const index = html.indexOf("<!--SLOT-->");
126
- if (index > 0) {
127
- const part1 = html.slice(0, index);
128
- const part2 = html.slice(index + "<!--SLOT-->".length);
129
- return /* @__PURE__ */ jsx(Host, {
130
- ref,
131
- ...getHostProps(props),
132
- children: /* @__PURE__ */ jsx(SSRStream, {
133
- children: async function* () {
134
- yield /* @__PURE__ */ jsx(SSRComment, {
135
- data: "q:ignore"
136
- });
137
- yield /* @__PURE__ */ jsx(SSRRaw, {
138
- data: part1
139
- });
140
- yield /* @__PURE__ */ jsx(SSRComment, {
141
- data: "q:container-island"
142
- });
143
- yield /* @__PURE__ */ jsx("q-slot", {
144
- ref: slotRef,
145
- children: /* @__PURE__ */ jsx(Slot, {})
146
- });
147
- yield /* @__PURE__ */ jsx(SSRComment, {
148
- data: "/q:container-island"
149
- });
150
- yield /* @__PURE__ */ jsx(SSRRaw, {
151
- data: part2
152
- });
153
- yield /* @__PURE__ */ jsx(SSRComment, {
154
- data: "/q:ignore"
155
- });
182
+ setSSRProjectionRegistry(null);
183
+ const hasSlot = html.includes(SLOT_MARKER);
184
+ const hasProj = registry.entries.size > 0;
185
+ if (hasSlot || hasProj) {
186
+ const segments = splitHtmlAtMarkers(html);
187
+ return /* @__PURE__ */ _jsxSorted(Fragment, null, null, [
188
+ /* @__PURE__ */ _jsxSplit(Host, {
189
+ ref,
190
+ ...getHostProps(props)
191
+ }, null, /* @__PURE__ */ _jsxSorted(SSRStream, null, null, async function* () {
192
+ yield /* @__PURE__ */ _jsxSorted(SSRComment, null, {
193
+ data: "q:ignore"
194
+ }, null, 3, "cl_0");
195
+ for (const segment of segments) {
196
+ if (segment.type === "html") {
197
+ yield /* @__PURE__ */ _jsxSorted(SSRRaw, {
198
+ data: _wrapProp(segment, "content")
199
+ }, null, null, 3, "cl_1");
200
+ } else if (segment.type === "slot") {
201
+ yield /* @__PURE__ */ _jsxSorted(SSRComment, null, {
202
+ data: "q:container-island"
203
+ }, null, 3, "cl_2");
204
+ yield /* @__PURE__ */ _jsxSorted("q-slot", {
205
+ ref: slotRef
206
+ }, null, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "cl_3"), 1, "cl_4");
207
+ yield /* @__PURE__ */ _jsxSorted(SSRComment, null, {
208
+ data: "/q:container-island"
209
+ }, null, 3, "cl_5");
210
+ } else if (segment.type === "proj") {
211
+ const entry = registry.entries.get(segment.slotName);
212
+ if (entry) {
213
+ yield /* @__PURE__ */ _jsxSorted(SSRComment, null, {
214
+ data: "q:container-island"
215
+ }, null, 3, "cl_6");
216
+ const QwikComp = await entry.qrl.resolve();
217
+ yield jsx(QwikComp, entry.props);
218
+ yield /* @__PURE__ */ _jsxSorted(SSRComment, null, {
219
+ data: "/q:container-island"
220
+ }, null, 3, "cl_7");
221
+ }
222
+ }
156
223
  }
157
- })
158
- });
224
+ yield /* @__PURE__ */ _jsxSorted(SSRComment, null, {
225
+ data: "/q:ignore"
226
+ }, null, 3, "cl_8");
227
+ }, 1, "cl_9"), 0, "cl_10"),
228
+ !hasSlot && /* @__PURE__ */ _jsxSorted("q-slot", {
229
+ ref: slotRef
230
+ }, null, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "cl_11"), 1, "cl_12")
231
+ ], 1, "cl_13");
159
232
  }
160
- return /* @__PURE__ */ jsxs(Fragment, {
161
- children: [
162
- /* @__PURE__ */ jsxs(Host, {
163
- ref,
164
- children: [
165
- /* @__PURE__ */ jsx(SSRComment, {
166
- data: "q:container=html"
167
- }),
168
- /* @__PURE__ */ jsx(SSRRaw, {
169
- data: html
170
- }),
171
- /* @__PURE__ */ jsx(SSRComment, {
172
- data: "/q:container"
173
- })
174
- ]
175
- }),
176
- /* @__PURE__ */ jsx("q-slot", {
177
- ref: slotRef,
178
- children: /* @__PURE__ */ jsx(Slot, {})
179
- })
180
- ]
181
- });
233
+ return /* @__PURE__ */ _jsxSorted(Fragment, null, null, [
234
+ /* @__PURE__ */ _jsxSorted(Host, {
235
+ ref
236
+ }, null, [
237
+ /* @__PURE__ */ _jsxSorted(SSRComment, null, {
238
+ data: "q:container=html"
239
+ }, null, 3, "cl_14"),
240
+ /* @__PURE__ */ _jsxSorted(SSRRaw, {
241
+ data: html
242
+ }, null, null, 3, "cl_15"),
243
+ /* @__PURE__ */ _jsxSorted(SSRComment, null, {
244
+ data: "/q:container"
245
+ }, null, 3, "cl_16")
246
+ ], 1, "cl_17"),
247
+ /* @__PURE__ */ _jsxSorted("q-slot", {
248
+ ref: slotRef
249
+ }, null, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "cl_18"), 1, null)
250
+ ], 1, "cl_19");
182
251
  }
183
252
  }
184
253
  function qwikifyQrl(reactCmp$, opts) {
185
- return component$((props) => {
186
- const { scopeId } = useStylesScoped$(`q-slot{display:none} q-slotc,q-slotc>q-slot{display:contents}`);
254
+ return /* @__PURE__ */ componentQrl(/* @__PURE__ */ inlinedQrl((props) => {
255
+ const opts2 = _captures[0], reactCmp$2 = _captures[1];
256
+ const { scopeId } = useStylesScopedQrl(/* @__PURE__ */ inlinedQrl(`q-slot{display:none} q-slotc,q-slotc>q-slot{display:contents}`, "qwikifyQrl_component_useStylesScoped_ppvg9vpFqsY"));
187
257
  const hostRef = useSignal();
188
258
  const slotRef = useSignal();
189
259
  const internalState = useSignal();
190
- const [signal, isClientOnly] = useWakeupSignal(props, opts);
260
+ const [signal, isClientOnly] = useWakeupSignal(props, opts2);
191
261
  const hydrationKeys = useStore({});
192
- const TagName = opts?.tagName ?? "qwik-react";
193
- useTask$(async ({ track }) => {
262
+ const TagName = opts2?.tagName ?? "qwik-react";
263
+ useTaskQrl(/* @__PURE__ */ inlinedQrl(async ({ track }) => {
264
+ const hostRef2 = _captures[0], hydrationKeys2 = _captures[1], internalState2 = _captures[2], isClientOnly2 = _captures[3], props2 = _captures[4], reactCmp$3 = _captures[5], scopeId2 = _captures[6], signal2 = _captures[7], slotRef2 = _captures[8];
194
265
  const trackedProps = track(() => ({
195
- ...props
266
+ ...props2
196
267
  }));
197
- track(signal);
268
+ track(signal2);
198
269
  if (!isBrowser) {
199
270
  return;
200
271
  }
201
- if (internalState.value) {
202
- if (internalState.value.root) {
203
- internalState.value.root.render(main(slotRef.value, scopeId, internalState.value.cmp, trackedProps));
272
+ let projectionState = null;
273
+ const container = _getContextContainer();
274
+ const hostVNode = _getContextHostElement();
275
+ if (container && hostVNode) {
276
+ projectionState = {
277
+ parentVNode: hostVNode,
278
+ container
279
+ };
280
+ }
281
+ if (internalState2.value) {
282
+ if (internalState2.value.root) {
283
+ internalState2.value.root.render(main(slotRef2.value, scopeId2, internalState2.value.cmp, trackedProps, internalState2.value.projectionState));
204
284
  }
205
285
  } else {
206
286
  let root = void 0;
207
- const Cmp = await reactCmp$.resolve();
208
- const hostElement = hostRef.value;
287
+ const Cmp = await reactCmp$3.resolve();
288
+ const hostElement = hostRef2.value;
209
289
  if (hostElement) {
210
- if (isClientOnly) {
290
+ if (isClientOnly2) {
211
291
  root = createRoot(hostElement);
212
292
  } else {
213
293
  root = flushSync(() => {
214
- return hydrateRoot(hostElement, mainExactProps(slotRef.value, scopeId, Cmp, hydrationKeys));
294
+ return hydrateRoot(hostElement, mainExactProps(slotRef2.value, scopeId2, Cmp, hydrationKeys2, projectionState));
215
295
  });
216
296
  }
217
- if (isClientOnly || signal.value === false) {
218
- root.render(main(slotRef.value, scopeId, Cmp, trackedProps));
297
+ if (isClientOnly2 || signal2.value === false) {
298
+ root.render(main(slotRef2.value, scopeId2, Cmp, trackedProps, projectionState));
219
299
  }
220
300
  }
221
- internalState.value = noSerialize({
301
+ internalState2.value = noSerialize({
222
302
  cmp: Cmp,
223
- root
303
+ root,
304
+ projectionState
224
305
  });
225
306
  }
226
- });
227
- useTask$(({ track, cleanup }) => {
228
- track(signal);
307
+ }, "qwikifyQrl_component_useTask_JuFeaMCL0P0", [
308
+ hostRef,
309
+ hydrationKeys,
310
+ internalState,
311
+ isClientOnly,
312
+ props,
313
+ reactCmp$2,
314
+ scopeId,
315
+ signal,
316
+ slotRef
317
+ ]));
318
+ useTaskQrl(/* @__PURE__ */ inlinedQrl(({ track, cleanup }) => {
319
+ const internalState2 = _captures[0], signal2 = _captures[1];
320
+ track(signal2);
229
321
  if (isBrowser) {
230
322
  cleanup(() => {
231
- internalState.value?.root?.unmount();
323
+ const root = internalState2.value?.root;
324
+ if (root) {
325
+ queueMicrotask(() => root.unmount());
326
+ }
232
327
  });
233
328
  }
234
- });
329
+ }, "qwikifyQrl_component_useTask_1_mwaGrLCLc2w", [
330
+ internalState,
331
+ signal
332
+ ]));
235
333
  if (isServer && !isClientOnly) {
236
- const jsx$1 = renderFromServer(TagName, reactCmp$, scopeId, props, hostRef, slotRef, hydrationKeys);
237
- return /* @__PURE__ */ jsx(RenderOnce, {
238
- children: jsx$1
239
- }, 2);
334
+ const jsx2 = renderFromServer(TagName, reactCmp$2, scopeId, props, hostRef, slotRef, hydrationKeys);
335
+ return /* @__PURE__ */ _jsxSorted(RenderOnce, null, null, jsx2, 1, 2);
240
336
  }
241
- return /* @__PURE__ */ jsxs(Fragment, {
242
- children: [
243
- /* @__PURE__ */ jsx(TagName, {
244
- ...getHostProps(props),
245
- ref: (el) => {
246
- if (isBrowser) {
247
- queueMicrotask(() => {
248
- const internalData = internalState.value;
249
- if (internalData && !internalData.root) {
250
- const root = internalData.root = createRoot(el);
251
- root.render(main(slotRef.value, scopeId, internalData.cmp, props));
252
- }
253
- });
254
- } else {
255
- hostRef.value = el;
256
- }
257
- },
258
- children: SkipRender
259
- }),
260
- /* @__PURE__ */ jsx("q-slot", {
261
- ref: slotRef,
262
- children: /* @__PURE__ */ jsx(Slot, {})
263
- })
264
- ]
265
- });
266
- });
337
+ return /* @__PURE__ */ _jsxSorted(Fragment, null, null, [
338
+ /* @__PURE__ */ _jsxSplit(TagName, {
339
+ ...getHostProps(props)
340
+ }, {
341
+ ref: (el) => {
342
+ if (isBrowser) {
343
+ queueMicrotask(() => {
344
+ const internalData = internalState.value;
345
+ if (internalData && !internalData.root) {
346
+ const root = internalData.root = createRoot(el);
347
+ root.render(main(slotRef.value, scopeId, internalData.cmp, props, internalData.projectionState));
348
+ }
349
+ });
350
+ } else {
351
+ hostRef.value = el;
352
+ }
353
+ }
354
+ }, SkipRender, 0, "sV_0"),
355
+ /* @__PURE__ */ _jsxSorted("q-slot", {
356
+ ref: slotRef
357
+ }, null, /* @__PURE__ */ _jsxSorted(Slot, null, null, null, 3, "sV_1"), 1, null)
358
+ ], 1, "sV_2");
359
+ }, "qwikifyQrl_component_5bB3apdeFTY", [
360
+ opts,
361
+ reactCmp$
362
+ ]));
267
363
  }
268
364
  const qwikify$ = /* @__PURE__ */ implicit$FirstArg(qwikifyQrl);
365
+ let slotCounter = 0;
366
+ function reactifyQrl(qwikCompQrl) {
367
+ const _QwikInReact = class _QwikInReact extends Component {
368
+ constructor() {
369
+ super(...arguments);
370
+ __publicField(this, "slotName", `_rq:${slotCounter++}`);
371
+ __publicField(this, "vnode", null);
372
+ __publicField(this, "divRef", createRef());
373
+ __publicField(this, "mounted", false);
374
+ __publicField(this, "pendingProps", null);
375
+ }
376
+ componentDidMount() {
377
+ this.mounted = true;
378
+ const projectionState = this.context;
379
+ if (!projectionState) {
380
+ if (typeof console !== "undefined") {
381
+ console.warn("reactify$: component must be rendered inside a qwikify$() React tree.");
382
+ }
383
+ return;
384
+ }
385
+ const div = this.divRef.current;
386
+ if (!div) {
387
+ return;
388
+ }
389
+ if (div.firstElementChild) {
390
+ return;
391
+ }
392
+ qwikCompQrl.resolve().then((QwikComp) => {
393
+ if (!this.mounted) {
394
+ return;
395
+ }
396
+ const name = QwikComp.displayName || QwikComp.name || "QwikComponent";
397
+ _QwikInReact.displayName = `reactify$(${name})`;
398
+ const { parentVNode, container } = projectionState;
399
+ const reactProps = getReactProps(this.pendingProps || this.props);
400
+ this.vnode = _addProjection(container, parentVNode, qwikCompQrl, reactProps, this.slotName);
401
+ div.replaceChildren();
402
+ _setProjectionTarget(this.vnode, div);
403
+ });
404
+ }
405
+ componentWillUnmount() {
406
+ this.mounted = false;
407
+ if (this.vnode && this.context) {
408
+ _removeProjection(this.context.container, this.context.parentVNode, this.vnode, this.slotName);
409
+ this.vnode = null;
410
+ }
411
+ }
412
+ shouldComponentUpdate(nextProps) {
413
+ if (this.vnode && this.context) {
414
+ const reactProps = getReactProps(nextProps);
415
+ _updateProjectionProps(this.context.container, this.vnode, reactProps);
416
+ } else {
417
+ this.pendingProps = nextProps;
418
+ }
419
+ return false;
420
+ }
421
+ render() {
422
+ const registry = getSSRProjectionRegistry();
423
+ if (registry) {
424
+ const reactProps = getReactProps(this.props);
425
+ registry.entries.set(this.slotName, {
426
+ qrl: qwikCompQrl,
427
+ props: reactProps
428
+ });
429
+ return createElement("div", {
430
+ "data-qwik-projection": this.slotName,
431
+ suppressHydrationWarning: true,
432
+ dangerouslySetInnerHTML: {
433
+ __html: `<!--QWIK-PROJ:${this.slotName}-->`
434
+ }
435
+ });
436
+ }
437
+ return createElement("div", {
438
+ ref: this.divRef,
439
+ suppressHydrationWarning: true,
440
+ dangerouslySetInnerHTML: {
441
+ __html: `<!--QWIK-PROJ:${this.slotName}-->`
442
+ },
443
+ "data-qwik-projection": this.slotName
444
+ });
445
+ }
446
+ };
447
+ __publicField(_QwikInReact, "contextType", QwikProjectionCtx);
448
+ let QwikInReact = _QwikInReact;
449
+ QwikInReact.displayName = `reactify$(...)`;
450
+ return QwikInReact;
451
+ }
452
+ const reactify$ = /* @__PURE__ */ implicit$FirstArg(reactifyQrl);
269
453
  export {
270
454
  qwikify$,
271
- qwikifyQrl
455
+ qwikifyQrl,
456
+ reactify$,
457
+ reactifyQrl
272
458
  };
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "version": "1",
3
- "manifestHash": "r0ysh8",
3
+ "manifestHash": "v6wp5f",
4
4
  "options": {
5
5
  "target": "lib",
6
6
  "buildMode": "development",
@@ -13,11 +13,12 @@
13
13
  "mapping": {},
14
14
  "bundles": {
15
15
  "../index.qwik.mjs": {
16
- "size": 8785,
17
- "total": 8785,
16
+ "size": 16132,
17
+ "total": 16132,
18
18
  "origins": [
19
19
  "src/index.qwik.ts",
20
20
  "src/react/qwikify.tsx",
21
+ "src/react/reactify.ts",
21
22
  "src/react/server-render.tsx",
22
23
  "src/react/slot.ts"
23
24
  ],
@@ -1,2 +1,3 @@
1
1
  export { qwikify$, qwikifyQrl } from './react/qwikify';
2
+ export { reactify$, reactifyQrl } from './react/reactify';
2
3
  export type { QwikifyProps } from './react/types';
@@ -0,0 +1,55 @@
1
+ import { type QRL } from '@qwik.dev/core';
2
+ /**
3
+ * Creates a React component that renders a Qwik component inside a qwikify$ React tree.
4
+ *
5
+ * This is the QRL form. Use `reactify$` for the convenience form with automatic `$()` wrapping.
6
+ *
7
+ * The returned React component must be rendered inside a `qwikify$()` React tree. It creates a div
8
+ * that Qwik renders into, while React ignores its contents.
9
+ *
10
+ * During SSR, a marker is emitted so that server-render.tsx can render the Qwik component inline
11
+ * inside `q:container-island` comments. On the client, Qwik resumes the SSR content naturally
12
+ * (events, signals, state are all serialized). For pure CSR, `_addProjection` renders from
13
+ * scratch.
14
+ *
15
+ * @param qwikCompQrl - A QRL wrapping a Qwik component (created with `component$`)
16
+ * @returns A React component that renders the Qwik component
17
+ */
18
+ export declare function reactifyQrl(qwikCompQrl: QRL<any>): any;
19
+ /**
20
+ * Creates a React component that renders a Qwik component inside a qwikify$ React tree.
21
+ *
22
+ * The returned React component must be rendered inside a `qwikify$()` React tree. It creates a div
23
+ * that Qwik renders into, while React ignores its contents.
24
+ *
25
+ * During SSR, the Qwik component is rendered as HTML inside `q:container-island` comments. On the
26
+ * client, the component re-renders via the external projection API.
27
+ *
28
+ * @example
29
+ *
30
+ * ```tsx
31
+ * import { component$ } from '@qwik.dev/core';
32
+ * import { qwikify$, reactify$ } from '@qwik.dev/react';
33
+ *
34
+ * const QwikCounter = component$(() => {
35
+ * const count = useSignal(0);
36
+ * return <button onClick$={() => count.value++}>{count.value}</button>;
37
+ * });
38
+ *
39
+ * const ReactCounter = reactify$(QwikCounter);
40
+ *
41
+ * const ReactApp = ({ children }) => (
42
+ * <div>
43
+ * <h1>React App</h1>
44
+ * <ReactCounter />
45
+ * {children}
46
+ * </div>
47
+ * );
48
+ *
49
+ * export const QwikifiedApp = qwikify$(ReactApp);
50
+ * ```
51
+ *
52
+ * @param qwikComp - A Qwik component (created with `component$`)
53
+ * @returns A React component that renders the Qwik component
54
+ */
55
+ export declare const reactify$: (qrl: any) => any;
@@ -1,4 +1,5 @@
1
- import { Component } from 'react';
1
+ import { type QRL } from '@qwik.dev/core';
2
+ import { Component, type ReactElement } from 'react';
2
3
  import type { QwikifyOptions, QwikifyProps } from './types';
3
4
  interface SlotState {
4
5
  el?: Element;
@@ -6,8 +7,13 @@ interface SlotState {
6
7
  attachedEl?: Element;
7
8
  }
8
9
  declare const SlotCtx: import("react").Context<SlotState>;
9
- export declare function main(slotEl: Element | undefined, scopeId: string, RootCmp: any, props: any): import("react").FunctionComponentElement<import("react").ProviderProps<SlotState>>;
10
- export declare function mainExactProps(slotEl: Element | undefined, scopeId: string, RootCmp: any, props: any): import("react").FunctionComponentElement<import("react").ProviderProps<SlotState>>;
10
+ export interface QwikProjectionState {
11
+ parentVNode: any;
12
+ container: any;
13
+ }
14
+ export declare const QwikProjectionCtx: import("react").Context<QwikProjectionState | null>;
15
+ export declare function main(slotEl: Element | undefined, scopeId: string, RootCmp: any, props: any, projectionState?: QwikProjectionState | null): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
16
+ export declare function mainExactProps(slotEl: Element | undefined, scopeId: string, RootCmp: any, props: any, projectionState?: QwikProjectionState | null): ReactElement<unknown, string | import("react").JSXElementConstructor<any>>;
11
17
  export declare class SlotElement extends Component {
12
18
  static contextType: import("react").Context<SlotState>;
13
19
  context: React.ContextType<typeof SlotCtx>;
@@ -25,5 +31,14 @@ export declare class SlotElement extends Component {
25
31
  }
26
32
  export declare const getReactProps: (props: Record<string, any>) => Record<string, any>;
27
33
  export declare const getHostProps: (props: Record<string, any>) => Record<string, any>;
28
- export declare const useWakeupSignal: (props: QwikifyProps<{}>, opts?: QwikifyOptions) => readonly [import("@qwik.dev/core").Signal<boolean>, boolean, import("@qwik.dev/core").QRL<() => true>];
34
+ export declare const useWakeupSignal: (props: QwikifyProps<{}>, opts?: QwikifyOptions) => readonly [import("@qwik.dev/core").Signal<boolean>, boolean, QRL<() => true>];
35
+ export interface SSRProjectionEntry {
36
+ qrl: QRL<any>;
37
+ props: Record<string, any>;
38
+ }
39
+ export interface SSRProjectionRegistry {
40
+ entries: Map<string, SSRProjectionEntry>;
41
+ }
42
+ export declare function setSSRProjectionRegistry(registry: SSRProjectionRegistry | null): void;
43
+ export declare function getSSRProjectionRegistry(): SSRProjectionRegistry | null;
29
44
  export {};
@@ -1,9 +1,11 @@
1
1
  import type { QRL, Signal } from '@qwik.dev/core';
2
2
  import type { FunctionComponent as ReactFC } from 'react';
3
3
  import type { Root } from 'react-dom/client';
4
+ import type { QwikProjectionState } from './slot';
4
5
  export interface Internal<PROPS> {
5
6
  root: Root | undefined;
6
7
  cmp: ReactFC<PROPS>;
8
+ projectionState: QwikProjectionState | null;
7
9
  }
8
10
  export interface QwikifyBase {
9
11
  /**
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@qwik.dev/react",
3
3
  "description": "Qwik React allows adding React components into existing Qwik application",
4
- "version": "2.0.0-beta.28",
4
+ "version": "2.0.0-beta.29",
5
5
  "bugs": "https://github.com/QwikDev/qwik/issues",
6
6
  "devDependencies": {
7
7
  "@types/react": "19.2.7",
@@ -10,7 +10,7 @@
10
10
  "react-dom": "19.2.3",
11
11
  "typescript": "5.9.3",
12
12
  "vite": "7.3.1",
13
- "@qwik.dev/core": "2.0.0-beta.28"
13
+ "@qwik.dev/core": "2.0.0-beta.29"
14
14
  },
15
15
  "engines": {
16
16
  "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
@@ -38,7 +38,7 @@
38
38
  "react": "^18",
39
39
  "react-dom": "^18",
40
40
  "vite": ">=6 <9",
41
- "@qwik.dev/core": "^2.0.0-beta.28"
41
+ "@qwik.dev/core": "^2.0.0-beta.29"
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public"