): ResponsiveSize {
+ const p = typeof v === "number" ? { xs: v } : v;
+ const xs = p.xs || 12;
+ const sm = p.sm || xs;
+ const md = p.md || sm;
+ const lg = p.lg || md;
+ const xl = p.xl || lg;
+ return {
+ xs,
+ sm,
+ md,
+ lg,
+ xl,
+ };
+}
+
+export function Grid({
+ columns: cp,
+ container = false,
+ item = false,
+ direction = "row",
+ lg,
+ md,
+ sm,
+ xl,
+ xs,
+ wrap = "wrap",
+ spacing = 0,
+ columnSpacing: csp,
+ rowSpacing: rsp,
+ alignItems,
+ justifyContent,
+ zeroMinWidth = false,
+ children,
+}: Props): VNode {
+ const cc = useContext(GridContext);
+ const columns = !cp ? cc : toResponsive(cp);
+
+ const rowSpacing = rsp ? toResponsive(rsp) : toResponsive(spacing);
+ const columnSpacing = csp ? toResponsive(csp) : toResponsive(spacing);
+
+ const ssize = toResponsive({ xs, md, lg, xl, sm } as any);
+
+ if (container) {
+ console.log(rowSpacing);
+ console.log(columnSpacing);
+ }
+ const spacingStyles = !container
+ ? {}
+ : {
+ "--space-col-xs": getOffset(theme.spacing(columnSpacing.xs)),
+ "--space-col-sm": getOffset(theme.spacing(columnSpacing.sm)),
+ "--space-col-md": getOffset(theme.spacing(columnSpacing.md)),
+ "--space-col-lg": getOffset(theme.spacing(columnSpacing.lg)),
+ "--space-col-xl": getOffset(theme.spacing(columnSpacing.xl)),
+
+ "--space-row-xs": getOffset(theme.spacing(rowSpacing.xs)),
+ "--space-row-sm": getOffset(theme.spacing(rowSpacing.sm)),
+ "--space-row-md": getOffset(theme.spacing(rowSpacing.md)),
+ "--space-row-lg": getOffset(theme.spacing(rowSpacing.lg)),
+ "--space-row-xl": getOffset(theme.spacing(rowSpacing.xl)),
+ };
+ const relationStyles = !item
+ ? {}
+ : {
+ "--relation-col-vs-sm": relation(columns, ssize, "sm"),
+ "--relation-col-vs-lg": relation(columns, ssize, "lg"),
+ "--relation-col-vs-xs": relation(columns, ssize, "xs"),
+ "--relation-col-vs-xl": relation(columns, ssize, "xl"),
+ "--relation-col-vs-md": relation(columns, ssize, "md"),
+ };
+
+ return (
+
+
+ {children}
+
+
+ );
+}
+function relation(
+ cols: ResponsiveSize,
+ values: ResponsiveSize,
+ size: ResponsiveKeys,
+) {
+ const colsNum = typeof cols === "number" ? cols : cols[size] || 12;
+ return (
+ String(Math.round(((values[size] || 1) / colsNum) * 10e7) / 10e5) + "%"
+ );
}
diff --git a/packages/taler-wallet-webextension/src/mui/Paper.tsx b/packages/taler-wallet-webextension/src/mui/Paper.tsx
index 52524380b..00eeda324 100644
--- a/packages/taler-wallet-webextension/src/mui/Paper.tsx
+++ b/packages/taler-wallet-webextension/src/mui/Paper.tsx
@@ -35,7 +35,7 @@ export function Paper({
{children};
+const defaultVariantMapping = {
+ h1: "h1",
+ h2: "h2",
+ h3: "h3",
+ h4: "h4",
+ h5: "h5",
+ h6: "h6",
+ subtitle1: "h6",
+ subtitle2: "h6",
+ body1: "p",
+ body2: "p",
+ inherit: "p",
+};
+
+const root = css`
+ margin: 0;
+`;
+
+const noWrapStyle = css`
+ overflow: "hidden";
+ text-overflow: "ellipsis";
+ white-space: "nowrap";
+`;
+const gutterBottomStyle = css`
+ margin-bottom: 0.35em;
+`;
+const paragraphStyle = css`
+ margin-bottom: 16px;
+`;
+
+export function Typography({
+ align,
+ gutterBottom = false,
+ noWrap = false,
+ paragraph = false,
+ variant = "body1",
+ children,
+}: Props): VNode {
+ const cmp = paragraph
+ ? "p"
+ : defaultVariantMapping[variant as "h1"] || "span";
+
+ const alignStyle =
+ align == "inherit"
+ ? {}
+ : {
+ textAlign: align,
+ };
+ return h(
+ cmp,
+ {
+ class: [
+ root,
+ noWrap && noWrapStyle,
+ gutterBottom && gutterBottomStyle,
+ paragraph && paragraphStyle,
+ ].join(" "),
+ style: {
+ ...alignStyle,
+ },
+ },
+ children,
+ );
}
diff --git a/packages/taler-wallet-webextension/src/mui/style.tsx b/packages/taler-wallet-webextension/src/mui/style.tsx
index 84b0538be..e2af05c49 100644
--- a/packages/taler-wallet-webextension/src/mui/style.tsx
+++ b/packages/taler-wallet-webextension/src/mui/style.tsx
@@ -22,6 +22,14 @@ export function pxToRem(size: number): string {
return `${(size / htmlFontSize) * coef}rem`;
}
+export interface Spacing {
+ (): string;
+ (value: number): string;
+ (topBottom: number, rightLeft: number): string;
+ (top: number, rightLeft: number, bottom: number): string;
+ (top: number, right: number, bottom: number, left: number): string;
+}
+
export const theme = createTheme();
export const ripple = css`
@@ -117,11 +125,78 @@ function createTheme() {
const shadows = createAllShadows();
const transitions = createTransitions({});
const breakpoints = createBreakpoints({});
+ const spacing = createSpacing();
const shape = {
- borderRadius: css`
+ roundBorder: css`
border-radius: 4px;
`,
+ squareBorder: css`
+ border-radius: 0px;
+ `,
+ circularBorder: css`
+ border-radius: 50%;
+ `,
};
+
+ /////////////////////
+ ///////////////////// SPACING
+ /////////////////////
+
+ function createUnaryUnit(theme: { spacing: number }, defaultValue: number) {
+ const themeSpacing = theme.spacing || defaultValue;
+
+ if (typeof themeSpacing === "number") {
+ return (abs: number | string) => {
+ if (typeof abs === "string") {
+ return abs;
+ }
+
+ return themeSpacing * abs;
+ };
+ }
+
+ if (Array.isArray(themeSpacing)) {
+ return (abs: number | string) => {
+ if (typeof abs === "string") {
+ return abs;
+ }
+
+ return themeSpacing[abs];
+ };
+ }
+
+ if (typeof themeSpacing === "function") {
+ return themeSpacing;
+ }
+
+ return (a: string | number) => "";
+ }
+
+ function createUnarySpacing(theme: { spacing: number }) {
+ return createUnaryUnit(theme, 8);
+ }
+
+ function createSpacing(spacingInput: number = 8): Spacing {
+ // Material Design layouts are visually balanced. Most measurements align to an 8dp grid, which aligns both spacing and the overall layout.
+ // Smaller components, such as icons, can align to a 4dp grid.
+ // https://material.io/design/layout/understanding-layout.html#usage
+ const transform = createUnarySpacing({
+ spacing: spacingInput,
+ });
+
+ const spacing = (...argsInput: ReadonlyArray): string => {
+ const args = argsInput.length === 0 ? [1] : argsInput;
+
+ return args
+ .map((argument) => {
+ const output = transform(argument);
+ return typeof output === "number" ? `${output}px` : output;
+ })
+ .join(" ");
+ };
+
+ return spacing;
+ }
/////////////////////
///////////////////// BREAKPOINTS
/////////////////////
@@ -691,6 +766,7 @@ function createTheme() {
shape,
transitions,
breakpoints,
+ spacing,
pxToRem,
};
}