|
11 | 11 | import type { Gist, User } from '$lib/db/types'; |
12 | 12 | import type { File } from '@sveltejs/repl'; |
13 | 13 | import { browser } from '$app/environment'; |
| 14 | + import SelectIcon from '$lib/components/SelectIcon.svelte'; |
| 15 | + import { untrack } from 'svelte'; |
14 | 16 |
|
15 | 17 | interface Props { |
16 | 18 | examples: Array<{ title: string; examples: any[] }>; |
|
40 | 42 | let downloading = $state(false); |
41 | 43 | let justSaved = $state(false); |
42 | 44 | let justForked = $state(false); |
43 | | - let select: HTMLSelectElement; |
| 45 | + let select: any; // TODO why can't i do `select: SelectIcon`? |
44 | 46 |
|
45 | 47 | function wait(ms: number) { |
46 | 48 | return new Promise((f) => setTimeout(f, ms)); |
@@ -214,35 +216,37 @@ export default app;` |
214 | 216 | // the example can be reselected |
215 | 217 | $effect(() => { |
216 | 218 | if (modified) { |
217 | | - select.value = ''; |
| 219 | + // this is a little tricky, but: we need to wrap this in untrack |
| 220 | + // because otherwise we'll read `select.value` and re-run this |
| 221 | + // when we navigate, which we don't want |
| 222 | + untrack(() => { |
| 223 | + select.value = ''; |
| 224 | + }); |
218 | 225 | } |
219 | 226 | }); |
220 | 227 | </script> |
221 | 228 |
|
222 | 229 | <svelte:window on:keydown={handleKeydown} /> |
223 | 230 |
|
224 | 231 | <div class="app-controls"> |
225 | | - <div class="examples-select"> |
226 | | - <span class="raised icon"><Icon name="menu" /></span> |
227 | | - <select |
228 | | - bind:this={select} |
229 | | - title="examples" |
230 | | - value={gist.id} |
231 | | - onchange={(e) => { |
232 | | - goto(`/playground/${e.currentTarget.value}`); |
233 | | - }} |
234 | | - > |
235 | | - <option value="untitled">Create new</option> |
236 | | - <option disabled selected value="">or choose an example</option> |
237 | | - {#each examples as section} |
238 | | - <optgroup label={section.title}> |
239 | | - {#each section.examples as example} |
240 | | - <option value={example.slug}>{example.title}</option> |
241 | | - {/each} |
242 | | - </optgroup> |
243 | | - {/each} |
244 | | - </select> |
245 | | - </div> |
| 232 | + <SelectIcon |
| 233 | + bind:this={select} |
| 234 | + title="examples" |
| 235 | + value={gist.id} |
| 236 | + onchange={async (e) => { |
| 237 | + goto(`/playground/${e.currentTarget.value}`); |
| 238 | + }} |
| 239 | + > |
| 240 | + <option value="untitled">Create new</option> |
| 241 | + <option disabled selected value="">or choose an example</option> |
| 242 | + {#each examples as section} |
| 243 | + <optgroup label={section.title}> |
| 244 | + {#each section.examples as example} |
| 245 | + <option value={example.slug}>{example.title}</option> |
| 246 | + {/each} |
| 247 | + </optgroup> |
| 248 | + {/each} |
| 249 | + </SelectIcon> |
246 | 250 |
|
247 | 251 | <input |
248 | 252 | bind:value={name} |
@@ -325,30 +329,7 @@ export default app;` |
325 | 329 | gap: 0.2rem; |
326 | 330 | } |
327 | 331 |
|
328 | | - .examples-select { |
329 | | - position: relative; |
330 | | -
|
331 | | - &:has(select:focus-visible) .raised.icon { |
332 | | - outline: 2px solid hsla(var(--sk-theme-1-hsl), 0.6); |
333 | | - border-radius: var(--sk-border-radius); |
334 | | - } |
335 | | -
|
336 | | - span { |
337 | | - pointer-events: none; |
338 | | - } |
339 | | - } |
340 | | -
|
341 | | - select { |
342 | | - opacity: 0.0001; |
343 | | - position: absolute; |
344 | | - top: 0; |
345 | | - left: 0; |
346 | | - width: 100%; |
347 | | - height: 100%; |
348 | | - } |
349 | | -
|
350 | | - button, |
351 | | - span.icon { |
| 332 | + button { |
352 | 333 | display: flex; |
353 | 334 | align-items: center; |
354 | 335 | justify-content: center; |
|
0 commit comments