web/src/lib/components/CapturePanel.svelte 3.4 K raw
1
<script>
2
  import { createEventDispatcher } from 'svelte';
3
  import StatsBar from './StatsBar.svelte';
4
5
  export let digraphs = [];
6
  export let typedText = '';
7
8
  const dispatch = createEventDispatcher();
9
10
  let copied = false;
11
12
  function copyJson() {
13
    navigator.clipboard.writeText(jsonData);
14
    copied = true;
15
    setTimeout(() => (copied = false), 2000);
16
  }
17
18
  $: jsonData = JSON.stringify(
19
    digraphs.map((d) => ({
20
      keys: d.keys,
21
      key_1: d.key1,
22
      key_2: d.key2,
23
      hold_time_1_ms: d.holdTime1,
24
      hold_time_2_ms: d.holdTime2,
25
      press_press_ms: d.pressPress,
26
      release_release_ms: d.releaseRelease,
27
      press_release_ms: d.pressRelease,
28
      release_press_ms: d.releasePress,
29
    })),
30
    null,
31
    2
32
  );
33
</script>
34
35
<textarea
36
  bind:value={typedText}
37
  placeholder="start typing..."
38
  rows="4"
39
  on:paste={(e) => dispatch('paste', e)}
40
></textarea>
41
42
{#if digraphs.length > 0}
43
  <StatsBar {digraphs} />
44
45
  <div class="digraph-table-wrap">
46
    <table class="digraph-table">
47
      <thead>
48
        <tr>
49
          <th>keys</th>
50
          <th>HT1</th>
51
          <th>HT2</th>
52
          <th>PP</th>
53
          <th>RR</th>
54
          <th>PR</th>
55
          <th>RP</th>
56
        </tr>
57
      </thead>
58
      <tbody>
59
        {#each digraphs as d (d.id)}
60
          <tr>
61
            <td class="keys-cell">{d.keys}</td>
62
            <td>{d.holdTime1}</td>
63
            <td>{d.holdTime2}</td>
64
            <td>{d.pressPress}</td>
65
            <td>{d.releaseRelease}</td>
66
            <td>{d.pressRelease}</td>
67
            <td>{d.releasePress}</td>
68
          </tr>
69
        {/each}
70
      </tbody>
71
    </table>
72
  </div>
73
74
  <div class="json-section">
75
    <div class="json-header">
76
      <span>data</span>
77
      <div class="json-actions">
78
        <button on:click={copyJson}>{copied ? 'copied!' : 'copy'}</button>
79
      </div>
80
    </div>
81
    <pre class="json-output">{jsonData}</pre>
82
  </div>
83
{/if}
84
85
<style>
86
  textarea {
87
    width: 100%;
88
    border: 1px solid #333;
89
    background: transparent;
90
    color: inherit;
91
    font-family: inherit;
92
    font-size: 14px;
93
    padding: 1rem;
94
    resize: vertical;
95
    outline: none;
96
    box-sizing: border-box;
97
  }
98
99
  textarea::placeholder {
100
    color: #888;
101
  }
102
103
  textarea:focus {
104
    border-color: #888;
105
  }
106
107
  .digraph-table-wrap {
108
    border: 1px solid #333;
109
    max-height: 300px;
110
    overflow-y: auto;
111
  }
112
113
  .digraph-table {
114
    width: 100%;
115
    border-collapse: collapse;
116
    font-size: 12px;
117
  }
118
119
  .digraph-table th,
120
  .digraph-table td {
121
    padding: 0.4rem 0.5rem;
122
    text-align: center;
123
    border-bottom: 1px solid #333;
124
  }
125
126
  .digraph-table th {
127
    position: sticky;
128
    top: 0;
129
    background: #121113;
130
    color: #888;
131
    font-weight: 400;
132
    font-size: 10px;
133
    text-transform: uppercase;
134
    letter-spacing: 0.05em;
135
  }
136
137
  .digraph-table .keys-cell {
138
    text-align: left;
139
    font-weight: 700;
140
  }
141
142
  .json-section {
143
    display: flex;
144
    flex-direction: column;
145
    gap: 0.5rem;
146
  }
147
148
  .json-header {
149
    display: flex;
150
    justify-content: space-between;
151
    align-items: center;
152
    font-size: 12px;
153
    color: #888;
154
  }
155
156
  .json-actions {
157
    display: flex;
158
    gap: 0.5rem;
159
  }
160
161
  .json-actions button {
162
    font-size: 12px;
163
    padding: 4px 8px;
164
  }
165
166
  .json-output {
167
    font-size: 12px;
168
    line-height: 1.5;
169
    color: #ffffff;
170
    border: 1px solid #333;
171
    padding: 1rem;
172
    overflow-x: auto;
173
    white-space: pre;
174
    max-height: 400px;
175
    overflow-y: auto;
176
  }
177
</style>