function DocumentationLinksInput()

in packages/dmn-editor/src/propertiesPanel/DocumentationLinksFormGroup.tsx [228:422]


function DocumentationLinksInput({
  title,
  url,
  isReadOnly,
  isUrlExpanded,
  onChange,
  onRemove,
  setUrlExpanded,
  autoFocus: parentAutoFocus,
}: {
  title: string;
  url: string;
  isReadOnly: boolean;
  isUrlExpanded: boolean;
  onChange: (newUrlTitle: string, newUrl: string) => void;
  onRemove: () => void;
  setUrlExpanded: (isExpanded: boolean) => void;
  autoFocus: boolean;
}) {
  const urlTitleRef = useRef<HTMLInputElement>(null);
  const uuid = useMemo(() => generateUuid(), []);
  const [titleIsUrl, setTitleIsUrl] = useState(false);
  const updatedOnToogle = useRef(false);
  const { hovered } = useDraggableItemContext();
  const [autoFocus, setAutoFocus] = useState(false);

  const parseUrl = useCallback((newUrl: string) => {
    try {
      const url = new URL(newUrl);
      return url.toString();
    } catch (error) {
      try {
        if (!newUrl.includes("http://") && !newUrl.includes("https://")) {
          const urlWithProtocol = "https://" + newUrl + "/";
          const url = new URL(urlWithProtocol);
          // the new URL automatically converts the whitespaces to %20
          // this check verifies if the url has whitespaces
          return url.toString() === urlWithProtocol ? url.toString() : undefined;
        }
      } catch (error) {
        return undefined;
      }
      return undefined;
    }
  }, []);

  const toogleExpanded = useCallback(
    (title: string, url: string) => {
      const parsedUrl = parseUrl(url);
      if (parsedUrl !== undefined && isUrlExpanded === true && (title === "" || titleIsUrl)) {
        // valid parsed url and empty title
        setTitleIsUrl(true);
        updatedOnToogle.current = true;
        onChange(parsedUrl, parsedUrl);
        setUrlExpanded(false);
        setAutoFocus(false);
      } else if (parsedUrl !== undefined && parsedUrl !== url && isUrlExpanded === true) {
        // valid parsed url and different than the current url
        updatedOnToogle.current = true;
        onChange(title, parsedUrl);
        setUrlExpanded(false);
        setAutoFocus(false);
      } else if (url !== "" && parsedUrl === undefined && title === "") {
        // invalid parsed url and empty title
        updatedOnToogle.current = true;
        onChange("", url);
      } else if (url !== "" && parsedUrl === undefined) {
        // nothing should be done with an invalid url
      } else {
        setUrlExpanded(!isUrlExpanded);
        setAutoFocus(!isUrlExpanded);
      }
    },
    [isUrlExpanded, titleIsUrl, parseUrl, setUrlExpanded, onChange]
  );

  const isUrl = useMemo(() => {
    try {
      return new URL(url) && !isUrlExpanded;
    } catch (error) {
      return false;
    }
  }, [url, isUrlExpanded]);

  const allUniqueNames = useMemo(() => new Map<string, string>(), []);

  const validateTitle = useCallback((id, name, allUniqueNames) => true, []);

  const validateUrl = useCallback(
    (id: string, url: string | undefined, allUniqueNames) => {
      if (url !== undefined && url !== "") {
        return parseUrl(url) !== undefined;
      }
      return true;
    },
    [parseUrl]
  );

  const urlDescriptionTooltip = useMemo(() => {
    return url !== "" ? (
      <Text component={TextVariants.p}>{url}</Text>
    ) : (
      <Text component={TextVariants.p}>Empty URL</Text>
    );
  }, [url]);
  const removeTooltip = useMemo(() => <Text component={TextVariants.p}>Remove</Text>, []);

  return (
    <React.Fragment>
      <div
        className={"kie-dmn-editor--documentation-link--row"}
        data-testid={"kie-tools--dmn-editor--documentation-link--row"}
      >
        <Button
          title={"Expand / collapse documentation link"}
          variant={ButtonVariant.plain}
          className={"kie-dmn-editor--documentation-link--row-expand-toogle"}
          onClick={() => toogleExpanded(title, url)}
        >
          {(isUrlExpanded && <AngleDownIcon />) || <AngleRightIcon />}
        </Button>
        <div className={"kie-dmn-editor--documentation-link--row-item"}>
          {!isUrlExpanded ? (
            <>
              <div ref={urlTitleRef} className={"kie-dmn-editor--documentation-link--row-title"}>
                {isUrl ? (
                  <a href={url} target={"_blank"} data-testid={"kie-tools--dmn-editor--documentation-link--row-title"}>
                    {title}
                  </a>
                ) : (
                  <p style={title === "" ? {} : invalidInlineFeelNameStyle} onClick={() => setUrlExpanded(true)}>
                    {title !== "" ? title : PLACEHOLDER_URL_TITLE}
                  </p>
                )}
              </div>
              {!isUrlExpanded && (
                <Tooltip content={urlDescriptionTooltip} position={TooltipPosition.topStart} triggerRef={urlTitleRef} />
              )}
            </>
          ) : (
            <div className={"kie-dmn-editor--documentation-link--row-inputs"}>
              <InlineFeelNameInput
                isPlain={true}
                isReadOnly={isReadOnly}
                id={`${uuid}-name`}
                shouldCommitOnBlur={true}
                placeholder={PLACEHOLDER_URL_TITLE}
                name={title ?? ""}
                onRenamed={(newUrlTitle) => {
                  if (!updatedOnToogle.current && newUrlTitle !== title) {
                    onChange(newUrlTitle, url);
                    setTitleIsUrl(false);
                  }
                  // reset the changedByToogle
                  updatedOnToogle.current = false;
                }}
                allUniqueNames={() => allUniqueNames}
                validate={validateTitle}
                autoFocus={parentAutoFocus || autoFocus}
                onKeyDown={(e) => {
                  if (e.code === "Enter") {
                    // onRenamed and onKeyDown are performed simultaneously, calling the toggleExpdaded callback
                    // with a outdate title value, making it necessary to use the e.currentTarget.value.
                    toogleExpanded(e.currentTarget.value, url);
                  }
                }}
              />
              <InlineFeelNameInput
                className={"kie-dmn-editor--documentation-link--row-inputs-url"}
                isPlain={true}
                isReadOnly={isReadOnly}
                id={`${uuid}-url`}
                shouldCommitOnBlur={true}
                placeholder={PLACEHOLDER_URL}
                name={url ?? ""}
                onRenamed={(newUrl: string) => {
                  if (!updatedOnToogle.current && newUrl !== url) {
                    onChange(title, newUrl);
                  }
                  // reset the changedByToogle
                  updatedOnToogle.current = false;
                }}
                allUniqueNames={() => allUniqueNames}
                validate={validateUrl}
                saveInvalidValue={true}
                onKeyDown={(e) => {
                  if (e.code === "Enter") {
                    // onRenamed and onKeyDown are performed simultaneously, calling the toggleExpdaded callback
                    // with a outdate url value, making it necessary to use the e.currentTarget.value.
                    toogleExpanded(title, e.currentTarget.value);
                  }
                }}
              />
            </div>
          )}