File size: 1,677 Bytes
c126239
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<script lang="ts">
  import { randomSeed } from '../../lib/stores/app-state';

  /**
   * The seed lives in the store, not in a binding: `wizard` is a plain object
   * read out of a Svelte store, so mutating a nested field on it would not be
   * observed. The parent commits the value through setSeed().
   */
  let {
    seed,
    onSeed,
    label = 'Secret seed',
    hint = '',
  }: {
    seed: number | null;
    onSeed: (value: number | null) => void;
    label?: string;
    hint?: string;
  } = $props();

  let input: HTMLInputElement | undefined = $state();
  const awaiting = $derived(seed === null);

  $effect(() => {
    // Put the caret in the box so the pulsing border reads as "type here".
    if (awaiting && input) input.focus();
  });

  function onInput(e: Event) {
    const v = (e.target as HTMLInputElement).value.trim();
    onSeed(v === '' ? null : Math.abs(Math.trunc(Number(v))) || 0);
  }
</script>

<div class="seed">
  <label for="seed-input">{label}</label>
  <input
    id="seed-input"
    bind:this={input}
    class="mono"
    class:awaiting-input={awaiting}
    type="number"
    min="0"
    inputmode="numeric"
    placeholder="type a number…"
    value={seed ?? ''}
    oninput={onInput}
  />
  <button title="random seed" onclick={() => onSeed(randomSeed())}>&#9860; random</button>
  {#if awaiting}
    <span class="dim small">Enter a seed to derive the secret key.</span>
  {:else if hint}
    <span class="dim small mono">{hint}</span>
  {/if}
</div>

<style>
  .seed {
    display: flex;
    align-items: center;
    gap: 10px;
    flex-wrap: wrap;
  }
  label {
    font-weight: 550;
  }
  input {
    width: 150px;
  }
</style>