70 lines
2.2 KiB
TypeScript
70 lines
2.2 KiB
TypeScript
import type { ComponentType } from 'react'
|
|
import {
|
|
Sword, Swords, Palette, MoodHappy, MasksTheater, Mask, Wand, Ghost, Camera,
|
|
QuestionMark, Rocket, Bolt, Shield, HorseToy, News, Microphone, Ball,
|
|
Spy, Trophy, MoodKid, Heart, Music, Tv2 as Tv, Film, Backpack,
|
|
UserCheck, HomeHeart, Hourglass, Drone, Monument, Confetti, Flame,
|
|
Lock, Binoculars, ChefHat, Gavel, Stethoscope, Leaf, MoonStars, Plane,
|
|
} from './icons'
|
|
|
|
type IconType = ComponentType<{ size?: number; stroke?: number; className?: string }>
|
|
|
|
/**
|
|
* Maps a TMDB / Jellyfin genre name to a unique Tabler icon.
|
|
* Matches are case-insensitive. Order matters - more specific patterns
|
|
* (e.g. "tv movie", "action and adventure", "science fiction", "children")
|
|
* come before broader ones so the right icon wins.
|
|
*/
|
|
const map: Array<[RegExp, IconType]> = [
|
|
// Multi-word / compound matches first
|
|
[/^action.{0,4}adventure|action.+adventure/i, Swords],
|
|
[/^tv movie|television movie/i, Tv],
|
|
[/^game.?show/i, Trophy],
|
|
[/^talk.?show/i, Microphone],
|
|
[/^sci.?fi|science fiction/i, Rocket],
|
|
[/^children|kids/i, MoodKid],
|
|
|
|
// Single-word, alphabetised
|
|
[/^action/i, Sword],
|
|
[/^adult|erotic/i, Lock],
|
|
[/^adventure/i, Backpack],
|
|
[/^animation|animated/i, Palette],
|
|
[/^biography|biographic/i, UserCheck],
|
|
[/^comedy|sitcom/i, MoodHappy],
|
|
[/^crime/i, Spy],
|
|
[/^document/i, Camera],
|
|
[/^drama/i, MasksTheater],
|
|
[/^espionage/i, Binoculars],
|
|
[/^family/i, HomeHeart],
|
|
[/^fantasy/i, Wand],
|
|
[/^food|culinary|cooking/i, ChefHat],
|
|
[/^histor/i, Monument],
|
|
[/^holiday/i, Confetti],
|
|
[/^horror/i, Ghost],
|
|
[/^legal|law/i, Gavel],
|
|
[/^medical|hospital/i, Stethoscope],
|
|
[/^music/i, Music],
|
|
[/^myster/i, QuestionMark],
|
|
[/^natur|wildlife|environment/i, Leaf],
|
|
[/^news/i, News],
|
|
[/^realit/i, Drone],
|
|
[/^romance|romantic/i, Heart],
|
|
[/^short/i, Hourglass],
|
|
[/^soap/i, Mask],
|
|
[/^sport/i, Ball],
|
|
[/^supernatural|paranormal|occult/i, MoonStars],
|
|
[/^talk/i, Microphone],
|
|
[/^thriller|suspense/i, Bolt],
|
|
[/^travel/i, Plane],
|
|
[/^war/i, Shield],
|
|
[/^western/i, HorseToy],
|
|
]
|
|
|
|
export function iconForGenre(name: string | null | undefined): IconType {
|
|
if (!name) return Film
|
|
for (const [re, Icon] of map) {
|
|
if (re.test(name)) return Icon
|
|
}
|
|
return Flame
|
|
}
|