@behindthemusictree/app-kit-ui 37.1.0 → 39.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-DKQQLLMY.js → chunk-2GH7CSCE.js} +3 -3
- package/dist/{chunk-DKQQLLMY.js.map → chunk-2GH7CSCE.js.map} +1 -1
- package/dist/{chunk-57OI426Y.js → chunk-2K2SQOUJ.js} +542 -467
- package/dist/chunk-2K2SQOUJ.js.map +1 -0
- package/dist/{chunk-K4WMHUNM.js → chunk-NJYEQ3RS.js} +8 -8
- package/dist/chunk-NJYEQ3RS.js.map +1 -0
- package/dist/genre-tree/index.cjs +652 -579
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +13 -9
- package/dist/genre-tree/index.js +2 -2
- package/dist/index.cjs +658 -585
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +3 -3
- package/dist/popup/index.cjs +8 -8
- package/dist/popup/index.cjs.map +1 -1
- package/dist/popup/index.js +2 -2
- package/package.json +6 -6
- package/dist/chunk-57OI426Y.js.map +0 -1
- package/dist/chunk-K4WMHUNM.js.map +0 -1
|
@@ -48,13 +48,13 @@ __export(genre_tree_exports, {
|
|
|
48
48
|
module.exports = __toCommonJS(genre_tree_exports);
|
|
49
49
|
|
|
50
50
|
// src/genre-tree/GenreTreeView.tsx
|
|
51
|
-
var
|
|
51
|
+
var import_react19 = require("react");
|
|
52
52
|
var import_react_query3 = require("@tanstack/react-query");
|
|
53
|
-
var
|
|
54
|
-
var
|
|
55
|
-
var
|
|
53
|
+
var import_lucide_react14 = require("lucide-react");
|
|
54
|
+
var import_lucide_react15 = require("lucide-react");
|
|
55
|
+
var import_ui21 = require("@behindthemusictree/ui");
|
|
56
56
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
57
|
-
var
|
|
57
|
+
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
58
58
|
var import_popup5 = require("@behindthemusictree/app-kit/popup");
|
|
59
59
|
|
|
60
60
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
@@ -296,7 +296,7 @@ function InternalErrorPopup({ errorCode, contactEmail, ...rest }) {
|
|
|
296
296
|
" ",
|
|
297
297
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("a", { href: `mailto:${contactEmail}`, className: "text-[var(--color-primary)] hover:text-[var(--color-primary-hover)]", children: contactEmail })
|
|
298
298
|
] }) }),
|
|
299
|
-
errorCode && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "text-
|
|
299
|
+
errorCode && /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "text-body text-[var(--color-neutral-500)] bg-[var(--color-neutral-100)] p-3 rounded-lg border border-[var(--color-neutral-100)]", children: [
|
|
300
300
|
"Error Code: ",
|
|
301
301
|
errorCode
|
|
302
302
|
] })
|
|
@@ -318,21 +318,20 @@ function useGenrePlaylistPlayback({
|
|
|
318
318
|
}) {
|
|
319
319
|
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
320
320
|
const origin = trackList?.origin;
|
|
321
|
-
const
|
|
321
|
+
const playing = (0, import_react2.useMemo)(() => {
|
|
322
322
|
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
323
323
|
const playlistOrigin = origin;
|
|
324
324
|
if (playlistOrigin.artistUuid !== artist?.uuid) return null;
|
|
325
325
|
const playlist = genrePlaylists.find((item) => item.uuid === origin.uuid) ?? playlistOrigin.criteriaPlaylist;
|
|
326
326
|
const expected = scope === "reference" && playlist && !("criteria" in playlist && playlist.criteria === null) ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
327
|
-
|
|
328
|
-
return origin.uuid;
|
|
327
|
+
return { uuid: origin.uuid, selectionKey: (0, import_genre_tree2.genreMusicSelectionKey)(playlistOrigin.selection ?? expected).join() };
|
|
329
328
|
}, [origin, artist, genrePlaylists, scope]);
|
|
330
|
-
const play = (0, import_react2.useCallback)(async (playlist) => {
|
|
329
|
+
const play = (0, import_react2.useCallback)(async (playlist, requested) => {
|
|
331
330
|
if (artist && !playlist.criteria) return;
|
|
332
|
-
const selection = scope === "reference" && playlist.criteria !== null ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
331
|
+
const selection = scope === "reference" && playlist.criteria !== null ? requested ?? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
333
332
|
return selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope);
|
|
334
333
|
}, [artist, scope, playNewTrackListFromGenrePlaylist]);
|
|
335
|
-
return (0, import_react2.useMemo)(() => ({
|
|
334
|
+
return (0, import_react2.useMemo)(() => ({ playing, play }), [playing, play]);
|
|
336
335
|
}
|
|
337
336
|
|
|
338
337
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
@@ -359,7 +358,8 @@ function GenrePlaylistTreePerRoot({
|
|
|
359
358
|
}) {
|
|
360
359
|
const { isPlaying, setIsPlaying } = (0, import_player.usePlayer)();
|
|
361
360
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: genrePlaylistTreePerRoot });
|
|
362
|
-
const {
|
|
361
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
362
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
363
363
|
const { showPopup } = (0, import_popup.usePopup)();
|
|
364
364
|
const nodes = (0, import_react3.useMemo)(
|
|
365
365
|
() => genrePlaylistTreePerRoot.map((genrePlaylist) => ({
|
|
@@ -477,7 +477,8 @@ function GenrePlaylistTreeWheel({
|
|
|
477
477
|
}) {
|
|
478
478
|
const { isPlaying, setIsPlaying } = (0, import_player2.usePlayer)();
|
|
479
479
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
480
|
-
const {
|
|
480
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
481
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
481
482
|
const { showPopup } = (0, import_popup2.usePopup)();
|
|
482
483
|
const nodes = (0, import_react4.useMemo)(
|
|
483
484
|
() => genrePlaylists.map((genrePlaylist) => ({
|
|
@@ -599,7 +600,8 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
599
600
|
};
|
|
600
601
|
const { isPlaying, setIsPlaying } = (0, import_player3.usePlayer)();
|
|
601
602
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
602
|
-
const {
|
|
603
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
604
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
603
605
|
const nodes = (0, import_react5.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric), [genrePlaylists, sizeMetric]);
|
|
604
606
|
const handlePlayPause = (0, import_react5.useCallback)(
|
|
605
607
|
(nodeId) => {
|
|
@@ -786,7 +788,7 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
786
788
|
artist.disambiguation
|
|
787
789
|
] })
|
|
788
790
|
] }),
|
|
789
|
-
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "block truncate text-
|
|
791
|
+
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [
|
|
790
792
|
"also known as ",
|
|
791
793
|
artist.matchedAlias
|
|
792
794
|
] })
|
|
@@ -811,7 +813,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
811
813
|
key: song.uuid,
|
|
812
814
|
content: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
813
815
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
814
|
-
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { className: "block truncate text-
|
|
816
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.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 ") })
|
|
815
817
|
] }),
|
|
816
818
|
onSelect: () => onSelect(song)
|
|
817
819
|
})),
|
|
@@ -834,9 +836,9 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
834
836
|
content: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(import_jsx_runtime12.Fragment, { children: [
|
|
835
837
|
/* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
836
838
|
genre.name,
|
|
837
|
-
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-2 text-
|
|
839
|
+
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "ml-2 text-caption font-normal italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
838
840
|
] }),
|
|
839
|
-
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "block truncate text-
|
|
841
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: describe?.(genre) ?? `${genre.treeName} \xB7 ${genre.root.name}` })
|
|
840
842
|
] }),
|
|
841
843
|
onSelect: () => onSelect(genre)
|
|
842
844
|
})),
|
|
@@ -877,7 +879,7 @@ function GenreSearch({
|
|
|
877
879
|
key: genrePlaylist.uuid,
|
|
878
880
|
content: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
879
881
|
genrePlaylist.name,
|
|
880
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ml-2 text-
|
|
882
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
881
883
|
] }),
|
|
882
884
|
onSelect: () => select(genrePlaylist)
|
|
883
885
|
}))
|
|
@@ -952,22 +954,22 @@ function GenreTreeSearch({
|
|
|
952
954
|
}
|
|
953
955
|
|
|
954
956
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
955
|
-
var
|
|
957
|
+
var import_react15 = require("react");
|
|
956
958
|
var import_genre_tree_view4 = require("@behindthemusictree/genre-tree-view");
|
|
957
|
-
var
|
|
958
|
-
var
|
|
959
|
-
var
|
|
959
|
+
var import_ui10 = require("@behindthemusictree/ui");
|
|
960
|
+
var import_lucide_react9 = require("lucide-react");
|
|
961
|
+
var import_genre_tree20 = require("@behindthemusictree/app-kit/genre-tree");
|
|
960
962
|
|
|
961
963
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
962
|
-
var
|
|
963
|
-
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
964
|
-
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
964
|
+
var import_genre_tree19 = require("@behindthemusictree/app-kit/genre-tree");
|
|
965
965
|
|
|
966
966
|
// src/genre-tree/GenreActionBand.tsx
|
|
967
967
|
var import_lucide_react7 = require("lucide-react");
|
|
968
|
+
var import_ui6 = require("@behindthemusictree/ui");
|
|
968
969
|
|
|
969
970
|
// src/genre-tree/ShareActionButton.tsx
|
|
970
971
|
var import_lucide_react6 = require("lucide-react");
|
|
972
|
+
var import_ui5 = require("@behindthemusictree/ui");
|
|
971
973
|
var import_popup3 = require("@behindthemusictree/app-kit/popup");
|
|
972
974
|
|
|
973
975
|
// src/genre-tree/SharePopup.tsx
|
|
@@ -995,7 +997,7 @@ function Toast({ message, onClose, durationMs = 2200 }) {
|
|
|
995
997
|
role: "status",
|
|
996
998
|
"aria-live": "polite",
|
|
997
999
|
"aria-atomic": "true",
|
|
998
|
-
className: "pointer-events-auto w-full max-w-md rounded-md bg-[var(--color-surface)] px-4 py-4 text-
|
|
1000
|
+
className: "pointer-events-auto w-full max-w-md rounded-md bg-[var(--color-surface)] px-4 py-4 text-body text-[var(--color-text)] shadow-lg ring-1 ring-black/10",
|
|
999
1001
|
children: message
|
|
1000
1002
|
}
|
|
1001
1003
|
) }),
|
|
@@ -1005,7 +1007,7 @@ function Toast({ message, onClose, durationMs = 2200 }) {
|
|
|
1005
1007
|
|
|
1006
1008
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
1007
1009
|
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1008
|
-
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-
|
|
1010
|
+
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";
|
|
1009
1011
|
function Contents({ icon, label }) {
|
|
1010
1012
|
return /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(import_jsx_runtime16.Fragment, { children: [
|
|
1011
1013
|
/* @__PURE__ */ (0, import_jsx_runtime16.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 }),
|
|
@@ -1035,9 +1037,9 @@ function SharePreviewCard({ target, url }) {
|
|
|
1035
1037
|
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "rounded-3xl bg-[var(--color-surface-muted)] p-4", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex min-h-32 overflow-hidden rounded-2xl bg-[var(--color-surface)] shadow-lg", children: [
|
|
1036
1038
|
/* @__PURE__ */ (0, import_jsx_runtime17.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_runtime17.jsx)(Icon, { "aria-hidden": "true", className: "h-10 w-10" }) }),
|
|
1037
1039
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
1038
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-
|
|
1040
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
1039
1041
|
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
1040
|
-
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate text-
|
|
1042
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
1041
1043
|
] })
|
|
1042
1044
|
] }) });
|
|
1043
1045
|
}
|
|
@@ -1178,8 +1180,8 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1178
1180
|
}
|
|
1179
1181
|
)
|
|
1180
1182
|
] }),
|
|
1181
|
-
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { role: "alert", className: "text-center text-
|
|
1182
|
-
shareError && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { role: "alert", className: "text-center text-
|
|
1183
|
+
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: "Could not copy the link." }),
|
|
1184
|
+
shareError && /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
1183
1185
|
] })
|
|
1184
1186
|
}
|
|
1185
1187
|
),
|
|
@@ -1194,18 +1196,14 @@ function ShareActionButton({ target, url }) {
|
|
|
1194
1196
|
const openSharePopup = () => {
|
|
1195
1197
|
showPopup(/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SharePopup, { target, url, onClose: hidePopup }));
|
|
1196
1198
|
};
|
|
1197
|
-
return /* @__PURE__ */ (0, import_jsx_runtime19.
|
|
1198
|
-
|
|
1199
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1200
|
+
import_ui5.ActionButton,
|
|
1199
1201
|
{
|
|
1200
|
-
|
|
1201
|
-
|
|
1202
|
-
className: "group flex flex-col items-center gap-1 w-16 text-xs text-center text-[var(--color-text)] focus-visible:outline-none",
|
|
1202
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react6.Share2, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1203
|
+
label: "Share",
|
|
1203
1204
|
"aria-label": `Share ${target.name}`,
|
|
1204
1205
|
title: `Share ${target.name}`,
|
|
1205
|
-
|
|
1206
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "flex items-center justify-center w-10 h-10 rounded-full group-focus-visible:ring-2 group-focus-visible:ring-[var(--color-focus-ring)] bg-[var(--color-surface-muted)] transition-colors group-hover:bg-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react6.Share2, { "aria-hidden": "true", className: "w-5 h-5" }) }),
|
|
1207
|
-
"Share"
|
|
1208
|
-
]
|
|
1206
|
+
onClick: openSharePopup
|
|
1209
1207
|
}
|
|
1210
1208
|
);
|
|
1211
1209
|
}
|
|
@@ -1214,8 +1212,7 @@ function ShareActionButton({ target, url }) {
|
|
|
1214
1212
|
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1215
1213
|
function GenreActionBand({
|
|
1216
1214
|
node,
|
|
1217
|
-
|
|
1218
|
-
isPlaying = false,
|
|
1215
|
+
playActions,
|
|
1219
1216
|
onZoomIn,
|
|
1220
1217
|
onAddChild,
|
|
1221
1218
|
onRename,
|
|
@@ -1229,14 +1226,6 @@ function GenreActionBand({
|
|
|
1229
1226
|
}) {
|
|
1230
1227
|
const items = [];
|
|
1231
1228
|
const adminItems = [];
|
|
1232
|
-
if (onPlayPause) {
|
|
1233
|
-
items.push({
|
|
1234
|
-
key: "play-pause",
|
|
1235
|
-
label: isPlaying ? "Pause" : "Play",
|
|
1236
|
-
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react7.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1237
|
-
onClick: onPlayPause
|
|
1238
|
-
});
|
|
1239
|
-
}
|
|
1240
1229
|
if (onZoomIn) {
|
|
1241
1230
|
items.push({
|
|
1242
1231
|
key: "zoom-in",
|
|
@@ -1273,66 +1262,147 @@ function GenreActionBand({
|
|
|
1273
1262
|
disabled: action.enabled ? !action.enabled(node) : false
|
|
1274
1263
|
});
|
|
1275
1264
|
}
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1265
|
+
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ui6.ActionButton, { icon: item.icon, label: item.label, disabled: item.disabled, title: item.title, onClick: item.onClick }, item.key));
|
|
1266
|
+
if (!playActions && items.length === 0 && adminItems.length === 0 && !(shareTarget && shareUrl)) return null;
|
|
1267
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_ui6.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(
|
|
1268
|
+
import_ui6.ActionBand,
|
|
1279
1269
|
{
|
|
1280
|
-
|
|
1281
|
-
|
|
1282
|
-
title: item.title,
|
|
1283
|
-
onClick: item.onClick,
|
|
1284
|
-
className: "group flex flex-col items-center gap-1 w-16 text-xs text-center text-[var(--color-text)] focus-visible:outline-none disabled:opacity-50",
|
|
1270
|
+
className: "genre-action-band",
|
|
1271
|
+
section: { title: "Admin", label: "Admin actions", children: renderItems(adminItems) },
|
|
1285
1272
|
children: [
|
|
1286
|
-
|
|
1287
|
-
|
|
1273
|
+
playActions,
|
|
1274
|
+
renderItems(items),
|
|
1275
|
+
shareTarget && shareUrl && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
1288
1276
|
]
|
|
1289
|
-
}
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
|
|
1294
|
-
|
|
1295
|
-
|
|
1277
|
+
}
|
|
1278
|
+
) });
|
|
1279
|
+
}
|
|
1280
|
+
|
|
1281
|
+
// src/genre-tree/GenrePlayActions.tsx
|
|
1282
|
+
var import_lucide_react8 = require("lucide-react");
|
|
1283
|
+
var import_ui7 = require("@behindthemusictree/ui");
|
|
1284
|
+
var import_genre_tree10 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1285
|
+
var import_player4 = require("@behindthemusictree/app-kit/player");
|
|
1286
|
+
|
|
1287
|
+
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1288
|
+
var import_react11 = require("react");
|
|
1289
|
+
|
|
1290
|
+
// src/genre-tree/regionGlobePaths.ts
|
|
1291
|
+
var REGION_GLOBE_PATHS = {
|
|
1292
|
+
africa: "M491.879,156.348c-19.45-45.96-51.89-85.017-92.734-112.614C358.3,16.13,308.964-0.008,256.004,0 c-35.306,0-69.02,7.163-99.654,20.122c-45.961,19.45-85.017,51.89-112.614,92.734C16.13,153.701-0.008,203.036,0,255.996 c0,35.306,7.163,69.02,20.122,99.654c19.45,45.961,51.882,85.017,92.735,112.614c40.844,27.605,90.18,43.743,143.147,43.735 c35.299,0,69.012-7.163,99.648-20.121c45.96-19.45,85.017-51.882,112.614-92.735c27.604-40.844,43.742-90.18,43.734-143.147 C512,220.698,504.837,186.984,491.879,156.348z M241.412,128.135c3.914-1.382,10.421,3.07,8.843,7.272 c-2.624,6.983,6.491,10.436,9.49,14.474c2.624,3.522,7.585,14.708-3.148,12.567c-5.094-1.015-6.866,5.234-13.623,1.313 c1.672-2.382,8.382-17.825,3.312-17.583C243.202,146.327,238.367,131.188,241.412,128.135z M233.812,142.281 C231.43,142.96,235.648,141.75,233.812,142.281c8.499-2.437,8.859,11.693,4.882,14.872c-8.303,6.617-8.654-0.328-7.241-5.96 C232.086,148.71,225.009,144.804,233.812,142.281z M48.445,168.331c5.914-13.966,13.224-27.199,21.708-39.572 c3.796-0.343,6.022-2.077,11.201-6.788c4.898,5.999,9.787,11.998,14.693,17.997c1.5,1.836-3.25,4.109-0.938,6.194 c2.921,2.632,4.999,2.75,8.053-0.875c2.008,3.632,4.007,7.272,6.015,10.905c-6.03,2.484-11.014,5.296-17.52,5.171 c-10.319-0.218-15.404-1.18-23.465,5.725c3.374,5.32,7.108,1.96,11.654,0c-2.07,6.093,0.914,14.842,7.897,15.802 c-3.078,2.96-6.163,5.913-9.233,8.874c-1.413,1.359-5.233-3.586-0.921-6.616c-1.57-1.203-4.835-2.562-6.764-3.015 c-0.618,7.194-7.491,2.984-10.53,7.522c-3.312,4.937,3.132,8.022-4.078,10.085c-12.084,3.452-8.655,15.88-17.872,23.019 c-0.952,0.742-3.358,2.203-5.678,3.835C35.322,206.184,40.712,186.641,48.445,168.331z M73.246,276.415 c-0.664-0.383-1.336-0.774-2.008-1.164c-0.468-2.203,5.586-1.289,6.374-0.657C79.464,276.071,73.745,276.321,73.246,276.415z M50.687,273.158c0.961,0.328,1.804,0.171,2.539-0.477c-0.938-0.758-1.945-1.414-3.008-1.96 c-0.875-3.484,18.575,2.672,15.818,4.226c-2,1.133-19.754,1.282-18.84-0.578c0.89-1.116,2.062-1.523,3.484-1.21 C49.5,272.712,50.203,272.978,50.687,273.158z M30.846,260.792c7.421,2.101,14.67,5.077,15.826,5.842 c0.305,0.211-2.733,1.437-1.758,1.765c0.985,0.227,1.906,0.586,2.796,1.055c0.875,0.726-12.068,3.663-11.31,0.695 c0.64-0.828,1.367-1.578,2.172-2.265c-0.149,0.203-3.766-1.781-7.656-3.609C30.877,263.12,30.877,261.948,30.846,260.792z M34.893,273.915c1.336-0.274,9.084,1.78,5.686,3.507c-1.148-0.164-2.296-0.336-3.437-0.508 C34.838,276.477,34.088,275.477,34.893,273.915z M167.386,365.564c-4.898,5.21-4.71,7.397-5.366,13.959 c-0.867,8.631-1.936,25.558-11.646,26.207c-15.982,1.062-20.544,14.216-25.082,26.69c-0.718,2-1.531,3.726-2.398,5.265 c-20.926-15.364-39.134-34.228-53.678-55.764c-15.63-23.152-27.042-49.336-33.213-77.502c2.265,1.031,3.171,3.312,3.179,5.663 c0,0.023,0,0.054,0,0.086c0.141-0.187,0.258-0.382,0.43-0.562c1.555-1.952,13.935-20.379,12.92-7.843 c6.999,1.445,6.038-3.921,11.154-4.772c5.499-0.914,6.788,7.108,12.201,5.39c9.498-3.023,10.186-1.555,15.411,6.288 c5.366,8.046,18.419,4.75,25.636,9.819c5.812,4.085,6.866,8.779,7.702,15.614c0.344,2.858,11.78,3.25,14.466,3.25 c2.867,0,2.429,4.062,3.655,5.6c1,1.258,5.07,0.797,6.374,0.968c6.592,0.829,14.076,2.632,19.466,6.687 C174.776,355.253,171.729,360.932,167.386,365.564z M195.304,92.75c1.585-0.336,4.342,2.726,5.248,2.125 c3.203-2.149,2.492-2.289,7.171-2.554c1.274-0.07,20.646,1.429,15.357,6.74c-0.007,0.008-0.007,0.008-0.007,0.008 c0,0.008,0,0.008-0.008,0.008c-7.452,7.436-13.256,4.96-21.988,4.96C197.318,104.037,187.977,94.265,195.304,92.75z M415.758,398.574c-3.179,10.991-2.187,13.771-12.842,17.474c-3.343-10.388-2.257-16.716-2.257-27.448 c0-0.367,14.552-13.873,16.169-15.802C421.984,382.646,418.766,388.177,415.758,398.574z M481.068,264.502 c-2.241-2.828-4.249-6.178-6.327-8.264c-4.491-4.491-16.732-0.938-23.738-1.882c-6.179-0.828-7.726,0.218-9.905-5.586 c-1.156-3.085-5.343,0.203-8.21,0.477c-8.694,0.82-12.56-13.334-20.575-8.803c2.578,4.038,10.365,16.24,13.584,17.31 c6.514,2.172,4.96-6.835,12.74-4.522c-0.618,2.366,0.281,5.155-0.375,7.514c22.738-5.748,3.14,23.129-6.905,20.981 c-2.75-0.594-1.695,3.5-4.601,4.343c-4.452,1.304-8.905,2.601-13.365,3.898c-5.648,1.648-10.654,5.758-13.842,0.297 c-7.428-12.724-12.263-28.401-21.621-38.658c-1.616-1.773-4.421-4.444-6.452-7.373c0.078,0.234,0.148,0.484,0.234,0.718 c-1.804-1.313-4.476-1.469-6.397-2.624c-2.321,6.444,6.491,15.021,10.177,20.285c4.75,6.781,5.882,16.154,10.882,22.575 c2.148,2.765,6.022,4.139,7.974,7.076c1.657,2.484,5.156,10.655,7.82,11.725c4.077,1.64,17.302-4.468,21.808-5.64 c-2.398,5.765-7.678,25.332-13.224,27.816c-10.6,4.75-13.278,9.03-20.113,18.677c-0.539,0.75-5.554,6.256-5.617,6.007 c1.266,4.944,2.531,9.888,3.789,14.832c0.936,3.664,2.336,20.138-0.485,20.966c-13.006,3.859-13.966,7.514-14.286,20.708 c-0.133,5.429-6.46,13.091-10.506,17.739c-5.936,6.819-10.545,15.99-19.715,17.263c-8.491,1.179-16.997,2.28-25.512,3.39 c0-6.881,0.633-9.397-3.694-14.583c-5.085-6.101-5.827-7.859-6.843-15.74c-1.141-8.905-11.92-21.231-9.428-29.058 c4.906-15.381,3.523-20.887-0.562-36.728c-1.226-4.773-7.186-7.343-8.413-11.803c-0.96-3.46,1.126-11.951,1.126-15.794 c-7.382,0.616-8.663,1.046-14.389-3.632c-4.694-3.835-9.194-0.352-14.747,1.445c-4.609,1.492-11.616-0.437-16.427-0.773 c-3.867-0.274-9.585,4.093-13.1,2.96c-7.413-2.39-18.2-21.575-23.309-27.644c-4.804-5.686-1.867-19.145-2.226-26.94 c-0.484-10.373,12.74-20.262,20.184-24.98c2.047-1.297,3.109-8.397,5.898-11.1c3.953-3.835,6.499-8.123,12.045-8.42 c9.764-0.516,20.903-5.335,31.026-6.764c5.632-0.797,11.272-1.594,16.912-2.39c2.328-0.329,6.475,8.389,0.758,10.1 c3.39,6.709,14.833,4.632,15.81,7.561c1.929,5.788,9.373,4.906,15.029,5.968c-0.782-14.225,10.88-3.976,17.746-2.047 c5.202,1.452,8.679-1.695,13.842-1.703c4.288-0.008,9.326,2.07,13.537,3.008c0.007,0.054,0.023,0.094,0.038,0.148 c0.07-0.328,0.157-0.656,0.29-0.984c2.812-7.03,4.178-11.21,4.178-18.724c-4.468,0.531-18.551,4.796-22.176,2.632 c-2.164-1.289-4.25-8.014-5.436-10.248c-2.062-3.906,0.687-3.859,4.265-6.194c12.318-8.03,26.535-2.484,39.892-5.366 c-1-4.85-3.57-7.178-7.14-10.154c-5.35-4.453-4.273-5.054-3.014-12.029c-3.508,1-7.015,2-10.53,3.007 c1.296,1.531,1.336,4.132,2.632,5.639c-8.828,6.148-6.359-5.163-12.404-6.006c-5.39-0.766-6.804,8.154-9.538,11.388 c-3.906,4.64,1.672,8.303-4.562,10.6c-4.351,1.602-7.241,5.577-12.217,3.952c3.664,2.024,5.882,4.976,4.882,9.022 c-1.453-0.798-3.468-0.641-4.882-1.5c0.727,1.984,0.298,4.444,1.125,6.381c-5.984-2.695-11.928-12.521-12.974-18.802 c-0.898-5.374-14.286-12.513-18.989-16.536c-7.577,8.288,13.286,12.63,15.224,19.739c-0.141-0.531-4.022,11.662-4.319,11.842 c-5.242,3.249-4.242-7.679-5.96-9.249c-5.147-4.671-15.669-19.348-21.254-14.825c-7.671,6.218-4.616-1.062-10.818,0.875 c-5.835,1.82-3.156,7.436-6.757,8.514c-9.662,2.898-2.382,5.866-8.155,10.678c-5.717,4.765-6.616,4.75-14.029,4.601 c-14.138-0.266-16.872-3.624-15.458-17.81c1.203-11.959,14.513-7.014,24.355-6.858c3.601,0.062,2.211-9.233,0.297-11.146 c-3.32-3.312-7.819-2.375-10.279-6.89c14.505-2.593,18.176-10.045,29.705-18.051c1.852-1.282,12.811-5.327,12.725-6.499 c-0.211-3.257-2.789-15.615,4.952-14.185c7.217,1.343-3.304,12.146,2.554,12.466c3.296,0.188,12.014,4.523,12.802,3.664 c4.648-5.07,10.162-3.164,16.92-2.992c2.335,0.062,5.46-11.146,6.452-13.513c8.279,8.366,6.725-2.53,5.632-7.522 c3.101,0.117,14.599,1.96,16.552-2.25c3.586-7.71-8.764-4.898-12.224-3.945c-4.085,1.11-11.778,2.039-13.349-4.327 c-0.508-2.085,4.304-12.279,6.272-13.318c5.617-2.976,7.617-5.991,1.946-10.623c-6.327-5.187-6.358,8.061-7.084,8.897 c-6.281,7.217-22.809,10.974-9.023,22.567c-4.382,0.984-6.014,3.179-6.147,7.084c-0.266,7.225,0.266,6.733-6.827,8.046 c-6.726,1.241-7.812-10.577-9.975-16.264c-4.929,5.21-15.006,14.271-19.169,2.258c-3.827-11.084,5.757-14.342,13.224-17.739 c6.351-2.882,12.646-15.802,16.95-21.387c2.531-3.273,0.43-5.117,4.234-8.257c3.788-3.116,6.96-3.483,11.826-4.577 c4.093-0.922,7.178-5.562,11.177-5.648c5.75-0.108,11.522,0.321,17.263,0.594c7.007,0.344,1.75,3.414,5.242,4.554 c5.218,1.71,10.428,3.421,15.638,5.124c5.718,1.875,17.763,6.96,13.521,12.795c-4.562,6.264-16.325-1.461-20.715-3.812 c-3.57,6.374,3.179,5.132,6.397,8.647c0.828,0.906-1.578,4.734-0.757,5.64c1.32,1.446,4.35,2.515,6.03,3.492 c5.108,2.953,3.077-8.1,1.125-6.124c2.726-2.765,4.663-2.765,9.014,0c0.641-5.827,7.257-7.913,12.037-5.265 c0.078-2.883,0.149-5.781,0.227-8.671c16.176,13.545,30.432,29.308,42.274,46.836c24.293,35.963,38.454,79.213,38.462,125.916 C481.248,258.847,481.177,261.683,481.068,264.502z M50.687,273.158c0,0,0,0-0.008,0C51.257,273.376,51.023,273.282,50.687,273.158z M432.998,199.451c0.226,1.078-5.476-4.804-5.928-5.444c-1.914-2.696-3.812-5.39-5.726-8.093 c5.89-0.257,7.695-4.014,7.523-9.389c-11.131,0-26.02,5.89-15.435,18.153c1.469,1.696,5.991,5.242,6.406,7.405 c0.305,1.578-4.391,2.858-3.906,5.32c1.586,7.904,3.742,7.17,11.428,9.725c1.952-0.141,4.163-1.555,6.022-2.25 c-1.304-2.819-4.178-6.725-4.514-9.787C428.764,204.247,433.756,203.106,432.998,199.451z",
|
|
1293
|
+
americas: "M491.875,156.347c-19.446-45.958-51.889-85.019-92.736-112.613C358.3,16.13,308.962-0.008,255.996,0 c-35.305,0-69.016,7.168-99.65,20.124C110.381,39.571,71.321,72.006,43.725,112.86C16.122,153.692-0.016,203.03,0,255.996 c-0.008,35.313,7.16,69.016,20.125,99.658c19.438,45.958,51.881,85.018,92.728,112.613C153.692,495.87,203.03,512.008,255.996,512 c35.305,0,69.016-7.168,99.649-20.125c45.966-19.446,85.018-51.882,112.621-92.736C495.87,358.308,512,308.97,512,255.996 C512,220.691,504.832,186.988,491.875,156.347z M374.27,351.228c-8.571,14.798-1.69,35.384-12.262,48.78 c-10.947,13.514-16.513,10.221-24.295,28.328c-0.853,2.36-14.742,31.917-18.211,23.122c3.054,7.854-0.383,15.66-10.357,16.274 c-7.95,0.47-2.233,5.071-4.704,8.252c-9.863,2.17-19.965,3.708-30.274,4.521c-6.928-25.299-10.74-54.6-10.565-62.972 c0.638-32.484-6.609-19.327-23.609-43.342c-11.616-16.513-21.91-34.803-21.304-55.733c-0.088,3.74,23.329-53.086,6.426-42.25 c-20.532,13.172-24.311-14.567-44.092-17.158c-10.102-1.339-7.16-11.768-18.49-9.982c-10.174,1.594-21.735-11.904-29.277-16.991 c-4.951-3.572-13.578-51.619-20.842-50.933c-10.373,0.383,7.598,33.049,3.835,34.142c-7.742,1.451-21.313-46.093-21.057-50.008 c0.39-12.63-0.83-19.75,7.527-30.251c3.245-4.226,21.718-20.475,19.773-26.304c-3.308-10.166-1.602-22.022-6.905-28.831 c4.681-3.739,9.504-7.311,14.487-10.677c10.31-6.968,21.249-13.076,32.675-18.282c1.332-0.04,2.663-0.096,3.97-0.239 c10.206-0.997,20.627-4.959,30.992-3.388c13.666,2.008,28.488,7.893,42.88,6.769c13.251-0.933,50.638-12.949,62-3.254 c5.015,4.306-56.443,21.72-58.396,30.043c-0.997,5.422,16.002,4.944,17.469,5.079c17.087,1.403-4.241,15.452,6.252,18.481 c16.114,3.891,27.738-56.338,41.205-24.844c5.502,13.06,24.406-8.547,26.543,7.566c2.153,16.951,18.426,22.684-11.506,24.885 c-28.073,2.28-4.864,14.726-23.186,22.811c-17.525,7.718-33.552,11.107-46.46,26.966c-14.559,17.987-15.954,17.389-21.671,40.408 c-3.15,12.565-19.678-8.842-13.371-16.696c-2.185,2.694-21.544-6.1-23.466-1.587c-3.755,8.706-13.961,4.035-21.982,9.369 c-10.142,6.706-20.077,28.44-9.927,38.63c8.125,8.101,36.095-17.884,37.618-9.01c1.196,6.786-9.919,11.601-8.706,18.387 c1.746,9.823,18.872-2.815,18.864,4.816c0.008,4.895-0.805,25.355,14.272,20.236c8.125-2.774,8.93,3.046,14.009,1.826 c6.96-1.683,10.07-10.963,18.275-9.752c9.766,1.427,20.714,6.371,30.074,9.13c15.213,4.504,14.535,17.214,31.463,19.821 c16.911,2.663,10.15,18.323,8.068,27.197C329.007,322.58,399.107,310.772,374.27,351.228z M440.711,127.133 c0.686,0.981,1.403,1.954,2.066,2.95c4.01,5.916,7.71,12.064,11.138,18.378c-1.443,0.494-2.806,0.893-3.851,1.012 c-4.417,0.558-11.585-3.301-12.685-4.959C436.493,143.191,439.468,131.726,440.711,127.133z M481.223,257.232 c-1.252-0.702-2.615-1.077-4.138-0.766c-5.518,1.1-26.471,6.618-34.189,5.509c-7.726-1.108-31.981-24.262-31.981-29.779 c0-5.51,1.101-26.471,3.301-29.78c2.209-3.309,14.336-18.426,18.753-25.036c4.409-6.625,11.027-15.436,16.544-16.544 c1.715-0.343,5.375-1.012,9.824-1.834c14.032,29.374,21.902,62.231,21.91,96.994C481.247,256.411,481.223,256.809,481.223,257.232z",
|
|
1294
|
+
asia: "M491.878,156.348C472.437,110.39,439.989,71.33,399.14,43.731C358.307,16.131,308.964-0.008,256,0 c-35.304,0-69.011,7.167-99.652,20.122C110.39,39.564,71.33,72.011,43.731,112.86C16.131,153.693-0.008,203.036,0,256 c0,35.304,7.167,69.02,20.122,99.653c19.442,45.957,51.889,85.016,92.738,112.616c40.832,27.6,90.176,43.74,143.14,43.731 c35.305,0,69.02-7.166,99.653-20.122c45.957-19.442,85.017-51.889,112.617-92.738c27.6-40.832,43.74-90.176,43.731-143.14 C512,220.697,504.842,186.98,491.878,156.348z M427.814,110.348c0.774,0.915,1.53,1.856,2.294,2.789 c-1.496-0.454-2.991-0.908-4.486-1.37C426.353,111.297,427.084,110.819,427.814,110.348z M382.832,101.182 C387.142,100.754,380.446,101.434,382.832,101.182c-1.798-0.126-3.159-0.858-4.066-2.177 C384.579,95.217,388.747,100.585,382.832,101.182z M290.917,81.127c1.613,4.142-9.956,0.277-11.216-0.336 c-0.739-0.739-1.294-1.58-1.663-2.52C278.021,79.203,290.388,79.749,290.917,81.127z M258.79,75.406 c2.823,0.958,14.022-1.572,14.383,1.722c0.673,6.049-3.99,0.058-4.956,0.058c-2.622,0,1.21,2.78,1.31,2.923 c-0.656-0.957-8.461-0.857-10.107-0.462C254.656,88.352,241.675,69.592,258.79,75.406z M271.711,87.026 c-3.108,1.142-8.443,0.168-11.754,0.168C253.808,85.58,276.718,85.194,271.711,87.026z M79.236,313.19 C79.06,315.812,79.346,311.544,79.236,313.19c0.042-0.663,1.126-5.755,2.084-6.049c1.513-0.453,4.613,6.999,4.487,8.041 C85.11,321.206,78.892,318.148,79.236,313.19z M136.15,339.169c-3.252-3.983-5.192-8.461-8.284-12.528 c-0.63-0.84-11.031-6.754-9.058-7.796c4.243-2.21,39.505,18.517,37.934,21.676c-0.152,0.303-7.889-6.797-9.847-5.52 c-1.302,0.848,2.689,3.932,2.689,5.419c2.016,1.033,7.149,8.646,2.932,8.872C147.862,349.545,138.872,342.512,136.15,339.169z M154.894,340.546c0.21,1.37-3.646-1.185-3.873-1.277C151.777,337.884,154.718,339.412,154.894,340.546z M151.92,353.208 c-3.898-2.487,12.569-0.554,13.459-0.487c3.252,0.243,11.418,0.076,13.552,3.974C179.569,357.862,155.574,355.544,151.92,353.208 C154.356,354.77,150.122,352.066,151.92,353.208z M188.686,317.644c4.125-4.201,8.839,3.235,9.174,2.932 c-2.596,2.369-6.486,6.94-1.252,9.671c3.932,2.058-4.672,3.537-4.672,4.268c0,2.966-4.771,10.795-7.814,12.014 c0.177-0.067-11.913-3.419-12.972-3.722c-2.638-0.764-3.445-8.082-5.058-10.426C166.093,328.036,184.51,321.895,188.686,317.644z M167.53,281.869c1.756-1.328,3.378-1.479,4.848-0.454C173.546,287.801,165.514,282.785,167.53,281.869z M195.718,306.864 c0.009-0.017,0.017-0.025,0.034-0.034c0.067-0.059,0.101-0.084,0.092-0.076c1.05-0.857,3.806-3.302,4.898-3.546 C203.716,302.529,193.676,308.502,195.718,306.864z M201.658,294.278c-0.563-3.353-0.151-3.974,0.093-6.68 c0.428-4.713,5.915-6.772,7.007-1.092c0.193,0.975-5.721,9.88-1.218,9.317c3.612-0.454,6.301-0.622,5.134,3.932 c-1.076-0.714-7.814-4.075-8.637-3.898c-0.798,0.168-3.36,8.746-6.049,7.939C199.162,304.151,201.809,295.95,201.658,294.278z M200.734,269.073c0.084-1.328,2.042-5.125,4.176-4.688c2.461,0.513-0.731,10.141-2.487,9.032c-1.26-1.193-1.823-2.639-1.689-4.335 C200.7,269.678,200.608,271.199,200.734,269.073z M213.479,300.403c0.016-0.008,0.016-0.016,0.034-0.016 c4.797-2.42,3.452,4.218,3.965,4.452C216.831,304.546,213.101,300.613,213.479,300.403z M218.184,308.04 C217.26,307.889,219.276,308.217,218.184,308.04c1.521,0.244,2.269,3.369,2.42,4.378c0.621,4.243,0.546,2.411-2.26,3.52 c-0.765,0.294,0.084,2.747-1.672,2.865c-0.84,0.05-5.436-0.908-3.948-2.672c3.091-3.663-5.663-0.815-5.663-1.134 c0-1.227,1.386-4.075,3.184-3.697C215.504,312.384,215.58,307.62,218.184,308.04z M223.435,335.086 c-1.311-1.748-0.118-6.075,1.159-7.512c-1.016,1.142,2.706,3.058,2.882,2.26C227.081,331.632,223.661,335.388,223.435,335.086z M230.03,343.202c-0.076-0.739-6.041-0.588-6.948-0.73C221.51,342.471,229.593,338.766,230.03,343.202z M223.704,262.839 c-3.907,0.89,0.816-2.747,1.664-2.823C226.518,259.907,223.914,262.554,223.704,262.839z M222.393,355.989 c1.529,3.941-8.503,4.672-9.906,5.008c1.076-0.261,7.284-2.588,7.898-4.26C220.494,356.426,221.612,353.964,222.393,355.989z M200.557,343.369c-2.243,1.227,0.21,5.831-2.16,6.066c-3.503,0.352-1.638-8.755-0.866-11.208 c3.798-11.998,9.352,4.495,12.469-3.47c-0.252,0.647-10.847-2.655-9.091-3.201c0.025-0.008,0.051-0.008,0.076-0.017 c2.89-0.873,12.997-3.184,15.408-2.596c0.571,0.134-6.662,10.132-10.636,9.83c4.798,0.369,2.705,7.419,0.941,9.351 c-0.63,0.689,4.411,2.646,3.722,3.117C207.993,352.914,197.574,345,200.557,343.369z M206.497,356.938 c0.597,0.303-2.731,1.025-3.159,1.109c-1.377,0.47-2.688,0.412-3.932-0.176C198.465,357.115,205.691,356.535,206.497,356.938z M199.297,358.946c-0.647,0.404-1.336,0.404-2.067,0C195.256,357.744,198.348,357.938,199.297,358.946z M205.548,300.05 c0,0,0,0-0.009,0c-0.025-0.025-0.051-0.042-0.076-0.058c0.017,0.008,0.034,0.025,0.058,0.041c-0.235-0.159-2.68-1.814-0.84-2.008 C207.278,297.757,205.582,300.076,205.548,300.05z M208.783,308.284c-2.798,0-3.016-4.05-3.134-5.621 C207.748,296.421,209.429,308.284,208.783,308.284z M209.975,358.132c0.74-0.387,8.208-2.403,7.704-1.613 c-0.471,0.748-8.838,4.604-9.679,2.924C208.228,358.527,208.883,358.09,209.975,358.132z M218.839,343.202c0.008,0,0.017,0,0.017,0 c-0.026,0-0.009,0-0.026,0c-1.142,0.051-1.622-0.328-1.403-1.143c2.445-1.126,3.344,1.303,1.429,1.143 C219.318,343.244,219.091,343.226,218.839,343.202z M209.707,304.738c-0.093-0.042-0.06-0.025-0.009-0.008 c-1.294-0.512-0.109-3.394,1.084-2.118C211.177,303.041,210.454,305.016,209.707,304.738z M212.244,305.528 c-0.084,0.68-0.605,3.453-1.84,3.453c-0.218-0.74-0.218-1.479,0-2.218C210.539,305.629,211.151,305.218,212.244,305.528z M202.355,305.184L202.355,305.184c-0.58,1.168-7.78,9.838-8.839,5.184C193.542,310.486,201.884,306.142,202.355,305.184z M194.903,356.737c-1.512,0.395-2.789,1.294-4.47,0.344C188.719,356.115,194.836,356.737,194.903,356.737z M187.451,356.325 c-0.992,0-0.446-0.656,0.268-0.739C188.442,355.502,188.35,356.325,187.451,356.325z M281.365,457.809 c-5.629,13.039-11.771-7.864-10.998-7.62C277.752,452.726,286.145,446.736,281.365,457.809z M293.849,421.691 c-1.949,5.721-3.814,11.728-7.343,16.845c-4.864,7.049-8.561,3.294-15.064,3.234c-3.723-0.034-2.849,2.866-6.916,1.278 c-2.285-0.899-5.402-1.597-7.444-2.916c2.521,1.63-4.394-9.427-3.764-5.411c-0.344-2.167-2.823-1.084-4.848-1.479 c1.093-1.386,1.042-3.537,2.151-4.915c-2.747-0.067-5.091,1.135-6.814,3.277c-7.738-9.561-14.93-10.452-27.372-7.327 c-2.882,0.723-8.604,5.361-10.208,5.361c-6.537,0-8.041-0.261-12.914,3.596c-3.344,2.646-11.703,0.84-12.678-3.596 c-0.446-2.016,3.218-4.797,3.226-6.89c0.008-1.327-3.84-2.596-4.31-3.94c-0.723-2.108,1-4.596-0.781-6.343 c-0.748-0.731-4.125-3.15-4.243-4.15c-0.151-1.319,2.874-2.731,2.874-4.386c0-2.336,0-4.663,0-6.999 c0-5.284,14.291-6.46,19.962-9.057c6.629-3.025,1.764-4.906,5.881-8.427c1.236-1.05,5.529,1.008,6.822,0 c0.739-0.571-0.218-3.36,0.781-4.478c1.412-1.562,7.796-8.108,8.284-1.874c0.286,3.697-0.067,3.402,3.99,3.402 c3.268,0-0.176-1.604,1.302-2.948c2.244-2.05,5-8.645,7.898-9.511c1.697-0.513,10.183,3.268,12.914,3.277 c-0.95,2.73-1.874,5.478-2.865,8.2c4.267,2.16,12.258,8.788,17.223,5.906c2.318-1.352,3.268-13.014,3.949-15.745 c2.881,4.453,7.83,7.755,9.519,12.09c2.579,6.604,6.864,6.83,10.729,12.233c3.604,5.016,6.906,9.864,9.906,15.199 C297.757,412.423,296.564,413.717,293.849,421.691z M237.466,240.155c1.05,1.444-3.789,8.956-4.907,6.982 c-0.772-1.37-0.982-4.73-1.554-6.428c-0.109-0.319-0.319-0.958,0-0.008C230.064,237.928,236.24,238.475,237.466,240.155z M267.989,202.381c3.991-0.008,4.168,5.125,8.604,3.772c-0.866,0.26,2.478,3.621-2.16,4.486c-2.916,0.529-6.965,3.73-10.166,1.63 c0.428,0.286,0.218,0.151,0.008,0.016c1.95,1.311-3.47,2.412-3.671,0.89C260.604,213.202,270.182,202.372,267.989,202.381z M268.569,177.066c0,0.092,1.604-2.21,2.252-3.176c-0.706,2.824,6.435,16.526,4.335,17.173c-1.31,0.404-3.101-2.134-3.596-1.529 c-2.209,2.697,1.74,6.83,0.479,7.973c0.319-0.286-2.958,0.723-3.772,1.193c0.017,0.152,0.042,0.236,0.067,0.236 c-0.335,0-0.302-0.093-0.067-0.236C268.023,196.458,268.712,178.62,268.569,177.066z M291.959,363.442 c-7.687,1.613-17.484-13.88-21.886-7.05c-3.151,4.89-16.854-2.201-17.409-0.083c0.782-2.992,5.84-0.933,2.579-5.294 c-2.805-3.756-6.351-3.546-10.897-4.201c-3.251-0.47-2.352-2.453-3.772-4.268c-0.874-1.117-1.832,1.958-2.689,1.639 c-0.118-0.042-4.848-6.982-4.848-7.209c5.864-7.688,7.494,2.764,10.771,4.1c6.612,2.697,6.704-4.73,13.098-1.806 c3.251,1.487,27.7,10.418,26.877,12.493c-0.428,0.496-0.949,0.874-1.571,1.118C283.382,354.77,291.144,363.618,291.959,363.442z M239.138,239.726c0-0.009,0-0.009,0-0.017c0.907-2.848,8.679-3.907,7.301-0.756C245.725,240.592,238.088,243.12,239.138,239.726z M261.218,221.948c0.008-0.176,3.126-11.066,4.722-8.15c1.756,3.218,0.95,19.433-2.874,21.769 c-0.991-0.084-1.352-0.597-1.076-1.538c0,2.05-13.325,5.05-13.14,5.234c-2.075-2.151,1.344-3.428-3.756-2.941 c0.075,0-11.309,1.487-7.746-0.546c3.798-2.168,7.074-2.714,11.527-2.798c3.646-0.067,3.319-5.276,5.94-5.511 c1.227-0.109,0.538,3.369,2.748,1.537C260.478,226.586,260.881,225.46,261.218,221.948z M292.53,351.729 c-2,0.488-7.343-2.218-5.478-2.453c-1.646,0.201-0.588,0.067,0.017-0.009c3.285-0.412,7.612-1.697,10.217-1.966 C299.899,347.041,293.539,351.486,292.53,351.729z M299.706,347.142c-0.513-0.538-0.908-1.134-1.16-1.806 C296.354,341.832,303.705,348.604,299.706,347.142z M376.371,386.555c-0.924-0.143-1.252-0.672-0.991-1.58 c0.984-2.823,3.059,1.033,3.386,1.37C377.968,386.412,377.169,386.488,376.371,386.555z M379.958,381.53 c-0.865,0,1.924-3.042,3.588-1.395C385.26,381.824,380.295,381.446,379.958,381.53z M397.502,128.882 c-4.588-0.865-3.108-4.159-6.713-4.462c-4.226-0.353-1.932,5.016-5.713,4c-13.897-3.73-0.63,5.469-4.882,9.612 c0.428-0.412-7.335-1.093-8.712-0.622c-2.815,0.966-6.738,1.622-9.108,3.352c-3.193,2.336-6.385,4.672-9.578,6.999 c-1.68,1.236-3.822-2.016-6.15-0.932c-2.731,1.269-8.78,0.513-10.595,1.697c-1.941,1.277-3.369,7.192-4.318,9.208 c-3.756,8.007-8.108,25.087-19.727,26.222c-0.572-4.79-5.957-24.718,3.73-25.752c7.747-0.84,18.82-12.014,16.728-19.845 c-7.771,0.311-3.847,4.739-7.183,6.235c-6.084,2.722-6.94-3.168-9.074-2.286c-6.377,2.655-6.974,2.454-8.284,8.755 c-0.487,2.336-8.847,0.774-11.107,0.689c-6.436-0.227-22.358-2.588-27.138,0.605c-7.427,4.957-14.854,9.914-22.282,14.871 c3.982,7.579,14.846,2.512,17.224,10.167c1.571,5.023-5.192,14.938-8.914,18.76c-3.664,3.772-7.335,7.545-11.006,11.318 c-3.512,3.612-3.991-0.488-7.352,1.411c-5.218,2.941-5.201,11.897-12.57,12.14c3.117,4.109,3.681,7.016,4.058,11.847 c0.378,4.89-3.243,4.487-8.007,6.192c-0.143-3.016-0.588-6.04,0-9.023c0.849-4.26-4.074-0.336-3.226-4.588 c1.47-7.385-7.906-3.201-11.846-2.134c0.302-2.134-0.412-4.444,0-6.561c-4.067,2.294-8.132,4.595-12.199,6.889 c3.688,3.185,6.284,7.276,11.838,4.587c0.571,4.075-3.126,4.537-6.814,6.562c5.142,3,5.436,9.83,6.948,14.779 c1.932,6.285-2.252,8.41-6.645,13.561c-4.672,5.478-5.655,6.982-12.746,8.931c-3.932,1.092-7.864,2.176-11.796,3.26 c-2,0.554-0.319,3.428-4.117,3.428c-0.982-6.73-8.847-1.386-11.258,1.512c-3.579,4.284,3.159,7.486,6.756,10.998 c9.653,9.436-3.874,15.123-10.931,19.962c-2.563-6.772-10.234-8.67-12.208-14.106c-2.689,9.838-3.285,10.074,4.033,17.568 c5.335,5.469,6.058,9.796,8.175,16.87c-4.31-1.966-9.377-2.907-11.073-7.142c-2.076-5.167-3.621-8.048-7.47-12.267 c-3.965-4.352-4.134-17.256-6.225-23.231c-1.555,1.168-4.201,1.118-5.747,2.294c-1.16-4.436-4.217-16.913-9.687-18.694 c-4.453-1.453-14.241,4.646-17.82,7.267c-4.721,3.47-15.476,8.226-15.636,14.09c-0.268,10.234-0.538,10.998-8.897,17.677 c-8.007-11.67-12.108-21.239-14.359-34.775c-7.662,3.755-11.872-6.578-16.509-10.821c-2.151-1.957-6.16-2.151-10.461-1.966 c-0.092-2.655-0.15-5.318-0.15-7.99c0-31.145,6.301-60.728,17.694-87.672c16.123-38.135,42.504-70.936,75.649-94.922 c2.142-0.05,4.251,0.286,6.326,1.294c4.025,1.966,9.368-4.974,15.392-2.924c-2.142-8.746,18.668-9.174,13.997,0.328 c4.537-1.336,8.486-3.184,13.208-2.487c7.746,1.126,5.578,2.403,4.529,9.368c-0.042,0.261-24.189,8.838-15.812,10.014 c8.108,1.143,15.132-4.327,23.542-3.713c9.687,0.698,14.005,4.89,24.424,5.184c-4.159-9.99,12.728-2.789,17.946-1.638 c-5.78,4.748,5.738,10.158,9.696,13.452c-0.143-7.301,14.871-5.973,21.6-5.629c3.706,0.194,1.983-6.638,6.57-5.839 c6.226,1.084,12.443,2.167,18.668,3.251c5.252,0.916,8.015-0.344,13.148,2.403c3.512,1.882,1.143,6.394,5.948,5.882 c3.42-0.362,11.595-2.806,14.048-0.362c3.655,3.638,1.597,7.814,7.596,9.805c1.352-6.663,12.871-6.612,18.66-4.924 c2.68,0.79,14.972,10.544,10.41-1.311c10.871,2.21,21.734,4.411,32.606,6.621c4.26,0.866,4.352,4.192,7.956,5.848 c2.344,1.076,8.856,0.748,12.2,1.966C413.851,126.9,403.425,130.008,397.502,128.882z M406.693,134.654 c0.176-0.588,0.362-1.176,0.546-1.764c1.429-1.412,9.62-1.546,10.814,0.428C419.136,135.108,407.441,135.293,406.693,134.654z M437.107,168.185c4.974-4.864,9.897-9.754,15.081-14.425c-10.149,0.513-12.468,2.932-14.358-6.562 c-2.151,1.31-4.31,2.621-6.461,3.932c-2.638-3.923-8.838-9.552-2.874-13.778c1.782-1.252,6.008,0.487,7.898-0.656 c1.832-1.1,3.293-6.008,4.31-7.873c-5.176-1.84-5.31,2.723-9.334,2.63c-3.881-0.092-9.258-3.293-12.922-4.596 c3.377-6.99,11.485-5.906,17.013-6.939c2.521,3.318,4.982,6.687,7.326,10.158c6.41,9.494,12.09,19.508,17.022,29.943 C453.406,164.791,445.156,170.715,437.107,168.185z M453.18,278.096c-1.051,0.194-1.673-1.747-0.236-1.747 C454.381,276.349,454.381,277.878,453.18,278.096z M457.011,283.785c-0.47-0.58-0.227-0.278-0.008-0.017 c-2.243-2.739-1.663-6.209,2.403-4.352C461.498,280.356,458.43,285.499,457.011,283.785z M231.005,240.701v0.008C231.055,240.86,231.089,240.945,231.005,240.701z M287.07,349.268c-0.008,0-0.008,0.009-0.017,0.009C287.608,349.2,287.414,349.226,287.07,349.268z"
|
|
1295
|
+
};
|
|
1296
|
+
var REGION_GLOBES = ["africa", "americas", "asia"];
|
|
1297
|
+
|
|
1298
|
+
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1299
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1300
|
+
var ROTATION_INTERVAL_MS = 3e3;
|
|
1301
|
+
function RegionGlobeIcon({ className: className2 }) {
|
|
1302
|
+
const [index, setIndex] = (0, import_react11.useState)(0);
|
|
1303
|
+
(0, import_react11.useEffect)(() => {
|
|
1304
|
+
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
1305
|
+
let timer;
|
|
1306
|
+
const sync = () => {
|
|
1307
|
+
clearInterval(timer);
|
|
1308
|
+
timer = reducedMotion.matches ? void 0 : setInterval(() => setIndex((i) => (i + 1) % REGION_GLOBES.length), ROTATION_INTERVAL_MS);
|
|
1309
|
+
};
|
|
1310
|
+
sync();
|
|
1311
|
+
reducedMotion.addEventListener("change", sync);
|
|
1312
|
+
return () => {
|
|
1313
|
+
reducedMotion.removeEventListener("change", sync);
|
|
1314
|
+
clearInterval(timer);
|
|
1315
|
+
};
|
|
1316
|
+
}, []);
|
|
1317
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("svg", { viewBox: "0 0 512 512", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)("path", { "data-testid": "region-globe-path", d: REGION_GLOBE_PATHS[REGION_GLOBES[index]] }) });
|
|
1318
|
+
}
|
|
1319
|
+
|
|
1320
|
+
// src/genre-tree/treeMarkPath.ts
|
|
1321
|
+
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";
|
|
1322
|
+
|
|
1323
|
+
// src/genre-tree/TreeMarkIcon.tsx
|
|
1324
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1325
|
+
function TreeMarkIcon({ className: className2 }) {
|
|
1326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("svg", { viewBox: "0 0 551 567", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { transform: "translate(0 567) scale(0.1 -0.1)", d: TREE_MARK_PATH }) });
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
// src/genre-tree/GenrePlayActions.tsx
|
|
1330
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1331
|
+
function PlayIcon({ kind }) {
|
|
1332
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("span", { "aria-hidden": "true", className: "relative flex items-center justify-center w-5 h-5", children: [
|
|
1333
|
+
kind === "tree" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1334
|
+
kind === "map" && /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1335
|
+
kind === "tree-map" && /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)(import_jsx_runtime23.Fragment, { children: [
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_50%_0_0)]" }),
|
|
1337
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_0_0_50%)]" })
|
|
1296
1338
|
] }),
|
|
1297
|
-
|
|
1298
|
-
"section",
|
|
1299
|
-
{
|
|
1300
|
-
"aria-label": "Admin actions",
|
|
1301
|
-
className: `px-3.5 py-3 ${items.length > 0 ? "border-t border-[var(--color-border)]" : ""}`,
|
|
1302
|
-
children: [
|
|
1303
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("h3", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-[var(--color-text-muted)]", children: "Admin" }),
|
|
1304
|
-
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "flex flex-wrap gap-1", children: renderItems(adminItems) })
|
|
1305
|
-
]
|
|
1306
|
-
}
|
|
1307
|
-
)
|
|
1339
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react8.Play, { className: "relative w-5 h-5 fill-[var(--color-surface)]" })
|
|
1308
1340
|
] });
|
|
1309
1341
|
}
|
|
1342
|
+
function playOptions(playlist) {
|
|
1343
|
+
if (!("genreOnlyTracksCount" in playlist)) return [{ key: "all", label: "Play", icon: "play", count: playlist.tracksCount }];
|
|
1344
|
+
const direct = { key: "direct", label: "Genre", icon: "play", selection: { coverage: "genreOnly" }, count: (0, import_genre_tree10.genreMusicCount)(playlist, { coverage: "genreOnly" }) };
|
|
1345
|
+
const scopes = playlist.genreAndSubgenresTracksCount;
|
|
1346
|
+
const inclusive = (label, icon, subgenres) => {
|
|
1347
|
+
const selection = { coverage: "genreAndSubgenres", subgenres };
|
|
1348
|
+
return { key: subgenres, label, icon, selection, count: (0, import_genre_tree10.genreMusicCount)(playlist, selection) };
|
|
1349
|
+
};
|
|
1350
|
+
return "canonical" in scopes ? [direct, inclusive("Canonical", "tree", "canonical"), inclusive("Regional", "map", "regional"), inclusive("All", "tree-map", "all")] : [direct, inclusive("All", "map", "all")];
|
|
1351
|
+
}
|
|
1352
|
+
function GenrePlayActions({ genrePlaylist, playback }) {
|
|
1353
|
+
const { isPlaying, setIsPlaying } = (0, import_player4.usePlayer)();
|
|
1354
|
+
const options = playOptions(genrePlaylist);
|
|
1355
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_jsx_runtime23.Fragment, { children: options.map((option) => {
|
|
1356
|
+
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());
|
|
1357
|
+
const playing = isCurrent && isPlaying;
|
|
1358
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(
|
|
1359
|
+
import_ui7.ActionButton,
|
|
1360
|
+
{
|
|
1361
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(import_lucide_react8.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime23.jsx)(PlayIcon, { kind: option.icon }),
|
|
1362
|
+
label: playing ? "Pause" : option.label,
|
|
1363
|
+
caption: String(option.count),
|
|
1364
|
+
disabled: option.count === 0,
|
|
1365
|
+
title: option.count === 0 ? "No playable songs" : void 0,
|
|
1366
|
+
onClick: () => {
|
|
1367
|
+
if (isCurrent) {
|
|
1368
|
+
setIsPlaying(!isPlaying);
|
|
1369
|
+
return;
|
|
1370
|
+
}
|
|
1371
|
+
playback.play(genrePlaylist, option.selection).catch((error) => {
|
|
1372
|
+
console.error("Failed to load genre playlist tracks:", error);
|
|
1373
|
+
});
|
|
1374
|
+
}
|
|
1375
|
+
},
|
|
1376
|
+
option.key
|
|
1377
|
+
);
|
|
1378
|
+
}) });
|
|
1379
|
+
}
|
|
1310
1380
|
|
|
1311
1381
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1312
|
-
var
|
|
1313
|
-
var
|
|
1382
|
+
var import_ui9 = require("@behindthemusictree/ui");
|
|
1383
|
+
var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1314
1384
|
|
|
1315
1385
|
// src/genre-tree/ClampedText.tsx
|
|
1316
|
-
var
|
|
1317
|
-
var
|
|
1386
|
+
var import_react12 = require("react");
|
|
1387
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1318
1388
|
function ClampedText({ children, className: className2 = "" }) {
|
|
1319
|
-
const ref = (0,
|
|
1320
|
-
const [expanded, setExpanded] = (0,
|
|
1321
|
-
const [overflows, setOverflows] = (0,
|
|
1322
|
-
(0,
|
|
1389
|
+
const ref = (0, import_react12.useRef)(null);
|
|
1390
|
+
const [expanded, setExpanded] = (0, import_react12.useState)(false);
|
|
1391
|
+
const [overflows, setOverflows] = (0, import_react12.useState)(false);
|
|
1392
|
+
(0, import_react12.useLayoutEffect)(() => {
|
|
1323
1393
|
const element = ref.current;
|
|
1324
1394
|
if (!element || expanded) return;
|
|
1325
1395
|
setOverflows(element.scrollHeight > element.clientHeight);
|
|
1326
1396
|
}, [children, expanded]);
|
|
1327
|
-
return /* @__PURE__ */ (0,
|
|
1328
|
-
/* @__PURE__ */ (0,
|
|
1329
|
-
(overflows || expanded) && /* @__PURE__ */ (0,
|
|
1397
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
1398
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { ref, className: `${className2} ${expanded ? "" : "line-clamp-3"}`, children }),
|
|
1399
|
+
(overflows || expanded) && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1330
1400
|
"button",
|
|
1331
1401
|
{
|
|
1332
1402
|
type: "button",
|
|
1333
1403
|
"aria-expanded": expanded,
|
|
1334
1404
|
onClick: () => setExpanded((value) => !value),
|
|
1335
|
-
className: "mt-1 text-
|
|
1405
|
+
className: "mt-1 text-caption text-[var(--color-text-muted)] underline hover:text-[var(--color-text)]",
|
|
1336
1406
|
children: expanded ? "Show less" : "Show more"
|
|
1337
1407
|
}
|
|
1338
1408
|
)
|
|
@@ -1340,36 +1410,36 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1340
1410
|
}
|
|
1341
1411
|
|
|
1342
1412
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1343
|
-
var
|
|
1413
|
+
var import_react13 = require("react");
|
|
1344
1414
|
var import_react_query = require("@tanstack/react-query");
|
|
1345
1415
|
var import_zod = require("zod");
|
|
1346
1416
|
var import_fa2 = require("react-icons/fa");
|
|
1347
|
-
var
|
|
1417
|
+
var import_ui8 = require("@behindthemusictree/ui");
|
|
1348
1418
|
var import_auth = require("@behindthemusictree/app-kit/auth");
|
|
1349
1419
|
var import_transport3 = require("@behindthemusictree/app-kit/transport");
|
|
1350
1420
|
var import_transport4 = require("@behindthemusictree/app-kit/transport");
|
|
1351
1421
|
var import_transport5 = require("@behindthemusictree/app-kit/transport");
|
|
1352
|
-
var import_player4 = require("@behindthemusictree/app-kit/player");
|
|
1353
1422
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1423
|
+
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1354
1424
|
var import_popup4 = require("@behindthemusictree/app-kit/popup");
|
|
1355
1425
|
var import_transport6 = require("@behindthemusictree/app-kit/transport");
|
|
1356
|
-
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1357
1426
|
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1358
1427
|
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1359
1428
|
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1360
1429
|
var import_genre_tree15 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1430
|
+
var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1361
1431
|
|
|
1362
1432
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1363
|
-
var
|
|
1364
|
-
var
|
|
1433
|
+
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1434
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1365
1435
|
function MusicBrainzRecordingLink({
|
|
1366
1436
|
song,
|
|
1367
1437
|
children,
|
|
1368
1438
|
className: className2 = ""
|
|
1369
1439
|
}) {
|
|
1370
|
-
const url = (0,
|
|
1371
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1372
|
-
return /* @__PURE__ */ (0,
|
|
1440
|
+
const url = (0, import_genre_tree11.musicBrainzRecordingUrl)(song);
|
|
1441
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_jsx_runtime25.Fragment, { children });
|
|
1442
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1373
1443
|
"a",
|
|
1374
1444
|
{
|
|
1375
1445
|
href: url,
|
|
@@ -1384,11 +1454,11 @@ function MusicBrainzRecordingLink({
|
|
|
1384
1454
|
}
|
|
1385
1455
|
|
|
1386
1456
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1387
|
-
var
|
|
1457
|
+
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1388
1458
|
var import_track_noun = require("@behindthemusictree/app-kit/track-noun");
|
|
1389
|
-
var
|
|
1459
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1390
1460
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1391
|
-
var SongPageSchema = (0, import_transport4.PaginatedResponseSchema)(
|
|
1461
|
+
var SongPageSchema = (0, import_transport4.PaginatedResponseSchema)(import_genre_tree15.SongDetailedSchema).extend({
|
|
1392
1462
|
overallTotal: import_zod.z.number().nullable(),
|
|
1393
1463
|
page: import_zod.z.number().nullable(),
|
|
1394
1464
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1417,9 +1487,9 @@ function GenrePlaylistTracks({
|
|
|
1417
1487
|
renderTracksToolbar,
|
|
1418
1488
|
artist = null
|
|
1419
1489
|
}) {
|
|
1420
|
-
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0,
|
|
1490
|
+
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree16.useTrackList)();
|
|
1421
1491
|
const { session, sessionRestored } = (0, import_auth.useSession)();
|
|
1422
|
-
const { playerTrackObject, playState, handlePlayPauseAction } = (0,
|
|
1492
|
+
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player5.usePlayer)();
|
|
1423
1493
|
const { showPopup } = (0, import_popup4.usePopup)();
|
|
1424
1494
|
const trackNoun = (0, import_track_noun.useTrackNoun)();
|
|
1425
1495
|
const uuid = genrePlaylist?.uuid;
|
|
@@ -1427,18 +1497,18 @@ function GenrePlaylistTracks({
|
|
|
1427
1497
|
const { fetchBound } = (0, import_transport3.usePlaybackFetch)(getBackendBaseUrl);
|
|
1428
1498
|
const playback = (0, import_transport3.usePlaybackContext)();
|
|
1429
1499
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1430
|
-
queryKey: [...scope === "me" ? uuid ?
|
|
1500
|
+
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] : []],
|
|
1431
1501
|
queryFn: async ({ pageParam }) => {
|
|
1432
1502
|
if (scope === "me") {
|
|
1433
1503
|
if (!uuid) throw new Error("Personal genre has no playlist");
|
|
1434
1504
|
return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
|
|
1435
1505
|
}
|
|
1436
1506
|
const response = await fetchBound(
|
|
1437
|
-
|
|
1507
|
+
import_genre_tree14.libraryEndpoints.reference.songs.list(),
|
|
1438
1508
|
true,
|
|
1439
1509
|
false,
|
|
1440
1510
|
{},
|
|
1441
|
-
{ genre: genreUuid, ...(0,
|
|
1511
|
+
{ genre: genreUuid, ...(0, import_genre_tree12.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1442
1512
|
);
|
|
1443
1513
|
const parsed = (0, import_transport5.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1444
1514
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
@@ -1449,8 +1519,8 @@ function GenrePlaylistTracks({
|
|
|
1449
1519
|
retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
|
|
1450
1520
|
retryDelay: 0
|
|
1451
1521
|
});
|
|
1452
|
-
const [sentinel, setSentinel] = (0,
|
|
1453
|
-
(0,
|
|
1522
|
+
const [sentinel, setSentinel] = (0, import_react13.useState)(null);
|
|
1523
|
+
(0, import_react13.useEffect)(() => {
|
|
1454
1524
|
if (!hasNextPage || isFetchingNextPage || !sentinel) return;
|
|
1455
1525
|
const observer = new IntersectionObserver((entries) => {
|
|
1456
1526
|
if (entries.some((entry) => entry.isIntersecting)) {
|
|
@@ -1472,35 +1542,35 @@ function GenrePlaylistTracks({
|
|
|
1472
1542
|
}) : 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"));
|
|
1473
1543
|
started.catch((error) => {
|
|
1474
1544
|
console.error("Failed to play genre playlist:", error);
|
|
1475
|
-
showPopup(/* @__PURE__ */ (0,
|
|
1545
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(InternalErrorPopup, { errorCode: import_transport6.ErrorCode.CLIENT_UNKNOWN }));
|
|
1476
1546
|
});
|
|
1477
1547
|
};
|
|
1478
|
-
return /* @__PURE__ */ (0,
|
|
1548
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui8.PanelSection, { title: `${(0, import_track_noun.capitalize)(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("div", { children: [
|
|
1479
1549
|
renderTracksToolbar?.(),
|
|
1480
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0,
|
|
1550
|
+
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { children: "\u2014" }) : isPending ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui8.Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("p", { role: "alert", children: [
|
|
1481
1551
|
"Couldn't load ",
|
|
1482
1552
|
trackNoun.plural,
|
|
1483
1553
|
".",
|
|
1484
1554
|
" ",
|
|
1485
|
-
/* @__PURE__ */ (0,
|
|
1486
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0,
|
|
1555
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1556
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1487
1557
|
tracks.map((track, index) => {
|
|
1488
1558
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1489
1559
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1490
|
-
const isPlaying = isCurrent && playState ===
|
|
1491
|
-
const text = /* @__PURE__ */ (0,
|
|
1492
|
-
/* @__PURE__ */ (0,
|
|
1493
|
-
track.artists?.length ? /* @__PURE__ */ (0,
|
|
1494
|
-
/* @__PURE__ */ (0,
|
|
1495
|
-
track.album && /* @__PURE__ */ (0,
|
|
1560
|
+
const isPlaying = isCurrent && playState === import_player6.PlayStates.PLAYING;
|
|
1561
|
+
const text = /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1562
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree15.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1563
|
+
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1564
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_genre_tree17.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1565
|
+
track.album && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1496
1566
|
] });
|
|
1497
1567
|
const leading = renderSongLeading?.(track, index);
|
|
1498
1568
|
const actions = renderSongActions?.(track);
|
|
1499
|
-
const isUnplayable = (0,
|
|
1569
|
+
const isUnplayable = (0, import_genre_tree15.isSong)(track) && (0, import_genre_tree15.songUnplayableReason)(track) !== null;
|
|
1500
1570
|
if (isUnplayable) {
|
|
1501
|
-
return /* @__PURE__ */ (0,
|
|
1571
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1502
1572
|
leading,
|
|
1503
|
-
/* @__PURE__ */ (0,
|
|
1573
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1504
1574
|
"button",
|
|
1505
1575
|
{
|
|
1506
1576
|
type: "button",
|
|
@@ -1508,27 +1578,27 @@ function GenrePlaylistTracks({
|
|
|
1508
1578
|
"aria-disabled": "true",
|
|
1509
1579
|
"aria-label": label,
|
|
1510
1580
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1511
|
-
children: /* @__PURE__ */ (0,
|
|
1581
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_fa2.FaPlay, { size: 10 })
|
|
1512
1582
|
}
|
|
1513
1583
|
),
|
|
1514
1584
|
text,
|
|
1515
1585
|
actions
|
|
1516
1586
|
] }, track.uuid);
|
|
1517
1587
|
}
|
|
1518
|
-
return /* @__PURE__ */ (0,
|
|
1588
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1519
1589
|
"li",
|
|
1520
1590
|
{
|
|
1521
1591
|
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)]" : ""}`,
|
|
1522
1592
|
children: [
|
|
1523
1593
|
leading,
|
|
1524
|
-
/* @__PURE__ */ (0,
|
|
1594
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1525
1595
|
"button",
|
|
1526
1596
|
{
|
|
1527
1597
|
type: "button",
|
|
1528
1598
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1529
|
-
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 !==
|
|
1599
|
+
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"}`,
|
|
1530
1600
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1531
|
-
children: isCurrent && playState ===
|
|
1601
|
+
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui8.RingLoader, { size: 10 }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_fa2.FaPause, { size: 10 }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_fa2.FaPlay, { size: 10 })
|
|
1532
1602
|
}
|
|
1533
1603
|
),
|
|
1534
1604
|
text,
|
|
@@ -1538,7 +1608,7 @@ function GenrePlaylistTracks({
|
|
|
1538
1608
|
track.uuid
|
|
1539
1609
|
);
|
|
1540
1610
|
}),
|
|
1541
|
-
hasNextPage && /* @__PURE__ */ (0,
|
|
1611
|
+
hasNextPage && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1542
1612
|
] })
|
|
1543
1613
|
] }) });
|
|
1544
1614
|
}
|
|
@@ -1546,7 +1616,7 @@ function GenrePlaylistTracks({
|
|
|
1546
1616
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1547
1617
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1548
1618
|
var import_si2 = require("react-icons/si");
|
|
1549
|
-
var
|
|
1619
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1550
1620
|
function GenreDetailExtras({
|
|
1551
1621
|
genreUuid,
|
|
1552
1622
|
genrePlaylist,
|
|
@@ -1565,24 +1635,24 @@ function GenreDetailExtras({
|
|
|
1565
1635
|
...trackSlots
|
|
1566
1636
|
}) {
|
|
1567
1637
|
const trackNoun = (0, import_track_noun2.useTrackNoun)();
|
|
1568
|
-
const { data: overview, isPending } = (0,
|
|
1638
|
+
const { data: overview, isPending } = (0, import_genre_tree18.useFetchGenreOverview)(
|
|
1569
1639
|
genreUuid,
|
|
1570
1640
|
scope,
|
|
1571
1641
|
getBackendBaseUrl,
|
|
1572
1642
|
criteriaOverviewSchema
|
|
1573
1643
|
);
|
|
1574
1644
|
if (isPending) {
|
|
1575
|
-
return /* @__PURE__ */ (0,
|
|
1576
|
-
/* @__PURE__ */ (0,
|
|
1645
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
1646
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.PanelSection, { title: "Summary", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.Skeleton, { className: "h-4 w-3/4" }) }) }),
|
|
1577
1647
|
family
|
|
1578
1648
|
] });
|
|
1579
1649
|
}
|
|
1580
|
-
if (!overview) return /* @__PURE__ */ (0,
|
|
1650
|
+
if (!overview) return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_jsx_runtime27.Fragment, { children: family });
|
|
1581
1651
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1582
1652
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1583
|
-
return /* @__PURE__ */ (0,
|
|
1584
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0,
|
|
1585
|
-
summarySourceUrl && /* @__PURE__ */ (0,
|
|
1653
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(import_jsx_runtime27.Fragment, { children: [
|
|
1654
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1655
|
+
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1586
1656
|
"a",
|
|
1587
1657
|
{
|
|
1588
1658
|
href: summarySourceUrl,
|
|
@@ -1590,12 +1660,12 @@ function GenreDetailExtras({
|
|
|
1590
1660
|
rel: "noopener noreferrer",
|
|
1591
1661
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1592
1662
|
children: [
|
|
1593
|
-
/* @__PURE__ */ (0,
|
|
1663
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_si2.SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1594
1664
|
"Wikipedia"
|
|
1595
1665
|
]
|
|
1596
1666
|
}
|
|
1597
1667
|
),
|
|
1598
|
-
wikidataUrl && /* @__PURE__ */ (0,
|
|
1668
|
+
wikidataUrl && /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1599
1669
|
"a",
|
|
1600
1670
|
{
|
|
1601
1671
|
href: wikidataUrl,
|
|
@@ -1603,17 +1673,17 @@ function GenreDetailExtras({
|
|
|
1603
1673
|
rel: "noopener noreferrer",
|
|
1604
1674
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1605
1675
|
children: [
|
|
1606
|
-
/* @__PURE__ */ (0,
|
|
1676
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_si2.SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1607
1677
|
"Wikidata"
|
|
1608
1678
|
]
|
|
1609
1679
|
}
|
|
1610
1680
|
)
|
|
1611
1681
|
] }) }),
|
|
1612
|
-
/* @__PURE__ */ (0,
|
|
1682
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1613
1683
|
family,
|
|
1614
1684
|
renderGenreDetailExtras?.(overview),
|
|
1615
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0,
|
|
1616
|
-
/* @__PURE__ */ (0,
|
|
1685
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui9.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
1686
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1617
1687
|
GenrePlaylistTracks,
|
|
1618
1688
|
{
|
|
1619
1689
|
genreUuid,
|
|
@@ -1631,28 +1701,10 @@ function GenreDetailExtras({
|
|
|
1631
1701
|
}
|
|
1632
1702
|
|
|
1633
1703
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1634
|
-
var
|
|
1635
|
-
var
|
|
1704
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1705
|
+
var import_react14 = require("react");
|
|
1636
1706
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
1637
|
-
|
|
1638
|
-
const isCurrentTrackList = playback.playingNodeId === genrePlaylist.uuid;
|
|
1639
|
-
const handlePlayPause = () => {
|
|
1640
|
-
if (isCurrentTrackList) {
|
|
1641
|
-
setIsPlaying(!isPlaying);
|
|
1642
|
-
return;
|
|
1643
|
-
}
|
|
1644
|
-
playback.play(genrePlaylist).catch((error) => {
|
|
1645
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
1646
|
-
});
|
|
1647
|
-
};
|
|
1648
|
-
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1649
|
-
GenreActionBand,
|
|
1650
|
-
{
|
|
1651
|
-
...bandProps,
|
|
1652
|
-
onPlayPause: ("genreOnlyTracksCount" in genrePlaylist ? (0, import_genre_tree18.genreMusicCount)(genrePlaylist) : genrePlaylist.tracksCount) > 0 ? handlePlayPause : void 0,
|
|
1653
|
-
isPlaying: isCurrentTrackList && isPlaying
|
|
1654
|
-
}
|
|
1655
|
-
);
|
|
1707
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(GenrePlayActions, { genrePlaylist, playback }) });
|
|
1656
1708
|
}
|
|
1657
1709
|
function GenreInfoPanelBody({
|
|
1658
1710
|
toolbar,
|
|
@@ -1660,7 +1712,6 @@ function GenreInfoPanelBody({
|
|
|
1660
1712
|
genreUuid,
|
|
1661
1713
|
genrePlaylist,
|
|
1662
1714
|
catalogue,
|
|
1663
|
-
countsContext,
|
|
1664
1715
|
wikidataId,
|
|
1665
1716
|
scope,
|
|
1666
1717
|
getBackendBaseUrl,
|
|
@@ -1668,33 +1719,12 @@ function GenreInfoPanelBody({
|
|
|
1668
1719
|
band,
|
|
1669
1720
|
extras
|
|
1670
1721
|
}) {
|
|
1671
|
-
const
|
|
1672
|
-
const
|
|
1673
|
-
|
|
1674
|
-
const describeCounts = (counts) => {
|
|
1675
|
-
const scopes = counts.genreAndSubgenresTracksCount;
|
|
1676
|
-
return "canonical" in scopes ? `${counts.genreOnlyTracksCount} this genre only \xB7 ${scopes.canonical} with canonical subgenres \xB7 ${scopes.regional} with regional subgenres \xB7 ${scopes.all} with all subgenres` : `${counts.genreOnlyTracksCount} this genre only \xB7 ${scopes.all} with subgenres`;
|
|
1677
|
-
};
|
|
1678
|
-
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
1722
|
+
const summary = scope === "reference" ? import_genre_tree19.GenreCatalogueCountsSchema.parse(genrePlaylist ?? catalogue) : void 0;
|
|
1723
|
+
const selection = summary ? (0, import_genre_tree19.defaultGenreMusicSelection)(summary) : void 0;
|
|
1724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
1679
1725
|
toolbar,
|
|
1680
|
-
genrePlaylist ? /* @__PURE__ */ (0,
|
|
1681
|
-
|
|
1682
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("p", { children: [
|
|
1683
|
-
"Catalogue ",
|
|
1684
|
-
noun.plural,
|
|
1685
|
-
countsContext ? ` (${countsContext})` : "",
|
|
1686
|
-
": ",
|
|
1687
|
-
describeCounts(catalogue)
|
|
1688
|
-
] }),
|
|
1689
|
-
genrePlaylist && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("p", { children: [
|
|
1690
|
-
"Playlist ",
|
|
1691
|
-
noun.plural,
|
|
1692
|
-
countsContext ? ` (${countsContext})` : "",
|
|
1693
|
-
": ",
|
|
1694
|
-
describeCounts(summary)
|
|
1695
|
-
] })
|
|
1696
|
-
] }),
|
|
1697
|
-
/* @__PURE__ */ (0, import_react13.createElement)(
|
|
1726
|
+
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(GenreActionBand, { ...band }),
|
|
1727
|
+
/* @__PURE__ */ (0, import_react14.createElement)(
|
|
1698
1728
|
GenreDetailExtras,
|
|
1699
1729
|
{
|
|
1700
1730
|
...extras,
|
|
@@ -1713,7 +1743,7 @@ function GenreInfoPanelBody({
|
|
|
1713
1743
|
}
|
|
1714
1744
|
|
|
1715
1745
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
1716
|
-
var
|
|
1746
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1717
1747
|
var RELATIVE_ITEM_COUNT = 1;
|
|
1718
1748
|
function toNode(genre, parentId) {
|
|
1719
1749
|
return {
|
|
@@ -1735,80 +1765,88 @@ function useGenreDetailContent({
|
|
|
1735
1765
|
playback: hostPlayback,
|
|
1736
1766
|
trailing,
|
|
1737
1767
|
genrePlaylist: hostPlaylist,
|
|
1738
|
-
expanded
|
|
1768
|
+
expanded,
|
|
1769
|
+
treeRelations
|
|
1739
1770
|
}) {
|
|
1740
|
-
const { data: detail, isPending, isError } = (0,
|
|
1771
|
+
const { data: detail, isPending, isError } = (0, import_genre_tree20.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
1741
1772
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: [], artist: extras?.artist });
|
|
1742
1773
|
const playback = hostPlayback ?? defaultPlayback;
|
|
1743
|
-
const view = (0,
|
|
1774
|
+
const view = (0, import_react15.useMemo)(() => {
|
|
1744
1775
|
if (!detail) return null;
|
|
1745
1776
|
const rootColor = (0, import_genre_tree_view4.getGenreTreeColor)(detail.root.wikidataId);
|
|
1777
|
+
const treeStyles = /* @__PURE__ */ new Map();
|
|
1778
|
+
if (treeRelations) {
|
|
1779
|
+
const drawn = [treeRelations, treeRelations.parentNode, ...treeRelations.childNodes, ...treeRelations.ancestorNodes];
|
|
1780
|
+
for (const entry of drawn) {
|
|
1781
|
+
if (entry) treeStyles.set(entry.node.id, { fill: entry.fill, textColor: entry.textColor });
|
|
1782
|
+
}
|
|
1783
|
+
}
|
|
1746
1784
|
const relative = (genre, parentId) => ({
|
|
1747
1785
|
node: toNode(genre, parentId),
|
|
1748
|
-
fill: (0, import_genre_tree_view4.tintSurface)(rootColor),
|
|
1749
|
-
textColor: import_genre_tree_view4.TEXT_COLOR
|
|
1786
|
+
...treeStyles.get(genre.uuid) ?? { fill: (0, import_genre_tree_view4.tintSurface)(rootColor), textColor: import_genre_tree_view4.TEXT_COLOR }
|
|
1750
1787
|
});
|
|
1751
1788
|
const ancestors2 = [...detail.ascendants].sort((a, b) => b.degree - a.degree);
|
|
1789
|
+
const own = treeStyles.get(detail.uuid) ?? { fill: rootColor, textColor: (0, import_genre_tree_view4.getTextColorOnFill)(rootColor) };
|
|
1752
1790
|
return {
|
|
1753
1791
|
node: {
|
|
1754
1792
|
id: detail.uuid,
|
|
1755
1793
|
parentId: detail.parent?.uuid ?? null,
|
|
1756
1794
|
name: detail.name,
|
|
1757
|
-
itemCount: scope === "reference" ? (0,
|
|
1795
|
+
itemCount: scope === "reference" ? (0, import_genre_tree20.genreMusicCount)(detail.criteriaPlaylist ? import_genre_tree20.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist) : import_genre_tree20.GenreCatalogueCountsSchema.parse(detail.catalogue)) : detail.tracksCount,
|
|
1758
1796
|
wikidataId: detail.wikidataId
|
|
1759
1797
|
},
|
|
1760
|
-
fill:
|
|
1798
|
+
fill: own.fill,
|
|
1799
|
+
textColor: own.textColor,
|
|
1761
1800
|
parentNode: detail.parent ? relative(detail.parent, null) : null,
|
|
1762
1801
|
childNodes: detail.children.map((child) => relative(child, detail.uuid)),
|
|
1763
1802
|
ancestorNodes: ancestors2.map(
|
|
1764
1803
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
1765
1804
|
)
|
|
1766
1805
|
};
|
|
1767
|
-
}, [detail, scope]);
|
|
1806
|
+
}, [detail, scope, treeRelations]);
|
|
1768
1807
|
if (isError) return {
|
|
1769
1808
|
name: null,
|
|
1770
1809
|
title: "Genre unavailable",
|
|
1771
|
-
content: /* @__PURE__ */ (0,
|
|
1810
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { role: "alert", className: "text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
1772
1811
|
};
|
|
1773
1812
|
if (isPending || !detail || !view) return {
|
|
1774
1813
|
name: null,
|
|
1775
1814
|
title: "Loading genre\u2026",
|
|
1776
|
-
content: /* @__PURE__ */ (0,
|
|
1777
|
-
/* @__PURE__ */ (0,
|
|
1778
|
-
/* @__PURE__ */ (0,
|
|
1779
|
-
/* @__PURE__ */ (0,
|
|
1815
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
1816
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ui10.Skeleton, { className: "h-6 w-2/3" }),
|
|
1817
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ui10.Skeleton, { className: "h-4 w-full" }),
|
|
1818
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ui10.Skeleton, { className: "h-4 w-3/4" })
|
|
1780
1819
|
] })
|
|
1781
1820
|
};
|
|
1782
|
-
const selectGenre = (nodeId) => onSelectGenre(
|
|
1783
|
-
const family = /* @__PURE__ */ (0,
|
|
1821
|
+
const selectGenre = (nodeId) => onSelectGenre(import_genre_tree20.GenreUuidSchema.parse(nodeId));
|
|
1822
|
+
const family = /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1784
1823
|
import_genre_tree_view4.GenreNodeFamily,
|
|
1785
1824
|
{
|
|
1786
1825
|
node: view.node,
|
|
1787
1826
|
fill: view.fill,
|
|
1788
|
-
textColor:
|
|
1827
|
+
textColor: view.textColor,
|
|
1789
1828
|
parentNode: view.parentNode,
|
|
1790
1829
|
childNodes: view.childNodes,
|
|
1791
1830
|
onSelectNode: selectGenre
|
|
1792
1831
|
}
|
|
1793
1832
|
);
|
|
1794
|
-
const ancestors = /* @__PURE__ */ (0,
|
|
1833
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
1795
1834
|
return {
|
|
1796
1835
|
name: detail.name,
|
|
1797
1836
|
title: detail.name,
|
|
1798
|
-
headerAccent: { background: view.fill, color:
|
|
1837
|
+
headerAccent: { background: view.fill, color: view.textColor },
|
|
1799
1838
|
aside: expanded ? ancestors : void 0,
|
|
1800
|
-
content: /* @__PURE__ */ (0,
|
|
1801
|
-
/* @__PURE__ */ (0,
|
|
1839
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
1840
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1802
1841
|
GenreInfoPanelBody,
|
|
1803
1842
|
{
|
|
1804
|
-
family: /* @__PURE__ */ (0,
|
|
1843
|
+
family: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
1805
1844
|
family,
|
|
1806
1845
|
!expanded && ancestors
|
|
1807
1846
|
] }),
|
|
1808
1847
|
genreUuid: detail.uuid,
|
|
1809
|
-
genrePlaylist: hostPlaylist ?? (detail.criteriaPlaylist === null ? null : scope === "reference" ? { ...
|
|
1848
|
+
genrePlaylist: hostPlaylist ?? (detail.criteriaPlaylist === null ? null : scope === "reference" ? { ...import_genre_tree20.GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist), criteria: import_genre_tree20.CriteriaMinimumSchema.parse(detail) } : { ...detail.criteriaPlaylist, criteria: import_genre_tree20.CriteriaMinimumSchema.parse(detail), tracksCount: detail.tracksCount }),
|
|
1810
1849
|
catalogue: detail.catalogue,
|
|
1811
|
-
countsContext: !hostPlaylist && extras?.artist ? "all artists" : void 0,
|
|
1812
1850
|
wikidataId: detail.wikidataId,
|
|
1813
1851
|
scope,
|
|
1814
1852
|
getBackendBaseUrl,
|
|
@@ -1846,8 +1884,8 @@ function GenreDetailPanel({
|
|
|
1846
1884
|
expanded,
|
|
1847
1885
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
1848
1886
|
});
|
|
1849
|
-
return /* @__PURE__ */ (0,
|
|
1850
|
-
|
|
1887
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1888
|
+
import_ui10.DetailPanel,
|
|
1851
1889
|
{
|
|
1852
1890
|
side: "left",
|
|
1853
1891
|
title: panel.title,
|
|
@@ -1859,16 +1897,16 @@ function GenreDetailPanel({
|
|
|
1859
1897
|
edgeTab,
|
|
1860
1898
|
aside: panel.aside,
|
|
1861
1899
|
titleInSearch,
|
|
1862
|
-
headerActions: onExpandedChange ? /* @__PURE__ */ (0,
|
|
1900
|
+
headerActions: onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_ui10.IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react9.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react9.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
1863
1901
|
children: panel.content
|
|
1864
1902
|
}
|
|
1865
1903
|
);
|
|
1866
1904
|
}
|
|
1867
1905
|
|
|
1868
1906
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
1869
|
-
var
|
|
1870
|
-
var
|
|
1871
|
-
var
|
|
1907
|
+
var import_react16 = require("react");
|
|
1908
|
+
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1909
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1872
1910
|
function ChangeParentPopup({
|
|
1873
1911
|
genrePlaylist,
|
|
1874
1912
|
genrePlaylists,
|
|
@@ -1877,9 +1915,9 @@ function ChangeParentPopup({
|
|
|
1877
1915
|
onClose,
|
|
1878
1916
|
onParentChanged
|
|
1879
1917
|
}) {
|
|
1880
|
-
const { mutate, isPending, formErrors } = (0,
|
|
1881
|
-
const candidates = (0,
|
|
1882
|
-
() => (0,
|
|
1918
|
+
const { mutate, isPending, formErrors } = (0, import_genre_tree21.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
1919
|
+
const candidates = (0, import_react16.useMemo)(
|
|
1920
|
+
() => (0, import_genre_tree21.getReparentCandidates)(genrePlaylists, genrePlaylist.uuid),
|
|
1883
1921
|
[genrePlaylists, genrePlaylist.uuid]
|
|
1884
1922
|
);
|
|
1885
1923
|
const handleSelect = (newParent) => {
|
|
@@ -1896,19 +1934,19 @@ function ChangeParentPopup({
|
|
|
1896
1934
|
}
|
|
1897
1935
|
);
|
|
1898
1936
|
};
|
|
1899
|
-
(0,
|
|
1937
|
+
(0, import_react16.useEffect)(() => {
|
|
1900
1938
|
const handleKeyDown = (event) => {
|
|
1901
1939
|
if (event.key === "Escape") onClose();
|
|
1902
1940
|
};
|
|
1903
1941
|
window.addEventListener("keydown", handleKeyDown);
|
|
1904
1942
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1905
1943
|
}, [onClose]);
|
|
1906
|
-
return /* @__PURE__ */ (0,
|
|
1907
|
-
/* @__PURE__ */ (0,
|
|
1944
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
1945
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
1908
1946
|
"Current parent: ",
|
|
1909
1947
|
genrePlaylist.parent?.name ?? "none"
|
|
1910
1948
|
] }),
|
|
1911
|
-
/* @__PURE__ */ (0,
|
|
1949
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1912
1950
|
GenreSearch,
|
|
1913
1951
|
{
|
|
1914
1952
|
genrePlaylists: candidates,
|
|
@@ -1916,24 +1954,61 @@ function ChangeParentPopup({
|
|
|
1916
1954
|
placeholder: "Search a new parent\u2026"
|
|
1917
1955
|
}
|
|
1918
1956
|
) }),
|
|
1919
|
-
formErrors.length > 0 && /* @__PURE__ */ (0,
|
|
1957
|
+
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
1920
1958
|
] });
|
|
1921
1959
|
}
|
|
1922
1960
|
|
|
1923
1961
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
1924
|
-
var
|
|
1925
|
-
var
|
|
1962
|
+
var import_ui17 = require("@behindthemusictree/ui");
|
|
1963
|
+
var import_genre_tree27 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1964
|
+
|
|
1965
|
+
// src/genre-tree/artist/ArtistActionBand.tsx
|
|
1966
|
+
var import_lucide_react10 = require("lucide-react");
|
|
1967
|
+
var import_ui11 = require("@behindthemusictree/ui");
|
|
1968
|
+
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1969
|
+
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
1970
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1971
|
+
function ArtistActionBand({ artist, share }) {
|
|
1972
|
+
const { trackList, playNewTrackListFromArtist } = (0, import_genre_tree22.useTrackList)();
|
|
1973
|
+
const { isPlaying, setIsPlaying } = (0, import_player7.usePlayer)();
|
|
1974
|
+
const origin = trackList?.origin;
|
|
1975
|
+
const isCurrent = origin?.type === import_genre_tree22.TrackListOriginType.ARTIST && origin.uuid === artist.uuid;
|
|
1976
|
+
const playing = isCurrent && isPlaying;
|
|
1977
|
+
const handleClick = () => {
|
|
1978
|
+
if (isCurrent) {
|
|
1979
|
+
setIsPlaying(!isPlaying);
|
|
1980
|
+
return;
|
|
1981
|
+
}
|
|
1982
|
+
playNewTrackListFromArtist({ uuid: artist.uuid, name: artist.name }, "reference", { ordering: "title" }).catch((error) => {
|
|
1983
|
+
console.error("Failed to load artist tracks:", error);
|
|
1984
|
+
});
|
|
1985
|
+
};
|
|
1986
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_ui11.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_ui11.ActionBand, { children: [
|
|
1987
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1988
|
+
import_ui11.ActionButton,
|
|
1989
|
+
{
|
|
1990
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react10.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_lucide_react10.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1991
|
+
label: playing ? "Pause" : "Play",
|
|
1992
|
+
caption: String(artist.playableTracksCount),
|
|
1993
|
+
disabled: artist.playableTracksCount === 0,
|
|
1994
|
+
title: artist.playableTracksCount === 0 ? "No playable songs" : void 0,
|
|
1995
|
+
onClick: handleClick
|
|
1996
|
+
}
|
|
1997
|
+
),
|
|
1998
|
+
share
|
|
1999
|
+
] }) });
|
|
2000
|
+
}
|
|
1926
2001
|
|
|
1927
2002
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
1928
|
-
var
|
|
2003
|
+
var import_ui13 = require("@behindthemusictree/ui");
|
|
1929
2004
|
|
|
1930
2005
|
// src/genre-tree/artist/ArtistLinks.tsx
|
|
1931
|
-
var
|
|
2006
|
+
var import_lucide_react11 = require("lucide-react");
|
|
1932
2007
|
var import_si3 = require("react-icons/si");
|
|
1933
|
-
var
|
|
1934
|
-
var
|
|
2008
|
+
var import_ui12 = require("@behindthemusictree/ui");
|
|
2009
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1935
2010
|
var LINK_KINDS = {
|
|
1936
|
-
official: { label: "Official website", Icon:
|
|
2011
|
+
official: { label: "Official website", Icon: import_lucide_react11.Globe },
|
|
1937
2012
|
wikipedia: { label: "Wikipedia", Icon: import_si3.SiWikipedia },
|
|
1938
2013
|
wikidata: { label: "Wikidata", Icon: import_si3.SiWikidata },
|
|
1939
2014
|
spotify: { label: "Spotify", Icon: import_si3.SiSpotify },
|
|
@@ -1941,7 +2016,7 @@ var LINK_KINDS = {
|
|
|
1941
2016
|
bandcamp: { label: "Bandcamp", Icon: import_si3.SiBandcamp },
|
|
1942
2017
|
soundcloud: { label: "SoundCloud", Icon: import_si3.SiSoundcloud },
|
|
1943
2018
|
discogs: { label: "Discogs", Icon: import_si3.SiDiscogs },
|
|
1944
|
-
social: { label: "Social", Icon:
|
|
2019
|
+
social: { label: "Social", Icon: import_lucide_react11.Share2 }
|
|
1945
2020
|
};
|
|
1946
2021
|
function socialLabel(url) {
|
|
1947
2022
|
try {
|
|
@@ -1968,7 +2043,7 @@ function artistLinks(artist) {
|
|
|
1968
2043
|
return links;
|
|
1969
2044
|
}
|
|
1970
2045
|
function ArtistLinks({ links }) {
|
|
1971
|
-
return /* @__PURE__ */ (0,
|
|
2046
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_ui12.Chip, { href: url, icon: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
1972
2047
|
}
|
|
1973
2048
|
|
|
1974
2049
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -1979,7 +2054,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
1979
2054
|
}
|
|
1980
2055
|
|
|
1981
2056
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
1982
|
-
var
|
|
2057
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1983
2058
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
1984
2059
|
function ArtistHeader({ artist }) {
|
|
1985
2060
|
const fields = [];
|
|
@@ -1989,35 +2064,35 @@ function ArtistHeader({ artist }) {
|
|
|
1989
2064
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
1990
2065
|
if (years) fields.push({ label: "Active", value: years });
|
|
1991
2066
|
const links = artistLinks(artist);
|
|
1992
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0,
|
|
2067
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ArtistLinks, { links }) });
|
|
1993
2068
|
if (fields.length === 0) return null;
|
|
1994
|
-
return /* @__PURE__ */ (0,
|
|
2069
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui13.FieldList, { items: fields });
|
|
1995
2070
|
}
|
|
1996
2071
|
|
|
1997
2072
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
1998
|
-
var
|
|
2073
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
1999
2074
|
function ExternalLink({ href, children }) {
|
|
2000
|
-
return /* @__PURE__ */ (0,
|
|
2075
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
2001
2076
|
}
|
|
2002
2077
|
function ArtistPhoto({ image, name }) {
|
|
2003
|
-
return /* @__PURE__ */ (0,
|
|
2004
|
-
/* @__PURE__ */ (0,
|
|
2005
|
-
/* @__PURE__ */ (0,
|
|
2078
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("figure", { className: "flex flex-col gap-1.5", children: [
|
|
2079
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
2080
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2006
2081
|
"Photo: ",
|
|
2007
|
-
/* @__PURE__ */ (0,
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2008
2083
|
",",
|
|
2009
2084
|
" ",
|
|
2010
|
-
image.licenseUrl ? /* @__PURE__ */ (0,
|
|
2085
|
+
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
2011
2086
|
] })
|
|
2012
2087
|
] });
|
|
2013
2088
|
}
|
|
2014
2089
|
|
|
2015
2090
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2016
|
-
var
|
|
2017
|
-
var
|
|
2091
|
+
var import_ui14 = require("@behindthemusictree/ui");
|
|
2092
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2018
2093
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2019
2094
|
if (memberships.length === 0) return null;
|
|
2020
|
-
return /* @__PURE__ */ (0,
|
|
2095
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui14.PanelGroup, { title, children: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("ul", { children: memberships.map((membership, index) => {
|
|
2021
2096
|
const details = [
|
|
2022
2097
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2023
2098
|
...membership.roles
|
|
@@ -2025,9 +2100,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2025
2100
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
2026
2101
|
return (
|
|
2027
2102
|
// A member can have several periods in the same group.
|
|
2028
|
-
/* @__PURE__ */ (0,
|
|
2029
|
-
/* @__PURE__ */ (0,
|
|
2030
|
-
detailsText && /* @__PURE__ */ (0,
|
|
2103
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
2104
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
2105
|
+
detailsText && /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2031
2106
|
" \u2014 ",
|
|
2032
2107
|
detailsText
|
|
2033
2108
|
] })
|
|
@@ -2038,9 +2113,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2038
2113
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2039
2114
|
if (memberships.length === 0) return null;
|
|
2040
2115
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2041
|
-
return /* @__PURE__ */ (0,
|
|
2042
|
-
/* @__PURE__ */ (0,
|
|
2043
|
-
/* @__PURE__ */ (0,
|
|
2116
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_ui14.PanelSection, { title, children: [
|
|
2117
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2118
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2044
2119
|
MembershipList,
|
|
2045
2120
|
{
|
|
2046
2121
|
title: "Past",
|
|
@@ -2052,8 +2127,8 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2052
2127
|
}
|
|
2053
2128
|
|
|
2054
2129
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2055
|
-
var
|
|
2056
|
-
var
|
|
2130
|
+
var import_ui15 = require("@behindthemusictree/ui");
|
|
2131
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2057
2132
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2058
2133
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
2059
2134
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -2073,55 +2148,55 @@ function byYear(a, b) {
|
|
|
2073
2148
|
function ArtistDiscography({ albums }) {
|
|
2074
2149
|
if (albums.length === 0) return null;
|
|
2075
2150
|
const sorted = [...albums].sort(byYear);
|
|
2076
|
-
return /* @__PURE__ */ (0,
|
|
2151
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui15.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2077
2152
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2078
2153
|
if (groupAlbums.length === 0) return null;
|
|
2079
|
-
return /* @__PURE__ */ (0,
|
|
2080
|
-
/* @__PURE__ */ (0,
|
|
2081
|
-
/* @__PURE__ */ (0,
|
|
2154
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui15.PanelGroup, { title: group, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
2155
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2156
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2082
2157
|
] }, album.uuid)) }) }, group);
|
|
2083
2158
|
}) });
|
|
2084
2159
|
}
|
|
2085
2160
|
|
|
2086
2161
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2087
|
-
var
|
|
2162
|
+
var import_react17 = require("react");
|
|
2088
2163
|
var import_react_query2 = require("@tanstack/react-query");
|
|
2089
|
-
var
|
|
2090
|
-
var
|
|
2091
|
-
var
|
|
2092
|
-
var
|
|
2164
|
+
var import_lucide_react12 = require("lucide-react");
|
|
2165
|
+
var import_ui16 = require("@behindthemusictree/ui");
|
|
2166
|
+
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2167
|
+
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2093
2168
|
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
2094
2169
|
|
|
2095
2170
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2096
|
-
var
|
|
2097
|
-
var
|
|
2171
|
+
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
2172
|
+
var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2098
2173
|
|
|
2099
2174
|
// src/genre-tree/TrackPositionPlayPause.tsx
|
|
2100
2175
|
var import_fa3 = require("react-icons/fa");
|
|
2101
|
-
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2102
2176
|
var import_player8 = require("@behindthemusictree/app-kit/player");
|
|
2103
|
-
var
|
|
2177
|
+
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2178
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2104
2179
|
function TrackPositionPlayPause({
|
|
2105
2180
|
position,
|
|
2106
2181
|
uuid,
|
|
2107
2182
|
handlePlayPauseClick,
|
|
2108
2183
|
isSelected = false
|
|
2109
2184
|
}) {
|
|
2110
|
-
const { playerTrackObject, playbackConfirmedTrackId, playState, isLoading: isPlayerLoading } = (0,
|
|
2185
|
+
const { playerTrackObject, playbackConfirmedTrackId, playState, isLoading: isPlayerLoading } = (0, import_player8.usePlayer)();
|
|
2111
2186
|
const isThisTrack = playerTrackObject?.track.id === uuid;
|
|
2112
2187
|
const isConfirmedPlayable = playbackConfirmedTrackId === uuid;
|
|
2113
|
-
const isAwaitingPlayback = (isSelected || isThisTrack) && !isConfirmedPlayable && !(isThisTrack && playerTrackObject?.loadError) && (!isThisTrack || isPlayerLoading || playState ===
|
|
2114
|
-
const isPlaying = isThisTrack && isConfirmedPlayable && playState ===
|
|
2115
|
-
const isPaused = isThisTrack && isConfirmedPlayable && playState ===
|
|
2188
|
+
const isAwaitingPlayback = (isSelected || isThisTrack) && !isConfirmedPlayable && !(isThisTrack && playerTrackObject?.loadError) && (!isThisTrack || isPlayerLoading || playState === import_player9.PlayStates.LOADING || playState === import_player9.PlayStates.PLAYING);
|
|
2189
|
+
const isPlaying = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PLAYING;
|
|
2190
|
+
const isPaused = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PAUSED;
|
|
2116
2191
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
2117
|
-
return /* @__PURE__ */ (0,
|
|
2192
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
2118
2193
|
"div",
|
|
2119
2194
|
{
|
|
2120
2195
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
2121
2196
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
2122
2197
|
onClick: handlePlayPauseClick,
|
|
2123
2198
|
children: [
|
|
2124
|
-
/* @__PURE__ */ (0,
|
|
2199
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(
|
|
2125
2200
|
"span",
|
|
2126
2201
|
{
|
|
2127
2202
|
className: "track-position-play-pause__bars",
|
|
@@ -2129,18 +2204,18 @@ function TrackPositionPlayPause({
|
|
|
2129
2204
|
role: "img",
|
|
2130
2205
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
2131
2206
|
children: [
|
|
2132
|
-
/* @__PURE__ */ (0,
|
|
2133
|
-
/* @__PURE__ */ (0,
|
|
2134
|
-
/* @__PURE__ */ (0,
|
|
2207
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2208
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2209
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "track-position-play-pause__bar" })
|
|
2135
2210
|
]
|
|
2136
2211
|
}
|
|
2137
2212
|
) : position }),
|
|
2138
|
-
/* @__PURE__ */ (0,
|
|
2213
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2139
2214
|
"div",
|
|
2140
2215
|
{
|
|
2141
2216
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
2142
2217
|
"aria-hidden": "true",
|
|
2143
|
-
children: isAwaitingPlayback ? /* @__PURE__ */ (0,
|
|
2218
|
+
children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "track-position-play-pause__spinner" }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fa3.FaPause, {}) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_fa3.FaPlay, {})
|
|
2144
2219
|
}
|
|
2145
2220
|
)
|
|
2146
2221
|
]
|
|
@@ -2149,9 +2224,9 @@ function TrackPositionPlayPause({
|
|
|
2149
2224
|
}
|
|
2150
2225
|
|
|
2151
2226
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2152
|
-
var
|
|
2153
|
-
var
|
|
2154
|
-
var
|
|
2227
|
+
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2228
|
+
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2229
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2155
2230
|
function TrackItem({
|
|
2156
2231
|
track,
|
|
2157
2232
|
position,
|
|
@@ -2160,12 +2235,12 @@ function TrackItem({
|
|
|
2160
2235
|
renderArtistLink,
|
|
2161
2236
|
renderSongLink
|
|
2162
2237
|
}) {
|
|
2163
|
-
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = (0,
|
|
2164
|
-
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0,
|
|
2238
|
+
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = (0, import_player10.usePlayer)();
|
|
2239
|
+
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0, import_genre_tree23.useTrackList)();
|
|
2165
2240
|
const scope = trackList?.origin?.scope ?? null;
|
|
2166
2241
|
const isCurrentTrack = playerTrackObject?.track.id === track.uuid;
|
|
2167
2242
|
const hasPlaybackError = isCurrentTrack && !!playerTrackObject?.loadError;
|
|
2168
|
-
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0,
|
|
2243
|
+
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0, import_genre_tree24.isSong)(track) && (0, import_genre_tree24.songUnplayableReason)(track) !== null;
|
|
2169
2244
|
const handlePlayPauseClick = (event) => {
|
|
2170
2245
|
event.stopPropagation();
|
|
2171
2246
|
if (isCurrentTrack) {
|
|
@@ -2175,12 +2250,12 @@ function TrackItem({
|
|
|
2175
2250
|
loadTrackForPlayer(track.uuid);
|
|
2176
2251
|
}
|
|
2177
2252
|
};
|
|
2178
|
-
return /* @__PURE__ */ (0,
|
|
2253
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2179
2254
|
"div",
|
|
2180
2255
|
{
|
|
2181
2256
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
2182
2257
|
children: [
|
|
2183
|
-
isUnplayable ? /* @__PURE__ */ (0,
|
|
2258
|
+
isUnplayable ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2184
2259
|
"div",
|
|
2185
2260
|
{
|
|
2186
2261
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -2188,7 +2263,7 @@ function TrackItem({
|
|
|
2188
2263
|
"aria-disabled": "true",
|
|
2189
2264
|
children: position
|
|
2190
2265
|
}
|
|
2191
|
-
) : /* @__PURE__ */ (0,
|
|
2266
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2192
2267
|
TrackPositionPlayPause,
|
|
2193
2268
|
{
|
|
2194
2269
|
position,
|
|
@@ -2197,12 +2272,12 @@ function TrackItem({
|
|
|
2197
2272
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
2198
2273
|
}
|
|
2199
2274
|
),
|
|
2200
|
-
/* @__PURE__ */ (0,
|
|
2201
|
-
/* @__PURE__ */ (0,
|
|
2202
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0,
|
|
2275
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2276
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime38.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_runtime38.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2277
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_genre_tree25.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2203
2278
|
] }),
|
|
2204
|
-
/* @__PURE__ */ (0,
|
|
2205
|
-
renderDuration && /* @__PURE__ */ (0,
|
|
2279
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.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_runtime38.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2280
|
+
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2206
2281
|
"div",
|
|
2207
2282
|
{
|
|
2208
2283
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -2210,28 +2285,28 @@ function TrackItem({
|
|
|
2210
2285
|
children: renderDuration(track)
|
|
2211
2286
|
}
|
|
2212
2287
|
),
|
|
2213
|
-
renderActions && /* @__PURE__ */ (0,
|
|
2288
|
+
renderActions && /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "edit flex text-base w-6 items-center justify-center mr-2 cursor-pointer", children: renderActions(track) })
|
|
2214
2289
|
]
|
|
2215
2290
|
}
|
|
2216
2291
|
);
|
|
2217
2292
|
}
|
|
2218
2293
|
|
|
2219
2294
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2220
|
-
var
|
|
2221
|
-
var SongPageSchema2 = (0, import_transport7.PaginatedResponseSchema)(
|
|
2295
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2296
|
+
var SongPageSchema2 = (0, import_transport7.PaginatedResponseSchema)(import_genre_tree26.SongDetailedSchema);
|
|
2222
2297
|
var SORTS = [
|
|
2223
2298
|
{ ordering: "title", label: "Title" },
|
|
2224
2299
|
{ ordering: "-albumYear", label: "Year" }
|
|
2225
2300
|
];
|
|
2226
2301
|
function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
|
|
2227
|
-
const [page, setPage] = (0,
|
|
2228
|
-
const [ordering, setOrdering] = (0,
|
|
2229
|
-
const { playNewTrackListFromArtist } = (0,
|
|
2230
|
-
const { playerTrackObject } = (0,
|
|
2302
|
+
const [page, setPage] = (0, import_react17.useState)(1);
|
|
2303
|
+
const [ordering, setOrdering] = (0, import_react17.useState)("title");
|
|
2304
|
+
const { playNewTrackListFromArtist } = (0, import_genre_tree26.useTrackList)();
|
|
2305
|
+
const { playerTrackObject } = (0, import_player11.usePlayer)();
|
|
2231
2306
|
const { data, isPending, isError } = (0, import_transport7.usePlaybackQuery)({
|
|
2232
2307
|
getBackendBaseUrl,
|
|
2233
2308
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
2234
|
-
queryFn: (fetchBound) => fetchBound(
|
|
2309
|
+
queryFn: (fetchBound) => fetchBound(import_genre_tree26.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
2235
2310
|
artist: artist.uuid,
|
|
2236
2311
|
ordering,
|
|
2237
2312
|
page
|
|
@@ -2246,25 +2321,25 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2246
2321
|
});
|
|
2247
2322
|
const handleRowClickCapture = (event, song) => {
|
|
2248
2323
|
if (!(event.target instanceof Element) || !event.target.closest(".track-position-play-pause")) return;
|
|
2249
|
-
if (playerTrackObject?.track.id === song.uuid || (0,
|
|
2324
|
+
if (playerTrackObject?.track.id === song.uuid || (0, import_genre_tree26.songUnplayableReason)(song) !== null) return;
|
|
2250
2325
|
event.stopPropagation();
|
|
2251
2326
|
void play(song.uuid);
|
|
2252
2327
|
};
|
|
2253
|
-
return /* @__PURE__ */ (0,
|
|
2254
|
-
/* @__PURE__ */ (0,
|
|
2255
|
-
/* @__PURE__ */ (0,
|
|
2328
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui16.PanelSection, { title: "Songs", children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui16.Skeleton, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_jsx_runtime39.Fragment, { children: [
|
|
2329
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-2", children: [
|
|
2330
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
2256
2331
|
"button",
|
|
2257
2332
|
{
|
|
2258
2333
|
type: "button",
|
|
2259
2334
|
onClick: () => void play(),
|
|
2260
|
-
className: "flex w-fit items-center gap-1.5 px-3 py-1 text-
|
|
2335
|
+
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",
|
|
2261
2336
|
children: [
|
|
2262
|
-
/* @__PURE__ */ (0,
|
|
2337
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react12.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2263
2338
|
"Play all"
|
|
2264
2339
|
]
|
|
2265
2340
|
}
|
|
2266
2341
|
),
|
|
2267
|
-
/* @__PURE__ */ (0,
|
|
2342
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2268
2343
|
"button",
|
|
2269
2344
|
{
|
|
2270
2345
|
type: "button",
|
|
@@ -2279,7 +2354,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2279
2354
|
sort.ordering
|
|
2280
2355
|
)) })
|
|
2281
2356
|
] }),
|
|
2282
|
-
/* @__PURE__ */ (0,
|
|
2357
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("ul", { className: "overflow-hidden mb-2 bg-zinc-950 rounded-lg", children: data.results.map((song, index) => /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("li", { onClickCapture: (event) => handleRowClickCapture(event, song), children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2283
2358
|
TrackItem,
|
|
2284
2359
|
{
|
|
2285
2360
|
track: song,
|
|
@@ -2288,12 +2363,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2288
2363
|
renderSongLink
|
|
2289
2364
|
}
|
|
2290
2365
|
) }, song.uuid)) }),
|
|
2291
|
-
/* @__PURE__ */ (0,
|
|
2366
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui16.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2292
2367
|
] }) });
|
|
2293
2368
|
}
|
|
2294
2369
|
|
|
2295
2370
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2296
|
-
var
|
|
2371
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2297
2372
|
function useArtistPanel({
|
|
2298
2373
|
uuid,
|
|
2299
2374
|
scope,
|
|
@@ -2305,7 +2380,7 @@ function useArtistPanel({
|
|
|
2305
2380
|
onExpandedChange,
|
|
2306
2381
|
onClose
|
|
2307
2382
|
}) {
|
|
2308
|
-
const result = (0,
|
|
2383
|
+
const result = (0, import_genre_tree27.useArtist)(uuid, getBackendBaseUrl);
|
|
2309
2384
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2310
2385
|
switch (result.status) {
|
|
2311
2386
|
case "idle":
|
|
@@ -2314,26 +2389,26 @@ function useArtistPanel({
|
|
|
2314
2389
|
return {
|
|
2315
2390
|
...panel,
|
|
2316
2391
|
title: "Artist",
|
|
2317
|
-
content: /* @__PURE__ */ (0,
|
|
2318
|
-
/* @__PURE__ */ (0,
|
|
2319
|
-
/* @__PURE__ */ (0,
|
|
2320
|
-
/* @__PURE__ */ (0,
|
|
2321
|
-
/* @__PURE__ */ (0,
|
|
2322
|
-
/* @__PURE__ */ (0,
|
|
2323
|
-
/* @__PURE__ */ (0,
|
|
2392
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2393
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui17.Skeleton, { className: "h-3 w-16" }),
|
|
2394
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui17.Skeleton, { className: "h-4 w-32" }),
|
|
2395
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui17.Skeleton, { className: "h-3 w-16" }),
|
|
2396
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui17.Skeleton, { className: "h-4 w-24" }),
|
|
2397
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui17.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2398
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui17.Skeleton, { className: "h-16" })
|
|
2324
2399
|
] })
|
|
2325
2400
|
};
|
|
2326
2401
|
case "not-found":
|
|
2327
2402
|
return {
|
|
2328
2403
|
...panel,
|
|
2329
2404
|
title: "Artist not found",
|
|
2330
|
-
content: /* @__PURE__ */ (0,
|
|
2405
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2331
2406
|
};
|
|
2332
2407
|
case "error":
|
|
2333
2408
|
return {
|
|
2334
2409
|
...panel,
|
|
2335
2410
|
title: "Artist",
|
|
2336
|
-
content: /* @__PURE__ */ (0,
|
|
2411
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2337
2412
|
};
|
|
2338
2413
|
case "success": {
|
|
2339
2414
|
const { artist } = result;
|
|
@@ -2342,13 +2417,19 @@ function useArtistPanel({
|
|
|
2342
2417
|
return {
|
|
2343
2418
|
...panel,
|
|
2344
2419
|
title: artist.name,
|
|
2345
|
-
content: /* @__PURE__ */ (0,
|
|
2346
|
-
|
|
2347
|
-
|
|
2348
|
-
|
|
2349
|
-
|
|
2350
|
-
|
|
2351
|
-
|
|
2420
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
|
|
2421
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2422
|
+
ArtistActionBand,
|
|
2423
|
+
{
|
|
2424
|
+
artist,
|
|
2425
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2426
|
+
}
|
|
2427
|
+
),
|
|
2428
|
+
artist.image && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2429
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistHeader, { artist }),
|
|
2430
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2431
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2432
|
+
artist.tracksCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2352
2433
|
ArtistSongs,
|
|
2353
2434
|
{
|
|
2354
2435
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2358,69 +2439,62 @@ function useArtistPanel({
|
|
|
2358
2439
|
}
|
|
2359
2440
|
)
|
|
2360
2441
|
] }),
|
|
2361
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0,
|
|
2442
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2362
2443
|
};
|
|
2363
2444
|
}
|
|
2364
2445
|
}
|
|
2365
2446
|
}
|
|
2366
2447
|
|
|
2367
2448
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2368
|
-
var
|
|
2369
|
-
var
|
|
2449
|
+
var import_ui19 = require("@behindthemusictree/ui");
|
|
2450
|
+
var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2370
2451
|
|
|
2371
2452
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2372
|
-
var
|
|
2373
|
-
var
|
|
2374
|
-
var
|
|
2375
|
-
var
|
|
2376
|
-
var
|
|
2377
|
-
var
|
|
2453
|
+
var import_react18 = require("react");
|
|
2454
|
+
var import_lucide_react13 = require("lucide-react");
|
|
2455
|
+
var import_ui18 = require("@behindthemusictree/ui");
|
|
2456
|
+
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2457
|
+
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2458
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2378
2459
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2379
2460
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2380
2461
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
2381
2462
|
function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
2382
|
-
const [open, setOpen] = (0,
|
|
2383
|
-
const history = (0,
|
|
2463
|
+
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2464
|
+
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2384
2465
|
let body = null;
|
|
2385
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0,
|
|
2386
|
-
else if (history.status === "error") body = /* @__PURE__ */ (0,
|
|
2466
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui18.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2467
|
+
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2387
2468
|
else if (history.status === "success")
|
|
2388
|
-
body = history.entries.length === 0 ? /* @__PURE__ */ (0,
|
|
2389
|
-
/* @__PURE__ */ (0,
|
|
2390
|
-
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0,
|
|
2469
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
2470
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2471
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2391
2472
|
" ",
|
|
2392
2473
|
"\u2014 ",
|
|
2393
2474
|
entry.oldValue ?? "none",
|
|
2394
2475
|
" \u2192 ",
|
|
2395
2476
|
entry.newValue ?? "none"
|
|
2396
2477
|
] }) : null,
|
|
2397
|
-
/* @__PURE__ */ (0,
|
|
2478
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2398
2479
|
entry.actorPseudo ?? "Anonymous",
|
|
2399
2480
|
" \xB7 ",
|
|
2400
2481
|
dateFormat.format(new Date(entry.createdOn))
|
|
2401
2482
|
] })
|
|
2402
2483
|
] }, entry.uuid)) });
|
|
2403
|
-
return /* @__PURE__ */ (0,
|
|
2404
|
-
"
|
|
2405
|
-
{
|
|
2406
|
-
|
|
2407
|
-
className: "px-6 pb-2.5 mt-2.5 border-t border-[var(--color-border)]",
|
|
2408
|
-
children: [
|
|
2409
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("summary", { className: "mt-2.5 cursor-pointer text-[0.6875rem] font-semibold uppercase text-[var(--color-text-muted)]", children: "History" }),
|
|
2410
|
-
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("div", { className: "mt-1.5", children: body })
|
|
2411
|
-
]
|
|
2412
|
-
}
|
|
2413
|
-
);
|
|
2484
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui18.PanelBleed, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2485
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui18.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { className: "mt-1.5", children: body })
|
|
2487
|
+
] }) });
|
|
2414
2488
|
}
|
|
2415
2489
|
function SongPanelContent(props) {
|
|
2416
2490
|
const { song, scope, getBackendBaseUrl, shareUrl, renderArtistLink } = props;
|
|
2417
|
-
const { playNewTrackListFromTrackUuid } = (0,
|
|
2418
|
-
const { playerTrackObject, playState, handlePlayPauseAction } = (0,
|
|
2419
|
-
const unplayableReason = (0,
|
|
2491
|
+
const { playNewTrackListFromTrackUuid } = (0, import_genre_tree28.useTrackList)();
|
|
2492
|
+
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player12.usePlayer)();
|
|
2493
|
+
const unplayableReason = (0, import_genre_tree28.songUnplayableReason)(song);
|
|
2420
2494
|
const isCurrent = playerTrackObject?.track.id === song.uuid;
|
|
2421
|
-
const isPlaying = isCurrent && playState ===
|
|
2495
|
+
const isPlaying = isCurrent && playState === import_player12.PlayStates.PLAYING;
|
|
2422
2496
|
const shareTarget = { kind: "song", uuid: song.uuid, name: song.title, scope };
|
|
2423
|
-
const musicBrainzUrl = (0,
|
|
2497
|
+
const musicBrainzUrl = (0, import_genre_tree28.musicBrainzRecordingUrl)(song);
|
|
2424
2498
|
const fields = [];
|
|
2425
2499
|
if (song.genre) {
|
|
2426
2500
|
const path = props.genrePath && props.genrePath.length > 0 ? props.genrePath : null;
|
|
@@ -2428,13 +2502,13 @@ function SongPanelContent(props) {
|
|
|
2428
2502
|
const genre = song.genre;
|
|
2429
2503
|
fields.push({
|
|
2430
2504
|
label: "Genre",
|
|
2431
|
-
value: onSelectGenre ? /* @__PURE__ */ (0,
|
|
2432
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
2433
|
-
/* @__PURE__ */ (0,
|
|
2505
|
+
value: onSelectGenre ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { children: [
|
|
2506
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2434
2508
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2435
2509
|
});
|
|
2436
2510
|
} else {
|
|
2437
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */ (0,
|
|
2511
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2438
2512
|
}
|
|
2439
2513
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2440
2514
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2444,11 +2518,11 @@ function SongPanelContent(props) {
|
|
|
2444
2518
|
const links = [];
|
|
2445
2519
|
if (musicBrainzUrl)
|
|
2446
2520
|
links.push(
|
|
2447
|
-
/* @__PURE__ */ (0,
|
|
2521
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2448
2522
|
);
|
|
2449
2523
|
if (song.youtubeVideo)
|
|
2450
2524
|
links.push(
|
|
2451
|
-
/* @__PURE__ */ (0,
|
|
2525
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2452
2526
|
"a",
|
|
2453
2527
|
{
|
|
2454
2528
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2463,33 +2537,31 @@ function SongPanelContent(props) {
|
|
|
2463
2537
|
if (links.length > 0)
|
|
2464
2538
|
fields.push({
|
|
2465
2539
|
label: "Links",
|
|
2466
|
-
value: /* @__PURE__ */ (0,
|
|
2540
|
+
value: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "flex gap-3", children: links })
|
|
2467
2541
|
});
|
|
2468
|
-
return /* @__PURE__ */ (0,
|
|
2469
|
-
/* @__PURE__ */ (0,
|
|
2470
|
-
|
|
2471
|
-
|
|
2542
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
2543
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui18.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_ui18.ActionBand, { children: [
|
|
2544
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2545
|
+
import_ui18.ActionButton,
|
|
2472
2546
|
{
|
|
2473
|
-
|
|
2474
|
-
|
|
2475
|
-
|
|
2476
|
-
|
|
2477
|
-
|
|
2478
|
-
isPlaying ? "Pause" : "Play"
|
|
2479
|
-
]
|
|
2547
|
+
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react13.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react13.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2548
|
+
label: isPlaying ? "Pause" : "Play",
|
|
2549
|
+
disabled: !!unplayableReason,
|
|
2550
|
+
title: unplayableReason ?? void 0,
|
|
2551
|
+
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2480
2552
|
}
|
|
2481
2553
|
),
|
|
2482
|
-
shareUrl && /* @__PURE__ */ (0,
|
|
2554
|
+
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2483
2555
|
] }) }),
|
|
2484
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0,
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
2486
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0,
|
|
2487
|
-
/* @__PURE__ */ (0,
|
|
2556
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_genre_tree28.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2557
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui18.FieldList, { items: fields }),
|
|
2558
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui18.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2559
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2488
2560
|
] });
|
|
2489
2561
|
}
|
|
2490
2562
|
|
|
2491
2563
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2492
|
-
var
|
|
2564
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2493
2565
|
function useSongPanel({
|
|
2494
2566
|
uuid,
|
|
2495
2567
|
scope,
|
|
@@ -2501,7 +2573,7 @@ function useSongPanel({
|
|
|
2501
2573
|
onClose,
|
|
2502
2574
|
...navigation
|
|
2503
2575
|
}) {
|
|
2504
|
-
const result = (0,
|
|
2576
|
+
const result = (0, import_genre_tree29.useSong)(uuid, getBackendBaseUrl);
|
|
2505
2577
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2506
2578
|
switch (result.status) {
|
|
2507
2579
|
case "idle":
|
|
@@ -2510,24 +2582,24 @@ function useSongPanel({
|
|
|
2510
2582
|
return {
|
|
2511
2583
|
...panel,
|
|
2512
2584
|
title: "Song",
|
|
2513
|
-
content: /* @__PURE__ */ (0,
|
|
2514
|
-
/* @__PURE__ */ (0,
|
|
2515
|
-
/* @__PURE__ */ (0,
|
|
2516
|
-
/* @__PURE__ */ (0,
|
|
2517
|
-
/* @__PURE__ */ (0,
|
|
2585
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2586
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui19.Skeleton, { className: "h-3 w-16" }),
|
|
2587
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui19.Skeleton, { className: "h-4 w-32" }),
|
|
2588
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui19.Skeleton, { className: "h-3 w-16" }),
|
|
2589
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui19.Skeleton, { className: "h-4 w-24" })
|
|
2518
2590
|
] })
|
|
2519
2591
|
};
|
|
2520
2592
|
case "not-found":
|
|
2521
2593
|
return {
|
|
2522
2594
|
...panel,
|
|
2523
2595
|
title: "Song not found",
|
|
2524
|
-
content: /* @__PURE__ */ (0,
|
|
2596
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2525
2597
|
};
|
|
2526
2598
|
case "error":
|
|
2527
2599
|
return {
|
|
2528
2600
|
...panel,
|
|
2529
2601
|
title: "Song",
|
|
2530
|
-
content: /* @__PURE__ */ (0,
|
|
2602
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2531
2603
|
};
|
|
2532
2604
|
case "success": {
|
|
2533
2605
|
const { song } = result;
|
|
@@ -2535,7 +2607,7 @@ function useSongPanel({
|
|
|
2535
2607
|
return {
|
|
2536
2608
|
...panel,
|
|
2537
2609
|
title: song.title,
|
|
2538
|
-
content: /* @__PURE__ */ (0,
|
|
2610
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2539
2611
|
SongPanelContent,
|
|
2540
2612
|
{
|
|
2541
2613
|
song,
|
|
@@ -2587,29 +2659,29 @@ function useEntityPanel({
|
|
|
2587
2659
|
|
|
2588
2660
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2589
2661
|
var import_md = require("react-icons/md");
|
|
2590
|
-
var
|
|
2591
|
-
var
|
|
2662
|
+
var import_ui20 = require("@behindthemusictree/ui");
|
|
2663
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2592
2664
|
function SizeMetricToggle({
|
|
2593
2665
|
value,
|
|
2594
2666
|
onChange
|
|
2595
2667
|
}) {
|
|
2596
|
-
return /* @__PURE__ */ (0,
|
|
2597
|
-
|
|
2668
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2669
|
+
import_ui20.SegmentedControl,
|
|
2598
2670
|
{
|
|
2599
2671
|
variant: "floating",
|
|
2600
2672
|
"aria-label": "Size nodes by",
|
|
2601
2673
|
value,
|
|
2602
2674
|
onChange,
|
|
2603
2675
|
options: [
|
|
2604
|
-
{ value: "songs", label: /* @__PURE__ */ (0,
|
|
2605
|
-
{ value: "views", label: /* @__PURE__ */ (0,
|
|
2676
|
+
{ value: "songs", label: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_md.MdMusicNote, { size: 18, "aria-hidden": true }), "aria-label": "Size by songs", title: "Node size by song count" },
|
|
2677
|
+
{ value: "views", label: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_md.MdVisibility, { size: 18, "aria-hidden": true }), "aria-label": "Size by views", title: "Node size by song views" }
|
|
2606
2678
|
]
|
|
2607
2679
|
}
|
|
2608
2680
|
);
|
|
2609
2681
|
}
|
|
2610
2682
|
|
|
2611
2683
|
// src/genre-tree/GenreTreeView.tsx
|
|
2612
|
-
var
|
|
2684
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2613
2685
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2614
2686
|
var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
|
|
2615
2687
|
var noop = () => {
|
|
@@ -2671,21 +2743,21 @@ function GenreTreeView({
|
|
|
2671
2743
|
placement = "default",
|
|
2672
2744
|
...focus
|
|
2673
2745
|
}) {
|
|
2674
|
-
const getShareUrlRef = (0,
|
|
2746
|
+
const getShareUrlRef = (0, import_react19.useRef)(getShareUrl);
|
|
2675
2747
|
getShareUrlRef.current = getShareUrl;
|
|
2676
|
-
const [internalArtistUuid, setInternalArtistUuid] = (0,
|
|
2748
|
+
const [internalArtistUuid, setInternalArtistUuid] = (0, import_react19.useState)(null);
|
|
2677
2749
|
const isArtistControlled = controlledArtistUuid !== void 0;
|
|
2678
2750
|
const artistUuid = isArtistControlled ? controlledArtistUuid : internalArtistUuid;
|
|
2679
|
-
const [internalSongUuid, setInternalSongUuid] = (0,
|
|
2751
|
+
const [internalSongUuid, setInternalSongUuid] = (0, import_react19.useState)(null);
|
|
2680
2752
|
const isSongControlled = controlledSongUuid !== void 0;
|
|
2681
2753
|
const songUuid = isSongControlled ? controlledSongUuid : internalSongUuid;
|
|
2682
2754
|
const changeSong = (uuid) => {
|
|
2683
2755
|
if (!isSongControlled) setInternalSongUuid(uuid);
|
|
2684
2756
|
onSongUuidChange?.(uuid);
|
|
2685
2757
|
};
|
|
2686
|
-
const [internalSizeMetric, setInternalSizeMetric] = (0,
|
|
2758
|
+
const [internalSizeMetric, setInternalSizeMetric] = (0, import_react19.useState)("songs");
|
|
2687
2759
|
const sizeMetric = controlledSizeMetric ?? internalSizeMetric;
|
|
2688
|
-
const deferredSizeMetric = (0,
|
|
2760
|
+
const deferredSizeMetric = (0, import_react19.useDeferredValue)(sizeMetric);
|
|
2689
2761
|
const changeSizeMetric = (metric) => {
|
|
2690
2762
|
if (controlledSizeMetric === void 0) setInternalSizeMetric(metric);
|
|
2691
2763
|
onSizeMetricChange?.(metric);
|
|
@@ -2716,7 +2788,7 @@ function GenreTreeView({
|
|
|
2716
2788
|
allowWheelRotation: internalAllowWheelRotation,
|
|
2717
2789
|
toggleWheelRotation,
|
|
2718
2790
|
onNodeHover: handleNodeHover
|
|
2719
|
-
} = (0,
|
|
2791
|
+
} = (0, import_genre_tree30.useGenreTreeViewState)({
|
|
2720
2792
|
scope,
|
|
2721
2793
|
getBackendBaseUrl,
|
|
2722
2794
|
viewMode: controlledViewMode,
|
|
@@ -2726,7 +2798,7 @@ function GenreTreeView({
|
|
|
2726
2798
|
artistUuid
|
|
2727
2799
|
});
|
|
2728
2800
|
const restoreRevision = viewportRestore?.revision;
|
|
2729
|
-
const [stackedRestoreOwner, setStackedRestoreOwner] = (0,
|
|
2801
|
+
const [stackedRestoreOwner, setStackedRestoreOwner] = (0, import_react19.useState)({ revision: restoreRevision, rootUuid: selectedGenrePlaylist?.root.uuid });
|
|
2730
2802
|
let restoreRootUuid = stackedRestoreOwner.rootUuid;
|
|
2731
2803
|
if (stackedRestoreOwner.revision !== restoreRevision) {
|
|
2732
2804
|
restoreRootUuid = selectedGenrePlaylist?.root.uuid;
|
|
@@ -2735,14 +2807,14 @@ function GenreTreeView({
|
|
|
2735
2807
|
restoreRootUuid = selectedGenrePlaylist.root.uuid;
|
|
2736
2808
|
setStackedRestoreOwner({ revision: restoreRevision, rootUuid: restoreRootUuid });
|
|
2737
2809
|
}
|
|
2738
|
-
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey:
|
|
2739
|
-
const { mutate: updateGenre } = (0,
|
|
2810
|
+
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey: import_genre_tree30.genreUpdateMutationKey }) > 0;
|
|
2811
|
+
const { mutate: updateGenre } = (0, import_genre_tree30.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
2740
2812
|
const busy = deferredSizeMetric !== sizeMetric || isTreeFetching || isGenreUpdating;
|
|
2741
2813
|
const isArtistFiltered = artistUuid !== null;
|
|
2742
2814
|
const canSizeByViews = !isArtistFiltered && hasViewsCount(visibleGenrePlaylists);
|
|
2743
|
-
const artistResult = (0,
|
|
2815
|
+
const artistResult = (0, import_genre_tree30.useArtist)(artistUuid, artistSearchBaseUrl ?? getBackendBaseUrl);
|
|
2744
2816
|
const filterArtistName = artistResult.status === "success" ? artistResult.artist.name : null;
|
|
2745
|
-
const filterArtist = (0,
|
|
2817
|
+
const filterArtist = (0, import_react19.useMemo)(
|
|
2746
2818
|
() => artistUuid !== null && filterArtistName !== null ? { uuid: artistUuid, name: filterArtistName } : null,
|
|
2747
2819
|
[artistUuid, filterArtistName]
|
|
2748
2820
|
);
|
|
@@ -2757,17 +2829,17 @@ function GenreTreeView({
|
|
|
2757
2829
|
if (selectedGenreUuid !== null) clearSelection();
|
|
2758
2830
|
changeSong(uuid);
|
|
2759
2831
|
};
|
|
2760
|
-
const openSongRef = (0,
|
|
2832
|
+
const openSongRef = (0, import_react19.useRef)(openSong);
|
|
2761
2833
|
openSongRef.current = openSong;
|
|
2762
|
-
const resolvedRenderSongLink = (0,
|
|
2763
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0,
|
|
2834
|
+
const resolvedRenderSongLink = (0, import_react19.useCallback)(
|
|
2835
|
+
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
|
|
2764
2836
|
[renderSongLink]
|
|
2765
2837
|
);
|
|
2766
|
-
const [expandedSongUuid, setExpandedSongUuid] = (0,
|
|
2767
|
-
const [expandedArtistUuid, setExpandedArtistUuid] = (0,
|
|
2838
|
+
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react19.useState)(null);
|
|
2839
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react19.useState)(null);
|
|
2768
2840
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
2769
2841
|
const songBaseUrl = getBackendBaseUrl;
|
|
2770
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
2842
|
+
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
2771
2843
|
const getGenrePath = (genre) => {
|
|
2772
2844
|
const path = [];
|
|
2773
2845
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -2810,8 +2882,8 @@ function GenreTreeView({
|
|
|
2810
2882
|
}
|
|
2811
2883
|
});
|
|
2812
2884
|
const builtInPanel = overlayPanel || selectedGenreUuid !== null ? void 0 : entityPanel;
|
|
2813
|
-
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0,
|
|
2814
|
-
const [uncontrolledExpanded, setUncontrolledExpanded] = (0,
|
|
2885
|
+
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react19.useState)(false);
|
|
2886
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react19.useState)(false);
|
|
2815
2887
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
2816
2888
|
const isExpanded = expanded ?? uncontrolledExpanded;
|
|
2817
2889
|
const changeCollapsed = (next) => {
|
|
@@ -2822,28 +2894,28 @@ function GenreTreeView({
|
|
|
2822
2894
|
setUncontrolledExpanded(next);
|
|
2823
2895
|
onExpandedChange?.(next);
|
|
2824
2896
|
};
|
|
2825
|
-
(0,
|
|
2897
|
+
(0, import_react19.useEffect)(() => {
|
|
2826
2898
|
setUncontrolledCollapsed(false);
|
|
2827
2899
|
}, [selectedGenreUuid, artistUuid, songUuid]);
|
|
2828
|
-
const [isWheelRevealed, setIsWheelRevealed] = (0,
|
|
2900
|
+
const [isWheelRevealed, setIsWheelRevealed] = (0, import_react19.useState)(false);
|
|
2829
2901
|
const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
|
|
2830
2902
|
const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
|
|
2831
|
-
const [resolveStyle, setResolveStyle] = (0,
|
|
2832
|
-
const handleNodeStyleResolverChange = (0,
|
|
2903
|
+
const [resolveStyle, setResolveStyle] = (0, import_react19.useState)(null);
|
|
2904
|
+
const handleNodeStyleResolverChange = (0, import_react19.useCallback)(
|
|
2833
2905
|
(resolver) => setResolveStyle(() => resolver),
|
|
2834
2906
|
[]
|
|
2835
2907
|
);
|
|
2836
|
-
const panelRef = (0,
|
|
2837
|
-
const obscuredInset = (0,
|
|
2908
|
+
const panelRef = (0, import_react19.useRef)(null);
|
|
2909
|
+
const obscuredInset = (0, import_ui21.useObscuredInset)(panelRef);
|
|
2838
2910
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
2839
2911
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
2840
|
-
const treeNodes = (0,
|
|
2912
|
+
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric), [visibleGenrePlaylists, nodeMetric]);
|
|
2841
2913
|
const relations = (0, import_genre_tree_view5.useGenreNodeRelations)(
|
|
2842
2914
|
treeNodes,
|
|
2843
2915
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
2844
2916
|
resolveStyle
|
|
2845
2917
|
);
|
|
2846
|
-
const [selectionHistory, setSelectionHistory] = (0,
|
|
2918
|
+
const [selectionHistory, setSelectionHistory] = (0, import_react19.useState)({ current: selectedGenreUuid, previous: null });
|
|
2847
2919
|
if (selectionHistory.current !== selectedGenreUuid) {
|
|
2848
2920
|
setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
2849
2921
|
}
|
|
@@ -2869,7 +2941,7 @@ function GenreTreeView({
|
|
|
2869
2941
|
const handleGenreSearchZoomIn = () => {
|
|
2870
2942
|
if (selectedUuid) focus.onFocusGenreChange?.(selectedUuid, "zoom-in");
|
|
2871
2943
|
};
|
|
2872
|
-
const zoomInRef = (0,
|
|
2944
|
+
const zoomInRef = (0, import_react19.useRef)(void 0);
|
|
2873
2945
|
zoomInRef.current = canZoomIn ? handleGenreSearchZoomIn : void 0;
|
|
2874
2946
|
const genrePlaylist = selectedGenrePlaylist;
|
|
2875
2947
|
const criteria = genrePlaylist?.criteria;
|
|
@@ -2888,6 +2960,7 @@ function GenreTreeView({
|
|
|
2888
2960
|
selectGenre(uuid);
|
|
2889
2961
|
},
|
|
2890
2962
|
expanded: isExpanded,
|
|
2963
|
+
treeRelations: relations,
|
|
2891
2964
|
playback,
|
|
2892
2965
|
genrePlaylist: selectedGenrePlaylist,
|
|
2893
2966
|
band: {
|
|
@@ -2898,7 +2971,7 @@ function GenreTreeView({
|
|
|
2898
2971
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
2899
2972
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
2900
2973
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
2901
|
-
/* @__PURE__ */ (0,
|
|
2974
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2902
2975
|
ChangeParentPopup,
|
|
2903
2976
|
{
|
|
2904
2977
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -2951,7 +3024,7 @@ function GenreTreeView({
|
|
|
2951
3024
|
onExpandedChange: changeExpanded,
|
|
2952
3025
|
onClose: clearSelection,
|
|
2953
3026
|
titleInSearch: true,
|
|
2954
|
-
headerAccent:
|
|
3027
|
+
headerAccent: genreContent.headerAccent
|
|
2955
3028
|
};
|
|
2956
3029
|
} else if (builtInPanel) {
|
|
2957
3030
|
activePanel = {
|
|
@@ -2969,19 +3042,19 @@ function GenreTreeView({
|
|
|
2969
3042
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
2970
3043
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
2971
3044
|
} : void 0;
|
|
2972
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0,
|
|
2973
|
-
|
|
3045
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3046
|
+
import_ui21.IconButton,
|
|
2974
3047
|
{
|
|
2975
3048
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
2976
3049
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
2977
3050
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
2978
|
-
children: activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3051
|
+
children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react15.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_lucide_react15.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
2979
3052
|
}
|
|
2980
3053
|
) : null;
|
|
2981
3054
|
const renderArtistFilter = () => {
|
|
2982
3055
|
if (isLoading || !filterArtist) return null;
|
|
2983
|
-
return /* @__PURE__ */ (0,
|
|
2984
|
-
/* @__PURE__ */ (0,
|
|
3056
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
3057
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2985
3058
|
"button",
|
|
2986
3059
|
{
|
|
2987
3060
|
type: "button",
|
|
@@ -2993,7 +3066,7 @@ function GenreTreeView({
|
|
|
2993
3066
|
children: filterArtist.name
|
|
2994
3067
|
}
|
|
2995
3068
|
),
|
|
2996
|
-
/* @__PURE__ */ (0,
|
|
3069
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2997
3070
|
"button",
|
|
2998
3071
|
{
|
|
2999
3072
|
type: "button",
|
|
@@ -3005,8 +3078,8 @@ function GenreTreeView({
|
|
|
3005
3078
|
)
|
|
3006
3079
|
] });
|
|
3007
3080
|
};
|
|
3008
|
-
const actions = /* @__PURE__ */ (0,
|
|
3009
|
-
!isLoading && !isError && /* @__PURE__ */ (0,
|
|
3081
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
3082
|
+
!isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3010
3083
|
GenreTreeSearch,
|
|
3011
3084
|
{
|
|
3012
3085
|
artistBaseUrl,
|
|
@@ -3039,10 +3112,10 @@ function GenreTreeView({
|
|
|
3039
3112
|
extraGroups: extraSearchGroups
|
|
3040
3113
|
}
|
|
3041
3114
|
),
|
|
3042
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3043
|
-
/* @__PURE__ */ (0,
|
|
3044
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0,
|
|
3045
|
-
|
|
3115
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3116
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.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: [
|
|
3117
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3118
|
+
import_ui21.SegmentedControl,
|
|
3046
3119
|
{
|
|
3047
3120
|
"aria-label": "Tree view mode",
|
|
3048
3121
|
value: viewMode,
|
|
@@ -3055,14 +3128,14 @@ function GenreTreeView({
|
|
|
3055
3128
|
]
|
|
3056
3129
|
}
|
|
3057
3130
|
),
|
|
3058
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0,
|
|
3131
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3059
3132
|
"div",
|
|
3060
3133
|
{
|
|
3061
3134
|
className: "flex items-center gap-1",
|
|
3062
3135
|
role: "group",
|
|
3063
3136
|
"aria-label": "Tree display options",
|
|
3064
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0,
|
|
3065
|
-
|
|
3137
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3138
|
+
import_ui21.Button,
|
|
3066
3139
|
{
|
|
3067
3140
|
variant: allowWheelRotation ? "default" : "outline",
|
|
3068
3141
|
size: "sm",
|
|
@@ -3072,48 +3145,48 @@ function GenreTreeView({
|
|
|
3072
3145
|
)
|
|
3073
3146
|
}
|
|
3074
3147
|
),
|
|
3075
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0,
|
|
3076
|
-
|
|
3148
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3149
|
+
import_ui21.IconTextButton,
|
|
3077
3150
|
{
|
|
3078
|
-
icon:
|
|
3151
|
+
icon: import_lucide_react14.Plus,
|
|
3079
3152
|
text: "Add root",
|
|
3080
3153
|
onClick: () => handleGenreCreationAction(null)
|
|
3081
3154
|
}
|
|
3082
3155
|
)
|
|
3083
3156
|
] })
|
|
3084
3157
|
] });
|
|
3085
|
-
return /* @__PURE__ */ (0,
|
|
3158
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
3086
3159
|
"div",
|
|
3087
3160
|
{
|
|
3088
3161
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
3089
3162
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
3090
3163
|
children: [
|
|
3091
|
-
/* @__PURE__ */ (0,
|
|
3164
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3092
3165
|
"div",
|
|
3093
3166
|
{
|
|
3094
|
-
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))] 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"}`,
|
|
3167
|
+
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"}`,
|
|
3095
3168
|
children: actions
|
|
3096
3169
|
}
|
|
3097
3170
|
),
|
|
3098
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3171
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3099
3172
|
"div",
|
|
3100
3173
|
{
|
|
3101
|
-
className: `absolute left-1/2 z-30 hidden -translate-x-1/2 md:block ${placement === "regions" ? "top-[calc(var(--layout-gutter)+var(--layout-panel-inset))]" : "top-5"}`,
|
|
3174
|
+
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"}`,
|
|
3102
3175
|
children: renderArtistFilter()
|
|
3103
3176
|
}
|
|
3104
3177
|
),
|
|
3105
|
-
/* @__PURE__ */ (0,
|
|
3106
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0,
|
|
3107
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3178
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
3179
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
3180
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
|
|
3108
3181
|
"Couldn't load the genre tree.",
|
|
3109
3182
|
" ",
|
|
3110
|
-
/* @__PURE__ */ (0,
|
|
3183
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
3111
3184
|
] }) : viewMode === "wheel" ? (
|
|
3112
3185
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
3113
3186
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
3114
3187
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
3115
3188
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
3116
|
-
/* @__PURE__ */ (0,
|
|
3189
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3117
3190
|
GenrePlaylistTreeWheel,
|
|
3118
3191
|
{
|
|
3119
3192
|
scope,
|
|
@@ -3130,9 +3203,9 @@ function GenreTreeView({
|
|
|
3130
3203
|
allowWheelRotation,
|
|
3131
3204
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3132
3205
|
busy,
|
|
3133
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3206
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3134
3207
|
floatingControlsLeading,
|
|
3135
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3208
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3136
3209
|
] }) : void 0,
|
|
3137
3210
|
defaultViewport,
|
|
3138
3211
|
viewportRestore,
|
|
@@ -3141,7 +3214,7 @@ function GenreTreeView({
|
|
|
3141
3214
|
) }) })
|
|
3142
3215
|
) : viewMode === "pop-core" ? (
|
|
3143
3216
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
3144
|
-
/* @__PURE__ */ (0,
|
|
3217
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3145
3218
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3146
3219
|
{
|
|
3147
3220
|
scope,
|
|
@@ -3158,9 +3231,9 @@ function GenreTreeView({
|
|
|
3158
3231
|
allowWheelRotation,
|
|
3159
3232
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3160
3233
|
busy,
|
|
3161
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3234
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3162
3235
|
floatingControlsLeading,
|
|
3163
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3236
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3164
3237
|
] }) : void 0,
|
|
3165
3238
|
defaultViewport,
|
|
3166
3239
|
viewportRestore,
|
|
@@ -3168,7 +3241,7 @@ function GenreTreeView({
|
|
|
3168
3241
|
...focus
|
|
3169
3242
|
}
|
|
3170
3243
|
) }) })
|
|
3171
|
-
) : viewMode === "outline" ? /* @__PURE__ */ (0,
|
|
3244
|
+
) : viewMode === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "tree-container flex-1 min-h-0 w-full overflow-y-auto relative", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3172
3245
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3173
3246
|
{
|
|
3174
3247
|
outline: true,
|
|
@@ -3184,13 +3257,13 @@ function GenreTreeView({
|
|
|
3184
3257
|
selectedNodeId,
|
|
3185
3258
|
readOnly
|
|
3186
3259
|
}
|
|
3187
|
-
) }) : /* @__PURE__ */ (0,
|
|
3260
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime44.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(
|
|
3188
3261
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
3189
|
-
return /* @__PURE__ */ (0,
|
|
3262
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3190
3263
|
"div",
|
|
3191
3264
|
{
|
|
3192
3265
|
className: "tree-per-root-container relative shrink-0 h-[28rem] mt-2 mr-16 p-2 bg-[var(--color-neutral-100)] rounded-lg",
|
|
3193
|
-
children: /* @__PURE__ */ (0,
|
|
3266
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3194
3267
|
GenrePlaylistTreePerRoot,
|
|
3195
3268
|
{
|
|
3196
3269
|
scope,
|
|
@@ -3216,8 +3289,8 @@ function GenreTreeView({
|
|
|
3216
3289
|
);
|
|
3217
3290
|
}
|
|
3218
3291
|
) }),
|
|
3219
|
-
/* @__PURE__ */ (0,
|
|
3220
|
-
|
|
3292
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
3293
|
+
import_ui21.DetailPanel,
|
|
3221
3294
|
{
|
|
3222
3295
|
ref: panelRef,
|
|
3223
3296
|
side: "left",
|
|
@@ -3231,8 +3304,8 @@ function GenreTreeView({
|
|
|
3231
3304
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3232
3305
|
aside: activePanel?.aside,
|
|
3233
3306
|
edgeTab: detailTab,
|
|
3234
|
-
headerClassName: activePanel?.titleInSearch ? void 0 : "pt-
|
|
3235
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3307
|
+
headerClassName: activePanel?.titleInSearch ? void 0 : "pt-search-clear",
|
|
3308
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
3236
3309
|
activePanel.content,
|
|
3237
3310
|
activePanel.aside
|
|
3238
3311
|
] }) : activePanel?.content
|
|
@@ -3248,13 +3321,13 @@ function GenreTreeView({
|
|
|
3248
3321
|
var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
3249
3322
|
|
|
3250
3323
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3251
|
-
var
|
|
3252
|
-
var
|
|
3253
|
-
var
|
|
3254
|
-
var
|
|
3255
|
-
var
|
|
3256
|
-
var
|
|
3257
|
-
var useBrowserLayoutEffect = typeof window === "undefined" ?
|
|
3324
|
+
var import_react20 = require("react");
|
|
3325
|
+
var import_lucide_react16 = require("lucide-react");
|
|
3326
|
+
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3327
|
+
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3328
|
+
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
3329
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
3330
|
+
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react20.useEffect : import_react20.useLayoutEffect;
|
|
3258
3331
|
function TrackListSidebar({
|
|
3259
3332
|
className: className2 = "",
|
|
3260
3333
|
renderDuration,
|
|
@@ -3266,18 +3339,18 @@ function TrackListSidebar({
|
|
|
3266
3339
|
renderArtistLink,
|
|
3267
3340
|
renderSongLink
|
|
3268
3341
|
}) {
|
|
3269
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } = (0,
|
|
3270
|
-
const trackNoun = (0,
|
|
3271
|
-
const trackListRef = (0,
|
|
3272
|
-
const previousOriginRef = (0,
|
|
3273
|
-
const handledAutoAdvanceRequestIdRef = (0,
|
|
3274
|
-
const shouldFollowPlaybackRef = (0,
|
|
3275
|
-
const programmaticScrollTopRef = (0,
|
|
3276
|
-
const userScrollIntentRef = (0,
|
|
3277
|
-
const userScrollIntentTimerRef = (0,
|
|
3278
|
-
const loadMoreSentinelRef = (0,
|
|
3342
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = (0, import_genre_tree31.useTrackList)();
|
|
3343
|
+
const trackNoun = (0, import_track_noun3.useTrackNoun)();
|
|
3344
|
+
const trackListRef = (0, import_react20.useRef)(null);
|
|
3345
|
+
const previousOriginRef = (0, import_react20.useRef)(trackList?.origin ?? null);
|
|
3346
|
+
const handledAutoAdvanceRequestIdRef = (0, import_react20.useRef)(null);
|
|
3347
|
+
const shouldFollowPlaybackRef = (0, import_react20.useRef)(true);
|
|
3348
|
+
const programmaticScrollTopRef = (0, import_react20.useRef)(null);
|
|
3349
|
+
const userScrollIntentRef = (0, import_react20.useRef)(false);
|
|
3350
|
+
const userScrollIntentTimerRef = (0, import_react20.useRef)(null);
|
|
3351
|
+
const loadMoreSentinelRef = (0, import_react20.useRef)(null);
|
|
3279
3352
|
const hasMore = !!trackList && trackList.nextPage !== null;
|
|
3280
|
-
(0,
|
|
3353
|
+
(0, import_react20.useEffect)(() => {
|
|
3281
3354
|
const sentinel = loadMoreSentinelRef.current;
|
|
3282
3355
|
if (!hasMore || !sentinel) return;
|
|
3283
3356
|
const observer = new IntersectionObserver((entries) => {
|
|
@@ -3297,11 +3370,11 @@ function TrackListSidebar({
|
|
|
3297
3370
|
programmaticScrollTopRef.current = null;
|
|
3298
3371
|
if (trackListRef.current) trackListRef.current.scrollTop = 0;
|
|
3299
3372
|
}, [trackList?.origin]);
|
|
3300
|
-
(0,
|
|
3373
|
+
(0, import_react20.useEffect)(() => {
|
|
3301
3374
|
const list = trackListRef.current;
|
|
3302
3375
|
if (!isCollapsed && list?.scrollTop === 0) shouldFollowPlaybackRef.current = true;
|
|
3303
3376
|
}, [isCollapsed]);
|
|
3304
|
-
(0,
|
|
3377
|
+
(0, import_react20.useEffect)(
|
|
3305
3378
|
() => () => {
|
|
3306
3379
|
if (userScrollIntentTimerRef.current !== null) clearTimeout(userScrollIntentTimerRef.current);
|
|
3307
3380
|
},
|
|
@@ -3355,25 +3428,25 @@ function TrackListSidebar({
|
|
|
3355
3428
|
}
|
|
3356
3429
|
};
|
|
3357
3430
|
const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
|
|
3358
|
-
return trackList ? /* @__PURE__ */ (0,
|
|
3431
|
+
return trackList ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
3359
3432
|
"div",
|
|
3360
3433
|
{
|
|
3361
3434
|
"data-theme": "dark",
|
|
3362
3435
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3363
3436
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3364
3437
|
children: [
|
|
3365
|
-
/* @__PURE__ */ (0,
|
|
3366
|
-
/* @__PURE__ */ (0,
|
|
3367
|
-
/* @__PURE__ */ (0,
|
|
3368
|
-
/* @__PURE__ */ (0,
|
|
3369
|
-
/* @__PURE__ */ (0,
|
|
3438
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3439
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3440
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "origin flex text-xl", children: [
|
|
3441
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3442
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.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_runtime45.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3370
3443
|
] }),
|
|
3371
|
-
/* @__PURE__ */ (0,
|
|
3372
|
-
trackList.origin.type ===
|
|
3444
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3445
|
+
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 `,
|
|
3373
3446
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3374
3447
|
] })
|
|
3375
3448
|
] }),
|
|
3376
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0,
|
|
3449
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3377
3450
|
"button",
|
|
3378
3451
|
{
|
|
3379
3452
|
type: "button",
|
|
@@ -3382,11 +3455,11 @@ function TrackListSidebar({
|
|
|
3382
3455
|
"aria-expanded": !isCollapsed,
|
|
3383
3456
|
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"}`,
|
|
3384
3457
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3385
|
-
children: /* @__PURE__ */ (0,
|
|
3458
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react16.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3386
3459
|
}
|
|
3387
3460
|
)
|
|
3388
3461
|
] }),
|
|
3389
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
3462
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
3390
3463
|
"ul",
|
|
3391
3464
|
{
|
|
3392
3465
|
ref: trackListRef,
|
|
@@ -3396,7 +3469,7 @@ function TrackListSidebar({
|
|
|
3396
3469
|
onPointerDown: markUserScrollIntent,
|
|
3397
3470
|
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",
|
|
3398
3471
|
children: [
|
|
3399
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */ (0,
|
|
3472
|
+
trackList.tracks.map((track, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("li", { "data-track-uuid": track.uuid, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3400
3473
|
TrackItem,
|
|
3401
3474
|
{
|
|
3402
3475
|
track,
|
|
@@ -3407,7 +3480,7 @@ function TrackListSidebar({
|
|
|
3407
3480
|
renderSongLink
|
|
3408
3481
|
}
|
|
3409
3482
|
) }, track.uuid)),
|
|
3410
|
-
hasMore && /* @__PURE__ */ (0,
|
|
3483
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3411
3484
|
]
|
|
3412
3485
|
}
|
|
3413
3486
|
)
|
|
@@ -3417,17 +3490,17 @@ function TrackListSidebar({
|
|
|
3417
3490
|
}
|
|
3418
3491
|
|
|
3419
3492
|
// src/genre-tree/PlayerPanel.tsx
|
|
3420
|
-
var
|
|
3493
|
+
var import_react21 = require("react");
|
|
3421
3494
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3422
|
-
var
|
|
3423
|
-
var
|
|
3424
|
-
var
|
|
3495
|
+
var import_player14 = require("@behindthemusictree/app-kit/player");
|
|
3496
|
+
var import_genre_tree34 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3497
|
+
var import_ui22 = require("@behindthemusictree/ui");
|
|
3425
3498
|
|
|
3426
3499
|
// src/genre-tree/PlayerControls.tsx
|
|
3427
|
-
var
|
|
3428
|
-
var
|
|
3429
|
-
var
|
|
3430
|
-
var
|
|
3500
|
+
var import_lucide_react17 = require("lucide-react");
|
|
3501
|
+
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3502
|
+
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3503
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3431
3504
|
function PlayerControls() {
|
|
3432
3505
|
const {
|
|
3433
3506
|
duration,
|
|
@@ -3438,23 +3511,23 @@ function PlayerControls() {
|
|
|
3438
3511
|
seekTo,
|
|
3439
3512
|
setVolume,
|
|
3440
3513
|
volume
|
|
3441
|
-
} = (0,
|
|
3442
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0,
|
|
3443
|
-
const currentTime = (0,
|
|
3444
|
-
const isBusy = isLoading || playState ===
|
|
3514
|
+
} = (0, import_player13.usePlayer)();
|
|
3515
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0, import_genre_tree33.useTrackList)();
|
|
3516
|
+
const currentTime = (0, import_player13.useCurrentTime)();
|
|
3517
|
+
const isBusy = isLoading || playState === import_player13.PlayStates.LOADING;
|
|
3445
3518
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
3446
3519
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3447
3520
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3448
|
-
const isPlaying = playState ===
|
|
3449
|
-
return /* @__PURE__ */ (0,
|
|
3521
|
+
const isPlaying = playState === import_player13.PlayStates.PLAYING;
|
|
3522
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
3450
3523
|
"section",
|
|
3451
3524
|
{
|
|
3452
3525
|
"aria-label": "Player controls",
|
|
3453
3526
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3454
3527
|
children: [
|
|
3455
|
-
/* @__PURE__ */ (0,
|
|
3456
|
-
/* @__PURE__ */ (0,
|
|
3457
|
-
/* @__PURE__ */ (0,
|
|
3528
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3529
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree33.formatTime)(safeCurrentTime) }),
|
|
3530
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3458
3531
|
"input",
|
|
3459
3532
|
{
|
|
3460
3533
|
"aria-label": "Seek",
|
|
@@ -3468,11 +3541,11 @@ function PlayerControls() {
|
|
|
3468
3541
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3469
3542
|
}
|
|
3470
3543
|
),
|
|
3471
|
-
/* @__PURE__ */ (0,
|
|
3544
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree33.formatTime)(safeDuration) })
|
|
3472
3545
|
] }),
|
|
3473
|
-
/* @__PURE__ */ (0,
|
|
3474
|
-
/* @__PURE__ */ (0,
|
|
3475
|
-
/* @__PURE__ */ (0,
|
|
3546
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3547
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3548
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3476
3549
|
"button",
|
|
3477
3550
|
{
|
|
3478
3551
|
type: "button",
|
|
@@ -3481,10 +3554,10 @@ function PlayerControls() {
|
|
|
3481
3554
|
disabled: !isReady || !hasPreviousTrack,
|
|
3482
3555
|
onClick: playPreviousTrack,
|
|
3483
3556
|
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",
|
|
3484
|
-
children: /* @__PURE__ */ (0,
|
|
3557
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react17.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3485
3558
|
}
|
|
3486
3559
|
),
|
|
3487
|
-
/* @__PURE__ */ (0,
|
|
3560
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3488
3561
|
"button",
|
|
3489
3562
|
{
|
|
3490
3563
|
type: "button",
|
|
@@ -3493,10 +3566,10 @@ function PlayerControls() {
|
|
|
3493
3566
|
disabled: !isReady,
|
|
3494
3567
|
onClick: handlePlayPauseAction,
|
|
3495
3568
|
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",
|
|
3496
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3569
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react17.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react17.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3497
3570
|
}
|
|
3498
3571
|
),
|
|
3499
|
-
/* @__PURE__ */ (0,
|
|
3572
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3500
3573
|
"button",
|
|
3501
3574
|
{
|
|
3502
3575
|
type: "button",
|
|
@@ -3505,14 +3578,14 @@ function PlayerControls() {
|
|
|
3505
3578
|
disabled: !isReady || !hasNextTrack,
|
|
3506
3579
|
onClick: playNextTrack,
|
|
3507
3580
|
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",
|
|
3508
|
-
children: /* @__PURE__ */ (0,
|
|
3581
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react17.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3509
3582
|
}
|
|
3510
3583
|
)
|
|
3511
3584
|
] }),
|
|
3512
|
-
/* @__PURE__ */ (0,
|
|
3513
|
-
volume === 0 ? /* @__PURE__ */ (0,
|
|
3514
|
-
/* @__PURE__ */ (0,
|
|
3515
|
-
/* @__PURE__ */ (0,
|
|
3585
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.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: [
|
|
3586
|
+
volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react17.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react17.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3587
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("span", { className: "sr-only", children: "Volume" }),
|
|
3588
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3516
3589
|
"input",
|
|
3517
3590
|
{
|
|
3518
3591
|
"aria-label": "Volume",
|
|
@@ -3534,7 +3607,7 @@ function PlayerControls() {
|
|
|
3534
3607
|
}
|
|
3535
3608
|
|
|
3536
3609
|
// src/genre-tree/PlayerPanel.tsx
|
|
3537
|
-
var
|
|
3610
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
3538
3611
|
var PANEL_ID = "player-panel";
|
|
3539
3612
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3540
3613
|
function PlayerPanel({
|
|
@@ -3546,14 +3619,14 @@ function PlayerPanel({
|
|
|
3546
3619
|
renderArtistLink,
|
|
3547
3620
|
renderSongLink
|
|
3548
3621
|
}) {
|
|
3549
|
-
const { playerTrackObject, retryPlayback } = (0,
|
|
3550
|
-
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0,
|
|
3551
|
-
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0,
|
|
3622
|
+
const { playerTrackObject, retryPlayback } = (0, import_player14.usePlayer)();
|
|
3623
|
+
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree34.useTrackListSidebarVisibility)();
|
|
3624
|
+
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react21.useState)("");
|
|
3552
3625
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3553
|
-
(0,
|
|
3626
|
+
(0, import_react21.useEffect)(() => {
|
|
3554
3627
|
if (loadedTrackTitle) setLastLoadedTrackTitle(loadedTrackTitle);
|
|
3555
3628
|
}, [loadedTrackTitle]);
|
|
3556
|
-
const [uncontrolledExtended, setUncontrolledExtended] = (0,
|
|
3629
|
+
const [uncontrolledExtended, setUncontrolledExtended] = (0, import_react21.useState)(false);
|
|
3557
3630
|
const isExtendRequested = expanded ?? uncontrolledExtended;
|
|
3558
3631
|
const setIsExtendRequested = (next) => {
|
|
3559
3632
|
setUncontrolledExtended(next);
|
|
@@ -3574,7 +3647,7 @@ function PlayerPanel({
|
|
|
3574
3647
|
onClick: () => setIsExtendRequested(true),
|
|
3575
3648
|
expanded: false
|
|
3576
3649
|
} : null;
|
|
3577
|
-
return /* @__PURE__ */ (0,
|
|
3650
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
3578
3651
|
"div",
|
|
3579
3652
|
{
|
|
3580
3653
|
id: PANEL_ID,
|
|
@@ -3587,8 +3660,8 @@ function PlayerPanel({
|
|
|
3587
3660
|
),
|
|
3588
3661
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3589
3662
|
children: [
|
|
3590
|
-
/* @__PURE__ */ (0,
|
|
3591
|
-
|
|
3663
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3664
|
+
import_ui22.PanelEdgeTab,
|
|
3592
3665
|
{
|
|
3593
3666
|
side: "right",
|
|
3594
3667
|
edge: tabEdge,
|
|
@@ -3597,7 +3670,7 @@ function PlayerPanel({
|
|
|
3597
3670
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3598
3671
|
}
|
|
3599
3672
|
),
|
|
3600
|
-
/* @__PURE__ */ (0,
|
|
3673
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
3601
3674
|
"div",
|
|
3602
3675
|
{
|
|
3603
3676
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -3605,20 +3678,20 @@ function PlayerPanel({
|
|
|
3605
3678
|
isExtended ? "flex-row" : "flex-col"
|
|
3606
3679
|
),
|
|
3607
3680
|
children: [
|
|
3608
|
-
/* @__PURE__ */ (0,
|
|
3609
|
-
/* @__PURE__ */ (0,
|
|
3610
|
-
/* @__PURE__ */ (0,
|
|
3611
|
-
/* @__PURE__ */ (0,
|
|
3612
|
-
playerTrackObject?.loadError && /* @__PURE__ */ (0,
|
|
3681
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3682
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
|
|
3683
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
3684
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3685
|
+
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3613
3686
|
playerTrackObject.loadError,
|
|
3614
|
-
/* @__PURE__ */ (0,
|
|
3687
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3615
3688
|
void retryPlayback();
|
|
3616
3689
|
}, children: "Retry" })
|
|
3617
3690
|
] })
|
|
3618
3691
|
] }),
|
|
3619
|
-
/* @__PURE__ */ (0,
|
|
3692
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(PlayerControls, {})
|
|
3620
3693
|
] }),
|
|
3621
|
-
/* @__PURE__ */ (0,
|
|
3694
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3622
3695
|
TrackListSidebar,
|
|
3623
3696
|
{
|
|
3624
3697
|
layout: "inline",
|
|
@@ -3644,33 +3717,33 @@ function PlayerPanel({
|
|
|
3644
3717
|
// src/genre-tree/Rating.tsx
|
|
3645
3718
|
var import_uuid = require("uuid");
|
|
3646
3719
|
var import_ai = require("react-icons/ai");
|
|
3647
|
-
var
|
|
3648
|
-
var
|
|
3720
|
+
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3721
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
3649
3722
|
function Rating({ rating, handleChange }) {
|
|
3650
3723
|
const instanceId = (0, import_uuid.v4)();
|
|
3651
|
-
return /* @__PURE__ */ (0,
|
|
3652
|
-
/* @__PURE__ */ (0,
|
|
3724
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
|
|
3725
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3653
3726
|
"input",
|
|
3654
3727
|
{
|
|
3655
3728
|
id: `star-${instanceId}-${i}`,
|
|
3656
3729
|
className: "w-6 h-6 opacity-0",
|
|
3657
3730
|
type: "radio",
|
|
3658
3731
|
name: "rating",
|
|
3659
|
-
value: i === 0 ?
|
|
3732
|
+
value: i === 0 ? import_genre_tree35.FORM_RATING_NULL_VALUE : i,
|
|
3660
3733
|
checked: rating === (i === 0 ? null : i),
|
|
3661
3734
|
onChange: handleChange
|
|
3662
3735
|
}
|
|
3663
3736
|
),
|
|
3664
|
-
/* @__PURE__ */ (0,
|
|
3665
|
-
/* @__PURE__ */ (0,
|
|
3737
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex", children: [
|
|
3738
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3666
3739
|
import_ai.AiOutlineStar,
|
|
3667
3740
|
{
|
|
3668
|
-
className: `w-7 h-7 absolute top-0 left-0 ${rating ===
|
|
3741
|
+
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)]"}`
|
|
3669
3742
|
}
|
|
3670
3743
|
),
|
|
3671
|
-
/* @__PURE__ */ (0,
|
|
3744
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "flex-grow w-8" }),
|
|
3672
3745
|
" "
|
|
3673
|
-
] }) : /* @__PURE__ */ (0,
|
|
3746
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3674
3747
|
import_ai.AiFillStar,
|
|
3675
3748
|
{
|
|
3676
3749
|
className: `w-7 h-7 absolute top-0 left-0 ${(rating ?? -1) >= i ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
@@ -3680,9 +3753,9 @@ function Rating({ rating, handleChange }) {
|
|
|
3680
3753
|
}
|
|
3681
3754
|
|
|
3682
3755
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
3683
|
-
var
|
|
3684
|
-
var
|
|
3685
|
-
var
|
|
3756
|
+
var import_react22 = require("react");
|
|
3757
|
+
var import_ui23 = require("@behindthemusictree/ui");
|
|
3758
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3686
3759
|
function EntityDetailPanel({
|
|
3687
3760
|
scope,
|
|
3688
3761
|
getBackendBaseUrl,
|
|
@@ -3698,15 +3771,15 @@ function EntityDetailPanel({
|
|
|
3698
3771
|
edgeTab,
|
|
3699
3772
|
...navigation
|
|
3700
3773
|
}) {
|
|
3701
|
-
const [expandedSongUuid, setExpandedSongUuid] = (0,
|
|
3702
|
-
const [expandedArtistUuid, setExpandedArtistUuid] = (0,
|
|
3774
|
+
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react22.useState)(null);
|
|
3775
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react22.useState)(null);
|
|
3703
3776
|
const panel = useEntityPanel({
|
|
3704
3777
|
scope,
|
|
3705
3778
|
getBackendBaseUrl,
|
|
3706
3779
|
getArtistBackendBaseUrl,
|
|
3707
3780
|
getShareUrl,
|
|
3708
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
3709
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0,
|
|
3781
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
3782
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
3710
3783
|
song: {
|
|
3711
3784
|
uuid: songUuid,
|
|
3712
3785
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -3722,8 +3795,8 @@ function EntityDetailPanel({
|
|
|
3722
3795
|
...navigation
|
|
3723
3796
|
});
|
|
3724
3797
|
if (!panel) return null;
|
|
3725
|
-
return /* @__PURE__ */ (0,
|
|
3726
|
-
|
|
3798
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3799
|
+
import_ui23.DetailPanel,
|
|
3727
3800
|
{
|
|
3728
3801
|
side: "left",
|
|
3729
3802
|
title: panel.title,
|
|
@@ -3734,7 +3807,7 @@ function EntityDetailPanel({
|
|
|
3734
3807
|
onExpandedChange: panel.onExpandedChange,
|
|
3735
3808
|
aside: panel.extraContent,
|
|
3736
3809
|
edgeTab,
|
|
3737
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0,
|
|
3810
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
|
|
3738
3811
|
panel.content,
|
|
3739
3812
|
panel.extraContent
|
|
3740
3813
|
] }) : panel.content
|