UNPKG

@proca/widget

Version:

Proca is an open-source campaign toolkit designed to empower activists and organisations in their digital advocacy efforts. It provides a flexible and customisable platform for creating and managing online petitions, email campaigns, and other forms of di

182 lines (160 loc) 4.7 kB
import React from "react"; import "./polyfill"; import ReactDOM from "react-dom"; import { goStep, hook, setConfig, setGlobalState } from "./hooks/useConfig"; import "./lib/i18n"; import { isTest } from "./lib/urlparser"; import { scrollTo } from "./lib/scroll"; import ProcaAlert from "./components/Alert.js"; import Portals from "./components/Portals.js"; import ProcaWidget from "./components/Widget.js"; import { config as Config } from "./actionPage"; let config = { selector: ".proca-widget", // +, "[href='#proca_widget']" }; let rendered = false; const getJourney = () => Config.journey; const Alert = (text, severity) => { const selector = "proca_alert"; if (!document.querySelector(`#${selector}`)) { const elem = document.createElement("div"); elem.id = selector; document.body.appendChild(elem); } ReactDOM.render( <ProcaAlert text={text} severity={severity} />, document.querySelector(`#${selector}`) ); }; const initPortals = portals => { portals.forEach((d, i) => { if (typeof d === "string") { portals[i] = d.replaceAll("/", "_"); return; } portals[i].component = d.component.replaceAll("/", "_"); }); }; const Widget = args => { if (rendered) return; if (args) config = { ...config, data: args }; config = { ...config, ...Config }; config.actionPage = config.actionPage || config.actionpage; config.journey.forEach((d, i) => { if (typeof d !== "string") return; config.journey[i] = d.replaceAll("/", "_"); }); config.portal && initPortals(config.portal); let dom = document.querySelector(config.selector); const frag = document.createDocumentFragment(); if (!dom) { dom = document.createElement("div"); dom.id = "proca-widget"; dom.className = "proca-widget"; const script = document.getElementById("proca"); if (document.body.contains(script)) { // dom.insertAdjacentElement("beforeBegin",script); script.parentNode.insertBefore(dom, script); } else { // alert( "proca script isn't in the body, but no object with 'proca-widget' class" ); // document.body.appendChild(dom); } } else { Array.from(dom.childNodes).forEach(d => { frag.appendChild(d); }); } if (isTest()) config.test = isTest(); // <ProcaWidget config={config} {...config} />, rendered = true; ReactDOM.render( <ProcaWidget {...config} container={frag}> {config.test && ( <ProcaAlert title="TEST MODE" severity="warning"> Experiment freely, this action will not be counted </ProcaAlert> )} <Portals portals={config.portal} dom={frag} /> </ProcaWidget>, dom ); }; Widget.jump = step => { // if step is empty, jump to next ProcaWidget.action(step); }; const go = action => { goStep(action); scrollTo({ delay: 300 }); }; const set = (atom, key, value) => { config[key] = value; // pointless? if ((atom && key && value) || (atom && typeof key === "object")) { return setGlobalState(atom, key, value); } setConfig(key, value); }; const render = script => { try { if (!script) { script = {}; } // return; I have no clue why it happens Widget({ ...script.dataset }); } catch (e) { console.log(e); } }; const autoRender = () => { if (document.currentScript) document.currentScript.id = "proca"; console.log("Powered by proca.app", Config.actionpage, Config.filename); const currentScript = document.currentScript; try { if ( document.readyState === "loading" // !(document.readyState === "complete" || document.readyState === "loaded" || document.readyState === "interactive") ) { if (Config.component?.widget?.delay) { const delay = Config.component.widget.delay; document.addEventListener("DOMContentLoaded", () => { setTimeout(render, delay, currentScript); }); } else { document.addEventListener("DOMContentLoaded", () => render(currentScript) ); } } else { console.log("loaded", currentScript); if (Config.component?.widget?.delay) { const delay = Config.component.widget.delay; setTimeout(render, delay, currentScript); return; } render(currentScript); } } catch (e) { console.log(e); } }; autoRender(); const addEventListener = (type, listener) => { let el = document.getElementById("proca"); if (!el) el = window; el.addEventListener(type, listener); }; export { addEventListener, Alert, go, scrollTo, hook, React, ReactDOM, set, Widget, getJourney, }; // <SignatureForm margin= "dense" variant= "filled" />