diff --git a/src/NodeInspector.tsx b/src/NodeInspector.tsx index f6028b6..b363de4 100644 --- a/src/NodeInspector.tsx +++ b/src/NodeInspector.tsx @@ -1,8 +1,8 @@ -import { useRef, useState, type RefObject } from 'react'; -import { Button } from '@consta/uikit/Button'; -import { TextField } from '@consta/uikit/TextField'; -import { ColorPicker, hexModel } from '@consta/uikit/ColorPicker'; -import { Text } from '@consta/uikit/Text'; +import { useRef, useState, type RefObject } from "react"; +import { Button } from "@consta/uikit/Button"; +import { TextField } from "@consta/uikit/TextField"; +import { ColorPicker, hexModel } from "@consta/uikit/ColorPicker"; +import { Text } from "@consta/uikit/Text"; import { DEFAULT_CAPTION_TEXT_COLOR, DEFAULT_NODE_BACKGROUND, @@ -10,51 +10,51 @@ import { DEFAULT_NODE_FONT_SIZE, DEFAULT_NODE_TEXT_COLOR, DEFAULT_TASK_BORDER_RADIUS, -} from './nodes'; -import type { DiagramNodeData, NodeKind } from './types'; +} from "./nodes"; +import type { DiagramNodeData, NodeKind } from "./types"; // Every gradient defined in palette.css, across its three "for diagrams / // flowcharts / semantic highlights" sections. Consta's ColorPicker `palette` // prop can't render these — it goes through hexModel, which only understands // flat colors — so these render as our own swatch row instead. const GRADIENT_PRESETS: { name: string; label: string }[] = [ - { name: 'navy', label: 'Тёмно-синий' }, - { name: 'azure', label: 'Лазурный' }, - { name: 'sky', label: 'Небесный' }, - { name: 'teal-dark', label: 'Тёмная бирюза' }, - { name: 'teal-light', label: 'Светлая бирюза' }, - { name: 'navy-dark', label: 'Глубокий синий' }, - { name: 'ice', label: 'Лёд' }, - { name: 'frost', label: 'Иней' }, - { name: 'purple', label: 'Пурпурный' }, - { name: 'red', label: 'Красный' }, - { name: 'orange', label: 'Оранжевый' }, - { name: 'olive', label: 'Оливковый' }, - { name: 'green', label: 'Зелёный' }, - { name: 'green-dark', label: 'Тёмно-зелёный' }, - { name: 'blue', label: 'Синий' }, - { name: 'cyan', label: 'Циан' }, - { name: 'violet', label: 'Виолет' }, - { name: 'lavender', label: 'Лавандовый' }, - { name: 'pink', label: 'Розовый' }, + { name: "navy", label: "Тёмно-синий" }, + { name: "azure", label: "Лазурный" }, + { name: "sky", label: "Небесный" }, + { name: "teal-dark", label: "Тёмная бирюза" }, + { name: "teal-light", label: "Светлая бирюза" }, + { name: "navy-dark", label: "Глубокий синий" }, + { name: "ice", label: "Лёд" }, + { name: "frost", label: "Иней" }, + { name: "purple", label: "Пурпурный" }, + { name: "red", label: "Красный" }, + { name: "orange", label: "Оранжевый" }, + { name: "olive", label: "Оливковый" }, + { name: "green", label: "Зелёный" }, + { name: "green-dark", label: "Тёмно-зелёный" }, + { name: "blue", label: "Синий" }, + { name: "cyan", label: "Циан" }, + { name: "violet", label: "Виолет" }, + { name: "lavender", label: "Лавандовый" }, + { name: "pink", label: "Розовый" }, ]; // "Цвета текста" from palette.css. const TEXT_COLOR_PRESETS: { hex: string; label: string }[] = [ - { hex: '#0079C2', label: 'Синий' }, - { hex: '#525A64', label: 'Тёмный' }, - { hex: '#929AA4', label: 'Серый' }, - { hex: '#FFFFFF', label: 'Белый' }, + { hex: "#0079C2", label: "Синий" }, + { hex: "#525A64", label: "Тёмный" }, + { hex: "#929AA4", label: "Серый" }, + { hex: "#FFFFFF", label: "Белый" }, ]; const TYPE_LABELS: Record = { - task: 'Задача', - startEvent: 'Начальное событие', - intermediateEvent: 'Промежуточное событие', - endEvent: 'Конечное событие', - exclusiveGateway: 'Исключающий шлюз', - parallelGateway: 'Параллельный шлюз', - inclusiveGateway: 'Включающий шлюз', + task: "Задача", + startEvent: "Начальное событие", + intermediateEvent: "Промежуточное событие", + endEvent: "Конечное событие", + exclusiveGateway: "Исключающий шлюз", + parallelGateway: "Параллельный шлюз", + inclusiveGateway: "Включающий шлюз", }; interface NodeInspectorProps { @@ -62,7 +62,7 @@ interface NodeInspectorProps { nodeType: NodeKind; data: DiagramNodeData; childCount: number; - mode: 'edit' | 'view'; + mode: "edit" | "view"; onChange: (patch: Partial) => void; onEnterSubProcess: (nodeId: string) => void; onDuplicate: () => void; @@ -86,20 +86,28 @@ export function NodeInspector({ }: NodeInspectorProps) { const [colorPickerOpen, setColorPickerOpen] = useState(false); // Consta's ref props still use the pre-React-19 non-nullable RefObject shape. - const colorButtonRef = useRef(null) as RefObject; + const colorButtonRef = useRef( + null, + ) as RefObject; // data.color can be a `var(--gradient-x)` reference from the preset row — // hexModel tries to parse that as a hex color and produces NaN, so the // hex-only ColorControl/ColorPicker always need a real flat hex fallback. - const flatColor = data.color && !data.color.startsWith('var(') ? data.color : DEFAULT_NODE_COLOR[nodeType]; + const flatColor = + data.color && !data.color.startsWith("var(") ? + data.color + : DEFAULT_NODE_COLOR[nodeType]; const [textColorPickerOpen, setTextColorPickerOpen] = useState(false); - const textColorButtonRef = useRef(null) as RefObject; + const textColorButtonRef = useRef( + null, + ) as RefObject; // Text sits directly on the colored fill for tasks (needs a light default) // but on the plain canvas for every other shape's caption (needs a dark one). - const defaultTextColor = nodeType === 'task' ? DEFAULT_NODE_TEXT_COLOR : DEFAULT_CAPTION_TEXT_COLOR; + const defaultTextColor = + nodeType === "task" ? DEFAULT_NODE_TEXT_COLOR : DEFAULT_CAPTION_TEXT_COLOR; const currentTextColor = data.textColor ?? defaultTextColor; - if (mode === 'view') { + if (mode === "view") { const hasMeta = Boolean(data.responsible || data.duration); return (
@@ -114,7 +122,11 @@ export function NodeInspector({ {data.description && ( - + {data.description} )} @@ -160,13 +172,28 @@ export function NodeInspector({
-
-
@@ -176,14 +203,15 @@ export function NodeInspector({
{GRADIENT_PRESETS.map(({ name, label }) => { const value = `var(--gradient-${name})`; - const isActive = (data.color ?? DEFAULT_NODE_BACKGROUND[nodeType]) === value; + const isActive = + (data.color ?? DEFAULT_NODE_BACKGROUND[nodeType]) === value; return (
-
{colorPickerOpen && ( onChange({ textColor: hex })} /> ))}
-
{textColorPickerOpen && ( onChange({ label: value ?? '' })} + onChange={(value) => onChange({ label: value ?? "" })} /> onChange({ description: value ?? '' })} + value={data.description ?? ""} + onChange={(value) => onChange({ description: value ?? "" })} /> - onChange({ responsible: value ?? '' })} - /> + {nodeType === "task" && ( + <> + onChange({ responsible: value ?? "" })} + /> - onChange({ duration: value ?? '' })} - /> + onChange({ duration: value ?? "" })} + /> - {nodeType === 'task' && ( - { - const n = Number(value); - if (value && !Number.isNaN(n)) onChange({ borderRadius: n }); - }} - /> + { + const n = Number(value); + if (value && !Number.isNaN(n)) onChange({ borderRadius: n }); + }} + /> + +