| 1 | import { type TElement } from "platejs"; |
| 2 | import { SlateElement, type SlateElementProps } from "platejs/static"; |
| 3 | import type * as React from "react"; |
| 4 | |
| 5 | import { cn } from "@/lib/utils"; |
| 6 | import { type BUTTON_ELEMENT } from "../../lib"; |
| 7 | |
| 8 | type ButtonStaticElement = TElement & { |
| 9 | alignment?: "center" | "left" | "right"; |
| 10 | backgroundColor?: string; |
| 11 | color?: string; |
| 12 | textColor?: string; |
| 13 | type: typeof BUTTON_ELEMENT; |
| 14 | variant?: "filled" | "outline" | "ghost"; |
| 15 | size?: "sm" | "md" | "lg"; |
| 16 | }; |
| 17 | |
| 18 | function getJustifyClass(alignment: ButtonStaticElement["alignment"]) { |
| 19 | if (alignment === "left") return "justify-start"; |
| 20 | if (alignment === "right") return "justify-end"; |
| 21 | return "justify-center"; |
| 22 | } |
| 23 | |
| 24 | export default function ButtonStatic( |
| 25 | props: SlateElementProps<ButtonStaticElement>, |
| 26 | ) { |
| 27 | const element = props.element as ButtonStaticElement; |
| 28 | const variant = element.variant ?? "filled"; |
| 29 | const size = element.size ?? "md"; |
| 30 | const alignment = element.alignment ?? "left"; |
| 31 | const accentColor = element.backgroundColor ?? "var(--presentation-primary)"; |
| 32 | const textColor = element.textColor ?? element.color; |
| 33 | const backgroundColor = |
| 34 | element.backgroundColor ?? "var(--presentation-primary)"; |
| 35 | |
| 36 | const sizeClasses = |
| 37 | size === "sm" |
| 38 | ? "px-3 py-1 text-sm" |
| 39 | : size === "lg" |
| 40 | ? "px-6 py-3 text-lg" |
| 41 | : "px-4 py-2 text-base"; |
| 42 | |
| 43 | const commonClasses = |
| 44 | "inline-flex items-center gap-2 font-medium transition-(--presentation-transition)"; |
| 45 | |
| 46 | const variantClasses = |
| 47 | variant === "outline" |
| 48 | ? "border" |
| 49 | : variant === "ghost" |
| 50 | ? "bg-transparent" |
| 51 | : ""; |
| 52 | |
| 53 | const style: React.CSSProperties = (() => { |
| 54 | const baseStyle = { |
| 55 | borderRadius: "var(--presentation-button-border-radius, 0.5rem)", |
| 56 | }; |
| 57 | |
| 58 | if (variant === "outline") { |
| 59 | return { |
| 60 | ...baseStyle, |
| 61 | color: textColor ?? accentColor, |
| 62 | backgroundColor: "transparent", |
| 63 | borderColor: accentColor, |
| 64 | } as React.CSSProperties; |
| 65 | } |
| 66 | if (variant === "ghost") { |
| 67 | return { |
| 68 | ...baseStyle, |
| 69 | color: textColor ?? accentColor, |
| 70 | backgroundColor: "transparent", |
| 71 | } as React.CSSProperties; |
| 72 | } |
| 73 | return { |
| 74 | ...baseStyle, |
| 75 | backgroundColor, |
| 76 | color: textColor ?? "var(--presentation-background)", |
| 77 | boxShadow: "var(--presentation-button-shadow, 0 2px 4px rgba(0,0,0,0.1))", |
| 78 | } as React.CSSProperties; |
| 79 | })(); |
| 80 | |
| 81 | return ( |
| 82 | <SlateElement |
| 83 | {...props} |
| 84 | className={cn( |
| 85 | "relative my-1 flex w-full transition-all duration-300", |
| 86 | getJustifyClass(alignment), |
| 87 | props.className, |
| 88 | )} |
| 89 | > |
| 90 | <div |
| 91 | className={cn( |
| 92 | "presentation-element", |
| 93 | commonClasses, |
| 94 | sizeClasses, |
| 95 | variantClasses, |
| 96 | )} |
| 97 | style={style} |
| 98 | > |
| 99 | {props.children} |
| 100 | </div> |
| 101 | </SlateElement> |
| 102 | ); |
| 103 | } |
| 104 |