БазовийКонтролиКастомізаціяПлагінReact.jsКонтекстне менюМіні-картаЗміна маршруту
Цей плагін використовує класичний пресет, який включає візуальні компоненти для вузлів, з’єднань, сокетів і контроли полів вводу. Він використовує styled-components
для стилізації цих компонентів.
Цей плагін можна використовувати в будь-якому додатку, незалежно від стеку (React.js, Vue.js, Angular тощо).
npm i rete-react-plugin rete-render-utils styled-components
Якщо ви використовуєте цей плагін у додатку, яка не використовує React.js, обов’язково також установіть необхідні залежності React.js.
npm i react@18 react-dom@18
import { createRoot } from "react-dom/client";
import { AreaPlugin } from "rete-area-plugin";
import { ReactPlugin, Presets, ReactArea2D } from "rete-react-plugin";
type AreaExtra = ReactArea2D<Schemes>;
// ....
const render = new ReactPlugin<Schemes, AreaExtra>({ createRoot });
render.addPreset(Presets.classic.setup());
area.use(render);
Перегляньте сторінку Базовий редактор, щоб отримати приклад використання цього плагіна рендерінгу.
У випадку, якщо ви використовуєте React.js версії 16 (або 17), просто видаліть метод createRoot
const render = new ReactPlugin<Schemes, AreaExtra>();
Під час роботи з додатком на React хук useRete
усуває необхідність шаблонного коду, який прив’язує редактор до елемента HTML. Це особливо важливо для динамічних оновлень додатку, коли старий екземпляр редактора потрібно видалити та замінити новим.
import { useRete } from 'rete-react-plugin';
function App() {
const [ref, editor] = useRete(createEditor)
return <div ref={ref} className="rete"></div>
}
де createEditor
має повернути об’єкт із методом destroy
(зазвичай він має виклик area.destroy()
)
Цей плагін містить вбудовані контроли, які відображаються на основі таких об’єктів:
ClassicPreset.InputControl
як <input type="number" />
або <input type="text" />
Просто додайте контрол до вузла
node.addControl('my-control', new ClassicPreset.InputControl("number", {
initial: 0,
readonly: false,
change(value) { }
}))
Якщо ви хочете додати різні типи контролів, ви можете повернути необхідний функціональний компонент в обробнику control
властивості customize
.
render.addPreset(Presets.classic.setup({
customize: {
control(context) {
if (context.payload.isButton) {
return (props: { data: { isButton: true, label: string, onClick: () => void }}) => (
<button
onPointerDown={(e) => e.stopPropagation()}
onClick={props.data.onClick}
>
{props.data.label}
</button>
)
}
if (context.payload instanceof ClassicPreset.InputControl) { // не забудьте явно вказати вбудований Presets.classic.Control
return Presets.classic.Control;
}
}
}
}));
node.addControl('my-button', { isButton: true, label: 'Click', onClick() {} })
Це спрощена версія, яка підходить для ознайомлення. Для проектів рекомендується дотримуватися підходу, продемонстрованого в прикладі
Обов’язково викликайте stopPropagation
в onPointerDown
, щоб запобігти перехопленню областю таких подій, як click
. Якщо ви зіткнулися з цією проблемою в React 16 або ваші інтерактивні елементи додаються до кастомного вузла замість контрола, спробуйте наступне рішення:
import { Drag } from "rete-react-plugin";
<Drag.NoDrag>
<button>
{props.data.label}
</button>
</Drag.NoDrag>
Або використовуйте хук, щоб уникнути додаткового вкладення
const ref = React.useRef(null)
Drag.useNoDrag(ref)
<button ref={ref}>
{props.data.label}
</button>
Подібно до підходу, описаного вище, ви можете замінити компоненти вузла, з’єднання або сокета.
Найпростішим підходом є розширення поточного компонента та використання styled-components
для додавання стилів.
import { Presets } from "rete-react-plugin";
import { css } from "styled-components";
const myStyles = css<{ selected?: boolean }>`
background: white;
${(props) => props.selected && css`
border-color: red;
`}
`;
function StyledNode(props: { data: Schemes['Node'] }) {
return <Presets.classic.Node styles={() => myStyles} {...props} />;
}
render.addPreset(Presets.classic.setup({
customize: {
node() {
return StyledNode
}
}
}))
Реалізація цього призведе до того, що всі ваші вузли будуть використовувати myStyles
.
Ви можете додати умову для застосування цих стилів лише до певних вузлів.
render.addPreset(Presets.classic.setup({
customize: {
node(context) {
if (context.payload.label === "White") {
return StyledNode;
}
return Presets.classic.Node;
}
}
}))
await editor.addNode(new ClassicPreset.Node('White'))
Якщо ви хочете повністю змінити структуру вузла, ви можете реалізувати власний компонент, подібний до Node.tsx із класичного пресету.
import { CustomNode } from './CustomNode'
render.addPreset(Presets.classic.setup({
customize: {
node() {
return CustomNode
}
}
}))
Реалізація CustomNode
доступна у файлі CustomNode.tsx прикладу Кастомізація для React.js.
Використовуйте Connection.tsx як відправну точку з presets/classic/components директорії вихідного коду плагіна.
import { CustomConnection } from './CustomConnection'
render.addPreset(Presets.classic.setup({
customize: {
connection() {
return CustomConnection
}
}
}))
Використовуйте Socket.tsx як відправну точку з presets/classic/components директорії вихідного коду плагіна.
import { CustomSocket } from './CustomSocket'
render.addPreset(Presets.classic.setup({
customize: {
socket() {
return CustomSocket
}
}
}))
Оскільки компоненти контекстного меню використовують styled-components
, ви можете кастомізувати їхні стилі за допомогою:
import styled from "styled-components";
const { Menu, Common, Search, Item, Subitems } = Presets.contextMenu
const CustomMenu = styled(Menu)`
width: 320px;
`
const CustomItem = styled(Item)`
background: grey;
`
render.addPreset(Presets.contextMenu.setup({
customize: {
main: () => CustomMenu,
item: () => CustomItem,
common: () => Common,
search: () => Search,
subitems: () => Subitems
}
}))
Перегляньте повний результат на сторінці прикладу Кастомізація для React.js.