返回 presentation-ai
timeline.tsx
1 import { cva } from "class-variance-authority";
2 import { PlateElement, type PlateElementProps } from "platejs/react";
3 import { type CSSProperties } from "react";
4
5 import { cn } from "@/lib/utils";
6 import { type TTimelineGroupElement } from "../plugins/timeline-plugin";
7 import { getPresentationAccentColor } from "./color-utils";
8
9 export const containerVariants = cva("mb-4 flex", {
10 variants: {
11 orientation: {
12 horizontal: "justify-around",
13 vertical: "flex-col",
14 },
15
16 sidedness: {
17 single: "",
18 double: "",
19 },
20 },
21 compoundVariants: [
22 {
23 orientation: "horizontal",
24 sidedness: "double",
25 class: "my-6 py-4",
26 },
27 ],
28 });
29
30 export const lineVariants = cva("absolute transform", {
31 variants: {
32 orientation: {
33 horizontal: "h-0.5",
34 vertical: "w-0.5",
35 },
36
37 sidedness: {
38 single: "",
39 double: "",
40 },
41 alignment: {
42 left: "",
43 center: "",
44 right: "",
45 },
46 },
47 compoundVariants: [
48 {
49 orientation: "horizontal",
50 sidedness: "single",
51 alignment: "center",
52 class:
53 "top-5 right-[var(--timeline-line-inset)] left-[var(--timeline-line-inset)]",
54 },
55
56 {
57 orientation: "horizontal",
58 sidedness: "single",
59 class:
60 "top-5 right-[var(--timeline-line-inset)] left-[var(--timeline-line-inset)]",
61 alignment: "left",
62 },
63
64 {
65 orientation: "horizontal",
66 sidedness: "single",
67 class:
68 "top-auto right-[var(--timeline-line-inset)] bottom-5 left-[var(--timeline-line-inset)]",
69 alignment: "right",
70 },
71
72 {
73 orientation: "horizontal",
74 sidedness: "double",
75 class:
76 "top-1/2 right-[var(--timeline-line-inset)] left-[var(--timeline-line-inset)] -translate-y-1/2",
77 },
78 {
79 orientation: "vertical",
80 sidedness: "single",
81 class: "top-9 bottom-9 left-5",
82 alignment: "center",
83 },
84
85 {
86 orientation: "vertical",
87 sidedness: "single",
88 class: "top-9 bottom-9 left-5",
89 alignment: "left",
90 },
91
92 {
93 orientation: "vertical",
94 sidedness: "single",
95 class: "top-9 right-5 bottom-9 left-auto",
96 alignment: "right",
97 },
98
99 {
100 orientation: "vertical",
101 sidedness: "double",
102 class: "top-9 bottom-9 left-1/2 -translate-x-1/2",
103 },
104 ],
105 });
106
107 export default function Timeline({
108 element,
109 children,
110 ...props
111 }: PlateElementProps<TTimelineGroupElement>) {
112 const orientation = element.orientation ?? "vertical";
113 const sidedness = element.sidedness ?? "single";
114 const alignment = element.alignment ?? "center";
115 const showLine = element.showLine ?? true;
116 const itemCount = Math.max(element.children.length, 1);
117 const timelineColor = getPresentationAccentColor(
118 element,
119 undefined,
120 "var(--presentation-smart-layout, var(--presentation-primary))",
121 );
122 const lineStyle = {
123 backgroundColor: timelineColor,
124 "--timeline-line-inset": `calc(50% / ${itemCount})`,
125 } satisfies CSSProperties & { "--timeline-line-inset": string };
126
127 return (
128 <div className="relative h-max">
129 {showLine ? (
130 <div
131 data-shape="rect"
132 data-shape-role="timeline-rail"
133 data-fill-color={timelineColor}
134 data-orientation={orientation}
135 className={cn(lineVariants({ orientation, sidedness, alignment }))}
136 style={lineStyle}
137 />
138 ) : null}
139
140 <PlateElement
141 element={element}
142 {...props}
143 className={cn(
144 containerVariants({ orientation, sidedness }),
145 sidedness === "single" && orientation === "horizontal" && "*:flex-1",
146 orientation === "horizontal" && sidedness === "double" && "*:flex-1",
147 )}
148 >
149 {children}
150 </PlateElement>
151 </div>
152 );
153 }
154
154 lines Plain Text