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:
parent
e2027a3d27
commit
76fd31ef9e
|
@ -39,6 +39,7 @@
|
||||||
"svelte-markdown": "^0.2.3",
|
"svelte-markdown": "^0.2.3",
|
||||||
"svelte-modals": "^1.2.1",
|
"svelte-modals": "^1.2.1",
|
||||||
"svelte-spa-router": "^3.3.0",
|
"svelte-spa-router": "^3.3.0",
|
||||||
|
"svelte-typeahead": "^4.4.1",
|
||||||
"svelte-use-click-outside": "^1.0.0",
|
"svelte-use-click-outside": "^1.0.0",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
|
@ -2576,6 +2577,15 @@
|
||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/fuzzy": {
|
||||||
|
"version": "0.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/fuzzy/-/fuzzy-0.1.3.tgz",
|
||||||
|
"integrity": "sha512-/gZffu4ykarLrCiP3Ygsa86UAo1E5vEVlvTrpkKywXSbP9Xhln3oSp9QSV57gEq3JFFpGJ4GZ+5zdEp3FcUh4w==",
|
||||||
|
"dev": true,
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/get-intrinsic": {
|
"node_modules/get-intrinsic": {
|
||||||
"version": "1.2.2",
|
"version": "1.2.2",
|
||||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz",
|
||||||
|
@ -4514,6 +4524,12 @@
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-search": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-search/-/svelte-search-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-e5hci9fZPMXb3fuRZvcYJGqh448M8vV3biY4lN4Nr9fqrG/HBnTjWYstKb399aUe9tsBxRbxRAWgtKicisL23g==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
"node_modules/svelte-spa-router": {
|
"node_modules/svelte-spa-router": {
|
||||||
"version": "3.3.0",
|
"version": "3.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-spa-router/-/svelte-spa-router-3.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-spa-router/-/svelte-spa-router-3.3.0.tgz",
|
||||||
|
@ -4526,6 +4542,16 @@
|
||||||
"url": "https://github.com/sponsors/ItalyPaleAle"
|
"url": "https://github.com/sponsors/ItalyPaleAle"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/svelte-typeahead": {
|
||||||
|
"version": "4.4.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/svelte-typeahead/-/svelte-typeahead-4.4.1.tgz",
|
||||||
|
"integrity": "sha512-U8EYkCQ1HaDrQq1fnkVCEm8emZrdEfgfHhMulgOdoYnWV5PTvypiwCTNvqqxFHbz9ZGe5juAR9ok5tEcfnP9zw==",
|
||||||
|
"dev": true,
|
||||||
|
"dependencies": {
|
||||||
|
"fuzzy": "0.1.3",
|
||||||
|
"svelte-search": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/svelte-use-click-outside": {
|
"node_modules/svelte-use-click-outside": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/svelte-use-click-outside/-/svelte-use-click-outside-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/svelte-use-click-outside/-/svelte-use-click-outside-1.0.0.tgz",
|
||||||
|
|
|
@ -45,6 +45,7 @@
|
||||||
"svelte-markdown": "^0.2.3",
|
"svelte-markdown": "^0.2.3",
|
||||||
"svelte-modals": "^1.2.1",
|
"svelte-modals": "^1.2.1",
|
||||||
"svelte-spa-router": "^3.3.0",
|
"svelte-spa-router": "^3.3.0",
|
||||||
|
"svelte-typeahead": "^4.4.1",
|
||||||
"svelte-use-click-outside": "^1.0.0",
|
"svelte-use-click-outside": "^1.0.0",
|
||||||
"tslib": "^2.6.2",
|
"tslib": "^2.6.2",
|
||||||
"typescript": "^5.0.4",
|
"typescript": "^5.0.4",
|
||||||
|
|
32
src/app.scss
32
src/app.scss
|
@ -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 */
|
/* Bulma layout hacks */
|
||||||
|
|
||||||
.chat-option-menu.navbar-item {
|
.chat-option-menu.navbar-item {
|
||||||
|
|
|
@ -1,39 +1,37 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
|
import Typeahead from 'svelte-typeahead'
|
||||||
import prompts from '../awesome-chatgpt-prompts/prompts.csv'
|
import prompts from '../awesome-chatgpt-prompts/prompts.csv'
|
||||||
|
|
||||||
const inputPrompt = (prompt: string) => {
|
const inputPrompt = (prompt: string) => {
|
||||||
input.value = prompt
|
input.value = prompt
|
||||||
input.style.height = 'auto'
|
input.style.height = 'auto'
|
||||||
input.style.height = input.scrollHeight + 'px'
|
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>
|
</script>
|
||||||
|
|
||||||
{#if input}
|
{#if input}
|
||||||
<div class="columns is-centered">
|
<div class="columns is-centered">
|
||||||
<div class="column is-half">
|
<div class="column is-half">
|
||||||
<div class="dropdown is-fullwidth" class:is-active={active}>
|
<Typeahead
|
||||||
<!-- svelte-ignore a11y-click-events-have-key-events -->
|
data={prompts}
|
||||||
<div class="dropdown-trigger" on:click={() => { active = !active }}>
|
{extract}
|
||||||
<button class="button is-fullwidth" aria-haspopup="true" aria-controls="dropdown-menu">
|
label="Select a pre-made prompt"
|
||||||
<span>Select a pre-made prompt</span>
|
hideLabel
|
||||||
<span class="icon is-small">👇</span>
|
showDropdownOnFocus
|
||||||
</button>
|
showAllResultsOnFocus
|
||||||
</div>
|
inputAfterSelect="clear"
|
||||||
<div class="dropdown-menu" id="dropdown-menu" role="menu">
|
on:select={({ detail }) => inputPrompt(detail.original.prompt)}
|
||||||
<div class="dropdown-content">
|
placeholder="Select a pre-made prompt 👇"
|
||||||
{#each prompts as prompt}
|
let:result
|
||||||
<a title={prompt.prompt} class="dropdown-item" href={'#'} on:click|preventDefault={() => inputPrompt(prompt.prompt)}>
|
>
|
||||||
{prompt.act}
|
<a class="dropdown-item" href="#top" on:click|preventDefault title="{result.original.prompt}">
|
||||||
|
{@html result.string}
|
||||||
</a>
|
</a>
|
||||||
{/each}
|
</Typeahead>
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue