This commit is contained in:
Simon Cambier 2023-10-31 07:05:32 +01:00
parent e7125bc07a
commit 327d3f77b8
6 changed files with 103 additions and 28 deletions

View File

@ -34,6 +34,7 @@
}, },
"type": "module", "type": "module",
"dependencies": { "dependencies": {
"@svelte-put/clickoutside": "^3.0.0",
"@sveltejs/adapter-static": "^2.0.3", "@sveltejs/adapter-static": "^2.0.3",
"brotli-compress": "^1.3.3", "brotli-compress": "^1.3.3",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",

View File

@ -5,6 +5,9 @@ settings:
excludeLinksFromLockfile: false excludeLinksFromLockfile: false
dependencies: dependencies:
'@svelte-put/clickoutside':
specifier: ^3.0.0
version: 3.0.0
'@sveltejs/adapter-static': '@sveltejs/adapter-static':
specifier: ^2.0.3 specifier: ^2.0.3
version: 2.0.3(@sveltejs/kit@1.20.4) version: 2.0.3(@sveltejs/kit@1.20.4)
@ -400,6 +403,10 @@ packages:
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==} resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
dev: false dev: false
/@svelte-put/clickoutside@3.0.0:
resolution: {integrity: sha512-a2aA0+uMo2LGK4bwQE+etra57cJuqQsXRkI0IM+cPzjIowqUg5CMSSeQ6YsXBJUdtzm/s6WQKcmoswK/875wtA==}
dev: false
/@sveltejs/adapter-auto@2.0.0(@sveltejs/kit@1.20.4): /@sveltejs/adapter-auto@2.0.0(@sveltejs/kit@1.20.4):
resolution: {integrity: sha512-b+gkHFZgD771kgV3aO4avHFd7y1zhmMYy9i6xOK7m/rwmwaRO8gnF5zBc0Rgca80B2PMU1bKNxyBTHA14OzUAQ==} resolution: {integrity: sha512-b+gkHFZgD771kgV3aO4avHFd7y1zhmMYy9i6xOK7m/rwmwaRO8gnF5zBc0Rgca80B2PMU1bKNxyBTHA14OzUAQ==}
peerDependencies: peerDependencies:

View File

@ -11,8 +11,7 @@
npm/bootstrap@4.6.1/dist/css/bootstrap-grid.min.css, npm/bootstrap@4.6.1/dist/css/bootstrap-grid.min.css,
npm/codemirror@5.65.5/lib/codemirror.min.css, npm/codemirror@5.65.5/lib/codemirror.min.css,
npm/codemirror@5.65.5/addon/scroll/simplescrollbars.css, npm/codemirror@5.65.5/addon/scroll/simplescrollbars.css,
npm/codemirror@5.65.5/theme/dracula.min.css, npm/codemirror@5.65.5/theme/dracula.min.css"
npm/microtip@0.2.2/microtip.min.css"
/> />
<meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head% %sveltekit.head%
@ -22,8 +21,6 @@ npm/microtip@0.2.2/microtip.min.css"
<script src="https://cdn.jsdelivr.net/combine/ <script src="https://cdn.jsdelivr.net/combine/
npm/lzma@2.3.2/src/lzma.min.js, npm/lzma@2.3.2/src/lzma.min.js,
npm/clipboard@2.0.11/dist/clipboard.min.js,
npm/micromodal@0.4.10/dist/micromodal.min.js,
npm/codemirror@5.65.5, npm/codemirror@5.65.5,
npm/codemirror@5.65.5/addon/mode/loadmode.min.js, npm/codemirror@5.65.5/addon/mode/loadmode.min.js,
npm/codemirror@5.65.5/addon/mode/overlay.min.js, npm/codemirror@5.65.5/addon/mode/overlay.min.js,

View File

@ -0,0 +1,90 @@
<script lang="ts">
import { clickoutside } from '@svelte-put/clickoutside'
import { onMount, tick } from 'svelte'
type Item = { text: string }
export let value: Item | null = null
export let items: Item[]
let filteredItems: Item[] = []
let inputFilter: HTMLInputElement | null = null
let filter = ''
let divContainer: HTMLDivElement | null = null
let areOptionsVisible = false
$: {
if (filter) {
filteredItems = items.filter((item) => item.text.toLowerCase().includes(filter.toLowerCase()))
} else {
filteredItems = [...items]
}
}
$: {
// Watch filter value
if (filter) {
tick().then(() => {
if (divContainer) {
if (divContainer.scrollHeight > divContainer.clientHeight) {
divContainer.classList.add('h-96')
} else {
divContainer.classList.remove('h-96')
}
}
})
}
}
function showOptions() {
// Add a delay so that the click outside event doesn't trigger too soon
setTimeout(() => {
areOptionsVisible = true
tick().then(() => inputFilter?.select())
}, 0)
setTimeout(() => {}, 100)
}
function hideOptions() {
areOptionsVisible = false
}
function selectItem(item: Item) {
value = item
hideOptions()
}
</script>
<div class="relative" use:clickoutside on:clickoutside={hideOptions}>
{#if areOptionsVisible}
<input
type="text"
bind:value={filter}
bind:this={inputFilter}
class={$$restProps.class ?? ''}
/>
<div
class="absolute top-full left-0 w-full bg-gray-700 max-h-[90vh] overflow-y-auto"
bind:this={divContainer}
>
{#each filteredItems as item}
<div class="p-1 hover:bg-gray-600" on:click={() => selectItem(item)}>{item.text}</div>
{/each}
</div>
{:else}
<input
type="text"
readonly
value={value?.text ?? ''}
class={$$restProps.class ?? ''}
on:click={showOptions}
/>
{/if}
</div>
<style lang="scss">
select {
appearance: none;
}
</style>

View File

@ -1,20 +0,0 @@
<script lang="ts">
type Item = { text: string }
export let value: Item | null = null
export let items: Item[]
</script>
<select bind:value={value} class={ ($$restProps.class ?? '') }>
{#each items as item}
<option value={item}>
{item.text}
</option>
{/each}
</select>
<style lang="scss">
select {
appearance: none;
}
</style>

View File

@ -1,9 +1,9 @@
<script lang="ts"> <script lang="ts">
import { onMount, tick } from 'svelte' import { onMount, tick } from 'svelte'
import { shorten } from '$lib/utils' import { shorten } from '$lib/utils'
import Select from './Select.svelte'
import type { Editor } from 'codemirror' import type { Editor } from 'codemirror'
import { shareUrl, selectedLang } from '../store' import { shareUrl, selectedLang } from '../store'
import ComboBox from './ComboBox.svelte'
type Language = { type Language = {
text: string text: string
@ -64,11 +64,11 @@
} }
</script> </script>
<div class="flex justify-between p-2 text-sm relative z-10 shadow-md"> <div class="flex justify-between items-center px-3 py-1 text-sm relative z-10 shadow-md">
<div>NoPaste</div> <h1 class="text-xl">NoPaste</h1>
<div class="flex justify-end gap-2"> <div class="flex justify-end gap-2">
<div> <div>
<Select <ComboBox
items={languages} items={languages}
bind:value={selectedLanguage} bind:value={selectedLanguage}
class="bg-gray-700 border border-gray-300 p-1" class="bg-gray-700 border border-gray-300 p-1"