add grouping and totals

This commit is contained in:
2024-08-29 02:32:30 +02:00
parent 796d866a33
commit bfb0949c25
13 changed files with 636 additions and 25 deletions

View File

@@ -0,0 +1,52 @@
import { Color, DeltaType, HorizontalPosition, Size, VerticalPosition } from "./inputTypes";
export const DeltaTypes: { [key: string]: DeltaType } = {
Increase: "increase",
ModerateIncrease: "moderateIncrease",
Decrease: "decrease",
ModerateDecrease: "moderateDecrease",
Unchanged: "unchanged",
};
export const BaseColors: { [key: string]: Color } = {
Slate: "slate",
Gray: "gray",
Zinc: "zinc",
Neutral: "neutral",
Stone: "stone",
Red: "red",
Orange: "orange",
Amber: "amber",
Yellow: "yellow",
Lime: "lime",
Green: "green",
Emerald: "emerald",
Teal: "teal",
Cyan: "cyan",
Sky: "sky",
Blue: "blue",
Indigo: "indigo",
Violet: "violet",
Purple: "purple",
Fuchsia: "fuchsia",
Pink: "pink",
Rose: "rose",
};
export const Sizes: { [key: string]: Size } = {
XS: "xs",
SM: "sm",
MD: "md",
LG: "lg",
XL: "xl",
};
export const HorizontalPositions: { [key: string]: HorizontalPosition } = {
Left: "left",
Right: "right",
};
export const VerticalPositions: { [key: string]: VerticalPosition } = {
Top: "top",
Bottom: "bottom",
};

5
app/lib/tremor/index.ts Normal file
View File

@@ -0,0 +1,5 @@
export * from "./constants";
export * from "./inputTypes";
export * from "./theme";
export * from "./tremorTwMerge";
export * from "./utils";

View File

@@ -0,0 +1,72 @@
export type ValueFormatter = {
(value: number): string;
};
export type CurveType = "linear" | "natural" | "monotone" | "step";
export type Interval = "preserveStartEnd" | "equidistantPreserveStart";
export type IntervalType = "preserveStartEnd" | Interval;
const iconVariantValues = ["simple", "light", "shadow", "solid", "outlined"] as const;
export type IconVariant = (typeof iconVariantValues)[number];
export type HorizontalPosition = "left" | "right";
export type VerticalPosition = "top" | "bottom";
export type ButtonVariant = "primary" | "secondary" | "light";
const deltaTypeValues = [
"increase",
"moderateIncrease",
"decrease",
"moderateDecrease",
"unchanged",
] as const;
export type DeltaType = (typeof deltaTypeValues)[number];
const sizeValues = ["xs", "sm", "md", "lg", "xl"] as const;
export type Size = (typeof sizeValues)[number];
const colorValues = [
"slate",
"gray",
"zinc",
"neutral",
"stone",
"red",
"orange",
"amber",
"yellow",
"lime",
"green",
"emerald",
"teal",
"cyan",
"sky",
"blue",
"indigo",
"violet",
"purple",
"fuchsia",
"pink",
"rose",
] as const;
export type Color = (typeof colorValues)[number];
export type CustomColor = Color | string;
export const getIsBaseColor = (color: Color | string) => colorValues.includes(color as Color);
const justifyContentValues = ["start", "end", "center", "between", "around", "evenly"] as const;
export type JustifyContent = (typeof justifyContentValues)[number];
const alignItemsValues = ["start", "end", "center", "baseline", "stretch"] as const;
export type AlignItems = (typeof alignItemsValues)[number];
export type FlexDirection = "row" | "col" | "row-reverse" | "col-reverse";
export type FunnelVariantType = "base" | "center";

51
app/lib/tremor/theme.ts Normal file
View File

@@ -0,0 +1,51 @@
import { BaseColors } from "./constants";
import { Color } from "./inputTypes";
export const DEFAULT_COLOR: Color = "gray";
export const WHITE = "white";
export const TRANSPARENT = "transparent";
export const colorPalette = {
canvasBackground: 50,
lightBackground: 100,
background: 500,
darkBackground: 600,
darkestBackground: 800,
lightBorder: 200,
border: 500,
darkBorder: 700,
lightRing: 200,
ring: 300,
iconRing: 500,
lightText: 400,
text: 500,
iconText: 600,
darkText: 700,
darkestText: 900,
icon: 500,
};
export const themeColorRange: Color[] = [
BaseColors.Blue,
BaseColors.Cyan,
BaseColors.Sky,
BaseColors.Indigo,
BaseColors.Violet,
BaseColors.Purple,
BaseColors.Fuchsia,
BaseColors.Slate,
BaseColors.Gray,
BaseColors.Zinc,
BaseColors.Neutral,
BaseColors.Stone,
BaseColors.Red,
BaseColors.Orange,
BaseColors.Amber,
BaseColors.Yellow,
BaseColors.Lime,
BaseColors.Green,
BaseColors.Emerald,
BaseColors.Teal,
BaseColors.Pink,
BaseColors.Rose,
];

View File

@@ -0,0 +1,36 @@
import { extendTailwindMerge } from "tailwind-merge";
export const tremorTwMerge = extendTailwindMerge({
classGroups: {
boxShadow: [
{
shadow: [
{
tremor: ["input", "card", "dropdown"],
"dark-tremor": ["input", "card", "dropdown"],
},
],
},
],
borderRadius: [
{
rounded: [
{
tremor: ["small", "default", "full"],
"dark-tremor": ["small", "default", "full"],
},
],
},
],
fontSize: [
{
text: [
{
tremor: ["default", "title", "metric"],
"dark-tremor": ["default", "title", "metric"],
},
],
},
],
},
});

114
app/lib/tremor/utils.tsx Normal file
View File

@@ -0,0 +1,114 @@
import { DeltaTypes } from "./constants";
import { Color, getIsBaseColor, ValueFormatter } from "./inputTypes";
export const mapInputsToDeltaType = (deltaType: string, isIncreasePositive: boolean): string => {
if (isIncreasePositive || deltaType === DeltaTypes.Unchanged) {
return deltaType;
}
switch (deltaType) {
case DeltaTypes.Increase:
return DeltaTypes.Decrease;
case DeltaTypes.ModerateIncrease:
return DeltaTypes.ModerateDecrease;
case DeltaTypes.Decrease:
return DeltaTypes.Increase;
case DeltaTypes.ModerateDecrease:
return DeltaTypes.ModerateIncrease;
}
return "";
};
export const defaultValueFormatter: ValueFormatter = (value: number) => value.toString();
export const currencyValueFormatter: ValueFormatter = (e: number) =>
`$ ${Intl.NumberFormat("en-US").format(e)}`;
export const sumNumericArray = (arr: number[]) =>
arr.reduce((prefixSum, num) => prefixSum + num, 0);
export const isValueInArray = (value: any, array: any[]): boolean => {
for (let i = 0; i < array.length; i++) {
if (array[i] === value) {
return true;
}
}
return false;
};
export function mergeRefs<T = any>(
refs: Array<React.MutableRefObject<T> | React.LegacyRef<T>>,
): React.RefCallback<T> {
return (value) => {
refs.forEach((ref) => {
if (typeof ref === "function") {
ref(value);
} else if (ref != null) {
(ref as React.MutableRefObject<T | null>).current = value;
}
});
};
}
export function makeClassName(componentName: string) {
return (className: string) => {
return `tremor-${componentName}-${className}`;
};
}
interface ColorClassNames {
bgColor: string;
hoverBgColor: string;
selectBgColor: string;
textColor: string;
selectTextColor: string;
hoverTextColor: string;
borderColor: string;
selectBorderColor: string;
hoverBorderColor: string;
ringColor: string;
strokeColor: string;
fillColor: string;
}
/**
* Returns boolean based on a determination that a color should be considered an "arbitrary"
* Tailwind CSS class.
* @see {@link https://tailwindcss.com/docs/background-color#arbitrary-values | Tailwind CSS docs}
*/
const getIsArbitraryColor = (color: Color | string) =>
color.includes("#") || color.includes("--") || color.includes("rgb");
export function getColorClassNames(color: Color | string, shade?: number): ColorClassNames {
const isBaseColor = getIsBaseColor(color);
if (color === "white" || color === "black" || color === "transparent" || !shade || !isBaseColor) {
const unshadedColor = !getIsArbitraryColor(color) ? color : `[${color}]`;
return {
bgColor: `bg-${unshadedColor} dark:bg-${unshadedColor}`,
hoverBgColor: `hover:bg-${unshadedColor} dark:hover:bg-${unshadedColor}`,
selectBgColor: `ui-selected:bg-${unshadedColor} dark:ui-selected:bg-${unshadedColor}`,
textColor: `text-${unshadedColor} dark:text-${unshadedColor}`,
selectTextColor: `ui-selected:text-${unshadedColor} dark:ui-selected:text-${unshadedColor}`,
hoverTextColor: `hover:text-${unshadedColor} dark:hover:text-${unshadedColor}`,
borderColor: `border-${unshadedColor} dark:border-${unshadedColor}`,
selectBorderColor: `ui-selected:border-${unshadedColor} dark:ui-selected:border-${unshadedColor}`,
hoverBorderColor: `hover:border-${unshadedColor} dark:hover:border-${unshadedColor}`,
ringColor: `ring-${unshadedColor} dark:ring-${unshadedColor}`,
strokeColor: `stroke-${unshadedColor} dark:stroke-${unshadedColor}`,
fillColor: `fill-${unshadedColor} dark:fill-${unshadedColor}`,
};
}
return {
bgColor: `bg-${color}-${shade} dark:bg-${color}-${shade}`,
selectBgColor: `ui-selected:bg-${color}-${shade} dark:ui-selected:bg-${color}-${shade}`,
hoverBgColor: `hover:bg-${color}-${shade} dark:hover:bg-${color}-${shade}`,
textColor: `text-${color}-${shade} dark:text-${color}-${shade}`,
selectTextColor: `ui-selected:text-${color}-${shade} dark:ui-selected:text-${color}-${shade}`,
hoverTextColor: `hover:text-${color}-${shade} dark:hover:text-${color}-${shade}`,
borderColor: `border-${color}-${shade} dark:border-${color}-${shade}`,
selectBorderColor: `ui-selected:border-${color}-${shade} dark:ui-selected:border-${color}-${shade}`,
hoverBorderColor: `hover:border-${color}-${shade} dark:hover:border-${color}-${shade}`,
ringColor: `ring-${color}-${shade} dark:ring-${color}-${shade}`,
strokeColor: `stroke-${color}-${shade} dark:stroke-${color}-${shade}`,
fillColor: `fill-${color}-${shade} dark:fill-${color}-${shade}`,
};
}