Add typeahead prompt selector with fuzzy search on titles

This replaces the prompt dropdown button with a fuzzy search input to filter prompts. Uses [svelte-typeahead](https://metonym.github.io/svelte-typeahead/).
This commit is contained in:
Niel Thiart
2023-12-05 15:38:48 +02:00
parent e2027a3d27
commit 76fd31ef9e
4 changed files with 78 additions and 21 deletions

View File

@@ -264,6 +264,38 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
}
}
[data-svelte-typeahead] {
display: flex;
ul.svelte-typeahead-list {
max-height: calc(60vh);
overflow: auto;
> li:not(:last-of-type) {
padding: 0;
border-bottom: 0 none;
}
}
&[aria-expanded="true"] {
z-index: 3;
}
[data-svelte-search] {
flex: 1;
input {
@extend .button;
@extend .default-text;
text-align: center;
&::placeholder {
@extend .default-text;
}
}
}
}
/* Bulma layout hacks */
.chat-option-menu.navbar-item {

View File

@@ -1,39 +1,37 @@
<script lang="ts">
import Typeahead from 'svelte-typeahead'
import prompts from '../awesome-chatgpt-prompts/prompts.csv'
const inputPrompt = (prompt: string) => {
input.value = prompt
input.style.height = 'auto'
input.style.height = input.scrollHeight + 'px'
active = false
}
export let input : HTMLTextAreaElement
const extract = (prompt: typeof prompts[0]) => prompt.act
let active: boolean = false
export let input : HTMLTextAreaElement
</script>
{#if input}
<div class="columns is-centered">
<div class="column is-half">
<div class="dropdown is-fullwidth" class:is-active={active}>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<div class="dropdown-trigger" on:click={() => { active = !active }}>
<button class="button is-fullwidth" aria-haspopup="true" aria-controls="dropdown-menu">
<span>Select a pre-made prompt</span>
<span class="icon is-small">👇</span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
{#each prompts as prompt}
<a title={prompt.prompt} class="dropdown-item" href={'#'} on:click|preventDefault={() => inputPrompt(prompt.prompt)}>
{prompt.act}
</a>
{/each}
</div>
</div>
</div>
<Typeahead
data={prompts}
{extract}
label="Select a pre-made prompt"
hideLabel
showDropdownOnFocus
showAllResultsOnFocus
inputAfterSelect="clear"
on:select={({ detail }) => inputPrompt(detail.original.prompt)}
placeholder="Select a pre-made prompt 👇"
let:result
>
<a class="dropdown-item" href="#top" on:click|preventDefault title="{result.original.prompt}">
{@html result.string}
</a>
</Typeahead>
</div>
</div>