123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176 |
- import React, { useEffect, useMemo, useRef, useState } from "react";
- import { Input, InputRef } from "antd";
- import { Node } from "@antv/x6";
- import { useSafeState } from "ahooks";
- export default function Text(props: {
- value: string;
- styles: React.CSSProperties & {
- bold: boolean;
- italic: boolean;
- };
- node: Node;
- fixedWidth: boolean;
- placeholder?: string;
- txtStyle?: React.CSSProperties;
- onChange?: (value: string) => void;
- }) {
- const { value, styles, node, placeholder, txtStyle } = props;
- const [isEditing, setIsEditing] = useSafeState(false);
- const inputRef = useRef<InputRef>(null);
- const [labelText, setLabelText] = useState(value);
- useEffect(() => {
- setLabelText(value);
- }, [value]);
- const style = useMemo((): React.CSSProperties => {
- return {
- ...styles,
- fontWeight: styles.bold ? "bold" : undefined,
- fontStyle: styles.italic ? "italic" : undefined,
- minHeight: "12px",
- padding: 0,
- wordBreak: "break-all",
- };
- }, [styles]);
- const handleChange = (val: string) => {
- // node.setData({ label: val });
- setLabelText(val);
- props.onChange?.(val);
- };
- const handleSetEditing = (edit: boolean) => {
- if (node.data?.lock) {
- return;
- }
- node.setData({
- ignoreDrag: edit
- });
- if (edit) {
- // 置顶
- node.toFront();
- setTimeout(() => {
- inputRef.current?.focus({ cursor: "all" });
- }, 100);
- } else {
- // 更新数据
- node.prop("changeNodeData", {
- cellId: node.id,
- data: {
- label: labelText
- },
- ignoreRender: false,
- });
- }
- setIsEditing(edit);
- };
- const [findObj, setFindObj] = useState<{
- findStr: string;
- currentCellId?: string;
- currentIndex: number;
- }>();
- // 查找
- const handleFind = (args: any) => {
- setFindObj(args?.current || {});
- };
- const label = useMemo(() => {
- if (!findObj) return value;
- const list = (value || "").split(findObj.findStr || "");
- return list.map((str: string, index) => {
- // 当前的节点展示
- const style =
- findObj.currentCellId === node.id
- ? {
- background:
- index + 1 === findObj.currentIndex
- ? "#FF9933"
- : "rgba(255, 153, 51, 0.25)",
- }
- : {
- background: "#ffff00",
- };
- return (
- <span key={index}>
- {str}
- {index < list.length - 1 && (
- <span style={{
- ...style,
- color: '#333'
- }}>{findObj.findStr}</span>
- )}
- </span>
- );
- });
- }, [value, findObj]);
- const handleReplace = (args: any) => {
- const { type, searchText, replaceText, currentIndex, currentCellId } = args?.current || {};
- // 单个替换 全部替换不在此实现
- if(type === 'replace' && currentCellId === node.id) {
- const list = value.split(searchText);
- const text = list.map((str, index) => {
- const result = index + 1 === currentIndex ? replaceText : searchText;
- return str + (index < list.length - 1 ? result : '');
- }).join("");
- handleChange(text);
- }
- };
- const handleClear = () => {
- setFindObj(undefined);
- };
- useEffect(() => {
- node.off("change:find", handleFind);
- node.off("change:replace", handleReplace);
- node.off("change:clearFind", handleClear);
- node.off("change:customEdit", handleSetEditing);
- node.on("change:find", handleFind);
- node.on("change:replace", handleReplace);
- node.on("change:clearFind", handleClear);
- node.on("change:customEdit", handleSetEditing);
- return () => {
- node.off("change:find", handleFind);
- node.off("change:replace", handleReplace);
- node.off("change:clearFind", handleClear);
- node.off("change:customEdit", handleSetEditing);
- };
- }, [value]);
- return (
- <div style={txtStyle}>
- <div
- style={{
- ...style,
- opacity: isEditing ? 0 : 1,
- }}
- className="min-w-20px"
- onDoubleClick={() => handleSetEditing(true)}
- >
- {label}
- </div>
- {isEditing && (
- <Input.TextArea
- ref={inputRef}
- placeholder={placeholder}
- value={labelText}
- variant="borderless"
- style={{
- ...style,
- position: "absolute",
- left: 0,
- top: 0
- }}
- onChange={(e) => handleChange(e.target.value)}
- onBlur={() => handleSetEditing(false)}
- autoSize
- />
- )}
- </div>
- );
- }
|