返回 presentation-ai
circular-grid-static.tsx
根目录 / src / components / notebook / presentation / editor / custom-elements / static / circular-grid-static.tsx
1 "use client";
2
3 import { SlateElement, type SlateElementProps } from "platejs/static";
4
5 import { cn } from "@/lib/utils";
6 import { CIRCULAR_GRID_MAX_ITEMS } from "../../lib";
7 import { type TCircularGridGroupElement } from "../../plugins/diagram-components-plugin";
8 import { CircularGridLayoutProvider } from "../circular-grid";
9 import { getDiagramFitFrameStyle, useDiagramFitScale } from "../diagram-fit";
10 import { getSmartLayoutStepColor } from "../smart-layout-gradient";
11 import {
12 getStaticDiagramJustifyClass,
13 type StaticDiagramElement,
14 } from "./diagram-static-utils";
15
16 const CIRCULAR_GRID_LAYOUT_WIDTH_PX = 640;
17 const CIRCULAR_GRID_LAYOUT_HEIGHT_PX = 520;
18 const CIRCLE_SIZE_PX = 128;
19 const ITEM_COLUMN_WIDTH_PX = 220;
20 const ITEM_COLUMN_GAP_PX = 160;
21 const ITEM_ROW_GAP_PX = 56;
22
23 export default function CircularGridStatic(props: SlateElementProps) {
24 const element = props.element as TCircularGridGroupElement &
25 StaticDiagramElement;
26 const alignment = element.alignment ?? "center";
27 const total = Math.min(
28 element.children?.length || 1,
29 CIRCULAR_GRID_MAX_ITEMS,
30 );
31 const { containerRef, fitStyle, frameStyle, layoutRef } =
32 useDiagramFitScale<HTMLDivElement>(
33 CIRCULAR_GRID_LAYOUT_WIDTH_PX,
34 CIRCULAR_GRID_LAYOUT_HEIGHT_PX,
35 );
36
37 return (
38 <SlateElement {...props} className="my-4">
39 <div
40 ref={containerRef}
41 className={cn(
42 "w-full overflow-visible",
43 getStaticDiagramJustifyClass(alignment),
44 )}
45 >
46 <div
47 style={{
48 ...frameStyle,
49 ...getDiagramFitFrameStyle(alignment),
50 }}
51 >
52 <div
53 ref={layoutRef}
54 className="relative"
55 style={{
56 ...fitStyle,
57 minHeight: CIRCULAR_GRID_LAYOUT_HEIGHT_PX,
58 }}
59 >
60 <div
61 className="grid gap-4"
62 style={{
63 alignContent: "center",
64 columnGap: ITEM_COLUMN_GAP_PX,
65 gridTemplateColumns: `repeat(2, ${ITEM_COLUMN_WIDTH_PX}px)`,
66 gridTemplateRows: "repeat(3, minmax(96px, auto))",
67 height: CIRCULAR_GRID_LAYOUT_HEIGHT_PX,
68 justifyContent: "center",
69 rowGap: ITEM_ROW_GAP_PX,
70 }}
71 >
72 <CircularGridLayoutProvider
73 value={{ alignment, parentElement: element, total }}
74 >
75 {props.children}
76 </CircularGridLayoutProvider>
77
78 {/* Center circle */}
79 <div
80 className="pointer-events-none absolute inset-0 z-0 grid place-items-center"
81 style={{
82 width: "100%",
83 height: "100%",
84 }}
85 data-bg-export="true"
86 >
87 <div
88 className="absolute rounded-full opacity-30"
89 style={{
90 width: CIRCLE_SIZE_PX + 16,
91 height: CIRCLE_SIZE_PX + 16,
92 background: getSmartLayoutStepColor(
93 Math.floor(total / 2),
94 total,
95 ),
96 }}
97 aria-hidden="true"
98 data-decor="true"
99 />
100 <div
101 className="grid place-items-center rounded-full px-4 text-center text-lg font-semibold text-(--presentation-card-background)"
102 style={{
103 width: CIRCLE_SIZE_PX,
104 height: CIRCLE_SIZE_PX,
105 background: getSmartLayoutStepColor(
106 Math.floor(total / 2),
107 total,
108 ),
109 }}
110 >
111 {element.centerText ?? "Smart Diagram"}
112 </div>
113 </div>
114 </div>
115 </div>
116 </div>
117 </div>
118 </SlateElement>
119 );
120 }
121
121 lines Plain Text