UNPKG

cosmic-lib

Version:

A JavaScript implementation of the CosmicLink protocol for Stellar

185 lines (157 loc) 4.21 kB
"use strict"; /** * Signing Side Frame * * @private */ const html = require("@cosmic-plus/domutils/es5/html"); const Observable = require("@cosmic-plus/jsutils/es5/observable"); const { timeout } = require("@cosmic-plus/jsutils/es5/misc"); const ClickWall = require("./click-wall"); const cosmicLinkIcon = require("../../bundled/cosmic-link.svg"); /** * Class */ class SideFrame extends Observable { constructor(url) { super(); if (SideFrame.current) SideFrame.current.close(); SideFrame.current = this; this.shadow = makeShadow(); this.closeButton = new SideFrame.CloseButton(); this.domNode = html.create("iframe", { title: "Signing Frame", src: url, sandbox: "allow-same-origin allow-scripts allow-forms allow-popups", hidden: true }); Object.assign(this.domNode.style, SideFrame.style); this.domNode.style.transform = "translateX(100%)"; html.append(document.body, this.closeButton, this.domNode); this.closeButton.domNode.style.zIndex = +this.getRealZIndex() + 1; this.show(); } show() { if (!this.domNode.hidden) return; html.show(this.domNode); // That timeout is required for transition to play well. this.setTransition(250, "cubic-bezier(0, 0, 0.2, 1)"); timeout(5).then(() => this.domNode.style.transform = "none"); return this.shadow.enable().then(() => { this.shadow.onclick = () => this.close(); html.show(this.closeButton.domNode); this.closeButton.domNode.onclick = () => this.close(); this.trigger("show"); }); } hide() { if (this.domNode.hidden) return; html.hide(this.closeButton.domNode); this.setTransition(200, "cubic-bezier(0.4, 0, 1, 1)"); this.domNode.style.transform = "translateX(100%)"; return this.shadow.disable().then(() => { html.hide(this.domNode); this.trigger("hide"); }); } setTransition(delay, ease) { const transition = "transform ".concat(delay, "ms ").concat(ease); this.domNode.style.transition = transition; this.shadow.domNode.style.transition = transition; this.shadow.delay = delay; } close() { SideFrame.current = null; this.hide().then(() => { html.destroy(this.domNode); html.destroy(this.closeButton.domNode); this.shadow.destroy(); this.trigger("close"); this.destroy(); }); } getRealZIndex() { return document.defaultView.getComputedStyle(this.domNode).getPropertyValue("z-index"); } } /** * Event */ window.addEventListener("message", event => { const frameWindow = SideFrame.current && SideFrame.current.domNode.contentWindow; if (event.source === frameWindow) { switch (event.data) { case "show": SideFrame.current.show(); break; case "hide": SideFrame.current.hide(); break; case "close": SideFrame.current.close(); break; } } }); /** * Frame style */ SideFrame.style = { boxSizing: "border-box", position: "fixed", zIndex: 1000, right: 0, top: 0, width: "30em", minWidth: "38%", maxWidth: "100%", height: "100vh", border: 0, borderTop: "2em solid hsl(240, 40%, 98%)", boxShadow: "0px 7px 10px 1px rgba(0, 0, 0, 0.14), 0px 2px 16px 1px rgba(0, 0, 0, 0.12)", background: "hsl(240, 40%, 98%)", backgroundImage: "url('".concat(cosmicLinkIcon, "')"), backgroundRepeat: "no-repeat", backgroundPosition: "center", backgroundSize: "12em 12em", willChange: "transform" }; /** * Closing button */ SideFrame.CloseButton = class CloseButton { constructor() { this.domNode = html.create("span", { hidden: true }, "× Close"); Object.assign(this.domNode.style, SideFrame.CloseButton.style); } }; SideFrame.CloseButton.style = { position: "fixed", top: "0.1em", right: "0.1em", width: "29.8em", minWidth: "38%", maxWidth: "100%", lineHeight: "1.8em", color: "hsl(0, 0%, 40%)", fontWeight: "bold", cursor: "pointer", textAlign: "center" }; /** * Shadow Layer */ function makeShadow() { return new ClickWall({ scrollbar: "hide", opacity: 0.3, delay: 400 }); } /** * Export */ module.exports = SideFrame;