refac
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
<script lang="ts">
|
||||
import { flyAndScale } from '$lib/utils/transitions';
|
||||
import { tick } from 'svelte';
|
||||
import { createEventDispatcher, tick } from 'svelte';
|
||||
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
/** Whether the dropdown is open */
|
||||
export let show = false;
|
||||
@@ -104,6 +106,7 @@
|
||||
async function toggleOpen() {
|
||||
show = !show;
|
||||
onOpenChange(show);
|
||||
dispatch('change', show);
|
||||
if (show) {
|
||||
await tick();
|
||||
positionContent();
|
||||
@@ -126,12 +129,14 @@
|
||||
if (contentEl?.contains(event.target)) return;
|
||||
show = false;
|
||||
onOpenChange(false);
|
||||
dispatch('change', false);
|
||||
}
|
||||
|
||||
function handleKeydown(event) {
|
||||
if (event.key === 'Escape' && show) {
|
||||
show = false;
|
||||
onOpenChange(false);
|
||||
dispatch('change', false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -139,6 +144,7 @@
|
||||
export function close() {
|
||||
show = false;
|
||||
onOpenChange(false);
|
||||
dispatch('change', false);
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
@@ -1,12 +1,11 @@
|
||||
<script lang="ts">
|
||||
import { DropdownMenu } from 'bits-ui';
|
||||
import VirtualList from '@sveltejs/svelte-virtual-list';
|
||||
|
||||
import { getContext } from 'svelte';
|
||||
|
||||
import { flyAndScale } from '$lib/utils/transitions';
|
||||
import { WEBUI_BASE_URL } from '$lib/constants';
|
||||
|
||||
import Dropdown from '$lib/components/common/Dropdown.svelte';
|
||||
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||
|
||||
import emojiGroups from '$lib/emoji-groups.json';
|
||||
@@ -107,79 +106,74 @@
|
||||
}
|
||||
</script>
|
||||
|
||||
<DropdownMenu.Root
|
||||
bind:open={show}
|
||||
closeFocus={false}
|
||||
onOpenChange={(state) => {
|
||||
if (!state) {
|
||||
<Dropdown
|
||||
bind:show
|
||||
{align}
|
||||
on:change={(e) => {
|
||||
if (e.detail === false) {
|
||||
search = '';
|
||||
onClose();
|
||||
}
|
||||
}}
|
||||
typeahead={false}
|
||||
>
|
||||
<DropdownMenu.Trigger>
|
||||
<slot />
|
||||
</DropdownMenu.Trigger>
|
||||
<DropdownMenu.Content
|
||||
class="max-w-full w-80 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 rounded-3xl z-9999 shadow-lg dark:text-white"
|
||||
sideOffset={8}
|
||||
{side}
|
||||
{align}
|
||||
transition={flyAndScale}
|
||||
>
|
||||
<div class="mb-1 px-4 pt-2.5 pb-2">
|
||||
<input
|
||||
type="text"
|
||||
class="w-full text-sm bg-transparent outline-hidden"
|
||||
placeholder={$i18n.t('Search all emojis')}
|
||||
bind:value={search}
|
||||
/>
|
||||
</div>
|
||||
<slot />
|
||||
|
||||
<div slot="content">
|
||||
<div
|
||||
class="max-w-full w-80 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 rounded-3xl z-9999 shadow-lg dark:text-white"
|
||||
>
|
||||
<div class="mb-1 px-4 pt-2.5 pb-2">
|
||||
<input
|
||||
type="text"
|
||||
class="w-full text-sm bg-transparent outline-hidden"
|
||||
placeholder={$i18n.t('Search all emojis')}
|
||||
bind:value={search}
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Virtualized Emoji List -->
|
||||
<div class="w-full flex justify-start h-96 overflow-y-auto px-3 pb-3 text-sm">
|
||||
{#if emojiRows.length === 0}
|
||||
<div class="text-center text-xs text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('No results')}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-full flex ml-0.5">
|
||||
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
|
||||
<div class="w-full">
|
||||
{#if item.length === 1 && item[0].type === 'group'}
|
||||
<!-- Render group header -->
|
||||
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
|
||||
{item[0].label}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Render emojis in a row -->
|
||||
<div class="flex items-center gap-1.5 w-full">
|
||||
{#each item as emojiItem}
|
||||
<Tooltip
|
||||
content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
|
||||
placement="top"
|
||||
>
|
||||
<button
|
||||
class="p-1.5 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition {selected === emojiItem.shortCodes[0] ? 'bg-gray-200 dark:bg-gray-700' : ''}"
|
||||
on:click={() => selectEmoji(emojiItem)}
|
||||
<!-- Virtualized Emoji List -->
|
||||
<div class="w-full flex justify-start h-96 overflow-y-auto px-3 pb-3 text-sm">
|
||||
{#if emojiRows.length === 0}
|
||||
<div class="text-center text-xs text-gray-500 dark:text-gray-400">
|
||||
{$i18n.t('No results')}
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-full flex ml-0.5">
|
||||
<VirtualList rowHeight={ROW_HEIGHT} items={emojiRows} height={384} let:item>
|
||||
<div class="w-full">
|
||||
{#if item.length === 1 && item[0].type === 'group'}
|
||||
<!-- Render group header -->
|
||||
<div class="text-xs font-medium mb-2 text-gray-500 dark:text-gray-400">
|
||||
{item[0].label}
|
||||
</div>
|
||||
{:else}
|
||||
<!-- Render emojis in a row -->
|
||||
<div class="flex items-center gap-1.5 w-full">
|
||||
{#each item as emojiItem}
|
||||
<Tooltip
|
||||
content={emojiItem.shortCodes.map((code) => `:${code}:`).join(', ')}
|
||||
placement="top"
|
||||
>
|
||||
<img
|
||||
src="{WEBUI_BASE_URL}/assets/emojis/{emojiItem.name.toLowerCase()}.svg"
|
||||
alt={emojiItem.name}
|
||||
class="size-5"
|
||||
loading="lazy"
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</VirtualList>
|
||||
</div>
|
||||
{/if}
|
||||
<button
|
||||
class="p-1.5 rounded-lg cursor-pointer hover:bg-gray-200 dark:hover:bg-gray-700 transition {selected === emojiItem.shortCodes[0] ? 'bg-gray-200 dark:bg-gray-700' : ''}"
|
||||
on:click={() => selectEmoji(emojiItem)}
|
||||
>
|
||||
<img
|
||||
src="{WEBUI_BASE_URL}/assets/emojis/{emojiItem.name.toLowerCase()}.svg"
|
||||
alt={emojiItem.name}
|
||||
class="size-5"
|
||||
loading="lazy"
|
||||
/>
|
||||
</button>
|
||||
</Tooltip>
|
||||
{/each}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</VirtualList>
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
</div>
|
||||
</DropdownMenu.Content>
|
||||
</DropdownMenu.Root>
|
||||
</div>
|
||||
</Dropdown>
|
||||
|
||||
Reference in New Issue
Block a user