@behindthemusictree/app-kit-ui 41.0.0 → 42.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -43,5 +43,5 @@ Third-party brand colors (Spotify, Google) stay literal.
43
43
 
44
44
  - `GenreTreeView` takes `className` on its root (no outer margin by default) and
45
45
  `showDisplayOptions` (default `true`) to hide the "Tree display options" group.
46
- - Render props (`renderArtistLink`, `renderSummary`, `renderTracksToolbar`, …) replace pieces of
46
+ - Render props (`renderArtistLink`, `renderPlaceLink`, `renderSummary`, `renderTracksToolbar`, …) replace pieces of
47
47
  the genre detail panel.
@@ -1741,7 +1741,9 @@ function ChangeParentPopup({
1741
1741
 
1742
1742
  // src/genre-tree/artist/useArtistPanel.tsx
1743
1743
  import { Skeleton as Skeleton5 } from "@behindthemusictree/ui";
1744
- import { useArtist } from "@behindthemusictree/app-kit/genre-tree";
1744
+ import {
1745
+ useArtist
1746
+ } from "@behindthemusictree/app-kit/genre-tree";
1745
1747
 
1746
1748
  // src/genre-tree/artist/ArtistActionBand.tsx
1747
1749
  import { Pause as Pause2, Play as Play2 } from "lucide-react";
@@ -1844,13 +1846,39 @@ function formatYears(beginYear, endYear, ended) {
1844
1846
  }
1845
1847
 
1846
1848
  // src/genre-tree/artist/ArtistHeader.tsx
1847
- import { jsx as jsx29 } from "react/jsx-runtime";
1849
+ import { Fragment as Fragment12, jsx as jsx29, jsxs as jsxs19 } from "react/jsx-runtime";
1848
1850
  var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
1849
- function ArtistHeader({ artist }) {
1851
+ function originLabel(artist, origin) {
1852
+ if (origin.source === "area") return "From";
1853
+ if (artist.type === "person") return "Born in";
1854
+ if (artist.type === "group") return "Formed in";
1855
+ return "From";
1856
+ }
1857
+ function OriginValue({
1858
+ origin,
1859
+ country,
1860
+ renderPlaceLink
1861
+ }) {
1862
+ const place = renderPlaceLink && origin.regionId !== null ? renderPlaceLink({ ...origin, regionId: origin.regionId }) : origin.name;
1863
+ return /* @__PURE__ */ jsxs19(Fragment12, { children: [
1864
+ place,
1865
+ country && origin.kind !== "country" && `, ${country}`
1866
+ ] });
1867
+ }
1868
+ function ArtistHeader({
1869
+ artist,
1870
+ renderPlaceLink
1871
+ }) {
1850
1872
  const fields = [];
1851
1873
  if (artist.type) fields.push({ label: "Type", value: artist.type.charAt(0).toUpperCase() + artist.type.slice(1) });
1852
- const country = artist.country && countryNames.of(artist.country);
1853
- if (country) fields.push({ label: "Country", value: country });
1874
+ const country = artist.country ? countryNames.of(artist.country) : void 0;
1875
+ if (artist.origin) {
1876
+ fields.push({
1877
+ label: originLabel(artist, artist.origin),
1878
+ value: /* @__PURE__ */ jsx29(OriginValue, { origin: artist.origin, country, renderPlaceLink })
1879
+ });
1880
+ }
1881
+ if (country && !artist.origin) fields.push({ label: "Country", value: country });
1854
1882
  const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
1855
1883
  if (years) fields.push({ label: "Active", value: years });
1856
1884
  const links = artistLinks(artist);
@@ -1867,7 +1895,7 @@ function ArtistPhoto({ image, name }) {
1867
1895
 
1868
1896
  // src/genre-tree/artist/ArtistMembers.tsx
1869
1897
  import { PanelGroup, PanelSection as PanelSection3 } from "@behindthemusictree/ui";
1870
- import { jsx as jsx31, jsxs as jsxs19 } from "react/jsx-runtime";
1898
+ import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
1871
1899
  function MembershipList({ title, memberships, renderArtistLink }) {
1872
1900
  if (memberships.length === 0) return null;
1873
1901
  return /* @__PURE__ */ jsx31(PanelGroup, { title, children: /* @__PURE__ */ jsx31("ul", { children: memberships.map((membership, index) => {
@@ -1878,9 +1906,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
1878
1906
  const detailsText = details.filter(Boolean).join(" \xB7 ");
1879
1907
  return (
1880
1908
  // A member can have several periods in the same group.
1881
- /* @__PURE__ */ jsxs19("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
1909
+ /* @__PURE__ */ jsxs20("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
1882
1910
  /* @__PURE__ */ jsx31("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
1883
- detailsText && /* @__PURE__ */ jsxs19("span", { className: "text-[var(--color-text-muted)]", children: [
1911
+ detailsText && /* @__PURE__ */ jsxs20("span", { className: "text-[var(--color-text-muted)]", children: [
1884
1912
  " \u2014 ",
1885
1913
  detailsText
1886
1914
  ] })
@@ -1891,7 +1919,7 @@ function MembershipList({ title, memberships, renderArtistLink }) {
1891
1919
  function ArtistMembers({ title, memberships, renderArtistLink }) {
1892
1920
  if (memberships.length === 0) return null;
1893
1921
  const isCurrent = (membership) => !membership.ended && membership.endYear === null;
1894
- return /* @__PURE__ */ jsxs19(PanelSection3, { title, children: [
1922
+ return /* @__PURE__ */ jsxs20(PanelSection3, { title, children: [
1895
1923
  /* @__PURE__ */ jsx31(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
1896
1924
  /* @__PURE__ */ jsx31(
1897
1925
  MembershipList,
@@ -1906,7 +1934,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
1906
1934
 
1907
1935
  // src/genre-tree/artist/ArtistDiscography.tsx
1908
1936
  import { PanelGroup as PanelGroup2, PanelSection as PanelSection4 } from "@behindthemusictree/ui";
1909
- import { jsx as jsx32, jsxs as jsxs20 } from "react/jsx-runtime";
1937
+ import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
1910
1938
  var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
1911
1939
  var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
1912
1940
  function discographyGroup({ primaryType, secondaryTypes }) {
@@ -1929,7 +1957,7 @@ function ArtistDiscography({ albums }) {
1929
1957
  return /* @__PURE__ */ jsx32(PanelSection4, { title: "Discography", children: GROUPS.map((group) => {
1930
1958
  const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
1931
1959
  if (groupAlbums.length === 0) return null;
1932
- return /* @__PURE__ */ jsx32(PanelGroup2, { title: group, children: /* @__PURE__ */ jsx32("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ jsxs20("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
1960
+ return /* @__PURE__ */ jsx32(PanelGroup2, { title: group, children: /* @__PURE__ */ jsx32("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ jsxs21("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
1933
1961
  /* @__PURE__ */ jsx32("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
1934
1962
  /* @__PURE__ */ jsx32("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
1935
1963
  ] }, album.uuid)) }) }, group);
@@ -1957,7 +1985,7 @@ import { useTrackList as useTrackList4 } from "@behindthemusictree/app-kit/genre
1957
1985
  import { FaPlay as FaPlay2, FaPause as FaPause2 } from "react-icons/fa";
1958
1986
  import { usePlayer as usePlayer7 } from "@behindthemusictree/app-kit/player";
1959
1987
  import { PlayStates as PlayStates2 } from "@behindthemusictree/app-kit/player";
1960
- import { jsx as jsx33, jsxs as jsxs21 } from "react/jsx-runtime";
1988
+ import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
1961
1989
  function TrackPositionPlayPause({
1962
1990
  position,
1963
1991
  uuid,
@@ -1971,14 +1999,14 @@ function TrackPositionPlayPause({
1971
1999
  const isPlaying = isThisTrack && isConfirmedPlayable && playState === PlayStates2.PLAYING;
1972
2000
  const isPaused = isThisTrack && isConfirmedPlayable && playState === PlayStates2.PAUSED;
1973
2001
  const isCurrentTrackActive = isPlaying || isPaused;
1974
- return /* @__PURE__ */ jsxs21(
2002
+ return /* @__PURE__ */ jsxs22(
1975
2003
  "div",
1976
2004
  {
1977
2005
  className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
1978
2006
  style: { minWidth: "4rem", maxWidth: "4rem" },
1979
2007
  onClick: handlePlayPauseClick,
1980
2008
  children: [
1981
- /* @__PURE__ */ jsx33("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ jsx33("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ jsxs21(
2009
+ /* @__PURE__ */ jsx33("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ jsx33("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ jsxs22(
1982
2010
  "span",
1983
2011
  {
1984
2012
  className: "track-position-play-pause__bars",
@@ -2008,7 +2036,7 @@ function TrackPositionPlayPause({
2008
2036
  // src/genre-tree/track-list-sidebar/TrackItem.tsx
2009
2037
  import { isSong as isSong2, songUnplayableReason as songUnplayableReason2 } from "@behindthemusictree/app-kit/genre-tree";
2010
2038
  import { ArtistNames as ArtistNames2 } from "@behindthemusictree/app-kit/genre-tree";
2011
- import { jsx as jsx34, jsxs as jsxs22 } from "react/jsx-runtime";
2039
+ import { jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
2012
2040
  function TrackItem({
2013
2041
  track,
2014
2042
  position,
@@ -2032,7 +2060,7 @@ function TrackItem({
2032
2060
  loadTrackForPlayer(track.uuid);
2033
2061
  }
2034
2062
  };
2035
- return /* @__PURE__ */ jsxs22(
2063
+ return /* @__PURE__ */ jsxs23(
2036
2064
  "div",
2037
2065
  {
2038
2066
  className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
@@ -2054,7 +2082,7 @@ function TrackItem({
2054
2082
  isSelected: selectedTrack?.uuid === track.uuid
2055
2083
  }
2056
2084
  ),
2057
- /* @__PURE__ */ jsxs22("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
2085
+ /* @__PURE__ */ jsxs23("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
2058
2086
  /* @__PURE__ */ jsx34("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ jsx34("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : isSong2(track) ? /* @__PURE__ */ jsx34(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
2059
2087
  track.artists && track.artists.length > 0 ? /* @__PURE__ */ jsx34("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ jsx34(ArtistNames2, { artists: track.artists, renderArtistLink }) }) : ""
2060
2088
  ] }),
@@ -2074,7 +2102,7 @@ function TrackItem({
2074
2102
  }
2075
2103
 
2076
2104
  // src/genre-tree/artist/ArtistSongs.tsx
2077
- import { Fragment as Fragment12, jsx as jsx35, jsxs as jsxs23 } from "react/jsx-runtime";
2105
+ import { Fragment as Fragment13, jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
2078
2106
  var SongPageSchema2 = PaginatedResponseSchema2(SongDetailedSchema2);
2079
2107
  var SORTS = [
2080
2108
  { ordering: "title", label: "Title" },
@@ -2107,7 +2135,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
2107
2135
  event.stopPropagation();
2108
2136
  void play(song.uuid);
2109
2137
  };
2110
- return /* @__PURE__ */ jsx35(PanelSection5, { title: "Songs", children: isPending ? /* @__PURE__ */ jsx35(Skeleton4, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ jsx35("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ jsx35("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ jsxs23(Fragment12, { children: [
2138
+ return /* @__PURE__ */ jsx35(PanelSection5, { title: "Songs", children: isPending ? /* @__PURE__ */ jsx35(Skeleton4, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ jsx35("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ jsx35("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ jsxs24(Fragment13, { children: [
2111
2139
  /* @__PURE__ */ jsx35("div", { className: "flex flex-wrap items-center justify-end gap-2 mb-2", children: /* @__PURE__ */ jsx35("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ jsx35(
2112
2140
  "button",
2113
2141
  {
@@ -2136,7 +2164,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
2136
2164
  }
2137
2165
 
2138
2166
  // src/genre-tree/artist/useArtistPanel.tsx
2139
- import { Fragment as Fragment13, jsx as jsx36, jsxs as jsxs24 } from "react/jsx-runtime";
2167
+ import { Fragment as Fragment14, jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
2140
2168
  function useArtistPanel({
2141
2169
  uuid,
2142
2170
  scope,
@@ -2144,6 +2172,7 @@ function useArtistPanel({
2144
2172
  getShareUrl,
2145
2173
  renderArtistLink,
2146
2174
  renderSongLink,
2175
+ renderPlaceLink,
2147
2176
  expanded,
2148
2177
  onExpandedChange,
2149
2178
  onClose
@@ -2157,7 +2186,7 @@ function useArtistPanel({
2157
2186
  return {
2158
2187
  ...panel,
2159
2188
  title: "Artist",
2160
- content: /* @__PURE__ */ jsxs24("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
2189
+ content: /* @__PURE__ */ jsxs25("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
2161
2190
  /* @__PURE__ */ jsx36(Skeleton5, { className: "h-3 w-16" }),
2162
2191
  /* @__PURE__ */ jsx36(Skeleton5, { className: "h-4 w-32" }),
2163
2192
  /* @__PURE__ */ jsx36(Skeleton5, { className: "h-3 w-16" }),
@@ -2185,7 +2214,7 @@ function useArtistPanel({
2185
2214
  return {
2186
2215
  ...panel,
2187
2216
  title: artist.name,
2188
- content: /* @__PURE__ */ jsxs24(Fragment13, { children: [
2217
+ content: /* @__PURE__ */ jsxs25(Fragment14, { children: [
2189
2218
  /* @__PURE__ */ jsx36(
2190
2219
  ArtistActionBand,
2191
2220
  {
@@ -2194,7 +2223,7 @@ function useArtistPanel({
2194
2223
  }
2195
2224
  ),
2196
2225
  artist.image && /* @__PURE__ */ jsx36(ArtistPhoto, { image: artist.image, name: artist.name }),
2197
- /* @__PURE__ */ jsx36(ArtistHeader, { artist }),
2226
+ /* @__PURE__ */ jsx36(ArtistHeader, { artist, renderPlaceLink }),
2198
2227
  /* @__PURE__ */ jsx36(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
2199
2228
  /* @__PURE__ */ jsx36(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
2200
2229
  artist.tracksCount > 0 && /* @__PURE__ */ jsx36(
@@ -2231,7 +2260,7 @@ import {
2231
2260
  useSongHistory,
2232
2261
  useTrackList as useTrackList6
2233
2262
  } from "@behindthemusictree/app-kit/genre-tree";
2234
- import { Fragment as Fragment14, jsx as jsx37, jsxs as jsxs25 } from "react/jsx-runtime";
2263
+ import { Fragment as Fragment15, jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
2235
2264
  var numberFormat = new Intl.NumberFormat("en");
2236
2265
  var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
2237
2266
  var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
@@ -2242,22 +2271,22 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
2242
2271
  if (history.status === "loading") body = /* @__PURE__ */ jsx37(Skeleton6, { className: "h-10", "aria-busy": "true" });
2243
2272
  else if (history.status === "error") body = /* @__PURE__ */ jsx37("p", { className: "text-red-600", children: "Could not load the history." });
2244
2273
  else if (history.status === "success")
2245
- body = history.entries.length === 0 ? /* @__PURE__ */ jsx37("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ jsx37("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ jsxs25("li", { className: "py-1.5 text-body", children: [
2274
+ body = history.entries.length === 0 ? /* @__PURE__ */ jsx37("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ jsx37("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ jsxs26("li", { className: "py-1.5 text-body", children: [
2246
2275
  /* @__PURE__ */ jsx37("span", { className: "font-medium", children: entry.action }),
2247
- entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ jsxs25("span", { className: "text-[var(--color-text-muted)]", children: [
2276
+ entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ jsxs26("span", { className: "text-[var(--color-text-muted)]", children: [
2248
2277
  " ",
2249
2278
  "\u2014 ",
2250
2279
  entry.oldValue ?? "none",
2251
2280
  " \u2192 ",
2252
2281
  entry.newValue ?? "none"
2253
2282
  ] }) : null,
2254
- /* @__PURE__ */ jsxs25("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
2283
+ /* @__PURE__ */ jsxs26("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
2255
2284
  entry.actorPseudo ?? "Anonymous",
2256
2285
  " \xB7 ",
2257
2286
  dateFormat.format(new Date(entry.createdOn))
2258
2287
  ] })
2259
2288
  ] }, entry.uuid)) });
2260
- return /* @__PURE__ */ jsx37(PanelBleed3, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ jsxs25("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
2289
+ return /* @__PURE__ */ jsx37(PanelBleed3, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ jsxs26("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
2261
2290
  /* @__PURE__ */ jsx37("summary", { className: `mt-2.5 cursor-pointer ${PANEL_LABEL_CLASS}`, children: "History" }),
2262
2291
  /* @__PURE__ */ jsx37("div", { className: "mt-1.5", children: body })
2263
2292
  ] }) });
@@ -2278,7 +2307,7 @@ function SongPanelContent(props) {
2278
2307
  const genre = song.genre;
2279
2308
  fields.push({
2280
2309
  label: "Genre",
2281
- value: onSelectGenre ? /* @__PURE__ */ jsx37("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ jsx37("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ jsxs25("span", { children: [
2310
+ value: onSelectGenre ? /* @__PURE__ */ jsx37("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ jsx37("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ jsxs26("span", { children: [
2282
2311
  index > 0 && /* @__PURE__ */ jsx37("span", { "aria-hidden": "true", children: "\u203A " }),
2283
2312
  /* @__PURE__ */ jsx37("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
2284
2313
  ] }, genrePlaylist.uuid)) }) : song.genre.name
@@ -2315,8 +2344,8 @@ function SongPanelContent(props) {
2315
2344
  label: "Links",
2316
2345
  value: /* @__PURE__ */ jsx37("span", { className: "flex gap-3", children: links })
2317
2346
  });
2318
- return /* @__PURE__ */ jsxs25(Fragment14, { children: [
2319
- /* @__PURE__ */ jsx37(PanelBleed3, { children: /* @__PURE__ */ jsxs25(ActionBand3, { children: [
2347
+ return /* @__PURE__ */ jsxs26(Fragment15, { children: [
2348
+ /* @__PURE__ */ jsx37(PanelBleed3, { children: /* @__PURE__ */ jsxs26(ActionBand3, { children: [
2320
2349
  /* @__PURE__ */ jsx37(
2321
2350
  ActionButton5,
2322
2351
  {
@@ -2337,7 +2366,7 @@ function SongPanelContent(props) {
2337
2366
  }
2338
2367
 
2339
2368
  // src/genre-tree/song/useSongPanel.tsx
2340
- import { jsx as jsx38, jsxs as jsxs26 } from "react/jsx-runtime";
2369
+ import { jsx as jsx38, jsxs as jsxs27 } from "react/jsx-runtime";
2341
2370
  function useSongPanel({
2342
2371
  uuid,
2343
2372
  scope,
@@ -2358,7 +2387,7 @@ function useSongPanel({
2358
2387
  return {
2359
2388
  ...panel,
2360
2389
  title: "Song",
2361
- content: /* @__PURE__ */ jsxs26("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
2390
+ content: /* @__PURE__ */ jsxs27("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
2362
2391
  /* @__PURE__ */ jsx38(Skeleton7, { className: "h-3 w-16" }),
2363
2392
  /* @__PURE__ */ jsx38(Skeleton7, { className: "h-4 w-32" }),
2364
2393
  /* @__PURE__ */ jsx38(Skeleton7, { className: "h-3 w-16" }),
@@ -2410,6 +2439,7 @@ function useEntityPanel({
2410
2439
  getShareUrl,
2411
2440
  renderArtistLink,
2412
2441
  renderSongLink,
2442
+ renderPlaceLink,
2413
2443
  song,
2414
2444
  artist,
2415
2445
  ...navigation
@@ -2428,7 +2458,8 @@ function useEntityPanel({
2428
2458
  getBackendBaseUrl: getArtistBackendBaseUrl ?? getBackendBaseUrl,
2429
2459
  getShareUrl,
2430
2460
  renderArtistLink,
2431
- renderSongLink
2461
+ renderSongLink,
2462
+ renderPlaceLink
2432
2463
  });
2433
2464
  return songPanel ?? artistPanel;
2434
2465
  }
@@ -2457,7 +2488,7 @@ function SizeMetricToggle({
2457
2488
  }
2458
2489
 
2459
2490
  // src/genre-tree/GenreTreeView.tsx
2460
- import { Fragment as Fragment15, jsx as jsx40, jsxs as jsxs27 } from "react/jsx-runtime";
2491
+ import { Fragment as Fragment16, jsx as jsx40, jsxs as jsxs28 } from "react/jsx-runtime";
2461
2492
  var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
2462
2493
  var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
2463
2494
  var noop = () => {
@@ -2505,6 +2536,7 @@ function GenreTreeView({
2505
2536
  songSearch = true,
2506
2537
  onSongSelect,
2507
2538
  renderSongLink,
2539
+ renderPlaceLink,
2508
2540
  renderSummary,
2509
2541
  renderEssentialTracks,
2510
2542
  renderSongLeading,
@@ -2634,6 +2666,7 @@ function GenreTreeView({
2634
2666
  getShareUrl: getShareUrlRef.current,
2635
2667
  renderArtistLink: resolvedRenderArtistLink,
2636
2668
  renderSongLink: resolvedRenderSongLink,
2669
+ renderPlaceLink,
2637
2670
  song: {
2638
2671
  uuid: songUuid,
2639
2672
  expanded: controlledSongExpanded ?? (songUuid !== null && expandedSongUuid === songUuid),
@@ -2822,7 +2855,7 @@ function GenreTreeView({
2822
2855
  ) : null;
2823
2856
  const renderArtistFilter = () => {
2824
2857
  if (isLoading || !filterArtist) return null;
2825
- return /* @__PURE__ */ jsxs27("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
2858
+ return /* @__PURE__ */ jsxs28("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
2826
2859
  /* @__PURE__ */ jsx40(
2827
2860
  "button",
2828
2861
  {
@@ -2847,7 +2880,7 @@ function GenreTreeView({
2847
2880
  )
2848
2881
  ] });
2849
2882
  };
2850
- const actions = /* @__PURE__ */ jsxs27(Fragment15, { children: [
2883
+ const actions = /* @__PURE__ */ jsxs28(Fragment16, { children: [
2851
2884
  !isLoading && !isError && /* @__PURE__ */ jsx40(
2852
2885
  GenreTreeSearch,
2853
2886
  {
@@ -2882,7 +2915,7 @@ function GenreTreeView({
2882
2915
  }
2883
2916
  ),
2884
2917
  !isLoading && !isError && filterArtist && /* @__PURE__ */ jsx40("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
2885
- /* @__PURE__ */ jsxs27("div", { className: "contents max-md:flex max-md:w-full max-md:items-center max-md:gap-2 max-md:overflow-x-auto max-md:[scrollbar-width:none] max-md:[&>*]:shrink-0", children: [
2918
+ /* @__PURE__ */ jsxs28("div", { className: "contents max-md:flex max-md:w-full max-md:items-center max-md:gap-2 max-md:overflow-x-auto max-md:[scrollbar-width:none] max-md:[&>*]:shrink-0", children: [
2886
2919
  !isLoading && !isError && !isControlled && /* @__PURE__ */ jsx40(
2887
2920
  SegmentedControl2,
2888
2921
  {
@@ -2924,7 +2957,7 @@ function GenreTreeView({
2924
2957
  )
2925
2958
  ] })
2926
2959
  ] });
2927
- return /* @__PURE__ */ jsxs27(
2960
+ return /* @__PURE__ */ jsxs28(
2928
2961
  "div",
2929
2962
  {
2930
2963
  "data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
@@ -2944,9 +2977,9 @@ function GenreTreeView({
2944
2977
  children: renderArtistFilter()
2945
2978
  }
2946
2979
  ),
2947
- /* @__PURE__ */ jsx40("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ jsxs27("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
2980
+ /* @__PURE__ */ jsx40("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ jsxs28("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
2948
2981
  !isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ jsx40("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
2949
- isLoading ? /* @__PURE__ */ jsx40(GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ jsxs27("p", { role: "alert", className: "m-auto text-center", children: [
2982
+ isLoading ? /* @__PURE__ */ jsx40(GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ jsxs28("p", { role: "alert", className: "m-auto text-center", children: [
2950
2983
  "Couldn't load the genre tree.",
2951
2984
  " ",
2952
2985
  /* @__PURE__ */ jsx40("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
@@ -2973,7 +3006,7 @@ function GenreTreeView({
2973
3006
  allowWheelRotation,
2974
3007
  sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
2975
3008
  busy,
2976
- floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
3009
+ floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
2977
3010
  floatingControlsLeading,
2978
3011
  canSizeByViews && /* @__PURE__ */ jsx40(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
2979
3012
  ] }) : void 0,
@@ -3002,7 +3035,7 @@ function GenreTreeView({
3002
3035
  allowWheelRotation,
3003
3036
  sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
3004
3037
  busy,
3005
- floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
3038
+ floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ jsxs28("div", { className: "flex items-center gap-2", children: [
3006
3039
  floatingControlsLeading,
3007
3040
  canSizeByViews && /* @__PURE__ */ jsx40(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
3008
3041
  ] }) : void 0,
@@ -3077,7 +3110,7 @@ function GenreTreeView({
3077
3110
  onExpandedChange: activePanel?.onExpandedChange,
3078
3111
  aside: activePanel?.aside,
3079
3112
  edgeTab: detailTab,
3080
- children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ jsxs27(Fragment15, { children: [
3113
+ children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ jsxs28(Fragment16, { children: [
3081
3114
  activePanel.content,
3082
3115
  activePanel.aside
3083
3116
  ] }) : activePanel?.content
@@ -3103,7 +3136,7 @@ import { ListMusic } from "lucide-react";
3103
3136
  import { useTrackList as useTrackList7 } from "@behindthemusictree/app-kit/genre-tree";
3104
3137
  import { TrackListOriginType as TrackListOriginType3 } from "@behindthemusictree/app-kit/genre-tree";
3105
3138
  import { useTrackNoun as useTrackNoun3 } from "@behindthemusictree/app-kit/track-noun";
3106
- import { jsx as jsx41, jsxs as jsxs28 } from "react/jsx-runtime";
3139
+ import { jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
3107
3140
  var useBrowserLayoutEffect = typeof window === "undefined" ? useEffect7 : useLayoutEffect2;
3108
3141
  function TrackListSidebar({
3109
3142
  className: className2 = "",
@@ -3205,20 +3238,20 @@ function TrackListSidebar({
3205
3238
  }
3206
3239
  };
3207
3240
  const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
3208
- return trackList ? /* @__PURE__ */ jsxs28(
3241
+ return trackList ? /* @__PURE__ */ jsxs29(
3209
3242
  "div",
3210
3243
  {
3211
3244
  "data-theme": "dark",
3212
3245
  className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
3213
3246
  style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
3214
3247
  children: [
3215
- /* @__PURE__ */ jsxs28("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
3216
- /* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
3217
- /* @__PURE__ */ jsxs28("div", { className: "origin flex text-xl", children: [
3248
+ /* @__PURE__ */ jsxs29("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
3249
+ /* @__PURE__ */ jsxs29("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
3250
+ /* @__PURE__ */ jsxs29("div", { className: "origin flex text-xl", children: [
3218
3251
  /* @__PURE__ */ jsx41("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
3219
3252
  /* @__PURE__ */ jsx41("div", { className: "name-container flex flex-col justify-center items-center text-[var(--color-text)] font-bold pr-2 max-w-[27.5rem]", children: /* @__PURE__ */ jsx41("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
3220
3253
  ] }),
3221
- /* @__PURE__ */ jsxs28("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
3254
+ /* @__PURE__ */ jsxs29("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
3222
3255
  trackList.origin.type === TrackListOriginType3.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === TrackListOriginType3.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
3223
3256
  `${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
3224
3257
  ] })
@@ -3236,7 +3269,7 @@ function TrackListSidebar({
3236
3269
  }
3237
3270
  )
3238
3271
  ] }),
3239
- !isCollapsed && /* @__PURE__ */ jsxs28(
3272
+ !isCollapsed && /* @__PURE__ */ jsxs29(
3240
3273
  "ul",
3241
3274
  {
3242
3275
  ref: trackListRef,
@@ -3282,7 +3315,7 @@ import { PanelEdgeTab } from "@behindthemusictree/ui";
3282
3315
  import { Pause as Pause4, Play as Play4, SkipBack, SkipForward, Volume2, VolumeX } from "lucide-react";
3283
3316
  import { formatTime, useTrackList as useTrackList8 } from "@behindthemusictree/app-kit/genre-tree";
3284
3317
  import { PlayStates as PlayStates4, useCurrentTime, usePlayer as usePlayer11 } from "@behindthemusictree/app-kit/player";
3285
- import { jsx as jsx42, jsxs as jsxs29 } from "react/jsx-runtime";
3318
+ import { jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
3286
3319
  function PlayerControls() {
3287
3320
  const {
3288
3321
  duration,
@@ -3301,13 +3334,13 @@ function PlayerControls() {
3301
3334
  const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
3302
3335
  const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
3303
3336
  const isPlaying = playState === PlayStates4.PLAYING;
3304
- return /* @__PURE__ */ jsxs29(
3337
+ return /* @__PURE__ */ jsxs30(
3305
3338
  "section",
3306
3339
  {
3307
3340
  "aria-label": "Player controls",
3308
3341
  className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
3309
3342
  children: [
3310
- /* @__PURE__ */ jsxs29("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
3343
+ /* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
3311
3344
  /* @__PURE__ */ jsx42("span", { "aria-label": "Elapsed time", children: formatTime(safeCurrentTime) }),
3312
3345
  /* @__PURE__ */ jsx42(
3313
3346
  "input",
@@ -3325,8 +3358,8 @@ function PlayerControls() {
3325
3358
  ),
3326
3359
  /* @__PURE__ */ jsx42("span", { "aria-label": "Duration", children: formatTime(safeDuration) })
3327
3360
  ] }),
3328
- /* @__PURE__ */ jsxs29("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
3329
- /* @__PURE__ */ jsxs29("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
3361
+ /* @__PURE__ */ jsxs30("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
3362
+ /* @__PURE__ */ jsxs30("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
3330
3363
  /* @__PURE__ */ jsx42(
3331
3364
  "button",
3332
3365
  {
@@ -3364,7 +3397,7 @@ function PlayerControls() {
3364
3397
  }
3365
3398
  )
3366
3399
  ] }),
3367
- /* @__PURE__ */ jsxs29("label", { className: "col-start-3 flex w-[4.2rem] shrink-0 items-center gap-[0.35rem] justify-self-end text-zinc-400 sm:w-[4.9rem]", children: [
3400
+ /* @__PURE__ */ jsxs30("label", { className: "col-start-3 flex w-[4.2rem] shrink-0 items-center gap-[0.35rem] justify-self-end text-zinc-400 sm:w-[4.9rem]", children: [
3368
3401
  volume === 0 ? /* @__PURE__ */ jsx42(VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ jsx42(Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
3369
3402
  /* @__PURE__ */ jsx42("span", { className: "sr-only", children: "Volume" }),
3370
3403
  /* @__PURE__ */ jsx42(
@@ -3389,7 +3422,7 @@ function PlayerControls() {
3389
3422
  }
3390
3423
 
3391
3424
  // src/genre-tree/PlayerPanel.tsx
3392
- import { jsx as jsx43, jsxs as jsxs30 } from "react/jsx-runtime";
3425
+ import { jsx as jsx43, jsxs as jsxs31 } from "react/jsx-runtime";
3393
3426
  var PANEL_ID = "player-panel";
3394
3427
  var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
3395
3428
  function PlayerPanel({
@@ -3429,7 +3462,7 @@ function PlayerPanel({
3429
3462
  onClick: () => setIsExtendRequested(true),
3430
3463
  expanded: false
3431
3464
  } : null;
3432
- return /* @__PURE__ */ jsxs30(
3465
+ return /* @__PURE__ */ jsxs31(
3433
3466
  "div",
3434
3467
  {
3435
3468
  id: PANEL_ID,
@@ -3452,7 +3485,7 @@ function PlayerPanel({
3452
3485
  className: "absolute right-full top-1/2 -translate-y-1/2"
3453
3486
  }
3454
3487
  ),
3455
- /* @__PURE__ */ jsxs30(
3488
+ /* @__PURE__ */ jsxs31(
3456
3489
  "div",
3457
3490
  {
3458
3491
  className: twMerge(
@@ -3460,11 +3493,11 @@ function PlayerPanel({
3460
3493
  isExtended ? "flex-row" : "flex-col"
3461
3494
  ),
3462
3495
  children: [
3463
- /* @__PURE__ */ jsxs30("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
3496
+ /* @__PURE__ */ jsxs31("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
3464
3497
  /* @__PURE__ */ jsx43("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ jsx43("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
3465
- /* @__PURE__ */ jsxs30("div", { className: "relative w-full shrink-0", children: [
3498
+ /* @__PURE__ */ jsxs31("div", { className: "relative w-full shrink-0", children: [
3466
3499
  /* @__PURE__ */ jsx43(PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
3467
- playerTrackObject?.loadError && /* @__PURE__ */ jsxs30("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
3500
+ playerTrackObject?.loadError && /* @__PURE__ */ jsxs31("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
3468
3501
  playerTrackObject.loadError,
3469
3502
  /* @__PURE__ */ jsx43("button", { type: "button", className: "ml-2 underline", onClick: () => {
3470
3503
  void retryPlayback();
@@ -3500,10 +3533,10 @@ function PlayerPanel({
3500
3533
  import { v4 as uuidv4 } from "uuid";
3501
3534
  import { AiFillStar, AiOutlineStar } from "react-icons/ai";
3502
3535
  import { FORM_RATING_NULL_VALUE } from "@behindthemusictree/app-kit/genre-tree";
3503
- import { jsx as jsx44, jsxs as jsxs31 } from "react/jsx-runtime";
3536
+ import { jsx as jsx44, jsxs as jsxs32 } from "react/jsx-runtime";
3504
3537
  function Rating({ rating, handleChange }) {
3505
3538
  const instanceId = uuidv4();
3506
- return /* @__PURE__ */ jsx44("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsxs31("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
3539
+ return /* @__PURE__ */ jsx44("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsxs32("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
3507
3540
  /* @__PURE__ */ jsx44(
3508
3541
  "input",
3509
3542
  {
@@ -3516,7 +3549,7 @@ function Rating({ rating, handleChange }) {
3516
3549
  onChange: handleChange
3517
3550
  }
3518
3551
  ),
3519
- /* @__PURE__ */ jsx44("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ jsxs31("div", { className: "flex", children: [
3552
+ /* @__PURE__ */ jsx44("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ jsxs32("div", { className: "flex", children: [
3520
3553
  /* @__PURE__ */ jsx44(
3521
3554
  AiOutlineStar,
3522
3555
  {
@@ -3537,7 +3570,7 @@ function Rating({ rating, handleChange }) {
3537
3570
  // src/genre-tree/EntityDetailPanel.tsx
3538
3571
  import { useState as useState12 } from "react";
3539
3572
  import { DetailPanel as DetailPanel3 } from "@behindthemusictree/ui";
3540
- import { Fragment as Fragment16, jsx as jsx45, jsxs as jsxs32 } from "react/jsx-runtime";
3573
+ import { Fragment as Fragment17, jsx as jsx45, jsxs as jsxs33 } from "react/jsx-runtime";
3541
3574
  function EntityDetailPanel({
3542
3575
  scope,
3543
3576
  getBackendBaseUrl,
@@ -3549,6 +3582,7 @@ function EntityDetailPanel({
3549
3582
  onArtistUuidChange,
3550
3583
  renderArtistLink,
3551
3584
  renderSongLink,
3585
+ renderPlaceLink,
3552
3586
  collapsed,
3553
3587
  edgeTab,
3554
3588
  ...navigation
@@ -3560,6 +3594,7 @@ function EntityDetailPanel({
3560
3594
  getBackendBaseUrl,
3561
3595
  getArtistBackendBaseUrl,
3562
3596
  getShareUrl,
3597
+ renderPlaceLink,
3563
3598
  renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ jsx45("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
3564
3599
  renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ jsx45("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
3565
3600
  song: {
@@ -3589,7 +3624,7 @@ function EntityDetailPanel({
3589
3624
  onExpandedChange: panel.onExpandedChange,
3590
3625
  aside: panel.extraContent,
3591
3626
  edgeTab,
3592
- children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ jsxs32(Fragment16, { children: [
3627
+ children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ jsxs33(Fragment17, { children: [
3593
3628
  panel.content,
3594
3629
  panel.extraContent
3595
3630
  ] }) : panel.content
@@ -3623,4 +3658,4 @@ export {
3623
3658
  GenreTreeViewSkeleton2 as GenreTreeViewSkeleton,
3624
3659
  GenreTreeOutlineSkeleton
3625
3660
  };
3626
- //# sourceMappingURL=chunk-GR4PCPCU.js.map
3661
+ //# sourceMappingURL=chunk-PVYUC2PN.js.map