Merge pull request #372 from nielthiart/prompt-typeahead

Add typeahead prompt selector with fuzzy search on titles
This commit is contained in:
Niek van der Maas 2023-12-22 11:18:08 +01:00 committed by GitHub
commit 9c3dbd5587
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 118 additions and 22 deletions

49
package-lock.json generated
View File

@ -17,12 +17,14 @@
"@sveltejs/vite-plugin-svelte": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^2.5.2",
"@tauri-apps/cli": "^1.5.8", "@tauri-apps/cli": "^1.5.8",
"@tsconfig/svelte": "^5.0.0", "@tsconfig/svelte": "^5.0.0",
"@types/dompurify": "^3.0.5",
"@types/marked": "^6.0.0", "@types/marked": "^6.0.0",
"@types/node": "^20.10.3", "@types/node": "^20.10.3",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"bulma-prefers-dark": "^0.1.0-beta.1", "bulma-prefers-dark": "^0.1.0-beta.1",
"copy-to-clipboard": "^3.3.3", "copy-to-clipboard": "^3.3.3",
"dexie": "^4.0.1-beta.5", "dexie": "^4.0.1-beta.5",
"dompurify": "^3.0.6",
"eslint-config-standard-with-typescript": "^35.0.0", "eslint-config-standard-with-typescript": "^35.0.0",
"eslint-plugin-svelte3": "^4.0.0", "eslint-plugin-svelte3": "^4.0.0",
"flourite": "^1.2.4", "flourite": "^1.2.4",
@ -39,6 +41,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",
@ -912,6 +915,15 @@
"integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==", "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==",
"dev": true "dev": true
}, },
"node_modules/@types/dompurify": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.5.tgz",
"integrity": "sha512-1Wg0g3BtQF7sSb27fJQAKck1HECM6zV1EB66j8JH9i3LCjYabJa0FSdiSgsD5K/RbrsR0SiraKacLB+T8ZVYAg==",
"dev": true,
"dependencies": {
"@types/trusted-types": "*"
}
},
"node_modules/@types/estree": { "node_modules/@types/estree": {
"version": "1.0.5", "version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz",
@ -964,6 +976,12 @@
"dev": true, "dev": true,
"peer": true "peer": true
}, },
"node_modules/@types/trusted-types": {
"version": "2.0.7",
"resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
"integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "5.62.0", "version": "5.62.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
@ -1728,6 +1746,12 @@
"node": ">=6.0.0" "node": ">=6.0.0"
} }
}, },
"node_modules/dompurify": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.0.6.tgz",
"integrity": "sha512-ilkD8YEnnGh1zJ240uJsW7AzE+2qpbOUYjacomn3AvJ6J4JhKGSZ2nh4wUIXPZrEPppaCLx5jFe8T89Rk8tQ7w==",
"dev": true
},
"node_modules/es-abstract": { "node_modules/es-abstract": {
"version": "1.22.3", "version": "1.22.3",
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz",
@ -2566,6 +2590,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",
@ -4493,6 +4526,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",
@ -4505,6 +4544,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",

View File

@ -23,12 +23,14 @@
"@sveltejs/vite-plugin-svelte": "^2.5.2", "@sveltejs/vite-plugin-svelte": "^2.5.2",
"@tauri-apps/cli": "^1.5.8", "@tauri-apps/cli": "^1.5.8",
"@tsconfig/svelte": "^5.0.0", "@tsconfig/svelte": "^5.0.0",
"@types/dompurify": "^3.0.5",
"@types/marked": "^6.0.0", "@types/marked": "^6.0.0",
"@types/node": "^20.10.3", "@types/node": "^20.10.3",
"bulma": "^0.9.4", "bulma": "^0.9.4",
"bulma-prefers-dark": "^0.1.0-beta.1", "bulma-prefers-dark": "^0.1.0-beta.1",
"copy-to-clipboard": "^3.3.3", "copy-to-clipboard": "^3.3.3",
"dexie": "^4.0.1-beta.5", "dexie": "^4.0.1-beta.5",
"dompurify": "^3.0.6",
"eslint-config-standard-with-typescript": "^35.0.0", "eslint-config-standard-with-typescript": "^35.0.0",
"eslint-plugin-svelte3": "^4.0.0", "eslint-plugin-svelte3": "^4.0.0",
"flourite": "^1.2.4", "flourite": "^1.2.4",
@ -45,6 +47,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",

View File

@ -264,6 +264,46 @@ $modal-background-background-color-dark: rgba($dark, 0.86) !default; // remove t
} }
} }
[data-svelte-typeahead] {
display: flex;
background-color: transparent !important;
&[aria-expanded="true"] {
z-index: 3;
ul.svelte-typeahead-list {
@extend .dropdown-content;
max-height: 60vh;
overflow: auto;
> li {
padding: 0;
border-bottom: 0 none;
&.selected {
@media (prefers-color-scheme: dark) {
background-color: #2a2a2a;
}
}
}
}
}
[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 {

View File

@ -1,39 +1,42 @@
<script lang="ts"> <script lang="ts">
import DOMPurify from 'dompurify'
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}">
<!--
Sanitize result.string because Typeahead introduces HTML tags and prompt
strings are untrusted.
-->
{@html DOMPurify.sanitize(result.string, { ALLOWED_TAGS: ['mark'] })}
</a> </a>
{/each} </Typeahead>
</div>
</div>
</div>
</div> </div>
</div> </div>

View File

@ -5,7 +5,8 @@
"useDefineForClassFields": true, "useDefineForClassFields": true,
"module": "ESNext", "module": "ESNext",
"resolveJsonModule": true, "resolveJsonModule": true,
"strictNullChecks": true "strictNullChecks": true,
"allowSyntheticDefaultImports": true
}, },
"include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "vite.config.ts", "svelte.config.js"], "include": ["src/**/*.d.ts", "src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "vite.config.ts", "svelte.config.js"],
"references": [{ "path": "./tsconfig.node.json" }] "references": [{ "path": "./tsconfig.node.json" }]