Componenteditors0.92 KB gzipZero dependencies

Regex Visualizer

Match highlighter with validity flag.

Preview

Live Preview

Regex visualizer

ROW C SEAT 12, ROW D SEAT 04

Installation

Tokens guide →

Add to your project via CLI (zero dependencies, code you own):

npx bigbullui add regex-visualizer

Or install the full npm package:

npm install bigbullui
import { RegexVisualizer } from "@/components/ui/regex-visualizer";

<RegexVisualizer />

Usage guidance

Use Regex Visualizer when a ticket stub surface needs Match highlighter with validity flag. Keep props minimal and prefer composition with sibling stubs.

Avoid Regex Visualizer for long form flows or dense data grids where a dedicated layout block fits better.

Source code

regex-visualizer.tsx

Zero dependencies (only React + utils). Copy and paste directly into your project:

"use client";

import * as React from "react";
import { cn } from "./lib/utils";

export interface RegexVisualizerProps extends React.HTMLAttributes<HTMLDivElement> {
  defaultPattern?: string;
  defaultSample?: string;
}

/** Regex match highlighter with group readout. */
export function RegexVisualizer({ defaultPattern = "ROW [A-Z]", defaultSample = "ROW C SEAT 12, ROW D SEAT 04", className, ...props }: RegexVisualizerProps) {
  const [pattern, setPattern] = React.useState(defaultPattern);
  const [sample, setSample] = React.useState(defaultSample);
  const parts = React.useMemo(() => {
    try {
      const re = new RegExp(`(${pattern})`, "g");
      return sample.split(re);
    } catch {
      return [sample];
    }
  }, [pattern, sample]);
  let valid = true;
  try {
    new RegExp(pattern);
  } catch {
    valid = false;
  }
  return (
    <div className={cn("w-full rounded-lg border-2 border-foreground bg-card p-4 shadow-md", className)} {...props}>
      <p className="font-mono text-[10px] font-bold uppercase tracking-widest text-muted-foreground">Regex visualizer</p>
      <input value={pattern} onChange={(e) => setPattern(e.target.value)} spellCheck={false} aria-label="Regex pattern" className={cn("mt-2 w-full rounded-md border border-dashed bg-secondary/40 p-2 font-mono text-sm text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring", valid ? "border-border" : "border-destructive")} />
      <textarea value={sample} onChange={(e) => setSample(e.target.value)} rows={2} aria-label="Sample text" className="mt-2 w-full resize-none rounded-md border border-dashed border-border bg-secondary/40 p-2 font-mono text-xs text-foreground focus:outline-none focus-visible:ring-2 focus-visible:ring-ring" />
      <p className="mt-2 rounded-md border border-border bg-background p-2 font-mono text-xs leading-relaxed text-foreground" aria-live="polite">
        {parts.map((p, i) =>
          i % 2 === 1 ? <mark key={i} className="rounded bg-accent px-0.5 text-accent-foreground">{p}</mark> : <span key={i}>{p}</span>
        )}
      </p>
      {!valid && <p className="mt-1 font-mono text-[11px] uppercase text-destructive">Invalid pattern</p>}
    </div>
  );
}