Skip to content

Commit 5ceb8ff

Browse files
committed
feat(): createRoot supports useChildren
1 parent 604aacd commit 5ceb8ff

File tree

8 files changed

+198
-122
lines changed

8 files changed

+198
-122
lines changed

etc/runtime.api.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ export interface CreateRootOptions {
118118
// (undocumented)
119119
portal?: HTMLElement;
120120
scope?: "page" | "fragment";
121+
supportsUseChildren?: boolean;
121122
unknownBricks?: "silent" | "throw";
122123
unsafe_penetrate?: boolean;
123124
}
@@ -586,7 +587,7 @@ const symbolForRootRuntimeContext: unique symbol;
586587
function unmountUseBrick({ rendererContext }: RenderUseBrickResult, mountResult: MountUseBrickResult): void;
587588

588589
// @public (undocumented)
589-
export function unstable_createRoot(container: HTMLElement | DocumentFragment, { portal: _portal, scope, unknownBricks, unsafe_penetrate, }?: CreateRootOptions): {
590+
export function unstable_createRoot(container: HTMLElement | DocumentFragment, { portal: _portal, scope, unknownBricks, supportsUseChildren, unsafe_penetrate, }?: CreateRootOptions): {
590591
render(brick: BrickConf | BrickConf[], { theme, uiVersion, language, context, functions, templates, i18n: i18nData, url, app, }?: RenderOptions): Promise<void>;
591592
unmount(): void;
592593
};

packages/preview/package.json

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,15 @@
2222
},
2323
"scripts": {
2424
"start": "cross-env NODE_ENV='development' build-next-bricks --watch",
25-
"build": "cross-env NODE_ENV='production' build-next-bricks",
26-
"test": "cross-env NODE_ENV='test' test-next",
27-
"test:ci": "cross-env NODE_ENV='test' CI=true test-next"
25+
"build": "cross-env NODE_ENV='production' build-next-bricks"
2826
},
2927
"devDependencies": {
3028
"@next-core/build-next-bricks": "^1.23.13",
3129
"@next-core/http": "^1.2.13",
3230
"@next-core/loader": "^1.6.16",
3331
"@next-core/runtime": "^1.62.3",
34-
"@next-core/test-next": "^2.0.0",
3532
"@next-core/theme": "^1.5.4",
3633
"@next-core/types": "^1.15.0",
37-
"@next-core/utils": "^1.7.36",
3834
"html-webpack-plugin": "^5.6.3",
3935
"js-yaml": "^3.14.1"
4036
}

packages/preview/src/bootstrap.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ import type {
2626
PreviewWindow,
2727
} from "../types.d.ts";
2828
import { get } from "lodash";
29-
import { replaceUseChildren } from "./replaceUseChildren.js";
3029
// Chrome supports `Element.prototype.replaceChildren` since version 86
3130
import "../../brick-container/src/replaceChildren.js";
3231

@@ -92,6 +91,7 @@ const root = unstable_createRoot(container, {
9291
portal,
9392
scope: "page",
9493
unknownBricks: "silent",
94+
supportsUseChildren: true,
9595
});
9696

9797
const bootstrap = http
@@ -225,7 +225,6 @@ async function render(
225225
| BrickConf[])
226226
: null;
227227
const bricks = [].concat(parsed ?? []);
228-
replaceUseChildren(bricks);
229228
if (styleText) {
230229
bricks.push({
231230
brick: "style",
@@ -244,14 +243,6 @@ async function render(
244243
) as CustomTemplate[];
245244
const parsedI18n = loadYaml(i18nData) as MetaI18n;
246245

247-
if (Array.isArray(parsedTemplates)) {
248-
for (const template of parsedTemplates) {
249-
if (Array.isArray(template.bricks)) {
250-
replaceUseChildren(template.bricks);
251-
}
252-
}
253-
}
254-
255246
await bootstrap;
256247
await root.render(bricks, {
257248
theme: theme === "light" ? theme : "dark-v2",

packages/runtime/src/createRoot.spec.ts

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ const consoleError = jest.spyOn(console, "error");
77
jest.mock("./themeAndMode.js");
88
window.scrollTo = jest.fn();
99

10+
class MyBrick extends HTMLElement {
11+
useBrick: unknown;
12+
}
13+
customElements.define("my-brick", MyBrick);
14+
1015
describe("preview", () => {
1116
const container = document.createElement("div");
1217
const portal = document.createElement("div");
@@ -250,4 +255,67 @@ describe("preview", () => {
250255
expect(container.innerHTML).toBe("");
251256
expect(portal.innerHTML).toBe("");
252257
});
258+
259+
test("use children", async () => {
260+
const root = unstable_createRoot(container, {
261+
supportsUseChildren: true,
262+
});
263+
264+
await root.render([
265+
{
266+
brick: "my-brick",
267+
properties: {
268+
useChildren: "[items]",
269+
},
270+
children: [
271+
{
272+
brick: "div",
273+
slot: "[items]",
274+
properties: {
275+
textContent: "Hello Use Children",
276+
},
277+
},
278+
],
279+
},
280+
]);
281+
282+
expect(container.innerHTML).toBe("<my-brick></my-brick>");
283+
expect((container.firstElementChild as MyBrick).useBrick).toMatchObject({
284+
brick: "div",
285+
properties: {
286+
textContent: "Hello Use Children",
287+
},
288+
});
289+
290+
root.unmount();
291+
});
292+
293+
test("use children without supports", async () => {
294+
const root = unstable_createRoot(container);
295+
296+
await root.render([
297+
{
298+
brick: "my-brick",
299+
properties: {
300+
useChildren: "[items]",
301+
},
302+
children: [
303+
{
304+
brick: "div",
305+
slot: "[items]",
306+
properties: {
307+
textContent: "Hello Use Children",
308+
},
309+
},
310+
],
311+
},
312+
]);
313+
314+
expect(container.innerHTML).toBe(
315+
'<my-brick><div slot="[items]">Hello Use Children</div></my-brick>'
316+
);
317+
expect((container.firstElementChild as MyBrick).useBrick).toBe(undefined);
318+
319+
root.unmount();
320+
});
253321
});

packages/runtime/src/createRoot.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import type {
99
StoryboardFunction,
1010
} from "@next-core/types";
1111
import { i18n } from "@next-core/i18n";
12+
import { replaceUseChildren } from "@next-core/utils/storyboard";
1213
import { uniqueId } from "lodash";
1314
import {
1415
RenderOutput,
@@ -44,6 +45,11 @@ export interface CreateRootOptions {
4445
*/
4546
unknownBricks?: "silent" | "throw";
4647

48+
/**
49+
* Whether the root supports `useChildren`.
50+
*/
51+
supportsUseChildren?: boolean;
52+
4753
/**
4854
* Set unsafe_penetrate to true to allow accessing global variables
4955
* from an isolated root.
@@ -71,6 +77,7 @@ export function unstable_createRoot(
7177
portal: _portal,
7278
scope = "fragment",
7379
unknownBricks,
80+
supportsUseChildren,
7481
unsafe_penetrate,
7582
}: CreateRootOptions = {}
7683
) {
@@ -114,6 +121,16 @@ export function unstable_createRoot(
114121
}
115122
const bricks = ([] as BrickConf[]).concat(brick);
116123

124+
if (supportsUseChildren) {
125+
replaceUseChildren(bricks);
126+
127+
for (const template of templates ?? []) {
128+
if (Array.isArray(template.bricks)) {
129+
replaceUseChildren(template.bricks);
130+
}
131+
}
132+
}
133+
117134
const previousRendererContext = rendererContext;
118135
const renderId = uniqueId("render-id-");
119136
rendererContext = new RendererContext(scope, { unknownBricks, renderId });

packages/utils/src/storyboard/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
export * from "./expressions/index.js";
22
export * from "./functions/index.js";
33
export * from "./permissions.js";
4+
export * from "./replaceUseChildren.js";
45
import { createProviderClass, unwrapProvider } from "@next-core/utils/general";
56
export {
67
/** @deprecated import it from "@next-core/utils/general" instead */

0 commit comments

Comments
 (0)