From 1d85662946c393ea6985c178842be40d38fc687d Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 28 Mar 2022 14:03:59 -0300 Subject: storybook like page for dev, plus some style fixes --- packages/taler-wallet-webextension/src/stories.tsx | 322 +++++++++++++++++++++ 1 file changed, 322 insertions(+) create mode 100644 packages/taler-wallet-webextension/src/stories.tsx (limited to 'packages/taler-wallet-webextension/src/stories.tsx') diff --git a/packages/taler-wallet-webextension/src/stories.tsx b/packages/taler-wallet-webextension/src/stories.tsx new file mode 100644 index 000000000..2f410f68c --- /dev/null +++ b/packages/taler-wallet-webextension/src/stories.tsx @@ -0,0 +1,322 @@ +/* + This file is part of GNU Taler + (C) 2021 Taler Systems S.A. + + GNU Taler is free software; you can redistribute it and/or modify it under the + terms of the GNU General Public License as published by the Free Software + Foundation; either version 3, or (at your option) any later version. + + GNU Taler is distributed in the hope that it will be useful, but WITHOUT ANY + WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR + A PARTICULAR PURPOSE. See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License along with + GNU Taler; see the file COPYING. If not, see + */ + +/** + * + * @author Sebastian Javier Marchano (sebasjm) + */ +import { setupI18n } from "@gnu-taler/taler-util"; +import { styled } from "@linaria/react"; +import { + ComponentChild, + ComponentProps, + Fragment, + FunctionComponent, + h, + render, + VNode, +} from "preact"; +import { useEffect, useErrorBoundary, useState } from "preact/hooks"; +import { LogoHeader } from "./components/LogoHeader"; +import { PopupBox, WalletBox } from "./components/styled"; +import * as mui from "./mui/index.stories"; +import { PopupNavBar, WalletNavBar } from "./NavigationBar"; +import * as popup from "./popup/index.stories"; +import * as wallet from "./wallet/index.stories"; + +setupI18n("en", { en: {} }); + +const Page = styled.div` + * { + margin: 0px; + padding: 0px; + font-size: 100%; + font-family: Arial, Helvetica, sans-serif; + } + p:not([class]) { + margin-bottom: 1em; + margin-top: 1em; + } + width: 100%; + display: flex; + flex-direction: row; +`; + +const SideBar = styled.div` + min-width: 200px; + height: calc(100vh - 20px); + overflow-y: visible; + overflow-x: hidden; + & > { + ol { + padding: 4px; + div { + background-color: lightcoral; + cursor: pointer; + } + dd { + margin-left: 1em; + padding: 4px; + cursor: pointer; + border-radius: 4px; + margin-bottom: 4px; + } + dd:nth-child(even) { + background-color: lightgray; + } + dd:nth-child(odd) { + background-color: lightblue; + } + } + } +`; + +const Content = styled.div` + width: 100%; +`; + +function parseExampleImport(group: string, im: any) { + const component = im.default.title; + return { + name: component, + examples: Object.entries(im) + .filter(([k]) => k !== "default") + .map( + ([name, render]) => + ({ + group, + component, + name, + render, + } as ExampleItem), + ), + }; +} + +const allExamples = Object.entries({ popup, wallet, mui }).map( + ([title, value]) => ({ + title, + list: value.default.map((s) => parseExampleImport(title, s)), + }), +); + +interface ExampleItem { + group: string; + component: string; + name: string; + render: { + (args: any): VNode; + args: any; + }; +} + +function findByGroupComponentName( + group: string, + component: string, + name: string, +) { + const gl = allExamples.filter((e) => e.title === group); + if (gl.length === 0) { + return undefined; + } + const cl = gl[0].list.filter((l) => l.name === component); + if (cl.length === 0) { + return undefined; + } + const el = cl[0].examples.filter((c) => c.name === name); + if (el.length === 0) { + return undefined; + } + return el[0]; +} + +function getContentForExample(item: ExampleItem | undefined): () => VNode { + if (!item) return () =>
select example from the list on the left
; + const example = findByGroupComponentName( + item.group, + item.component, + item.name, + ); + if (!example) return () =>
example not found
; + return () => example.render(example.render.args); +} + +function ExampleList({ + name, + list, +}: { + name: string; + list: { + name: string; + examples: ExampleItem[]; + }[]; +}) { + const [open, setOpen] = useState(true); + return ( +
    +
    setOpen(!open)}>{name}
    + {open && + list.map((k) => ( +
  1. +
    +
    {k.name}
    + {k.examples.map((r) => ( +
    + + {r.name} + +
    + ))} +
    +
  2. + ))} +
+ ); +} + +function getWrapperForGroup(group: string): FunctionComponent { + switch (group) { + case "popup": + return ({ children }: any) => ( + + + {children} + + ); + case "wallet": + return ({ children }: any) => ( + + + + {children} + + ); + default: + return Fragment; + } +} + +function ErrorReport({ + children, + selected, +}: { + children: ComponentChild; + selected: ExampleItem | undefined; +}) { + const [error] = useErrorBoundary(); + if (error) { + return ( +
+

Error was thrown trying to render

+ {selected && ( +
    +
  • + group: {selected.group} +
  • +
  • + component: {selected.component} +
  • +
  • + example: {selected.name} +
  • +
  • + args:{" "} +
    {JSON.stringify(selected.render.args, undefined, 2)}
    +
  • +
+ )} +

{error.message}

+
{error.stack}
+
+ ); + } + return {children}; +} + +function getSelectionFromLocationHash(): ExampleItem | undefined { + if (!location.hash) return undefined; + const parts = location.hash.substring(1).split("-"); + if (parts.length < 3) return undefined; + return findByGroupComponentName( + decodeURIComponent(parts[0]), + decodeURIComponent(parts[1]), + decodeURIComponent(parts[2]), + ); +} + +function Application() { + const initialSelection = getSelectionFromLocationHash(); + const [selected, updateSelected] = useState( + initialSelection, + ); + + function updateSelectedFromHashChange({ newURL, oldURL }: any) { + const selected = getSelectionFromLocationHash(); + updateSelected(selected); + } + useEffect(() => { + window.addEventListener("hashchange", updateSelectedFromHashChange); + return () => { + window.removeEventListener("hashchange", updateSelectedFromHashChange); + }; + }, []); + + const ExampleContent = getContentForExample(selected); + + const GroupWrapper = getWrapperForGroup(selected?.group || "default"); + + return ( + + + {allExamples.map((e) => ( + + ))} +
+
+ + + + + + + +
+ ); +} + +if (document.readyState === "loading") { + document.addEventListener("DOMContentLoaded", main); +} else { + main(); +} +function main(): void { + try { + const container = document.getElementById("container"); + if (!container) { + throw Error("container not found, can't mount page contents"); + } + render(, container); + } catch (e) { + console.error("got error", e); + if (e instanceof Error) { + document.body.innerText = `Fatal error: "${e.message}". Please report this bug at https://bugs.gnunet.org/.`; + } + } +} -- cgit v1.2.3