@webiny/react-composition 6.3.0-beta.4 → 6.4.0-beta.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.
package/Compose.js CHANGED
@@ -1,83 +1,56 @@
1
- import React, { useEffect, useRef } from "react";
1
+ import react, { useEffect, useRef } from "react";
2
2
  import { useCompositionStore } from "./Context.js";
3
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] ?? "*";
21
-
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
- inherit: inherit
32
- });
4
+ const Compose = (props)=>{
5
+ const store = useCompositionStore();
6
+ const { scope, inherit } = useCompositionScope();
7
+ const targetFn = props.function ?? props.component;
8
+ if (!targetFn) {
9
+ console.warn("You must provide a function or a component to compose with!", props);
10
+ return null;
11
+ }
12
+ if (void 0 === targetFn.original) {
13
+ console.warn(`You must make your function "${targetFn.originalName ?? targetFn.name}" composable, by using the makeDecoratable() function!`);
14
+ return null;
15
+ }
16
+ const decorators = Array.isArray(props.with) ? props.with : [
17
+ props.with
18
+ ];
19
+ const currentScope = scope[scope.length - 1] ?? "*";
20
+ store.register(targetFn.original, decorators, currentScope, inherit, true);
21
+ return /*#__PURE__*/ react.createElement(ComposeEffects, {
22
+ store: store,
23
+ target: targetFn.original,
24
+ decorators: decorators,
25
+ scope: currentScope,
26
+ inherit: inherit
27
+ });
33
28
  };
34
-
35
- /**
36
- * Separate component for the effect to avoid re-running the cleanup on every render.
37
- * This component handles cleanup on unmount and when props change.
38
- */
39
- function ComposeEffects({
40
- store,
41
- target,
42
- decorators,
43
- scope,
44
- inherit
45
- }) {
46
- const prevRef = useRef(null);
47
-
48
- // Tracks the decorators currently live in the store as of the last render.
49
- // Updated synchronously during render so it always reflects the most recently
50
- // registered decorators, allowing the atomic swap below to remove the right ones.
51
- const liveRef = useRef(decorators);
52
-
53
- // On re-render with new decorators: atomically replace the old ones in the store
54
- // during render (before React commits). This ensures the store never transiently
55
- // holds both old and new HOCs — which would cause useSyncExternalStore subscribers
56
- // to render with a doubly-wrapped component and mount inner components twice.
57
- if (liveRef.current !== decorators) {
58
- store.register(target, decorators, scope, inherit, true, liveRef.current);
59
- liveRef.current = decorators;
60
- }
61
- useEffect(() => {
62
- const prev = prevRef.current;
63
-
64
- // On prop change: the render-phase atomic swap already updated the store.
65
- // Emit a non-silent notification now that effects have settled so subscribers
66
- // re-render with the final, clean composition (old HOCs fully gone).
67
- if (prev && (prev.decorators !== decorators || prev.scope !== scope)) {
68
- store.notify();
29
+ function ComposeEffects({ store, target, decorators, scope, inherit }) {
30
+ const prevRef = useRef(null);
31
+ const liveRef = useRef(decorators);
32
+ if (liveRef.current !== decorators) {
33
+ store.register(target, decorators, scope, inherit, true, liveRef.current);
34
+ liveRef.current = decorators;
69
35
  }
70
- prevRef.current = {
71
- decorators,
72
- scope
73
- };
74
-
75
- // Cleanup on unmount.
76
- return () => {
77
- store.unregister(target, decorators, scope);
78
- };
79
- }, [store, target, decorators, scope]);
80
- return null;
36
+ useEffect(()=>{
37
+ const prev = prevRef.current;
38
+ if (prev && (prev.decorators !== decorators || prev.scope !== scope)) store.notify();
39
+ prevRef.current = {
40
+ decorators,
41
+ scope
42
+ };
43
+ return ()=>{
44
+ store.unregister(target, decorators, scope);
45
+ };
46
+ }, [
47
+ store,
48
+ target,
49
+ decorators,
50
+ scope
51
+ ]);
52
+ return null;
81
53
  }
54
+ export { Compose };
82
55
 
83
56
  //# sourceMappingURL=Compose.js.map
package/Compose.js.map CHANGED
@@ -1 +1 @@
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","liveRef","current","prev","notify","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 inherit={inherit}\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 inherit\n}: {\n store: ReturnType<typeof useCompositionStore>;\n target: any;\n decorators: Decorator<GenericComponent | GenericHook>[];\n scope: string;\n inherit: boolean;\n}) {\n const prevRef = useRef<{\n decorators: Decorator<GenericComponent | GenericHook>[];\n scope: string;\n } | null>(null);\n\n // Tracks the decorators currently live in the store as of the last render.\n // Updated synchronously during render so it always reflects the most recently\n // registered decorators, allowing the atomic swap below to remove the right ones.\n const liveRef = useRef<Decorator<GenericComponent | GenericHook>[]>(decorators);\n\n // On re-render with new decorators: atomically replace the old ones in the store\n // during render (before React commits). This ensures the store never transiently\n // holds both old and new HOCs — which would cause useSyncExternalStore subscribers\n // to render with a doubly-wrapped component and mount inner components twice.\n if (liveRef.current !== decorators) {\n store.register(target, decorators, scope, inherit, true, liveRef.current);\n liveRef.current = decorators;\n }\n\n useEffect(() => {\n const prev = prevRef.current;\n\n // On prop change: the render-phase atomic swap already updated the store.\n // Emit a non-silent notification now that effects have settled so subscribers\n // re-render with the final, clean composition (old HOCs fully gone).\n if (prev && (prev.decorators !== decorators || prev.scope !== scope)) {\n store.notify();\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,YAAa;IACpBb,OAAO,EAAEA;EAAQ,CACpB,CAAC;AAEV,CAAC;;AAED;AACA;AACA;AACA;AACA,SAASiB,cAAcA,CAAC;EACpBnB,KAAK;EACLoB,MAAM;EACNT,UAAU;EACVV,KAAK;EACLC;AAOJ,CAAC,EAAE;EACC,MAAMmB,OAAO,GAAG1B,MAAM,CAGZ,IAAI,CAAC;;EAEf;EACA;EACA;EACA,MAAM2B,OAAO,GAAG3B,MAAM,CAA8CgB,UAAU,CAAC;;EAE/E;EACA;EACA;EACA;EACA,IAAIW,OAAO,CAACC,OAAO,KAAKZ,UAAU,EAAE;IAChCX,KAAK,CAACiB,QAAQ,CAACG,MAAM,EAAET,UAAU,EAAEV,KAAK,EAAEC,OAAO,EAAE,IAAI,EAAEoB,OAAO,CAACC,OAAO,CAAC;IACzED,OAAO,CAACC,OAAO,GAAGZ,UAAU;EAChC;EAEAjB,SAAS,CAAC,MAAM;IACZ,MAAM8B,IAAI,GAAGH,OAAO,CAACE,OAAO;;IAE5B;IACA;IACA;IACA,IAAIC,IAAI,KAAKA,IAAI,CAACb,UAAU,KAAKA,UAAU,IAAIa,IAAI,CAACvB,KAAK,KAAKA,KAAK,CAAC,EAAE;MAClED,KAAK,CAACyB,MAAM,CAAC,CAAC;IAClB;IAEAJ,OAAO,CAACE,OAAO,GAAG;MAAEZ,UAAU;MAAEV;IAAM,CAAC;;IAEvC;IACA,OAAO,MAAM;MACTD,KAAK,CAAC0B,UAAU,CAACN,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":[]}
1
+ {"version":3,"file":"Compose.js","sources":["../src/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 inherit={inherit}\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 inherit\n}: {\n store: ReturnType<typeof useCompositionStore>;\n target: any;\n decorators: Decorator<GenericComponent | GenericHook>[];\n scope: string;\n inherit: boolean;\n}) {\n const prevRef = useRef<{\n decorators: Decorator<GenericComponent | GenericHook>[];\n scope: string;\n } | null>(null);\n\n // Tracks the decorators currently live in the store as of the last render.\n // Updated synchronously during render so it always reflects the most recently\n // registered decorators, allowing the atomic swap below to remove the right ones.\n const liveRef = useRef<Decorator<GenericComponent | GenericHook>[]>(decorators);\n\n // On re-render with new decorators: atomically replace the old ones in the store\n // during render (before React commits). This ensures the store never transiently\n // holds both old and new HOCs — which would cause useSyncExternalStore subscribers\n // to render with a doubly-wrapped component and mount inner components twice.\n if (liveRef.current !== decorators) {\n store.register(target, decorators, scope, inherit, true, liveRef.current);\n liveRef.current = decorators;\n }\n\n useEffect(() => {\n const prev = prevRef.current;\n\n // On prop change: the render-phase atomic swap already updated the store.\n // Emit a non-silent notification now that effects have settled so subscribers\n // re-render with the final, clean composition (old HOCs fully gone).\n if (prev && (prev.decorators !== decorators || prev.scope !== scope)) {\n store.notify();\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"],"names":["Compose","props","store","useCompositionStore","scope","inherit","useCompositionScope","targetFn","console","decorators","Array","currentScope","ComposeEffects","target","prevRef","useRef","liveRef","useEffect","prev"],"mappings":";;;AAkBO,MAAMA,UAAU,CAACC;IACpB,MAAMC,QAAQC;IACd,MAAM,EAAEC,KAAK,EAAEC,OAAO,EAAE,GAAGC;IAE3B,MAAMC,WAAYN,MAAM,QAAQ,IAAIA,MAAM,SAAS;IAEnD,IAAI,CAACM,UAAU;QACXC,QAAQ,IAAI,CAAC,+DAA+DP;QAC5E,OAAO;IACX;IAEA,IAAI,AAA6B,WAAtBM,SAAS,QAAQ,EAAkB;QAC1CC,QAAQ,IAAI,CACR,CAAC,6BAA6B,EAC1BD,SAAS,YAAY,IAAIA,SAAS,IAAI,CACzC,sDAAsD,CAAC;QAE5D,OAAO;IACX;IAEA,MAAME,aAAcC,MAAM,OAAO,CAACT,MAAM,IAAI,IAAIA,MAAM,IAAI,GAAG;QAACA,MAAM,IAAI;KAAC;IAGzE,MAAMU,eAAeP,KAAK,CAACA,MAAM,MAAM,GAAG,EAAE,IAAI;IAKhDF,MAAM,QAAQ,CAACK,SAAS,QAAQ,EAAEE,YAAYE,cAAcN,SAAS;IAErE,OAAO,WAAP,GACI,oBAACO,gBAAcA;QACX,OAAOV;QACP,QAAQK,SAAS,QAAQ;QACzB,YAAYE;QACZ,OAAOE;QACP,SAASN;;AAGrB;AAMA,SAASO,eAAe,EACpBV,KAAK,EACLW,MAAM,EACNJ,UAAU,EACVL,KAAK,EACLC,OAAO,EAOV;IACG,MAAMS,UAAUC,OAGN;IAKV,MAAMC,UAAUD,OAAoDN;IAMpE,IAAIO,QAAQ,OAAO,KAAKP,YAAY;QAChCP,MAAM,QAAQ,CAACW,QAAQJ,YAAYL,OAAOC,SAAS,MAAMW,QAAQ,OAAO;QACxEA,QAAQ,OAAO,GAAGP;IACtB;IAEAQ,UAAU;QACN,MAAMC,OAAOJ,QAAQ,OAAO;QAK5B,IAAII,QAASA,CAAAA,KAAK,UAAU,KAAKT,cAAcS,KAAK,KAAK,KAAKd,KAAI,GAC9DF,MAAM,MAAM;QAGhBY,QAAQ,OAAO,GAAG;YAAEL;YAAYL;QAAM;QAGtC,OAAO;YACHF,MAAM,UAAU,CAACW,QAAQJ,YAAYL;QACzC;IACJ,GAAG;QAACF;QAAOW;QAAQJ;QAAYL;KAAM;IAErC,OAAO;AACX"}
@@ -1,27 +1,25 @@
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);
1
+ import react from "react";
2
+ const CompositionScopeContext = /*#__PURE__*/ react.createContext(void 0);
3
+ const CompositionScope = ({ name, inherit = false, children })=>{
4
+ const parentScope = useCompositionScope();
5
+ return /*#__PURE__*/ react.createElement(CompositionScopeContext.Provider, {
6
+ value: {
7
+ scope: [
8
+ ...parentScope.scope,
9
+ name
10
+ ],
11
+ inherit
12
+ }
13
+ }, children);
15
14
  };
16
- export function useCompositionScope() {
17
- const context = React.useContext(CompositionScopeContext);
18
- if (!context) {
19
- return {
20
- scope: [],
21
- inherit: false
15
+ function useCompositionScope() {
16
+ const context = react.useContext(CompositionScopeContext);
17
+ if (!context) return {
18
+ scope: [],
19
+ inherit: false
22
20
  };
23
- }
24
- return context;
21
+ return context;
25
22
  }
23
+ export { CompositionScope, useCompositionScope };
26
24
 
27
25
  //# sourceMappingURL=CompositionScope.js.map
@@ -1 +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":[]}
1
+ {"version":3,"file":"CompositionScope.js","sources":["../src/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"],"names":["CompositionScopeContext","React","undefined","CompositionScope","name","inherit","children","parentScope","useCompositionScope","context"],"mappings":";AAOA,MAAMA,0BAA0B,WAAHA,GAAGC,MAAAA,aAAmB,CAAsCC;AAYlF,MAAMC,mBAAmB,CAAC,EAAEC,IAAI,EAAEC,UAAU,KAAK,EAAEC,QAAQ,EAAyB;IACvF,MAAMC,cAAcC;IAEpB,OAAO,WAAP,GACI,oBAACR,wBAAwB,QAAQ;QAAC,OAAO;YAAE,OAAO;mBAAIO,YAAY,KAAK;gBAAEH;aAAK;YAAEC;QAAQ;OACnFC;AAGb;AAEO,SAASE;IACZ,MAAMC,UAAUR,MAAAA,UAAgB,CAACD;IAEjC,IAAI,CAACS,SACD,OAAO;QAAE,OAAO,EAAE;QAAE,SAAS;IAAM;IAGvC,OAAOA;AACX"}
package/Context.js CHANGED
@@ -1,92 +1,54 @@
1
- import React, { createContext, useContext, useRef, useSyncExternalStore } from "react";
1
+ import react, { createContext, useContext, useRef, useSyncExternalStore } from "react";
2
2
  import { useCompositionScope } from "./CompositionScope.js";
3
3
  import { CompositionStore } from "./domain/CompositionStore.js";
4
- export function compose(...fns) {
5
- return decoratee => {
6
- return fns.reduceRight((decoratee, decorator) => decorator(decoratee), decoratee);
7
- };
4
+ function compose(...fns) {
5
+ return (decoratee)=>fns.reduceRight((decoratee, decorator)=>decorator(decoratee), decoratee);
8
6
  }
9
-
10
- /**
11
- * @deprecated Use `Decorator` instead.
12
- */
13
-
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);
7
+ const CompositionStoreContext = /*#__PURE__*/ createContext(void 0);
8
+ const CompositionProvider = ({ decorators = [], children })=>{
9
+ const storeRef = useRef(null);
10
+ if (null === storeRef.current) {
11
+ const store = new CompositionStore();
12
+ for (const [decoratable, hocs] of decorators)store.register(decoratable.original, hocs);
13
+ storeRef.current = store;
25
14
  }
26
- storeRef.current = store;
27
- }
28
- return /*#__PURE__*/React.createElement(CompositionStoreContext.Provider, {
29
- value: storeRef.current
30
- }, children);
15
+ return /*#__PURE__*/ react.createElement(CompositionStoreContext.Provider, {
16
+ value: storeRef.current
17
+ }, children);
31
18
  };
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!`);
36
- }
37
- return store;
19
+ function useCompositionStore() {
20
+ const store = useContext(CompositionStoreContext);
21
+ if (!store) throw new Error("You're missing a <CompositionProvider> higher up in your component hierarchy!");
22
+ return store;
38
23
  }
39
- export function useOptionalCompositionStore() {
40
- return useContext(CompositionStoreContext);
24
+ function useOptionalCompositionStore() {
25
+ return useContext(CompositionStoreContext);
41
26
  }
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
- const result = store.getComponent(baseFunction, scope.scope) || baseFunction;
52
- return result;
27
+ function useComponent(baseFunction) {
28
+ const store = useOptionalCompositionStore();
29
+ const scope = useCompositionScope();
30
+ useSyncExternalStore(store ? store.subscribe : noopSubscribe, store ? store.getSnapshot : noopGetSnapshot);
31
+ if (!store) return baseFunction;
32
+ const result = store.getComponent(baseFunction, scope.scope) || baseFunction;
33
+ return result;
53
34
  }
54
- const noopSubscribe = () => () => {};
55
- const noopGetSnapshot = () => 0;
56
-
57
- // Legacy compatibility — kept for any external consumers.
58
-
59
- /**
60
- * This hook will throw an error if composition context doesn't exist.
61
- */
62
- export function useComposition() {
63
- const store = useCompositionStore();
64
- return {
65
- composeComponent: (component, hocs, scope = "*", inherit = false) => {
66
- return store.register(component, hocs, scope, inherit);
67
- },
68
- getComponent: (component, scope) => {
69
- return store.getComponent(component, scope);
70
- }
71
- };
35
+ const noopSubscribe = ()=>()=>{};
36
+ const noopGetSnapshot = ()=>0;
37
+ function useComposition() {
38
+ const store = useCompositionStore();
39
+ return {
40
+ composeComponent: (component, hocs, scope = "*", inherit = false)=>store.register(component, hocs, scope, inherit),
41
+ getComponent: (component, scope)=>store.getComponent(component, scope)
42
+ };
72
43
  }
73
-
74
- /**
75
- * This hook will not throw an error if composition context doesn't exist.
76
- */
77
- export function useOptionalComposition() {
78
- const store = useOptionalCompositionStore();
79
- if (!store) {
80
- return undefined;
81
- }
82
- return {
83
- composeComponent: (component, hocs, scope = "*", inherit = false) => {
84
- return store.register(component, hocs, scope, inherit);
85
- },
86
- getComponent: (component, scope) => {
87
- return store.getComponent(component, scope);
88
- }
89
- };
44
+ function useOptionalComposition() {
45
+ const store = useOptionalCompositionStore();
46
+ if (!store) return;
47
+ return {
48
+ composeComponent: (component, hocs, scope = "*", inherit = false)=>store.register(component, hocs, scope, inherit),
49
+ getComponent: (component, scope)=>store.getComponent(component, scope)
50
+ };
90
51
  }
52
+ export { CompositionProvider, compose, useComponent, useComposition, useCompositionStore, useOptionalComposition, useOptionalCompositionStore };
91
53
 
92
54
  //# sourceMappingURL=Context.js.map
package/Context.js.map CHANGED
@@ -1 +1 @@
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","result","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\";\n\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 const result = store.getComponent(baseFunction as any, scope.scope) || baseFunction;\n\n return result 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":[]}
1
+ {"version":3,"file":"Context.js","sources":["../src/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\";\n\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 const result = store.getComponent(baseFunction as any, scope.scope) || baseFunction;\n\n return result 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"],"names":["compose","fns","decoratee","decorator","CompositionStoreContext","createContext","undefined","CompositionProvider","decorators","children","storeRef","useRef","store","CompositionStore","decoratable","hocs","useCompositionStore","useContext","Error","useOptionalCompositionStore","useComponent","baseFunction","scope","useCompositionScope","useSyncExternalStore","noopSubscribe","noopGetSnapshot","result","useComposition","component","inherit","useOptionalComposition"],"mappings":";;;AAgBO,SAASA,QAAW,GAAGC,GAAmB;IAC7C,OAAO,CAACC,YACGD,IAAI,WAAW,CAAC,CAACC,WAAWC,YAAcA,UAAUD,YAAYA;AAE/E;AAWA,MAAME,0BAA0B,WAAHA,GAAGC,cAA4CC;AAUrE,MAAMC,sBAAsB,CAAC,EAAEC,aAAa,EAAE,EAAEC,QAAQ,EAA4B;IACvF,MAAMC,WAAWC,OAAgC;IACjD,IAAID,AAAqB,SAArBA,SAAS,OAAO,EAAW;QAC3B,MAAME,QAAQ,IAAIC;QAElB,KAAK,MAAM,CAACC,aAAaC,KAAK,IAAIP,WAC9BI,MAAM,QAAQ,CAACE,YAAY,QAAQ,EAA4BC;QAEnEL,SAAS,OAAO,GAAGE;IACvB;IAEA,OAAO,WAAP,GACI,oBAACR,wBAAwB,QAAQ;QAAC,OAAOM,SAAS,OAAO;OACpDD;AAGb;AAEO,SAASO;IACZ,MAAMJ,QAAQK,WAAWb;IACzB,IAAI,CAACQ,OACD,MAAM,IAAIM,MACN;IAGR,OAAON;AACX;AAEO,SAASO;IACZ,OAAOF,WAAWb;AACtB;AAEO,SAASgB,aAAgBC,YAAe;IAC3C,MAAMT,QAAQO;IACd,MAAMG,QAAQC;IAGdC,qBACIZ,QAAQA,MAAM,SAAS,GAAGa,eAC1Bb,QAAQA,MAAM,WAAW,GAAGc;IAGhC,IAAI,CAACd,OACD,OAAOS;IAGX,MAAMM,SAASf,MAAM,YAAY,CAACS,cAAqBC,MAAM,KAAK,KAAKD;IAEvE,OAAOM;AACX;AAEA,MAAMF,gBAAgB,IAAM,KAAO;AACnC,MAAMC,kBAAkB,IAAM;AAoBvB,SAASE;IACZ,MAAMhB,QAAQI;IAEd,OAAO;QACH,kBAAkB,CAACa,WAAWd,MAAMO,QAAQ,GAAG,EAAEQ,UAAU,KAAK,GACrDlB,MAAM,QAAQ,CAACiB,WAAWd,MAAeO,OAAOQ;QAE3D,cAAc,CAACD,WAAWP,QACfV,MAAM,YAAY,CAACiB,WAAWP;IAE7C;AACJ;AAKO,SAASS;IACZ,MAAMnB,QAAQO;IACd,IAAI,CAACP,OACD;IAGJ,OAAO;QACH,kBAAkB,CAACiB,WAAWd,MAAMO,QAAQ,GAAG,EAAEQ,UAAU,KAAK,GACrDlB,MAAM,QAAQ,CAACiB,WAAWd,MAAeO,OAAOQ;QAE3D,cAAc,CAACD,WAAWP,QACfV,MAAM,YAAY,CAACiB,WAAWP;IAE7C;AACJ"}
@@ -1,29 +1,17 @@
1
- import React from "react";
1
+ import react from "react";
2
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);
3
+ function createComponentPlugin(Base, hoc) {
4
+ return createDecorator(Base, hoc);
10
5
  }
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;
6
+ const isDecoratableComponent = (decoratable)=>"displayName" in decoratable;
7
+ function createDecorator(Base, hoc) {
8
+ const DecoratorPlugin = ()=>/*#__PURE__*/ react.createElement(Compose, {
9
+ component: Base,
10
+ with: hoc
11
+ });
12
+ if (isDecoratableComponent(Base)) DecoratorPlugin.displayName = Base.displayName;
13
+ return DecoratorPlugin;
27
14
  }
15
+ export { createComponentPlugin, createDecorator };
28
16
 
29
17
  //# sourceMappingURL=createDecorator.js.map
@@ -1 +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":[]}
1
+ {"version":3,"file":"createDecorator.js","sources":["../src/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"],"names":["createComponentPlugin","Base","hoc","createDecorator","isDecoratableComponent","decoratable","DecoratorPlugin","Compose"],"mappings":";;AAiBO,SAASA,sBACZC,IAAO,EACPC,GAEmC;IAEnC,OAAOC,gBAAgBF,MAAMC;AACjC;AAaA,MAAME,yBAAyB,CAC3BC,cAEO,iBAAiBA;AAGrB,SAASF,gBACZF,IAAO,EACPC,GAEmC;IAEnC,MAAMI,kBAAkB,kBAAM,oBAACC,SAAOA;YAAC,WAAWN;YAAM,MAAMC;;IAC9D,IAAIE,uBAAuBH,OACvBK,gBAAgB,WAAW,GAAGL,KAAK,WAAW;IAElD,OAAOK;AACX"}
package/decorators.js CHANGED
@@ -1,71 +1,63 @@
1
- import React from "react";
1
+ import react from "react";
2
2
  import { Compose } from "./Compose.js";
3
- export function createConditionalDecorator(shouldDecorate, decorator, decoratorProps) {
4
- return Original => {
5
- const DecoratedComponent = /*#__PURE__*/React.memo(decorator(Original));
6
- DecoratedComponent.displayName = Original.displayName;
7
- return function ShouldDecorate(props) {
8
- if (shouldDecorate(decoratorProps, props)) {
9
- // @ts-expect-error
10
- return /*#__PURE__*/React.createElement(DecoratedComponent, props);
11
- }
12
-
13
- // @ts-expect-error
14
- return /*#__PURE__*/React.createElement(Original, props);
3
+ function createConditionalDecorator(shouldDecorate, decorator, decoratorProps) {
4
+ return (Original)=>{
5
+ const DecoratedComponent = /*#__PURE__*/ react.memo(decorator(Original));
6
+ DecoratedComponent.displayName = Original.displayName;
7
+ return function(props) {
8
+ if (shouldDecorate(decoratorProps, props)) return /*#__PURE__*/ react.createElement(DecoratedComponent, props);
9
+ return /*#__PURE__*/ react.createElement(Original, props);
10
+ };
15
11
  };
16
- };
17
12
  }
18
- const memoizedComponent = decorator => {
19
- return decoratee => {
20
- return /*#__PURE__*/React.memo(decorator(decoratee));
21
- };
22
- };
23
- export function createDecoratorFactory() {
24
- return function from(decoratable, shouldDecorate) {
25
- return function createDecorator(decorator) {
26
- return function DecoratorPlugin(props) {
27
- if (shouldDecorate) {
28
- const componentDecorator = createConditionalDecorator(shouldDecorate, decorator, props);
29
- return /*#__PURE__*/React.createElement(Compose, {
30
- function: decoratable,
31
- with: componentDecorator
32
- });
33
- }
34
- return /*#__PURE__*/React.createElement(Compose, {
35
- function: decoratable,
36
- with: memoizedComponent(decorator)
37
- });
38
- };
13
+ const memoizedComponent = (decorator)=>(decoratee)=>/*#__PURE__*/ react.memo(decorator(decoratee));
14
+ function createDecoratorFactory() {
15
+ return function(decoratable, shouldDecorate) {
16
+ return function(decorator) {
17
+ return function(props) {
18
+ if (shouldDecorate) {
19
+ const componentDecorator = createConditionalDecorator(shouldDecorate, decorator, props);
20
+ return /*#__PURE__*/ react.createElement(Compose, {
21
+ function: decoratable,
22
+ with: componentDecorator
23
+ });
24
+ }
25
+ return /*#__PURE__*/ react.createElement(Compose, {
26
+ function: decoratable,
27
+ with: memoizedComponent(decorator)
28
+ });
29
+ };
30
+ };
39
31
  };
40
- };
41
32
  }
42
- export function createHookDecoratorFactory() {
43
- return function from(decoratable) {
44
- return function createDecorator(decorator) {
45
- return function DecoratorPlugin() {
46
- return /*#__PURE__*/React.createElement(Compose, {
47
- function: decoratable,
48
- with: decorator
49
- });
50
- };
33
+ function createHookDecoratorFactory() {
34
+ return function(decoratable) {
35
+ return function(decorator) {
36
+ return function() {
37
+ return /*#__PURE__*/ react.createElement(Compose, {
38
+ function: decoratable,
39
+ with: decorator
40
+ });
41
+ };
42
+ };
51
43
  };
52
- };
53
44
  }
54
- export function withDecoratorFactory() {
55
- return function WithDecorator(Component, shouldDecorate) {
56
- const createDecorator = createDecoratorFactory()(Component, shouldDecorate);
57
- return Object.assign(Component, {
58
- createDecorator
59
- });
60
- };
45
+ function withDecoratorFactory() {
46
+ return function(Component, shouldDecorate) {
47
+ const createDecorator = createDecoratorFactory()(Component, shouldDecorate);
48
+ return Object.assign(Component, {
49
+ createDecorator
50
+ });
51
+ };
61
52
  }
62
- export function withHookDecoratorFactory() {
63
- return function WithHookDecorator(hook) {
64
- const createDecorator = createHookDecoratorFactory()(hook);
65
- return Object.assign(hook, {
66
- createDecorator
67
- });
68
- };
53
+ function withHookDecoratorFactory() {
54
+ return function(hook) {
55
+ const createDecorator = createHookDecoratorFactory()(hook);
56
+ return Object.assign(hook, {
57
+ createDecorator
58
+ });
59
+ };
69
60
  }
61
+ export { createConditionalDecorator, createDecoratorFactory, createHookDecoratorFactory, withDecoratorFactory, withHookDecoratorFactory };
70
62
 
71
63
  //# sourceMappingURL=decorators.js.map
package/decorators.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"names":["React","Compose","createConditionalDecorator","shouldDecorate","decorator","decoratorProps","Original","DecoratedComponent","memo","displayName","ShouldDecorate","props","createElement","memoizedComponent","decoratee","createDecoratorFactory","from","decoratable","createDecorator","DecoratorPlugin","componentDecorator","function","with","createHookDecoratorFactory","withDecoratorFactory","WithDecorator","Component","Object","assign","withHookDecoratorFactory","WithHookDecorator","hook"],"sources":["decorators.tsx"],"sourcesContent":["import React from \"react\";\nimport { Compose } from \"~/Compose.js\";\nimport type { GetDecoratee, GetDecorateeParams } from \"~/createDecorator.js\";\nimport type {\n DecoratableComponent,\n GenericComponent,\n Decorator,\n GenericHook,\n DecoratableHook,\n ComponentDecorator\n} from \"~/types.js\";\n\nexport interface ShouldDecorate<TDecorator = any, TComponent = any> {\n (decoratorProps: TDecorator, componentProps: TComponent): boolean;\n}\n\nexport function createConditionalDecorator<TDecoratee extends GenericComponent>(\n shouldDecorate: ShouldDecorate,\n decorator: Decorator<TDecoratee>,\n decoratorProps: unknown\n): Decorator<TDecoratee> {\n return (Original => {\n const DecoratedComponent = React.memo(decorator(Original));\n DecoratedComponent.displayName = Original.displayName;\n\n return function ShouldDecorate(props: unknown) {\n if (shouldDecorate(decoratorProps, props)) {\n // @ts-expect-error\n return <DecoratedComponent {...props} />;\n }\n\n // @ts-expect-error\n return <Original {...props} />;\n };\n }) as Decorator<TDecoratee>;\n}\n\nconst memoizedComponent = <T extends GenericComponent>(decorator: Decorator<T>) => {\n return (decoratee: T) => {\n return React.memo(decorator(decoratee));\n };\n};\n\nexport function createDecoratorFactory<TDecorator>() {\n return function from<TDecoratable extends DecoratableComponent>(\n decoratable: TDecoratable,\n shouldDecorate?: ShouldDecorate<TDecorator, GetDecorateeParams<GetDecoratee<TDecoratable>>>\n ) {\n return function createDecorator(decorator: ComponentDecorator<GetDecoratee<TDecoratable>>) {\n return function DecoratorPlugin(props: TDecorator) {\n if (shouldDecorate) {\n const componentDecorator = createConditionalDecorator<GenericComponent>(\n shouldDecorate,\n decorator as unknown as Decorator<GenericComponent>,\n props\n );\n\n return <Compose function={decoratable} with={componentDecorator} />;\n }\n\n return (\n <Compose\n function={decoratable}\n with={memoizedComponent(\n decorator as unknown as Decorator<GenericComponent>\n )}\n />\n );\n };\n };\n };\n}\n\nexport function createHookDecoratorFactory() {\n return function from<TDecoratable extends DecoratableHook>(decoratable: TDecoratable) {\n return function createDecorator(decorator: Decorator<GetDecoratee<TDecoratable>>) {\n return function DecoratorPlugin() {\n return (\n <Compose\n function={decoratable}\n with={decorator as unknown as Decorator<GenericHook>}\n />\n );\n };\n };\n };\n}\n\nexport function withDecoratorFactory<TDecorator>() {\n return function WithDecorator<TDecoratable extends DecoratableComponent>(\n Component: TDecoratable,\n shouldDecorate?: ShouldDecorate<TDecorator, GetDecorateeParams<GetDecoratee<TDecoratable>>>\n ) {\n const createDecorator = createDecoratorFactory<TDecorator>()(Component, shouldDecorate);\n\n return Object.assign(Component, { createDecorator }) as TDecoratable & {\n createDecorator: typeof createDecorator;\n };\n };\n}\n\nexport function withHookDecoratorFactory() {\n return function WithHookDecorator<TDecoratable extends DecoratableHook>(hook: TDecoratable) {\n const createDecorator = createHookDecoratorFactory()(hook);\n\n return Object.assign(hook, { createDecorator }) as unknown as DecoratableHook<\n GenericHook<\n GetDecorateeParams<GetDecoratee<TDecoratable>>,\n ReturnType<GetDecoratee<TDecoratable>>\n >\n > & { createDecorator: typeof createDecorator };\n };\n}\n"],"mappings":"AAAA,OAAOA,KAAK,MAAM,OAAO;AACzB,SAASC,OAAO;AAehB,OAAO,SAASC,0BAA0BA,CACtCC,cAA8B,EAC9BC,SAAgC,EAChCC,cAAuB,EACF;EACrB,OAAQC,QAAQ,IAAI;IAChB,MAAMC,kBAAkB,gBAAGP,KAAK,CAACQ,IAAI,CAACJ,SAAS,CAACE,QAAQ,CAAC,CAAC;IAC1DC,kBAAkB,CAACE,WAAW,GAAGH,QAAQ,CAACG,WAAW;IAErD,OAAO,SAASC,cAAcA,CAACC,KAAc,EAAE;MAC3C,IAAIR,cAAc,CAACE,cAAc,EAAEM,KAAK,CAAC,EAAE;QACvC;QACA,oBAAOX,KAAA,CAAAY,aAAA,CAACL,kBAAkB,EAAKI,KAAQ,CAAC;MAC5C;;MAEA;MACA,oBAAOX,KAAA,CAAAY,aAAA,CAACN,QAAQ,EAAKK,KAAQ,CAAC;IAClC,CAAC;EACL,CAAC;AACL;AAEA,MAAME,iBAAiB,GAAgCT,SAAuB,IAAK;EAC/E,OAAQU,SAAY,IAAK;IACrB,oBAAOd,KAAK,CAACQ,IAAI,CAACJ,SAAS,CAACU,SAAS,CAAC,CAAC;EAC3C,CAAC;AACL,CAAC;AAED,OAAO,SAASC,sBAAsBA,CAAA,EAAe;EACjD,OAAO,SAASC,IAAIA,CAChBC,WAAyB,EACzBd,cAA2F,EAC7F;IACE,OAAO,SAASe,eAAeA,CAACd,SAAyD,EAAE;MACvF,OAAO,SAASe,eAAeA,CAACR,KAAiB,EAAE;QAC/C,IAAIR,cAAc,EAAE;UAChB,MAAMiB,kBAAkB,GAAGlB,0BAA0B,CACjDC,cAAc,EACdC,SAAS,EACTO,KACJ,CAAC;UAED,oBAAOX,KAAA,CAAAY,aAAA,CAACX,OAAO;YAACoB,QAAQ,EAAEJ,WAAY;YAACK,IAAI,EAAEF;UAAmB,CAAE,CAAC;QACvE;QAEA,oBACIpB,KAAA,CAAAY,aAAA,CAACX,OAAO;UACJoB,QAAQ,EAAEJ,WAAY;UACtBK,IAAI,EAAET,iBAAiB,CACnBT,SACJ;QAAE,CACL,CAAC;MAEV,CAAC;IACL,CAAC;EACL,CAAC;AACL;AAEA,OAAO,SAASmB,0BAA0BA,CAAA,EAAG;EACzC,OAAO,SAASP,IAAIA,CAAuCC,WAAyB,EAAE;IAClF,OAAO,SAASC,eAAeA,CAACd,SAAgD,EAAE;MAC9E,OAAO,SAASe,eAAeA,CAAA,EAAG;QAC9B,oBACInB,KAAA,CAAAY,aAAA,CAACX,OAAO;UACJoB,QAAQ,EAAEJ,WAAY;UACtBK,IAAI,EAAElB;QAA+C,CACxD,CAAC;MAEV,CAAC;IACL,CAAC;EACL,CAAC;AACL;AAEA,OAAO,SAASoB,oBAAoBA,CAAA,EAAe;EAC/C,OAAO,SAASC,aAAaA,CACzBC,SAAuB,EACvBvB,cAA2F,EAC7F;IACE,MAAMe,eAAe,GAAGH,sBAAsB,CAAa,CAAC,CAACW,SAAS,EAAEvB,cAAc,CAAC;IAEvF,OAAOwB,MAAM,CAACC,MAAM,CAACF,SAAS,EAAE;MAAER;IAAgB,CAAC,CAAC;EAGxD,CAAC;AACL;AAEA,OAAO,SAASW,wBAAwBA,CAAA,EAAG;EACvC,OAAO,SAASC,iBAAiBA,CAAuCC,IAAkB,EAAE;IACxF,MAAMb,eAAe,GAAGK,0BAA0B,CAAC,CAAC,CAACQ,IAAI,CAAC;IAE1D,OAAOJ,MAAM,CAACC,MAAM,CAACG,IAAI,EAAE;MAAEb;IAAgB,CAAC,CAAC;EAMnD,CAAC;AACL","ignoreList":[]}
1
+ {"version":3,"file":"decorators.js","sources":["../src/decorators.tsx"],"sourcesContent":["import React from \"react\";\nimport { Compose } from \"~/Compose.js\";\nimport type { GetDecoratee, GetDecorateeParams } from \"~/createDecorator.js\";\nimport type {\n DecoratableComponent,\n GenericComponent,\n Decorator,\n GenericHook,\n DecoratableHook,\n ComponentDecorator\n} from \"~/types.js\";\n\nexport interface ShouldDecorate<TDecorator = any, TComponent = any> {\n (decoratorProps: TDecorator, componentProps: TComponent): boolean;\n}\n\nexport function createConditionalDecorator<TDecoratee extends GenericComponent>(\n shouldDecorate: ShouldDecorate,\n decorator: Decorator<TDecoratee>,\n decoratorProps: unknown\n): Decorator<TDecoratee> {\n return (Original => {\n const DecoratedComponent = React.memo(decorator(Original));\n DecoratedComponent.displayName = Original.displayName;\n\n return function ShouldDecorate(props: unknown) {\n if (shouldDecorate(decoratorProps, props)) {\n // @ts-expect-error\n return <DecoratedComponent {...props} />;\n }\n\n // @ts-expect-error\n return <Original {...props} />;\n };\n }) as Decorator<TDecoratee>;\n}\n\nconst memoizedComponent = <T extends GenericComponent>(decorator: Decorator<T>) => {\n return (decoratee: T) => {\n return React.memo(decorator(decoratee));\n };\n};\n\nexport function createDecoratorFactory<TDecorator>() {\n return function from<TDecoratable extends DecoratableComponent>(\n decoratable: TDecoratable,\n shouldDecorate?: ShouldDecorate<TDecorator, GetDecorateeParams<GetDecoratee<TDecoratable>>>\n ) {\n return function createDecorator(decorator: ComponentDecorator<GetDecoratee<TDecoratable>>) {\n return function DecoratorPlugin(props: TDecorator) {\n if (shouldDecorate) {\n const componentDecorator = createConditionalDecorator<GenericComponent>(\n shouldDecorate,\n decorator as unknown as Decorator<GenericComponent>,\n props\n );\n\n return <Compose function={decoratable} with={componentDecorator} />;\n }\n\n return (\n <Compose\n function={decoratable}\n with={memoizedComponent(\n decorator as unknown as Decorator<GenericComponent>\n )}\n />\n );\n };\n };\n };\n}\n\nexport function createHookDecoratorFactory() {\n return function from<TDecoratable extends DecoratableHook>(decoratable: TDecoratable) {\n return function createDecorator(decorator: Decorator<GetDecoratee<TDecoratable>>) {\n return function DecoratorPlugin() {\n return (\n <Compose\n function={decoratable}\n with={decorator as unknown as Decorator<GenericHook>}\n />\n );\n };\n };\n };\n}\n\nexport function withDecoratorFactory<TDecorator>() {\n return function WithDecorator<TDecoratable extends DecoratableComponent>(\n Component: TDecoratable,\n shouldDecorate?: ShouldDecorate<TDecorator, GetDecorateeParams<GetDecoratee<TDecoratable>>>\n ) {\n const createDecorator = createDecoratorFactory<TDecorator>()(Component, shouldDecorate);\n\n return Object.assign(Component, { createDecorator }) as TDecoratable & {\n createDecorator: typeof createDecorator;\n };\n };\n}\n\nexport function withHookDecoratorFactory() {\n return function WithHookDecorator<TDecoratable extends DecoratableHook>(hook: TDecoratable) {\n const createDecorator = createHookDecoratorFactory()(hook);\n\n return Object.assign(hook, { createDecorator }) as unknown as DecoratableHook<\n GenericHook<\n GetDecorateeParams<GetDecoratee<TDecoratable>>,\n ReturnType<GetDecoratee<TDecoratable>>\n >\n > & { createDecorator: typeof createDecorator };\n };\n}\n"],"names":["createConditionalDecorator","shouldDecorate","decorator","decoratorProps","Original","DecoratedComponent","React","props","memoizedComponent","decoratee","createDecoratorFactory","decoratable","componentDecorator","Compose","createHookDecoratorFactory","withDecoratorFactory","Component","createDecorator","Object","withHookDecoratorFactory","hook"],"mappings":";;AAgBO,SAASA,2BACZC,cAA8B,EAC9BC,SAAgC,EAChCC,cAAuB;IAEvB,OAAQC,CAAAA;QACJ,MAAMC,qBAAqB,WAArBA,GAAqBC,MAAAA,IAAU,CAACJ,UAAUE;QAChDC,mBAAmB,WAAW,GAAGD,SAAS,WAAW;QAErD,OAAO,SAAwBG,KAAc;YACzC,IAAIN,eAAeE,gBAAgBI,QAE/B,OAAO,WAAP,GAAO,oBAACF,oBAAuBE;YAInC,OAAO,WAAP,GAAO,oBAACH,UAAaG;QACzB;IACJ;AACJ;AAEA,MAAMC,oBAAoB,CAA6BN,YAC5C,CAACO,YACG,WAAP,GAAOH,MAAAA,IAAU,CAACJ,UAAUO;AAI7B,SAASC;IACZ,OAAO,SACHC,WAAyB,EACzBV,cAA2F;QAE3F,OAAO,SAAyBC,SAAyD;YACrF,OAAO,SAAyBK,KAAiB;gBAC7C,IAAIN,gBAAgB;oBAChB,MAAMW,qBAAqBZ,2BACvBC,gBACAC,WACAK;oBAGJ,OAAO,WAAP,GAAO,oBAACM,SAAOA;wBAAC,UAAUF;wBAAa,MAAMC;;gBACjD;gBAEA,OAAO,WAAP,GACI,oBAACC,SAAOA;oBACJ,UAAUF;oBACV,MAAMH,kBACFN;;YAIhB;QACJ;IACJ;AACJ;AAEO,SAASY;IACZ,OAAO,SAAoDH,WAAyB;QAChF,OAAO,SAAyBT,SAAgD;YAC5E,OAAO;gBACH,OAAO,WAAP,GACI,oBAACW,SAAOA;oBACJ,UAAUF;oBACV,MAAMT;;YAGlB;QACJ;IACJ;AACJ;AAEO,SAASa;IACZ,OAAO,SACHC,SAAuB,EACvBf,cAA2F;QAE3F,MAAMgB,kBAAkBP,yBAAqCM,WAAWf;QAExE,OAAOiB,OAAO,MAAM,CAACF,WAAW;YAAEC;QAAgB;IAGtD;AACJ;AAEO,SAASE;IACZ,OAAO,SAAiEC,IAAkB;QACtF,MAAMH,kBAAkBH,6BAA6BM;QAErD,OAAOF,OAAO,MAAM,CAACE,MAAM;YAAEH;QAAgB;IAMjD;AACJ"}
@@ -1,117 +1,89 @@
1
1
  import { compose } from "../Context.js";
2
- export class CompositionStore {
3
- scopes = new Map();
4
- version = 0;
5
- listeners = new Set();
6
- register(component, hocs, scope = "*", inherit = false, silent = false, replaces = []) {
7
- const scopeMap = this.scopes.get(scope) || new Map();
8
- const recipe = scopeMap.get(component) || {
9
- component: component,
10
- hocs: []
11
- };
12
-
13
- // Idempotent: skip if all HOCs are already registered (handles StrictMode double-render).
14
- const newHocs = hocs.filter(hoc => !recipe.hocs.includes(hoc));
15
- if (newHocs.length === 0 && replaces.length === 0) {
16
- return () => this.unregister(component, hocs, scope);
17
- }
18
-
19
- // Atomically remove the HOCs being replaced so the store never transiently
20
- // holds both the old and new decorators at the same time. This prevents
21
- // useSyncExternalStore subscribers from seeing a doubly-wrapped component
22
- // in the window between a render-phase registration and its effect cleanup.
23
- const existingHocs = replaces.length ? recipe.hocs.filter(hoc => !replaces.includes(hoc)) : [...recipe.hocs];
24
- if (inherit && scope !== "*") {
25
- const globalScope = this.scopes.get("*") || new Map();
26
- const globalRecipe = globalScope.get(component) || {
27
- component: component,
28
- hocs: []
29
- };
30
- // Only prepend global HOCs that aren't already present.
31
- const globalHocsToAdd = globalRecipe.hocs.filter(hoc => !existingHocs.includes(hoc));
32
- existingHocs.unshift(...globalHocsToAdd);
33
- }
34
- const finalHocs = [...existingHocs, ...newHocs];
35
- scopeMap.set(component, {
36
- component: compose(...[...finalHocs].reverse())(component),
37
- hocs: finalHocs
38
- });
39
- this.scopes.set(scope, scopeMap);
40
-
41
- // Bump the version so useSyncExternalStore sees a new snapshot.
42
- this.version++;
43
-
44
- // When called during render (silent=true), don't notify listeners —
45
- // that would trigger setState in other components mid-render.
46
- // Components that render after this point will see the updated snapshot.
47
- if (!silent) {
48
- this.notifyListeners();
2
+ class CompositionStore {
3
+ register(component, hocs, scope = "*", inherit = false, silent = false, replaces = []) {
4
+ const scopeMap = this.scopes.get(scope) || new Map();
5
+ const recipe = scopeMap.get(component) || {
6
+ component: component,
7
+ hocs: []
8
+ };
9
+ const newHocs = hocs.filter((hoc)=>!recipe.hocs.includes(hoc));
10
+ if (0 === newHocs.length && 0 === replaces.length) return ()=>this.unregister(component, hocs, scope);
11
+ const existingHocs = replaces.length ? recipe.hocs.filter((hoc)=>!replaces.includes(hoc)) : [
12
+ ...recipe.hocs
13
+ ];
14
+ if (inherit && "*" !== scope) {
15
+ const globalScope = this.scopes.get("*") || new Map();
16
+ const globalRecipe = globalScope.get(component) || {
17
+ component: component,
18
+ hocs: []
19
+ };
20
+ const globalHocsToAdd = globalRecipe.hocs.filter((hoc)=>!existingHocs.includes(hoc));
21
+ existingHocs.unshift(...globalHocsToAdd);
22
+ }
23
+ const finalHocs = [
24
+ ...existingHocs,
25
+ ...newHocs
26
+ ];
27
+ scopeMap.set(component, {
28
+ component: compose(...[
29
+ ...finalHocs
30
+ ].reverse())(component),
31
+ hocs: finalHocs
32
+ });
33
+ this.scopes.set(scope, scopeMap);
34
+ this.version++;
35
+ if (!silent) this.notifyListeners();
36
+ return ()=>this.unregister(component, hocs, scope);
49
37
  }
50
- return () => this.unregister(component, hocs, scope);
51
- }
52
- unregister(component, hocs, scope = "*") {
53
- const scopeMap = this.scopes.get(scope);
54
- if (!scopeMap) {
55
- return;
38
+ unregister(component, hocs, scope = "*") {
39
+ const scopeMap = this.scopes.get(scope);
40
+ if (!scopeMap) return;
41
+ const recipe = scopeMap.get(component);
42
+ if (!recipe) return;
43
+ const newHocs = recipe.hocs.filter((hoc)=>!hocs.includes(hoc));
44
+ if (newHocs.length === recipe.hocs.length) return;
45
+ if (0 === newHocs.length) scopeMap.delete(component);
46
+ else scopeMap.set(component, {
47
+ component: compose(...[
48
+ ...newHocs
49
+ ].reverse())(component),
50
+ hocs: newHocs
51
+ });
52
+ this.version++;
53
+ this.notifyListeners();
56
54
  }
57
- const recipe = scopeMap.get(component);
58
- if (!recipe) {
59
- return;
55
+ getComponent(component, scope = []) {
56
+ const scopesToResolve = [
57
+ "*",
58
+ ...scope
59
+ ].reverse();
60
+ for (const s of scopesToResolve){
61
+ const scopeMap = this.scopes.get(s);
62
+ if (!scopeMap) continue;
63
+ const composed = scopeMap.get(component);
64
+ if (composed) return composed.component;
65
+ }
60
66
  }
61
- const newHocs = recipe.hocs.filter(hoc => !hocs.includes(hoc));
62
- if (newHocs.length === recipe.hocs.length) {
63
- // Nothing was removed.
64
- return;
67
+ notify() {
68
+ this.version++;
69
+ this.notifyListeners();
65
70
  }
66
- if (newHocs.length === 0) {
67
- scopeMap.delete(component);
68
- } else {
69
- scopeMap.set(component, {
70
- component: compose(...[...newHocs].reverse())(component),
71
- hocs: newHocs
72
- });
71
+ notifyListeners() {
72
+ for (const listener of this.listeners)listener();
73
73
  }
74
- this.version++;
75
- this.notifyListeners();
76
- }
77
- getComponent(component, scope = []) {
78
- const scopesToResolve = ["*", ...scope].reverse();
79
- for (const s of scopesToResolve) {
80
- const scopeMap = this.scopes.get(s);
81
- if (!scopeMap) {
82
- continue;
83
- }
84
- const composed = scopeMap.get(component);
85
- if (composed) {
86
- return composed.component;
87
- }
88
- }
89
- return undefined;
90
- }
91
-
92
- /**
93
- * Bump version and notify listeners without changing store state.
94
- * Used after a render-phase atomic swap (silent) to inform subscribers
95
- * that the swap has settled and they should re-render with the final state.
96
- */
97
- notify() {
98
- this.version++;
99
- this.notifyListeners();
100
- }
101
- subscribe = listener => {
102
- this.listeners.add(listener);
103
- return () => {
104
- this.listeners.delete(listener);
105
- };
106
- };
107
- getSnapshot = () => {
108
- return this.version;
109
- };
110
- notifyListeners() {
111
- for (const listener of this.listeners) {
112
- listener();
74
+ constructor(){
75
+ this.scopes = new Map();
76
+ this.version = 0;
77
+ this.listeners = new Set();
78
+ this.subscribe = (listener)=>{
79
+ this.listeners.add(listener);
80
+ return ()=>{
81
+ this.listeners.delete(listener);
82
+ };
83
+ };
84
+ this.getSnapshot = ()=>this.version;
113
85
  }
114
- }
115
86
  }
87
+ export { CompositionStore };
116
88
 
117
89
  //# sourceMappingURL=CompositionStore.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["compose","CompositionStore","scopes","Map","version","listeners","Set","register","component","hocs","scope","inherit","silent","replaces","scopeMap","get","recipe","newHocs","filter","hoc","includes","length","unregister","existingHocs","globalScope","globalRecipe","globalHocsToAdd","unshift","finalHocs","set","reverse","notifyListeners","delete","getComponent","scopesToResolve","s","composed","undefined","notify","subscribe","listener","add","getSnapshot"],"sources":["CompositionStore.ts"],"sourcesContent":["import type { ComponentType } from \"react\";\nimport { compose } from \"~/Context.js\";\nimport type { Decorator, GenericComponent, GenericHook } from \"~/types.js\";\n\ninterface ComposedComponent {\n component: GenericHook | GenericComponent;\n hocs: Decorator<GenericComponent | GenericHook>[];\n}\n\ntype ComposedComponents = Map<ComponentType<unknown>, ComposedComponent>;\ntype ComponentScopes = Map<string, ComposedComponents>;\n\ntype Listener = () => void;\n\nexport class CompositionStore {\n private scopes: ComponentScopes = new Map();\n private version = 0;\n private listeners = new Set<Listener>();\n\n register(\n component: ComponentType<unknown>,\n hocs: Decorator<GenericComponent | GenericHook>[],\n scope = \"*\",\n inherit = false,\n silent = false,\n replaces: Decorator<GenericComponent | GenericHook>[] = []\n ): () => void {\n const scopeMap: ComposedComponents = this.scopes.get(scope) || new Map();\n const recipe = scopeMap.get(component) || {\n component: component as any,\n hocs: [] as Decorator<GenericComponent | GenericHook>[]\n };\n\n // Idempotent: skip if all HOCs are already registered (handles StrictMode double-render).\n const newHocs = hocs.filter(hoc => !recipe.hocs.includes(hoc));\n if (newHocs.length === 0 && replaces.length === 0) {\n return () => this.unregister(component, hocs, scope);\n }\n\n // Atomically remove the HOCs being replaced so the store never transiently\n // holds both the old and new decorators at the same time. This prevents\n // useSyncExternalStore subscribers from seeing a doubly-wrapped component\n // in the window between a render-phase registration and its effect cleanup.\n const existingHocs = replaces.length\n ? recipe.hocs.filter(hoc => !replaces.includes(hoc))\n : [...recipe.hocs];\n if (inherit && scope !== \"*\") {\n const globalScope = this.scopes.get(\"*\") || new Map();\n const globalRecipe = globalScope.get(component) || {\n component: component as any,\n hocs: [] as Decorator<GenericComponent | GenericHook>[]\n };\n // Only prepend global HOCs that aren't already present.\n const globalHocsToAdd = globalRecipe.hocs.filter(\n (hoc: Decorator<GenericComponent | GenericHook>) => !existingHocs.includes(hoc)\n );\n existingHocs.unshift(...globalHocsToAdd);\n }\n\n const finalHocs = [...existingHocs, ...newHocs];\n\n scopeMap.set(component, {\n component: compose(...[...finalHocs].reverse())(component as any),\n hocs: finalHocs\n });\n\n this.scopes.set(scope, scopeMap);\n\n // Bump the version so useSyncExternalStore sees a new snapshot.\n this.version++;\n\n // When called during render (silent=true), don't notify listeners —\n // that would trigger setState in other components mid-render.\n // Components that render after this point will see the updated snapshot.\n if (!silent) {\n this.notifyListeners();\n }\n\n return () => this.unregister(component, hocs, scope);\n }\n\n unregister(\n component: ComponentType<unknown>,\n hocs: Decorator<GenericComponent | GenericHook>[],\n scope = \"*\"\n ): void {\n const scopeMap = this.scopes.get(scope);\n if (!scopeMap) {\n return;\n }\n\n const recipe = scopeMap.get(component);\n if (!recipe) {\n return;\n }\n\n const newHocs = recipe.hocs.filter(hoc => !hocs.includes(hoc));\n if (newHocs.length === recipe.hocs.length) {\n // Nothing was removed.\n return;\n }\n\n if (newHocs.length === 0) {\n scopeMap.delete(component);\n } else {\n scopeMap.set(component, {\n component: compose(...[...newHocs].reverse())(component as any),\n hocs: newHocs\n });\n }\n\n this.version++;\n this.notifyListeners();\n }\n\n getComponent(\n component: ComponentType<unknown>,\n scope: string[] = []\n ): GenericComponent | GenericHook | undefined {\n const scopesToResolve = [\"*\", ...scope].reverse();\n for (const s of scopesToResolve) {\n const scopeMap = this.scopes.get(s);\n if (!scopeMap) {\n continue;\n }\n const composed = scopeMap.get(component);\n if (composed) {\n return composed.component;\n }\n }\n return undefined;\n }\n\n /**\n * Bump version and notify listeners without changing store state.\n * Used after a render-phase atomic swap (silent) to inform subscribers\n * that the swap has settled and they should re-render with the final state.\n */\n notify(): void {\n this.version++;\n this.notifyListeners();\n }\n\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): number => {\n return this.version;\n };\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"domain/CompositionStore.js","sources":["../../src/domain/CompositionStore.ts"],"sourcesContent":["import type { ComponentType } from \"react\";\nimport { compose } from \"~/Context.js\";\nimport type { Decorator, GenericComponent, GenericHook } from \"~/types.js\";\n\ninterface ComposedComponent {\n component: GenericHook | GenericComponent;\n hocs: Decorator<GenericComponent | GenericHook>[];\n}\n\ntype ComposedComponents = Map<ComponentType<unknown>, ComposedComponent>;\ntype ComponentScopes = Map<string, ComposedComponents>;\n\ntype Listener = () => void;\n\nexport class CompositionStore {\n private scopes: ComponentScopes = new Map();\n private version = 0;\n private listeners = new Set<Listener>();\n\n register(\n component: ComponentType<unknown>,\n hocs: Decorator<GenericComponent | GenericHook>[],\n scope = \"*\",\n inherit = false,\n silent = false,\n replaces: Decorator<GenericComponent | GenericHook>[] = []\n ): () => void {\n const scopeMap: ComposedComponents = this.scopes.get(scope) || new Map();\n const recipe = scopeMap.get(component) || {\n component: component as any,\n hocs: [] as Decorator<GenericComponent | GenericHook>[]\n };\n\n // Idempotent: skip if all HOCs are already registered (handles StrictMode double-render).\n const newHocs = hocs.filter(hoc => !recipe.hocs.includes(hoc));\n if (newHocs.length === 0 && replaces.length === 0) {\n return () => this.unregister(component, hocs, scope);\n }\n\n // Atomically remove the HOCs being replaced so the store never transiently\n // holds both the old and new decorators at the same time. This prevents\n // useSyncExternalStore subscribers from seeing a doubly-wrapped component\n // in the window between a render-phase registration and its effect cleanup.\n const existingHocs = replaces.length\n ? recipe.hocs.filter(hoc => !replaces.includes(hoc))\n : [...recipe.hocs];\n if (inherit && scope !== \"*\") {\n const globalScope = this.scopes.get(\"*\") || new Map();\n const globalRecipe = globalScope.get(component) || {\n component: component as any,\n hocs: [] as Decorator<GenericComponent | GenericHook>[]\n };\n // Only prepend global HOCs that aren't already present.\n const globalHocsToAdd = globalRecipe.hocs.filter(\n (hoc: Decorator<GenericComponent | GenericHook>) => !existingHocs.includes(hoc)\n );\n existingHocs.unshift(...globalHocsToAdd);\n }\n\n const finalHocs = [...existingHocs, ...newHocs];\n\n scopeMap.set(component, {\n component: compose(...[...finalHocs].reverse())(component as any),\n hocs: finalHocs\n });\n\n this.scopes.set(scope, scopeMap);\n\n // Bump the version so useSyncExternalStore sees a new snapshot.\n this.version++;\n\n // When called during render (silent=true), don't notify listeners —\n // that would trigger setState in other components mid-render.\n // Components that render after this point will see the updated snapshot.\n if (!silent) {\n this.notifyListeners();\n }\n\n return () => this.unregister(component, hocs, scope);\n }\n\n unregister(\n component: ComponentType<unknown>,\n hocs: Decorator<GenericComponent | GenericHook>[],\n scope = \"*\"\n ): void {\n const scopeMap = this.scopes.get(scope);\n if (!scopeMap) {\n return;\n }\n\n const recipe = scopeMap.get(component);\n if (!recipe) {\n return;\n }\n\n const newHocs = recipe.hocs.filter(hoc => !hocs.includes(hoc));\n if (newHocs.length === recipe.hocs.length) {\n // Nothing was removed.\n return;\n }\n\n if (newHocs.length === 0) {\n scopeMap.delete(component);\n } else {\n scopeMap.set(component, {\n component: compose(...[...newHocs].reverse())(component as any),\n hocs: newHocs\n });\n }\n\n this.version++;\n this.notifyListeners();\n }\n\n getComponent(\n component: ComponentType<unknown>,\n scope: string[] = []\n ): GenericComponent | GenericHook | undefined {\n const scopesToResolve = [\"*\", ...scope].reverse();\n for (const s of scopesToResolve) {\n const scopeMap = this.scopes.get(s);\n if (!scopeMap) {\n continue;\n }\n const composed = scopeMap.get(component);\n if (composed) {\n return composed.component;\n }\n }\n return undefined;\n }\n\n /**\n * Bump version and notify listeners without changing store state.\n * Used after a render-phase atomic swap (silent) to inform subscribers\n * that the swap has settled and they should re-render with the final state.\n */\n notify(): void {\n this.version++;\n this.notifyListeners();\n }\n\n subscribe = (listener: Listener): (() => void) => {\n this.listeners.add(listener);\n return () => {\n this.listeners.delete(listener);\n };\n };\n\n getSnapshot = (): number => {\n return this.version;\n };\n\n private notifyListeners(): void {\n for (const listener of this.listeners) {\n listener();\n }\n }\n}\n"],"names":["CompositionStore","component","hocs","scope","inherit","silent","replaces","scopeMap","Map","recipe","newHocs","hoc","existingHocs","globalScope","globalRecipe","globalHocsToAdd","finalHocs","compose","scopesToResolve","s","composed","listener","Set"],"mappings":"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"}
package/index.js CHANGED
@@ -6,5 +6,3 @@ export * from "./createDecorator.js";
6
6
  export * from "./decorators.js";
7
7
  export * from "./CompositionScope.js";
8
8
  export { CompositionStore } from "./domain/CompositionStore.js";
9
-
10
- //# sourceMappingURL=index.js.map
package/makeComposable.js CHANGED
@@ -1,14 +1,11 @@
1
1
  import { createContext } from "react";
2
2
  import { makeDecoratable } from "./makeDecoratable.js";
3
- const ComposableContext = /*#__PURE__*/createContext([]);
3
+ const ComposableContext = /*#__PURE__*/ createContext([]);
4
4
  ComposableContext.displayName = "ComposableContext";
5
- const nullRenderer = () => null;
6
-
7
- /**
8
- * @deprecated Use `makeDecoratable` instead.
9
- */
10
- export function makeComposable(name, Component) {
11
- return makeDecoratable(name, Component ?? nullRenderer);
5
+ const nullRenderer = ()=>null;
6
+ function makeComposable(name, Component) {
7
+ return makeDecoratable(name, Component ?? nullRenderer);
12
8
  }
9
+ export { makeComposable };
13
10
 
14
11
  //# sourceMappingURL=makeComposable.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["createContext","makeDecoratable","ComposableContext","displayName","nullRenderer","makeComposable","name","Component"],"sources":["makeComposable.tsx"],"sourcesContent":["import { createContext } from \"react\";\nimport type { GenericComponent } from \"~/types.js\";\nimport { makeDecoratable } from \"~/makeDecoratable.js\";\n\nconst ComposableContext = createContext<string[]>([]);\nComposableContext.displayName = \"ComposableContext\";\n\nconst nullRenderer = () => null;\n\n/**\n * @deprecated Use `makeDecoratable` instead.\n */\nexport function makeComposable<T extends GenericComponent>(name: string, Component?: T) {\n return makeDecoratable(name, Component ?? nullRenderer);\n}\n"],"mappings":"AAAA,SAASA,aAAa,QAAQ,OAAO;AAErC,SAASC,eAAe;AAExB,MAAMC,iBAAiB,gBAAGF,aAAa,CAAW,EAAE,CAAC;AACrDE,iBAAiB,CAACC,WAAW,GAAG,mBAAmB;AAEnD,MAAMC,YAAY,GAAGA,CAAA,KAAM,IAAI;;AAE/B;AACA;AACA;AACA,OAAO,SAASC,cAAcA,CAA6BC,IAAY,EAAEC,SAAa,EAAE;EACpF,OAAON,eAAe,CAACK,IAAI,EAAEC,SAAS,IAAIH,YAAY,CAAC;AAC3D","ignoreList":[]}
1
+ {"version":3,"file":"makeComposable.js","sources":["../src/makeComposable.tsx"],"sourcesContent":["import { createContext } from \"react\";\nimport type { GenericComponent } from \"~/types.js\";\nimport { makeDecoratable } from \"~/makeDecoratable.js\";\n\nconst ComposableContext = createContext<string[]>([]);\nComposableContext.displayName = \"ComposableContext\";\n\nconst nullRenderer = () => null;\n\n/**\n * @deprecated Use `makeDecoratable` instead.\n */\nexport function makeComposable<T extends GenericComponent>(name: string, Component?: T) {\n return makeDecoratable(name, Component ?? nullRenderer);\n}\n"],"names":["ComposableContext","createContext","nullRenderer","makeComposable","name","Component","makeDecoratable"],"mappings":";;AAIA,MAAMA,oBAAoB,WAAHA,GAAGC,cAAwB,EAAE;AACpDD,kBAAkB,WAAW,GAAG;AAEhC,MAAME,eAAe,IAAM;AAKpB,SAASC,eAA2CC,IAAY,EAAEC,SAAa;IAClF,OAAOC,gBAAgBF,MAAMC,aAAaH;AAC9C"}
@@ -1,90 +1,90 @@
1
- import React, { createContext, useContext, useMemo } from "react";
1
+ import react, { createContext, useContext, useMemo } from "react";
2
2
  import { useComponent } from "./Context.js";
3
3
  import { withDecoratorFactory, withHookDecoratorFactory } from "./decorators.js";
4
- class DecoratableErrorBoundary extends React.Component {
5
- constructor(props) {
6
- super(props);
7
- this.state = {
8
- hasError: false,
9
- error: undefined
10
- };
11
- }
12
- static getDerivedStateFromError(error) {
13
- return {
14
- hasError: true,
15
- error
16
- };
17
- }
18
- componentDidCatch(error, errorInfo) {
19
- console.groupCollapsed(`%cCOMPONENT ERROR%c: "${this.props.name}" failed to render.`, "color:red", "color:default");
20
- console.error(error, errorInfo);
21
- console.groupEnd();
22
- }
23
- render() {
24
- if (this.state.hasError) {
25
- return /*#__PURE__*/React.createElement("div", {
26
- style: {
27
- padding: "8px 12px",
28
- border: "1px solid #e53e3e",
29
- borderRadius: 4,
30
- background: "#fff5f5",
31
- color: "#c53030",
32
- fontSize: 13
33
- }
34
- }, /*#__PURE__*/React.createElement("strong", null, this.props.name), ": ", this.state.error?.message);
4
+ class DecoratableErrorBoundary extends react.Component {
5
+ constructor(props){
6
+ super(props);
7
+ this.state = {
8
+ hasError: false,
9
+ error: void 0
10
+ };
11
+ }
12
+ static getDerivedStateFromError(error) {
13
+ return {
14
+ hasError: true,
15
+ error
16
+ };
17
+ }
18
+ componentDidCatch(error, errorInfo) {
19
+ console.groupCollapsed(`%cCOMPONENT ERROR%c: "${this.props.name}" failed to render.`, "color:red", "color:default");
20
+ console.error(error, errorInfo);
21
+ console.groupEnd();
22
+ }
23
+ render() {
24
+ if (this.state.hasError) return /*#__PURE__*/ react.createElement("div", {
25
+ style: {
26
+ padding: "8px 12px",
27
+ border: "1px solid #e53e3e",
28
+ borderRadius: 4,
29
+ background: "#fff5f5",
30
+ color: "#c53030",
31
+ fontSize: 13
32
+ }
33
+ }, /*#__PURE__*/ react.createElement("strong", null, this.props.name), ": ", this.state.error?.message);
34
+ return this.props.children;
35
35
  }
36
- return this.props.children;
37
- }
38
36
  }
39
- const ComposableContext = /*#__PURE__*/createContext([]);
37
+ const ComposableContext = /*#__PURE__*/ createContext([]);
40
38
  ComposableContext.displayName = "ComposableContext";
41
39
  function useComposableParents() {
42
- const context = useContext(ComposableContext);
43
- if (!context) {
44
- return [];
45
- }
46
- return context;
40
+ const context = useContext(ComposableContext);
41
+ if (!context) return [];
42
+ return context;
47
43
  }
48
- const nullRenderer = () => null;
44
+ const nullRenderer = ()=>null;
49
45
  function makeDecoratableComponent(name, Component = nullRenderer) {
50
- const Decoratable = props => {
51
- const parents = useComposableParents();
52
- const ComposedComponent = useComponent(Component);
53
- const context = useMemo(() => [...parents, name], [parents, name]);
54
- return /*#__PURE__*/React.createElement(ComposableContext.Provider, {
55
- value: context
56
- }, /*#__PURE__*/React.createElement(DecoratableErrorBoundary, {
57
- name: name
58
- }, /*#__PURE__*/React.createElement(ComposedComponent, props, props.children)));
59
- };
60
- const staticProps = {
61
- original: Component,
62
- originalName: name,
63
- displayName: `Decoratable<${name}>`
64
- };
65
- return withDecoratorFactory()(Object.assign(Decoratable, staticProps));
46
+ const Decoratable = (props)=>{
47
+ const parents = useComposableParents();
48
+ const ComposedComponent = useComponent(Component);
49
+ const context = useMemo(()=>[
50
+ ...parents,
51
+ name
52
+ ], [
53
+ parents,
54
+ name
55
+ ]);
56
+ return /*#__PURE__*/ react.createElement(ComposableContext.Provider, {
57
+ value: context
58
+ }, /*#__PURE__*/ react.createElement(DecoratableErrorBoundary, {
59
+ name: name
60
+ }, /*#__PURE__*/ react.createElement(ComposedComponent, props, props.children)));
61
+ };
62
+ const staticProps = {
63
+ original: Component,
64
+ originalName: name,
65
+ displayName: `Decoratable<${name}>`
66
+ };
67
+ return withDecoratorFactory()(Object.assign(Decoratable, staticProps));
66
68
  }
67
- export function makeDecoratableHook(hook) {
68
- const decoratableHook = params => {
69
- const composedHook = useComponent(hook);
70
- return composedHook(params);
71
- };
72
- decoratableHook.original = hook;
73
- return withHookDecoratorFactory()(decoratableHook);
69
+ function makeDecoratableHook(hook) {
70
+ const decoratableHook = (params)=>{
71
+ const composedHook = useComponent(hook);
72
+ return composedHook(params);
73
+ };
74
+ decoratableHook.original = hook;
75
+ return withHookDecoratorFactory()(decoratableHook);
74
76
  }
75
- export function createVoidComponent() {
76
- // oxlint-disable-next-line typescript/no-unused-vars
77
- return props => {
78
- return null;
79
- };
77
+ function createVoidComponent() {
78
+ return (props)=>null;
80
79
  }
81
- export function makeDecoratable(hookOrName, Component) {
82
- if (Component) {
83
- const component = makeDecoratableComponent(hookOrName, /*#__PURE__*/React.memo(Component));
84
- component.original.displayName = hookOrName;
85
- return component;
86
- }
87
- return makeDecoratableHook(hookOrName);
80
+ function makeDecoratable(hookOrName, Component) {
81
+ if (Component) {
82
+ const component = makeDecoratableComponent(hookOrName, /*#__PURE__*/ react.memo(Component));
83
+ component.original.displayName = hookOrName;
84
+ return component;
85
+ }
86
+ return makeDecoratableHook(hookOrName);
88
87
  }
88
+ export { createVoidComponent, makeDecoratable, makeDecoratableHook };
89
89
 
90
90
  //# sourceMappingURL=makeDecoratable.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","createContext","useContext","useMemo","useComponent","withDecoratorFactory","withHookDecoratorFactory","DecoratableErrorBoundary","Component","constructor","props","state","hasError","error","undefined","getDerivedStateFromError","componentDidCatch","errorInfo","console","groupCollapsed","name","groupEnd","render","createElement","style","padding","border","borderRadius","background","color","fontSize","message","children","ComposableContext","displayName","useComposableParents","context","nullRenderer","makeDecoratableComponent","Decoratable","parents","ComposedComponent","Provider","value","staticProps","original","originalName","Object","assign","makeDecoratableHook","hook","decoratableHook","params","composedHook","createVoidComponent","makeDecoratable","hookOrName","component","memo"],"sources":["makeDecoratable.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from \"react\";\nimport type { ErrorInfo } from \"react\";\nimport { useComponent } from \"./Context.js\";\nimport type {\n DecoratableComponent,\n DecoratableHook,\n GenericComponent,\n GenericHook\n} from \"~/types.js\";\nimport { withDecoratorFactory, withHookDecoratorFactory } from \"~/decorators.js\";\n\ninterface ErrorBoundaryProps {\n name: string;\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | undefined;\n}\n\nclass DecoratableErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: undefined };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.groupCollapsed(\n `%cCOMPONENT ERROR%c: \"${this.props.name}\" failed to render.`,\n \"color:red\",\n \"color:default\"\n );\n console.error(error, errorInfo);\n console.groupEnd();\n }\n\n override render() {\n if (this.state.hasError) {\n return (\n <div\n style={{\n padding: \"8px 12px\",\n border: \"1px solid #e53e3e\",\n borderRadius: 4,\n background: \"#fff5f5\",\n color: \"#c53030\",\n fontSize: 13\n }}\n >\n <strong>{this.props.name}</strong>: {this.state.error?.message}\n </div>\n );\n }\n return this.props.children;\n }\n}\n\nconst ComposableContext = createContext<string[]>([]);\nComposableContext.displayName = \"ComposableContext\";\n\nfunction useComposableParents() {\n const context = useContext(ComposableContext);\n if (!context) {\n return [];\n }\n\n return context;\n}\n\nconst nullRenderer = () => null;\n\nfunction makeDecoratableComponent<T extends GenericComponent>(\n name: string,\n Component: T = nullRenderer as unknown as T\n) {\n const Decoratable = (props: React.ComponentProps<T>): React.JSX.Element | null => {\n const parents = useComposableParents();\n const ComposedComponent = useComponent(Component) as GenericComponent<\n React.ComponentProps<T>\n >;\n\n const context = useMemo(() => [...parents, name], [parents, name]);\n\n return (\n <ComposableContext.Provider value={context}>\n <DecoratableErrorBoundary name={name}>\n <ComposedComponent {...props}>{props.children}</ComposedComponent>\n </DecoratableErrorBoundary>\n </ComposableContext.Provider>\n );\n };\n\n const staticProps = {\n original: Component,\n originalName: name,\n displayName: `Decoratable<${name}>`\n };\n\n return withDecoratorFactory()(\n Object.assign(Decoratable, staticProps) as DecoratableComponent<\n typeof Component & typeof staticProps\n >\n );\n}\n\nexport function makeDecoratableHook<T extends GenericHook>(hook: T) {\n const decoratableHook = (params: Parameters<T>) => {\n const composedHook = useComponent(hook);\n\n return composedHook(params) as DecoratableHook<T>;\n };\n\n decoratableHook.original = hook;\n\n return withHookDecoratorFactory()(decoratableHook as DecoratableHook<T>);\n}\n\nexport function createVoidComponent<T>() {\n // oxlint-disable-next-line typescript/no-unused-vars\n return (props: T): React.JSX.Element | null => {\n return null;\n };\n}\n\nexport function makeDecoratable<T extends GenericHook>(\n hook: T\n): ReturnType<typeof makeDecoratableHook<T>>;\nexport function makeDecoratable<T extends GenericComponent>(\n name: string,\n Component: T\n): ReturnType<typeof makeDecoratableComponent<T>>;\nexport function makeDecoratable(hookOrName: any, Component?: any) {\n if (Component) {\n const component = makeDecoratableComponent(hookOrName, React.memo(Component));\n component.original.displayName = hookOrName;\n return component;\n }\n\n return makeDecoratableHook(hookOrName);\n}\n"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"file":"makeDecoratable.js","sources":["../src/makeDecoratable.tsx"],"sourcesContent":["import React, { createContext, useContext, useMemo } from \"react\";\nimport type { ErrorInfo } from \"react\";\nimport { useComponent } from \"./Context.js\";\nimport type {\n DecoratableComponent,\n DecoratableHook,\n GenericComponent,\n GenericHook\n} from \"~/types.js\";\nimport { withDecoratorFactory, withHookDecoratorFactory } from \"~/decorators.js\";\n\ninterface ErrorBoundaryProps {\n name: string;\n children: React.ReactNode;\n}\n\ninterface ErrorBoundaryState {\n hasError: boolean;\n error: Error | undefined;\n}\n\nclass DecoratableErrorBoundary extends React.Component<ErrorBoundaryProps, ErrorBoundaryState> {\n constructor(props: ErrorBoundaryProps) {\n super(props);\n this.state = { hasError: false, error: undefined };\n }\n\n static getDerivedStateFromError(error: Error): ErrorBoundaryState {\n return { hasError: true, error };\n }\n\n override componentDidCatch(error: Error, errorInfo: ErrorInfo) {\n console.groupCollapsed(\n `%cCOMPONENT ERROR%c: \"${this.props.name}\" failed to render.`,\n \"color:red\",\n \"color:default\"\n );\n console.error(error, errorInfo);\n console.groupEnd();\n }\n\n override render() {\n if (this.state.hasError) {\n return (\n <div\n style={{\n padding: \"8px 12px\",\n border: \"1px solid #e53e3e\",\n borderRadius: 4,\n background: \"#fff5f5\",\n color: \"#c53030\",\n fontSize: 13\n }}\n >\n <strong>{this.props.name}</strong>: {this.state.error?.message}\n </div>\n );\n }\n return this.props.children;\n }\n}\n\nconst ComposableContext = createContext<string[]>([]);\nComposableContext.displayName = \"ComposableContext\";\n\nfunction useComposableParents() {\n const context = useContext(ComposableContext);\n if (!context) {\n return [];\n }\n\n return context;\n}\n\nconst nullRenderer = () => null;\n\nfunction makeDecoratableComponent<T extends GenericComponent>(\n name: string,\n Component: T = nullRenderer as unknown as T\n) {\n const Decoratable = (props: React.ComponentProps<T>): React.JSX.Element | null => {\n const parents = useComposableParents();\n const ComposedComponent = useComponent(Component) as GenericComponent<\n React.ComponentProps<T>\n >;\n\n const context = useMemo(() => [...parents, name], [parents, name]);\n\n return (\n <ComposableContext.Provider value={context}>\n <DecoratableErrorBoundary name={name}>\n <ComposedComponent {...props}>{props.children}</ComposedComponent>\n </DecoratableErrorBoundary>\n </ComposableContext.Provider>\n );\n };\n\n const staticProps = {\n original: Component,\n originalName: name,\n displayName: `Decoratable<${name}>`\n };\n\n return withDecoratorFactory()(\n Object.assign(Decoratable, staticProps) as DecoratableComponent<\n typeof Component & typeof staticProps\n >\n );\n}\n\nexport function makeDecoratableHook<T extends GenericHook>(hook: T) {\n const decoratableHook = (params: Parameters<T>) => {\n const composedHook = useComponent(hook);\n\n return composedHook(params) as DecoratableHook<T>;\n };\n\n decoratableHook.original = hook;\n\n return withHookDecoratorFactory()(decoratableHook as DecoratableHook<T>);\n}\n\nexport function createVoidComponent<T>() {\n // oxlint-disable-next-line typescript/no-unused-vars\n return (props: T): React.JSX.Element | null => {\n return null;\n };\n}\n\nexport function makeDecoratable<T extends GenericHook>(\n hook: T\n): ReturnType<typeof makeDecoratableHook<T>>;\nexport function makeDecoratable<T extends GenericComponent>(\n name: string,\n Component: T\n): ReturnType<typeof makeDecoratableComponent<T>>;\nexport function makeDecoratable(hookOrName: any, Component?: any) {\n if (Component) {\n const component = makeDecoratableComponent(hookOrName, React.memo(Component));\n component.original.displayName = hookOrName;\n return component;\n }\n\n return makeDecoratableHook(hookOrName);\n}\n"],"names":["DecoratableErrorBoundary","React","props","undefined","error","errorInfo","console","ComposableContext","createContext","useComposableParents","context","useContext","nullRenderer","makeDecoratableComponent","name","Component","Decoratable","parents","ComposedComponent","useComponent","useMemo","staticProps","withDecoratorFactory","Object","makeDecoratableHook","hook","decoratableHook","params","composedHook","withHookDecoratorFactory","createVoidComponent","makeDecoratable","hookOrName","component"],"mappings":";;;AAqBA,MAAMA,iCAAiCC,MAAAA,SAAe;IAClD,YAAYC,KAAyB,CAAE;QACnC,KAAK,CAACA;QACN,IAAI,CAAC,KAAK,GAAG;YAAE,UAAU;YAAO,OAAOC;QAAU;IACrD;IAEA,OAAO,yBAAyBC,KAAY,EAAsB;QAC9D,OAAO;YAAE,UAAU;YAAMA;QAAM;IACnC;IAES,kBAAkBA,KAAY,EAAEC,SAAoB,EAAE;QAC3DC,QAAQ,cAAc,CAClB,CAAC,sBAAsB,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,mBAAmB,CAAC,EAC7D,aACA;QAEJA,QAAQ,KAAK,CAACF,OAAOC;QACrBC,QAAQ,QAAQ;IACpB;IAES,SAAS;QACd,IAAI,IAAI,CAAC,KAAK,CAAC,QAAQ,EACnB,OAAO,WAAP,GACI,oBAAC;YACG,OAAO;gBACH,SAAS;gBACT,QAAQ;gBACR,cAAc;gBACd,YAAY;gBACZ,OAAO;gBACP,UAAU;YACd;yBAEA,oBAAC,gBAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,GAAU,MAAG,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE;QAInE,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ;IAC9B;AACJ;AAEA,MAAMC,oBAAoB,WAAHA,GAAGC,cAAwB,EAAE;AACpDD,kBAAkB,WAAW,GAAG;AAEhC,SAASE;IACL,MAAMC,UAAUC,WAAWJ;IAC3B,IAAI,CAACG,SACD,OAAO,EAAE;IAGb,OAAOA;AACX;AAEA,MAAME,eAAe,IAAM;AAE3B,SAASC,yBACLC,IAAY,EACZC,YAAeH,YAA4B;IAE3C,MAAMI,cAAc,CAACd;QACjB,MAAMe,UAAUR;QAChB,MAAMS,oBAAoBC,aAAaJ;QAIvC,MAAML,UAAUU,QAAQ,IAAM;mBAAIH;gBAASH;aAAK,EAAE;YAACG;YAASH;SAAK;QAEjE,OAAO,WAAP,GACI,oBAACP,kBAAkB,QAAQ;YAAC,OAAOG;yBAC/B,oBAACV,0BAAwBA;YAAC,MAAMc;yBAC5B,oBAACI,mBAAsBhB,OAAQA,MAAM,QAAQ;IAI7D;IAEA,MAAMmB,cAAc;QAChB,UAAUN;QACV,cAAcD;QACd,aAAa,CAAC,YAAY,EAAEA,KAAK,CAAC,CAAC;IACvC;IAEA,OAAOQ,uBACHC,OAAO,MAAM,CAACP,aAAaK;AAInC;AAEO,SAASG,oBAA2CC,IAAO;IAC9D,MAAMC,kBAAkB,CAACC;QACrB,MAAMC,eAAeT,aAAaM;QAElC,OAAOG,aAAaD;IACxB;IAEAD,gBAAgB,QAAQ,GAAGD;IAE3B,OAAOI,2BAA2BH;AACtC;AAEO,SAASI;IAEZ,OAAO,CAAC5B,QACG;AAEf;AASO,SAAS6B,gBAAgBC,UAAe,EAAEjB,SAAe;IAC5D,IAAIA,WAAW;QACX,MAAMkB,YAAYpB,yBAAyBmB,YAAY,WAAZA,GAAY/B,MAAAA,IAAU,CAACc;QAClEkB,UAAU,QAAQ,CAAC,WAAW,GAAGD;QACjC,OAAOC;IACX;IAEA,OAAOT,oBAAoBQ;AAC/B"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webiny/react-composition",
3
- "version": "6.3.0-beta.4",
3
+ "version": "6.4.0-beta.0",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./index.js",
@@ -24,13 +24,13 @@
24
24
  },
25
25
  "devDependencies": {
26
26
  "@testing-library/react": "16.3.2",
27
- "@webiny/build-tools": "6.3.0-beta.4",
27
+ "@webiny/build-tools": "6.4.0-beta.0",
28
28
  "typescript": "6.0.3",
29
- "vitest": "4.1.5"
29
+ "vitest": "4.1.6"
30
30
  },
31
31
  "publishConfig": {
32
32
  "access": "public",
33
33
  "directory": "dist"
34
34
  },
35
- "gitHead": "7cefe15431dbd65504e1f58147dc9e55bcbfa693"
35
+ "gitHead": "a545d7529828af07d08d49c3da1bcb967483b9ce"
36
36
  }
package/types.js CHANGED
@@ -1,3 +0,0 @@
1
- export {};
2
-
3
- //# sourceMappingURL=types.js.map
package/index.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"names":["CompositionStore"],"sources":["index.ts"],"sourcesContent":["export * from \"./Context.js\";\nexport * from \"./Compose.js\";\nexport * from \"./makeComposable.js\";\nexport * from \"./makeDecoratable.js\";\nexport * from \"./createDecorator.js\";\nexport * from \"./decorators.js\";\nexport * from \"./CompositionScope.js\";\nexport { CompositionStore } from \"./domain/CompositionStore.js\";\nexport type * from \"./types.js\";\n"],"mappings":"AAAA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,SAASA,gBAAgB","ignoreList":[]}
package/types.js.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"names":[],"sources":["types.ts"],"sourcesContent":["import type React from \"react\";\n\nexport type GenericHook<TParams = any, TReturn = any> = (...args: TParams[]) => TReturn;\n\nexport type GenericComponent<T = any> = React.FunctionComponent<T>;\n\nexport type ComposedFunction = GenericHook;\n\nexport type Decorator<T> = (decoratee: T) => T;\n\n/**\n * Some decoratable components will always return `null`, by design.\n * To allow you to decorate these components, we must tell TS that the decorator is allowed to return not just `null`\n * (which is inferred from the component type), but also a JSX.Element.\n */\nexport type ComponentDecorator<T> = (decoratee: T) => CanReturnNullOrElement<T>;\n\n/**\n * @deprecated\n */\nexport type ComposableFC<T> = T & {\n displayName?: string;\n original: T;\n originalName: string;\n};\n\nexport type Enumerable<T> = T extends Array<infer D> ? Array<D> : never;\n\nexport type ComposeWith =\n | Decorator<GenericComponent>\n | Decorator<GenericComponent>[]\n | Decorator<GenericHook>\n | Decorator<GenericHook>[];\n\nexport type DecoratableHook<T extends GenericHook = GenericHook> = T & {\n original: T;\n originalName: string;\n};\n\nexport type DecoratableComponent<T = GenericComponent> = T & {\n original: T;\n originalName: string;\n displayName: string;\n};\n\nexport type Decoratable = DecoratableComponent | DecoratableHook;\n\n/**\n * @internal Add `null` to the ReturnType of the given function.\n */\nexport type CanReturnNullOrElement<T> = T extends (...args: any) => any\n ? (...args: Parameters<T>) => React.JSX.Element | null\n : never;\n"],"mappings":"","ignoreList":[]}