From d4aa5f93e16c564d5248da99cd22101b314d3d63 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miguel=20=C3=81ngel?= Date: Tue, 23 Jun 2026 19:56:21 -0400 Subject: [PATCH] fix(studio): guard against null tag in timeline track style (#1679) getTrackStyle() can receive a falsy tag at runtime (e.g. empty string from timeline element defaults), causing toLowerCase() and startsWith() to throw. Default to "div" when tag is falsy. --- packages/studio/src/player/components/timelineIcons.tsx | 6 ++++-- packages/studio/src/player/lib/timelineDOM.ts | 8 ++++++-- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/packages/studio/src/player/components/timelineIcons.tsx b/packages/studio/src/player/components/timelineIcons.tsx index 9db5a3d22..8846cd049 100644 --- a/packages/studio/src/player/components/timelineIcons.tsx +++ b/packages/studio/src/player/components/timelineIcons.tsx @@ -39,8 +39,10 @@ const ICONS: Record = { }; export function getTrackStyle(tag: string): TrackVisualStyle { - const trackStyle = getTimelineTrackStyle(tag); - const normalized = tag.toLowerCase(); + if (!tag) console.warn("[Timeline] getTrackStyle received empty tag, defaulting to div"); + const safeTag = tag || "div"; + const trackStyle = getTimelineTrackStyle(safeTag); + const normalized = safeTag.toLowerCase(); const icon = normalized.startsWith("h") && normalized.length === 2 && "123456".includes(normalized[1] ?? "") ? ICONS.h1 diff --git a/packages/studio/src/player/lib/timelineDOM.ts b/packages/studio/src/player/lib/timelineDOM.ts index 825fe9d57..2657c1f54 100644 --- a/packages/studio/src/player/lib/timelineDOM.ts +++ b/packages/studio/src/player/lib/timelineDOM.ts @@ -61,6 +61,10 @@ export { // TimelineElement factories // --------------------------------------------------------------------------- +function resolveClipTag(clip: ClipManifestClip): string { + return clip.tagName || clip.kind || "div"; +} + export function createTimelineElementFromManifestClip(params: { clip: ClipManifestClip; fallbackIndex: number; @@ -72,7 +76,7 @@ export function createTimelineElementFromManifestClip(params: { const label = getTimelineElementDisplayLabel({ id: clip.id, label: clip.label, - tag: clip.tagName || clip.kind, + tag: resolveClipTag(clip), }); let domId: string | undefined; @@ -103,7 +107,7 @@ export function createTimelineElementFromManifestClip(params: { id: identity.id, label, key: identity.key, - tag: clip.tagName || clip.kind, + tag: resolveClipTag(clip), start: clip.start, duration: clip.duration, track: clip.track,