cta stories and input filled mui
This commit is contained in:
parent
bb56d61424
commit
f300850b19
@ -28,7 +28,7 @@ import firefoxAPI from "./platform/firefox.js";
|
||||
import chromeAPI from "./platform/chrome.js";
|
||||
import { wxMain } from "./wxBackend.js";
|
||||
|
||||
const isFirefox = typeof (window as any)['InstallTrigger'] !== 'undefined'
|
||||
const isFirefox = typeof (window as any) !== 'undefined' && typeof (window as any)['InstallTrigger'] !== 'undefined'
|
||||
|
||||
// FIXME: create different entry point for any platform instead of
|
||||
// switching in runtime
|
||||
|
@ -147,7 +147,7 @@ export const TicketWithAProductList = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
||||
export const AlreadyConfirmedByOther = createExample(TestedComponent, {
|
||||
payStatus: {
|
||||
status: PreparePayResultType.AlreadyConfirmed,
|
||||
amountEffective: "USD:10",
|
||||
@ -156,8 +156,6 @@ export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
||||
merchant: {
|
||||
name: "someone",
|
||||
},
|
||||
fulfillment_message:
|
||||
"congratulations! you are looking at the fulfillment message! ",
|
||||
summary: "some beers",
|
||||
amount: "USD:10",
|
||||
} as Partial<ContractTerms> as any,
|
||||
@ -167,28 +165,25 @@ export const AlreadyConfirmedWithFullfilment = createExample(TestedComponent, {
|
||||
},
|
||||
});
|
||||
|
||||
export const AlreadyConfirmedWithoutFullfilment = createExample(
|
||||
TestedComponent,
|
||||
{
|
||||
payStatus: {
|
||||
status: PreparePayResultType.AlreadyConfirmed,
|
||||
amountEffective: "USD:10",
|
||||
amountRaw: "USD:10",
|
||||
contractTerms: {
|
||||
merchant: {
|
||||
name: "someone",
|
||||
},
|
||||
summary: "some beers",
|
||||
amount: "USD:10",
|
||||
} as Partial<ContractTerms> as any,
|
||||
contractTermsHash: "123456",
|
||||
proposalId: "proposal1234",
|
||||
paid: false,
|
||||
},
|
||||
export const AlreadyPaidWithoutFulfillment = createExample(TestedComponent, {
|
||||
payStatus: {
|
||||
status: PreparePayResultType.AlreadyConfirmed,
|
||||
amountEffective: "USD:10",
|
||||
amountRaw: "USD:10",
|
||||
contractTerms: {
|
||||
merchant: {
|
||||
name: "someone",
|
||||
},
|
||||
summary: "some beers",
|
||||
amount: "USD:10",
|
||||
} as Partial<ContractTerms> as any,
|
||||
contractTermsHash: "123456",
|
||||
proposalId: "proposal1234",
|
||||
paid: true,
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
export const AlreadyPaid = createExample(TestedComponent, {
|
||||
export const AlreadyPaidWithFulfillment = createExample(TestedComponent, {
|
||||
payStatus: {
|
||||
status: PreparePayResultType.AlreadyConfirmed,
|
||||
amountEffective: "USD:10",
|
||||
|
@ -105,6 +105,23 @@ export function PayPage({
|
||||
return { payStatus, balance };
|
||||
}, [NotificationType.CoinWithdrawn]);
|
||||
|
||||
useEffect(() => {
|
||||
const payStatus =
|
||||
hook && !hook.hasError ? hook.response.payStatus : undefined;
|
||||
if (
|
||||
payStatus &&
|
||||
payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
||||
payStatus.paid
|
||||
) {
|
||||
const fu = payStatus.contractTerms.fulfillment_url;
|
||||
if (fu) {
|
||||
setTimeout(() => {
|
||||
document.location.href = fu;
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
}, []);
|
||||
|
||||
if (!hook) {
|
||||
return <Loading />;
|
||||
}
|
||||
@ -172,20 +189,6 @@ export function PaymentRequestView({
|
||||
let totalFees: AmountJson = Amounts.getZero(payStatus.amountRaw);
|
||||
const contractTerms: ContractTerms = payStatus.contractTerms;
|
||||
|
||||
useEffect(() => {
|
||||
if (
|
||||
payStatus.status === PreparePayResultType.AlreadyConfirmed &&
|
||||
payStatus.paid
|
||||
) {
|
||||
const fu = payStatus.contractTerms.fulfillment_url;
|
||||
if (fu) {
|
||||
setTimeout(() => {
|
||||
document.location.href = fu;
|
||||
}, 3000);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (!contractTerms) {
|
||||
return (
|
||||
<ErrorMessage
|
||||
|
@ -136,9 +136,7 @@ export const TermsReviewingHTML = createExample(TestedComponent, {
|
||||
terms: {
|
||||
content: {
|
||||
type: "html",
|
||||
href: new URL(
|
||||
`data:text/html;base64,${Buffer.from(termsHtml).toString("base64")}`,
|
||||
),
|
||||
href: new URL(`data:text/html;base64,${toBase64(termsHtml)}`),
|
||||
},
|
||||
version: "",
|
||||
status: "new",
|
||||
@ -146,6 +144,14 @@ export const TermsReviewingHTML = createExample(TestedComponent, {
|
||||
reviewing: true,
|
||||
});
|
||||
|
||||
function toBase64(str: string): string {
|
||||
return btoa(
|
||||
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
|
||||
return String.fromCharCode(parseInt(p1, 16));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
export const TermsReviewingPDF = createExample(TestedComponent, {
|
||||
knownExchanges: exchangeList,
|
||||
exchangeBaseUrl: "exchange.demo.taler.net",
|
||||
@ -166,9 +172,7 @@ export const TermsReviewingPDF = createExample(TestedComponent, {
|
||||
terms: {
|
||||
content: {
|
||||
type: "pdf",
|
||||
location: new URL(
|
||||
`data:text/html;base64,${Buffer.from(termsPdf).toString("base64")}`,
|
||||
),
|
||||
location: new URL(`data:text/html;base64,${toBase64(termsPdf)}`),
|
||||
},
|
||||
status: "new",
|
||||
version: "",
|
||||
|
28
packages/taler-wallet-webextension/src/cta/index.stories.ts
Normal file
28
packages/taler-wallet-webextension/src/cta/index.stories.ts
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
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 * as a1 from "./Deposit.stories.jsx";
|
||||
import * as a3 from "./Pay.stories.jsx";
|
||||
import * as a4 from "./Refund.stories.jsx";
|
||||
import * as a5 from "./Tip.stories.jsx";
|
||||
import * as a6 from "./Withdraw.stories.jsx";
|
||||
|
||||
export default [a1, a3, a4, a5, a6];
|
@ -33,7 +33,7 @@ const Container = styled.div`
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
& > * {
|
||||
margin: 20px;
|
||||
margin-bottom: 20px !important;
|
||||
}
|
||||
`;
|
||||
|
||||
|
@ -54,7 +54,7 @@ export function TextField({
|
||||
select,
|
||||
helperText,
|
||||
children,
|
||||
variant = "standard",
|
||||
variant = "filled",
|
||||
...props
|
||||
}: Props): VNode {
|
||||
// htmlFor={id} id={inputLabelId}
|
||||
|
@ -56,7 +56,7 @@ export function FormControl({
|
||||
margin = "none",
|
||||
required = false,
|
||||
size = "medium",
|
||||
variant = "standard",
|
||||
variant = "filled",
|
||||
children,
|
||||
}: Partial<Props>): VNode {
|
||||
const [filled, setFilled] = useState(false);
|
||||
@ -138,7 +138,7 @@ const defaultContextValue: FCCProps = {
|
||||
onFilled: () => null,
|
||||
onFocus: () => null,
|
||||
required: false,
|
||||
variant: "outlined",
|
||||
variant: "filled",
|
||||
};
|
||||
|
||||
function withoutUndefinedProperties(obj: any): any {
|
||||
|
@ -61,7 +61,6 @@ const componentStyle = css`
|
||||
font: inherit;
|
||||
letter-spacing: inherit;
|
||||
color: currentColor;
|
||||
padding: 4px 0 5px;
|
||||
border: 0px;
|
||||
box-sizing: content-box;
|
||||
background: none;
|
||||
@ -128,6 +127,7 @@ export function InputBaseComponent({
|
||||
size,
|
||||
multiline,
|
||||
type,
|
||||
class: _class,
|
||||
...props
|
||||
}: any): VNode {
|
||||
return (
|
||||
@ -136,6 +136,7 @@ export function InputBaseComponent({
|
||||
type={type}
|
||||
class={[
|
||||
componentStyle,
|
||||
_class,
|
||||
disabled && componentDisabledStyle,
|
||||
size === "small" && componentSmallStyle,
|
||||
multiline && componentMultilineStyle,
|
||||
|
@ -1,5 +1,170 @@
|
||||
import { css } from "@linaria/core";
|
||||
import { h, VNode } from "preact";
|
||||
// eslint-disable-next-line import/extensions
|
||||
import { Colors, theme } from "../style";
|
||||
import { useFormControl } from "./FormControl.js";
|
||||
import { InputBase, InputBaseComponent, InputBaseRoot } from "./InputBase.js";
|
||||
|
||||
export function InputFilled(): VNode {
|
||||
return <div />;
|
||||
export interface Props {
|
||||
autoComplete?: string;
|
||||
autoFocus?: boolean;
|
||||
color?: Colors;
|
||||
defaultValue?: string;
|
||||
disabled?: boolean;
|
||||
disableUnderline?: boolean;
|
||||
endAdornment?: VNode;
|
||||
error?: boolean;
|
||||
fullWidth?: boolean;
|
||||
id?: string;
|
||||
margin?: "dense" | "normal" | "none";
|
||||
maxRows?: number;
|
||||
minRows?: number;
|
||||
multiline?: boolean;
|
||||
name?: string;
|
||||
onChange?: (s: string) => void;
|
||||
placeholder?: string;
|
||||
readOnly?: boolean;
|
||||
required?: boolean;
|
||||
rows?: number;
|
||||
startAdornment?: VNode;
|
||||
type?: string;
|
||||
value?: string;
|
||||
}
|
||||
export function InputFilled({
|
||||
type = "text",
|
||||
multiline,
|
||||
...props
|
||||
}: Props): VNode {
|
||||
const fcs = useFormControl(props);
|
||||
return (
|
||||
<InputBase
|
||||
Root={Root}
|
||||
Input={Input}
|
||||
fullWidth={fcs.fullWidth}
|
||||
multiline={multiline}
|
||||
type={type}
|
||||
{...props}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
const light = theme.palette.mode === "light";
|
||||
const bottomLineColor = light
|
||||
? "rgba(0, 0, 0, 0.42)"
|
||||
: "rgba(255, 255, 255, 0.7)";
|
||||
const backgroundColor = light
|
||||
? "rgba(0, 0, 0, 0.06)"
|
||||
: "rgba(255, 255, 255, 0.09)";
|
||||
const backgroundColorHover = light
|
||||
? "rgba(0, 0, 0, 0.09)"
|
||||
: "rgba(255, 255, 255, 0.13)";
|
||||
const backgroundColorDisabled = light
|
||||
? "rgba(0, 0, 0, 0.12)"
|
||||
: "rgba(255, 255, 255, 0.12)";
|
||||
|
||||
const formControlStyle = css`
|
||||
label + & {
|
||||
margin-top: 16px;
|
||||
}
|
||||
`;
|
||||
|
||||
const filledRootStyle = css`
|
||||
position: relative;
|
||||
background-color: ${backgroundColor};
|
||||
border-top-left-radius: ${theme.shape.borderRadius}px;
|
||||
border-top-right-radius: ${theme.shape.borderRadius}px;
|
||||
transition: ${theme.transitions.create("background-color", {
|
||||
duration: theme.transitions.duration.shorter,
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
})};
|
||||
// when is not disabled underline
|
||||
&:hover {
|
||||
background-color: ${backgroundColorHover};
|
||||
@media (hover: none) {
|
||||
background-color: ${backgroundColor};
|
||||
}
|
||||
}
|
||||
[data-focused] {
|
||||
background-color: ${backgroundColor};
|
||||
}
|
||||
[data-disabled] {
|
||||
background-color: ${backgroundColorDisabled};
|
||||
}
|
||||
`;
|
||||
|
||||
const underlineStyle = css`
|
||||
// when is not disabled underline
|
||||
&:after {
|
||||
border-bottom: 2px solid var(--color-main);
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
content: "";
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
transform: scaleX(0);
|
||||
transition: ${theme.transitions.create("transform", {
|
||||
duration: theme.transitions.duration.shorter,
|
||||
easing: theme.transitions.easing.easeOut,
|
||||
})};
|
||||
pointer-events: none;
|
||||
}
|
||||
&[data-focused]:after {
|
||||
transform: scaleX(1);
|
||||
}
|
||||
&[data-error]:after {
|
||||
border-bottom-color: ${theme.palette.error.main};
|
||||
transform: scaleY(1);
|
||||
}
|
||||
&:before {
|
||||
border-bottom: 1px solid
|
||||
${theme.palette.mode === "light"
|
||||
? "rgba(0, 0, 0, 0.42)"
|
||||
: "rgba(255, 255, 255, 0.7)"};
|
||||
left: 0px;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
content: "\\00a0";
|
||||
position: absolute;
|
||||
transition: ${theme.transitions.create("border-bottom-color", {
|
||||
duration: theme.transitions.duration.shorter,
|
||||
})};
|
||||
pointer-events: none;
|
||||
}
|
||||
&:hover:not([data-disabled]:before) {
|
||||
border-bottom: 2px solid var(--color-main);
|
||||
@media (hover: none) {
|
||||
border-bottom: 1px solid
|
||||
${theme.palette.mode === "light"
|
||||
? "rgba(0, 0, 0, 0.42)"
|
||||
: "rgba(255, 255, 255, 0.7)"};
|
||||
}
|
||||
}
|
||||
&[data-disabled]:before {
|
||||
border-bottom-style: solid;
|
||||
}
|
||||
`;
|
||||
|
||||
function Root({ fullWidth, disabled, focused, error, children }: any): VNode {
|
||||
return (
|
||||
<InputBaseRoot
|
||||
disabled={disabled}
|
||||
focused={focused}
|
||||
fullWidth={fullWidth}
|
||||
error={error}
|
||||
class={[filledRootStyle, underlineStyle].join(" ")}
|
||||
>
|
||||
{children}
|
||||
</InputBaseRoot>
|
||||
);
|
||||
}
|
||||
|
||||
const filledBaseStyle = css`
|
||||
padding-top: 25px;
|
||||
padding-right: 12px;
|
||||
padding-bottom: 8px;
|
||||
padding-left: 12px;
|
||||
`;
|
||||
|
||||
function Input(props: any): VNode {
|
||||
return <InputBaseComponent class={[filledBaseStyle].join(" ")} {...props} />;
|
||||
}
|
||||
|
@ -50,6 +50,7 @@ export function InputStandard({
|
||||
|
||||
const rootStyle = css`
|
||||
position: relative;
|
||||
padding: 4px 0 5px;
|
||||
`;
|
||||
const formControlStyle = css`
|
||||
label + & {
|
||||
@ -57,6 +58,7 @@ const formControlStyle = css`
|
||||
}
|
||||
`;
|
||||
const underlineStyle = css`
|
||||
// when is not disabled underline
|
||||
&:after {
|
||||
border-bottom: 2px solid var(--color-main);
|
||||
left: 0px;
|
||||
@ -107,11 +109,12 @@ const underlineStyle = css`
|
||||
}
|
||||
`;
|
||||
|
||||
function Root({ disabled, focused, error, children }: any): VNode {
|
||||
function Root({ fullWidth, disabled, focused, error, children }: any): VNode {
|
||||
return (
|
||||
<InputBaseRoot
|
||||
disabled={disabled}
|
||||
focused={focused}
|
||||
fullWidth={fullWidth}
|
||||
error={error}
|
||||
class={[rootStyle, formControlStyle, underlineStyle].join(" ")}
|
||||
>
|
||||
|
@ -147,6 +147,7 @@ function createTheme() {
|
||||
circularBorder: css`
|
||||
border-radius: 50%;
|
||||
`,
|
||||
borderRadius: 4,
|
||||
};
|
||||
|
||||
/////////////////////
|
||||
|
@ -35,6 +35,7 @@ import * as mui from "./mui/index.stories.js";
|
||||
import { PopupNavBar, WalletNavBar } from "./NavigationBar.js";
|
||||
import * as popup from "./popup/index.stories.js";
|
||||
import * as wallet from "./wallet/index.stories.js";
|
||||
import * as cta from "./cta/index.stories.js";
|
||||
import * as components from "./components/index.stories.js";
|
||||
import { strings } from "./i18n/strings.js";
|
||||
|
||||
@ -112,7 +113,7 @@ function parseExampleImport(group: string, im: any): ComponentItem {
|
||||
};
|
||||
}
|
||||
|
||||
const allExamples = Object.entries({ popup, wallet, mui, components }).map(
|
||||
const allExamples = Object.entries({ popup, wallet, cta, mui, components }).map(
|
||||
([title, value]) => ({
|
||||
title,
|
||||
list: value.default.map((s) => parseExampleImport(title, s)),
|
||||
@ -227,6 +228,14 @@ function getWrapperForGroup(group: string): FunctionComponent {
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
case "cta":
|
||||
return function WalletWrapper({ children }: any) {
|
||||
return (
|
||||
<Fragment>
|
||||
<WalletBox>{children}</WalletBox>
|
||||
</Fragment>
|
||||
);
|
||||
};
|
||||
default:
|
||||
return Fragment;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user