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

/**
* 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;
}
};
}