@behindthemusictree/app-kit-ui 39.0.0 → 40.1.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-2K2SQOUJ.js → chunk-DPYUE6WD.js} +379 -411
- package/dist/chunk-DPYUE6WD.js.map +1 -0
- package/dist/genre-tree/index.cjs +461 -494
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +12 -5
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +456 -489
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -6
- package/dist/chunk-2K2SQOUJ.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -591,12 +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
|
|
599
|
+
var import_popup5 = require("@behindthemusictree/app-kit/popup");
|
|
600
600
|
|
|
601
601
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
602
602
|
var import_genre_tree = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -610,7 +610,7 @@ var genrePlaylistSize = (genrePlaylist, metric) => {
|
|
|
610
610
|
};
|
|
611
611
|
|
|
612
612
|
// src/genre-tree/playlist-tree/toTreeNodes.ts
|
|
613
|
-
function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
613
|
+
function toTreeNodes(genrePlaylists, sizeMetric, focusUuids) {
|
|
614
614
|
return genrePlaylists.map((genrePlaylist) => ({
|
|
615
615
|
id: genrePlaylist.uuid,
|
|
616
616
|
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
@@ -621,27 +621,45 @@ function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
|
621
621
|
side: genrePlaylist.criteria?.side ?? void 0,
|
|
622
622
|
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
623
623
|
umbrella: genrePlaylist.isUmbrella,
|
|
624
|
-
scene: genrePlaylist.scene ?? void 0
|
|
624
|
+
scene: genrePlaylist.scene ?? void 0,
|
|
625
|
+
muted: focusUuids ? !focusUuids.has(genrePlaylist.uuid) : void 0
|
|
625
626
|
}));
|
|
626
627
|
}
|
|
627
628
|
|
|
629
|
+
// src/genre-tree/playlist-tree/toGenreNodeStyles.ts
|
|
630
|
+
function toGenreNodeStyles(relations, genrePlaylists) {
|
|
631
|
+
const styles = /* @__PURE__ */ new Map();
|
|
632
|
+
if (!relations) return styles;
|
|
633
|
+
const genreUuidByPlaylistUuid = new Map(
|
|
634
|
+
genrePlaylists.flatMap((genrePlaylist) => genrePlaylist.criteria ? [[genrePlaylist.uuid, genrePlaylist.criteria.uuid]] : [])
|
|
635
|
+
);
|
|
636
|
+
const drawn = [relations, relations.parentNode, ...relations.childNodes, ...relations.ancestorNodes];
|
|
637
|
+
for (const entry of drawn) {
|
|
638
|
+
const genreUuid = entry && genreUuidByPlaylistUuid.get(entry.node.id);
|
|
639
|
+
if (entry && genreUuid) styles.set(genreUuid, { fill: entry.fill, textColor: entry.textColor });
|
|
640
|
+
}
|
|
641
|
+
return styles;
|
|
642
|
+
}
|
|
643
|
+
|
|
628
644
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
629
645
|
var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
|
|
630
646
|
var import_react4 = require("react");
|
|
631
647
|
var import_genre_tree_view = require("@behindthemusictree/genre-tree-view");
|
|
632
648
|
var import_player = require("@behindthemusictree/app-kit/player");
|
|
633
|
-
var import_popup2 = require("@behindthemusictree/app-kit/popup");
|
|
634
|
-
var import_transport3 = require("@behindthemusictree/app-kit/transport");
|
|
635
649
|
|
|
636
|
-
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.
|
|
650
|
+
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.tsx
|
|
637
651
|
var import_react3 = require("react");
|
|
638
652
|
var import_genre_tree2 = require("@behindthemusictree/app-kit/genre-tree");
|
|
653
|
+
var import_popup2 = require("@behindthemusictree/app-kit/popup");
|
|
654
|
+
var import_transport3 = require("@behindthemusictree/app-kit/transport");
|
|
655
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
639
656
|
function useGenrePlaylistPlayback({
|
|
640
657
|
scope,
|
|
641
658
|
genrePlaylists,
|
|
642
659
|
artist = null
|
|
643
660
|
}) {
|
|
644
661
|
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
662
|
+
const { showPopup } = (0, import_popup2.usePopup)();
|
|
645
663
|
const origin = trackList?.origin;
|
|
646
664
|
const playing = (0, import_react3.useMemo)(() => {
|
|
647
665
|
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
@@ -653,14 +671,20 @@ function useGenrePlaylistPlayback({
|
|
|
653
671
|
}, [origin, artist, genrePlaylists, scope]);
|
|
654
672
|
const play = (0, import_react3.useCallback)(async (playlist, requested) => {
|
|
655
673
|
if (artist && !playlist.criteria) return;
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
674
|
+
try {
|
|
675
|
+
const selection = scope === "reference" && playlist.criteria !== null ? requested ?? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
676
|
+
await (selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope));
|
|
677
|
+
} catch (error) {
|
|
678
|
+
console.error("Failed to load genre playlist tracks:", error);
|
|
679
|
+
if (error instanceof import_genre_tree2.TracksFailureAlreadyReportedError) return;
|
|
680
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport3.AppError ? error.code : import_transport3.ErrorCode.CLIENT_UNKNOWN }));
|
|
681
|
+
}
|
|
682
|
+
}, [artist, scope, playNewTrackListFromGenrePlaylist, showPopup]);
|
|
659
683
|
return (0, import_react3.useMemo)(() => ({ playing, play }), [playing, play]);
|
|
660
684
|
}
|
|
661
685
|
|
|
662
686
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
663
|
-
var
|
|
687
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
664
688
|
function GenrePlaylistTreePerRoot({
|
|
665
689
|
scope,
|
|
666
690
|
className: className2,
|
|
@@ -679,25 +703,16 @@ function GenrePlaylistTreePerRoot({
|
|
|
679
703
|
viewportRestore,
|
|
680
704
|
onViewportChange,
|
|
681
705
|
playback,
|
|
706
|
+
focusUuids,
|
|
682
707
|
...hostPanel
|
|
683
708
|
}) {
|
|
684
709
|
const { isPlaying, setIsPlaying } = (0, import_player.usePlayer)();
|
|
685
710
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: genrePlaylistTreePerRoot });
|
|
686
711
|
const { playing, play } = playback ?? defaultPlayback;
|
|
687
712
|
const playingNodeId = playing?.uuid ?? null;
|
|
688
|
-
const { showPopup } = (0, import_popup2.usePopup)();
|
|
689
713
|
const nodes = (0, import_react4.useMemo)(
|
|
690
|
-
() => genrePlaylistTreePerRoot
|
|
691
|
-
|
|
692
|
-
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
693
|
-
name: genrePlaylist.name,
|
|
694
|
-
itemCount: (0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist),
|
|
695
|
-
actionable: Boolean(genrePlaylist.criteria),
|
|
696
|
-
side: genrePlaylist.criteria?.side ?? void 0,
|
|
697
|
-
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
698
|
-
umbrella: genrePlaylist.isUmbrella
|
|
699
|
-
})),
|
|
700
|
-
[genrePlaylistTreePerRoot]
|
|
714
|
+
() => toTreeNodes(genrePlaylistTreePerRoot, "songs", focusUuids),
|
|
715
|
+
[genrePlaylistTreePerRoot, focusUuids]
|
|
701
716
|
);
|
|
702
717
|
const handlePlayPause = (0, import_react4.useCallback)(
|
|
703
718
|
(nodeId) => {
|
|
@@ -710,18 +725,14 @@ function GenrePlaylistTreePerRoot({
|
|
|
710
725
|
if ((0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
711
726
|
return;
|
|
712
727
|
}
|
|
713
|
-
play(genrePlaylist)
|
|
714
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
715
|
-
showPopup(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(InternalErrorPopup, { errorCode: import_transport3.ErrorCode.CLIENT_UNKNOWN }));
|
|
716
|
-
});
|
|
728
|
+
void play(genrePlaylist);
|
|
717
729
|
},
|
|
718
730
|
[
|
|
719
731
|
genrePlaylistTreePerRoot,
|
|
720
732
|
playingNodeId,
|
|
721
733
|
isPlaying,
|
|
722
734
|
setIsPlaying,
|
|
723
|
-
play
|
|
724
|
-
showPopup
|
|
735
|
+
play
|
|
725
736
|
]
|
|
726
737
|
);
|
|
727
738
|
const handleAddChild = (0, import_react4.useCallback)(
|
|
@@ -744,7 +755,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
744
755
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
745
756
|
}
|
|
746
757
|
}, []);
|
|
747
|
-
return /* @__PURE__ */ (0,
|
|
758
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
748
759
|
import_genre_tree_view.GenreTree,
|
|
749
760
|
{
|
|
750
761
|
className: className2,
|
|
@@ -775,9 +786,7 @@ var import_genre_tree4 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
775
786
|
var import_react5 = require("react");
|
|
776
787
|
var import_genre_tree_view2 = require("@behindthemusictree/genre-tree-view");
|
|
777
788
|
var import_player2 = require("@behindthemusictree/app-kit/player");
|
|
778
|
-
var
|
|
779
|
-
var import_transport4 = require("@behindthemusictree/app-kit/transport");
|
|
780
|
-
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
789
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
781
790
|
function GenrePlaylistTreeWheel({
|
|
782
791
|
scope,
|
|
783
792
|
className: className2,
|
|
@@ -798,24 +807,16 @@ function GenrePlaylistTreeWheel({
|
|
|
798
807
|
viewportRestore,
|
|
799
808
|
onViewportChange,
|
|
800
809
|
playback,
|
|
810
|
+
focusUuids,
|
|
801
811
|
...hostPanel
|
|
802
812
|
}) {
|
|
803
813
|
const { isPlaying, setIsPlaying } = (0, import_player2.usePlayer)();
|
|
804
814
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
805
815
|
const { playing, play } = playback ?? defaultPlayback;
|
|
806
816
|
const playingNodeId = playing?.uuid ?? null;
|
|
807
|
-
const { showPopup } = (0, import_popup3.usePopup)();
|
|
808
817
|
const nodes = (0, import_react5.useMemo)(
|
|
809
|
-
() => genrePlaylists
|
|
810
|
-
|
|
811
|
-
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
812
|
-
name: genrePlaylist.name,
|
|
813
|
-
itemCount: genrePlaylistSize(genrePlaylist, sizeMetric),
|
|
814
|
-
actionable: Boolean(genrePlaylist.criteria),
|
|
815
|
-
side: genrePlaylist.criteria?.side ?? void 0,
|
|
816
|
-
wikidataId: genrePlaylist.criteria?.wikidataId ?? null
|
|
817
|
-
})),
|
|
818
|
-
[genrePlaylists, sizeMetric]
|
|
818
|
+
() => toTreeNodes(genrePlaylists, sizeMetric, focusUuids),
|
|
819
|
+
[genrePlaylists, sizeMetric, focusUuids]
|
|
819
820
|
);
|
|
820
821
|
const handlePlayPause = (0, import_react5.useCallback)(
|
|
821
822
|
(nodeId) => {
|
|
@@ -828,18 +829,14 @@ function GenrePlaylistTreeWheel({
|
|
|
828
829
|
if ((0, import_genre_tree4.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
829
830
|
return;
|
|
830
831
|
}
|
|
831
|
-
play(genrePlaylist)
|
|
832
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
833
|
-
showPopup(/* @__PURE__ */ (0, import_jsx_runtime13.jsx)(InternalErrorPopup, { errorCode: import_transport4.ErrorCode.CLIENT_UNKNOWN }));
|
|
834
|
-
});
|
|
832
|
+
void play(genrePlaylist);
|
|
835
833
|
},
|
|
836
834
|
[
|
|
837
835
|
genrePlaylists,
|
|
838
836
|
playingNodeId,
|
|
839
837
|
isPlaying,
|
|
840
838
|
setIsPlaying,
|
|
841
|
-
play
|
|
842
|
-
showPopup
|
|
839
|
+
play
|
|
843
840
|
]
|
|
844
841
|
);
|
|
845
842
|
const handleAddChild = (0, import_react5.useCallback)(
|
|
@@ -862,7 +859,7 @@ function GenrePlaylistTreeWheel({
|
|
|
862
859
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
863
860
|
}
|
|
864
861
|
}, []);
|
|
865
|
-
return /* @__PURE__ */ (0,
|
|
862
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
866
863
|
import_genre_tree_view2.GenreTreeWheel,
|
|
867
864
|
{
|
|
868
865
|
className: className2,
|
|
@@ -894,7 +891,7 @@ var import_genre_tree5 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
894
891
|
var import_react6 = require("react");
|
|
895
892
|
var import_genre_tree_view3 = require("@behindthemusictree/genre-tree-view");
|
|
896
893
|
var import_player3 = require("@behindthemusictree/app-kit/player");
|
|
897
|
-
var
|
|
894
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
898
895
|
function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
899
896
|
const {
|
|
900
897
|
scope,
|
|
@@ -927,7 +924,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
927
924
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
928
925
|
const { playing, play } = playback ?? defaultPlayback;
|
|
929
926
|
const playingNodeId = playing?.uuid ?? null;
|
|
930
|
-
const nodes = (0, import_react6.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric), [genrePlaylists, sizeMetric]);
|
|
927
|
+
const nodes = (0, import_react6.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric, props.focusUuids), [genrePlaylists, sizeMetric, props.focusUuids]);
|
|
931
928
|
const handlePlayPause = (0, import_react6.useCallback)(
|
|
932
929
|
(nodeId) => {
|
|
933
930
|
const genrePlaylist = genrePlaylists.find((g) => g.uuid === nodeId);
|
|
@@ -939,9 +936,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
939
936
|
if ((0, import_genre_tree5.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
940
937
|
return;
|
|
941
938
|
}
|
|
942
|
-
play(genrePlaylist)
|
|
943
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
944
|
-
});
|
|
939
|
+
void play(genrePlaylist);
|
|
945
940
|
},
|
|
946
941
|
[genrePlaylists, playingNodeId, isPlaying, setIsPlaying, play]
|
|
947
942
|
);
|
|
@@ -981,7 +976,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
981
976
|
onSelectedNodeChange,
|
|
982
977
|
...hostPanel
|
|
983
978
|
};
|
|
984
|
-
return outline ? /* @__PURE__ */ (0,
|
|
979
|
+
return outline ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_genre_tree_view3.GenreTreeOutline, { ...treeProps }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
985
980
|
import_genre_tree_view3.GenreTreeWheelRadialPopCore,
|
|
986
981
|
{
|
|
987
982
|
...treeProps,
|
|
@@ -998,7 +993,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
998
993
|
|
|
999
994
|
// src/genre-tree/GenreTreeWheelHandoff.tsx
|
|
1000
995
|
var import_react7 = require("react");
|
|
1001
|
-
var
|
|
996
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1002
997
|
function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
1003
998
|
const [revealed, setRevealed] = (0, import_react7.useState)(false);
|
|
1004
999
|
const onRevealedChangeRef = (0, import_react7.useRef)(onRevealedChange);
|
|
@@ -1017,8 +1012,8 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
1017
1012
|
cancelAnimationFrame(innerFrame);
|
|
1018
1013
|
};
|
|
1019
1014
|
}, []);
|
|
1020
|
-
return /* @__PURE__ */ (0,
|
|
1021
|
-
/* @__PURE__ */ (0,
|
|
1015
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
1016
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1022
1017
|
"div",
|
|
1023
1018
|
{
|
|
1024
1019
|
className: "absolute inset-0 transition-opacity duration-150 ease-out",
|
|
@@ -1027,7 +1022,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
1027
1022
|
children
|
|
1028
1023
|
}
|
|
1029
1024
|
),
|
|
1030
|
-
!revealed && /* @__PURE__ */ (0,
|
|
1025
|
+
!revealed && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "absolute inset-0", "aria-hidden": "true", children: skeleton })
|
|
1031
1026
|
] });
|
|
1032
1027
|
}
|
|
1033
1028
|
|
|
@@ -1042,7 +1037,7 @@ var import_genre_tree9 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1042
1037
|
// src/genre-tree/search/SearchBox.tsx
|
|
1043
1038
|
var import_react8 = require("react");
|
|
1044
1039
|
var import_ui6 = require("@behindthemusictree/ui");
|
|
1045
|
-
var
|
|
1040
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1046
1041
|
function SearchBox({
|
|
1047
1042
|
label,
|
|
1048
1043
|
placeholder,
|
|
@@ -1064,7 +1059,7 @@ function SearchBox({
|
|
|
1064
1059
|
groups.find((group) => group.key === groupKey)?.items.find((item) => item.key === itemKey)?.onSelect();
|
|
1065
1060
|
onPicked?.(groupKey, itemKey);
|
|
1066
1061
|
};
|
|
1067
|
-
return /* @__PURE__ */ (0,
|
|
1062
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: className2, onFocusCapture: onFocus, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1068
1063
|
import_ui6.SearchCombobox,
|
|
1069
1064
|
{
|
|
1070
1065
|
ariaLabel: label,
|
|
@@ -1096,7 +1091,7 @@ var searchStatus = (state, count, noun) => state.isError ? SEARCH_FAILED_STATUS
|
|
|
1096
1091
|
|
|
1097
1092
|
// src/genre-tree/search/useArtistSearchGroup.tsx
|
|
1098
1093
|
var import_genre_tree6 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1099
|
-
var
|
|
1094
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1100
1095
|
function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
1101
1096
|
const search = (0, import_genre_tree6.useArtistSearch)(getBaseUrl, enabled ? text : "");
|
|
1102
1097
|
if (!enabled) return void 0;
|
|
@@ -1105,15 +1100,15 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1105
1100
|
label: "Artists",
|
|
1106
1101
|
items: search.artists.map((artist) => ({
|
|
1107
1102
|
key: artist.uuid,
|
|
1108
|
-
content: /* @__PURE__ */ (0,
|
|
1109
|
-
/* @__PURE__ */ (0,
|
|
1103
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
1104
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
1110
1105
|
artist.name,
|
|
1111
|
-
artist.disambiguation && /* @__PURE__ */ (0,
|
|
1106
|
+
artist.disambiguation && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "font-normal text-[var(--color-neutral-500)]", children: [
|
|
1112
1107
|
" \xB7 ",
|
|
1113
1108
|
artist.disambiguation
|
|
1114
1109
|
] })
|
|
1115
1110
|
] }),
|
|
1116
|
-
artist.matchedAlias && /* @__PURE__ */ (0,
|
|
1111
|
+
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [
|
|
1117
1112
|
"also known as ",
|
|
1118
1113
|
artist.matchedAlias
|
|
1119
1114
|
] })
|
|
@@ -1127,7 +1122,7 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1127
1122
|
|
|
1128
1123
|
// src/genre-tree/search/useSongSearchGroup.tsx
|
|
1129
1124
|
var import_genre_tree7 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1130
|
-
var
|
|
1125
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1131
1126
|
function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
1132
1127
|
const search = (0, import_genre_tree7.useSongSearch)(getBaseUrl, enabled ? text : "");
|
|
1133
1128
|
if (!enabled) return void 0;
|
|
@@ -1136,9 +1131,9 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1136
1131
|
label: "Songs",
|
|
1137
1132
|
items: search.songs.map((song) => ({
|
|
1138
1133
|
key: song.uuid,
|
|
1139
|
-
content: /* @__PURE__ */ (0,
|
|
1140
|
-
/* @__PURE__ */ (0,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1134
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
1135
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
1136
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [song.artists.map((artist) => artist.name).join(", "), song.genre?.name ?? "No genre"].filter(Boolean).join(" \xB7 ") })
|
|
1142
1137
|
] }),
|
|
1143
1138
|
onSelect: () => onSelect(song)
|
|
1144
1139
|
})),
|
|
@@ -1149,7 +1144,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1149
1144
|
|
|
1150
1145
|
// src/genre-tree/search/useGenreRemoteSearchGroup.tsx
|
|
1151
1146
|
var import_genre_tree8 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1152
|
-
var
|
|
1147
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1153
1148
|
function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres", label = "Genres", filter, describe, ...options } = {}) {
|
|
1154
1149
|
const search = (0, import_genre_tree8.useGenreRemoteSearch)(getBaseUrl, text, options);
|
|
1155
1150
|
const genres = filter ? search.genres.filter(filter) : search.genres;
|
|
@@ -1158,12 +1153,12 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
1158
1153
|
label,
|
|
1159
1154
|
items: genres.map((genre) => ({
|
|
1160
1155
|
key: genre.uuid,
|
|
1161
|
-
content: /* @__PURE__ */ (0,
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1156
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
1157
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
1163
1158
|
genre.name,
|
|
1164
|
-
genre.isUmbrella && /* @__PURE__ */ (0,
|
|
1159
|
+
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ml-2 text-caption font-normal italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1165
1160
|
] }),
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1161
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: describe?.(genre) ?? `${genre.treeName} \xB7 ${genre.root.name}` })
|
|
1167
1162
|
] }),
|
|
1168
1163
|
onSelect: () => onSelect(genre)
|
|
1169
1164
|
})),
|
|
@@ -1173,7 +1168,7 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
1173
1168
|
}
|
|
1174
1169
|
|
|
1175
1170
|
// src/genre-tree/GenreSearch.tsx
|
|
1176
|
-
var
|
|
1171
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1177
1172
|
function GenreSearch({
|
|
1178
1173
|
genrePlaylists,
|
|
1179
1174
|
onSelect,
|
|
@@ -1202,9 +1197,9 @@ function GenreSearch({
|
|
|
1202
1197
|
label: hasExtras ? "Genres" : void 0,
|
|
1203
1198
|
items: results.map((genrePlaylist) => ({
|
|
1204
1199
|
key: genrePlaylist.uuid,
|
|
1205
|
-
content: /* @__PURE__ */ (0,
|
|
1200
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
1206
1201
|
genrePlaylist.name,
|
|
1207
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */ (0,
|
|
1202
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1208
1203
|
] }),
|
|
1209
1204
|
onSelect: () => select(genrePlaylist)
|
|
1210
1205
|
}))
|
|
@@ -1213,7 +1208,7 @@ function GenreSearch({
|
|
|
1213
1208
|
(group) => active ? group : { ...group, items: [], status: "", loading: false }
|
|
1214
1209
|
)
|
|
1215
1210
|
];
|
|
1216
|
-
return /* @__PURE__ */ (0,
|
|
1211
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("div", { className: "genre-search w-[calc(var(--layout-detail-panel-w,25.5rem)-2*var(--layout-panel-inset,1rem))] shrink-0 max-md:w-full", children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(
|
|
1217
1212
|
SearchBox,
|
|
1218
1213
|
{
|
|
1219
1214
|
label,
|
|
@@ -1233,14 +1228,14 @@ function GenreSearch({
|
|
|
1233
1228
|
clear();
|
|
1234
1229
|
onQueryChange?.("");
|
|
1235
1230
|
} : void 0,
|
|
1236
|
-
leading: onPrevious && /* @__PURE__ */ (0,
|
|
1231
|
+
leading: onPrevious && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("button", { type: "button", "aria-label": "Previous", title: "Previous", className: import_ui7.SEARCH_LEADING_BUTTON_CLASS, onClick: onPrevious, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.ArrowLeft, { "aria-hidden": "true", className: "h-4 w-4" }) }),
|
|
1237
1232
|
onFocus
|
|
1238
1233
|
}
|
|
1239
1234
|
) });
|
|
1240
1235
|
}
|
|
1241
1236
|
|
|
1242
1237
|
// src/genre-tree/GenreTreeSearch.tsx
|
|
1243
|
-
var
|
|
1238
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1244
1239
|
function GenreTreeSearch({
|
|
1245
1240
|
artistBaseUrl,
|
|
1246
1241
|
songBaseUrl,
|
|
@@ -1260,7 +1255,7 @@ function GenreTreeSearch({
|
|
|
1260
1255
|
const deferredQuery = (0, import_react9.useDeferredValue)(query);
|
|
1261
1256
|
const artistGroup = useArtistSearchGroup(artistBaseUrl, deferredQuery, onArtistSelect, artistSearch);
|
|
1262
1257
|
const songGroup = useSongSearchGroup(songBaseUrl, deferredQuery, onSongSelect, songSearch);
|
|
1263
|
-
const render = (hostGroups) => /* @__PURE__ */ (0,
|
|
1258
|
+
const render = (hostGroups) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1264
1259
|
GenreSearch,
|
|
1265
1260
|
{
|
|
1266
1261
|
...props,
|
|
@@ -1275,7 +1270,7 @@ function GenreTreeSearch({
|
|
|
1275
1270
|
extraGroups: [...extraGroups, ...hostGroups, artistGroup, songGroup].filter((group) => group !== void 0)
|
|
1276
1271
|
}
|
|
1277
1272
|
);
|
|
1278
|
-
return SearchGroups ? /* @__PURE__ */ (0,
|
|
1273
|
+
return SearchGroups ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SearchGroups, { query: deferredQuery, focused, onSelectGenre, children: render }) : render([]);
|
|
1279
1274
|
}
|
|
1280
1275
|
|
|
1281
1276
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
@@ -1295,7 +1290,7 @@ var import_ui9 = require("@behindthemusictree/ui");
|
|
|
1295
1290
|
// src/genre-tree/ShareActionButton.tsx
|
|
1296
1291
|
var import_lucide_react10 = require("lucide-react");
|
|
1297
1292
|
var import_ui8 = require("@behindthemusictree/ui");
|
|
1298
|
-
var
|
|
1293
|
+
var import_popup3 = require("@behindthemusictree/app-kit/popup");
|
|
1299
1294
|
|
|
1300
1295
|
// src/genre-tree/SharePopup.tsx
|
|
1301
1296
|
var import_react10 = require("react");
|
|
@@ -1304,12 +1299,12 @@ var import_fa3 = require("react-icons/fa");
|
|
|
1304
1299
|
var import_si = require("react-icons/si");
|
|
1305
1300
|
|
|
1306
1301
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
1307
|
-
var
|
|
1302
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1308
1303
|
var className = "group flex min-w-0 flex-1 flex-col items-center justify-center gap-1.5 rounded-xl px-2 py-2 text-caption text-[var(--color-text)] transition-colors hover:bg-[var(--color-surface-muted)] focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[var(--color-focus-ring)] disabled:cursor-not-allowed disabled:opacity-50";
|
|
1309
1304
|
function Contents({ icon, label }) {
|
|
1310
|
-
return /* @__PURE__ */ (0,
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1305
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1306
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-[var(--color-surface-muted)] transition-colors group-hover:bg-[var(--color-border)]", children: icon }),
|
|
1307
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "max-w-full truncate", children: label })
|
|
1313
1308
|
] });
|
|
1314
1309
|
}
|
|
1315
1310
|
function ShareDestinationButton({
|
|
@@ -1321,29 +1316,29 @@ function ShareDestinationButton({
|
|
|
1321
1316
|
ariaLabel
|
|
1322
1317
|
}) {
|
|
1323
1318
|
if (href) {
|
|
1324
|
-
return /* @__PURE__ */ (0,
|
|
1319
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", "aria-label": ariaLabel, className, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Contents, { icon, label }) });
|
|
1325
1320
|
}
|
|
1326
|
-
return /* @__PURE__ */ (0,
|
|
1321
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("button", { type: "button", onClick, disabled, "aria-label": ariaLabel, className, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(Contents, { icon, label }) });
|
|
1327
1322
|
}
|
|
1328
1323
|
|
|
1329
1324
|
// src/genre-tree/SharePreviewCard.tsx
|
|
1330
1325
|
var import_lucide_react8 = require("lucide-react");
|
|
1331
|
-
var
|
|
1326
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1332
1327
|
function SharePreviewCard({ target, url }) {
|
|
1333
1328
|
const Icon = { genre: import_lucide_react8.Music2, artist: import_lucide_react8.UserRound, song: import_lucide_react8.Music }[target.kind];
|
|
1334
1329
|
const typeLabel = { genre: "Genre", artist: "Artist", song: "Song" }[target.kind];
|
|
1335
|
-
return /* @__PURE__ */ (0,
|
|
1336
|
-
/* @__PURE__ */ (0,
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1338
|
-
/* @__PURE__ */ (0,
|
|
1339
|
-
/* @__PURE__ */ (0,
|
|
1340
|
-
/* @__PURE__ */ (0,
|
|
1330
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "rounded-3xl bg-[var(--color-surface-muted)] p-4", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-h-32 overflow-hidden rounded-2xl bg-[var(--color-surface)] shadow-lg", children: [
|
|
1331
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("div", { className: "flex w-28 shrink-0 items-center justify-center bg-[var(--color-primary)]/15 text-[var(--color-primary)]", children: /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(Icon, { "aria-hidden": "true", className: "h-10 w-10" }) }),
|
|
1332
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
1333
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
1334
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
1335
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
1341
1336
|
] })
|
|
1342
1337
|
] }) });
|
|
1343
1338
|
}
|
|
1344
1339
|
|
|
1345
1340
|
// src/genre-tree/SharePopup.tsx
|
|
1346
|
-
var
|
|
1341
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1347
1342
|
function resolveAbsoluteUrl(url) {
|
|
1348
1343
|
try {
|
|
1349
1344
|
const parsed = new URL(url, window.location.href);
|
|
@@ -1418,8 +1413,8 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1418
1413
|
setShareError("Could not open the share options.");
|
|
1419
1414
|
}
|
|
1420
1415
|
};
|
|
1421
|
-
return /* @__PURE__ */ (0,
|
|
1422
|
-
/* @__PURE__ */ (0,
|
|
1416
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
1417
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1423
1418
|
BasePopup_default,
|
|
1424
1419
|
{
|
|
1425
1420
|
title: "Share",
|
|
@@ -1434,70 +1429,70 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1434
1429
|
titleTextClassName: "!text-xl !font-semibold !text-[var(--color-text)]",
|
|
1435
1430
|
closeButtonClassName: "!h-10 !w-10 !rounded-none !border-0 !bg-transparent !p-0 !text-[var(--color-text)] hover:!bg-transparent hover:!text-[var(--color-text)]",
|
|
1436
1431
|
contentClassName: "!rounded-none !bg-transparent !px-6 !pb-6 !pt-2",
|
|
1437
|
-
children: /* @__PURE__ */ (0,
|
|
1438
|
-
/* @__PURE__ */ (0,
|
|
1439
|
-
/* @__PURE__ */ (0,
|
|
1440
|
-
/* @__PURE__ */ (0,
|
|
1432
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
1433
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SharePreviewCard, { target, url: absoluteUrl || url }),
|
|
1434
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "grid grid-cols-3 gap-1 rounded-3xl bg-[var(--color-surface)] p-3 sm:grid-cols-4", children: [
|
|
1435
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1441
1436
|
ShareDestinationButton,
|
|
1442
1437
|
{
|
|
1443
1438
|
label: "Copy Link",
|
|
1444
|
-
icon: /* @__PURE__ */ (0,
|
|
1439
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react9.Link2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
1445
1440
|
onClick: () => void handleCopy(),
|
|
1446
1441
|
ariaLabel: "Copy link",
|
|
1447
1442
|
disabled: !absoluteUrl
|
|
1448
1443
|
}
|
|
1449
1444
|
),
|
|
1450
|
-
/* @__PURE__ */ (0,
|
|
1445
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1451
1446
|
ShareDestinationButton,
|
|
1452
1447
|
{
|
|
1453
1448
|
label: "WhatsApp",
|
|
1454
|
-
icon: /* @__PURE__ */ (0,
|
|
1449
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_fa3.FaWhatsapp, { "aria-hidden": "true", className: "h-9 w-9 text-[#25D366]" }),
|
|
1455
1450
|
href: destinationUrls?.whatsapp,
|
|
1456
1451
|
ariaLabel: `Share ${target.name} via WhatsApp`,
|
|
1457
1452
|
disabled: !absoluteUrl
|
|
1458
1453
|
}
|
|
1459
1454
|
),
|
|
1460
|
-
/* @__PURE__ */ (0,
|
|
1455
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1461
1456
|
ShareDestinationButton,
|
|
1462
1457
|
{
|
|
1463
1458
|
label: "Gmail",
|
|
1464
|
-
icon: /* @__PURE__ */ (0,
|
|
1459
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_si.SiGmail, { "aria-hidden": "true", className: "h-8 w-8 text-[#EA4335]" }),
|
|
1465
1460
|
href: destinationUrls?.gmail,
|
|
1466
1461
|
ariaLabel: `Email ${target.name} with Gmail`,
|
|
1467
1462
|
disabled: !absoluteUrl
|
|
1468
1463
|
}
|
|
1469
1464
|
),
|
|
1470
|
-
canUseNativeShare && /* @__PURE__ */ (0,
|
|
1465
|
+
canUseNativeShare && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1471
1466
|
ShareDestinationButton,
|
|
1472
1467
|
{
|
|
1473
1468
|
label: "More",
|
|
1474
|
-
icon: /* @__PURE__ */ (0,
|
|
1469
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react9.Share2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
1475
1470
|
onClick: () => void handleNativeShare(),
|
|
1476
1471
|
ariaLabel: "More sharing options",
|
|
1477
1472
|
disabled: !absoluteUrl
|
|
1478
1473
|
}
|
|
1479
1474
|
)
|
|
1480
1475
|
] }),
|
|
1481
|
-
copyStatus === "failed" && /* @__PURE__ */ (0,
|
|
1482
|
-
shareError && /* @__PURE__ */ (0,
|
|
1476
|
+
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: "Could not copy the link." }),
|
|
1477
|
+
shareError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
1483
1478
|
] })
|
|
1484
1479
|
}
|
|
1485
1480
|
),
|
|
1486
|
-
toastId > 0 && /* @__PURE__ */ (0,
|
|
1481
|
+
toastId > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Toast, { message: "Link copied", onClose: dismissToast }, toastId)
|
|
1487
1482
|
] });
|
|
1488
1483
|
}
|
|
1489
1484
|
|
|
1490
1485
|
// src/genre-tree/ShareActionButton.tsx
|
|
1491
|
-
var
|
|
1486
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1492
1487
|
function ShareActionButton({ target, url }) {
|
|
1493
|
-
const { showPopup, hidePopup } = (0,
|
|
1488
|
+
const { showPopup, hidePopup } = (0, import_popup3.usePopup)();
|
|
1494
1489
|
const openSharePopup = () => {
|
|
1495
|
-
showPopup(/* @__PURE__ */ (0,
|
|
1490
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SharePopup, { target, url, onClose: hidePopup }));
|
|
1496
1491
|
};
|
|
1497
|
-
return /* @__PURE__ */ (0,
|
|
1492
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1498
1493
|
import_ui8.ActionButton,
|
|
1499
1494
|
{
|
|
1500
|
-
icon: /* @__PURE__ */ (0,
|
|
1495
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react10.Share2, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1501
1496
|
label: "Share",
|
|
1502
1497
|
"aria-label": `Share ${target.name}`,
|
|
1503
1498
|
title: `Share ${target.name}`,
|
|
@@ -1507,7 +1502,7 @@ function ShareActionButton({ target, url }) {
|
|
|
1507
1502
|
}
|
|
1508
1503
|
|
|
1509
1504
|
// src/genre-tree/GenreActionBand.tsx
|
|
1510
|
-
var
|
|
1505
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1511
1506
|
function GenreActionBand({
|
|
1512
1507
|
node,
|
|
1513
1508
|
playActions,
|
|
@@ -1528,24 +1523,24 @@ function GenreActionBand({
|
|
|
1528
1523
|
items.push({
|
|
1529
1524
|
key: "zoom-in",
|
|
1530
1525
|
label: "Focus",
|
|
1531
|
-
icon: /* @__PURE__ */ (0,
|
|
1526
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.ZoomIn, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1532
1527
|
onClick: onZoomIn
|
|
1533
1528
|
});
|
|
1534
1529
|
}
|
|
1535
1530
|
if (onAddChild) {
|
|
1536
|
-
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */ (0,
|
|
1531
|
+
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.Plus, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onAddChild });
|
|
1537
1532
|
}
|
|
1538
1533
|
if (onRename) {
|
|
1539
|
-
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */ (0,
|
|
1534
|
+
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.Pencil, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onRename });
|
|
1540
1535
|
}
|
|
1541
1536
|
if (onChangeParent) {
|
|
1542
|
-
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */ (0,
|
|
1537
|
+
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.MoveUpRight, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onChangeParent });
|
|
1543
1538
|
}
|
|
1544
1539
|
if (onToggleSide) {
|
|
1545
1540
|
adminItems.push({
|
|
1546
1541
|
key: "toggle-side",
|
|
1547
1542
|
label: side === "pop" ? "Make core" : "Make pop",
|
|
1548
|
-
icon: /* @__PURE__ */ (0,
|
|
1543
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.ArrowLeftRight, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1549
1544
|
onClick: onToggleSide,
|
|
1550
1545
|
disabled: !!toggleSideDisabledReason,
|
|
1551
1546
|
title: toggleSideDisabledReason
|
|
@@ -1560,9 +1555,9 @@ function GenreActionBand({
|
|
|
1560
1555
|
disabled: action.enabled ? !action.enabled(node) : false
|
|
1561
1556
|
});
|
|
1562
1557
|
}
|
|
1563
|
-
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0,
|
|
1558
|
+
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.ActionButton, { icon: item.icon, label: item.label, disabled: item.disabled, title: item.title, onClick: item.onClick }, item.key));
|
|
1564
1559
|
if (!playActions && items.length === 0 && adminItems.length === 0 && !(shareTarget && shareUrl)) return null;
|
|
1565
|
-
return /* @__PURE__ */ (0,
|
|
1560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1566
1561
|
import_ui9.ActionBand,
|
|
1567
1562
|
{
|
|
1568
1563
|
className: "genre-action-band",
|
|
@@ -1570,7 +1565,7 @@ function GenreActionBand({
|
|
|
1570
1565
|
children: [
|
|
1571
1566
|
playActions,
|
|
1572
1567
|
renderItems(items),
|
|
1573
|
-
shareTarget && shareUrl && /* @__PURE__ */ (0,
|
|
1568
|
+
shareTarget && shareUrl && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
1574
1569
|
]
|
|
1575
1570
|
}
|
|
1576
1571
|
) });
|
|
@@ -1594,7 +1589,7 @@ var REGION_GLOBE_PATHS = {
|
|
|
1594
1589
|
var REGION_GLOBES = ["africa", "americas", "asia"];
|
|
1595
1590
|
|
|
1596
1591
|
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1597
|
-
var
|
|
1592
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1598
1593
|
var ROTATION_INTERVAL_MS = 3e3;
|
|
1599
1594
|
function RegionGlobeIcon({ className: className2 }) {
|
|
1600
1595
|
const [index, setIndex] = (0, import_react11.useState)(0);
|
|
@@ -1612,29 +1607,29 @@ function RegionGlobeIcon({ className: className2 }) {
|
|
|
1612
1607
|
clearInterval(timer);
|
|
1613
1608
|
};
|
|
1614
1609
|
}, []);
|
|
1615
|
-
return /* @__PURE__ */ (0,
|
|
1610
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { viewBox: "0 0 512 512", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { "data-testid": "region-globe-path", d: REGION_GLOBE_PATHS[REGION_GLOBES[index]] }) });
|
|
1616
1611
|
}
|
|
1617
1612
|
|
|
1618
1613
|
// src/genre-tree/treeMarkPath.ts
|
|
1619
1614
|
var TREE_MARK_PATH = "M3171 5598 c-5 -13 -5 -24 0 -26 5 -2 9 -16 9 -31 0 -25 -3 -28 -25 -23 l-25 4 0 -116 c0 -64 3 -116 8 -116 10 0 32 51 26 61 -3 5 -1 9 4 9 5 0 15 12 21 28 7 15 26 36 43 47 30 20 88 105 71 105 -4 0 -33 -21 -62 -47 l-54 -47 6 63 c4 35 7 72 7 82 0 10 9 19 23 22 16 3 13 5 -11 6 -25 1 -35 -4 -41 -21z M2893 5485 c8 -76 24 -100 71 -100 l36 0 0 53 c0 58 -15 69 -28 20 -8 -29 -10 -30 -16 -13 -15 43 -42 89 -55 93 -11 4 -13 -6 -8 -53z M2484 5438 c8 -70 49 -169 54 -131 2 12 10 27 18 33 17 15 19 84 3 129 -9 27 -16 31 -46 31 l-36 0 7 -62z M2625 5448 c-7 -22 -24 -121 -31 -179 l-6 -57 -27 11 c-15 5 -32 19 -37 31 -9 21 -88 86 -105 86 -39 0 38 -104 118 -158 17 -12 56 -59 86 -105 30 -45 67 -92 81 -104 14 -13 26 -30 26 -38 0 -13 -9 -11 -45 11 -67 39 -58 10 21 -66 67 -65 96 -110 108 -167 4 -17 13 -34 20 -36 20 -8 66 -186 75 -289 13 -161 -8 -272 -72 -365 -12 -18 -30 -33 -39 -33 -23 0 -53 33 -79 89 -25 54 -69 112 -121 162 -35 33 -38 40 -38 92 0 58 36 172 79 252 25 47 29 125 6 125 -19 0 -30 -22 -50 -100 -9 -35 -24 -78 -32 -94 l-16 -30 -19 24 -20 25 7 -58 c8 -62 0 -127 -16 -127 -19 0 -122 107 -166 172 -52 79 -68 150 -60 273 8 108 17 129 67 149 58 23 97 64 105 109 9 47 -5 49 -63 6 l-42 -30 15 35 c17 41 20 102 5 111 -18 11 -45 -4 -64 -36 -11 -19 -20 -60 -23 -110 -4 -54 -10 -79 -18 -79 -20 0 -27 28 -30 108 -2 40 -6 76 -9 79 -3 4 -6 51 -6 105 0 86 -3 101 -21 119 -27 27 -42 20 -53 -24 -7 -28 -5 -51 7 -90 9 -30 17 -76 17 -103 l0 -49 -29 51 c-29 49 -92 114 -111 114 -6 0 -10 -11 -10 -25 0 -14 5 -25 10 -25 6 0 10 -6 10 -13 0 -7 23 -44 51 -82 61 -84 59 -82 52 -57 -3 14 2 24 15 31 12 6 23 23 25 38 2 16 5 2 6 -29 1 -46 -2 -58 -14 -58 -21 0 -19 -13 10 -70 22 -44 25 -61 25 -165 l0 -116 -47 27 c-65 36 -142 118 -176 187 -15 31 -37 62 -49 68 -21 11 -21 10 -15 -41 l6 -52 -29 6 c-37 7 -39 -7 -4 -31 14 -10 53 -40 86 -68 92 -76 130 -104 163 -119 39 -19 101 -84 109 -116 10 -42 50 -88 217 -245 50 -47 94 -102 134 -167 33 -54 65 -98 71 -98 17 0 45 -79 51 -145 4 -47 0 -76 -20 -135 -14 -41 -39 -121 -56 -177 -18 -57 -35 -103 -40 -103 -4 0 -26 13 -49 30 -31 22 -50 49 -82 117 -99 209 -116 241 -185 337 -123 172 -123 173 -128 311 -5 140 -29 245 -57 245 -12 0 -20 -11 -24 -31 -9 -46 -7 -108 3 -127 14 -26 25 -162 14 -162 -20 0 -160 99 -192 135 -19 22 -42 58 -52 80 -10 23 -27 52 -37 66 -10 13 -26 38 -34 54 -9 17 -23 45 -33 64 -15 29 -16 40 -6 80 31 116 34 139 27 205 -7 57 -11 69 -28 74 -14 3 -32 30 -54 79 -21 46 -39 73 -47 70 -13 -5 -14 -15 -3 -65 l8 -33 -49 25 c-61 31 -93 40 -93 27 0 -13 43 -41 122 -79 47 -22 72 -41 83 -61 19 -38 19 -51 0 -51 -12 0 -15 -15 -16 -72 -1 -79 -12 -134 -22 -108 -3 8 -10 48 -16 89 -14 89 -25 111 -54 111 -38 0 -50 -15 -45 -54 4 -40 2 -42 -26 -21 -29 22 -36 19 -36 -20 0 -39 39 -85 125 -145 38 -27 62 -56 99 -120 45 -79 82 -177 70 -189 -2 -3 -42 3 -87 13 -45 10 -99 21 -119 26 -47 9 -103 51 -125 93 -24 44 -83 203 -94 252 -5 25 -4 59 3 91 14 68 3 140 -23 155 -12 6 -23 8 -27 5 -14 -15 -13 -115 2 -159 39 -116 0 -116 -70 1 -22 36 -31 42 -59 42 -20 0 -35 6 -39 15 -6 16 -56 21 -56 6 0 -5 23 -25 51 -44 53 -36 158 -156 188 -216 10 -20 26 -60 36 -88 11 -29 25 -53 32 -53 8 0 13 -12 13 -30 0 -26 -4 -30 -27 -31 l-28 -1 25 -7 c26 -8 177 -87 196 -102 5 -4 50 -18 100 -29 122 -29 277 -78 300 -95 10 -8 26 -15 34 -15 35 0 160 -166 160 -212 0 -22 -32 -24 -50 -4 -11 14 -100 46 -165 61 -16 3 -68 25 -115 48 -102 49 -163 56 -168 19 -9 -62 58 -104 178 -112 63 -5 103 -14 155 -37 39 -16 91 -38 117 -47 26 -9 74 -35 106 -56 52 -33 65 -48 96 -112 20 -40 39 -95 43 -122 6 -47 6 -48 -18 -41 -33 10 -69 33 -69 45 0 6 -10 10 -23 10 -13 0 -27 4 -32 9 -6 5 -27 14 -47 20 -20 7 -53 23 -73 37 -43 29 -45 29 -45 7 0 -26 80 -96 145 -127 119 -56 274 -185 311 -259 55 -107 104 -410 104 -640 0 -162 -22 -325 -45 -333 -25 -10 -72 25 -168 123 -129 131 -140 148 -182 274 -20 60 -50 142 -66 181 -16 39 -45 131 -65 202 -24 93 -55 173 -104 274 -77 158 -78 166 -32 256 31 64 27 129 -12 181 -31 40 -39 42 -65 18 -51 -49 -55 -120 -11 -208 37 -74 37 -85 3 -85 -36 0 -94 65 -137 154 -18 39 -37 80 -40 92 -3 11 -14 29 -24 40 -10 10 -28 35 -42 54 -13 19 -40 55 -61 80 -20 25 -41 63 -47 85 -6 22 -16 62 -23 89 -20 81 -95 147 -113 100 -18 -47 -6 -92 39 -147 25 -31 45 -61 45 -67 0 -15 -42 -3 -116 31 -94 44 -156 124 -184 235 -9 36 -13 41 -38 40 -39 -2 -144 113 -186 205 -31 66 -33 68 -53 54 -11 -8 -24 -11 -27 -7 -4 4 11 -24 33 -62 39 -67 43 -86 18 -86 -8 0 -8 3 1 9 11 6 9 9 -7 14 -11 3 -25 -1 -31 -7 -7 -10 0 -16 29 -24 39 -12 203 -147 215 -178 13 -34 4 -35 -48 -6 -64 37 -126 51 -126 30 0 -26 55 -67 125 -92 46 -16 80 -36 100 -58 l29 -33 -54 -3 c-79 -5 -203 14 -249 38 -47 24 -70 54 -105 140 -43 105 -115 163 -103 83 3 -21 9 -47 13 -57 4 -11 -15 4 -42 32 -62 64 -84 67 -84 14 0 -41 24 -76 61 -87 16 -6 18 -9 8 -15 -23 -15 15 -45 117 -91 52 -24 93 -48 91 -54 -10 -28 -150 -28 -190 0 -21 15 -47 5 -47 -17 0 -5 -10 -19 -22 -29 -23 -20 -23 -20 112 -14 174 8 208 8 430 0 l185 -7 84 -41 c115 -57 180 -118 225 -212 20 -41 36 -77 36 -80 0 -14 89 -126 150 -190 74 -78 120 -144 120 -175 0 -30 10 -33 -201 52 -94 38 -131 71 -218 195 -27 37 -59 77 -71 88 l-23 20 7 -40 c4 -22 12 -44 17 -49 13 -14 11 -26 -4 -26 -7 0 -29 21 -48 48 -33 45 -34 51 -39 159 -4 89 -9 116 -22 130 -17 16 -18 16 -18 0 0 -9 -7 -17 -16 -17 -14 0 -16 -9 -11 -62 3 -35 8 -74 12 -88 l7 -25 -25 27 c-41 44 -127 118 -137 118 -18 0 -10 -57 12 -85 18 -24 20 -32 10 -57 -10 -28 -9 -30 22 -43 18 -8 54 -19 79 -26 36 -9 60 -24 99 -66 80 -83 80 -83 1 -83 -80 0 -176 21 -236 51 -107 54 -234 169 -252 228 -4 14 -12 29 -17 35 -5 6 -18 25 -28 43 -24 40 -90 64 -116 42 -22 -18 -13 -84 17 -116 13 -13 42 -32 64 -42 22 -10 74 -53 115 -96 l75 -77 -75 5 c-135 8 -243 76 -336 207 -31 44 -65 87 -77 95 -37 26 -34 -9 7 -88 20 -39 34 -72 31 -75 -2 -2 -26 11 -52 31 -90 65 -143 83 -143 49 0 -32 71 -88 150 -117 41 -15 113 -47 159 -71 46 -24 99 -46 118 -50 18 -3 33 -12 33 -18 0 -12 -111 -46 -149 -46 -12 0 -29 -8 -39 -17 -10 -10 -27 -19 -37 -19 -11 -1 -45 -9 -75 -17 -58 -16 -110 -62 -110 -97 0 -39 116 -45 167 -9 11 8 34 31 52 51 28 32 50 43 144 74 145 47 222 48 404 5 70 -17 177 -38 237 -47 128 -19 202 -43 250 -79 18 -14 73 -42 122 -61 164 -66 208 -112 243 -251 36 -141 27 -167 -44 -123 -19 12 -63 23 -111 28 -117 13 -134 25 -275 193 -63 74 -193 151 -266 157 -29 2 -66 -1 -81 -7 -24 -10 -37 -9 -80 8 -66 26 -70 9 -11 -44 72 -65 119 -80 239 -78 60 1 109 -2 117 -8 6 -6 26 -35 42 -64 17 -30 46 -64 64 -77 19 -13 49 -40 67 -61 l34 -39 -79 3 c-57 3 -80 0 -83 -9 -3 -10 -7 -10 -18 -1 -8 6 -11 15 -8 20 3 5 0 9 -5 9 -16 0 -13 -16 6 -36 36 -36 78 -44 227 -44 119 0 152 -3 188 -19 56 -24 95 -64 125 -126 13 -27 35 -68 48 -90 14 -22 25 -53 25 -69 l0 -29 -107 5 c-131 6 -193 28 -290 100 -37 28 -82 56 -98 63 -75 32 -176 123 -277 247 -34 42 -122 98 -134 85 -5 -5 103 -138 184 -226 52 -57 46 -61 -49 -31 -87 28 -173 85 -325 214 -144 123 -189 151 -254 159 -25 2 -39 3 -32 0 6 -3 12 -16 12 -29 0 -17 -4 -23 -12 -19 -7 4 -1 -5 15 -19 15 -14 46 -30 70 -36 23 -6 60 -17 82 -25 l40 -13 -52 -1 c-49 -1 -53 -3 -53 -25 0 -28 28 -36 122 -36 54 0 62 -3 91 -32 l32 -33 -52 -3 c-88 -5 -75 -26 39 -62 130 -41 178 -63 206 -93 l22 -24 -20 -18 c-12 -11 -41 -20 -74 -23 -48 -4 -60 0 -116 32 -118 69 -241 96 -279 62 -13 -12 -40 -16 -104 -16 -48 0 -95 4 -105 9 -9 5 -34 16 -55 25 -20 9 -76 53 -122 97 -47 45 -88 79 -91 76 -12 -12 6 -54 41 -100 l36 -47 -74 0 c-88 0 -112 15 -78 49 26 26 21 39 -34 84 -87 73 -132 32 -50 -45 25 -23 45 -46 45 -50 0 -4 -21 2 -46 12 -45 20 -114 27 -114 12 0 -4 16 -22 35 -40 39 -38 78 -47 255 -61 164 -14 178 -17 172 -47 -2 -13 -2 -30 2 -39 5 -13 9 -13 40 2 19 9 33 20 30 25 -4 5 4 4 15 -4 21 -13 20 -15 -44 -74 -36 -33 -65 -66 -65 -72 0 -21 68 15 142 74 38 30 84 62 103 70 73 30 203 11 312 -46 32 -17 82 -33 111 -37 l53 -6 -28 -30 c-15 -16 -44 -40 -63 -52 -63 -42 -100 -82 -100 -111 0 -25 2 -26 37 -21 28 5 47 17 73 49 65 78 175 183 224 216 34 22 61 32 88 32 43 0 122 -36 152 -69 10 -11 39 -32 62 -46 43 -25 53 -46 36 -72 -11 -17 -200 -86 -232 -85 -28 1 -122 -47 -127 -65 -3 -8 14 -13 54 -15 l58 -3 -65 -44 c-36 -25 -68 -49 -71 -53 -11 -17 -115 -10 -188 12 -105 32 -112 11 -14 -39 l56 -28 -40 -6 c-52 -9 -96 0 -154 29 -31 15 -50 19 -60 13 -15 -10 -16 -10 44 -47 20 -13 37 -27 37 -31 0 -15 -144 -71 -205 -81 -33 -5 -85 -10 -116 -10 -32 0 -63 -6 -75 -14 -18 -13 -15 -15 34 -22 l53 -7 -31 -18 c-18 -12 -30 -27 -30 -40 0 -21 4 -21 61 -16 50 4 75 14 145 57 46 28 112 63 146 77 62 24 191 62 215 63 22 0 -47 -103 -107 -161 -42 -41 -60 -66 -65 -92 -10 -49 0 -60 47 -54 65 9 99 53 124 160 20 83 49 133 94 163 22 15 40 30 40 34 0 4 8 10 18 13 9 3 31 15 49 27 31 21 31 21 26 0 -3 -11 -21 -37 -40 -58 -43 -45 -72 -106 -73 -150 0 -39 18 -49 56 -30 38 18 63 64 75 137 13 82 40 142 89 194 22 24 40 49 40 54 0 6 24 21 53 34 49 22 63 23 237 20 193 -2 278 -14 348 -50 21 -11 44 -27 52 -36 7 -9 32 -27 55 -41 49 -28 138 -147 184 -243 16 -35 42 -114 57 -175 35 -147 31 -268 -14 -436 -17 -63 -37 -166 -45 -227 -12 -94 -21 -127 -54 -195 -22 -46 -52 -94 -67 -108 -15 -14 -46 -44 -68 -67 -23 -24 -47 -43 -53 -43 -7 0 -25 -12 -41 -26 -129 -121 -526 -267 -721 -268 -104 0 -109 -15 -19 -57 75 -35 67 -35 221 -10 125 21 235 27 235 13 0 -16 -66 -72 -85 -72 -24 0 -85 -36 -85 -49 0 -14 12 -19 58 -27 35 -5 42 -4 42 10 0 9 5 17 10 17 28 4 74 20 80 29 9 14 226 119 288 139 63 21 215 43 239 34 32 -12 12 -50 -52 -102 -36 -28 -73 -55 -83 -58 -17 -7 -66 -39 -92 -60 -8 -7 -38 -32 -67 -57 l-52 -45 42 -6 c36 -6 54 -1 122 33 44 22 120 56 169 76 112 45 222 107 289 164 46 40 84 62 107 62 18 0 130 -83 130 -96 0 -8 4 -14 10 -14 5 0 39 -26 75 -59 36 -32 96 -76 132 -97 36 -21 68 -46 71 -56 5 -19 21 -22 59 -12 18 5 20 9 10 19 -7 7 -69 71 -139 143 -147 149 -161 179 -80 168 136 -19 195 -39 378 -128 78 -37 147 -68 152 -68 6 0 15 -7 20 -16 8 -14 14 -15 46 -4 l38 12 -104 57 c-125 69 -148 84 -148 93 0 16 94 7 223 -22 74 -17 146 -30 160 -30 14 0 29 -4 32 -10 7 -11 54 6 115 43 l40 24 -38 1 c-22 1 -68 11 -103 21 -35 11 -107 30 -159 41 -131 31 -295 99 -406 171 -235 153 -355 366 -357 634 -1 211 65 343 285 568 117 119 206 167 368 198 153 29 267 59 328 86 80 35 166 44 264 27 148 -26 167 -38 251 -169 71 -110 136 -165 196 -165 26 0 31 4 31 23 -1 32 -28 62 -87 91 -39 20 -66 45 -118 112 -95 123 -95 135 -5 92 25 -12 77 -31 116 -43 56 -17 76 -19 97 -10 27 11 26 11 -25 29 -113 39 -138 49 -138 57 0 14 91 55 153 68 33 7 75 10 95 7 27 -4 31 -3 17 4 -19 8 -19 9 3 9 12 1 22 7 22 15 0 10 7 12 22 8 12 -3 17 -7 10 -10 -6 -2 -12 -10 -12 -18 0 -8 -6 -14 -12 -15 -27 -2 39 -17 80 -18 29 -1 42 3 42 13 0 20 -19 32 -67 45 -49 13 -53 22 -20 44 49 32 128 39 235 21 56 -9 112 -14 126 -10 26 6 96 69 96 86 0 6 -32 10 -77 10 -84 0 -126 -7 -118 -20 9 -14 -17 -24 -67 -24 -34 -1 -48 3 -48 13 0 8 -7 11 -20 8 -17 -4 -18 -2 -9 14 5 11 14 17 20 14 5 -4 9 0 9 8 0 8 16 35 35 60 35 45 35 46 14 57 -18 10 -23 8 -37 -12 -67 -95 -162 -167 -297 -225 -55 -23 -99 -47 -98 -53 2 -5 -6 -10 -18 -10 -27 0 -23 8 31 71 100 117 116 131 161 155 80 40 80 70 1 41 l-47 -18 36 38 c47 49 59 73 59 120 0 67 -24 80 -82 46 -49 -29 -76 -85 -89 -183 -10 -81 -9 -80 -89 -174 -20 -22 -43 -53 -53 -68 -28 -45 -89 -61 -217 -56 -70 2 -114 8 -118 15 -4 6 -28 13 -54 15 l-46 3 53 71 c51 68 100 104 140 104 50 0 125 73 125 122 0 30 0 31 -45 26 -28 -4 -59 -16 -82 -34 -30 -23 -35 -24 -28 -8 22 51 37 105 31 111 -13 13 -47 -34 -105 -146 -72 -138 -171 -248 -261 -292 -62 -30 -164 -44 -242 -34 -48 7 -50 8 -45 34 14 70 51 144 95 190 42 43 56 51 127 69 44 12 98 24 120 27 99 15 155 57 155 117 l0 31 -51 -5 c-40 -4 -58 -12 -87 -40 -56 -52 -66 -58 -131 -78 l-60 -18 10 27 c6 14 36 62 68 106 70 96 91 136 91 170 0 41 -18 29 -50 -35 -30 -59 -31 -60 -74 -60 -56 0 -71 -18 -101 -115 -23 -75 -43 -114 -72 -145 -8 -8 -41 -61 -73 -117 -35 -59 -75 -113 -95 -128 -37 -29 -177 -85 -210 -85 -35 0 -222 -134 -282 -202 -31 -35 -64 -64 -72 -66 -22 -4 -68 116 -88 223 -20 113 -5 256 37 340 37 76 124 182 195 238 140 110 221 137 416 137 136 0 171 6 186 28 9 15 2 17 -76 18 -47 0 -127 4 -178 9 -167 15 -274 -28 -423 -170 -72 -68 -114 -95 -128 -81 -12 12 17 138 44 194 64 132 229 243 439 298 182 46 319 21 425 -80 68 -65 144 -115 202 -135 119 -41 155 -32 72 17 -88 52 -224 144 -224 152 0 14 51 20 210 22 115 2 160 0 175 -10 19 -12 18 -13 -8 -9 -36 6 -45 -9 -11 -17 56 -15 117 -51 183 -110 66 -59 119 -86 169 -86 54 0 31 59 -35 90 -167 77 -176 82 -158 93 25 13 138 -8 201 -37 27 -13 67 -43 89 -66 50 -53 84 -70 134 -70 37 0 71 19 71 40 0 24 -62 57 -129 70 -40 7 -74 17 -77 22 -3 4 24 8 60 8 36 0 68 -4 71 -10 3 -5 26 -10 51 -10 50 0 57 15 23 46 -24 21 -113 25 -226 10 -50 -7 -65 -6 -77 7 -19 18 -100 37 -160 37 -74 0 -136 12 -136 26 0 17 11 23 53 28 32 4 83 29 97 47 8 10 71 40 99 47 28 7 159 8 309 1 50 -2 92 -1 92 4 0 4 14 7 30 7 23 0 30 -4 30 -20 0 -15 -7 -20 -25 -20 -42 0 -28 -17 30 -39 75 -28 103 -27 117 4 8 18 19 25 38 25 34 0 47 35 23 62 -24 27 -70 31 -190 18 -101 -11 -112 -10 -173 10 -36 12 -104 24 -152 27 -49 3 -88 9 -88 13 0 8 35 26 66 35 12 3 37 21 55 40 19 20 67 58 106 86 57 39 86 52 134 60 71 11 170 58 193 91 34 49 10 51 -66 5 -52 -31 -154 -65 -165 -54 -11 12 9 25 67 47 33 12 60 26 60 30 0 5 15 17 34 28 31 18 67 84 53 98 -15 15 -69 -17 -124 -75 -35 -36 -63 -63 -63 -58 0 4 14 31 30 60 43 77 39 180 -7 151 -39 -24 -56 -62 -63 -141 -7 -87 -27 -127 -98 -200 -50 -52 -120 -103 -139 -103 -8 0 -22 -8 -31 -17 -31 -31 -26 11 12 94 33 74 61 171 53 180 -3 2 -17 1 -32 -3 -38 -10 -65 -74 -75 -185 -9 -97 -31 -147 -79 -176 -31 -20 -81 -71 -81 -83 0 -5 -24 -16 -52 -26 -29 -9 -58 -24 -64 -32 -7 -9 -33 -17 -70 -19 l-59 -4 55 48 c120 105 133 126 66 103 -19 -6 -58 -36 -88 -66 -29 -30 -72 -64 -96 -76 -41 -19 -50 -20 -163 -9 -168 16 -237 52 -196 103 21 27 121 88 143 88 60 0 183 34 234 65 30 18 74 36 97 40 85 14 180 99 131 118 -16 5 -19 13 -14 33 7 25 5 25 -26 19 -52 -11 -83 -31 -122 -76 -54 -63 -94 -86 -197 -109 -52 -12 -102 -24 -111 -26 -28 -8 -22 22 10 44 15 11 35 34 45 51 16 27 16 31 2 31 -8 0 -18 -7 -22 -16 -8 -23 -23 2 -23 40 0 23 -3 27 -12 18 -14 -14 -42 -16 -33 -2 3 6 4 10 1 10 -9 0 -37 -61 -62 -133 -29 -84 -85 -162 -137 -189 -24 -12 -67 -21 -110 -24 -40 -2 -100 -6 -134 -9 l-62 -4 36 72 c20 39 48 84 62 98 29 29 86 122 96 157 9 32 -20 29 -42 -5 -17 -27 -128 -174 -222 -297 -45 -58 -101 -96 -141 -96 -48 0 -9 184 59 284 41 59 113 107 234 156 51 20 141 67 198 102 57 36 118 72 134 80 40 21 155 46 240 53 48 5 82 14 113 32 58 34 150 44 258 28 41 -6 57 -4 75 9 17 12 46 16 111 16 88 0 116 12 57 24 -17 3 -48 6 -69 6 -21 0 -43 6 -49 14 -14 17 -8 22 40 31 30 5 36 10 32 26 -4 13 0 19 12 19 23 0 95 44 129 79 34 35 30 67 -6 55 -13 -4 -31 -7 -41 -6 -11 0 -38 -25 -68 -64 -28 -35 -53 -64 -55 -64 -2 0 7 22 21 50 14 27 25 60 25 74 0 14 5 37 11 53 7 19 7 29 0 31 -6 2 -11 17 -11 33 0 16 -4 29 -10 29 -5 0 -10 -19 -10 -42 0 -50 -37 -158 -74 -222 -28 -48 -90 -86 -141 -86 l-29 0 36 38 c20 20 43 52 52 70 16 31 16 32 -5 32 -25 0 -94 -47 -109 -75 -19 -35 -161 -104 -245 -120 -42 -8 -85 -15 -96 -15 -18 0 -18 1 -2 35 9 19 20 35 25 35 4 0 8 6 8 13 0 7 13 34 30 60 30 48 75 77 182 117 58 21 112 66 176 146 26 31 57 57 84 69 124 52 167 75 177 93 17 33 -14 35 -71 6 -29 -14 -69 -32 -89 -39 l-38 -14 20 51 c11 28 24 59 29 68 10 19 -20 60 -45 60 -18 0 -21 46 -4 52 6 2 14 26 16 53 4 43 2 52 -16 63 -20 11 -21 10 -21 -25 -1 -209 -5 -248 -32 -305 -34 -73 -116 -188 -133 -188 -8 0 -20 -6 -27 -13 -7 -7 -29 -18 -48 -24 -19 -6 -52 -18 -72 -27 -34 -15 -38 -15 -38 -1 0 35 32 73 89 109 60 37 77 51 45 39 -14 -5 -14 -3 -3 14 7 13 9 28 4 39 -5 11 -7 24 -6 29 1 6 -19 -11 -44 -37 -25 -26 -45 -44 -45 -40 0 4 18 34 40 67 30 45 40 69 40 100 0 53 -11 67 -46 63 -22 -2 -34 -13 -53 -47 -14 -25 -26 -40 -29 -33 -2 7 -10 12 -17 12 -10 0 -14 -33 -17 -142 l-4 -143 -63 -127 c-39 -81 -74 -137 -94 -154 -51 -43 -167 -87 -167 -63 0 6 26 38 58 72 32 34 66 73 75 87 18 26 23 100 8 100 -5 0 -22 -19 -38 -42 -15 -23 -52 -60 -81 -82 -31 -25 -61 -59 -74 -85 -37 -75 -125 -156 -220 -201 -46 -22 -101 -43 -121 -47 -32 -5 -37 -3 -37 13 0 36 50 229 70 269 10 23 38 95 61 160 39 116 84 211 117 248 12 13 13 20 4 29 -9 9 -21 5 -49 -18 -58 -46 -166 -272 -249 -519 -37 -110 -73 -207 -80 -216 -8 -8 -14 -21 -14 -28 0 -8 -19 -54 -41 -105 -23 -50 -61 -146 -84 -212 -49 -144 -77 -193 -152 -274 -71 -77 -89 -77 -115 2 -11 33 -27 59 -36 62 -19 6 -21 27 -23 201 -2 197 49 394 151 580 33 61 72 135 86 165 118 253 140 288 273 462 87 112 121 167 121 195 0 37 -25 27 -75 -29 -42 -48 -45 -50 -38 -23 13 50 9 145 -8 156 -19 12 -30 7 -50 -22 -23 -33 -15 -116 12 -124 28 -9 35 -49 12 -73 -10 -11 -36 -45 -58 -76 -22 -31 -44 -56 -48 -56 -12 0 -3 78 17 160 8 36 15 84 16 107 0 23 4 44 9 47 4 3 11 37 14 75 3 39 14 86 26 109 26 50 80 97 94 83 16 -16 59 -13 85 5 30 21 52 66 52 109 0 33 -2 35 -32 35 -59 0 -78 -12 -118 -69 -21 -31 -55 -74 -74 -96 l-35 -40 -1 41 c0 23 7 60 15 83 15 43 92 151 124 173 20 14 55 77 48 85 -3 2 -8 -5 -12 -16 -7 -24 -35 -17 -35 9 0 23 -13 32 -35 24 -9 -4 -12 -9 -7 -13 17 -10 2 -62 -16 -59 -11 2 -30 -24 -61 -87 -34 -68 -46 -84 -49 -67 -2 12 -8 22 -13 22 -5 0 -9 -10 -9 -22 -1 -23 -1 -23 -16 -3 -9 11 -24 37 -34 58 -11 24 -20 34 -23 25 -3 -7 -6 25 -6 72 -1 105 -21 98 -26 -10 -3 -43 -9 -76 -16 -81 -10 -6 -10 -11 0 -23 14 -16 3 -22 -15 -8 -5 4 2 -2 15 -13 51 -41 78 -76 96 -128 26 -70 25 -187 -3 -292 -13 -49 -21 -109 -20 -155 0 -104 -54 -310 -81 -310 -6 0 -11 3 -11 8 -1 44 -24 191 -41 259 l-22 85 27 108 c30 123 34 211 10 231 -20 16 -40 5 -72 -42 -21 -30 -23 -42 -18 -97 3 -36 1 -60 -4 -57 -17 11 -34 81 -34 150 -1 64 2 76 39 140 22 39 45 84 52 100 17 43 16 92 -2 98 -17 7 -17 8 -44 -73 -12 -36 -34 -87 -50 -113 -33 -56 -41 -48 -41 39 0 41 -4 54 -15 54 -11 0 -15 -18 -17 -80 -2 -45 -7 -80 -13 -80 -5 0 -10 4 -10 8 0 5 -8 16 -18 26 -58 58 -70 132 -53 314 7 69 6 92 -3 92 -6 0 -13 -6 -16 -12z m321 -503 c3 -20 4 -39 0 -42 -3 -4 -6 6 -6 20 0 17 -5 27 -15 27 -16 0 -20 12 -8 23 14 14 22 6 29 -28z m-1006 -80 c0 -8 -9 -15 -19 -15 -29 0 -35 18 -9 23 13 2 24 5 26 6 1 0 2 -6 2 -14z m327 -27 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-462 -358 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-835 -40 c-6 -11 -15 -20 -19 -20 -5 0 -7 9 -4 20 3 11 12 20 20 20 11 0 11 -4 3 -20z m864 -25 c3 -9 0 -15 -9 -15 -9 0 -15 -10 -16 -27 0 -27 -1 -27 -13 7 -10 25 -10 37 -2 42 18 12 33 9 40 -7z m-892 -863 c38 2 68 0 68 -4 0 -5 -33 -8 -73 -8 -49 0 -80 -5 -95 -16 -21 -14 -22 -14 -22 5 0 14 -6 21 -20 21 -11 0 -20 2 -20 4 0 2 -3 12 -6 21 -6 13 1 13 47 -5 40 -16 70 -21 121 -18z m3218 -91 c0 -10 -7 -21 -15 -25 -11 -4 -15 1 -15 19 0 16 6 25 15 25 8 0 15 -9 15 -19z m-3479 -32 c-14 -5 -30 -14 -37 -20 -8 -7 -13 -3 -17 11 -5 18 0 20 36 19 38 0 40 -1 18 -10z m3359 -572 c0 -7 -7 -22 -15 -33 -13 -17 -14 -16 -4 14 11 33 19 41 19 19z m-3345 -198 c7 -22 -7 -39 -33 -39 -10 0 -10 4 0 20 11 17 10 22 -2 30 -12 8 -11 10 7 10 13 0 24 -8 28 -21z m445 -37 c0 -23 -35 -8 -38 16 -3 21 -2 22 17 10 12 -7 21 -19 21 -26z m-310 -647 c-28 -30 -60 -33 -60 -7 0 26 9 32 48 32 l35 0 -23 -25z M3684 5414 c-14 -21 -16 -41 -10 -124 4 -62 2 -100 -3 -100 -9 0 -17 26 -25 84 -1 11 -8 22 -14 24 -9 3 -12 -27 -12 -105 0 -69 -6 -130 -16 -164 -24 -86 -24 -85 -33 -70 -6 9 -10 3 -14 -17 -4 -20 -23 -43 -59 -72 -29 -23 -54 -46 -54 -51 -1 -5 -3 -39 -4 -76 -1 -46 -4 -60 -9 -43 -6 21 -9 15 -20 -35 -16 -74 -29 -99 -97 -197 -35 -49 -54 -86 -54 -105 0 -31 59 -200 60 -171 0 9 6 21 14 25 13 7 13 16 0 68 -17 72 -12 78 75 93 106 19 127 33 145 95 20 70 65 111 186 172 83 42 89 47 75 62 -9 8 -14 23 -11 32 5 14 5 14 -6 1 -7 -8 -41 -25 -75 -37 -54 -19 -61 -19 -56 -5 10 26 43 72 91 126 46 53 77 104 68 114 -6 6 -95 -81 -143 -141 l-30 -38 -7 80 c-4 45 -5 89 -1 98 3 10 31 34 63 53 61 37 147 112 164 144 21 38 -53 8 -126 -52 -98 -80 -100 -81 -92 -46 12 47 54 133 81 166 14 16 25 42 25 56 l-1 27 -25 -30 -26 -30 6 53 c3 28 9 74 12 100 5 40 3 50 -10 55 -10 4 -22 -2 -32 -19z m-79 -654 c0 -125 0 -126 -33 -176 -22 -36 -56 -67 -109 -103 -42 -28 -82 -51 -90 -51 -20 0 -16 22 11 59 13 18 30 46 36 62 7 16 16 29 20 29 5 0 13 33 20 73 16 102 29 149 40 142 6 -4 10 -2 10 3 0 5 13 25 30 43 16 19 30 38 30 42 0 5 8 7 18 5 15 -3 17 -17 17 -128z M2287 5348 c-10 -10 -22 -16 -27 -13 -5 3 -8 -3 -8 -12 1 -10 -2 -37 -6 -59 -6 -32 -4 -43 7 -47 23 -9 67 61 67 105 0 44 -9 51 -33 26z M1853 5256 c4 -22 11 -42 17 -46 7 -4 14 -26 17 -49 3 -22 10 -41 15 -41 5 0 7 12 4 28 -3 15 -8 46 -11 69 -4 23 -16 49 -27 60 -21 18 -21 18 -15 -21z M1780 5267 c0 -47 15 -79 42 -93 l30 -16 -7 34 c-4 18 -12 44 -19 58 -12 28 -46 40 -46 17z M1960 5120 c0 -21 30 -70 49 -80 27 -14 31 -13 31 10 0 11 5 20 10 20 6 0 8 -11 4 -25 -6 -23 -4 -25 30 -25 20 0 36 4 36 8 0 18 -68 72 -109 87 -52 18 -51 18 -51 5z M4127 5076 c-4 -10 -7 -45 -7 -79 0 -42 -6 -70 -18 -88 -56 -85 -73 -107 -106 -138 -20 -19 -36 -39 -36 -43 0 -18 34 -6 62 23 29 28 34 30 84 24 41 -6 59 -3 83 11 37 22 44 37 28 59 -16 21 -72 22 -95 2 -21 -19 -32 -22 -32 -7 0 5 38 35 84 66 77 51 106 84 106 119 0 26 -43 16 -77 -17 l-33 -32 0 47 c0 34 -4 47 -14 47 -8 0 -16 5 -18 12 -3 7 -7 5 -11 -6z M1049 5043 c-8 -10 -9 -14 -2 -10 7 5 28 -18 57 -63 48 -74 62 -86 52 -45 -4 15 -2 25 4 25 15 0 -17 72 -41 93 -27 22 -53 22 -70 0z M3400 4964 c-14 -37 -12 -60 6 -75 14 -11 18 -10 30 6 19 26 18 81 -2 89 -23 9 -24 8 -34 -20z M3910 4933 c-29 -20 -40 -33 -40 -50 0 -33 63 6 75 45 8 26 -2 28 -35 5z M3401 4844 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z M4532 4829 c-8 -12 -9 -18 -3 -14 7 4 11 -8 12 -32 1 -21 4 -51 8 -68 6 -26 8 -22 13 29 5 39 3 67 -5 83 l-12 23 -13 -21z M1017 4820 c-8 -30 16 -52 65 -60 41 -6 45 -5 40 12 -5 20 -68 68 -88 68 -6 0 -14 -9 -17 -20z M2529 4778 c-11 -21 -7 -134 7 -185 8 -30 24 -19 24 17 0 16 7 35 15 44 18 17 20 70 4 115 -13 36 -33 40 -50 9z M830 4767 c0 -24 30 -116 40 -122 11 -7 1 92 -12 118 -10 20 -28 23 -28 4z M4660 4751 c0 -5 -9 -12 -19 -16 -23 -7 -101 -81 -101 -95 0 -26 50 -6 98 38 51 47 67 82 37 82 -8 0 -15 -4 -15 -9z M764 4719 c-7 -13 82 -106 92 -96 11 11 -9 43 -46 75 -27 23 -41 29 -46 21z M1887 4634 c-18 -18 -6 -91 21 -131 79 -118 125 -171 138 -159 10 9 8 18 -9 46 -12 19 -25 37 -29 38 -4 2 -8 25 -8 50 0 60 -15 115 -38 135 -20 19 -65 31 -75 21z M1030 4579 c0 -35 54 -169 68 -169 6 0 12 -8 12 -17 1 -17 2 -17 15 0 11 16 11 26 -5 71 -25 75 -47 114 -70 126 -17 9 -20 8 -20 -11z M697 4553 c19 -54 69 -92 112 -85 36 5 46 34 20 58 -11 9 -22 14 -25 11 -4 -4 -18 3 -32 13 -32 26 -84 28 -75 3z M1150 4486 c0 -36 52 -76 101 -76 47 0 57 29 12 32 -16 1 6 4 47 8 l75 6 -75 2 c-41 1 -85 8 -96 15 -12 6 -31 18 -43 25 -19 12 -21 11 -21 -12z M3909 4427 c-16 -27 -19 -51 -19 -149 0 -111 1 -118 20 -118 15 0 24 14 40 68 39 124 39 215 -1 225 -15 4 -25 -2 -40 -26z M4723 4375 c-30 -13 -33 -18 -33 -60 l0 -45 24 15 c27 18 49 48 60 83 9 26 -4 28 -51 7z M5002 4348 c-5 -7 -23 -40 -40 -73 -32 -65 -106 -146 -156 -172 -17 -9 -51 -21 -75 -28 -46 -11 -63 -28 -38 -38 7 -3 47 2 87 10 58 12 85 13 128 4 96 -19 162 -13 162 15 0 11 -19 14 -82 15 -46 0 -91 4 -101 8 -17 6 -17 8 2 25 11 10 44 25 73 32 34 8 43 13 27 13 -31 1 -44 24 -23 41 8 7 14 21 14 31 0 11 10 36 23 57 33 52 39 72 23 72 -7 0 -18 -6 -24 -12z M3632 4290 c-52 -37 -68 -69 -74 -145 -3 -33 -3 -54 0 -47 3 10 7 9 16 -4 12 -15 18 -14 79 15 69 33 101 66 95 98 -4 22 -37 30 -49 11 -6 -8 -7 10 -3 45 8 68 -2 72 -64 27z M5016 4271 c-11 -12 -16 -24 -12 -28 9 -9 39 22 34 37 -2 7 -10 4 -22 -9z M470 4264 c0 -9 8 -28 18 -42 10 -15 22 -33 27 -40 8 -15 -67 31 -102 62 -13 11 -23 14 -23 8 0 -7 -7 -12 -15 -12 -19 0 -19 -15 2 -50 20 -35 48 -48 118 -56 37 -5 55 -11 55 -20 0 -8 11 -14 25 -14 14 0 25 4 25 10 0 5 -22 43 -50 84 -49 73 -80 100 -80 70z M2382 4102 c-5 -9 -12 -42 -14 -72 -9 -96 18 -125 39 -43 17 66 17 120 -2 127 -8 3 -19 -2 -23 -12z M4235 3850 c36 -39 118 -80 162 -80 30 0 93 41 93 61 0 5 -14 15 -30 24 -25 13 -44 14 -107 6 -43 -5 -80 -6 -83 -1 -3 5 -19 12 -35 16 l-30 7 30 -33z M133 3667 c-19 -41 -15 -59 18 -86 30 -24 135 -55 151 -45 11 7 10 42 -2 49 -5 3 -10 11 -10 17 0 6 7 5 17 -3 12 -10 15 -10 9 -1 -13 22 -84 52 -125 52 -33 0 -40 4 -43 22 -3 21 -4 21 -15 -5z M5265 3631 c-16 -10 -43 -33 -60 -51 l-30 -32 83 4 c77 3 86 6 107 30 35 41 24 68 -29 68 -23 0 -54 -8 -71 -19z M400 3512 c0 -5 -53 -12 -117 -16 -64 -4 -120 -9 -125 -12 -16 -10 -8 -53 13 -65 51 -27 183 0 213 43 13 17 19 18 68 9 29 -5 66 -13 81 -16 22 -6 26 -4 21 9 -5 12 0 16 17 17 13 1 -3 7 -36 14 -106 22 -135 26 -135 17z M5090 3480 c0 -5 9 -10 20 -10 11 0 47 -13 80 -30 57 -29 121 -39 147 -22 22 14 19 45 -7 59 -30 15 -240 18 -240 3z M926 3272 c-12 -11 -6 -94 9 -122 16 -31 39 -47 86 -60 24 -7 29 -5 39 21 19 44 5 94 -34 124 -35 27 -90 47 -100 37z M500 3049 c0 -23 9 -62 20 -85 17 -33 30 -46 70 -62 34 -14 56 -32 70 -54 16 -28 109 -108 125 -108 3 0 5 7 5 15 0 12 7 14 28 9 15 -3 -8 11 -50 32 -42 20 -80 44 -83 53 -4 9 -9 46 -12 84 -5 61 -9 70 -41 98 -34 30 -59 43 -107 55 -24 6 -25 4 -25 -37z M5203 2779 c-18 -11 -35 -29 -38 -40 -7 -22 -20 -25 -32 -6 -8 13 -20 -26 -22 -74 -1 -30 25 -36 35 -7 4 15 9 17 20 7 8 -6 14 -18 14 -26 0 -11 7 -9 27 7 43 33 63 71 63 118 0 49 -14 53 -67 21z M5307 2622 c-34 -32 -86 -72 -115 -88 -51 -29 -61 -46 -29 -52 25 -5 198 81 229 114 15 16 30 41 33 57 7 25 5 27 -24 27 -25 0 -45 -13 -94 -58z M447 2652 c-10 -10 -15 -21 -12 -24 7 -7 75 24 75 34 0 15 -47 8 -63 -10z M263 2600 c-12 -5 -26 -18 -32 -28 -8 -15 -6 -24 13 -41 33 -31 84 -27 160 13 68 36 68 47 1 51 -16 1 -50 5 -75 8 -25 4 -55 3 -67 -3z M996 2540 c-37 -11 -102 -74 -115 -112 l-10 -28 58 0 c48 0 65 5 98 29 49 35 87 86 79 106 -6 17 -62 19 -110 5z M673 2324 c-43 -18 -42 -43 1 -88 33 -35 35 -36 114 -36 70 0 80 2 78 18 0 10 6 16 16 16 13 -1 9 8 -18 40 -19 22 -45 46 -57 53 -29 16 -94 15 -134 -3z M4790 2120 c-9 -17 -5 -20 43 -29 72 -15 166 -19 169 -9 2 5 11 6 21 3 20 -8 23 -35 5 -35 -7 -1 -2 -7 12 -15 29 -17 113 -20 141 -5 24 13 25 36 2 48 -10 5 -58 12 -108 15 -49 3 -117 12 -150 20 -110 28 -124 28 -135 7z M4881 2021 c6 -17 30 -50 53 -75 33 -36 49 -46 74 -46 25 0 32 4 32 19 0 25 -60 77 -99 86 -17 4 -36 15 -41 26 -17 30 -30 23 -19 -10z";
|
|
1620
1615
|
|
|
1621
1616
|
// src/genre-tree/TreeMarkIcon.tsx
|
|
1622
|
-
var
|
|
1617
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1623
1618
|
function TreeMarkIcon({ className: className2 }) {
|
|
1624
|
-
return /* @__PURE__ */ (0,
|
|
1619
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("svg", { viewBox: "0 0 551 567", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("path", { transform: "translate(0 567) scale(0.1 -0.1)", d: TREE_MARK_PATH }) });
|
|
1625
1620
|
}
|
|
1626
1621
|
|
|
1627
1622
|
// src/genre-tree/GenrePlayActions.tsx
|
|
1628
|
-
var
|
|
1623
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1629
1624
|
function PlayIcon({ kind }) {
|
|
1630
|
-
return /* @__PURE__ */ (0,
|
|
1631
|
-
kind === "tree" && /* @__PURE__ */ (0,
|
|
1632
|
-
kind === "map" && /* @__PURE__ */ (0,
|
|
1633
|
-
kind === "tree-map" && /* @__PURE__ */ (0,
|
|
1634
|
-
/* @__PURE__ */ (0,
|
|
1635
|
-
/* @__PURE__ */ (0,
|
|
1625
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { "aria-hidden": "true", className: "relative flex items-center justify-center w-5 h-5", children: [
|
|
1626
|
+
kind === "tree" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1627
|
+
kind === "map" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1628
|
+
kind === "tree-map" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1629
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_50%_0_0)]" }),
|
|
1630
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_0_0_50%)]" })
|
|
1636
1631
|
] }),
|
|
1637
|
-
/* @__PURE__ */ (0,
|
|
1632
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react12.Play, { className: "relative w-5 h-5 fill-[var(--color-surface)]" })
|
|
1638
1633
|
] });
|
|
1639
1634
|
}
|
|
1640
1635
|
function playOptions(playlist) {
|
|
@@ -1650,13 +1645,13 @@ function playOptions(playlist) {
|
|
|
1650
1645
|
function GenrePlayActions({ genrePlaylist, playback }) {
|
|
1651
1646
|
const { isPlaying, setIsPlaying } = (0, import_player4.usePlayer)();
|
|
1652
1647
|
const options = playOptions(genrePlaylist);
|
|
1653
|
-
return /* @__PURE__ */ (0,
|
|
1648
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: options.map((option) => {
|
|
1654
1649
|
const isCurrent = playback.playing?.uuid === genrePlaylist.uuid && (option.selection === void 0 || playback.playing.selectionKey === "" || playback.playing.selectionKey === (0, import_genre_tree10.genreMusicSelectionKey)(option.selection).join());
|
|
1655
1650
|
const playing = isCurrent && isPlaying;
|
|
1656
|
-
return /* @__PURE__ */ (0,
|
|
1651
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1657
1652
|
import_ui10.ActionButton,
|
|
1658
1653
|
{
|
|
1659
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
1654
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react12.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(PlayIcon, { kind: option.icon }),
|
|
1660
1655
|
label: playing ? "Pause" : option.label,
|
|
1661
1656
|
caption: String(option.count),
|
|
1662
1657
|
disabled: option.count === 0,
|
|
@@ -1666,9 +1661,7 @@ function GenrePlayActions({ genrePlaylist, playback }) {
|
|
|
1666
1661
|
setIsPlaying(!isPlaying);
|
|
1667
1662
|
return;
|
|
1668
1663
|
}
|
|
1669
|
-
playback.play(genrePlaylist, option.selection)
|
|
1670
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
1671
|
-
});
|
|
1664
|
+
void playback.play(genrePlaylist, option.selection);
|
|
1672
1665
|
}
|
|
1673
1666
|
},
|
|
1674
1667
|
option.key
|
|
@@ -1682,7 +1675,7 @@ var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1682
1675
|
|
|
1683
1676
|
// src/genre-tree/ClampedText.tsx
|
|
1684
1677
|
var import_react12 = require("react");
|
|
1685
|
-
var
|
|
1678
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1686
1679
|
function ClampedText({ children, className: className2 = "" }) {
|
|
1687
1680
|
const ref = (0, import_react12.useRef)(null);
|
|
1688
1681
|
const [expanded, setExpanded] = (0, import_react12.useState)(false);
|
|
@@ -1692,9 +1685,9 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1692
1685
|
if (!element || expanded) return;
|
|
1693
1686
|
setOverflows(element.scrollHeight > element.clientHeight);
|
|
1694
1687
|
}, [children, expanded]);
|
|
1695
|
-
return /* @__PURE__ */ (0,
|
|
1696
|
-
/* @__PURE__ */ (0,
|
|
1697
|
-
(overflows || expanded) && /* @__PURE__ */ (0,
|
|
1688
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
1689
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { ref, className: `${className2} ${expanded ? "" : "line-clamp-3"}`, children }),
|
|
1690
|
+
(overflows || expanded) && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1698
1691
|
"button",
|
|
1699
1692
|
{
|
|
1700
1693
|
type: "button",
|
|
@@ -1714,13 +1707,13 @@ var import_zod = require("zod");
|
|
|
1714
1707
|
var import_fa4 = require("react-icons/fa");
|
|
1715
1708
|
var import_ui11 = require("@behindthemusictree/ui");
|
|
1716
1709
|
var import_auth2 = require("@behindthemusictree/app-kit/auth");
|
|
1710
|
+
var import_transport4 = require("@behindthemusictree/app-kit/transport");
|
|
1717
1711
|
var import_transport5 = require("@behindthemusictree/app-kit/transport");
|
|
1718
1712
|
var import_transport6 = require("@behindthemusictree/app-kit/transport");
|
|
1719
|
-
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
1720
1713
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1721
1714
|
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1722
|
-
var
|
|
1723
|
-
var
|
|
1715
|
+
var import_popup4 = require("@behindthemusictree/app-kit/popup");
|
|
1716
|
+
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
1724
1717
|
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1725
1718
|
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1726
1719
|
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -1729,15 +1722,15 @@ var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1729
1722
|
|
|
1730
1723
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1731
1724
|
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1732
|
-
var
|
|
1725
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1733
1726
|
function MusicBrainzRecordingLink({
|
|
1734
1727
|
song,
|
|
1735
1728
|
children,
|
|
1736
1729
|
className: className2 = ""
|
|
1737
1730
|
}) {
|
|
1738
1731
|
const url = (0, import_genre_tree11.musicBrainzRecordingUrl)(song);
|
|
1739
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1740
|
-
return /* @__PURE__ */ (0,
|
|
1732
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children });
|
|
1733
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1741
1734
|
"a",
|
|
1742
1735
|
{
|
|
1743
1736
|
href: url,
|
|
@@ -1754,9 +1747,9 @@ function MusicBrainzRecordingLink({
|
|
|
1754
1747
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1755
1748
|
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1756
1749
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1757
|
-
var
|
|
1750
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1758
1751
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1759
|
-
var SongPageSchema = (0,
|
|
1752
|
+
var SongPageSchema = (0, import_transport5.PaginatedResponseSchema)(import_genre_tree15.SongDetailedSchema).extend({
|
|
1760
1753
|
overallTotal: import_zod.z.number().nullable(),
|
|
1761
1754
|
page: import_zod.z.number().nullable(),
|
|
1762
1755
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1788,12 +1781,12 @@ function GenrePlaylistTracks({
|
|
|
1788
1781
|
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree16.useTrackList)();
|
|
1789
1782
|
const { session, sessionRestored } = (0, import_auth2.useSession)();
|
|
1790
1783
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player5.usePlayer)();
|
|
1791
|
-
const { showPopup } = (0,
|
|
1784
|
+
const { showPopup } = (0, import_popup4.usePopup)();
|
|
1792
1785
|
const trackNoun = (0, import_track_noun2.useTrackNoun)();
|
|
1793
1786
|
const uuid = genrePlaylist?.uuid;
|
|
1794
1787
|
const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
|
|
1795
|
-
const { fetchBound } = (0,
|
|
1796
|
-
const playback = (0,
|
|
1788
|
+
const { fetchBound } = (0, import_transport4.usePlaybackFetch)(getBackendBaseUrl);
|
|
1789
|
+
const playback = (0, import_transport4.usePlaybackContext)();
|
|
1797
1790
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1798
1791
|
queryKey: [...scope === "me" ? uuid ? import_genre_tree13.genrePlaylistQueryKeys.me.tracks(uuid) : ["missing-personal-genre-playlist", genreUuid] : artist ? [...import_genre_tree14.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), "artist", artist.uuid] : import_genre_tree14.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), ...playback.key ? [playback.key] : []],
|
|
1799
1792
|
queryFn: async ({ pageParam }) => {
|
|
@@ -1808,7 +1801,7 @@ function GenrePlaylistTracks({
|
|
|
1808
1801
|
{},
|
|
1809
1802
|
{ genre: genreUuid, ...(0, import_genre_tree12.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1810
1803
|
);
|
|
1811
|
-
const parsed = (0,
|
|
1804
|
+
const parsed = (0, import_transport6.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1812
1805
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
1813
1806
|
},
|
|
1814
1807
|
initialPageParam: scope === "me" ? 1 : "",
|
|
@@ -1840,35 +1833,36 @@ function GenrePlaylistTracks({
|
|
|
1840
1833
|
}) : scope === "reference" ? playNewTrackListFromGenreCatalogue({ uuid: genreUuid, name: genreName }, scope, { startSongUuid, ...selection && { selection } }) : genrePlaylist ? playNewTrackListFromGenrePlaylist(genrePlaylist, scope, { startSongUuid }) : Promise.reject(new Error("Personal genre has no playlist"));
|
|
1841
1834
|
started.catch((error) => {
|
|
1842
1835
|
console.error("Failed to play genre playlist:", error);
|
|
1843
|
-
|
|
1836
|
+
if (error instanceof import_genre_tree16.TracksFailureAlreadyReportedError) return;
|
|
1837
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport7.AppError ? error.code : import_transport7.ErrorCode.CLIENT_UNKNOWN }));
|
|
1844
1838
|
});
|
|
1845
1839
|
};
|
|
1846
|
-
return /* @__PURE__ */ (0,
|
|
1840
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui11.PanelSection, { title: `${(0, import_track_noun2.capitalize)(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { children: [
|
|
1847
1841
|
renderTracksToolbar?.(),
|
|
1848
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0,
|
|
1842
|
+
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: "\u2014" }) : isPending ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui11.Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { role: "alert", children: [
|
|
1849
1843
|
"Couldn't load ",
|
|
1850
1844
|
trackNoun.plural,
|
|
1851
1845
|
".",
|
|
1852
1846
|
" ",
|
|
1853
|
-
/* @__PURE__ */ (0,
|
|
1854
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0,
|
|
1847
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1848
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1855
1849
|
tracks.map((track, index) => {
|
|
1856
1850
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1857
1851
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1858
1852
|
const isPlaying = isCurrent && playState === import_player6.PlayStates.PLAYING;
|
|
1859
|
-
const text = /* @__PURE__ */ (0,
|
|
1860
|
-
/* @__PURE__ */ (0,
|
|
1861
|
-
track.artists?.length ? /* @__PURE__ */ (0,
|
|
1862
|
-
/* @__PURE__ */ (0,
|
|
1863
|
-
track.album && /* @__PURE__ */ (0,
|
|
1853
|
+
const text = /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1854
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree15.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1855
|
+
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1856
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_genre_tree17.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1857
|
+
track.album && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1864
1858
|
] });
|
|
1865
1859
|
const leading = renderSongLeading?.(track, index);
|
|
1866
1860
|
const actions = renderSongActions?.(track);
|
|
1867
1861
|
const isUnplayable = (0, import_genre_tree15.isSong)(track) && (0, import_genre_tree15.songUnplayableReason)(track) !== null;
|
|
1868
1862
|
if (isUnplayable) {
|
|
1869
|
-
return /* @__PURE__ */ (0,
|
|
1863
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1870
1864
|
leading,
|
|
1871
|
-
/* @__PURE__ */ (0,
|
|
1865
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1872
1866
|
"button",
|
|
1873
1867
|
{
|
|
1874
1868
|
type: "button",
|
|
@@ -1876,27 +1870,27 @@ function GenrePlaylistTracks({
|
|
|
1876
1870
|
"aria-disabled": "true",
|
|
1877
1871
|
"aria-label": label,
|
|
1878
1872
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1879
|
-
children: /* @__PURE__ */ (0,
|
|
1873
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1880
1874
|
}
|
|
1881
1875
|
),
|
|
1882
1876
|
text,
|
|
1883
1877
|
actions
|
|
1884
1878
|
] }, track.uuid);
|
|
1885
1879
|
}
|
|
1886
|
-
return /* @__PURE__ */ (0,
|
|
1880
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
1887
1881
|
"li",
|
|
1888
1882
|
{
|
|
1889
1883
|
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)]" : ""}`,
|
|
1890
1884
|
children: [
|
|
1891
1885
|
leading,
|
|
1892
|
-
/* @__PURE__ */ (0,
|
|
1886
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1893
1887
|
"button",
|
|
1894
1888
|
{
|
|
1895
1889
|
type: "button",
|
|
1896
1890
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1897
1891
|
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"}`,
|
|
1898
1892
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1899
|
-
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0,
|
|
1893
|
+
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui11.RingLoader, { size: 10 }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_fa4.FaPause, { size: 10 }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1900
1894
|
}
|
|
1901
1895
|
),
|
|
1902
1896
|
text,
|
|
@@ -1906,7 +1900,7 @@ function GenrePlaylistTracks({
|
|
|
1906
1900
|
track.uuid
|
|
1907
1901
|
);
|
|
1908
1902
|
}),
|
|
1909
|
-
hasNextPage && /* @__PURE__ */ (0,
|
|
1903
|
+
hasNextPage && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1910
1904
|
] })
|
|
1911
1905
|
] }) });
|
|
1912
1906
|
}
|
|
@@ -1914,7 +1908,7 @@ function GenrePlaylistTracks({
|
|
|
1914
1908
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1915
1909
|
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
1916
1910
|
var import_si2 = require("react-icons/si");
|
|
1917
|
-
var
|
|
1911
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1918
1912
|
function GenreDetailExtras({
|
|
1919
1913
|
genreUuid,
|
|
1920
1914
|
genrePlaylist,
|
|
@@ -1940,17 +1934,17 @@ function GenreDetailExtras({
|
|
|
1940
1934
|
criteriaOverviewSchema
|
|
1941
1935
|
);
|
|
1942
1936
|
if (isPending) {
|
|
1943
|
-
return /* @__PURE__ */ (0,
|
|
1944
|
-
/* @__PURE__ */ (0,
|
|
1937
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
1938
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui12.PanelSection, { title: "Summary", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui12.Skeleton, { className: "h-4 w-3/4" }) }) }),
|
|
1945
1939
|
family
|
|
1946
1940
|
] });
|
|
1947
1941
|
}
|
|
1948
|
-
if (!overview) return /* @__PURE__ */ (0,
|
|
1942
|
+
if (!overview) return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, { children: family });
|
|
1949
1943
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1950
1944
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1951
|
-
return /* @__PURE__ */ (0,
|
|
1952
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0,
|
|
1953
|
-
summarySourceUrl && /* @__PURE__ */ (0,
|
|
1945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
1946
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui12.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1947
|
+
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1954
1948
|
"a",
|
|
1955
1949
|
{
|
|
1956
1950
|
href: summarySourceUrl,
|
|
@@ -1958,12 +1952,12 @@ function GenreDetailExtras({
|
|
|
1958
1952
|
rel: "noopener noreferrer",
|
|
1959
1953
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1960
1954
|
children: [
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
1955
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_si2.SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1962
1956
|
"Wikipedia"
|
|
1963
1957
|
]
|
|
1964
1958
|
}
|
|
1965
1959
|
),
|
|
1966
|
-
wikidataUrl && /* @__PURE__ */ (0,
|
|
1960
|
+
wikidataUrl && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1967
1961
|
"a",
|
|
1968
1962
|
{
|
|
1969
1963
|
href: wikidataUrl,
|
|
@@ -1971,17 +1965,17 @@ function GenreDetailExtras({
|
|
|
1971
1965
|
rel: "noopener noreferrer",
|
|
1972
1966
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1973
1967
|
children: [
|
|
1974
|
-
/* @__PURE__ */ (0,
|
|
1968
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_si2.SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1975
1969
|
"Wikidata"
|
|
1976
1970
|
]
|
|
1977
1971
|
}
|
|
1978
1972
|
)
|
|
1979
1973
|
] }) }),
|
|
1980
|
-
/* @__PURE__ */ (0,
|
|
1974
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui12.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1981
1975
|
family,
|
|
1982
1976
|
renderGenreDetailExtras?.(overview),
|
|
1983
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0,
|
|
1984
|
-
/* @__PURE__ */ (0,
|
|
1977
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui12.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
1978
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1985
1979
|
GenrePlaylistTracks,
|
|
1986
1980
|
{
|
|
1987
1981
|
genreUuid,
|
|
@@ -1999,10 +1993,10 @@ function GenreDetailExtras({
|
|
|
1999
1993
|
}
|
|
2000
1994
|
|
|
2001
1995
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
2002
|
-
var
|
|
1996
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2003
1997
|
var import_react14 = require("react");
|
|
2004
1998
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
2005
|
-
return /* @__PURE__ */ (0,
|
|
1999
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenrePlayActions, { genrePlaylist, playback }) });
|
|
2006
2000
|
}
|
|
2007
2001
|
function GenreInfoPanelBody({
|
|
2008
2002
|
toolbar,
|
|
@@ -2019,9 +2013,9 @@ function GenreInfoPanelBody({
|
|
|
2019
2013
|
}) {
|
|
2020
2014
|
const summary = scope === "reference" ? import_genre_tree19.GenreCatalogueCountsSchema.parse(genrePlaylist ?? catalogue) : void 0;
|
|
2021
2015
|
const selection = summary ? (0, import_genre_tree19.defaultGenreMusicSelection)(summary) : void 0;
|
|
2022
|
-
return /* @__PURE__ */ (0,
|
|
2016
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
2023
2017
|
toolbar,
|
|
2024
|
-
genrePlaylist ? /* @__PURE__ */ (0,
|
|
2018
|
+
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenreActionBand, { ...band }),
|
|
2025
2019
|
/* @__PURE__ */ (0, import_react14.createElement)(
|
|
2026
2020
|
GenreDetailExtras,
|
|
2027
2021
|
{
|
|
@@ -2041,7 +2035,7 @@ function GenreInfoPanelBody({
|
|
|
2041
2035
|
}
|
|
2042
2036
|
|
|
2043
2037
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
2044
|
-
var
|
|
2038
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2045
2039
|
var RELATIVE_ITEM_COUNT = 1;
|
|
2046
2040
|
function toNode(genre, parentId) {
|
|
2047
2041
|
return {
|
|
@@ -2064,7 +2058,7 @@ function useGenreDetailContent({
|
|
|
2064
2058
|
trailing,
|
|
2065
2059
|
genrePlaylist: hostPlaylist,
|
|
2066
2060
|
expanded,
|
|
2067
|
-
|
|
2061
|
+
treeStyles
|
|
2068
2062
|
}) {
|
|
2069
2063
|
const { data: detail, isPending, isError } = (0, import_genre_tree20.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
2070
2064
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: [], artist: extras?.artist });
|
|
@@ -2072,19 +2066,12 @@ function useGenreDetailContent({
|
|
|
2072
2066
|
const view = (0, import_react15.useMemo)(() => {
|
|
2073
2067
|
if (!detail) return null;
|
|
2074
2068
|
const rootColor = (0, import_genre_tree_view4.getGenreTreeColor)(detail.root.wikidataId);
|
|
2075
|
-
const treeStyles = /* @__PURE__ */ new Map();
|
|
2076
|
-
if (treeRelations) {
|
|
2077
|
-
const drawn = [treeRelations, treeRelations.parentNode, ...treeRelations.childNodes, ...treeRelations.ancestorNodes];
|
|
2078
|
-
for (const entry of drawn) {
|
|
2079
|
-
if (entry) treeStyles.set(entry.node.id, { fill: entry.fill, textColor: entry.textColor });
|
|
2080
|
-
}
|
|
2081
|
-
}
|
|
2082
2069
|
const relative = (genre, parentId) => ({
|
|
2083
2070
|
node: toNode(genre, parentId),
|
|
2084
|
-
...treeStyles
|
|
2071
|
+
...treeStyles?.get(genre.uuid) ?? { fill: (0, import_genre_tree_view4.tintSurface)(rootColor), textColor: import_genre_tree_view4.TEXT_COLOR }
|
|
2085
2072
|
});
|
|
2086
2073
|
const ancestors2 = [...detail.ascendants].sort((a, b) => b.degree - a.degree);
|
|
2087
|
-
const own = treeStyles
|
|
2074
|
+
const own = treeStyles?.get(detail.uuid) ?? { fill: rootColor, textColor: (0, import_genre_tree_view4.getTextColorOnFill)(rootColor) };
|
|
2088
2075
|
return {
|
|
2089
2076
|
node: {
|
|
2090
2077
|
id: detail.uuid,
|
|
@@ -2101,23 +2088,23 @@ function useGenreDetailContent({
|
|
|
2101
2088
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
2102
2089
|
)
|
|
2103
2090
|
};
|
|
2104
|
-
}, [detail, scope,
|
|
2091
|
+
}, [detail, scope, treeStyles]);
|
|
2105
2092
|
if (isError) return {
|
|
2106
2093
|
name: null,
|
|
2107
2094
|
title: "Genre unavailable",
|
|
2108
|
-
content: /* @__PURE__ */ (0,
|
|
2095
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { role: "alert", className: "text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
2109
2096
|
};
|
|
2110
2097
|
if (isPending || !detail || !view) return {
|
|
2111
2098
|
name: null,
|
|
2112
2099
|
title: "Loading genre\u2026",
|
|
2113
|
-
content: /* @__PURE__ */ (0,
|
|
2114
|
-
/* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2116
|
-
/* @__PURE__ */ (0,
|
|
2100
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
2101
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.Skeleton, { className: "h-6 w-2/3" }),
|
|
2102
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.Skeleton, { className: "h-4 w-full" }),
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.Skeleton, { className: "h-4 w-3/4" })
|
|
2117
2104
|
] })
|
|
2118
2105
|
};
|
|
2119
2106
|
const selectGenre = (nodeId) => onSelectGenre(import_genre_tree20.GenreUuidSchema.parse(nodeId));
|
|
2120
|
-
const family = /* @__PURE__ */ (0,
|
|
2107
|
+
const family = /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2121
2108
|
import_genre_tree_view4.GenreNodeFamily,
|
|
2122
2109
|
{
|
|
2123
2110
|
node: view.node,
|
|
@@ -2128,17 +2115,17 @@ function useGenreDetailContent({
|
|
|
2128
2115
|
onSelectNode: selectGenre
|
|
2129
2116
|
}
|
|
2130
2117
|
);
|
|
2131
|
-
const ancestors = /* @__PURE__ */ (0,
|
|
2118
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
2132
2119
|
return {
|
|
2133
2120
|
name: detail.name,
|
|
2134
2121
|
title: detail.name,
|
|
2135
2122
|
headerAccent: { background: view.fill, color: view.textColor },
|
|
2136
2123
|
aside: expanded ? ancestors : void 0,
|
|
2137
|
-
content: /* @__PURE__ */ (0,
|
|
2138
|
-
/* @__PURE__ */ (0,
|
|
2124
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
2125
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2139
2126
|
GenreInfoPanelBody,
|
|
2140
2127
|
{
|
|
2141
|
-
family: /* @__PURE__ */ (0,
|
|
2128
|
+
family: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
2142
2129
|
family,
|
|
2143
2130
|
!expanded && ancestors
|
|
2144
2131
|
] }),
|
|
@@ -2182,7 +2169,7 @@ function GenreDetailPanel({
|
|
|
2182
2169
|
expanded,
|
|
2183
2170
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
2184
2171
|
});
|
|
2185
|
-
return /* @__PURE__ */ (0,
|
|
2172
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2186
2173
|
import_ui13.DetailPanel,
|
|
2187
2174
|
{
|
|
2188
2175
|
side: "left",
|
|
@@ -2195,7 +2182,7 @@ function GenreDetailPanel({
|
|
|
2195
2182
|
edgeTab,
|
|
2196
2183
|
aside: panel.aside,
|
|
2197
2184
|
titleInSearch,
|
|
2198
|
-
headerActions: onExpandedChange ? /* @__PURE__ */ (0,
|
|
2185
|
+
headerActions: onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react13.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_lucide_react13.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
2199
2186
|
children: panel.content
|
|
2200
2187
|
}
|
|
2201
2188
|
);
|
|
@@ -2204,7 +2191,7 @@ function GenreDetailPanel({
|
|
|
2204
2191
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
2205
2192
|
var import_react16 = require("react");
|
|
2206
2193
|
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2207
|
-
var
|
|
2194
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2208
2195
|
function ChangeParentPopup({
|
|
2209
2196
|
genrePlaylist,
|
|
2210
2197
|
genrePlaylists,
|
|
@@ -2239,12 +2226,12 @@ function ChangeParentPopup({
|
|
|
2239
2226
|
window.addEventListener("keydown", handleKeyDown);
|
|
2240
2227
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2241
2228
|
}, [onClose]);
|
|
2242
|
-
return /* @__PURE__ */ (0,
|
|
2243
|
-
/* @__PURE__ */ (0,
|
|
2229
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
2230
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
2244
2231
|
"Current parent: ",
|
|
2245
2232
|
genrePlaylist.parent?.name ?? "none"
|
|
2246
2233
|
] }),
|
|
2247
|
-
/* @__PURE__ */ (0,
|
|
2234
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2248
2235
|
GenreSearch,
|
|
2249
2236
|
{
|
|
2250
2237
|
genrePlaylists: candidates,
|
|
@@ -2252,7 +2239,7 @@ function ChangeParentPopup({
|
|
|
2252
2239
|
placeholder: "Search a new parent\u2026"
|
|
2253
2240
|
}
|
|
2254
2241
|
) }),
|
|
2255
|
-
formErrors.length > 0 && /* @__PURE__ */ (0,
|
|
2242
|
+
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
2256
2243
|
] });
|
|
2257
2244
|
}
|
|
2258
2245
|
|
|
@@ -2265,7 +2252,7 @@ var import_lucide_react14 = require("lucide-react");
|
|
|
2265
2252
|
var import_ui14 = require("@behindthemusictree/ui");
|
|
2266
2253
|
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2267
2254
|
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2268
|
-
var
|
|
2255
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2269
2256
|
function ArtistActionBand({ artist, share }) {
|
|
2270
2257
|
const { trackList, playNewTrackListFromArtist } = (0, import_genre_tree22.useTrackList)();
|
|
2271
2258
|
const { isPlaying, setIsPlaying } = (0, import_player7.usePlayer)();
|
|
@@ -2281,11 +2268,11 @@ function ArtistActionBand({ artist, share }) {
|
|
|
2281
2268
|
console.error("Failed to load artist tracks:", error);
|
|
2282
2269
|
});
|
|
2283
2270
|
};
|
|
2284
|
-
return /* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
2271
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_ui14.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_ui14.ActionBand, { children: [
|
|
2272
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2286
2273
|
import_ui14.ActionButton,
|
|
2287
2274
|
{
|
|
2288
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
2275
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react14.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_lucide_react14.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2289
2276
|
label: playing ? "Pause" : "Play",
|
|
2290
2277
|
caption: String(artist.playableTracksCount),
|
|
2291
2278
|
disabled: artist.playableTracksCount === 0,
|
|
@@ -2304,7 +2291,7 @@ var import_ui16 = require("@behindthemusictree/ui");
|
|
|
2304
2291
|
var import_lucide_react15 = require("lucide-react");
|
|
2305
2292
|
var import_si3 = require("react-icons/si");
|
|
2306
2293
|
var import_ui15 = require("@behindthemusictree/ui");
|
|
2307
|
-
var
|
|
2294
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2308
2295
|
var LINK_KINDS = {
|
|
2309
2296
|
official: { label: "Official website", Icon: import_lucide_react15.Globe },
|
|
2310
2297
|
wikipedia: { label: "Wikipedia", Icon: import_si3.SiWikipedia },
|
|
@@ -2341,7 +2328,7 @@ function artistLinks(artist) {
|
|
|
2341
2328
|
return links;
|
|
2342
2329
|
}
|
|
2343
2330
|
function ArtistLinks({ links }) {
|
|
2344
|
-
return /* @__PURE__ */ (0,
|
|
2331
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui15.Chip, { href: url, icon: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
2345
2332
|
}
|
|
2346
2333
|
|
|
2347
2334
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -2352,7 +2339,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
2352
2339
|
}
|
|
2353
2340
|
|
|
2354
2341
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2355
|
-
var
|
|
2342
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2356
2343
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
2357
2344
|
function ArtistHeader({ artist }) {
|
|
2358
2345
|
const fields = [];
|
|
@@ -2362,35 +2349,35 @@ function ArtistHeader({ artist }) {
|
|
|
2362
2349
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
2363
2350
|
if (years) fields.push({ label: "Active", value: years });
|
|
2364
2351
|
const links = artistLinks(artist);
|
|
2365
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0,
|
|
2352
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistLinks, { links }) });
|
|
2366
2353
|
if (fields.length === 0) return null;
|
|
2367
|
-
return /* @__PURE__ */ (0,
|
|
2354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui16.FieldList, { items: fields });
|
|
2368
2355
|
}
|
|
2369
2356
|
|
|
2370
2357
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
2371
|
-
var
|
|
2358
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2372
2359
|
function ExternalLink({ href, children }) {
|
|
2373
|
-
return /* @__PURE__ */ (0,
|
|
2360
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
2374
2361
|
}
|
|
2375
2362
|
function ArtistPhoto({ image, name }) {
|
|
2376
|
-
return /* @__PURE__ */ (0,
|
|
2377
|
-
/* @__PURE__ */ (0,
|
|
2378
|
-
/* @__PURE__ */ (0,
|
|
2363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("figure", { className: "flex flex-col gap-1.5", children: [
|
|
2364
|
+
/* @__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" }),
|
|
2365
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2379
2366
|
"Photo: ",
|
|
2380
|
-
/* @__PURE__ */ (0,
|
|
2367
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2381
2368
|
",",
|
|
2382
2369
|
" ",
|
|
2383
|
-
image.licenseUrl ? /* @__PURE__ */ (0,
|
|
2370
|
+
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
2384
2371
|
] })
|
|
2385
2372
|
] });
|
|
2386
2373
|
}
|
|
2387
2374
|
|
|
2388
2375
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2389
2376
|
var import_ui17 = require("@behindthemusictree/ui");
|
|
2390
|
-
var
|
|
2377
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2391
2378
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2392
2379
|
if (memberships.length === 0) return null;
|
|
2393
|
-
return /* @__PURE__ */ (0,
|
|
2380
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui17.PanelGroup, { title, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { children: memberships.map((membership, index) => {
|
|
2394
2381
|
const details = [
|
|
2395
2382
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2396
2383
|
...membership.roles
|
|
@@ -2398,9 +2385,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2398
2385
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
2399
2386
|
return (
|
|
2400
2387
|
// A member can have several periods in the same group.
|
|
2401
|
-
/* @__PURE__ */ (0,
|
|
2402
|
-
/* @__PURE__ */ (0,
|
|
2403
|
-
detailsText && /* @__PURE__ */ (0,
|
|
2388
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
2389
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
2390
|
+
detailsText && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2404
2391
|
" \u2014 ",
|
|
2405
2392
|
detailsText
|
|
2406
2393
|
] })
|
|
@@ -2411,9 +2398,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2411
2398
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2412
2399
|
if (memberships.length === 0) return null;
|
|
2413
2400
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2414
|
-
return /* @__PURE__ */ (0,
|
|
2415
|
-
/* @__PURE__ */ (0,
|
|
2416
|
-
/* @__PURE__ */ (0,
|
|
2401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_ui17.PanelSection, { title, children: [
|
|
2402
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2403
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2417
2404
|
MembershipList,
|
|
2418
2405
|
{
|
|
2419
2406
|
title: "Past",
|
|
@@ -2426,7 +2413,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2426
2413
|
|
|
2427
2414
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2428
2415
|
var import_ui18 = require("@behindthemusictree/ui");
|
|
2429
|
-
var
|
|
2416
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2430
2417
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2431
2418
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
2432
2419
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -2446,12 +2433,12 @@ function byYear(a, b) {
|
|
|
2446
2433
|
function ArtistDiscography({ albums }) {
|
|
2447
2434
|
if (albums.length === 0) return null;
|
|
2448
2435
|
const sorted = [...albums].sort(byYear);
|
|
2449
|
-
return /* @__PURE__ */ (0,
|
|
2436
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui18.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2450
2437
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2451
2438
|
if (groupAlbums.length === 0) return null;
|
|
2452
|
-
return /* @__PURE__ */ (0,
|
|
2453
|
-
/* @__PURE__ */ (0,
|
|
2454
|
-
/* @__PURE__ */ (0,
|
|
2439
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui18.PanelGroup, { title: group, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
2440
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2441
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2455
2442
|
] }, album.uuid)) }) }, group);
|
|
2456
2443
|
}) });
|
|
2457
2444
|
}
|
|
@@ -2459,11 +2446,10 @@ function ArtistDiscography({ albums }) {
|
|
|
2459
2446
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2460
2447
|
var import_react17 = require("react");
|
|
2461
2448
|
var import_react_query2 = require("@tanstack/react-query");
|
|
2462
|
-
var import_lucide_react16 = require("lucide-react");
|
|
2463
2449
|
var import_ui19 = require("@behindthemusictree/ui");
|
|
2464
2450
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2465
2451
|
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2466
|
-
var
|
|
2452
|
+
var import_transport8 = require("@behindthemusictree/app-kit/transport");
|
|
2467
2453
|
|
|
2468
2454
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2469
2455
|
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
@@ -2473,7 +2459,7 @@ var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
2473
2459
|
var import_fa5 = require("react-icons/fa");
|
|
2474
2460
|
var import_player8 = require("@behindthemusictree/app-kit/player");
|
|
2475
2461
|
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2476
|
-
var
|
|
2462
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2477
2463
|
function TrackPositionPlayPause({
|
|
2478
2464
|
position,
|
|
2479
2465
|
uuid,
|
|
@@ -2487,14 +2473,14 @@ function TrackPositionPlayPause({
|
|
|
2487
2473
|
const isPlaying = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PLAYING;
|
|
2488
2474
|
const isPaused = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PAUSED;
|
|
2489
2475
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
2490
|
-
return /* @__PURE__ */ (0,
|
|
2476
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2491
2477
|
"div",
|
|
2492
2478
|
{
|
|
2493
2479
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
2494
2480
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
2495
2481
|
onClick: handlePlayPauseClick,
|
|
2496
2482
|
children: [
|
|
2497
|
-
/* @__PURE__ */ (0,
|
|
2483
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2498
2484
|
"span",
|
|
2499
2485
|
{
|
|
2500
2486
|
className: "track-position-play-pause__bars",
|
|
@@ -2502,18 +2488,18 @@ function TrackPositionPlayPause({
|
|
|
2502
2488
|
role: "img",
|
|
2503
2489
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
2504
2490
|
children: [
|
|
2505
|
-
/* @__PURE__ */ (0,
|
|
2506
|
-
/* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
2491
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2492
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2493
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__bar" })
|
|
2508
2494
|
]
|
|
2509
2495
|
}
|
|
2510
2496
|
) : position }),
|
|
2511
|
-
/* @__PURE__ */ (0,
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2512
2498
|
"div",
|
|
2513
2499
|
{
|
|
2514
2500
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
2515
2501
|
"aria-hidden": "true",
|
|
2516
|
-
children: isAwaitingPlayback ? /* @__PURE__ */ (0,
|
|
2502
|
+
children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__spinner" }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_fa5.FaPause, {}) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_fa5.FaPlay, {})
|
|
2517
2503
|
}
|
|
2518
2504
|
)
|
|
2519
2505
|
]
|
|
@@ -2524,7 +2510,7 @@ function TrackPositionPlayPause({
|
|
|
2524
2510
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2525
2511
|
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2526
2512
|
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2527
|
-
var
|
|
2513
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2528
2514
|
function TrackItem({
|
|
2529
2515
|
track,
|
|
2530
2516
|
position,
|
|
@@ -2548,12 +2534,12 @@ function TrackItem({
|
|
|
2548
2534
|
loadTrackForPlayer(track.uuid);
|
|
2549
2535
|
}
|
|
2550
2536
|
};
|
|
2551
|
-
return /* @__PURE__ */ (0,
|
|
2537
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2552
2538
|
"div",
|
|
2553
2539
|
{
|
|
2554
2540
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
2555
2541
|
children: [
|
|
2556
|
-
isUnplayable ? /* @__PURE__ */ (0,
|
|
2542
|
+
isUnplayable ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2557
2543
|
"div",
|
|
2558
2544
|
{
|
|
2559
2545
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -2561,7 +2547,7 @@ function TrackItem({
|
|
|
2561
2547
|
"aria-disabled": "true",
|
|
2562
2548
|
children: position
|
|
2563
2549
|
}
|
|
2564
|
-
) : /* @__PURE__ */ (0,
|
|
2550
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2565
2551
|
TrackPositionPlayPause,
|
|
2566
2552
|
{
|
|
2567
2553
|
position,
|
|
@@ -2570,12 +2556,12 @@ function TrackItem({
|
|
|
2570
2556
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
2571
2557
|
}
|
|
2572
2558
|
),
|
|
2573
|
-
/* @__PURE__ */ (0,
|
|
2574
|
-
/* @__PURE__ */ (0,
|
|
2575
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0,
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2560
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime45.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_runtime45.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2561
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_genre_tree25.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2576
2562
|
] }),
|
|
2577
|
-
/* @__PURE__ */ (0,
|
|
2578
|
-
renderDuration && /* @__PURE__ */ (0,
|
|
2563
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.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_runtime45.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2564
|
+
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2579
2565
|
"div",
|
|
2580
2566
|
{
|
|
2581
2567
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -2583,15 +2569,15 @@ function TrackItem({
|
|
|
2583
2569
|
children: renderDuration(track)
|
|
2584
2570
|
}
|
|
2585
2571
|
),
|
|
2586
|
-
renderActions && /* @__PURE__ */ (0,
|
|
2572
|
+
renderActions && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "edit flex text-base w-6 items-center justify-center mr-2 cursor-pointer", children: renderActions(track) })
|
|
2587
2573
|
]
|
|
2588
2574
|
}
|
|
2589
2575
|
);
|
|
2590
2576
|
}
|
|
2591
2577
|
|
|
2592
2578
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2593
|
-
var
|
|
2594
|
-
var SongPageSchema2 = (0,
|
|
2579
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2580
|
+
var SongPageSchema2 = (0, import_transport8.PaginatedResponseSchema)(import_genre_tree26.SongDetailedSchema);
|
|
2595
2581
|
var SORTS = [
|
|
2596
2582
|
{ ordering: "title", label: "Title" },
|
|
2597
2583
|
{ ordering: "-albumYear", label: "Year" }
|
|
@@ -2601,7 +2587,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2601
2587
|
const [ordering, setOrdering] = (0, import_react17.useState)("title");
|
|
2602
2588
|
const { playNewTrackListFromArtist } = (0, import_genre_tree26.useTrackList)();
|
|
2603
2589
|
const { playerTrackObject } = (0, import_player11.usePlayer)();
|
|
2604
|
-
const { data, isPending, isError } = (0,
|
|
2590
|
+
const { data, isPending, isError } = (0, import_transport8.usePlaybackQuery)({
|
|
2605
2591
|
getBackendBaseUrl,
|
|
2606
2592
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
2607
2593
|
queryFn: (fetchBound) => fetchBound(import_genre_tree26.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
@@ -2623,36 +2609,22 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2623
2609
|
event.stopPropagation();
|
|
2624
2610
|
void play(song.uuid);
|
|
2625
2611
|
};
|
|
2626
|
-
return /* @__PURE__ */ (0,
|
|
2627
|
-
/* @__PURE__ */ (0,
|
|
2628
|
-
|
|
2629
|
-
|
|
2630
|
-
|
|
2631
|
-
|
|
2632
|
-
|
|
2633
|
-
|
|
2634
|
-
|
|
2635
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react16.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2636
|
-
"Play all"
|
|
2637
|
-
]
|
|
2638
|
-
}
|
|
2639
|
-
),
|
|
2640
|
-
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2641
|
-
"button",
|
|
2642
|
-
{
|
|
2643
|
-
type: "button",
|
|
2644
|
-
"aria-pressed": ordering === sort.ordering,
|
|
2645
|
-
onClick: () => {
|
|
2646
|
-
setOrdering(sort.ordering);
|
|
2647
|
-
setPage(1);
|
|
2648
|
-
},
|
|
2649
|
-
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",
|
|
2650
|
-
children: sort.label
|
|
2612
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui19.PanelSection, { title: "Songs", children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui19.Skeleton, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
|
|
2613
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-2 mb-2", children: /* @__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)(
|
|
2614
|
+
"button",
|
|
2615
|
+
{
|
|
2616
|
+
type: "button",
|
|
2617
|
+
"aria-pressed": ordering === sort.ordering,
|
|
2618
|
+
onClick: () => {
|
|
2619
|
+
setOrdering(sort.ordering);
|
|
2620
|
+
setPage(1);
|
|
2651
2621
|
},
|
|
2652
|
-
|
|
2653
|
-
|
|
2654
|
-
|
|
2655
|
-
|
|
2622
|
+
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",
|
|
2623
|
+
children: sort.label
|
|
2624
|
+
},
|
|
2625
|
+
sort.ordering
|
|
2626
|
+
)) }) }),
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("ul", { className: "overflow-hidden mb-2 bg-zinc-950 rounded-lg", children: data.results.map((song, index) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("li", { onClickCapture: (event) => handleRowClickCapture(event, song), children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2656
2628
|
TrackItem,
|
|
2657
2629
|
{
|
|
2658
2630
|
track: song,
|
|
@@ -2661,12 +2633,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2661
2633
|
renderSongLink
|
|
2662
2634
|
}
|
|
2663
2635
|
) }, song.uuid)) }),
|
|
2664
|
-
/* @__PURE__ */ (0,
|
|
2636
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui19.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2665
2637
|
] }) });
|
|
2666
2638
|
}
|
|
2667
2639
|
|
|
2668
2640
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2669
|
-
var
|
|
2641
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2670
2642
|
function useArtistPanel({
|
|
2671
2643
|
uuid,
|
|
2672
2644
|
scope,
|
|
@@ -2687,26 +2659,26 @@ function useArtistPanel({
|
|
|
2687
2659
|
return {
|
|
2688
2660
|
...panel,
|
|
2689
2661
|
title: "Artist",
|
|
2690
|
-
content: /* @__PURE__ */ (0,
|
|
2691
|
-
/* @__PURE__ */ (0,
|
|
2692
|
-
/* @__PURE__ */ (0,
|
|
2693
|
-
/* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2696
|
-
/* @__PURE__ */ (0,
|
|
2662
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2663
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-4 w-32" }),
|
|
2665
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2666
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-4 w-24" }),
|
|
2667
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2668
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-16" })
|
|
2697
2669
|
] })
|
|
2698
2670
|
};
|
|
2699
2671
|
case "not-found":
|
|
2700
2672
|
return {
|
|
2701
2673
|
...panel,
|
|
2702
2674
|
title: "Artist not found",
|
|
2703
|
-
content: /* @__PURE__ */ (0,
|
|
2675
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2704
2676
|
};
|
|
2705
2677
|
case "error":
|
|
2706
2678
|
return {
|
|
2707
2679
|
...panel,
|
|
2708
2680
|
title: "Artist",
|
|
2709
|
-
content: /* @__PURE__ */ (0,
|
|
2681
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2710
2682
|
};
|
|
2711
2683
|
case "success": {
|
|
2712
2684
|
const { artist } = result;
|
|
@@ -2715,19 +2687,19 @@ function useArtistPanel({
|
|
|
2715
2687
|
return {
|
|
2716
2688
|
...panel,
|
|
2717
2689
|
title: artist.name,
|
|
2718
|
-
content: /* @__PURE__ */ (0,
|
|
2719
|
-
/* @__PURE__ */ (0,
|
|
2690
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
|
|
2691
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2720
2692
|
ArtistActionBand,
|
|
2721
2693
|
{
|
|
2722
2694
|
artist,
|
|
2723
|
-
share: shareTarget && shareUrl ? /* @__PURE__ */ (0,
|
|
2695
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2724
2696
|
}
|
|
2725
2697
|
),
|
|
2726
|
-
artist.image && /* @__PURE__ */ (0,
|
|
2727
|
-
/* @__PURE__ */ (0,
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
/* @__PURE__ */ (0,
|
|
2730
|
-
artist.tracksCount > 0 && /* @__PURE__ */ (0,
|
|
2698
|
+
artist.image && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2699
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistHeader, { artist }),
|
|
2700
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2701
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2702
|
+
artist.tracksCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2731
2703
|
ArtistSongs,
|
|
2732
2704
|
{
|
|
2733
2705
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2737,7 +2709,7 @@ function useArtistPanel({
|
|
|
2737
2709
|
}
|
|
2738
2710
|
)
|
|
2739
2711
|
] }),
|
|
2740
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0,
|
|
2712
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2741
2713
|
};
|
|
2742
2714
|
}
|
|
2743
2715
|
}
|
|
@@ -2749,11 +2721,11 @@ var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
2749
2721
|
|
|
2750
2722
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2751
2723
|
var import_react18 = require("react");
|
|
2752
|
-
var
|
|
2724
|
+
var import_lucide_react16 = require("lucide-react");
|
|
2753
2725
|
var import_ui21 = require("@behindthemusictree/ui");
|
|
2754
2726
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2755
2727
|
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2756
|
-
var
|
|
2728
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2757
2729
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2758
2730
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2759
2731
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
@@ -2761,27 +2733,27 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2761
2733
|
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2762
2734
|
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2763
2735
|
let body = null;
|
|
2764
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0,
|
|
2765
|
-
else if (history.status === "error") body = /* @__PURE__ */ (0,
|
|
2736
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2737
|
+
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2766
2738
|
else if (history.status === "success")
|
|
2767
|
-
body = history.entries.length === 0 ? /* @__PURE__ */ (0,
|
|
2768
|
-
/* @__PURE__ */ (0,
|
|
2769
|
-
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0,
|
|
2739
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
2740
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2741
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2770
2742
|
" ",
|
|
2771
2743
|
"\u2014 ",
|
|
2772
2744
|
entry.oldValue ?? "none",
|
|
2773
2745
|
" \u2192 ",
|
|
2774
2746
|
entry.newValue ?? "none"
|
|
2775
2747
|
] }) : null,
|
|
2776
|
-
/* @__PURE__ */ (0,
|
|
2748
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2777
2749
|
entry.actorPseudo ?? "Anonymous",
|
|
2778
2750
|
" \xB7 ",
|
|
2779
2751
|
dateFormat.format(new Date(entry.createdOn))
|
|
2780
2752
|
] })
|
|
2781
2753
|
] }, entry.uuid)) });
|
|
2782
|
-
return /* @__PURE__ */ (0,
|
|
2783
|
-
/* @__PURE__ */ (0,
|
|
2784
|
-
/* @__PURE__ */ (0,
|
|
2754
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.PanelBleed, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui21.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2756
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "mt-1.5", children: body })
|
|
2785
2757
|
] }) });
|
|
2786
2758
|
}
|
|
2787
2759
|
function SongPanelContent(props) {
|
|
@@ -2800,13 +2772,13 @@ function SongPanelContent(props) {
|
|
|
2800
2772
|
const genre = song.genre;
|
|
2801
2773
|
fields.push({
|
|
2802
2774
|
label: "Genre",
|
|
2803
|
-
value: onSelectGenre ? /* @__PURE__ */ (0,
|
|
2804
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
2805
|
-
/* @__PURE__ */ (0,
|
|
2775
|
+
value: onSelectGenre ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { children: [
|
|
2776
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2777
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2806
2778
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2807
2779
|
});
|
|
2808
2780
|
} else {
|
|
2809
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */ (0,
|
|
2781
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2810
2782
|
}
|
|
2811
2783
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2812
2784
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2816,11 +2788,11 @@ function SongPanelContent(props) {
|
|
|
2816
2788
|
const links = [];
|
|
2817
2789
|
if (musicBrainzUrl)
|
|
2818
2790
|
links.push(
|
|
2819
|
-
/* @__PURE__ */ (0,
|
|
2791
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2820
2792
|
);
|
|
2821
2793
|
if (song.youtubeVideo)
|
|
2822
2794
|
links.push(
|
|
2823
|
-
/* @__PURE__ */ (0,
|
|
2795
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2824
2796
|
"a",
|
|
2825
2797
|
{
|
|
2826
2798
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2835,31 +2807,31 @@ function SongPanelContent(props) {
|
|
|
2835
2807
|
if (links.length > 0)
|
|
2836
2808
|
fields.push({
|
|
2837
2809
|
label: "Links",
|
|
2838
|
-
value: /* @__PURE__ */ (0,
|
|
2810
|
+
value: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "flex gap-3", children: links })
|
|
2839
2811
|
});
|
|
2840
|
-
return /* @__PURE__ */ (0,
|
|
2841
|
-
/* @__PURE__ */ (0,
|
|
2842
|
-
/* @__PURE__ */ (0,
|
|
2812
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
2813
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_ui21.ActionBand, { children: [
|
|
2814
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2843
2815
|
import_ui21.ActionButton,
|
|
2844
2816
|
{
|
|
2845
|
-
icon: isPlaying ? /* @__PURE__ */ (0,
|
|
2817
|
+
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react16.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react16.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2846
2818
|
label: isPlaying ? "Pause" : "Play",
|
|
2847
2819
|
disabled: !!unplayableReason,
|
|
2848
2820
|
title: unplayableReason ?? void 0,
|
|
2849
2821
|
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2850
2822
|
}
|
|
2851
2823
|
),
|
|
2852
|
-
shareUrl && /* @__PURE__ */ (0,
|
|
2824
|
+
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2853
2825
|
] }) }),
|
|
2854
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0,
|
|
2855
|
-
/* @__PURE__ */ (0,
|
|
2856
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0,
|
|
2857
|
-
/* @__PURE__ */ (0,
|
|
2826
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_genre_tree28.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2827
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.FieldList, { items: fields }),
|
|
2828
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2829
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2858
2830
|
] });
|
|
2859
2831
|
}
|
|
2860
2832
|
|
|
2861
2833
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2862
|
-
var
|
|
2834
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2863
2835
|
function useSongPanel({
|
|
2864
2836
|
uuid,
|
|
2865
2837
|
scope,
|
|
@@ -2880,24 +2852,24 @@ function useSongPanel({
|
|
|
2880
2852
|
return {
|
|
2881
2853
|
...panel,
|
|
2882
2854
|
title: "Song",
|
|
2883
|
-
content: /* @__PURE__ */ (0,
|
|
2884
|
-
/* @__PURE__ */ (0,
|
|
2885
|
-
/* @__PURE__ */ (0,
|
|
2886
|
-
/* @__PURE__ */ (0,
|
|
2887
|
-
/* @__PURE__ */ (0,
|
|
2855
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2856
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2857
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-4 w-32" }),
|
|
2858
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2859
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-4 w-24" })
|
|
2888
2860
|
] })
|
|
2889
2861
|
};
|
|
2890
2862
|
case "not-found":
|
|
2891
2863
|
return {
|
|
2892
2864
|
...panel,
|
|
2893
2865
|
title: "Song not found",
|
|
2894
|
-
content: /* @__PURE__ */ (0,
|
|
2866
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2895
2867
|
};
|
|
2896
2868
|
case "error":
|
|
2897
2869
|
return {
|
|
2898
2870
|
...panel,
|
|
2899
2871
|
title: "Song",
|
|
2900
|
-
content: /* @__PURE__ */ (0,
|
|
2872
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2901
2873
|
};
|
|
2902
2874
|
case "success": {
|
|
2903
2875
|
const { song } = result;
|
|
@@ -2905,7 +2877,7 @@ function useSongPanel({
|
|
|
2905
2877
|
return {
|
|
2906
2878
|
...panel,
|
|
2907
2879
|
title: song.title,
|
|
2908
|
-
content: /* @__PURE__ */ (0,
|
|
2880
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2909
2881
|
SongPanelContent,
|
|
2910
2882
|
{
|
|
2911
2883
|
song,
|
|
@@ -2958,12 +2930,12 @@ function useEntityPanel({
|
|
|
2958
2930
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2959
2931
|
var import_md2 = require("react-icons/md");
|
|
2960
2932
|
var import_ui23 = require("@behindthemusictree/ui");
|
|
2961
|
-
var
|
|
2933
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2962
2934
|
function SizeMetricToggle({
|
|
2963
2935
|
value,
|
|
2964
2936
|
onChange
|
|
2965
2937
|
}) {
|
|
2966
|
-
return /* @__PURE__ */ (0,
|
|
2938
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2967
2939
|
import_ui23.SegmentedControl,
|
|
2968
2940
|
{
|
|
2969
2941
|
variant: "floating",
|
|
@@ -2971,15 +2943,15 @@ function SizeMetricToggle({
|
|
|
2971
2943
|
value,
|
|
2972
2944
|
onChange,
|
|
2973
2945
|
options: [
|
|
2974
|
-
{ value: "songs", label: /* @__PURE__ */ (0,
|
|
2975
|
-
{ value: "views", label: /* @__PURE__ */ (0,
|
|
2946
|
+
{ value: "songs", label: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_md2.MdMusicNote, { size: 18, "aria-hidden": true }), "aria-label": "Size by songs", title: "Node size by song count" },
|
|
2947
|
+
{ value: "views", label: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_md2.MdVisibility, { size: 18, "aria-hidden": true }), "aria-label": "Size by views", title: "Node size by song views" }
|
|
2976
2948
|
]
|
|
2977
2949
|
}
|
|
2978
2950
|
);
|
|
2979
2951
|
}
|
|
2980
2952
|
|
|
2981
2953
|
// src/genre-tree/GenreTreeView.tsx
|
|
2982
|
-
var
|
|
2954
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2983
2955
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2984
2956
|
var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
|
|
2985
2957
|
var noop = () => {
|
|
@@ -3071,6 +3043,7 @@ function GenreTreeView({
|
|
|
3071
3043
|
isFetching: isTreeFetching,
|
|
3072
3044
|
genrePlaylistByNodeId,
|
|
3073
3045
|
visibleGenrePlaylists,
|
|
3046
|
+
focusUuids,
|
|
3074
3047
|
groupedGenrePlaylistsByRoot,
|
|
3075
3048
|
selectedGenreUuid,
|
|
3076
3049
|
selectGenre,
|
|
@@ -3130,14 +3103,14 @@ function GenreTreeView({
|
|
|
3130
3103
|
const openSongRef = (0, import_react19.useRef)(openSong);
|
|
3131
3104
|
openSongRef.current = openSong;
|
|
3132
3105
|
const resolvedRenderSongLink = (0, import_react19.useCallback)(
|
|
3133
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0,
|
|
3106
|
+
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
|
|
3134
3107
|
[renderSongLink]
|
|
3135
3108
|
);
|
|
3136
3109
|
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react19.useState)(null);
|
|
3137
3110
|
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react19.useState)(null);
|
|
3138
3111
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
3139
3112
|
const songBaseUrl = getBackendBaseUrl;
|
|
3140
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
3113
|
+
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
3141
3114
|
const getGenrePath = (genre) => {
|
|
3142
3115
|
const path = [];
|
|
3143
3116
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -3179,7 +3152,7 @@ function GenreTreeView({
|
|
|
3179
3152
|
selectGenrePlaylist(genrePlaylist2);
|
|
3180
3153
|
}
|
|
3181
3154
|
});
|
|
3182
|
-
const
|
|
3155
|
+
const otherPanel = overlayPanel ?? (selectedGenreUuid !== null ? void 0 : entityPanel);
|
|
3183
3156
|
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react19.useState)(false);
|
|
3184
3157
|
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react19.useState)(false);
|
|
3185
3158
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
@@ -3207,18 +3180,19 @@ function GenreTreeView({
|
|
|
3207
3180
|
const obscuredInset = (0, import_ui24.useObscuredInset)(panelRef);
|
|
3208
3181
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
3209
3182
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
3210
|
-
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric), [visibleGenrePlaylists, nodeMetric]);
|
|
3183
|
+
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric, focusUuids), [visibleGenrePlaylists, nodeMetric, focusUuids]);
|
|
3211
3184
|
const relations = (0, import_genre_tree_view5.useGenreNodeRelations)(
|
|
3212
3185
|
treeNodes,
|
|
3213
3186
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
3214
3187
|
resolveStyle
|
|
3215
3188
|
);
|
|
3189
|
+
const treeStyles = (0, import_react19.useMemo)(() => toGenreNodeStyles(relations, visibleGenrePlaylists), [relations, visibleGenrePlaylists]);
|
|
3216
3190
|
const [selectionHistory, setSelectionHistory] = (0, import_react19.useState)({ current: selectedGenreUuid, previous: null });
|
|
3217
3191
|
if (selectionHistory.current !== selectedGenreUuid) {
|
|
3218
3192
|
setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
3219
3193
|
}
|
|
3220
3194
|
const handlePrevious = selectionHistory.previous ? () => selectGenre(selectionHistory.previous) : void 0;
|
|
3221
|
-
const { showPopup, hidePopup } = (0,
|
|
3195
|
+
const { showPopup, hidePopup } = (0, import_popup5.usePopup)();
|
|
3222
3196
|
const reopenPanel = () => {
|
|
3223
3197
|
setUncontrolledCollapsed(false);
|
|
3224
3198
|
onCollapsedChange?.(false);
|
|
@@ -3258,7 +3232,7 @@ function GenreTreeView({
|
|
|
3258
3232
|
selectGenre(uuid);
|
|
3259
3233
|
},
|
|
3260
3234
|
expanded: isExpanded,
|
|
3261
|
-
|
|
3235
|
+
treeStyles,
|
|
3262
3236
|
playback,
|
|
3263
3237
|
genrePlaylist: selectedGenrePlaylist,
|
|
3264
3238
|
band: {
|
|
@@ -3269,7 +3243,7 @@ function GenreTreeView({
|
|
|
3269
3243
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
3270
3244
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
3271
3245
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
3272
|
-
/* @__PURE__ */ (0,
|
|
3246
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3273
3247
|
ChangeParentPopup,
|
|
3274
3248
|
{
|
|
3275
3249
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -3303,15 +3277,15 @@ function GenreTreeView({
|
|
|
3303
3277
|
const isRotationControlled = controlledAllowWheelRotation !== void 0;
|
|
3304
3278
|
const allowWheelRotation = controlledAllowWheelRotation ?? internalAllowWheelRotation;
|
|
3305
3279
|
let activePanel = null;
|
|
3306
|
-
if (
|
|
3280
|
+
if (otherPanel) {
|
|
3307
3281
|
activePanel = {
|
|
3308
|
-
title:
|
|
3309
|
-
content:
|
|
3310
|
-
aside:
|
|
3311
|
-
expanded:
|
|
3312
|
-
onExpandedChange:
|
|
3313
|
-
onClose:
|
|
3314
|
-
|
|
3282
|
+
title: otherPanel.title,
|
|
3283
|
+
content: otherPanel.content,
|
|
3284
|
+
aside: otherPanel.extraContent,
|
|
3285
|
+
expanded: otherPanel.expanded ?? false,
|
|
3286
|
+
onExpandedChange: otherPanel.onExpandedChange,
|
|
3287
|
+
onClose: otherPanel.onClose,
|
|
3288
|
+
searchName: otherPanel.title
|
|
3315
3289
|
};
|
|
3316
3290
|
} else if (selectedGenreUuid) {
|
|
3317
3291
|
activePanel = {
|
|
@@ -3321,38 +3295,28 @@ function GenreTreeView({
|
|
|
3321
3295
|
expanded: isExpanded,
|
|
3322
3296
|
onExpandedChange: changeExpanded,
|
|
3323
3297
|
onClose: clearSelection,
|
|
3324
|
-
|
|
3298
|
+
searchName: genreContent.name,
|
|
3325
3299
|
headerAccent: genreContent.headerAccent
|
|
3326
3300
|
};
|
|
3327
|
-
} else if (builtInPanel) {
|
|
3328
|
-
activePanel = {
|
|
3329
|
-
title: builtInPanel.title,
|
|
3330
|
-
content: builtInPanel.content,
|
|
3331
|
-
aside: builtInPanel.extraContent,
|
|
3332
|
-
expanded: builtInPanel.expanded,
|
|
3333
|
-
onExpandedChange: builtInPanel.onExpandedChange,
|
|
3334
|
-
onClose: builtInPanel.onClose,
|
|
3335
|
-
titleInSearch: true
|
|
3336
|
-
};
|
|
3337
3301
|
}
|
|
3338
3302
|
const isPanelShown = activePanel !== null && (selectedGenreUuid !== null || isTreeReady);
|
|
3339
3303
|
const detailTab = placement === "regions" && activePanel?.onExpandedChange ? {
|
|
3340
3304
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
3341
3305
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
3342
3306
|
} : void 0;
|
|
3343
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0,
|
|
3307
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3344
3308
|
import_ui24.IconButton,
|
|
3345
3309
|
{
|
|
3346
3310
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
3347
3311
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
3348
3312
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
3349
|
-
children: activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3313
|
+
children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react18.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react18.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3350
3314
|
}
|
|
3351
3315
|
) : null;
|
|
3352
3316
|
const renderArtistFilter = () => {
|
|
3353
3317
|
if (isLoading || !filterArtist) return null;
|
|
3354
|
-
return /* @__PURE__ */ (0,
|
|
3355
|
-
/* @__PURE__ */ (0,
|
|
3318
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
3319
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3356
3320
|
"button",
|
|
3357
3321
|
{
|
|
3358
3322
|
type: "button",
|
|
@@ -3364,7 +3328,7 @@ function GenreTreeView({
|
|
|
3364
3328
|
children: filterArtist.name
|
|
3365
3329
|
}
|
|
3366
3330
|
),
|
|
3367
|
-
/* @__PURE__ */ (0,
|
|
3331
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3368
3332
|
"button",
|
|
3369
3333
|
{
|
|
3370
3334
|
type: "button",
|
|
@@ -3376,8 +3340,8 @@ function GenreTreeView({
|
|
|
3376
3340
|
)
|
|
3377
3341
|
] });
|
|
3378
3342
|
};
|
|
3379
|
-
const actions = /* @__PURE__ */ (0,
|
|
3380
|
-
!isLoading && !isError && /* @__PURE__ */ (0,
|
|
3343
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
3344
|
+
!isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3381
3345
|
GenreTreeSearch,
|
|
3382
3346
|
{
|
|
3383
3347
|
artistBaseUrl,
|
|
@@ -3400,9 +3364,9 @@ function GenreTreeView({
|
|
|
3400
3364
|
if (songUuid) changeSong(null);
|
|
3401
3365
|
selectGenre(uuid);
|
|
3402
3366
|
},
|
|
3403
|
-
selectedName:
|
|
3367
|
+
selectedName: activePanel?.searchName ?? null,
|
|
3404
3368
|
onClear: activePanel?.onClose,
|
|
3405
|
-
showClear: activePanel
|
|
3369
|
+
showClear: activePanel !== null,
|
|
3406
3370
|
clearLabel: "Close panel",
|
|
3407
3371
|
onPrevious: handlePrevious,
|
|
3408
3372
|
onQueryChange: onSearchQueryChange,
|
|
@@ -3410,9 +3374,9 @@ function GenreTreeView({
|
|
|
3410
3374
|
extraGroups: extraSearchGroups
|
|
3411
3375
|
}
|
|
3412
3376
|
),
|
|
3413
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3414
|
-
/* @__PURE__ */ (0,
|
|
3415
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0,
|
|
3377
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3378
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.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: [
|
|
3379
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3416
3380
|
import_ui24.SegmentedControl,
|
|
3417
3381
|
{
|
|
3418
3382
|
"aria-label": "Tree view mode",
|
|
@@ -3426,13 +3390,13 @@ function GenreTreeView({
|
|
|
3426
3390
|
]
|
|
3427
3391
|
}
|
|
3428
3392
|
),
|
|
3429
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0,
|
|
3393
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3430
3394
|
"div",
|
|
3431
3395
|
{
|
|
3432
3396
|
className: "flex items-center gap-1",
|
|
3433
3397
|
role: "group",
|
|
3434
3398
|
"aria-label": "Tree display options",
|
|
3435
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0,
|
|
3399
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3436
3400
|
import_ui24.Button,
|
|
3437
3401
|
{
|
|
3438
3402
|
variant: allowWheelRotation ? "default" : "outline",
|
|
@@ -3443,52 +3407,53 @@ function GenreTreeView({
|
|
|
3443
3407
|
)
|
|
3444
3408
|
}
|
|
3445
3409
|
),
|
|
3446
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0,
|
|
3410
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3447
3411
|
import_ui24.IconTextButton,
|
|
3448
3412
|
{
|
|
3449
|
-
icon:
|
|
3413
|
+
icon: import_lucide_react17.Plus,
|
|
3450
3414
|
text: "Add root",
|
|
3451
3415
|
onClick: () => handleGenreCreationAction(null)
|
|
3452
3416
|
}
|
|
3453
3417
|
)
|
|
3454
3418
|
] })
|
|
3455
3419
|
] });
|
|
3456
|
-
return /* @__PURE__ */ (0,
|
|
3420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
3457
3421
|
"div",
|
|
3458
3422
|
{
|
|
3459
3423
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
3460
3424
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
3461
3425
|
children: [
|
|
3462
|
-
/* @__PURE__ */ (0,
|
|
3426
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3463
3427
|
"div",
|
|
3464
3428
|
{
|
|
3465
3429
|
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"}`,
|
|
3466
3430
|
children: actions
|
|
3467
3431
|
}
|
|
3468
3432
|
),
|
|
3469
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3433
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3470
3434
|
"div",
|
|
3471
3435
|
{
|
|
3472
3436
|
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"}`,
|
|
3473
3437
|
children: renderArtistFilter()
|
|
3474
3438
|
}
|
|
3475
3439
|
),
|
|
3476
|
-
/* @__PURE__ */ (0,
|
|
3477
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0,
|
|
3478
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
3441
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
3442
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
|
|
3479
3443
|
"Couldn't load the genre tree.",
|
|
3480
3444
|
" ",
|
|
3481
|
-
/* @__PURE__ */ (0,
|
|
3445
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
3482
3446
|
] }) : viewMode === "wheel" ? (
|
|
3483
3447
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
3484
3448
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
3485
3449
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
3486
3450
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
3487
|
-
/* @__PURE__ */ (0,
|
|
3451
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3488
3452
|
GenrePlaylistTreeWheel,
|
|
3489
3453
|
{
|
|
3490
3454
|
scope,
|
|
3491
3455
|
genrePlaylists: visibleGenrePlaylists,
|
|
3456
|
+
focusUuids,
|
|
3492
3457
|
handleGenreCreationAction,
|
|
3493
3458
|
handleGenreRenameAction,
|
|
3494
3459
|
additionalActions,
|
|
@@ -3501,9 +3466,9 @@ function GenreTreeView({
|
|
|
3501
3466
|
allowWheelRotation,
|
|
3502
3467
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3503
3468
|
busy,
|
|
3504
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3469
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3505
3470
|
floatingControlsLeading,
|
|
3506
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3471
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3507
3472
|
] }) : void 0,
|
|
3508
3473
|
defaultViewport,
|
|
3509
3474
|
viewportRestore,
|
|
@@ -3512,11 +3477,12 @@ function GenreTreeView({
|
|
|
3512
3477
|
) }) })
|
|
3513
3478
|
) : viewMode === "pop-core" ? (
|
|
3514
3479
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
3515
|
-
/* @__PURE__ */ (0,
|
|
3480
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3516
3481
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3517
3482
|
{
|
|
3518
3483
|
scope,
|
|
3519
3484
|
genrePlaylists: visibleGenrePlaylists,
|
|
3485
|
+
focusUuids,
|
|
3520
3486
|
handleGenreCreationAction,
|
|
3521
3487
|
handleGenreRenameAction,
|
|
3522
3488
|
additionalActions,
|
|
@@ -3529,9 +3495,9 @@ function GenreTreeView({
|
|
|
3529
3495
|
allowWheelRotation,
|
|
3530
3496
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3531
3497
|
busy,
|
|
3532
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3498
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3533
3499
|
floatingControlsLeading,
|
|
3534
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3500
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3535
3501
|
] }) : void 0,
|
|
3536
3502
|
defaultViewport,
|
|
3537
3503
|
viewportRestore,
|
|
@@ -3539,12 +3505,13 @@ function GenreTreeView({
|
|
|
3539
3505
|
...focus
|
|
3540
3506
|
}
|
|
3541
3507
|
) }) })
|
|
3542
|
-
) : viewMode === "outline" ? /* @__PURE__ */ (0,
|
|
3508
|
+
) : viewMode === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "tree-container flex-1 min-h-0 w-full overflow-y-auto relative", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3543
3509
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3544
3510
|
{
|
|
3545
3511
|
outline: true,
|
|
3546
3512
|
scope,
|
|
3547
3513
|
genrePlaylists: visibleGenrePlaylists,
|
|
3514
|
+
focusUuids,
|
|
3548
3515
|
handleGenreCreationAction,
|
|
3549
3516
|
handleGenreRenameAction,
|
|
3550
3517
|
additionalActions,
|
|
@@ -3555,13 +3522,13 @@ function GenreTreeView({
|
|
|
3555
3522
|
selectedNodeId,
|
|
3556
3523
|
readOnly
|
|
3557
3524
|
}
|
|
3558
|
-
) }) : /* @__PURE__ */ (0,
|
|
3525
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime51.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(
|
|
3559
3526
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
3560
|
-
return /* @__PURE__ */ (0,
|
|
3527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3561
3528
|
"div",
|
|
3562
3529
|
{
|
|
3563
3530
|
className: "tree-per-root-container relative shrink-0 h-[28rem] mt-2 mr-16 p-2 bg-[var(--color-neutral-100)] rounded-lg",
|
|
3564
|
-
children: /* @__PURE__ */ (0,
|
|
3531
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3565
3532
|
GenrePlaylistTreePerRoot,
|
|
3566
3533
|
{
|
|
3567
3534
|
scope,
|
|
@@ -3574,6 +3541,7 @@ function GenreTreeView({
|
|
|
3574
3541
|
onNodeHover: handleNodeHover,
|
|
3575
3542
|
...hostPanel,
|
|
3576
3543
|
playback,
|
|
3544
|
+
focusUuids,
|
|
3577
3545
|
selectedNodeId: uuid === selectedGenrePlaylist?.root.uuid ? selectedNodeId : null,
|
|
3578
3546
|
readOnly,
|
|
3579
3547
|
wheelZoom: "modifier",
|
|
@@ -3587,13 +3555,13 @@ function GenreTreeView({
|
|
|
3587
3555
|
);
|
|
3588
3556
|
}
|
|
3589
3557
|
) }),
|
|
3590
|
-
/* @__PURE__ */ (0,
|
|
3558
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3591
3559
|
import_ui24.DetailPanel,
|
|
3592
3560
|
{
|
|
3593
3561
|
ref: panelRef,
|
|
3594
3562
|
side: "left",
|
|
3595
3563
|
title: activePanel?.title ?? "",
|
|
3596
|
-
titleInSearch:
|
|
3564
|
+
titleInSearch: !isLoading && !isError,
|
|
3597
3565
|
headerAccent: activePanel?.headerAccent,
|
|
3598
3566
|
headerActions: expandButton,
|
|
3599
3567
|
onClose: activePanel?.onClose ?? noop,
|
|
@@ -3602,8 +3570,7 @@ function GenreTreeView({
|
|
|
3602
3570
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3603
3571
|
aside: activePanel?.aside,
|
|
3604
3572
|
edgeTab: detailTab,
|
|
3605
|
-
|
|
3606
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
3573
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
3607
3574
|
activePanel.content,
|
|
3608
3575
|
activePanel.aside
|
|
3609
3576
|
] }) : activePanel?.content
|
|
@@ -3620,11 +3587,11 @@ var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
|
3620
3587
|
|
|
3621
3588
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3622
3589
|
var import_react20 = require("react");
|
|
3623
|
-
var
|
|
3590
|
+
var import_lucide_react19 = require("lucide-react");
|
|
3624
3591
|
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3625
3592
|
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3626
3593
|
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
3627
|
-
var
|
|
3594
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3628
3595
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react20.useEffect : import_react20.useLayoutEffect;
|
|
3629
3596
|
function TrackListSidebar({
|
|
3630
3597
|
className: className2 = "",
|
|
@@ -3726,25 +3693,25 @@ function TrackListSidebar({
|
|
|
3726
3693
|
}
|
|
3727
3694
|
};
|
|
3728
3695
|
const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
|
|
3729
|
-
return trackList ? /* @__PURE__ */ (0,
|
|
3696
|
+
return trackList ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3730
3697
|
"div",
|
|
3731
3698
|
{
|
|
3732
3699
|
"data-theme": "dark",
|
|
3733
3700
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3734
3701
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3735
3702
|
children: [
|
|
3736
|
-
/* @__PURE__ */ (0,
|
|
3737
|
-
/* @__PURE__ */ (0,
|
|
3738
|
-
/* @__PURE__ */ (0,
|
|
3739
|
-
/* @__PURE__ */ (0,
|
|
3740
|
-
/* @__PURE__ */ (0,
|
|
3703
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3704
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3705
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "origin flex text-xl", children: [
|
|
3706
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3707
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.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_runtime52.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3741
3708
|
] }),
|
|
3742
|
-
/* @__PURE__ */ (0,
|
|
3709
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3743
3710
|
trackList.origin.type === import_genre_tree32.TrackListOriginType.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === import_genre_tree32.TrackListOriginType.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
|
|
3744
3711
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3745
3712
|
] })
|
|
3746
3713
|
] }),
|
|
3747
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0,
|
|
3714
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3748
3715
|
"button",
|
|
3749
3716
|
{
|
|
3750
3717
|
type: "button",
|
|
@@ -3753,11 +3720,11 @@ function TrackListSidebar({
|
|
|
3753
3720
|
"aria-expanded": !isCollapsed,
|
|
3754
3721
|
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"}`,
|
|
3755
3722
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3756
|
-
children: /* @__PURE__ */ (0,
|
|
3723
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react19.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3757
3724
|
}
|
|
3758
3725
|
)
|
|
3759
3726
|
] }),
|
|
3760
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
3727
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3761
3728
|
"ul",
|
|
3762
3729
|
{
|
|
3763
3730
|
ref: trackListRef,
|
|
@@ -3767,7 +3734,7 @@ function TrackListSidebar({
|
|
|
3767
3734
|
onPointerDown: markUserScrollIntent,
|
|
3768
3735
|
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",
|
|
3769
3736
|
children: [
|
|
3770
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */ (0,
|
|
3737
|
+
trackList.tracks.map((track, index) => /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("li", { "data-track-uuid": track.uuid, children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3771
3738
|
TrackItem,
|
|
3772
3739
|
{
|
|
3773
3740
|
track,
|
|
@@ -3778,7 +3745,7 @@ function TrackListSidebar({
|
|
|
3778
3745
|
renderSongLink
|
|
3779
3746
|
}
|
|
3780
3747
|
) }, track.uuid)),
|
|
3781
|
-
hasMore && /* @__PURE__ */ (0,
|
|
3748
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3782
3749
|
]
|
|
3783
3750
|
}
|
|
3784
3751
|
)
|
|
@@ -3795,10 +3762,10 @@ var import_genre_tree34 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
3795
3762
|
var import_ui25 = require("@behindthemusictree/ui");
|
|
3796
3763
|
|
|
3797
3764
|
// src/genre-tree/PlayerControls.tsx
|
|
3798
|
-
var
|
|
3765
|
+
var import_lucide_react20 = require("lucide-react");
|
|
3799
3766
|
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3800
3767
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3801
|
-
var
|
|
3768
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3802
3769
|
function PlayerControls() {
|
|
3803
3770
|
const {
|
|
3804
3771
|
duration,
|
|
@@ -3817,15 +3784,15 @@ function PlayerControls() {
|
|
|
3817
3784
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3818
3785
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3819
3786
|
const isPlaying = playState === import_player13.PlayStates.PLAYING;
|
|
3820
|
-
return /* @__PURE__ */ (0,
|
|
3787
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3821
3788
|
"section",
|
|
3822
3789
|
{
|
|
3823
3790
|
"aria-label": "Player controls",
|
|
3824
3791
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3825
3792
|
children: [
|
|
3826
|
-
/* @__PURE__ */ (0,
|
|
3827
|
-
/* @__PURE__ */ (0,
|
|
3828
|
-
/* @__PURE__ */ (0,
|
|
3793
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3794
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree33.formatTime)(safeCurrentTime) }),
|
|
3795
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3829
3796
|
"input",
|
|
3830
3797
|
{
|
|
3831
3798
|
"aria-label": "Seek",
|
|
@@ -3839,11 +3806,11 @@ function PlayerControls() {
|
|
|
3839
3806
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3840
3807
|
}
|
|
3841
3808
|
),
|
|
3842
|
-
/* @__PURE__ */ (0,
|
|
3809
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree33.formatTime)(safeDuration) })
|
|
3843
3810
|
] }),
|
|
3844
|
-
/* @__PURE__ */ (0,
|
|
3845
|
-
/* @__PURE__ */ (0,
|
|
3846
|
-
/* @__PURE__ */ (0,
|
|
3811
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3812
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3813
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3847
3814
|
"button",
|
|
3848
3815
|
{
|
|
3849
3816
|
type: "button",
|
|
@@ -3852,10 +3819,10 @@ function PlayerControls() {
|
|
|
3852
3819
|
disabled: !isReady || !hasPreviousTrack,
|
|
3853
3820
|
onClick: playPreviousTrack,
|
|
3854
3821
|
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",
|
|
3855
|
-
children: /* @__PURE__ */ (0,
|
|
3822
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react20.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3856
3823
|
}
|
|
3857
3824
|
),
|
|
3858
|
-
/* @__PURE__ */ (0,
|
|
3825
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3859
3826
|
"button",
|
|
3860
3827
|
{
|
|
3861
3828
|
type: "button",
|
|
@@ -3864,10 +3831,10 @@ function PlayerControls() {
|
|
|
3864
3831
|
disabled: !isReady,
|
|
3865
3832
|
onClick: handlePlayPauseAction,
|
|
3866
3833
|
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",
|
|
3867
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3834
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react20.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react20.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3868
3835
|
}
|
|
3869
3836
|
),
|
|
3870
|
-
/* @__PURE__ */ (0,
|
|
3837
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3871
3838
|
"button",
|
|
3872
3839
|
{
|
|
3873
3840
|
type: "button",
|
|
@@ -3876,14 +3843,14 @@ function PlayerControls() {
|
|
|
3876
3843
|
disabled: !isReady || !hasNextTrack,
|
|
3877
3844
|
onClick: playNextTrack,
|
|
3878
3845
|
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",
|
|
3879
|
-
children: /* @__PURE__ */ (0,
|
|
3846
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react20.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3880
3847
|
}
|
|
3881
3848
|
)
|
|
3882
3849
|
] }),
|
|
3883
|
-
/* @__PURE__ */ (0,
|
|
3884
|
-
volume === 0 ? /* @__PURE__ */ (0,
|
|
3885
|
-
/* @__PURE__ */ (0,
|
|
3886
|
-
/* @__PURE__ */ (0,
|
|
3850
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.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: [
|
|
3851
|
+
volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react20.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react20.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3852
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "sr-only", children: "Volume" }),
|
|
3853
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3887
3854
|
"input",
|
|
3888
3855
|
{
|
|
3889
3856
|
"aria-label": "Volume",
|
|
@@ -3905,7 +3872,7 @@ function PlayerControls() {
|
|
|
3905
3872
|
}
|
|
3906
3873
|
|
|
3907
3874
|
// src/genre-tree/PlayerPanel.tsx
|
|
3908
|
-
var
|
|
3875
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
3909
3876
|
var PANEL_ID = "player-panel";
|
|
3910
3877
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3911
3878
|
function PlayerPanel({
|
|
@@ -3945,7 +3912,7 @@ function PlayerPanel({
|
|
|
3945
3912
|
onClick: () => setIsExtendRequested(true),
|
|
3946
3913
|
expanded: false
|
|
3947
3914
|
} : null;
|
|
3948
|
-
return /* @__PURE__ */ (0,
|
|
3915
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3949
3916
|
"div",
|
|
3950
3917
|
{
|
|
3951
3918
|
id: PANEL_ID,
|
|
@@ -3958,7 +3925,7 @@ function PlayerPanel({
|
|
|
3958
3925
|
),
|
|
3959
3926
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3960
3927
|
children: [
|
|
3961
|
-
/* @__PURE__ */ (0,
|
|
3928
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3962
3929
|
import_ui25.PanelEdgeTab,
|
|
3963
3930
|
{
|
|
3964
3931
|
side: "right",
|
|
@@ -3968,7 +3935,7 @@ function PlayerPanel({
|
|
|
3968
3935
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3969
3936
|
}
|
|
3970
3937
|
),
|
|
3971
|
-
/* @__PURE__ */ (0,
|
|
3938
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3972
3939
|
"div",
|
|
3973
3940
|
{
|
|
3974
3941
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -3976,20 +3943,20 @@ function PlayerPanel({
|
|
|
3976
3943
|
isExtended ? "flex-row" : "flex-col"
|
|
3977
3944
|
),
|
|
3978
3945
|
children: [
|
|
3979
|
-
/* @__PURE__ */ (0,
|
|
3980
|
-
/* @__PURE__ */ (0,
|
|
3981
|
-
/* @__PURE__ */ (0,
|
|
3982
|
-
/* @__PURE__ */ (0,
|
|
3983
|
-
playerTrackObject?.loadError && /* @__PURE__ */ (0,
|
|
3946
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3947
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
|
|
3948
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
3949
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3950
|
+
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3984
3951
|
playerTrackObject.loadError,
|
|
3985
|
-
/* @__PURE__ */ (0,
|
|
3952
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3986
3953
|
void retryPlayback();
|
|
3987
3954
|
}, children: "Retry" })
|
|
3988
3955
|
] })
|
|
3989
3956
|
] }),
|
|
3990
|
-
/* @__PURE__ */ (0,
|
|
3957
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(PlayerControls, {})
|
|
3991
3958
|
] }),
|
|
3992
|
-
/* @__PURE__ */ (0,
|
|
3959
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3993
3960
|
TrackListSidebar,
|
|
3994
3961
|
{
|
|
3995
3962
|
layout: "inline",
|
|
@@ -4016,11 +3983,11 @@ function PlayerPanel({
|
|
|
4016
3983
|
var import_uuid = require("uuid");
|
|
4017
3984
|
var import_ai = require("react-icons/ai");
|
|
4018
3985
|
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
4019
|
-
var
|
|
3986
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4020
3987
|
function Rating({ rating, handleChange }) {
|
|
4021
3988
|
const instanceId = (0, import_uuid.v4)();
|
|
4022
|
-
return /* @__PURE__ */ (0,
|
|
4023
|
-
/* @__PURE__ */ (0,
|
|
3989
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
|
|
3990
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4024
3991
|
"input",
|
|
4025
3992
|
{
|
|
4026
3993
|
id: `star-${instanceId}-${i}`,
|
|
@@ -4032,16 +3999,16 @@ function Rating({ rating, handleChange }) {
|
|
|
4032
3999
|
onChange: handleChange
|
|
4033
4000
|
}
|
|
4034
4001
|
),
|
|
4035
|
-
/* @__PURE__ */ (0,
|
|
4036
|
-
/* @__PURE__ */ (0,
|
|
4002
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex", children: [
|
|
4003
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4037
4004
|
import_ai.AiOutlineStar,
|
|
4038
4005
|
{
|
|
4039
4006
|
className: `w-7 h-7 absolute top-0 left-0 ${rating === import_genre_tree35.FORM_RATING_NULL_VALUE ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
4040
4007
|
}
|
|
4041
4008
|
),
|
|
4042
|
-
/* @__PURE__ */ (0,
|
|
4009
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "flex-grow w-8" }),
|
|
4043
4010
|
" "
|
|
4044
|
-
] }) : /* @__PURE__ */ (0,
|
|
4011
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4045
4012
|
import_ai.AiFillStar,
|
|
4046
4013
|
{
|
|
4047
4014
|
className: `w-7 h-7 absolute top-0 left-0 ${(rating ?? -1) >= i ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
@@ -4053,7 +4020,7 @@ function Rating({ rating, handleChange }) {
|
|
|
4053
4020
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
4054
4021
|
var import_react22 = require("react");
|
|
4055
4022
|
var import_ui26 = require("@behindthemusictree/ui");
|
|
4056
|
-
var
|
|
4023
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
4057
4024
|
function EntityDetailPanel({
|
|
4058
4025
|
scope,
|
|
4059
4026
|
getBackendBaseUrl,
|
|
@@ -4076,8 +4043,8 @@ function EntityDetailPanel({
|
|
|
4076
4043
|
getBackendBaseUrl,
|
|
4077
4044
|
getArtistBackendBaseUrl,
|
|
4078
4045
|
getShareUrl,
|
|
4079
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
4080
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0,
|
|
4046
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
4047
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
4081
4048
|
song: {
|
|
4082
4049
|
uuid: songUuid,
|
|
4083
4050
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -4093,7 +4060,7 @@ function EntityDetailPanel({
|
|
|
4093
4060
|
...navigation
|
|
4094
4061
|
});
|
|
4095
4062
|
if (!panel) return null;
|
|
4096
|
-
return /* @__PURE__ */ (0,
|
|
4063
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4097
4064
|
import_ui26.DetailPanel,
|
|
4098
4065
|
{
|
|
4099
4066
|
side: "left",
|
|
@@ -4105,7 +4072,7 @@ function EntityDetailPanel({
|
|
|
4105
4072
|
onExpandedChange: panel.onExpandedChange,
|
|
4106
4073
|
aside: panel.extraContent,
|
|
4107
4074
|
edgeTab,
|
|
4108
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0,
|
|
4075
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
4109
4076
|
panel.content,
|
|
4110
4077
|
panel.extraContent
|
|
4111
4078
|
] }) : panel.content
|