Skip to content

Commit 4e4de20

Browse files
authored
fix(app-website): decorate lexical renderers on first mount (#4452)
1 parent 9b7ddad commit 4e4de20

File tree

9 files changed

+93
-41
lines changed

9 files changed

+93
-41
lines changed

extensions/theme/src/layouts/pages/Static/HeaderMobile.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const HeaderMobileWrapper = styled.div`
9898
}
9999
100100
> nav {
101+
display: none;
101102
-moz-osx-font-smoothing: grayscale;
102103
-webkit-font-smoothing: antialiased;
103104
animation: slide-out 0.5s forwards;

packages/app-page-builder/src/render/PageBuilder.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ import React from "react";
22
import { AddButtonClickHandlers } from "~/elementDecorators/AddButtonClickHandlers";
33
import { AddButtonLinkComponent } from "~/elementDecorators/AddButtonLinkComponent";
44
import { InjectElementVariables } from "~/render/variables/InjectElementVariables";
5-
import { LexicalParagraphRenderer } from "~/render/plugins/elements/paragraph/LexicalParagraph";
6-
import { LexicalHeadingRenderer } from "~/render/plugins/elements/heading/LexicalHeading";
75

8-
export const PageBuilder = () => {
6+
export const PageBuilder = React.memo(() => {
97
return (
108
<>
119
<AddButtonLinkComponent />
1210
<AddButtonClickHandlers />
1311
<InjectElementVariables />
14-
<LexicalParagraphRenderer />
15-
<LexicalHeadingRenderer />
1612
</>
1713
);
18-
};
14+
});
15+
16+
PageBuilder.displayName = "PageBuilder";
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import type { DecoratorsCollection } from "@webiny/app";
2+
import { ParagraphRenderer } from "@webiny/app-page-builder-elements/renderers/paragraph";
3+
import { HeadingRenderer } from "@webiny/app-page-builder-elements/renderers/heading";
4+
import { LexicalParagraphDecorator } from "~/render/plugins/elements/paragraph/LexicalParagraph";
5+
import { LexicalHeadingDecorator } from "~/render/plugins/elements/heading/LexicalHeading";
6+
7+
export const lexicalRendererDecorators: DecoratorsCollection = [
8+
[ParagraphRenderer.Component, [LexicalParagraphDecorator]],
9+
[HeadingRenderer.Component, [LexicalHeadingDecorator]]
10+
];

packages/app-page-builder/src/render/plugins/elements/heading/LexicalHeading.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import React from "react";
22
import {
3-
HeadingRenderer,
4-
elementInputs
3+
elementInputs,
4+
HeadingRenderer
55
} from "@webiny/app-page-builder-elements/renderers/heading";
66
import { usePageElements, useRenderer } from "@webiny/app-page-builder-elements";
77
import { assignStyles } from "@webiny/app-page-builder-elements/utils";
88
import { isValidLexicalData, LexicalHtmlRenderer } from "@webiny/lexical-editor";
9+
import type { ComponentDecorator } from "@webiny/app";
10+
import type { Renderer } from "@webiny/app-page-builder-elements/types";
911

10-
export const LexicalHeadingRenderer = HeadingRenderer.Component.createDecorator(Original => {
11-
return function LexicalHeadingRenderer() {
12+
export const LexicalHeadingDecorator: ComponentDecorator<Renderer> = Original => {
13+
return function LexicalHeadingRenderer(props) {
1214
const { theme } = usePageElements();
1315
const { getInputValues } = useRenderer();
1416
const inputs = getInputValues<typeof elementInputs>();
@@ -29,6 +31,9 @@ export const LexicalHeadingRenderer = HeadingRenderer.Component.createDecorator(
2931
);
3032
}
3133

32-
return <Original />;
34+
return <Original {...props} />;
3335
};
34-
});
36+
};
37+
38+
export const LexicalHeadingRenderer =
39+
HeadingRenderer.Component.createDecorator(LexicalHeadingDecorator);

packages/app-page-builder/src/render/plugins/elements/paragraph/LexicalParagraph.tsx

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
11
import React from "react";
22
import {
3-
ParagraphRenderer,
4-
elementInputs
3+
elementInputs,
4+
ParagraphRenderer
55
} from "@webiny/app-page-builder-elements/renderers/paragraph";
66
import { usePageElements, useRenderer } from "@webiny/app-page-builder-elements";
77
import { assignStyles } from "@webiny/app-page-builder-elements/utils";
88
import { isValidLexicalData, LexicalHtmlRenderer } from "@webiny/lexical-editor";
9+
import type { ComponentDecorator } from "@webiny/app";
10+
import type { Renderer } from "@webiny/app-page-builder-elements/types";
911

10-
export const LexicalParagraphRenderer = ParagraphRenderer.Component.createDecorator(Original => {
11-
return function LexicalParagraphRenderer() {
12+
export const LexicalParagraphDecorator: ComponentDecorator<Renderer> = Original => {
13+
return function LexicalParagraphRenderer(props) {
1214
const { theme } = usePageElements();
1315
const { getInputValues } = useRenderer();
1416
const inputs = getInputValues<typeof elementInputs>();
@@ -29,6 +31,9 @@ export const LexicalParagraphRenderer = ParagraphRenderer.Component.createDecora
2931
);
3032
}
3133

32-
return <Original />;
34+
return <Original {...props} />;
3335
};
34-
});
36+
};
37+
38+
export const LexicalParagraphRenderer =
39+
ParagraphRenderer.Component.createDecorator(LexicalParagraphDecorator);

packages/app-website/src/Website.tsx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,13 @@ import React, { useMemo } from "react";
22
import { App, AppProps, Decorator, GenericComponent } from "@webiny/app";
33
import { ApolloProvider } from "@apollo/react-hooks";
44
import { CacheProvider } from "@emotion/react";
5-
import { Page } from "./Page";
6-
import { createApolloClient, createEmotionCache } from "~/utils";
75
import { ThemeProvider } from "@webiny/app-theme";
86
import { PageBuilderProvider } from "@webiny/app-page-builder/contexts/PageBuilder";
7+
import { lexicalRendererDecorators } from "@webiny/app-page-builder/render/lexicalRendererDecorators";
98
import { PageBuilder } from "@webiny/app-page-builder/render";
109
import { RouteProps } from "@webiny/react-router";
10+
import { createApolloClient, createEmotionCache } from "~/utils";
11+
import { Page } from "./Page";
1112
import { LinkPreload } from "~/LinkPreload";
1213
import { WebsiteLoaderCache } from "~/utils/WebsiteLoaderCache";
1314

@@ -53,6 +54,7 @@ export const Website = ({ children, routes = [], providers = [], ...props }: Web
5354
debounceRender={debounceMs}
5455
routes={appRoutes}
5556
providers={[PageBuilderProviderHOC, ...providers]}
57+
decorators={[...lexicalRendererDecorators]}
5658
>
5759
<LinkPreload />
5860
<PageBuilder />

packages/app/src/App.tsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@ import {
1313
GenericComponent,
1414
compose,
1515
Decorator,
16-
HigherOrderComponent
16+
HigherOrderComponent,
17+
DecoratorsCollection
1718
} from "@webiny/react-composition";
1819
import { Routes as SortRoutes } from "./core/Routes";
1920
import { DebounceRender } from "./core/DebounceRender";
@@ -53,6 +54,7 @@ export interface AppProps {
5354
debounceRender?: number;
5455
routes?: Array<RouteProps>;
5556
providers?: Array<Decorator<GenericComponent<ProviderProps>>>;
57+
decorators?: DecoratorsCollection;
5658
children?: React.ReactNode | React.ReactNode[];
5759
}
5860

@@ -62,7 +64,13 @@ interface ProviderProps {
6264

6365
type ComponentWithChildren = React.ComponentType<{ children?: React.ReactNode }>;
6466

65-
export const App = ({ debounceRender = 50, routes = [], providers = [], children }: AppProps) => {
67+
export const App = ({
68+
debounceRender = 50,
69+
routes = [],
70+
providers = [],
71+
decorators = [],
72+
children
73+
}: AppProps) => {
6674
const [state, setState] = useState<State>({
6775
routes: routes.reduce<RoutesByPath>((acc, item) => {
6876
return { ...acc, [item.path as string]: <Route {...item} /> };
@@ -129,7 +137,7 @@ export const App = ({ debounceRender = 50, routes = [], providers = [], children
129137

130138
return (
131139
<AppContext.Provider value={appContext}>
132-
<CompositionProvider>
140+
<CompositionProvider decorators={decorators}>
133141
{children}
134142
<BrowserRouter>
135143
<Providers>

packages/cwp-template-aws/template/common/extensions/theme/src/layouts/pages/Static/HeaderMobile.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ const HeaderMobileWrapper = styled.div`
9898
}
9999
100100
> nav {
101+
display: none;
101102
-moz-osx-font-smoothing: grayscale;
102103
-webkit-font-smoothing: antialiased;
103104
animation: slide-out 0.5s forwards;

packages/react-composition/src/Context.tsx

Lines changed: 40 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import { useCompositionScope } from "~/CompositionScope";
1010
import {
1111
ComposedFunction,
1212
ComposeWith,
13+
Decoratable,
1314
DecoratableComponent,
1415
DecoratableHook,
1516
Decorator,
@@ -70,35 +71,56 @@ interface CompositionContext {
7071

7172
const CompositionContext = createContext<CompositionContext | undefined>(undefined);
7273

74+
export type DecoratorsTuple = [Decoratable, Decorator<any>[]];
75+
export type DecoratorsCollection = Array<DecoratorsTuple>;
76+
7377
interface CompositionProviderProps {
78+
decorators?: DecoratorsCollection;
7479
children: React.ReactNode;
7580
}
7681

77-
export const CompositionProvider = ({ children }: CompositionProviderProps) => {
78-
const [components, setComponents] = useState<ComponentScopes>(new Map());
82+
const composeComponents = (
83+
components: ComponentScopes,
84+
decorators: Array<[GenericComponent | GenericHook, Decorator<any>[]]>,
85+
scope = "*"
86+
) => {
87+
const scopeMap: ComposedComponents = components.get(scope) || new Map();
88+
for (const [component, hocs] of decorators) {
89+
const recipe = scopeMap.get(component) || { component: null, hocs: [] };
90+
91+
const newHocs = [...(recipe.hocs || []), ...hocs] as Decorator<
92+
GenericHook | GenericComponent
93+
>[];
94+
95+
scopeMap.set(component, {
96+
component: compose(...[...newHocs].reverse())(component),
97+
hocs: newHocs
98+
});
99+
100+
components.set(scope, scopeMap);
101+
}
102+
103+
return components;
104+
};
105+
106+
export const CompositionProvider = ({ decorators = [], children }: CompositionProviderProps) => {
107+
const [components, setComponents] = useState<ComponentScopes>(() => {
108+
return composeComponents(
109+
new Map(),
110+
decorators.map(tuple => {
111+
return [tuple[0].original, tuple[1]];
112+
})
113+
);
114+
});
79115

80116
const composeComponent = useCallback(
81117
(
82-
component: GenericHook | GenericComponent,
118+
component: GenericComponent | GenericHook,
83119
hocs: HigherOrderComponent<any, any>[],
84120
scope: string | undefined = "*"
85121
) => {
86122
setComponents(prevComponents => {
87-
const components = new Map(prevComponents);
88-
const scopeMap: ComposedComponents = components.get(scope) || new Map();
89-
const recipe = scopeMap.get(component) || { component: null, hocs: [] };
90-
91-
const newHocs = [...(recipe.hocs || []), ...hocs] as Decorator<
92-
GenericHook | GenericComponent
93-
>[];
94-
95-
scopeMap.set(component, {
96-
component: compose(...[...newHocs].reverse())(component),
97-
hocs: newHocs
98-
});
99-
100-
components.set(scope, scopeMap);
101-
return components;
123+
return composeComponents(new Map(prevComponents), [[component, hocs]], scope);
102124
});
103125

104126
// Return a function that will remove the added HOCs.

0 commit comments

Comments
 (0)