feat: render server-side invoice pdf template using React server

This commit is contained in:
Ahmed Bouhuolia
2024-11-04 12:55:12 +02:00
parent 6687db4085
commit 51aec8d8b3
17 changed files with 787 additions and 70 deletions

View File

@@ -0,0 +1,19 @@
import React, { forwardRef, Ref } from 'react';
import { SystemProps, x } from '@xstyled/emotion';
interface IProps {
className?: string;
}
export interface BoxProps
extends SystemProps,
IProps,
Omit<React.HTMLProps<HTMLDivElement>, 'color' | 'as'> { }
export const Box = forwardRef(
({ className, ...rest }: BoxProps, ref: Ref<HTMLDivElement>) => {
const Element = x.div;
return <Element className={className} ref={ref} {...rest} />;
},
);
Box.displayName = '@bigcapital/Box';

View File

@@ -0,0 +1,58 @@
import React from 'react';
import { SystemProps } from '@xstyled/emotion';
import { Box } from './Box';
import { filterFalsyChildren } from './utils';
export type GroupPosition = 'right' | 'center' | 'left' | 'apart';
export const GROUP_POSITIONS = {
left: 'flex-start',
center: 'center',
right: 'flex-end',
apart: 'space-between',
};
export interface GroupProps
extends SystemProps,
Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
/** Defines justify-content property */
position?: GroupPosition;
/** Defined flex-wrap property */
noWrap?: boolean;
/** Defines flex-grow property for each element, true -> 1, false -> 0 */
grow?: boolean;
/** Space between elements */
spacing?: number;
/** Defines align-items css property */
align?: React.CSSProperties['alignItems'];
}
export function Group({
position = 'left',
spacing = 20,
align = 'center',
noWrap,
children,
...props
}: GroupProps) {
const filteredChildren = filterFalsyChildren(children);
return (
<Box
boxSizing={'border-box'}
display={'flex'}
flexDirection={'row'}
alignItems={align}
flexWrap={noWrap ? 'nowrap' : 'wrap'}
justifyContent={GROUP_POSITIONS[position]}
gap={`${spacing}px`}
{...props}
>
{filteredChildren}
</Box>
);
}

View File

@@ -0,0 +1,33 @@
import React from 'react';
import { x, SystemProps } from '@xstyled/emotion';
export interface StackProps
extends SystemProps,
Omit<React.ComponentPropsWithoutRef<'div'>, 'color'> {
/** Key of theme.spacing or number to set gap in px */
spacing?: number;
/** align-items CSS property */
align?: React.CSSProperties['alignItems'];
/** justify-content CSS property */
justify?: React.CSSProperties['justifyContent'];
}
export function Stack({
spacing = 20,
align = 'stretch',
justify = 'top',
...restProps
}: StackProps) {
return (
<x.div
display={'flex'}
flexDirection="column"
justifyContent="justify"
gap={`${spacing}px`}
alignItems={align}
{...restProps}
/>
);
}

View File

@@ -0,0 +1,5 @@
import React from 'react';
export const filterFalsyChildren = (children: React.ReactNode) => {
return React.Children.toArray(children).filter(Boolean);
};

View File

@@ -0,0 +1,4 @@
export * from './layout/Stack';
export * from './layout/Group';
export * from './layout/Box';
export * from './text/Text';

View File

@@ -0,0 +1,5 @@
import { x } from '@xstyled/emotion';
export const Text = ({ children }: { children: React.ReactNode }) => {
return <x.div>{children}</x.div>;
};