From ce2e41d61d2e266a8462776bff89cf1ddf2b21f5 Mon Sep 17 00:00:00 2001 From: Sergo Date: Thu, 25 Jun 2020 11:56:22 +0300 Subject: [PATCH] Add frame component (#76) --- .eslintrc.json | 3 +- .gitignore | 1 + package-lock.json | 2 +- package.json | 2 +- rollup.js | 2 +- src/packages/frame/frame.jsx | 120 +++++++++++++++++++++++++++++++++++ src/packages/frame/frame.md | 1 + 7 files changed, 127 insertions(+), 4 deletions(-) create mode 100644 src/packages/frame/frame.jsx create mode 100644 src/packages/frame/frame.md diff --git a/.eslintrc.json b/.eslintrc.json index efb57487..558afada 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -5,6 +5,7 @@ "jquery": true }, "rules": { - "node/no-unsupported-features/es-syntax": 0 + "node/no-unsupported-features/es-syntax": 0, + "no-underscore-dangle": 0 } } diff --git a/.gitignore b/.gitignore index e0bcd2f0..534f7c30 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,4 @@ node_modules /packages /styleguide /coverage +*.sw* diff --git a/package-lock.json b/package-lock.json index a5bbd111..5a980e99 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "@netology-group/media-ui", - "version": "0.1.43", + "version": "0.1.44", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 4a095324..2de4488f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@netology-group/media-ui", - "version": "0.1.43", + "version": "0.1.44", "description": "UI components library", "homepage": "https://github.com/netology-group/ulms-media-ui", "bugs": { diff --git a/rollup.js b/rollup.js index 3eb120d6..5544ffee 100755 --- a/rollup.js +++ b/rollup.js @@ -39,7 +39,7 @@ const copyDir = promisify(ncp.ncp) const copyFile = promisify(fs.copyFile) const mkDir = promisify(mkdirp) -const matchScript = it => it.includes('.js') +const matchScript = it => it.endsWith('.js') || it.endsWith('.jsx') const matchImage = it => it.includes('/images') async function processJson (entry) { diff --git a/src/packages/frame/frame.jsx b/src/packages/frame/frame.jsx new file mode 100644 index 00000000..bb855957 --- /dev/null +++ b/src/packages/frame/frame.jsx @@ -0,0 +1,120 @@ +/* eslint react/prop-types: 0 */ +import React from 'react' + +export class FrameComponent extends React.PureComponent { + static get actions () { + return new Map([['getState', 'get_state'], ['updateState', 'update_state'], ['notify', 'notify']]) + } + + static getAction (name) { + const keys = [...FrameComponent.actions.keys()] + const names = [...FrameComponent.actions.values()] + + const actionIndex = keys.findIndex(a => a === name) + if (actionIndex === -1) throw new Error('Can not find action') + + return names[actionIndex] + } + + static get type () { + return 'about:iframe#taskdigests' + } + + static isEnabled (env) { + return env.length > 0 + } + + static isComponent (data) { + return data.url && data.url.startsWith(FrameComponent.type) + } + + static data ({ + data = '""', page = 1, title, url, + }) { + return { + data, + page, + title, + url: new URL(`${FrameComponent.type}/${url}`).href, + } + } + + constructor (props) { + super(props) + this.iframeR = React.createRef() + } + + componentDidMount () { + this.iframeWindow.addEventListener('message', this.handleMessage) + } + + componentWillUnmount () { + this.iframeWindow.removeEventListener('message', this.handleMessage) + } + + get iframeWindow () { + return this.iframeR.current && this.iframeR.current.ownerDocument.defaultView + } + + handleMessage = (event) => { + const { handleMessage } = this.props + if (event.source !== this.iframeR.current.contentWindow) return + // bypass iframe-only events + + const { payload, type } = event.data + + handleMessage(type, payload) + } + + postMessage = (message) => { + const el = this.iframeR.current + + if (!message) throw new Error('Could not post message') + + el && el.contentWindow.postMessage(message, '*') + } + + postGetState = (message) => { + this.postMessage({ + type: FrameComponent.actions.get('getState'), + payload: message, + }) + } + + postUpdateState = (message) => { + this.postMessage({ + type: FrameComponent.actions.get('updateState'), + payload: message, + }) + } + + postNotify = (message) => { + this.postMessage({ + type: FrameComponent.actions.get('notify'), + payload: message, + }) + } + + render () { + const { + scope, + title, + url, + } = this.props + + return ( +