@behindthemusictree/app-kit-ui 39.0.0 → 40.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-2K2SQOUJ.js → chunk-I2TEOHVG.js} +345 -371
- package/dist/chunk-I2TEOHVG.js.map +1 -0
- package/dist/genre-tree/index.cjs +426 -453
- 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 +421 -448
- 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
|
@@ -596,7 +596,7 @@ 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,7 +621,8 @@ 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
|
|
|
@@ -630,18 +631,20 @@ var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
630
631
|
var import_react4 = require("react");
|
|
631
632
|
var import_genre_tree_view = require("@behindthemusictree/genre-tree-view");
|
|
632
633
|
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
634
|
|
|
636
|
-
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.
|
|
635
|
+
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.tsx
|
|
637
636
|
var import_react3 = require("react");
|
|
638
637
|
var import_genre_tree2 = require("@behindthemusictree/app-kit/genre-tree");
|
|
638
|
+
var import_popup2 = require("@behindthemusictree/app-kit/popup");
|
|
639
|
+
var import_transport3 = require("@behindthemusictree/app-kit/transport");
|
|
640
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
639
641
|
function useGenrePlaylistPlayback({
|
|
640
642
|
scope,
|
|
641
643
|
genrePlaylists,
|
|
642
644
|
artist = null
|
|
643
645
|
}) {
|
|
644
646
|
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
647
|
+
const { showPopup } = (0, import_popup2.usePopup)();
|
|
645
648
|
const origin = trackList?.origin;
|
|
646
649
|
const playing = (0, import_react3.useMemo)(() => {
|
|
647
650
|
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
@@ -653,14 +656,20 @@ function useGenrePlaylistPlayback({
|
|
|
653
656
|
}, [origin, artist, genrePlaylists, scope]);
|
|
654
657
|
const play = (0, import_react3.useCallback)(async (playlist, requested) => {
|
|
655
658
|
if (artist && !playlist.criteria) return;
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
+
try {
|
|
660
|
+
const selection = scope === "reference" && playlist.criteria !== null ? requested ?? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
661
|
+
await (selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope));
|
|
662
|
+
} catch (error) {
|
|
663
|
+
console.error("Failed to load genre playlist tracks:", error);
|
|
664
|
+
if (error instanceof import_genre_tree2.TracksFailureAlreadyReportedError) return;
|
|
665
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime12.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport3.AppError ? error.code : import_transport3.ErrorCode.CLIENT_UNKNOWN }));
|
|
666
|
+
}
|
|
667
|
+
}, [artist, scope, playNewTrackListFromGenrePlaylist, showPopup]);
|
|
659
668
|
return (0, import_react3.useMemo)(() => ({ playing, play }), [playing, play]);
|
|
660
669
|
}
|
|
661
670
|
|
|
662
671
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
663
|
-
var
|
|
672
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
664
673
|
function GenrePlaylistTreePerRoot({
|
|
665
674
|
scope,
|
|
666
675
|
className: className2,
|
|
@@ -679,25 +688,16 @@ function GenrePlaylistTreePerRoot({
|
|
|
679
688
|
viewportRestore,
|
|
680
689
|
onViewportChange,
|
|
681
690
|
playback,
|
|
691
|
+
focusUuids,
|
|
682
692
|
...hostPanel
|
|
683
693
|
}) {
|
|
684
694
|
const { isPlaying, setIsPlaying } = (0, import_player.usePlayer)();
|
|
685
695
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: genrePlaylistTreePerRoot });
|
|
686
696
|
const { playing, play } = playback ?? defaultPlayback;
|
|
687
697
|
const playingNodeId = playing?.uuid ?? null;
|
|
688
|
-
const { showPopup } = (0, import_popup2.usePopup)();
|
|
689
698
|
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]
|
|
699
|
+
() => toTreeNodes(genrePlaylistTreePerRoot, "songs", focusUuids),
|
|
700
|
+
[genrePlaylistTreePerRoot, focusUuids]
|
|
701
701
|
);
|
|
702
702
|
const handlePlayPause = (0, import_react4.useCallback)(
|
|
703
703
|
(nodeId) => {
|
|
@@ -710,18 +710,14 @@ function GenrePlaylistTreePerRoot({
|
|
|
710
710
|
if ((0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
711
711
|
return;
|
|
712
712
|
}
|
|
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
|
-
});
|
|
713
|
+
void play(genrePlaylist);
|
|
717
714
|
},
|
|
718
715
|
[
|
|
719
716
|
genrePlaylistTreePerRoot,
|
|
720
717
|
playingNodeId,
|
|
721
718
|
isPlaying,
|
|
722
719
|
setIsPlaying,
|
|
723
|
-
play
|
|
724
|
-
showPopup
|
|
720
|
+
play
|
|
725
721
|
]
|
|
726
722
|
);
|
|
727
723
|
const handleAddChild = (0, import_react4.useCallback)(
|
|
@@ -744,7 +740,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
744
740
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
745
741
|
}
|
|
746
742
|
}, []);
|
|
747
|
-
return /* @__PURE__ */ (0,
|
|
743
|
+
return /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
|
|
748
744
|
import_genre_tree_view.GenreTree,
|
|
749
745
|
{
|
|
750
746
|
className: className2,
|
|
@@ -775,9 +771,7 @@ var import_genre_tree4 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
775
771
|
var import_react5 = require("react");
|
|
776
772
|
var import_genre_tree_view2 = require("@behindthemusictree/genre-tree-view");
|
|
777
773
|
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");
|
|
774
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
781
775
|
function GenrePlaylistTreeWheel({
|
|
782
776
|
scope,
|
|
783
777
|
className: className2,
|
|
@@ -798,24 +792,16 @@ function GenrePlaylistTreeWheel({
|
|
|
798
792
|
viewportRestore,
|
|
799
793
|
onViewportChange,
|
|
800
794
|
playback,
|
|
795
|
+
focusUuids,
|
|
801
796
|
...hostPanel
|
|
802
797
|
}) {
|
|
803
798
|
const { isPlaying, setIsPlaying } = (0, import_player2.usePlayer)();
|
|
804
799
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
805
800
|
const { playing, play } = playback ?? defaultPlayback;
|
|
806
801
|
const playingNodeId = playing?.uuid ?? null;
|
|
807
|
-
const { showPopup } = (0, import_popup3.usePopup)();
|
|
808
802
|
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]
|
|
803
|
+
() => toTreeNodes(genrePlaylists, sizeMetric, focusUuids),
|
|
804
|
+
[genrePlaylists, sizeMetric, focusUuids]
|
|
819
805
|
);
|
|
820
806
|
const handlePlayPause = (0, import_react5.useCallback)(
|
|
821
807
|
(nodeId) => {
|
|
@@ -828,18 +814,14 @@ function GenrePlaylistTreeWheel({
|
|
|
828
814
|
if ((0, import_genre_tree4.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
829
815
|
return;
|
|
830
816
|
}
|
|
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
|
-
});
|
|
817
|
+
void play(genrePlaylist);
|
|
835
818
|
},
|
|
836
819
|
[
|
|
837
820
|
genrePlaylists,
|
|
838
821
|
playingNodeId,
|
|
839
822
|
isPlaying,
|
|
840
823
|
setIsPlaying,
|
|
841
|
-
play
|
|
842
|
-
showPopup
|
|
824
|
+
play
|
|
843
825
|
]
|
|
844
826
|
);
|
|
845
827
|
const handleAddChild = (0, import_react5.useCallback)(
|
|
@@ -862,7 +844,7 @@ function GenrePlaylistTreeWheel({
|
|
|
862
844
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
863
845
|
}
|
|
864
846
|
}, []);
|
|
865
|
-
return /* @__PURE__ */ (0,
|
|
847
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
866
848
|
import_genre_tree_view2.GenreTreeWheel,
|
|
867
849
|
{
|
|
868
850
|
className: className2,
|
|
@@ -894,7 +876,7 @@ var import_genre_tree5 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
894
876
|
var import_react6 = require("react");
|
|
895
877
|
var import_genre_tree_view3 = require("@behindthemusictree/genre-tree-view");
|
|
896
878
|
var import_player3 = require("@behindthemusictree/app-kit/player");
|
|
897
|
-
var
|
|
879
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
898
880
|
function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
899
881
|
const {
|
|
900
882
|
scope,
|
|
@@ -927,7 +909,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
927
909
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
928
910
|
const { playing, play } = playback ?? defaultPlayback;
|
|
929
911
|
const playingNodeId = playing?.uuid ?? null;
|
|
930
|
-
const nodes = (0, import_react6.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric), [genrePlaylists, sizeMetric]);
|
|
912
|
+
const nodes = (0, import_react6.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric, props.focusUuids), [genrePlaylists, sizeMetric, props.focusUuids]);
|
|
931
913
|
const handlePlayPause = (0, import_react6.useCallback)(
|
|
932
914
|
(nodeId) => {
|
|
933
915
|
const genrePlaylist = genrePlaylists.find((g) => g.uuid === nodeId);
|
|
@@ -939,9 +921,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
939
921
|
if ((0, import_genre_tree5.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
940
922
|
return;
|
|
941
923
|
}
|
|
942
|
-
play(genrePlaylist)
|
|
943
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
944
|
-
});
|
|
924
|
+
void play(genrePlaylist);
|
|
945
925
|
},
|
|
946
926
|
[genrePlaylists, playingNodeId, isPlaying, setIsPlaying, play]
|
|
947
927
|
);
|
|
@@ -981,7 +961,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
981
961
|
onSelectedNodeChange,
|
|
982
962
|
...hostPanel
|
|
983
963
|
};
|
|
984
|
-
return outline ? /* @__PURE__ */ (0,
|
|
964
|
+
return outline ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(import_genre_tree_view3.GenreTreeOutline, { ...treeProps }) : /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
985
965
|
import_genre_tree_view3.GenreTreeWheelRadialPopCore,
|
|
986
966
|
{
|
|
987
967
|
...treeProps,
|
|
@@ -998,7 +978,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
998
978
|
|
|
999
979
|
// src/genre-tree/GenreTreeWheelHandoff.tsx
|
|
1000
980
|
var import_react7 = require("react");
|
|
1001
|
-
var
|
|
981
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1002
982
|
function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
1003
983
|
const [revealed, setRevealed] = (0, import_react7.useState)(false);
|
|
1004
984
|
const onRevealedChangeRef = (0, import_react7.useRef)(onRevealedChange);
|
|
@@ -1017,8 +997,8 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
1017
997
|
cancelAnimationFrame(innerFrame);
|
|
1018
998
|
};
|
|
1019
999
|
}, []);
|
|
1020
|
-
return /* @__PURE__ */ (0,
|
|
1021
|
-
/* @__PURE__ */ (0,
|
|
1000
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
1001
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1022
1002
|
"div",
|
|
1023
1003
|
{
|
|
1024
1004
|
className: "absolute inset-0 transition-opacity duration-150 ease-out",
|
|
@@ -1027,7 +1007,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
1027
1007
|
children
|
|
1028
1008
|
}
|
|
1029
1009
|
),
|
|
1030
|
-
!revealed && /* @__PURE__ */ (0,
|
|
1010
|
+
!revealed && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "absolute inset-0", "aria-hidden": "true", children: skeleton })
|
|
1031
1011
|
] });
|
|
1032
1012
|
}
|
|
1033
1013
|
|
|
@@ -1042,7 +1022,7 @@ var import_genre_tree9 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1042
1022
|
// src/genre-tree/search/SearchBox.tsx
|
|
1043
1023
|
var import_react8 = require("react");
|
|
1044
1024
|
var import_ui6 = require("@behindthemusictree/ui");
|
|
1045
|
-
var
|
|
1025
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1046
1026
|
function SearchBox({
|
|
1047
1027
|
label,
|
|
1048
1028
|
placeholder,
|
|
@@ -1064,7 +1044,7 @@ function SearchBox({
|
|
|
1064
1044
|
groups.find((group) => group.key === groupKey)?.items.find((item) => item.key === itemKey)?.onSelect();
|
|
1065
1045
|
onPicked?.(groupKey, itemKey);
|
|
1066
1046
|
};
|
|
1067
|
-
return /* @__PURE__ */ (0,
|
|
1047
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: className2, onFocusCapture: onFocus, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1068
1048
|
import_ui6.SearchCombobox,
|
|
1069
1049
|
{
|
|
1070
1050
|
ariaLabel: label,
|
|
@@ -1096,7 +1076,7 @@ var searchStatus = (state, count, noun) => state.isError ? SEARCH_FAILED_STATUS
|
|
|
1096
1076
|
|
|
1097
1077
|
// src/genre-tree/search/useArtistSearchGroup.tsx
|
|
1098
1078
|
var import_genre_tree6 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1099
|
-
var
|
|
1079
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1100
1080
|
function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
1101
1081
|
const search = (0, import_genre_tree6.useArtistSearch)(getBaseUrl, enabled ? text : "");
|
|
1102
1082
|
if (!enabled) return void 0;
|
|
@@ -1105,15 +1085,15 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1105
1085
|
label: "Artists",
|
|
1106
1086
|
items: search.artists.map((artist) => ({
|
|
1107
1087
|
key: artist.uuid,
|
|
1108
|
-
content: /* @__PURE__ */ (0,
|
|
1109
|
-
/* @__PURE__ */ (0,
|
|
1088
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)(import_jsx_runtime18.Fragment, { children: [
|
|
1089
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
1110
1090
|
artist.name,
|
|
1111
|
-
artist.disambiguation && /* @__PURE__ */ (0,
|
|
1091
|
+
artist.disambiguation && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "font-normal text-[var(--color-neutral-500)]", children: [
|
|
1112
1092
|
" \xB7 ",
|
|
1113
1093
|
artist.disambiguation
|
|
1114
1094
|
] })
|
|
1115
1095
|
] }),
|
|
1116
|
-
artist.matchedAlias && /* @__PURE__ */ (0,
|
|
1096
|
+
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [
|
|
1117
1097
|
"also known as ",
|
|
1118
1098
|
artist.matchedAlias
|
|
1119
1099
|
] })
|
|
@@ -1127,7 +1107,7 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1127
1107
|
|
|
1128
1108
|
// src/genre-tree/search/useSongSearchGroup.tsx
|
|
1129
1109
|
var import_genre_tree7 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1130
|
-
var
|
|
1110
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1131
1111
|
function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
1132
1112
|
const search = (0, import_genre_tree7.useSongSearch)(getBaseUrl, enabled ? text : "");
|
|
1133
1113
|
if (!enabled) return void 0;
|
|
@@ -1136,9 +1116,9 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1136
1116
|
label: "Songs",
|
|
1137
1117
|
items: search.songs.map((song) => ({
|
|
1138
1118
|
key: song.uuid,
|
|
1139
|
-
content: /* @__PURE__ */ (0,
|
|
1140
|
-
/* @__PURE__ */ (0,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1119
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
1120
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
1121
|
+
/* @__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
1122
|
] }),
|
|
1143
1123
|
onSelect: () => onSelect(song)
|
|
1144
1124
|
})),
|
|
@@ -1149,7 +1129,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1149
1129
|
|
|
1150
1130
|
// src/genre-tree/search/useGenreRemoteSearchGroup.tsx
|
|
1151
1131
|
var import_genre_tree8 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1152
|
-
var
|
|
1132
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1153
1133
|
function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres", label = "Genres", filter, describe, ...options } = {}) {
|
|
1154
1134
|
const search = (0, import_genre_tree8.useGenreRemoteSearch)(getBaseUrl, text, options);
|
|
1155
1135
|
const genres = filter ? search.genres.filter(filter) : search.genres;
|
|
@@ -1158,12 +1138,12 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
1158
1138
|
label,
|
|
1159
1139
|
items: genres.map((genre) => ({
|
|
1160
1140
|
key: genre.uuid,
|
|
1161
|
-
content: /* @__PURE__ */ (0,
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1141
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
1163
1143
|
genre.name,
|
|
1164
|
-
genre.isUmbrella && /* @__PURE__ */ (0,
|
|
1144
|
+
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
1145
|
] }),
|
|
1166
|
-
/* @__PURE__ */ (0,
|
|
1146
|
+
/* @__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
1147
|
] }),
|
|
1168
1148
|
onSelect: () => onSelect(genre)
|
|
1169
1149
|
})),
|
|
@@ -1173,7 +1153,7 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
1173
1153
|
}
|
|
1174
1154
|
|
|
1175
1155
|
// src/genre-tree/GenreSearch.tsx
|
|
1176
|
-
var
|
|
1156
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1177
1157
|
function GenreSearch({
|
|
1178
1158
|
genrePlaylists,
|
|
1179
1159
|
onSelect,
|
|
@@ -1202,9 +1182,9 @@ function GenreSearch({
|
|
|
1202
1182
|
label: hasExtras ? "Genres" : void 0,
|
|
1203
1183
|
items: results.map((genrePlaylist) => ({
|
|
1204
1184
|
key: genrePlaylist.uuid,
|
|
1205
|
-
content: /* @__PURE__ */ (0,
|
|
1185
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(import_jsx_runtime21.Fragment, { children: [
|
|
1206
1186
|
genrePlaylist.name,
|
|
1207
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */ (0,
|
|
1187
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1208
1188
|
] }),
|
|
1209
1189
|
onSelect: () => select(genrePlaylist)
|
|
1210
1190
|
}))
|
|
@@ -1213,7 +1193,7 @@ function GenreSearch({
|
|
|
1213
1193
|
(group) => active ? group : { ...group, items: [], status: "", loading: false }
|
|
1214
1194
|
)
|
|
1215
1195
|
];
|
|
1216
|
-
return /* @__PURE__ */ (0,
|
|
1196
|
+
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
1197
|
SearchBox,
|
|
1218
1198
|
{
|
|
1219
1199
|
label,
|
|
@@ -1233,14 +1213,14 @@ function GenreSearch({
|
|
|
1233
1213
|
clear();
|
|
1234
1214
|
onQueryChange?.("");
|
|
1235
1215
|
} : void 0,
|
|
1236
|
-
leading: onPrevious && /* @__PURE__ */ (0,
|
|
1216
|
+
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
1217
|
onFocus
|
|
1238
1218
|
}
|
|
1239
1219
|
) });
|
|
1240
1220
|
}
|
|
1241
1221
|
|
|
1242
1222
|
// src/genre-tree/GenreTreeSearch.tsx
|
|
1243
|
-
var
|
|
1223
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1244
1224
|
function GenreTreeSearch({
|
|
1245
1225
|
artistBaseUrl,
|
|
1246
1226
|
songBaseUrl,
|
|
@@ -1260,7 +1240,7 @@ function GenreTreeSearch({
|
|
|
1260
1240
|
const deferredQuery = (0, import_react9.useDeferredValue)(query);
|
|
1261
1241
|
const artistGroup = useArtistSearchGroup(artistBaseUrl, deferredQuery, onArtistSelect, artistSearch);
|
|
1262
1242
|
const songGroup = useSongSearchGroup(songBaseUrl, deferredQuery, onSongSelect, songSearch);
|
|
1263
|
-
const render = (hostGroups) => /* @__PURE__ */ (0,
|
|
1243
|
+
const render = (hostGroups) => /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(
|
|
1264
1244
|
GenreSearch,
|
|
1265
1245
|
{
|
|
1266
1246
|
...props,
|
|
@@ -1275,7 +1255,7 @@ function GenreTreeSearch({
|
|
|
1275
1255
|
extraGroups: [...extraGroups, ...hostGroups, artistGroup, songGroup].filter((group) => group !== void 0)
|
|
1276
1256
|
}
|
|
1277
1257
|
);
|
|
1278
|
-
return SearchGroups ? /* @__PURE__ */ (0,
|
|
1258
|
+
return SearchGroups ? /* @__PURE__ */ (0, import_jsx_runtime22.jsx)(SearchGroups, { query: deferredQuery, focused, onSelectGenre, children: render }) : render([]);
|
|
1279
1259
|
}
|
|
1280
1260
|
|
|
1281
1261
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
@@ -1295,7 +1275,7 @@ var import_ui9 = require("@behindthemusictree/ui");
|
|
|
1295
1275
|
// src/genre-tree/ShareActionButton.tsx
|
|
1296
1276
|
var import_lucide_react10 = require("lucide-react");
|
|
1297
1277
|
var import_ui8 = require("@behindthemusictree/ui");
|
|
1298
|
-
var
|
|
1278
|
+
var import_popup3 = require("@behindthemusictree/app-kit/popup");
|
|
1299
1279
|
|
|
1300
1280
|
// src/genre-tree/SharePopup.tsx
|
|
1301
1281
|
var import_react10 = require("react");
|
|
@@ -1304,12 +1284,12 @@ var import_fa3 = require("react-icons/fa");
|
|
|
1304
1284
|
var import_si = require("react-icons/si");
|
|
1305
1285
|
|
|
1306
1286
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
1307
|
-
var
|
|
1287
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1308
1288
|
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
1289
|
function Contents({ icon, label }) {
|
|
1310
|
-
return /* @__PURE__ */ (0,
|
|
1311
|
-
/* @__PURE__ */ (0,
|
|
1312
|
-
/* @__PURE__ */ (0,
|
|
1290
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1291
|
+
/* @__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 }),
|
|
1292
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "max-w-full truncate", children: label })
|
|
1313
1293
|
] });
|
|
1314
1294
|
}
|
|
1315
1295
|
function ShareDestinationButton({
|
|
@@ -1321,29 +1301,29 @@ function ShareDestinationButton({
|
|
|
1321
1301
|
ariaLabel
|
|
1322
1302
|
}) {
|
|
1323
1303
|
if (href) {
|
|
1324
|
-
return /* @__PURE__ */ (0,
|
|
1304
|
+
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
1305
|
}
|
|
1326
|
-
return /* @__PURE__ */ (0,
|
|
1306
|
+
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
1307
|
}
|
|
1328
1308
|
|
|
1329
1309
|
// src/genre-tree/SharePreviewCard.tsx
|
|
1330
1310
|
var import_lucide_react8 = require("lucide-react");
|
|
1331
|
-
var
|
|
1311
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1332
1312
|
function SharePreviewCard({ target, url }) {
|
|
1333
1313
|
const Icon = { genre: import_lucide_react8.Music2, artist: import_lucide_react8.UserRound, song: import_lucide_react8.Music }[target.kind];
|
|
1334
1314
|
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,
|
|
1315
|
+
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: [
|
|
1316
|
+
/* @__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" }) }),
|
|
1317
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
1318
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
1320
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
1341
1321
|
] })
|
|
1342
1322
|
] }) });
|
|
1343
1323
|
}
|
|
1344
1324
|
|
|
1345
1325
|
// src/genre-tree/SharePopup.tsx
|
|
1346
|
-
var
|
|
1326
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1347
1327
|
function resolveAbsoluteUrl(url) {
|
|
1348
1328
|
try {
|
|
1349
1329
|
const parsed = new URL(url, window.location.href);
|
|
@@ -1418,8 +1398,8 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1418
1398
|
setShareError("Could not open the share options.");
|
|
1419
1399
|
}
|
|
1420
1400
|
};
|
|
1421
|
-
return /* @__PURE__ */ (0,
|
|
1422
|
-
/* @__PURE__ */ (0,
|
|
1401
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
1402
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1423
1403
|
BasePopup_default,
|
|
1424
1404
|
{
|
|
1425
1405
|
title: "Share",
|
|
@@ -1434,70 +1414,70 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1434
1414
|
titleTextClassName: "!text-xl !font-semibold !text-[var(--color-text)]",
|
|
1435
1415
|
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
1416
|
contentClassName: "!rounded-none !bg-transparent !px-6 !pb-6 !pt-2",
|
|
1437
|
-
children: /* @__PURE__ */ (0,
|
|
1438
|
-
/* @__PURE__ */ (0,
|
|
1439
|
-
/* @__PURE__ */ (0,
|
|
1440
|
-
/* @__PURE__ */ (0,
|
|
1417
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
1418
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SharePreviewCard, { target, url: absoluteUrl || url }),
|
|
1419
|
+
/* @__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: [
|
|
1420
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1441
1421
|
ShareDestinationButton,
|
|
1442
1422
|
{
|
|
1443
1423
|
label: "Copy Link",
|
|
1444
|
-
icon: /* @__PURE__ */ (0,
|
|
1424
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react9.Link2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
1445
1425
|
onClick: () => void handleCopy(),
|
|
1446
1426
|
ariaLabel: "Copy link",
|
|
1447
1427
|
disabled: !absoluteUrl
|
|
1448
1428
|
}
|
|
1449
1429
|
),
|
|
1450
|
-
/* @__PURE__ */ (0,
|
|
1430
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1451
1431
|
ShareDestinationButton,
|
|
1452
1432
|
{
|
|
1453
1433
|
label: "WhatsApp",
|
|
1454
|
-
icon: /* @__PURE__ */ (0,
|
|
1434
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_fa3.FaWhatsapp, { "aria-hidden": "true", className: "h-9 w-9 text-[#25D366]" }),
|
|
1455
1435
|
href: destinationUrls?.whatsapp,
|
|
1456
1436
|
ariaLabel: `Share ${target.name} via WhatsApp`,
|
|
1457
1437
|
disabled: !absoluteUrl
|
|
1458
1438
|
}
|
|
1459
1439
|
),
|
|
1460
|
-
/* @__PURE__ */ (0,
|
|
1440
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1461
1441
|
ShareDestinationButton,
|
|
1462
1442
|
{
|
|
1463
1443
|
label: "Gmail",
|
|
1464
|
-
icon: /* @__PURE__ */ (0,
|
|
1444
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_si.SiGmail, { "aria-hidden": "true", className: "h-8 w-8 text-[#EA4335]" }),
|
|
1465
1445
|
href: destinationUrls?.gmail,
|
|
1466
1446
|
ariaLabel: `Email ${target.name} with Gmail`,
|
|
1467
1447
|
disabled: !absoluteUrl
|
|
1468
1448
|
}
|
|
1469
1449
|
),
|
|
1470
|
-
canUseNativeShare && /* @__PURE__ */ (0,
|
|
1450
|
+
canUseNativeShare && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1471
1451
|
ShareDestinationButton,
|
|
1472
1452
|
{
|
|
1473
1453
|
label: "More",
|
|
1474
|
-
icon: /* @__PURE__ */ (0,
|
|
1454
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react9.Share2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
1475
1455
|
onClick: () => void handleNativeShare(),
|
|
1476
1456
|
ariaLabel: "More sharing options",
|
|
1477
1457
|
disabled: !absoluteUrl
|
|
1478
1458
|
}
|
|
1479
1459
|
)
|
|
1480
1460
|
] }),
|
|
1481
|
-
copyStatus === "failed" && /* @__PURE__ */ (0,
|
|
1482
|
-
shareError && /* @__PURE__ */ (0,
|
|
1461
|
+
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." }),
|
|
1462
|
+
shareError && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
1483
1463
|
] })
|
|
1484
1464
|
}
|
|
1485
1465
|
),
|
|
1486
|
-
toastId > 0 && /* @__PURE__ */ (0,
|
|
1466
|
+
toastId > 0 && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(Toast, { message: "Link copied", onClose: dismissToast }, toastId)
|
|
1487
1467
|
] });
|
|
1488
1468
|
}
|
|
1489
1469
|
|
|
1490
1470
|
// src/genre-tree/ShareActionButton.tsx
|
|
1491
|
-
var
|
|
1471
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1492
1472
|
function ShareActionButton({ target, url }) {
|
|
1493
|
-
const { showPopup, hidePopup } = (0,
|
|
1473
|
+
const { showPopup, hidePopup } = (0, import_popup3.usePopup)();
|
|
1494
1474
|
const openSharePopup = () => {
|
|
1495
|
-
showPopup(/* @__PURE__ */ (0,
|
|
1475
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(SharePopup, { target, url, onClose: hidePopup }));
|
|
1496
1476
|
};
|
|
1497
|
-
return /* @__PURE__ */ (0,
|
|
1477
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1498
1478
|
import_ui8.ActionButton,
|
|
1499
1479
|
{
|
|
1500
|
-
icon: /* @__PURE__ */ (0,
|
|
1480
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react10.Share2, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1501
1481
|
label: "Share",
|
|
1502
1482
|
"aria-label": `Share ${target.name}`,
|
|
1503
1483
|
title: `Share ${target.name}`,
|
|
@@ -1507,7 +1487,7 @@ function ShareActionButton({ target, url }) {
|
|
|
1507
1487
|
}
|
|
1508
1488
|
|
|
1509
1489
|
// src/genre-tree/GenreActionBand.tsx
|
|
1510
|
-
var
|
|
1490
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1511
1491
|
function GenreActionBand({
|
|
1512
1492
|
node,
|
|
1513
1493
|
playActions,
|
|
@@ -1528,24 +1508,24 @@ function GenreActionBand({
|
|
|
1528
1508
|
items.push({
|
|
1529
1509
|
key: "zoom-in",
|
|
1530
1510
|
label: "Focus",
|
|
1531
|
-
icon: /* @__PURE__ */ (0,
|
|
1511
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.ZoomIn, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1532
1512
|
onClick: onZoomIn
|
|
1533
1513
|
});
|
|
1534
1514
|
}
|
|
1535
1515
|
if (onAddChild) {
|
|
1536
|
-
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */ (0,
|
|
1516
|
+
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
1517
|
}
|
|
1538
1518
|
if (onRename) {
|
|
1539
|
-
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */ (0,
|
|
1519
|
+
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
1520
|
}
|
|
1541
1521
|
if (onChangeParent) {
|
|
1542
|
-
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */ (0,
|
|
1522
|
+
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
1523
|
}
|
|
1544
1524
|
if (onToggleSide) {
|
|
1545
1525
|
adminItems.push({
|
|
1546
1526
|
key: "toggle-side",
|
|
1547
1527
|
label: side === "pop" ? "Make core" : "Make pop",
|
|
1548
|
-
icon: /* @__PURE__ */ (0,
|
|
1528
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_lucide_react11.ArrowLeftRight, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1549
1529
|
onClick: onToggleSide,
|
|
1550
1530
|
disabled: !!toggleSideDisabledReason,
|
|
1551
1531
|
title: toggleSideDisabledReason
|
|
@@ -1560,9 +1540,9 @@ function GenreActionBand({
|
|
|
1560
1540
|
disabled: action.enabled ? !action.enabled(node) : false
|
|
1561
1541
|
});
|
|
1562
1542
|
}
|
|
1563
|
-
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0,
|
|
1543
|
+
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
1544
|
if (!playActions && items.length === 0 && adminItems.length === 0 && !(shareTarget && shareUrl)) return null;
|
|
1565
|
-
return /* @__PURE__ */ (0,
|
|
1545
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1566
1546
|
import_ui9.ActionBand,
|
|
1567
1547
|
{
|
|
1568
1548
|
className: "genre-action-band",
|
|
@@ -1570,7 +1550,7 @@ function GenreActionBand({
|
|
|
1570
1550
|
children: [
|
|
1571
1551
|
playActions,
|
|
1572
1552
|
renderItems(items),
|
|
1573
|
-
shareTarget && shareUrl && /* @__PURE__ */ (0,
|
|
1553
|
+
shareTarget && shareUrl && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
1574
1554
|
]
|
|
1575
1555
|
}
|
|
1576
1556
|
) });
|
|
@@ -1594,7 +1574,7 @@ var REGION_GLOBE_PATHS = {
|
|
|
1594
1574
|
var REGION_GLOBES = ["africa", "americas", "asia"];
|
|
1595
1575
|
|
|
1596
1576
|
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1597
|
-
var
|
|
1577
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1598
1578
|
var ROTATION_INTERVAL_MS = 3e3;
|
|
1599
1579
|
function RegionGlobeIcon({ className: className2 }) {
|
|
1600
1580
|
const [index, setIndex] = (0, import_react11.useState)(0);
|
|
@@ -1612,29 +1592,29 @@ function RegionGlobeIcon({ className: className2 }) {
|
|
|
1612
1592
|
clearInterval(timer);
|
|
1613
1593
|
};
|
|
1614
1594
|
}, []);
|
|
1615
|
-
return /* @__PURE__ */ (0,
|
|
1595
|
+
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
1596
|
}
|
|
1617
1597
|
|
|
1618
1598
|
// src/genre-tree/treeMarkPath.ts
|
|
1619
1599
|
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
1600
|
|
|
1621
1601
|
// src/genre-tree/TreeMarkIcon.tsx
|
|
1622
|
-
var
|
|
1602
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1623
1603
|
function TreeMarkIcon({ className: className2 }) {
|
|
1624
|
-
return /* @__PURE__ */ (0,
|
|
1604
|
+
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
1605
|
}
|
|
1626
1606
|
|
|
1627
1607
|
// src/genre-tree/GenrePlayActions.tsx
|
|
1628
|
-
var
|
|
1608
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1629
1609
|
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,
|
|
1610
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("span", { "aria-hidden": "true", className: "relative flex items-center justify-center w-5 h-5", children: [
|
|
1611
|
+
kind === "tree" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1612
|
+
kind === "map" && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1613
|
+
kind === "tree-map" && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1614
|
+
/* @__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)]" }),
|
|
1615
|
+
/* @__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
1616
|
] }),
|
|
1637
|
-
/* @__PURE__ */ (0,
|
|
1617
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react12.Play, { className: "relative w-5 h-5 fill-[var(--color-surface)]" })
|
|
1638
1618
|
] });
|
|
1639
1619
|
}
|
|
1640
1620
|
function playOptions(playlist) {
|
|
@@ -1650,13 +1630,13 @@ function playOptions(playlist) {
|
|
|
1650
1630
|
function GenrePlayActions({ genrePlaylist, playback }) {
|
|
1651
1631
|
const { isPlaying, setIsPlaying } = (0, import_player4.usePlayer)();
|
|
1652
1632
|
const options = playOptions(genrePlaylist);
|
|
1653
|
-
return /* @__PURE__ */ (0,
|
|
1633
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_jsx_runtime30.Fragment, { children: options.map((option) => {
|
|
1654
1634
|
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
1635
|
const playing = isCurrent && isPlaying;
|
|
1656
|
-
return /* @__PURE__ */ (0,
|
|
1636
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1657
1637
|
import_ui10.ActionButton,
|
|
1658
1638
|
{
|
|
1659
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
1639
|
+
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
1640
|
label: playing ? "Pause" : option.label,
|
|
1661
1641
|
caption: String(option.count),
|
|
1662
1642
|
disabled: option.count === 0,
|
|
@@ -1666,9 +1646,7 @@ function GenrePlayActions({ genrePlaylist, playback }) {
|
|
|
1666
1646
|
setIsPlaying(!isPlaying);
|
|
1667
1647
|
return;
|
|
1668
1648
|
}
|
|
1669
|
-
playback.play(genrePlaylist, option.selection)
|
|
1670
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
1671
|
-
});
|
|
1649
|
+
void playback.play(genrePlaylist, option.selection);
|
|
1672
1650
|
}
|
|
1673
1651
|
},
|
|
1674
1652
|
option.key
|
|
@@ -1682,7 +1660,7 @@ var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1682
1660
|
|
|
1683
1661
|
// src/genre-tree/ClampedText.tsx
|
|
1684
1662
|
var import_react12 = require("react");
|
|
1685
|
-
var
|
|
1663
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1686
1664
|
function ClampedText({ children, className: className2 = "" }) {
|
|
1687
1665
|
const ref = (0, import_react12.useRef)(null);
|
|
1688
1666
|
const [expanded, setExpanded] = (0, import_react12.useState)(false);
|
|
@@ -1692,9 +1670,9 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1692
1670
|
if (!element || expanded) return;
|
|
1693
1671
|
setOverflows(element.scrollHeight > element.clientHeight);
|
|
1694
1672
|
}, [children, expanded]);
|
|
1695
|
-
return /* @__PURE__ */ (0,
|
|
1696
|
-
/* @__PURE__ */ (0,
|
|
1697
|
-
(overflows || expanded) && /* @__PURE__ */ (0,
|
|
1673
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
1674
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { ref, className: `${className2} ${expanded ? "" : "line-clamp-3"}`, children }),
|
|
1675
|
+
(overflows || expanded) && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1698
1676
|
"button",
|
|
1699
1677
|
{
|
|
1700
1678
|
type: "button",
|
|
@@ -1714,13 +1692,13 @@ var import_zod = require("zod");
|
|
|
1714
1692
|
var import_fa4 = require("react-icons/fa");
|
|
1715
1693
|
var import_ui11 = require("@behindthemusictree/ui");
|
|
1716
1694
|
var import_auth2 = require("@behindthemusictree/app-kit/auth");
|
|
1695
|
+
var import_transport4 = require("@behindthemusictree/app-kit/transport");
|
|
1717
1696
|
var import_transport5 = require("@behindthemusictree/app-kit/transport");
|
|
1718
1697
|
var import_transport6 = require("@behindthemusictree/app-kit/transport");
|
|
1719
|
-
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
1720
1698
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1721
1699
|
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1722
|
-
var
|
|
1723
|
-
var
|
|
1700
|
+
var import_popup4 = require("@behindthemusictree/app-kit/popup");
|
|
1701
|
+
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
1724
1702
|
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1725
1703
|
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1726
1704
|
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -1729,15 +1707,15 @@ var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1729
1707
|
|
|
1730
1708
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1731
1709
|
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1732
|
-
var
|
|
1710
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1733
1711
|
function MusicBrainzRecordingLink({
|
|
1734
1712
|
song,
|
|
1735
1713
|
children,
|
|
1736
1714
|
className: className2 = ""
|
|
1737
1715
|
}) {
|
|
1738
1716
|
const url = (0, import_genre_tree11.musicBrainzRecordingUrl)(song);
|
|
1739
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1740
|
-
return /* @__PURE__ */ (0,
|
|
1717
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_jsx_runtime32.Fragment, { children });
|
|
1718
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1741
1719
|
"a",
|
|
1742
1720
|
{
|
|
1743
1721
|
href: url,
|
|
@@ -1754,9 +1732,9 @@ function MusicBrainzRecordingLink({
|
|
|
1754
1732
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1755
1733
|
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1756
1734
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1757
|
-
var
|
|
1735
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1758
1736
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1759
|
-
var SongPageSchema = (0,
|
|
1737
|
+
var SongPageSchema = (0, import_transport5.PaginatedResponseSchema)(import_genre_tree15.SongDetailedSchema).extend({
|
|
1760
1738
|
overallTotal: import_zod.z.number().nullable(),
|
|
1761
1739
|
page: import_zod.z.number().nullable(),
|
|
1762
1740
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1788,12 +1766,12 @@ function GenrePlaylistTracks({
|
|
|
1788
1766
|
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree16.useTrackList)();
|
|
1789
1767
|
const { session, sessionRestored } = (0, import_auth2.useSession)();
|
|
1790
1768
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player5.usePlayer)();
|
|
1791
|
-
const { showPopup } = (0,
|
|
1769
|
+
const { showPopup } = (0, import_popup4.usePopup)();
|
|
1792
1770
|
const trackNoun = (0, import_track_noun2.useTrackNoun)();
|
|
1793
1771
|
const uuid = genrePlaylist?.uuid;
|
|
1794
1772
|
const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
|
|
1795
|
-
const { fetchBound } = (0,
|
|
1796
|
-
const playback = (0,
|
|
1773
|
+
const { fetchBound } = (0, import_transport4.usePlaybackFetch)(getBackendBaseUrl);
|
|
1774
|
+
const playback = (0, import_transport4.usePlaybackContext)();
|
|
1797
1775
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1798
1776
|
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
1777
|
queryFn: async ({ pageParam }) => {
|
|
@@ -1808,7 +1786,7 @@ function GenrePlaylistTracks({
|
|
|
1808
1786
|
{},
|
|
1809
1787
|
{ genre: genreUuid, ...(0, import_genre_tree12.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1810
1788
|
);
|
|
1811
|
-
const parsed = (0,
|
|
1789
|
+
const parsed = (0, import_transport6.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1812
1790
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
1813
1791
|
},
|
|
1814
1792
|
initialPageParam: scope === "me" ? 1 : "",
|
|
@@ -1840,35 +1818,36 @@ function GenrePlaylistTracks({
|
|
|
1840
1818
|
}) : 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
1819
|
started.catch((error) => {
|
|
1842
1820
|
console.error("Failed to play genre playlist:", error);
|
|
1843
|
-
|
|
1821
|
+
if (error instanceof import_genre_tree16.TracksFailureAlreadyReportedError) return;
|
|
1822
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport7.AppError ? error.code : import_transport7.ErrorCode.CLIENT_UNKNOWN }));
|
|
1844
1823
|
});
|
|
1845
1824
|
};
|
|
1846
|
-
return /* @__PURE__ */ (0,
|
|
1825
|
+
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
1826
|
renderTracksToolbar?.(),
|
|
1848
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0,
|
|
1827
|
+
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
1828
|
"Couldn't load ",
|
|
1850
1829
|
trackNoun.plural,
|
|
1851
1830
|
".",
|
|
1852
1831
|
" ",
|
|
1853
|
-
/* @__PURE__ */ (0,
|
|
1854
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0,
|
|
1832
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1833
|
+
] }) : 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
1834
|
tracks.map((track, index) => {
|
|
1856
1835
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1857
1836
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1858
1837
|
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,
|
|
1838
|
+
const text = /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1839
|
+
/* @__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 }),
|
|
1840
|
+
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1841
|
+
/* @__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 }),
|
|
1842
|
+
track.album && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1864
1843
|
] });
|
|
1865
1844
|
const leading = renderSongLeading?.(track, index);
|
|
1866
1845
|
const actions = renderSongActions?.(track);
|
|
1867
1846
|
const isUnplayable = (0, import_genre_tree15.isSong)(track) && (0, import_genre_tree15.songUnplayableReason)(track) !== null;
|
|
1868
1847
|
if (isUnplayable) {
|
|
1869
|
-
return /* @__PURE__ */ (0,
|
|
1848
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1870
1849
|
leading,
|
|
1871
|
-
/* @__PURE__ */ (0,
|
|
1850
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1872
1851
|
"button",
|
|
1873
1852
|
{
|
|
1874
1853
|
type: "button",
|
|
@@ -1876,27 +1855,27 @@ function GenrePlaylistTracks({
|
|
|
1876
1855
|
"aria-disabled": "true",
|
|
1877
1856
|
"aria-label": label,
|
|
1878
1857
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1879
|
-
children: /* @__PURE__ */ (0,
|
|
1858
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1880
1859
|
}
|
|
1881
1860
|
),
|
|
1882
1861
|
text,
|
|
1883
1862
|
actions
|
|
1884
1863
|
] }, track.uuid);
|
|
1885
1864
|
}
|
|
1886
|
-
return /* @__PURE__ */ (0,
|
|
1865
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
1887
1866
|
"li",
|
|
1888
1867
|
{
|
|
1889
1868
|
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
1869
|
children: [
|
|
1891
1870
|
leading,
|
|
1892
|
-
/* @__PURE__ */ (0,
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1893
1872
|
"button",
|
|
1894
1873
|
{
|
|
1895
1874
|
type: "button",
|
|
1896
1875
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1897
1876
|
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
1877
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1899
|
-
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0,
|
|
1878
|
+
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
1879
|
}
|
|
1901
1880
|
),
|
|
1902
1881
|
text,
|
|
@@ -1906,7 +1885,7 @@ function GenrePlaylistTracks({
|
|
|
1906
1885
|
track.uuid
|
|
1907
1886
|
);
|
|
1908
1887
|
}),
|
|
1909
|
-
hasNextPage && /* @__PURE__ */ (0,
|
|
1888
|
+
hasNextPage && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1910
1889
|
] })
|
|
1911
1890
|
] }) });
|
|
1912
1891
|
}
|
|
@@ -1914,7 +1893,7 @@ function GenrePlaylistTracks({
|
|
|
1914
1893
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1915
1894
|
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
1916
1895
|
var import_si2 = require("react-icons/si");
|
|
1917
|
-
var
|
|
1896
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1918
1897
|
function GenreDetailExtras({
|
|
1919
1898
|
genreUuid,
|
|
1920
1899
|
genrePlaylist,
|
|
@@ -1940,17 +1919,17 @@ function GenreDetailExtras({
|
|
|
1940
1919
|
criteriaOverviewSchema
|
|
1941
1920
|
);
|
|
1942
1921
|
if (isPending) {
|
|
1943
|
-
return /* @__PURE__ */ (0,
|
|
1944
|
-
/* @__PURE__ */ (0,
|
|
1922
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
1923
|
+
/* @__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
1924
|
family
|
|
1946
1925
|
] });
|
|
1947
1926
|
}
|
|
1948
|
-
if (!overview) return /* @__PURE__ */ (0,
|
|
1927
|
+
if (!overview) return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_jsx_runtime34.Fragment, { children: family });
|
|
1949
1928
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1950
1929
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1951
|
-
return /* @__PURE__ */ (0,
|
|
1952
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0,
|
|
1953
|
-
summarySourceUrl && /* @__PURE__ */ (0,
|
|
1930
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
1931
|
+
(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: [
|
|
1932
|
+
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1954
1933
|
"a",
|
|
1955
1934
|
{
|
|
1956
1935
|
href: summarySourceUrl,
|
|
@@ -1958,12 +1937,12 @@ function GenreDetailExtras({
|
|
|
1958
1937
|
rel: "noopener noreferrer",
|
|
1959
1938
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1960
1939
|
children: [
|
|
1961
|
-
/* @__PURE__ */ (0,
|
|
1940
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_si2.SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1962
1941
|
"Wikipedia"
|
|
1963
1942
|
]
|
|
1964
1943
|
}
|
|
1965
1944
|
),
|
|
1966
|
-
wikidataUrl && /* @__PURE__ */ (0,
|
|
1945
|
+
wikidataUrl && /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(
|
|
1967
1946
|
"a",
|
|
1968
1947
|
{
|
|
1969
1948
|
href: wikidataUrl,
|
|
@@ -1971,17 +1950,17 @@ function GenreDetailExtras({
|
|
|
1971
1950
|
rel: "noopener noreferrer",
|
|
1972
1951
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1973
1952
|
children: [
|
|
1974
|
-
/* @__PURE__ */ (0,
|
|
1953
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_si2.SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1975
1954
|
"Wikidata"
|
|
1976
1955
|
]
|
|
1977
1956
|
}
|
|
1978
1957
|
)
|
|
1979
1958
|
] }) }),
|
|
1980
|
-
/* @__PURE__ */ (0,
|
|
1959
|
+
/* @__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
1960
|
family,
|
|
1982
1961
|
renderGenreDetailExtras?.(overview),
|
|
1983
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0,
|
|
1984
|
-
/* @__PURE__ */ (0,
|
|
1962
|
+
(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" }) }),
|
|
1963
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(
|
|
1985
1964
|
GenrePlaylistTracks,
|
|
1986
1965
|
{
|
|
1987
1966
|
genreUuid,
|
|
@@ -1999,10 +1978,10 @@ function GenreDetailExtras({
|
|
|
1999
1978
|
}
|
|
2000
1979
|
|
|
2001
1980
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
2002
|
-
var
|
|
1981
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2003
1982
|
var import_react14 = require("react");
|
|
2004
1983
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
2005
|
-
return /* @__PURE__ */ (0,
|
|
1984
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenrePlayActions, { genrePlaylist, playback }) });
|
|
2006
1985
|
}
|
|
2007
1986
|
function GenreInfoPanelBody({
|
|
2008
1987
|
toolbar,
|
|
@@ -2019,9 +1998,9 @@ function GenreInfoPanelBody({
|
|
|
2019
1998
|
}) {
|
|
2020
1999
|
const summary = scope === "reference" ? import_genre_tree19.GenreCatalogueCountsSchema.parse(genrePlaylist ?? catalogue) : void 0;
|
|
2021
2000
|
const selection = summary ? (0, import_genre_tree19.defaultGenreMusicSelection)(summary) : void 0;
|
|
2022
|
-
return /* @__PURE__ */ (0,
|
|
2001
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
2023
2002
|
toolbar,
|
|
2024
|
-
genrePlaylist ? /* @__PURE__ */ (0,
|
|
2003
|
+
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(GenreActionBand, { ...band }),
|
|
2025
2004
|
/* @__PURE__ */ (0, import_react14.createElement)(
|
|
2026
2005
|
GenreDetailExtras,
|
|
2027
2006
|
{
|
|
@@ -2041,7 +2020,7 @@ function GenreInfoPanelBody({
|
|
|
2041
2020
|
}
|
|
2042
2021
|
|
|
2043
2022
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
2044
|
-
var
|
|
2023
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2045
2024
|
var RELATIVE_ITEM_COUNT = 1;
|
|
2046
2025
|
function toNode(genre, parentId) {
|
|
2047
2026
|
return {
|
|
@@ -2105,19 +2084,19 @@ function useGenreDetailContent({
|
|
|
2105
2084
|
if (isError) return {
|
|
2106
2085
|
name: null,
|
|
2107
2086
|
title: "Genre unavailable",
|
|
2108
|
-
content: /* @__PURE__ */ (0,
|
|
2087
|
+
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
2088
|
};
|
|
2110
2089
|
if (isPending || !detail || !view) return {
|
|
2111
2090
|
name: null,
|
|
2112
2091
|
title: "Loading genre\u2026",
|
|
2113
|
-
content: /* @__PURE__ */ (0,
|
|
2114
|
-
/* @__PURE__ */ (0,
|
|
2115
|
-
/* @__PURE__ */ (0,
|
|
2116
|
-
/* @__PURE__ */ (0,
|
|
2092
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
2093
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.Skeleton, { className: "h-6 w-2/3" }),
|
|
2094
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.Skeleton, { className: "h-4 w-full" }),
|
|
2095
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui13.Skeleton, { className: "h-4 w-3/4" })
|
|
2117
2096
|
] })
|
|
2118
2097
|
};
|
|
2119
2098
|
const selectGenre = (nodeId) => onSelectGenre(import_genre_tree20.GenreUuidSchema.parse(nodeId));
|
|
2120
|
-
const family = /* @__PURE__ */ (0,
|
|
2099
|
+
const family = /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2121
2100
|
import_genre_tree_view4.GenreNodeFamily,
|
|
2122
2101
|
{
|
|
2123
2102
|
node: view.node,
|
|
@@ -2128,17 +2107,17 @@ function useGenreDetailContent({
|
|
|
2128
2107
|
onSelectNode: selectGenre
|
|
2129
2108
|
}
|
|
2130
2109
|
);
|
|
2131
|
-
const ancestors = /* @__PURE__ */ (0,
|
|
2110
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
2132
2111
|
return {
|
|
2133
2112
|
name: detail.name,
|
|
2134
2113
|
title: detail.name,
|
|
2135
2114
|
headerAccent: { background: view.fill, color: view.textColor },
|
|
2136
2115
|
aside: expanded ? ancestors : void 0,
|
|
2137
|
-
content: /* @__PURE__ */ (0,
|
|
2138
|
-
/* @__PURE__ */ (0,
|
|
2116
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
2117
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2139
2118
|
GenreInfoPanelBody,
|
|
2140
2119
|
{
|
|
2141
|
-
family: /* @__PURE__ */ (0,
|
|
2120
|
+
family: /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_jsx_runtime36.Fragment, { children: [
|
|
2142
2121
|
family,
|
|
2143
2122
|
!expanded && ancestors
|
|
2144
2123
|
] }),
|
|
@@ -2182,7 +2161,7 @@ function GenreDetailPanel({
|
|
|
2182
2161
|
expanded,
|
|
2183
2162
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
2184
2163
|
});
|
|
2185
|
-
return /* @__PURE__ */ (0,
|
|
2164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2186
2165
|
import_ui13.DetailPanel,
|
|
2187
2166
|
{
|
|
2188
2167
|
side: "left",
|
|
@@ -2195,7 +2174,7 @@ function GenreDetailPanel({
|
|
|
2195
2174
|
edgeTab,
|
|
2196
2175
|
aside: panel.aside,
|
|
2197
2176
|
titleInSearch,
|
|
2198
|
-
headerActions: onExpandedChange ? /* @__PURE__ */ (0,
|
|
2177
|
+
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
2178
|
children: panel.content
|
|
2200
2179
|
}
|
|
2201
2180
|
);
|
|
@@ -2204,7 +2183,7 @@ function GenreDetailPanel({
|
|
|
2204
2183
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
2205
2184
|
var import_react16 = require("react");
|
|
2206
2185
|
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2207
|
-
var
|
|
2186
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2208
2187
|
function ChangeParentPopup({
|
|
2209
2188
|
genrePlaylist,
|
|
2210
2189
|
genrePlaylists,
|
|
@@ -2239,12 +2218,12 @@ function ChangeParentPopup({
|
|
|
2239
2218
|
window.addEventListener("keydown", handleKeyDown);
|
|
2240
2219
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2241
2220
|
}, [onClose]);
|
|
2242
|
-
return /* @__PURE__ */ (0,
|
|
2243
|
-
/* @__PURE__ */ (0,
|
|
2221
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
2222
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
2244
2223
|
"Current parent: ",
|
|
2245
2224
|
genrePlaylist.parent?.name ?? "none"
|
|
2246
2225
|
] }),
|
|
2247
|
-
/* @__PURE__ */ (0,
|
|
2226
|
+
/* @__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
2227
|
GenreSearch,
|
|
2249
2228
|
{
|
|
2250
2229
|
genrePlaylists: candidates,
|
|
@@ -2252,7 +2231,7 @@ function ChangeParentPopup({
|
|
|
2252
2231
|
placeholder: "Search a new parent\u2026"
|
|
2253
2232
|
}
|
|
2254
2233
|
) }),
|
|
2255
|
-
formErrors.length > 0 && /* @__PURE__ */ (0,
|
|
2234
|
+
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
2235
|
] });
|
|
2257
2236
|
}
|
|
2258
2237
|
|
|
@@ -2265,7 +2244,7 @@ var import_lucide_react14 = require("lucide-react");
|
|
|
2265
2244
|
var import_ui14 = require("@behindthemusictree/ui");
|
|
2266
2245
|
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2267
2246
|
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2268
|
-
var
|
|
2247
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2269
2248
|
function ArtistActionBand({ artist, share }) {
|
|
2270
2249
|
const { trackList, playNewTrackListFromArtist } = (0, import_genre_tree22.useTrackList)();
|
|
2271
2250
|
const { isPlaying, setIsPlaying } = (0, import_player7.usePlayer)();
|
|
@@ -2281,11 +2260,11 @@ function ArtistActionBand({ artist, share }) {
|
|
|
2281
2260
|
console.error("Failed to load artist tracks:", error);
|
|
2282
2261
|
});
|
|
2283
2262
|
};
|
|
2284
|
-
return /* @__PURE__ */ (0,
|
|
2285
|
-
/* @__PURE__ */ (0,
|
|
2263
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_ui14.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(import_ui14.ActionBand, { children: [
|
|
2264
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2286
2265
|
import_ui14.ActionButton,
|
|
2287
2266
|
{
|
|
2288
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
2267
|
+
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
2268
|
label: playing ? "Pause" : "Play",
|
|
2290
2269
|
caption: String(artist.playableTracksCount),
|
|
2291
2270
|
disabled: artist.playableTracksCount === 0,
|
|
@@ -2304,7 +2283,7 @@ var import_ui16 = require("@behindthemusictree/ui");
|
|
|
2304
2283
|
var import_lucide_react15 = require("lucide-react");
|
|
2305
2284
|
var import_si3 = require("react-icons/si");
|
|
2306
2285
|
var import_ui15 = require("@behindthemusictree/ui");
|
|
2307
|
-
var
|
|
2286
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2308
2287
|
var LINK_KINDS = {
|
|
2309
2288
|
official: { label: "Official website", Icon: import_lucide_react15.Globe },
|
|
2310
2289
|
wikipedia: { label: "Wikipedia", Icon: import_si3.SiWikipedia },
|
|
@@ -2341,7 +2320,7 @@ function artistLinks(artist) {
|
|
|
2341
2320
|
return links;
|
|
2342
2321
|
}
|
|
2343
2322
|
function ArtistLinks({ links }) {
|
|
2344
|
-
return /* @__PURE__ */ (0,
|
|
2323
|
+
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
2324
|
}
|
|
2346
2325
|
|
|
2347
2326
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -2352,7 +2331,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
2352
2331
|
}
|
|
2353
2332
|
|
|
2354
2333
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2355
|
-
var
|
|
2334
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2356
2335
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
2357
2336
|
function ArtistHeader({ artist }) {
|
|
2358
2337
|
const fields = [];
|
|
@@ -2362,35 +2341,35 @@ function ArtistHeader({ artist }) {
|
|
|
2362
2341
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
2363
2342
|
if (years) fields.push({ label: "Active", value: years });
|
|
2364
2343
|
const links = artistLinks(artist);
|
|
2365
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0,
|
|
2344
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistLinks, { links }) });
|
|
2366
2345
|
if (fields.length === 0) return null;
|
|
2367
|
-
return /* @__PURE__ */ (0,
|
|
2346
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui16.FieldList, { items: fields });
|
|
2368
2347
|
}
|
|
2369
2348
|
|
|
2370
2349
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
2371
|
-
var
|
|
2350
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2372
2351
|
function ExternalLink({ href, children }) {
|
|
2373
|
-
return /* @__PURE__ */ (0,
|
|
2352
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
2374
2353
|
}
|
|
2375
2354
|
function ArtistPhoto({ image, name }) {
|
|
2376
|
-
return /* @__PURE__ */ (0,
|
|
2377
|
-
/* @__PURE__ */ (0,
|
|
2378
|
-
/* @__PURE__ */ (0,
|
|
2355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("figure", { className: "flex flex-col gap-1.5", children: [
|
|
2356
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2379
2358
|
"Photo: ",
|
|
2380
|
-
/* @__PURE__ */ (0,
|
|
2359
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2381
2360
|
",",
|
|
2382
2361
|
" ",
|
|
2383
|
-
image.licenseUrl ? /* @__PURE__ */ (0,
|
|
2362
|
+
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
2384
2363
|
] })
|
|
2385
2364
|
] });
|
|
2386
2365
|
}
|
|
2387
2366
|
|
|
2388
2367
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2389
2368
|
var import_ui17 = require("@behindthemusictree/ui");
|
|
2390
|
-
var
|
|
2369
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2391
2370
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2392
2371
|
if (memberships.length === 0) return null;
|
|
2393
|
-
return /* @__PURE__ */ (0,
|
|
2372
|
+
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
2373
|
const details = [
|
|
2395
2374
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2396
2375
|
...membership.roles
|
|
@@ -2398,9 +2377,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2398
2377
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
2399
2378
|
return (
|
|
2400
2379
|
// A member can have several periods in the same group.
|
|
2401
|
-
/* @__PURE__ */ (0,
|
|
2402
|
-
/* @__PURE__ */ (0,
|
|
2403
|
-
detailsText && /* @__PURE__ */ (0,
|
|
2380
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
2381
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
2382
|
+
detailsText && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2404
2383
|
" \u2014 ",
|
|
2405
2384
|
detailsText
|
|
2406
2385
|
] })
|
|
@@ -2411,9 +2390,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2411
2390
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2412
2391
|
if (memberships.length === 0) return null;
|
|
2413
2392
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2414
|
-
return /* @__PURE__ */ (0,
|
|
2415
|
-
/* @__PURE__ */ (0,
|
|
2416
|
-
/* @__PURE__ */ (0,
|
|
2393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_ui17.PanelSection, { title, children: [
|
|
2394
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2417
2396
|
MembershipList,
|
|
2418
2397
|
{
|
|
2419
2398
|
title: "Past",
|
|
@@ -2426,7 +2405,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2426
2405
|
|
|
2427
2406
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2428
2407
|
var import_ui18 = require("@behindthemusictree/ui");
|
|
2429
|
-
var
|
|
2408
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2430
2409
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2431
2410
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
2432
2411
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -2446,12 +2425,12 @@ function byYear(a, b) {
|
|
|
2446
2425
|
function ArtistDiscography({ albums }) {
|
|
2447
2426
|
if (albums.length === 0) return null;
|
|
2448
2427
|
const sorted = [...albums].sort(byYear);
|
|
2449
|
-
return /* @__PURE__ */ (0,
|
|
2428
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui18.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2450
2429
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2451
2430
|
if (groupAlbums.length === 0) return null;
|
|
2452
|
-
return /* @__PURE__ */ (0,
|
|
2453
|
-
/* @__PURE__ */ (0,
|
|
2454
|
-
/* @__PURE__ */ (0,
|
|
2431
|
+
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: [
|
|
2432
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2433
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2455
2434
|
] }, album.uuid)) }) }, group);
|
|
2456
2435
|
}) });
|
|
2457
2436
|
}
|
|
@@ -2463,7 +2442,7 @@ var import_lucide_react16 = require("lucide-react");
|
|
|
2463
2442
|
var import_ui19 = require("@behindthemusictree/ui");
|
|
2464
2443
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2465
2444
|
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2466
|
-
var
|
|
2445
|
+
var import_transport8 = require("@behindthemusictree/app-kit/transport");
|
|
2467
2446
|
|
|
2468
2447
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2469
2448
|
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
@@ -2473,7 +2452,7 @@ var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
2473
2452
|
var import_fa5 = require("react-icons/fa");
|
|
2474
2453
|
var import_player8 = require("@behindthemusictree/app-kit/player");
|
|
2475
2454
|
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2476
|
-
var
|
|
2455
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2477
2456
|
function TrackPositionPlayPause({
|
|
2478
2457
|
position,
|
|
2479
2458
|
uuid,
|
|
@@ -2487,14 +2466,14 @@ function TrackPositionPlayPause({
|
|
|
2487
2466
|
const isPlaying = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PLAYING;
|
|
2488
2467
|
const isPaused = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PAUSED;
|
|
2489
2468
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
2490
|
-
return /* @__PURE__ */ (0,
|
|
2469
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2491
2470
|
"div",
|
|
2492
2471
|
{
|
|
2493
2472
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
2494
2473
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
2495
2474
|
onClick: handlePlayPauseClick,
|
|
2496
2475
|
children: [
|
|
2497
|
-
/* @__PURE__ */ (0,
|
|
2476
|
+
/* @__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
2477
|
"span",
|
|
2499
2478
|
{
|
|
2500
2479
|
className: "track-position-play-pause__bars",
|
|
@@ -2502,18 +2481,18 @@ function TrackPositionPlayPause({
|
|
|
2502
2481
|
role: "img",
|
|
2503
2482
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
2504
2483
|
children: [
|
|
2505
|
-
/* @__PURE__ */ (0,
|
|
2506
|
-
/* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
2484
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "track-position-play-pause__bar" })
|
|
2508
2487
|
]
|
|
2509
2488
|
}
|
|
2510
2489
|
) : position }),
|
|
2511
|
-
/* @__PURE__ */ (0,
|
|
2490
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2512
2491
|
"div",
|
|
2513
2492
|
{
|
|
2514
2493
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
2515
2494
|
"aria-hidden": "true",
|
|
2516
|
-
children: isAwaitingPlayback ? /* @__PURE__ */ (0,
|
|
2495
|
+
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
2496
|
}
|
|
2518
2497
|
)
|
|
2519
2498
|
]
|
|
@@ -2524,7 +2503,7 @@ function TrackPositionPlayPause({
|
|
|
2524
2503
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2525
2504
|
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2526
2505
|
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2527
|
-
var
|
|
2506
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2528
2507
|
function TrackItem({
|
|
2529
2508
|
track,
|
|
2530
2509
|
position,
|
|
@@ -2548,12 +2527,12 @@ function TrackItem({
|
|
|
2548
2527
|
loadTrackForPlayer(track.uuid);
|
|
2549
2528
|
}
|
|
2550
2529
|
};
|
|
2551
|
-
return /* @__PURE__ */ (0,
|
|
2530
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2552
2531
|
"div",
|
|
2553
2532
|
{
|
|
2554
2533
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
2555
2534
|
children: [
|
|
2556
|
-
isUnplayable ? /* @__PURE__ */ (0,
|
|
2535
|
+
isUnplayable ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2557
2536
|
"div",
|
|
2558
2537
|
{
|
|
2559
2538
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -2561,7 +2540,7 @@ function TrackItem({
|
|
|
2561
2540
|
"aria-disabled": "true",
|
|
2562
2541
|
children: position
|
|
2563
2542
|
}
|
|
2564
|
-
) : /* @__PURE__ */ (0,
|
|
2543
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2565
2544
|
TrackPositionPlayPause,
|
|
2566
2545
|
{
|
|
2567
2546
|
position,
|
|
@@ -2570,12 +2549,12 @@ function TrackItem({
|
|
|
2570
2549
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
2571
2550
|
}
|
|
2572
2551
|
),
|
|
2573
|
-
/* @__PURE__ */ (0,
|
|
2574
|
-
/* @__PURE__ */ (0,
|
|
2575
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0,
|
|
2552
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2553
|
+
/* @__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 }) }),
|
|
2554
|
+
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
2555
|
] }),
|
|
2577
|
-
/* @__PURE__ */ (0,
|
|
2578
|
-
renderDuration && /* @__PURE__ */ (0,
|
|
2556
|
+
/* @__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 }) : "" }),
|
|
2557
|
+
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2579
2558
|
"div",
|
|
2580
2559
|
{
|
|
2581
2560
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -2583,15 +2562,15 @@ function TrackItem({
|
|
|
2583
2562
|
children: renderDuration(track)
|
|
2584
2563
|
}
|
|
2585
2564
|
),
|
|
2586
|
-
renderActions && /* @__PURE__ */ (0,
|
|
2565
|
+
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
2566
|
]
|
|
2588
2567
|
}
|
|
2589
2568
|
);
|
|
2590
2569
|
}
|
|
2591
2570
|
|
|
2592
2571
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2593
|
-
var
|
|
2594
|
-
var SongPageSchema2 = (0,
|
|
2572
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2573
|
+
var SongPageSchema2 = (0, import_transport8.PaginatedResponseSchema)(import_genre_tree26.SongDetailedSchema);
|
|
2595
2574
|
var SORTS = [
|
|
2596
2575
|
{ ordering: "title", label: "Title" },
|
|
2597
2576
|
{ ordering: "-albumYear", label: "Year" }
|
|
@@ -2601,7 +2580,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2601
2580
|
const [ordering, setOrdering] = (0, import_react17.useState)("title");
|
|
2602
2581
|
const { playNewTrackListFromArtist } = (0, import_genre_tree26.useTrackList)();
|
|
2603
2582
|
const { playerTrackObject } = (0, import_player11.usePlayer)();
|
|
2604
|
-
const { data, isPending, isError } = (0,
|
|
2583
|
+
const { data, isPending, isError } = (0, import_transport8.usePlaybackQuery)({
|
|
2605
2584
|
getBackendBaseUrl,
|
|
2606
2585
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
2607
2586
|
queryFn: (fetchBound) => fetchBound(import_genre_tree26.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
@@ -2623,21 +2602,21 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2623
2602
|
event.stopPropagation();
|
|
2624
2603
|
void play(song.uuid);
|
|
2625
2604
|
};
|
|
2626
|
-
return /* @__PURE__ */ (0,
|
|
2627
|
-
/* @__PURE__ */ (0,
|
|
2628
|
-
/* @__PURE__ */ (0,
|
|
2605
|
+
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: [
|
|
2606
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-2", children: [
|
|
2607
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
2629
2608
|
"button",
|
|
2630
2609
|
{
|
|
2631
2610
|
type: "button",
|
|
2632
2611
|
onClick: () => void play(),
|
|
2633
2612
|
className: "flex w-fit items-center gap-1.5 px-3 py-1 text-caption font-medium bg-gray-900 text-white rounded-full hover:bg-gray-700",
|
|
2634
2613
|
children: [
|
|
2635
|
-
/* @__PURE__ */ (0,
|
|
2614
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react16.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2636
2615
|
"Play all"
|
|
2637
2616
|
]
|
|
2638
2617
|
}
|
|
2639
2618
|
),
|
|
2640
|
-
/* @__PURE__ */ (0,
|
|
2619
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2641
2620
|
"button",
|
|
2642
2621
|
{
|
|
2643
2622
|
type: "button",
|
|
@@ -2652,7 +2631,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2652
2631
|
sort.ordering
|
|
2653
2632
|
)) })
|
|
2654
2633
|
] }),
|
|
2655
|
-
/* @__PURE__ */ (0,
|
|
2634
|
+
/* @__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
2635
|
TrackItem,
|
|
2657
2636
|
{
|
|
2658
2637
|
track: song,
|
|
@@ -2661,12 +2640,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2661
2640
|
renderSongLink
|
|
2662
2641
|
}
|
|
2663
2642
|
) }, song.uuid)) }),
|
|
2664
|
-
/* @__PURE__ */ (0,
|
|
2643
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui19.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2665
2644
|
] }) });
|
|
2666
2645
|
}
|
|
2667
2646
|
|
|
2668
2647
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2669
|
-
var
|
|
2648
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2670
2649
|
function useArtistPanel({
|
|
2671
2650
|
uuid,
|
|
2672
2651
|
scope,
|
|
@@ -2687,26 +2666,26 @@ function useArtistPanel({
|
|
|
2687
2666
|
return {
|
|
2688
2667
|
...panel,
|
|
2689
2668
|
title: "Artist",
|
|
2690
|
-
content: /* @__PURE__ */ (0,
|
|
2691
|
-
/* @__PURE__ */ (0,
|
|
2692
|
-
/* @__PURE__ */ (0,
|
|
2693
|
-
/* @__PURE__ */ (0,
|
|
2694
|
-
/* @__PURE__ */ (0,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2696
|
-
/* @__PURE__ */ (0,
|
|
2669
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2670
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2671
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-4 w-32" }),
|
|
2672
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2673
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-4 w-24" }),
|
|
2674
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2675
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-16" })
|
|
2697
2676
|
] })
|
|
2698
2677
|
};
|
|
2699
2678
|
case "not-found":
|
|
2700
2679
|
return {
|
|
2701
2680
|
...panel,
|
|
2702
2681
|
title: "Artist not found",
|
|
2703
|
-
content: /* @__PURE__ */ (0,
|
|
2682
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2704
2683
|
};
|
|
2705
2684
|
case "error":
|
|
2706
2685
|
return {
|
|
2707
2686
|
...panel,
|
|
2708
2687
|
title: "Artist",
|
|
2709
|
-
content: /* @__PURE__ */ (0,
|
|
2688
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2710
2689
|
};
|
|
2711
2690
|
case "success": {
|
|
2712
2691
|
const { artist } = result;
|
|
@@ -2715,19 +2694,19 @@ function useArtistPanel({
|
|
|
2715
2694
|
return {
|
|
2716
2695
|
...panel,
|
|
2717
2696
|
title: artist.name,
|
|
2718
|
-
content: /* @__PURE__ */ (0,
|
|
2719
|
-
/* @__PURE__ */ (0,
|
|
2697
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
|
|
2698
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2720
2699
|
ArtistActionBand,
|
|
2721
2700
|
{
|
|
2722
2701
|
artist,
|
|
2723
|
-
share: shareTarget && shareUrl ? /* @__PURE__ */ (0,
|
|
2702
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2724
2703
|
}
|
|
2725
2704
|
),
|
|
2726
|
-
artist.image && /* @__PURE__ */ (0,
|
|
2727
|
-
/* @__PURE__ */ (0,
|
|
2728
|
-
/* @__PURE__ */ (0,
|
|
2729
|
-
/* @__PURE__ */ (0,
|
|
2730
|
-
artist.tracksCount > 0 && /* @__PURE__ */ (0,
|
|
2705
|
+
artist.image && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2706
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistHeader, { artist }),
|
|
2707
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2708
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2709
|
+
artist.tracksCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2731
2710
|
ArtistSongs,
|
|
2732
2711
|
{
|
|
2733
2712
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2737,7 +2716,7 @@ function useArtistPanel({
|
|
|
2737
2716
|
}
|
|
2738
2717
|
)
|
|
2739
2718
|
] }),
|
|
2740
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0,
|
|
2719
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2741
2720
|
};
|
|
2742
2721
|
}
|
|
2743
2722
|
}
|
|
@@ -2753,7 +2732,7 @@ var import_lucide_react17 = require("lucide-react");
|
|
|
2753
2732
|
var import_ui21 = require("@behindthemusictree/ui");
|
|
2754
2733
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2755
2734
|
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2756
|
-
var
|
|
2735
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2757
2736
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2758
2737
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2759
2738
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
@@ -2761,27 +2740,27 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2761
2740
|
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2762
2741
|
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2763
2742
|
let body = null;
|
|
2764
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0,
|
|
2765
|
-
else if (history.status === "error") body = /* @__PURE__ */ (0,
|
|
2743
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2744
|
+
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2766
2745
|
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,
|
|
2746
|
+
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: [
|
|
2747
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2748
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2770
2749
|
" ",
|
|
2771
2750
|
"\u2014 ",
|
|
2772
2751
|
entry.oldValue ?? "none",
|
|
2773
2752
|
" \u2192 ",
|
|
2774
2753
|
entry.newValue ?? "none"
|
|
2775
2754
|
] }) : null,
|
|
2776
|
-
/* @__PURE__ */ (0,
|
|
2755
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2777
2756
|
entry.actorPseudo ?? "Anonymous",
|
|
2778
2757
|
" \xB7 ",
|
|
2779
2758
|
dateFormat.format(new Date(entry.createdOn))
|
|
2780
2759
|
] })
|
|
2781
2760
|
] }, entry.uuid)) });
|
|
2782
|
-
return /* @__PURE__ */ (0,
|
|
2783
|
-
/* @__PURE__ */ (0,
|
|
2784
|
-
/* @__PURE__ */ (0,
|
|
2761
|
+
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: [
|
|
2762
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui21.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2763
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "mt-1.5", children: body })
|
|
2785
2764
|
] }) });
|
|
2786
2765
|
}
|
|
2787
2766
|
function SongPanelContent(props) {
|
|
@@ -2800,13 +2779,13 @@ function SongPanelContent(props) {
|
|
|
2800
2779
|
const genre = song.genre;
|
|
2801
2780
|
fields.push({
|
|
2802
2781
|
label: "Genre",
|
|
2803
|
-
value: onSelectGenre ? /* @__PURE__ */ (0,
|
|
2804
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
2805
|
-
/* @__PURE__ */ (0,
|
|
2782
|
+
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: [
|
|
2783
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2806
2785
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2807
2786
|
});
|
|
2808
2787
|
} else {
|
|
2809
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */ (0,
|
|
2788
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2810
2789
|
}
|
|
2811
2790
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2812
2791
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2816,11 +2795,11 @@ function SongPanelContent(props) {
|
|
|
2816
2795
|
const links = [];
|
|
2817
2796
|
if (musicBrainzUrl)
|
|
2818
2797
|
links.push(
|
|
2819
|
-
/* @__PURE__ */ (0,
|
|
2798
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2820
2799
|
);
|
|
2821
2800
|
if (song.youtubeVideo)
|
|
2822
2801
|
links.push(
|
|
2823
|
-
/* @__PURE__ */ (0,
|
|
2802
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2824
2803
|
"a",
|
|
2825
2804
|
{
|
|
2826
2805
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2835,31 +2814,31 @@ function SongPanelContent(props) {
|
|
|
2835
2814
|
if (links.length > 0)
|
|
2836
2815
|
fields.push({
|
|
2837
2816
|
label: "Links",
|
|
2838
|
-
value: /* @__PURE__ */ (0,
|
|
2817
|
+
value: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "flex gap-3", children: links })
|
|
2839
2818
|
});
|
|
2840
|
-
return /* @__PURE__ */ (0,
|
|
2841
|
-
/* @__PURE__ */ (0,
|
|
2842
|
-
/* @__PURE__ */ (0,
|
|
2819
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_jsx_runtime48.Fragment, { children: [
|
|
2820
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(import_ui21.ActionBand, { children: [
|
|
2821
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2843
2822
|
import_ui21.ActionButton,
|
|
2844
2823
|
{
|
|
2845
|
-
icon: isPlaying ? /* @__PURE__ */ (0,
|
|
2824
|
+
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react17.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_lucide_react17.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2846
2825
|
label: isPlaying ? "Pause" : "Play",
|
|
2847
2826
|
disabled: !!unplayableReason,
|
|
2848
2827
|
title: unplayableReason ?? void 0,
|
|
2849
2828
|
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2850
2829
|
}
|
|
2851
2830
|
),
|
|
2852
|
-
shareUrl && /* @__PURE__ */ (0,
|
|
2831
|
+
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2853
2832
|
] }) }),
|
|
2854
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0,
|
|
2855
|
-
/* @__PURE__ */ (0,
|
|
2856
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0,
|
|
2857
|
-
/* @__PURE__ */ (0,
|
|
2833
|
+
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 }) }),
|
|
2834
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.FieldList, { items: fields }),
|
|
2835
|
+
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)) }) }),
|
|
2836
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2858
2837
|
] });
|
|
2859
2838
|
}
|
|
2860
2839
|
|
|
2861
2840
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2862
|
-
var
|
|
2841
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2863
2842
|
function useSongPanel({
|
|
2864
2843
|
uuid,
|
|
2865
2844
|
scope,
|
|
@@ -2880,24 +2859,24 @@ function useSongPanel({
|
|
|
2880
2859
|
return {
|
|
2881
2860
|
...panel,
|
|
2882
2861
|
title: "Song",
|
|
2883
|
-
content: /* @__PURE__ */ (0,
|
|
2884
|
-
/* @__PURE__ */ (0,
|
|
2885
|
-
/* @__PURE__ */ (0,
|
|
2886
|
-
/* @__PURE__ */ (0,
|
|
2887
|
-
/* @__PURE__ */ (0,
|
|
2862
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2863
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2864
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-4 w-32" }),
|
|
2865
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2866
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-4 w-24" })
|
|
2888
2867
|
] })
|
|
2889
2868
|
};
|
|
2890
2869
|
case "not-found":
|
|
2891
2870
|
return {
|
|
2892
2871
|
...panel,
|
|
2893
2872
|
title: "Song not found",
|
|
2894
|
-
content: /* @__PURE__ */ (0,
|
|
2873
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2895
2874
|
};
|
|
2896
2875
|
case "error":
|
|
2897
2876
|
return {
|
|
2898
2877
|
...panel,
|
|
2899
2878
|
title: "Song",
|
|
2900
|
-
content: /* @__PURE__ */ (0,
|
|
2879
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2901
2880
|
};
|
|
2902
2881
|
case "success": {
|
|
2903
2882
|
const { song } = result;
|
|
@@ -2905,7 +2884,7 @@ function useSongPanel({
|
|
|
2905
2884
|
return {
|
|
2906
2885
|
...panel,
|
|
2907
2886
|
title: song.title,
|
|
2908
|
-
content: /* @__PURE__ */ (0,
|
|
2887
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2909
2888
|
SongPanelContent,
|
|
2910
2889
|
{
|
|
2911
2890
|
song,
|
|
@@ -2958,12 +2937,12 @@ function useEntityPanel({
|
|
|
2958
2937
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2959
2938
|
var import_md2 = require("react-icons/md");
|
|
2960
2939
|
var import_ui23 = require("@behindthemusictree/ui");
|
|
2961
|
-
var
|
|
2940
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2962
2941
|
function SizeMetricToggle({
|
|
2963
2942
|
value,
|
|
2964
2943
|
onChange
|
|
2965
2944
|
}) {
|
|
2966
|
-
return /* @__PURE__ */ (0,
|
|
2945
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2967
2946
|
import_ui23.SegmentedControl,
|
|
2968
2947
|
{
|
|
2969
2948
|
variant: "floating",
|
|
@@ -2971,15 +2950,15 @@ function SizeMetricToggle({
|
|
|
2971
2950
|
value,
|
|
2972
2951
|
onChange,
|
|
2973
2952
|
options: [
|
|
2974
|
-
{ value: "songs", label: /* @__PURE__ */ (0,
|
|
2975
|
-
{ value: "views", label: /* @__PURE__ */ (0,
|
|
2953
|
+
{ 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" },
|
|
2954
|
+
{ 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
2955
|
]
|
|
2977
2956
|
}
|
|
2978
2957
|
);
|
|
2979
2958
|
}
|
|
2980
2959
|
|
|
2981
2960
|
// src/genre-tree/GenreTreeView.tsx
|
|
2982
|
-
var
|
|
2961
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2983
2962
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2984
2963
|
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
2964
|
var noop = () => {
|
|
@@ -3071,6 +3050,7 @@ function GenreTreeView({
|
|
|
3071
3050
|
isFetching: isTreeFetching,
|
|
3072
3051
|
genrePlaylistByNodeId,
|
|
3073
3052
|
visibleGenrePlaylists,
|
|
3053
|
+
focusUuids,
|
|
3074
3054
|
groupedGenrePlaylistsByRoot,
|
|
3075
3055
|
selectedGenreUuid,
|
|
3076
3056
|
selectGenre,
|
|
@@ -3130,14 +3110,14 @@ function GenreTreeView({
|
|
|
3130
3110
|
const openSongRef = (0, import_react19.useRef)(openSong);
|
|
3131
3111
|
openSongRef.current = openSong;
|
|
3132
3112
|
const resolvedRenderSongLink = (0, import_react19.useCallback)(
|
|
3133
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0,
|
|
3113
|
+
(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
3114
|
[renderSongLink]
|
|
3135
3115
|
);
|
|
3136
3116
|
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react19.useState)(null);
|
|
3137
3117
|
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react19.useState)(null);
|
|
3138
3118
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
3139
3119
|
const songBaseUrl = getBackendBaseUrl;
|
|
3140
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
3120
|
+
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
3121
|
const getGenrePath = (genre) => {
|
|
3142
3122
|
const path = [];
|
|
3143
3123
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -3179,7 +3159,7 @@ function GenreTreeView({
|
|
|
3179
3159
|
selectGenrePlaylist(genrePlaylist2);
|
|
3180
3160
|
}
|
|
3181
3161
|
});
|
|
3182
|
-
const
|
|
3162
|
+
const otherPanel = overlayPanel ?? (selectedGenreUuid !== null ? void 0 : entityPanel);
|
|
3183
3163
|
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react19.useState)(false);
|
|
3184
3164
|
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react19.useState)(false);
|
|
3185
3165
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
@@ -3207,7 +3187,7 @@ function GenreTreeView({
|
|
|
3207
3187
|
const obscuredInset = (0, import_ui24.useObscuredInset)(panelRef);
|
|
3208
3188
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
3209
3189
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
3210
|
-
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric), [visibleGenrePlaylists, nodeMetric]);
|
|
3190
|
+
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric, focusUuids), [visibleGenrePlaylists, nodeMetric, focusUuids]);
|
|
3211
3191
|
const relations = (0, import_genre_tree_view5.useGenreNodeRelations)(
|
|
3212
3192
|
treeNodes,
|
|
3213
3193
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
@@ -3218,7 +3198,7 @@ function GenreTreeView({
|
|
|
3218
3198
|
setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
3219
3199
|
}
|
|
3220
3200
|
const handlePrevious = selectionHistory.previous ? () => selectGenre(selectionHistory.previous) : void 0;
|
|
3221
|
-
const { showPopup, hidePopup } = (0,
|
|
3201
|
+
const { showPopup, hidePopup } = (0, import_popup5.usePopup)();
|
|
3222
3202
|
const reopenPanel = () => {
|
|
3223
3203
|
setUncontrolledCollapsed(false);
|
|
3224
3204
|
onCollapsedChange?.(false);
|
|
@@ -3269,7 +3249,7 @@ function GenreTreeView({
|
|
|
3269
3249
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
3270
3250
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
3271
3251
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
3272
|
-
/* @__PURE__ */ (0,
|
|
3252
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3273
3253
|
ChangeParentPopup,
|
|
3274
3254
|
{
|
|
3275
3255
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -3303,15 +3283,15 @@ function GenreTreeView({
|
|
|
3303
3283
|
const isRotationControlled = controlledAllowWheelRotation !== void 0;
|
|
3304
3284
|
const allowWheelRotation = controlledAllowWheelRotation ?? internalAllowWheelRotation;
|
|
3305
3285
|
let activePanel = null;
|
|
3306
|
-
if (
|
|
3286
|
+
if (otherPanel) {
|
|
3307
3287
|
activePanel = {
|
|
3308
|
-
title:
|
|
3309
|
-
content:
|
|
3310
|
-
aside:
|
|
3311
|
-
expanded:
|
|
3312
|
-
onExpandedChange:
|
|
3313
|
-
onClose:
|
|
3314
|
-
|
|
3288
|
+
title: otherPanel.title,
|
|
3289
|
+
content: otherPanel.content,
|
|
3290
|
+
aside: otherPanel.extraContent,
|
|
3291
|
+
expanded: otherPanel.expanded ?? false,
|
|
3292
|
+
onExpandedChange: otherPanel.onExpandedChange,
|
|
3293
|
+
onClose: otherPanel.onClose,
|
|
3294
|
+
searchName: otherPanel.title
|
|
3315
3295
|
};
|
|
3316
3296
|
} else if (selectedGenreUuid) {
|
|
3317
3297
|
activePanel = {
|
|
@@ -3321,38 +3301,28 @@ function GenreTreeView({
|
|
|
3321
3301
|
expanded: isExpanded,
|
|
3322
3302
|
onExpandedChange: changeExpanded,
|
|
3323
3303
|
onClose: clearSelection,
|
|
3324
|
-
|
|
3304
|
+
searchName: genreContent.name,
|
|
3325
3305
|
headerAccent: genreContent.headerAccent
|
|
3326
3306
|
};
|
|
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
3307
|
}
|
|
3338
3308
|
const isPanelShown = activePanel !== null && (selectedGenreUuid !== null || isTreeReady);
|
|
3339
3309
|
const detailTab = placement === "regions" && activePanel?.onExpandedChange ? {
|
|
3340
3310
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
3341
3311
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
3342
3312
|
} : void 0;
|
|
3343
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0,
|
|
3313
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3344
3314
|
import_ui24.IconButton,
|
|
3345
3315
|
{
|
|
3346
3316
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
3347
3317
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
3348
3318
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
3349
|
-
children: activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3319
|
+
children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react19.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react19.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3350
3320
|
}
|
|
3351
3321
|
) : null;
|
|
3352
3322
|
const renderArtistFilter = () => {
|
|
3353
3323
|
if (isLoading || !filterArtist) return null;
|
|
3354
|
-
return /* @__PURE__ */ (0,
|
|
3355
|
-
/* @__PURE__ */ (0,
|
|
3324
|
+
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: [
|
|
3325
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3356
3326
|
"button",
|
|
3357
3327
|
{
|
|
3358
3328
|
type: "button",
|
|
@@ -3364,7 +3334,7 @@ function GenreTreeView({
|
|
|
3364
3334
|
children: filterArtist.name
|
|
3365
3335
|
}
|
|
3366
3336
|
),
|
|
3367
|
-
/* @__PURE__ */ (0,
|
|
3337
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3368
3338
|
"button",
|
|
3369
3339
|
{
|
|
3370
3340
|
type: "button",
|
|
@@ -3376,8 +3346,8 @@ function GenreTreeView({
|
|
|
3376
3346
|
)
|
|
3377
3347
|
] });
|
|
3378
3348
|
};
|
|
3379
|
-
const actions = /* @__PURE__ */ (0,
|
|
3380
|
-
!isLoading && !isError && /* @__PURE__ */ (0,
|
|
3349
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
3350
|
+
!isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3381
3351
|
GenreTreeSearch,
|
|
3382
3352
|
{
|
|
3383
3353
|
artistBaseUrl,
|
|
@@ -3400,9 +3370,9 @@ function GenreTreeView({
|
|
|
3400
3370
|
if (songUuid) changeSong(null);
|
|
3401
3371
|
selectGenre(uuid);
|
|
3402
3372
|
},
|
|
3403
|
-
selectedName:
|
|
3373
|
+
selectedName: activePanel?.searchName ?? null,
|
|
3404
3374
|
onClear: activePanel?.onClose,
|
|
3405
|
-
showClear: activePanel
|
|
3375
|
+
showClear: activePanel !== null,
|
|
3406
3376
|
clearLabel: "Close panel",
|
|
3407
3377
|
onPrevious: handlePrevious,
|
|
3408
3378
|
onQueryChange: onSearchQueryChange,
|
|
@@ -3410,9 +3380,9 @@ function GenreTreeView({
|
|
|
3410
3380
|
extraGroups: extraSearchGroups
|
|
3411
3381
|
}
|
|
3412
3382
|
),
|
|
3413
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3414
|
-
/* @__PURE__ */ (0,
|
|
3415
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0,
|
|
3383
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3384
|
+
/* @__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: [
|
|
3385
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3416
3386
|
import_ui24.SegmentedControl,
|
|
3417
3387
|
{
|
|
3418
3388
|
"aria-label": "Tree view mode",
|
|
@@ -3426,13 +3396,13 @@ function GenreTreeView({
|
|
|
3426
3396
|
]
|
|
3427
3397
|
}
|
|
3428
3398
|
),
|
|
3429
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0,
|
|
3399
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3430
3400
|
"div",
|
|
3431
3401
|
{
|
|
3432
3402
|
className: "flex items-center gap-1",
|
|
3433
3403
|
role: "group",
|
|
3434
3404
|
"aria-label": "Tree display options",
|
|
3435
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0,
|
|
3405
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3436
3406
|
import_ui24.Button,
|
|
3437
3407
|
{
|
|
3438
3408
|
variant: allowWheelRotation ? "default" : "outline",
|
|
@@ -3443,7 +3413,7 @@ function GenreTreeView({
|
|
|
3443
3413
|
)
|
|
3444
3414
|
}
|
|
3445
3415
|
),
|
|
3446
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0,
|
|
3416
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3447
3417
|
import_ui24.IconTextButton,
|
|
3448
3418
|
{
|
|
3449
3419
|
icon: import_lucide_react18.Plus,
|
|
@@ -3453,42 +3423,43 @@ function GenreTreeView({
|
|
|
3453
3423
|
)
|
|
3454
3424
|
] })
|
|
3455
3425
|
] });
|
|
3456
|
-
return /* @__PURE__ */ (0,
|
|
3426
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
3457
3427
|
"div",
|
|
3458
3428
|
{
|
|
3459
3429
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
3460
3430
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
3461
3431
|
children: [
|
|
3462
|
-
/* @__PURE__ */ (0,
|
|
3432
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3463
3433
|
"div",
|
|
3464
3434
|
{
|
|
3465
3435
|
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
3436
|
children: actions
|
|
3467
3437
|
}
|
|
3468
3438
|
),
|
|
3469
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3439
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3470
3440
|
"div",
|
|
3471
3441
|
{
|
|
3472
3442
|
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
3443
|
children: renderArtistFilter()
|
|
3474
3444
|
}
|
|
3475
3445
|
),
|
|
3476
|
-
/* @__PURE__ */ (0,
|
|
3477
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0,
|
|
3478
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3446
|
+
/* @__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: [
|
|
3447
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
3448
|
+
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
3449
|
"Couldn't load the genre tree.",
|
|
3480
3450
|
" ",
|
|
3481
|
-
/* @__PURE__ */ (0,
|
|
3451
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
3482
3452
|
] }) : viewMode === "wheel" ? (
|
|
3483
3453
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
3484
3454
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
3485
3455
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
3486
3456
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
3487
|
-
/* @__PURE__ */ (0,
|
|
3457
|
+
/* @__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
3458
|
GenrePlaylistTreeWheel,
|
|
3489
3459
|
{
|
|
3490
3460
|
scope,
|
|
3491
3461
|
genrePlaylists: visibleGenrePlaylists,
|
|
3462
|
+
focusUuids,
|
|
3492
3463
|
handleGenreCreationAction,
|
|
3493
3464
|
handleGenreRenameAction,
|
|
3494
3465
|
additionalActions,
|
|
@@ -3501,9 +3472,9 @@ function GenreTreeView({
|
|
|
3501
3472
|
allowWheelRotation,
|
|
3502
3473
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3503
3474
|
busy,
|
|
3504
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3475
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3505
3476
|
floatingControlsLeading,
|
|
3506
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3477
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3507
3478
|
] }) : void 0,
|
|
3508
3479
|
defaultViewport,
|
|
3509
3480
|
viewportRestore,
|
|
@@ -3512,11 +3483,12 @@ function GenreTreeView({
|
|
|
3512
3483
|
) }) })
|
|
3513
3484
|
) : viewMode === "pop-core" ? (
|
|
3514
3485
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
3515
|
-
/* @__PURE__ */ (0,
|
|
3486
|
+
/* @__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
3487
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3517
3488
|
{
|
|
3518
3489
|
scope,
|
|
3519
3490
|
genrePlaylists: visibleGenrePlaylists,
|
|
3491
|
+
focusUuids,
|
|
3520
3492
|
handleGenreCreationAction,
|
|
3521
3493
|
handleGenreRenameAction,
|
|
3522
3494
|
additionalActions,
|
|
@@ -3529,9 +3501,9 @@ function GenreTreeView({
|
|
|
3529
3501
|
allowWheelRotation,
|
|
3530
3502
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3531
3503
|
busy,
|
|
3532
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3504
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3533
3505
|
floatingControlsLeading,
|
|
3534
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3506
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3535
3507
|
] }) : void 0,
|
|
3536
3508
|
defaultViewport,
|
|
3537
3509
|
viewportRestore,
|
|
@@ -3539,12 +3511,13 @@ function GenreTreeView({
|
|
|
3539
3511
|
...focus
|
|
3540
3512
|
}
|
|
3541
3513
|
) }) })
|
|
3542
|
-
) : viewMode === "outline" ? /* @__PURE__ */ (0,
|
|
3514
|
+
) : 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
3515
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3544
3516
|
{
|
|
3545
3517
|
outline: true,
|
|
3546
3518
|
scope,
|
|
3547
3519
|
genrePlaylists: visibleGenrePlaylists,
|
|
3520
|
+
focusUuids,
|
|
3548
3521
|
handleGenreCreationAction,
|
|
3549
3522
|
handleGenreRenameAction,
|
|
3550
3523
|
additionalActions,
|
|
@@ -3555,13 +3528,13 @@ function GenreTreeView({
|
|
|
3555
3528
|
selectedNodeId,
|
|
3556
3529
|
readOnly
|
|
3557
3530
|
}
|
|
3558
|
-
) }) : /* @__PURE__ */ (0,
|
|
3531
|
+
) }) : /* @__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
3532
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
3560
|
-
return /* @__PURE__ */ (0,
|
|
3533
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3561
3534
|
"div",
|
|
3562
3535
|
{
|
|
3563
3536
|
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,
|
|
3537
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3565
3538
|
GenrePlaylistTreePerRoot,
|
|
3566
3539
|
{
|
|
3567
3540
|
scope,
|
|
@@ -3574,6 +3547,7 @@ function GenreTreeView({
|
|
|
3574
3547
|
onNodeHover: handleNodeHover,
|
|
3575
3548
|
...hostPanel,
|
|
3576
3549
|
playback,
|
|
3550
|
+
focusUuids,
|
|
3577
3551
|
selectedNodeId: uuid === selectedGenrePlaylist?.root.uuid ? selectedNodeId : null,
|
|
3578
3552
|
readOnly,
|
|
3579
3553
|
wheelZoom: "modifier",
|
|
@@ -3587,13 +3561,13 @@ function GenreTreeView({
|
|
|
3587
3561
|
);
|
|
3588
3562
|
}
|
|
3589
3563
|
) }),
|
|
3590
|
-
/* @__PURE__ */ (0,
|
|
3564
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3591
3565
|
import_ui24.DetailPanel,
|
|
3592
3566
|
{
|
|
3593
3567
|
ref: panelRef,
|
|
3594
3568
|
side: "left",
|
|
3595
3569
|
title: activePanel?.title ?? "",
|
|
3596
|
-
titleInSearch:
|
|
3570
|
+
titleInSearch: !isLoading && !isError,
|
|
3597
3571
|
headerAccent: activePanel?.headerAccent,
|
|
3598
3572
|
headerActions: expandButton,
|
|
3599
3573
|
onClose: activePanel?.onClose ?? noop,
|
|
@@ -3602,8 +3576,7 @@ function GenreTreeView({
|
|
|
3602
3576
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3603
3577
|
aside: activePanel?.aside,
|
|
3604
3578
|
edgeTab: detailTab,
|
|
3605
|
-
|
|
3606
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
3579
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
3607
3580
|
activePanel.content,
|
|
3608
3581
|
activePanel.aside
|
|
3609
3582
|
] }) : activePanel?.content
|
|
@@ -3624,7 +3597,7 @@ var import_lucide_react20 = require("lucide-react");
|
|
|
3624
3597
|
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3625
3598
|
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3626
3599
|
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
3627
|
-
var
|
|
3600
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3628
3601
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react20.useEffect : import_react20.useLayoutEffect;
|
|
3629
3602
|
function TrackListSidebar({
|
|
3630
3603
|
className: className2 = "",
|
|
@@ -3726,25 +3699,25 @@ function TrackListSidebar({
|
|
|
3726
3699
|
}
|
|
3727
3700
|
};
|
|
3728
3701
|
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,
|
|
3702
|
+
return trackList ? /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3730
3703
|
"div",
|
|
3731
3704
|
{
|
|
3732
3705
|
"data-theme": "dark",
|
|
3733
3706
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3734
3707
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3735
3708
|
children: [
|
|
3736
|
-
/* @__PURE__ */ (0,
|
|
3737
|
-
/* @__PURE__ */ (0,
|
|
3738
|
-
/* @__PURE__ */ (0,
|
|
3739
|
-
/* @__PURE__ */ (0,
|
|
3740
|
-
/* @__PURE__ */ (0,
|
|
3709
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3710
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3711
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "origin flex text-xl", children: [
|
|
3712
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3713
|
+
/* @__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
3714
|
] }),
|
|
3742
|
-
/* @__PURE__ */ (0,
|
|
3715
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3743
3716
|
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
3717
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3745
3718
|
] })
|
|
3746
3719
|
] }),
|
|
3747
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0,
|
|
3720
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3748
3721
|
"button",
|
|
3749
3722
|
{
|
|
3750
3723
|
type: "button",
|
|
@@ -3753,11 +3726,11 @@ function TrackListSidebar({
|
|
|
3753
3726
|
"aria-expanded": !isCollapsed,
|
|
3754
3727
|
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
3728
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3756
|
-
children: /* @__PURE__ */ (0,
|
|
3729
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react20.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3757
3730
|
}
|
|
3758
3731
|
)
|
|
3759
3732
|
] }),
|
|
3760
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
3733
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3761
3734
|
"ul",
|
|
3762
3735
|
{
|
|
3763
3736
|
ref: trackListRef,
|
|
@@ -3767,7 +3740,7 @@ function TrackListSidebar({
|
|
|
3767
3740
|
onPointerDown: markUserScrollIntent,
|
|
3768
3741
|
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
3742
|
children: [
|
|
3770
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */ (0,
|
|
3743
|
+
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
3744
|
TrackItem,
|
|
3772
3745
|
{
|
|
3773
3746
|
track,
|
|
@@ -3778,7 +3751,7 @@ function TrackListSidebar({
|
|
|
3778
3751
|
renderSongLink
|
|
3779
3752
|
}
|
|
3780
3753
|
) }, track.uuid)),
|
|
3781
|
-
hasMore && /* @__PURE__ */ (0,
|
|
3754
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3782
3755
|
]
|
|
3783
3756
|
}
|
|
3784
3757
|
)
|
|
@@ -3798,7 +3771,7 @@ var import_ui25 = require("@behindthemusictree/ui");
|
|
|
3798
3771
|
var import_lucide_react21 = require("lucide-react");
|
|
3799
3772
|
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3800
3773
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3801
|
-
var
|
|
3774
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3802
3775
|
function PlayerControls() {
|
|
3803
3776
|
const {
|
|
3804
3777
|
duration,
|
|
@@ -3817,15 +3790,15 @@ function PlayerControls() {
|
|
|
3817
3790
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3818
3791
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3819
3792
|
const isPlaying = playState === import_player13.PlayStates.PLAYING;
|
|
3820
|
-
return /* @__PURE__ */ (0,
|
|
3793
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3821
3794
|
"section",
|
|
3822
3795
|
{
|
|
3823
3796
|
"aria-label": "Player controls",
|
|
3824
3797
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3825
3798
|
children: [
|
|
3826
|
-
/* @__PURE__ */ (0,
|
|
3827
|
-
/* @__PURE__ */ (0,
|
|
3828
|
-
/* @__PURE__ */ (0,
|
|
3799
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3800
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree33.formatTime)(safeCurrentTime) }),
|
|
3801
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3829
3802
|
"input",
|
|
3830
3803
|
{
|
|
3831
3804
|
"aria-label": "Seek",
|
|
@@ -3839,11 +3812,11 @@ function PlayerControls() {
|
|
|
3839
3812
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3840
3813
|
}
|
|
3841
3814
|
),
|
|
3842
|
-
/* @__PURE__ */ (0,
|
|
3815
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree33.formatTime)(safeDuration) })
|
|
3843
3816
|
] }),
|
|
3844
|
-
/* @__PURE__ */ (0,
|
|
3845
|
-
/* @__PURE__ */ (0,
|
|
3846
|
-
/* @__PURE__ */ (0,
|
|
3817
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3818
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3819
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3847
3820
|
"button",
|
|
3848
3821
|
{
|
|
3849
3822
|
type: "button",
|
|
@@ -3852,10 +3825,10 @@ function PlayerControls() {
|
|
|
3852
3825
|
disabled: !isReady || !hasPreviousTrack,
|
|
3853
3826
|
onClick: playPreviousTrack,
|
|
3854
3827
|
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,
|
|
3828
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react21.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3856
3829
|
}
|
|
3857
3830
|
),
|
|
3858
|
-
/* @__PURE__ */ (0,
|
|
3831
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3859
3832
|
"button",
|
|
3860
3833
|
{
|
|
3861
3834
|
type: "button",
|
|
@@ -3864,10 +3837,10 @@ function PlayerControls() {
|
|
|
3864
3837
|
disabled: !isReady,
|
|
3865
3838
|
onClick: handlePlayPauseAction,
|
|
3866
3839
|
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,
|
|
3840
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react21.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react21.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3868
3841
|
}
|
|
3869
3842
|
),
|
|
3870
|
-
/* @__PURE__ */ (0,
|
|
3843
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3871
3844
|
"button",
|
|
3872
3845
|
{
|
|
3873
3846
|
type: "button",
|
|
@@ -3876,14 +3849,14 @@ function PlayerControls() {
|
|
|
3876
3849
|
disabled: !isReady || !hasNextTrack,
|
|
3877
3850
|
onClick: playNextTrack,
|
|
3878
3851
|
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,
|
|
3852
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react21.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3880
3853
|
}
|
|
3881
3854
|
)
|
|
3882
3855
|
] }),
|
|
3883
|
-
/* @__PURE__ */ (0,
|
|
3884
|
-
volume === 0 ? /* @__PURE__ */ (0,
|
|
3885
|
-
/* @__PURE__ */ (0,
|
|
3886
|
-
/* @__PURE__ */ (0,
|
|
3856
|
+
/* @__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: [
|
|
3857
|
+
volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react21.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_lucide_react21.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3858
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "sr-only", children: "Volume" }),
|
|
3859
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3887
3860
|
"input",
|
|
3888
3861
|
{
|
|
3889
3862
|
"aria-label": "Volume",
|
|
@@ -3905,7 +3878,7 @@ function PlayerControls() {
|
|
|
3905
3878
|
}
|
|
3906
3879
|
|
|
3907
3880
|
// src/genre-tree/PlayerPanel.tsx
|
|
3908
|
-
var
|
|
3881
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
3909
3882
|
var PANEL_ID = "player-panel";
|
|
3910
3883
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3911
3884
|
function PlayerPanel({
|
|
@@ -3945,7 +3918,7 @@ function PlayerPanel({
|
|
|
3945
3918
|
onClick: () => setIsExtendRequested(true),
|
|
3946
3919
|
expanded: false
|
|
3947
3920
|
} : null;
|
|
3948
|
-
return /* @__PURE__ */ (0,
|
|
3921
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3949
3922
|
"div",
|
|
3950
3923
|
{
|
|
3951
3924
|
id: PANEL_ID,
|
|
@@ -3958,7 +3931,7 @@ function PlayerPanel({
|
|
|
3958
3931
|
),
|
|
3959
3932
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3960
3933
|
children: [
|
|
3961
|
-
/* @__PURE__ */ (0,
|
|
3934
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3962
3935
|
import_ui25.PanelEdgeTab,
|
|
3963
3936
|
{
|
|
3964
3937
|
side: "right",
|
|
@@ -3968,7 +3941,7 @@ function PlayerPanel({
|
|
|
3968
3941
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3969
3942
|
}
|
|
3970
3943
|
),
|
|
3971
|
-
/* @__PURE__ */ (0,
|
|
3944
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)(
|
|
3972
3945
|
"div",
|
|
3973
3946
|
{
|
|
3974
3947
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -3976,20 +3949,20 @@ function PlayerPanel({
|
|
|
3976
3949
|
isExtended ? "flex-row" : "flex-col"
|
|
3977
3950
|
),
|
|
3978
3951
|
children: [
|
|
3979
|
-
/* @__PURE__ */ (0,
|
|
3980
|
-
/* @__PURE__ */ (0,
|
|
3981
|
-
/* @__PURE__ */ (0,
|
|
3982
|
-
/* @__PURE__ */ (0,
|
|
3983
|
-
playerTrackObject?.loadError && /* @__PURE__ */ (0,
|
|
3952
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3953
|
+
/* @__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 }) }),
|
|
3954
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
3955
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3956
|
+
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3984
3957
|
playerTrackObject.loadError,
|
|
3985
|
-
/* @__PURE__ */ (0,
|
|
3958
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3986
3959
|
void retryPlayback();
|
|
3987
3960
|
}, children: "Retry" })
|
|
3988
3961
|
] })
|
|
3989
3962
|
] }),
|
|
3990
|
-
/* @__PURE__ */ (0,
|
|
3963
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(PlayerControls, {})
|
|
3991
3964
|
] }),
|
|
3992
|
-
/* @__PURE__ */ (0,
|
|
3965
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3993
3966
|
TrackListSidebar,
|
|
3994
3967
|
{
|
|
3995
3968
|
layout: "inline",
|
|
@@ -4016,11 +3989,11 @@ function PlayerPanel({
|
|
|
4016
3989
|
var import_uuid = require("uuid");
|
|
4017
3990
|
var import_ai = require("react-icons/ai");
|
|
4018
3991
|
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
4019
|
-
var
|
|
3992
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
4020
3993
|
function Rating({ rating, handleChange }) {
|
|
4021
3994
|
const instanceId = (0, import_uuid.v4)();
|
|
4022
|
-
return /* @__PURE__ */ (0,
|
|
4023
|
-
/* @__PURE__ */ (0,
|
|
3995
|
+
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: [
|
|
3996
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4024
3997
|
"input",
|
|
4025
3998
|
{
|
|
4026
3999
|
id: `star-${instanceId}-${i}`,
|
|
@@ -4032,16 +4005,16 @@ function Rating({ rating, handleChange }) {
|
|
|
4032
4005
|
onChange: handleChange
|
|
4033
4006
|
}
|
|
4034
4007
|
),
|
|
4035
|
-
/* @__PURE__ */ (0,
|
|
4036
|
-
/* @__PURE__ */ (0,
|
|
4008
|
+
/* @__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: [
|
|
4009
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4037
4010
|
import_ai.AiOutlineStar,
|
|
4038
4011
|
{
|
|
4039
4012
|
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
4013
|
}
|
|
4041
4014
|
),
|
|
4042
|
-
/* @__PURE__ */ (0,
|
|
4015
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "flex-grow w-8" }),
|
|
4043
4016
|
" "
|
|
4044
|
-
] }) : /* @__PURE__ */ (0,
|
|
4017
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4045
4018
|
import_ai.AiFillStar,
|
|
4046
4019
|
{
|
|
4047
4020
|
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 +4026,7 @@ function Rating({ rating, handleChange }) {
|
|
|
4053
4026
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
4054
4027
|
var import_react22 = require("react");
|
|
4055
4028
|
var import_ui26 = require("@behindthemusictree/ui");
|
|
4056
|
-
var
|
|
4029
|
+
var import_jsx_runtime56 = require("react/jsx-runtime");
|
|
4057
4030
|
function EntityDetailPanel({
|
|
4058
4031
|
scope,
|
|
4059
4032
|
getBackendBaseUrl,
|
|
@@ -4076,8 +4049,8 @@ function EntityDetailPanel({
|
|
|
4076
4049
|
getBackendBaseUrl,
|
|
4077
4050
|
getArtistBackendBaseUrl,
|
|
4078
4051
|
getShareUrl,
|
|
4079
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
4080
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0,
|
|
4052
|
+
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 })),
|
|
4053
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime56.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
4081
4054
|
song: {
|
|
4082
4055
|
uuid: songUuid,
|
|
4083
4056
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -4093,7 +4066,7 @@ function EntityDetailPanel({
|
|
|
4093
4066
|
...navigation
|
|
4094
4067
|
});
|
|
4095
4068
|
if (!panel) return null;
|
|
4096
|
-
return /* @__PURE__ */ (0,
|
|
4069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime56.jsx)(
|
|
4097
4070
|
import_ui26.DetailPanel,
|
|
4098
4071
|
{
|
|
4099
4072
|
side: "left",
|
|
@@ -4105,7 +4078,7 @@ function EntityDetailPanel({
|
|
|
4105
4078
|
onExpandedChange: panel.onExpandedChange,
|
|
4106
4079
|
aside: panel.extraContent,
|
|
4107
4080
|
edgeTab,
|
|
4108
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0,
|
|
4081
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime56.jsxs)(import_jsx_runtime56.Fragment, { children: [
|
|
4109
4082
|
panel.content,
|
|
4110
4083
|
panel.extraContent
|
|
4111
4084
|
] }) : panel.content
|