refactor: remove EnhancedComposer backward compatibility

- Remove EnhancedComposer shim and old backup file
- Update all imports to use new Composer from ./composer
- Fix editor command implementations for link operations
- Fix dropdown hook usage with proper reactive patterns
- All 5 components now directly import the modular implementation

🤖 Generated with [Claude Code](https://claude.ai/code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Justin Edmund 2025-06-26 09:12:08 -04:00
parent 237d8f8c89
commit e64788962e
10 changed files with 47 additions and 1418 deletions

View file

@ -8,7 +8,7 @@
import StatusDropdown from './StatusDropdown.svelte' import StatusDropdown from './StatusDropdown.svelte'
import UnifiedMediaModal from './UnifiedMediaModal.svelte' import UnifiedMediaModal from './UnifiedMediaModal.svelte'
import SmartImage from '../SmartImage.svelte' import SmartImage from '../SmartImage.svelte'
import EnhancedComposer from './EnhancedComposer.svelte' import Composer from './composer'
import { authenticatedFetch } from '$lib/admin-auth' import { authenticatedFetch } from '$lib/admin-auth'
import { toast } from '$lib/stores/toast' import { toast } from '$lib/stores/toast'
import type { Album } from '@prisma/client' import type { Album } from '@prisma/client'
@ -350,7 +350,7 @@
<!-- Content Panel --> <!-- Content Panel -->
<div class="panel panel-content" class:active={activeTab === 'content'}> <div class="panel panel-content" class:active={activeTab === 'content'}>
<EnhancedComposer <Composer
bind:this={editorInstance} bind:this={editorInstance}
bind:data={formData.content} bind:data={formData.content}
placeholder="Add album content..." placeholder="Add album content..."

File diff suppressed because it is too large Load diff

View file

@ -1,41 +0,0 @@
<!--
This file is a shim for backward compatibility.
The actual implementation is in ./composer/ComposerCore.svelte
-->
<script lang="ts">
import ComposerCore from './composer/ComposerCore.svelte'
import type { ComposerProps } from './composer/types'
// Re-export all props
let props: ComposerProps = $props()
// Re-export component reference
let composerRef = $state<ComposerCore>()
// Re-export public methods
export function focus() {
composerRef?.focus()
}
export function blur() {
composerRef?.blur()
}
export function clear() {
composerRef?.clear()
}
export function isEmpty() {
return composerRef?.isEmpty() || true
}
export function getContent() {
return composerRef?.getContent()
}
export function getText() {
return composerRef?.getText() || ''
}
</script>
<ComposerCore bind:this={composerRef} {...props} />

View file

@ -2,7 +2,7 @@
import { createEventDispatcher } from 'svelte' import { createEventDispatcher } from 'svelte'
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import Modal from './Modal.svelte' import Modal from './Modal.svelte'
import EnhancedComposer from './EnhancedComposer.svelte' import Composer from './composer'
import AdminSegmentedControl from './AdminSegmentedControl.svelte' import AdminSegmentedControl from './AdminSegmentedControl.svelte'
import FormField from './FormField.svelte' import FormField from './FormField.svelte'
import Button from './Button.svelte' import Button from './Button.svelte'
@ -270,7 +270,7 @@
</div> </div>
<div class="composer-body"> <div class="composer-body">
<EnhancedComposer <Composer
bind:this={editorInstance} bind:this={editorInstance}
bind:data={content} bind:data={content}
onChange={(newContent) => { onChange={(newContent) => {
@ -423,7 +423,7 @@
</div> </div>
{:else} {:else}
<div class="content-section"> <div class="content-section">
<EnhancedComposer <Composer
bind:this={editorInstance} bind:this={editorInstance}
bind:data={content} bind:data={content}
onChange={(newContent) => { onChange={(newContent) => {
@ -471,7 +471,7 @@
</Button> </Button>
{/if} {/if}
<div class="composer-body"> <div class="composer-body">
<EnhancedComposer <Composer
bind:this={editorInstance} bind:this={editorInstance}
bind:data={content} bind:data={content}
onChange={(newContent) => { onChange={(newContent) => {

View file

@ -4,7 +4,7 @@
import AdminPage from './AdminPage.svelte' import AdminPage from './AdminPage.svelte'
import AdminSegmentedControl from './AdminSegmentedControl.svelte' import AdminSegmentedControl from './AdminSegmentedControl.svelte'
import FormField from './FormField.svelte' import FormField from './FormField.svelte'
import EnhancedComposer from './EnhancedComposer.svelte' import Composer from './composer'
import ProjectMetadataForm from './ProjectMetadataForm.svelte' import ProjectMetadataForm from './ProjectMetadataForm.svelte'
import ProjectBrandingForm from './ProjectBrandingForm.svelte' import ProjectBrandingForm from './ProjectBrandingForm.svelte'
import ProjectImagesForm from './ProjectImagesForm.svelte' import ProjectImagesForm from './ProjectImagesForm.svelte'
@ -274,7 +274,7 @@
<!-- Case Study Panel --> <!-- Case Study Panel -->
<div class="panel panel-case-study" class:active={activeTab === 'case-study'}> <div class="panel panel-case-study" class:active={activeTab === 'case-study'}>
<EnhancedComposer <Composer
bind:this={editorRef} bind:this={editorRef}
bind:data={formData.caseStudyContent} bind:data={formData.caseStudyContent}
onChange={handleEditorChange} onChange={handleEditorChange}

View file

@ -92,19 +92,23 @@
let showMediaDropdown = $state(false) let showMediaDropdown = $state(false)
// Text style dropdown // Text style dropdown
const textStyleDropdown = useDropdown({ const textStyleDropdown = $derived.by(() => {
triggerRef: toolbarRef?.getDropdownRefs().textStyle, return useDropdown({
isOpen: showTextStyleDropdown, triggerRef: toolbarRef?.getDropdownRefs()?.textStyle,
onClose: () => (showTextStyleDropdown = false), isOpen: showTextStyleDropdown,
portalClass: 'dropdown-menu-portal' onClose: () => (showTextStyleDropdown = false),
portalClass: 'dropdown-menu-portal'
})
}) })
// Media dropdown // Media dropdown
const mediaDropdown = useDropdown({ const mediaDropdown = $derived.by(() => {
triggerRef: toolbarRef?.getDropdownRefs().media, return useDropdown({
isOpen: showMediaDropdown, triggerRef: toolbarRef?.getDropdownRefs()?.media,
onClose: () => (showMediaDropdown = false), isOpen: showMediaDropdown,
portalClass: 'media-dropdown-portal' onClose: () => (showMediaDropdown = false),
portalClass: 'media-dropdown-portal'
})
}) })
// Event handlers // Event handlers
@ -242,11 +246,11 @@
showMediaLibrary={!!features.mediaLibrary} showMediaLibrary={!!features.mediaLibrary}
onTextStyleDropdownToggle={() => { onTextStyleDropdownToggle={() => {
showTextStyleDropdown = !showTextStyleDropdown showTextStyleDropdown = !showTextStyleDropdown
textStyleDropdown.toggle() textStyleDropdown?.toggle()
}} }}
onMediaDropdownToggle={() => { onMediaDropdownToggle={() => {
showMediaDropdown = !showMediaDropdown showMediaDropdown = !showMediaDropdown
mediaDropdown.toggle() mediaDropdown?.toggle()
}} }}
/> />
{/if} {/if}
@ -286,7 +290,7 @@
{#if showTextStyleDropdown && editor} {#if showTextStyleDropdown && editor}
<TextStyleDropdown <TextStyleDropdown
{editor} {editor}
position={textStyleDropdown.position()} position={textStyleDropdown?.position() || { top: 0, left: 0 }}
{features} {features}
onDismiss={() => (showTextStyleDropdown = false)} onDismiss={() => (showTextStyleDropdown = false)}
/> />
@ -296,7 +300,7 @@
{#if showMediaDropdown && editor && features.mediaLibrary} {#if showMediaDropdown && editor && features.mediaLibrary}
<MediaInsertDropdown <MediaInsertDropdown
{editor} {editor}
position={mediaDropdown.position()} position={mediaDropdown?.position() || { top: 0, left: 0 }}
{features} {features}
{albumId} {albumId}
onDismiss={() => (showMediaDropdown = false)} onDismiss={() => (showMediaDropdown = false)}

View file

@ -76,7 +76,18 @@
function handleSaveLink(newUrl: string) { function handleSaveLink(newUrl: string) {
if (!editor || linkEditPos === null) return if (!editor || linkEditPos === null) return
editor.commands.updateLinkUrl(linkEditPos, newUrl) // Update link by setting selection and re-applying link mark
const { state } = editor
const { doc } = state
const node = doc.nodeAt(linkEditPos)
if (node) {
editor
.chain()
.focus()
.setTextSelection({ from: linkEditPos, to: linkEditPos + node.nodeSize })
.setLink({ href: newUrl })
.run()
}
showLinkEditDialog = false showLinkEditDialog = false
linkEditPos = null linkEditPos = null
linkEditUrl = '' linkEditUrl = ''
@ -92,7 +103,8 @@
function handleRemoveLink() { function handleRemoveLink() {
if (!editor || linkContextPos === null) return if (!editor || linkContextPos === null) return
editor.commands.removeLink(linkContextPos) // Remove link by unset link command
editor.chain().focus().unsetLink().run()
showLinkContextMenu = false showLinkContextMenu = false
linkContextPos = null linkContextPos = null
linkContextUrl = null linkContextUrl = null

View file

@ -1,5 +1,6 @@
// Export ComposerCore as EnhancedComposer for backward compatibility // Export the main composer component
export { default as EnhancedComposer } from './ComposerCore.svelte' export { default } from './ComposerCore.svelte'
export { default as Composer } from './ComposerCore.svelte'
// Export types // Export types
export type { ComposerVariant, ComposerFeatures, ComposerProps } from './types' export type { ComposerVariant, ComposerFeatures, ComposerProps } from './types'

View file

@ -3,7 +3,7 @@
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import AdminPage from '$lib/components/admin/AdminPage.svelte' import AdminPage from '$lib/components/admin/AdminPage.svelte'
import EnhancedComposer from '$lib/components/admin/EnhancedComposer.svelte' import Composer from '$lib/components/admin/composer'
import LoadingSpinner from '$lib/components/admin/LoadingSpinner.svelte' import LoadingSpinner from '$lib/components/admin/LoadingSpinner.svelte'
import PostMetadataPopover from '$lib/components/admin/PostMetadataPopover.svelte' import PostMetadataPopover from '$lib/components/admin/PostMetadataPopover.svelte'
import DeleteConfirmationModal from '$lib/components/admin/DeleteConfirmationModal.svelte' import DeleteConfirmationModal from '$lib/components/admin/DeleteConfirmationModal.svelte'
@ -396,7 +396,7 @@
{#if config?.showContent && contentReady} {#if config?.showContent && contentReady}
<div class="editor-wrapper"> <div class="editor-wrapper">
<EnhancedComposer bind:data={content} placeholder="Continue writing..." /> <Composer bind:data={content} placeholder="Continue writing..." />
</div> </div>
{/if} {/if}
</div> </div>

View file

@ -3,7 +3,7 @@
import { goto } from '$app/navigation' import { goto } from '$app/navigation'
import { onMount } from 'svelte' import { onMount } from 'svelte'
import AdminPage from '$lib/components/admin/AdminPage.svelte' import AdminPage from '$lib/components/admin/AdminPage.svelte'
import EnhancedComposer from '$lib/components/admin/EnhancedComposer.svelte' import Composer from '$lib/components/admin/composer'
import PostMetadataPopover from '$lib/components/admin/PostMetadataPopover.svelte' import PostMetadataPopover from '$lib/components/admin/PostMetadataPopover.svelte'
import Button from '$lib/components/admin/Button.svelte' import Button from '$lib/components/admin/Button.svelte'
import PublishDropdown from '$lib/components/admin/PublishDropdown.svelte' import PublishDropdown from '$lib/components/admin/PublishDropdown.svelte'
@ -199,7 +199,7 @@
{#if config?.showContent} {#if config?.showContent}
<div class="editor-wrapper"> <div class="editor-wrapper">
<EnhancedComposer bind:data={content} placeholder="Start writing..." /> <Composer bind:data={content} placeholder="Start writing..." />
</div> </div>
{/if} {/if}
</div> </div>