Небольшие правки
This commit is contained in:
@@ -1,10 +1,3 @@
|
|||||||
/*
|
|
||||||
Извлечено со скриншотов брендбука/стайлгайда.
|
|
||||||
Угол градиента в источнике указан как «60%» — трактован как 60deg
|
|
||||||
(стандартная запись угла в CSS linear-gradient). Проверьте по оригиналу,
|
|
||||||
если это принципиально.
|
|
||||||
*/
|
|
||||||
|
|
||||||
:root {
|
:root {
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
ОСНОВНЫЕ ГРАДИЕНТЫ (синие) — для инфоблоков, диаграмм, блок-схем
|
ОСНОВНЫЕ ГРАДИЕНТЫ (синие) — для инфоблоков, диаграмм, блок-схем
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
.diagram-node__label {
|
.diagram-node__label {
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
overflow-wrap: break-word;
|
overflow-wrap: break-word;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diagram-node__badge {
|
.diagram-node__badge {
|
||||||
@@ -89,6 +90,7 @@
|
|||||||
max-width: 120px;
|
max-width: 120px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
|
font-weight: 600;
|
||||||
}
|
}
|
||||||
|
|
||||||
.diagram-node--circle {
|
.diagram-node--circle {
|
||||||
|
|||||||
+69
-37
@@ -1,6 +1,12 @@
|
|||||||
import { createContext, useContext } from 'react';
|
import { createContext, useContext } from "react";
|
||||||
import { Handle, NodeResizer, Position, type Node, type NodeProps } from '@xyflow/react';
|
import {
|
||||||
import type { DiagramNodeData, NodeKind } from './types';
|
Handle,
|
||||||
|
NodeResizer,
|
||||||
|
Position,
|
||||||
|
type Node,
|
||||||
|
type NodeProps,
|
||||||
|
} from "@xyflow/react";
|
||||||
|
import type { DiagramNodeData, NodeKind } from "./types";
|
||||||
|
|
||||||
type ShapeNode = Node<DiagramNodeData, NodeKind>;
|
type ShapeNode = Node<DiagramNodeData, NodeKind>;
|
||||||
|
|
||||||
@@ -8,31 +14,31 @@ type ShapeNode = Node<DiagramNodeData, NodeKind>;
|
|||||||
export const NodesWithChildrenContext = createContext<Set<string>>(new Set());
|
export const NodesWithChildrenContext = createContext<Set<string>>(new Set());
|
||||||
|
|
||||||
/** Current editor mode — resize handles and connection points only show in 'edit'. */
|
/** Current editor mode — resize handles and connection points only show in 'edit'. */
|
||||||
export const ModeContext = createContext<'edit' | 'view'>('edit');
|
export const ModeContext = createContext<"edit" | "view">("edit");
|
||||||
|
|
||||||
// Gradients from palette.css's "ОСНОВНАЯ ПАЛИТРА" section — the one the
|
// Gradients from palette.css's "ОСНОВНАЯ ПАЛИТРА" section — the one the
|
||||||
// palette itself labels as meant for diagrams/flowcharts/semantic highlights.
|
// palette itself labels as meant for diagrams/flowcharts/semantic highlights.
|
||||||
// This is what nodes actually render with until a user picks a custom color.
|
// This is what nodes actually render with until a user picks a custom color.
|
||||||
export const DEFAULT_NODE_BACKGROUND: Record<NodeKind, string> = {
|
export const DEFAULT_NODE_BACKGROUND: Record<NodeKind, string> = {
|
||||||
task: 'var(--gradient-blue)',
|
task: "var(--gradient-blue)",
|
||||||
startEvent: 'var(--gradient-green)',
|
startEvent: "var(--gradient-green)",
|
||||||
intermediateEvent: 'var(--gradient-orange)',
|
intermediateEvent: "var(--gradient-orange)",
|
||||||
endEvent: 'var(--gradient-red)',
|
endEvent: "var(--gradient-red)",
|
||||||
exclusiveGateway: 'var(--gradient-purple)',
|
exclusiveGateway: "var(--gradient-purple)",
|
||||||
parallelGateway: 'var(--gradient-cyan)',
|
parallelGateway: "var(--gradient-cyan)",
|
||||||
inclusiveGateway: 'var(--gradient-olive)',
|
inclusiveGateway: "var(--gradient-olive)",
|
||||||
};
|
};
|
||||||
|
|
||||||
// The color picker only understands flat hex, so it needs a solid fallback
|
// The color picker only understands flat hex, so it needs a solid fallback
|
||||||
// distinct from the gradient rendered on canvas — the gradient's start color.
|
// distinct from the gradient rendered on canvas — the gradient's start color.
|
||||||
export const DEFAULT_NODE_COLOR: Record<NodeKind, string> = {
|
export const DEFAULT_NODE_COLOR: Record<NodeKind, string> = {
|
||||||
task: '#0790CB',
|
task: "#0790CB",
|
||||||
startEvent: '#2CB587',
|
startEvent: "#2CB587",
|
||||||
intermediateEvent: '#FF8E58',
|
intermediateEvent: "#FF8E58",
|
||||||
endEvent: '#E13042',
|
endEvent: "#E13042",
|
||||||
exclusiveGateway: '#A12C7E',
|
exclusiveGateway: "#A12C7E",
|
||||||
parallelGateway: '#1BD3F7',
|
parallelGateway: "#1BD3F7",
|
||||||
inclusiveGateway: '#BBBD39',
|
inclusiveGateway: "#BBBD39",
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DEFAULT_TASK_BORDER_RADIUS = 6;
|
export const DEFAULT_TASK_BORDER_RADIUS = 6;
|
||||||
@@ -41,15 +47,15 @@ export const DEFAULT_TASK_BORDER_RADIUS = 6;
|
|||||||
// default; the caption below events/gateways sits on the plain canvas
|
// default; the caption below events/gateways sits on the plain canvas
|
||||||
// background instead and needs a dark one. Both are overridable via the
|
// background instead and needs a dark one. Both are overridable via the
|
||||||
// same `data.textColor`/`data.fontSize`.
|
// same `data.textColor`/`data.fontSize`.
|
||||||
export const DEFAULT_NODE_TEXT_COLOR = '#FFFFFF';
|
export const DEFAULT_NODE_TEXT_COLOR = "#FFFFFF";
|
||||||
export const DEFAULT_CAPTION_TEXT_COLOR = '#525A64';
|
export const DEFAULT_CAPTION_TEXT_COLOR = "#525A64";
|
||||||
export const DEFAULT_NODE_FONT_SIZE = 12;
|
export const DEFAULT_NODE_FONT_SIZE = 12;
|
||||||
|
|
||||||
const HANDLE_POSITIONS: { id: string; position: Position }[] = [
|
const HANDLE_POSITIONS: { id: string; position: Position }[] = [
|
||||||
{ id: 'top', position: Position.Top },
|
{ id: "top", position: Position.Top },
|
||||||
{ id: 'right', position: Position.Right },
|
{ id: "right", position: Position.Right },
|
||||||
{ id: 'bottom', position: Position.Bottom },
|
{ id: "bottom", position: Position.Bottom },
|
||||||
{ id: 'left', position: Position.Left },
|
{ id: "left", position: Position.Left },
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -71,7 +77,10 @@ function SubProcessBadge({ id }: { id: string }) {
|
|||||||
const withChildren = useContext(NodesWithChildrenContext);
|
const withChildren = useContext(NodesWithChildrenContext);
|
||||||
if (!withChildren.has(id)) return null;
|
if (!withChildren.has(id)) return null;
|
||||||
return (
|
return (
|
||||||
<span className="diagram-node__badge" title="Есть вложенные узлы — двойной клик, чтобы открыть">
|
<span
|
||||||
|
className="diagram-node__badge"
|
||||||
|
title="Есть вложенные узлы — двойной клик, чтобы открыть"
|
||||||
|
>
|
||||||
⊞
|
⊞
|
||||||
</span>
|
</span>
|
||||||
);
|
);
|
||||||
@@ -91,7 +100,7 @@ function ShapeResizer({
|
|||||||
const mode = useContext(ModeContext);
|
const mode = useContext(ModeContext);
|
||||||
return (
|
return (
|
||||||
<NodeResizer
|
<NodeResizer
|
||||||
isVisible={selected && mode === 'edit'}
|
isVisible={selected && mode === "edit"}
|
||||||
minWidth={minWidth}
|
minWidth={minWidth}
|
||||||
minHeight={minHeight}
|
minHeight={minHeight}
|
||||||
keepAspectRatio={keepAspectRatio}
|
keepAspectRatio={keepAspectRatio}
|
||||||
@@ -108,12 +117,20 @@ function TaskNode({ id, data, selected }: NodeProps<ShapeNode>) {
|
|||||||
borderRadius: data.borderRadius ?? DEFAULT_TASK_BORDER_RADIUS,
|
borderRadius: data.borderRadius ?? DEFAULT_TASK_BORDER_RADIUS,
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<ShapeResizer selected={selected} minWidth={70} minHeight={32} keepAspectRatio={false} />
|
<ShapeResizer
|
||||||
|
selected={selected}
|
||||||
|
minWidth={70}
|
||||||
|
minHeight={32}
|
||||||
|
keepAspectRatio={false}
|
||||||
|
/>
|
||||||
<ShapeHandles />
|
<ShapeHandles />
|
||||||
<SubProcessBadge id={id} />
|
<SubProcessBadge id={id} />
|
||||||
<span
|
<span
|
||||||
className="diagram-node__label"
|
className="diagram-node__label"
|
||||||
style={{ color: data.textColor ?? DEFAULT_NODE_TEXT_COLOR, fontSize: data.fontSize ?? DEFAULT_NODE_FONT_SIZE }}
|
style={{
|
||||||
|
color: data.textColor ?? DEFAULT_NODE_TEXT_COLOR,
|
||||||
|
fontSize: data.fontSize ?? DEFAULT_NODE_FONT_SIZE,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{data.label}
|
{data.label}
|
||||||
</span>
|
</span>
|
||||||
@@ -122,7 +139,8 @@ function TaskNode({ id, data, selected }: NodeProps<ShapeNode>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function EventNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
function EventNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
||||||
const kind = (type as 'startEvent' | 'intermediateEvent' | 'endEvent') ?? 'startEvent';
|
const kind =
|
||||||
|
(type as "startEvent" | "intermediateEvent" | "endEvent") ?? "startEvent";
|
||||||
return (
|
return (
|
||||||
<div
|
<div
|
||||||
className="diagram-node diagram-node--circle"
|
className="diagram-node diagram-node--circle"
|
||||||
@@ -133,7 +151,10 @@ function EventNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
|||||||
<SubProcessBadge id={id} />
|
<SubProcessBadge id={id} />
|
||||||
<span
|
<span
|
||||||
className="diagram-node__caption"
|
className="diagram-node__caption"
|
||||||
style={{ color: data.textColor ?? DEFAULT_CAPTION_TEXT_COLOR, fontSize: data.fontSize ?? DEFAULT_NODE_FONT_SIZE }}
|
style={{
|
||||||
|
color: data.textColor ?? DEFAULT_CAPTION_TEXT_COLOR,
|
||||||
|
fontSize: data.fontSize ?? DEFAULT_NODE_FONT_SIZE,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{data.label}
|
{data.label}
|
||||||
</span>
|
</span>
|
||||||
@@ -141,14 +162,19 @@ function EventNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
const GATEWAY_ICON: Record<'exclusiveGateway' | 'parallelGateway' | 'inclusiveGateway', string> = {
|
const GATEWAY_ICON: Record<
|
||||||
exclusiveGateway: '✕',
|
"exclusiveGateway" | "parallelGateway" | "inclusiveGateway",
|
||||||
parallelGateway: '+',
|
string
|
||||||
inclusiveGateway: '○',
|
> = {
|
||||||
|
exclusiveGateway: "✕",
|
||||||
|
parallelGateway: "+",
|
||||||
|
inclusiveGateway: "○",
|
||||||
};
|
};
|
||||||
|
|
||||||
function GatewayNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
function GatewayNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
||||||
const kind = (type as 'exclusiveGateway' | 'parallelGateway' | 'inclusiveGateway') ?? 'exclusiveGateway';
|
const kind =
|
||||||
|
(type as "exclusiveGateway" | "parallelGateway" | "inclusiveGateway") ??
|
||||||
|
"exclusiveGateway";
|
||||||
return (
|
return (
|
||||||
<div className="diagram-node--gateway-outer">
|
<div className="diagram-node--gateway-outer">
|
||||||
<ShapeResizer selected={selected} minWidth={32} minHeight={32} />
|
<ShapeResizer selected={selected} minWidth={32} minHeight={32} />
|
||||||
@@ -165,13 +191,19 @@ function GatewayNode({ id, data, type, selected }: NodeProps<ShapeNode>) {
|
|||||||
of it, since clip-path would otherwise cut off anything of theirs
|
of it, since clip-path would otherwise cut off anything of theirs
|
||||||
that renders outside the diamond outline.
|
that renders outside the diamond outline.
|
||||||
*/}
|
*/}
|
||||||
<div className="diagram-node--diamond-bg" style={{ background: data.color ?? DEFAULT_NODE_BACKGROUND[kind] }} />
|
<div
|
||||||
|
className="diagram-node--diamond-bg"
|
||||||
|
style={{ background: data.color ?? DEFAULT_NODE_BACKGROUND[kind] }}
|
||||||
|
/>
|
||||||
<ShapeHandles />
|
<ShapeHandles />
|
||||||
<SubProcessBadge id={id} />
|
<SubProcessBadge id={id} />
|
||||||
<span className="diagram-node__icon">{GATEWAY_ICON[kind]}</span>
|
<span className="diagram-node__icon">{GATEWAY_ICON[kind]}</span>
|
||||||
<span
|
<span
|
||||||
className="diagram-node__caption"
|
className="diagram-node__caption"
|
||||||
style={{ color: data.textColor ?? DEFAULT_CAPTION_TEXT_COLOR, fontSize: data.fontSize ?? DEFAULT_NODE_FONT_SIZE }}
|
style={{
|
||||||
|
color: data.textColor ?? DEFAULT_CAPTION_TEXT_COLOR,
|
||||||
|
fontSize: data.fontSize ?? DEFAULT_NODE_FONT_SIZE,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
{data.label}
|
{data.label}
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
Reference in New Issue
Block a user