@behindthemusictree/app-kit-ui 35.0.0 → 36.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.
@@ -21,7 +21,7 @@ import {
21
21
  useGenrePlaylistPlayback,
22
22
  useGenreRemoteSearchGroup,
23
23
  useSongSearchGroup
24
- } from "../chunk-YC3WBUVO.js";
24
+ } from "../chunk-RTXLUHJY.js";
25
25
  import "../chunk-DKQQLLMY.js";
26
26
  export {
27
27
  GenreDetailPanel,
package/dist/index.cjs CHANGED
@@ -1715,7 +1715,7 @@ function GenrePlaylistTracks({
1715
1715
  const trackNoun = (0, import_track_noun2.useTrackNoun)();
1716
1716
  const uuid = genrePlaylist?.uuid;
1717
1717
  const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
1718
- const { fetch } = (0, import_transport5.useFetchWrapper)(getBackendBaseUrl);
1718
+ const { fetchBound } = (0, import_transport5.usePlaybackFetch)(getBackendBaseUrl);
1719
1719
  const playback = (0, import_transport5.usePlaybackContext)();
1720
1720
  const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
1721
1721
  queryKey: [...scope === "me" ? uuid ? import_genre_tree12.genrePlaylistQueryKeys.me.tracks(uuid) : ["missing-personal-genre-playlist", genreUuid] : artist ? [...import_genre_tree13.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), "artist", artist.uuid] : import_genre_tree13.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), ...playback.key ? [playback.key] : []],
@@ -1724,7 +1724,7 @@ function GenrePlaylistTracks({
1724
1724
  if (!uuid) throw new Error("Personal genre has no playlist");
1725
1725
  return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
1726
1726
  }
1727
- const response = await fetch(
1727
+ const response = await fetchBound(
1728
1728
  import_genre_tree13.libraryEndpoints.reference.songs.list(),
1729
1729
  true,
1730
1730
  false,
@@ -1736,7 +1736,9 @@ function GenrePlaylistTracks({
1736
1736
  },
1737
1737
  initialPageParam: scope === "me" ? 1 : "",
1738
1738
  getNextPageParam: (lastPage) => lastPage.nextPage ?? void 0,
1739
- enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken)
1739
+ enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken),
1740
+ retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
1741
+ retryDelay: 0
1740
1742
  });
1741
1743
  const [sentinel, setSentinel] = (0, import_react12.useState)(null);
1742
1744
  (0, import_react12.useEffect)(() => {
@@ -2512,12 +2514,12 @@ var SORTS = [
2512
2514
  function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
2513
2515
  const [page, setPage] = (0, import_react16.useState)(1);
2514
2516
  const [ordering, setOrdering] = (0, import_react16.useState)("title");
2515
- const { fetch } = (0, import_transport9.useFetchWrapper)(getBackendBaseUrl);
2516
2517
  const { playNewTrackListFromArtist } = (0, import_genre_tree24.useTrackList)();
2517
2518
  const { playerTrackObject } = (0, import_player10.usePlayer)();
2518
- const { data, isPending, isError } = (0, import_transport9.useQueryWithParse)({
2519
+ const { data, isPending, isError } = (0, import_transport9.usePlaybackQuery)({
2520
+ getBackendBaseUrl,
2519
2521
  queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
2520
- queryFn: () => fetch(import_genre_tree24.libraryEndpoints.reference.songs.list(), true, false, void 0, {
2522
+ queryFn: (fetchBound) => fetchBound(import_genre_tree24.libraryEndpoints.reference.songs.list(), true, false, void 0, {
2521
2523
  artist: artist.uuid,
2522
2524
  ordering,
2523
2525
  page
@@ -2955,6 +2957,8 @@ function GenreTreeView({
2955
2957
  };
2956
2958
  const {
2957
2959
  isLoading,
2960
+ isError,
2961
+ refetch,
2958
2962
  isFetching: isTreeFetching,
2959
2963
  genrePlaylistByNodeId,
2960
2964
  visibleGenrePlaylists,
@@ -3087,7 +3091,7 @@ function GenreTreeView({
3087
3091
  }, [selectedGenreUuid, artistUuid, songUuid]);
3088
3092
  const [isWheelRevealed, setIsWheelRevealed] = (0, import_react18.useState)(false);
3089
3093
  const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
3090
- const isTreeReady = !isLoading && (!usesHandoff || isWheelRevealed);
3094
+ const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
3091
3095
  const [resolveStyle, setResolveStyle] = (0, import_react18.useState)(null);
3092
3096
  const handleNodeStyleResolverChange = (0, import_react18.useCallback)(
3093
3097
  (resolver) => setResolveStyle(() => resolver),
@@ -3267,7 +3271,7 @@ function GenreTreeView({
3267
3271
  ] });
3268
3272
  };
3269
3273
  const actions = /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
3270
- !isLoading && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3274
+ !isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3271
3275
  GenreTreeSearch,
3272
3276
  {
3273
3277
  artistBaseUrl,
@@ -3298,9 +3302,9 @@ function GenreTreeView({
3298
3302
  extraGroups: extraSearchGroups
3299
3303
  }
3300
3304
  ),
3301
- !isLoading && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
3305
+ !isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
3302
3306
  /* @__PURE__ */ (0, import_jsx_runtime46.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: [
3303
- !isLoading && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3307
+ !isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3304
3308
  import_ui20.SegmentedControl,
3305
3309
  {
3306
3310
  "aria-label": "Tree view mode",
@@ -3314,7 +3318,7 @@ function GenreTreeView({
3314
3318
  ]
3315
3319
  }
3316
3320
  ),
3317
- !isLoading && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3321
+ !isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3318
3322
  "div",
3319
3323
  {
3320
3324
  className: "flex items-center gap-1",
@@ -3331,7 +3335,7 @@ function GenreTreeView({
3331
3335
  )
3332
3336
  }
3333
3337
  ),
3334
- !isLoading && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3338
+ !isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3335
3339
  import_ui20.IconTextButton,
3336
3340
  {
3337
3341
  icon: import_lucide_react16.Plus,
@@ -3354,7 +3358,7 @@ function GenreTreeView({
3354
3358
  children: actions
3355
3359
  }
3356
3360
  ),
3357
- !isLoading && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3361
+ !isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
3358
3362
  "div",
3359
3363
  {
3360
3364
  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))]" : "top-5"}`,
@@ -3362,8 +3366,12 @@ function GenreTreeView({
3362
3366
  }
3363
3367
  ),
3364
3368
  /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
3365
- !isLoading && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
3366
- isLoading ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : viewMode === "wheel" ? (
3369
+ !isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
3370
+ isLoading ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
3371
+ "Couldn't load the genre tree.",
3372
+ " ",
3373
+ /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
3374
+ ] }) : viewMode === "wheel" ? (
3367
3375
  // The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
3368
3376
  // and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
3369
3377
  // Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.