@elementor/locations 0.1.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.
@@ -0,0 +1,38 @@
1
+ import { ComponentType } from 'react';
2
+
3
+ type Location = string;
4
+ type Filler = ComponentType;
5
+ type Name = string;
6
+ type Id = string;
7
+ type Priority = number;
8
+ type InjectionOptions = {
9
+ priority?: Priority;
10
+ overwrite?: boolean;
11
+ };
12
+ type Injection = {
13
+ location: Location;
14
+ filler: Filler;
15
+ priority: Priority;
16
+ id: Id;
17
+ };
18
+
19
+ type InjectArgs = {
20
+ location: Location;
21
+ filler: Filler;
22
+ name: Name;
23
+ options?: InjectionOptions;
24
+ };
25
+ declare function inject({ location, filler, name, options }: InjectArgs): void;
26
+ declare function createInjectorFor(location: Location): ({ filler, name, options }: Omit<InjectArgs, 'location'>) => void;
27
+ declare function getInjectionsOf(location: string): Injection[];
28
+ declare function flushInjections(): void;
29
+
30
+ declare function useInjectionsOf(locations: string[]): Injection[][];
31
+ declare function useInjectionsOf(location: string): Injection[];
32
+
33
+ type Props = {
34
+ location: Location;
35
+ };
36
+ declare function Slot({ location }: Props): JSX.Element;
37
+
38
+ export { Filler, Id, Injection, InjectionOptions, Location, Name, Priority, Slot, createInjectorFor, flushInjections, getInjectionsOf, inject, useInjectionsOf };
package/dist/index.js ADDED
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/index.ts
31
+ var src_exports = {};
32
+ __export(src_exports, {
33
+ Slot: () => Slot,
34
+ createInjectorFor: () => createInjectorFor,
35
+ flushInjections: () => flushInjections,
36
+ getInjectionsOf: () => getInjectionsOf,
37
+ inject: () => inject,
38
+ useInjectionsOf: () => useInjectionsOf
39
+ });
40
+ module.exports = __toCommonJS(src_exports);
41
+
42
+ // src/injections.tsx
43
+ var React2 = __toESM(require("react"));
44
+
45
+ // src/components/filler-wrapper.tsx
46
+ var React = __toESM(require("react"));
47
+ var import_react2 = require("react");
48
+
49
+ // src/components/error-boundary.tsx
50
+ var import_react = require("react");
51
+ var ErrorBoundary = class extends import_react.Component {
52
+ state = {
53
+ hasError: false
54
+ };
55
+ static getDerivedStateFromError() {
56
+ return { hasError: true };
57
+ }
58
+ render() {
59
+ if (this.state.hasError) {
60
+ return this.props.fallback;
61
+ }
62
+ return this.props.children;
63
+ }
64
+ };
65
+
66
+ // src/components/filler-wrapper.tsx
67
+ function FillerWrapper({ children }) {
68
+ return /* @__PURE__ */ React.createElement(ErrorBoundary, { fallback: null }, /* @__PURE__ */ React.createElement(import_react2.Suspense, { fallback: null }, children));
69
+ }
70
+
71
+ // src/injections.tsx
72
+ var DEFAULT_PRIORITY = 10;
73
+ var injections = /* @__PURE__ */ new Map();
74
+ function inject({ location, filler, name, options = {} }) {
75
+ const id = generateId(location, name);
76
+ if (injections.has(id) && !options?.overwrite) {
77
+ console.error(
78
+ `An injection named "${name}" under location "${location}" already exists. Did you mean to use "options.overwrite"?`
79
+ );
80
+ return;
81
+ }
82
+ const injection = {
83
+ id,
84
+ location,
85
+ filler: wrapFiller(filler),
86
+ priority: options.priority ?? DEFAULT_PRIORITY
87
+ };
88
+ injections.set(id, injection);
89
+ }
90
+ function createInjectorFor(location) {
91
+ return ({ filler, name, options }) => {
92
+ return inject({ location, name, filler, options });
93
+ };
94
+ }
95
+ function getInjectionsOf(location) {
96
+ return [...injections.values()].filter((injection) => injection.location === location).sort((a, b) => a.priority - b.priority);
97
+ }
98
+ function flushInjections() {
99
+ injections.clear();
100
+ }
101
+ function wrapFiller(FillerComponent) {
102
+ return (props) => /* @__PURE__ */ React2.createElement(FillerWrapper, null, /* @__PURE__ */ React2.createElement(FillerComponent, { ...props }));
103
+ }
104
+ function generateId(location, name) {
105
+ return `${location}::${name}`;
106
+ }
107
+
108
+ // src/hooks/use-injections-of.ts
109
+ var import_react3 = require("react");
110
+ function useInjectionsOf(locations) {
111
+ return (0, import_react3.useMemo)(
112
+ () => {
113
+ if (Array.isArray(locations)) {
114
+ return locations.map((location) => getInjectionsOf(location));
115
+ }
116
+ return getInjectionsOf(locations);
117
+ },
118
+ [locations]
119
+ );
120
+ }
121
+
122
+ // src/components/slot.tsx
123
+ var React3 = __toESM(require("react"));
124
+ function Slot({ location }) {
125
+ const injections2 = useInjectionsOf(location);
126
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, injections2.map(({ id, filler: Filler }) => /* @__PURE__ */ React3.createElement(Filler, { key: id })));
127
+ }
128
+ // Annotate the CommonJS export names for ESM import in node:
129
+ 0 && (module.exports = {
130
+ Slot,
131
+ createInjectorFor,
132
+ flushInjections,
133
+ getInjectionsOf,
134
+ inject,
135
+ useInjectionsOf
136
+ });
137
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts","../src/injections.tsx","../src/components/filler-wrapper.tsx","../src/components/error-boundary.tsx","../src/hooks/use-injections-of.ts","../src/components/slot.tsx"],"sourcesContent":["export * from './types';\nexport { inject, getInjectionsOf, flushInjections, createInjectorFor } from './injections';\nexport { default as useInjectionsOf } from './hooks/use-injections-of';\nexport { default as Slot } from './components/slot';\n","import * as React from 'react';\nimport { Location, Filler, Injection, InjectionOptions, Name, Id } from './types';\nimport FillerWrapper from './components/filler-wrapper';\n\nconst DEFAULT_PRIORITY = 10;\n\nconst injections: Map<Id, Injection> = new Map();\n\ntype InjectArgs = {\n\tlocation: Location;\n\tfiller: Filler;\n\tname: Name;\n\toptions?: InjectionOptions;\n}\n\nexport function inject( { location, filler, name, options = {} }: InjectArgs ) {\n\tconst id = generateId( location, name );\n\n\tif ( injections.has( id ) && ! options?.overwrite ) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.error(\n\t\t\t`An injection named \"${ name }\" under location \"${ location }\" already exists. Did you mean to use \"options.overwrite\"?`\n\t\t);\n\n\t\treturn;\n\t}\n\n\tconst injection = {\n\t\tid,\n\t\tlocation,\n\t\tfiller: wrapFiller( filler ),\n\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t};\n\n\tinjections.set( id, injection );\n}\n\nexport function createInjectorFor( location: Location ) {\n\treturn ( { filler, name, options }: Omit<InjectArgs, 'location'> ) => {\n\t\treturn inject( { location, name, filler, options } );\n\t};\n}\n\nexport function getInjectionsOf( location: string ) {\n\treturn [ ...injections.values() ]\n\t\t.filter( ( injection ) => injection.location === location )\n\t\t.sort( ( a, b ) => a.priority - b.priority );\n}\n\nexport function flushInjections() {\n\tinjections.clear();\n}\n\nfunction wrapFiller( FillerComponent: Filler ) {\n\treturn ( props: object ) => (\n\t\t<FillerWrapper>\n\t\t\t<FillerComponent { ...props } />\n\t\t</FillerWrapper>\n\t);\n}\n\nfunction generateId( location: Location, name: Name ) {\n\treturn `${ location }::${ name }`;\n}\n","import * as React from 'react';\nimport { ReactNode, Suspense } from 'react';\nimport ErrorBoundary from './error-boundary';\n\nexport default function FillerWrapper( { children }: { children: ReactNode } ) {\n\treturn (\n\t\t<ErrorBoundary fallback={ null }>\n\t\t\t<Suspense fallback={ null }>\n\t\t\t\t{ children }\n\t\t\t</Suspense>\n\t\t</ErrorBoundary>\n\t);\n}\n","import { Component, ReactNode } from 'react';\n\ninterface Props {\n\tchildren?: ReactNode;\n\tfallback: ReactNode;\n}\n\ninterface State {\n\thasError: boolean;\n}\n\nexport default class ErrorBoundary extends Component<Props, State> {\n\tpublic state: State = {\n\t\thasError: false,\n\t};\n\n\tpublic static getDerivedStateFromError(): State {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn { hasError: true };\n\t}\n\n\tpublic render() {\n\t\tif ( this.state.hasError ) {\n\t\t\treturn this.props.fallback;\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import { useMemo } from 'react';\nimport { getInjectionsOf } from '../injections';\nimport { Injection } from '../types';\n\nexport default function useInjectionsOf( locations: string[] ): Injection[][];\nexport default function useInjectionsOf( location: string ): Injection[];\nexport default function useInjectionsOf( locations: string | string[] ) {\n\treturn useMemo(\n\t\t() => {\n\t\t\tif ( Array.isArray( locations ) ) {\n\t\t\t\treturn locations.map( ( location ) => getInjectionsOf( location ) );\n\t\t\t}\n\n\t\t\treturn getInjectionsOf( locations );\n\t\t},\n\t\t[ locations ]\n\t);\n}\n","import * as React from 'react';\nimport useInjectionsOf from '../hooks/use-injections-of';\nimport { Location } from '../types';\n\ntype Props = {\n\tlocation: Location\n}\n\nexport default function Slot( { location }: Props ) {\n\tconst injections = useInjectionsOf( location );\n\n\treturn (\n\t\t<>\n\t\t\t{ injections.map( ( { id, filler: Filler } ) => (\n\t\t\t\t<Filler key={ id } />\n\t\t\t) ) }\n\t\t</>\n\t);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAA,IAAAA,SAAuB;;;ACAvB,YAAuB;AACvB,IAAAC,gBAAoC;;;ACDpC,mBAAqC;AAWrC,IAAqB,gBAArB,cAA2C,uBAAwB;AAAA,EAC3D,QAAe;AAAA,IACrB,UAAU;AAAA,EACX;AAAA,EAEA,OAAc,2BAAkC;AAE/C,WAAO,EAAE,UAAU,KAAK;AAAA,EACzB;AAAA,EAEO,SAAS;AACf,QAAK,KAAK,MAAM,UAAW;AAC1B,aAAO,KAAK,MAAM;AAAA,IACnB;AAEA,WAAO,KAAK,MAAM;AAAA,EACnB;AACD;;;ADxBe,SAAR,cAAgC,EAAE,SAAS,GAA6B;AAC9E,SACC,oCAAC,iBAAc,UAAW,QACzB,oCAAC,0BAAS,UAAW,QAClB,QACH,CACD;AAEF;;;ADRA,IAAM,mBAAmB;AAEzB,IAAM,aAAiC,oBAAI,IAAI;AASxC,SAAS,OAAQ,EAAE,UAAU,QAAQ,MAAM,UAAU,CAAC,EAAE,GAAgB;AAC9E,QAAM,KAAK,WAAY,UAAU,IAAK;AAEtC,MAAK,WAAW,IAAK,EAAG,KAAK,CAAE,SAAS,WAAY;AAEnD,YAAQ;AAAA,MACP,uBAAwB,yBAA2B;AAAA,IACpD;AAEA;AAAA,EACD;AAEA,QAAM,YAAY;AAAA,IACjB;AAAA,IACA;AAAA,IACA,QAAQ,WAAY,MAAO;AAAA,IAC3B,UAAU,QAAQ,YAAY;AAAA,EAC/B;AAEA,aAAW,IAAK,IAAI,SAAU;AAC/B;AAEO,SAAS,kBAAmB,UAAqB;AACvD,SAAO,CAAE,EAAE,QAAQ,MAAM,QAAQ,MAAqC;AACrE,WAAO,OAAQ,EAAE,UAAU,MAAM,QAAQ,QAAQ,CAAE;AAAA,EACpD;AACD;AAEO,SAAS,gBAAiB,UAAmB;AACnD,SAAO,CAAE,GAAG,WAAW,OAAO,CAAE,EAC9B,OAAQ,CAAE,cAAe,UAAU,aAAa,QAAS,EACzD,KAAM,CAAE,GAAG,MAAO,EAAE,WAAW,EAAE,QAAS;AAC7C;AAEO,SAAS,kBAAkB;AACjC,aAAW,MAAM;AAClB;AAEA,SAAS,WAAY,iBAA0B;AAC9C,SAAO,CAAE,UACR,qCAAC,qBACA,qCAAC,mBAAkB,GAAG,OAAQ,CAC/B;AAEF;AAEA,SAAS,WAAY,UAAoB,MAAa;AACrD,SAAO,GAAI,aAAe;AAC3B;;;AG/DA,IAAAC,gBAAwB;AAMT,SAAR,gBAAkC,WAA+B;AACvE,aAAO;AAAA,IACN,MAAM;AACL,UAAK,MAAM,QAAS,SAAU,GAAI;AACjC,eAAO,UAAU,IAAK,CAAE,aAAc,gBAAiB,QAAS,CAAE;AAAA,MACnE;AAEA,aAAO,gBAAiB,SAAU;AAAA,IACnC;AAAA,IACA,CAAE,SAAU;AAAA,EACb;AACD;;;ACjBA,IAAAC,SAAuB;AAQR,SAAR,KAAuB,EAAE,SAAS,GAAW;AACnD,QAAMC,cAAa,gBAAiB,QAAS;AAE7C,SACC,4DACGA,YAAW,IAAK,CAAE,EAAE,IAAI,QAAQ,OAAO,MACxC,qCAAC,UAAO,KAAM,IAAK,CAClB,CACH;AAEF;","names":["React","import_react","import_react","React","injections"]}
package/dist/index.mjs ADDED
@@ -0,0 +1,95 @@
1
+ // src/injections.tsx
2
+ import * as React2 from "react";
3
+
4
+ // src/components/filler-wrapper.tsx
5
+ import * as React from "react";
6
+ import { Suspense } from "react";
7
+
8
+ // src/components/error-boundary.tsx
9
+ import { Component } from "react";
10
+ var ErrorBoundary = class extends Component {
11
+ state = {
12
+ hasError: false
13
+ };
14
+ static getDerivedStateFromError() {
15
+ return { hasError: true };
16
+ }
17
+ render() {
18
+ if (this.state.hasError) {
19
+ return this.props.fallback;
20
+ }
21
+ return this.props.children;
22
+ }
23
+ };
24
+
25
+ // src/components/filler-wrapper.tsx
26
+ function FillerWrapper({ children }) {
27
+ return /* @__PURE__ */ React.createElement(ErrorBoundary, { fallback: null }, /* @__PURE__ */ React.createElement(Suspense, { fallback: null }, children));
28
+ }
29
+
30
+ // src/injections.tsx
31
+ var DEFAULT_PRIORITY = 10;
32
+ var injections = /* @__PURE__ */ new Map();
33
+ function inject({ location, filler, name, options = {} }) {
34
+ const id = generateId(location, name);
35
+ if (injections.has(id) && !options?.overwrite) {
36
+ console.error(
37
+ `An injection named "${name}" under location "${location}" already exists. Did you mean to use "options.overwrite"?`
38
+ );
39
+ return;
40
+ }
41
+ const injection = {
42
+ id,
43
+ location,
44
+ filler: wrapFiller(filler),
45
+ priority: options.priority ?? DEFAULT_PRIORITY
46
+ };
47
+ injections.set(id, injection);
48
+ }
49
+ function createInjectorFor(location) {
50
+ return ({ filler, name, options }) => {
51
+ return inject({ location, name, filler, options });
52
+ };
53
+ }
54
+ function getInjectionsOf(location) {
55
+ return [...injections.values()].filter((injection) => injection.location === location).sort((a, b) => a.priority - b.priority);
56
+ }
57
+ function flushInjections() {
58
+ injections.clear();
59
+ }
60
+ function wrapFiller(FillerComponent) {
61
+ return (props) => /* @__PURE__ */ React2.createElement(FillerWrapper, null, /* @__PURE__ */ React2.createElement(FillerComponent, { ...props }));
62
+ }
63
+ function generateId(location, name) {
64
+ return `${location}::${name}`;
65
+ }
66
+
67
+ // src/hooks/use-injections-of.ts
68
+ import { useMemo } from "react";
69
+ function useInjectionsOf(locations) {
70
+ return useMemo(
71
+ () => {
72
+ if (Array.isArray(locations)) {
73
+ return locations.map((location) => getInjectionsOf(location));
74
+ }
75
+ return getInjectionsOf(locations);
76
+ },
77
+ [locations]
78
+ );
79
+ }
80
+
81
+ // src/components/slot.tsx
82
+ import * as React3 from "react";
83
+ function Slot({ location }) {
84
+ const injections2 = useInjectionsOf(location);
85
+ return /* @__PURE__ */ React3.createElement(React3.Fragment, null, injections2.map(({ id, filler: Filler }) => /* @__PURE__ */ React3.createElement(Filler, { key: id })));
86
+ }
87
+ export {
88
+ Slot,
89
+ createInjectorFor,
90
+ flushInjections,
91
+ getInjectionsOf,
92
+ inject,
93
+ useInjectionsOf
94
+ };
95
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/injections.tsx","../src/components/filler-wrapper.tsx","../src/components/error-boundary.tsx","../src/hooks/use-injections-of.ts","../src/components/slot.tsx"],"sourcesContent":["import * as React from 'react';\nimport { Location, Filler, Injection, InjectionOptions, Name, Id } from './types';\nimport FillerWrapper from './components/filler-wrapper';\n\nconst DEFAULT_PRIORITY = 10;\n\nconst injections: Map<Id, Injection> = new Map();\n\ntype InjectArgs = {\n\tlocation: Location;\n\tfiller: Filler;\n\tname: Name;\n\toptions?: InjectionOptions;\n}\n\nexport function inject( { location, filler, name, options = {} }: InjectArgs ) {\n\tconst id = generateId( location, name );\n\n\tif ( injections.has( id ) && ! options?.overwrite ) {\n\t\t// eslint-disable-next-line no-console\n\t\tconsole.error(\n\t\t\t`An injection named \"${ name }\" under location \"${ location }\" already exists. Did you mean to use \"options.overwrite\"?`\n\t\t);\n\n\t\treturn;\n\t}\n\n\tconst injection = {\n\t\tid,\n\t\tlocation,\n\t\tfiller: wrapFiller( filler ),\n\t\tpriority: options.priority ?? DEFAULT_PRIORITY,\n\t};\n\n\tinjections.set( id, injection );\n}\n\nexport function createInjectorFor( location: Location ) {\n\treturn ( { filler, name, options }: Omit<InjectArgs, 'location'> ) => {\n\t\treturn inject( { location, name, filler, options } );\n\t};\n}\n\nexport function getInjectionsOf( location: string ) {\n\treturn [ ...injections.values() ]\n\t\t.filter( ( injection ) => injection.location === location )\n\t\t.sort( ( a, b ) => a.priority - b.priority );\n}\n\nexport function flushInjections() {\n\tinjections.clear();\n}\n\nfunction wrapFiller( FillerComponent: Filler ) {\n\treturn ( props: object ) => (\n\t\t<FillerWrapper>\n\t\t\t<FillerComponent { ...props } />\n\t\t</FillerWrapper>\n\t);\n}\n\nfunction generateId( location: Location, name: Name ) {\n\treturn `${ location }::${ name }`;\n}\n","import * as React from 'react';\nimport { ReactNode, Suspense } from 'react';\nimport ErrorBoundary from './error-boundary';\n\nexport default function FillerWrapper( { children }: { children: ReactNode } ) {\n\treturn (\n\t\t<ErrorBoundary fallback={ null }>\n\t\t\t<Suspense fallback={ null }>\n\t\t\t\t{ children }\n\t\t\t</Suspense>\n\t\t</ErrorBoundary>\n\t);\n}\n","import { Component, ReactNode } from 'react';\n\ninterface Props {\n\tchildren?: ReactNode;\n\tfallback: ReactNode;\n}\n\ninterface State {\n\thasError: boolean;\n}\n\nexport default class ErrorBoundary extends Component<Props, State> {\n\tpublic state: State = {\n\t\thasError: false,\n\t};\n\n\tpublic static getDerivedStateFromError(): State {\n\t\t// Update state so the next render will show the fallback UI.\n\t\treturn { hasError: true };\n\t}\n\n\tpublic render() {\n\t\tif ( this.state.hasError ) {\n\t\t\treturn this.props.fallback;\n\t\t}\n\n\t\treturn this.props.children;\n\t}\n}\n","import { useMemo } from 'react';\nimport { getInjectionsOf } from '../injections';\nimport { Injection } from '../types';\n\nexport default function useInjectionsOf( locations: string[] ): Injection[][];\nexport default function useInjectionsOf( location: string ): Injection[];\nexport default function useInjectionsOf( locations: string | string[] ) {\n\treturn useMemo(\n\t\t() => {\n\t\t\tif ( Array.isArray( locations ) ) {\n\t\t\t\treturn locations.map( ( location ) => getInjectionsOf( location ) );\n\t\t\t}\n\n\t\t\treturn getInjectionsOf( locations );\n\t\t},\n\t\t[ locations ]\n\t);\n}\n","import * as React from 'react';\nimport useInjectionsOf from '../hooks/use-injections-of';\nimport { Location } from '../types';\n\ntype Props = {\n\tlocation: Location\n}\n\nexport default function Slot( { location }: Props ) {\n\tconst injections = useInjectionsOf( location );\n\n\treturn (\n\t\t<>\n\t\t\t{ injections.map( ( { id, filler: Filler } ) => (\n\t\t\t\t<Filler key={ id } />\n\t\t\t) ) }\n\t\t</>\n\t);\n}\n"],"mappings":";AAAA,YAAYA,YAAW;;;ACAvB,YAAY,WAAW;AACvB,SAAoB,gBAAgB;;;ACDpC,SAAS,iBAA4B;AAWrC,IAAqB,gBAArB,cAA2C,UAAwB;AAAA,EAC3D,QAAe;AAAA,IACrB,UAAU;AAAA,EACX;AAAA,EAEA,OAAc,2BAAkC;AAE/C,WAAO,EAAE,UAAU,KAAK;AAAA,EACzB;AAAA,EAEO,SAAS;AACf,QAAK,KAAK,MAAM,UAAW;AAC1B,aAAO,KAAK,MAAM;AAAA,IACnB;AAEA,WAAO,KAAK,MAAM;AAAA,EACnB;AACD;;;ADxBe,SAAR,cAAgC,EAAE,SAAS,GAA6B;AAC9E,SACC,oCAAC,iBAAc,UAAW,QACzB,oCAAC,YAAS,UAAW,QAClB,QACH,CACD;AAEF;;;ADRA,IAAM,mBAAmB;AAEzB,IAAM,aAAiC,oBAAI,IAAI;AASxC,SAAS,OAAQ,EAAE,UAAU,QAAQ,MAAM,UAAU,CAAC,EAAE,GAAgB;AAC9E,QAAM,KAAK,WAAY,UAAU,IAAK;AAEtC,MAAK,WAAW,IAAK,EAAG,KAAK,CAAE,SAAS,WAAY;AAEnD,YAAQ;AAAA,MACP,uBAAwB,yBAA2B;AAAA,IACpD;AAEA;AAAA,EACD;AAEA,QAAM,YAAY;AAAA,IACjB;AAAA,IACA;AAAA,IACA,QAAQ,WAAY,MAAO;AAAA,IAC3B,UAAU,QAAQ,YAAY;AAAA,EAC/B;AAEA,aAAW,IAAK,IAAI,SAAU;AAC/B;AAEO,SAAS,kBAAmB,UAAqB;AACvD,SAAO,CAAE,EAAE,QAAQ,MAAM,QAAQ,MAAqC;AACrE,WAAO,OAAQ,EAAE,UAAU,MAAM,QAAQ,QAAQ,CAAE;AAAA,EACpD;AACD;AAEO,SAAS,gBAAiB,UAAmB;AACnD,SAAO,CAAE,GAAG,WAAW,OAAO,CAAE,EAC9B,OAAQ,CAAE,cAAe,UAAU,aAAa,QAAS,EACzD,KAAM,CAAE,GAAG,MAAO,EAAE,WAAW,EAAE,QAAS;AAC7C;AAEO,SAAS,kBAAkB;AACjC,aAAW,MAAM;AAClB;AAEA,SAAS,WAAY,iBAA0B;AAC9C,SAAO,CAAE,UACR,qCAAC,qBACA,qCAAC,mBAAkB,GAAG,OAAQ,CAC/B;AAEF;AAEA,SAAS,WAAY,UAAoB,MAAa;AACrD,SAAO,GAAI,aAAe;AAC3B;;;AG/DA,SAAS,eAAe;AAMT,SAAR,gBAAkC,WAA+B;AACvE,SAAO;AAAA,IACN,MAAM;AACL,UAAK,MAAM,QAAS,SAAU,GAAI;AACjC,eAAO,UAAU,IAAK,CAAE,aAAc,gBAAiB,QAAS,CAAE;AAAA,MACnE;AAEA,aAAO,gBAAiB,SAAU;AAAA,IACnC;AAAA,IACA,CAAE,SAAU;AAAA,EACb;AACD;;;ACjBA,YAAYC,YAAW;AAQR,SAAR,KAAuB,EAAE,SAAS,GAAW;AACnD,QAAMC,cAAa,gBAAiB,QAAS;AAE7C,SACC,4DACGA,YAAW,IAAK,CAAE,EAAE,IAAI,QAAQ,OAAO,MACxC,qCAAC,UAAO,KAAM,IAAK,CAClB,CACH;AAEF;","names":["React","React","injections"]}
package/package.json ADDED
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "@elementor/locations",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "author": "Elementor Team",
6
+ "homepage": "https://elementor.com/",
7
+ "license": "GPL-3.0-or-later",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.mjs",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.mjs",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
16
+ },
17
+ "./package.json": "./package.json"
18
+ },
19
+ "repository": {
20
+ "type": "git",
21
+ "url": "https://github.com/elementor/elementor-packages.git",
22
+ "directory": "packages/locations"
23
+ },
24
+ "bugs": {
25
+ "url": "https://github.com/elementor/elementor-packages/issues"
26
+ },
27
+ "publishConfig": {
28
+ "access": "public"
29
+ },
30
+ "scripts": {
31
+ "build": "tsup --config=../../tsup.build.ts",
32
+ "dev": "tsup --config=../../tsup.dev.ts"
33
+ },
34
+ "peerDependencies": {
35
+ "react": "17.x"
36
+ },
37
+ "gitHead": "2ba9f13a9dbd085eb6ed8e6e303e9275ce626b8d"
38
+ }
@@ -0,0 +1,217 @@
1
+ import * as React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import { lazy } from 'react';
4
+ import { inject, getInjectionsOf } from '../injections';
5
+ import Slot from '../components/slot';
6
+
7
+ describe( '@elementor/locations injections', () => {
8
+ it( 'should render components based on the location name', () => {
9
+ // Arrange.
10
+ inject( {
11
+ name: 'test-1',
12
+ location: 'test',
13
+ filler: () => <div data-testid="element">First div</div>,
14
+ } );
15
+
16
+ inject( {
17
+ name: 'test-2',
18
+ location: 'test',
19
+ filler: () => <div data-testid="element">Second div</div>,
20
+ } );
21
+
22
+ inject( {
23
+ name: 'test-3',
24
+ location: 'test2',
25
+ filler: () => <div data-testid="element">Should not exist</div>,
26
+ } );
27
+
28
+ // Act.
29
+ const { getAllByTestId } = render( <Slot location="test" /> );
30
+
31
+ // Assert.
32
+ const elements = getAllByTestId( 'element' );
33
+
34
+ expect( elements ).toHaveLength( 2 );
35
+ expect( elements[ 0 ].innerHTML ).toBe( 'First div' );
36
+ expect( elements[ 1 ].innerHTML ).toBe( 'Second div' );
37
+ } );
38
+
39
+ it( 'should render components based on priority', () => {
40
+ // Arrange.
41
+ inject( {
42
+ name: 'test-1',
43
+ location: 'test',
44
+ filler: () => <div data-testid="element">Third div</div>,
45
+ // Default priority is 10.
46
+ } );
47
+
48
+ inject( {
49
+ name: 'test-2',
50
+ location: 'test',
51
+ filler: () => <div data-testid="element">First div</div>,
52
+ options: { priority: 5 },
53
+ } );
54
+
55
+ inject( {
56
+ name: 'test-3',
57
+ location: 'test',
58
+ filler: () => <div data-testid="element">Second div</div>,
59
+ options: { priority: 5 },
60
+ } );
61
+
62
+ // Act.
63
+ const { getAllByTestId } = render( <Slot location="test" /> );
64
+
65
+ // Assert.
66
+ const elements = getAllByTestId( 'element' );
67
+
68
+ expect( elements ).toHaveLength( 3 );
69
+ expect( elements[ 0 ].innerHTML ).toBe( 'First div' );
70
+ expect( elements[ 1 ].innerHTML ).toBe( 'Second div' );
71
+ expect( elements[ 2 ].innerHTML ).toBe( 'Third div' );
72
+ } );
73
+
74
+ it( 'should render empty slot when there are no fills', () => {
75
+ // Arrange + Act.
76
+ const { container } = render( <Slot location="empty" /> );
77
+
78
+ // Assert.
79
+ expect( container.innerHTML ).toBe( '' );
80
+ } );
81
+
82
+ it( 'should render lazy components', async () => {
83
+ // Arrange.
84
+ inject( {
85
+ name: 'test-1',
86
+ location: 'test',
87
+ filler: () => <div>First div</div>,
88
+ } );
89
+
90
+ inject( {
91
+ name: 'test-2',
92
+ location: 'test',
93
+ filler: lazy( () => Promise.resolve( {
94
+ default: () => <div>Second div</div>,
95
+ } ) ),
96
+ } );
97
+
98
+ // Act.
99
+ const { queryByText, findByText } = render( <Slot location="test" /> );
100
+
101
+ // Assert.
102
+ expect( queryByText( 'First div' ) ).toBeTruthy();
103
+ expect( queryByText( 'Second div' ) ).toBeNull();
104
+
105
+ // Waits for the lazy component to be loaded.
106
+ await findByText( 'Second div' );
107
+
108
+ expect( queryByText( 'First div' ) ).toBeTruthy();
109
+ expect( queryByText( 'Second div' ) ).toBeTruthy();
110
+ } );
111
+
112
+ it( 'should error when injecting filler with the same name (without overwrite option)', async () => {
113
+ // Arrange.
114
+ inject( {
115
+ name: 'test',
116
+ location: 'test',
117
+ filler: () => <div>First div</div>,
118
+ } );
119
+
120
+ inject( {
121
+ name: 'test',
122
+ location: 'test',
123
+ filler: () => <div>Second div</div>,
124
+ } );
125
+
126
+ // Act
127
+ const { queryByText } = render( <Slot location="test" /> );
128
+
129
+ // Assert.
130
+ expect( queryByText( 'First div' ) ).toBeTruthy();
131
+ expect( queryByText( 'Second div' ) ).toBeNull();
132
+ expect( console ).toHaveErrored();
133
+ } );
134
+
135
+ it( 'should overwrite the filler if has same name', async () => {
136
+ // Arrange.
137
+ inject( {
138
+ name: 'test',
139
+ location: 'test',
140
+ filler: () => <div>First div</div>,
141
+ } );
142
+
143
+ inject( {
144
+ name: 'test',
145
+ location: 'test',
146
+ filler: () => <div>Second div</div>,
147
+ options: { overwrite: true },
148
+ } );
149
+
150
+ inject( {
151
+ name: 'test-2',
152
+ location: 'test',
153
+ filler: () => <div>Third div</div>,
154
+ options: { overwrite: true },
155
+ } );
156
+
157
+ // Act
158
+ const { queryByText } = render( <Slot location="test" /> );
159
+
160
+ // Assert.
161
+ expect( queryByText( 'First div' ) ).toBeNull();
162
+ expect( queryByText( 'Second div' ) ).toBeTruthy();
163
+ expect( queryByText( 'Third div' ) ).toBeTruthy();
164
+ } );
165
+
166
+ it( 'should overwrite the injection priority', () => {
167
+ // Arrange.
168
+ inject( {
169
+ name: 'test-1',
170
+ location: 'test',
171
+ filler: () => <div />,
172
+ options: { priority: 5 },
173
+ } );
174
+
175
+ inject( {
176
+ name: 'test-1',
177
+ location: 'test',
178
+ filler: () => <div />,
179
+ options: { overwrite: true },
180
+ } );
181
+
182
+ // Act + Assert.
183
+ expect( getInjectionsOf( 'test' ) ).toHaveLength( 1 );
184
+ expect( getInjectionsOf( 'test' )[ 0 ].priority ).toBe( 10 );
185
+ } );
186
+
187
+ it( 'should catch filler errors with error boundary', () => {
188
+ // Arrange.
189
+ inject( {
190
+ name: 'test-1',
191
+ location: 'test',
192
+ filler: () => <div>Test 1</div>,
193
+ } );
194
+
195
+ inject( {
196
+ name: 'test-2',
197
+ location: 'test',
198
+ filler: () => {
199
+ throw new Error( 'Error' );
200
+ },
201
+ } );
202
+
203
+ inject( {
204
+ name: 'test-3',
205
+ location: 'test',
206
+ filler: () => <div>Test 3</div>,
207
+ } );
208
+
209
+ // Act.
210
+ const { queryByText } = render( <Slot location="test" /> );
211
+
212
+ // Assert.
213
+ expect( queryByText( 'Test 1' ) ).toBeTruthy();
214
+ expect( queryByText( 'Test 3' ) ).toBeTruthy();
215
+ expect( console ).toHaveErrored();
216
+ } );
217
+ } );
@@ -0,0 +1,29 @@
1
+ import { Component, ReactNode } from 'react';
2
+
3
+ interface Props {
4
+ children?: ReactNode;
5
+ fallback: ReactNode;
6
+ }
7
+
8
+ interface State {
9
+ hasError: boolean;
10
+ }
11
+
12
+ export default class ErrorBoundary extends Component<Props, State> {
13
+ public state: State = {
14
+ hasError: false,
15
+ };
16
+
17
+ public static getDerivedStateFromError(): State {
18
+ // Update state so the next render will show the fallback UI.
19
+ return { hasError: true };
20
+ }
21
+
22
+ public render() {
23
+ if ( this.state.hasError ) {
24
+ return this.props.fallback;
25
+ }
26
+
27
+ return this.props.children;
28
+ }
29
+ }
@@ -0,0 +1,13 @@
1
+ import * as React from 'react';
2
+ import { ReactNode, Suspense } from 'react';
3
+ import ErrorBoundary from './error-boundary';
4
+
5
+ export default function FillerWrapper( { children }: { children: ReactNode } ) {
6
+ return (
7
+ <ErrorBoundary fallback={ null }>
8
+ <Suspense fallback={ null }>
9
+ { children }
10
+ </Suspense>
11
+ </ErrorBoundary>
12
+ );
13
+ }
@@ -0,0 +1,19 @@
1
+ import * as React from 'react';
2
+ import useInjectionsOf from '../hooks/use-injections-of';
3
+ import { Location } from '../types';
4
+
5
+ type Props = {
6
+ location: Location
7
+ }
8
+
9
+ export default function Slot( { location }: Props ) {
10
+ const injections = useInjectionsOf( location );
11
+
12
+ return (
13
+ <>
14
+ { injections.map( ( { id, filler: Filler } ) => (
15
+ <Filler key={ id } />
16
+ ) ) }
17
+ </>
18
+ );
19
+ }
@@ -0,0 +1,18 @@
1
+ import { useMemo } from 'react';
2
+ import { getInjectionsOf } from '../injections';
3
+ import { Injection } from '../types';
4
+
5
+ export default function useInjectionsOf( locations: string[] ): Injection[][];
6
+ export default function useInjectionsOf( location: string ): Injection[];
7
+ export default function useInjectionsOf( locations: string | string[] ) {
8
+ return useMemo(
9
+ () => {
10
+ if ( Array.isArray( locations ) ) {
11
+ return locations.map( ( location ) => getInjectionsOf( location ) );
12
+ }
13
+
14
+ return getInjectionsOf( locations );
15
+ },
16
+ [ locations ]
17
+ );
18
+ }
package/src/index.ts ADDED
@@ -0,0 +1,4 @@
1
+ export * from './types';
2
+ export { inject, getInjectionsOf, flushInjections, createInjectorFor } from './injections';
3
+ export { default as useInjectionsOf } from './hooks/use-injections-of';
4
+ export { default as Slot } from './components/slot';