@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
package/dist/index.cjs
CHANGED
|
@@ -260,7 +260,7 @@ function Toast({ message, onClose, durationMs = 2200 }) {
|
|
|
260
260
|
role: "status",
|
|
261
261
|
"aria-live": "polite",
|
|
262
262
|
"aria-atomic": "true",
|
|
263
|
-
className: "pointer-events-auto w-full max-w-md rounded-md bg-[var(--color-surface)] px-4 py-4 text-
|
|
263
|
+
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",
|
|
264
264
|
children: message
|
|
265
265
|
}
|
|
266
266
|
) }),
|
|
@@ -332,14 +332,14 @@ function TrackUploadPopup({
|
|
|
332
332
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center space-x-3", children: [
|
|
333
333
|
getStatusIcon(item.status),
|
|
334
334
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
335
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "font-medium text-
|
|
336
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-
|
|
335
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "font-medium text-body truncate max-w-xs", title: item.file.name, children: item.file.name }),
|
|
336
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-caption text-[var(--color-neutral-500)]", children: [
|
|
337
337
|
(item.file.size / 1024 / 1024).toFixed(1),
|
|
338
338
|
" MB"
|
|
339
339
|
] })
|
|
340
340
|
] })
|
|
341
341
|
] }),
|
|
342
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-body text-[var(--color-neutral-600)]", children: getStatusText(item.status) })
|
|
343
343
|
] }),
|
|
344
344
|
item.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-full bg-[var(--color-neutral-200)] rounded-full h-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
345
345
|
"div",
|
|
@@ -348,9 +348,9 @@ function TrackUploadPopup({
|
|
|
348
348
|
style: { width: `${item.progress}%` }
|
|
349
349
|
}
|
|
350
350
|
) }),
|
|
351
|
-
item.status === "error" && item.error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-[var(--color-red-500)] text-
|
|
351
|
+
item.status === "error" && item.error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-[var(--color-red-500)] text-body mt-2", children: item.error.name === "InvalidInputError" ? "Upload failed due to invalid file data. Please check your file and try again." : item.error.name === "ZodError" ? "Upload failed due to a server error. Please try again later." : item.error.message })
|
|
352
352
|
] }, item.id)),
|
|
353
|
-
allComplete && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-
|
|
353
|
+
allComplete && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-body text-[var(--color-neutral-600)]", children: [
|
|
354
354
|
successfulCount,
|
|
355
355
|
" successful, ",
|
|
356
356
|
errorCount,
|
|
@@ -399,7 +399,7 @@ function InternalErrorPopup({ errorCode, contactEmail, ...rest }) {
|
|
|
399
399
|
" ",
|
|
400
400
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: `mailto:${contactEmail}`, className: "text-[var(--color-primary)] hover:text-[var(--color-primary-hover)]", children: contactEmail })
|
|
401
401
|
] }) }),
|
|
402
|
-
errorCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "text-
|
|
402
|
+
errorCode && /* @__PURE__ */ (0, import_jsx_runtime7.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: [
|
|
403
403
|
"Error Code: ",
|
|
404
404
|
errorCode
|
|
405
405
|
] })
|
|
@@ -515,7 +515,7 @@ function SpotifyAuthErrorPopup({
|
|
|
515
515
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_fa2.FaSpotify, { className: "text-[#1DB954] text-7xl" }),
|
|
516
516
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-3 text-center", children: [
|
|
517
517
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-xl font-medium text-[var(--color-text)]", children: message }),
|
|
518
|
-
details && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-
|
|
518
|
+
details && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-body text-[var(--color-neutral-500)] bg-[var(--color-neutral-100)] p-3 rounded-lg border border-[var(--color-neutral-100)]", children: details }),
|
|
519
519
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-2 text-center", children: [
|
|
520
520
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-base text-[var(--color-neutral-700)]", children: "The Spotify app is in development mode, so only allowlisted accounts can connect." }),
|
|
521
521
|
requestAccessHref && contactEmail ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "text-base text-[var(--color-neutral-700)]", children: [
|
|
@@ -589,13 +589,13 @@ function AuthCallbackHandler({ renderStatus, ...options }) {
|
|
|
589
589
|
}
|
|
590
590
|
|
|
591
591
|
// src/genre-tree/GenreTreeView.tsx
|
|
592
|
-
var
|
|
592
|
+
var import_react19 = require("react");
|
|
593
593
|
var import_react_query3 = require("@tanstack/react-query");
|
|
594
|
-
var
|
|
595
|
-
var
|
|
596
|
-
var
|
|
594
|
+
var import_lucide_react18 = require("lucide-react");
|
|
595
|
+
var import_lucide_react19 = require("lucide-react");
|
|
596
|
+
var import_ui24 = require("@behindthemusictree/ui");
|
|
597
597
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
598
|
-
var
|
|
598
|
+
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
599
599
|
var import_popup6 = require("@behindthemusictree/app-kit/popup");
|
|
600
600
|
|
|
601
601
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
@@ -643,21 +643,20 @@ function useGenrePlaylistPlayback({
|
|
|
643
643
|
}) {
|
|
644
644
|
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
645
645
|
const origin = trackList?.origin;
|
|
646
|
-
const
|
|
646
|
+
const playing = (0, import_react3.useMemo)(() => {
|
|
647
647
|
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
648
648
|
const playlistOrigin = origin;
|
|
649
649
|
if (playlistOrigin.artistUuid !== artist?.uuid) return null;
|
|
650
650
|
const playlist = genrePlaylists.find((item) => item.uuid === origin.uuid) ?? playlistOrigin.criteriaPlaylist;
|
|
651
651
|
const expected = scope === "reference" && playlist && !("criteria" in playlist && playlist.criteria === null) ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
652
|
-
|
|
653
|
-
return origin.uuid;
|
|
652
|
+
return { uuid: origin.uuid, selectionKey: (0, import_genre_tree2.genreMusicSelectionKey)(playlistOrigin.selection ?? expected).join() };
|
|
654
653
|
}, [origin, artist, genrePlaylists, scope]);
|
|
655
|
-
const play = (0, import_react3.useCallback)(async (playlist) => {
|
|
654
|
+
const play = (0, import_react3.useCallback)(async (playlist, requested) => {
|
|
656
655
|
if (artist && !playlist.criteria) return;
|
|
657
|
-
const selection = scope === "reference" && playlist.criteria !== null ? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
656
|
+
const selection = scope === "reference" && playlist.criteria !== null ? requested ?? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
658
657
|
return selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope);
|
|
659
658
|
}, [artist, scope, playNewTrackListFromGenrePlaylist]);
|
|
660
|
-
return (0, import_react3.useMemo)(() => ({
|
|
659
|
+
return (0, import_react3.useMemo)(() => ({ playing, play }), [playing, play]);
|
|
661
660
|
}
|
|
662
661
|
|
|
663
662
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
@@ -684,7 +683,8 @@ function GenrePlaylistTreePerRoot({
|
|
|
684
683
|
}) {
|
|
685
684
|
const { isPlaying, setIsPlaying } = (0, import_player.usePlayer)();
|
|
686
685
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: genrePlaylistTreePerRoot });
|
|
687
|
-
const {
|
|
686
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
687
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
688
688
|
const { showPopup } = (0, import_popup2.usePopup)();
|
|
689
689
|
const nodes = (0, import_react4.useMemo)(
|
|
690
690
|
() => genrePlaylistTreePerRoot.map((genrePlaylist) => ({
|
|
@@ -802,7 +802,8 @@ function GenrePlaylistTreeWheel({
|
|
|
802
802
|
}) {
|
|
803
803
|
const { isPlaying, setIsPlaying } = (0, import_player2.usePlayer)();
|
|
804
804
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
805
|
-
const {
|
|
805
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
806
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
806
807
|
const { showPopup } = (0, import_popup3.usePopup)();
|
|
807
808
|
const nodes = (0, import_react5.useMemo)(
|
|
808
809
|
() => genrePlaylists.map((genrePlaylist) => ({
|
|
@@ -924,7 +925,8 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
924
925
|
};
|
|
925
926
|
const { isPlaying, setIsPlaying } = (0, import_player3.usePlayer)();
|
|
926
927
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
927
|
-
const {
|
|
928
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
929
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
928
930
|
const nodes = (0, import_react6.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric), [genrePlaylists, sizeMetric]);
|
|
929
931
|
const handlePlayPause = (0, import_react6.useCallback)(
|
|
930
932
|
(nodeId) => {
|
|
@@ -1111,7 +1113,7 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1111
1113
|
artist.disambiguation
|
|
1112
1114
|
] })
|
|
1113
1115
|
] }),
|
|
1114
|
-
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "block truncate text-
|
|
1116
|
+
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [
|
|
1115
1117
|
"also known as ",
|
|
1116
1118
|
artist.matchedAlias
|
|
1117
1119
|
] })
|
|
@@ -1136,7 +1138,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1136
1138
|
key: song.uuid,
|
|
1137
1139
|
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
1138
1140
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
1139
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate text-
|
|
1141
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.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 ") })
|
|
1140
1142
|
] }),
|
|
1141
1143
|
onSelect: () => onSelect(song)
|
|
1142
1144
|
})),
|
|
@@ -1159,9 +1161,9 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
1159
1161
|
content: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
1160
1162
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
1161
1163
|
genre.name,
|
|
1162
|
-
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ml-2 text-
|
|
1164
|
+
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ml-2 text-caption font-normal italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1163
1165
|
] }),
|
|
1164
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate text-
|
|
1166
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: describe?.(genre) ?? `${genre.treeName} \xB7 ${genre.root.name}` })
|
|
1165
1167
|
] }),
|
|
1166
1168
|
onSelect: () => onSelect(genre)
|
|
1167
1169
|
})),
|
|
@@ -1202,7 +1204,7 @@ function GenreSearch({
|
|
|
1202
1204
|
key: genrePlaylist.uuid,
|
|
1203
1205
|
content: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
1204
1206
|
genrePlaylist.name,
|
|
1205
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ml-2 text-
|
|
1207
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1206
1208
|
] }),
|
|
1207
1209
|
onSelect: () => select(genrePlaylist)
|
|
1208
1210
|
}))
|
|
@@ -1277,22 +1279,22 @@ function GenreTreeSearch({
|
|
|
1277
1279
|
}
|
|
1278
1280
|
|
|
1279
1281
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
1280
|
-
var
|
|
1282
|
+
var import_react15 = require("react");
|
|
1281
1283
|
var import_genre_tree_view4 = require("@behindthemusictree/genre-tree-view");
|
|
1282
|
-
var
|
|
1283
|
-
var
|
|
1284
|
-
var
|
|
1284
|
+
var import_ui13 = require("@behindthemusictree/ui");
|
|
1285
|
+
var import_lucide_react13 = require("lucide-react");
|
|
1286
|
+
var import_genre_tree20 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1285
1287
|
|
|
1286
1288
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1287
|
-
var
|
|
1288
|
-
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
1289
|
-
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1289
|
+
var import_genre_tree19 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1290
1290
|
|
|
1291
1291
|
// src/genre-tree/GenreActionBand.tsx
|
|
1292
1292
|
var import_lucide_react11 = require("lucide-react");
|
|
1293
|
+
var import_ui9 = require("@behindthemusictree/ui");
|
|
1293
1294
|
|
|
1294
1295
|
// src/genre-tree/ShareActionButton.tsx
|
|
1295
1296
|
var import_lucide_react10 = require("lucide-react");
|
|
1297
|
+
var import_ui8 = require("@behindthemusictree/ui");
|
|
1296
1298
|
var import_popup4 = require("@behindthemusictree/app-kit/popup");
|
|
1297
1299
|
|
|
1298
1300
|
// src/genre-tree/SharePopup.tsx
|
|
@@ -1303,7 +1305,7 @@ var import_si = require("react-icons/si");
|
|
|
1303
1305
|
|
|
1304
1306
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
1305
1307
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1306
|
-
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-
|
|
1308
|
+
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";
|
|
1307
1309
|
function Contents({ icon, label }) {
|
|
1308
1310
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
1309
1311
|
/* @__PURE__ */ (0, import_jsx_runtime22.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 }),
|
|
@@ -1333,9 +1335,9 @@ function SharePreviewCard({ target, url }) {
|
|
|
1333
1335
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "rounded-3xl bg-[var(--color-surface-muted)] p-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex min-h-32 overflow-hidden rounded-2xl bg-[var(--color-surface)] shadow-lg", children: [
|
|
1334
1336
|
/* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)(Icon, { "aria-hidden": "true", className: "h-10 w-10" }) }),
|
|
1335
1337
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
1336
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
1337
1339
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
1338
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-
|
|
1340
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
1339
1341
|
] })
|
|
1340
1342
|
] }) });
|
|
1341
1343
|
}
|
|
@@ -1476,8 +1478,8 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1476
1478
|
}
|
|
1477
1479
|
)
|
|
1478
1480
|
] }),
|
|
1479
|
-
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-
|
|
1480
|
-
shareError && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-
|
|
1481
|
+
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: "Could not copy the link." }),
|
|
1482
|
+
shareError && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
1481
1483
|
] })
|
|
1482
1484
|
}
|
|
1483
1485
|
),
|
|
@@ -1492,18 +1494,14 @@ function ShareActionButton({ target, url }) {
|
|
|
1492
1494
|
const openSharePopup = () => {
|
|
1493
1495
|
showPopup(/* @__PURE__ */ (0, import_jsx_runtime25.jsx)(SharePopup, { target, url, onClose: hidePopup }));
|
|
1494
1496
|
};
|
|
1495
|
-
return /* @__PURE__ */ (0, import_jsx_runtime25.
|
|
1496
|
-
|
|
1497
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1498
|
+
import_ui8.ActionButton,
|
|
1497
1499
|
{
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
className: "group flex flex-col items-center gap-1 w-16 text-xs text-center text-[var(--color-text)] focus-visible:outline-none",
|
|
1500
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_lucide_react10.Share2, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1501
|
+
label: "Share",
|
|
1501
1502
|
"aria-label": `Share ${target.name}`,
|
|
1502
1503
|
title: `Share ${target.name}`,
|
|
1503
|
-
|
|
1504
|
-
/* @__PURE__ */ (0, import_jsx_runtime25.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_runtime25.jsx)(import_lucide_react10.Share2, { "aria-hidden": "true", className: "w-5 h-5" }) }),
|
|
1505
|
-
"Share"
|
|
1506
|
-
]
|
|
1504
|
+
onClick: openSharePopup
|
|
1507
1505
|
}
|
|
1508
1506
|
);
|
|
1509
1507
|
}
|
|
@@ -1512,8 +1510,7 @@ function ShareActionButton({ target, url }) {
|
|
|
1512
1510
|
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1513
1511
|
function GenreActionBand({
|
|
1514
1512
|
node,
|
|
1515
|
-
|
|
1516
|
-
isPlaying = false,
|
|
1513
|
+
playActions,
|
|
1517
1514
|
onZoomIn,
|
|
1518
1515
|
onAddChild,
|
|
1519
1516
|
onRename,
|
|
@@ -1527,14 +1524,6 @@ function GenreActionBand({
|
|
|
1527
1524
|
}) {
|
|
1528
1525
|
const items = [];
|
|
1529
1526
|
const adminItems = [];
|
|
1530
|
-
if (onPlayPause) {
|
|
1531
|
-
items.push({
|
|
1532
|
-
key: "play-pause",
|
|
1533
|
-
label: isPlaying ? "Pause" : "Play",
|
|
1534
|
-
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react11.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_lucide_react11.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1535
|
-
onClick: onPlayPause
|
|
1536
|
-
});
|
|
1537
|
-
}
|
|
1538
1527
|
if (onZoomIn) {
|
|
1539
1528
|
items.push({
|
|
1540
1529
|
key: "zoom-in",
|
|
@@ -1571,66 +1560,147 @@ function GenreActionBand({
|
|
|
1571
1560
|
disabled: action.enabled ? !action.enabled(node) : false
|
|
1572
1561
|
});
|
|
1573
1562
|
}
|
|
1574
|
-
|
|
1575
|
-
|
|
1576
|
-
|
|
1563
|
+
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui9.ActionButton, { icon: item.icon, label: item.label, disabled: item.disabled, title: item.title, onClick: item.onClick }, item.key));
|
|
1564
|
+
if (!playActions && items.length === 0 && adminItems.length === 0 && !(shareTarget && shareUrl)) return null;
|
|
1565
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_ui9.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime26.jsxs)(
|
|
1566
|
+
import_ui9.ActionBand,
|
|
1577
1567
|
{
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
title: item.title,
|
|
1581
|
-
onClick: item.onClick,
|
|
1582
|
-
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",
|
|
1568
|
+
className: "genre-action-band",
|
|
1569
|
+
section: { title: "Admin", label: "Admin actions", children: renderItems(adminItems) },
|
|
1583
1570
|
children: [
|
|
1584
|
-
|
|
1585
|
-
|
|
1571
|
+
playActions,
|
|
1572
|
+
renderItems(items),
|
|
1573
|
+
shareTarget && shareUrl && /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
1586
1574
|
]
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1575
|
+
}
|
|
1576
|
+
) });
|
|
1577
|
+
}
|
|
1578
|
+
|
|
1579
|
+
// src/genre-tree/GenrePlayActions.tsx
|
|
1580
|
+
var import_lucide_react12 = require("lucide-react");
|
|
1581
|
+
var import_ui10 = require("@behindthemusictree/ui");
|
|
1582
|
+
var import_genre_tree10 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1583
|
+
var import_player4 = require("@behindthemusictree/app-kit/player");
|
|
1584
|
+
|
|
1585
|
+
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1586
|
+
var import_react11 = require("react");
|
|
1587
|
+
|
|
1588
|
+
// src/genre-tree/regionGlobePaths.ts
|
|
1589
|
+
var REGION_GLOBE_PATHS = {
|
|
1590
|
+
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",
|
|
1591
|
+
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",
|
|
1592
|
+
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"
|
|
1593
|
+
};
|
|
1594
|
+
var REGION_GLOBES = ["africa", "americas", "asia"];
|
|
1595
|
+
|
|
1596
|
+
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1597
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1598
|
+
var ROTATION_INTERVAL_MS = 3e3;
|
|
1599
|
+
function RegionGlobeIcon({ className: className2 }) {
|
|
1600
|
+
const [index, setIndex] = (0, import_react11.useState)(0);
|
|
1601
|
+
(0, import_react11.useEffect)(() => {
|
|
1602
|
+
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
1603
|
+
let timer;
|
|
1604
|
+
const sync = () => {
|
|
1605
|
+
clearInterval(timer);
|
|
1606
|
+
timer = reducedMotion.matches ? void 0 : setInterval(() => setIndex((i) => (i + 1) % REGION_GLOBES.length), ROTATION_INTERVAL_MS);
|
|
1607
|
+
};
|
|
1608
|
+
sync();
|
|
1609
|
+
reducedMotion.addEventListener("change", sync);
|
|
1610
|
+
return () => {
|
|
1611
|
+
reducedMotion.removeEventListener("change", sync);
|
|
1612
|
+
clearInterval(timer);
|
|
1613
|
+
};
|
|
1614
|
+
}, []);
|
|
1615
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("svg", { viewBox: "0 0 512 512", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("path", { "data-testid": "region-globe-path", d: REGION_GLOBE_PATHS[REGION_GLOBES[index]] }) });
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
// src/genre-tree/treeMarkPath.ts
|
|
1619
|
+
var TREE_MARK_PATH = "M3171 5598 c-5 -13 -5 -24 0 -26 5 -2 9 -16 9 -31 0 -25 -3 -28 -25 -23 l-25 4 0 -116 c0 -64 3 -116 8 -116 10 0 32 51 26 61 -3 5 -1 9 4 9 5 0 15 12 21 28 7 15 26 36 43 47 30 20 88 105 71 105 -4 0 -33 -21 -62 -47 l-54 -47 6 63 c4 35 7 72 7 82 0 10 9 19 23 22 16 3 13 5 -11 6 -25 1 -35 -4 -41 -21z M2893 5485 c8 -76 24 -100 71 -100 l36 0 0 53 c0 58 -15 69 -28 20 -8 -29 -10 -30 -16 -13 -15 43 -42 89 -55 93 -11 4 -13 -6 -8 -53z M2484 5438 c8 -70 49 -169 54 -131 2 12 10 27 18 33 17 15 19 84 3 129 -9 27 -16 31 -46 31 l-36 0 7 -62z M2625 5448 c-7 -22 -24 -121 -31 -179 l-6 -57 -27 11 c-15 5 -32 19 -37 31 -9 21 -88 86 -105 86 -39 0 38 -104 118 -158 17 -12 56 -59 86 -105 30 -45 67 -92 81 -104 14 -13 26 -30 26 -38 0 -13 -9 -11 -45 11 -67 39 -58 10 21 -66 67 -65 96 -110 108 -167 4 -17 13 -34 20 -36 20 -8 66 -186 75 -289 13 -161 -8 -272 -72 -365 -12 -18 -30 -33 -39 -33 -23 0 -53 33 -79 89 -25 54 -69 112 -121 162 -35 33 -38 40 -38 92 0 58 36 172 79 252 25 47 29 125 6 125 -19 0 -30 -22 -50 -100 -9 -35 -24 -78 -32 -94 l-16 -30 -19 24 -20 25 7 -58 c8 -62 0 -127 -16 -127 -19 0 -122 107 -166 172 -52 79 -68 150 -60 273 8 108 17 129 67 149 58 23 97 64 105 109 9 47 -5 49 -63 6 l-42 -30 15 35 c17 41 20 102 5 111 -18 11 -45 -4 -64 -36 -11 -19 -20 -60 -23 -110 -4 -54 -10 -79 -18 -79 -20 0 -27 28 -30 108 -2 40 -6 76 -9 79 -3 4 -6 51 -6 105 0 86 -3 101 -21 119 -27 27 -42 20 -53 -24 -7 -28 -5 -51 7 -90 9 -30 17 -76 17 -103 l0 -49 -29 51 c-29 49 -92 114 -111 114 -6 0 -10 -11 -10 -25 0 -14 5 -25 10 -25 6 0 10 -6 10 -13 0 -7 23 -44 51 -82 61 -84 59 -82 52 -57 -3 14 2 24 15 31 12 6 23 23 25 38 2 16 5 2 6 -29 1 -46 -2 -58 -14 -58 -21 0 -19 -13 10 -70 22 -44 25 -61 25 -165 l0 -116 -47 27 c-65 36 -142 118 -176 187 -15 31 -37 62 -49 68 -21 11 -21 10 -15 -41 l6 -52 -29 6 c-37 7 -39 -7 -4 -31 14 -10 53 -40 86 -68 92 -76 130 -104 163 -119 39 -19 101 -84 109 -116 10 -42 50 -88 217 -245 50 -47 94 -102 134 -167 33 -54 65 -98 71 -98 17 0 45 -79 51 -145 4 -47 0 -76 -20 -135 -14 -41 -39 -121 -56 -177 -18 -57 -35 -103 -40 -103 -4 0 -26 13 -49 30 -31 22 -50 49 -82 117 -99 209 -116 241 -185 337 -123 172 -123 173 -128 311 -5 140 -29 245 -57 245 -12 0 -20 -11 -24 -31 -9 -46 -7 -108 3 -127 14 -26 25 -162 14 -162 -20 0 -160 99 -192 135 -19 22 -42 58 -52 80 -10 23 -27 52 -37 66 -10 13 -26 38 -34 54 -9 17 -23 45 -33 64 -15 29 -16 40 -6 80 31 116 34 139 27 205 -7 57 -11 69 -28 74 -14 3 -32 30 -54 79 -21 46 -39 73 -47 70 -13 -5 -14 -15 -3 -65 l8 -33 -49 25 c-61 31 -93 40 -93 27 0 -13 43 -41 122 -79 47 -22 72 -41 83 -61 19 -38 19 -51 0 -51 -12 0 -15 -15 -16 -72 -1 -79 -12 -134 -22 -108 -3 8 -10 48 -16 89 -14 89 -25 111 -54 111 -38 0 -50 -15 -45 -54 4 -40 2 -42 -26 -21 -29 22 -36 19 -36 -20 0 -39 39 -85 125 -145 38 -27 62 -56 99 -120 45 -79 82 -177 70 -189 -2 -3 -42 3 -87 13 -45 10 -99 21 -119 26 -47 9 -103 51 -125 93 -24 44 -83 203 -94 252 -5 25 -4 59 3 91 14 68 3 140 -23 155 -12 6 -23 8 -27 5 -14 -15 -13 -115 2 -159 39 -116 0 -116 -70 1 -22 36 -31 42 -59 42 -20 0 -35 6 -39 15 -6 16 -56 21 -56 6 0 -5 23 -25 51 -44 53 -36 158 -156 188 -216 10 -20 26 -60 36 -88 11 -29 25 -53 32 -53 8 0 13 -12 13 -30 0 -26 -4 -30 -27 -31 l-28 -1 25 -7 c26 -8 177 -87 196 -102 5 -4 50 -18 100 -29 122 -29 277 -78 300 -95 10 -8 26 -15 34 -15 35 0 160 -166 160 -212 0 -22 -32 -24 -50 -4 -11 14 -100 46 -165 61 -16 3 -68 25 -115 48 -102 49 -163 56 -168 19 -9 -62 58 -104 178 -112 63 -5 103 -14 155 -37 39 -16 91 -38 117 -47 26 -9 74 -35 106 -56 52 -33 65 -48 96 -112 20 -40 39 -95 43 -122 6 -47 6 -48 -18 -41 -33 10 -69 33 -69 45 0 6 -10 10 -23 10 -13 0 -27 4 -32 9 -6 5 -27 14 -47 20 -20 7 -53 23 -73 37 -43 29 -45 29 -45 7 0 -26 80 -96 145 -127 119 -56 274 -185 311 -259 55 -107 104 -410 104 -640 0 -162 -22 -325 -45 -333 -25 -10 -72 25 -168 123 -129 131 -140 148 -182 274 -20 60 -50 142 -66 181 -16 39 -45 131 -65 202 -24 93 -55 173 -104 274 -77 158 -78 166 -32 256 31 64 27 129 -12 181 -31 40 -39 42 -65 18 -51 -49 -55 -120 -11 -208 37 -74 37 -85 3 -85 -36 0 -94 65 -137 154 -18 39 -37 80 -40 92 -3 11 -14 29 -24 40 -10 10 -28 35 -42 54 -13 19 -40 55 -61 80 -20 25 -41 63 -47 85 -6 22 -16 62 -23 89 -20 81 -95 147 -113 100 -18 -47 -6 -92 39 -147 25 -31 45 -61 45 -67 0 -15 -42 -3 -116 31 -94 44 -156 124 -184 235 -9 36 -13 41 -38 40 -39 -2 -144 113 -186 205 -31 66 -33 68 -53 54 -11 -8 -24 -11 -27 -7 -4 4 11 -24 33 -62 39 -67 43 -86 18 -86 -8 0 -8 3 1 9 11 6 9 9 -7 14 -11 3 -25 -1 -31 -7 -7 -10 0 -16 29 -24 39 -12 203 -147 215 -178 13 -34 4 -35 -48 -6 -64 37 -126 51 -126 30 0 -26 55 -67 125 -92 46 -16 80 -36 100 -58 l29 -33 -54 -3 c-79 -5 -203 14 -249 38 -47 24 -70 54 -105 140 -43 105 -115 163 -103 83 3 -21 9 -47 13 -57 4 -11 -15 4 -42 32 -62 64 -84 67 -84 14 0 -41 24 -76 61 -87 16 -6 18 -9 8 -15 -23 -15 15 -45 117 -91 52 -24 93 -48 91 -54 -10 -28 -150 -28 -190 0 -21 15 -47 5 -47 -17 0 -5 -10 -19 -22 -29 -23 -20 -23 -20 112 -14 174 8 208 8 430 0 l185 -7 84 -41 c115 -57 180 -118 225 -212 20 -41 36 -77 36 -80 0 -14 89 -126 150 -190 74 -78 120 -144 120 -175 0 -30 10 -33 -201 52 -94 38 -131 71 -218 195 -27 37 -59 77 -71 88 l-23 20 7 -40 c4 -22 12 -44 17 -49 13 -14 11 -26 -4 -26 -7 0 -29 21 -48 48 -33 45 -34 51 -39 159 -4 89 -9 116 -22 130 -17 16 -18 16 -18 0 0 -9 -7 -17 -16 -17 -14 0 -16 -9 -11 -62 3 -35 8 -74 12 -88 l7 -25 -25 27 c-41 44 -127 118 -137 118 -18 0 -10 -57 12 -85 18 -24 20 -32 10 -57 -10 -28 -9 -30 22 -43 18 -8 54 -19 79 -26 36 -9 60 -24 99 -66 80 -83 80 -83 1 -83 -80 0 -176 21 -236 51 -107 54 -234 169 -252 228 -4 14 -12 29 -17 35 -5 6 -18 25 -28 43 -24 40 -90 64 -116 42 -22 -18 -13 -84 17 -116 13 -13 42 -32 64 -42 22 -10 74 -53 115 -96 l75 -77 -75 5 c-135 8 -243 76 -336 207 -31 44 -65 87 -77 95 -37 26 -34 -9 7 -88 20 -39 34 -72 31 -75 -2 -2 -26 11 -52 31 -90 65 -143 83 -143 49 0 -32 71 -88 150 -117 41 -15 113 -47 159 -71 46 -24 99 -46 118 -50 18 -3 33 -12 33 -18 0 -12 -111 -46 -149 -46 -12 0 -29 -8 -39 -17 -10 -10 -27 -19 -37 -19 -11 -1 -45 -9 -75 -17 -58 -16 -110 -62 -110 -97 0 -39 116 -45 167 -9 11 8 34 31 52 51 28 32 50 43 144 74 145 47 222 48 404 5 70 -17 177 -38 237 -47 128 -19 202 -43 250 -79 18 -14 73 -42 122 -61 164 -66 208 -112 243 -251 36 -141 27 -167 -44 -123 -19 12 -63 23 -111 28 -117 13 -134 25 -275 193 -63 74 -193 151 -266 157 -29 2 -66 -1 -81 -7 -24 -10 -37 -9 -80 8 -66 26 -70 9 -11 -44 72 -65 119 -80 239 -78 60 1 109 -2 117 -8 6 -6 26 -35 42 -64 17 -30 46 -64 64 -77 19 -13 49 -40 67 -61 l34 -39 -79 3 c-57 3 -80 0 -83 -9 -3 -10 -7 -10 -18 -1 -8 6 -11 15 -8 20 3 5 0 9 -5 9 -16 0 -13 -16 6 -36 36 -36 78 -44 227 -44 119 0 152 -3 188 -19 56 -24 95 -64 125 -126 13 -27 35 -68 48 -90 14 -22 25 -53 25 -69 l0 -29 -107 5 c-131 6 -193 28 -290 100 -37 28 -82 56 -98 63 -75 32 -176 123 -277 247 -34 42 -122 98 -134 85 -5 -5 103 -138 184 -226 52 -57 46 -61 -49 -31 -87 28 -173 85 -325 214 -144 123 -189 151 -254 159 -25 2 -39 3 -32 0 6 -3 12 -16 12 -29 0 -17 -4 -23 -12 -19 -7 4 -1 -5 15 -19 15 -14 46 -30 70 -36 23 -6 60 -17 82 -25 l40 -13 -52 -1 c-49 -1 -53 -3 -53 -25 0 -28 28 -36 122 -36 54 0 62 -3 91 -32 l32 -33 -52 -3 c-88 -5 -75 -26 39 -62 130 -41 178 -63 206 -93 l22 -24 -20 -18 c-12 -11 -41 -20 -74 -23 -48 -4 -60 0 -116 32 -118 69 -241 96 -279 62 -13 -12 -40 -16 -104 -16 -48 0 -95 4 -105 9 -9 5 -34 16 -55 25 -20 9 -76 53 -122 97 -47 45 -88 79 -91 76 -12 -12 6 -54 41 -100 l36 -47 -74 0 c-88 0 -112 15 -78 49 26 26 21 39 -34 84 -87 73 -132 32 -50 -45 25 -23 45 -46 45 -50 0 -4 -21 2 -46 12 -45 20 -114 27 -114 12 0 -4 16 -22 35 -40 39 -38 78 -47 255 -61 164 -14 178 -17 172 -47 -2 -13 -2 -30 2 -39 5 -13 9 -13 40 2 19 9 33 20 30 25 -4 5 4 4 15 -4 21 -13 20 -15 -44 -74 -36 -33 -65 -66 -65 -72 0 -21 68 15 142 74 38 30 84 62 103 70 73 30 203 11 312 -46 32 -17 82 -33 111 -37 l53 -6 -28 -30 c-15 -16 -44 -40 -63 -52 -63 -42 -100 -82 -100 -111 0 -25 2 -26 37 -21 28 5 47 17 73 49 65 78 175 183 224 216 34 22 61 32 88 32 43 0 122 -36 152 -69 10 -11 39 -32 62 -46 43 -25 53 -46 36 -72 -11 -17 -200 -86 -232 -85 -28 1 -122 -47 -127 -65 -3 -8 14 -13 54 -15 l58 -3 -65 -44 c-36 -25 -68 -49 -71 -53 -11 -17 -115 -10 -188 12 -105 32 -112 11 -14 -39 l56 -28 -40 -6 c-52 -9 -96 0 -154 29 -31 15 -50 19 -60 13 -15 -10 -16 -10 44 -47 20 -13 37 -27 37 -31 0 -15 -144 -71 -205 -81 -33 -5 -85 -10 -116 -10 -32 0 -63 -6 -75 -14 -18 -13 -15 -15 34 -22 l53 -7 -31 -18 c-18 -12 -30 -27 -30 -40 0 -21 4 -21 61 -16 50 4 75 14 145 57 46 28 112 63 146 77 62 24 191 62 215 63 22 0 -47 -103 -107 -161 -42 -41 -60 -66 -65 -92 -10 -49 0 -60 47 -54 65 9 99 53 124 160 20 83 49 133 94 163 22 15 40 30 40 34 0 4 8 10 18 13 9 3 31 15 49 27 31 21 31 21 26 0 -3 -11 -21 -37 -40 -58 -43 -45 -72 -106 -73 -150 0 -39 18 -49 56 -30 38 18 63 64 75 137 13 82 40 142 89 194 22 24 40 49 40 54 0 6 24 21 53 34 49 22 63 23 237 20 193 -2 278 -14 348 -50 21 -11 44 -27 52 -36 7 -9 32 -27 55 -41 49 -28 138 -147 184 -243 16 -35 42 -114 57 -175 35 -147 31 -268 -14 -436 -17 -63 -37 -166 -45 -227 -12 -94 -21 -127 -54 -195 -22 -46 -52 -94 -67 -108 -15 -14 -46 -44 -68 -67 -23 -24 -47 -43 -53 -43 -7 0 -25 -12 -41 -26 -129 -121 -526 -267 -721 -268 -104 0 -109 -15 -19 -57 75 -35 67 -35 221 -10 125 21 235 27 235 13 0 -16 -66 -72 -85 -72 -24 0 -85 -36 -85 -49 0 -14 12 -19 58 -27 35 -5 42 -4 42 10 0 9 5 17 10 17 28 4 74 20 80 29 9 14 226 119 288 139 63 21 215 43 239 34 32 -12 12 -50 -52 -102 -36 -28 -73 -55 -83 -58 -17 -7 -66 -39 -92 -60 -8 -7 -38 -32 -67 -57 l-52 -45 42 -6 c36 -6 54 -1 122 33 44 22 120 56 169 76 112 45 222 107 289 164 46 40 84 62 107 62 18 0 130 -83 130 -96 0 -8 4 -14 10 -14 5 0 39 -26 75 -59 36 -32 96 -76 132 -97 36 -21 68 -46 71 -56 5 -19 21 -22 59 -12 18 5 20 9 10 19 -7 7 -69 71 -139 143 -147 149 -161 179 -80 168 136 -19 195 -39 378 -128 78 -37 147 -68 152 -68 6 0 15 -7 20 -16 8 -14 14 -15 46 -4 l38 12 -104 57 c-125 69 -148 84 -148 93 0 16 94 7 223 -22 74 -17 146 -30 160 -30 14 0 29 -4 32 -10 7 -11 54 6 115 43 l40 24 -38 1 c-22 1 -68 11 -103 21 -35 11 -107 30 -159 41 -131 31 -295 99 -406 171 -235 153 -355 366 -357 634 -1 211 65 343 285 568 117 119 206 167 368 198 153 29 267 59 328 86 80 35 166 44 264 27 148 -26 167 -38 251 -169 71 -110 136 -165 196 -165 26 0 31 4 31 23 -1 32 -28 62 -87 91 -39 20 -66 45 -118 112 -95 123 -95 135 -5 92 25 -12 77 -31 116 -43 56 -17 76 -19 97 -10 27 11 26 11 -25 29 -113 39 -138 49 -138 57 0 14 91 55 153 68 33 7 75 10 95 7 27 -4 31 -3 17 4 -19 8 -19 9 3 9 12 1 22 7 22 15 0 10 7 12 22 8 12 -3 17 -7 10 -10 -6 -2 -12 -10 -12 -18 0 -8 -6 -14 -12 -15 -27 -2 39 -17 80 -18 29 -1 42 3 42 13 0 20 -19 32 -67 45 -49 13 -53 22 -20 44 49 32 128 39 235 21 56 -9 112 -14 126 -10 26 6 96 69 96 86 0 6 -32 10 -77 10 -84 0 -126 -7 -118 -20 9 -14 -17 -24 -67 -24 -34 -1 -48 3 -48 13 0 8 -7 11 -20 8 -17 -4 -18 -2 -9 14 5 11 14 17 20 14 5 -4 9 0 9 8 0 8 16 35 35 60 35 45 35 46 14 57 -18 10 -23 8 -37 -12 -67 -95 -162 -167 -297 -225 -55 -23 -99 -47 -98 -53 2 -5 -6 -10 -18 -10 -27 0 -23 8 31 71 100 117 116 131 161 155 80 40 80 70 1 41 l-47 -18 36 38 c47 49 59 73 59 120 0 67 -24 80 -82 46 -49 -29 -76 -85 -89 -183 -10 -81 -9 -80 -89 -174 -20 -22 -43 -53 -53 -68 -28 -45 -89 -61 -217 -56 -70 2 -114 8 -118 15 -4 6 -28 13 -54 15 l-46 3 53 71 c51 68 100 104 140 104 50 0 125 73 125 122 0 30 0 31 -45 26 -28 -4 -59 -16 -82 -34 -30 -23 -35 -24 -28 -8 22 51 37 105 31 111 -13 13 -47 -34 -105 -146 -72 -138 -171 -248 -261 -292 -62 -30 -164 -44 -242 -34 -48 7 -50 8 -45 34 14 70 51 144 95 190 42 43 56 51 127 69 44 12 98 24 120 27 99 15 155 57 155 117 l0 31 -51 -5 c-40 -4 -58 -12 -87 -40 -56 -52 -66 -58 -131 -78 l-60 -18 10 27 c6 14 36 62 68 106 70 96 91 136 91 170 0 41 -18 29 -50 -35 -30 -59 -31 -60 -74 -60 -56 0 -71 -18 -101 -115 -23 -75 -43 -114 -72 -145 -8 -8 -41 -61 -73 -117 -35 -59 -75 -113 -95 -128 -37 -29 -177 -85 -210 -85 -35 0 -222 -134 -282 -202 -31 -35 -64 -64 -72 -66 -22 -4 -68 116 -88 223 -20 113 -5 256 37 340 37 76 124 182 195 238 140 110 221 137 416 137 136 0 171 6 186 28 9 15 2 17 -76 18 -47 0 -127 4 -178 9 -167 15 -274 -28 -423 -170 -72 -68 -114 -95 -128 -81 -12 12 17 138 44 194 64 132 229 243 439 298 182 46 319 21 425 -80 68 -65 144 -115 202 -135 119 -41 155 -32 72 17 -88 52 -224 144 -224 152 0 14 51 20 210 22 115 2 160 0 175 -10 19 -12 18 -13 -8 -9 -36 6 -45 -9 -11 -17 56 -15 117 -51 183 -110 66 -59 119 -86 169 -86 54 0 31 59 -35 90 -167 77 -176 82 -158 93 25 13 138 -8 201 -37 27 -13 67 -43 89 -66 50 -53 84 -70 134 -70 37 0 71 19 71 40 0 24 -62 57 -129 70 -40 7 -74 17 -77 22 -3 4 24 8 60 8 36 0 68 -4 71 -10 3 -5 26 -10 51 -10 50 0 57 15 23 46 -24 21 -113 25 -226 10 -50 -7 -65 -6 -77 7 -19 18 -100 37 -160 37 -74 0 -136 12 -136 26 0 17 11 23 53 28 32 4 83 29 97 47 8 10 71 40 99 47 28 7 159 8 309 1 50 -2 92 -1 92 4 0 4 14 7 30 7 23 0 30 -4 30 -20 0 -15 -7 -20 -25 -20 -42 0 -28 -17 30 -39 75 -28 103 -27 117 4 8 18 19 25 38 25 34 0 47 35 23 62 -24 27 -70 31 -190 18 -101 -11 -112 -10 -173 10 -36 12 -104 24 -152 27 -49 3 -88 9 -88 13 0 8 35 26 66 35 12 3 37 21 55 40 19 20 67 58 106 86 57 39 86 52 134 60 71 11 170 58 193 91 34 49 10 51 -66 5 -52 -31 -154 -65 -165 -54 -11 12 9 25 67 47 33 12 60 26 60 30 0 5 15 17 34 28 31 18 67 84 53 98 -15 15 -69 -17 -124 -75 -35 -36 -63 -63 -63 -58 0 4 14 31 30 60 43 77 39 180 -7 151 -39 -24 -56 -62 -63 -141 -7 -87 -27 -127 -98 -200 -50 -52 -120 -103 -139 -103 -8 0 -22 -8 -31 -17 -31 -31 -26 11 12 94 33 74 61 171 53 180 -3 2 -17 1 -32 -3 -38 -10 -65 -74 -75 -185 -9 -97 -31 -147 -79 -176 -31 -20 -81 -71 -81 -83 0 -5 -24 -16 -52 -26 -29 -9 -58 -24 -64 -32 -7 -9 -33 -17 -70 -19 l-59 -4 55 48 c120 105 133 126 66 103 -19 -6 -58 -36 -88 -66 -29 -30 -72 -64 -96 -76 -41 -19 -50 -20 -163 -9 -168 16 -237 52 -196 103 21 27 121 88 143 88 60 0 183 34 234 65 30 18 74 36 97 40 85 14 180 99 131 118 -16 5 -19 13 -14 33 7 25 5 25 -26 19 -52 -11 -83 -31 -122 -76 -54 -63 -94 -86 -197 -109 -52 -12 -102 -24 -111 -26 -28 -8 -22 22 10 44 15 11 35 34 45 51 16 27 16 31 2 31 -8 0 -18 -7 -22 -16 -8 -23 -23 2 -23 40 0 23 -3 27 -12 18 -14 -14 -42 -16 -33 -2 3 6 4 10 1 10 -9 0 -37 -61 -62 -133 -29 -84 -85 -162 -137 -189 -24 -12 -67 -21 -110 -24 -40 -2 -100 -6 -134 -9 l-62 -4 36 72 c20 39 48 84 62 98 29 29 86 122 96 157 9 32 -20 29 -42 -5 -17 -27 -128 -174 -222 -297 -45 -58 -101 -96 -141 -96 -48 0 -9 184 59 284 41 59 113 107 234 156 51 20 141 67 198 102 57 36 118 72 134 80 40 21 155 46 240 53 48 5 82 14 113 32 58 34 150 44 258 28 41 -6 57 -4 75 9 17 12 46 16 111 16 88 0 116 12 57 24 -17 3 -48 6 -69 6 -21 0 -43 6 -49 14 -14 17 -8 22 40 31 30 5 36 10 32 26 -4 13 0 19 12 19 23 0 95 44 129 79 34 35 30 67 -6 55 -13 -4 -31 -7 -41 -6 -11 0 -38 -25 -68 -64 -28 -35 -53 -64 -55 -64 -2 0 7 22 21 50 14 27 25 60 25 74 0 14 5 37 11 53 7 19 7 29 0 31 -6 2 -11 17 -11 33 0 16 -4 29 -10 29 -5 0 -10 -19 -10 -42 0 -50 -37 -158 -74 -222 -28 -48 -90 -86 -141 -86 l-29 0 36 38 c20 20 43 52 52 70 16 31 16 32 -5 32 -25 0 -94 -47 -109 -75 -19 -35 -161 -104 -245 -120 -42 -8 -85 -15 -96 -15 -18 0 -18 1 -2 35 9 19 20 35 25 35 4 0 8 6 8 13 0 7 13 34 30 60 30 48 75 77 182 117 58 21 112 66 176 146 26 31 57 57 84 69 124 52 167 75 177 93 17 33 -14 35 -71 6 -29 -14 -69 -32 -89 -39 l-38 -14 20 51 c11 28 24 59 29 68 10 19 -20 60 -45 60 -18 0 -21 46 -4 52 6 2 14 26 16 53 4 43 2 52 -16 63 -20 11 -21 10 -21 -25 -1 -209 -5 -248 -32 -305 -34 -73 -116 -188 -133 -188 -8 0 -20 -6 -27 -13 -7 -7 -29 -18 -48 -24 -19 -6 -52 -18 -72 -27 -34 -15 -38 -15 -38 -1 0 35 32 73 89 109 60 37 77 51 45 39 -14 -5 -14 -3 -3 14 7 13 9 28 4 39 -5 11 -7 24 -6 29 1 6 -19 -11 -44 -37 -25 -26 -45 -44 -45 -40 0 4 18 34 40 67 30 45 40 69 40 100 0 53 -11 67 -46 63 -22 -2 -34 -13 -53 -47 -14 -25 -26 -40 -29 -33 -2 7 -10 12 -17 12 -10 0 -14 -33 -17 -142 l-4 -143 -63 -127 c-39 -81 -74 -137 -94 -154 -51 -43 -167 -87 -167 -63 0 6 26 38 58 72 32 34 66 73 75 87 18 26 23 100 8 100 -5 0 -22 -19 -38 -42 -15 -23 -52 -60 -81 -82 -31 -25 -61 -59 -74 -85 -37 -75 -125 -156 -220 -201 -46 -22 -101 -43 -121 -47 -32 -5 -37 -3 -37 13 0 36 50 229 70 269 10 23 38 95 61 160 39 116 84 211 117 248 12 13 13 20 4 29 -9 9 -21 5 -49 -18 -58 -46 -166 -272 -249 -519 -37 -110 -73 -207 -80 -216 -8 -8 -14 -21 -14 -28 0 -8 -19 -54 -41 -105 -23 -50 -61 -146 -84 -212 -49 -144 -77 -193 -152 -274 -71 -77 -89 -77 -115 2 -11 33 -27 59 -36 62 -19 6 -21 27 -23 201 -2 197 49 394 151 580 33 61 72 135 86 165 118 253 140 288 273 462 87 112 121 167 121 195 0 37 -25 27 -75 -29 -42 -48 -45 -50 -38 -23 13 50 9 145 -8 156 -19 12 -30 7 -50 -22 -23 -33 -15 -116 12 -124 28 -9 35 -49 12 -73 -10 -11 -36 -45 -58 -76 -22 -31 -44 -56 -48 -56 -12 0 -3 78 17 160 8 36 15 84 16 107 0 23 4 44 9 47 4 3 11 37 14 75 3 39 14 86 26 109 26 50 80 97 94 83 16 -16 59 -13 85 5 30 21 52 66 52 109 0 33 -2 35 -32 35 -59 0 -78 -12 -118 -69 -21 -31 -55 -74 -74 -96 l-35 -40 -1 41 c0 23 7 60 15 83 15 43 92 151 124 173 20 14 55 77 48 85 -3 2 -8 -5 -12 -16 -7 -24 -35 -17 -35 9 0 23 -13 32 -35 24 -9 -4 -12 -9 -7 -13 17 -10 2 -62 -16 -59 -11 2 -30 -24 -61 -87 -34 -68 -46 -84 -49 -67 -2 12 -8 22 -13 22 -5 0 -9 -10 -9 -22 -1 -23 -1 -23 -16 -3 -9 11 -24 37 -34 58 -11 24 -20 34 -23 25 -3 -7 -6 25 -6 72 -1 105 -21 98 -26 -10 -3 -43 -9 -76 -16 -81 -10 -6 -10 -11 0 -23 14 -16 3 -22 -15 -8 -5 4 2 -2 15 -13 51 -41 78 -76 96 -128 26 -70 25 -187 -3 -292 -13 -49 -21 -109 -20 -155 0 -104 -54 -310 -81 -310 -6 0 -11 3 -11 8 -1 44 -24 191 -41 259 l-22 85 27 108 c30 123 34 211 10 231 -20 16 -40 5 -72 -42 -21 -30 -23 -42 -18 -97 3 -36 1 -60 -4 -57 -17 11 -34 81 -34 150 -1 64 2 76 39 140 22 39 45 84 52 100 17 43 16 92 -2 98 -17 7 -17 8 -44 -73 -12 -36 -34 -87 -50 -113 -33 -56 -41 -48 -41 39 0 41 -4 54 -15 54 -11 0 -15 -18 -17 -80 -2 -45 -7 -80 -13 -80 -5 0 -10 4 -10 8 0 5 -8 16 -18 26 -58 58 -70 132 -53 314 7 69 6 92 -3 92 -6 0 -13 -6 -16 -12z m321 -503 c3 -20 4 -39 0 -42 -3 -4 -6 6 -6 20 0 17 -5 27 -15 27 -16 0 -20 12 -8 23 14 14 22 6 29 -28z m-1006 -80 c0 -8 -9 -15 -19 -15 -29 0 -35 18 -9 23 13 2 24 5 26 6 1 0 2 -6 2 -14z m327 -27 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-462 -358 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-835 -40 c-6 -11 -15 -20 -19 -20 -5 0 -7 9 -4 20 3 11 12 20 20 20 11 0 11 -4 3 -20z m864 -25 c3 -9 0 -15 -9 -15 -9 0 -15 -10 -16 -27 0 -27 -1 -27 -13 7 -10 25 -10 37 -2 42 18 12 33 9 40 -7z m-892 -863 c38 2 68 0 68 -4 0 -5 -33 -8 -73 -8 -49 0 -80 -5 -95 -16 -21 -14 -22 -14 -22 5 0 14 -6 21 -20 21 -11 0 -20 2 -20 4 0 2 -3 12 -6 21 -6 13 1 13 47 -5 40 -16 70 -21 121 -18z m3218 -91 c0 -10 -7 -21 -15 -25 -11 -4 -15 1 -15 19 0 16 6 25 15 25 8 0 15 -9 15 -19z m-3479 -32 c-14 -5 -30 -14 -37 -20 -8 -7 -13 -3 -17 11 -5 18 0 20 36 19 38 0 40 -1 18 -10z m3359 -572 c0 -7 -7 -22 -15 -33 -13 -17 -14 -16 -4 14 11 33 19 41 19 19z m-3345 -198 c7 -22 -7 -39 -33 -39 -10 0 -10 4 0 20 11 17 10 22 -2 30 -12 8 -11 10 7 10 13 0 24 -8 28 -21z m445 -37 c0 -23 -35 -8 -38 16 -3 21 -2 22 17 10 12 -7 21 -19 21 -26z m-310 -647 c-28 -30 -60 -33 -60 -7 0 26 9 32 48 32 l35 0 -23 -25z M3684 5414 c-14 -21 -16 -41 -10 -124 4 -62 2 -100 -3 -100 -9 0 -17 26 -25 84 -1 11 -8 22 -14 24 -9 3 -12 -27 -12 -105 0 -69 -6 -130 -16 -164 -24 -86 -24 -85 -33 -70 -6 9 -10 3 -14 -17 -4 -20 -23 -43 -59 -72 -29 -23 -54 -46 -54 -51 -1 -5 -3 -39 -4 -76 -1 -46 -4 -60 -9 -43 -6 21 -9 15 -20 -35 -16 -74 -29 -99 -97 -197 -35 -49 -54 -86 -54 -105 0 -31 59 -200 60 -171 0 9 6 21 14 25 13 7 13 16 0 68 -17 72 -12 78 75 93 106 19 127 33 145 95 20 70 65 111 186 172 83 42 89 47 75 62 -9 8 -14 23 -11 32 5 14 5 14 -6 1 -7 -8 -41 -25 -75 -37 -54 -19 -61 -19 -56 -5 10 26 43 72 91 126 46 53 77 104 68 114 -6 6 -95 -81 -143 -141 l-30 -38 -7 80 c-4 45 -5 89 -1 98 3 10 31 34 63 53 61 37 147 112 164 144 21 38 -53 8 -126 -52 -98 -80 -100 -81 -92 -46 12 47 54 133 81 166 14 16 25 42 25 56 l-1 27 -25 -30 -26 -30 6 53 c3 28 9 74 12 100 5 40 3 50 -10 55 -10 4 -22 -2 -32 -19z m-79 -654 c0 -125 0 -126 -33 -176 -22 -36 -56 -67 -109 -103 -42 -28 -82 -51 -90 -51 -20 0 -16 22 11 59 13 18 30 46 36 62 7 16 16 29 20 29 5 0 13 33 20 73 16 102 29 149 40 142 6 -4 10 -2 10 3 0 5 13 25 30 43 16 19 30 38 30 42 0 5 8 7 18 5 15 -3 17 -17 17 -128z M2287 5348 c-10 -10 -22 -16 -27 -13 -5 3 -8 -3 -8 -12 1 -10 -2 -37 -6 -59 -6 -32 -4 -43 7 -47 23 -9 67 61 67 105 0 44 -9 51 -33 26z M1853 5256 c4 -22 11 -42 17 -46 7 -4 14 -26 17 -49 3 -22 10 -41 15 -41 5 0 7 12 4 28 -3 15 -8 46 -11 69 -4 23 -16 49 -27 60 -21 18 -21 18 -15 -21z M1780 5267 c0 -47 15 -79 42 -93 l30 -16 -7 34 c-4 18 -12 44 -19 58 -12 28 -46 40 -46 17z M1960 5120 c0 -21 30 -70 49 -80 27 -14 31 -13 31 10 0 11 5 20 10 20 6 0 8 -11 4 -25 -6 -23 -4 -25 30 -25 20 0 36 4 36 8 0 18 -68 72 -109 87 -52 18 -51 18 -51 5z M4127 5076 c-4 -10 -7 -45 -7 -79 0 -42 -6 -70 -18 -88 -56 -85 -73 -107 -106 -138 -20 -19 -36 -39 -36 -43 0 -18 34 -6 62 23 29 28 34 30 84 24 41 -6 59 -3 83 11 37 22 44 37 28 59 -16 21 -72 22 -95 2 -21 -19 -32 -22 -32 -7 0 5 38 35 84 66 77 51 106 84 106 119 0 26 -43 16 -77 -17 l-33 -32 0 47 c0 34 -4 47 -14 47 -8 0 -16 5 -18 12 -3 7 -7 5 -11 -6z M1049 5043 c-8 -10 -9 -14 -2 -10 7 5 28 -18 57 -63 48 -74 62 -86 52 -45 -4 15 -2 25 4 25 15 0 -17 72 -41 93 -27 22 -53 22 -70 0z M3400 4964 c-14 -37 -12 -60 6 -75 14 -11 18 -10 30 6 19 26 18 81 -2 89 -23 9 -24 8 -34 -20z M3910 4933 c-29 -20 -40 -33 -40 -50 0 -33 63 6 75 45 8 26 -2 28 -35 5z M3401 4844 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z M4532 4829 c-8 -12 -9 -18 -3 -14 7 4 11 -8 12 -32 1 -21 4 -51 8 -68 6 -26 8 -22 13 29 5 39 3 67 -5 83 l-12 23 -13 -21z M1017 4820 c-8 -30 16 -52 65 -60 41 -6 45 -5 40 12 -5 20 -68 68 -88 68 -6 0 -14 -9 -17 -20z M2529 4778 c-11 -21 -7 -134 7 -185 8 -30 24 -19 24 17 0 16 7 35 15 44 18 17 20 70 4 115 -13 36 -33 40 -50 9z M830 4767 c0 -24 30 -116 40 -122 11 -7 1 92 -12 118 -10 20 -28 23 -28 4z M4660 4751 c0 -5 -9 -12 -19 -16 -23 -7 -101 -81 -101 -95 0 -26 50 -6 98 38 51 47 67 82 37 82 -8 0 -15 -4 -15 -9z M764 4719 c-7 -13 82 -106 92 -96 11 11 -9 43 -46 75 -27 23 -41 29 -46 21z M1887 4634 c-18 -18 -6 -91 21 -131 79 -118 125 -171 138 -159 10 9 8 18 -9 46 -12 19 -25 37 -29 38 -4 2 -8 25 -8 50 0 60 -15 115 -38 135 -20 19 -65 31 -75 21z M1030 4579 c0 -35 54 -169 68 -169 6 0 12 -8 12 -17 1 -17 2 -17 15 0 11 16 11 26 -5 71 -25 75 -47 114 -70 126 -17 9 -20 8 -20 -11z M697 4553 c19 -54 69 -92 112 -85 36 5 46 34 20 58 -11 9 -22 14 -25 11 -4 -4 -18 3 -32 13 -32 26 -84 28 -75 3z M1150 4486 c0 -36 52 -76 101 -76 47 0 57 29 12 32 -16 1 6 4 47 8 l75 6 -75 2 c-41 1 -85 8 -96 15 -12 6 -31 18 -43 25 -19 12 -21 11 -21 -12z M3909 4427 c-16 -27 -19 -51 -19 -149 0 -111 1 -118 20 -118 15 0 24 14 40 68 39 124 39 215 -1 225 -15 4 -25 -2 -40 -26z M4723 4375 c-30 -13 -33 -18 -33 -60 l0 -45 24 15 c27 18 49 48 60 83 9 26 -4 28 -51 7z M5002 4348 c-5 -7 -23 -40 -40 -73 -32 -65 -106 -146 -156 -172 -17 -9 -51 -21 -75 -28 -46 -11 -63 -28 -38 -38 7 -3 47 2 87 10 58 12 85 13 128 4 96 -19 162 -13 162 15 0 11 -19 14 -82 15 -46 0 -91 4 -101 8 -17 6 -17 8 2 25 11 10 44 25 73 32 34 8 43 13 27 13 -31 1 -44 24 -23 41 8 7 14 21 14 31 0 11 10 36 23 57 33 52 39 72 23 72 -7 0 -18 -6 -24 -12z M3632 4290 c-52 -37 -68 -69 -74 -145 -3 -33 -3 -54 0 -47 3 10 7 9 16 -4 12 -15 18 -14 79 15 69 33 101 66 95 98 -4 22 -37 30 -49 11 -6 -8 -7 10 -3 45 8 68 -2 72 -64 27z M5016 4271 c-11 -12 -16 -24 -12 -28 9 -9 39 22 34 37 -2 7 -10 4 -22 -9z M470 4264 c0 -9 8 -28 18 -42 10 -15 22 -33 27 -40 8 -15 -67 31 -102 62 -13 11 -23 14 -23 8 0 -7 -7 -12 -15 -12 -19 0 -19 -15 2 -50 20 -35 48 -48 118 -56 37 -5 55 -11 55 -20 0 -8 11 -14 25 -14 14 0 25 4 25 10 0 5 -22 43 -50 84 -49 73 -80 100 -80 70z M2382 4102 c-5 -9 -12 -42 -14 -72 -9 -96 18 -125 39 -43 17 66 17 120 -2 127 -8 3 -19 -2 -23 -12z M4235 3850 c36 -39 118 -80 162 -80 30 0 93 41 93 61 0 5 -14 15 -30 24 -25 13 -44 14 -107 6 -43 -5 -80 -6 -83 -1 -3 5 -19 12 -35 16 l-30 7 30 -33z M133 3667 c-19 -41 -15 -59 18 -86 30 -24 135 -55 151 -45 11 7 10 42 -2 49 -5 3 -10 11 -10 17 0 6 7 5 17 -3 12 -10 15 -10 9 -1 -13 22 -84 52 -125 52 -33 0 -40 4 -43 22 -3 21 -4 21 -15 -5z M5265 3631 c-16 -10 -43 -33 -60 -51 l-30 -32 83 4 c77 3 86 6 107 30 35 41 24 68 -29 68 -23 0 -54 -8 -71 -19z M400 3512 c0 -5 -53 -12 -117 -16 -64 -4 -120 -9 -125 -12 -16 -10 -8 -53 13 -65 51 -27 183 0 213 43 13 17 19 18 68 9 29 -5 66 -13 81 -16 22 -6 26 -4 21 9 -5 12 0 16 17 17 13 1 -3 7 -36 14 -106 22 -135 26 -135 17z M5090 3480 c0 -5 9 -10 20 -10 11 0 47 -13 80 -30 57 -29 121 -39 147 -22 22 14 19 45 -7 59 -30 15 -240 18 -240 3z M926 3272 c-12 -11 -6 -94 9 -122 16 -31 39 -47 86 -60 24 -7 29 -5 39 21 19 44 5 94 -34 124 -35 27 -90 47 -100 37z M500 3049 c0 -23 9 -62 20 -85 17 -33 30 -46 70 -62 34 -14 56 -32 70 -54 16 -28 109 -108 125 -108 3 0 5 7 5 15 0 12 7 14 28 9 15 -3 -8 11 -50 32 -42 20 -80 44 -83 53 -4 9 -9 46 -12 84 -5 61 -9 70 -41 98 -34 30 -59 43 -107 55 -24 6 -25 4 -25 -37z M5203 2779 c-18 -11 -35 -29 -38 -40 -7 -22 -20 -25 -32 -6 -8 13 -20 -26 -22 -74 -1 -30 25 -36 35 -7 4 15 9 17 20 7 8 -6 14 -18 14 -26 0 -11 7 -9 27 7 43 33 63 71 63 118 0 49 -14 53 -67 21z M5307 2622 c-34 -32 -86 -72 -115 -88 -51 -29 -61 -46 -29 -52 25 -5 198 81 229 114 15 16 30 41 33 57 7 25 5 27 -24 27 -25 0 -45 -13 -94 -58z M447 2652 c-10 -10 -15 -21 -12 -24 7 -7 75 24 75 34 0 15 -47 8 -63 -10z M263 2600 c-12 -5 -26 -18 -32 -28 -8 -15 -6 -24 13 -41 33 -31 84 -27 160 13 68 36 68 47 1 51 -16 1 -50 5 -75 8 -25 4 -55 3 -67 -3z M996 2540 c-37 -11 -102 -74 -115 -112 l-10 -28 58 0 c48 0 65 5 98 29 49 35 87 86 79 106 -6 17 -62 19 -110 5z M673 2324 c-43 -18 -42 -43 1 -88 33 -35 35 -36 114 -36 70 0 80 2 78 18 0 10 6 16 16 16 13 -1 9 8 -18 40 -19 22 -45 46 -57 53 -29 16 -94 15 -134 -3z M4790 2120 c-9 -17 -5 -20 43 -29 72 -15 166 -19 169 -9 2 5 11 6 21 3 20 -8 23 -35 5 -35 -7 -1 -2 -7 12 -15 29 -17 113 -20 141 -5 24 13 25 36 2 48 -10 5 -58 12 -108 15 -49 3 -117 12 -150 20 -110 28 -124 28 -135 7z M4881 2021 c6 -17 30 -50 53 -75 33 -36 49 -46 74 -46 25 0 32 4 32 19 0 25 -60 77 -99 86 -17 4 -36 15 -41 26 -17 30 -30 23 -19 -10z";
|
|
1620
|
+
|
|
1621
|
+
// src/genre-tree/TreeMarkIcon.tsx
|
|
1622
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1623
|
+
function TreeMarkIcon({ className: className2 }) {
|
|
1624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("svg", { viewBox: "0 0 551 567", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("path", { transform: "translate(0 567) scale(0.1 -0.1)", d: TREE_MARK_PATH }) });
|
|
1625
|
+
}
|
|
1626
|
+
|
|
1627
|
+
// src/genre-tree/GenrePlayActions.tsx
|
|
1628
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1629
|
+
function PlayIcon({ kind }) {
|
|
1630
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("span", { "aria-hidden": "true", className: "relative flex items-center justify-center w-5 h-5", children: [
|
|
1631
|
+
kind === "tree" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1632
|
+
kind === "map" && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1633
|
+
kind === "tree-map" && /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
1634
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_50%_0_0)]" }),
|
|
1635
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_0_0_50%)]" })
|
|
1594
1636
|
] }),
|
|
1595
|
-
|
|
1596
|
-
"section",
|
|
1597
|
-
{
|
|
1598
|
-
"aria-label": "Admin actions",
|
|
1599
|
-
className: `px-3.5 py-3 ${items.length > 0 ? "border-t border-[var(--color-border)]" : ""}`,
|
|
1600
|
-
children: [
|
|
1601
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "mb-2 text-xs font-semibold uppercase tracking-wide text-[var(--color-text-muted)]", children: "Admin" }),
|
|
1602
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-wrap gap-1", children: renderItems(adminItems) })
|
|
1603
|
-
]
|
|
1604
|
-
}
|
|
1605
|
-
)
|
|
1637
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react12.Play, { className: "relative w-5 h-5 fill-[var(--color-surface)]" })
|
|
1606
1638
|
] });
|
|
1607
1639
|
}
|
|
1640
|
+
function playOptions(playlist) {
|
|
1641
|
+
if (!("genreOnlyTracksCount" in playlist)) return [{ key: "all", label: "Play", icon: "play", count: playlist.tracksCount }];
|
|
1642
|
+
const direct = { key: "direct", label: "Genre", icon: "play", selection: { coverage: "genreOnly" }, count: (0, import_genre_tree10.genreMusicCount)(playlist, { coverage: "genreOnly" }) };
|
|
1643
|
+
const scopes = playlist.genreAndSubgenresTracksCount;
|
|
1644
|
+
const inclusive = (label, icon, subgenres) => {
|
|
1645
|
+
const selection = { coverage: "genreAndSubgenres", subgenres };
|
|
1646
|
+
return { key: subgenres, label, icon, selection, count: (0, import_genre_tree10.genreMusicCount)(playlist, selection) };
|
|
1647
|
+
};
|
|
1648
|
+
return "canonical" in scopes ? [direct, inclusive("Canonical", "tree", "canonical"), inclusive("Regional", "map", "regional"), inclusive("All", "tree-map", "all")] : [direct, inclusive("All", "map", "all")];
|
|
1649
|
+
}
|
|
1650
|
+
function GenrePlayActions({ genrePlaylist, playback }) {
|
|
1651
|
+
const { isPlaying, setIsPlaying } = (0, import_player4.usePlayer)();
|
|
1652
|
+
const options = playOptions(genrePlaylist);
|
|
1653
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_jsx_runtime29.Fragment, { children: options.map((option) => {
|
|
1654
|
+
const isCurrent = playback.playing?.uuid === genrePlaylist.uuid && (option.selection === void 0 || playback.playing.selectionKey === "" || playback.playing.selectionKey === (0, import_genre_tree10.genreMusicSelectionKey)(option.selection).join());
|
|
1655
|
+
const playing = isCurrent && isPlaying;
|
|
1656
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
1657
|
+
import_ui10.ActionButton,
|
|
1658
|
+
{
|
|
1659
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_lucide_react12.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(PlayIcon, { kind: option.icon }),
|
|
1660
|
+
label: playing ? "Pause" : option.label,
|
|
1661
|
+
caption: String(option.count),
|
|
1662
|
+
disabled: option.count === 0,
|
|
1663
|
+
title: option.count === 0 ? "No playable songs" : void 0,
|
|
1664
|
+
onClick: () => {
|
|
1665
|
+
if (isCurrent) {
|
|
1666
|
+
setIsPlaying(!isPlaying);
|
|
1667
|
+
return;
|
|
1668
|
+
}
|
|
1669
|
+
playback.play(genrePlaylist, option.selection).catch((error) => {
|
|
1670
|
+
console.error("Failed to load genre playlist tracks:", error);
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
},
|
|
1674
|
+
option.key
|
|
1675
|
+
);
|
|
1676
|
+
}) });
|
|
1677
|
+
}
|
|
1608
1678
|
|
|
1609
1679
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1610
|
-
var
|
|
1611
|
-
var
|
|
1680
|
+
var import_ui12 = require("@behindthemusictree/ui");
|
|
1681
|
+
var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1612
1682
|
|
|
1613
1683
|
// src/genre-tree/ClampedText.tsx
|
|
1614
|
-
var
|
|
1615
|
-
var
|
|
1684
|
+
var import_react12 = require("react");
|
|
1685
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1616
1686
|
function ClampedText({ children, className: className2 = "" }) {
|
|
1617
|
-
const ref = (0,
|
|
1618
|
-
const [expanded, setExpanded] = (0,
|
|
1619
|
-
const [overflows, setOverflows] = (0,
|
|
1620
|
-
(0,
|
|
1687
|
+
const ref = (0, import_react12.useRef)(null);
|
|
1688
|
+
const [expanded, setExpanded] = (0, import_react12.useState)(false);
|
|
1689
|
+
const [overflows, setOverflows] = (0, import_react12.useState)(false);
|
|
1690
|
+
(0, import_react12.useLayoutEffect)(() => {
|
|
1621
1691
|
const element = ref.current;
|
|
1622
1692
|
if (!element || expanded) return;
|
|
1623
1693
|
setOverflows(element.scrollHeight > element.clientHeight);
|
|
1624
1694
|
}, [children, expanded]);
|
|
1625
|
-
return /* @__PURE__ */ (0,
|
|
1626
|
-
/* @__PURE__ */ (0,
|
|
1627
|
-
(overflows || expanded) && /* @__PURE__ */ (0,
|
|
1695
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1696
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { ref, className: `${className2} ${expanded ? "" : "line-clamp-3"}`, children }),
|
|
1697
|
+
(overflows || expanded) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1628
1698
|
"button",
|
|
1629
1699
|
{
|
|
1630
1700
|
type: "button",
|
|
1631
1701
|
"aria-expanded": expanded,
|
|
1632
1702
|
onClick: () => setExpanded((value) => !value),
|
|
1633
|
-
className: "mt-1 text-
|
|
1703
|
+
className: "mt-1 text-caption text-[var(--color-text-muted)] underline hover:text-[var(--color-text)]",
|
|
1634
1704
|
children: expanded ? "Show less" : "Show more"
|
|
1635
1705
|
}
|
|
1636
1706
|
)
|
|
@@ -1638,36 +1708,36 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1638
1708
|
}
|
|
1639
1709
|
|
|
1640
1710
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1641
|
-
var
|
|
1711
|
+
var import_react13 = require("react");
|
|
1642
1712
|
var import_react_query = require("@tanstack/react-query");
|
|
1643
1713
|
var import_zod = require("zod");
|
|
1644
1714
|
var import_fa4 = require("react-icons/fa");
|
|
1645
|
-
var
|
|
1715
|
+
var import_ui11 = require("@behindthemusictree/ui");
|
|
1646
1716
|
var import_auth2 = require("@behindthemusictree/app-kit/auth");
|
|
1647
1717
|
var import_transport5 = require("@behindthemusictree/app-kit/transport");
|
|
1648
1718
|
var import_transport6 = require("@behindthemusictree/app-kit/transport");
|
|
1649
1719
|
var import_transport7 = require("@behindthemusictree/app-kit/transport");
|
|
1650
|
-
var import_player4 = require("@behindthemusictree/app-kit/player");
|
|
1651
1720
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1721
|
+
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1652
1722
|
var import_popup5 = require("@behindthemusictree/app-kit/popup");
|
|
1653
1723
|
var import_transport8 = require("@behindthemusictree/app-kit/transport");
|
|
1654
|
-
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1655
1724
|
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1656
1725
|
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1657
1726
|
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1658
1727
|
var import_genre_tree15 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1728
|
+
var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1659
1729
|
|
|
1660
1730
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1661
|
-
var
|
|
1662
|
-
var
|
|
1731
|
+
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1732
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1663
1733
|
function MusicBrainzRecordingLink({
|
|
1664
1734
|
song,
|
|
1665
1735
|
children,
|
|
1666
1736
|
className: className2 = ""
|
|
1667
1737
|
}) {
|
|
1668
|
-
const url = (0,
|
|
1669
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1670
|
-
return /* @__PURE__ */ (0,
|
|
1738
|
+
const url = (0, import_genre_tree11.musicBrainzRecordingUrl)(song);
|
|
1739
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(import_jsx_runtime31.Fragment, { children });
|
|
1740
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1671
1741
|
"a",
|
|
1672
1742
|
{
|
|
1673
1743
|
href: url,
|
|
@@ -1682,11 +1752,11 @@ function MusicBrainzRecordingLink({
|
|
|
1682
1752
|
}
|
|
1683
1753
|
|
|
1684
1754
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1685
|
-
var
|
|
1755
|
+
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1686
1756
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1687
|
-
var
|
|
1757
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1688
1758
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1689
|
-
var SongPageSchema = (0, import_transport6.PaginatedResponseSchema)(
|
|
1759
|
+
var SongPageSchema = (0, import_transport6.PaginatedResponseSchema)(import_genre_tree15.SongDetailedSchema).extend({
|
|
1690
1760
|
overallTotal: import_zod.z.number().nullable(),
|
|
1691
1761
|
page: import_zod.z.number().nullable(),
|
|
1692
1762
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1715,9 +1785,9 @@ function GenrePlaylistTracks({
|
|
|
1715
1785
|
renderTracksToolbar,
|
|
1716
1786
|
artist = null
|
|
1717
1787
|
}) {
|
|
1718
|
-
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0,
|
|
1788
|
+
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree16.useTrackList)();
|
|
1719
1789
|
const { session, sessionRestored } = (0, import_auth2.useSession)();
|
|
1720
|
-
const { playerTrackObject, playState, handlePlayPauseAction } = (0,
|
|
1790
|
+
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player5.usePlayer)();
|
|
1721
1791
|
const { showPopup } = (0, import_popup5.usePopup)();
|
|
1722
1792
|
const trackNoun = (0, import_track_noun2.useTrackNoun)();
|
|
1723
1793
|
const uuid = genrePlaylist?.uuid;
|
|
@@ -1725,18 +1795,18 @@ function GenrePlaylistTracks({
|
|
|
1725
1795
|
const { fetchBound } = (0, import_transport5.usePlaybackFetch)(getBackendBaseUrl);
|
|
1726
1796
|
const playback = (0, import_transport5.usePlaybackContext)();
|
|
1727
1797
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1728
|
-
queryKey: [...scope === "me" ? uuid ?
|
|
1798
|
+
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] : []],
|
|
1729
1799
|
queryFn: async ({ pageParam }) => {
|
|
1730
1800
|
if (scope === "me") {
|
|
1731
1801
|
if (!uuid) throw new Error("Personal genre has no playlist");
|
|
1732
1802
|
return fetchGenrePlaylistTracksPage(uuid, scope, Number(pageParam));
|
|
1733
1803
|
}
|
|
1734
1804
|
const response = await fetchBound(
|
|
1735
|
-
|
|
1805
|
+
import_genre_tree14.libraryEndpoints.reference.songs.list(),
|
|
1736
1806
|
true,
|
|
1737
1807
|
false,
|
|
1738
1808
|
{},
|
|
1739
|
-
{ genre: genreUuid, ...(0,
|
|
1809
|
+
{ genre: genreUuid, ...(0, import_genre_tree12.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1740
1810
|
);
|
|
1741
1811
|
const parsed = (0, import_transport7.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1742
1812
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
@@ -1747,8 +1817,8 @@ function GenrePlaylistTracks({
|
|
|
1747
1817
|
retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
|
|
1748
1818
|
retryDelay: 0
|
|
1749
1819
|
});
|
|
1750
|
-
const [sentinel, setSentinel] = (0,
|
|
1751
|
-
(0,
|
|
1820
|
+
const [sentinel, setSentinel] = (0, import_react13.useState)(null);
|
|
1821
|
+
(0, import_react13.useEffect)(() => {
|
|
1752
1822
|
if (!hasNextPage || isFetchingNextPage || !sentinel) return;
|
|
1753
1823
|
const observer = new IntersectionObserver((entries) => {
|
|
1754
1824
|
if (entries.some((entry) => entry.isIntersecting)) {
|
|
@@ -1770,35 +1840,35 @@ function GenrePlaylistTracks({
|
|
|
1770
1840
|
}) : 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"));
|
|
1771
1841
|
started.catch((error) => {
|
|
1772
1842
|
console.error("Failed to play genre playlist:", error);
|
|
1773
|
-
showPopup(/* @__PURE__ */ (0,
|
|
1843
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(InternalErrorPopup, { errorCode: import_transport8.ErrorCode.CLIENT_UNKNOWN }));
|
|
1774
1844
|
});
|
|
1775
1845
|
};
|
|
1776
|
-
return /* @__PURE__ */ (0,
|
|
1846
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_ui11.PanelSection, { title: `${(0, import_track_noun2.capitalize)(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("div", { children: [
|
|
1777
1847
|
renderTracksToolbar?.(),
|
|
1778
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0,
|
|
1848
|
+
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { children: "\u2014" }) : isPending ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_ui11.Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("p", { role: "alert", children: [
|
|
1779
1849
|
"Couldn't load ",
|
|
1780
1850
|
trackNoun.plural,
|
|
1781
1851
|
".",
|
|
1782
1852
|
" ",
|
|
1783
|
-
/* @__PURE__ */ (0,
|
|
1784
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0,
|
|
1853
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1854
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1785
1855
|
tracks.map((track, index) => {
|
|
1786
1856
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1787
1857
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1788
|
-
const isPlaying = isCurrent && playState ===
|
|
1789
|
-
const text = /* @__PURE__ */ (0,
|
|
1790
|
-
/* @__PURE__ */ (0,
|
|
1791
|
-
track.artists?.length ? /* @__PURE__ */ (0,
|
|
1792
|
-
/* @__PURE__ */ (0,
|
|
1793
|
-
track.album && /* @__PURE__ */ (0,
|
|
1858
|
+
const isPlaying = isCurrent && playState === import_player6.PlayStates.PLAYING;
|
|
1859
|
+
const text = /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1860
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree15.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1861
|
+
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1862
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_genre_tree17.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1863
|
+
track.album && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1794
1864
|
] });
|
|
1795
1865
|
const leading = renderSongLeading?.(track, index);
|
|
1796
1866
|
const actions = renderSongActions?.(track);
|
|
1797
|
-
const isUnplayable = (0,
|
|
1867
|
+
const isUnplayable = (0, import_genre_tree15.isSong)(track) && (0, import_genre_tree15.songUnplayableReason)(track) !== null;
|
|
1798
1868
|
if (isUnplayable) {
|
|
1799
|
-
return /* @__PURE__ */ (0,
|
|
1869
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1800
1870
|
leading,
|
|
1801
|
-
/* @__PURE__ */ (0,
|
|
1871
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1802
1872
|
"button",
|
|
1803
1873
|
{
|
|
1804
1874
|
type: "button",
|
|
@@ -1806,27 +1876,27 @@ function GenrePlaylistTracks({
|
|
|
1806
1876
|
"aria-disabled": "true",
|
|
1807
1877
|
"aria-label": label,
|
|
1808
1878
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1809
|
-
children: /* @__PURE__ */ (0,
|
|
1879
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1810
1880
|
}
|
|
1811
1881
|
),
|
|
1812
1882
|
text,
|
|
1813
1883
|
actions
|
|
1814
1884
|
] }, track.uuid);
|
|
1815
1885
|
}
|
|
1816
|
-
return /* @__PURE__ */ (0,
|
|
1886
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(
|
|
1817
1887
|
"li",
|
|
1818
1888
|
{
|
|
1819
1889
|
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)]" : ""}`,
|
|
1820
1890
|
children: [
|
|
1821
1891
|
leading,
|
|
1822
|
-
/* @__PURE__ */ (0,
|
|
1892
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1823
1893
|
"button",
|
|
1824
1894
|
{
|
|
1825
1895
|
type: "button",
|
|
1826
1896
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1827
|
-
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 !==
|
|
1897
|
+
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"}`,
|
|
1828
1898
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1829
|
-
children: isCurrent && playState ===
|
|
1899
|
+
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_ui11.RingLoader, { size: 10 }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_fa4.FaPause, { size: 10 }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_fa4.FaPlay, { size: 10 })
|
|
1830
1900
|
}
|
|
1831
1901
|
),
|
|
1832
1902
|
text,
|
|
@@ -1836,7 +1906,7 @@ function GenrePlaylistTracks({
|
|
|
1836
1906
|
track.uuid
|
|
1837
1907
|
);
|
|
1838
1908
|
}),
|
|
1839
|
-
hasNextPage && /* @__PURE__ */ (0,
|
|
1909
|
+
hasNextPage && /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1840
1910
|
] })
|
|
1841
1911
|
] }) });
|
|
1842
1912
|
}
|
|
@@ -1844,7 +1914,7 @@ function GenrePlaylistTracks({
|
|
|
1844
1914
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1845
1915
|
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
1846
1916
|
var import_si2 = require("react-icons/si");
|
|
1847
|
-
var
|
|
1917
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
1848
1918
|
function GenreDetailExtras({
|
|
1849
1919
|
genreUuid,
|
|
1850
1920
|
genrePlaylist,
|
|
@@ -1863,24 +1933,24 @@ function GenreDetailExtras({
|
|
|
1863
1933
|
...trackSlots
|
|
1864
1934
|
}) {
|
|
1865
1935
|
const trackNoun = (0, import_track_noun3.useTrackNoun)();
|
|
1866
|
-
const { data: overview, isPending } = (0,
|
|
1936
|
+
const { data: overview, isPending } = (0, import_genre_tree18.useFetchGenreOverview)(
|
|
1867
1937
|
genreUuid,
|
|
1868
1938
|
scope,
|
|
1869
1939
|
getBackendBaseUrl,
|
|
1870
1940
|
criteriaOverviewSchema
|
|
1871
1941
|
);
|
|
1872
1942
|
if (isPending) {
|
|
1873
|
-
return /* @__PURE__ */ (0,
|
|
1874
|
-
/* @__PURE__ */ (0,
|
|
1943
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
1944
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui12.PanelSection, { title: "Summary", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui12.Skeleton, { className: "h-4 w-3/4" }) }) }),
|
|
1875
1945
|
family
|
|
1876
1946
|
] });
|
|
1877
1947
|
}
|
|
1878
|
-
if (!overview) return /* @__PURE__ */ (0,
|
|
1948
|
+
if (!overview) return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_jsx_runtime33.Fragment, { children: family });
|
|
1879
1949
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1880
1950
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1881
|
-
return /* @__PURE__ */ (0,
|
|
1882
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0,
|
|
1883
|
-
summarySourceUrl && /* @__PURE__ */ (0,
|
|
1951
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(import_jsx_runtime33.Fragment, { children: [
|
|
1952
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui12.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1953
|
+
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
1884
1954
|
"a",
|
|
1885
1955
|
{
|
|
1886
1956
|
href: summarySourceUrl,
|
|
@@ -1888,12 +1958,12 @@ function GenreDetailExtras({
|
|
|
1888
1958
|
rel: "noopener noreferrer",
|
|
1889
1959
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1890
1960
|
children: [
|
|
1891
|
-
/* @__PURE__ */ (0,
|
|
1961
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_si2.SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1892
1962
|
"Wikipedia"
|
|
1893
1963
|
]
|
|
1894
1964
|
}
|
|
1895
1965
|
),
|
|
1896
|
-
wikidataUrl && /* @__PURE__ */ (0,
|
|
1966
|
+
wikidataUrl && /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(
|
|
1897
1967
|
"a",
|
|
1898
1968
|
{
|
|
1899
1969
|
href: wikidataUrl,
|
|
@@ -1901,17 +1971,17 @@ function GenreDetailExtras({
|
|
|
1901
1971
|
rel: "noopener noreferrer",
|
|
1902
1972
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1903
1973
|
children: [
|
|
1904
|
-
/* @__PURE__ */ (0,
|
|
1974
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_si2.SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1905
1975
|
"Wikidata"
|
|
1906
1976
|
]
|
|
1907
1977
|
}
|
|
1908
1978
|
)
|
|
1909
1979
|
] }) }),
|
|
1910
|
-
/* @__PURE__ */ (0,
|
|
1980
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui12.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1911
1981
|
family,
|
|
1912
1982
|
renderGenreDetailExtras?.(overview),
|
|
1913
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0,
|
|
1914
|
-
/* @__PURE__ */ (0,
|
|
1983
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui12.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
1984
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsx)(
|
|
1915
1985
|
GenrePlaylistTracks,
|
|
1916
1986
|
{
|
|
1917
1987
|
genreUuid,
|
|
@@ -1929,28 +1999,10 @@ function GenreDetailExtras({
|
|
|
1929
1999
|
}
|
|
1930
2000
|
|
|
1931
2001
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1932
|
-
var
|
|
1933
|
-
var
|
|
2002
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2003
|
+
var import_react14 = require("react");
|
|
1934
2004
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
1935
|
-
|
|
1936
|
-
const isCurrentTrackList = playback.playingNodeId === genrePlaylist.uuid;
|
|
1937
|
-
const handlePlayPause = () => {
|
|
1938
|
-
if (isCurrentTrackList) {
|
|
1939
|
-
setIsPlaying(!isPlaying);
|
|
1940
|
-
return;
|
|
1941
|
-
}
|
|
1942
|
-
playback.play(genrePlaylist).catch((error) => {
|
|
1943
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
1944
|
-
});
|
|
1945
|
-
};
|
|
1946
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1947
|
-
GenreActionBand,
|
|
1948
|
-
{
|
|
1949
|
-
...bandProps,
|
|
1950
|
-
onPlayPause: ("genreOnlyTracksCount" in genrePlaylist ? (0, import_genre_tree18.genreMusicCount)(genrePlaylist) : genrePlaylist.tracksCount) > 0 ? handlePlayPause : void 0,
|
|
1951
|
-
isPlaying: isCurrentTrackList && isPlaying
|
|
1952
|
-
}
|
|
1953
|
-
);
|
|
2005
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(GenrePlayActions, { genrePlaylist, playback }) });
|
|
1954
2006
|
}
|
|
1955
2007
|
function GenreInfoPanelBody({
|
|
1956
2008
|
toolbar,
|
|
@@ -1958,7 +2010,6 @@ function GenreInfoPanelBody({
|
|
|
1958
2010
|
genreUuid,
|
|
1959
2011
|
genrePlaylist,
|
|
1960
2012
|
catalogue,
|
|
1961
|
-
countsContext,
|
|
1962
2013
|
wikidataId,
|
|
1963
2014
|
scope,
|
|
1964
2015
|
getBackendBaseUrl,
|
|
@@ -1966,33 +2017,12 @@ function GenreInfoPanelBody({
|
|
|
1966
2017
|
band,
|
|
1967
2018
|
extras
|
|
1968
2019
|
}) {
|
|
1969
|
-
const
|
|
1970
|
-
const
|
|
1971
|
-
|
|
1972
|
-
const describeCounts = (counts) => {
|
|
1973
|
-
const scopes = counts.genreAndSubgenresTracksCount;
|
|
1974
|
-
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`;
|
|
1975
|
-
};
|
|
1976
|
-
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
2020
|
+
const summary = scope === "reference" ? import_genre_tree19.GenreCatalogueCountsSchema.parse(genrePlaylist ?? catalogue) : void 0;
|
|
2021
|
+
const selection = summary ? (0, import_genre_tree19.defaultGenreMusicSelection)(summary) : void 0;
|
|
2022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsxs)(import_jsx_runtime34.Fragment, { children: [
|
|
1977
2023
|
toolbar,
|
|
1978
|
-
genrePlaylist ? /* @__PURE__ */ (0,
|
|
1979
|
-
|
|
1980
|
-
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { children: [
|
|
1981
|
-
"Catalogue ",
|
|
1982
|
-
noun.plural,
|
|
1983
|
-
countsContext ? ` (${countsContext})` : "",
|
|
1984
|
-
": ",
|
|
1985
|
-
describeCounts(catalogue)
|
|
1986
|
-
] }),
|
|
1987
|
-
genrePlaylist && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { children: [
|
|
1988
|
-
"Playlist ",
|
|
1989
|
-
noun.plural,
|
|
1990
|
-
countsContext ? ` (${countsContext})` : "",
|
|
1991
|
-
": ",
|
|
1992
|
-
describeCounts(summary)
|
|
1993
|
-
] })
|
|
1994
|
-
] }),
|
|
1995
|
-
/* @__PURE__ */ (0, import_react13.createElement)(
|
|
2024
|
+
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(GenreActionBand, { ...band }),
|
|
2025
|
+
/* @__PURE__ */ (0, import_react14.createElement)(
|
|
1996
2026
|
GenreDetailExtras,
|
|
1997
2027
|
{
|
|
1998
2028
|
...extras,
|
|
@@ -2011,7 +2041,7 @@ function GenreInfoPanelBody({
|
|
|
2011
2041
|
}
|
|
2012
2042
|
|
|
2013
2043
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
2014
|
-
var
|
|
2044
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2015
2045
|
var RELATIVE_ITEM_COUNT = 1;
|
|
2016
2046
|
function toNode(genre, parentId) {
|
|
2017
2047
|
return {
|
|
@@ -2033,80 +2063,88 @@ function useGenreDetailContent({
|
|
|
2033
2063
|
playback: hostPlayback,
|
|
2034
2064
|
trailing,
|
|
2035
2065
|
genrePlaylist: hostPlaylist,
|
|
2036
|
-
expanded
|
|
2066
|
+
expanded,
|
|
2067
|
+
treeRelations
|
|
2037
2068
|
}) {
|
|
2038
|
-
const { data: detail, isPending, isError } = (0,
|
|
2069
|
+
const { data: detail, isPending, isError } = (0, import_genre_tree20.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
|
|
2039
2070
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: [], artist: extras?.artist });
|
|
2040
2071
|
const playback = hostPlayback ?? defaultPlayback;
|
|
2041
|
-
const view = (0,
|
|
2072
|
+
const view = (0, import_react15.useMemo)(() => {
|
|
2042
2073
|
if (!detail) return null;
|
|
2043
2074
|
const rootColor = (0, import_genre_tree_view4.getGenreTreeColor)(detail.root.wikidataId);
|
|
2075
|
+
const treeStyles = /* @__PURE__ */ new Map();
|
|
2076
|
+
if (treeRelations) {
|
|
2077
|
+
const drawn = [treeRelations, treeRelations.parentNode, ...treeRelations.childNodes, ...treeRelations.ancestorNodes];
|
|
2078
|
+
for (const entry of drawn) {
|
|
2079
|
+
if (entry) treeStyles.set(entry.node.id, { fill: entry.fill, textColor: entry.textColor });
|
|
2080
|
+
}
|
|
2081
|
+
}
|
|
2044
2082
|
const relative = (genre, parentId) => ({
|
|
2045
2083
|
node: toNode(genre, parentId),
|
|
2046
|
-
fill: (0, import_genre_tree_view4.tintSurface)(rootColor),
|
|
2047
|
-
textColor: import_genre_tree_view4.TEXT_COLOR
|
|
2084
|
+
...treeStyles.get(genre.uuid) ?? { fill: (0, import_genre_tree_view4.tintSurface)(rootColor), textColor: import_genre_tree_view4.TEXT_COLOR }
|
|
2048
2085
|
});
|
|
2049
2086
|
const ancestors2 = [...detail.ascendants].sort((a, b) => b.degree - a.degree);
|
|
2087
|
+
const own = treeStyles.get(detail.uuid) ?? { fill: rootColor, textColor: (0, import_genre_tree_view4.getTextColorOnFill)(rootColor) };
|
|
2050
2088
|
return {
|
|
2051
2089
|
node: {
|
|
2052
2090
|
id: detail.uuid,
|
|
2053
2091
|
parentId: detail.parent?.uuid ?? null,
|
|
2054
2092
|
name: detail.name,
|
|
2055
|
-
itemCount: scope === "reference" ? (0,
|
|
2093
|
+
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,
|
|
2056
2094
|
wikidataId: detail.wikidataId
|
|
2057
2095
|
},
|
|
2058
|
-
fill:
|
|
2096
|
+
fill: own.fill,
|
|
2097
|
+
textColor: own.textColor,
|
|
2059
2098
|
parentNode: detail.parent ? relative(detail.parent, null) : null,
|
|
2060
2099
|
childNodes: detail.children.map((child) => relative(child, detail.uuid)),
|
|
2061
2100
|
ancestorNodes: ancestors2.map(
|
|
2062
2101
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
2063
2102
|
)
|
|
2064
2103
|
};
|
|
2065
|
-
}, [detail, scope]);
|
|
2104
|
+
}, [detail, scope, treeRelations]);
|
|
2066
2105
|
if (isError) return {
|
|
2067
2106
|
name: null,
|
|
2068
2107
|
title: "Genre unavailable",
|
|
2069
|
-
content: /* @__PURE__ */ (0,
|
|
2108
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("p", { role: "alert", className: "text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
2070
2109
|
};
|
|
2071
2110
|
if (isPending || !detail || !view) return {
|
|
2072
2111
|
name: null,
|
|
2073
2112
|
title: "Loading genre\u2026",
|
|
2074
|
-
content: /* @__PURE__ */ (0,
|
|
2075
|
-
/* @__PURE__ */ (0,
|
|
2076
|
-
/* @__PURE__ */ (0,
|
|
2077
|
-
/* @__PURE__ */ (0,
|
|
2113
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
2114
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.Skeleton, { className: "h-6 w-2/3" }),
|
|
2115
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.Skeleton, { className: "h-4 w-full" }),
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.Skeleton, { className: "h-4 w-3/4" })
|
|
2078
2117
|
] })
|
|
2079
2118
|
};
|
|
2080
|
-
const selectGenre = (nodeId) => onSelectGenre(
|
|
2081
|
-
const family = /* @__PURE__ */ (0,
|
|
2119
|
+
const selectGenre = (nodeId) => onSelectGenre(import_genre_tree20.GenreUuidSchema.parse(nodeId));
|
|
2120
|
+
const family = /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2082
2121
|
import_genre_tree_view4.GenreNodeFamily,
|
|
2083
2122
|
{
|
|
2084
2123
|
node: view.node,
|
|
2085
2124
|
fill: view.fill,
|
|
2086
|
-
textColor:
|
|
2125
|
+
textColor: view.textColor,
|
|
2087
2126
|
parentNode: view.parentNode,
|
|
2088
2127
|
childNodes: view.childNodes,
|
|
2089
2128
|
onSelectNode: selectGenre
|
|
2090
2129
|
}
|
|
2091
2130
|
);
|
|
2092
|
-
const ancestors = /* @__PURE__ */ (0,
|
|
2131
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
2093
2132
|
return {
|
|
2094
2133
|
name: detail.name,
|
|
2095
2134
|
title: detail.name,
|
|
2096
|
-
headerAccent: { background: view.fill, color:
|
|
2135
|
+
headerAccent: { background: view.fill, color: view.textColor },
|
|
2097
2136
|
aside: expanded ? ancestors : void 0,
|
|
2098
|
-
content: /* @__PURE__ */ (0,
|
|
2099
|
-
/* @__PURE__ */ (0,
|
|
2137
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
2138
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2100
2139
|
GenreInfoPanelBody,
|
|
2101
2140
|
{
|
|
2102
|
-
family: /* @__PURE__ */ (0,
|
|
2141
|
+
family: /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)(import_jsx_runtime35.Fragment, { children: [
|
|
2103
2142
|
family,
|
|
2104
2143
|
!expanded && ancestors
|
|
2105
2144
|
] }),
|
|
2106
2145
|
genreUuid: detail.uuid,
|
|
2107
|
-
genrePlaylist: hostPlaylist ?? (detail.criteriaPlaylist === null ? null : scope === "reference" ? { ...
|
|
2146
|
+
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 }),
|
|
2108
2147
|
catalogue: detail.catalogue,
|
|
2109
|
-
countsContext: !hostPlaylist && extras?.artist ? "all artists" : void 0,
|
|
2110
2148
|
wikidataId: detail.wikidataId,
|
|
2111
2149
|
scope,
|
|
2112
2150
|
getBackendBaseUrl,
|
|
@@ -2144,8 +2182,8 @@ function GenreDetailPanel({
|
|
|
2144
2182
|
expanded,
|
|
2145
2183
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
2146
2184
|
});
|
|
2147
|
-
return /* @__PURE__ */ (0,
|
|
2148
|
-
|
|
2185
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(
|
|
2186
|
+
import_ui13.DetailPanel,
|
|
2149
2187
|
{
|
|
2150
2188
|
side: "left",
|
|
2151
2189
|
title: panel.title,
|
|
@@ -2157,16 +2195,16 @@ function GenreDetailPanel({
|
|
|
2157
2195
|
edgeTab,
|
|
2158
2196
|
aside: panel.aside,
|
|
2159
2197
|
titleInSearch,
|
|
2160
|
-
headerActions: onExpandedChange ? /* @__PURE__ */ (0,
|
|
2198
|
+
headerActions: onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_ui13.IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react13.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(import_lucide_react13.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
2161
2199
|
children: panel.content
|
|
2162
2200
|
}
|
|
2163
2201
|
);
|
|
2164
2202
|
}
|
|
2165
2203
|
|
|
2166
2204
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
2167
|
-
var
|
|
2168
|
-
var
|
|
2169
|
-
var
|
|
2205
|
+
var import_react16 = require("react");
|
|
2206
|
+
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2207
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2170
2208
|
function ChangeParentPopup({
|
|
2171
2209
|
genrePlaylist,
|
|
2172
2210
|
genrePlaylists,
|
|
@@ -2175,9 +2213,9 @@ function ChangeParentPopup({
|
|
|
2175
2213
|
onClose,
|
|
2176
2214
|
onParentChanged
|
|
2177
2215
|
}) {
|
|
2178
|
-
const { mutate, isPending, formErrors } = (0,
|
|
2179
|
-
const candidates = (0,
|
|
2180
|
-
() => (0,
|
|
2216
|
+
const { mutate, isPending, formErrors } = (0, import_genre_tree21.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
2217
|
+
const candidates = (0, import_react16.useMemo)(
|
|
2218
|
+
() => (0, import_genre_tree21.getReparentCandidates)(genrePlaylists, genrePlaylist.uuid),
|
|
2181
2219
|
[genrePlaylists, genrePlaylist.uuid]
|
|
2182
2220
|
);
|
|
2183
2221
|
const handleSelect = (newParent) => {
|
|
@@ -2194,19 +2232,19 @@ function ChangeParentPopup({
|
|
|
2194
2232
|
}
|
|
2195
2233
|
);
|
|
2196
2234
|
};
|
|
2197
|
-
(0,
|
|
2235
|
+
(0, import_react16.useEffect)(() => {
|
|
2198
2236
|
const handleKeyDown = (event) => {
|
|
2199
2237
|
if (event.key === "Escape") onClose();
|
|
2200
2238
|
};
|
|
2201
2239
|
window.addEventListener("keydown", handleKeyDown);
|
|
2202
2240
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2203
2241
|
}, [onClose]);
|
|
2204
|
-
return /* @__PURE__ */ (0,
|
|
2205
|
-
/* @__PURE__ */ (0,
|
|
2242
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
2243
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
2206
2244
|
"Current parent: ",
|
|
2207
2245
|
genrePlaylist.parent?.name ?? "none"
|
|
2208
2246
|
] }),
|
|
2209
|
-
/* @__PURE__ */ (0,
|
|
2247
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2210
2248
|
GenreSearch,
|
|
2211
2249
|
{
|
|
2212
2250
|
genrePlaylists: candidates,
|
|
@@ -2214,24 +2252,61 @@ function ChangeParentPopup({
|
|
|
2214
2252
|
placeholder: "Search a new parent\u2026"
|
|
2215
2253
|
}
|
|
2216
2254
|
) }),
|
|
2217
|
-
formErrors.length > 0 && /* @__PURE__ */ (0,
|
|
2255
|
+
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
2218
2256
|
] });
|
|
2219
2257
|
}
|
|
2220
2258
|
|
|
2221
2259
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2222
|
-
var
|
|
2223
|
-
var
|
|
2260
|
+
var import_ui20 = require("@behindthemusictree/ui");
|
|
2261
|
+
var import_genre_tree27 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2262
|
+
|
|
2263
|
+
// src/genre-tree/artist/ArtistActionBand.tsx
|
|
2264
|
+
var import_lucide_react14 = require("lucide-react");
|
|
2265
|
+
var import_ui14 = require("@behindthemusictree/ui");
|
|
2266
|
+
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2267
|
+
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2268
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2269
|
+
function ArtistActionBand({ artist, share }) {
|
|
2270
|
+
const { trackList, playNewTrackListFromArtist } = (0, import_genre_tree22.useTrackList)();
|
|
2271
|
+
const { isPlaying, setIsPlaying } = (0, import_player7.usePlayer)();
|
|
2272
|
+
const origin = trackList?.origin;
|
|
2273
|
+
const isCurrent = origin?.type === import_genre_tree22.TrackListOriginType.ARTIST && origin.uuid === artist.uuid;
|
|
2274
|
+
const playing = isCurrent && isPlaying;
|
|
2275
|
+
const handleClick = () => {
|
|
2276
|
+
if (isCurrent) {
|
|
2277
|
+
setIsPlaying(!isPlaying);
|
|
2278
|
+
return;
|
|
2279
|
+
}
|
|
2280
|
+
playNewTrackListFromArtist({ uuid: artist.uuid, name: artist.name }, "reference", { ordering: "title" }).catch((error) => {
|
|
2281
|
+
console.error("Failed to load artist tracks:", error);
|
|
2282
|
+
});
|
|
2283
|
+
};
|
|
2284
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui14.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)(import_ui14.ActionBand, { children: [
|
|
2285
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2286
|
+
import_ui14.ActionButton,
|
|
2287
|
+
{
|
|
2288
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react14.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_lucide_react14.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2289
|
+
label: playing ? "Pause" : "Play",
|
|
2290
|
+
caption: String(artist.playableTracksCount),
|
|
2291
|
+
disabled: artist.playableTracksCount === 0,
|
|
2292
|
+
title: artist.playableTracksCount === 0 ? "No playable songs" : void 0,
|
|
2293
|
+
onClick: handleClick
|
|
2294
|
+
}
|
|
2295
|
+
),
|
|
2296
|
+
share
|
|
2297
|
+
] }) });
|
|
2298
|
+
}
|
|
2224
2299
|
|
|
2225
2300
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2226
|
-
var
|
|
2301
|
+
var import_ui16 = require("@behindthemusictree/ui");
|
|
2227
2302
|
|
|
2228
2303
|
// src/genre-tree/artist/ArtistLinks.tsx
|
|
2229
|
-
var
|
|
2304
|
+
var import_lucide_react15 = require("lucide-react");
|
|
2230
2305
|
var import_si3 = require("react-icons/si");
|
|
2231
|
-
var
|
|
2232
|
-
var
|
|
2306
|
+
var import_ui15 = require("@behindthemusictree/ui");
|
|
2307
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2233
2308
|
var LINK_KINDS = {
|
|
2234
|
-
official: { label: "Official website", Icon:
|
|
2309
|
+
official: { label: "Official website", Icon: import_lucide_react15.Globe },
|
|
2235
2310
|
wikipedia: { label: "Wikipedia", Icon: import_si3.SiWikipedia },
|
|
2236
2311
|
wikidata: { label: "Wikidata", Icon: import_si3.SiWikidata },
|
|
2237
2312
|
spotify: { label: "Spotify", Icon: import_si3.SiSpotify },
|
|
@@ -2239,7 +2314,7 @@ var LINK_KINDS = {
|
|
|
2239
2314
|
bandcamp: { label: "Bandcamp", Icon: import_si3.SiBandcamp },
|
|
2240
2315
|
soundcloud: { label: "SoundCloud", Icon: import_si3.SiSoundcloud },
|
|
2241
2316
|
discogs: { label: "Discogs", Icon: import_si3.SiDiscogs },
|
|
2242
|
-
social: { label: "Social", Icon:
|
|
2317
|
+
social: { label: "Social", Icon: import_lucide_react15.Share2 }
|
|
2243
2318
|
};
|
|
2244
2319
|
function socialLabel(url) {
|
|
2245
2320
|
try {
|
|
@@ -2266,7 +2341,7 @@ function artistLinks(artist) {
|
|
|
2266
2341
|
return links;
|
|
2267
2342
|
}
|
|
2268
2343
|
function ArtistLinks({ links }) {
|
|
2269
|
-
return /* @__PURE__ */ (0,
|
|
2344
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_ui15.Chip, { href: url, icon: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
2270
2345
|
}
|
|
2271
2346
|
|
|
2272
2347
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -2277,7 +2352,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
2277
2352
|
}
|
|
2278
2353
|
|
|
2279
2354
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2280
|
-
var
|
|
2355
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2281
2356
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
2282
2357
|
function ArtistHeader({ artist }) {
|
|
2283
2358
|
const fields = [];
|
|
@@ -2287,35 +2362,35 @@ function ArtistHeader({ artist }) {
|
|
|
2287
2362
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
2288
2363
|
if (years) fields.push({ label: "Active", value: years });
|
|
2289
2364
|
const links = artistLinks(artist);
|
|
2290
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0,
|
|
2365
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(ArtistLinks, { links }) });
|
|
2291
2366
|
if (fields.length === 0) return null;
|
|
2292
|
-
return /* @__PURE__ */ (0,
|
|
2367
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui16.FieldList, { items: fields });
|
|
2293
2368
|
}
|
|
2294
2369
|
|
|
2295
2370
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
2296
|
-
var
|
|
2371
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2297
2372
|
function ExternalLink({ href, children }) {
|
|
2298
|
-
return /* @__PURE__ */ (0,
|
|
2373
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
2299
2374
|
}
|
|
2300
2375
|
function ArtistPhoto({ image, name }) {
|
|
2301
|
-
return /* @__PURE__ */ (0,
|
|
2302
|
-
/* @__PURE__ */ (0,
|
|
2303
|
-
/* @__PURE__ */ (0,
|
|
2376
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("figure", { className: "flex flex-col gap-1.5", children: [
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
2378
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2304
2379
|
"Photo: ",
|
|
2305
|
-
/* @__PURE__ */ (0,
|
|
2380
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2306
2381
|
",",
|
|
2307
2382
|
" ",
|
|
2308
|
-
image.licenseUrl ? /* @__PURE__ */ (0,
|
|
2383
|
+
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
2309
2384
|
] })
|
|
2310
2385
|
] });
|
|
2311
2386
|
}
|
|
2312
2387
|
|
|
2313
2388
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2314
|
-
var
|
|
2315
|
-
var
|
|
2389
|
+
var import_ui17 = require("@behindthemusictree/ui");
|
|
2390
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2316
2391
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2317
2392
|
if (memberships.length === 0) return null;
|
|
2318
|
-
return /* @__PURE__ */ (0,
|
|
2393
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.PanelGroup, { title, children: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("ul", { children: memberships.map((membership, index) => {
|
|
2319
2394
|
const details = [
|
|
2320
2395
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2321
2396
|
...membership.roles
|
|
@@ -2323,9 +2398,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2323
2398
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
2324
2399
|
return (
|
|
2325
2400
|
// A member can have several periods in the same group.
|
|
2326
|
-
/* @__PURE__ */ (0,
|
|
2327
|
-
/* @__PURE__ */ (0,
|
|
2328
|
-
detailsText && /* @__PURE__ */ (0,
|
|
2401
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
2402
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
2403
|
+
detailsText && /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2329
2404
|
" \u2014 ",
|
|
2330
2405
|
detailsText
|
|
2331
2406
|
] })
|
|
@@ -2336,9 +2411,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2336
2411
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2337
2412
|
if (memberships.length === 0) return null;
|
|
2338
2413
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2339
|
-
return /* @__PURE__ */ (0,
|
|
2340
|
-
/* @__PURE__ */ (0,
|
|
2341
|
-
/* @__PURE__ */ (0,
|
|
2414
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_ui17.PanelSection, { title, children: [
|
|
2415
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2416
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2342
2417
|
MembershipList,
|
|
2343
2418
|
{
|
|
2344
2419
|
title: "Past",
|
|
@@ -2350,8 +2425,8 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2350
2425
|
}
|
|
2351
2426
|
|
|
2352
2427
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2353
|
-
var
|
|
2354
|
-
var
|
|
2428
|
+
var import_ui18 = require("@behindthemusictree/ui");
|
|
2429
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2355
2430
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2356
2431
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
2357
2432
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -2371,55 +2446,55 @@ function byYear(a, b) {
|
|
|
2371
2446
|
function ArtistDiscography({ albums }) {
|
|
2372
2447
|
if (albums.length === 0) return null;
|
|
2373
2448
|
const sorted = [...albums].sort(byYear);
|
|
2374
|
-
return /* @__PURE__ */ (0,
|
|
2449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2375
2450
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2376
2451
|
if (groupAlbums.length === 0) return null;
|
|
2377
|
-
return /* @__PURE__ */ (0,
|
|
2378
|
-
/* @__PURE__ */ (0,
|
|
2379
|
-
/* @__PURE__ */ (0,
|
|
2452
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.PanelGroup, { title: group, children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
2453
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2454
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2380
2455
|
] }, album.uuid)) }) }, group);
|
|
2381
2456
|
}) });
|
|
2382
2457
|
}
|
|
2383
2458
|
|
|
2384
2459
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2385
|
-
var
|
|
2460
|
+
var import_react17 = require("react");
|
|
2386
2461
|
var import_react_query2 = require("@tanstack/react-query");
|
|
2387
|
-
var
|
|
2388
|
-
var
|
|
2389
|
-
var
|
|
2390
|
-
var
|
|
2462
|
+
var import_lucide_react16 = require("lucide-react");
|
|
2463
|
+
var import_ui19 = require("@behindthemusictree/ui");
|
|
2464
|
+
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2465
|
+
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2391
2466
|
var import_transport9 = require("@behindthemusictree/app-kit/transport");
|
|
2392
2467
|
|
|
2393
2468
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2394
|
-
var
|
|
2395
|
-
var
|
|
2469
|
+
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
2470
|
+
var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2396
2471
|
|
|
2397
2472
|
// src/genre-tree/TrackPositionPlayPause.tsx
|
|
2398
2473
|
var import_fa5 = require("react-icons/fa");
|
|
2399
|
-
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2400
2474
|
var import_player8 = require("@behindthemusictree/app-kit/player");
|
|
2401
|
-
var
|
|
2475
|
+
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2476
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2402
2477
|
function TrackPositionPlayPause({
|
|
2403
2478
|
position,
|
|
2404
2479
|
uuid,
|
|
2405
2480
|
handlePlayPauseClick,
|
|
2406
2481
|
isSelected = false
|
|
2407
2482
|
}) {
|
|
2408
|
-
const { playerTrackObject, playbackConfirmedTrackId, playState, isLoading: isPlayerLoading } = (0,
|
|
2483
|
+
const { playerTrackObject, playbackConfirmedTrackId, playState, isLoading: isPlayerLoading } = (0, import_player8.usePlayer)();
|
|
2409
2484
|
const isThisTrack = playerTrackObject?.track.id === uuid;
|
|
2410
2485
|
const isConfirmedPlayable = playbackConfirmedTrackId === uuid;
|
|
2411
|
-
const isAwaitingPlayback = (isSelected || isThisTrack) && !isConfirmedPlayable && !(isThisTrack && playerTrackObject?.loadError) && (!isThisTrack || isPlayerLoading || playState ===
|
|
2412
|
-
const isPlaying = isThisTrack && isConfirmedPlayable && playState ===
|
|
2413
|
-
const isPaused = isThisTrack && isConfirmedPlayable && playState ===
|
|
2486
|
+
const isAwaitingPlayback = (isSelected || isThisTrack) && !isConfirmedPlayable && !(isThisTrack && playerTrackObject?.loadError) && (!isThisTrack || isPlayerLoading || playState === import_player9.PlayStates.LOADING || playState === import_player9.PlayStates.PLAYING);
|
|
2487
|
+
const isPlaying = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PLAYING;
|
|
2488
|
+
const isPaused = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PAUSED;
|
|
2414
2489
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
2415
|
-
return /* @__PURE__ */ (0,
|
|
2490
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2416
2491
|
"div",
|
|
2417
2492
|
{
|
|
2418
2493
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
2419
2494
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
2420
2495
|
onClick: handlePlayPauseClick,
|
|
2421
2496
|
children: [
|
|
2422
|
-
/* @__PURE__ */ (0,
|
|
2497
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2423
2498
|
"span",
|
|
2424
2499
|
{
|
|
2425
2500
|
className: "track-position-play-pause__bars",
|
|
@@ -2427,18 +2502,18 @@ function TrackPositionPlayPause({
|
|
|
2427
2502
|
role: "img",
|
|
2428
2503
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
2429
2504
|
children: [
|
|
2430
|
-
/* @__PURE__ */ (0,
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2432
|
-
/* @__PURE__ */ (0,
|
|
2505
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2506
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2507
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "track-position-play-pause__bar" })
|
|
2433
2508
|
]
|
|
2434
2509
|
}
|
|
2435
2510
|
) : position }),
|
|
2436
|
-
/* @__PURE__ */ (0,
|
|
2511
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2437
2512
|
"div",
|
|
2438
2513
|
{
|
|
2439
2514
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
2440
2515
|
"aria-hidden": "true",
|
|
2441
|
-
children: isAwaitingPlayback ? /* @__PURE__ */ (0,
|
|
2516
|
+
children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "track-position-play-pause__spinner" }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_fa5.FaPause, {}) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_fa5.FaPlay, {})
|
|
2442
2517
|
}
|
|
2443
2518
|
)
|
|
2444
2519
|
]
|
|
@@ -2447,9 +2522,9 @@ function TrackPositionPlayPause({
|
|
|
2447
2522
|
}
|
|
2448
2523
|
|
|
2449
2524
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2450
|
-
var
|
|
2451
|
-
var
|
|
2452
|
-
var
|
|
2525
|
+
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2526
|
+
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2527
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2453
2528
|
function TrackItem({
|
|
2454
2529
|
track,
|
|
2455
2530
|
position,
|
|
@@ -2458,12 +2533,12 @@ function TrackItem({
|
|
|
2458
2533
|
renderArtistLink,
|
|
2459
2534
|
renderSongLink
|
|
2460
2535
|
}) {
|
|
2461
|
-
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = (0,
|
|
2462
|
-
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0,
|
|
2536
|
+
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = (0, import_player10.usePlayer)();
|
|
2537
|
+
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = (0, import_genre_tree23.useTrackList)();
|
|
2463
2538
|
const scope = trackList?.origin?.scope ?? null;
|
|
2464
2539
|
const isCurrentTrack = playerTrackObject?.track.id === track.uuid;
|
|
2465
2540
|
const hasPlaybackError = isCurrentTrack && !!playerTrackObject?.loadError;
|
|
2466
|
-
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0,
|
|
2541
|
+
const isUnplayable = hasPlaybackError || runtimeUnplayableTrackIds?.has(track.uuid) === true || (0, import_genre_tree24.isSong)(track) && (0, import_genre_tree24.songUnplayableReason)(track) !== null;
|
|
2467
2542
|
const handlePlayPauseClick = (event) => {
|
|
2468
2543
|
event.stopPropagation();
|
|
2469
2544
|
if (isCurrentTrack) {
|
|
@@ -2473,12 +2548,12 @@ function TrackItem({
|
|
|
2473
2548
|
loadTrackForPlayer(track.uuid);
|
|
2474
2549
|
}
|
|
2475
2550
|
};
|
|
2476
|
-
return /* @__PURE__ */ (0,
|
|
2551
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(
|
|
2477
2552
|
"div",
|
|
2478
2553
|
{
|
|
2479
2554
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
2480
2555
|
children: [
|
|
2481
|
-
isUnplayable ? /* @__PURE__ */ (0,
|
|
2556
|
+
isUnplayable ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2482
2557
|
"div",
|
|
2483
2558
|
{
|
|
2484
2559
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -2486,7 +2561,7 @@ function TrackItem({
|
|
|
2486
2561
|
"aria-disabled": "true",
|
|
2487
2562
|
children: position
|
|
2488
2563
|
}
|
|
2489
|
-
) : /* @__PURE__ */ (0,
|
|
2564
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2490
2565
|
TrackPositionPlayPause,
|
|
2491
2566
|
{
|
|
2492
2567
|
position,
|
|
@@ -2495,12 +2570,12 @@ function TrackItem({
|
|
|
2495
2570
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
2496
2571
|
}
|
|
2497
2572
|
),
|
|
2498
|
-
/* @__PURE__ */ (0,
|
|
2499
|
-
/* @__PURE__ */ (0,
|
|
2500
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0,
|
|
2573
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2574
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2575
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_genre_tree25.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2501
2576
|
] }),
|
|
2502
|
-
/* @__PURE__ */ (0,
|
|
2503
|
-
renderDuration && /* @__PURE__ */ (0,
|
|
2577
|
+
/* @__PURE__ */ (0, import_jsx_runtime44.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_runtime44.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2578
|
+
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2504
2579
|
"div",
|
|
2505
2580
|
{
|
|
2506
2581
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -2508,28 +2583,28 @@ function TrackItem({
|
|
|
2508
2583
|
children: renderDuration(track)
|
|
2509
2584
|
}
|
|
2510
2585
|
),
|
|
2511
|
-
renderActions && /* @__PURE__ */ (0,
|
|
2586
|
+
renderActions && /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("div", { className: "edit flex text-base w-6 items-center justify-center mr-2 cursor-pointer", children: renderActions(track) })
|
|
2512
2587
|
]
|
|
2513
2588
|
}
|
|
2514
2589
|
);
|
|
2515
2590
|
}
|
|
2516
2591
|
|
|
2517
2592
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2518
|
-
var
|
|
2519
|
-
var SongPageSchema2 = (0, import_transport9.PaginatedResponseSchema)(
|
|
2593
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2594
|
+
var SongPageSchema2 = (0, import_transport9.PaginatedResponseSchema)(import_genre_tree26.SongDetailedSchema);
|
|
2520
2595
|
var SORTS = [
|
|
2521
2596
|
{ ordering: "title", label: "Title" },
|
|
2522
2597
|
{ ordering: "-albumYear", label: "Year" }
|
|
2523
2598
|
];
|
|
2524
2599
|
function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
|
|
2525
|
-
const [page, setPage] = (0,
|
|
2526
|
-
const [ordering, setOrdering] = (0,
|
|
2527
|
-
const { playNewTrackListFromArtist } = (0,
|
|
2528
|
-
const { playerTrackObject } = (0,
|
|
2600
|
+
const [page, setPage] = (0, import_react17.useState)(1);
|
|
2601
|
+
const [ordering, setOrdering] = (0, import_react17.useState)("title");
|
|
2602
|
+
const { playNewTrackListFromArtist } = (0, import_genre_tree26.useTrackList)();
|
|
2603
|
+
const { playerTrackObject } = (0, import_player11.usePlayer)();
|
|
2529
2604
|
const { data, isPending, isError } = (0, import_transport9.usePlaybackQuery)({
|
|
2530
2605
|
getBackendBaseUrl,
|
|
2531
2606
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
2532
|
-
queryFn: (fetchBound) => fetchBound(
|
|
2607
|
+
queryFn: (fetchBound) => fetchBound(import_genre_tree26.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
2533
2608
|
artist: artist.uuid,
|
|
2534
2609
|
ordering,
|
|
2535
2610
|
page
|
|
@@ -2544,25 +2619,25 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2544
2619
|
});
|
|
2545
2620
|
const handleRowClickCapture = (event, song) => {
|
|
2546
2621
|
if (!(event.target instanceof Element) || !event.target.closest(".track-position-play-pause")) return;
|
|
2547
|
-
if (playerTrackObject?.track.id === song.uuid || (0,
|
|
2622
|
+
if (playerTrackObject?.track.id === song.uuid || (0, import_genre_tree26.songUnplayableReason)(song) !== null) return;
|
|
2548
2623
|
event.stopPropagation();
|
|
2549
2624
|
void play(song.uuid);
|
|
2550
2625
|
};
|
|
2551
|
-
return /* @__PURE__ */ (0,
|
|
2552
|
-
/* @__PURE__ */ (0,
|
|
2553
|
-
/* @__PURE__ */ (0,
|
|
2626
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_ui19.PanelSection, { title: "Songs", children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_ui19.Skeleton, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
|
|
2627
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-2", children: [
|
|
2628
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
2554
2629
|
"button",
|
|
2555
2630
|
{
|
|
2556
2631
|
type: "button",
|
|
2557
2632
|
onClick: () => void play(),
|
|
2558
|
-
className: "flex w-fit items-center gap-1.5 px-3 py-1 text-
|
|
2633
|
+
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",
|
|
2559
2634
|
children: [
|
|
2560
|
-
/* @__PURE__ */ (0,
|
|
2635
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react16.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2561
2636
|
"Play all"
|
|
2562
2637
|
]
|
|
2563
2638
|
}
|
|
2564
2639
|
),
|
|
2565
|
-
/* @__PURE__ */ (0,
|
|
2640
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2566
2641
|
"button",
|
|
2567
2642
|
{
|
|
2568
2643
|
type: "button",
|
|
@@ -2577,7 +2652,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2577
2652
|
sort.ordering
|
|
2578
2653
|
)) })
|
|
2579
2654
|
] }),
|
|
2580
|
-
/* @__PURE__ */ (0,
|
|
2655
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("ul", { className: "overflow-hidden mb-2 bg-zinc-950 rounded-lg", children: data.results.map((song, index) => /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("li", { onClickCapture: (event) => handleRowClickCapture(event, song), children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2581
2656
|
TrackItem,
|
|
2582
2657
|
{
|
|
2583
2658
|
track: song,
|
|
@@ -2586,12 +2661,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2586
2661
|
renderSongLink
|
|
2587
2662
|
}
|
|
2588
2663
|
) }, song.uuid)) }),
|
|
2589
|
-
/* @__PURE__ */ (0,
|
|
2664
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_ui19.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2590
2665
|
] }) });
|
|
2591
2666
|
}
|
|
2592
2667
|
|
|
2593
2668
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2594
|
-
var
|
|
2669
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
2595
2670
|
function useArtistPanel({
|
|
2596
2671
|
uuid,
|
|
2597
2672
|
scope,
|
|
@@ -2603,7 +2678,7 @@ function useArtistPanel({
|
|
|
2603
2678
|
onExpandedChange,
|
|
2604
2679
|
onClose
|
|
2605
2680
|
}) {
|
|
2606
|
-
const result = (0,
|
|
2681
|
+
const result = (0, import_genre_tree27.useArtist)(uuid, getBackendBaseUrl);
|
|
2607
2682
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2608
2683
|
switch (result.status) {
|
|
2609
2684
|
case "idle":
|
|
@@ -2612,26 +2687,26 @@ function useArtistPanel({
|
|
|
2612
2687
|
return {
|
|
2613
2688
|
...panel,
|
|
2614
2689
|
title: "Artist",
|
|
2615
|
-
content: /* @__PURE__ */ (0,
|
|
2616
|
-
/* @__PURE__ */ (0,
|
|
2617
|
-
/* @__PURE__ */ (0,
|
|
2618
|
-
/* @__PURE__ */ (0,
|
|
2619
|
-
/* @__PURE__ */ (0,
|
|
2620
|
-
/* @__PURE__ */ (0,
|
|
2621
|
-
/* @__PURE__ */ (0,
|
|
2690
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2691
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2692
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui20.Skeleton, { className: "h-4 w-32" }),
|
|
2693
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui20.Skeleton, { className: "h-3 w-16" }),
|
|
2694
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui20.Skeleton, { className: "h-4 w-24" }),
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui20.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2696
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_ui20.Skeleton, { className: "h-16" })
|
|
2622
2697
|
] })
|
|
2623
2698
|
};
|
|
2624
2699
|
case "not-found":
|
|
2625
2700
|
return {
|
|
2626
2701
|
...panel,
|
|
2627
2702
|
title: "Artist not found",
|
|
2628
|
-
content: /* @__PURE__ */ (0,
|
|
2703
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2629
2704
|
};
|
|
2630
2705
|
case "error":
|
|
2631
2706
|
return {
|
|
2632
2707
|
...panel,
|
|
2633
2708
|
title: "Artist",
|
|
2634
|
-
content: /* @__PURE__ */ (0,
|
|
2709
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2635
2710
|
};
|
|
2636
2711
|
case "success": {
|
|
2637
2712
|
const { artist } = result;
|
|
@@ -2640,13 +2715,19 @@ function useArtistPanel({
|
|
|
2640
2715
|
return {
|
|
2641
2716
|
...panel,
|
|
2642
2717
|
title: artist.name,
|
|
2643
|
-
content: /* @__PURE__ */ (0,
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2718
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(import_jsx_runtime46.Fragment, { children: [
|
|
2719
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2720
|
+
ArtistActionBand,
|
|
2721
|
+
{
|
|
2722
|
+
artist,
|
|
2723
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2724
|
+
}
|
|
2725
|
+
),
|
|
2726
|
+
artist.image && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2727
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ArtistHeader, { artist }),
|
|
2728
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2729
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2730
|
+
artist.tracksCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
2650
2731
|
ArtistSongs,
|
|
2651
2732
|
{
|
|
2652
2733
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2656,69 +2737,62 @@ function useArtistPanel({
|
|
|
2656
2737
|
}
|
|
2657
2738
|
)
|
|
2658
2739
|
] }),
|
|
2659
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0,
|
|
2740
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2660
2741
|
};
|
|
2661
2742
|
}
|
|
2662
2743
|
}
|
|
2663
2744
|
}
|
|
2664
2745
|
|
|
2665
2746
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2666
|
-
var
|
|
2667
|
-
var
|
|
2747
|
+
var import_ui22 = require("@behindthemusictree/ui");
|
|
2748
|
+
var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2668
2749
|
|
|
2669
2750
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2670
|
-
var
|
|
2671
|
-
var
|
|
2672
|
-
var
|
|
2673
|
-
var
|
|
2674
|
-
var
|
|
2675
|
-
var
|
|
2751
|
+
var import_react18 = require("react");
|
|
2752
|
+
var import_lucide_react17 = require("lucide-react");
|
|
2753
|
+
var import_ui21 = require("@behindthemusictree/ui");
|
|
2754
|
+
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2755
|
+
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2756
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
2676
2757
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2677
2758
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2678
2759
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
2679
2760
|
function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
2680
|
-
const [open, setOpen] = (0,
|
|
2681
|
-
const history = (0,
|
|
2761
|
+
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2762
|
+
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2682
2763
|
let body = null;
|
|
2683
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0,
|
|
2684
|
-
else if (history.status === "error") body = /* @__PURE__ */ (0,
|
|
2764
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui21.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2765
|
+
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2685
2766
|
else if (history.status === "success")
|
|
2686
|
-
body = history.entries.length === 0 ? /* @__PURE__ */ (0,
|
|
2687
|
-
/* @__PURE__ */ (0,
|
|
2688
|
-
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0,
|
|
2767
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
2768
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2769
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2689
2770
|
" ",
|
|
2690
2771
|
"\u2014 ",
|
|
2691
2772
|
entry.oldValue ?? "none",
|
|
2692
2773
|
" \u2192 ",
|
|
2693
2774
|
entry.newValue ?? "none"
|
|
2694
2775
|
] }) : null,
|
|
2695
|
-
/* @__PURE__ */ (0,
|
|
2776
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2696
2777
|
entry.actorPseudo ?? "Anonymous",
|
|
2697
2778
|
" \xB7 ",
|
|
2698
2779
|
dateFormat.format(new Date(entry.createdOn))
|
|
2699
2780
|
] })
|
|
2700
2781
|
] }, entry.uuid)) });
|
|
2701
|
-
return /* @__PURE__ */ (0,
|
|
2702
|
-
"
|
|
2703
|
-
{
|
|
2704
|
-
|
|
2705
|
-
className: "px-6 pb-2.5 mt-2.5 border-t border-[var(--color-border)]",
|
|
2706
|
-
children: [
|
|
2707
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("summary", { className: "mt-2.5 cursor-pointer text-[0.6875rem] font-semibold uppercase text-[var(--color-text-muted)]", children: "History" }),
|
|
2708
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "mt-1.5", children: body })
|
|
2709
|
-
]
|
|
2710
|
-
}
|
|
2711
|
-
);
|
|
2782
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui21.PanelBleed, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2783
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui21.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2784
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "mt-1.5", children: body })
|
|
2785
|
+
] }) });
|
|
2712
2786
|
}
|
|
2713
2787
|
function SongPanelContent(props) {
|
|
2714
2788
|
const { song, scope, getBackendBaseUrl, shareUrl, renderArtistLink } = props;
|
|
2715
|
-
const { playNewTrackListFromTrackUuid } = (0,
|
|
2716
|
-
const { playerTrackObject, playState, handlePlayPauseAction } = (0,
|
|
2717
|
-
const unplayableReason = (0,
|
|
2789
|
+
const { playNewTrackListFromTrackUuid } = (0, import_genre_tree28.useTrackList)();
|
|
2790
|
+
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player12.usePlayer)();
|
|
2791
|
+
const unplayableReason = (0, import_genre_tree28.songUnplayableReason)(song);
|
|
2718
2792
|
const isCurrent = playerTrackObject?.track.id === song.uuid;
|
|
2719
|
-
const isPlaying = isCurrent && playState ===
|
|
2793
|
+
const isPlaying = isCurrent && playState === import_player12.PlayStates.PLAYING;
|
|
2720
2794
|
const shareTarget = { kind: "song", uuid: song.uuid, name: song.title, scope };
|
|
2721
|
-
const musicBrainzUrl = (0,
|
|
2795
|
+
const musicBrainzUrl = (0, import_genre_tree28.musicBrainzRecordingUrl)(song);
|
|
2722
2796
|
const fields = [];
|
|
2723
2797
|
if (song.genre) {
|
|
2724
2798
|
const path = props.genrePath && props.genrePath.length > 0 ? props.genrePath : null;
|
|
@@ -2726,13 +2800,13 @@ function SongPanelContent(props) {
|
|
|
2726
2800
|
const genre = song.genre;
|
|
2727
2801
|
fields.push({
|
|
2728
2802
|
label: "Genre",
|
|
2729
|
-
value: onSelectGenre ? /* @__PURE__ */ (0,
|
|
2730
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
2731
|
-
/* @__PURE__ */ (0,
|
|
2803
|
+
value: onSelectGenre ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("span", { children: [
|
|
2804
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2805
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2732
2806
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2733
2807
|
});
|
|
2734
2808
|
} else {
|
|
2735
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */ (0,
|
|
2809
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2736
2810
|
}
|
|
2737
2811
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2738
2812
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2742,11 +2816,11 @@ function SongPanelContent(props) {
|
|
|
2742
2816
|
const links = [];
|
|
2743
2817
|
if (musicBrainzUrl)
|
|
2744
2818
|
links.push(
|
|
2745
|
-
/* @__PURE__ */ (0,
|
|
2819
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2746
2820
|
);
|
|
2747
2821
|
if (song.youtubeVideo)
|
|
2748
2822
|
links.push(
|
|
2749
|
-
/* @__PURE__ */ (0,
|
|
2823
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2750
2824
|
"a",
|
|
2751
2825
|
{
|
|
2752
2826
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2761,33 +2835,31 @@ function SongPanelContent(props) {
|
|
|
2761
2835
|
if (links.length > 0)
|
|
2762
2836
|
fields.push({
|
|
2763
2837
|
label: "Links",
|
|
2764
|
-
value: /* @__PURE__ */ (0,
|
|
2838
|
+
value: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "flex gap-3", children: links })
|
|
2765
2839
|
});
|
|
2766
|
-
return /* @__PURE__ */ (0,
|
|
2767
|
-
/* @__PURE__ */ (0,
|
|
2768
|
-
|
|
2769
|
-
|
|
2840
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
|
|
2841
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui21.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_ui21.ActionBand, { children: [
|
|
2842
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2843
|
+
import_ui21.ActionButton,
|
|
2770
2844
|
{
|
|
2771
|
-
|
|
2772
|
-
|
|
2773
|
-
|
|
2774
|
-
|
|
2775
|
-
|
|
2776
|
-
isPlaying ? "Pause" : "Play"
|
|
2777
|
-
]
|
|
2845
|
+
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2846
|
+
label: isPlaying ? "Pause" : "Play",
|
|
2847
|
+
disabled: !!unplayableReason,
|
|
2848
|
+
title: unplayableReason ?? void 0,
|
|
2849
|
+
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2778
2850
|
}
|
|
2779
2851
|
),
|
|
2780
|
-
shareUrl && /* @__PURE__ */ (0,
|
|
2852
|
+
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2781
2853
|
] }) }),
|
|
2782
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0,
|
|
2783
|
-
/* @__PURE__ */ (0,
|
|
2784
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0,
|
|
2785
|
-
/* @__PURE__ */ (0,
|
|
2854
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_genre_tree28.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2855
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui21.FieldList, { items: fields }),
|
|
2856
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui21.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2857
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2786
2858
|
] });
|
|
2787
2859
|
}
|
|
2788
2860
|
|
|
2789
2861
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2790
|
-
var
|
|
2862
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
2791
2863
|
function useSongPanel({
|
|
2792
2864
|
uuid,
|
|
2793
2865
|
scope,
|
|
@@ -2799,7 +2871,7 @@ function useSongPanel({
|
|
|
2799
2871
|
onClose,
|
|
2800
2872
|
...navigation
|
|
2801
2873
|
}) {
|
|
2802
|
-
const result = (0,
|
|
2874
|
+
const result = (0, import_genre_tree29.useSong)(uuid, getBackendBaseUrl);
|
|
2803
2875
|
const panel = { expanded, onExpandedChange, onClose };
|
|
2804
2876
|
switch (result.status) {
|
|
2805
2877
|
case "idle":
|
|
@@ -2808,24 +2880,24 @@ function useSongPanel({
|
|
|
2808
2880
|
return {
|
|
2809
2881
|
...panel,
|
|
2810
2882
|
title: "Song",
|
|
2811
|
-
content: /* @__PURE__ */ (0,
|
|
2812
|
-
/* @__PURE__ */ (0,
|
|
2813
|
-
/* @__PURE__ */ (0,
|
|
2814
|
-
/* @__PURE__ */ (0,
|
|
2815
|
-
/* @__PURE__ */ (0,
|
|
2883
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2884
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2885
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui22.Skeleton, { className: "h-4 w-32" }),
|
|
2886
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui22.Skeleton, { className: "h-3 w-16" }),
|
|
2887
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui22.Skeleton, { className: "h-4 w-24" })
|
|
2816
2888
|
] })
|
|
2817
2889
|
};
|
|
2818
2890
|
case "not-found":
|
|
2819
2891
|
return {
|
|
2820
2892
|
...panel,
|
|
2821
2893
|
title: "Song not found",
|
|
2822
|
-
content: /* @__PURE__ */ (0,
|
|
2894
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2823
2895
|
};
|
|
2824
2896
|
case "error":
|
|
2825
2897
|
return {
|
|
2826
2898
|
...panel,
|
|
2827
2899
|
title: "Song",
|
|
2828
|
-
content: /* @__PURE__ */ (0,
|
|
2900
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2829
2901
|
};
|
|
2830
2902
|
case "success": {
|
|
2831
2903
|
const { song } = result;
|
|
@@ -2833,7 +2905,7 @@ function useSongPanel({
|
|
|
2833
2905
|
return {
|
|
2834
2906
|
...panel,
|
|
2835
2907
|
title: song.title,
|
|
2836
|
-
content: /* @__PURE__ */ (0,
|
|
2908
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2837
2909
|
SongPanelContent,
|
|
2838
2910
|
{
|
|
2839
2911
|
song,
|
|
@@ -2885,29 +2957,29 @@ function useEntityPanel({
|
|
|
2885
2957
|
|
|
2886
2958
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2887
2959
|
var import_md2 = require("react-icons/md");
|
|
2888
|
-
var
|
|
2889
|
-
var
|
|
2960
|
+
var import_ui23 = require("@behindthemusictree/ui");
|
|
2961
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
2890
2962
|
function SizeMetricToggle({
|
|
2891
2963
|
value,
|
|
2892
2964
|
onChange
|
|
2893
2965
|
}) {
|
|
2894
|
-
return /* @__PURE__ */ (0,
|
|
2895
|
-
|
|
2966
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2967
|
+
import_ui23.SegmentedControl,
|
|
2896
2968
|
{
|
|
2897
2969
|
variant: "floating",
|
|
2898
2970
|
"aria-label": "Size nodes by",
|
|
2899
2971
|
value,
|
|
2900
2972
|
onChange,
|
|
2901
2973
|
options: [
|
|
2902
|
-
{ value: "songs", label: /* @__PURE__ */ (0,
|
|
2903
|
-
{ value: "views", label: /* @__PURE__ */ (0,
|
|
2974
|
+
{ value: "songs", label: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_md2.MdMusicNote, { size: 18, "aria-hidden": true }), "aria-label": "Size by songs", title: "Node size by song count" },
|
|
2975
|
+
{ value: "views", label: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_md2.MdVisibility, { size: 18, "aria-hidden": true }), "aria-label": "Size by views", title: "Node size by song views" }
|
|
2904
2976
|
]
|
|
2905
2977
|
}
|
|
2906
2978
|
);
|
|
2907
2979
|
}
|
|
2908
2980
|
|
|
2909
2981
|
// src/genre-tree/GenreTreeView.tsx
|
|
2910
|
-
var
|
|
2982
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
2911
2983
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2912
2984
|
var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
|
|
2913
2985
|
var noop = () => {
|
|
@@ -2969,21 +3041,21 @@ function GenreTreeView({
|
|
|
2969
3041
|
placement = "default",
|
|
2970
3042
|
...focus
|
|
2971
3043
|
}) {
|
|
2972
|
-
const getShareUrlRef = (0,
|
|
3044
|
+
const getShareUrlRef = (0, import_react19.useRef)(getShareUrl);
|
|
2973
3045
|
getShareUrlRef.current = getShareUrl;
|
|
2974
|
-
const [internalArtistUuid, setInternalArtistUuid] = (0,
|
|
3046
|
+
const [internalArtistUuid, setInternalArtistUuid] = (0, import_react19.useState)(null);
|
|
2975
3047
|
const isArtistControlled = controlledArtistUuid !== void 0;
|
|
2976
3048
|
const artistUuid = isArtistControlled ? controlledArtistUuid : internalArtistUuid;
|
|
2977
|
-
const [internalSongUuid, setInternalSongUuid] = (0,
|
|
3049
|
+
const [internalSongUuid, setInternalSongUuid] = (0, import_react19.useState)(null);
|
|
2978
3050
|
const isSongControlled = controlledSongUuid !== void 0;
|
|
2979
3051
|
const songUuid = isSongControlled ? controlledSongUuid : internalSongUuid;
|
|
2980
3052
|
const changeSong = (uuid) => {
|
|
2981
3053
|
if (!isSongControlled) setInternalSongUuid(uuid);
|
|
2982
3054
|
onSongUuidChange?.(uuid);
|
|
2983
3055
|
};
|
|
2984
|
-
const [internalSizeMetric, setInternalSizeMetric] = (0,
|
|
3056
|
+
const [internalSizeMetric, setInternalSizeMetric] = (0, import_react19.useState)("songs");
|
|
2985
3057
|
const sizeMetric = controlledSizeMetric ?? internalSizeMetric;
|
|
2986
|
-
const deferredSizeMetric = (0,
|
|
3058
|
+
const deferredSizeMetric = (0, import_react19.useDeferredValue)(sizeMetric);
|
|
2987
3059
|
const changeSizeMetric = (metric) => {
|
|
2988
3060
|
if (controlledSizeMetric === void 0) setInternalSizeMetric(metric);
|
|
2989
3061
|
onSizeMetricChange?.(metric);
|
|
@@ -3014,7 +3086,7 @@ function GenreTreeView({
|
|
|
3014
3086
|
allowWheelRotation: internalAllowWheelRotation,
|
|
3015
3087
|
toggleWheelRotation,
|
|
3016
3088
|
onNodeHover: handleNodeHover
|
|
3017
|
-
} = (0,
|
|
3089
|
+
} = (0, import_genre_tree30.useGenreTreeViewState)({
|
|
3018
3090
|
scope,
|
|
3019
3091
|
getBackendBaseUrl,
|
|
3020
3092
|
viewMode: controlledViewMode,
|
|
@@ -3024,7 +3096,7 @@ function GenreTreeView({
|
|
|
3024
3096
|
artistUuid
|
|
3025
3097
|
});
|
|
3026
3098
|
const restoreRevision = viewportRestore?.revision;
|
|
3027
|
-
const [stackedRestoreOwner, setStackedRestoreOwner] = (0,
|
|
3099
|
+
const [stackedRestoreOwner, setStackedRestoreOwner] = (0, import_react19.useState)({ revision: restoreRevision, rootUuid: selectedGenrePlaylist?.root.uuid });
|
|
3028
3100
|
let restoreRootUuid = stackedRestoreOwner.rootUuid;
|
|
3029
3101
|
if (stackedRestoreOwner.revision !== restoreRevision) {
|
|
3030
3102
|
restoreRootUuid = selectedGenrePlaylist?.root.uuid;
|
|
@@ -3033,14 +3105,14 @@ function GenreTreeView({
|
|
|
3033
3105
|
restoreRootUuid = selectedGenrePlaylist.root.uuid;
|
|
3034
3106
|
setStackedRestoreOwner({ revision: restoreRevision, rootUuid: restoreRootUuid });
|
|
3035
3107
|
}
|
|
3036
|
-
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey:
|
|
3037
|
-
const { mutate: updateGenre } = (0,
|
|
3108
|
+
const isGenreUpdating = (0, import_react_query3.useIsMutating)({ mutationKey: import_genre_tree30.genreUpdateMutationKey }) > 0;
|
|
3109
|
+
const { mutate: updateGenre } = (0, import_genre_tree30.useUpdateGenre)(scope, getBackendBaseUrl);
|
|
3038
3110
|
const busy = deferredSizeMetric !== sizeMetric || isTreeFetching || isGenreUpdating;
|
|
3039
3111
|
const isArtistFiltered = artistUuid !== null;
|
|
3040
3112
|
const canSizeByViews = !isArtistFiltered && hasViewsCount(visibleGenrePlaylists);
|
|
3041
|
-
const artistResult = (0,
|
|
3113
|
+
const artistResult = (0, import_genre_tree30.useArtist)(artistUuid, artistSearchBaseUrl ?? getBackendBaseUrl);
|
|
3042
3114
|
const filterArtistName = artistResult.status === "success" ? artistResult.artist.name : null;
|
|
3043
|
-
const filterArtist = (0,
|
|
3115
|
+
const filterArtist = (0, import_react19.useMemo)(
|
|
3044
3116
|
() => artistUuid !== null && filterArtistName !== null ? { uuid: artistUuid, name: filterArtistName } : null,
|
|
3045
3117
|
[artistUuid, filterArtistName]
|
|
3046
3118
|
);
|
|
@@ -3055,17 +3127,17 @@ function GenreTreeView({
|
|
|
3055
3127
|
if (selectedGenreUuid !== null) clearSelection();
|
|
3056
3128
|
changeSong(uuid);
|
|
3057
3129
|
};
|
|
3058
|
-
const openSongRef = (0,
|
|
3130
|
+
const openSongRef = (0, import_react19.useRef)(openSong);
|
|
3059
3131
|
openSongRef.current = openSong;
|
|
3060
|
-
const resolvedRenderSongLink = (0,
|
|
3061
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0,
|
|
3132
|
+
const resolvedRenderSongLink = (0, import_react19.useCallback)(
|
|
3133
|
+
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
|
|
3062
3134
|
[renderSongLink]
|
|
3063
3135
|
);
|
|
3064
|
-
const [expandedSongUuid, setExpandedSongUuid] = (0,
|
|
3065
|
-
const [expandedArtistUuid, setExpandedArtistUuid] = (0,
|
|
3136
|
+
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react19.useState)(null);
|
|
3137
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react19.useState)(null);
|
|
3066
3138
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
3067
3139
|
const songBaseUrl = getBackendBaseUrl;
|
|
3068
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
3140
|
+
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
3069
3141
|
const getGenrePath = (genre) => {
|
|
3070
3142
|
const path = [];
|
|
3071
3143
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -3108,8 +3180,8 @@ function GenreTreeView({
|
|
|
3108
3180
|
}
|
|
3109
3181
|
});
|
|
3110
3182
|
const builtInPanel = overlayPanel || selectedGenreUuid !== null ? void 0 : entityPanel;
|
|
3111
|
-
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0,
|
|
3112
|
-
const [uncontrolledExpanded, setUncontrolledExpanded] = (0,
|
|
3183
|
+
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react19.useState)(false);
|
|
3184
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react19.useState)(false);
|
|
3113
3185
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
3114
3186
|
const isExpanded = expanded ?? uncontrolledExpanded;
|
|
3115
3187
|
const changeCollapsed = (next) => {
|
|
@@ -3120,28 +3192,28 @@ function GenreTreeView({
|
|
|
3120
3192
|
setUncontrolledExpanded(next);
|
|
3121
3193
|
onExpandedChange?.(next);
|
|
3122
3194
|
};
|
|
3123
|
-
(0,
|
|
3195
|
+
(0, import_react19.useEffect)(() => {
|
|
3124
3196
|
setUncontrolledCollapsed(false);
|
|
3125
3197
|
}, [selectedGenreUuid, artistUuid, songUuid]);
|
|
3126
|
-
const [isWheelRevealed, setIsWheelRevealed] = (0,
|
|
3198
|
+
const [isWheelRevealed, setIsWheelRevealed] = (0, import_react19.useState)(false);
|
|
3127
3199
|
const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
|
|
3128
3200
|
const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
|
|
3129
|
-
const [resolveStyle, setResolveStyle] = (0,
|
|
3130
|
-
const handleNodeStyleResolverChange = (0,
|
|
3201
|
+
const [resolveStyle, setResolveStyle] = (0, import_react19.useState)(null);
|
|
3202
|
+
const handleNodeStyleResolverChange = (0, import_react19.useCallback)(
|
|
3131
3203
|
(resolver) => setResolveStyle(() => resolver),
|
|
3132
3204
|
[]
|
|
3133
3205
|
);
|
|
3134
|
-
const panelRef = (0,
|
|
3135
|
-
const obscuredInset = (0,
|
|
3206
|
+
const panelRef = (0, import_react19.useRef)(null);
|
|
3207
|
+
const obscuredInset = (0, import_ui24.useObscuredInset)(panelRef);
|
|
3136
3208
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
3137
3209
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
3138
|
-
const treeNodes = (0,
|
|
3210
|
+
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric), [visibleGenrePlaylists, nodeMetric]);
|
|
3139
3211
|
const relations = (0, import_genre_tree_view5.useGenreNodeRelations)(
|
|
3140
3212
|
treeNodes,
|
|
3141
3213
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
3142
3214
|
resolveStyle
|
|
3143
3215
|
);
|
|
3144
|
-
const [selectionHistory, setSelectionHistory] = (0,
|
|
3216
|
+
const [selectionHistory, setSelectionHistory] = (0, import_react19.useState)({ current: selectedGenreUuid, previous: null });
|
|
3145
3217
|
if (selectionHistory.current !== selectedGenreUuid) {
|
|
3146
3218
|
setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
3147
3219
|
}
|
|
@@ -3167,7 +3239,7 @@ function GenreTreeView({
|
|
|
3167
3239
|
const handleGenreSearchZoomIn = () => {
|
|
3168
3240
|
if (selectedUuid) focus.onFocusGenreChange?.(selectedUuid, "zoom-in");
|
|
3169
3241
|
};
|
|
3170
|
-
const zoomInRef = (0,
|
|
3242
|
+
const zoomInRef = (0, import_react19.useRef)(void 0);
|
|
3171
3243
|
zoomInRef.current = canZoomIn ? handleGenreSearchZoomIn : void 0;
|
|
3172
3244
|
const genrePlaylist = selectedGenrePlaylist;
|
|
3173
3245
|
const criteria = genrePlaylist?.criteria;
|
|
@@ -3186,6 +3258,7 @@ function GenreTreeView({
|
|
|
3186
3258
|
selectGenre(uuid);
|
|
3187
3259
|
},
|
|
3188
3260
|
expanded: isExpanded,
|
|
3261
|
+
treeRelations: relations,
|
|
3189
3262
|
playback,
|
|
3190
3263
|
genrePlaylist: selectedGenrePlaylist,
|
|
3191
3264
|
band: {
|
|
@@ -3196,7 +3269,7 @@ function GenreTreeView({
|
|
|
3196
3269
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
3197
3270
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
3198
3271
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
3199
|
-
/* @__PURE__ */ (0,
|
|
3272
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3200
3273
|
ChangeParentPopup,
|
|
3201
3274
|
{
|
|
3202
3275
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -3249,7 +3322,7 @@ function GenreTreeView({
|
|
|
3249
3322
|
onExpandedChange: changeExpanded,
|
|
3250
3323
|
onClose: clearSelection,
|
|
3251
3324
|
titleInSearch: true,
|
|
3252
|
-
headerAccent:
|
|
3325
|
+
headerAccent: genreContent.headerAccent
|
|
3253
3326
|
};
|
|
3254
3327
|
} else if (builtInPanel) {
|
|
3255
3328
|
activePanel = {
|
|
@@ -3267,19 +3340,19 @@ function GenreTreeView({
|
|
|
3267
3340
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
3268
3341
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
3269
3342
|
} : void 0;
|
|
3270
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0,
|
|
3271
|
-
|
|
3343
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3344
|
+
import_ui24.IconButton,
|
|
3272
3345
|
{
|
|
3273
3346
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
3274
3347
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
3275
3348
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
3276
|
-
children: activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3349
|
+
children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_lucide_react19.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_lucide_react19.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3277
3350
|
}
|
|
3278
3351
|
) : null;
|
|
3279
3352
|
const renderArtistFilter = () => {
|
|
3280
3353
|
if (isLoading || !filterArtist) return null;
|
|
3281
|
-
return /* @__PURE__ */ (0,
|
|
3282
|
-
/* @__PURE__ */ (0,
|
|
3354
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
3355
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3283
3356
|
"button",
|
|
3284
3357
|
{
|
|
3285
3358
|
type: "button",
|
|
@@ -3291,7 +3364,7 @@ function GenreTreeView({
|
|
|
3291
3364
|
children: filterArtist.name
|
|
3292
3365
|
}
|
|
3293
3366
|
),
|
|
3294
|
-
/* @__PURE__ */ (0,
|
|
3367
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3295
3368
|
"button",
|
|
3296
3369
|
{
|
|
3297
3370
|
type: "button",
|
|
@@ -3303,8 +3376,8 @@ function GenreTreeView({
|
|
|
3303
3376
|
)
|
|
3304
3377
|
] });
|
|
3305
3378
|
};
|
|
3306
|
-
const actions = /* @__PURE__ */ (0,
|
|
3307
|
-
!isLoading && !isError && /* @__PURE__ */ (0,
|
|
3379
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
3380
|
+
!isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3308
3381
|
GenreTreeSearch,
|
|
3309
3382
|
{
|
|
3310
3383
|
artistBaseUrl,
|
|
@@ -3337,10 +3410,10 @@ function GenreTreeView({
|
|
|
3337
3410
|
extraGroups: extraSearchGroups
|
|
3338
3411
|
}
|
|
3339
3412
|
),
|
|
3340
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3341
|
-
/* @__PURE__ */ (0,
|
|
3342
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0,
|
|
3343
|
-
|
|
3413
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3414
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.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: [
|
|
3415
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3416
|
+
import_ui24.SegmentedControl,
|
|
3344
3417
|
{
|
|
3345
3418
|
"aria-label": "Tree view mode",
|
|
3346
3419
|
value: viewMode,
|
|
@@ -3353,14 +3426,14 @@ function GenreTreeView({
|
|
|
3353
3426
|
]
|
|
3354
3427
|
}
|
|
3355
3428
|
),
|
|
3356
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0,
|
|
3429
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3357
3430
|
"div",
|
|
3358
3431
|
{
|
|
3359
3432
|
className: "flex items-center gap-1",
|
|
3360
3433
|
role: "group",
|
|
3361
3434
|
"aria-label": "Tree display options",
|
|
3362
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0,
|
|
3363
|
-
|
|
3435
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3436
|
+
import_ui24.Button,
|
|
3364
3437
|
{
|
|
3365
3438
|
variant: allowWheelRotation ? "default" : "outline",
|
|
3366
3439
|
size: "sm",
|
|
@@ -3370,48 +3443,48 @@ function GenreTreeView({
|
|
|
3370
3443
|
)
|
|
3371
3444
|
}
|
|
3372
3445
|
),
|
|
3373
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0,
|
|
3374
|
-
|
|
3446
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3447
|
+
import_ui24.IconTextButton,
|
|
3375
3448
|
{
|
|
3376
|
-
icon:
|
|
3449
|
+
icon: import_lucide_react18.Plus,
|
|
3377
3450
|
text: "Add root",
|
|
3378
3451
|
onClick: () => handleGenreCreationAction(null)
|
|
3379
3452
|
}
|
|
3380
3453
|
)
|
|
3381
3454
|
] })
|
|
3382
3455
|
] });
|
|
3383
|
-
return /* @__PURE__ */ (0,
|
|
3456
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(
|
|
3384
3457
|
"div",
|
|
3385
3458
|
{
|
|
3386
3459
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
3387
3460
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
3388
3461
|
children: [
|
|
3389
|
-
/* @__PURE__ */ (0,
|
|
3462
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3390
3463
|
"div",
|
|
3391
3464
|
{
|
|
3392
|
-
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"}`,
|
|
3465
|
+
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"}`,
|
|
3393
3466
|
children: actions
|
|
3394
3467
|
}
|
|
3395
3468
|
),
|
|
3396
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3469
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3397
3470
|
"div",
|
|
3398
3471
|
{
|
|
3399
|
-
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"}`,
|
|
3472
|
+
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"}`,
|
|
3400
3473
|
children: renderArtistFilter()
|
|
3401
3474
|
}
|
|
3402
3475
|
),
|
|
3403
|
-
/* @__PURE__ */ (0,
|
|
3404
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0,
|
|
3405
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3476
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
3477
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
3478
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
|
|
3406
3479
|
"Couldn't load the genre tree.",
|
|
3407
3480
|
" ",
|
|
3408
|
-
/* @__PURE__ */ (0,
|
|
3481
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
3409
3482
|
] }) : viewMode === "wheel" ? (
|
|
3410
3483
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
3411
3484
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
3412
3485
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
3413
3486
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
3414
|
-
/* @__PURE__ */ (0,
|
|
3487
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3415
3488
|
GenrePlaylistTreeWheel,
|
|
3416
3489
|
{
|
|
3417
3490
|
scope,
|
|
@@ -3428,9 +3501,9 @@ function GenreTreeView({
|
|
|
3428
3501
|
allowWheelRotation,
|
|
3429
3502
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3430
3503
|
busy,
|
|
3431
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3504
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3432
3505
|
floatingControlsLeading,
|
|
3433
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3506
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3434
3507
|
] }) : void 0,
|
|
3435
3508
|
defaultViewport,
|
|
3436
3509
|
viewportRestore,
|
|
@@ -3439,7 +3512,7 @@ function GenreTreeView({
|
|
|
3439
3512
|
) }) })
|
|
3440
3513
|
) : viewMode === "pop-core" ? (
|
|
3441
3514
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
3442
|
-
/* @__PURE__ */ (0,
|
|
3515
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3443
3516
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3444
3517
|
{
|
|
3445
3518
|
scope,
|
|
@@ -3456,9 +3529,9 @@ function GenreTreeView({
|
|
|
3456
3529
|
allowWheelRotation,
|
|
3457
3530
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3458
3531
|
busy,
|
|
3459
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3532
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3460
3533
|
floatingControlsLeading,
|
|
3461
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3534
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3462
3535
|
] }) : void 0,
|
|
3463
3536
|
defaultViewport,
|
|
3464
3537
|
viewportRestore,
|
|
@@ -3466,7 +3539,7 @@ function GenreTreeView({
|
|
|
3466
3539
|
...focus
|
|
3467
3540
|
}
|
|
3468
3541
|
) }) })
|
|
3469
|
-
) : viewMode === "outline" ? /* @__PURE__ */ (0,
|
|
3542
|
+
) : viewMode === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "tree-container flex-1 min-h-0 w-full overflow-y-auto relative", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3470
3543
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3471
3544
|
{
|
|
3472
3545
|
outline: true,
|
|
@@ -3482,13 +3555,13 @@ function GenreTreeView({
|
|
|
3482
3555
|
selectedNodeId,
|
|
3483
3556
|
readOnly
|
|
3484
3557
|
}
|
|
3485
|
-
) }) : /* @__PURE__ */ (0,
|
|
3558
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime50.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(
|
|
3486
3559
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
3487
|
-
return /* @__PURE__ */ (0,
|
|
3560
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3488
3561
|
"div",
|
|
3489
3562
|
{
|
|
3490
3563
|
className: "tree-per-root-container relative shrink-0 h-[28rem] mt-2 mr-16 p-2 bg-[var(--color-neutral-100)] rounded-lg",
|
|
3491
|
-
children: /* @__PURE__ */ (0,
|
|
3564
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3492
3565
|
GenrePlaylistTreePerRoot,
|
|
3493
3566
|
{
|
|
3494
3567
|
scope,
|
|
@@ -3514,8 +3587,8 @@ function GenreTreeView({
|
|
|
3514
3587
|
);
|
|
3515
3588
|
}
|
|
3516
3589
|
) }),
|
|
3517
|
-
/* @__PURE__ */ (0,
|
|
3518
|
-
|
|
3590
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3591
|
+
import_ui24.DetailPanel,
|
|
3519
3592
|
{
|
|
3520
3593
|
ref: panelRef,
|
|
3521
3594
|
side: "left",
|
|
@@ -3529,8 +3602,8 @@ function GenreTreeView({
|
|
|
3529
3602
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3530
3603
|
aside: activePanel?.aside,
|
|
3531
3604
|
edgeTab: detailTab,
|
|
3532
|
-
headerClassName: activePanel?.titleInSearch ? void 0 : "pt-
|
|
3533
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3605
|
+
headerClassName: activePanel?.titleInSearch ? void 0 : "pt-search-clear",
|
|
3606
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
3534
3607
|
activePanel.content,
|
|
3535
3608
|
activePanel.aside
|
|
3536
3609
|
] }) : activePanel?.content
|
|
@@ -3546,13 +3619,13 @@ function GenreTreeView({
|
|
|
3546
3619
|
var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
|
|
3547
3620
|
|
|
3548
3621
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3549
|
-
var
|
|
3550
|
-
var
|
|
3551
|
-
var
|
|
3552
|
-
var
|
|
3553
|
-
var
|
|
3554
|
-
var
|
|
3555
|
-
var useBrowserLayoutEffect = typeof window === "undefined" ?
|
|
3622
|
+
var import_react20 = require("react");
|
|
3623
|
+
var import_lucide_react20 = require("lucide-react");
|
|
3624
|
+
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3625
|
+
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3626
|
+
var import_track_noun4 = require("@behindthemusictree/app-kit/track-noun");
|
|
3627
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3628
|
+
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react20.useEffect : import_react20.useLayoutEffect;
|
|
3556
3629
|
function TrackListSidebar({
|
|
3557
3630
|
className: className2 = "",
|
|
3558
3631
|
renderDuration,
|
|
@@ -3564,18 +3637,18 @@ function TrackListSidebar({
|
|
|
3564
3637
|
renderArtistLink,
|
|
3565
3638
|
renderSongLink
|
|
3566
3639
|
}) {
|
|
3567
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } = (0,
|
|
3568
|
-
const trackNoun = (0,
|
|
3569
|
-
const trackListRef = (0,
|
|
3570
|
-
const previousOriginRef = (0,
|
|
3571
|
-
const handledAutoAdvanceRequestIdRef = (0,
|
|
3572
|
-
const shouldFollowPlaybackRef = (0,
|
|
3573
|
-
const programmaticScrollTopRef = (0,
|
|
3574
|
-
const userScrollIntentRef = (0,
|
|
3575
|
-
const userScrollIntentTimerRef = (0,
|
|
3576
|
-
const loadMoreSentinelRef = (0,
|
|
3640
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = (0, import_genre_tree31.useTrackList)();
|
|
3641
|
+
const trackNoun = (0, import_track_noun4.useTrackNoun)();
|
|
3642
|
+
const trackListRef = (0, import_react20.useRef)(null);
|
|
3643
|
+
const previousOriginRef = (0, import_react20.useRef)(trackList?.origin ?? null);
|
|
3644
|
+
const handledAutoAdvanceRequestIdRef = (0, import_react20.useRef)(null);
|
|
3645
|
+
const shouldFollowPlaybackRef = (0, import_react20.useRef)(true);
|
|
3646
|
+
const programmaticScrollTopRef = (0, import_react20.useRef)(null);
|
|
3647
|
+
const userScrollIntentRef = (0, import_react20.useRef)(false);
|
|
3648
|
+
const userScrollIntentTimerRef = (0, import_react20.useRef)(null);
|
|
3649
|
+
const loadMoreSentinelRef = (0, import_react20.useRef)(null);
|
|
3577
3650
|
const hasMore = !!trackList && trackList.nextPage !== null;
|
|
3578
|
-
(0,
|
|
3651
|
+
(0, import_react20.useEffect)(() => {
|
|
3579
3652
|
const sentinel = loadMoreSentinelRef.current;
|
|
3580
3653
|
if (!hasMore || !sentinel) return;
|
|
3581
3654
|
const observer = new IntersectionObserver((entries) => {
|
|
@@ -3595,11 +3668,11 @@ function TrackListSidebar({
|
|
|
3595
3668
|
programmaticScrollTopRef.current = null;
|
|
3596
3669
|
if (trackListRef.current) trackListRef.current.scrollTop = 0;
|
|
3597
3670
|
}, [trackList?.origin]);
|
|
3598
|
-
(0,
|
|
3671
|
+
(0, import_react20.useEffect)(() => {
|
|
3599
3672
|
const list = trackListRef.current;
|
|
3600
3673
|
if (!isCollapsed && list?.scrollTop === 0) shouldFollowPlaybackRef.current = true;
|
|
3601
3674
|
}, [isCollapsed]);
|
|
3602
|
-
(0,
|
|
3675
|
+
(0, import_react20.useEffect)(
|
|
3603
3676
|
() => () => {
|
|
3604
3677
|
if (userScrollIntentTimerRef.current !== null) clearTimeout(userScrollIntentTimerRef.current);
|
|
3605
3678
|
},
|
|
@@ -3653,25 +3726,25 @@ function TrackListSidebar({
|
|
|
3653
3726
|
}
|
|
3654
3727
|
};
|
|
3655
3728
|
const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
|
|
3656
|
-
return trackList ? /* @__PURE__ */ (0,
|
|
3729
|
+
return trackList ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
3657
3730
|
"div",
|
|
3658
3731
|
{
|
|
3659
3732
|
"data-theme": "dark",
|
|
3660
3733
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3661
3734
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3662
3735
|
children: [
|
|
3663
|
-
/* @__PURE__ */ (0,
|
|
3664
|
-
/* @__PURE__ */ (0,
|
|
3665
|
-
/* @__PURE__ */ (0,
|
|
3666
|
-
/* @__PURE__ */ (0,
|
|
3667
|
-
/* @__PURE__ */ (0,
|
|
3736
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3737
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3738
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "origin flex text-xl", children: [
|
|
3739
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3740
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.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_runtime51.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3668
3741
|
] }),
|
|
3669
|
-
/* @__PURE__ */ (0,
|
|
3670
|
-
trackList.origin.type ===
|
|
3742
|
+
/* @__PURE__ */ (0, import_jsx_runtime51.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3743
|
+
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 `,
|
|
3671
3744
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3672
3745
|
] })
|
|
3673
3746
|
] }),
|
|
3674
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0,
|
|
3747
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3675
3748
|
"button",
|
|
3676
3749
|
{
|
|
3677
3750
|
type: "button",
|
|
@@ -3680,11 +3753,11 @@ function TrackListSidebar({
|
|
|
3680
3753
|
"aria-expanded": !isCollapsed,
|
|
3681
3754
|
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"}`,
|
|
3682
3755
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3683
|
-
children: /* @__PURE__ */ (0,
|
|
3756
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(import_lucide_react20.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3684
3757
|
}
|
|
3685
3758
|
)
|
|
3686
3759
|
] }),
|
|
3687
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
3760
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(
|
|
3688
3761
|
"ul",
|
|
3689
3762
|
{
|
|
3690
3763
|
ref: trackListRef,
|
|
@@ -3694,7 +3767,7 @@ function TrackListSidebar({
|
|
|
3694
3767
|
onPointerDown: markUserScrollIntent,
|
|
3695
3768
|
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",
|
|
3696
3769
|
children: [
|
|
3697
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */ (0,
|
|
3770
|
+
trackList.tracks.map((track, index) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("li", { "data-track-uuid": track.uuid, children: /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
3698
3771
|
TrackItem,
|
|
3699
3772
|
{
|
|
3700
3773
|
track,
|
|
@@ -3705,7 +3778,7 @@ function TrackListSidebar({
|
|
|
3705
3778
|
renderSongLink
|
|
3706
3779
|
}
|
|
3707
3780
|
) }, track.uuid)),
|
|
3708
|
-
hasMore && /* @__PURE__ */ (0,
|
|
3781
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3709
3782
|
]
|
|
3710
3783
|
}
|
|
3711
3784
|
)
|
|
@@ -3715,17 +3788,17 @@ function TrackListSidebar({
|
|
|
3715
3788
|
}
|
|
3716
3789
|
|
|
3717
3790
|
// src/genre-tree/PlayerPanel.tsx
|
|
3718
|
-
var
|
|
3791
|
+
var import_react21 = require("react");
|
|
3719
3792
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3720
|
-
var
|
|
3721
|
-
var
|
|
3722
|
-
var
|
|
3793
|
+
var import_player14 = require("@behindthemusictree/app-kit/player");
|
|
3794
|
+
var import_genre_tree34 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3795
|
+
var import_ui25 = require("@behindthemusictree/ui");
|
|
3723
3796
|
|
|
3724
3797
|
// src/genre-tree/PlayerControls.tsx
|
|
3725
|
-
var
|
|
3726
|
-
var
|
|
3727
|
-
var
|
|
3728
|
-
var
|
|
3798
|
+
var import_lucide_react21 = require("lucide-react");
|
|
3799
|
+
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3800
|
+
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3801
|
+
var import_jsx_runtime52 = require("react/jsx-runtime");
|
|
3729
3802
|
function PlayerControls() {
|
|
3730
3803
|
const {
|
|
3731
3804
|
duration,
|
|
@@ -3736,23 +3809,23 @@ function PlayerControls() {
|
|
|
3736
3809
|
seekTo,
|
|
3737
3810
|
setVolume,
|
|
3738
3811
|
volume
|
|
3739
|
-
} = (0,
|
|
3740
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0,
|
|
3741
|
-
const currentTime = (0,
|
|
3742
|
-
const isBusy = isLoading || playState ===
|
|
3812
|
+
} = (0, import_player13.usePlayer)();
|
|
3813
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = (0, import_genre_tree33.useTrackList)();
|
|
3814
|
+
const currentTime = (0, import_player13.useCurrentTime)();
|
|
3815
|
+
const isBusy = isLoading || playState === import_player13.PlayStates.LOADING;
|
|
3743
3816
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
3744
3817
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3745
3818
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3746
|
-
const isPlaying = playState ===
|
|
3747
|
-
return /* @__PURE__ */ (0,
|
|
3819
|
+
const isPlaying = playState === import_player13.PlayStates.PLAYING;
|
|
3820
|
+
return /* @__PURE__ */ (0, import_jsx_runtime52.jsxs)(
|
|
3748
3821
|
"section",
|
|
3749
3822
|
{
|
|
3750
3823
|
"aria-label": "Player controls",
|
|
3751
3824
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3752
3825
|
children: [
|
|
3753
|
-
/* @__PURE__ */ (0,
|
|
3754
|
-
/* @__PURE__ */ (0,
|
|
3755
|
-
/* @__PURE__ */ (0,
|
|
3826
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3827
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree33.formatTime)(safeCurrentTime) }),
|
|
3828
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3756
3829
|
"input",
|
|
3757
3830
|
{
|
|
3758
3831
|
"aria-label": "Seek",
|
|
@@ -3766,11 +3839,11 @@ function PlayerControls() {
|
|
|
3766
3839
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3767
3840
|
}
|
|
3768
3841
|
),
|
|
3769
|
-
/* @__PURE__ */ (0,
|
|
3842
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree33.formatTime)(safeDuration) })
|
|
3770
3843
|
] }),
|
|
3771
|
-
/* @__PURE__ */ (0,
|
|
3772
|
-
/* @__PURE__ */ (0,
|
|
3773
|
-
/* @__PURE__ */ (0,
|
|
3844
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3845
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3846
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3774
3847
|
"button",
|
|
3775
3848
|
{
|
|
3776
3849
|
type: "button",
|
|
@@ -3779,10 +3852,10 @@ function PlayerControls() {
|
|
|
3779
3852
|
disabled: !isReady || !hasPreviousTrack,
|
|
3780
3853
|
onClick: playPreviousTrack,
|
|
3781
3854
|
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",
|
|
3782
|
-
children: /* @__PURE__ */ (0,
|
|
3855
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react21.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3783
3856
|
}
|
|
3784
3857
|
),
|
|
3785
|
-
/* @__PURE__ */ (0,
|
|
3858
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3786
3859
|
"button",
|
|
3787
3860
|
{
|
|
3788
3861
|
type: "button",
|
|
@@ -3791,10 +3864,10 @@ function PlayerControls() {
|
|
|
3791
3864
|
disabled: !isReady,
|
|
3792
3865
|
onClick: handlePlayPauseAction,
|
|
3793
3866
|
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",
|
|
3794
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3867
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react21.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react21.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3795
3868
|
}
|
|
3796
3869
|
),
|
|
3797
|
-
/* @__PURE__ */ (0,
|
|
3870
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3798
3871
|
"button",
|
|
3799
3872
|
{
|
|
3800
3873
|
type: "button",
|
|
@@ -3803,14 +3876,14 @@ function PlayerControls() {
|
|
|
3803
3876
|
disabled: !isReady || !hasNextTrack,
|
|
3804
3877
|
onClick: playNextTrack,
|
|
3805
3878
|
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",
|
|
3806
|
-
children: /* @__PURE__ */ (0,
|
|
3879
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react21.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3807
3880
|
}
|
|
3808
3881
|
)
|
|
3809
3882
|
] }),
|
|
3810
|
-
/* @__PURE__ */ (0,
|
|
3811
|
-
volume === 0 ? /* @__PURE__ */ (0,
|
|
3812
|
-
/* @__PURE__ */ (0,
|
|
3813
|
-
/* @__PURE__ */ (0,
|
|
3883
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.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: [
|
|
3884
|
+
volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react21.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(import_lucide_react21.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3885
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)("span", { className: "sr-only", children: "Volume" }),
|
|
3886
|
+
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3814
3887
|
"input",
|
|
3815
3888
|
{
|
|
3816
3889
|
"aria-label": "Volume",
|
|
@@ -3832,7 +3905,7 @@ function PlayerControls() {
|
|
|
3832
3905
|
}
|
|
3833
3906
|
|
|
3834
3907
|
// src/genre-tree/PlayerPanel.tsx
|
|
3835
|
-
var
|
|
3908
|
+
var import_jsx_runtime53 = require("react/jsx-runtime");
|
|
3836
3909
|
var PANEL_ID = "player-panel";
|
|
3837
3910
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3838
3911
|
function PlayerPanel({
|
|
@@ -3844,14 +3917,14 @@ function PlayerPanel({
|
|
|
3844
3917
|
renderArtistLink,
|
|
3845
3918
|
renderSongLink
|
|
3846
3919
|
}) {
|
|
3847
|
-
const { playerTrackObject, retryPlayback } = (0,
|
|
3848
|
-
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0,
|
|
3849
|
-
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0,
|
|
3920
|
+
const { playerTrackObject, retryPlayback } = (0, import_player14.usePlayer)();
|
|
3921
|
+
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree34.useTrackListSidebarVisibility)();
|
|
3922
|
+
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react21.useState)("");
|
|
3850
3923
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3851
|
-
(0,
|
|
3924
|
+
(0, import_react21.useEffect)(() => {
|
|
3852
3925
|
if (loadedTrackTitle) setLastLoadedTrackTitle(loadedTrackTitle);
|
|
3853
3926
|
}, [loadedTrackTitle]);
|
|
3854
|
-
const [uncontrolledExtended, setUncontrolledExtended] = (0,
|
|
3927
|
+
const [uncontrolledExtended, setUncontrolledExtended] = (0, import_react21.useState)(false);
|
|
3855
3928
|
const isExtendRequested = expanded ?? uncontrolledExtended;
|
|
3856
3929
|
const setIsExtendRequested = (next) => {
|
|
3857
3930
|
setUncontrolledExtended(next);
|
|
@@ -3872,7 +3945,7 @@ function PlayerPanel({
|
|
|
3872
3945
|
onClick: () => setIsExtendRequested(true),
|
|
3873
3946
|
expanded: false
|
|
3874
3947
|
} : null;
|
|
3875
|
-
return /* @__PURE__ */ (0,
|
|
3948
|
+
return /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3876
3949
|
"div",
|
|
3877
3950
|
{
|
|
3878
3951
|
id: PANEL_ID,
|
|
@@ -3885,8 +3958,8 @@ function PlayerPanel({
|
|
|
3885
3958
|
),
|
|
3886
3959
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3887
3960
|
children: [
|
|
3888
|
-
/* @__PURE__ */ (0,
|
|
3889
|
-
|
|
3961
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3962
|
+
import_ui25.PanelEdgeTab,
|
|
3890
3963
|
{
|
|
3891
3964
|
side: "right",
|
|
3892
3965
|
edge: tabEdge,
|
|
@@ -3895,7 +3968,7 @@ function PlayerPanel({
|
|
|
3895
3968
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3896
3969
|
}
|
|
3897
3970
|
),
|
|
3898
|
-
/* @__PURE__ */ (0,
|
|
3971
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)(
|
|
3899
3972
|
"div",
|
|
3900
3973
|
{
|
|
3901
3974
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -3903,20 +3976,20 @@ function PlayerPanel({
|
|
|
3903
3976
|
isExtended ? "flex-row" : "flex-col"
|
|
3904
3977
|
),
|
|
3905
3978
|
children: [
|
|
3906
|
-
/* @__PURE__ */ (0,
|
|
3907
|
-
/* @__PURE__ */ (0,
|
|
3908
|
-
/* @__PURE__ */ (0,
|
|
3909
|
-
/* @__PURE__ */ (0,
|
|
3910
|
-
playerTrackObject?.loadError && /* @__PURE__ */ (0,
|
|
3979
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3980
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ (0, import_jsx_runtime53.jsx)("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
|
|
3981
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
3982
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3983
|
+
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime53.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3911
3984
|
playerTrackObject.loadError,
|
|
3912
|
-
/* @__PURE__ */ (0,
|
|
3985
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3913
3986
|
void retryPlayback();
|
|
3914
3987
|
}, children: "Retry" })
|
|
3915
3988
|
] })
|
|
3916
3989
|
] }),
|
|
3917
|
-
/* @__PURE__ */ (0,
|
|
3990
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(PlayerControls, {})
|
|
3918
3991
|
] }),
|
|
3919
|
-
/* @__PURE__ */ (0,
|
|
3992
|
+
/* @__PURE__ */ (0, import_jsx_runtime53.jsx)(
|
|
3920
3993
|
TrackListSidebar,
|
|
3921
3994
|
{
|
|
3922
3995
|
layout: "inline",
|
|
@@ -3942,33 +4015,33 @@ function PlayerPanel({
|
|
|
3942
4015
|
// src/genre-tree/Rating.tsx
|
|
3943
4016
|
var import_uuid = require("uuid");
|
|
3944
4017
|
var import_ai = require("react-icons/ai");
|
|
3945
|
-
var
|
|
3946
|
-
var
|
|
4018
|
+
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
4019
|
+
var import_jsx_runtime54 = require("react/jsx-runtime");
|
|
3947
4020
|
function Rating({ rating, handleChange }) {
|
|
3948
4021
|
const instanceId = (0, import_uuid.v4)();
|
|
3949
|
-
return /* @__PURE__ */ (0,
|
|
3950
|
-
/* @__PURE__ */ (0,
|
|
4022
|
+
return /* @__PURE__ */ (0, import_jsx_runtime54.jsx)("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
|
|
4023
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3951
4024
|
"input",
|
|
3952
4025
|
{
|
|
3953
4026
|
id: `star-${instanceId}-${i}`,
|
|
3954
4027
|
className: "w-6 h-6 opacity-0",
|
|
3955
4028
|
type: "radio",
|
|
3956
4029
|
name: "rating",
|
|
3957
|
-
value: i === 0 ?
|
|
4030
|
+
value: i === 0 ? import_genre_tree35.FORM_RATING_NULL_VALUE : i,
|
|
3958
4031
|
checked: rating === (i === 0 ? null : i),
|
|
3959
4032
|
onChange: handleChange
|
|
3960
4033
|
}
|
|
3961
4034
|
),
|
|
3962
|
-
/* @__PURE__ */ (0,
|
|
3963
|
-
/* @__PURE__ */ (0,
|
|
4035
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime54.jsxs)("div", { className: "flex", children: [
|
|
4036
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3964
4037
|
import_ai.AiOutlineStar,
|
|
3965
4038
|
{
|
|
3966
|
-
className: `w-7 h-7 absolute top-0 left-0 ${rating ===
|
|
4039
|
+
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)]"}`
|
|
3967
4040
|
}
|
|
3968
4041
|
),
|
|
3969
|
-
/* @__PURE__ */ (0,
|
|
4042
|
+
/* @__PURE__ */ (0, import_jsx_runtime54.jsx)("span", { className: "flex-grow w-8" }),
|
|
3970
4043
|
" "
|
|
3971
|
-
] }) : /* @__PURE__ */ (0,
|
|
4044
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime54.jsx)(
|
|
3972
4045
|
import_ai.AiFillStar,
|
|
3973
4046
|
{
|
|
3974
4047
|
className: `w-7 h-7 absolute top-0 left-0 ${(rating ?? -1) >= i ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
@@ -3978,9 +4051,9 @@ function Rating({ rating, handleChange }) {
|
|
|
3978
4051
|
}
|
|
3979
4052
|
|
|
3980
4053
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
3981
|
-
var
|
|
3982
|
-
var
|
|
3983
|
-
var
|
|
4054
|
+
var import_react22 = require("react");
|
|
4055
|
+
var import_ui26 = require("@behindthemusictree/ui");
|
|
4056
|
+
var import_jsx_runtime55 = require("react/jsx-runtime");
|
|
3984
4057
|
function EntityDetailPanel({
|
|
3985
4058
|
scope,
|
|
3986
4059
|
getBackendBaseUrl,
|
|
@@ -3996,15 +4069,15 @@ function EntityDetailPanel({
|
|
|
3996
4069
|
edgeTab,
|
|
3997
4070
|
...navigation
|
|
3998
4071
|
}) {
|
|
3999
|
-
const [expandedSongUuid, setExpandedSongUuid] = (0,
|
|
4000
|
-
const [expandedArtistUuid, setExpandedArtistUuid] = (0,
|
|
4072
|
+
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react22.useState)(null);
|
|
4073
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react22.useState)(null);
|
|
4001
4074
|
const panel = useEntityPanel({
|
|
4002
4075
|
scope,
|
|
4003
4076
|
getBackendBaseUrl,
|
|
4004
4077
|
getArtistBackendBaseUrl,
|
|
4005
4078
|
getShareUrl,
|
|
4006
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
4007
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0,
|
|
4079
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
4080
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime55.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
4008
4081
|
song: {
|
|
4009
4082
|
uuid: songUuid,
|
|
4010
4083
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -4020,8 +4093,8 @@ function EntityDetailPanel({
|
|
|
4020
4093
|
...navigation
|
|
4021
4094
|
});
|
|
4022
4095
|
if (!panel) return null;
|
|
4023
|
-
return /* @__PURE__ */ (0,
|
|
4024
|
-
|
|
4096
|
+
return /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
4097
|
+
import_ui26.DetailPanel,
|
|
4025
4098
|
{
|
|
4026
4099
|
side: "left",
|
|
4027
4100
|
title: panel.title,
|
|
@@ -4032,7 +4105,7 @@ function EntityDetailPanel({
|
|
|
4032
4105
|
onExpandedChange: panel.onExpandedChange,
|
|
4033
4106
|
aside: panel.extraContent,
|
|
4034
4107
|
edgeTab,
|
|
4035
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0,
|
|
4108
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)(import_jsx_runtime55.Fragment, { children: [
|
|
4036
4109
|
panel.content,
|
|
4037
4110
|
panel.extraContent
|
|
4038
4111
|
] }) : panel.content
|