WIP: Shadow DOM

This commit is contained in:
Manuel Bouza
2019-02-19 15:32:53 +01:00
parent dd4fa996e8
commit a9007b825e
21 changed files with 251 additions and 220 deletions

View File

@@ -1,7 +1,7 @@
import React, { Component } from "react"
import PropTypes from "prop-types"
import ApiClient from "api/Client"
import Modal, { Content } from "components/Modal"
import Modal from "components/Modal"
import InvalidConfigurationError from "components/InvalidConfigurationError"
import Form from "components/Form"
import Spinner from "components/Spinner"
@@ -160,6 +160,7 @@ class Bubble extends Component {
// EVENT HANDLERS -----------------------------------------------------------
handleKeyDown = event => {
event.stopPropagation()
if (event.keyCode === 27) {
this.close()
}
@@ -223,19 +224,18 @@ class Bubble extends Component {
}
return (
<>
<div className="moco-bx-bubble">
<img
onClick={this.open}
src={chrome.extension.getURL(logoUrl)}
width="50%"
/>
{this.bookedHours > 0 && <span className="booked-hours"><small>{this.bookedHours}h</small></span>}
{this.isOpen && (
<Modal>
<Content>{this.renderContent()}</Content>
{this.renderContent()}
</Modal>
)}
</>
</div>
)
}
}

View File

@@ -1,5 +1,4 @@
import React, { Component } from "react"
import { createPortal } from "react-dom"
import PropTypes from "prop-types"
class Modal extends Component {
@@ -7,35 +6,17 @@ class Modal extends Component {
children: PropTypes.node.isRequired
}
constructor(props) {
super(props)
this.el = document.createElement("div")
this.el.setAttribute("class", "moco-bx-modal")
}
componentDidMount() {
const modalRoot = document.getElementById("moco-bx-container")
modalRoot.appendChild(this.el)
}
componentWillUnmount() {
const modalRoot = document.getElementById("moco-bx-container")
modalRoot.removeChild(this.el)
}
// RENDER -------------------------------------------------------------------
render() {
return createPortal(this.props.children, this.el)
return (
<div className="moco-bx-modal">
<div className="moco-bx-modal-content">
{this.props.children}
</div>
</div>
)
}
}
export function Content({ children }) {
return <div className="moco-bx-modal-content">{children}</div>
}
Content.propTypes = {
children: PropTypes.node
}
export default Modal

View File

@@ -12,7 +12,6 @@ import {
flatMap,
pathEq
} from "lodash/fp"
import { trace } from "utils"
const customTheme = theme => ({
...theme,

View File

@@ -1,9 +1,7 @@
import React from 'react'
const Spinner = () => (
<div className="spinner" role="status">
<span className="sr-only">Loading...</span>
</div>
<div className="moco-bx-spinner" role="status" />
)
export default Spinner

View File

@@ -1,11 +1,11 @@
import { createElement } from "react"
import React from "react"
import ReactDOM from "react-dom"
import ShadowDOM from "react-shadow"
import Bubble from "./components/Bubble"
import services from "remoteServices"
import { parseServices, createMatcher, createEnhancer } from "utils/urlMatcher"
import { createMatcher, createEnhancer } from "utils/urlMatcher"
import remoteServices from "./remoteServices"
import { pipe } from 'lodash/fp'
import "../css/main.scss"
import "../css/content.scss"
const matcher = createMatcher(remoteServices)
const serviceEnhancer = createEnhancer(window.document)
@@ -32,35 +32,27 @@ const mountBubble = (settings) => {
return
}
if (!document.getElementById("moco-bx-container")) {
const domContainer = document.createElement("div")
domContainer.setAttribute("id", "moco-bx-container")
document.body.appendChild(domContainer)
}
if (!document.getElementById("moco-bx-bubble")) {
const domBubble = document.createElement("div")
domBubble.setAttribute("id", "moco-bx-bubble")
document.body.appendChild(domBubble)
if (!document.getElementById("moco-bx-root")) {
const domRoot = document.createElement("div")
domRoot.setAttribute("id", "moco-bx-root")
document.body.appendChild(domRoot)
}
ReactDOM.render(
createElement(Bubble, { service, settings }),
document.getElementById("moco-bx-bubble")
<ShadowDOM include={[chrome.extension.getURL('content.css')]}>
<div>
<Bubble service={service} settings={settings} />
</div>
</ShadowDOM>,
document.getElementById("moco-bx-root")
)
}
const unmountBubble = () => {
const domBubble = document.getElementById("moco-bx-bubble")
const domContainer = document.getElementById("moco-bx-container")
const domRoot = document.getElementById("moco-bx-root")
if (domBubble) {
ReactDOM.unmountComponentAtNode(domBubble)
domBubble.remove()
}
if (domContainer) {
ReactDOM.unmountComponentAtNode(domContainer)
domContainer.remove()
if (domRoot) {
ReactDOM.unmountComponentAtNode(domRoot)
domRoot.remove()
}
}

View File

@@ -1,7 +1,7 @@
import { createElement } from "react"
import React from "react"
import ReactDOM from "react-dom"
import Setup from "./components/Setup"
import "../css/main.scss"
import "../css/options.scss"
const domContainer = document.querySelector("#moco-bx-container")
ReactDOM.render(createElement(Setup), domContainer)
const domContainer = document.querySelector("#moco-bx-root")
ReactDOM.render(<Setup />, domContainer)

View File

@@ -1,6 +0,0 @@
import { createElement } from 'react'
import ReactDOM from 'react-dom'
import Form from './components/Form'
const domContainer = document.querySelector('#moco-bx-container')
ReactDOM.render(createElement(Form, {inline: false}), domContainer)

View File

@@ -25,6 +25,12 @@ export default {
description: (document, service, { org, repo, id }) =>
`${org}/${repo}/${id} - ${document
.querySelector(".gh-header-title")
.textContent.trim()}`
.textContent.trim()}`,
},
"trello": {
name: "trello",
urlPattern: "https://trello.com/c/:id/:title",
description: (document, service, { title }) => title.split('-').slice(1).join(' ')
}
}