import { useState, useEffect, useRef } from 'react';
import init, { IwordDict } from 'iword-rs';
const DICT = `shutdown\t0
crash\t0
kernel_panic\t0
disk_full\t1
oom\t1
deprecated_api\t2
slow_query\t3
user_login\t4
health_check\t5
ping\t5
`;
const KEY_META = {
0: { name: 'BLOCK', color: '#dc2626' },
1: { name: 'ALERT', color: '#ea580c' },
2: { name: 'FLAG', color: '#d97706' },
3: { name: 'THROTTLE', color: '#7c3aed' },
4: { name: 'LOG', color: '#2563eb' },
5: { name: 'PASS', color: '#16a34a' },
};
export default function App() {
const [ready, setReady] = useState(false);
const [text, setText] = useState('');
const [matches, setMatches] = useState([]);
const [filtered, setFiltered] = useState('');
const dictRef = useRef(null);
useEffect(() => {
init().then(() => {
dictRef.current = new IwordDict(DICT);
setReady(true);
});
}, []);
useEffect(() => {
if (!ready || !dictRef.current) return;
const d = dictRef.current;
const m = d.scan(text, true, false);
setMatches(m);
setFiltered(d.filter(text, true));
}, [text, ready]);
const blocked = matches.some(m => m.key === 0);
return (
<div style={{ fontFamily: 'sans-serif', maxWidth: 640, margin: '40px auto', padding: '0 16px' }}>
<h1 style={{ fontSize: 20, marginBottom: 4 }}>iword-rs WASM — Real-time Filter</h1>
<p style={{ color: '#666', fontSize: 13, marginBottom: 16 }}>
Powered by Rust + WebAssembly. Scanning happens in-browser at near-native speed.
</p>
<textarea
rows={4}
style={{ width: '100%', fontSize: 15, padding: 8, boxSizing: 'border-box',
border: blocked ? '2px solid #dc2626' : '1px solid #ccc', borderRadius: 4 }}
placeholder="Type something..."
value={text}
onChange={e => setText(e.target.value)}
disabled={!ready}
/>
{matches.length > 0 && (
<div style={{ marginTop: 12 }}>
<strong>Matches:</strong>
<div style={{ display: 'flex', flexWrap: 'wrap', gap: 8, marginTop: 6 }}>
{matches.map((m, i) => {
const meta = KEY_META[m.key] ?? { name: `USER(${m.key})`, color: '#888' };
return (
<span key={i} style={{
background: meta.color, color: '#fff', borderRadius: 4,
padding: '2px 8px', fontSize: 13,
}}>
{meta.name}: "{m.extract(text)}"
</span>
);
})}
</div>
</div>
)}
{text && (
<div style={{ marginTop: 12 }}>
<strong>Filtered:</strong>
<div style={{ marginTop: 4, padding: 8, background: '#f5f5f5',
borderRadius: 4, fontFamily: 'monospace', fontSize: 14 }}>
{filtered || '(empty)'}
</div>
</div>
)}
{blocked && (
<div style={{ marginTop: 12, padding: 10, background: '#fef2f2',
border: '1px solid #dc2626', borderRadius: 4, color: '#dc2626', fontWeight: 'bold' }}>
BLOCK word detected — submission disabled
</div>
)}
<button
disabled={blocked || !text}
style={{ marginTop: 16, padding: '8px 20px', fontSize: 14,
background: blocked ? '#ccc' : '#2563eb', color: '#fff',
border: 'none', borderRadius: 4, cursor: blocked ? 'not-allowed' : 'pointer' }}
>
Submit
</button>
{!ready && <p style={{ color: '#888', marginTop: 8 }}>Loading WASM...</p>}
</div>
);
}