22import Key from " @/ui-components/Key.svelte" ;
33import { onMount } from " svelte" ;
44import " @/ui-components/menu/menu.css" ;
5+ import { replaceState } from " $app/navigation" ;
56
6- let w = " 1" ;
7+ let w: string | null = null ;
8+ let selected: number | null = null ;
79
810onMount (() => {
911 const params = new URLSearchParams (window .location .search );
1012 w = params .get (" w" ) ?? " 1" ;
13+ selected = Number (params .get (" s" ) ?? " 1" ) - 1 ;
1114});
1215
1316$ : blocks = [
@@ -17,7 +20,6 @@ $: blocks = [
1720 { label: " 4" , link: ` /game?stage=${w }-4 ` },
1821];
1922
20- let selected = 0 ;
2123let lastKeyTime = 0 ;
2224let lastKey: string | null = null ;
2325const KEY_REPEAT_DELAY = 180 ; // ms
@@ -27,15 +29,22 @@ function prevWorld() {
2729 w = String (Math .max (1 , Number (w ) - 1 ));
2830 const url = new URL (window .location .href );
2931 url .searchParams .set (" w" , w );
30- window . history . replaceState (null , " " , url .toString ());
32+ replaceState (url .toString (), {} );
3133}
3234function nextWorld() {
3335 // wを数値として1増やす(4より大きくしない)
3436 w = String (Math .min (4 , Number (w ) + 1 ));
3537 const url = new URL (window .location .href );
3638 url .searchParams .set (" w" , w );
37- window . history . replaceState (null , " " , url .toString ());
39+ replaceState (url .toString (), {} );
3840}
41+ function select(index : number ): void {
42+ selected = index ;
43+ const url = new URL (window .location .href );
44+ url .searchParams .set (" s" , String (index + 1 ));
45+ replaceState (url .toString (), {});
46+ }
47+
3948function handleKey(e : KeyboardEvent ): void {
4049 const now = Date .now ();
4150 if (e .key === " ArrowRight" || e .key === " ArrowLeft" ) {
@@ -46,23 +55,27 @@ function handleKey(e: KeyboardEvent): void {
4655 lastKey = e .key ;
4756 }
4857
58+ if (selected === null ) {
59+ return ;
60+ }
61+
4962 if (e .key === " ArrowRight" ) {
5063 if (selected === blocks .length - 1 ) {
5164 if (w !== " 4" ) {
5265 nextWorld ();
53- selected = 0 ;
66+ select ( 0 ) ;
5467 }
5568 } else {
56- selected += 1 ;
69+ select ( selected + 1 ) ;
5770 }
5871 } else if (e .key === " ArrowLeft" ) {
5972 if (selected === 0 ) {
6073 if (w !== " 1" ) {
6174 prevWorld ();
62- selected = blocks .length - 1 ;
75+ select ( blocks .length - 1 ) ;
6376 }
6477 } else {
65- selected -= 1 ;
78+ select ( selected - 1 ) ;
6679 }
6780 } else if (e .key === " Enter" || e .key === " " ) {
6881 window .location .href = blocks [selected ].link ;
@@ -73,10 +86,6 @@ function handleKeyUp() {
7386 lastKey = null ;
7487}
7588
76- function handleClick(index : number ): void {
77- selected = index ;
78- }
79-
8089let container: HTMLDivElement | null = null ;
8190
8291onMount (() => {
@@ -131,7 +140,7 @@ onMount(() => {
131140 class ={` appearance-none focus:outline-none bg-white border-6 pt-8 pb-6 pl-8 pr-6 transition-colors duration-200 text-7xl cursor-pointer ${
132141 selected === i ? ' border-red-500 ring ring-red-500' : ' border-base'
133142 } ` }
134- on:click ={() => handleClick (i )}
143+ on:click ={() => select (i )}
135144 >
136145 {block .label }
137146 </button >
@@ -145,7 +154,13 @@ onMount(() => {
145154 <div class =" flex justify-center items-center basis-2/5 min-h-0 shrink grow-2" >
146155 <!-- 画像を中央に配置 -->
147156 <div class =" h-full " >
148- <img src ="/assets/thumbnail {w }- {selected + 1 }.png" alt =" " class =" h-full " />
157+ {#if selected !== null }
158+ <img
159+ src ="/assets/thumbnail {w }- {selected + 1 }.png"
160+ alt =" "
161+ class =" h-full "
162+ />
163+ {/if }
149164 </div >
150165 <!-- テキストを画像の右側に配置 -->
151166 <div class =" flex-none w-max max-h-full flex flex-col items-start bg-white/90 p-4 m-4 rounded-lg border-2" >
0 commit comments