-
+
...)', meaning: 'Named capturing group' },
+ { tokens: '(?:...)', meaning: 'Non-capturing group' },
+ { tokens: '(?i) (?m) (?s)', meaning: 'Inline flags: case-insensitive, multi-line, dot-matches-newline' },
+]
+
+// "@" icon next to regex inputs; shows a compact cheat sheet for the regex flavor the server actually
+// uses (Rust `regex` crate — no lookaround/backreferences), modeled on HelpIcon's button styling.
+export function RegexHelpIcon({ label }: { label?: string }) {
+ const [open, setOpen] = useState(false)
+ const ref = useRef
(null)
+
+ useEffect(() => {
+ if (!open) return
+ function onClickOutside(e: MouseEvent) {
+ if (ref.current && !ref.current.contains(e.target as Node)) setOpen(false)
+ }
+ document.addEventListener('mousedown', onClickOutside)
+ return () => document.removeEventListener('mousedown', onClickOutside)
+ }, [open])
+
+ return (
+ setOpen(true)} onMouseLeave={() => setOpen(false)}>
+
+ {open && (
+
+
Regex syntax (Rust regex crate)
+
+
+ {CHEAT_SHEET.map(({ tokens, meaning }) => (
+
+ | {tokens} |
+ {meaning} |
+
+ ))}
+
+
+
No lookaround or backreferences (not supported by the Rust regex crate).
+
+ )}
+
+ )
+}