@webiny/react-composition 0.0.0-unstable.d7f521b032 → 0.0.0-unstable.dbdf5d6258
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.
- package/Compose.d.ts +6 -12
- package/Compose.js +61 -21
- package/Compose.js.map +1 -1
- package/CompositionScope.d.ts +17 -0
- package/CompositionScope.js +27 -0
- package/CompositionScope.js.map +1 -0
- package/Context.d.ts +24 -27
- package/Context.js +75 -110
- package/Context.js.map +1 -1
- package/README.md +9 -6
- package/createDecorator.d.ts +19 -0
- package/createDecorator.js +29 -0
- package/createDecorator.js.map +1 -0
- package/decorators.d.ts +15 -0
- package/decorators.js +71 -0
- package/decorators.js.map +1 -0
- package/domain/CompositionStore.d.ts +15 -0
- package/domain/CompositionStore.js +102 -0
- package/domain/CompositionStore.js.map +1 -0
- package/index.d.ts +9 -4
- package/index.js +10 -57
- package/index.js.map +1 -1
- package/makeComposable.d.ts +43 -3
- package/makeComposable.js +10 -68
- package/makeComposable.js.map +1 -1
- package/makeDecoratable.d.ts +31 -0
- package/makeDecoratable.js +53 -0
- package/makeDecoratable.js.map +1 -0
- package/package.json +10 -19
- package/types.d.ts +35 -0
- package/types.js +3 -0
- package/types.js.map +1 -0
- package/createComponentPlugin.d.ts +0 -8
- package/createComponentPlugin.js +0 -29
- package/createComponentPlugin.js.map +0 -1
package/Compose.d.ts
CHANGED
|
@@ -1,15 +1,9 @@
|
|
|
1
1
|
import React from "react";
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
original: React.FC<TProps>;
|
|
5
|
-
originalName: string;
|
|
6
|
-
}
|
|
2
|
+
import type { DecoratableTypes } from "./Context.js";
|
|
3
|
+
import type { ComposeWith } from "./types.js";
|
|
7
4
|
export interface ComposeProps {
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
*/
|
|
12
|
-
component: ComposableFC<any>;
|
|
13
|
-
with: HigherOrderComponent | HigherOrderComponent[];
|
|
5
|
+
function?: DecoratableTypes;
|
|
6
|
+
component?: DecoratableTypes;
|
|
7
|
+
with: ComposeWith;
|
|
14
8
|
}
|
|
15
|
-
export declare const Compose: React.
|
|
9
|
+
export declare const Compose: (props: ComposeProps) => React.JSX.Element | null;
|
package/Compose.js
CHANGED
|
@@ -1,28 +1,68 @@
|
|
|
1
|
-
|
|
1
|
+
import React, { useEffect, useRef } from "react";
|
|
2
|
+
import { useCompositionStore } from "./Context.js";
|
|
3
|
+
import { useCompositionScope } from "./CompositionScope.js";
|
|
4
|
+
export const Compose = props => {
|
|
5
|
+
const store = useCompositionStore();
|
|
6
|
+
const {
|
|
7
|
+
scope,
|
|
8
|
+
inherit
|
|
9
|
+
} = useCompositionScope();
|
|
10
|
+
const targetFn = props.function ?? props.component;
|
|
11
|
+
if (!targetFn) {
|
|
12
|
+
console.warn("You must provide a function or a component to compose with!", props);
|
|
13
|
+
return null;
|
|
14
|
+
}
|
|
15
|
+
if (typeof targetFn.original === "undefined") {
|
|
16
|
+
console.warn(`You must make your function "${targetFn.originalName ?? targetFn.name}" composable, by using the makeDecoratable() function!`);
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
const decorators = Array.isArray(props.with) ? props.with : [props.with];
|
|
20
|
+
const currentScope = scope[scope.length - 1] ?? "*";
|
|
2
21
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
22
|
+
// Register synchronously during render so decorators are available immediately.
|
|
23
|
+
// Pass silent=true to avoid notifying listeners mid-render (which would trigger
|
|
24
|
+
// setState in other components and cause React warnings).
|
|
25
|
+
store.register(targetFn.original, decorators, currentScope, inherit, true);
|
|
26
|
+
return /*#__PURE__*/React.createElement(ComposeEffects, {
|
|
27
|
+
store: store,
|
|
28
|
+
target: targetFn.original,
|
|
29
|
+
decorators: decorators,
|
|
30
|
+
scope: currentScope
|
|
31
|
+
});
|
|
32
|
+
};
|
|
11
33
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Separate component for the effect to avoid re-running the cleanup on every render.
|
|
36
|
+
* This component handles cleanup on unmount and when props change.
|
|
37
|
+
*/
|
|
38
|
+
function ComposeEffects({
|
|
39
|
+
store,
|
|
40
|
+
target,
|
|
41
|
+
decorators,
|
|
42
|
+
scope
|
|
43
|
+
}) {
|
|
44
|
+
const prevRef = useRef(null);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
const prev = prevRef.current;
|
|
15
47
|
|
|
16
|
-
|
|
17
|
-
if (
|
|
18
|
-
|
|
19
|
-
|
|
48
|
+
// On prop change: unregister old decorators.
|
|
49
|
+
if (prev && (prev.decorators !== decorators || prev.scope !== scope)) {
|
|
50
|
+
store.unregister(target, prev.decorators, prev.scope);
|
|
51
|
+
// Re-register new ones (they were already registered during render,
|
|
52
|
+
// but the idempotency check handles this).
|
|
53
|
+
store.register(target, decorators, scope);
|
|
20
54
|
}
|
|
55
|
+
prevRef.current = {
|
|
56
|
+
decorators,
|
|
57
|
+
scope
|
|
58
|
+
};
|
|
21
59
|
|
|
22
|
-
|
|
23
|
-
return
|
|
24
|
-
|
|
60
|
+
// Cleanup on unmount.
|
|
61
|
+
return () => {
|
|
62
|
+
store.unregister(target, decorators, scope);
|
|
63
|
+
};
|
|
64
|
+
}, [store, target, decorators, scope]);
|
|
25
65
|
return null;
|
|
26
|
-
}
|
|
66
|
+
}
|
|
27
67
|
|
|
28
|
-
|
|
68
|
+
//# sourceMappingURL=Compose.js.map
|
package/Compose.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["Compose","props","
|
|
1
|
+
{"version":3,"names":["React","useEffect","useRef","useCompositionStore","useCompositionScope","Compose","props","store","scope","inherit","targetFn","function","component","console","warn","original","originalName","name","decorators","Array","isArray","with","currentScope","length","register","createElement","ComposeEffects","target","prevRef","prev","current","unregister"],"sources":["Compose.tsx"],"sourcesContent":["import React, { useEffect, useRef } from \"react\";\nimport type { DecoratableTypes } from \"./Context.js\";\nimport { useCompositionStore } from \"./Context.js\";\nimport { useCompositionScope } from \"~/CompositionScope.js\";\nimport type {\n ComposeWith,\n Decoratable,\n Decorator,\n GenericComponent,\n GenericHook\n} from \"./types.js\";\n\nexport interface ComposeProps {\n function?: DecoratableTypes;\n component?: DecoratableTypes;\n with: ComposeWith;\n}\n\nexport const Compose = (props: ComposeProps) => {\n const store = useCompositionStore();\n const { scope, inherit } = useCompositionScope();\n\n const targetFn = (props.function ?? props.component) as Decoratable;\n\n if (!targetFn) {\n console.warn(\"You must provide a function or a component to compose with!\", props);\n return null;\n }\n\n if (typeof targetFn.original === \"undefined\") {\n console.warn(\n `You must make your function \"${\n targetFn.originalName ?? targetFn.name\n }\" composable, by using the makeDecoratable() function!`\n );\n return null;\n }\n\n const decorators = (Array.isArray(props.with) ? props.with : [props.with]) as Decorator<\n GenericComponent | GenericHook\n >[];\n const currentScope = scope[scope.length - 1] ?? \"*\";\n\n // Register synchronously during render so decorators are available immediately.\n // Pass silent=true to avoid notifying listeners mid-render (which would trigger\n // setState in other components and cause React warnings).\n store.register(targetFn.original, decorators, currentScope, inherit, true);\n\n return (\n <ComposeEffects\n store={store}\n target={targetFn.original}\n decorators={decorators}\n scope={currentScope}\n />\n );\n};\n\n/**\n * Separate component for the effect to avoid re-running the cleanup on every render.\n * This component handles cleanup on unmount and when props change.\n */\nfunction ComposeEffects({\n store,\n target,\n decorators,\n scope\n}: {\n store: ReturnType<typeof useCompositionStore>;\n target: any;\n decorators: Decorator<GenericComponent | GenericHook>[];\n scope: string;\n}) {\n const prevRef = useRef<{\n decorators: Decorator<GenericComponent | GenericHook>[];\n scope: string;\n } | null>(null);\n\n useEffect(() => {\n const prev = prevRef.current;\n\n // On prop change: unregister old decorators.\n if (prev && (prev.decorators !== decorators || prev.scope !== scope)) {\n store.unregister(target, prev.decorators, prev.scope);\n // Re-register new ones (they were already registered during render,\n // but the idempotency check handles this).\n store.register(target, decorators, scope);\n }\n\n prevRef.current = { decorators, scope };\n\n // Cleanup on unmount.\n return () => {\n store.unregister(target, decorators, scope);\n };\n }, [store, target, decorators, scope]);\n\n return null;\n}\n"],"mappings":"AAAA,OAAOA,KAAK,IAAIC,SAAS,EAAEC,MAAM,QAAQ,OAAO;AAEhD,SAASC,mBAAmB;AAC5B,SAASC,mBAAmB;AAe5B,OAAO,MAAMC,OAAO,GAAIC,KAAmB,IAAK;EAC5C,MAAMC,KAAK,GAAGJ,mBAAmB,CAAC,CAAC;EACnC,MAAM;IAAEK,KAAK;IAAEC;EAAQ,CAAC,GAAGL,mBAAmB,CAAC,CAAC;EAEhD,MAAMM,QAAQ,GAAIJ,KAAK,CAACK,QAAQ,IAAIL,KAAK,CAACM,SAAyB;EAEnE,IAAI,CAACF,QAAQ,EAAE;IACXG,OAAO,CAACC,IAAI,CAAC,6DAA6D,EAAER,KAAK,CAAC;IAClF,OAAO,IAAI;EACf;EAEA,IAAI,OAAOI,QAAQ,CAACK,QAAQ,KAAK,WAAW,EAAE;IAC1CF,OAAO,CAACC,IAAI,CACR,gCACIJ,QAAQ,CAACM,YAAY,IAAIN,QAAQ,CAACO,IAAI,wDAE9C,CAAC;IACD,OAAO,IAAI;EACf;EAEA,MAAMC,UAAU,GAAIC,KAAK,CAACC,OAAO,CAACd,KAAK,CAACe,IAAI,CAAC,GAAGf,KAAK,CAACe,IAAI,GAAG,CAACf,KAAK,CAACe,IAAI,CAErE;EACH,MAAMC,YAAY,GAAGd,KAAK,CAACA,KAAK,CAACe,MAAM,GAAG,CAAC,CAAC,IAAI,GAAG;;EAEnD;EACA;EACA;EACAhB,KAAK,CAACiB,QAAQ,CAACd,QAAQ,CAACK,QAAQ,EAAEG,UAAU,EAAEI,YAAY,EAAEb,OAAO,EAAE,IAAI,CAAC;EAE1E,oBACIT,KAAA,CAAAyB,aAAA,CAACC,cAAc;IACXnB,KAAK,EAAEA,KAAM;IACboB,MAAM,EAAEjB,QAAQ,CAACK,QAAS;IAC1BG,UAAU,EAAEA,UAAW;IACvBV,KAAK,EAAEc;EAAa,CACvB,CAAC;AAEV,CAAC;;AAED;AACA;AACA;AACA;AACA,SAASI,cAAcA,CAAC;EACpBnB,KAAK;EACLoB,MAAM;EACNT,UAAU;EACVV;AAMJ,CAAC,EAAE;EACC,MAAMoB,OAAO,GAAG1B,MAAM,CAGZ,IAAI,CAAC;EAEfD,SAAS,CAAC,MAAM;IACZ,MAAM4B,IAAI,GAAGD,OAAO,CAACE,OAAO;;IAE5B;IACA,IAAID,IAAI,KAAKA,IAAI,CAACX,UAAU,KAAKA,UAAU,IAAIW,IAAI,CAACrB,KAAK,KAAKA,KAAK,CAAC,EAAE;MAClED,KAAK,CAACwB,UAAU,CAACJ,MAAM,EAAEE,IAAI,CAACX,UAAU,EAAEW,IAAI,CAACrB,KAAK,CAAC;MACrD;MACA;MACAD,KAAK,CAACiB,QAAQ,CAACG,MAAM,EAAET,UAAU,EAAEV,KAAK,CAAC;IAC7C;IAEAoB,OAAO,CAACE,OAAO,GAAG;MAAEZ,UAAU;MAAEV;IAAM,CAAC;;IAEvC;IACA,OAAO,MAAM;MACTD,KAAK,CAACwB,UAAU,CAACJ,MAAM,EAAET,UAAU,EAAEV,KAAK,CAAC;IAC/C,CAAC;EACL,CAAC,EAAE,CAACD,KAAK,EAAEoB,MAAM,EAAET,UAAU,EAAEV,KAAK,CAAC,CAAC;EAEtC,OAAO,IAAI;AACf","ignoreList":[]}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface CompositionScopeContext {
|
|
3
|
+
inherit: boolean;
|
|
4
|
+
scope: string[];
|
|
5
|
+
}
|
|
6
|
+
interface CompositionScopeProps {
|
|
7
|
+
name: string;
|
|
8
|
+
/**
|
|
9
|
+
* Use this prop on components that are used to register decorators.
|
|
10
|
+
* Components are inherited at the time of registration, and then cached.
|
|
11
|
+
*/
|
|
12
|
+
inherit?: boolean;
|
|
13
|
+
children: React.ReactNode;
|
|
14
|
+
}
|
|
15
|
+
export declare const CompositionScope: ({ name, inherit, children }: CompositionScopeProps) => React.JSX.Element;
|
|
16
|
+
export declare function useCompositionScope(): CompositionScopeContext;
|
|
17
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
const CompositionScopeContext = /*#__PURE__*/React.createContext(undefined);
|
|
3
|
+
export const CompositionScope = ({
|
|
4
|
+
name,
|
|
5
|
+
inherit = false,
|
|
6
|
+
children
|
|
7
|
+
}) => {
|
|
8
|
+
const parentScope = useCompositionScope();
|
|
9
|
+
return /*#__PURE__*/React.createElement(CompositionScopeContext.Provider, {
|
|
10
|
+
value: {
|
|
11
|
+
scope: [...parentScope.scope, name],
|
|
12
|
+
inherit
|
|
13
|
+
}
|
|
14
|
+
}, children);
|
|
15
|
+
};
|
|
16
|
+
export function useCompositionScope() {
|
|
17
|
+
const context = React.useContext(CompositionScopeContext);
|
|
18
|
+
if (!context) {
|
|
19
|
+
return {
|
|
20
|
+
scope: [],
|
|
21
|
+
inherit: false
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
return context;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
//# sourceMappingURL=CompositionScope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","CompositionScopeContext","createContext","undefined","CompositionScope","name","inherit","children","parentScope","useCompositionScope","createElement","Provider","value","scope","context","useContext"],"sources":["CompositionScope.tsx"],"sourcesContent":["import React from \"react\";\n\nexport interface CompositionScopeContext {\n inherit: boolean;\n scope: string[];\n}\n\nconst CompositionScopeContext = React.createContext<CompositionScopeContext | undefined>(undefined);\n\ninterface CompositionScopeProps {\n name: string;\n /**\n * Use this prop on components that are used to register decorators.\n * Components are inherited at the time of registration, and then cached.\n */\n inherit?: boolean;\n children: React.ReactNode;\n}\n\nexport const CompositionScope = ({ name, inherit = false, children }: CompositionScopeProps) => {\n const parentScope = useCompositionScope();\n\n return (\n <CompositionScopeContext.Provider value={{ scope: [...parentScope.scope, name], inherit }}>\n {children}\n </CompositionScopeContext.Provider>\n );\n};\n\nexport function useCompositionScope() {\n const context = React.useContext(CompositionScopeContext);\n\n if (!context) {\n return { scope: [], inherit: false };\n }\n\n return context;\n}\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAOzB,MAAMC,uBAAuB,gBAAGD,KAAK,CAACE,aAAa,CAAsCC,SAAS,CAAC;AAYnG,OAAO,MAAMC,gBAAgB,GAAGA,CAAC;EAAEC,IAAI;EAAEC,OAAO,GAAG,KAAK;EAAEC;AAAgC,CAAC,KAAK;EAC5F,MAAMC,WAAW,GAAGC,mBAAmB,CAAC,CAAC;EAEzC,oBACIT,KAAA,CAAAU,aAAA,CAACT,uBAAuB,CAACU,QAAQ;IAACC,KAAK,EAAE;MAAEC,KAAK,EAAE,CAAC,GAAGL,WAAW,CAACK,KAAK,EAAER,IAAI,CAAC;MAAEC;IAAQ;EAAE,GACrFC,QAC6B,CAAC;AAE3C,CAAC;AAED,OAAO,SAASE,mBAAmBA,CAAA,EAAG;EAClC,MAAMK,OAAO,GAAGd,KAAK,CAACe,UAAU,CAACd,uBAAuB,CAAC;EAEzD,IAAI,CAACa,OAAO,EAAE;IACV,OAAO;MAAED,KAAK,EAAE,EAAE;MAAEP,OAAO,EAAE;IAAM,CAAC;EACxC;EAEA,OAAOQ,OAAO;AAClB","ignoreList":[]}
|
package/Context.d.ts
CHANGED
|
@@ -1,38 +1,35 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
*/
|
|
7
|
-
component: ComponentType<unknown>;
|
|
8
|
-
/**
|
|
9
|
-
* HOCs used to compose the original component.
|
|
10
|
-
*/
|
|
11
|
-
hocs: HigherOrderComponent[];
|
|
12
|
-
}
|
|
1
|
+
import type { ComponentType } from "react";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { CompositionStore } from "./domain/CompositionStore.js";
|
|
4
|
+
import type { ComposeWith, Decoratable, DecoratableComponent, DecoratableHook, Decorator, Enumerable, GenericComponent, GenericHook } from "./types.js";
|
|
5
|
+
export declare function compose<T>(...fns: Decorator<T>[]): (decoratee: T) => T;
|
|
13
6
|
/**
|
|
14
|
-
*
|
|
15
|
-
* You can pass any HigherOrderComponent as a prop, regardless of its TInputProps type. The only way to allow that is
|
|
16
|
-
* to let it be `any` in this interface.
|
|
7
|
+
* @deprecated Use `Decorator` instead.
|
|
17
8
|
*/
|
|
18
|
-
export interface HigherOrderComponent<
|
|
19
|
-
(Component:
|
|
9
|
+
export interface HigherOrderComponent<TProps = any, TOutput = TProps> {
|
|
10
|
+
(Component: GenericComponent<TProps>): GenericComponent<TOutput>;
|
|
11
|
+
}
|
|
12
|
+
export type DecoratableTypes = DecoratableComponent | DecoratableHook;
|
|
13
|
+
export type DecoratorsTuple = [Decoratable, Decorator<any>[]];
|
|
14
|
+
export type DecoratorsCollection = Array<DecoratorsTuple>;
|
|
15
|
+
interface CompositionProviderProps {
|
|
16
|
+
decorators?: DecoratorsCollection;
|
|
17
|
+
children: React.ReactNode;
|
|
20
18
|
}
|
|
21
|
-
declare
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
19
|
+
export declare const CompositionProvider: ({ decorators, children }: CompositionProviderProps) => React.JSX.Element;
|
|
20
|
+
export declare function useCompositionStore(): CompositionStore;
|
|
21
|
+
export declare function useOptionalCompositionStore(): CompositionStore | undefined;
|
|
22
|
+
export declare function useComponent<T>(baseFunction: T): T;
|
|
23
|
+
interface CompositionContextValue {
|
|
24
|
+
composeComponent(component: ComponentType<unknown>, hocs: Enumerable<ComposeWith>, scope?: string, inherit?: boolean): () => void;
|
|
25
|
+
getComponent(component: ComponentType<unknown>, scope: string[]): GenericComponent | GenericHook | undefined;
|
|
26
26
|
}
|
|
27
|
-
declare const CompositionContext: React.Context<CompositionContext | undefined>;
|
|
28
|
-
export declare const CompositionProvider: React.FC;
|
|
29
|
-
export declare function useComponent(Component: ComponentType<any>): React.ComponentType<any>;
|
|
30
27
|
/**
|
|
31
28
|
* This hook will throw an error if composition context doesn't exist.
|
|
32
29
|
*/
|
|
33
|
-
export declare function useComposition():
|
|
30
|
+
export declare function useComposition(): CompositionContextValue;
|
|
34
31
|
/**
|
|
35
32
|
* This hook will not throw an error if composition context doesn't exist.
|
|
36
33
|
*/
|
|
37
|
-
export declare function useOptionalComposition():
|
|
34
|
+
export declare function useOptionalComposition(): CompositionContextValue | undefined;
|
|
38
35
|
export {};
|
package/Context.js
CHANGED
|
@@ -1,126 +1,91 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, "__esModule", {
|
|
8
|
-
value: true
|
|
9
|
-
});
|
|
10
|
-
exports.CompositionProvider = void 0;
|
|
11
|
-
exports.compose = compose;
|
|
12
|
-
exports.useComponent = useComponent;
|
|
13
|
-
exports.useComposition = useComposition;
|
|
14
|
-
exports.useOptionalComposition = useOptionalComposition;
|
|
15
|
-
|
|
16
|
-
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
|
|
17
|
-
|
|
18
|
-
var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
|
|
19
|
-
|
|
20
|
-
var _react = _interopRequireWildcard(require("react"));
|
|
21
|
-
|
|
22
|
-
function compose() {
|
|
23
|
-
for (var _len = arguments.length, fns = new Array(_len), _key = 0; _key < _len; _key++) {
|
|
24
|
-
fns[_key] = arguments[_key];
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
return function ComposedComponent(Base) {
|
|
28
|
-
return fns.reduceRight(function (Component, hoc) {
|
|
29
|
-
return hoc(Component);
|
|
30
|
-
}, Base);
|
|
1
|
+
import React, { createContext, useContext, useRef, useSyncExternalStore } from "react";
|
|
2
|
+
import { useCompositionScope } from "./CompositionScope.js";
|
|
3
|
+
import { CompositionStore } from "./domain/CompositionStore.js";
|
|
4
|
+
export function compose(...fns) {
|
|
5
|
+
return decoratee => {
|
|
6
|
+
return fns.reduceRight((decoratee, decorator) => decorator(decoratee), decoratee);
|
|
31
7
|
};
|
|
32
8
|
}
|
|
33
9
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
var children = _ref.children;
|
|
38
|
-
|
|
39
|
-
var _useState = (0, _react.useState)(new Map()),
|
|
40
|
-
_useState2 = (0, _slicedToArray2.default)(_useState, 2),
|
|
41
|
-
components = _useState2[0],
|
|
42
|
-
setComponents = _useState2[1];
|
|
43
|
-
|
|
44
|
-
var composeComponent = (0, _react.useCallback)(function (component, hocs) {
|
|
45
|
-
setComponents(function (prevComponents) {
|
|
46
|
-
var components = new Map(prevComponents);
|
|
47
|
-
var recipe = components.get(component) || {
|
|
48
|
-
component: null,
|
|
49
|
-
hocs: []
|
|
50
|
-
};
|
|
51
|
-
var newHocs = [].concat((0, _toConsumableArray2.default)(recipe.hocs || []), (0, _toConsumableArray2.default)(hocs));
|
|
52
|
-
components.set(component, {
|
|
53
|
-
component: compose.apply(void 0, (0, _toConsumableArray2.default)((0, _toConsumableArray2.default)(newHocs).reverse()))(component),
|
|
54
|
-
hocs: newHocs
|
|
55
|
-
});
|
|
56
|
-
return components;
|
|
57
|
-
}); // Return a function that will remove the added HOCs.
|
|
10
|
+
/**
|
|
11
|
+
* @deprecated Use `Decorator` instead.
|
|
12
|
+
*/
|
|
58
13
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
});
|
|
76
|
-
};
|
|
77
|
-
}, [setComponents]);
|
|
78
|
-
var getComponent = (0, _react.useCallback)(function (Component) {
|
|
79
|
-
var composedComponent = components.get(Component);
|
|
80
|
-
return composedComponent ? composedComponent.component : undefined;
|
|
81
|
-
}, [components]);
|
|
82
|
-
var context = (0, _react.useMemo)(function () {
|
|
83
|
-
return {
|
|
84
|
-
getComponent: getComponent,
|
|
85
|
-
composeComponent: composeComponent,
|
|
86
|
-
components: components
|
|
87
|
-
};
|
|
88
|
-
}, [components, composeComponent]);
|
|
89
|
-
return /*#__PURE__*/_react.default.createElement(CompositionContext.Provider, {
|
|
90
|
-
value: context
|
|
14
|
+
const CompositionStoreContext = /*#__PURE__*/createContext(undefined);
|
|
15
|
+
export const CompositionProvider = ({
|
|
16
|
+
decorators = [],
|
|
17
|
+
children
|
|
18
|
+
}) => {
|
|
19
|
+
const storeRef = useRef(null);
|
|
20
|
+
if (storeRef.current === null) {
|
|
21
|
+
const store = new CompositionStore();
|
|
22
|
+
// Pre-register decorators from props.
|
|
23
|
+
for (const [decoratable, hocs] of decorators) {
|
|
24
|
+
store.register(decoratable.original, hocs);
|
|
25
|
+
}
|
|
26
|
+
storeRef.current = store;
|
|
27
|
+
}
|
|
28
|
+
return /*#__PURE__*/React.createElement(CompositionStoreContext.Provider, {
|
|
29
|
+
value: storeRef.current
|
|
91
30
|
}, children);
|
|
92
31
|
};
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
var context = useOptionalComposition();
|
|
98
|
-
|
|
99
|
-
if (!context) {
|
|
100
|
-
return Component;
|
|
32
|
+
export function useCompositionStore() {
|
|
33
|
+
const store = useContext(CompositionStoreContext);
|
|
34
|
+
if (!store) {
|
|
35
|
+
throw new Error(`You're missing a <CompositionProvider> higher up in your component hierarchy!`);
|
|
101
36
|
}
|
|
102
|
-
|
|
103
|
-
|
|
37
|
+
return store;
|
|
38
|
+
}
|
|
39
|
+
export function useOptionalCompositionStore() {
|
|
40
|
+
return useContext(CompositionStoreContext);
|
|
104
41
|
}
|
|
42
|
+
export function useComponent(baseFunction) {
|
|
43
|
+
const store = useOptionalCompositionStore();
|
|
44
|
+
const scope = useCompositionScope();
|
|
45
|
+
|
|
46
|
+
// Subscribe to store changes so we re-render when compositions change.
|
|
47
|
+
useSyncExternalStore(store ? store.subscribe : noopSubscribe, store ? store.getSnapshot : noopGetSnapshot);
|
|
48
|
+
if (!store) {
|
|
49
|
+
return baseFunction;
|
|
50
|
+
}
|
|
51
|
+
return store.getComponent(baseFunction, scope.scope) || baseFunction;
|
|
52
|
+
}
|
|
53
|
+
const noopSubscribe = () => () => {};
|
|
54
|
+
const noopGetSnapshot = () => 0;
|
|
55
|
+
|
|
56
|
+
// Legacy compatibility — kept for any external consumers.
|
|
57
|
+
|
|
105
58
|
/**
|
|
106
59
|
* This hook will throw an error if composition context doesn't exist.
|
|
107
60
|
*/
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
61
|
+
export function useComposition() {
|
|
62
|
+
const store = useCompositionStore();
|
|
63
|
+
return {
|
|
64
|
+
composeComponent: (component, hocs, scope = "*", inherit = false) => {
|
|
65
|
+
return store.register(component, hocs, scope, inherit);
|
|
66
|
+
},
|
|
67
|
+
getComponent: (component, scope) => {
|
|
68
|
+
return store.getComponent(component, scope);
|
|
69
|
+
}
|
|
70
|
+
};
|
|
118
71
|
}
|
|
72
|
+
|
|
119
73
|
/**
|
|
120
74
|
* This hook will not throw an error if composition context doesn't exist.
|
|
121
75
|
*/
|
|
76
|
+
export function useOptionalComposition() {
|
|
77
|
+
const store = useOptionalCompositionStore();
|
|
78
|
+
if (!store) {
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
composeComponent: (component, hocs, scope = "*", inherit = false) => {
|
|
83
|
+
return store.register(component, hocs, scope, inherit);
|
|
84
|
+
},
|
|
85
|
+
getComponent: (component, scope) => {
|
|
86
|
+
return store.getComponent(component, scope);
|
|
87
|
+
}
|
|
88
|
+
};
|
|
89
|
+
}
|
|
122
90
|
|
|
123
|
-
|
|
124
|
-
function useOptionalComposition() {
|
|
125
|
-
return (0, _react.useContext)(CompositionContext);
|
|
126
|
-
}
|
|
91
|
+
//# sourceMappingURL=Context.js.map
|
package/Context.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["
|
|
1
|
+
{"version":3,"names":["React","createContext","useContext","useRef","useSyncExternalStore","useCompositionScope","CompositionStore","compose","fns","decoratee","reduceRight","decorator","CompositionStoreContext","undefined","CompositionProvider","decorators","children","storeRef","current","store","decoratable","hocs","register","original","createElement","Provider","value","useCompositionStore","Error","useOptionalCompositionStore","useComponent","baseFunction","scope","subscribe","noopSubscribe","getSnapshot","noopGetSnapshot","getComponent","useComposition","composeComponent","component","inherit","useOptionalComposition"],"sources":["Context.tsx"],"sourcesContent":["import type { ComponentType } from \"react\";\nimport React, { createContext, useContext, useRef, useSyncExternalStore } from \"react\";\nimport { useCompositionScope } from \"~/CompositionScope.js\";\nimport { CompositionStore } from \"~/domain/CompositionStore.js\";\nimport type {\n ComposeWith,\n Decoratable,\n DecoratableComponent,\n DecoratableHook,\n Decorator,\n Enumerable,\n GenericComponent,\n GenericHook\n} from \"~/types.js\";\n\nexport function compose<T>(...fns: Decorator<T>[]) {\n return (decoratee: T): T => {\n return fns.reduceRight((decoratee, decorator) => decorator(decoratee), decoratee) as T;\n };\n}\n\n/**\n * @deprecated Use `Decorator` instead.\n */\nexport interface HigherOrderComponent<TProps = any, TOutput = TProps> {\n (Component: GenericComponent<TProps>): GenericComponent<TOutput>;\n}\n\nexport type DecoratableTypes = DecoratableComponent | DecoratableHook;\n\nconst CompositionStoreContext = createContext<CompositionStore | undefined>(undefined);\n\nexport type DecoratorsTuple = [Decoratable, Decorator<any>[]];\nexport type DecoratorsCollection = Array<DecoratorsTuple>;\n\ninterface CompositionProviderProps {\n decorators?: DecoratorsCollection;\n children: React.ReactNode;\n}\n\nexport const CompositionProvider = ({ decorators = [], children }: CompositionProviderProps) => {\n const storeRef = useRef<CompositionStore | null>(null);\n if (storeRef.current === null) {\n const store = new CompositionStore();\n // Pre-register decorators from props.\n for (const [decoratable, hocs] of decorators) {\n store.register(decoratable.original as ComponentType<unknown>, hocs);\n }\n storeRef.current = store;\n }\n\n return (\n <CompositionStoreContext.Provider value={storeRef.current}>\n {children}\n </CompositionStoreContext.Provider>\n );\n};\n\nexport function useCompositionStore(): CompositionStore {\n const store = useContext(CompositionStoreContext);\n if (!store) {\n throw new Error(\n `You're missing a <CompositionProvider> higher up in your component hierarchy!`\n );\n }\n return store;\n}\n\nexport function useOptionalCompositionStore(): CompositionStore | undefined {\n return useContext(CompositionStoreContext);\n}\n\nexport function useComponent<T>(baseFunction: T) {\n const store = useOptionalCompositionStore();\n const scope = useCompositionScope();\n\n // Subscribe to store changes so we re-render when compositions change.\n useSyncExternalStore(\n store ? store.subscribe : noopSubscribe,\n store ? store.getSnapshot : noopGetSnapshot\n );\n\n if (!store) {\n return baseFunction;\n }\n\n return (store.getComponent(baseFunction as any, scope.scope) || baseFunction) as T;\n}\n\nconst noopSubscribe = () => () => {};\nconst noopGetSnapshot = () => 0;\n\n// Legacy compatibility — kept for any external consumers.\n\ninterface CompositionContextValue {\n composeComponent(\n component: ComponentType<unknown>,\n hocs: Enumerable<ComposeWith>,\n scope?: string,\n inherit?: boolean\n ): () => void;\n getComponent(\n component: ComponentType<unknown>,\n scope: string[]\n ): GenericComponent | GenericHook | undefined;\n}\n\n/**\n * This hook will throw an error if composition context doesn't exist.\n */\nexport function useComposition(): CompositionContextValue {\n const store = useCompositionStore();\n\n return {\n composeComponent: (component, hocs, scope = \"*\", inherit = false) => {\n return store.register(component, hocs as any[], scope, inherit);\n },\n getComponent: (component, scope) => {\n return store.getComponent(component, scope);\n }\n };\n}\n\n/**\n * This hook will not throw an error if composition context doesn't exist.\n */\nexport function useOptionalComposition(): CompositionContextValue | undefined {\n const store = useOptionalCompositionStore();\n if (!store) {\n return undefined;\n }\n\n return {\n composeComponent: (component, hocs, scope = \"*\", inherit = false) => {\n return store.register(component, hocs as any[], scope, inherit);\n },\n getComponent: (component, scope) => {\n return store.getComponent(component, scope);\n }\n };\n}\n"],"mappings":"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","ignoreList":[]}
|
package/README.md
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
#
|
|
2
|
-
[](https://www.npmjs.com/package/@webiny/react-composition)
|
|
3
|
-
[](https://www.npmjs.com/package/@webiny/react-composition)
|
|
4
|
-
[](https://github.com/prettier/prettier)
|
|
5
|
-
[](http://makeapullrequest.com)
|
|
1
|
+
# @webiny/react-composition
|
|
6
2
|
|
|
7
|
-
|
|
3
|
+
> [!NOTE]
|
|
4
|
+
> This package is part of the [Webiny](https://www.webiny.com) monorepo.
|
|
5
|
+
> It’s **included in every Webiny project by default** and is not meant to be used as a standalone package.
|
|
8
6
|
|
|
7
|
+
📘 **Documentation:** [https://www.webiny.com/docs](https://www.webiny.com/docs)
|
|
8
|
+
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
_This README file is automatically generated during the publish process._
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { CanReturnNullOrElement, Decoratable, DecoratableComponent, DecoratableHook, Decorator } from "./types.js";
|
|
3
|
+
type GetBaseFunction<T> = T extends DecoratableComponent<infer F> ? F : never;
|
|
4
|
+
/**
|
|
5
|
+
* Creates a component which, when mounted, registers a Higher Order Component for the given base component.
|
|
6
|
+
* This is particularly useful for decorating (wrapping) existing composable components.
|
|
7
|
+
* For more information, visit https://www.webiny.com/docs/admin-area/basics/framework.
|
|
8
|
+
*/
|
|
9
|
+
export declare function createComponentPlugin<T extends Decoratable>(Base: T, hoc: T extends DecoratableComponent ? Decorator<CanReturnNullOrElement<GetBaseFunction<T>>> : Decorator<GetBaseFunction<T>>): {
|
|
10
|
+
(): React.JSX.Element;
|
|
11
|
+
displayName: string;
|
|
12
|
+
};
|
|
13
|
+
export type GetDecorateeParams<T> = T extends (params?: infer P1) => any ? P1 : T extends (params: infer P2) => any ? P2 : any;
|
|
14
|
+
export type GetDecoratee<T> = T extends DecoratableHook<infer F> ? F : T extends DecoratableComponent<infer F> ? F : never;
|
|
15
|
+
export declare function createDecorator<T extends Decoratable>(Base: T, hoc: T extends DecoratableComponent ? Decorator<CanReturnNullOrElement<GetBaseFunction<T>>> : Decorator<GetBaseFunction<T>>): {
|
|
16
|
+
(): React.JSX.Element;
|
|
17
|
+
displayName: string;
|
|
18
|
+
};
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Compose } from "./Compose.js";
|
|
3
|
+
/**
|
|
4
|
+
* Creates a component which, when mounted, registers a Higher Order Component for the given base component.
|
|
5
|
+
* This is particularly useful for decorating (wrapping) existing composable components.
|
|
6
|
+
* For more information, visit https://www.webiny.com/docs/admin-area/basics/framework.
|
|
7
|
+
*/
|
|
8
|
+
export function createComponentPlugin(Base, hoc) {
|
|
9
|
+
return createDecorator(Base, hoc);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Maybe there's a better way to mark params as non-existent, but for now I left it as `any`.
|
|
13
|
+
// TODO: revisit this type; not sure if `?` can be handled in one clause
|
|
14
|
+
|
|
15
|
+
const isDecoratableComponent = decoratable => {
|
|
16
|
+
return "displayName" in decoratable;
|
|
17
|
+
};
|
|
18
|
+
export function createDecorator(Base, hoc) {
|
|
19
|
+
const DecoratorPlugin = () => /*#__PURE__*/React.createElement(Compose, {
|
|
20
|
+
component: Base,
|
|
21
|
+
with: hoc
|
|
22
|
+
});
|
|
23
|
+
if (isDecoratableComponent(Base)) {
|
|
24
|
+
DecoratorPlugin.displayName = Base.displayName;
|
|
25
|
+
}
|
|
26
|
+
return DecoratorPlugin;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
//# sourceMappingURL=createDecorator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["React","Compose","createComponentPlugin","Base","hoc","createDecorator","isDecoratableComponent","decoratable","DecoratorPlugin","createElement","component","with","displayName"],"sources":["createDecorator.tsx"],"sourcesContent":["import React from \"react\";\nimport type {\n CanReturnNullOrElement,\n Decoratable,\n DecoratableComponent,\n DecoratableHook,\n Decorator\n} from \"~/types.js\";\nimport { Compose } from \"~/Compose.js\";\n\ntype GetBaseFunction<T> = T extends DecoratableComponent<infer F> ? F : never;\n\n/**\n * Creates a component which, when mounted, registers a Higher Order Component for the given base component.\n * This is particularly useful for decorating (wrapping) existing composable components.\n * For more information, visit https://www.webiny.com/docs/admin-area/basics/framework.\n */\nexport function createComponentPlugin<T extends Decoratable>(\n Base: T,\n hoc: T extends DecoratableComponent\n ? Decorator<CanReturnNullOrElement<GetBaseFunction<T>>>\n : Decorator<GetBaseFunction<T>>\n) {\n return createDecorator(Base, hoc);\n}\n\n// Maybe there's a better way to mark params as non-existent, but for now I left it as `any`.\n// TODO: revisit this type; not sure if `?` can be handled in one clause\nexport type GetDecorateeParams<T> = T extends (params?: infer P1) => any\n ? P1\n : T extends (params: infer P2) => any\n ? P2\n : any;\n\nexport type GetDecoratee<T> =\n T extends DecoratableHook<infer F> ? F : T extends DecoratableComponent<infer F> ? F : never;\n\nconst isDecoratableComponent = (\n decoratable: DecoratableComponent | DecoratableHook\n): decoratable is DecoratableComponent => {\n return \"displayName\" in decoratable;\n};\n\nexport function createDecorator<T extends Decoratable>(\n Base: T,\n hoc: T extends DecoratableComponent\n ? Decorator<CanReturnNullOrElement<GetBaseFunction<T>>>\n : Decorator<GetBaseFunction<T>>\n) {\n const DecoratorPlugin = () => <Compose component={Base} with={hoc as any} />;\n if (isDecoratableComponent(Base)) {\n DecoratorPlugin.displayName = Base.displayName;\n }\n return DecoratorPlugin;\n}\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AAQzB,SAASC,OAAO;AAIhB;AACA;AACA;AACA;AACA;AACA,OAAO,SAASC,qBAAqBA,CACjCC,IAAO,EACPC,GAEmC,EACrC;EACE,OAAOC,eAAe,CAACF,IAAI,EAAEC,GAAG,CAAC;AACrC;;AAEA;AACA;;AAUA,MAAME,sBAAsB,GACxBC,WAAmD,IACb;EACtC,OAAO,aAAa,IAAIA,WAAW;AACvC,CAAC;AAED,OAAO,SAASF,eAAeA,CAC3BF,IAAO,EACPC,GAEmC,EACrC;EACE,MAAMI,eAAe,GAAGA,CAAA,kBAAMR,KAAA,CAAAS,aAAA,CAACR,OAAO;IAACS,SAAS,EAAEP,IAAK;IAACQ,IAAI,EAAEP;EAAW,CAAE,CAAC;EAC5E,IAAIE,sBAAsB,CAACH,IAAI,CAAC,EAAE;IAC9BK,eAAe,CAACI,WAAW,GAAGT,IAAI,CAACS,WAAW;EAClD;EACA,OAAOJ,eAAe;AAC1B","ignoreList":[]}
|
package/decorators.d.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import type { GetDecoratee, GetDecorateeParams } from "./createDecorator.js";
|
|
3
|
+
import type { DecoratableComponent, GenericComponent, Decorator, GenericHook, DecoratableHook, ComponentDecorator } from "./types.js";
|
|
4
|
+
export interface ShouldDecorate<TDecorator = any, TComponent = any> {
|
|
5
|
+
(decoratorProps: TDecorator, componentProps: TComponent): boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function createConditionalDecorator<TDecoratee extends GenericComponent>(shouldDecorate: ShouldDecorate, decorator: Decorator<TDecoratee>, decoratorProps: unknown): Decorator<TDecoratee>;
|
|
8
|
+
export declare function createDecoratorFactory<TDecorator>(): <TDecoratable extends DecoratableComponent>(decoratable: TDecoratable, shouldDecorate?: ShouldDecorate<TDecorator, GetDecorateeParams<GetDecoratee<TDecoratable>>>) => (decorator: ComponentDecorator<GetDecoratee<TDecoratable>>) => (props: TDecorator) => React.JSX.Element;
|
|
9
|
+
export declare function createHookDecoratorFactory(): <TDecoratable extends DecoratableHook>(decoratable: TDecoratable) => (decorator: Decorator<GetDecoratee<TDecoratable>>) => () => React.JSX.Element;
|
|
10
|
+
export declare function withDecoratorFactory<TDecorator>(): <TDecoratable extends DecoratableComponent>(Component: TDecoratable, shouldDecorate?: ShouldDecorate<TDecorator, GetDecorateeParams<GetDecoratee<TDecoratable>>>) => TDecoratable & {
|
|
11
|
+
createDecorator: (decorator: ComponentDecorator<GetDecoratee<TDecoratable>>) => (props: TDecorator) => React.JSX.Element;
|
|
12
|
+
};
|
|
13
|
+
export declare function withHookDecoratorFactory(): <TDecoratable extends DecoratableHook>(hook: TDecoratable) => DecoratableHook<GenericHook<GetDecorateeParams<GetDecoratee<TDecoratable>>, ReturnType<GetDecoratee<TDecoratable>>>> & {
|
|
14
|
+
createDecorator: (decorator: Decorator<GetDecoratee<TDecoratable>>) => () => React.JSX.Element;
|
|
15
|
+
};
|