/* * Copyright (c) 2021 - 2025, Ludvig Lundgren and the autobrr contributors. * SPDX-License-Identifier: GPL-2.0-or-later */ import { useEffect } from "react"; import { Field, FieldProps, useFormikContext } from "formik"; import { EyeIcon, EyeSlashIcon, CheckCircleIcon, XCircleIcon } from "@heroicons/react/24/solid"; import TextareaAutosize from "react-textarea-autosize"; import { useToggle } from "@hooks/hooks"; import { DocsTooltip } from "@components/tooltips/DocsTooltip"; import { classNames } from "@utils"; type COL_WIDTHS = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12; interface TextFieldProps { name: string; defaultValue?: string; label?: string; required?: boolean; placeholder?: string; columns?: COL_WIDTHS; autoComplete?: string; hidden?: boolean; disabled?: boolean; tooltip?: React.JSX.Element; } export const TextField = ({ name, defaultValue, label, required, placeholder, columns, autoComplete, hidden, tooltip, disabled }: TextFieldProps) => ( ); interface RegexFieldProps { name: string; defaultValue?: string; label?: string; placeholder?: string; columns?: COL_WIDTHS; autoComplete?: string; useRegex?: boolean; hidden?: boolean; disabled?: boolean; tooltip?: React.JSX.Element; } export const RegexField = ({ name, defaultValue, label, placeholder, columns, autoComplete, useRegex, hidden, tooltip, disabled }: RegexFieldProps) => { const validRegex = (pattern: string) => { // Check for unsupported lookahead and lookbehind assertions if (/\(\?<=|\(\?/.test(pattern)) { return false; } // Check for unsupported recursive patterns if (/\(\?(R|0)\)/.test(pattern)) { return false; } // Check for unsupported possessive quantifiers if (/[*+?]{1}\+|\{[0-9]+,[0-9]*\}\+/.test(pattern)) { return false; } // Check for unsupported control verbs if (/\\g { let error = ""; if (!validRegex(val)) { error = "Invalid regex"; } return error; }; const { validateForm } = useFormikContext(); useEffect(() => { if (useRegex) { validateForm(); } }, [useRegex, validateForm]); return ( ); }; export const RegexTextAreaField = ({ name, defaultValue, label, placeholder, columns, autoComplete = "off", useRegex, hidden, tooltip, disabled }: RegexFieldProps) => { const validRegex = (pattern: string) => { // Check for unsupported lookahead and lookbehind assertions if (/\(\?<=|\(\?/.test(pattern)) { return false; } // Check for unsupported recursive patterns if (/\(\?(R|0)\)/.test(pattern)) { return false; } // Check for unsupported possessive quantifiers if (/[*+?]{1}\+|\{[0-9]+,[0-9]*\}\+/.test(pattern)) { return false; } // Check for unsupported control verbs if (/\\g { let error = ""; if (!validRegex(val)) { error = "Invalid regex"; } return error; }; const { validateForm } = useFormikContext(); useEffect(() => { if (useRegex) { validateForm(); } }, [useRegex, validateForm]); return ( ); }; interface TextAreaProps { name: string; defaultValue?: string; label?: string; placeholder?: string; columns?: COL_WIDTHS; rows?: number; autoComplete?: string; hidden?: boolean; disabled?: boolean; tooltip?: React.JSX.Element; } export const TextArea = ({ name, defaultValue, label, placeholder, columns, rows, autoComplete, hidden, tooltip, disabled }: TextAreaProps) => (