You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
82 lines
2.2 KiB
82 lines
2.2 KiB
/** |
|
* Svelte action to mount a Svelte component into a DOM element |
|
*/ |
|
import type { ComponentType, Snippet } from 'svelte'; |
|
import { mount, unmount } from 'svelte'; |
|
|
|
export function mountComponent( |
|
node: HTMLElement, |
|
component: ComponentType<any>, |
|
props: Record<string, any> |
|
) { |
|
let instance: any = null; |
|
|
|
// Mount the component |
|
if (component && typeof component === 'function') { |
|
try { |
|
// Clear the node first to ensure clean mounting |
|
node.innerHTML = ''; |
|
|
|
// Try using Svelte 5's mount function first |
|
try { |
|
instance = mount(component, { |
|
target: node, |
|
props |
|
}); |
|
} catch (e) { |
|
// Fallback to Svelte 4 compatibility API |
|
console.debug('[mountComponent] Svelte 5 mount failed, trying compatibility API:', e); |
|
instance = new (component as any)({ |
|
target: node, |
|
props, |
|
hydrate: false, |
|
intro: false |
|
}); |
|
} |
|
|
|
// Verify the component was mounted |
|
if (!instance) { |
|
console.warn('[mountComponent] Component instance not created', { component, props }); |
|
} else { |
|
// Force a tick to ensure effects run |
|
setTimeout(() => { |
|
// Effects should have run by now |
|
}, 0); |
|
} |
|
} catch (e) { |
|
console.error('[mountComponent] Failed to mount component:', e, { component, props, node }); |
|
} |
|
} else { |
|
console.warn('[mountComponent] Invalid component provided', { component, props }); |
|
} |
|
|
|
return { |
|
update(newProps: Record<string, any>) { |
|
if (instance) { |
|
// Try Svelte 5 update first |
|
if (typeof instance.$set === 'function') { |
|
try { |
|
instance.$set(newProps); |
|
} catch (e) { |
|
console.error('[mountComponent] Failed to update component:', e); |
|
} |
|
} |
|
} |
|
}, |
|
destroy() { |
|
if (instance) { |
|
// Try Svelte 5 unmount first |
|
try { |
|
if (typeof unmount === 'function') { |
|
unmount(instance); |
|
} else if (typeof instance.$destroy === 'function') { |
|
instance.$destroy(); |
|
} |
|
} catch (e) { |
|
console.error('[mountComponent] Failed to destroy component:', e); |
|
} |
|
} |
|
instance = null; |
|
} |
|
}; |
|
}
|
|
|