@financial-times/custom-code-component 1.0.6 → 1.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.
- package/dist/custom-code-component.d.ts +21 -0
- package/dist/custom-code-component.js +64 -0
- package/package.json +6 -2
- package/src/custom-code-component.ts +5 -2
- package/.eslintignore +0 -1
- package/.eslintrc.cjs +0 -23
- package/index.html +0 -22
- package/test/fixture.xml +0 -21
- package/test/styles.css +0 -6
- package/test/test16.jsx +0 -31
- package/test/test18.jsx +0 -29
- package/test.json +0 -1
- package/vite.config.js +0 -18
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file
|
|
3
|
+
* Main component definition for custom-code-component
|
|
4
|
+
*/
|
|
5
|
+
import { ContentTree } from "@financial-times/content-tree";
|
|
6
|
+
export declare const init: () => void;
|
|
7
|
+
export interface CustomCodeComponent extends ContentTree.Node {
|
|
8
|
+
type: "CustomCodeComponent";
|
|
9
|
+
path: string;
|
|
10
|
+
versionRange: string;
|
|
11
|
+
altText: string;
|
|
12
|
+
lastModified: string;
|
|
13
|
+
fallbackImage?: ContentTree.Image;
|
|
14
|
+
displayFallbackText: boolean;
|
|
15
|
+
layout: "in-line" | "mid-grid" | "full-grid" | "full-bleed";
|
|
16
|
+
attributes: {
|
|
17
|
+
[key: string]: string | boolean | undefined;
|
|
18
|
+
} | {
|
|
19
|
+
children?: CustomCodeComponent | Array<CustomCodeComponent>;
|
|
20
|
+
};
|
|
21
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
class l extends HTMLElement {
|
|
2
|
+
constructor() {
|
|
3
|
+
super(...arguments), this.RESERVED_ATTRS = /* @__PURE__ */ new Set([
|
|
4
|
+
"iframe",
|
|
5
|
+
"path",
|
|
6
|
+
"version",
|
|
7
|
+
"data-component-props",
|
|
8
|
+
"data-asset-type",
|
|
9
|
+
"shadow-open",
|
|
10
|
+
"env"
|
|
11
|
+
]), this.unmount = () => {
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
async connectedCallback() {
|
|
15
|
+
var m;
|
|
16
|
+
const e = this.getAttribute("path"), c = this.hasAttribute("shadow-open") ? "open" : "closed", a = this.getAttribute("version"), p = (m = this.getAttribute("env")) == null ? void 0 : m.toLowerCase().startsWith("d");
|
|
17
|
+
if (!e)
|
|
18
|
+
throw new Error(
|
|
19
|
+
"path attribute not specified in <custom-code-component>"
|
|
20
|
+
);
|
|
21
|
+
const [n, i, r] = e.split("/").reverse();
|
|
22
|
+
if (!n || !i || !r)
|
|
23
|
+
return;
|
|
24
|
+
const d = p ? `http://localhost:5173/src/${n}/index.jsx` : `https://www.ft.com/__component/${r}/${i}${a ? `@${a}` : "@latest"}/${n}/${n}.js`;
|
|
25
|
+
try {
|
|
26
|
+
const s = await import(
|
|
27
|
+
/* webpackIgnore: true */
|
|
28
|
+
d
|
|
29
|
+
/* @vite-ignore */
|
|
30
|
+
), h = JSON.parse(this.getAttribute("data-component-props")), u = Object.fromEntries(
|
|
31
|
+
[...this.attributes].filter((t) => !this.RESERVED_ATTRS.has(t.name)).map((t) => [t.name, t.value])
|
|
32
|
+
);
|
|
33
|
+
if (this.hasAttribute("iframe")) {
|
|
34
|
+
const t = document.createElement("iframe");
|
|
35
|
+
t.addEventListener("load", () => {
|
|
36
|
+
const o = s.default(
|
|
37
|
+
t.contentDocument,
|
|
38
|
+
{ ...u, data: h },
|
|
39
|
+
...this.children
|
|
40
|
+
);
|
|
41
|
+
o && (this.unmount = o);
|
|
42
|
+
}), this.attachShadow({ mode: c }).append(t);
|
|
43
|
+
} else {
|
|
44
|
+
const t = this.attachShadow({ mode: c }), o = await s.default(
|
|
45
|
+
t,
|
|
46
|
+
{ ...u, data: h },
|
|
47
|
+
...this.children
|
|
48
|
+
);
|
|
49
|
+
o && (this.unmount = o);
|
|
50
|
+
}
|
|
51
|
+
} catch (s) {
|
|
52
|
+
console.info(`<custom-code-component> uncaught error from ${e}: `, s);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
async disconnectedCallback() {
|
|
56
|
+
const e = this.getAttribute("path");
|
|
57
|
+
console.info(`<custom-code-component:${e}> disconnected`), this.unmount();
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
const f = () => customElements.define("custom-code-component", l);
|
|
61
|
+
customElements && !customElements.get("custom-code-component") && f();
|
|
62
|
+
export {
|
|
63
|
+
f as init
|
|
64
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@financial-times/custom-code-component",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -36,5 +36,9 @@
|
|
|
36
36
|
"react16": {
|
|
37
37
|
"react-dom": "react-dom16"
|
|
38
38
|
}
|
|
39
|
-
}
|
|
39
|
+
},
|
|
40
|
+
"files": [
|
|
41
|
+
"dist",
|
|
42
|
+
"src"
|
|
43
|
+
]
|
|
40
44
|
}
|
|
@@ -16,6 +16,8 @@ class FTCustomCodeComponent extends HTMLElement {
|
|
|
16
16
|
"env",
|
|
17
17
|
]);
|
|
18
18
|
|
|
19
|
+
unmount = () => {};
|
|
20
|
+
|
|
19
21
|
async connectedCallback() {
|
|
20
22
|
const path = this.getAttribute("path");
|
|
21
23
|
const mode = this.hasAttribute("shadow-open") ? "open" : "closed";
|
|
@@ -64,7 +66,7 @@ class FTCustomCodeComponent extends HTMLElement {
|
|
|
64
66
|
...this.children
|
|
65
67
|
);
|
|
66
68
|
|
|
67
|
-
if (unmount) this.
|
|
69
|
+
if (unmount) this.unmount = unmount;
|
|
68
70
|
});
|
|
69
71
|
|
|
70
72
|
this.attachShadow({ mode }).append(mountPoint);
|
|
@@ -77,7 +79,7 @@ class FTCustomCodeComponent extends HTMLElement {
|
|
|
77
79
|
...this.children
|
|
78
80
|
);
|
|
79
81
|
|
|
80
|
-
if (unmount) this.
|
|
82
|
+
if (unmount) this.unmount = unmount;
|
|
81
83
|
}
|
|
82
84
|
} catch (e) {
|
|
83
85
|
console.info(`<custom-code-component> uncaught error from ${path}: `, e);
|
|
@@ -87,6 +89,7 @@ class FTCustomCodeComponent extends HTMLElement {
|
|
|
87
89
|
async disconnectedCallback() {
|
|
88
90
|
const path = this.getAttribute("path");
|
|
89
91
|
console.info(`<custom-code-component:${path}> disconnected`);
|
|
92
|
+
this.unmount();
|
|
90
93
|
}
|
|
91
94
|
}
|
|
92
95
|
|
package/.eslintignore
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
dist
|
package/.eslintrc.cjs
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
module.exports = {
|
|
2
|
-
env: {
|
|
3
|
-
browser: true,
|
|
4
|
-
es2021: true,
|
|
5
|
-
},
|
|
6
|
-
extends: ["eslint:recommended", "plugin:react/recommended"],
|
|
7
|
-
overrides: [
|
|
8
|
-
{
|
|
9
|
-
env: {
|
|
10
|
-
node: true,
|
|
11
|
-
},
|
|
12
|
-
files: [".eslintrc.{js,cjs}"],
|
|
13
|
-
parserOptions: {
|
|
14
|
-
sourceType: "script",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
],
|
|
18
|
-
parserOptions: {
|
|
19
|
-
ecmaVersion: "latest",
|
|
20
|
-
sourceType: "module",
|
|
21
|
-
},
|
|
22
|
-
rules: {},
|
|
23
|
-
};
|
package/index.html
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
<!doctype html>
|
|
2
|
-
<html lang="en">
|
|
3
|
-
<head>
|
|
4
|
-
<meta charset="UTF-8" />
|
|
5
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
-
<title>custom-code-component loader</title>
|
|
7
|
-
</head>
|
|
8
|
-
<body>
|
|
9
|
-
<custom-code-component
|
|
10
|
-
src="../test/test16.jsx"
|
|
11
|
-
data='{"jsonWorks": true}'
|
|
12
|
-
extra="test 1"
|
|
13
|
-
></custom-code-component>
|
|
14
|
-
<custom-code-component
|
|
15
|
-
src="../test/test18.jsx"
|
|
16
|
-
data="./test.json"
|
|
17
|
-
extra="test 2"
|
|
18
|
-
></custom-code-component>
|
|
19
|
-
|
|
20
|
-
<script type="module" src="./src/custom-code-component.js"></script>
|
|
21
|
-
</body>
|
|
22
|
-
</html>
|
package/test/fixture.xml
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
<?xml-model href="../src/custom-code-component.xsd"?>
|
|
2
|
-
|
|
3
|
-
<custom-code-component
|
|
4
|
-
path="Financial-Times/awesome-component"
|
|
5
|
-
versionRange="^0.3.5"
|
|
6
|
-
altText="awesome component"
|
|
7
|
-
lastModifiedTimestamp="2024-01-26T03:25Z"
|
|
8
|
-
fallbackImageURL="https://picsum.photos/200/300"
|
|
9
|
-
layout="in-line"
|
|
10
|
-
attributes='{"test": "data"}'
|
|
11
|
-
>
|
|
12
|
-
<custom-code-component
|
|
13
|
-
path="Financial-Times/awesome-child-component"
|
|
14
|
-
versionRange="^0.3.5"
|
|
15
|
-
altText="awesome child component"
|
|
16
|
-
lastModifiedTimestamp="2024-01-26T03:25Z"
|
|
17
|
-
fallbackImageURL="https://picsum.photos/100/100"
|
|
18
|
-
displayFallbackText="true"
|
|
19
|
-
attributes='{"test2": "data2"}'
|
|
20
|
-
/>
|
|
21
|
-
</custom-code-component>
|
package/test/styles.css
DELETED
package/test/test16.jsx
DELETED
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import React from "react16";
|
|
2
|
-
import ReactDOM from "react-dom16";
|
|
3
|
-
import css from "./styles.css?inline";
|
|
4
|
-
|
|
5
|
-
// eslint-disable-next-line react/prop-types
|
|
6
|
-
const App = ({ children, ...props }) => (
|
|
7
|
-
<div>
|
|
8
|
-
<h1>React 16 component</h1>
|
|
9
|
-
{JSON.stringify(props)}
|
|
10
|
-
{children}
|
|
11
|
-
</div>
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
export default async (shadowRoot, props, ...children) => {
|
|
15
|
-
const style = document.createElement("style");
|
|
16
|
-
const mountPoint = document.createElement("div");
|
|
17
|
-
|
|
18
|
-
style.innerHTML = css;
|
|
19
|
-
mountPoint.id = "component-root";
|
|
20
|
-
|
|
21
|
-
shadowRoot.appendChild(style);
|
|
22
|
-
shadowRoot.appendChild(mountPoint);
|
|
23
|
-
|
|
24
|
-
// eslint-disable-next-line react/no-deprecated
|
|
25
|
-
ReactDOM.render(
|
|
26
|
-
<React.StrictMode>
|
|
27
|
-
<App {...props}>{children}</App>
|
|
28
|
-
</React.StrictMode>,
|
|
29
|
-
mountPoint
|
|
30
|
-
);
|
|
31
|
-
};
|
package/test/test18.jsx
DELETED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
import React from "react";
|
|
2
|
-
import ReactDOM from "react-dom/client";
|
|
3
|
-
import css from "./styles.css?inline";
|
|
4
|
-
|
|
5
|
-
// eslint-disable-next-line react/prop-types
|
|
6
|
-
const App = ({ children, ...props }) => (
|
|
7
|
-
<>
|
|
8
|
-
<h1>React 18 component</h1>
|
|
9
|
-
{JSON.stringify(props)}
|
|
10
|
-
{children}
|
|
11
|
-
</>
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
export default (shadowRoot, props, ...children) => {
|
|
15
|
-
const style = document.createElement("style");
|
|
16
|
-
const mountPoint = document.createElement("div");
|
|
17
|
-
|
|
18
|
-
style.innerHTML = css;
|
|
19
|
-
mountPoint.id = "component-root";
|
|
20
|
-
|
|
21
|
-
shadowRoot.appendChild(style);
|
|
22
|
-
shadowRoot.appendChild(mountPoint);
|
|
23
|
-
|
|
24
|
-
ReactDOM.createRoot(mountPoint).render(
|
|
25
|
-
<React.StrictMode>
|
|
26
|
-
<App {...props}>{children}</App>
|
|
27
|
-
</React.StrictMode>
|
|
28
|
-
);
|
|
29
|
-
};
|
package/test.json
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{ "hasJSON": true }
|
package/vite.config.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
// Vite.config.js
|
|
2
|
-
import { defineConfig } from "vite";
|
|
3
|
-
import react from "@vitejs/plugin-react";
|
|
4
|
-
import { basename } from "path";
|
|
5
|
-
import dts from "vite-plugin-dts";
|
|
6
|
-
|
|
7
|
-
export default defineConfig({
|
|
8
|
-
build: {
|
|
9
|
-
lib: {
|
|
10
|
-
// Could also be a dictionary or array of multiple entry points
|
|
11
|
-
entry: "./src/custom-code-component.ts",
|
|
12
|
-
formats: ["es"],
|
|
13
|
-
fileName: (format, entry) => `${basename(entry)}.js`,
|
|
14
|
-
name: "CustomCodeComponent",
|
|
15
|
-
},
|
|
16
|
-
},
|
|
17
|
-
plugins: [react(), dts()],
|
|
18
|
-
});
|