@behindthemusictree/app-kit-ui 31.0.0 → 32.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.
@@ -5,7 +5,7 @@ import {
5
5
  } from "./chunk-DKQQLLMY.js";
6
6
 
7
7
  // src/genre-tree/GenreTreeView.tsx
8
- import { useCallback as useCallback6, useDeferredValue, useEffect as useEffect5, useMemo as useMemo7, useRef as useRef4, useState as useState7 } from "react";
8
+ import { useCallback as useCallback6, useDeferredValue, useEffect as useEffect5, useMemo as useMemo7, useRef as useRef3, useState as useState8 } from "react";
9
9
  import { useIsMutating } from "@tanstack/react-query";
10
10
  import { Plus as Plus2 } from "lucide-react";
11
11
  import { Maximize2, Minimize2 } from "lucide-react";
@@ -916,7 +916,7 @@ function GenreActionBand({
916
916
  }
917
917
 
918
918
  // src/genre-tree/GenreDetailExtras.tsx
919
- import { Skeleton as Skeleton2 } from "@behindthemusictree/ui";
919
+ import { PanelSection as PanelSection2, Skeleton as Skeleton2 } from "@behindthemusictree/ui";
920
920
  import { useFetchGenreOverview } from "@behindthemusictree/app-kit/genre-tree";
921
921
 
922
922
  // src/genre-tree/ClampedText.tsx
@@ -947,11 +947,11 @@ function ClampedText({ children, className: className2 = "" }) {
947
947
  }
948
948
 
949
949
  // src/genre-tree/GenrePlaylistTracks.tsx
950
- import { useEffect as useEffect3, useRef as useRef3 } from "react";
950
+ import { useEffect as useEffect3, useState as useState5 } from "react";
951
951
  import { useInfiniteQuery } from "@tanstack/react-query";
952
952
  import { z } from "zod";
953
953
  import { FaPlay, FaPause } from "react-icons/fa";
954
- import { RingLoader, Skeleton } from "@behindthemusictree/ui";
954
+ import { PanelSection, RingLoader, Skeleton } from "@behindthemusictree/ui";
955
955
  import { useSession } from "@behindthemusictree/app-kit/auth";
956
956
  import { useFetchWrapper } from "@behindthemusictree/app-kit/transport";
957
957
  import { PaginatedResponseSchema } from "@behindthemusictree/app-kit/transport";
@@ -1046,9 +1046,8 @@ function GenrePlaylistTracks({
1046
1046
  getNextPageParam: (lastPage) => lastPage.nextPage ?? void 0,
1047
1047
  enabled: scope !== "me" || sessionRestored && !!session?.accessToken
1048
1048
  });
1049
- const sentinelRef = useRef3(null);
1049
+ const [sentinel, setSentinel] = useState5(null);
1050
1050
  useEffect3(() => {
1051
- const sentinel = sentinelRef.current;
1052
1051
  if (!hasNextPage || isFetchingNextPage || !sentinel) return;
1053
1052
  const observer = new IntersectionObserver((entries) => {
1054
1053
  if (entries.some((entry) => entry.isIntersecting)) {
@@ -1057,7 +1056,7 @@ function GenrePlaylistTracks({
1057
1056
  });
1058
1057
  observer.observe(sentinel);
1059
1058
  return () => observer.disconnect();
1060
- }, [hasNextPage, isFetchingNextPage, fetchNextPage]);
1059
+ }, [hasNextPage, isFetchingNextPage, fetchNextPage, sentinel]);
1061
1060
  const pages = data?.pages ?? [];
1062
1061
  const tracks = pages.flatMap((page) => page.tracks);
1063
1062
  const total = pages[0]?.total ?? void 0;
@@ -1068,11 +1067,7 @@ function GenrePlaylistTracks({
1068
1067
  showPopup(/* @__PURE__ */ jsx13(InternalErrorPopup, { errorCode: ErrorCode3.CLIENT_UNKNOWN }));
1069
1068
  });
1070
1069
  };
1071
- return /* @__PURE__ */ jsxs9("div", { className: "gtv-info-panel-children", children: [
1072
- /* @__PURE__ */ jsxs9("span", { className: "gtv-info-panel-children-title", children: [
1073
- capitalize(trackNoun.plural),
1074
- total !== void 0 && ` (${total})`
1075
- ] }),
1070
+ return /* @__PURE__ */ jsx13(PanelSection, { title: `${capitalize(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ jsxs9("div", { children: [
1076
1071
  renderTracksToolbar?.(),
1077
1072
  isPending ? /* @__PURE__ */ jsx13(Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ jsxs9("p", { role: "alert", children: [
1078
1073
  "Couldn't load ",
@@ -1135,9 +1130,9 @@ function GenrePlaylistTracks({
1135
1130
  track.uuid
1136
1131
  );
1137
1132
  }),
1138
- hasNextPage && /* @__PURE__ */ jsx13("li", { ref: sentinelRef, "aria-hidden": "true", className: "h-4" })
1133
+ hasNextPage && /* @__PURE__ */ jsx13("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
1139
1134
  ] })
1140
- ] });
1135
+ ] }) });
1141
1136
  }
1142
1137
 
1143
1138
  // src/genre-tree/GenreDetailExtras.tsx
@@ -1168,10 +1163,7 @@ function GenreDetailExtras({
1168
1163
  );
1169
1164
  if (isPending) {
1170
1165
  return /* @__PURE__ */ jsxs10(Fragment6, { children: [
1171
- /* @__PURE__ */ jsxs10("div", { className: "gtv-info-panel-children", "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: [
1172
- /* @__PURE__ */ jsx14("span", { className: "gtv-info-panel-children-title", children: "Summary" }),
1173
- /* @__PURE__ */ jsx14(Skeleton2, { className: "h-4 w-3/4" })
1174
- ] }),
1166
+ /* @__PURE__ */ jsx14(PanelSection2, { title: "Summary", children: /* @__PURE__ */ jsx14("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ jsx14(Skeleton2, { className: "h-4 w-3/4" }) }) }),
1175
1167
  family
1176
1168
  ] });
1177
1169
  }
@@ -1179,50 +1171,38 @@ function GenreDetailExtras({
1179
1171
  const { summary, summarySourceUrl, essentialSongs } = overview;
1180
1172
  const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
1181
1173
  return /* @__PURE__ */ jsxs10(Fragment6, { children: [
1182
- (summarySourceUrl || wikidataUrl) && /* @__PURE__ */ jsxs10("div", { className: "gtv-info-panel-children text-[0.8125rem] leading-[1.45] text-[var(--color-text)]", children: [
1183
- /* @__PURE__ */ jsx14("span", { className: "gtv-info-panel-children-title", children: "Links" }),
1184
- /* @__PURE__ */ jsxs10("div", { className: "mt-1 flex flex-wrap gap-x-3 gap-y-1 text-xs", children: [
1185
- summarySourceUrl && /* @__PURE__ */ jsxs10(
1186
- "a",
1187
- {
1188
- href: summarySourceUrl,
1189
- target: "_blank",
1190
- rel: "noopener noreferrer",
1191
- className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
1192
- children: [
1193
- /* @__PURE__ */ jsx14(SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
1194
- "Wikipedia"
1195
- ]
1196
- }
1197
- ),
1198
- wikidataUrl && /* @__PURE__ */ jsxs10(
1199
- "a",
1200
- {
1201
- href: wikidataUrl,
1202
- target: "_blank",
1203
- rel: "noopener noreferrer",
1204
- className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
1205
- children: [
1206
- /* @__PURE__ */ jsx14(SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
1207
- "Wikidata"
1208
- ]
1209
- }
1210
- )
1211
- ] })
1212
- ] }),
1213
- renderSummary ? renderSummary(overview) : /* @__PURE__ */ jsxs10("div", { className: "gtv-info-panel-children text-[0.8125rem] leading-[1.45] text-[var(--color-text)]", children: [
1214
- /* @__PURE__ */ jsx14("span", { className: "gtv-info-panel-children-title", children: "Summary" }),
1215
- /* @__PURE__ */ jsx14(ClampedText, { className: "mt-1", children: summary ?? "\u2014" }, genreUuid)
1216
- ] }),
1174
+ (summarySourceUrl || wikidataUrl) && /* @__PURE__ */ jsx14(PanelSection2, { title: "Links", children: /* @__PURE__ */ jsxs10("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-xs text-[var(--color-text)]", children: [
1175
+ summarySourceUrl && /* @__PURE__ */ jsxs10(
1176
+ "a",
1177
+ {
1178
+ href: summarySourceUrl,
1179
+ target: "_blank",
1180
+ rel: "noopener noreferrer",
1181
+ className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
1182
+ children: [
1183
+ /* @__PURE__ */ jsx14(SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
1184
+ "Wikipedia"
1185
+ ]
1186
+ }
1187
+ ),
1188
+ wikidataUrl && /* @__PURE__ */ jsxs10(
1189
+ "a",
1190
+ {
1191
+ href: wikidataUrl,
1192
+ target: "_blank",
1193
+ rel: "noopener noreferrer",
1194
+ className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
1195
+ children: [
1196
+ /* @__PURE__ */ jsx14(SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
1197
+ "Wikidata"
1198
+ ]
1199
+ }
1200
+ )
1201
+ ] }) }),
1202
+ /* @__PURE__ */ jsx14(PanelSection2, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ jsx14(ClampedText, { className: "text-[0.8125rem] leading-[1.45] text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
1217
1203
  family,
1218
1204
  renderGenreDetailExtras?.(overview),
1219
- renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && /* @__PURE__ */ jsxs10("div", { className: "gtv-info-panel-children text-[0.8125rem] leading-[1.45] text-[var(--color-text)]", children: [
1220
- /* @__PURE__ */ jsxs10("span", { className: "gtv-info-panel-children-title", children: [
1221
- "Essential ",
1222
- trackNoun.plural
1223
- ] }),
1224
- essentialSongs.length > 0 ? /* @__PURE__ */ jsx14("ul", { className: "mt-1 divide-y divide-[var(--color-border)]", children: essentialSongs.map((track) => /* @__PURE__ */ jsx14("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ jsx14("p", { className: "mt-1", children: "\u2014" })
1225
- ] }),
1205
+ (renderEssentialTracks || essentialSongs) && /* @__PURE__ */ jsx14(PanelSection2, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ jsx14("ul", { className: "text-[0.8125rem] leading-[1.45] text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ jsx14("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ jsx14("p", { className: "text-[0.8125rem] leading-[1.45] text-[var(--color-text)]", children: "\u2014" }) }),
1226
1206
  /* @__PURE__ */ jsx14(
1227
1207
  GenrePlaylistTracks,
1228
1208
  {
@@ -1453,7 +1433,7 @@ function ArtistPhoto({ image, name }) {
1453
1433
  }
1454
1434
 
1455
1435
  // src/genre-tree/artist/ArtistMembers.tsx
1456
- import { PanelGroup, PanelSection } from "@behindthemusictree/ui";
1436
+ import { PanelGroup, PanelSection as PanelSection3 } from "@behindthemusictree/ui";
1457
1437
  import { jsx as jsx20, jsxs as jsxs14 } from "react/jsx-runtime";
1458
1438
  function MembershipList({ title, memberships, renderArtistLink }) {
1459
1439
  if (memberships.length === 0) return null;
@@ -1478,7 +1458,7 @@ function MembershipList({ title, memberships, renderArtistLink }) {
1478
1458
  function ArtistMembers({ title, memberships, renderArtistLink }) {
1479
1459
  if (memberships.length === 0) return null;
1480
1460
  const isCurrent = (membership) => !membership.ended && membership.endYear === null;
1481
- return /* @__PURE__ */ jsxs14(PanelSection, { title, children: [
1461
+ return /* @__PURE__ */ jsxs14(PanelSection3, { title, children: [
1482
1462
  /* @__PURE__ */ jsx20(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
1483
1463
  /* @__PURE__ */ jsx20(
1484
1464
  MembershipList,
@@ -1492,7 +1472,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
1492
1472
  }
1493
1473
 
1494
1474
  // src/genre-tree/artist/ArtistDiscography.tsx
1495
- import { PanelGroup as PanelGroup2, PanelSection as PanelSection2 } from "@behindthemusictree/ui";
1475
+ import { PanelGroup as PanelGroup2, PanelSection as PanelSection4 } from "@behindthemusictree/ui";
1496
1476
  import { jsx as jsx21, jsxs as jsxs15 } from "react/jsx-runtime";
1497
1477
  var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
1498
1478
  var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
@@ -1513,7 +1493,7 @@ function byYear(a, b) {
1513
1493
  function ArtistDiscography({ albums }) {
1514
1494
  if (albums.length === 0) return null;
1515
1495
  const sorted = [...albums].sort(byYear);
1516
- return /* @__PURE__ */ jsx21(PanelSection2, { title: "Discography", children: GROUPS.map((group) => {
1496
+ return /* @__PURE__ */ jsx21(PanelSection4, { title: "Discography", children: GROUPS.map((group) => {
1517
1497
  const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
1518
1498
  if (groupAlbums.length === 0) return null;
1519
1499
  return /* @__PURE__ */ jsx21(PanelGroup2, { title: group, children: /* @__PURE__ */ jsx21("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ jsxs15("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
@@ -1524,10 +1504,10 @@ function ArtistDiscography({ albums }) {
1524
1504
  }
1525
1505
 
1526
1506
  // src/genre-tree/artist/ArtistSongs.tsx
1527
- import { useState as useState5 } from "react";
1507
+ import { useState as useState6 } from "react";
1528
1508
  import { keepPreviousData } from "@tanstack/react-query";
1529
1509
  import { Play as Play2 } from "lucide-react";
1530
- import { Pagination, PanelSection as PanelSection3, Skeleton as Skeleton3 } from "@behindthemusictree/ui";
1510
+ import { Pagination, PanelSection as PanelSection5, Skeleton as Skeleton3 } from "@behindthemusictree/ui";
1531
1511
  import { usePlayer as usePlayer8 } from "@behindthemusictree/app-kit/player";
1532
1512
  import {
1533
1513
  SongDetailedSchema as SongDetailedSchema2,
@@ -1669,8 +1649,8 @@ var SORTS = [
1669
1649
  { ordering: "-albumYear", label: "Year" }
1670
1650
  ];
1671
1651
  function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
1672
- const [page, setPage] = useState5(1);
1673
- const [ordering, setOrdering] = useState5("title");
1652
+ const [page, setPage] = useState6(1);
1653
+ const [ordering, setOrdering] = useState6("title");
1674
1654
  const { fetch } = useFetchWrapper2(getBackendBaseUrl);
1675
1655
  const { playNewTrackListFromArtist } = useTrackList4();
1676
1656
  const { playerTrackObject } = usePlayer8();
@@ -1695,7 +1675,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
1695
1675
  event.stopPropagation();
1696
1676
  void play(song.uuid);
1697
1677
  };
1698
- return /* @__PURE__ */ jsx24(PanelSection3, { title: "Songs", children: isPending ? /* @__PURE__ */ jsx24(Skeleton3, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ jsx24("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ jsx24("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
1678
+ return /* @__PURE__ */ jsx24(PanelSection5, { title: "Songs", children: isPending ? /* @__PURE__ */ jsx24(Skeleton3, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ jsx24("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ jsx24("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ jsxs18(Fragment8, { children: [
1699
1679
  /* @__PURE__ */ jsxs18("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-2", children: [
1700
1680
  /* @__PURE__ */ jsxs18(
1701
1681
  "button",
@@ -1816,9 +1796,9 @@ import {
1816
1796
  } from "@behindthemusictree/app-kit/genre-tree";
1817
1797
 
1818
1798
  // src/genre-tree/song/SongPanelContent.tsx
1819
- import { useState as useState6 } from "react";
1799
+ import { useState as useState7 } from "react";
1820
1800
  import { Pause as Pause2, Play as Play3 } from "lucide-react";
1821
- import { FieldList as FieldList2, PanelSection as PanelSection4, Skeleton as Skeleton5 } from "@behindthemusictree/ui";
1801
+ import { FieldList as FieldList2, PanelSection as PanelSection6, Skeleton as Skeleton5 } from "@behindthemusictree/ui";
1822
1802
  import { PlayStates as PlayStates3, usePlayer as usePlayer9 } from "@behindthemusictree/app-kit/player";
1823
1803
  import {
1824
1804
  ArtistNames as ArtistNames3,
@@ -1832,7 +1812,7 @@ var numberFormat = new Intl.NumberFormat("en");
1832
1812
  var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
1833
1813
  var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
1834
1814
  function SongHistory({ uuid, getBackendBaseUrl }) {
1835
- const [open, setOpen] = useState6(false);
1815
+ const [open, setOpen] = useState7(false);
1836
1816
  const history = useSongHistory(uuid, getBackendBaseUrl, open);
1837
1817
  let body = null;
1838
1818
  if (history.status === "loading") body = /* @__PURE__ */ jsx26(Skeleton5, { className: "h-10", "aria-busy": "true" });
@@ -1941,7 +1921,7 @@ function SongPanelContent({
1941
1921
  ] }) }),
1942
1922
  song.artists && song.artists.length > 0 && /* @__PURE__ */ jsx26("p", { className: "px-6 pt-2.5 text-[var(--color-text-muted)]", children: /* @__PURE__ */ jsx26(ArtistNames3, { artists: song.artists, renderArtistLink }) }),
1943
1923
  /* @__PURE__ */ jsx26(FieldList2, { items: fields }),
1944
- song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ jsx26(PanelSection4, { title: "Essential in", children: /* @__PURE__ */ jsx26("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ jsx26("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
1924
+ song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ jsx26(PanelSection6, { title: "Essential in", children: /* @__PURE__ */ jsx26("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ jsx26("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
1945
1925
  /* @__PURE__ */ jsx26(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
1946
1926
  ] });
1947
1927
  }
@@ -2093,19 +2073,19 @@ function GenreTreeView({
2093
2073
  placement = "default",
2094
2074
  ...focus
2095
2075
  }) {
2096
- const getShareUrlRef = useRef4(getShareUrl);
2076
+ const getShareUrlRef = useRef3(getShareUrl);
2097
2077
  getShareUrlRef.current = getShareUrl;
2098
- const [internalArtistUuid, setInternalArtistUuid] = useState7(null);
2078
+ const [internalArtistUuid, setInternalArtistUuid] = useState8(null);
2099
2079
  const isArtistControlled = controlledArtistUuid !== void 0;
2100
2080
  const artistUuid = isArtistControlled ? controlledArtistUuid : internalArtistUuid;
2101
- const [internalSongUuid, setInternalSongUuid] = useState7(null);
2081
+ const [internalSongUuid, setInternalSongUuid] = useState8(null);
2102
2082
  const isSongControlled = controlledSongUuid !== void 0;
2103
2083
  const songUuid = isSongControlled ? controlledSongUuid : internalSongUuid;
2104
2084
  const changeSong = (uuid) => {
2105
2085
  if (!isSongControlled) setInternalSongUuid(uuid);
2106
2086
  onSongUuidChange?.(uuid);
2107
2087
  };
2108
- const [internalSizeMetric, setInternalSizeMetric] = useState7("songs");
2088
+ const [internalSizeMetric, setInternalSizeMetric] = useState8("songs");
2109
2089
  const sizeMetric = controlledSizeMetric ?? internalSizeMetric;
2110
2090
  const deferredSizeMetric = useDeferredValue(sizeMetric);
2111
2091
  const changeSizeMetric = (metric) => {
@@ -2144,7 +2124,7 @@ function GenreTreeView({
2144
2124
  artistUuid
2145
2125
  });
2146
2126
  const restoreRevision = viewportRestore?.revision;
2147
- const [stackedRestoreOwner, setStackedRestoreOwner] = useState7({ revision: restoreRevision, rootUuid: selectedGenrePlaylist?.root.uuid });
2127
+ const [stackedRestoreOwner, setStackedRestoreOwner] = useState8({ revision: restoreRevision, rootUuid: selectedGenrePlaylist?.root.uuid });
2148
2128
  let restoreRootUuid = stackedRestoreOwner.rootUuid;
2149
2129
  if (stackedRestoreOwner.revision !== restoreRevision) {
2150
2130
  restoreRootUuid = selectedGenrePlaylist?.root.uuid;
@@ -2175,14 +2155,14 @@ function GenreTreeView({
2175
2155
  if (selectedNodeId !== null) clearSelection();
2176
2156
  changeSong(uuid);
2177
2157
  };
2178
- const openSongRef = useRef4(openSong);
2158
+ const openSongRef = useRef3(openSong);
2179
2159
  openSongRef.current = openSong;
2180
2160
  const resolvedRenderSongLink = useCallback6(
2181
2161
  (song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ jsx29("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
2182
2162
  [renderSongLink]
2183
2163
  );
2184
- const [expandedSongUuid, setExpandedSongUuid] = useState7(null);
2185
- const [expandedArtistUuid, setExpandedArtistUuid] = useState7(null);
2164
+ const [expandedSongUuid, setExpandedSongUuid] = useState8(null);
2165
+ const [expandedArtistUuid, setExpandedArtistUuid] = useState8(null);
2186
2166
  const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
2187
2167
  const songBaseUrl = getBackendBaseUrl;
2188
2168
  const artistPanel = useArtistPanel({
@@ -2231,8 +2211,8 @@ function GenreTreeView({
2231
2211
  const builtInSongPanel = overlayPanel || hasSelectedGenreNode ? void 0 : songPanel;
2232
2212
  const builtInArtistPanel = overlayPanel || hasSelectedGenreNode || builtInSongPanel ? void 0 : artistPanel;
2233
2213
  const builtInPanel = builtInSongPanel ?? builtInArtistPanel;
2234
- const [uncontrolledCollapsed, setUncontrolledCollapsed] = useState7(false);
2235
- const [uncontrolledExpanded, setUncontrolledExpanded] = useState7(false);
2214
+ const [uncontrolledCollapsed, setUncontrolledCollapsed] = useState8(false);
2215
+ const [uncontrolledExpanded, setUncontrolledExpanded] = useState8(false);
2236
2216
  const isCollapsed = collapsed ?? uncontrolledCollapsed;
2237
2217
  const isExpanded = expanded ?? uncontrolledExpanded;
2238
2218
  const changeCollapsed = (next) => {
@@ -2246,15 +2226,15 @@ function GenreTreeView({
2246
2226
  useEffect5(() => {
2247
2227
  setUncontrolledCollapsed(false);
2248
2228
  }, [selectedNodeId, artistUuid, songUuid]);
2249
- const [isWheelRevealed, setIsWheelRevealed] = useState7(false);
2229
+ const [isWheelRevealed, setIsWheelRevealed] = useState8(false);
2250
2230
  const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
2251
2231
  const isTreeReady = !isLoading && (!usesHandoff || isWheelRevealed);
2252
- const [resolveStyle, setResolveStyle] = useState7(null);
2232
+ const [resolveStyle, setResolveStyle] = useState8(null);
2253
2233
  const handleNodeStyleResolverChange = useCallback6(
2254
2234
  (resolver) => setResolveStyle(() => resolver),
2255
2235
  []
2256
2236
  );
2257
- const panelRef = useRef4(null);
2237
+ const panelRef = useRef3(null);
2258
2238
  const obscuredInset = useObscuredInset(panelRef);
2259
2239
  const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
2260
2240
  const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
@@ -2264,7 +2244,7 @@ function GenreTreeView({
2264
2244
  !overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
2265
2245
  resolveStyle
2266
2246
  );
2267
- const [selectionHistory, setSelectionHistory] = useState7({
2247
+ const [selectionHistory, setSelectionHistory] = useState8({
2268
2248
  current: selectedNodeId,
2269
2249
  previous: null
2270
2250
  });
@@ -2277,7 +2257,7 @@ function GenreTreeView({
2277
2257
  const previousPlaylist = selectionHistory.previous !== null && selectionHistory.previous !== selectedNodeId ? genrePlaylistByNodeId.get(selectionHistory.previous) : void 0;
2278
2258
  const handlePrevious = previousPlaylist && visibleGenrePlaylists.includes(previousPlaylist) ? () => handleGenreSearchSelect(previousPlaylist) : void 0;
2279
2259
  const { showPopup, hidePopup } = usePopup5();
2280
- const [searchText, setSearchText] = useState7("");
2260
+ const [searchText, setSearchText] = useState8("");
2281
2261
  const artistSearchResult = useArtistSearch(artistBaseUrl, artistSearch ? searchText : "");
2282
2262
  const artistGroup = artistSearch ? {
2283
2263
  key: "artists",
@@ -2339,7 +2319,7 @@ function GenreTreeView({
2339
2319
  const handleGenreSearchZoomIn = () => {
2340
2320
  if (selectedUuid) focus.onFocusGenreChange?.(selectedUuid, "zoom-in");
2341
2321
  };
2342
- const zoomInRef = useRef4(void 0);
2322
+ const zoomInRef = useRef3(void 0);
2343
2323
  zoomInRef.current = canZoomIn ? handleGenreSearchZoomIn : void 0;
2344
2324
  const selectGenreFromPanel = (nodeId) => {
2345
2325
  const genrePlaylist = genrePlaylistByNodeId.get(nodeId);
@@ -2868,7 +2848,7 @@ import {
2868
2848
  } from "@behindthemusictree/genre-tree-view";
2869
2849
 
2870
2850
  // src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
2871
- import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useRef as useRef5 } from "react";
2851
+ import { useEffect as useEffect6, useLayoutEffect as useLayoutEffect2, useRef as useRef4 } from "react";
2872
2852
  import { ListMusic } from "lucide-react";
2873
2853
  import { useTrackList as useTrackList6 } from "@behindthemusictree/app-kit/genre-tree";
2874
2854
  import { TrackListOriginType as TrackListOriginType2 } from "@behindthemusictree/app-kit/genre-tree";
@@ -2888,14 +2868,14 @@ function TrackListSidebar({
2888
2868
  }) {
2889
2869
  const { trackList, loadMore, autoAdvanceScrollRequest } = useTrackList6();
2890
2870
  const trackNoun = useTrackNoun3();
2891
- const trackListRef = useRef5(null);
2892
- const previousOriginRef = useRef5(trackList?.origin ?? null);
2893
- const handledAutoAdvanceRequestIdRef = useRef5(null);
2894
- const shouldFollowPlaybackRef = useRef5(true);
2895
- const programmaticScrollTopRef = useRef5(null);
2896
- const userScrollIntentRef = useRef5(false);
2897
- const userScrollIntentTimerRef = useRef5(null);
2898
- const loadMoreSentinelRef = useRef5(null);
2871
+ const trackListRef = useRef4(null);
2872
+ const previousOriginRef = useRef4(trackList?.origin ?? null);
2873
+ const handledAutoAdvanceRequestIdRef = useRef4(null);
2874
+ const shouldFollowPlaybackRef = useRef4(true);
2875
+ const programmaticScrollTopRef = useRef4(null);
2876
+ const userScrollIntentRef = useRef4(false);
2877
+ const userScrollIntentTimerRef = useRef4(null);
2878
+ const loadMoreSentinelRef = useRef4(null);
2899
2879
  const hasMore = !!trackList && trackList.nextPage !== null;
2900
2880
  useEffect6(() => {
2901
2881
  const sentinel = loadMoreSentinelRef.current;
@@ -3037,7 +3017,7 @@ function TrackListSidebar({
3037
3017
  }
3038
3018
 
3039
3019
  // src/genre-tree/PlayerPanel.tsx
3040
- import { useEffect as useEffect7, useState as useState8 } from "react";
3020
+ import { useEffect as useEffect7, useState as useState9 } from "react";
3041
3021
  import { twMerge } from "tailwind-merge";
3042
3022
  import {
3043
3023
  usePlayer as usePlayer11,
@@ -3173,12 +3153,12 @@ function PlayerPanel({
3173
3153
  }) {
3174
3154
  const { playerTrackObject } = usePlayer11();
3175
3155
  const { toggleTrackListSidebar, isTrackListSidebarVisible } = useTrackListSidebarVisibility();
3176
- const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = useState8("");
3156
+ const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = useState9("");
3177
3157
  const loadedTrackTitle = playerTrackObject?.track.title;
3178
3158
  useEffect7(() => {
3179
3159
  if (loadedTrackTitle) setLastLoadedTrackTitle(loadedTrackTitle);
3180
3160
  }, [loadedTrackTitle]);
3181
- const [uncontrolledExtended, setUncontrolledExtended] = useState8(false);
3161
+ const [uncontrolledExtended, setUncontrolledExtended] = useState9(false);
3182
3162
  const isExtendRequested = expanded ?? uncontrolledExtended;
3183
3163
  const setIsExtendRequested = (next) => {
3184
3164
  setUncontrolledExtended(next);
@@ -3317,4 +3297,4 @@ export {
3317
3297
  GenreTreeViewSkeleton2 as GenreTreeViewSkeleton,
3318
3298
  GenreTreeOutlineSkeleton
3319
3299
  };
3320
- //# sourceMappingURL=chunk-AQASG5KT.js.map
3300
+ //# sourceMappingURL=chunk-QGGVPIXY.js.map