@behindthemusictree/app-kit-ui 35.0.0 → 37.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-YC3WBUVO.js → chunk-FTYMRCJS.js} +46 -30
- package/dist/chunk-FTYMRCJS.js.map +1 -0
- package/dist/genre-tree/index.cjs +43 -27
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +9 -4
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +43 -27
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +5 -5
- package/dist/chunk-YC3WBUVO.js.map +0 -1
|
@@ -483,6 +483,7 @@ function SearchBox({
|
|
|
483
483
|
groups,
|
|
484
484
|
onPicked,
|
|
485
485
|
onClear,
|
|
486
|
+
clearLabel,
|
|
486
487
|
leading,
|
|
487
488
|
className: className2,
|
|
488
489
|
onFocus
|
|
@@ -514,6 +515,7 @@ function SearchBox({
|
|
|
514
515
|
status,
|
|
515
516
|
loading,
|
|
516
517
|
onClear,
|
|
518
|
+
clearLabel,
|
|
517
519
|
leading,
|
|
518
520
|
inputClassName: "focus-visible:ring-0"
|
|
519
521
|
}
|
|
@@ -614,6 +616,8 @@ function GenreSearch({
|
|
|
614
616
|
onSelect,
|
|
615
617
|
selectedName = null,
|
|
616
618
|
onClear,
|
|
619
|
+
showClear,
|
|
620
|
+
clearLabel,
|
|
617
621
|
onPrevious,
|
|
618
622
|
placeholder,
|
|
619
623
|
onQueryChange,
|
|
@@ -661,7 +665,8 @@ function GenreSearch({
|
|
|
661
665
|
if (groupKey !== "genres") setQuery("");
|
|
662
666
|
onQueryChange?.("");
|
|
663
667
|
},
|
|
664
|
-
|
|
668
|
+
clearLabel,
|
|
669
|
+
onClear: showClear ?? canClear ? () => {
|
|
665
670
|
clear();
|
|
666
671
|
onQueryChange?.("");
|
|
667
672
|
} : void 0,
|
|
@@ -1096,7 +1101,7 @@ import { z } from "zod";
|
|
|
1096
1101
|
import { FaPlay, FaPause } from "react-icons/fa";
|
|
1097
1102
|
import { PanelSection, RingLoader, Skeleton } from "@behindthemusictree/ui";
|
|
1098
1103
|
import { useSession } from "@behindthemusictree/app-kit/auth";
|
|
1099
|
-
import { usePlaybackContext,
|
|
1104
|
+
import { usePlaybackContext, usePlaybackFetch } from "@behindthemusictree/app-kit/transport";
|
|
1100
1105
|
import { PaginatedResponseSchema } from "@behindthemusictree/app-kit/transport";
|
|
1101
1106
|
import { parseWithLog } from "@behindthemusictree/app-kit/transport";
|
|
1102
1107
|
import { usePlayer as usePlayer4 } from "@behindthemusictree/app-kit/player";
|
|
@@ -1174,7 +1179,7 @@ function GenrePlaylistTracks({
|
|
|
1174
1179
|
const trackNoun = useTrackNoun();
|
|
1175
1180
|
const uuid = genrePlaylist?.uuid;
|
|
1176
1181
|
const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
|
|
1177
|
-
const {
|
|
1182
|
+
const { fetchBound } = usePlaybackFetch(getBackendBaseUrl);
|
|
1178
1183
|
const playback = usePlaybackContext();
|
|
1179
1184
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = useInfiniteQuery({
|
|
1180
1185
|
queryKey: [...scope === "me" ? uuid ? genrePlaylistQueryKeys.me.tracks(uuid) : ["missing-personal-genre-playlist", genreUuid] : artist ? [...libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), "artist", artist.uuid] : libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), ...playback.key ? [playback.key] : []],
|
|
@@ -1183,7 +1188,7 @@ function GenrePlaylistTracks({
|
|
|
1183
1188
|
if (!uuid) throw new Error("Personal genre has no playlist");
|
|
1184
1189
|
return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
|
|
1185
1190
|
}
|
|
1186
|
-
const response = await
|
|
1191
|
+
const response = await fetchBound(
|
|
1187
1192
|
libraryEndpoints.reference.songs.list(),
|
|
1188
1193
|
true,
|
|
1189
1194
|
false,
|
|
@@ -1195,7 +1200,9 @@ function GenrePlaylistTracks({
|
|
|
1195
1200
|
},
|
|
1196
1201
|
initialPageParam: scope === "me" ? 1 : "",
|
|
1197
1202
|
getNextPageParam: (lastPage) => lastPage.nextPage ?? void 0,
|
|
1198
|
-
enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken)
|
|
1203
|
+
enabled: playback.ready && (scope !== "me" || uuid !== void 0 && sessionRestored && !!session?.accessToken),
|
|
1204
|
+
retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
|
|
1205
|
+
retryDelay: 0
|
|
1199
1206
|
});
|
|
1200
1207
|
const [sentinel, setSentinel] = useState6(null);
|
|
1201
1208
|
useEffect3(() => {
|
|
@@ -1514,10 +1521,12 @@ function useGenreDetailContent({
|
|
|
1514
1521
|
};
|
|
1515
1522
|
}, [detail, scope]);
|
|
1516
1523
|
if (isError) return {
|
|
1524
|
+
name: null,
|
|
1517
1525
|
title: "Genre unavailable",
|
|
1518
1526
|
content: /* @__PURE__ */ jsx20("p", { role: "alert", className: "p-4 text-sm text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
1519
1527
|
};
|
|
1520
1528
|
if (isPending || !detail || !view) return {
|
|
1529
|
+
name: null,
|
|
1521
1530
|
title: "Loading genre\u2026",
|
|
1522
1531
|
content: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3 p-4", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
1523
1532
|
/* @__PURE__ */ jsx20(Skeleton3, { className: "h-6 w-2/3" }),
|
|
@@ -1539,6 +1548,7 @@ function useGenreDetailContent({
|
|
|
1539
1548
|
);
|
|
1540
1549
|
const ancestors = /* @__PURE__ */ jsx20(GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
1541
1550
|
return {
|
|
1551
|
+
name: detail.name,
|
|
1542
1552
|
title: detail.name,
|
|
1543
1553
|
headerAccent: { background: view.fill, color: ACCENT_TEXT_COLOR },
|
|
1544
1554
|
aside: expanded ? ancestors : void 0,
|
|
@@ -1580,7 +1590,7 @@ function GenreDetailPanel({
|
|
|
1580
1590
|
onExpandedChange,
|
|
1581
1591
|
edgeTab,
|
|
1582
1592
|
extras,
|
|
1583
|
-
|
|
1593
|
+
titleInSearch
|
|
1584
1594
|
}) {
|
|
1585
1595
|
const panel = useGenreDetailContent({
|
|
1586
1596
|
genreUuid,
|
|
@@ -1603,7 +1613,7 @@ function GenreDetailPanel({
|
|
|
1603
1613
|
onExpandedChange,
|
|
1604
1614
|
edgeTab,
|
|
1605
1615
|
aside: panel.aside,
|
|
1606
|
-
|
|
1616
|
+
titleInSearch,
|
|
1607
1617
|
headerActions: onExpandedChange ? /* @__PURE__ */ jsx20(IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ jsx20(Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ jsx20(Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
1608
1618
|
children: panel.content
|
|
1609
1619
|
}
|
|
@@ -1852,7 +1862,7 @@ import {
|
|
|
1852
1862
|
songUnplayableReason as songUnplayableReason3,
|
|
1853
1863
|
useTrackList as useTrackList4
|
|
1854
1864
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
1855
|
-
import { PaginatedResponseSchema as PaginatedResponseSchema2,
|
|
1865
|
+
import { PaginatedResponseSchema as PaginatedResponseSchema2, usePlaybackQuery } from "@behindthemusictree/app-kit/transport";
|
|
1856
1866
|
|
|
1857
1867
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
1858
1868
|
import { usePlayer as usePlayer7 } from "@behindthemusictree/app-kit/player";
|
|
@@ -1988,12 +1998,12 @@ var SORTS = [
|
|
|
1988
1998
|
function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
|
|
1989
1999
|
const [page, setPage] = useState7(1);
|
|
1990
2000
|
const [ordering, setOrdering] = useState7("title");
|
|
1991
|
-
const { fetch } = useFetchWrapper2(getBackendBaseUrl);
|
|
1992
2001
|
const { playNewTrackListFromArtist } = useTrackList4();
|
|
1993
2002
|
const { playerTrackObject } = usePlayer8();
|
|
1994
|
-
const { data, isPending, isError } =
|
|
2003
|
+
const { data, isPending, isError } = usePlaybackQuery({
|
|
2004
|
+
getBackendBaseUrl,
|
|
1995
2005
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
1996
|
-
queryFn: () =>
|
|
2006
|
+
queryFn: (fetchBound) => fetchBound(libraryEndpoints2.reference.songs.list(), true, false, void 0, {
|
|
1997
2007
|
artist: artist.uuid,
|
|
1998
2008
|
ordering,
|
|
1999
2009
|
page
|
|
@@ -2439,6 +2449,8 @@ function GenreTreeView({
|
|
|
2439
2449
|
};
|
|
2440
2450
|
const {
|
|
2441
2451
|
isLoading,
|
|
2452
|
+
isError,
|
|
2453
|
+
refetch,
|
|
2442
2454
|
isFetching: isTreeFetching,
|
|
2443
2455
|
genrePlaylistByNodeId,
|
|
2444
2456
|
visibleGenrePlaylists,
|
|
@@ -2571,7 +2583,7 @@ function GenreTreeView({
|
|
|
2571
2583
|
}, [selectedGenreUuid, artistUuid, songUuid]);
|
|
2572
2584
|
const [isWheelRevealed, setIsWheelRevealed] = useState9(false);
|
|
2573
2585
|
const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
|
|
2574
|
-
const isTreeReady = !isLoading && (!usesHandoff || isWheelRevealed);
|
|
2586
|
+
const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
|
|
2575
2587
|
const [resolveStyle, setResolveStyle] = useState9(null);
|
|
2576
2588
|
const handleNodeStyleResolverChange = useCallback6(
|
|
2577
2589
|
(resolver) => setResolveStyle(() => resolver),
|
|
@@ -2602,7 +2614,6 @@ function GenreTreeView({
|
|
|
2602
2614
|
if (node !== null && songUuid !== null) changeSong(null);
|
|
2603
2615
|
selectNode(node);
|
|
2604
2616
|
};
|
|
2605
|
-
const handleGenreSearchClear = clearSelection;
|
|
2606
2617
|
const handleGenreSearchSelect = (genrePlaylist2) => {
|
|
2607
2618
|
reopenPanel();
|
|
2608
2619
|
if (songUuid !== null) changeSong(null);
|
|
@@ -2685,7 +2696,7 @@ function GenreTreeView({
|
|
|
2685
2696
|
expanded: overlayPanel.expanded ?? false,
|
|
2686
2697
|
onExpandedChange: overlayPanel.onExpandedChange,
|
|
2687
2698
|
onClose: overlayPanel.onClose,
|
|
2688
|
-
|
|
2699
|
+
titleInSearch: false
|
|
2689
2700
|
};
|
|
2690
2701
|
} else if (selectedGenreUuid) {
|
|
2691
2702
|
activePanel = {
|
|
@@ -2695,7 +2706,7 @@ function GenreTreeView({
|
|
|
2695
2706
|
expanded: isExpanded,
|
|
2696
2707
|
onExpandedChange: changeExpanded,
|
|
2697
2708
|
onClose: clearSelection,
|
|
2698
|
-
|
|
2709
|
+
titleInSearch: true,
|
|
2699
2710
|
headerAccent: relations ? { background: relations.fill, color: relations.textColor } : genreContent.headerAccent
|
|
2700
2711
|
};
|
|
2701
2712
|
} else if (builtInPanel) {
|
|
@@ -2706,7 +2717,7 @@ function GenreTreeView({
|
|
|
2706
2717
|
expanded: builtInPanel.expanded,
|
|
2707
2718
|
onExpandedChange: builtInPanel.onExpandedChange,
|
|
2708
2719
|
onClose: builtInPanel.onClose,
|
|
2709
|
-
|
|
2720
|
+
titleInSearch: true
|
|
2710
2721
|
};
|
|
2711
2722
|
}
|
|
2712
2723
|
const isPanelShown = activePanel !== null && (selectedGenreUuid !== null || isTreeReady);
|
|
@@ -2751,7 +2762,7 @@ function GenreTreeView({
|
|
|
2751
2762
|
] });
|
|
2752
2763
|
};
|
|
2753
2764
|
const actions = /* @__PURE__ */ jsxs26(Fragment14, { children: [
|
|
2754
|
-
!isLoading && /* @__PURE__ */ jsx34(
|
|
2765
|
+
!isLoading && !isError && /* @__PURE__ */ jsx34(
|
|
2755
2766
|
GenreTreeSearch,
|
|
2756
2767
|
{
|
|
2757
2768
|
artistBaseUrl,
|
|
@@ -2774,17 +2785,19 @@ function GenreTreeView({
|
|
|
2774
2785
|
if (songUuid) changeSong(null);
|
|
2775
2786
|
selectGenre(uuid);
|
|
2776
2787
|
},
|
|
2777
|
-
selectedName:
|
|
2778
|
-
onClear:
|
|
2788
|
+
selectedName: selectedGenreUuid ? genreContent.name : typeof builtInPanel?.title === "string" ? builtInPanel.title : null,
|
|
2789
|
+
onClear: activePanel?.onClose,
|
|
2790
|
+
showClear: activePanel?.titleInSearch ?? false,
|
|
2791
|
+
clearLabel: "Close panel",
|
|
2779
2792
|
onPrevious: handlePrevious,
|
|
2780
2793
|
onQueryChange: onSearchQueryChange,
|
|
2781
2794
|
onFocus: onSearchFocus,
|
|
2782
2795
|
extraGroups: extraSearchGroups
|
|
2783
2796
|
}
|
|
2784
2797
|
),
|
|
2785
|
-
!isLoading && filterArtist && /* @__PURE__ */ jsx34("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
2798
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ jsx34("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
2786
2799
|
/* @__PURE__ */ jsxs26("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: [
|
|
2787
|
-
!isLoading && !isControlled && /* @__PURE__ */ jsx34(
|
|
2800
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ jsx34(
|
|
2788
2801
|
SegmentedControl2,
|
|
2789
2802
|
{
|
|
2790
2803
|
"aria-label": "Tree view mode",
|
|
@@ -2798,7 +2811,7 @@ function GenreTreeView({
|
|
|
2798
2811
|
]
|
|
2799
2812
|
}
|
|
2800
2813
|
),
|
|
2801
|
-
!isLoading && showDisplayOptions && /* @__PURE__ */ jsx34(
|
|
2814
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ jsx34(
|
|
2802
2815
|
"div",
|
|
2803
2816
|
{
|
|
2804
2817
|
className: "flex items-center gap-1",
|
|
@@ -2815,7 +2828,7 @@ function GenreTreeView({
|
|
|
2815
2828
|
)
|
|
2816
2829
|
}
|
|
2817
2830
|
),
|
|
2818
|
-
!isLoading && !readOnly && showAddRoot && /* @__PURE__ */ jsx34(
|
|
2831
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ jsx34(
|
|
2819
2832
|
IconTextButton,
|
|
2820
2833
|
{
|
|
2821
2834
|
icon: Plus2,
|
|
@@ -2838,7 +2851,7 @@ function GenreTreeView({
|
|
|
2838
2851
|
children: actions
|
|
2839
2852
|
}
|
|
2840
2853
|
),
|
|
2841
|
-
!isLoading && filterArtist && /* @__PURE__ */ jsx34(
|
|
2854
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ jsx34(
|
|
2842
2855
|
"div",
|
|
2843
2856
|
{
|
|
2844
2857
|
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"}`,
|
|
@@ -2846,8 +2859,12 @@ function GenreTreeView({
|
|
|
2846
2859
|
}
|
|
2847
2860
|
),
|
|
2848
2861
|
/* @__PURE__ */ jsx34("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ jsxs26("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
2849
|
-
!isLoading && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ jsx34("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
2850
|
-
isLoading ? /* @__PURE__ */ jsx34(GenreTreeViewSkeleton, { viewMode }) :
|
|
2862
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ jsx34("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
2863
|
+
isLoading ? /* @__PURE__ */ jsx34(GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ jsxs26("p", { role: "alert", className: "m-auto text-center", children: [
|
|
2864
|
+
"Couldn't load the genre tree.",
|
|
2865
|
+
" ",
|
|
2866
|
+
/* @__PURE__ */ jsx34("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
2867
|
+
] }) : viewMode === "wheel" ? (
|
|
2851
2868
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
2852
2869
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
2853
2870
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
@@ -2961,8 +2978,7 @@ function GenreTreeView({
|
|
|
2961
2978
|
ref: panelRef,
|
|
2962
2979
|
side: "left",
|
|
2963
2980
|
title: activePanel?.title ?? "",
|
|
2964
|
-
|
|
2965
|
-
hideClose: activePanel?.compact,
|
|
2981
|
+
titleInSearch: activePanel?.titleInSearch,
|
|
2966
2982
|
headerAccent: activePanel?.headerAccent,
|
|
2967
2983
|
headerActions: expandButton,
|
|
2968
2984
|
onClose: activePanel?.onClose ?? noop,
|
|
@@ -2971,7 +2987,7 @@ function GenreTreeView({
|
|
|
2971
2987
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
2972
2988
|
aside: activePanel?.aside,
|
|
2973
2989
|
edgeTab: detailTab,
|
|
2974
|
-
headerClassName: "pt-[calc(var(--layout-search-h)+var(--layout-panel-inset)+0.5rem)]",
|
|
2990
|
+
headerClassName: activePanel?.titleInSearch ? void 0 : "pt-[calc(var(--layout-search-h)+var(--layout-panel-inset)+0.5rem)]",
|
|
2975
2991
|
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ jsxs26(Fragment14, { children: [
|
|
2976
2992
|
activePanel.content,
|
|
2977
2993
|
activePanel.aside
|
|
@@ -3453,4 +3469,4 @@ export {
|
|
|
3453
3469
|
GenreTreeViewSkeleton2 as GenreTreeViewSkeleton,
|
|
3454
3470
|
GenreTreeOutlineSkeleton
|
|
3455
3471
|
};
|
|
3456
|
-
//# sourceMappingURL=chunk-
|
|
3472
|
+
//# sourceMappingURL=chunk-FTYMRCJS.js.map
|