mirror of
https://github.com/excalidraw/excalidraw.git
synced 2025-05-03 10:00:07 -04:00
feats: 完善选择箭头样式的 ui 样式
This commit is contained in:
parent
5bc27c64f2
commit
df48c49812
6 changed files with 191 additions and 77 deletions
|
@ -1542,11 +1542,54 @@ export const actionChangeArrowhead = register({
|
|||
};
|
||||
},
|
||||
PanelComponent: ({ elements, appState, updateData }) => {
|
||||
const customOptions = useContext(ExcalidrawPropsCustomOptionsContext);
|
||||
|
||||
const isRTL = getLanguage().rtl;
|
||||
|
||||
return (
|
||||
<fieldset>
|
||||
<legend>{t("labels.arrowheads")}</legend>
|
||||
{customOptions?.pickerRenders?.ButtonList && (
|
||||
<customOptions.pickerRenders.ButtonList className="iconPickerList">
|
||||
<IconPicker
|
||||
label="arrowhead_start"
|
||||
options={getArrowheadOptions(!isRTL)}
|
||||
value={getFormValue<Arrowhead | null>(
|
||||
elements,
|
||||
appState,
|
||||
(element) =>
|
||||
isLinearElement(element) && canHaveArrowheads(element.type)
|
||||
? element.startArrowhead
|
||||
: appState.currentItemStartArrowhead,
|
||||
true,
|
||||
appState.currentItemStartArrowhead,
|
||||
)}
|
||||
onChange={(value) =>
|
||||
updateData({ position: "start", type: value })
|
||||
}
|
||||
numberOfOptionsToAlwaysShow={4}
|
||||
/>
|
||||
<IconPicker
|
||||
label="arrowhead_end"
|
||||
group="arrowheads"
|
||||
options={getArrowheadOptions(!!isRTL)}
|
||||
value={getFormValue<Arrowhead | null>(
|
||||
elements,
|
||||
appState,
|
||||
(element) =>
|
||||
isLinearElement(element) && canHaveArrowheads(element.type)
|
||||
? element.endArrowhead
|
||||
: appState.currentItemEndArrowhead,
|
||||
true,
|
||||
appState.currentItemEndArrowhead,
|
||||
)}
|
||||
onChange={(value) => updateData({ position: "end", type: value })}
|
||||
numberOfOptionsToAlwaysShow={4}
|
||||
/>
|
||||
</customOptions.pickerRenders.ButtonList>
|
||||
)}
|
||||
|
||||
{!customOptions?.pickerRenders?.ButtonList && (
|
||||
<div className="iconSelectList buttonList">
|
||||
<IconPicker
|
||||
label="arrowhead_start"
|
||||
|
@ -1561,7 +1604,9 @@ export const actionChangeArrowhead = register({
|
|||
true,
|
||||
appState.currentItemStartArrowhead,
|
||||
)}
|
||||
onChange={(value) => updateData({ position: "start", type: value })}
|
||||
onChange={(value) =>
|
||||
updateData({ position: "start", type: value })
|
||||
}
|
||||
numberOfOptionsToAlwaysShow={4}
|
||||
/>
|
||||
<IconPicker
|
||||
|
@ -1582,6 +1627,7 @@ export const actionChangeArrowhead = register({
|
|||
numberOfOptionsToAlwaysShow={4}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</fieldset>
|
||||
);
|
||||
},
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import * as Popover from "@radix-ui/react-popover";
|
||||
import clsx from "clsx";
|
||||
import React, { useEffect } from "react";
|
||||
import React, { useContext, useEffect } from "react";
|
||||
|
||||
import { isArrowKey, KEYS } from "@excalidraw/common";
|
||||
|
||||
import { atom, useAtom } from "../editor-jotai";
|
||||
import { getLanguage, t } from "../i18n";
|
||||
|
||||
import { ExcalidrawPropsCustomOptionsContext } from "../types";
|
||||
|
||||
import Collapsible from "./Stats/Collapsible";
|
||||
import { useDevice } from "./App";
|
||||
|
||||
|
@ -115,10 +117,33 @@ function Picker<T>({
|
|||
}
|
||||
}, [value, alwaysVisibleOptions, setShowMoreOptions]);
|
||||
|
||||
const customOptions = useContext(ExcalidrawPropsCustomOptionsContext);
|
||||
|
||||
const renderOptions = (options: Option<T>[]) => {
|
||||
return (
|
||||
<div className="picker-content">
|
||||
{options.map((option, i) => (
|
||||
{options.map((option, i) => {
|
||||
if (customOptions?.pickerRenders?.layerButtonRender) {
|
||||
return customOptions.pickerRenders.layerButtonRender({
|
||||
active: value === option.value,
|
||||
title: option.text,
|
||||
children: (
|
||||
<>
|
||||
{option.icon}
|
||||
{/* {option.keyBinding && (
|
||||
<span className="picker-keybinding">
|
||||
{option.keyBinding}
|
||||
</span>
|
||||
)} */}
|
||||
</>
|
||||
),
|
||||
key: option.text,
|
||||
onClick: () => onChange(option.value),
|
||||
name: option.text,
|
||||
});
|
||||
}
|
||||
|
||||
return (
|
||||
<button
|
||||
type="button"
|
||||
className={clsx("picker-option", {
|
||||
|
@ -147,7 +172,8 @@ function Picker<T>({
|
|||
<span className="picker-keybinding">{option.keyBinding}</span>
|
||||
)}
|
||||
</button>
|
||||
))}
|
||||
);
|
||||
})}
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
@ -162,7 +188,7 @@ function Picker<T>({
|
|||
align="start"
|
||||
sideOffset={12}
|
||||
style={{ zIndex: "var(--zIndex-popup)" }}
|
||||
onKeyDown={handleKeyDown}
|
||||
onKeyDown={customOptions?.disableKeyEvents ? undefined : handleKeyDown}
|
||||
>
|
||||
<div
|
||||
className={`picker`}
|
||||
|
@ -209,12 +235,15 @@ export function IconPicker<T>({
|
|||
numberOfOptionsToAlwaysShow?: number;
|
||||
group?: string;
|
||||
}) {
|
||||
const customOptions = useContext(ExcalidrawPropsCustomOptionsContext);
|
||||
|
||||
const [isActive, setActive] = React.useState(false);
|
||||
const rPickerButton = React.useRef<any>(null);
|
||||
|
||||
const renderTrigger = () => {
|
||||
if (customOptions?.pickerRenders?.layerButtonRender) {
|
||||
return (
|
||||
<div>
|
||||
<Popover.Root open={isActive} onOpenChange={(open) => setActive(open)}>
|
||||
<>
|
||||
<Popover.Trigger
|
||||
name={group}
|
||||
type="button"
|
||||
|
@ -222,9 +251,30 @@ export function IconPicker<T>({
|
|||
onClick={() => setActive(!isActive)}
|
||||
ref={rPickerButton}
|
||||
className={isActive ? "active" : ""}
|
||||
style={{
|
||||
padding: 0,
|
||||
border: "unset",
|
||||
width: 0,
|
||||
}}
|
||||
>
|
||||
{options.find((option) => option.value === value)?.icon}
|
||||
</Popover.Trigger>
|
||||
{customOptions.pickerRenders.layerButtonRender({
|
||||
name: group,
|
||||
title: "",
|
||||
onClick: () => setActive(!isActive),
|
||||
children: options.find((option) => option.value === value)?.icon,
|
||||
active: isActive,
|
||||
})}
|
||||
</>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Popover.Root open={isActive} onOpenChange={(open) => setActive(open)}>
|
||||
{renderTrigger()}
|
||||
{isActive && (
|
||||
<Picker
|
||||
options={options}
|
||||
|
|
|
@ -47,6 +47,7 @@ const StaticCanvas = (props: StaticCanvasProps) => {
|
|||
|
||||
wrapper.replaceChildren(canvas);
|
||||
canvas.classList.add("excalidraw__canvas", "static");
|
||||
canvas.id = "excalidraw__content-canvas";
|
||||
}
|
||||
|
||||
const widthString = `${props.appState.width}px`;
|
||||
|
|
|
@ -44,12 +44,19 @@
|
|||
"arrowhead_triangle_outline": "三角箭头(空心)",
|
||||
"arrowhead_diamond": "菱形",
|
||||
"arrowhead_diamond_outline": "菱形(空心)",
|
||||
"arrowhead_crowfoot_many": "交叉箭头(多个)",
|
||||
"arrowhead_crowfoot_one": "交叉箭头(一个)",
|
||||
"arrowhead_crowfoot_one_or_many": "交叉箭头(一个或多个)",
|
||||
"arrowtypes": "箭头类型",
|
||||
"arrowtype_sharp": "尖锐箭头",
|
||||
"arrowtype_round": "圆润箭头",
|
||||
"arrowtype_elbowed": "弯曲箭头",
|
||||
"fontSize": "字体大小",
|
||||
"fontFamily": "字体",
|
||||
"addWatermark": "添加 “使用 Excalidraw 创建” 水印",
|
||||
"handDrawn": "手写",
|
||||
"normal": "普通",
|
||||
"more_options": "更多选项",
|
||||
"code": "代码",
|
||||
"small": "小",
|
||||
"medium": "中",
|
||||
|
|
|
@ -44,11 +44,19 @@
|
|||
"arrowhead_triangle_outline": "三角形(外框)",
|
||||
"arrowhead_diamond": "菱形",
|
||||
"arrowhead_diamond_outline": "菱形(外框)",
|
||||
"arrowhead_crowfoot_many": "交叉箭頭(多個)",
|
||||
"arrowhead_crowfoot_one": "交叉箭頭(一個)",
|
||||
"arrowhead_crowfoot_one_or_many": "交叉箭頭(一個或多個)",
|
||||
"arrowtypes": "箭頭類型",
|
||||
"arrowtype_sharp": "尖銳箭頭",
|
||||
"arrowtype_round": "圓潤箭頭",
|
||||
"arrowtype_elbowed": "彎曲箭頭",
|
||||
"fontSize": "字型大小",
|
||||
"fontFamily": "字體集",
|
||||
"addWatermark": "加上 \"Made with Excalidraw\" 浮水印",
|
||||
"handDrawn": "手寫",
|
||||
"normal": "一般",
|
||||
"more_options": "更多選項",
|
||||
"code": "代碼",
|
||||
"small": "小",
|
||||
"medium": "中",
|
||||
|
|
|
@ -544,7 +544,7 @@ export interface ExcalidrawPropsCustomOptions {
|
|||
menuRender?: (props: { children: React.ReactNode }) => React.ReactNode;
|
||||
};
|
||||
pickerRenders?: {
|
||||
ButtonList?: React.ComponentType<{ children: React.ReactNode }>;
|
||||
ButtonList?: React.ComponentType<{ children: React.ReactNode; className?: string }>;
|
||||
elementStrokeColors?: ColorTuple;
|
||||
elementBackgroundColors?: ColorTuple;
|
||||
buttonIconSelectRender?: <T extends Object>(
|
||||
|
@ -569,6 +569,8 @@ export interface ExcalidrawPropsCustomOptions {
|
|||
name: string;
|
||||
visible?: boolean;
|
||||
hidden?: boolean;
|
||||
key?: string;
|
||||
active?: boolean;
|
||||
}) => JSX.Element;
|
||||
rangeRender?: (props: {
|
||||
value: number;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue