@financial-times/custom-code-component 0.0.9 → 1.0.1

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.
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file
3
- * Main component definition for g-react-loader
3
+ * Main component definition for custom-code-component
4
4
  */
5
5
  import { ContentTree } from "@financial-times/content-tree";
6
6
  export declare const init: () => void;
@@ -9,7 +9,13 @@ export interface CustomCodeComponent extends ContentTree.Node {
9
9
  path: string;
10
10
  versionRange: string;
11
11
  altText: string;
12
- timestamp?: string;
12
+ lastModified: string;
13
13
  fallbackImage?: ContentTree.Image;
14
- attributes?: [string, string][];
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
+ };
15
21
  }
@@ -11,36 +11,39 @@ class u extends HTMLElement {
11
11
  ]);
12
12
  }
13
13
  async connectedCallback() {
14
- var a;
15
- const n = this.getAttribute("path"), s = this.hasAttribute("shadow-open") ? "open" : "closed", c = this.getAttribute("version"), m = (a = this.getAttribute("env")) == null ? void 0 : a.toLowerCase().startsWith("d");
14
+ var i;
15
+ const n = this.getAttribute("path"), s = this.hasAttribute("shadow-open") ? "open" : "closed", c = this.getAttribute("version"), h = (i = this.getAttribute("env")) == null ? void 0 : i.toLowerCase().startsWith("d");
16
16
  if (!n)
17
17
  throw new Error(
18
18
  "path attribute not specified in <custom-code-component>"
19
19
  );
20
- const [o, p, h] = n.split("/").reverse(), d = m ? `http://localhost:5173/src/${o}/index.jsx` : `https://www.ft.com/__component/${h}/${p}/${o}${c ? `@${c}` : "@latest"}/${o}.js`;
20
+ const [e, a, r] = n.split("/").reverse();
21
+ if (!e || !a || !r)
22
+ return;
23
+ const d = h ? `http://localhost:5173/src/${e}/index.jsx` : `https://www.ft.com/__component/${r}/${a}${c ? `@${c}` : "@latest"}/${e}/${e}.js`;
21
24
  try {
22
- const e = await import(
25
+ const o = await import(
23
26
  /* webpackIgnore: true */
24
27
  d
25
28
  /* @vite-ignore */
26
- ), i = JSON.parse(this.getAttribute("data-component-props")), r = Object.fromEntries(
29
+ ), m = JSON.parse(this.getAttribute("data-component-props")), p = Object.fromEntries(
27
30
  [...this.attributes].filter((t) => !this.RESERVED_ATTRS.has(t.name)).map((t) => [t.name, t.value])
28
31
  );
29
32
  if (this.hasAttribute("iframe")) {
30
33
  const t = document.createElement("iframe");
31
34
  t.addEventListener("load", () => {
32
- e.default(
35
+ o.default(
33
36
  t.contentDocument,
34
- { ...r, data: i },
37
+ { ...p, data: m },
35
38
  ...this.children
36
39
  );
37
40
  }), this.attachShadow({ mode: s }).append(t);
38
41
  } else {
39
42
  const t = this.attachShadow({ mode: s });
40
- e.default(t, { ...r, data: i }, ...this.children);
43
+ o.default(t, { ...p, data: m }, ...this.children);
41
44
  }
42
- } catch (e) {
43
- console.info("<custom-code-component> caught: ", e);
45
+ } catch (o) {
46
+ console.info(`<custom-code-component> uncaught error from ${n}: `, o);
44
47
  }
45
48
  }
46
49
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@financial-times/custom-code-component",
3
- "version": "0.0.9",
3
+ "version": "1.0.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -18,7 +18,6 @@
18
18
  "@vitejs/plugin-react": "^4.0.4",
19
19
  "eslint": "^8.47.0",
20
20
  "eslint-plugin-react": "^7.33.1",
21
- "prettier": "^3.0.1",
22
21
  "react-dom16": "npm:react-dom@^16.14.0",
23
22
  "react16": "npm:react@^16.14.0",
24
23
  "typescript": "^5.2.2",
@@ -29,6 +28,10 @@
29
28
  "react": "^18.2.0",
30
29
  "react-dom": "^18.2.0"
31
30
  },
31
+ "files": [
32
+ "dist",
33
+ "src"
34
+ ],
32
35
  "overrides": {
33
36
  "react-dom16": {
34
37
  "react": "react16"
@@ -1,6 +1,6 @@
1
1
  /**
2
2
  * @file
3
- * Main component definition for g-react-loader
3
+ * Main component definition for custom-code-component
4
4
  */
5
5
 
6
6
  import { ContentTree } from "@financial-times/content-tree";
@@ -33,11 +33,14 @@ class FTCustomCodeComponent extends HTMLElement {
33
33
  .split("/")
34
34
  .reverse();
35
35
 
36
+ if (!componentName || !componentRepo || !componentOrg) return;
37
+
36
38
  const source = useLocalVersion
37
39
  ? `http://localhost:5173/src/${componentName}/index.jsx`
38
- : `https://www.ft.com/__component/${componentOrg}/${componentRepo}/${componentName}${
40
+ : `https://www.ft.com/__component/${componentOrg}/${componentRepo}${
39
41
  componentVersionRange ? `@${componentVersionRange}` : "@latest"
40
- }/${componentName}.js`;
42
+ }/${componentName}/${componentName}.js`;
43
+
41
44
  try {
42
45
  const App = await import(
43
46
  /* webpackIgnore: true */ source /* @vite-ignore */
@@ -69,14 +72,16 @@ class FTCustomCodeComponent extends HTMLElement {
69
72
  App.default(shadowRoot, { ...extraProps, data }, ...this.children);
70
73
  }
71
74
  } catch (e) {
72
- console.info("<custom-code-component> caught: ", e);
75
+ console.info(`<custom-code-component> uncaught error from ${path}: `, e);
73
76
  }
74
77
  }
75
78
  }
76
79
 
80
+ // Register the custom element
77
81
  export const init = () =>
78
82
  customElements.define("custom-code-component", FTCustomCodeComponent);
79
83
 
84
+ // Allows module to be imported multiple times but custom element only registered once
80
85
  if (customElements && !customElements.get("custom-code-component")) init();
81
86
 
82
87
  export interface CustomCodeComponent extends ContentTree.Node {
@@ -84,7 +89,12 @@ export interface CustomCodeComponent extends ContentTree.Node {
84
89
  path: string;
85
90
  versionRange: string;
86
91
  altText: string;
87
- timestamp?: string;
92
+ lastModified: string;
88
93
  fallbackImage?: ContentTree.Image;
89
- attributes?: [string, string][];
94
+ displayFallbackText: boolean;
95
+ layout: "in-line" | "mid-grid" | "full-grid" | "full-bleed";
96
+ /* prettier-ignore */
97
+ attributes: {
98
+ [key: string]: string | boolean | undefined;
99
+ } | { children?: CustomCodeComponent | Array<CustomCodeComponent> };
90
100
  }
@@ -0,0 +1,67 @@
1
+ <?xml version="1.0"?>
2
+
3
+ <xs:schema
4
+ xmlns:xs="http://www.w3.org/2001/XMLSchema"
5
+ xmlns:sch="http://purl.oclc.org/dsdl/schematron"
6
+ >
7
+ <xs:complexType name="CustomCodeComponent">
8
+ <xs:sequence minOccurs="0">
9
+ <xs:element
10
+ name="custom-code-component"
11
+ type="CustomCodeComponent"
12
+ maxOccurs="unbounded"
13
+ />
14
+ </xs:sequence>
15
+ <xs:attribute
16
+ name="path"
17
+ type="xs:anyURI"
18
+ use="required"
19
+ />
20
+ <xs:attribute
21
+ name="versionRange"
22
+ type="xs:string"
23
+ use="required"
24
+ />
25
+ <xs:attribute
26
+ name="altText"
27
+ type="xs:string"
28
+ use="required"
29
+ />
30
+ <xs:attribute
31
+ name="lastModifiedTimestamp"
32
+ type="xs:string"
33
+ use="required"
34
+ />
35
+ <xs:attribute
36
+ name="fallbackImageURL"
37
+ type="xs:string"
38
+ />
39
+ <xs:attribute
40
+ name="displayFallbackText"
41
+ type="xs:boolean"
42
+ default="false"
43
+ />
44
+ <xs:attribute
45
+ name="layout"
46
+ default="in-line"
47
+ >
48
+ <xs:simpleType>
49
+ <xs:restriction base="xs:string">
50
+ <xs:enumeration value="in-line" />
51
+ <xs:enumeration value="mid-grid" />
52
+ <xs:enumeration value="full-grid" />
53
+ <xs:enumeration value="full-bleed" />
54
+ </xs:restriction>
55
+ </xs:simpleType>
56
+ </xs:attribute>
57
+ <xs:attribute
58
+ name="attributes"
59
+ type="xs:string"
60
+ default="{}"
61
+ />
62
+ </xs:complexType>
63
+ <xs:element
64
+ name="custom-code-component"
65
+ type="CustomCodeComponent"
66
+ />
67
+ </xs:schema>
@@ -1,44 +0,0 @@
1
- version: 2.1
2
-
3
- orbs:
4
- node: circleci/node@5.1.0
5
- doppler-circleci: ft-circleci-orbs/doppler-circleci@1.3
6
-
7
- references:
8
- default_container_config: &default_container_config
9
- executor:
10
- name: node/default
11
- tag: 'lts'
12
-
13
- only_version_tags: &only_version_tags
14
- tags:
15
- only: /^v.*/
16
- branches:
17
- ignore: /.*/
18
-
19
- jobs:
20
- build:
21
- <<: *default_container_config
22
- steps:
23
- - checkout
24
- - doppler-circleci/install
25
- - doppler-circleci/load_secrets:
26
- doppler_token: DOPPLER_TOKEN_VS_COMPONENTS
27
- - run:
28
- name: Install dependencies
29
- command: npm install
30
- - run:
31
- name: Publish package
32
- command: |
33
- npm set @Financial-Times:registry=https://npm.pkg.github.com/
34
- npm set //npm.pkg.github.com/:_authToken=${GPR_WRITE_AUTH_TOKEN}
35
- npm publish
36
-
37
- workflows:
38
- build-and-release:
39
- jobs:
40
- - build:
41
- context:
42
- - djd-starter-kit-s3-deployment # context is named the same in both orgs
43
- filters:
44
- <<: *only_version_tags
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
- };
@@ -1 +0,0 @@
1
- * @Financial-Times/visual-data-journalism-admins
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/styles.css DELETED
@@ -1,6 +0,0 @@
1
- @import url("https://www.ft.com/__origami/service/build/v3/bundles/css?components=o-fonts@^5&brand=core&system_code=djd-projects");
2
-
3
- :host {
4
- background: 'transparent';
5
- font-family: 'Metric', 'MetricWeb';
6
- }
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
- });