Generator.tsx

2.9 KB · raw

1import { createSignal } from "solid-js";2import { generatePassword } from "../../shared/generate";34interface GeneratorProps {5  onSelect?: (password: string) => void;6  onClose?: () => void;7}89export function Generator(props: GeneratorProps) {10  const [password, setPassword] = createSignal(generatePassword({ length: 20 }));11  const [length, setLength] = createSignal(20);12  const [upper, setUpper] = createSignal(true);13  const [lower, setLower] = createSignal(true);14  const [numbers, setNumbers] = createSignal(true);15  const [symbols, setSymbols] = createSignal(true);1617  function regenerate() {18    setPassword(19      generatePassword({20        length: length(),21        includeUppercase: upper(),22        includeLowercase: lower(),23        includeNumbers: numbers(),24        includeSymbols: symbols(),25      })26    );27  }2829  function handleUse() {30    if (props.onSelect) {31      props.onSelect(password());32    }33    if (props.onClose) {34      props.onClose();35    }36  }3738  return (39    <div>40      <div class="generator-preview">{password()}</div>41      <div class="generator-controls">42        <span class="generator-label">Length: {length()}</span>43        <input44          type="range"45          class="gen-slider"46          min="8"47          max="64"48          value={length()}49          onInput={(e) => {50            setLength(parseInt((e.target as HTMLInputElement).value));51            regenerate();52          }}53        />54        <label style={{ display: "flex", "align-items": "center", gap: "4px", color: "var(--t2)", "font-size": "11px" }}>55          <input type="checkbox" checked={upper()} onChange={(e) => { setUpper((e.target as HTMLInputElement).checked); regenerate(); }} />56          ABC57        </label>58        <label style={{ display: "flex", "align-items": "center", gap: "4px", color: "var(--t2)", "font-size": "11px" }}>59          <input type="checkbox" checked={lower()} onChange={(e) => { setLower((e.target as HTMLInputElement).checked); regenerate(); }} />60          abc61        </label>62        <label style={{ display: "flex", "align-items": "center", gap: "4px", color: "var(--t2)", "font-size": "11px" }}>63          <input type="checkbox" checked={numbers()} onChange={(e) => { setNumbers((e.target as HTMLInputElement).checked); regenerate(); }} />64          12365        </label>66        <label style={{ display: "flex", "align-items": "center", gap: "4px", color: "var(--t2)", "font-size": "11px" }}>67          <input type="checkbox" checked={symbols()} onChange={(e) => { setSymbols((e.target as HTMLInputElement).checked); regenerate(); }} />68          !@#69        </label>70        <button class="gen-btn" onClick={regenerate}>Regenerate</button>71      </div>72      <div style={{ "margin-top": "12px", display: "flex", gap: "8px" }}>73        <button class="btn-primary" onClick={handleUse} style={{ flex: 1 }}>Use Password</button>74        <button class="btn-secondary" onClick={props.onClose} style={{ flex: 1 }}>Cancel</button>75      </div>76    </div>77  );78}