Skip to content

Commit 8214782

Browse files
committed
fix(content-renderer): preserve class methods when merging renderers
Event-card-root was spreading ContentRenderer into a plain object, which lost all class methods like getKindHandler(). This caused "getKindHandler is not a function" errors in embedded-event. Solution: - Add clone() method to ContentRenderer that properly duplicates all handlers, components, and priorities - Update event-card-root to use clone() instead of spread operator - Fall back to defaultContentRenderer instead of empty object
1 parent b247546 commit 8214782

File tree

2 files changed

+66
-16
lines changed

2 files changed

+66
-16
lines changed

svelte/registry/src/lib/registry/components/event-card/event-card-root.svelte

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,13 @@
44
import { getContext, setContext } from 'svelte';
55
import { EVENT_CARD_CONTEXT_KEY, type EventCardContext } from './event-card.context.js';
66
import { CONTENT_RENDERER_CONTEXT_KEY, type ContentRendererContext } from '../../ui/content-renderer/content-renderer.context.js';
7-
import type {
8-
UserClickCallback,
9-
EventClickCallback,
10-
HashtagClickCallback,
11-
LinkClickCallback,
12-
MediaClickCallback
7+
import {
8+
defaultContentRenderer,
9+
type UserClickCallback,
10+
type EventClickCallback,
11+
type HashtagClickCallback,
12+
type LinkClickCallback,
13+
type MediaClickCallback
1314
} from '../../ui/content-renderer/index.svelte.js';
1415
import { getNDK } from '../../utils/ndk';
1516
import { cn } from '../../utils/cn';
@@ -67,17 +68,23 @@
6768
// Get parent ContentRendererContext if it exists
6869
const parentRendererContext = getContext<ContentRendererContext | undefined>(CONTENT_RENDERER_CONTEXT_KEY);
6970
70-
// Create a renderer that merges parent renderer with local callbacks
71+
// Create a renderer that clones parent renderer with overridden callbacks
7172
const renderer = $derived.by(() => {
72-
const base = parentRendererContext?.renderer ?? {} as any;
73-
return {
74-
...base,
75-
onUserClick: onUserClick ?? base.onUserClick,
76-
onEventClick: onEventClick ?? base.onEventClick,
77-
onHashtagClick: onHashtagClick ?? base.onHashtagClick,
78-
onLinkClick: onLinkClick ?? base.onLinkClick,
79-
onMediaClick: onMediaClick ?? base.onMediaClick
80-
};
73+
const base = parentRendererContext?.renderer ?? defaultContentRenderer;
74+
75+
// If no callbacks to override, return base as-is
76+
if (!onUserClick && !onEventClick && !onHashtagClick && !onLinkClick && !onMediaClick) {
77+
return base;
78+
}
79+
80+
// Clone the renderer with overridden callbacks
81+
return base.clone({
82+
onUserClick,
83+
onEventClick,
84+
onHashtagClick,
85+
onLinkClick,
86+
onMediaClick
87+
});
8188
});
8289
8390
// ContentRendererContext: provide the merged renderer

svelte/registry/src/lib/registry/ui/content-renderer/index.svelte.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,6 +363,49 @@ export class ContentRenderer {
363363
this.mediaPriority = 0;
364364
this.fallbackPriority = 0;
365365
}
366+
367+
/**
368+
* Create a clone of this renderer with all handlers and components
369+
* Optionally override click callbacks
370+
*/
371+
clone(callbacks?: {
372+
onUserClick?: UserClickCallback;
373+
onEventClick?: EventClickCallback;
374+
onHashtagClick?: HashtagClickCallback;
375+
onLinkClick?: LinkClickCallback;
376+
onMediaClick?: MediaClickCallback;
377+
}): ContentRenderer {
378+
const cloned = new ContentRenderer();
379+
380+
// Copy all public properties
381+
cloned.blockNsfw = this.blockNsfw;
382+
cloned.mentionComponent = this.mentionComponent;
383+
cloned.hashtagComponent = this.hashtagComponent;
384+
cloned.linkComponent = this.linkComponent;
385+
cloned.mediaComponent = this.mediaComponent;
386+
cloned.fallbackComponent = this.fallbackComponent;
387+
388+
// Copy callbacks (use provided overrides or original values)
389+
cloned.onUserClick = callbacks?.onUserClick ?? this.onUserClick;
390+
cloned.onEventClick = callbacks?.onEventClick ?? this.onEventClick;
391+
cloned.onHashtagClick = callbacks?.onHashtagClick ?? this.onHashtagClick;
392+
cloned.onLinkClick = callbacks?.onLinkClick ?? this.onLinkClick;
393+
cloned.onMediaClick = callbacks?.onMediaClick ?? this.onMediaClick;
394+
395+
// Copy all handlers from the private map
396+
for (const [kind, info] of this.handlers) {
397+
cloned.handlers.set(kind, info);
398+
}
399+
400+
// Copy priorities
401+
cloned.mentionPriority = this.mentionPriority;
402+
cloned.hashtagPriority = this.hashtagPriority;
403+
cloned.linkPriority = this.linkPriority;
404+
cloned.mediaPriority = this.mediaPriority;
405+
cloned.fallbackPriority = this.fallbackPriority;
406+
407+
return cloned;
408+
}
366409
}
367410

368411
/**

0 commit comments

Comments
 (0)