@behindthemusictree/app-kit-ui 40.0.0 → 41.0.0
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/dist/{chunk-I2TEOHVG.js → chunk-GR4PCPCU.js} +295 -279
- package/dist/chunk-GR4PCPCU.js.map +1 -0
- package/dist/genre-tree/index.cjs +345 -331
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +7 -3
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +345 -331
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-I2TEOHVG.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -591,11 +591,12 @@ function AuthCallbackHandler({ renderStatus, ...options }) {
|
|
|
591
591
|
// src/genre-tree/GenreTreeView.tsx
|
|
592
592
|
var import_react19 = require("react");
|
|
593
593
|
var import_react_query3 = require("@tanstack/react-query");
|
|
594
|
+
var import_lucide_react17 = require("lucide-react");
|
|
594
595
|
var import_lucide_react18 = require("lucide-react");
|
|
595
|
-
var import_lucide_react19 = require("lucide-react");
|
|
596
596
|
var import_ui24 = require("@behindthemusictree/ui");
|
|
597
597
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
598
598
|
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
599
|
+
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
599
600
|
var import_popup5 = require("@behindthemusictree/app-kit/popup");
|
|
600
601
|
|
|
601
602
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
@@ -626,6 +627,21 @@ function toTreeNodes(genrePlaylists, sizeMetric, focusUuids) {
|
|
|
626
627
|
}));
|
|
627
628
|
}
|
|
628
629
|
|
|
630
|
+
// src/genre-tree/playlist-tree/toGenreNodeStyles.ts
|
|
631
|
+
function toGenreNodeStyles(relations, genrePlaylists) {
|
|
632
|
+
const styles = /* @__PURE__ */ new Map();
|
|
633
|
+
if (!relations) return styles;
|
|
634
|
+
const genreUuidByPlaylistUuid = new Map(
|
|
635
|
+
genrePlaylists.flatMap((genrePlaylist) => genrePlaylist.criteria ? [[genrePlaylist.uuid, genrePlaylist.criteria.uuid]] : [])
|
|
636
|
+
);
|
|
637
|
+
const drawn = [relations, relations.parentNode, ...relations.childNodes, ...relations.ancestorNodes];
|
|
638
|
+
for (const entry of drawn) {
|
|
639
|
+
const genreUuid = entry && genreUuidByPlaylistUuid.get(entry.node.id);
|
|
640
|
+
if (entry && genreUuid) styles.set(genreUuid, { fill: entry.fill, textColor: entry.textColor });
|
|
641
|
+
}
|
|
642
|
+
return styles;
|
|
643
|
+
}
|
|
644
|
+
|
|
629
645
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
630
646
|
var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
|
|
631
647
|
var import_react4 = require("react");
|
|
@@ -1685,6 +1701,29 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1685
1701
|
] });
|
|
1686
1702
|
}
|
|
1687
1703
|
|
|
1704
|
+
// src/genre-tree/CommonsPhoto.tsx
|
|
1705
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1706
|
+
function ExternalLink({ href, children }) {
|
|
1707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
1708
|
+
}
|
|
1709
|
+
function CommonsPhoto({
|
|
1710
|
+
image,
|
|
1711
|
+
alt,
|
|
1712
|
+
creditLabel = "Photo"
|
|
1713
|
+
}) {
|
|
1714
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("figure", { className: "flex flex-col gap-1.5", children: [
|
|
1715
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("img", { src: image.url, alt, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
1716
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
1717
|
+
creditLabel,
|
|
1718
|
+
": ",
|
|
1719
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
1720
|
+
",",
|
|
1721
|
+
" ",
|
|
1722
|
+
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
1723
|
+
] })
|
|
1724
|
+
] });
|
|
1725
|
+
}
|
|
1726
|
+
|
|
1688
1727
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1689
1728
|
var import_react13 = require("react");
|
|
1690
1729
|
var import_react_query = require("@tanstack/react-query");
|
|
@@ -1707,15 +1746,15 @@ var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1707
1746
|
|
|
1708
1747
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1709
1748
|
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1710
|
-
var
|
|
1749
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1711
1750
|
function MusicBrainzRecordingLink({
|
|
1712
1751
|
song,
|
|
1713
1752
|
children,
|
|
1714
1753
|
className: className2 = ""
|
|
1715
1754
|
}) {
|
|
1716
1755
|
const url = (0, import_genre_tree11.musicBrainzRecordingUrl)(song);
|
|
1717
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1718
|
-
return /* @__PURE__ */ (0,
|
|
1756
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_jsx_runtime33.Fragment, { children });
|
|
1757
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1719
1758
|
"a",
|
|
1720
1759
|
{
|
|
1721
1760
|
href: url,
|
|
@@ -1732,7 +1771,7 @@ function MusicBrainzRecordingLink({
|
|
|
1732
1771
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1733
1772
|
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1734
1773
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1735
|
-
var
|
|
1774
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1736
1775
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1737
1776
|
var SongPageSchema = (0, import_transport5.PaginatedResponseSchema)(import_genre_tree15.SongDetailedSchema).extend({
|
|
1738
1777
|
overallTotal: import_zod.z.number().nullable(),
|
|
@@ -1819,35 +1858,35 @@ function GenrePlaylistTracks({
|
|
|
1819
1858
|
started.catch((error) => {
|
|
1820
1859
|
console.error("Failed to play genre playlist:", error);
|
|
1821
1860
|
if (error instanceof import_genre_tree16.TracksFailureAlreadyReportedError) return;
|
|
1822
|
-
showPopup(/* @__PURE__ */ (0,
|
|
1861
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport7.AppError ? error.code : import_transport7.ErrorCode.CLIENT_UNKNOWN }));
|
|
1823
1862
|
});
|
|
1824
1863
|
};
|
|
1825
|
-
return /* @__PURE__ */ (0,
|
|
1864
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui11.PanelSection, { title: `${(0, import_track_noun2.capitalize)(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { children: [
|
|
1826
1865
|
renderTracksToolbar?.(),
|
|
1827
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0,
|
|
1866
|
+
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: "\u2014" }) : isPending ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui11.Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("p", { role: "alert", children: [
|
|
1828
1867
|
"Couldn't load ",
|
|
1829
1868
|
trackNoun.plural,
|
|
1830
1869
|
".",
|
|
1831
1870
|
" ",
|
|
1832
|
-
/* @__PURE__ */ (0,
|
|
1833
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0,
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1872
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1834
1873
|
tracks.map((track, index) => {
|
|
1835
1874
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1836
1875
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1837
1876
|
const isPlaying = isCurrent && playState === import_player6.PlayStates.PLAYING;
|
|
1838
|
-
const text = /* @__PURE__ */ (0,
|
|
1839
|
-
/* @__PURE__ */ (0,
|
|
1840
|
-
track.artists?.length ? /* @__PURE__ */ (0,
|
|
1841
|
-
/* @__PURE__ */ (0,
|
|
1842
|
-
track.album && /* @__PURE__ */ (0,
|
|
1877
|
+
const text = /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1878
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree15.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1879
|
+
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1880
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_genre_tree17.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1881
|
+
track.album && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1843
1882
|
] });
|
|
1844
1883
|
const leading = renderSongLeading?.(track, index);
|
|
1845
1884
|
const actions = renderSongActions?.(track);
|
|
1846
1885
|
const isUnplayable = (0, import_genre_tree15.isSong)(track) && (0, import_genre_tree15.songUnplayableReason)(track) !== null;
|
|
1847
1886
|
if (isUnplayable) {
|
|
1848
|
-
return /* @__PURE__ */ (0,
|
|
1887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1849
1888
|
leading,
|
|
1850
|
-
/* @__PURE__ */ (0,
|
|
1889
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1851
1890
|
"button",
|
|
1852
1891
|
{
|
|
1853
1892
|
type: "button",
|
|
@@ -1855,27 +1894,27 @@ function GenrePlaylistTracks({
|
|
|
1855
1894
|
"aria-disabled": "true",
|
|
1856
1895
|
"aria-label": label,
|
|
1857
1896
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1858
|
-
children: /* @__PURE__ */ (0,
|
|
1897
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1859
1898
|
}
|
|
1860
1899
|
),
|
|
1861
1900
|
text,
|
|
1862
1901
|
actions
|
|
1863
1902
|
] }, track.uuid);
|
|
1864
1903
|
}
|
|
1865
|
-
return /* @__PURE__ */ (0,
|
|
1904
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1866
1905
|
"li",
|
|
1867
1906
|
{
|
|
1868
1907
|
className: `group flex min-h-8 items-center gap-1 rounded px-1 hover:bg-[var(--color-neutral-100)] ${isCurrent ? "font-medium text-[var(--color-primary)]" : ""}`,
|
|
1869
1908
|
children: [
|
|
1870
1909
|
leading,
|
|
1871
|
-
/* @__PURE__ */ (0,
|
|
1910
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1872
1911
|
"button",
|
|
1873
1912
|
{
|
|
1874
1913
|
type: "button",
|
|
1875
1914
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1876
1915
|
className: `flex h-6 w-6 shrink-0 items-center justify-center rounded-full cursor-pointer group-hover:opacity-100 focus-visible:opacity-100 ${isCurrent && playState !== import_player6.PlayStates.STOPPED ? "opacity-100" : "opacity-0 [@media(pointer:coarse)]:opacity-100"}`,
|
|
1877
1916
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1878
|
-
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0,
|
|
1917
|
+
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui11.RingLoader, { size: 10 }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_fa4.FaPause, { size: 10 }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1879
1918
|
}
|
|
1880
1919
|
),
|
|
1881
1920
|
text,
|
|
@@ -1885,7 +1924,7 @@ function GenrePlaylistTracks({
|
|
|
1885
1924
|
track.uuid
|
|
1886
1925
|
);
|
|
1887
1926
|
}),
|
|
1888
|
-
hasNextPage && /* @__PURE__ */ (0,
|
|
1927
|
+
hasNextPage && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1889
1928
|
] })
|
|
1890
1929
|
] }) });
|
|
1891
1930
|
}
|
|
@@ -1893,7 +1932,7 @@ function GenrePlaylistTracks({
|
|
|
1893
1932
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1894
1933
|
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
1895
1934
|
var import_si2 = require("react-icons/si");
|
|
1896
|
-
var
|
|
1935
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
1897
1936
|
function GenreDetailExtras({
|
|
1898
1937
|
genreUuid,
|
|
1899
1938
|
genrePlaylist,
|
|
@@ -1919,17 +1958,18 @@ function GenreDetailExtras({
|
|
|
1919
1958
|
criteriaOverviewSchema
|
|
1920
1959
|
);
|
|
1921
1960
|
if (isPending) {
|
|
1922
|
-
return /* @__PURE__ */ (0,
|
|
1923
|
-
/* @__PURE__ */ (0,
|
|
1961
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
1962
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui12.PanelSection, { title: "Summary", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui12.Skeleton, { className: "h-4 w-3/4" }) }) }),
|
|
1924
1963
|
family
|
|
1925
1964
|
] });
|
|
1926
1965
|
}
|
|
1927
|
-
if (!overview) return /* @__PURE__ */ (0,
|
|
1928
|
-
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1966
|
+
if (!overview) return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_jsx_runtime35.Fragment, { children: family });
|
|
1967
|
+
const { summary, summarySourceUrl, essentialSongs, image } = overview;
|
|
1929
1968
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1930
|
-
return /* @__PURE__ */ (0,
|
|
1931
|
-
|
|
1932
|
-
|
|
1969
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
1970
|
+
image && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(CommonsPhoto, { image, alt: overview.name, creditLabel: "Image" }),
|
|
1971
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui12.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1972
|
+
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
1933
1973
|
"a",
|
|
1934
1974
|
{
|
|
1935
1975
|
href: summarySourceUrl,
|
|
@@ -1937,12 +1977,12 @@ function GenreDetailExtras({
|
|
|
1937
1977
|
rel: "noopener noreferrer",
|
|
1938
1978
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1939
1979
|
children: [
|
|
1940
|
-
/* @__PURE__ */ (0,
|
|
1980
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_si2.SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1941
1981
|
"Wikipedia"
|
|
1942
1982
|
]
|
|
1943
1983
|
}
|
|
1944
1984
|
),
|
|
1945
|
-
wikidataUrl && /* @__PURE__ */ (0,
|
|
1985
|
+
wikidataUrl && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(
|
|
1946
1986
|
"a",
|
|
1947
1987
|
{
|
|
1948
1988
|
href: wikidataUrl,
|
|
@@ -1950,17 +1990,17 @@ function GenreDetailExtras({
|
|
|
1950
1990
|
rel: "noopener noreferrer",
|
|
1951
1991
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1952
1992
|
children: [
|
|
1953
|
-
/* @__PURE__ */ (0,
|
|
1993
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_si2.SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1954
1994
|
"Wikidata"
|
|
1955
1995
|
]
|
|
1956
1996
|
}
|
|
1957
1997
|
)
|
|
1958
1998
|
] }) }),
|
|
1959
|
-
/* @__PURE__ */ (0,
|
|
1999
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui12.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1960
2000
|
family,
|
|
1961
2001
|
renderGenreDetailExtras?.(overview),
|
|
1962
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0,
|
|
1963
|
-
/* @__PURE__ */ (0,
|
|
2002
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui12.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
2003
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
1964
2004
|
GenrePlaylistTracks,
|
|
1965
2005
|
{
|
|
1966
2006
|
genreUuid,
|
|
@@ -1978,10 +2018,10 @@ function GenreDetailExtras({
|
|
|
1978
2018
|
}
|
|
1979
2019
|
|
|
1980
2020
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1981
|
-
var
|
|
2021
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
1982
2022
|
var import_react14 = require("react");
|
|
1983
2023
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
1984
|
-
return /* @__PURE__ */ (0,
|
|
2024
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(GenrePlayActions, { genrePlaylist, playback }) });
|
|
1985
2025
|
}
|
|
1986
2026
|
function GenreInfoPanelBody({
|
|
1987
2027
|
toolbar,
|
|
@@ -1998,9 +2038,9 @@ function GenreInfoPanelBody({
|
|
|
1998
2038
|
}) {
|
|
1999
2039
|
const summary = scope === "reference" ? import_genre_tree19.GenreCatalogueCountsSchema.parse(genrePlaylist ?? catalogue) : void 0;
|
|
2000
2040
|
const selection = summary ? (0, import_genre_tree19.defaultGenreMusicSelection)(summary) : void 0;
|
|
2001
|
-
return /* @__PURE__ */ (0,
|
|
2041
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
2002
2042
|
toolbar,
|
|
2003
|
-
genrePlaylist ? /* @__PURE__ */ (0,
|
|
2043
|
+
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(GenreActionBand, { ...band }),
|
|
2004
2044
|
/* @__PURE__ */ (0, import_react14.createElement)(
|
|
2005
2045
|
GenreDetailExtras,
|
|
2006
2046
|
{
|
|
@@ -2020,7 +2060,7 @@ function GenreInfoPanelBody({
|
|
|
2020
2060
|
}
|
|
2021
2061
|
|
|
2022
2062
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
2023
|
-
var
|
|
2063
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2024
2064
|
var RELATIVE_ITEM_COUNT = 1;
|
|
2025
2065
|
function toNode(genre, parentId) {
|
|
2026
2066
|
return {
|
|
@@ -2043,27 +2083,21 @@ function useGenreDetailContent({
|
|
|
2043
2083
|
trailing,
|
|
2044
2084
|
genrePlaylist: hostPlaylist,
|
|
2045
2085
|
expanded,
|
|
2046
|
-
|
|
2086
|
+
treeStyles
|
|
2047
2087
|
}) {
|
|
2048
|
-
const
|
|
2088
|
+
const result = (0, import_genre_tree20.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
2089
|
+
const detail = result.status === "success" ? result.genre : void 0;
|
|
2049
2090
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: [], artist: extras?.artist });
|
|
2050
2091
|
const playback = hostPlayback ?? defaultPlayback;
|
|
2051
2092
|
const view = (0, import_react15.useMemo)(() => {
|
|
2052
2093
|
if (!detail) return null;
|
|
2053
2094
|
const rootColor = (0, import_genre_tree_view4.getGenreTreeColor)(detail.root.wikidataId);
|
|
2054
|
-
const treeStyles = /* @__PURE__ */ new Map();
|
|
2055
|
-
if (treeRelations) {
|
|
2056
|
-
const drawn = [treeRelations, treeRelations.parentNode, ...treeRelations.childNodes, ...treeRelations.ancestorNodes];
|
|
2057
|
-
for (const entry of drawn) {
|
|
2058
|
-
if (entry) treeStyles.set(entry.node.id, { fill: entry.fill, textColor: entry.textColor });
|
|
2059
|
-
}
|
|
2060
|
-
}
|
|
2061
2095
|
const relative = (genre, parentId) => ({
|
|
2062
2096
|
node: toNode(genre, parentId),
|
|
2063
|
-
...treeStyles
|
|
2097
|
+
...treeStyles?.get(genre.uuid) ?? { fill: (0, import_genre_tree_view4.tintSurface)(rootColor), textColor: import_genre_tree_view4.TEXT_COLOR }
|
|
2064
2098
|
});
|
|
2065
2099
|
const ancestors2 = [...detail.ascendants].sort((a, b) => b.degree - a.degree);
|
|
2066
|
-
const own = treeStyles
|
|
2100
|
+
const own = treeStyles?.get(detail.uuid) ?? { fill: rootColor, textColor: (0, import_genre_tree_view4.getTextColorOnFill)(rootColor) };
|
|
2067
2101
|
return {
|
|
2068
2102
|
node: {
|
|
2069
2103
|
id: detail.uuid,
|
|
@@ -2080,23 +2114,28 @@ function useGenreDetailContent({
|
|
|
2080
2114
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
2081
2115
|
)
|
|
2082
2116
|
};
|
|
2083
|
-
}, [detail, scope,
|
|
2084
|
-
if (
|
|
2117
|
+
}, [detail, scope, treeStyles]);
|
|
2118
|
+
if (result.status === "not-found") return {
|
|
2119
|
+
name: null,
|
|
2120
|
+
title: "Genre not found",
|
|
2121
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This genre does not exist." })
|
|
2122
|
+
};
|
|
2123
|
+
if (result.status === "error") return {
|
|
2085
2124
|
name: null,
|
|
2086
2125
|
title: "Genre unavailable",
|
|
2087
|
-
content: /* @__PURE__ */ (0,
|
|
2126
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { role: "alert", className: "text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
2088
2127
|
};
|
|
2089
|
-
if (
|
|
2128
|
+
if (!detail || !view) return {
|
|
2090
2129
|
name: null,
|
|
2091
2130
|
title: "Loading genre\u2026",
|
|
2092
|
-
content: /* @__PURE__ */ (0,
|
|
2093
|
-
/* @__PURE__ */ (0,
|
|
2094
|
-
/* @__PURE__ */ (0,
|
|
2095
|
-
/* @__PURE__ */ (0,
|
|
2131
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
2132
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui13.Skeleton, { className: "h-6 w-2/3" }),
|
|
2133
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui13.Skeleton, { className: "h-4 w-full" }),
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui13.Skeleton, { className: "h-4 w-3/4" })
|
|
2096
2135
|
] })
|
|
2097
2136
|
};
|
|
2098
2137
|
const selectGenre = (nodeId) => onSelectGenre(import_genre_tree20.GenreUuidSchema.parse(nodeId));
|
|
2099
|
-
const family = /* @__PURE__ */ (0,
|
|
2138
|
+
const family = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2100
2139
|
import_genre_tree_view4.GenreNodeFamily,
|
|
2101
2140
|
{
|
|
2102
2141
|
node: view.node,
|
|
@@ -2107,17 +2146,17 @@ function useGenreDetailContent({
|
|
|
2107
2146
|
onSelectNode: selectGenre
|
|
2108
2147
|
}
|
|
2109
2148
|
);
|
|
2110
|
-
const ancestors = /* @__PURE__ */ (0,
|
|
2149
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
2111
2150
|
return {
|
|
2112
2151
|
name: detail.name,
|
|
2113
2152
|
title: detail.name,
|
|
2114
2153
|
headerAccent: { background: view.fill, color: view.textColor },
|
|
2115
2154
|
aside: expanded ? ancestors : void 0,
|
|
2116
|
-
content: /* @__PURE__ */ (0,
|
|
2117
|
-
/* @__PURE__ */ (0,
|
|
2155
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2118
2157
|
GenreInfoPanelBody,
|
|
2119
2158
|
{
|
|
2120
|
-
family: /* @__PURE__ */ (0,
|
|
2159
|
+
family: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_jsx_runtime37.Fragment, { children: [
|
|
2121
2160
|
family,
|
|
2122
2161
|
!expanded && ancestors
|
|
2123
2162
|
] }),
|
|
@@ -2161,7 +2200,7 @@ function GenreDetailPanel({
|
|
|
2161
2200
|
expanded,
|
|
2162
2201
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
2163
2202
|
});
|
|
2164
|
-
return /* @__PURE__ */ (0,
|
|
2203
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2165
2204
|
import_ui13.DetailPanel,
|
|
2166
2205
|
{
|
|
2167
2206
|
side: "left",
|
|
@@ -2174,7 +2213,7 @@ function GenreDetailPanel({
|
|
|
2174
2213
|
edgeTab,
|
|
2175
2214
|
aside: panel.aside,
|
|
2176
2215
|
titleInSearch,
|
|
2177
|
-
headerActions: onExpandedChange ? /* @__PURE__ */ (0,
|
|
2216
|
+
headerActions: onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui13.IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react13.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react13.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
2178
2217
|
children: panel.content
|
|
2179
2218
|
}
|
|
2180
2219
|
);
|
|
@@ -2183,7 +2222,7 @@ function GenreDetailPanel({
|
|
|
2183
2222
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
2184
2223
|
var import_react16 = require("react");
|
|
2185
2224
|
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2186
|
-
var
|
|
2225
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2187
2226
|
function ChangeParentPopup({
|
|
2188
2227
|
genrePlaylist,
|
|
2189
2228
|
genrePlaylists,
|
|
@@ -2218,12 +2257,12 @@ function ChangeParentPopup({
|
|
|
2218
2257
|
window.addEventListener("keydown", handleKeyDown);
|
|
2219
2258
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2220
2259
|
}, [onClose]);
|
|
2221
|
-
return /* @__PURE__ */ (0,
|
|
2222
|
-
/* @__PURE__ */ (0,
|
|
2260
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
2261
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
2223
2262
|
"Current parent: ",
|
|
2224
2263
|
genrePlaylist.parent?.name ?? "none"
|
|
2225
2264
|
] }),
|
|
2226
|
-
/* @__PURE__ */ (0,
|
|
2265
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2227
2266
|
GenreSearch,
|
|
2228
2267
|
{
|
|
2229
2268
|
genrePlaylists: candidates,
|
|
@@ -2231,7 +2270,7 @@ function ChangeParentPopup({
|
|
|
2231
2270
|
placeholder: "Search a new parent\u2026"
|
|
2232
2271
|
}
|
|
2233
2272
|
) }),
|
|
2234
|
-
formErrors.length > 0 && /* @__PURE__ */ (0,
|
|
2273
|
+
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
2235
2274
|
] });
|
|
2236
2275
|
}
|
|
2237
2276
|
|
|
@@ -2244,7 +2283,7 @@ var import_lucide_react14 = require("lucide-react");
|
|
|
2244
2283
|
var import_ui14 = require("@behindthemusictree/ui");
|
|
2245
2284
|
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2246
2285
|
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2247
|
-
var
|
|
2286
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2248
2287
|
function ArtistActionBand({ artist, share }) {
|
|
2249
2288
|
const { trackList, playNewTrackListFromArtist } = (0, import_genre_tree22.useTrackList)();
|
|
2250
2289
|
const { isPlaying, setIsPlaying } = (0, import_player7.usePlayer)();
|
|
@@ -2260,11 +2299,11 @@ function ArtistActionBand({ artist, share }) {
|
|
|
2260
2299
|
console.error("Failed to load artist tracks:", error);
|
|
2261
2300
|
});
|
|
2262
2301
|
};
|
|
2263
|
-
return /* @__PURE__ */ (0,
|
|
2264
|
-
/* @__PURE__ */ (0,
|
|
2302
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui14.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_ui14.ActionBand, { children: [
|
|
2303
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2265
2304
|
import_ui14.ActionButton,
|
|
2266
2305
|
{
|
|
2267
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
2306
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react14.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react14.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2268
2307
|
label: playing ? "Pause" : "Play",
|
|
2269
2308
|
caption: String(artist.playableTracksCount),
|
|
2270
2309
|
disabled: artist.playableTracksCount === 0,
|
|
@@ -2283,7 +2322,7 @@ var import_ui16 = require("@behindthemusictree/ui");
|
|
|
2283
2322
|
var import_lucide_react15 = require("lucide-react");
|
|
2284
2323
|
var import_si3 = require("react-icons/si");
|
|
2285
2324
|
var import_ui15 = require("@behindthemusictree/ui");
|
|
2286
|
-
var
|
|
2325
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2287
2326
|
var LINK_KINDS = {
|
|
2288
2327
|
official: { label: "Official website", Icon: import_lucide_react15.Globe },
|
|
2289
2328
|
wikipedia: { label: "Wikipedia", Icon: import_si3.SiWikipedia },
|
|
@@ -2320,7 +2359,7 @@ function artistLinks(artist) {
|
|
|
2320
2359
|
return links;
|
|
2321
2360
|
}
|
|
2322
2361
|
function ArtistLinks({ links }) {
|
|
2323
|
-
return /* @__PURE__ */ (0,
|
|
2362
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui15.Chip, { href: url, icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
2324
2363
|
}
|
|
2325
2364
|
|
|
2326
2365
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -2331,7 +2370,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
2331
2370
|
}
|
|
2332
2371
|
|
|
2333
2372
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2334
|
-
var
|
|
2373
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2335
2374
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
2336
2375
|
function ArtistHeader({ artist }) {
|
|
2337
2376
|
const fields = [];
|
|
@@ -2341,35 +2380,23 @@ function ArtistHeader({ artist }) {
|
|
|
2341
2380
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
2342
2381
|
if (years) fields.push({ label: "Active", value: years });
|
|
2343
2382
|
const links = artistLinks(artist);
|
|
2344
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0,
|
|
2383
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistLinks, { links }) });
|
|
2345
2384
|
if (fields.length === 0) return null;
|
|
2346
|
-
return /* @__PURE__ */ (0,
|
|
2385
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui16.FieldList, { items: fields });
|
|
2347
2386
|
}
|
|
2348
2387
|
|
|
2349
2388
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
2350
|
-
var
|
|
2351
|
-
function ExternalLink({ href, children }) {
|
|
2352
|
-
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
2353
|
-
}
|
|
2389
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2354
2390
|
function ArtistPhoto({ image, name }) {
|
|
2355
|
-
return /* @__PURE__ */ (0,
|
|
2356
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
2357
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2358
|
-
"Photo: ",
|
|
2359
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2360
|
-
",",
|
|
2361
|
-
" ",
|
|
2362
|
-
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
2363
|
-
] })
|
|
2364
|
-
] });
|
|
2391
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(CommonsPhoto, { image, alt: name });
|
|
2365
2392
|
}
|
|
2366
2393
|
|
|
2367
2394
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2368
2395
|
var import_ui17 = require("@behindthemusictree/ui");
|
|
2369
|
-
var
|
|
2396
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2370
2397
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2371
2398
|
if (memberships.length === 0) return null;
|
|
2372
|
-
return /* @__PURE__ */ (0,
|
|
2399
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui17.PanelGroup, { title, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { children: memberships.map((membership, index) => {
|
|
2373
2400
|
const details = [
|
|
2374
2401
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2375
2402
|
...membership.roles
|
|
@@ -2377,9 +2404,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2377
2404
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
2378
2405
|
return (
|
|
2379
2406
|
// A member can have several periods in the same group.
|
|
2380
|
-
/* @__PURE__ */ (0,
|
|
2381
|
-
/* @__PURE__ */ (0,
|
|
2382
|
-
detailsText && /* @__PURE__ */ (0,
|
|
2407
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
2408
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
2409
|
+
detailsText && /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2383
2410
|
" \u2014 ",
|
|
2384
2411
|
detailsText
|
|
2385
2412
|
] })
|
|
@@ -2390,9 +2417,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2390
2417
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2391
2418
|
if (memberships.length === 0) return null;
|
|
2392
2419
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2393
|
-
return /* @__PURE__ */ (0,
|
|
2394
|
-
/* @__PURE__ */ (0,
|
|
2395
|
-
/* @__PURE__ */ (0,
|
|
2420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_ui17.PanelSection, { title, children: [
|
|
2421
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2422
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2396
2423
|
MembershipList,
|
|
2397
2424
|
{
|
|
2398
2425
|
title: "Past",
|
|
@@ -2405,7 +2432,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2405
2432
|
|
|
2406
2433
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2407
2434
|
var import_ui18 = require("@behindthemusictree/ui");
|
|
2408
|
-
var
|
|
2435
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2409
2436
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2410
2437
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
2411
2438
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -2425,12 +2452,12 @@ function byYear(a, b) {
|
|
|
2425
2452
|
function ArtistDiscography({ albums }) {
|
|
2426
2453
|
if (albums.length === 0) return null;
|
|
2427
2454
|
const sorted = [...albums].sort(byYear);
|
|
2428
|
-
return /* @__PURE__ */ (0,
|
|
2455
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_ui18.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2429
2456
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2430
2457
|
if (groupAlbums.length === 0) return null;
|
|
2431
|
-
return /* @__PURE__ */ (0,
|
|
2432
|
-
/* @__PURE__ */ (0,
|
|
2433
|
-
/* @__PURE__ */ (0,
|
|
2458
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_ui18.PanelGroup, { title: group, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
2459
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2460
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2434
2461
|
] }, album.uuid)) }) }, group);
|
|
2435
2462
|
}) });
|
|
2436
2463
|
}
|
|
@@ -2438,7 +2465,6 @@ function ArtistDiscography({ albums }) {
|
|
|
2438
2465
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2439
2466
|
var import_react17 = require("react");
|
|
2440
2467
|
var import_react_query2 = require("@tanstack/react-query");
|
|
2441
|
-
var import_lucide_react16 = require("lucide-react");
|
|
2442
2468
|
var import_ui19 = require("@behindthemusictree/ui");
|
|
2443
2469
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2444
2470
|
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -2452,7 +2478,7 @@ var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
2452
2478
|
var import_fa5 = require("react-icons/fa");
|
|
2453
2479
|
var import_player8 = require("@behindthemusictree/app-kit/player");
|
|
2454
2480
|
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2455
|
-
var
|
|
2481
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2456
2482
|
function TrackPositionPlayPause({
|
|
2457
2483
|
position,
|
|
2458
2484
|
uuid,
|
|
@@ -2466,14 +2492,14 @@ function TrackPositionPlayPause({
|
|
|
2466
2492
|
const isPlaying = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PLAYING;
|
|
2467
2493
|
const isPaused = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PAUSED;
|
|
2468
2494
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
2469
|
-
return /* @__PURE__ */ (0,
|
|
2495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2470
2496
|
"div",
|
|
2471
2497
|
{
|
|
2472
2498
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
2473
2499
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
2474
2500
|
onClick: handlePlayPauseClick,
|
|
2475
2501
|
children: [
|
|
2476
|
-
/* @__PURE__ */ (0,
|
|
2502
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2477
2503
|
"span",
|
|
2478
2504
|
{
|
|
2479
2505
|
className: "track-position-play-pause__bars",
|
|
@@ -2481,18 +2507,18 @@ function TrackPositionPlayPause({
|
|
|
2481
2507
|
role: "img",
|
|
2482
2508
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
2483
2509
|
children: [
|
|
2484
|
-
/* @__PURE__ */ (0,
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
2486
|
-
/* @__PURE__ */ (0,
|
|
2510
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2511
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2512
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "track-position-play-pause__bar" })
|
|
2487
2513
|
]
|
|
2488
2514
|
}
|
|
2489
2515
|
) : position }),
|
|
2490
|
-
/* @__PURE__ */ (0,
|
|
2516
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2491
2517
|
"div",
|
|
2492
2518
|
{
|
|
2493
2519
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
2494
2520
|
"aria-hidden": "true",
|
|
2495
|
-
children: isAwaitingPlayback ? /* @__PURE__ */ (0,
|
|
2521
|
+
children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("span", { className: "track-position-play-pause__spinner" }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_fa5.FaPause, {}) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_fa5.FaPlay, {})
|
|
2496
2522
|
}
|
|
2497
2523
|
)
|
|
2498
2524
|
]
|
|
@@ -2503,7 +2529,7 @@ function TrackPositionPlayPause({
|
|
|
2503
2529
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2504
2530
|
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2505
2531
|
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2506
|
-
var
|
|
2532
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2507
2533
|
function TrackItem({
|
|
2508
2534
|
track,
|
|
2509
2535
|
position,
|
|
@@ -2527,12 +2553,12 @@ function TrackItem({
|
|
|
2527
2553
|
loadTrackForPlayer(track.uuid);
|
|
2528
2554
|
}
|
|
2529
2555
|
};
|
|
2530
|
-
return /* @__PURE__ */ (0,
|
|
2556
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2531
2557
|
"div",
|
|
2532
2558
|
{
|
|
2533
2559
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
2534
2560
|
children: [
|
|
2535
|
-
isUnplayable ? /* @__PURE__ */ (0,
|
|
2561
|
+
isUnplayable ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2536
2562
|
"div",
|
|
2537
2563
|
{
|
|
2538
2564
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -2540,7 +2566,7 @@ function TrackItem({
|
|
|
2540
2566
|
"aria-disabled": "true",
|
|
2541
2567
|
children: position
|
|
2542
2568
|
}
|
|
2543
|
-
) : /* @__PURE__ */ (0,
|
|
2569
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2544
2570
|
TrackPositionPlayPause,
|
|
2545
2571
|
{
|
|
2546
2572
|
position,
|
|
@@ -2549,12 +2575,12 @@ function TrackItem({
|
|
|
2549
2575
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
2550
2576
|
}
|
|
2551
2577
|
),
|
|
2552
|
-
/* @__PURE__ */ (0,
|
|
2553
|
-
/* @__PURE__ */ (0,
|
|
2554
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0,
|
|
2578
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2579
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree24.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2580
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_genre_tree25.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2555
2581
|
] }),
|
|
2556
|
-
/* @__PURE__ */ (0,
|
|
2557
|
-
renderDuration && /* @__PURE__ */ (0,
|
|
2582
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "genre-name-container flex items-center justify-start w-[21.6%] min-w-0 shrink-0", children: track.genre ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2583
|
+
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2558
2584
|
"div",
|
|
2559
2585
|
{
|
|
2560
2586
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -2562,14 +2588,14 @@ function TrackItem({
|
|
|
2562
2588
|
children: renderDuration(track)
|
|
2563
2589
|
}
|
|
2564
2590
|
),
|
|
2565
|
-
renderActions && /* @__PURE__ */ (0,
|
|
2591
|
+
renderActions && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "edit flex text-base w-6 items-center justify-center mr-2 cursor-pointer", children: renderActions(track) })
|
|
2566
2592
|
]
|
|
2567
2593
|
}
|
|
2568
2594
|
);
|
|
2569
2595
|
}
|
|
2570
2596
|
|
|
2571
2597
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2572
|
-
var
|
|
2598
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2573
2599
|
var SongPageSchema2 = (0, import_transport8.PaginatedResponseSchema)(import_genre_tree26.SongDetailedSchema);
|
|
2574
2600
|
var SORTS = [
|
|
2575
2601
|
{ ordering: "title", label: "Title" },
|
|
@@ -2602,36 +2628,22 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2602
2628
|
event.stopPropagation();
|
|
2603
2629
|
void play(song.uuid);
|
|
2604
2630
|
};
|
|
2605
|
-
return /* @__PURE__ */ (0,
|
|
2606
|
-
/* @__PURE__ */ (0,
|
|
2607
|
-
|
|
2608
|
-
|
|
2609
|
-
|
|
2610
|
-
|
|
2611
|
-
|
|
2612
|
-
|
|
2613
|
-
|
|
2614
|
-
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react16.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2615
|
-
"Play all"
|
|
2616
|
-
]
|
|
2617
|
-
}
|
|
2618
|
-
),
|
|
2619
|
-
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2620
|
-
"button",
|
|
2621
|
-
{
|
|
2622
|
-
type: "button",
|
|
2623
|
-
"aria-pressed": ordering === sort.ordering,
|
|
2624
|
-
onClick: () => {
|
|
2625
|
-
setOrdering(sort.ordering);
|
|
2626
|
-
setPage(1);
|
|
2627
|
-
},
|
|
2628
|
-
className: "px-2.5 py-0.5 text-[var(--color-text)] rounded-full hover:bg-[var(--color-surface-muted)] aria-pressed:bg-gray-900 aria-pressed:text-white",
|
|
2629
|
-
children: sort.label
|
|
2631
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui19.PanelSection, { title: "Songs", children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui19.Skeleton, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
|
|
2632
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-2 mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2633
|
+
"button",
|
|
2634
|
+
{
|
|
2635
|
+
type: "button",
|
|
2636
|
+
"aria-pressed": ordering === sort.ordering,
|
|
2637
|
+
onClick: () => {
|
|
2638
|
+
setOrdering(sort.ordering);
|
|
2639
|
+
setPage(1);
|
|
2630
2640
|
},
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2641
|
+
className: "px-2.5 py-0.5 text-[var(--color-text)] rounded-full hover:bg-[var(--color-surface-muted)] aria-pressed:bg-gray-900 aria-pressed:text-white",
|
|
2642
|
+
children: sort.label
|
|
2643
|
+
},
|
|
2644
|
+
sort.ordering
|
|
2645
|
+
)) }) }),
|
|
2646
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("ul", { className: "overflow-hidden mb-2 bg-zinc-950 rounded-lg", children: data.results.map((song, index) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("li", { onClickCapture: (event) => handleRowClickCapture(event, song), children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2635
2647
|
TrackItem,
|
|
2636
2648
|
{
|
|
2637
2649
|
track: song,
|
|
@@ -2640,12 +2652,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2640
2652
|
renderSongLink
|
|
2641
2653
|
}
|
|
2642
2654
|
) }, song.uuid)) }),
|
|
2643
|
-
/* @__PURE__ */ (0,
|
|
2655
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui19.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2644
2656
|
] }) });
|
|
2645
2657
|
}
|
|
2646
2658
|
|
|
2647
2659
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2648
|
-
var
|
|
2660
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2649
2661
|
function useArtistPanel({
|
|
2650
2662
|
uuid,
|
|
2651
2663
|
scope,
|
|
@@ -2666,26 +2678,26 @@ function useArtistPanel({
|
|
|
2666
2678
|
return {
|
|
2667
2679
|
...panel,
|
|
2668
2680
|
title: "Artist",
|
|
2669
|
-
content: /* @__PURE__ */ (0,
|
|
2670
|
-
/* @__PURE__ */ (0,
|
|
2671
|
-
/* @__PURE__ */ (0,
|
|
2672
|
-
/* @__PURE__ */ (0,
|
|
2673
|
-
/* @__PURE__ */ (0,
|
|
2674
|
-
/* @__PURE__ */ (0,
|
|
2675
|
-
/* @__PURE__ */ (0,
|
|
2681
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2682
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2683
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui20.Skeleton, { className: "h-4 w-32" }),
|
|
2684
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2685
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui20.Skeleton, { className: "h-4 w-24" }),
|
|
2686
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui20.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2687
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui20.Skeleton, { className: "h-16" })
|
|
2676
2688
|
] })
|
|
2677
2689
|
};
|
|
2678
2690
|
case "not-found":
|
|
2679
2691
|
return {
|
|
2680
2692
|
...panel,
|
|
2681
2693
|
title: "Artist not found",
|
|
2682
|
-
content: /* @__PURE__ */ (0,
|
|
2694
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2683
2695
|
};
|
|
2684
2696
|
case "error":
|
|
2685
2697
|
return {
|
|
2686
2698
|
...panel,
|
|
2687
2699
|
title: "Artist",
|
|
2688
|
-
content: /* @__PURE__ */ (0,
|
|
2700
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2689
2701
|
};
|
|
2690
2702
|
case "success": {
|
|
2691
2703
|
const { artist } = result;
|
|
@@ -2694,19 +2706,19 @@ function useArtistPanel({
|
|
|
2694
2706
|
return {
|
|
2695
2707
|
...panel,
|
|
2696
2708
|
title: artist.name,
|
|
2697
|
-
content: /* @__PURE__ */ (0,
|
|
2698
|
-
/* @__PURE__ */ (0,
|
|
2709
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
2710
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2699
2711
|
ArtistActionBand,
|
|
2700
2712
|
{
|
|
2701
2713
|
artist,
|
|
2702
|
-
share: shareTarget && shareUrl ? /* @__PURE__ */ (0,
|
|
2714
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2703
2715
|
}
|
|
2704
2716
|
),
|
|
2705
|
-
artist.image && /* @__PURE__ */ (0,
|
|
2706
|
-
/* @__PURE__ */ (0,
|
|
2707
|
-
/* @__PURE__ */ (0,
|
|
2708
|
-
/* @__PURE__ */ (0,
|
|
2709
|
-
artist.tracksCount > 0 && /* @__PURE__ */ (0,
|
|
2717
|
+
artist.image && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2718
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ArtistHeader, { artist }),
|
|
2719
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2720
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2721
|
+
artist.tracksCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2710
2722
|
ArtistSongs,
|
|
2711
2723
|
{
|
|
2712
2724
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2716,7 +2728,7 @@ function useArtistPanel({
|
|
|
2716
2728
|
}
|
|
2717
2729
|
)
|
|
2718
2730
|
] }),
|
|
2719
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0,
|
|
2731
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2720
2732
|
};
|
|
2721
2733
|
}
|
|
2722
2734
|
}
|
|
@@ -2728,11 +2740,11 @@ var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
2728
2740
|
|
|
2729
2741
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2730
2742
|
var import_react18 = require("react");
|
|
2731
|
-
var
|
|
2743
|
+
var import_lucide_react16 = require("lucide-react");
|
|
2732
2744
|
var import_ui21 = require("@behindthemusictree/ui");
|
|
2733
2745
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2734
2746
|
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2735
|
-
var
|
|
2747
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2736
2748
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2737
2749
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2738
2750
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
@@ -2740,27 +2752,27 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2740
2752
|
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2741
2753
|
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2742
2754
|
let body = null;
|
|
2743
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0,
|
|
2744
|
-
else if (history.status === "error") body = /* @__PURE__ */ (0,
|
|
2755
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui21.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2756
|
+
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2745
2757
|
else if (history.status === "success")
|
|
2746
|
-
body = history.entries.length === 0 ? /* @__PURE__ */ (0,
|
|
2747
|
-
/* @__PURE__ */ (0,
|
|
2748
|
-
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0,
|
|
2758
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
2759
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2760
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2749
2761
|
" ",
|
|
2750
2762
|
"\u2014 ",
|
|
2751
2763
|
entry.oldValue ?? "none",
|
|
2752
2764
|
" \u2192 ",
|
|
2753
2765
|
entry.newValue ?? "none"
|
|
2754
2766
|
] }) : null,
|
|
2755
|
-
/* @__PURE__ */ (0,
|
|
2767
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2756
2768
|
entry.actorPseudo ?? "Anonymous",
|
|
2757
2769
|
" \xB7 ",
|
|
2758
2770
|
dateFormat.format(new Date(entry.createdOn))
|
|
2759
2771
|
] })
|
|
2760
2772
|
] }, entry.uuid)) });
|
|
2761
|
-
return /* @__PURE__ */ (0,
|
|
2762
|
-
/* @__PURE__ */ (0,
|
|
2763
|
-
/* @__PURE__ */ (0,
|
|
2773
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui21.PanelBleed, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2774
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui21.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2775
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "mt-1.5", children: body })
|
|
2764
2776
|
] }) });
|
|
2765
2777
|
}
|
|
2766
2778
|
function SongPanelContent(props) {
|
|
@@ -2779,13 +2791,13 @@ function SongPanelContent(props) {
|
|
|
2779
2791
|
const genre = song.genre;
|
|
2780
2792
|
fields.push({
|
|
2781
2793
|
label: "Genre",
|
|
2782
|
-
value: onSelectGenre ? /* @__PURE__ */ (0,
|
|
2783
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
2784
|
-
/* @__PURE__ */ (0,
|
|
2794
|
+
value: onSelectGenre ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("span", { children: [
|
|
2795
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2796
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2785
2797
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2786
2798
|
});
|
|
2787
2799
|
} else {
|
|
2788
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */ (0,
|
|
2800
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2789
2801
|
}
|
|
2790
2802
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2791
2803
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2795,11 +2807,11 @@ function SongPanelContent(props) {
|
|
|
2795
2807
|
const links = [];
|
|
2796
2808
|
if (musicBrainzUrl)
|
|
2797
2809
|
links.push(
|
|
2798
|
-
/* @__PURE__ */ (0,
|
|
2810
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2799
2811
|
);
|
|
2800
2812
|
if (song.youtubeVideo)
|
|
2801
2813
|
links.push(
|
|
2802
|
-
/* @__PURE__ */ (0,
|
|
2814
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2803
2815
|
"a",
|
|
2804
2816
|
{
|
|
2805
2817
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2814,31 +2826,31 @@ function SongPanelContent(props) {
|
|
|
2814
2826
|
if (links.length > 0)
|
|
2815
2827
|
fields.push({
|
|
2816
2828
|
label: "Links",
|
|
2817
|
-
value: /* @__PURE__ */ (0,
|
|
2829
|
+
value: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex gap-3", children: links })
|
|
2818
2830
|
});
|
|
2819
|
-
return /* @__PURE__ */ (0,
|
|
2820
|
-
/* @__PURE__ */ (0,
|
|
2821
|
-
/* @__PURE__ */ (0,
|
|
2831
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
|
|
2832
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui21.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_ui21.ActionBand, { children: [
|
|
2833
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2822
2834
|
import_ui21.ActionButton,
|
|
2823
2835
|
{
|
|
2824
|
-
icon: isPlaying ? /* @__PURE__ */ (0,
|
|
2836
|
+
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react16.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react16.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2825
2837
|
label: isPlaying ? "Pause" : "Play",
|
|
2826
2838
|
disabled: !!unplayableReason,
|
|
2827
2839
|
title: unplayableReason ?? void 0,
|
|
2828
2840
|
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2829
2841
|
}
|
|
2830
2842
|
),
|
|
2831
|
-
shareUrl && /* @__PURE__ */ (0,
|
|
2843
|
+
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2832
2844
|
] }) }),
|
|
2833
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0,
|
|
2834
|
-
/* @__PURE__ */ (0,
|
|
2835
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0,
|
|
2836
|
-
/* @__PURE__ */ (0,
|
|
2845
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_genre_tree28.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2846
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui21.FieldList, { items: fields }),
|
|
2847
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui21.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2848
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2837
2849
|
] });
|
|
2838
2850
|
}
|
|
2839
2851
|
|
|
2840
2852
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2841
|
-
var
|
|
2853
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2842
2854
|
function useSongPanel({
|
|
2843
2855
|
uuid,
|
|
2844
2856
|
scope,
|
|
@@ -2859,24 +2871,24 @@ function useSongPanel({
|
|
|
2859
2871
|
return {
|
|
2860
2872
|
...panel,
|
|
2861
2873
|
title: "Song",
|
|
2862
|
-
content: /* @__PURE__ */ (0,
|
|
2863
|
-
/* @__PURE__ */ (0,
|
|
2864
|
-
/* @__PURE__ */ (0,
|
|
2865
|
-
/* @__PURE__ */ (0,
|
|
2866
|
-
/* @__PURE__ */ (0,
|
|
2874
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2875
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2876
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui22.Skeleton, { className: "h-4 w-32" }),
|
|
2877
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2878
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui22.Skeleton, { className: "h-4 w-24" })
|
|
2867
2879
|
] })
|
|
2868
2880
|
};
|
|
2869
2881
|
case "not-found":
|
|
2870
2882
|
return {
|
|
2871
2883
|
...panel,
|
|
2872
2884
|
title: "Song not found",
|
|
2873
|
-
content: /* @__PURE__ */ (0,
|
|
2885
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2874
2886
|
};
|
|
2875
2887
|
case "error":
|
|
2876
2888
|
return {
|
|
2877
2889
|
...panel,
|
|
2878
2890
|
title: "Song",
|
|
2879
|
-
content: /* @__PURE__ */ (0,
|
|
2891
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2880
2892
|
};
|
|
2881
2893
|
case "success": {
|
|
2882
2894
|
const { song } = result;
|
|
@@ -2884,7 +2896,7 @@ function useSongPanel({
|
|
|
2884
2896
|
return {
|
|
2885
2897
|
...panel,
|
|
2886
2898
|
title: song.title,
|
|
2887
|
-
content: /* @__PURE__ */ (0,
|
|
2899
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2888
2900
|
SongPanelContent,
|
|
2889
2901
|
{
|
|
2890
2902
|
song,
|
|
@@ -2937,12 +2949,12 @@ function useEntityPanel({
|
|
|
2937
2949
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2938
2950
|
var import_md2 = require("react-icons/md");
|
|
2939
2951
|
var import_ui23 = require("@behindthemusictree/ui");
|
|
2940
|
-
var
|
|
2952
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2941
2953
|
function SizeMetricToggle({
|
|
2942
2954
|
value,
|
|
2943
2955
|
onChange
|
|
2944
2956
|
}) {
|
|
2945
|
-
return /* @__PURE__ */ (0,
|
|
2957
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
2946
2958
|
import_ui23.SegmentedControl,
|
|
2947
2959
|
{
|
|
2948
2960
|
variant: "floating",
|
|
@@ -2950,15 +2962,15 @@ function SizeMetricToggle({
|
|
|
2950
2962
|
value,
|
|
2951
2963
|
onChange,
|
|
2952
2964
|
options: [
|
|
2953
|
-
{ value: "songs", label: /* @__PURE__ */ (0,
|
|
2954
|
-
{ value: "views", label: /* @__PURE__ */ (0,
|
|
2965
|
+
{ value: "songs", label: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_md2.MdMusicNote, { size: 18, "aria-hidden": true }), "aria-label": "Size by songs", title: "Node size by song count" },
|
|
2966
|
+
{ value: "views", label: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_md2.MdVisibility, { size: 18, "aria-hidden": true }), "aria-label": "Size by views", title: "Node size by song views" }
|
|
2955
2967
|
]
|
|
2956
2968
|
}
|
|
2957
2969
|
);
|
|
2958
2970
|
}
|
|
2959
2971
|
|
|
2960
2972
|
// src/genre-tree/GenreTreeView.tsx
|
|
2961
|
-
var
|
|
2973
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
2962
2974
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2963
2975
|
var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
|
|
2964
2976
|
var noop = () => {
|
|
@@ -3066,7 +3078,7 @@ function GenreTreeView({
|
|
|
3066
3078
|
allowWheelRotation: internalAllowWheelRotation,
|
|
3067
3079
|
toggleWheelRotation,
|
|
3068
3080
|
onNodeHover: handleNodeHover
|
|
3069
|
-
} = (0,
|
|
3081
|
+
} = (0, import_genre_tree31.useGenreTreeViewState)({
|
|
3070
3082
|
scope,
|
|
3071
3083
|
getBackendBaseUrl,
|
|
3072
3084
|
viewMode: controlledViewMode,
|
|
@@ -3085,12 +3097,12 @@ function GenreTreeView({
|
|
|
3085
3097
|
restoreRootUuid = selectedGenrePlaylist.root.uuid;
|
|
3086
3098
|
setStackedRestoreOwner({ revision: restoreRevision, rootUuid: restoreRootUuid });
|
|
3087
3099
|
}
|
|
3088
|
-
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey:
|
|
3089
|
-
const { mutate: updateGenre } = (0,
|
|
3100
|
+
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey: import_genre_tree31.genreUpdateMutationKey }) > 0;
|
|
3101
|
+
const { mutate: updateGenre } = (0, import_genre_tree31.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
3090
3102
|
const busy = deferredSizeMetric !== sizeMetric || isTreeFetching || isGenreUpdating;
|
|
3091
3103
|
const isArtistFiltered = artistUuid !== null;
|
|
3092
3104
|
const canSizeByViews = !isArtistFiltered && hasViewsCount(visibleGenrePlaylists);
|
|
3093
|
-
const artistResult = (0,
|
|
3105
|
+
const artistResult = (0, import_genre_tree31.useArtist)(artistUuid, artistSearchBaseUrl ?? getBackendBaseUrl);
|
|
3094
3106
|
const filterArtistName = artistResult.status === "success" ? artistResult.artist.name : null;
|
|
3095
3107
|
const filterArtist = (0, import_react19.useMemo)(
|
|
3096
3108
|
() => artistUuid !== null && filterArtistName !== null ? { uuid: artistUuid, name: filterArtistName } : null,
|
|
@@ -3110,14 +3122,14 @@ function GenreTreeView({
|
|
|
3110
3122
|
const openSongRef = (0, import_react19.useRef)(openSong);
|
|
3111
3123
|
openSongRef.current = openSong;
|
|
3112
3124
|
const resolvedRenderSongLink = (0, import_react19.useCallback)(
|
|
3113
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0,
|
|
3125
|
+
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
|
|
3114
3126
|
[renderSongLink]
|
|
3115
3127
|
);
|
|
3116
3128
|
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react19.useState)(null);
|
|
3117
3129
|
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react19.useState)(null);
|
|
3118
3130
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
3119
3131
|
const songBaseUrl = getBackendBaseUrl;
|
|
3120
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
3132
|
+
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
3121
3133
|
const getGenrePath = (genre) => {
|
|
3122
3134
|
const path = [];
|
|
3123
3135
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -3193,9 +3205,11 @@ function GenreTreeView({
|
|
|
3193
3205
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
3194
3206
|
resolveStyle
|
|
3195
3207
|
);
|
|
3196
|
-
const
|
|
3197
|
-
|
|
3198
|
-
|
|
3208
|
+
const treeStyles = (0, import_react19.useMemo)(() => toGenreNodeStyles(relations, visibleGenrePlaylists), [relations, visibleGenrePlaylists]);
|
|
3209
|
+
const validSelectedGenreUuid = (0, import_genre_tree30.toGenreUuid)(selectedGenreUuid);
|
|
3210
|
+
const [selectionHistory, setSelectionHistory] = (0, import_react19.useState)({ current: validSelectedGenreUuid, previous: null });
|
|
3211
|
+
if (selectionHistory.current !== validSelectedGenreUuid) {
|
|
3212
|
+
setSelectionHistory({ current: validSelectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
3199
3213
|
}
|
|
3200
3214
|
const handlePrevious = selectionHistory.previous ? () => selectGenre(selectionHistory.previous) : void 0;
|
|
3201
3215
|
const { showPopup, hidePopup } = (0, import_popup5.usePopup)();
|
|
@@ -3227,7 +3241,7 @@ function GenreTreeView({
|
|
|
3227
3241
|
const canToggleSide = !readOnly && criteria !== void 0 && criteria !== null && parentPlaylist !== void 0 && parentPlaylist.parent === null;
|
|
3228
3242
|
const side = criteria?.side ?? "core";
|
|
3229
3243
|
const popSibling = canToggleSide && side === "core" ? visibleGenrePlaylists.find((sibling) => sibling.parent?.uuid === parentPlaylist.uuid && sibling.uuid !== genrePlaylist?.uuid && sibling.criteria?.side === "pop") : void 0;
|
|
3230
|
-
const shareTarget =
|
|
3244
|
+
const shareTarget = validSelectedGenreUuid ? { kind: "genre", genreUuid: validSelectedGenreUuid, name: criteria?.name ?? "Genre", scope, artistUuid } : void 0;
|
|
3231
3245
|
const shareUrl = shareTarget ? getShareUrlRef.current?.(shareTarget) ?? void 0 : void 0;
|
|
3232
3246
|
const genreContent = useGenreDetailContent({
|
|
3233
3247
|
genreUuid: selectedGenreUuid,
|
|
@@ -3238,7 +3252,7 @@ function GenreTreeView({
|
|
|
3238
3252
|
selectGenre(uuid);
|
|
3239
3253
|
},
|
|
3240
3254
|
expanded: isExpanded,
|
|
3241
|
-
|
|
3255
|
+
treeStyles,
|
|
3242
3256
|
playback,
|
|
3243
3257
|
genrePlaylist: selectedGenrePlaylist,
|
|
3244
3258
|
band: {
|
|
@@ -3249,7 +3263,7 @@ function GenreTreeView({
|
|
|
3249
3263
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
3250
3264
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
3251
3265
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
3252
|
-
/* @__PURE__ */ (0,
|
|
3266
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3253
3267
|
ChangeParentPopup,
|
|
3254
3268
|
{
|
|
3255
3269
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -3293,7 +3307,7 @@ function GenreTreeView({
|
|
|
3293
3307
|
onClose: otherPanel.onClose,
|
|
3294
3308
|
searchName: otherPanel.title
|
|
3295
3309
|
};
|
|
3296
|
-
} else if (selectedGenreUuid) {
|
|
3310
|
+
} else if (selectedGenreUuid !== null) {
|
|
3297
3311
|
activePanel = {
|
|
3298
3312
|
title: genreContent.title,
|
|
3299
3313
|
content: genreContent.content,
|
|
@@ -3310,19 +3324,19 @@ function GenreTreeView({
|
|
|
3310
3324
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
3311
3325
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
3312
3326
|
} : void 0;
|
|
3313
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0,
|
|
3327
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3314
3328
|
import_ui24.IconButton,
|
|
3315
3329
|
{
|
|
3316
3330
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
3317
3331
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
3318
3332
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
3319
|
-
children: activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3333
|
+
children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react18.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react18.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3320
3334
|
}
|
|
3321
3335
|
) : null;
|
|
3322
3336
|
const renderArtistFilter = () => {
|
|
3323
3337
|
if (isLoading || !filterArtist) return null;
|
|
3324
|
-
return /* @__PURE__ */ (0,
|
|
3325
|
-
/* @__PURE__ */ (0,
|
|
3338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
3339
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3326
3340
|
"button",
|
|
3327
3341
|
{
|
|
3328
3342
|
type: "button",
|
|
@@ -3334,7 +3348,7 @@ function GenreTreeView({
|
|
|
3334
3348
|
children: filterArtist.name
|
|
3335
3349
|
}
|
|
3336
3350
|
),
|
|
3337
|
-
/* @__PURE__ */ (0,
|
|
3351
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3338
3352
|
"button",
|
|
3339
3353
|
{
|
|
3340
3354
|
type: "button",
|
|
@@ -3346,8 +3360,8 @@ function GenreTreeView({
|
|
|
3346
3360
|
)
|
|
3347
3361
|
] });
|
|
3348
3362
|
};
|
|
3349
|
-
const actions = /* @__PURE__ */ (0,
|
|
3350
|
-
!isLoading && !isError && /* @__PURE__ */ (0,
|
|
3363
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_jsx_runtime52.Fragment, { children: [
|
|
3364
|
+
!isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3351
3365
|
GenreTreeSearch,
|
|
3352
3366
|
{
|
|
3353
3367
|
artistBaseUrl,
|
|
@@ -3380,9 +3394,9 @@ function GenreTreeView({
|
|
|
3380
3394
|
extraGroups: extraSearchGroups
|
|
3381
3395
|
}
|
|
3382
3396
|
),
|
|
3383
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3384
|
-
/* @__PURE__ */ (0,
|
|
3385
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0,
|
|
3397
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3398
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("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: [
|
|
3399
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3386
3400
|
import_ui24.SegmentedControl,
|
|
3387
3401
|
{
|
|
3388
3402
|
"aria-label": "Tree view mode",
|
|
@@ -3396,13 +3410,13 @@ function GenreTreeView({
|
|
|
3396
3410
|
]
|
|
3397
3411
|
}
|
|
3398
3412
|
),
|
|
3399
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0,
|
|
3413
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3400
3414
|
"div",
|
|
3401
3415
|
{
|
|
3402
3416
|
className: "flex items-center gap-1",
|
|
3403
3417
|
role: "group",
|
|
3404
3418
|
"aria-label": "Tree display options",
|
|
3405
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0,
|
|
3419
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3406
3420
|
import_ui24.Button,
|
|
3407
3421
|
{
|
|
3408
3422
|
variant: allowWheelRotation ? "default" : "outline",
|
|
@@ -3413,48 +3427,48 @@ function GenreTreeView({
|
|
|
3413
3427
|
)
|
|
3414
3428
|
}
|
|
3415
3429
|
),
|
|
3416
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0,
|
|
3430
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3417
3431
|
import_ui24.IconTextButton,
|
|
3418
3432
|
{
|
|
3419
|
-
icon:
|
|
3433
|
+
icon: import_lucide_react17.Plus,
|
|
3420
3434
|
text: "Add root",
|
|
3421
3435
|
onClick: () => handleGenreCreationAction(null)
|
|
3422
3436
|
}
|
|
3423
3437
|
)
|
|
3424
3438
|
] })
|
|
3425
3439
|
] });
|
|
3426
|
-
return /* @__PURE__ */ (0,
|
|
3440
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3427
3441
|
"div",
|
|
3428
3442
|
{
|
|
3429
3443
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
3430
3444
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
3431
3445
|
children: [
|
|
3432
|
-
/* @__PURE__ */ (0,
|
|
3446
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3433
3447
|
"div",
|
|
3434
3448
|
{
|
|
3435
3449
|
className: `actions-container absolute z-30 flex items-center gap-2 ${placement === "regions" ? "left-[calc(var(--layout-gutter)+var(--layout-panel-inset))] top-[calc(var(--layout-gutter)+var(--layout-panel-inset))] md:left-[var(--layout-panel-inset)] md:top-[var(--layout-panel-inset)] max-md:right-[calc(var(--layout-gutter)+var(--layout-panel-inset))] max-md:top-[var(--layout-band-top)] max-md:flex-col max-md:items-stretch" : "left-5 top-5"}`,
|
|
3436
3450
|
children: actions
|
|
3437
3451
|
}
|
|
3438
3452
|
),
|
|
3439
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3453
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3440
3454
|
"div",
|
|
3441
3455
|
{
|
|
3442
3456
|
className: `absolute left-1/2 z-30 hidden -translate-x-1/2 md:block ${placement === "regions" ? "top-[calc(var(--layout-gutter)+var(--layout-panel-inset))] md:top-[var(--layout-panel-inset)]" : "top-5"}`,
|
|
3443
3457
|
children: renderArtistFilter()
|
|
3444
3458
|
}
|
|
3445
3459
|
),
|
|
3446
|
-
/* @__PURE__ */ (0,
|
|
3447
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0,
|
|
3448
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3460
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
3461
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
3462
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
|
|
3449
3463
|
"Couldn't load the genre tree.",
|
|
3450
3464
|
" ",
|
|
3451
|
-
/* @__PURE__ */ (0,
|
|
3465
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
3452
3466
|
] }) : viewMode === "wheel" ? (
|
|
3453
3467
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
3454
3468
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
3455
3469
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
3456
3470
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3471
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3458
3472
|
GenrePlaylistTreeWheel,
|
|
3459
3473
|
{
|
|
3460
3474
|
scope,
|
|
@@ -3472,9 +3486,9 @@ function GenreTreeView({
|
|
|
3472
3486
|
allowWheelRotation,
|
|
3473
3487
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3474
3488
|
busy,
|
|
3475
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3489
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3476
3490
|
floatingControlsLeading,
|
|
3477
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3491
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3478
3492
|
] }) : void 0,
|
|
3479
3493
|
defaultViewport,
|
|
3480
3494
|
viewportRestore,
|
|
@@ -3483,7 +3497,7 @@ function GenreTreeView({
|
|
|
3483
3497
|
) }) })
|
|
3484
3498
|
) : viewMode === "pop-core" ? (
|
|
3485
3499
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
3486
|
-
/* @__PURE__ */ (0,
|
|
3500
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3487
3501
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3488
3502
|
{
|
|
3489
3503
|
scope,
|
|
@@ -3501,9 +3515,9 @@ function GenreTreeView({
|
|
|
3501
3515
|
allowWheelRotation,
|
|
3502
3516
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3503
3517
|
busy,
|
|
3504
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3518
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3505
3519
|
floatingControlsLeading,
|
|
3506
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3520
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3507
3521
|
] }) : void 0,
|
|
3508
3522
|
defaultViewport,
|
|
3509
3523
|
viewportRestore,
|
|
@@ -3511,7 +3525,7 @@ function GenreTreeView({
|
|
|
3511
3525
|
...focus
|
|
3512
3526
|
}
|
|
3513
3527
|
) }) })
|
|
3514
|
-
) : viewMode === "outline" ? /* @__PURE__ */ (0,
|
|
3528
|
+
) : viewMode === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "tree-container flex-1 min-h-0 w-full overflow-y-auto relative", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3515
3529
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3516
3530
|
{
|
|
3517
3531
|
outline: true,
|
|
@@ -3528,13 +3542,13 @@ function GenreTreeView({
|
|
|
3528
3542
|
selectedNodeId,
|
|
3529
3543
|
readOnly
|
|
3530
3544
|
}
|
|
3531
|
-
) }) : /* @__PURE__ */ (0,
|
|
3545
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "tree-container relative flex flex-col gap-4 w-full pt-14 overflow-x-auto overflow-y-auto text-[var(--color-text)]", children: Object.entries(groupedGenrePlaylistsByRoot).map(
|
|
3532
3546
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
3533
|
-
return /* @__PURE__ */ (0,
|
|
3547
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3534
3548
|
"div",
|
|
3535
3549
|
{
|
|
3536
3550
|
className: "tree-per-root-container relative shrink-0 h-[28rem] mt-2 mr-16 p-2 bg-[var(--color-neutral-100)] rounded-lg",
|
|
3537
|
-
children: /* @__PURE__ */ (0,
|
|
3551
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3538
3552
|
GenrePlaylistTreePerRoot,
|
|
3539
3553
|
{
|
|
3540
3554
|
scope,
|
|
@@ -3561,7 +3575,7 @@ function GenreTreeView({
|
|
|
3561
3575
|
);
|
|
3562
3576
|
}
|
|
3563
3577
|
) }),
|
|
3564
|
-
/* @__PURE__ */ (0,
|
|
3578
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3565
3579
|
import_ui24.DetailPanel,
|
|
3566
3580
|
{
|
|
3567
3581
|
ref: panelRef,
|
|
@@ -3576,7 +3590,7 @@ function GenreTreeView({
|
|
|
3576
3590
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3577
3591
|
aside: activePanel?.aside,
|
|
3578
3592
|
edgeTab: detailTab,
|
|
3579
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3593
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(import_jsx_runtime52.Fragment, { children: [
|
|
3580
3594
|
activePanel.content,
|
|
3581
3595
|
activePanel.aside
|
|
3582
3596
|
] }) : activePanel?.content
|
|
@@ -3593,11 +3607,11 @@ var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
|
3593
3607
|
|
|
3594
3608
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3595
3609
|
var import_react20 = require("react");
|
|
3596
|
-
var
|
|
3597
|
-
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3610
|
+
var import_lucide_react19 = require("lucide-react");
|
|
3598
3611
|
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3612
|
+
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3599
3613
|
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
3600
|
-
var
|
|
3614
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3601
3615
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react20.useEffect : import_react20.useLayoutEffect;
|
|
3602
3616
|
function TrackListSidebar({
|
|
3603
3617
|
className: className2 = "",
|
|
@@ -3610,7 +3624,7 @@ function TrackListSidebar({
|
|
|
3610
3624
|
renderArtistLink,
|
|
3611
3625
|
renderSongLink
|
|
3612
3626
|
}) {
|
|
3613
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } = (0,
|
|
3627
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = (0, import_genre_tree32.useTrackList)();
|
|
3614
3628
|
const trackNoun = (0, import_track_noun4.useTrackNoun)();
|
|
3615
3629
|
const trackListRef = (0, import_react20.useRef)(null);
|
|
3616
3630
|
const previousOriginRef = (0, import_react20.useRef)(trackList?.origin ?? null);
|
|
@@ -3699,25 +3713,25 @@ function TrackListSidebar({
|
|
|
3699
3713
|
}
|
|
3700
3714
|
};
|
|
3701
3715
|
const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
|
|
3702
|
-
return trackList ? /* @__PURE__ */ (0,
|
|
3716
|
+
return trackList ? /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3703
3717
|
"div",
|
|
3704
3718
|
{
|
|
3705
3719
|
"data-theme": "dark",
|
|
3706
3720
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3707
3721
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3708
3722
|
children: [
|
|
3709
|
-
/* @__PURE__ */ (0,
|
|
3710
|
-
/* @__PURE__ */ (0,
|
|
3711
|
-
/* @__PURE__ */ (0,
|
|
3712
|
-
/* @__PURE__ */ (0,
|
|
3713
|
-
/* @__PURE__ */ (0,
|
|
3723
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3724
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3725
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "origin flex text-xl", children: [
|
|
3726
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3727
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("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__ */ (0, import_jsx_runtime53.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3714
3728
|
] }),
|
|
3715
|
-
/* @__PURE__ */ (0,
|
|
3716
|
-
trackList.origin.type ===
|
|
3729
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3730
|
+
trackList.origin.type === import_genre_tree33.TrackListOriginType.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === import_genre_tree33.TrackListOriginType.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
|
|
3717
3731
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3718
3732
|
] })
|
|
3719
3733
|
] }),
|
|
3720
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0,
|
|
3734
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3721
3735
|
"button",
|
|
3722
3736
|
{
|
|
3723
3737
|
type: "button",
|
|
@@ -3726,11 +3740,11 @@ function TrackListSidebar({
|
|
|
3726
3740
|
"aria-expanded": !isCollapsed,
|
|
3727
3741
|
className: `ml-2 flex h-8 w-8 shrink-0 items-center justify-center rounded-md hover:bg-[var(--color-surface-muted)] ${isCollapsed ? "text-[var(--color-text-muted)]" : "text-white"}`,
|
|
3728
3742
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3729
|
-
children: /* @__PURE__ */ (0,
|
|
3743
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react19.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3730
3744
|
}
|
|
3731
3745
|
)
|
|
3732
3746
|
] }),
|
|
3733
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
3747
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3734
3748
|
"ul",
|
|
3735
3749
|
{
|
|
3736
3750
|
ref: trackListRef,
|
|
@@ -3740,7 +3754,7 @@ function TrackListSidebar({
|
|
|
3740
3754
|
onPointerDown: markUserScrollIntent,
|
|
3741
3755
|
className: layout === "inline" ? "track-list flex-1 min-h-0 overflow-auto list-none p-0 m-0" : "track-list flex-1 min-h-0 overflow-auto list-none p-0 m-0",
|
|
3742
3756
|
children: [
|
|
3743
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */ (0,
|
|
3757
|
+
trackList.tracks.map((track, index) => /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("li", { "data-track-uuid": track.uuid, children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3744
3758
|
TrackItem,
|
|
3745
3759
|
{
|
|
3746
3760
|
track,
|
|
@@ -3751,7 +3765,7 @@ function TrackListSidebar({
|
|
|
3751
3765
|
renderSongLink
|
|
3752
3766
|
}
|
|
3753
3767
|
) }, track.uuid)),
|
|
3754
|
-
hasMore && /* @__PURE__ */ (0,
|
|
3768
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3755
3769
|
]
|
|
3756
3770
|
}
|
|
3757
3771
|
)
|
|
@@ -3764,14 +3778,14 @@ function TrackListSidebar({
|
|
|
3764
3778
|
var import_react21 = require("react");
|
|
3765
3779
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3766
3780
|
var import_player14 = require("@behindthemusictree/app-kit/player");
|
|
3767
|
-
var
|
|
3781
|
+
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3768
3782
|
var import_ui25 = require("@behindthemusictree/ui");
|
|
3769
3783
|
|
|
3770
3784
|
// src/genre-tree/PlayerControls.tsx
|
|
3771
|
-
var
|
|
3772
|
-
var
|
|
3785
|
+
var import_lucide_react20 = require("lucide-react");
|
|
3786
|
+
var import_genre_tree34 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3773
3787
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3774
|
-
var
|
|
3788
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
3775
3789
|
function PlayerControls() {
|
|
3776
3790
|
const {
|
|
3777
3791
|
duration,
|
|
@@ -3783,22 +3797,22 @@ function PlayerControls() {
|
|
|
3783
3797
|
setVolume,
|
|
3784
3798
|
volume
|
|
3785
3799
|
} = (0, import_player13.usePlayer)();
|
|
3786
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0,
|
|
3800
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0, import_genre_tree34.useTrackList)();
|
|
3787
3801
|
const currentTime = (0, import_player13.useCurrentTime)();
|
|
3788
3802
|
const isBusy = isLoading || playState === import_player13.PlayStates.LOADING;
|
|
3789
3803
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
3790
3804
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3791
3805
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3792
3806
|
const isPlaying = playState === import_player13.PlayStates.PLAYING;
|
|
3793
|
-
return /* @__PURE__ */ (0,
|
|
3807
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3794
3808
|
"section",
|
|
3795
3809
|
{
|
|
3796
3810
|
"aria-label": "Player controls",
|
|
3797
3811
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3798
3812
|
children: [
|
|
3799
|
-
/* @__PURE__ */ (0,
|
|
3800
|
-
/* @__PURE__ */ (0,
|
|
3801
|
-
/* @__PURE__ */ (0,
|
|
3813
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3814
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree34.formatTime)(safeCurrentTime) }),
|
|
3815
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3802
3816
|
"input",
|
|
3803
3817
|
{
|
|
3804
3818
|
"aria-label": "Seek",
|
|
@@ -3812,11 +3826,11 @@ function PlayerControls() {
|
|
|
3812
3826
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3813
3827
|
}
|
|
3814
3828
|
),
|
|
3815
|
-
/* @__PURE__ */ (0,
|
|
3829
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree34.formatTime)(safeDuration) })
|
|
3816
3830
|
] }),
|
|
3817
|
-
/* @__PURE__ */ (0,
|
|
3818
|
-
/* @__PURE__ */ (0,
|
|
3819
|
-
/* @__PURE__ */ (0,
|
|
3831
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3832
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3833
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3820
3834
|
"button",
|
|
3821
3835
|
{
|
|
3822
3836
|
type: "button",
|
|
@@ -3825,10 +3839,10 @@ function PlayerControls() {
|
|
|
3825
3839
|
disabled: !isReady || !hasPreviousTrack,
|
|
3826
3840
|
onClick: playPreviousTrack,
|
|
3827
3841
|
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-zinc-300 hover:bg-zinc-800 hover:text-white disabled:cursor-not-allowed disabled:opacity-40",
|
|
3828
|
-
children: /* @__PURE__ */ (0,
|
|
3842
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react20.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3829
3843
|
}
|
|
3830
3844
|
),
|
|
3831
|
-
/* @__PURE__ */ (0,
|
|
3845
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3832
3846
|
"button",
|
|
3833
3847
|
{
|
|
3834
3848
|
type: "button",
|
|
@@ -3837,10 +3851,10 @@ function PlayerControls() {
|
|
|
3837
3851
|
disabled: !isReady,
|
|
3838
3852
|
onClick: handlePlayPauseAction,
|
|
3839
3853
|
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-full bg-white text-zinc-950 hover:bg-zinc-200 disabled:cursor-not-allowed disabled:opacity-40",
|
|
3840
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3854
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react20.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react20.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3841
3855
|
}
|
|
3842
3856
|
),
|
|
3843
|
-
/* @__PURE__ */ (0,
|
|
3857
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3844
3858
|
"button",
|
|
3845
3859
|
{
|
|
3846
3860
|
type: "button",
|
|
@@ -3849,14 +3863,14 @@ function PlayerControls() {
|
|
|
3849
3863
|
disabled: !isReady || !hasNextTrack,
|
|
3850
3864
|
onClick: playNextTrack,
|
|
3851
3865
|
className: "flex h-8 w-8 shrink-0 items-center justify-center rounded-full text-zinc-300 hover:bg-zinc-800 hover:text-white disabled:cursor-not-allowed disabled:opacity-40",
|
|
3852
|
-
children: /* @__PURE__ */ (0,
|
|
3866
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react20.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3853
3867
|
}
|
|
3854
3868
|
)
|
|
3855
3869
|
] }),
|
|
3856
|
-
/* @__PURE__ */ (0,
|
|
3857
|
-
volume === 0 ? /* @__PURE__ */ (0,
|
|
3858
|
-
/* @__PURE__ */ (0,
|
|
3859
|
-
/* @__PURE__ */ (0,
|
|
3870
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("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: [
|
|
3871
|
+
volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react20.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_lucide_react20.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3872
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "sr-only", children: "Volume" }),
|
|
3873
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3860
3874
|
"input",
|
|
3861
3875
|
{
|
|
3862
3876
|
"aria-label": "Volume",
|
|
@@ -3878,7 +3892,7 @@ function PlayerControls() {
|
|
|
3878
3892
|
}
|
|
3879
3893
|
|
|
3880
3894
|
// src/genre-tree/PlayerPanel.tsx
|
|
3881
|
-
var
|
|
3895
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
3882
3896
|
var PANEL_ID = "player-panel";
|
|
3883
3897
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3884
3898
|
function PlayerPanel({
|
|
@@ -3891,7 +3905,7 @@ function PlayerPanel({
|
|
|
3891
3905
|
renderSongLink
|
|
3892
3906
|
}) {
|
|
3893
3907
|
const { playerTrackObject, retryPlayback } = (0, import_player14.usePlayer)();
|
|
3894
|
-
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0,
|
|
3908
|
+
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree35.useTrackListSidebarVisibility)();
|
|
3895
3909
|
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react21.useState)("");
|
|
3896
3910
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3897
3911
|
(0, import_react21.useEffect)(() => {
|
|
@@ -3918,7 +3932,7 @@ function PlayerPanel({
|
|
|
3918
3932
|
onClick: () => setIsExtendRequested(true),
|
|
3919
3933
|
expanded: false
|
|
3920
3934
|
} : null;
|
|
3921
|
-
return /* @__PURE__ */ (0,
|
|
3935
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
3922
3936
|
"div",
|
|
3923
3937
|
{
|
|
3924
3938
|
id: PANEL_ID,
|
|
@@ -3931,7 +3945,7 @@ function PlayerPanel({
|
|
|
3931
3945
|
),
|
|
3932
3946
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3933
3947
|
children: [
|
|
3934
|
-
/* @__PURE__ */ (0,
|
|
3948
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
3935
3949
|
import_ui25.PanelEdgeTab,
|
|
3936
3950
|
{
|
|
3937
3951
|
side: "right",
|
|
@@ -3941,7 +3955,7 @@ function PlayerPanel({
|
|
|
3941
3955
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3942
3956
|
}
|
|
3943
3957
|
),
|
|
3944
|
-
/* @__PURE__ */ (0,
|
|
3958
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(
|
|
3945
3959
|
"div",
|
|
3946
3960
|
{
|
|
3947
3961
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -3949,20 +3963,20 @@ function PlayerPanel({
|
|
|
3949
3963
|
isExtended ? "flex-row" : "flex-col"
|
|
3950
3964
|
),
|
|
3951
3965
|
children: [
|
|
3952
|
-
/* @__PURE__ */ (0,
|
|
3953
|
-
/* @__PURE__ */ (0,
|
|
3954
|
-
/* @__PURE__ */ (0,
|
|
3955
|
-
/* @__PURE__ */ (0,
|
|
3956
|
-
playerTrackObject?.loadError && /* @__PURE__ */ (0,
|
|
3966
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3967
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
|
|
3968
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
3969
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3970
|
+
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3957
3971
|
playerTrackObject.loadError,
|
|
3958
|
-
/* @__PURE__ */ (0,
|
|
3972
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3959
3973
|
void retryPlayback();
|
|
3960
3974
|
}, children: "Retry" })
|
|
3961
3975
|
] })
|
|
3962
3976
|
] }),
|
|
3963
|
-
/* @__PURE__ */ (0,
|
|
3977
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(PlayerControls, {})
|
|
3964
3978
|
] }),
|
|
3965
|
-
/* @__PURE__ */ (0,
|
|
3979
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
3966
3980
|
TrackListSidebar,
|
|
3967
3981
|
{
|
|
3968
3982
|
layout: "inline",
|
|
@@ -3988,33 +4002,33 @@ function PlayerPanel({
|
|
|
3988
4002
|
// src/genre-tree/Rating.tsx
|
|
3989
4003
|
var import_uuid = require("uuid");
|
|
3990
4004
|
var import_ai = require("react-icons/ai");
|
|
3991
|
-
var
|
|
3992
|
-
var
|
|
4005
|
+
var import_genre_tree36 = require("@behindthemusictree/app-kit/genre-tree");
|
|
4006
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
3993
4007
|
function Rating({ rating, handleChange }) {
|
|
3994
4008
|
const instanceId = (0, import_uuid.v4)();
|
|
3995
|
-
return /* @__PURE__ */ (0,
|
|
3996
|
-
/* @__PURE__ */ (0,
|
|
4009
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
|
|
4010
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
3997
4011
|
"input",
|
|
3998
4012
|
{
|
|
3999
4013
|
id: `star-${instanceId}-${i}`,
|
|
4000
4014
|
className: "w-6 h-6 opacity-0",
|
|
4001
4015
|
type: "radio",
|
|
4002
4016
|
name: "rating",
|
|
4003
|
-
value: i === 0 ?
|
|
4017
|
+
value: i === 0 ? import_genre_tree36.FORM_RATING_NULL_VALUE : i,
|
|
4004
4018
|
checked: rating === (i === 0 ? null : i),
|
|
4005
4019
|
onChange: handleChange
|
|
4006
4020
|
}
|
|
4007
4021
|
),
|
|
4008
|
-
/* @__PURE__ */ (0,
|
|
4009
|
-
/* @__PURE__ */ (0,
|
|
4022
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)("div", { className: "flex", children: [
|
|
4023
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4010
4024
|
import_ai.AiOutlineStar,
|
|
4011
4025
|
{
|
|
4012
|
-
className: `w-7 h-7 absolute top-0 left-0 ${rating ===
|
|
4026
|
+
className: `w-7 h-7 absolute top-0 left-0 ${rating === import_genre_tree36.FORM_RATING_NULL_VALUE ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
4013
4027
|
}
|
|
4014
4028
|
),
|
|
4015
|
-
/* @__PURE__ */ (0,
|
|
4029
|
+
/* @__PURE__ */ (0, import_jsx_runtime56.jsx)("span", { className: "flex-grow w-8" }),
|
|
4016
4030
|
" "
|
|
4017
|
-
] }) : /* @__PURE__ */ (0,
|
|
4031
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4018
4032
|
import_ai.AiFillStar,
|
|
4019
4033
|
{
|
|
4020
4034
|
className: `w-7 h-7 absolute top-0 left-0 ${(rating ?? -1) >= i ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
@@ -4026,7 +4040,7 @@ function Rating({ rating, handleChange }) {
|
|
|
4026
4040
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
4027
4041
|
var import_react22 = require("react");
|
|
4028
4042
|
var import_ui26 = require("@behindthemusictree/ui");
|
|
4029
|
-
var
|
|
4043
|
+
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
4030
4044
|
function EntityDetailPanel({
|
|
4031
4045
|
scope,
|
|
4032
4046
|
getBackendBaseUrl,
|
|
@@ -4049,8 +4063,8 @@ function EntityDetailPanel({
|
|
|
4049
4063
|
getBackendBaseUrl,
|
|
4050
4064
|
getArtistBackendBaseUrl,
|
|
4051
4065
|
getShareUrl,
|
|
4052
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
4053
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0,
|
|
4066
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
4067
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime57.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
4054
4068
|
song: {
|
|
4055
4069
|
uuid: songUuid,
|
|
4056
4070
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -4066,7 +4080,7 @@ function EntityDetailPanel({
|
|
|
4066
4080
|
...navigation
|
|
4067
4081
|
});
|
|
4068
4082
|
if (!panel) return null;
|
|
4069
|
-
return /* @__PURE__ */ (0,
|
|
4083
|
+
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
4070
4084
|
import_ui26.DetailPanel,
|
|
4071
4085
|
{
|
|
4072
4086
|
side: "left",
|
|
@@ -4078,7 +4092,7 @@ function EntityDetailPanel({
|
|
|
4078
4092
|
onExpandedChange: panel.onExpandedChange,
|
|
4079
4093
|
aside: panel.extraContent,
|
|
4080
4094
|
edgeTab,
|
|
4081
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0,
|
|
4095
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime57.jsxs)(import_jsx_runtime57.Fragment, { children: [
|
|
4082
4096
|
panel.content,
|
|
4083
4097
|
panel.extraContent
|
|
4084
4098
|
] }) : panel.content
|