mishig HF staff commited on
Commit
65131f6
1 Parent(s): b6d0c8a

Use arrow keys to select models

Browse files
src/lib/components/InferencePlayground/InferencePlaygroundModelSelectorModal.svelte CHANGED
@@ -1,7 +1,7 @@
1
  <script lang="ts">
2
  import type { ModelEntryWithTokenizer } from "./types";
3
 
4
- import { createEventDispatcher } from "svelte";
5
 
6
  import { FEATUED_MODELS_IDS } from "./inferencePlaygroundUtils";
7
  import IconSearch from "../Icons/IconSearch.svelte";
@@ -11,14 +11,51 @@
11
 
12
  let backdropEl: HTMLDivElement;
13
  let query = "";
 
 
 
14
 
15
  const dispatch = createEventDispatcher<{ modelSelected: string; close: void }>();
16
 
17
  function handleKeydown(event: KeyboardEvent) {
18
  const { key } = event;
 
19
  if (key === "Escape") {
20
  event.preventDefault();
21
  dispatch("close");
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
22
  }
23
  }
24
 
@@ -43,7 +80,7 @@
43
  );
44
  </script>
45
 
46
- <svelte:window on:keydown={handleKeydown} />
47
 
48
  <div
49
  class="fixed inset-0 z-10 flex h-screen items-start justify-center bg-black/85 pt-32"
@@ -51,7 +88,7 @@
51
  on:click|stopPropagation={handleBackdropClick}
52
  >
53
  <div class="flex w-full max-w-[600px] items-start justify-center p-10 whitespace-nowrap overflow-hidden">
54
- <div class="flex h-full w-full flex-col overflow-hidden rounded-lg border bg-white text-gray-900 shadow-md">
55
  <div class="flex items-center border-b px-3">
56
  <IconSearch classNames="mr-2 text-sm" />
57
  <input
@@ -65,10 +102,13 @@
65
  <div class="p-1">
66
  <div class="px-2 py-1.5 text-xs font-medium text-gray-500">Trending</div>
67
  <div>
68
- {#each featuredModels as model}
69
  {@const [nameSpace, modelName] = model.id.split("/")}
70
  <button
71
- class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm hover:bg-gray-100"
 
 
 
72
  on:click={() => {
73
  dispatch("modelSelected", model.id);
74
  dispatch("close");
@@ -88,10 +128,14 @@
88
  <div class="p-1">
89
  <div class="px-2 py-1.5 text-xs font-medium text-gray-500">Other Models</div>
90
  <div>
91
- {#each otherModels as model}
92
  {@const [nameSpace, modelName] = model.id.split("/")}
 
93
  <button
94
- class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm hover:bg-gray-100"
 
 
 
95
  on:click={() => {
96
  dispatch("modelSelected", model.id);
97
  dispatch("close");
 
1
  <script lang="ts">
2
  import type { ModelEntryWithTokenizer } from "./types";
3
 
4
+ import { createEventDispatcher, tick } from "svelte";
5
 
6
  import { FEATUED_MODELS_IDS } from "./inferencePlaygroundUtils";
7
  import IconSearch from "../Icons/IconSearch.svelte";
 
11
 
12
  let backdropEl: HTMLDivElement;
13
  let query = "";
14
+ let highlightIdx = 0;
15
+ let ignoreCursorHighlight = false;
16
+ let containerEl: HTMLDivElement;
17
 
18
  const dispatch = createEventDispatcher<{ modelSelected: string; close: void }>();
19
 
20
  function handleKeydown(event: KeyboardEvent) {
21
  const { key } = event;
22
+ let scrollLogicalPosition: ScrollLogicalPosition = "end";
23
  if (key === "Escape") {
24
  event.preventDefault();
25
  dispatch("close");
26
+ } else if (key === "Enter") {
27
+ const searchEls = (containerEl.firstChild?.childNodes ?? []) as HTMLAnchorElement[];
28
+ searchEls?.[highlightIdx].click();
29
+ } else if (key === "ArrowUp") {
30
+ event.preventDefault();
31
+ highlightIdx--;
32
+ scrollLogicalPosition = "start";
33
+ ignoreCursorHighlight = true;
34
+ } else if (key === "ArrowDown") {
35
+ event.preventDefault();
36
+ highlightIdx++;
37
+ ignoreCursorHighlight = true;
38
+ }
39
+ const n = models.length;
40
+ highlightIdx = ((highlightIdx % n) + n) % n;
41
+ scrollToResult(scrollLogicalPosition);
42
+ }
43
+
44
+ async function scrollToResult(block: ScrollLogicalPosition) {
45
+ await tick();
46
+ const highlightedEl = document.querySelector(".highlighted");
47
+ if (containerEl && highlightedEl) {
48
+ const { bottom: containerBottom, top: containerTop } = containerEl.getBoundingClientRect();
49
+ const { bottom: highlightedBottom, top: highlightedTop } = highlightedEl.getBoundingClientRect();
50
+ if (highlightedBottom > containerBottom || containerTop > highlightedTop) {
51
+ highlightedEl.scrollIntoView({ block });
52
+ }
53
+ }
54
+ }
55
+
56
+ function highlightRow(idx: number) {
57
+ if (!ignoreCursorHighlight) {
58
+ highlightIdx = idx;
59
  }
60
  }
61
 
 
80
  );
81
  </script>
82
 
83
+ <svelte:window on:keydown={handleKeydown} on:mousemove={() => (ignoreCursorHighlight = false)} />
84
 
85
  <div
86
  class="fixed inset-0 z-10 flex h-screen items-start justify-center bg-black/85 pt-32"
 
88
  on:click|stopPropagation={handleBackdropClick}
89
  >
90
  <div class="flex w-full max-w-[600px] items-start justify-center p-10 whitespace-nowrap overflow-hidden">
91
+ <div class="flex h-full w-full flex-col overflow-hidden rounded-lg border bg-white text-gray-900 shadow-md" bind:this={containerEl}>
92
  <div class="flex items-center border-b px-3">
93
  <IconSearch classNames="mr-2 text-sm" />
94
  <input
 
102
  <div class="p-1">
103
  <div class="px-2 py-1.5 text-xs font-medium text-gray-500">Trending</div>
104
  <div>
105
+ {#each featuredModels as model, idx}
106
  {@const [nameSpace, modelName] = model.id.split("/")}
107
  <button
108
+ class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm {highlightIdx === idx
109
+ ? 'highlighted bg-gray-100'
110
+ : ''}"
111
+ on:mouseenter={() => highlightRow(idx)}
112
  on:click={() => {
113
  dispatch("modelSelected", model.id);
114
  dispatch("close");
 
128
  <div class="p-1">
129
  <div class="px-2 py-1.5 text-xs font-medium text-gray-500">Other Models</div>
130
  <div>
131
+ {#each otherModels as model, _idx}
132
  {@const [nameSpace, modelName] = model.id.split("/")}
133
+ {@const idx = featuredModels.length + _idx}
134
  <button
135
+ class="flex w-full cursor-pointer items-center px-2 py-1.5 text-sm {highlightIdx === idx
136
+ ? 'highlighted bg-gray-100'
137
+ : ''}"
138
+ on:mouseenter={() => highlightRow(idx)}
139
  on:click={() => {
140
  dispatch("modelSelected", model.id);
141
  dispatch("close");