fix: update components to use Svelte 5 snippets and fix editor content loading
- Convert Button component to use snippets instead of slots - Update BaseDropdown and StatusDropdown to use new Button snippet syntax - Add effect to watch for data changes in ComposerCore and update editor content - Fix SVG component usage in Album component for Svelte 5 compatibility 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
e64788962e
commit
639a4a2429
5 changed files with 68 additions and 39 deletions
|
|
@ -165,9 +165,9 @@
|
|||
class:playing={isPlaying}
|
||||
>
|
||||
{#if isPlaying}
|
||||
<PauseIcon />
|
||||
<svelte:component this={PauseIcon} />
|
||||
{:else}
|
||||
<PlayIcon />
|
||||
<svelte:component this={PlayIcon} />
|
||||
{/if}
|
||||
</button>
|
||||
{/if}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
<script lang="ts">
|
||||
import type { Snippet } from 'svelte'
|
||||
import Button from './Button.svelte'
|
||||
import DropdownMenuContainer from './DropdownMenuContainer.svelte'
|
||||
|
||||
|
|
@ -9,6 +10,8 @@
|
|||
dropdownTriggerSize?: 'small' | 'medium' | 'large'
|
||||
class?: string
|
||||
onToggle?: (isOpen: boolean) => void
|
||||
trigger: Snippet
|
||||
dropdown?: Snippet
|
||||
}
|
||||
|
||||
let {
|
||||
|
|
@ -17,7 +20,9 @@
|
|||
isLoading = false,
|
||||
dropdownTriggerSize = 'large',
|
||||
class: className = '',
|
||||
onToggle
|
||||
onToggle,
|
||||
trigger,
|
||||
dropdown
|
||||
}: Props = $props()
|
||||
|
||||
function handleDropdownToggle(e: MouseEvent) {
|
||||
|
|
@ -47,9 +52,9 @@
|
|||
|
||||
<div class="dropdown-container {className}">
|
||||
<div class="dropdown-trigger">
|
||||
<slot name="trigger" />
|
||||
{@render trigger()}
|
||||
|
||||
{#if $$slots.dropdown}
|
||||
{#if dropdown}
|
||||
<Button
|
||||
variant="ghost"
|
||||
iconOnly
|
||||
|
|
@ -59,22 +64,24 @@
|
|||
{isLoading}
|
||||
class="dropdown-toggle"
|
||||
>
|
||||
<svg slot="icon" width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||||
<path
|
||||
d="M3 4.5L6 7.5L9 4.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
{#snippet icon()}
|
||||
<svg width="12" height="12" viewBox="0 0 12 12" fill="none">
|
||||
<path
|
||||
d="M3 4.5L6 7.5L9 4.5"
|
||||
stroke="currentColor"
|
||||
stroke-width="1.5"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
/>
|
||||
</svg>
|
||||
{/snippet}
|
||||
</Button>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
{#if isOpen && $$slots.dropdown}
|
||||
{#if isOpen && dropdown}
|
||||
<DropdownMenuContainer>
|
||||
<slot name="dropdown" />
|
||||
{@render dropdown()}
|
||||
</DropdownMenuContainer>
|
||||
{/if}
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
<script lang="ts">
|
||||
import type { HTMLButtonAttributes } from 'svelte/elements'
|
||||
import type { Snippet } from 'svelte'
|
||||
|
||||
interface Props extends HTMLButtonAttributes {
|
||||
variant?: 'primary' | 'secondary' | 'danger' | 'ghost' | 'text' | 'overlay' | 'danger-text'
|
||||
|
|
@ -12,6 +13,8 @@
|
|||
active?: boolean
|
||||
href?: string
|
||||
class?: string
|
||||
icon?: Snippet
|
||||
children?: Snippet
|
||||
}
|
||||
|
||||
let {
|
||||
|
|
@ -27,6 +30,7 @@
|
|||
type = 'button',
|
||||
href,
|
||||
class: className = '',
|
||||
icon,
|
||||
children,
|
||||
onclick,
|
||||
...restProps
|
||||
|
|
@ -60,8 +64,8 @@
|
|||
})
|
||||
|
||||
// Handle icon slot positioning
|
||||
const hasIcon = $derived(!!$$slots.icon)
|
||||
const hasDefaultSlot = $derived(!!$$slots.default)
|
||||
const hasIcon = $derived(!!icon)
|
||||
const hasDefaultSlot = $derived(!!children)
|
||||
const showSpinner = $derived(loading && !iconOnly)
|
||||
</script>
|
||||
|
||||
|
|
@ -94,21 +98,21 @@
|
|||
|
||||
{#if hasIcon && iconPosition === 'left' && !iconOnly}
|
||||
<span class="btn-icon-wrapper">
|
||||
<slot name="icon" />
|
||||
{@render icon()}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if hasDefaultSlot && !iconOnly}
|
||||
<span class="btn-label">
|
||||
<slot />
|
||||
{@render children()}
|
||||
</span>
|
||||
{:else if iconOnly && hasIcon}
|
||||
<slot name="icon" />
|
||||
{@render icon()}
|
||||
{/if}
|
||||
|
||||
{#if hasIcon && iconPosition === 'right' && !iconOnly}
|
||||
<span class="btn-icon-wrapper">
|
||||
<slot name="icon" />
|
||||
{@render icon()}
|
||||
</span>
|
||||
{/if}
|
||||
</a>
|
||||
|
|
@ -141,21 +145,21 @@
|
|||
|
||||
{#if hasIcon && iconPosition === 'left' && !iconOnly}
|
||||
<span class="btn-icon-wrapper">
|
||||
<slot name="icon" />
|
||||
{@render icon()}
|
||||
</span>
|
||||
{/if}
|
||||
|
||||
{#if hasDefaultSlot && !iconOnly}
|
||||
<span class="btn-label">
|
||||
<slot />
|
||||
{@render children()}
|
||||
</span>
|
||||
{:else if iconOnly && hasIcon}
|
||||
<slot name="icon" />
|
||||
{@render icon()}
|
||||
{/if}
|
||||
|
||||
{#if hasIcon && iconPosition === 'right' && !iconOnly}
|
||||
<span class="btn-icon-wrapper">
|
||||
<slot name="icon" />
|
||||
{@render icon()}
|
||||
</span>
|
||||
{/if}
|
||||
</button>
|
||||
|
|
|
|||
|
|
@ -55,18 +55,21 @@
|
|||
{isLoading}
|
||||
class="status-dropdown"
|
||||
>
|
||||
<Button
|
||||
slot="trigger"
|
||||
variant="primary"
|
||||
buttonSize="large"
|
||||
onclick={handlePrimaryAction}
|
||||
disabled={disabled || isLoading}
|
||||
>
|
||||
{primaryAction.label}
|
||||
</Button>
|
||||
{#snippet trigger()}
|
||||
<Button
|
||||
variant="primary"
|
||||
buttonSize="large"
|
||||
onclick={handlePrimaryAction}
|
||||
disabled={disabled || isLoading}
|
||||
>
|
||||
{#snippet children()}
|
||||
{primaryAction.label}
|
||||
{/snippet}
|
||||
</Button>
|
||||
{/snippet}
|
||||
|
||||
{#if hasDropdownContent}
|
||||
<div slot="dropdown">
|
||||
{#snippet dropdown()}
|
||||
{#if hasDropdownContent}
|
||||
{#each availableActions as action}
|
||||
<DropdownItem onclick={() => handleDropdownAction(action.status)}>
|
||||
{action.label}
|
||||
|
|
@ -85,8 +88,8 @@
|
|||
View on site
|
||||
</a>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
{/if}
|
||||
{/snippet}
|
||||
</BaseDropdown>
|
||||
|
||||
<style lang="scss">
|
||||
|
|
|
|||
|
|
@ -71,6 +71,7 @@
|
|||
let element = $state<HTMLElement>()
|
||||
let isLoading = $state(true)
|
||||
let initialized = false
|
||||
let contentLoaded = false
|
||||
const mediaSelectionState = $derived($mediaSelectionStore)
|
||||
|
||||
// Toolbar component ref
|
||||
|
|
@ -161,6 +162,20 @@
|
|||
}
|
||||
}
|
||||
|
||||
// Watch for external data changes and update editor
|
||||
$effect(() => {
|
||||
if (editor && data && !contentLoaded) {
|
||||
// Only update if the data has actual content (not just empty doc)
|
||||
const hasContent = data.content && data.content.length > 0 &&
|
||||
!(data.content.length === 1 && data.content[0].type === 'paragraph' && !data.content[0].content);
|
||||
|
||||
if (hasContent) {
|
||||
editor.commands.setContent(data);
|
||||
contentLoaded = true;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
onMount(() => {
|
||||
// Get extensions with custom options
|
||||
const extensions = getEditorExtensions({
|
||||
|
|
|
|||
Loading…
Reference in a new issue