This commit is contained in:
Timothy Jaeryang Baek
2026-03-23 23:39:52 -05:00
parent 3a4b862e81
commit 139e764b2f
45 changed files with 6251 additions and 5730 deletions
+6 -2
View File
@@ -132,7 +132,7 @@
if (event.key === 'Escape' && show) {
show = false;
onOpenChange(false);
}
}
}
/** Close the dropdown programmatically */
@@ -155,7 +155,11 @@
});
</script>
<svelte:window on:keydown={handleKeydown} on:scroll|capture={positionContent} on:resize={positionContent} />
<svelte:window
on:keydown={handleKeydown}
on:scroll|capture={positionContent}
on:resize={positionContent}
/>
<!-- svelte-ignore a11y-click-events-have-key-events -->
<!-- svelte-ignore a11y-no-static-element-interactions -->
+4 -3
View File
@@ -3,7 +3,8 @@
import { tick } from 'svelte';
/** CSS classes for the sub-content container */
export let contentClass = 'select-none rounded-2xl p-1 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-100 dark:border-gray-800';
export let contentClass =
'select-none rounded-2xl p-1 z-50 bg-white dark:bg-gray-850 dark:text-white shadow-lg border border-gray-100 dark:border-gray-800';
/** Max width in px, enforced at the component level */
export let maxWidth = 200;
@@ -48,12 +49,12 @@
// Vertical positioning with robust bounds clamping (shift method)
const contentHeight = contentEl.offsetHeight || 0;
let top = rect.top;
// If it overflows the bottom edge
if (top + contentHeight + 16 > window.innerHeight) {
top = window.innerHeight - contentHeight - 16;
}
// If shifting it up causes it to overflow the top edge, cap it at 16px
if (top < 16) {
top = 16;
+4 -1
View File
@@ -155,7 +155,10 @@
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' : ''}"
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
+13 -7
View File
@@ -829,11 +829,7 @@
// Only show on empty paragraphs at root depth
return (
view.hasFocus() &&
empty &&
isRootDepth &&
isEmptyTextBlock &&
editor.isEditable
view.hasFocus() && empty && isRootDepth && isEmptyTextBlock && editor.isEditable
);
}
})
@@ -1275,11 +1271,21 @@
</script>
{#if richText && showFormattingToolbar}
<div bind:this={bubbleMenuElement} id="bubble-menu" class="p-0" style="visibility: hidden; opacity: 0; position: absolute; z-index: 9999;">
<div
bind:this={bubbleMenuElement}
id="bubble-menu"
class="p-0"
style="visibility: hidden; opacity: 0; position: absolute; z-index: 9999;"
>
<FormattingButtons {editor} />
</div>
<div bind:this={floatingMenuElement} id="floating-menu" class="p-0" style="visibility: hidden; opacity: 0; position: absolute; z-index: 9999;">
<div
bind:this={floatingMenuElement}
id="floating-menu"
class="p-0"
style="visibility: hidden; opacity: 0; position: absolute; z-index: 9999;"
>
<FormattingButtons {editor} />
</div>
{/if}
+12 -14
View File
@@ -21,10 +21,12 @@
export let labelClass = '';
/** CSS classes for the dropdown content container */
export let contentClass = 'rounded-2xl min-w-[170px] p-1 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 dark:text-white shadow-lg';
export let contentClass =
'rounded-2xl min-w-[170px] p-1 border border-gray-100 dark:border-gray-800 bg-white dark:bg-gray-850 dark:text-white shadow-lg';
/** CSS classes for each item button */
export let itemClass = 'flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl';
export let itemClass =
'flex w-full gap-2 items-center px-3 py-1.5 text-sm cursor-pointer hover:bg-gray-50 dark:hover:bg-gray-800 rounded-xl';
/** Alignment of the dropdown: 'start' | 'end' */
export let align = 'start';
@@ -99,7 +101,12 @@
}
</script>
<svelte:window on:click={handleWindowClick} on:keydown={handleKeydown} on:scroll|capture={positionContent} on:resize={positionContent} />
<svelte:window
on:click={handleWindowClick}
on:keydown={handleKeydown}
on:scroll|capture={positionContent}
on:resize={positionContent}
/>
<button
bind:this={triggerEl}
@@ -116,19 +123,10 @@
</button>
{#if open}
<div
use:portal
bind:this={contentEl}
class={contentClass}
transition:flyAndScale
>
<div use:portal bind:this={contentEl} class={contentClass} transition:flyAndScale>
<slot {open} {selectItem}>
{#each items as item}
<button
class={itemClass}
type="button"
on:click={() => selectItem(item)}
>
<button class={itemClass} type="button" on:click={() => selectItem(item)}>
<slot name="item" {item} selected={value === item.value}>
{item.label}
</slot>
+3 -3
View File
@@ -1,6 +1,4 @@
<script lang="ts">
import ChevronDown from '../icons/ChevronDown.svelte';
import Check from '../icons/Check.svelte';
import Search from '../icons/Search.svelte';
@@ -34,7 +32,9 @@
{placeholder}
triggerClass="relative w-full"
contentClass="w-full rounded-lg bg-white dark:bg-gray-900 dark:text-white shadow-lg border border-gray-300/30 dark:border-gray-700/40 outline-hidden"
onClose={() => { searchValue = ''; }}
onClose={() => {
searchValue = '';
}}
>
<svelte:fragment slot="trigger" let:selectedLabel>
<span