feat(dm): add first / last message date, dm duration and overall messages
This commit is contained in:
parent
ad643ad862
commit
2fedbdc884
12 changed files with 495 additions and 65 deletions
|
@ -1,5 +1,5 @@
|
|||
import type { Component } from "solid-js";
|
||||
import { createEffect, createSignal, mergeProps, on, onCleanup, onMount } from "solid-js";
|
||||
import type { Component, JSX } from "solid-js";
|
||||
import { createEffect, createSignal, mergeProps, on, onCleanup, onMount, splitProps } from "solid-js";
|
||||
import { unwrap } from "solid-js/store";
|
||||
|
||||
import type { Ref } from "@solid-primitives/refs";
|
||||
|
@ -51,9 +51,10 @@ interface TypedChartProps {
|
|||
height?: number | undefined;
|
||||
}
|
||||
|
||||
type ChartProps = TypedChartProps & {
|
||||
type: ChartType;
|
||||
};
|
||||
type ChartProps = JSX.CanvasHTMLAttributes<HTMLCanvasElement> &
|
||||
TypedChartProps & {
|
||||
type: ChartType;
|
||||
};
|
||||
|
||||
interface ChartContext {
|
||||
chart: Chart;
|
||||
|
@ -74,6 +75,8 @@ const BaseChart: Component<ChartProps> = (rawProps) => {
|
|||
rawProps,
|
||||
);
|
||||
|
||||
const [, otherProps] = splitProps(props, ["options", "plugins", "data"]);
|
||||
|
||||
const init = () => {
|
||||
const ctx = canvasRef()?.getContext("2d") as ChartItem;
|
||||
const config = unwrap(props);
|
||||
|
@ -153,7 +156,7 @@ const BaseChart: Component<ChartProps> = (rawProps) => {
|
|||
});
|
||||
|
||||
Chart.register(Colors, Filler, Legend, Tooltip);
|
||||
return <canvas ref={mergeRefs(props.ref, (el) => setCanvasRef(el))} height={props.height} width={props.width} />;
|
||||
return <canvas ref={mergeRefs(props.ref, (el) => setCanvasRef(el))} {...otherProps} />;
|
||||
};
|
||||
|
||||
function showTooltip(context: ChartContext) {
|
||||
|
@ -202,7 +205,10 @@ function showTooltip(context: ChartContext) {
|
|||
el.style.pointerEvents = "none";
|
||||
}
|
||||
|
||||
function createTypedChart(type: ChartType, components: ChartComponent[]): Component<TypedChartProps> {
|
||||
function createTypedChart(
|
||||
type: ChartType,
|
||||
components: ChartComponent[],
|
||||
): Component<TypedChartProps & JSX.CanvasHTMLAttributes<HTMLCanvasElement>> {
|
||||
const chartsWithScales: ChartType[] = ["bar", "line", "scatter"];
|
||||
const chartsWithLegends: ChartType[] = ["bar", "line"];
|
||||
|
||||
|
|
67
src/components/ui/flex.tsx
Normal file
67
src/components/ui/flex.tsx
Normal file
|
@ -0,0 +1,67 @@
|
|||
import type { Component, ComponentProps } from "solid-js";
|
||||
import { mergeProps, splitProps } from "solid-js";
|
||||
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
type JustifyContent = "start" | "end" | "center" | "between" | "around" | "evenly" | "normal" | "stretch";
|
||||
type AlignItems = "start" | "end" | "center" | "baseline" | "stretch";
|
||||
type FlexDirection = "row" | "col" | "row-reverse" | "col-reverse";
|
||||
|
||||
type FlexProps = ComponentProps<"div"> & {
|
||||
flexDirection?: FlexDirection;
|
||||
justifyContent?: JustifyContent;
|
||||
alignItems?: AlignItems;
|
||||
};
|
||||
|
||||
const Flex: Component<FlexProps> = (rawProps) => {
|
||||
const props = mergeProps(
|
||||
{
|
||||
flexDirection: "row",
|
||||
justifyContent: "normal",
|
||||
alignItems: "center",
|
||||
} satisfies FlexProps,
|
||||
rawProps,
|
||||
);
|
||||
const [local, others] = splitProps(props, ["flexDirection", "justifyContent", "alignItems", "class"]);
|
||||
|
||||
return (
|
||||
<div
|
||||
class={cn(
|
||||
"flex",
|
||||
flexDirectionClassNames[local.flexDirection],
|
||||
justifyContentClassNames[local.justifyContent],
|
||||
alignItemsClassNames[local.alignItems],
|
||||
local.class,
|
||||
)}
|
||||
{...others}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
export { Flex };
|
||||
|
||||
const justifyContentClassNames: { [key in JustifyContent]: string } = {
|
||||
start: "justify-start",
|
||||
end: "justify-end",
|
||||
center: "justify-center",
|
||||
between: "justify-between",
|
||||
around: "justify-around",
|
||||
evenly: "justify-evenly",
|
||||
normal: "justify-normal",
|
||||
stretch: "justify-stretch",
|
||||
};
|
||||
|
||||
const alignItemsClassNames: { [key in AlignItems]: string } = {
|
||||
start: "items-start",
|
||||
end: "items-end",
|
||||
center: "items-center",
|
||||
baseline: "items-baseline",
|
||||
stretch: "items-stretch",
|
||||
};
|
||||
|
||||
const flexDirectionClassNames: { [key in FlexDirection]: string } = {
|
||||
row: "flex-row",
|
||||
col: "flex-col",
|
||||
"row-reverse": "flex-row-reverse",
|
||||
"col-reverse": "flex-col-reverse",
|
||||
};
|
188
src/components/ui/grid.tsx
Normal file
188
src/components/ui/grid.tsx
Normal file
|
@ -0,0 +1,188 @@
|
|||
import type { Component, ComponentProps } from "solid-js"
|
||||
import { mergeProps, splitProps } from "solid-js"
|
||||
|
||||
import { cn } from "~/lib/utils"
|
||||
|
||||
type Cols = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12
|
||||
type Span = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13
|
||||
|
||||
type GridProps = ComponentProps<"div"> & {
|
||||
cols?: Cols
|
||||
colsSm?: Cols
|
||||
colsMd?: Cols
|
||||
colsLg?: Cols
|
||||
}
|
||||
|
||||
const Grid: Component<GridProps> = (rawProps) => {
|
||||
const props = mergeProps({ cols: 1 } satisfies GridProps, rawProps)
|
||||
const [local, others] = splitProps(props, ["cols", "colsSm", "colsMd", "colsLg", "class"])
|
||||
|
||||
return (
|
||||
<div
|
||||
class={cn(
|
||||
"grid",
|
||||
gridCols[local.cols],
|
||||
local.colsSm && gridColsSm[local.colsSm],
|
||||
local.colsMd && gridColsMd[local.colsMd],
|
||||
local.colsLg && gridColsLg[local.colsLg],
|
||||
local.class
|
||||
)}
|
||||
{...others}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
type ColProps = ComponentProps<"div"> & {
|
||||
span?: Span
|
||||
spanSm?: Span
|
||||
spanMd?: Span
|
||||
spanLg?: Span
|
||||
}
|
||||
|
||||
const Col: Component<ColProps> = (rawProps) => {
|
||||
const props = mergeProps({ span: 1 as Span }, rawProps)
|
||||
const [local, others] = splitProps(props, ["span", "spanSm", "spanMd", "spanLg", "class"])
|
||||
|
||||
return (
|
||||
<div
|
||||
class={cn(
|
||||
colSpan[local.span],
|
||||
local.spanSm && colSpanSm[local.spanSm],
|
||||
local.spanMd && colSpanMd[local.spanMd],
|
||||
local.spanLg && colSpanLg[local.spanLg],
|
||||
local.class
|
||||
)}
|
||||
{...others}
|
||||
/>
|
||||
)
|
||||
}
|
||||
|
||||
export { Grid, Col }
|
||||
|
||||
const gridCols: { [key in Cols]: string } = {
|
||||
0: "grid-cols-none",
|
||||
1: "grid-cols-1",
|
||||
2: "grid-cols-2",
|
||||
3: "grid-cols-3",
|
||||
4: "grid-cols-4",
|
||||
5: "grid-cols-5",
|
||||
6: "grid-cols-6",
|
||||
7: "grid-cols-7",
|
||||
8: "grid-cols-8",
|
||||
9: "grid-cols-9",
|
||||
10: "grid-cols-10",
|
||||
11: "grid-cols-11",
|
||||
12: "grid-cols-12"
|
||||
}
|
||||
|
||||
const gridColsSm: { [key in Cols]: string } = {
|
||||
0: "sm:grid-cols-none",
|
||||
1: "sm:grid-cols-1",
|
||||
2: "sm:grid-cols-2",
|
||||
3: "sm:grid-cols-3",
|
||||
4: "sm:grid-cols-4",
|
||||
5: "sm:grid-cols-5",
|
||||
6: "sm:grid-cols-6",
|
||||
7: "sm:grid-cols-7",
|
||||
8: "sm:grid-cols-8",
|
||||
9: "sm:grid-cols-9",
|
||||
10: "sm:grid-cols-10",
|
||||
11: "sm:grid-cols-11",
|
||||
12: "sm:grid-cols-12"
|
||||
}
|
||||
|
||||
const gridColsMd: { [key in Cols]: string } = {
|
||||
0: "md:grid-cols-none",
|
||||
1: "md:grid-cols-1",
|
||||
2: "md:grid-cols-2",
|
||||
3: "md:grid-cols-3",
|
||||
4: "md:grid-cols-4",
|
||||
5: "md:grid-cols-5",
|
||||
6: "md:grid-cols-6",
|
||||
7: "md:grid-cols-7",
|
||||
8: "md:grid-cols-8",
|
||||
9: "md:grid-cols-9",
|
||||
10: "md:grid-cols-10",
|
||||
11: "md:grid-cols-11",
|
||||
12: "md:grid-cols-12"
|
||||
}
|
||||
|
||||
const gridColsLg: { [key in Cols]: string } = {
|
||||
0: "lg:grid-cols-none",
|
||||
1: "lg:grid-cols-1",
|
||||
2: "lg:grid-cols-2",
|
||||
3: "lg:grid-cols-3",
|
||||
4: "lg:grid-cols-4",
|
||||
5: "lg:grid-cols-5",
|
||||
6: "lg:grid-cols-6",
|
||||
7: "lg:grid-cols-7",
|
||||
8: "lg:grid-cols-8",
|
||||
9: "lg:grid-cols-9",
|
||||
10: "lg:grid-cols-10",
|
||||
11: "lg:grid-cols-11",
|
||||
12: "lg:grid-cols-12"
|
||||
}
|
||||
|
||||
const colSpan: { [key in Span]: string } = {
|
||||
1: "col-span-1",
|
||||
2: "col-span-2",
|
||||
3: "col-span-3",
|
||||
4: "col-span-4",
|
||||
5: "col-span-5",
|
||||
6: "col-span-6",
|
||||
7: "col-span-7",
|
||||
8: "col-span-8",
|
||||
9: "col-span-9",
|
||||
10: "col-span-10",
|
||||
11: "col-span-11",
|
||||
12: "col-span-12",
|
||||
13: "col-span-13"
|
||||
}
|
||||
|
||||
const colSpanSm: { [key in Span]: string } = {
|
||||
1: "sm:col-span-1",
|
||||
2: "sm:col-span-2",
|
||||
3: "sm:col-span-3",
|
||||
4: "sm:col-span-4",
|
||||
5: "sm:col-span-5",
|
||||
6: "sm:col-span-6",
|
||||
7: "sm:col-span-7",
|
||||
8: "sm:col-span-8",
|
||||
9: "sm:col-span-9",
|
||||
10: "sm:col-span-10",
|
||||
11: "sm:col-span-11",
|
||||
12: "sm:col-span-12",
|
||||
13: "sm:col-span-13"
|
||||
}
|
||||
|
||||
const colSpanMd: { [key in Span]: string } = {
|
||||
1: "md:col-span-1",
|
||||
2: "md:col-span-2",
|
||||
3: "md:col-span-3",
|
||||
4: "md:col-span-4",
|
||||
5: "md:col-span-5",
|
||||
6: "md:col-span-6",
|
||||
7: "md:col-span-7",
|
||||
8: "md:col-span-8",
|
||||
9: "md:col-span-9",
|
||||
10: "md:col-span-10",
|
||||
11: "md:col-span-11",
|
||||
12: "md:col-span-12",
|
||||
13: "md:col-span-13"
|
||||
}
|
||||
|
||||
const colSpanLg: { [key in Span]: string } = {
|
||||
1: "lg:col-span-1",
|
||||
2: "lg:col-span-2",
|
||||
3: "lg:col-span-3",
|
||||
4: "lg:col-span-4",
|
||||
5: "lg:col-span-5",
|
||||
6: "lg:col-span-6",
|
||||
7: "lg:col-span-7",
|
||||
8: "lg:col-span-8",
|
||||
9: "lg:col-span-9",
|
||||
10: "lg:col-span-10",
|
||||
11: "lg:col-span-11",
|
||||
12: "lg:col-span-12",
|
||||
13: "lg:col-span-13"
|
||||
}
|
30
src/components/ui/heading.tsx
Normal file
30
src/components/ui/heading.tsx
Normal file
|
@ -0,0 +1,30 @@
|
|||
import { splitProps, type Component, type ComponentProps } from "solid-js";
|
||||
import { Dynamic } from "solid-js/web";
|
||||
import { cn } from "~/lib/utils";
|
||||
|
||||
type HeadingProps = ComponentProps<"h1"> & {
|
||||
level: 1 | 2 | 3 | 4 | 5 | 6;
|
||||
};
|
||||
|
||||
const levelClassNames: { [key in HeadingProps["level"]]: string } = {
|
||||
"1": "text-3xl mb-4",
|
||||
"2": "text-2xl mb-4 mt-4",
|
||||
"3": "text-lg mb-2",
|
||||
"4": "font-bold",
|
||||
"5": "font-bold",
|
||||
"6": "font-bold",
|
||||
};
|
||||
|
||||
export const Heading: Component<HeadingProps> = (props) => {
|
||||
const levelStyle = () => levelClassNames[props.level];
|
||||
|
||||
const [local, other] = splitProps(props, ["class", "level"]);
|
||||
|
||||
return (
|
||||
<Dynamic
|
||||
component={`h${local.level}`}
|
||||
class={cn("text-center font-bold", levelStyle(), local.class)}
|
||||
{...other}
|
||||
></Dynamic>
|
||||
);
|
||||
};
|
Loading…
Add table
Add a link
Reference in a new issue