This commit is contained in:
Sebastian 2023-09-19 08:31:08 -03:00
parent e628ca1af8
commit a5406c5a5d
No known key found for this signature in database
GPG Key ID: 173909D1A5F66069
52 changed files with 822 additions and 19158 deletions

View File

@ -24,5 +24,5 @@ await build({
assets: [{ base: "src", files: ["src/index.html"] }],
},
destination: "./dist/prod",
css: "sass",
css: "postcss",
});

View File

@ -28,7 +28,7 @@ const build = initializeDev({
},
destination: "./dist/dev",
public: "/app",
css: "sass",
css: "postcss",
});
await build();

View File

@ -46,6 +46,9 @@
"devDependencies": {
"@creativebulma/bulma-tooltip": "^1.2.0",
"@gnu-taler/pogen": "^0.0.5",
"@tailwindcss/forms": "^0.5.3",
"@tailwindcss/typography": "^0.5.9",
"autoprefixer": "^10.4.14",
"@types/chai": "^4.3.0",
"@types/history": "^4.7.8",
"@types/mocha": "^10.0.1",
@ -62,6 +65,7 @@
"po2json": "^0.4.5",
"preact-render-to-string": "^5.2.6",
"sass": "1.56.1",
"tailwindcss": "^3.3.2",
"typescript": "5.2.2"
},
"pogen": {

View File

@ -0,0 +1,6 @@
export default {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}

View File

@ -5,7 +5,7 @@ import { useEffect, useState } from "preact/hooks";
export function CopyIcon(): VNode {
return (
<svg height="16" viewBox="0 0 16 16" width="16">
<svg height="16" viewBox="0 0 16 16" width="16" stroke="currentColor" strokeWidth="1.5">
<path
fill-rule="evenodd"
d="M0 6.75C0 5.784.784 5 1.75 5h1.5a.75.75 0 010 1.5h-1.5a.25.25 0 00-.25.25v7.5c0 .138.112.25.25.25h7.5a.25.25 0 00.25-.25v-1.5a.75.75 0 011.5 0v1.5A1.75 1.75 0 019.25 16h-7.5A1.75 1.75 0 010 14.25v-7.5z"
@ -20,7 +20,7 @@ export function CopyIcon(): VNode {
export function CopiedIcon(): VNode {
return (
<svg height="16" viewBox="0 0 16 16" width="16">
<svg height="16" viewBox="0 0 16 16" width="16" stroke="currentColor" strokeWidth="1.5">
<path
fill-rule="evenodd"
d="M13.78 4.22a.75.75 0 010 1.06l-7.25 7.25a.75.75 0 01-1.06 0L2.22 9.28a.75.75 0 011.06-1.06L6 10.94l6.72-6.72a.75.75 0 011.06 0z"
@ -45,13 +45,13 @@ export function CopyButton({ getContent }: { getContent: () => string }): VNod
if (!copied) {
return (
<button onClick={copyText} style={{ width: 32, height: 32, fontSize: "initial" }}>
<button class="text-white" onClick={copyText} style={{ width: 32, height: 32, fontSize: "initial" }}>
<CopyIcon />
</button>
);
}
return (
<div content="Copied" style={{ display: "inline-block" }}>
<div class="text-white" content="Copied" style={{ display: "inline-block" }}>
<button disabled style={{ width: 32, height: 32, fontSize: "initial" }}>
<CopiedIcon />
</button>

View File

@ -23,6 +23,7 @@ import { BusinessAccount } from "../pages/BusinessAccount.js";
import { HomePage, WithdrawalOperationPage } from "../pages/HomePage.js";
import { PublicHistoriesPage } from "../pages/PublicHistoriesPage.js";
import { RegistrationPage } from "../pages/RegistrationPage.js";
import { Test } from "../pages/Test.js";
export function Routing(): VNode {
const history = createHashHistory();
@ -34,6 +35,10 @@ export function Routing(): VNode {
}}
>
<Router history={history}>
<Route
path="/test"
component={Test}
/>
<Route
path="/operation/:wopid"
component={({ wopid }: { wopid: string }) => (

View File

@ -33,42 +33,46 @@ export function LoadingUriView({ error }: State.LoadingUriError): VNode {
export function ReadyView({ transactions }: State.Ready): VNode {
const { i18n } = useTranslationContext();
return (
<div class="results">
<table class="pure-table pure-table-striped">
<div class="px-4 mt-4">
<div class="sm:flex sm:items-center">
<div class="sm:flex-auto">
<h1 class="text-base font-semibold leading-6 text-gray-900"><i18n.Translate>Latest transactions</i18n.Translate></h1>
</div>
</div>
<div class="-mx-4 mt-5 ring-1 ring-gray-300 sm:mx-0 sm:rounded-lg">
<table class="min-w-full divide-y divide-gray-300">
<thead>
<tr>
<th>{i18n.str`Date`}</th>
<th>{i18n.str`Amount`}</th>
<th>{i18n.str`Counterpart`}</th>
<th>{i18n.str`Subject`}</th>
<th scope="col" class="pl-4 pr-3 py-3.5 text-left text-sm font-semibold text-gray-900 sm:pl-6">{i18n.str`Date`}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">{i18n.str`Amount`}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">{i18n.str`Counterpart`}</th>
<th scope="col" class="px-3 py-3.5 text-left text-sm font-semibold text-gray-900 lg:table-cell">{i18n.str`Subject`}</th>
</tr>
</thead>
<tbody>
{transactions.map((item, idx) => {
return (
<tr key={idx}>
<td>
{item.when.t_ms === "never"
<td class="relative py-4 pl-4 pr-3 text-sm sm:pl-6">
<div class="font-medium text-gray-900">{item.when.t_ms === "never"
? ""
: format(item.when.t_ms, "dd/MM/yyyy HH:mm:ss")}
: format(item.when.t_ms, "dd/MM/yyyy HH:mm:ss")}</div>
</td>
<td>
{item.negative ? "-" : ""}
<td class="px-3 py-3.5 text-sm text-gray-500">{item.negative ? "-" : ""}
{item.amount ? (
`${Amounts.stringifyValue(item.amount)} ${
item.amount.currency
`${Amounts.stringifyValue(item.amount)} ${item.amount.currency
}`
) : (
<span style={{ color: "grey" }}>&lt;invalid value&gt;</span>
)}
</td>
<td>{item.counterpart}</td>
<td>{item.subject}</td>
<span style={{ color: "grey" }}>&lt;{i18n.str`invalid value`}&gt;</span>
)}</td>
<td class="px-3 py-3.5 text-sm text-gray-500">{item.counterpart}</td>
<td class="px-3 py-3.5 text-sm text-gray-500">{item.subject}</td>
</tr>
);
})}
</tbody>
</table>
</div>
</div>
);
}

View File

@ -24,7 +24,6 @@ import { SWRConfig } from "swr";
import { BackendStateProvider } from "../context/backend.js";
import { strings } from "../i18n/strings.js";
import { Routing } from "./Routing.js";
const WITH_LOCAL_STORAGE_CACHE = false;
/**

View File

@ -365,7 +365,15 @@ export function useTransactions(
RequestError<SandboxBackend.SandboxError>
>(
[`access-api/accounts/${account}/transactions`, args?.page, PAGE_SIZE],
paginatedFetcher,
paginatedFetcher, {
refreshInterval: 0,
refreshWhenHidden: false,
refreshWhenOffline: false,
// revalidateOnMount: false,
revalidateIfStale: false,
revalidateOnFocus: false,
revalidateOnReconnect: false,
}
);
const [lastAfter, setLastAfter] = useState<

View File

@ -16,7 +16,8 @@
@author Sebastian Javier Marchano
-->
<!DOCTYPE html>
<html lang="en">
<html lang="en" class="h-full bg-gray-100">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta charset="utf-8" />
@ -24,10 +25,8 @@
<meta name="taler-support" content="uri">
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<link
rel="icon"
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/Qn3//3ryn/795Tf/WrpP/2LCW/8B6T//w4Nb///////Pn4P+/d0v/9u3n/+7d0v/EhV7//v///+HDr//fxLD/zph2/+TJt//8/Pv/woBX//Lm3f/y5dz/v3hN//bu6f/JjGn/4sW0///////Df1j/8OLZ//v6+P+/elH/+vj1//jy7f+/elL//////+zYzP/Eg13//////967p//MlHT/wn5X///////v4Nb/yY1s///////jw7H/06KG////////////z5t9/+fNvf//////x4pn//Pp4v/8+vn/w39X/8WEX///////5s/A/9CbfP//////27Oc/9y2n////////////9itlf/gu6f//////86Vdf/r2Mz//////8SCXP/Df1j//////+7d0v/KkG7//////+HBrf/VpYr////////////RnoH/5sq6///////Ii2n/8ubf//39/P/Cf1j/xohk/+bNvv//////wn5W//Tq4//58/D/wHxV//7+/f/59fH/v3xU//39/P/w4Nf/xIFb///////hw7H/yo9t/+/f1f/AeU3/+/n2/+nSxP/FhmD//////9qzm//Upon/4MSx/96+qf//////xINc/+3bz//48e3/v3hN//Pn3///////6M+//752S//gw6//06aK/8J+VP/kzLr/zZd1/8OCWv/q18r/17KZ/9Ooi//fv6r/v3dK/+vWyP///////v39///////27un/1aeK/9Opjv/m1cf/1KCC/9a0nP/n08T/0Jx8/82YdP/QnHz/16yR//jx7P///////v39///////+/f3///7+///////+//7//v7+///////+/v7//v/+/////////////////////////v7//v79///////////////////+/v/+/Pv//v39///+/v/+/Pv///7+//7+/f/+/Pv//v39//79/P/+/Pv///7+////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="
/>
<link rel="icon"
href="data:;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAD///////////////////////////////////////////////////////////////////////////////////////////////////7//v38//78/P/+/fz//vz7///+/v/+/f3//vz7///+/v/+/fz//v38///////////////////////+/v3///7+/////////////////////////////////////////////////////////v3//v79///////+/v3///////r28v/ct5//06SG/9Gffv/Xqo7/7N/V/9e2nf/bsJb/6uDW/9Sskf/euKH/+/j2///////+/v3//////+3azv+/eE3/2rWd/9Kkhv/Vr5T/48i2/8J+VP/Qn3//3ryn/795Tf/WrpP/2LCW/8B6T//w4Nb///////Pn4P+/d0v/9u3n/+7d0v/EhV7//v///+HDr//fxLD/zph2/+TJt//8/Pv/woBX//Lm3f/y5dz/v3hN//bu6f/JjGn/4sW0///////Df1j/8OLZ//v6+P+/elH/+vj1//jy7f+/elL//////+zYzP/Eg13//////967p//MlHT/wn5X///////v4Nb/yY1s///////jw7H/06KG////////////z5t9/+fNvf//////x4pn//Pp4v/8+vn/w39X/8WEX///////5s/A/9CbfP//////27Oc/9y2n////////////9itlf/gu6f//////86Vdf/r2Mz//////8SCXP/Df1j//////+7d0v/KkG7//////+HBrf/VpYr////////////RnoH/5sq6///////Ii2n/8ubf//39/P/Cf1j/xohk/+bNvv//////wn5W//Tq4//58/D/wHxV//7+/f/59fH/v3xU//39/P/w4Nf/xIFb///////hw7H/yo9t/+/f1f/AeU3/+/n2/+nSxP/FhmD//////9qzm//Upon/4MSx/96+qf//////xINc/+3bz//48e3/v3hN//Pn3///////6M+//752S//gw6//06aK/8J+VP/kzLr/zZd1/8OCWv/q18r/17KZ/9Ooi//fv6r/v3dK/+vWyP///////v39///////27un/1aeK/9Opjv/m1cf/1KCC/9a0nP/n08T/0Jx8/82YdP/QnHz/16yR//jx7P///////v39///////+/f3///7+///////+//7//v7+///////+/v7//v/+/////////////////////////v7//v79///////////////////+/v/+/Pv//v39///+/v/+/Pv///7+//7+/f/+/Pv//v39//79/P/+/Pv///7+////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==" />
<link rel="shortcut icon" href="data:image/x-icon;," type="image/x-icon" />
<title>Demobank</title>
<!-- Optional customization script. -->
@ -36,7 +35,9 @@
<script type="module" src="index.js"></script>
<link rel="stylesheet" href="index.css" />
</head>
<body>
<body class="h-full">
<div id="app"></div>
</body>
</html>

View File

@ -16,7 +16,7 @@
import App from "./components/app.js";
import { h, render } from "preact";
import "./scss/main.scss";
import "./scss/main.css"
const app = document.getElementById("app");

View File

@ -21,6 +21,7 @@ import { Transactions } from "../../components/Transactions/index.js";
import { PaymentOptions } from "../PaymentOptions.js";
import { State } from "./index.js";
import { CopyButton } from "../../components/CopyButton.js";
import { bankUiSettings } from "../../settings.js";
export function InvalidIbanView({ error }: State.InvalidIban) {
return (
@ -28,47 +29,59 @@ export function InvalidIbanView({error}:State.InvalidIban) {
);
}
const IS_PUBLIC_ACCOUNT_ENABLED = false
function ImportantMessage(): VNode {
const { i18n } = useTranslationContext();
return <div aria-live="assertive" class="pointer-events-none flex items-end px-4 py-6 sm:items-start sm:p-6">
<div class="flex w-full flex-col items-center space-y-4 ">
<div class="pointer-events-auto flex w-full max-w-md rounded-lg bg-white shadow-lg ring-1 ring-black ring-opacity-5">
<div class="w-0 flex-1 p-4">
<div class="flex items-start">
<div class="ml-3 w-0 flex-1">
<p class="text-sm font-medium text-gray-900">
<i18n.Translate>
Welcome, "account"
</i18n.Translate>
</p>
<p class="mt-1 text-sm text-gray-500">
{bankUiSettings.showDemoNav &&
<p>
{IS_PUBLIC_ACCOUNT_ENABLED ? (
<i18n.Translate>
This part of the demo shows how a bank that supports Taler
directly would work. In addition to using your own bank
account, you can also see the transaction history of some{" "}
<a href="/public-accounts">Public Accounts</a>.
</i18n.Translate>
) : (
<i18n.Translate>
This part of the demo shows how a bank that supports Taler
directly would work.
</i18n.Translate>
)}
</p>
}</p>
</div>
</div>
</div>
<div class="flex border-l border-gray-200">
<button type="button" class="flex w-full items-center justify-center rounded-none rounded-r-lg border border-transparent p-4 text-sm font-medium text-indigo-600 hover:text-indigo-500 focus:outline-none focus:ring-2 focus:ring-indigo-500">
Dismiss
</button>
</div>
</div>
</div>
</div>
}
export function ReadyView({ account, balance, balanceIsDebit, limit, payto }: State.Ready): VNode<{}> {
const { i18n } = useTranslationContext();
return <Fragment>
<div>
<h1 class="nav welcome-text">
<i18n.Translate>
Welcome, {account} (<a href={stringifyPaytoUri(payto)}>{payto.iban}</a>)! <CopyButton getContent={() => stringifyPaytoUri(payto)} />
</i18n.Translate>
</h1>
</div>
<section id="assets">
<div class="asset-summary">
<h2>{i18n.str`Bank account balance`}</h2>
{!balance ? (
<div class="large-amount" style={{ color: "gray" }}>
Waiting server response...
</div>
) : (
<div class="large-amount amount">
{balanceIsDebit ? <b>-</b> : null}
<span class="value">{`${Amounts.stringifyValue(balance)}`}</span>
&nbsp;
<span class="currency">{`${balance.currency}`}</span>
</div>
)}
</div>
</section>
<section id="payments">
<div class="payments">
<h2>{i18n.str`Payments`}</h2>
<PaymentOptions limit={limit} />
</div>
</section>
<section style={{ marginTop: "2em" }}>
<div class="active">
<h3>{i18n.str`Latest transactions`}</h3>
<Transactions account={account} />
</div>
</section>
</Fragment>;
}

View File

@ -14,7 +14,7 @@
GNU Taler; see the file COPYING. If not, see <http://www.gnu.org/licenses/>
*/
import { Logger, TranslatedString } from "@gnu-taler/taler-util";
import { Logger, PaytoUriIBAN, TranslatedString, parsePaytoUri, stringifyPaytoUri } from "@gnu-taler/taler-util";
import { useTranslationContext } from "@gnu-taler/web-util/browser";
import { ComponentChildren, Fragment, h, VNode } from "preact";
import { StateUpdater, useEffect, useState } from "preact/hooks";
@ -25,6 +25,7 @@ import { useBusinessAccountDetails } from "../hooks/circuit.js";
import { bankUiSettings } from "../settings.js";
import { useSettings } from "../hooks/settings.js";
import { ErrorMessage, onNotificationUpdate } from "../hooks/notification.js";
import { CopyButton, CopyIcon } from "../components/CopyButton.js";
const IS_PUBLIC_ACCOUNT_ENABLED = false;
const GIT_HASH = typeof __GIT_HASH__ !== "undefined" ? __GIT_HASH__ : undefined;
@ -70,6 +71,7 @@ export function BankFrame({
const { i18n } = useTranslationContext();
const backend = useBackendContext();
const [settings, updateSettings] = useSettings();
const [open, setOpen] = useState(false)
const demo_sites = [];
for (const i in bankUiSettings.demoSites)
@ -79,83 +81,165 @@ export function BankFrame({
</a>,
);
return (
<Fragment>
<header
class="demobar"
style="display: flex; flex-direction: row; justify-content: space-between;"
>
<a href="#main" class="skip">{i18n.str`Skip to main content`}</a>
<div style="max-width: 50em; margin-left: 2em; margin-right: 2em;">
<h1>
<span class="it">
<a href="/">{bankUiSettings.bankName}</a>
</span>
</h1>
{maybeDemoContent(
<p>
{IS_PUBLIC_ACCOUNT_ENABLED ? (
<i18n.Translate>
This part of the demo shows how a bank that supports Taler
directly would work. In addition to using your own bank
account, you can also see the transaction history of some{" "}
<a href="/public-accounts">Public Accounts</a>.
</i18n.Translate>
) : (
<i18n.Translate>
This part of the demo shows how a bank that supports Taler
directly would work.
</i18n.Translate>
)}
</p>,
)}
return (<div class="min-h-full">
<div class="bg-indigo-600 pb-32">
<nav class="border-b border-indigo-300 border-opacity-25 bg-indigo-600 lg:border-none">
<div class="mx-auto max-w-7xl px-2 sm:px-4 lg:px-8">
<div class="relative flex h-16 items-center justify-between lg:border-b lg:border-indigo-400 lg:border-opacity-25">
<div class="flex items-center px-2 lg:px-0">
<div class="flex-shrink-0">
<img class="block h-8 w-8" src="https://tailwindui.com/img/logos/mark.svg?color=indigo&shade=300" alt="Your Company" />
</div>
<div class="hidden lg:ml-10 lg:block">
<div class="flex space-x-4">
{/* <!-- Current: "bg-indigo-700 text-white", Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" --> */}
{bankUiSettings.demoSites.map(([name, url]) => {
return <a href={url} class="text-white hover:bg-indigo-500 hover:bg-opacity-75 rounded-md py-2 px-3 text-sm font-medium">{name}</a>
})}
</div>
</div>
</div>
<div class="flex lg:hidden">
{/* <!-- Mobile menu button --> */}
<button type="button" class="relative inline-flex items-center justify-center rounded-md bg-indigo-600 p-2 text-indigo-200 hover:bg-indigo-500 hover:bg-opacity-75 hover:text-white focus:outline-none focus:ring-2 focus:ring-white focus:ring-offset-2 focus:ring-offset-indigo-600" aria-controls="mobile-menu" aria-expanded="false"
onClick={(e) => {
setOpen(!open)
}}>
<span class="absolute -inset-0.5"></span>
<span class="sr-only">Open main menu</span>
{/* <!-- Menu open: "hidden", Menu closed: "block" --> */}
<svg class="block h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5" />
</svg>
{/* <!-- Menu open: "block", Menu closed: "hidden" --> */}
<svg class="hidden h-6 w-6" fill="none" viewBox="0 0 24 24" stroke-width="1.5" stroke="currentColor" aria-hidden="true">
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18L18 6M6 6l12 12" />
</svg>
</button>
</div>
</div>
</div>
{/* <!-- Mobile menu, show/hide based on menu state. --> */}
{open &&
<div class="lg:hidden" id="mobile-menu">
<div class="space-y-1 px-2 pb-3 pt-2">
{/* <!-- Current: "bg-indigo-700 text-white", Default: "text-white hover:bg-indigo-500 hover:bg-opacity-75" --> */}
{bankUiSettings.demoSites.map(([name, url]) => {
return <a href={url} class="text-white hover:bg-indigo-500 hover:bg-opacity-75 block rounded-md py-2 px-3 text-base font-medium">{name}</a>
})}
</div>
</div>
}
</nav >
<header class="py-10">
<div class="mx-auto max-w-7xl px-4 sm:px-6 lg:px-8">
<div class=" flex flex-wrap items-center justify-between sm:flex-nowrap">
{/* <h1 class="text-base font-semibold leading-6 text-gray-900"></h1> */}
<h1 class="text-3xl font-bold tracking-tight text-white"><WelcomeAccount /></h1>
<div>
<h2 class="text-3xl font-bold tracking-tight text-white">KUDOS 100.00</h2>
</div>
{/* <div class="ml-4 mt-2 flex-shrink-0">
<button type="button" class="relative inline-flex items-center rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">Create new job</button>
</div> */}
</div>
</div>
</header>
<div style="display:flex; flex-direction: column;" class="navcontainer">
<nav class="demolist">
{maybeDemoContent(<Fragment>{demo_sites}</Fragment>)}
{backend.state.status === "loggedIn" ? (
<Fragment>
{goToBusinessAccount && !backend.state.isUserAdministrator ? (
<MaybeBusinessButton
account={backend.state.username}
onClick={goToBusinessAccount}
/>
) : undefined}
<LangSelector />
<a
href="#"
class="pure-button logout-button"
onClick={() => {
backend.logOut();
updateSettings("currentWithdrawalOperationId", undefined);
}}
>{i18n.str`Logout`}</a>
</Fragment>
) : undefined}
</nav>
</div >
<section id="main" class="content">
<StatusBanner />
<main class="-mt-32">
<div class="mx-auto max-w-7xl px-4 pb-12 sm:px-6 lg:px-8">
<div class="rounded-lg bg-white px-5 py-6 shadow sm:px-6">
{/* <!-- Your content --> */}
{children}
</section>
<section id="footer" class="footer">
<hr />
<div>
<p>
You can learn more about GNU Taler on our{" "}
<a href="https://taler.net">main website</a>.
</p>
</div>
<div style="flex-grow:1" />
<p>
Copyright &copy; 2014&mdash;2022 Taler Systems SA. {versionText}{" "}
<TestingTag />
</p>
</section>
</Fragment>
</div>
</main>
<Footer />
</div >
// <Fragment>
// <header
// class="demobar"
// style="display: flex; flex-direction: row; justify-content: space-between;"
// >
// <a href="#main" class="skip">{i18n.str`Skip to main content`}</a>
// <div style="max-width: 50em; margin-left: 2em; margin-right: 2em;">
// <h1>
// <span class="it">
// <a href="/">{bankUiSettings.bankName}</a>
// </span>
// </h1>
// {maybeDemoContent(
// <p>
// {IS_PUBLIC_ACCOUNT_ENABLED ? (
// <i18n.Translate>
// This part of the demo shows how a bank that supports Taler
// directly would work. In addition to using your own bank
// account, you can also see the transaction history of some{" "}
// <a href="/public-accounts">Public Accounts</a>.
// </i18n.Translate>
// ) : (
// <i18n.Translate>
// This part of the demo shows how a bank that supports Taler
// directly would work.
// </i18n.Translate>
// )}
// </p>,
// )}
// </div>
// </header>
// <div style="display:flex; flex-direction: column;" class="navcontainer">
// <nav class="demolist">
// {maybeDemoContent(<Fragment>{demo_sites}</Fragment>)}
// {backend.state.status === "loggedIn" ? (
// <Fragment>
// {goToBusinessAccount && !backend.state.isUserAdministrator ? (
// <MaybeBusinessButton
// account={backend.state.username}
// onClick={goToBusinessAccount}
// />
// ) : undefined}
// <LangSelector />
// <a
// href="#"
// class="pure-button logout-button"
// onClick={() => {
// backend.logOut();
// updateSettings("currentWithdrawalOperationId", undefined);
// }}
// >{i18n.str`Logout`}</a>
// </Fragment>
// ) : undefined}
// </nav>
// </div>
// <section id="main" class="content">
// <StatusBanner />
// {children}
// </section>
// <section id="footer" class="footer">
// <hr />
// <div>
// <p>
// You can learn more about GNU Taler on our{" "}
// <a href="https://taler.net">main website</a>.
// </p>
// </div>
// <div style="flex-grow:1" />
// <p>
// Copyright &copy; 2014&mdash;2022 Taler Systems SA. {versionText}{" "}
// <TestingTag />
// </p>
// </section>
// </Fragment>
);
}
@ -290,7 +374,7 @@ function TestingTag(): VNode {
const testingUrl = localStorage.getItem("bank-base-url");
if (!testingUrl) return <Fragment />;
return (
<span style={{ color: "gray" }}>
<p class="text-xs leading-5 text-gray-300">
Testing with {testingUrl}{" "}
<a
href=""
@ -302,6 +386,36 @@ function TestingTag(): VNode {
>
stop testing
</a>
</span>
</p>
);
}
function Footer() {
return (
<footer class="absolute bottom-4">
<div class="mt-8 mx-8 md:order-1 md:mt-0">
<div>
<p class="text-xs leading-5 text-gray-400">
You can learn more about GNU Taler on our{" "}
<a class="font-semibold text-gray-500 hover:text-gray-400" href="https://taler.net">main website</a>.
</p>
</div>
<div style="flex-grow:1" />
<p class="text-xs leading-5 text-gray-400">
Copyright &copy; 2014&mdash;2022 Taler Systems SA. {versionText}{" "}
<TestingTag />
</p>
</div>
</footer>
);
}
function WelcomeAccount(): VNode {
const { i18n } = useTranslationContext();
const account = "Sebastian"
const payto: PaytoUriIBAN = parsePaytoUri("payto://iban/bank.localhost/DE955922") as PaytoUriIBAN
return <i18n.Translate>
Welcome, {account} (<a href={stringifyPaytoUri(payto)}>{payto.iban}</a>)! <CopyButton getContent={() => stringifyPaytoUri(payto)} />
</i18n.Translate>
}

View File

@ -31,11 +31,77 @@ export function PaymentOptions({ limit }: { limit: AmountJson }): VNode {
const { i18n } = useTranslationContext();
const [settings, updateSettings] = useSettings();
const [tab, setTab] = useState<"charge-wallet" | "wire-transfer">(
"charge-wallet",
);
const [tab, setTab] = useState<"charge-wallet" | "wire-transfer" | undefined>(undefined);
return (
return (<fieldset>
<legend class="px-4 text-base font-semibold leading-6 text-gray-900">
<i18n.Translate>Send money to</i18n.Translate>
</legend>
<div class="px-4 mt-4 grid grid-cols-1 gap-y-6 sm:grid-cols-2 sm:gap-x-4">
{/* <!-- Active: "border-indigo-600 ring-2 ring-indigo-600", Not Active: "border-gray-300" --> */}
<label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (tab === "charge-wallet" ? "border-indigo-600 ring-2 ring-indigo-600" : "border-gray-300")}>
<input type="radio" name="project-type" value="Newsletter" class="sr-only" aria-labelledby="project-type-0-label" aria-describedby="project-type-0-description-0 project-type-0-description-1" onChange={() => {
setTab("charge-wallet")
}} />
<span class="flex flex-1">
<span class="flex flex-col">
<span id="project-type-0-label" class="block text-sm font-semibold font-medium text-gray-900">
<i18n.Translate>a Taler Wallet</i18n.Translate>
</span>
<span id="project-type-0-description-0" class="mt-1 flex items-center text-sm text-gray-500">
<i18n.Translate>Withdraw digital money into your mobile wallet or browser extension</i18n.Translate>
</span>
</span>
</span>
{/* <!-- Not Checked: "invisible" --> */}
<svg class="h-5 w-5 text-indigo-600" style={{ visibility: tab === "charge-wallet" ? "visible" : "hidden" }} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
</svg>
</label>
{/* <!-- Active: "border-indigo-600 ring-2 ring-indigo-600", Not Active: "border-gray-300" --> */}
<label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (tab === "wire-transfer" ? "border-indigo-600 ring-2 ring-indigo-600" : "border-gray-300")}>
<input type="radio" name="project-type" value="Existing Customers" class="sr-only" aria-labelledby="project-type-1-label" aria-describedby="project-type-1-description-0 project-type-1-description-1" onChange={() => {
setTab("wire-transfer")
}} />
<span class="flex flex-1">
<span class="flex flex-col">
<span id="project-type-1-label" class="block text-sm font-semibold font-medium text-gray-900">
<i18n.Translate>another bank account</i18n.Translate>
</span>
<span id="project-type-1-description-0" class="mt-1 flex items-center text-sm text-gray-500">
<i18n.Translate>Make a wire transfer to an account which you know the address.</i18n.Translate>
</span>
</span>
</span>
<svg class="h-5 w-5 text-indigo-600" style={{ visibility: tab === "wire-transfer" ? "visible" : "hidden" }} viewBox="0 0 20 20" fill="currentColor" aria-hidden="true">
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z" clip-rule="evenodd" />
</svg>
</label>
</div>
{tab === "charge-wallet" && (
<WalletWithdrawForm
focus
limit={limit}
onSuccess={(id) => {
updateSettings("currentWithdrawalOperationId", id);
}}
/>
)}
{tab === "wire-transfer" && (
<PaytoWireTransferForm
focus
limit={limit}
onSuccess={() => {
notifyInfo(i18n.str`Wire transfer created!`);
}}
/>
)}
</fieldset>)
{/* return (
<article>
<div class="payments">
<div class="tab">
@ -56,31 +122,7 @@ export function PaymentOptions({ limit }: { limit: AmountJson }): VNode {
{i18n.str`Wire transfer`}
</button>
</div>
{tab === "charge-wallet" && (
<div id="charge-wallet" class="tabcontent active">
<h3>{i18n.str`Obtain digital cash`}</h3>
<WalletWithdrawForm
focus
limit={limit}
onSuccess={(id) => {
updateSettings("currentWithdrawalOperationId", id);
}}
/>
</div>
)}
{tab === "wire-transfer" && (
<div id="wire-transfer" class="tabcontent active">
<h3>{i18n.str`Transfer to bank account`}</h3>
<PaytoWireTransferForm
focus
limit={limit}
onSuccess={() => {
notifyInfo(i18n.str`Wire transfer created!`);
}}
/>
</div>
)}
</div>
</article>
);
); */}
}

View File

@ -17,26 +17,24 @@
import {
AmountJson,
Amounts,
buildPayto,
HttpStatusCode,
Logger,
parsePaytoUri,
stringifyPaytoUri,
parsePaytoUri
} from "@gnu-taler/taler-util";
import {
RequestError,
useTranslationContext,
} from "@gnu-taler/web-util/browser";
import { h, VNode } from "preact";
import { h, VNode, Fragment } from "preact";
import { useEffect, useRef, useState } from "preact/hooks";
import { notifyError } from "../hooks/notification.js";
import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
import { useAccessAPI } from "../hooks/access.js";
import { notifyError } from "../hooks/notification.js";
import {
buildRequestErrorMessage,
undefinedIfEmpty,
validateIBAN,
} from "../utils.js";
import { ShowInputErrorLabel } from "../components/ShowInputErrorLabel.js";
const logger = new Logger("PaytoWireTransferForm");
@ -88,163 +86,6 @@ export function PaytoWireTransferForm({
const { createTransaction } = useAccessAPI();
if (!isRawPayto)
return (
<div>
<form
class="pure-form"
name="wire-transfer-form"
onSubmit={(e) => {
e.preventDefault();
}}
autoCapitalize="none"
autoCorrect="off"
>
<label for="iban">{i18n.str`Receiver IBAN:`}</label>&nbsp;
<input
ref={ref}
type="text"
id="iban"
name="iban"
value={iban ?? ""}
placeholder="CC0123456789"
required
pattern={ibanRegex}
onInput={(e): void => {
setIban(e.currentTarget.value);
}}
/>
<ShowInputErrorLabel
message={errorsWire?.iban}
isDirty={iban !== undefined}
/>
<label for="subject">{i18n.str`Transfer subject:`}</label>&nbsp;
<input
type="text"
name="subject"
id="subject"
placeholder="subject"
value={subject ?? ""}
required
onInput={(e): void => {
setSubject(e.currentTarget.value);
}}
/>
<ShowInputErrorLabel
message={errorsWire?.subject}
isDirty={subject !== undefined}
/>
<label for="amount">{i18n.str`Amount:`}</label>&nbsp;
<div style={{ width: "max-content", display: "flex" }}>
<input
type="text"
readonly
class="currency-indicator"
size={limit.currency.length}
maxLength={limit.currency.length}
tabIndex={-1}
style={{
borderTopRightRadius: 0,
borderBottomRightRadius: 0,
borderRight: 0,
}}
value={limit.currency}
/>
<input
type="number"
name="amount"
id="amount"
placeholder="amount"
required
style={{
borderTopLeftRadius: 0,
borderBottomLeftRadius: 0,
borderLeft: 0,
width: 150,
}}
value={amount ?? ""}
onInput={(e): void => {
setAmount(e.currentTarget.value);
}}
/>
</div>
<ShowInputErrorLabel
message={errorsWire?.amount}
isDirty={amount !== undefined}
/>
<p style={{ display: "flex", justifyContent: "space-between" }}>
<input
type="submit"
class="pure-button pure-button-primary"
disabled={!!errorsWire}
value="Send"
onClick={async (e) => {
e.preventDefault();
if (!(iban && subject && amount)) {
return;
}
const ibanPayto = buildPayto("iban", iban, undefined);
ibanPayto.params.message = encodeURIComponent(subject);
const paytoUri = stringifyPaytoUri(ibanPayto);
try {
await createTransaction({
paytoUri,
amount: `${limit.currency}:${amount}`,
});
onSuccess();
setAmount(undefined);
setIban(undefined);
setSubject(undefined);
} catch (error) {
if (error instanceof RequestError) {
notifyError(
buildRequestErrorMessage(i18n, error.cause, {
onClientError: (status) =>
status === HttpStatusCode.BadRequest
? i18n.str`The request was invalid or the payto://-URI used unacceptable features.`
: undefined,
}),
);
} else {
notifyError({
title: i18n.str`Operation failed, please report`,
description:
error instanceof Error
? error.message
: JSON.stringify(error),
});
}
}
}}
/>
<input
type="button"
class="pure-button"
value="Clear"
onClick={async (e) => {
e.preventDefault();
setAmount(undefined);
setIban(undefined);
setSubject(undefined);
}}
/>
</p>
</form>
<p>
<a
href="#"
onClick={(e) => {
setIsRawPayto(true);
e.preventDefault();
}}
>
{i18n.str`Want to try the raw payto://-format?`}
</a>
</p>
</div>
);
const parsed = !rawPaytoInput ? undefined : parsePaytoUri(rawPaytoInput);
const errorsPayto = undefinedIfEmpty({
@ -264,30 +105,129 @@ export function PaytoWireTransferForm({
? i18n.str`IBAN should have just uppercased letters and numbers`
: validateIBAN(parsed.iban, i18n),
});
return (
// if (!isRawPayto) {
return (<div class="grid grid-cols-1 gap-x-8 gap-y-8 pt-10 md:grid-cols-3 bg-gray-100 my-4 px-4 pb-4 rounded-lg">
<div class="px-4 sm:px-0">
<h2 class="text-base font-semibold leading-7 text-gray-900"><i18n.Translate>Transfer details</i18n.Translate></h2>
<div>
<p>{i18n.str`Transfer money to account identified by payto:// URI:`}</p>
<form
class="pure-form"
name="payto-form"
onSubmit={(e) => {
e.preventDefault();
<div class="px-4 mt-4 grid grid-cols-1 gap-y-6 sm:grid-cols-2 sm:gap-x-4">
{/* <!-- Active: "border-indigo-600 ring-2 ring-indigo-600", Not Active: "border-gray-300" --> */}
<label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (!isRawPayto ? "border-indigo-600 ring-2 ring-indigo-600" : "border-gray-300")}>
<input type="radio" name="project-type" value="Newsletter" class="sr-only" aria-labelledby="project-type-0-label" aria-describedby="project-type-0-description-0 project-type-0-description-1" onChange={() => {
setIsRawPayto(false)
}} />
<span class="flex flex-1">
<span class="flex flex-col">
<span id="project-type-0-label" class="block text-sm font-medium text-gray-900">
<i18n.Translate>form</i18n.Translate>
</span>
</span>
</span>
</label>
{/* <!-- Active: "border-indigo-600 ring-2 ring-indigo-600", Not Active: "border-gray-300" --> */}
<label class={"relative flex cursor-pointer rounded-lg border bg-white p-4 shadow-sm focus:outline-none" + (isRawPayto ? "border-indigo-600 ring-2 ring-indigo-600" : "border-gray-300")}>
<input type="radio" name="project-type" value="Existing Customers" class="sr-only" aria-labelledby="project-type-1-label" aria-describedby="project-type-1-description-0 project-type-1-description-1" onChange={() => {
setIsRawPayto(true)
}} />
<span class="flex flex-1">
<span class="flex flex-col">
<span id="project-type-1-label" class="block text-sm font-medium text-gray-900">
<i18n.Translate>payto://</i18n.Translate>
</span>
</span>
</span>
</label>
</div>
</div>
</div>
<form class="bg-white shadow-sm ring-1 ring-gray-900/5 sm:rounded-xl md:col-span-2">
<div class="px-4 py-6 sm:p-8">
<div class="grid max-w-2xl grid-cols-1 gap-x-6 gap-y-8 sm:grid-cols-6">
{!isRawPayto ?
<Fragment>
<div class="sm:col-span-3">
<label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Account number`}</label>
<div class="mt-2">
<input
ref={ref}
type="text"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
id="iban"
name="iban"
value={iban ?? ""}
placeholder="CC0123456789"
required
pattern={ibanRegex}
onInput={(e): void => {
setIban(e.currentTarget.value);
}}
autoCapitalize="none"
autoCorrect="off"
>
<p>
<label for="address">{i18n.str`payto URI:`}</label>&nbsp;
/>
<ShowInputErrorLabel
message={errorsWire?.iban}
isDirty={iban !== undefined}
/>
</div>
<p class="mt-2 text-sm text-gray-500" id="email-description">the receiver of the money</p>
</div>
<div class="sm:col-span-3">
</div>
<div class="sm:col-span-3">
<label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Transfer subject`}</label>
<div class="mt-2">
<input
type="text"
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6"
name="subject"
id="subject"
placeholder="subject"
value={subject ?? ""}
required
onInput={(e): void => {
setSubject(e.currentTarget.value);
}}
/>
<ShowInputErrorLabel
message={errorsWire?.subject}
isDirty={subject !== undefined}
/>
</div>
<p class="mt-2 text-sm text-gray-500" id="email-description">some text to identify the transfer</p>
</div>
<div class="sm:col-span-3">
</div>
<div class="sm:col-span-3">
<label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`Amount`}</label>
<div class="mt-2">
<input type="text" name="first-name" id="first-name" autocomplete="given-name" class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" />
</div>
</div>
<div class="sm:col-span-3">
</div>
</Fragment> :
<Fragment>
<div class="sm:col-span-6">
<label for="first-name" class="block text-sm font-medium leading-6 text-gray-900">{i18n.str`payto URI:`}</label>
<div class="mt-2">
<input
name="address"
type="text"
size={50}
ref={ref}
class="block w-full rounded-md border-0 py-1.5 text-gray-900 shadow-sm ring-1 ring-inset ring-gray-300 placeholder:text-gray-400 focus:ring-2 focus:ring-inset focus:ring-indigo-600 sm:text-sm sm:leading-6" ref={ref}
id="address"
value={rawPaytoInput ?? ""}
required
placeholder={i18n.str`payto address`}
placeholder={i18n.str`payto://iban/[receiver-iban]?message=[subject]&amount=[${limit.currency}:X.Y]`}
// pattern={`payto://iban/[A-Z][A-Z][0-9]+?message=[a-zA-Z0-9 ]+&amount=${currency}:[0-9]+(.[0-9]+)?`}
onInput={(e): void => {
rawPaytoInputSetter(e.currentTarget.value);
@ -297,68 +237,155 @@ export function PaytoWireTransferForm({
message={errorsPayto?.rawPaytoInput}
isDirty={rawPaytoInput !== undefined}
/>
<br />
<div style={{ fontSize: "small", marginTop: 4 }}>
Hint:
<code>
payto://iban/[receiver-iban]?message=[subject]&amount=[
{limit.currency}
:X.Y]
</code>
</div>
</p>
<p>
<input
class="pure-button pure-button-primary"
type="button"
disabled={!!errorsPayto}
value={i18n.str`Send`}
onClick={async () => {
if (!rawPaytoInput) {
logger.error("Didn't get any raw Payto string!");
return;
}
</div>
try {
await createTransaction({
paytoUri: rawPaytoInput,
});
onSuccess();
rawPaytoInputSetter(undefined);
} catch (error) {
if (error instanceof RequestError) {
notifyError(
buildRequestErrorMessage(i18n, error.cause, {
onClientError: (status) =>
status === HttpStatusCode.BadRequest
? i18n.str`The request was invalid or the payto://-URI used unacceptable features.`
: undefined,
}),
);
} else {
notifyError({
title: i18n.str`Operation failed, please report`,
description:
error instanceof Error
? error.message
: JSON.stringify(error),
});
</Fragment>
}
}
}}
/>
</p>
<p>
<a
href="/account"
onClick={() => {
setIsRawPayto(false);
}}
>
{i18n.str`Use wire-transfer form?`}
</a>
</p>
</div>
</div>
<div class="flex items-center justify-end gap-x-6 border-t border-gray-900/10 px-4 py-4 sm:px-8">
<button type="button" class="text-sm font-semibold leading-6 text-gray-900">Cancel</button>
<button type="submit" class="rounded-md bg-indigo-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-indigo-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-indigo-600">
<i18n.Translate>Send</i18n.Translate>
</button>
</div>
</form>
</div >
);
)
// }
// return (
// <div>
// <form
// class="pure-form"
// name="wire-transfer-form"
// onSubmit={(e) => {
// e.preventDefault();
// }}
// autoCapitalize="none"
// autoCorrect="off"
// >
// <label for="iban">{i18n.str`Receiver IBAN:`}</label>&nbsp;
// <label for="subject">{i18n.str`Transfer subject:`}</label>&nbsp;
// <label for="amount">{i18n.str`Amount:`}</label>&nbsp;
// <div style={{ width: "max-content", display: "flex" }}>
// <input
// type="text"
// readonly
// class="currency-indicator"
// size={limit.currency.length}
// maxLength={limit.currency.length}
// tabIndex={-1}
// style={{
// borderTopRightRadius: 0,
// borderBottomRightRadius: 0,
// borderRight: 0,
// }}
// value={limit.currency}
// />
// <input
// type="number"
// name="amount"
// id="amount"
// placeholder="amount"
// required
// style={{
// borderTopLeftRadius: 0,
// borderBottomLeftRadius: 0,
// borderLeft: 0,
// width: 150,
// }}
// value={amount ?? ""}
// onInput={(e): void => {
// setAmount(e.currentTarget.value);
// }}
// />
// </div>
// <ShowInputErrorLabel
// message={errorsWire?.amount}
// isDirty={amount !== undefined}
// />
// <p style={{ display: "flex", justifyContent: "space-between" }}>
// <input
// type="submit"
// class="pure-button pure-button-primary"
// disabled={!!errorsWire}
// value="Send"
// onClick={async (e) => {
// e.preventDefault();
// if (!(iban && subject && amount)) {
// return;
// }
// const ibanPayto = buildPayto("iban", iban, undefined);
// ibanPayto.params.message = encodeURIComponent(subject);
// const paytoUri = stringifyPaytoUri(ibanPayto);
// try {
// await createTransaction({
// paytoUri,
// amount: `${limit.currency}:${amount}`,
// });
// onSuccess();
// setAmount(undefined);
// setIban(undefined);
// setSubject(undefined);
// } catch (error) {
// if (error instanceof RequestError) {
// notifyError(
// buildRequestErrorMessage(i18n, error.cause, {
// onClientError: (status) =>
// status === HttpStatusCode.BadRequest
// ? i18n.str`The request was invalid or the payto://-URI used unacceptable features.`
// : undefined,
// }),
// );
// } else {
// notifyError({
// title: i18n.str`Operation failed, please report`,
// description:
// error instanceof Error
// ? error.message
// : JSON.stringify(error),
// });
// }
// }
// }}
// />
// <input
// type="button"
// class="pure-button"
// value="Clear"
// onClick={async (e) => {
// e.preventDefault();
// setAmount(undefined);
// setIban(undefined);
// setSubject(undefined);
// }}
// />
// </p>
// </form>
// <p>
// <a
// href="#"
// onClick={(e) => {
// setIsRawPayto(true);
// e.preventDefault();
// }}
// >
// {i18n.str`Want to try the raw payto://-format?`}
// </a>
// </p>
// </div>
// );
// return (
// <div>
// <p>{i18n.str`Transfer money to account identified by payto:// URI:`}</p>
// </div>
// );
}

View File

@ -0,0 +1,5 @@
import { VNode, h } from "preact";
export function Test(): VNode {
return <div >hola</div>
}

View File

@ -1,70 +0,0 @@
.rdp-picker {
display: flex;
height: 175px;
}
@media (max-width: 400px) {
.rdp-picker {
width: 250px;
}
}
.rdp-masked-div {
overflow: hidden;
height: 175px;
position: relative;
}
.rdp-column-container {
flex-grow: 1;
display: inline-block;
}
.rdp-column {
position: absolute;
z-index: 0;
width: 100%;
}
.rdp-reticule {
border: 0;
border-top: 2px solid rgba(109, 202, 236, 1);
height: 2px;
position: absolute;
width: 80%;
margin: 0;
z-index: 100;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
.rdp-text-overlay {
position: absolute;
display: flex;
align-items: center;
justify-content: center;
height: 35px;
font-size: 20px;
left: 50%;
-webkit-transform: translateX(-50%);
transform: translateX(-50%);
}
.rdp-cell div {
font-size: 17px;
color: gray;
font-style: italic;
}
.rdp-cell {
display: flex;
align-items: center;
justify-content: center;
height: 35px;
font-size: 18px;
}
.rdp-center {
font-size: 25px;
}

View File

@ -1,128 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
html {
&.has-aside-left {
&.has-aside-expanded {
nav.navbar,
body {
padding-left: $aside-width;
}
}
aside.is-placed-left {
display: block;
}
}
}
aside.aside.is-expanded {
width: $aside-width;
.menu-list {
@include icon-with-update-mark($aside-icon-width);
span.menu-item-label {
display: inline-block;
}
li.is-active {
ul {
display: block;
}
background-color: $body-background-color;
}
}
}
aside.aside {
display: none;
position: fixed;
top: 0;
left: 0;
z-index: 40;
height: 100vh;
padding: 0;
box-shadow: $aside-box-shadow;
background: $aside-background-color;
.aside-tools {
display: flex;
flex-direction: row;
width: 100%;
background-color: $aside-tools-background-color;
color: $aside-tools-color;
line-height: $navbar-height;
height: $navbar-height;
padding-left: $default-padding * 0.5;
flex: 1;
.icon {
margin-right: $default-padding * 0.5;
}
}
.menu-list {
li {
a {
&.has-dropdown-icon {
position: relative;
padding-right: $aside-icon-width;
.dropdown-icon {
position: absolute;
top: $size-base * 0.5;
right: 0;
}
}
}
ul {
display: none;
border-left: 0;
background-color: darken($base-color, 2.5%);
padding-left: 0;
margin: 0 0 $default-padding * 0.5;
li {
a {
padding: $default-padding * 0.5 0 $default-padding * 0.5
$default-padding * 0.5;
font-size: $aside-submenu-font-size;
&.has-icon {
padding-left: 0;
}
&.is-active {
&:not(:hover) {
background: transparent;
}
}
}
}
}
}
}
.menu-label {
padding: 0 $default-padding * 0.5;
margin-top: $default-padding * 0.5;
margin-bottom: $default-padding * 0.5;
}
}

View File

@ -1,69 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
.card:not(:last-child) {
margin-bottom: $default-padding;
}
.card {
border-radius: $radius-large;
border: $card-border;
&.has-table {
.card-content {
padding: 0;
}
.b-table {
border-radius: $radius-large;
overflow: hidden;
}
}
&.is-card-widget {
.card-content {
padding: $default-padding * 0.5;
}
}
.card-header {
border-bottom: 1px solid $base-color-light;
}
.card-content {
hr {
margin-left: $card-content-padding * -1;
margin-right: $card-content-padding * -1;
}
}
.is-widget-icon {
.icon {
width: 5rem;
height: 5rem;
}
}
.is-widget-label {
.subtitle {
color: $grey;
}
}
}

View File

@ -1,263 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
:root {
--primary-color: #3298dc;
--primary-text-color-dark: rgba(0, 0, 0, 0.87);
--secondary-text-color-dark: rgba(0, 0, 0, 0.57);
--disabled-text-color-dark: rgba(0, 0, 0, 0.13);
--primary-text-color-light: rgba(255, 255, 255, 0.87);
--secondary-text-color-light: rgba(255, 255, 255, 0.57);
--disabled-text-color-light: rgba(255, 255, 255, 0.13);
--font-stack: "Roboto", "Helvetica Neue", Helvetica, Arial, sans-serif;
--primary-card-color: #fff;
--primary-background-color: #f2f2f2;
--box-shadow-lvl-1: 0 1px 3px rgba(0, 0, 0, 0.12),
0 1px 2px rgba(0, 0, 0, 0.24);
--box-shadow-lvl-2: 0 3px 6px rgba(0, 0, 0, 0.16),
0 3px 6px rgba(0, 0, 0, 0.23);
--box-shadow-lvl-3: 0 10px 20px rgba(0, 0, 0, 0.19),
0 6px 6px rgba(0, 0, 0, 0.23);
--box-shadow-lvl-4: 0 14px 28px rgba(0, 0, 0, 0.25),
0 10px 10px rgba(0, 0, 0, 0.22);
}
.home .datePicker div {
margin-top: 0px;
margin-bottom: 0px;
}
.datePicker {
text-align: left;
background: var(--primary-card-color);
border-radius: 3px;
z-index: 200;
position: fixed;
height: auto;
max-height: 90vh;
width: 90vw;
max-width: 448px;
transform-origin: top left;
transition: transform 0.22s ease-in-out, opacity 0.22s ease-in-out;
top: 50%;
left: 50%;
opacity: 0;
transform: scale(0) translate(-50%, -50%);
user-select: none;
&.datePicker--opened {
opacity: 1;
transform: scale(1) translate(-50%, -50%);
}
.datePicker--titles {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
padding: 24px;
height: 100px;
background: var(--primary-color);
h2,
h3 {
cursor: pointer;
color: #fff;
line-height: 1;
padding: 0;
margin: 0;
font-size: 32px;
}
h3 {
color: rgba(255, 255, 255, 0.57);
font-size: 18px;
padding-bottom: 2px;
}
}
nav {
padding: 20px;
height: 56px;
h4 {
width: calc(100% - 60px);
text-align: center;
display: inline-block;
padding: 0;
font-size: 14px;
line-height: 24px;
margin: 0;
position: relative;
top: -9px;
color: var(--primary-text-color);
}
i {
cursor: pointer;
color: var(--secondary-text-color);
font-size: 26px;
user-select: none;
border-radius: 50%;
&:hover {
background: var(--disabled-text-color-dark);
}
}
}
.datePicker--scroll {
overflow-y: auto;
max-height: calc(90vh - 56px - 100px);
}
.datePicker--calendar {
padding: 0 20px;
.datePicker--dayNames {
width: 100%;
display: grid;
text-align: center;
// there's probably a better way to do this, but wanted to try out CSS grid
grid-template-columns:
calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(100% / 7)
calc(100% / 7) calc(100% / 7) calc(100% / 7);
span {
color: var(--secondary-text-color-dark);
font-size: 14px;
line-height: 42px;
display: inline-grid;
}
}
.datePicker--days {
width: 100%;
display: grid;
text-align: center;
grid-template-columns:
calc(100% / 7) calc(100% / 7) calc(100% / 7) calc(100% / 7)
calc(100% / 7) calc(100% / 7) calc(100% / 7);
span {
color: var(--primary-text-color-dark);
line-height: 42px;
font-size: 14px;
display: inline-grid;
transition: color 0.22s;
height: 42px;
position: relative;
cursor: pointer;
user-select: none;
border-radius: 50%;
&::before {
content: "";
position: absolute;
z-index: -1;
height: 42px;
width: 42px;
left: calc(50% - 21px);
background: var(--primary-color);
border-radius: 50%;
transition: transform 0.22s, opacity 0.22s;
transform: scale(0);
opacity: 0;
}
&[disabled="true"] {
cursor: unset;
}
&.datePicker--today {
font-weight: 700;
}
&.datePicker--selected {
color: rgba(255, 255, 255, 0.87);
&:before {
transform: scale(1);
opacity: 1;
}
}
}
}
}
.datePicker--selectYear {
padding: 0 20px;
display: block;
width: 100%;
text-align: center;
max-height: 362px;
span {
display: block;
width: 100%;
font-size: 24px;
margin: 20px auto;
cursor: pointer;
&.selected {
font-size: 42px;
color: var(--primary-color);
}
}
}
div.datePicker--actions {
width: 100%;
padding: 8px;
text-align: right;
button {
margin-bottom: 0;
font-size: 15px;
cursor: pointer;
color: var(--primary-text-color);
border: none;
margin-left: 8px;
min-width: 64px;
line-height: 36px;
background-color: transparent;
appearance: none;
padding: 0 16px;
border-radius: 3px;
transition: background-color 0.13s;
&:hover,
&:focus {
outline: none;
background-color: var(--disabled-text-color-dark);
}
}
}
}
.datePicker--background {
z-index: 199;
position: fixed;
top: 0;
left: 0;
bottom: 0;
right: 0;
background: rgba(0, 0, 0, 0.52);
animation: fadeIn 0.22s forwards;
}

View File

@ -1,35 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
footer.footer {
.logo {
img {
width: auto;
height: $footer-logo-height;
}
}
}
@include mobile {
.footer-copyright {
text-align: center;
}
}

View File

@ -1,71 +0,0 @@
/*
This file is part of GNU Taler
(C) 2022 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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
.field {
&.has-check {
.field-body {
margin-top: $default-padding * 0.125;
}
}
.control {
.mdi-24px.mdi-set,
.mdi-24px.mdi:before {
font-size: inherit;
}
}
}
.upload {
.upload-draggable {
display: block;
}
}
.input,
.textarea,
select {
box-shadow: none;
&:focus,
&:active {
box-shadow: none !important;
}
}
.switch input[type="checkbox"] + .check:before {
box-shadow: none;
}
.switch,
.b-checkbox.checkbox {
input[type="checkbox"] {
&:focus + .check,
&:focus:checked + .check {
box-shadow: none !important;
}
}
}
.b-checkbox.checkbox input[type="checkbox"],
.b-radio.radio input[type="radio"] {
& + .check {
border: $checkbox-border;
}
}

View File

@ -1,55 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
section.hero.is-hero-bar {
background-color: $hero-bar-background;
border-bottom: $light-border;
.hero-body {
padding: $default-padding;
.level-item {
&.is-hero-avatar-item {
margin-right: $default-padding;
}
> div > .level {
margin-bottom: $default-padding * 0.5;
}
.subtitle + p {
margin-top: $default-padding * 0.5;
}
}
.button {
&.is-hero-button {
background-color: rgba($white, 0.5);
font-weight: 300;
@include transition(background-color);
&:hover {
background-color: $white;
}
}
}
}
}

View File

@ -1,51 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
.lds-ring {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 64px;
height: 64px;
margin: 8px;
border: 8px solid black;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: black transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -1,24 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
section.section.is-main-section {
padding-top: $default-padding;
}

View File

@ -1,50 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
.is-user-avatar {
&.has-max-width {
max-width: $size-base * 7;
}
&.is-aligned-center {
margin: 0 auto;
}
img {
margin: 0 auto;
border-radius: $radius-rounded;
}
}
.icon.has-update-mark {
position: relative;
&:after {
content: "";
width: $icon-update-mark-size;
height: $icon-update-mark-size;
position: absolute;
top: 1px;
right: 1px;
background-color: $icon-update-mark-color;
border-radius: $radius-rounded;
}
}

View File

@ -1,34 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
@mixin transition($t) {
transition: $t 250ms ease-in-out 50ms;
}
@mixin icon-with-update-mark($icon-base-width) {
.icon {
width: $icon-base-width;
&.has-update-mark:after {
right: ($icon-base-width / 2) - 0.85;
}
}
}

View File

@ -1,35 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
.modal-card {
width: $modal-card-width;
}
.modal-card-foot {
background-color: $modal-card-foot-background-color;
}
@include mobile {
.modal .animation-content .modal-card {
width: $modal-card-width-mobile;
margin: 0 auto;
}
}

View File

@ -1,144 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
nav.navbar {
box-shadow: $navbar-box-shadow;
.navbar-item {
&.has-user-avatar {
.is-user-avatar {
margin-right: $default-padding * 0.5;
display: inline-flex;
width: $navbar-avatar-size;
height: $navbar-avatar-size;
}
}
&.has-divider {
border-right: $navbar-divider-border;
}
&.no-left-space {
padding-left: 0;
}
&.has-dropdown {
padding-right: 0;
padding-left: 0;
.navbar-link {
padding-right: $navbar-item-h-padding;
padding-left: $navbar-item-h-padding;
}
}
&.has-control {
padding-top: 0;
padding-bottom: 0;
}
.control {
.input {
color: $navbar-input-color;
border: 0;
box-shadow: none;
background: transparent;
&::placeholder {
color: $navbar-input-placeholder-color;
}
}
}
}
}
@include touch {
nav.navbar {
display: flex;
padding-right: 0;
.navbar-brand {
flex: 1;
&.is-right {
flex: none;
}
}
.navbar-item {
&.no-left-space-touch {
padding-left: 0;
}
}
.navbar-menu {
position: absolute;
width: 100vw;
padding-top: 0;
top: $navbar-height;
left: 0;
.navbar-item {
.icon:first-child {
margin-right: $default-padding * 0.5;
}
&.has-dropdown {
> .navbar-link {
background-color: $white-ter;
.icon:last-child {
display: none;
}
}
}
&.has-user-avatar {
> .navbar-link {
display: flex;
align-items: center;
padding-top: $default-padding * 0.5;
padding-bottom: $default-padding * 0.5;
}
}
}
}
}
}
@include desktop {
nav.navbar {
.navbar-item {
padding-right: $navbar-item-h-padding;
padding-left: $navbar-item-h-padding;
&:not(.is-desktop-icon-only) {
.icon:first-child {
margin-right: $default-padding * 0.5;
}
}
&.is-desktop-icon-only {
span:not(.icon) {
display: none;
}
}
}
}
}

View File

@ -1,179 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
table.table {
thead {
th {
border-bottom-width: 1px;
}
}
td,
th {
&.checkbox-cell {
.b-checkbox.checkbox:not(.button) {
margin-right: 0;
width: 20px;
.control-label {
display: none;
padding: 0;
}
}
}
}
td {
.image {
margin: 0 auto;
width: $table-avatar-size;
height: $table-avatar-size;
}
&.is-progress-col {
min-width: 5rem;
vertical-align: middle;
}
}
}
.b-table {
.table {
border: 0;
border-radius: 0;
}
/* This stylizes buefy's pagination */
.table-wrapper {
margin-bottom: 0;
}
.table-wrapper + .level {
padding: $notification-padding;
padding-left: $card-content-padding;
padding-right: $card-content-padding;
margin: 0;
border-top: $base-color-light;
background: $notification-background-color;
.pagination-link {
background: $button-background-color;
color: $button-color;
border-color: $button-border-color;
&.is-current {
border-color: $button-active-border-color;
}
}
.pagination-previous,
.pagination-next,
.pagination-link {
border-color: $button-border-color;
color: $base-color;
&[disabled] {
background-color: transparent;
}
}
}
}
@include mobile {
.card {
&.has-table {
.b-table {
.table-wrapper + .level {
.level-left + .level-right {
margin-top: 0;
}
}
}
}
&.has-mobile-sort-spaced {
.b-table {
.field.table-mobile-sort {
padding-top: $default-padding * 0.5;
}
}
}
}
.b-table {
.field.table-mobile-sort {
padding: 0 $default-padding * 0.5;
}
.table-wrapper.has-mobile-cards {
tr {
box-shadow: 0 2px 3px rgba(10, 10, 10, 0.1);
margin-bottom: 3px !important;
}
td {
&.is-progress-col {
span,
progress {
display: flex;
width: 45%;
align-items: center;
align-self: center;
}
}
&.checkbox-cell,
&.is-image-cell {
border-bottom: 0 !important;
}
&.checkbox-cell,
&.is-actions-cell {
&:before {
display: none;
}
}
&.has-no-head-mobile {
&:before {
display: none;
}
span {
display: block;
width: 100%;
}
&.is-progress-col {
progress {
width: 100%;
}
}
&.is-image-cell {
.image {
width: $table-avatar-size-mobile;
height: auto;
margin: 0 auto $default-padding * 0.25;
}
}
}
}
}
}
}

View File

@ -1,136 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
/* We'll need some initial vars to use here */
@import "node_modules/bulma/sass/utilities/initial-variables";
/* Base: Size */
$size-base: 1rem;
$default-padding: $size-base * 1.5;
/* Default font */
$family-sans-serif: "Nunito", sans-serif;
/* Base color */
$base-color: #2e323a;
$base-color-light: rgba(24, 28, 33, 0.06);
/* General overrides */
$primary: $turquoise;
$body-background-color: #f8f8f8;
$link: $blue;
$link-visited: $purple;
$light-border: 1px solid $base-color-light;
$hr-height: 1px;
/* NavBar: specifics */
$navbar-input-color: $grey-darker;
$navbar-input-placeholder-color: $grey-lighter;
$navbar-box-shadow: 0 1px 0 rgba(24, 28, 33, 0.04);
$navbar-divider-border: 1px solid rgba($grey-lighter, 0.25);
$navbar-item-h-padding: $default-padding * 0.75;
$navbar-avatar-size: 1.75rem;
/* Aside: Bulma override */
$menu-item-radius: 0;
$menu-list-link-padding: $size-base * 0.5 0;
$menu-label-color: lighten($base-color, 25%);
$menu-item-color: lighten($base-color, 30%);
$menu-item-hover-color: $white;
$menu-item-hover-background-color: darken($base-color, 3.5%);
$menu-item-active-color: $white;
$menu-item-active-background-color: darken($base-color, 2.5%);
/* Aside: specifics */
$aside-width: $size-base * 14;
$aside-mobile-width: $size-base * 15;
$aside-icon-width: $size-base * 3;
$aside-submenu-font-size: $size-base * 0.95;
$aside-box-shadow: none;
$aside-background-color: $base-color;
$aside-tools-background-color: darken($aside-background-color, 10%);
$aside-tools-color: $white;
/* Title Bar: specifics */
$title-bar-color: $grey;
$title-bar-active-color: $black-ter;
/* Hero Bar: specifics */
$hero-bar-background: $white;
/* Card: Bulma override */
$card-shadow: none;
$card-header-shadow: none;
/* Card: specifics */
$card-border: 1px solid $base-color-light;
$card-header-border-bottom-color: $base-color-light;
/* Table: Bulma override */
$table-cell-border: 1px solid $white-bis;
/* Table: specifics */
$table-avatar-size: $size-base * 1.5;
$table-avatar-size-mobile: 25vw;
/* Form */
$checkbox-border: 1px solid $base-color;
/* Modal card: Bulma override */
$modal-card-head-background-color: $white-ter;
$modal-card-title-size: $size-base;
$modal-card-body-padding: $default-padding 20px;
$modal-card-head-border-bottom: 1px solid $white-ter;
$modal-card-foot-border-top: 0;
/* Modal card: specifics */
$modal-card-width: 80vw;
$modal-card-width-mobile: 90vw;
$modal-card-foot-background-color: $white-ter;
/* Notification: Bulma override */
$notification-padding: $default-padding * 0.75 $default-padding;
/* Footer: Bulma override */
$footer-background-color: $white;
$footer-padding: $default-padding * 0.33 $default-padding;
/* Footer: specifics */
$footer-logo-height: $size-base * 2;
/* Progress: Bulma override */
$progress-bar-background-color: $grey-lighter;
/* Icon: specifics */
$icon-update-mark-size: $size-base * 0.5;
$icon-update-mark-color: $yellow;
$input-disabled-border-color: $grey-lighter;
$table-row-hover-background-color: hsl(0, 0%, 80%);
.menu-list {
div {
border-radius: $menu-item-radius;
color: $menu-item-color;
display: block;
padding: $menu-list-link-padding;
}
}

View File

@ -1,24 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
.is-tiles-wrapper {
margin-bottom: $default-padding;
}

View File

@ -1,50 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
section.section.is-title-bar {
padding: $default-padding;
border-bottom: $light-border;
ul {
li {
display: inline-block;
padding: 0 $default-padding * 0.5 0 0;
font-size: $default-padding;
color: $title-bar-color;
&:after {
display: inline-block;
content: "/";
padding-left: $default-padding * 0.5;
}
&:last-child {
padding-right: 0;
font-weight: 900;
color: $title-bar-active-color;
&:after {
display: none;
}
}
}
}
}

View File

@ -1,353 +0,0 @@
.navcontainer:not(.default-navcontainer) {
margin-bottom: 0 !important;
}
.abort-button {
margin-left: 2px;
border: 2px solid rgb(0, 120, 231);
color: rgb(0, 120, 231);
font-size: 87%;
margin-top: 1px;
background: white;
}
div.pages-list {
margin-top: 15px;
}
.footer {
margin-left: 2em;
margin-right: 2em;
}
.qr-div,
.login-div,
.register-div {
display: block;
text-align: center;
}
a.page-number {
color: blue;
}
a.current-page-number {
color: inherit;
background-color: inherit;
}
.cancelled {
text-decoration: line-through;
}
input[type="number"]::-webkit-outer-spin-button,
input[type="number"]::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* This CSS code styles the tab */
.tab {
overflow: hidden;
}
.top-right {
float: right;
}
.some-space {
display: inline-block;
border: 20px;
margin-right: 15px;
margin-top: 15px;
}
.tab button {
background-color: lightgray;
color: black;
float: left;
border: none;
outline: none;
cursor: pointer;
padding: 18px 19px;
border: 2px solid #c1c1c1;
transition: 0.5s;
font-weight: bold;
}
.tab button:hover {
background-color: yellow;
border: 2px solid #c1c1c1;
color: black;
}
.tab button.active {
background-color: orange;
border: 2px solid #c1c1c1;
color: black;
font-weight: bold;
}
.tabcontent {
display: none;
padding: 8px 16px;
border: 2px solid #c1c1c1;
width: min-content;
}
.tabcontent.active {
display: block;
}
input[type="number"] {
-moz-appearance: textfield;
}
#transfer-fields {
display: flex;
flex-wrap: wrap;
}
#id_amount {
width: 6em;
display: inline-block;
border-radius: 4px 0px 0px 4px;
}
/**
* Amount without the currency,
* placed left to a .currency-indicator.
*/
#main .amount {
width: 6em;
display: inline-block;
border-radius: 4px 0px 0px 4px;
}
input {
background-color: inherit;
}
.large-amount {
font-weight: bold;
font-size: xxx-large;
}
.currency {
font-style: oblique;
}
/*
* Currency indicator to the right of input fields,
* with non-rounded corners to the left.
*/
#main .currency-indicator {
color: black;
border-radius: 4px 0px 0px 4px;
position: relative;
}
#main .fieldlabel {
display: block;
padding-bottom: 0.5em;
}
#main .fieldbox {
margin-right: 1em;
margin-bottom: 0.5em;
}
#logout-button {
display: block;
width: fit-content;
}
.register-form > .pure-form,
.login-form > .pure-form {
background: #4a4a4a;
color: #ffffff;
display: inline-block;
text-align: left;
margin-left: auto;
margin-right: auto;
padding: 16px 16px;
border-radius: 8px;
width: min-content;
.formFieldLabel {
margin: 2px 2px;
}
input[type="text"],
input[type="password"] {
border: none;
border-radius: 4px;
background: #6a6a6a;
color: #fefefe;
box-shadow: none;
}
input[placeholder="Password"][type="password"] {
margin-bottom: 8px;
}
.btn-register,
.btn-login {
float: left;
}
.btn-cancel {
float: right;
}
h2 {
margin-top: 0;
margin-bottom: 10px;
}
}
.challenge-div {
display: block;
text-align: center;
}
.challenge-form > .pure-form {
background: #4a4a4a;
color: #ffffff;
display: inline-block;
text-align: left;
margin-left: auto;
margin-right: auto;
padding: 16px 16px;
border-radius: 8px;
width: min-content;
.formFieldLabel {
margin: 2px 2px;
}
input[type="text"] {
border: none;
border-radius: 4px;
background: #6a6a6a;
color: #fefefe;
box-shadow: none;
}
.btn-confirm {
float: left;
}
.btn-cancel {
float: right;
}
h2 {
margin-top: 0;
margin-bottom: 10px;
}
}
.wire-transfer-form > .pure-form,
.payto-form > .pure-form,
.reserve-form > .pure-form {
background: #4a4a4a;
color: #ffffff;
display: inline-block;
text-align: left;
margin-left: auto;
margin-right: auto;
padding: 16px 16px;
border-radius: 8px;
width: min-content;
.formFieldLabel {
margin: 2px 2px;
}
input[type="text"] {
border: none;
border-radius: 4px;
background: #6a6a6a;
color: #fefefe;
box-shadow: none;
}
}
html {
background: #ffffff;
color: #2a2a2a;
}
.hint {
scale: 0.7;
}
h1.nav {
text-align: center;
}
.pure-form > fieldset > label {
display: block;
}
.pure-form > fieldset > input[disabled] {
color: black !important;
}
.pure-form > fieldset > div > input[disabled] {
color: black !important;
}
.pure-form > fieldset > div.channel > div {
display: inline-block;
margin: 1em;
border: 1px black solid;
width: fit-content;
padding: 0.4em;
cursor: pointer;
}
.button-success {
background: rgb(28, 184, 65);
/* this is a green */
}
.button-error {
background: rgb(202, 60, 60);
/* this is a maroon */
}
.button-warning {
background: rgb(223, 117, 20);
/* this is an orange */
}
.button-secondary {
background: rgb(66, 184, 221);
/* this is a light blue */
}
[name=wire-transfer-form] > input {
margin-bottom: 1em;
}
.lds-ring {
display: inline-block;
position: relative;
width: 80px;
height: 80px;
}
.lds-ring div {
box-sizing: border-box;
display: block;
position: absolute;
width: 64px;
height: 64px;
margin: 8px;
border: 8px solid black;
border-radius: 50%;
animation: lds-ring 1.2s cubic-bezier(0.5, 0, 0.5, 1) infinite;
border-color: black transparent transparent transparent;
}
.lds-ring div:nth-child(1) {
animation-delay: -0.45s;
}
.lds-ring div:nth-child(2) {
animation-delay: -0.3s;
}
.lds-ring div:nth-child(3) {
animation-delay: -0.15s;
}
@keyframes lds-ring {
0% {
transform: rotate(0deg);
}
100% {
transform: rotate(360deg);
}
}

View File

@ -1,31 +0,0 @@
nav,
nav a,
nav span,
.navcontainer,
nav button,
.demobar,
.navbtn {
color: white;
background: #a00000;
}
nav a.active,
nav button,
nav span.active,
.navbtn.active {
background-color: #7a0606;
}
nav a.active:hover,
nav span.active:hover,
.navbtn.active:hover,
nav button:hover,
nav a:hover,
nav span:hover,
.navbtn:hover {
background: #df3d3d;
}
nav a.navbtn.langbtn:focus {
background-color: #df3d3d;
}

View File

@ -1,167 +0,0 @@
@charset "UTF-8";
/*
Style common to all demo pages.
Colors:
- #1e2739 (dark blue)
- #0042b2 (default blue)
- #3daee9 (highlight blue)
*/
.demobar h1 {
text-align: center;
}
.demobar > p {
padding: 0.5em;
}
.demobar a,
.demobar a:visited {
color: inherit;
background-color: inherit;
}
.tt {
font-family: "Lucida Console", Monaco, monospace;
}
.informational-ok {
background: lightgreen;
border-radius: 1em;
padding: 0.5em;
}
.informational-fail {
background: lightpink;
border-radius: 1em;
padding: 0.5em;
}
.content {
margin-left: 1em;
margin-right: 1em;
overflow-x: auto;
}
.demobar {
overflow-x: auto;
background-color: #0042b2;
color: white;
}
body {
overflow-x: hidden;
overflow-y: auto;
}
.navcontainer {
background: #0042b2;
margin-bottom: 50px;
width: 100%;
color: white;
// position: -webkit-sticky;
// position: sticky;
top: 0px;
width: 100vw;
backdrop-filter: blur(10px);
opacity: 1;
z-index: 100;
}
nav {
// left: 1vw;
position: relative;
background: #0042b2;
z-index: 100;
}
nav a,
nav button,
nav span,
.navbtn {
border: none;
color: white;
text-align: center;
// text-decoration: none;
display: inline-block;
font-size: 16px;
background: #0042b2;
height: inherit;
}
nav a,
nav button,
nav span,
.navbtn {
padding: 8px;
}
nav a:hover,
nav span:hover,
.navbtn:hover {
background: #3daee9;
}
nav a.active,
nav span.active,
.navbtn.active {
background-color: #1e2739;
}
nav a.active:hover,
nav button.active:hover,
nav span.active:hover,
.navbtn.active:hover {
background: #3daee9;
}
nav a,
nav span,
.navbtn {
cursor: pointer;
}
nav .right {
float: right;
margin-right: 5vw;
}
nav .hide div.nav {
display: none;
}
// nav .right div.nav:hover {
// display: block;
// }
// nav .right:hover div.nav {
// display: block;
// }
.langbtn {
width: 100px;
text-align: left;
}
.skip {
position: absolute;
left: -10000px;
top: auto;
width: 1px;
height: 1px;
overflow: hidden;
}
.skip:focus {
position: static;
width: auto;
height: auto;
}
.demolist > a {
margin: 8px;
}
.buttons-account input.pure-button {
margin: 8px;
}

View File

@ -1,22 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
@font-face {
font-family: "Nunito";
font-style: normal;
font-weight: 400;
src: url(./XRXV3I6Li01BKofINeaE.ttf) format("truetype");
}

File diff suppressed because it is too large Load Diff

View File

@ -1,29 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>
*/
/**
*
* @author Sebastian Javier Marchano (sebasjm)
*/
@import "node_modules/bulma-radio/bulma-radio";
// @import "node_modules/bulma-responsive-tables/bulma-responsive-tables";
@import "node_modules/bulma-checkbox/bulma-checkbox";
// @import "node_modules/bulma-switch-control/bulma-switch-control";
// @import "node_modules/bulma-upload-control/bulma-upload-control";
/* Bulma */
@import "node_modules/bulma/bulma";

View File

@ -0,0 +1,3 @@
@tailwind base;
@tailwind components;
@tailwind utilities;

View File

@ -1,5 +0,0 @@
@use "pure";
@use "bank";
@use "demo";
@use "toggle";
@use "colors-bank";

File diff suppressed because it is too large Load Diff

View File

@ -1,51 +0,0 @@
$green: #56c080;
.toggle {
cursor: pointer;
display: inline-block;
}
.toggle-switch {
display: inline-block;
background: #ccc;
border-radius: 16px;
width: 58px;
height: 32px;
position: relative;
vertical-align: middle;
transition: background 0.25s;
&:before,
&:after {
content: "";
}
&:before {
display: block;
background: linear-gradient(to bottom, #fff 0%, #eee 100%);
border-radius: 50%;
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.25);
width: 24px;
height: 24px;
position: absolute;
top: 4px;
left: 4px;
transition: left 0.25s;
}
.toggle:hover &:before {
background: linear-gradient(to bottom, #fff 0%, #fff 100%);
box-shadow: 0 0 0 1px rgba(0, 0, 0, 0.5);
}
.toggle-checkbox:checked + & {
background: $green;
&:before {
left: 30px;
}
}
}
.toggle-checkbox {
position: absolute;
visibility: hidden;
}
.toggle-label {
margin-left: 5px;
position: relative;
top: 2px;
}

View File

@ -25,8 +25,6 @@ import * as components from "./components/index.examples.js";
import { renderStories } from "@gnu-taler/web-util/browser";
import "./scss/main.scss";
function main(): void {
renderStories(
{ pages, components },

View File

@ -0,0 +1,8 @@
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{html,tsx}"],
theme: {
extend: {},
},
plugins: [require("@tailwindcss/typography"), require("@tailwindcss/forms")],
};

View File

@ -1,4 +1,4 @@
lockfileVersion: '6.0'
lockfileVersion: '6.1'
settings:
autoInstallPeers: true
@ -259,6 +259,12 @@ importers:
'@gnu-taler/pogen':
specifier: ^0.0.5
version: link:../pogen
'@tailwindcss/forms':
specifier: ^0.5.3
version: 0.5.3(tailwindcss@3.3.2)
'@tailwindcss/typography':
specifier: ^0.5.9
version: 0.5.9(tailwindcss@3.3.2)
'@types/chai':
specifier: ^4.3.0
version: 4.3.3
@ -277,6 +283,9 @@ importers:
'@typescript-eslint/parser':
specifier: ^5.41.0
version: 5.41.0(eslint@8.48.0)(typescript@5.2.2)
autoprefixer:
specifier: ^10.4.14
version: 10.4.14(postcss@8.4.23)
bulma:
specifier: ^0.9.4
version: 0.9.4
@ -307,6 +316,9 @@ importers:
sass:
specifier: 1.56.1
version: 1.56.1
tailwindcss:
specifier: ^3.3.2
version: 3.3.2
typescript:
specifier: 5.2.2
version: 5.2.2
@ -319,7 +331,7 @@ importers:
optionalDependencies:
better-sqlite3:
specifier: ^8.4.0
version: 8.6.0
version: 8.4.0
devDependencies:
'@types/better-sqlite3':
specifier: ^7.6.4
@ -1122,7 +1134,7 @@ packages:
engines: {node: '>=6.9.0'}
dependencies:
'@babel/types': 7.22.4
'@jridgewell/gen-mapping': 0.3.2
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.17
jsesc: 2.5.2
@ -4925,15 +4937,15 @@ packages:
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.14
'@jridgewell/sourcemap-codec': 1.4.15
/@jridgewell/gen-mapping@0.3.2:
resolution: {integrity: sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==}
engines: {node: '>=6.0.0'}
dependencies:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.14
'@jridgewell/trace-mapping': 0.3.17
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.19
/@jridgewell/gen-mapping@0.3.3:
resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==}
@ -4942,7 +4954,6 @@ packages:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.19
dev: true
/@jridgewell/resolve-uri@3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
@ -4960,8 +4971,8 @@ packages:
/@jridgewell/source-map@0.3.2:
resolution: {integrity: sha512-m7O9o2uR8k2ObDysZYzdfhb08VuEml5oWGiosa1VdaPZ/A6QyPkAJuwN0Q1lhULOf6B7MtQmHENS743hWtCrgw==}
dependencies:
'@jridgewell/gen-mapping': 0.3.2
'@jridgewell/trace-mapping': 0.3.17
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.19
dev: true
/@jridgewell/source-map@0.3.5:
@ -4976,7 +4987,6 @@ packages:
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.17:
resolution: {integrity: sha512-MCNzAp77qzKca9+W/+I0+sEpaUnZoeasnghNeVc41VZCEKaCH73Vq3BZZ/SzWIgrqE4H4ceI+p+b6C0mHf9T4g==}
@ -4987,15 +4997,14 @@ packages:
/@jridgewell/trace-mapping@0.3.19:
resolution: {integrity: sha512-kf37QtfW+Hwx/buWGMPcR60iF9ziHa6r/CZJIHbmcm4+0qrXiVdxegAH0F6yddEVQ7zdkjcGCgCzUu+BcbhQxw==}
dependencies:
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@jridgewell/trace-mapping@0.3.9:
resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==}
dependencies:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
'@jridgewell/resolve-uri': 3.1.1
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/@leichtgewicht/ip-codec@2.0.4:
@ -5466,7 +5475,7 @@ packages:
builtin-modules: 3.3.0
deepmerge: 4.2.2
is-module: 1.0.0
resolve: 1.22.1
resolve: 1.22.2
rollup: 2.79.1
dev: true
@ -7003,7 +7012,7 @@ packages:
dependencies:
'@babel/runtime': 7.19.4
cosmiconfig: 7.0.1
resolve: 1.22.1
resolve: 1.22.2
dev: true
/babel-plugin-polyfill-corejs2@0.3.3(@babel/core@7.18.9):
@ -7159,8 +7168,8 @@ packages:
tweetnacl: 0.14.5
dev: true
/better-sqlite3@8.6.0:
resolution: {integrity: sha512-jwAudeiTMTSyby+/SfbHDebShbmC2MCH8mU2+DXi0WJfv13ypEJm47cd3kljmy/H130CazEvkf2Li//ewcMJ1g==}
/better-sqlite3@8.4.0:
resolution: {integrity: sha512-NmsNW1CQvqMszu/CFAJ3pLct6NEFlNfuGM6vw72KHkjOD1UDnL96XNN1BMQc1hiHo8vE2GbOWQYIpZ+YM5wrZw==}
requiresBuild: true
dependencies:
bindings: 1.5.0
@ -8210,7 +8219,7 @@ packages:
webpack: ^4.37.0 || ^5.0.0
dependencies:
cacache: 15.3.0
fast-glob: 3.2.12
fast-glob: 3.3.1
find-cache-dir: 3.3.2
glob-parent: 5.1.2
globby: 11.1.0
@ -8487,6 +8496,7 @@ packages:
/cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
engines: {node: '>=4'}
hasBin: true
/cssnano-preset-default@4.0.8:
resolution: {integrity: sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==}
@ -8610,7 +8620,7 @@ packages:
postcss: ^8.2.15
dependencies:
cssnano-preset-default: 5.2.12(postcss@8.4.23)
lilconfig: 2.0.6
lilconfig: 2.1.0
postcss: 8.4.23
yaml: 1.10.2
dev: true
@ -9449,7 +9459,7 @@ packages:
resolution: {integrity: sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==}
dependencies:
debug: 3.2.7
resolve: 1.22.1
resolve: 1.22.2
transitivePeerDependencies:
- supports-color
dev: true
@ -10885,7 +10895,7 @@ packages:
dependencies:
array-union: 2.1.0
dir-glob: 3.0.1
fast-glob: 3.2.12
fast-glob: 3.3.1
ignore: 5.2.0
merge2: 1.4.1
slash: 3.0.0
@ -11969,6 +11979,7 @@ packages:
/jiti@1.18.2:
resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==}
hasBin: true
/js-sdsl@4.1.5:
resolution: {integrity: sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==}
@ -12232,11 +12243,6 @@ packages:
type-check: 0.4.0
dev: true
/lilconfig@2.0.6:
resolution: {integrity: sha512-9JROoBW7pobfsx+Sq2JsASvCo6Pfo6WWoUW79HuB1BCoBXD4PLWJPqDF6fNj67pqBYTbAHkE57M1kS/+L1neOg==}
engines: {node: '>=10'}
dev: true
/lilconfig@2.1.0:
resolution: {integrity: sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==}
engines: {node: '>=10'}
@ -13966,7 +13972,7 @@ packages:
ts-node:
optional: true
dependencies:
lilconfig: 2.0.6
lilconfig: 2.1.0
postcss: 8.4.23
yaml: 1.10.2
dev: true
@ -15309,6 +15315,7 @@ packages:
/resolve@1.22.2:
resolution: {integrity: sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g==}
hasBin: true
dependencies:
is-core-module: 2.11.0
path-parse: 1.0.7
@ -16256,6 +16263,7 @@ packages:
/sucrase@3.32.0:
resolution: {integrity: sha512-ydQOU34rpSyj2TGyz4D2p8rbktIOZ8QY9s+DGLvFU1i5pWJE8vkpruCjGCMHsdXwnD7JDcS+noSwM/a7zyNFDQ==}
engines: {node: '>=8'}
hasBin: true
dependencies:
'@jridgewell/gen-mapping': 0.3.2
commander: 4.1.1
@ -16368,6 +16376,7 @@ packages:
/tailwindcss@3.3.2:
resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==}
engines: {node: '>=14.0.0'}
hasBin: true
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2