| 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> |