import type { BorderOptions, HorizontalAlignment, VerticalAlignment, } from "@ironcalc/wasm"; import { styled } from "@mui/material/styles"; import { AlignCenter, AlignLeft, AlignRight, ArrowDownToLine, ArrowUpToLine, Bold, ChevronDown, Euro, Grid2X2, Grid2x2Check, Grid2x2X, Italic, PaintBucket, Paintbrush2, Percent, Redo2, Strikethrough, Type, Underline, Undo2, } from "lucide-react"; import { useRef, useState } from "react"; import { useTranslation } from "react-i18next"; import { ArrowMiddleFromLine, DecimalPlacesDecreaseIcon, DecimalPlacesIncreaseIcon, } from "../icons"; import { theme } from "../theme"; import BorderPicker from "./borderPicker"; import ColorPicker from "./colorPicker"; import { TOOLBAR_HEIGH } from "./constants"; import FormatMenu from "./formatMenu"; import { NumberFormats, decreaseDecimalPlaces, increaseDecimalPlaces, } from "./formatUtil"; type ToolbarProperties = { canUndo: boolean; canRedo: boolean; onRedo: () => void; onUndo: () => void; onToggleUnderline: (u: boolean) => void; onToggleBold: (v: boolean) => void; onToggleItalic: (v: boolean) => void; onToggleStrike: (v: boolean) => void; onToggleHorizontalAlign: (v: string) => void; onToggleVerticalAlign: (v: string) => void; onCopyStyles: () => void; onTextColorPicked: (hex: string) => void; onFillColorPicked: (hex: string) => void; onNumberFormatPicked: (numberFmt: string) => void; onBorderChanged: (border: BorderOptions) => void; fillColor: string; fontColor: string; bold: boolean; underline: boolean; italic: boolean; strike: boolean; horizontalAlign: HorizontalAlignment; verticalAlign: VerticalAlignment; canEdit: boolean; numFmt: string; showGridLines: boolean; onToggleShowGridLines: (show: boolean) => void; }; function Toolbar(properties: ToolbarProperties) { const [fontColorPickerOpen, setFontColorPickerOpen] = useState(false); const [fillColorPickerOpen, setFillColorPickerOpen] = useState(false); const [borderPickerOpen, setBorderPickerOpen] = useState(false); const fontColorButton = useRef(null); const fillColorButton = useRef(null); const borderButton = useRef(null); const { t } = useTranslation(); const { canEdit } = properties; return ( { properties.onNumberFormatPicked(NumberFormats.CURRENCY_EUR); }} disabled={!canEdit} title={t("toolbar.euro")} > { properties.onNumberFormatPicked(NumberFormats.PERCENTAGE); }} disabled={!canEdit} title={t("toolbar.percentage")} > { properties.onNumberFormatPicked( decreaseDecimalPlaces(properties.numFmt), ); }} disabled={!canEdit} title={t("toolbar.decimal_places_decrease")} > { properties.onNumberFormatPicked( increaseDecimalPlaces(properties.numFmt), ); }} disabled={!canEdit} title={t("toolbar.decimal_places_increase")} > { properties.onNumberFormatPicked(numberFmt); }} onExited={(): void => {}} anchorOrigin={{ horizontal: 20, // Aligning the menu to the middle of FormatButton vertical: "bottom", }} > {"123"} properties.onToggleBold(!properties.bold)} disabled={!canEdit} title={t("toolbar.bold")} > properties.onToggleItalic(!properties.italic)} disabled={!canEdit} title={t("toolbar.italic")} > properties.onToggleUnderline(!properties.underline)} disabled={!canEdit} title={t("toolbar.underline")} > properties.onToggleStrike(!properties.strike)} disabled={!canEdit} title={t("toolbar.strike_through")} > setFontColorPickerOpen(true)} > setFillColorPickerOpen(true)} > setBorderPickerOpen(true)} ref={borderButton} disabled={!canEdit} title={t("toolbar.borders.title")} > properties.onToggleHorizontalAlign( properties.horizontalAlign === "left" ? "general" : "left", ) } disabled={!canEdit} title={t("toolbar.align_left")} > properties.onToggleHorizontalAlign( properties.horizontalAlign === "center" ? "general" : "center", ) } disabled={!canEdit} title={t("toolbar.align_center")} > properties.onToggleHorizontalAlign( properties.horizontalAlign === "right" ? "general" : "right", ) } disabled={!canEdit} title={t("toolbar.align_right")} > properties.onToggleVerticalAlign("top")} disabled={!canEdit} title={t("toolbar.vertical_align_top")} > properties.onToggleVerticalAlign("center")} disabled={!canEdit} title={t("toolbar.vertical_align_middle")} > properties.onToggleVerticalAlign("bottom")} disabled={!canEdit} title={t("toolbar.vertical_align_bottom")} > properties.onToggleShowGridLines(!properties.showGridLines) } disabled={!canEdit} title={t("toolbar.show_hide_grid_lines")} > {properties.showGridLines ? : } { properties.onTextColorPicked(color); setFontColorPickerOpen(false); }} onClose={() => { setFontColorPickerOpen(false); }} anchorEl={fontColorButton} open={fontColorPickerOpen} /> { properties.onFillColorPicked(color); setFillColorPickerOpen(false); }} onClose={() => { setFillColorPickerOpen(false); }} anchorEl={fillColorButton} open={fillColorPickerOpen} /> { properties.onBorderChanged(border); }} onClose={() => { setBorderPickerOpen(false); }} anchorEl={borderButton} open={borderPickerOpen} /> ); } const ToolbarContainer = styled("div")` display: flex; flex-shrink: 0; align-items: center; background: ${({ theme }) => theme.palette.background.paper}; height: ${TOOLBAR_HEIGH}px; line-height: ${TOOLBAR_HEIGH}px; border-bottom: 1px solid ${({ theme }) => theme.palette.grey["300"]}; font-family: Inter; border-radius: 4px 4px 0px 0px; overflow-x: auto; padding-left: 11px; `; type TypeButtonProperties = { $pressed: boolean; $underlinedColor?: string }; export const StyledButton = styled("button")( ({ disabled, $pressed, $underlinedColor }) => { const result = { width: "24px", height: "24px", display: "inline-flex", alignItems: "center", justifyContent: "center", fontSize: "26px", border: "0px solid #fff", borderRadius: "2px", marginRight: "5px", transition: "all 0.2s", cursor: "pointer", backgroundColor: "white", padding: "0px", svg: { width: "16px", height: "16px", }, }; if (disabled) { return { ...result, color: theme.palette.grey["600"], cursor: "default", }; } return { ...result, borderTop: $underlinedColor ? "3px solid #FFF" : "none", borderBottom: $underlinedColor ? `3px solid ${$underlinedColor}` : "none", color: "#21243A", backgroundColor: $pressed ? "#EEE" : "#FFF", "&:hover": { backgroundColor: "#F1F2F8", borderTopColor: "#F1F2F8", }, }; }, ); const Divider = styled("div")({ width: "0px", height: "10px", borderLeft: "1px solid #E0E0E0", marginLeft: "5px", marginRight: "10px", }); export default Toolbar;