@behindthemusictree/app-kit-ui 38.0.0 → 40.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-F7H5XPWU.js → chunk-I2TEOHVG.js} +635 -586
- package/dist/chunk-I2TEOHVG.js.map +1 -0
- package/dist/genre-tree/index.cjs +770 -724
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +24 -13
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +765 -719
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -6
- package/dist/chunk-F7H5XPWU.js.map +0 -1
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
} from "./chunk-2GH7CSCE.js";
|
|
6
6
|
|
|
7
7
|
// src/genre-tree/GenreTreeView.tsx
|
|
8
|
-
import { useCallback as useCallback6, useDeferredValue as useDeferredValue2, useEffect as
|
|
8
|
+
import { useCallback as useCallback6, useDeferredValue as useDeferredValue2, useEffect as useEffect6, useMemo as useMemo8, useRef as useRef3, useState as useState10 } from "react";
|
|
9
9
|
import { useIsMutating } from "@tanstack/react-query";
|
|
10
10
|
import { Plus as Plus2 } from "lucide-react";
|
|
11
11
|
import { Maximize2 as Maximize22, Minimize2 as Minimize22 } from "lucide-react";
|
|
@@ -16,7 +16,7 @@ import {
|
|
|
16
16
|
useGenreNodeRelations
|
|
17
17
|
} from "@behindthemusictree/genre-tree-view";
|
|
18
18
|
import { useGenreTreeViewState, useArtist as useArtist2, useUpdateGenre as useUpdateGenre2, genreUpdateMutationKey } from "@behindthemusictree/app-kit/genre-tree";
|
|
19
|
-
import { usePopup as
|
|
19
|
+
import { usePopup as usePopup4 } from "@behindthemusictree/app-kit/popup";
|
|
20
20
|
|
|
21
21
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
22
22
|
import { genrePlaylistTrackCount } from "@behindthemusictree/app-kit/genre-tree";
|
|
@@ -30,7 +30,7 @@ var genrePlaylistSize = (genrePlaylist, metric) => {
|
|
|
30
30
|
};
|
|
31
31
|
|
|
32
32
|
// src/genre-tree/playlist-tree/toTreeNodes.ts
|
|
33
|
-
function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
33
|
+
function toTreeNodes(genrePlaylists, sizeMetric, focusUuids) {
|
|
34
34
|
return genrePlaylists.map((genrePlaylist) => ({
|
|
35
35
|
id: genrePlaylist.uuid,
|
|
36
36
|
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
@@ -41,7 +41,8 @@ function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
|
41
41
|
side: genrePlaylist.criteria?.side ?? void 0,
|
|
42
42
|
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
43
43
|
umbrella: genrePlaylist.isUmbrella,
|
|
44
|
-
scene: genrePlaylist.scene ?? void 0
|
|
44
|
+
scene: genrePlaylist.scene ?? void 0,
|
|
45
|
+
muted: focusUuids ? !focusUuids.has(genrePlaylist.uuid) : void 0
|
|
45
46
|
}));
|
|
46
47
|
}
|
|
47
48
|
|
|
@@ -53,44 +54,52 @@ import {
|
|
|
53
54
|
getGenreTreeColor
|
|
54
55
|
} from "@behindthemusictree/genre-tree-view";
|
|
55
56
|
import { usePlayer } from "@behindthemusictree/app-kit/player";
|
|
56
|
-
import { usePopup } from "@behindthemusictree/app-kit/popup";
|
|
57
|
-
import { ErrorCode } from "@behindthemusictree/app-kit/transport";
|
|
58
57
|
|
|
59
|
-
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.
|
|
58
|
+
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.tsx
|
|
60
59
|
import { useCallback, useMemo } from "react";
|
|
61
60
|
import {
|
|
62
61
|
TrackListOriginType,
|
|
62
|
+
TracksFailureAlreadyReportedError,
|
|
63
63
|
useTrackList,
|
|
64
64
|
GenreCatalogueCountsSchema,
|
|
65
65
|
defaultGenreMusicSelection,
|
|
66
66
|
genreMusicSelectionKey
|
|
67
67
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
68
|
+
import { usePopup } from "@behindthemusictree/app-kit/popup";
|
|
69
|
+
import { AppError, ErrorCode } from "@behindthemusictree/app-kit/transport";
|
|
70
|
+
import { jsx } from "react/jsx-runtime";
|
|
68
71
|
function useGenrePlaylistPlayback({
|
|
69
72
|
scope,
|
|
70
73
|
genrePlaylists,
|
|
71
74
|
artist = null
|
|
72
75
|
}) {
|
|
73
76
|
const { trackList, playNewTrackListFromGenrePlaylist } = useTrackList();
|
|
77
|
+
const { showPopup } = usePopup();
|
|
74
78
|
const origin = trackList?.origin;
|
|
75
|
-
const
|
|
79
|
+
const playing = useMemo(() => {
|
|
76
80
|
if (!origin || origin.type !== TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
77
81
|
const playlistOrigin = origin;
|
|
78
82
|
if (playlistOrigin.artistUuid !== artist?.uuid) return null;
|
|
79
83
|
const playlist = genrePlaylists.find((item) => item.uuid === origin.uuid) ?? playlistOrigin.criteriaPlaylist;
|
|
80
84
|
const expected = scope === "reference" && playlist && !("criteria" in playlist && playlist.criteria === null) ? defaultGenreMusicSelection(GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
81
|
-
|
|
82
|
-
return origin.uuid;
|
|
85
|
+
return { uuid: origin.uuid, selectionKey: genreMusicSelectionKey(playlistOrigin.selection ?? expected).join() };
|
|
83
86
|
}, [origin, artist, genrePlaylists, scope]);
|
|
84
|
-
const play = useCallback(async (playlist) => {
|
|
87
|
+
const play = useCallback(async (playlist, requested) => {
|
|
85
88
|
if (artist && !playlist.criteria) return;
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
89
|
+
try {
|
|
90
|
+
const selection = scope === "reference" && playlist.criteria !== null ? requested ?? defaultGenreMusicSelection(GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
91
|
+
await (selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope));
|
|
92
|
+
} catch (error) {
|
|
93
|
+
console.error("Failed to load genre playlist tracks:", error);
|
|
94
|
+
if (error instanceof TracksFailureAlreadyReportedError) return;
|
|
95
|
+
showPopup(/* @__PURE__ */ jsx(InternalErrorPopup, { errorCode: error instanceof AppError ? error.code : ErrorCode.CLIENT_UNKNOWN }));
|
|
96
|
+
}
|
|
97
|
+
}, [artist, scope, playNewTrackListFromGenrePlaylist, showPopup]);
|
|
98
|
+
return useMemo(() => ({ playing, play }), [playing, play]);
|
|
90
99
|
}
|
|
91
100
|
|
|
92
101
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
93
|
-
import { jsx } from "react/jsx-runtime";
|
|
102
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
94
103
|
function GenrePlaylistTreePerRoot({
|
|
95
104
|
scope,
|
|
96
105
|
className: className2,
|
|
@@ -109,24 +118,16 @@ function GenrePlaylistTreePerRoot({
|
|
|
109
118
|
viewportRestore,
|
|
110
119
|
onViewportChange,
|
|
111
120
|
playback,
|
|
121
|
+
focusUuids,
|
|
112
122
|
...hostPanel
|
|
113
123
|
}) {
|
|
114
124
|
const { isPlaying, setIsPlaying } = usePlayer();
|
|
115
125
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: genrePlaylistTreePerRoot });
|
|
116
|
-
const {
|
|
117
|
-
const
|
|
126
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
127
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
118
128
|
const nodes = useMemo2(
|
|
119
|
-
() => genrePlaylistTreePerRoot
|
|
120
|
-
|
|
121
|
-
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
122
|
-
name: genrePlaylist.name,
|
|
123
|
-
itemCount: genrePlaylistTrackCount2(genrePlaylist),
|
|
124
|
-
actionable: Boolean(genrePlaylist.criteria),
|
|
125
|
-
side: genrePlaylist.criteria?.side ?? void 0,
|
|
126
|
-
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
127
|
-
umbrella: genrePlaylist.isUmbrella
|
|
128
|
-
})),
|
|
129
|
-
[genrePlaylistTreePerRoot]
|
|
129
|
+
() => toTreeNodes(genrePlaylistTreePerRoot, "songs", focusUuids),
|
|
130
|
+
[genrePlaylistTreePerRoot, focusUuids]
|
|
130
131
|
);
|
|
131
132
|
const handlePlayPause = useCallback2(
|
|
132
133
|
(nodeId) => {
|
|
@@ -139,18 +140,14 @@ function GenrePlaylistTreePerRoot({
|
|
|
139
140
|
if (genrePlaylistTrackCount2(genrePlaylist) === 0) {
|
|
140
141
|
return;
|
|
141
142
|
}
|
|
142
|
-
play(genrePlaylist)
|
|
143
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
144
|
-
showPopup(/* @__PURE__ */ jsx(InternalErrorPopup, { errorCode: ErrorCode.CLIENT_UNKNOWN }));
|
|
145
|
-
});
|
|
143
|
+
void play(genrePlaylist);
|
|
146
144
|
},
|
|
147
145
|
[
|
|
148
146
|
genrePlaylistTreePerRoot,
|
|
149
147
|
playingNodeId,
|
|
150
148
|
isPlaying,
|
|
151
149
|
setIsPlaying,
|
|
152
|
-
play
|
|
153
|
-
showPopup
|
|
150
|
+
play
|
|
154
151
|
]
|
|
155
152
|
);
|
|
156
153
|
const handleAddChild = useCallback2(
|
|
@@ -173,7 +170,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
173
170
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
174
171
|
}
|
|
175
172
|
}, []);
|
|
176
|
-
return /* @__PURE__ */
|
|
173
|
+
return /* @__PURE__ */ jsx2(
|
|
177
174
|
GenreTree,
|
|
178
175
|
{
|
|
179
176
|
className: className2,
|
|
@@ -206,9 +203,7 @@ import {
|
|
|
206
203
|
GenreTreeWheel
|
|
207
204
|
} from "@behindthemusictree/genre-tree-view";
|
|
208
205
|
import { usePlayer as usePlayer2 } from "@behindthemusictree/app-kit/player";
|
|
209
|
-
import {
|
|
210
|
-
import { ErrorCode as ErrorCode2 } from "@behindthemusictree/app-kit/transport";
|
|
211
|
-
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
206
|
+
import { jsx as jsx3 } from "react/jsx-runtime";
|
|
212
207
|
function GenrePlaylistTreeWheel({
|
|
213
208
|
scope,
|
|
214
209
|
className: className2,
|
|
@@ -229,23 +224,16 @@ function GenrePlaylistTreeWheel({
|
|
|
229
224
|
viewportRestore,
|
|
230
225
|
onViewportChange,
|
|
231
226
|
playback,
|
|
227
|
+
focusUuids,
|
|
232
228
|
...hostPanel
|
|
233
229
|
}) {
|
|
234
230
|
const { isPlaying, setIsPlaying } = usePlayer2();
|
|
235
231
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
236
|
-
const {
|
|
237
|
-
const
|
|
232
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
233
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
238
234
|
const nodes = useMemo3(
|
|
239
|
-
() => genrePlaylists
|
|
240
|
-
|
|
241
|
-
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
242
|
-
name: genrePlaylist.name,
|
|
243
|
-
itemCount: genrePlaylistSize(genrePlaylist, sizeMetric),
|
|
244
|
-
actionable: Boolean(genrePlaylist.criteria),
|
|
245
|
-
side: genrePlaylist.criteria?.side ?? void 0,
|
|
246
|
-
wikidataId: genrePlaylist.criteria?.wikidataId ?? null
|
|
247
|
-
})),
|
|
248
|
-
[genrePlaylists, sizeMetric]
|
|
235
|
+
() => toTreeNodes(genrePlaylists, sizeMetric, focusUuids),
|
|
236
|
+
[genrePlaylists, sizeMetric, focusUuids]
|
|
249
237
|
);
|
|
250
238
|
const handlePlayPause = useCallback3(
|
|
251
239
|
(nodeId) => {
|
|
@@ -258,18 +246,14 @@ function GenrePlaylistTreeWheel({
|
|
|
258
246
|
if (genrePlaylistTrackCount3(genrePlaylist) === 0) {
|
|
259
247
|
return;
|
|
260
248
|
}
|
|
261
|
-
play(genrePlaylist)
|
|
262
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
263
|
-
showPopup(/* @__PURE__ */ jsx2(InternalErrorPopup, { errorCode: ErrorCode2.CLIENT_UNKNOWN }));
|
|
264
|
-
});
|
|
249
|
+
void play(genrePlaylist);
|
|
265
250
|
},
|
|
266
251
|
[
|
|
267
252
|
genrePlaylists,
|
|
268
253
|
playingNodeId,
|
|
269
254
|
isPlaying,
|
|
270
255
|
setIsPlaying,
|
|
271
|
-
play
|
|
272
|
-
showPopup
|
|
256
|
+
play
|
|
273
257
|
]
|
|
274
258
|
);
|
|
275
259
|
const handleAddChild = useCallback3(
|
|
@@ -292,7 +276,7 @@ function GenrePlaylistTreeWheel({
|
|
|
292
276
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
293
277
|
}
|
|
294
278
|
}, []);
|
|
295
|
-
return /* @__PURE__ */
|
|
279
|
+
return /* @__PURE__ */ jsx3(
|
|
296
280
|
GenreTreeWheel,
|
|
297
281
|
{
|
|
298
282
|
className: className2,
|
|
@@ -327,7 +311,7 @@ import {
|
|
|
327
311
|
GenreTreeWheelRadialPopCore
|
|
328
312
|
} from "@behindthemusictree/genre-tree-view";
|
|
329
313
|
import { usePlayer as usePlayer3 } from "@behindthemusictree/app-kit/player";
|
|
330
|
-
import { jsx as
|
|
314
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
331
315
|
function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
332
316
|
const {
|
|
333
317
|
scope,
|
|
@@ -358,8 +342,9 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
358
342
|
};
|
|
359
343
|
const { isPlaying, setIsPlaying } = usePlayer3();
|
|
360
344
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
361
|
-
const {
|
|
362
|
-
const
|
|
345
|
+
const { playing, play } = playback ?? defaultPlayback;
|
|
346
|
+
const playingNodeId = playing?.uuid ?? null;
|
|
347
|
+
const nodes = useMemo4(() => toTreeNodes(genrePlaylists, sizeMetric, props.focusUuids), [genrePlaylists, sizeMetric, props.focusUuids]);
|
|
363
348
|
const handlePlayPause = useCallback4(
|
|
364
349
|
(nodeId) => {
|
|
365
350
|
const genrePlaylist = genrePlaylists.find((g) => g.uuid === nodeId);
|
|
@@ -371,9 +356,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
371
356
|
if (genrePlaylistTrackCount4(genrePlaylist) === 0) {
|
|
372
357
|
return;
|
|
373
358
|
}
|
|
374
|
-
play(genrePlaylist)
|
|
375
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
376
|
-
});
|
|
359
|
+
void play(genrePlaylist);
|
|
377
360
|
},
|
|
378
361
|
[genrePlaylists, playingNodeId, isPlaying, setIsPlaying, play]
|
|
379
362
|
);
|
|
@@ -413,7 +396,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
413
396
|
onSelectedNodeChange,
|
|
414
397
|
...hostPanel
|
|
415
398
|
};
|
|
416
|
-
return outline ? /* @__PURE__ */
|
|
399
|
+
return outline ? /* @__PURE__ */ jsx4(GenreTreeOutline, { ...treeProps }) : /* @__PURE__ */ jsx4(
|
|
417
400
|
GenreTreeWheelRadialPopCore,
|
|
418
401
|
{
|
|
419
402
|
...treeProps,
|
|
@@ -430,7 +413,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
430
413
|
|
|
431
414
|
// src/genre-tree/GenreTreeWheelHandoff.tsx
|
|
432
415
|
import { useEffect, useRef, useState } from "react";
|
|
433
|
-
import { jsx as
|
|
416
|
+
import { jsx as jsx5, jsxs } from "react/jsx-runtime";
|
|
434
417
|
function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
435
418
|
const [revealed, setRevealed] = useState(false);
|
|
436
419
|
const onRevealedChangeRef = useRef(onRevealedChange);
|
|
@@ -450,7 +433,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
450
433
|
};
|
|
451
434
|
}, []);
|
|
452
435
|
return /* @__PURE__ */ jsxs("div", { className: "relative w-full h-full", children: [
|
|
453
|
-
/* @__PURE__ */
|
|
436
|
+
/* @__PURE__ */ jsx5(
|
|
454
437
|
"div",
|
|
455
438
|
{
|
|
456
439
|
className: "absolute inset-0 transition-opacity duration-150 ease-out",
|
|
@@ -459,7 +442,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
459
442
|
children
|
|
460
443
|
}
|
|
461
444
|
),
|
|
462
|
-
!revealed && /* @__PURE__ */
|
|
445
|
+
!revealed && /* @__PURE__ */ jsx5("div", { className: "absolute inset-0", "aria-hidden": "true", children: skeleton })
|
|
463
446
|
] });
|
|
464
447
|
}
|
|
465
448
|
|
|
@@ -474,7 +457,7 @@ import { useGenreSearch } from "@behindthemusictree/app-kit/genre-tree";
|
|
|
474
457
|
// src/genre-tree/search/SearchBox.tsx
|
|
475
458
|
import { useState as useState2 } from "react";
|
|
476
459
|
import { SearchCombobox } from "@behindthemusictree/ui";
|
|
477
|
-
import { jsx as
|
|
460
|
+
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
478
461
|
function SearchBox({
|
|
479
462
|
label,
|
|
480
463
|
placeholder,
|
|
@@ -496,7 +479,7 @@ function SearchBox({
|
|
|
496
479
|
groups.find((group) => group.key === groupKey)?.items.find((item) => item.key === itemKey)?.onSelect();
|
|
497
480
|
onPicked?.(groupKey, itemKey);
|
|
498
481
|
};
|
|
499
|
-
return /* @__PURE__ */
|
|
482
|
+
return /* @__PURE__ */ jsx6("div", { className: className2, onFocusCapture: onFocus, children: /* @__PURE__ */ jsx6(
|
|
500
483
|
SearchCombobox,
|
|
501
484
|
{
|
|
502
485
|
ariaLabel: label,
|
|
@@ -562,7 +545,7 @@ import {
|
|
|
562
545
|
isSongSearchResultPlayable,
|
|
563
546
|
useSongSearch
|
|
564
547
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
565
|
-
import { jsx as
|
|
548
|
+
import { jsx as jsx7, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
566
549
|
function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
567
550
|
const search = useSongSearch(getBaseUrl, enabled ? text : "");
|
|
568
551
|
if (!enabled) return void 0;
|
|
@@ -572,8 +555,8 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
572
555
|
items: search.songs.map((song) => ({
|
|
573
556
|
key: song.uuid,
|
|
574
557
|
content: /* @__PURE__ */ jsxs3("span", { className: isSongSearchResultPlayable(song) ? void 0 : "opacity-60", children: [
|
|
575
|
-
/* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
558
|
+
/* @__PURE__ */ jsx7("span", { className: "block truncate font-medium", children: song.title }),
|
|
559
|
+
/* @__PURE__ */ jsx7("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 ") })
|
|
577
560
|
] }),
|
|
578
561
|
onSelect: () => onSelect(song)
|
|
579
562
|
})),
|
|
@@ -586,7 +569,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
586
569
|
import {
|
|
587
570
|
useGenreRemoteSearch
|
|
588
571
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
589
|
-
import { Fragment as Fragment2, jsx as
|
|
572
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
590
573
|
function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres", label = "Genres", filter, describe, ...options } = {}) {
|
|
591
574
|
const search = useGenreRemoteSearch(getBaseUrl, text, options);
|
|
592
575
|
const genres = filter ? search.genres.filter(filter) : search.genres;
|
|
@@ -598,9 +581,9 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
598
581
|
content: /* @__PURE__ */ jsxs4(Fragment2, { children: [
|
|
599
582
|
/* @__PURE__ */ jsxs4("span", { className: "block truncate font-medium", children: [
|
|
600
583
|
genre.name,
|
|
601
|
-
genre.isUmbrella && /* @__PURE__ */
|
|
584
|
+
genre.isUmbrella && /* @__PURE__ */ jsx8("span", { className: "ml-2 text-caption font-normal italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
602
585
|
] }),
|
|
603
|
-
/* @__PURE__ */
|
|
586
|
+
/* @__PURE__ */ jsx8("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: describe?.(genre) ?? `${genre.treeName} \xB7 ${genre.root.name}` })
|
|
604
587
|
] }),
|
|
605
588
|
onSelect: () => onSelect(genre)
|
|
606
589
|
})),
|
|
@@ -610,7 +593,7 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
610
593
|
}
|
|
611
594
|
|
|
612
595
|
// src/genre-tree/GenreSearch.tsx
|
|
613
|
-
import { Fragment as Fragment3, jsx as
|
|
596
|
+
import { Fragment as Fragment3, jsx as jsx9, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
614
597
|
function GenreSearch({
|
|
615
598
|
genrePlaylists,
|
|
616
599
|
onSelect,
|
|
@@ -641,7 +624,7 @@ function GenreSearch({
|
|
|
641
624
|
key: genrePlaylist.uuid,
|
|
642
625
|
content: /* @__PURE__ */ jsxs5(Fragment3, { children: [
|
|
643
626
|
genrePlaylist.name,
|
|
644
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */
|
|
627
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ jsx9("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
645
628
|
] }),
|
|
646
629
|
onSelect: () => select(genrePlaylist)
|
|
647
630
|
}))
|
|
@@ -650,7 +633,7 @@ function GenreSearch({
|
|
|
650
633
|
(group) => active ? group : { ...group, items: [], status: "", loading: false }
|
|
651
634
|
)
|
|
652
635
|
];
|
|
653
|
-
return /* @__PURE__ */
|
|
636
|
+
return /* @__PURE__ */ jsx9("div", { className: "genre-search w-[calc(var(--layout-detail-panel-w,25.5rem)-2*var(--layout-panel-inset,1rem))] shrink-0 max-md:w-full", children: /* @__PURE__ */ jsx9(
|
|
654
637
|
SearchBox,
|
|
655
638
|
{
|
|
656
639
|
label,
|
|
@@ -670,14 +653,14 @@ function GenreSearch({
|
|
|
670
653
|
clear();
|
|
671
654
|
onQueryChange?.("");
|
|
672
655
|
} : void 0,
|
|
673
|
-
leading: onPrevious && /* @__PURE__ */
|
|
656
|
+
leading: onPrevious && /* @__PURE__ */ jsx9("button", { type: "button", "aria-label": "Previous", title: "Previous", className: SEARCH_LEADING_BUTTON_CLASS, onClick: onPrevious, children: /* @__PURE__ */ jsx9(ArrowLeft, { "aria-hidden": "true", className: "h-4 w-4" }) }),
|
|
674
657
|
onFocus
|
|
675
658
|
}
|
|
676
659
|
) });
|
|
677
660
|
}
|
|
678
661
|
|
|
679
662
|
// src/genre-tree/GenreTreeSearch.tsx
|
|
680
|
-
import { jsx as
|
|
663
|
+
import { jsx as jsx10 } from "react/jsx-runtime";
|
|
681
664
|
function GenreTreeSearch({
|
|
682
665
|
artistBaseUrl,
|
|
683
666
|
songBaseUrl,
|
|
@@ -697,7 +680,7 @@ function GenreTreeSearch({
|
|
|
697
680
|
const deferredQuery = useDeferredValue(query);
|
|
698
681
|
const artistGroup = useArtistSearchGroup(artistBaseUrl, deferredQuery, onArtistSelect, artistSearch);
|
|
699
682
|
const songGroup = useSongSearchGroup(songBaseUrl, deferredQuery, onSongSelect, songSearch);
|
|
700
|
-
const render = (hostGroups) => /* @__PURE__ */
|
|
683
|
+
const render = (hostGroups) => /* @__PURE__ */ jsx10(
|
|
701
684
|
GenreSearch,
|
|
702
685
|
{
|
|
703
686
|
...props,
|
|
@@ -712,16 +695,16 @@ function GenreTreeSearch({
|
|
|
712
695
|
extraGroups: [...extraGroups, ...hostGroups, artistGroup, songGroup].filter((group) => group !== void 0)
|
|
713
696
|
}
|
|
714
697
|
);
|
|
715
|
-
return SearchGroups ? /* @__PURE__ */
|
|
698
|
+
return SearchGroups ? /* @__PURE__ */ jsx10(SearchGroups, { query: deferredQuery, focused, onSelectGenre, children: render }) : render([]);
|
|
716
699
|
}
|
|
717
700
|
|
|
718
701
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
719
702
|
import { useMemo as useMemo6 } from "react";
|
|
720
703
|
import {
|
|
721
|
-
ACCENT_TEXT_COLOR,
|
|
722
704
|
GenreNodeAncestors,
|
|
723
705
|
GenreNodeFamily,
|
|
724
706
|
getGenreTreeColor as getGenreTreeColor2,
|
|
707
|
+
getTextColorOnFill,
|
|
725
708
|
TEXT_COLOR,
|
|
726
709
|
tintSurface
|
|
727
710
|
} from "@behindthemusictree/genre-tree-view";
|
|
@@ -738,19 +721,18 @@ import {
|
|
|
738
721
|
|
|
739
722
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
740
723
|
import {
|
|
741
|
-
genreMusicCount,
|
|
742
724
|
defaultGenreMusicSelection as defaultGenreMusicSelection2,
|
|
743
725
|
GenreCatalogueCountsSchema as GenreCatalogueCountsSchema2
|
|
744
726
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
745
|
-
import { useTrackNoun as useTrackNoun3 } from "@behindthemusictree/app-kit/track-noun";
|
|
746
|
-
import { usePlayer as usePlayer5 } from "@behindthemusictree/app-kit/player";
|
|
747
727
|
|
|
748
728
|
// src/genre-tree/GenreActionBand.tsx
|
|
749
|
-
import { ArrowLeftRight, MoveUpRight,
|
|
729
|
+
import { ArrowLeftRight, MoveUpRight, Pencil, Plus, ZoomIn } from "lucide-react";
|
|
730
|
+
import { ActionBand, ActionButton as ActionButton2, PanelBleed } from "@behindthemusictree/ui";
|
|
750
731
|
|
|
751
732
|
// src/genre-tree/ShareActionButton.tsx
|
|
752
733
|
import { Share2 as Share22 } from "lucide-react";
|
|
753
|
-
import {
|
|
734
|
+
import { ActionButton } from "@behindthemusictree/ui";
|
|
735
|
+
import { usePopup as usePopup2 } from "@behindthemusictree/app-kit/popup";
|
|
754
736
|
|
|
755
737
|
// src/genre-tree/SharePopup.tsx
|
|
756
738
|
import { useCallback as useCallback5, useEffect as useEffect2, useMemo as useMemo5, useState as useState4 } from "react";
|
|
@@ -759,12 +741,12 @@ import { FaWhatsapp } from "react-icons/fa";
|
|
|
759
741
|
import { SiGmail } from "react-icons/si";
|
|
760
742
|
|
|
761
743
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
762
|
-
import { Fragment as Fragment4, jsx as
|
|
744
|
+
import { Fragment as Fragment4, jsx as jsx11, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
763
745
|
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";
|
|
764
746
|
function Contents({ icon, label }) {
|
|
765
747
|
return /* @__PURE__ */ jsxs6(Fragment4, { children: [
|
|
766
|
-
/* @__PURE__ */
|
|
767
|
-
/* @__PURE__ */
|
|
748
|
+
/* @__PURE__ */ jsx11("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 }),
|
|
749
|
+
/* @__PURE__ */ jsx11("span", { className: "max-w-full truncate", children: label })
|
|
768
750
|
] });
|
|
769
751
|
}
|
|
770
752
|
function ShareDestinationButton({
|
|
@@ -776,29 +758,29 @@ function ShareDestinationButton({
|
|
|
776
758
|
ariaLabel
|
|
777
759
|
}) {
|
|
778
760
|
if (href) {
|
|
779
|
-
return /* @__PURE__ */
|
|
761
|
+
return /* @__PURE__ */ jsx11("a", { href, target: "_blank", rel: "noopener noreferrer", "aria-label": ariaLabel, className, children: /* @__PURE__ */ jsx11(Contents, { icon, label }) });
|
|
780
762
|
}
|
|
781
|
-
return /* @__PURE__ */
|
|
763
|
+
return /* @__PURE__ */ jsx11("button", { type: "button", onClick, disabled, "aria-label": ariaLabel, className, children: /* @__PURE__ */ jsx11(Contents, { icon, label }) });
|
|
782
764
|
}
|
|
783
765
|
|
|
784
766
|
// src/genre-tree/SharePreviewCard.tsx
|
|
785
767
|
import { Music, Music2, UserRound } from "lucide-react";
|
|
786
|
-
import { jsx as
|
|
768
|
+
import { jsx as jsx12, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
787
769
|
function SharePreviewCard({ target, url }) {
|
|
788
770
|
const Icon = { genre: Music2, artist: UserRound, song: Music }[target.kind];
|
|
789
771
|
const typeLabel = { genre: "Genre", artist: "Artist", song: "Song" }[target.kind];
|
|
790
|
-
return /* @__PURE__ */
|
|
791
|
-
/* @__PURE__ */
|
|
772
|
+
return /* @__PURE__ */ jsx12("div", { className: "rounded-3xl bg-[var(--color-surface-muted)] p-4", children: /* @__PURE__ */ jsxs7("div", { className: "flex min-h-32 overflow-hidden rounded-2xl bg-[var(--color-surface)] shadow-lg", children: [
|
|
773
|
+
/* @__PURE__ */ jsx12("div", { className: "flex w-28 shrink-0 items-center justify-center bg-[var(--color-primary)]/15 text-[var(--color-primary)]", children: /* @__PURE__ */ jsx12(Icon, { "aria-hidden": "true", className: "h-10 w-10" }) }),
|
|
792
774
|
/* @__PURE__ */ jsxs7("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
793
|
-
/* @__PURE__ */
|
|
794
|
-
/* @__PURE__ */
|
|
795
|
-
/* @__PURE__ */
|
|
775
|
+
/* @__PURE__ */ jsx12("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
776
|
+
/* @__PURE__ */ jsx12("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
777
|
+
/* @__PURE__ */ jsx12("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
796
778
|
] })
|
|
797
779
|
] }) });
|
|
798
780
|
}
|
|
799
781
|
|
|
800
782
|
// src/genre-tree/SharePopup.tsx
|
|
801
|
-
import { Fragment as Fragment5, jsx as
|
|
783
|
+
import { Fragment as Fragment5, jsx as jsx13, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
802
784
|
function resolveAbsoluteUrl(url) {
|
|
803
785
|
try {
|
|
804
786
|
const parsed = new URL(url, window.location.href);
|
|
@@ -874,7 +856,7 @@ function SharePopup({ target, url, onClose }) {
|
|
|
874
856
|
}
|
|
875
857
|
};
|
|
876
858
|
return /* @__PURE__ */ jsxs8(Fragment5, { children: [
|
|
877
|
-
/* @__PURE__ */
|
|
859
|
+
/* @__PURE__ */ jsx13(
|
|
878
860
|
BasePopup_default,
|
|
879
861
|
{
|
|
880
862
|
title: "Share",
|
|
@@ -890,87 +872,82 @@ function SharePopup({ target, url, onClose }) {
|
|
|
890
872
|
closeButtonClassName: "!h-10 !w-10 !rounded-none !border-0 !bg-transparent !p-0 !text-[var(--color-text)] hover:!bg-transparent hover:!text-[var(--color-text)]",
|
|
891
873
|
contentClassName: "!rounded-none !bg-transparent !px-6 !pb-6 !pt-2",
|
|
892
874
|
children: /* @__PURE__ */ jsxs8("div", { className: "flex flex-col gap-4", children: [
|
|
893
|
-
/* @__PURE__ */
|
|
875
|
+
/* @__PURE__ */ jsx13(SharePreviewCard, { target, url: absoluteUrl || url }),
|
|
894
876
|
/* @__PURE__ */ jsxs8("div", { className: "grid grid-cols-3 gap-1 rounded-3xl bg-[var(--color-surface)] p-3 sm:grid-cols-4", children: [
|
|
895
|
-
/* @__PURE__ */
|
|
877
|
+
/* @__PURE__ */ jsx13(
|
|
896
878
|
ShareDestinationButton,
|
|
897
879
|
{
|
|
898
880
|
label: "Copy Link",
|
|
899
|
-
icon: /* @__PURE__ */
|
|
881
|
+
icon: /* @__PURE__ */ jsx13(Link2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
900
882
|
onClick: () => void handleCopy(),
|
|
901
883
|
ariaLabel: "Copy link",
|
|
902
884
|
disabled: !absoluteUrl
|
|
903
885
|
}
|
|
904
886
|
),
|
|
905
|
-
/* @__PURE__ */
|
|
887
|
+
/* @__PURE__ */ jsx13(
|
|
906
888
|
ShareDestinationButton,
|
|
907
889
|
{
|
|
908
890
|
label: "WhatsApp",
|
|
909
|
-
icon: /* @__PURE__ */
|
|
891
|
+
icon: /* @__PURE__ */ jsx13(FaWhatsapp, { "aria-hidden": "true", className: "h-9 w-9 text-[#25D366]" }),
|
|
910
892
|
href: destinationUrls?.whatsapp,
|
|
911
893
|
ariaLabel: `Share ${target.name} via WhatsApp`,
|
|
912
894
|
disabled: !absoluteUrl
|
|
913
895
|
}
|
|
914
896
|
),
|
|
915
|
-
/* @__PURE__ */
|
|
897
|
+
/* @__PURE__ */ jsx13(
|
|
916
898
|
ShareDestinationButton,
|
|
917
899
|
{
|
|
918
900
|
label: "Gmail",
|
|
919
|
-
icon: /* @__PURE__ */
|
|
901
|
+
icon: /* @__PURE__ */ jsx13(SiGmail, { "aria-hidden": "true", className: "h-8 w-8 text-[#EA4335]" }),
|
|
920
902
|
href: destinationUrls?.gmail,
|
|
921
903
|
ariaLabel: `Email ${target.name} with Gmail`,
|
|
922
904
|
disabled: !absoluteUrl
|
|
923
905
|
}
|
|
924
906
|
),
|
|
925
|
-
canUseNativeShare && /* @__PURE__ */
|
|
907
|
+
canUseNativeShare && /* @__PURE__ */ jsx13(
|
|
926
908
|
ShareDestinationButton,
|
|
927
909
|
{
|
|
928
910
|
label: "More",
|
|
929
|
-
icon: /* @__PURE__ */
|
|
911
|
+
icon: /* @__PURE__ */ jsx13(Share2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
930
912
|
onClick: () => void handleNativeShare(),
|
|
931
913
|
ariaLabel: "More sharing options",
|
|
932
914
|
disabled: !absoluteUrl
|
|
933
915
|
}
|
|
934
916
|
)
|
|
935
917
|
] }),
|
|
936
|
-
copyStatus === "failed" && /* @__PURE__ */
|
|
937
|
-
shareError && /* @__PURE__ */
|
|
918
|
+
copyStatus === "failed" && /* @__PURE__ */ jsx13("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: "Could not copy the link." }),
|
|
919
|
+
shareError && /* @__PURE__ */ jsx13("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
938
920
|
] })
|
|
939
921
|
}
|
|
940
922
|
),
|
|
941
|
-
toastId > 0 && /* @__PURE__ */
|
|
923
|
+
toastId > 0 && /* @__PURE__ */ jsx13(Toast, { message: "Link copied", onClose: dismissToast }, toastId)
|
|
942
924
|
] });
|
|
943
925
|
}
|
|
944
926
|
|
|
945
927
|
// src/genre-tree/ShareActionButton.tsx
|
|
946
|
-
import { jsx as
|
|
928
|
+
import { jsx as jsx14 } from "react/jsx-runtime";
|
|
947
929
|
function ShareActionButton({ target, url }) {
|
|
948
|
-
const { showPopup, hidePopup } =
|
|
930
|
+
const { showPopup, hidePopup } = usePopup2();
|
|
949
931
|
const openSharePopup = () => {
|
|
950
|
-
showPopup(/* @__PURE__ */
|
|
932
|
+
showPopup(/* @__PURE__ */ jsx14(SharePopup, { target, url, onClose: hidePopup }));
|
|
951
933
|
};
|
|
952
|
-
return /* @__PURE__ */
|
|
953
|
-
|
|
934
|
+
return /* @__PURE__ */ jsx14(
|
|
935
|
+
ActionButton,
|
|
954
936
|
{
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
className: "group flex flex-col items-center gap-1 w-16 text-caption text-center text-[var(--color-text)] focus-visible:outline-none",
|
|
937
|
+
icon: /* @__PURE__ */ jsx14(Share22, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
938
|
+
label: "Share",
|
|
958
939
|
"aria-label": `Share ${target.name}`,
|
|
959
940
|
title: `Share ${target.name}`,
|
|
960
|
-
|
|
961
|
-
/* @__PURE__ */ jsx13("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__ */ jsx13(Share22, { "aria-hidden": "true", className: "w-5 h-5" }) }),
|
|
962
|
-
"Share"
|
|
963
|
-
]
|
|
941
|
+
onClick: openSharePopup
|
|
964
942
|
}
|
|
965
943
|
);
|
|
966
944
|
}
|
|
967
945
|
|
|
968
946
|
// src/genre-tree/GenreActionBand.tsx
|
|
969
|
-
import { jsx as
|
|
947
|
+
import { jsx as jsx15, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
970
948
|
function GenreActionBand({
|
|
971
949
|
node,
|
|
972
|
-
|
|
973
|
-
isPlaying = false,
|
|
950
|
+
playActions,
|
|
974
951
|
onZoomIn,
|
|
975
952
|
onAddChild,
|
|
976
953
|
onRename,
|
|
@@ -984,36 +961,28 @@ function GenreActionBand({
|
|
|
984
961
|
}) {
|
|
985
962
|
const items = [];
|
|
986
963
|
const adminItems = [];
|
|
987
|
-
if (onPlayPause) {
|
|
988
|
-
items.push({
|
|
989
|
-
key: "play-pause",
|
|
990
|
-
label: isPlaying ? "Pause" : "Play",
|
|
991
|
-
icon: isPlaying ? /* @__PURE__ */ jsx14(Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ jsx14(Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
992
|
-
onClick: onPlayPause
|
|
993
|
-
});
|
|
994
|
-
}
|
|
995
964
|
if (onZoomIn) {
|
|
996
965
|
items.push({
|
|
997
966
|
key: "zoom-in",
|
|
998
967
|
label: "Focus",
|
|
999
|
-
icon: /* @__PURE__ */
|
|
968
|
+
icon: /* @__PURE__ */ jsx15(ZoomIn, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1000
969
|
onClick: onZoomIn
|
|
1001
970
|
});
|
|
1002
971
|
}
|
|
1003
972
|
if (onAddChild) {
|
|
1004
|
-
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */
|
|
973
|
+
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */ jsx15(Plus, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onAddChild });
|
|
1005
974
|
}
|
|
1006
975
|
if (onRename) {
|
|
1007
|
-
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */
|
|
976
|
+
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */ jsx15(Pencil, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onRename });
|
|
1008
977
|
}
|
|
1009
978
|
if (onChangeParent) {
|
|
1010
|
-
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */
|
|
979
|
+
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */ jsx15(MoveUpRight, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onChangeParent });
|
|
1011
980
|
}
|
|
1012
981
|
if (onToggleSide) {
|
|
1013
982
|
adminItems.push({
|
|
1014
983
|
key: "toggle-side",
|
|
1015
984
|
label: side === "pop" ? "Make core" : "Make pop",
|
|
1016
|
-
icon: /* @__PURE__ */
|
|
985
|
+
icon: /* @__PURE__ */ jsx15(ArrowLeftRight, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1017
986
|
onClick: onToggleSide,
|
|
1018
987
|
disabled: !!toggleSideDisabledReason,
|
|
1019
988
|
title: toggleSideDisabledReason
|
|
@@ -1028,60 +997,142 @@ function GenreActionBand({
|
|
|
1028
997
|
disabled: action.enabled ? !action.enabled(node) : false
|
|
1029
998
|
});
|
|
1030
999
|
}
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1000
|
+
const renderItems = (list) => list.map((item) => /* @__PURE__ */ jsx15(ActionButton2, { icon: item.icon, label: item.label, disabled: item.disabled, title: item.title, onClick: item.onClick }, item.key));
|
|
1001
|
+
if (!playActions && items.length === 0 && adminItems.length === 0 && !(shareTarget && shareUrl)) return null;
|
|
1002
|
+
return /* @__PURE__ */ jsx15(PanelBleed, { children: /* @__PURE__ */ jsxs9(
|
|
1003
|
+
ActionBand,
|
|
1034
1004
|
{
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
title: item.title,
|
|
1038
|
-
onClick: item.onClick,
|
|
1039
|
-
className: "group flex flex-col items-center gap-1 w-16 text-caption text-center text-[var(--color-text)] focus-visible:outline-none disabled:opacity-50",
|
|
1005
|
+
className: "genre-action-band",
|
|
1006
|
+
section: { title: "Admin", label: "Admin actions", children: renderItems(adminItems) },
|
|
1040
1007
|
children: [
|
|
1041
|
-
|
|
1042
|
-
|
|
1008
|
+
playActions,
|
|
1009
|
+
renderItems(items),
|
|
1010
|
+
shareTarget && shareUrl && /* @__PURE__ */ jsx15(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
1043
1011
|
]
|
|
1044
|
-
}
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1012
|
+
}
|
|
1013
|
+
) });
|
|
1014
|
+
}
|
|
1015
|
+
|
|
1016
|
+
// src/genre-tree/GenrePlayActions.tsx
|
|
1017
|
+
import { Pause, Play } from "lucide-react";
|
|
1018
|
+
import { ActionButton as ActionButton3 } from "@behindthemusictree/ui";
|
|
1019
|
+
import {
|
|
1020
|
+
genreMusicCount,
|
|
1021
|
+
genreMusicSelectionKey as genreMusicSelectionKey2
|
|
1022
|
+
} from "@behindthemusictree/app-kit/genre-tree";
|
|
1023
|
+
import { usePlayer as usePlayer4 } from "@behindthemusictree/app-kit/player";
|
|
1024
|
+
|
|
1025
|
+
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1026
|
+
import { useEffect as useEffect3, useState as useState5 } from "react";
|
|
1027
|
+
|
|
1028
|
+
// src/genre-tree/regionGlobePaths.ts
|
|
1029
|
+
var REGION_GLOBE_PATHS = {
|
|
1030
|
+
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",
|
|
1031
|
+
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",
|
|
1032
|
+
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"
|
|
1033
|
+
};
|
|
1034
|
+
var REGION_GLOBES = ["africa", "americas", "asia"];
|
|
1035
|
+
|
|
1036
|
+
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1037
|
+
import { jsx as jsx16 } from "react/jsx-runtime";
|
|
1038
|
+
var ROTATION_INTERVAL_MS = 3e3;
|
|
1039
|
+
function RegionGlobeIcon({ className: className2 }) {
|
|
1040
|
+
const [index, setIndex] = useState5(0);
|
|
1041
|
+
useEffect3(() => {
|
|
1042
|
+
const reducedMotion = window.matchMedia("(prefers-reduced-motion: reduce)");
|
|
1043
|
+
let timer;
|
|
1044
|
+
const sync = () => {
|
|
1045
|
+
clearInterval(timer);
|
|
1046
|
+
timer = reducedMotion.matches ? void 0 : setInterval(() => setIndex((i) => (i + 1) % REGION_GLOBES.length), ROTATION_INTERVAL_MS);
|
|
1047
|
+
};
|
|
1048
|
+
sync();
|
|
1049
|
+
reducedMotion.addEventListener("change", sync);
|
|
1050
|
+
return () => {
|
|
1051
|
+
reducedMotion.removeEventListener("change", sync);
|
|
1052
|
+
clearInterval(timer);
|
|
1053
|
+
};
|
|
1054
|
+
}, []);
|
|
1055
|
+
return /* @__PURE__ */ jsx16("svg", { viewBox: "0 0 512 512", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ jsx16("path", { "data-testid": "region-globe-path", d: REGION_GLOBE_PATHS[REGION_GLOBES[index]] }) });
|
|
1056
|
+
}
|
|
1057
|
+
|
|
1058
|
+
// src/genre-tree/treeMarkPath.ts
|
|
1059
|
+
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";
|
|
1060
|
+
|
|
1061
|
+
// src/genre-tree/TreeMarkIcon.tsx
|
|
1062
|
+
import { jsx as jsx17 } from "react/jsx-runtime";
|
|
1063
|
+
function TreeMarkIcon({ className: className2 }) {
|
|
1064
|
+
return /* @__PURE__ */ jsx17("svg", { viewBox: "0 0 551 567", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ jsx17("path", { transform: "translate(0 567) scale(0.1 -0.1)", d: TREE_MARK_PATH }) });
|
|
1065
|
+
}
|
|
1066
|
+
|
|
1067
|
+
// src/genre-tree/GenrePlayActions.tsx
|
|
1068
|
+
import { Fragment as Fragment6, jsx as jsx18, jsxs as jsxs10 } from "react/jsx-runtime";
|
|
1069
|
+
function PlayIcon({ kind }) {
|
|
1070
|
+
return /* @__PURE__ */ jsxs10("span", { "aria-hidden": "true", className: "relative flex items-center justify-center w-5 h-5", children: [
|
|
1071
|
+
kind === "tree" && /* @__PURE__ */ jsx18(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1072
|
+
kind === "map" && /* @__PURE__ */ jsx18(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1073
|
+
kind === "tree-map" && /* @__PURE__ */ jsxs10(Fragment6, { children: [
|
|
1074
|
+
/* @__PURE__ */ jsx18(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_50%_0_0)]" }),
|
|
1075
|
+
/* @__PURE__ */ jsx18(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_0_0_50%)]" })
|
|
1051
1076
|
] }),
|
|
1052
|
-
|
|
1053
|
-
"section",
|
|
1054
|
-
{
|
|
1055
|
-
"aria-label": "Admin actions",
|
|
1056
|
-
className: `px-3.5 py-3 ${items.length > 0 ? "border-t border-[var(--color-border)]" : ""}`,
|
|
1057
|
-
children: [
|
|
1058
|
-
/* @__PURE__ */ jsx14("h3", { className: "mb-2 text-caption font-semibold uppercase tracking-wide text-[var(--color-text-muted)]", children: "Admin" }),
|
|
1059
|
-
/* @__PURE__ */ jsx14("div", { className: "flex flex-wrap gap-1", children: renderItems(adminItems) })
|
|
1060
|
-
]
|
|
1061
|
-
}
|
|
1062
|
-
)
|
|
1077
|
+
/* @__PURE__ */ jsx18(Play, { className: "relative w-5 h-5 fill-[var(--color-surface)]" })
|
|
1063
1078
|
] });
|
|
1064
1079
|
}
|
|
1080
|
+
function playOptions(playlist) {
|
|
1081
|
+
if (!("genreOnlyTracksCount" in playlist)) return [{ key: "all", label: "Play", icon: "play", count: playlist.tracksCount }];
|
|
1082
|
+
const direct = { key: "direct", label: "Genre", icon: "play", selection: { coverage: "genreOnly" }, count: genreMusicCount(playlist, { coverage: "genreOnly" }) };
|
|
1083
|
+
const scopes = playlist.genreAndSubgenresTracksCount;
|
|
1084
|
+
const inclusive = (label, icon, subgenres) => {
|
|
1085
|
+
const selection = { coverage: "genreAndSubgenres", subgenres };
|
|
1086
|
+
return { key: subgenres, label, icon, selection, count: genreMusicCount(playlist, selection) };
|
|
1087
|
+
};
|
|
1088
|
+
return "canonical" in scopes ? [direct, inclusive("Canonical", "tree", "canonical"), inclusive("Regional", "map", "regional"), inclusive("All", "tree-map", "all")] : [direct, inclusive("All", "map", "all")];
|
|
1089
|
+
}
|
|
1090
|
+
function GenrePlayActions({ genrePlaylist, playback }) {
|
|
1091
|
+
const { isPlaying, setIsPlaying } = usePlayer4();
|
|
1092
|
+
const options = playOptions(genrePlaylist);
|
|
1093
|
+
return /* @__PURE__ */ jsx18(Fragment6, { children: options.map((option) => {
|
|
1094
|
+
const isCurrent = playback.playing?.uuid === genrePlaylist.uuid && (option.selection === void 0 || playback.playing.selectionKey === "" || playback.playing.selectionKey === genreMusicSelectionKey2(option.selection).join());
|
|
1095
|
+
const playing = isCurrent && isPlaying;
|
|
1096
|
+
return /* @__PURE__ */ jsx18(
|
|
1097
|
+
ActionButton3,
|
|
1098
|
+
{
|
|
1099
|
+
icon: playing ? /* @__PURE__ */ jsx18(Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ jsx18(PlayIcon, { kind: option.icon }),
|
|
1100
|
+
label: playing ? "Pause" : option.label,
|
|
1101
|
+
caption: String(option.count),
|
|
1102
|
+
disabled: option.count === 0,
|
|
1103
|
+
title: option.count === 0 ? "No playable songs" : void 0,
|
|
1104
|
+
onClick: () => {
|
|
1105
|
+
if (isCurrent) {
|
|
1106
|
+
setIsPlaying(!isPlaying);
|
|
1107
|
+
return;
|
|
1108
|
+
}
|
|
1109
|
+
void playback.play(genrePlaylist, option.selection);
|
|
1110
|
+
}
|
|
1111
|
+
},
|
|
1112
|
+
option.key
|
|
1113
|
+
);
|
|
1114
|
+
}) });
|
|
1115
|
+
}
|
|
1065
1116
|
|
|
1066
1117
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1067
1118
|
import { PanelSection as PanelSection2, Skeleton as Skeleton2 } from "@behindthemusictree/ui";
|
|
1068
1119
|
import { useFetchGenreOverview } from "@behindthemusictree/app-kit/genre-tree";
|
|
1069
1120
|
|
|
1070
1121
|
// src/genre-tree/ClampedText.tsx
|
|
1071
|
-
import { useLayoutEffect, useRef as useRef2, useState as
|
|
1072
|
-
import { Fragment as
|
|
1122
|
+
import { useLayoutEffect, useRef as useRef2, useState as useState6 } from "react";
|
|
1123
|
+
import { Fragment as Fragment7, jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
1073
1124
|
function ClampedText({ children, className: className2 = "" }) {
|
|
1074
1125
|
const ref = useRef2(null);
|
|
1075
|
-
const [expanded, setExpanded] =
|
|
1076
|
-
const [overflows, setOverflows] =
|
|
1126
|
+
const [expanded, setExpanded] = useState6(false);
|
|
1127
|
+
const [overflows, setOverflows] = useState6(false);
|
|
1077
1128
|
useLayoutEffect(() => {
|
|
1078
1129
|
const element = ref.current;
|
|
1079
1130
|
if (!element || expanded) return;
|
|
1080
1131
|
setOverflows(element.scrollHeight > element.clientHeight);
|
|
1081
1132
|
}, [children, expanded]);
|
|
1082
|
-
return /* @__PURE__ */ jsxs11(
|
|
1083
|
-
/* @__PURE__ */
|
|
1084
|
-
(overflows || expanded) && /* @__PURE__ */
|
|
1133
|
+
return /* @__PURE__ */ jsxs11(Fragment7, { children: [
|
|
1134
|
+
/* @__PURE__ */ jsx19("p", { ref, className: `${className2} ${expanded ? "" : "line-clamp-3"}`, children }),
|
|
1135
|
+
(overflows || expanded) && /* @__PURE__ */ jsx19(
|
|
1085
1136
|
"button",
|
|
1086
1137
|
{
|
|
1087
1138
|
type: "button",
|
|
@@ -1095,7 +1146,7 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1095
1146
|
}
|
|
1096
1147
|
|
|
1097
1148
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1098
|
-
import { useEffect as
|
|
1149
|
+
import { useEffect as useEffect4, useState as useState7 } from "react";
|
|
1099
1150
|
import { useInfiniteQuery } from "@tanstack/react-query";
|
|
1100
1151
|
import { z } from "zod";
|
|
1101
1152
|
import { FaPlay, FaPause } from "react-icons/fa";
|
|
@@ -1104,27 +1155,27 @@ import { useSession } from "@behindthemusictree/app-kit/auth";
|
|
|
1104
1155
|
import { usePlaybackContext, usePlaybackFetch } from "@behindthemusictree/app-kit/transport";
|
|
1105
1156
|
import { PaginatedResponseSchema } from "@behindthemusictree/app-kit/transport";
|
|
1106
1157
|
import { parseWithLog } from "@behindthemusictree/app-kit/transport";
|
|
1107
|
-
import { usePlayer as
|
|
1158
|
+
import { usePlayer as usePlayer5 } from "@behindthemusictree/app-kit/player";
|
|
1108
1159
|
import { PlayStates } from "@behindthemusictree/app-kit/player";
|
|
1109
|
-
import { usePopup as
|
|
1110
|
-
import { ErrorCode as
|
|
1160
|
+
import { usePopup as usePopup3 } from "@behindthemusictree/app-kit/popup";
|
|
1161
|
+
import { AppError as AppError2, ErrorCode as ErrorCode2 } from "@behindthemusictree/app-kit/transport";
|
|
1111
1162
|
import { genreMusicQueryParams } from "@behindthemusictree/app-kit/genre-tree";
|
|
1112
1163
|
import { genrePlaylistQueryKeys } from "@behindthemusictree/app-kit/genre-tree";
|
|
1113
1164
|
import { libraryEndpoints, libraryQueryKeys } from "@behindthemusictree/app-kit/genre-tree";
|
|
1114
1165
|
import { isSong, songUnplayableReason, SongDetailedSchema } from "@behindthemusictree/app-kit/genre-tree";
|
|
1115
|
-
import { useTrackList as useTrackList2 } from "@behindthemusictree/app-kit/genre-tree";
|
|
1166
|
+
import { TracksFailureAlreadyReportedError as TracksFailureAlreadyReportedError2, useTrackList as useTrackList2 } from "@behindthemusictree/app-kit/genre-tree";
|
|
1116
1167
|
|
|
1117
1168
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1118
1169
|
import { musicBrainzRecordingUrl } from "@behindthemusictree/app-kit/genre-tree";
|
|
1119
|
-
import { Fragment as
|
|
1170
|
+
import { Fragment as Fragment8, jsx as jsx20 } from "react/jsx-runtime";
|
|
1120
1171
|
function MusicBrainzRecordingLink({
|
|
1121
1172
|
song,
|
|
1122
1173
|
children,
|
|
1123
1174
|
className: className2 = ""
|
|
1124
1175
|
}) {
|
|
1125
1176
|
const url = musicBrainzRecordingUrl(song);
|
|
1126
|
-
if (!url) return /* @__PURE__ */
|
|
1127
|
-
return /* @__PURE__ */
|
|
1177
|
+
if (!url) return /* @__PURE__ */ jsx20(Fragment8, { children });
|
|
1178
|
+
return /* @__PURE__ */ jsx20(
|
|
1128
1179
|
"a",
|
|
1129
1180
|
{
|
|
1130
1181
|
href: url,
|
|
@@ -1141,7 +1192,7 @@ function MusicBrainzRecordingLink({
|
|
|
1141
1192
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1142
1193
|
import { ArtistNames } from "@behindthemusictree/app-kit/genre-tree";
|
|
1143
1194
|
import { capitalize, useTrackNoun } from "@behindthemusictree/app-kit/track-noun";
|
|
1144
|
-
import { jsx as
|
|
1195
|
+
import { jsx as jsx21, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
1145
1196
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1146
1197
|
var SongPageSchema = PaginatedResponseSchema(SongDetailedSchema).extend({
|
|
1147
1198
|
overallTotal: z.number().nullable(),
|
|
@@ -1174,8 +1225,8 @@ function GenrePlaylistTracks({
|
|
|
1174
1225
|
}) {
|
|
1175
1226
|
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = useTrackList2();
|
|
1176
1227
|
const { session, sessionRestored } = useSession();
|
|
1177
|
-
const { playerTrackObject, playState, handlePlayPauseAction } =
|
|
1178
|
-
const { showPopup } =
|
|
1228
|
+
const { playerTrackObject, playState, handlePlayPauseAction } = usePlayer5();
|
|
1229
|
+
const { showPopup } = usePopup3();
|
|
1179
1230
|
const trackNoun = useTrackNoun();
|
|
1180
1231
|
const uuid = genrePlaylist?.uuid;
|
|
1181
1232
|
const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
|
|
@@ -1204,8 +1255,8 @@ function GenrePlaylistTracks({
|
|
|
1204
1255
|
retry: (failureCount, error) => failureCount < 1 && error instanceof DOMException && error.name === "AbortError",
|
|
1205
1256
|
retryDelay: 0
|
|
1206
1257
|
});
|
|
1207
|
-
const [sentinel, setSentinel] =
|
|
1208
|
-
|
|
1258
|
+
const [sentinel, setSentinel] = useState7(null);
|
|
1259
|
+
useEffect4(() => {
|
|
1209
1260
|
if (!hasNextPage || isFetchingNextPage || !sentinel) return;
|
|
1210
1261
|
const observer = new IntersectionObserver((entries) => {
|
|
1211
1262
|
if (entries.some((entry) => entry.isIntersecting)) {
|
|
@@ -1227,27 +1278,28 @@ function GenrePlaylistTracks({
|
|
|
1227
1278
|
}) : 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"));
|
|
1228
1279
|
started.catch((error) => {
|
|
1229
1280
|
console.error("Failed to play genre playlist:", error);
|
|
1230
|
-
|
|
1281
|
+
if (error instanceof TracksFailureAlreadyReportedError2) return;
|
|
1282
|
+
showPopup(/* @__PURE__ */ jsx21(InternalErrorPopup, { errorCode: error instanceof AppError2 ? error.code : ErrorCode2.CLIENT_UNKNOWN }));
|
|
1231
1283
|
});
|
|
1232
1284
|
};
|
|
1233
|
-
return /* @__PURE__ */
|
|
1285
|
+
return /* @__PURE__ */ jsx21(PanelSection, { title: `${capitalize(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ jsxs12("div", { children: [
|
|
1234
1286
|
renderTracksToolbar?.(),
|
|
1235
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */
|
|
1287
|
+
scope === "me" && !genrePlaylist ? /* @__PURE__ */ jsx21("p", { children: "\u2014" }) : isPending ? /* @__PURE__ */ jsx21(Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ jsxs12("p", { role: "alert", children: [
|
|
1236
1288
|
"Couldn't load ",
|
|
1237
1289
|
trackNoun.plural,
|
|
1238
1290
|
".",
|
|
1239
1291
|
" ",
|
|
1240
|
-
/* @__PURE__ */
|
|
1241
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */
|
|
1292
|
+
/* @__PURE__ */ jsx21("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1293
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ jsx21("p", { children: "\u2014" }) : /* @__PURE__ */ jsxs12("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1242
1294
|
tracks.map((track, index) => {
|
|
1243
1295
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1244
1296
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1245
1297
|
const isPlaying = isCurrent && playState === PlayStates.PLAYING;
|
|
1246
1298
|
const text = /* @__PURE__ */ jsxs12("span", { className: TEXT_CELL, children: [
|
|
1247
|
-
/* @__PURE__ */
|
|
1248
|
-
track.artists?.length ? /* @__PURE__ */
|
|
1249
|
-
/* @__PURE__ */
|
|
1250
|
-
track.album && /* @__PURE__ */
|
|
1299
|
+
/* @__PURE__ */ jsx21("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : isSong(track) ? /* @__PURE__ */ jsx21(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1300
|
+
track.artists?.length ? /* @__PURE__ */ jsx21("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1301
|
+
/* @__PURE__ */ jsx21("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ jsx21(ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1302
|
+
track.album && /* @__PURE__ */ jsx21("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1251
1303
|
] });
|
|
1252
1304
|
const leading = renderSongLeading?.(track, index);
|
|
1253
1305
|
const actions = renderSongActions?.(track);
|
|
@@ -1255,7 +1307,7 @@ function GenrePlaylistTracks({
|
|
|
1255
1307
|
if (isUnplayable) {
|
|
1256
1308
|
return /* @__PURE__ */ jsxs12("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1257
1309
|
leading,
|
|
1258
|
-
/* @__PURE__ */
|
|
1310
|
+
/* @__PURE__ */ jsx21(
|
|
1259
1311
|
"button",
|
|
1260
1312
|
{
|
|
1261
1313
|
type: "button",
|
|
@@ -1263,7 +1315,7 @@ function GenrePlaylistTracks({
|
|
|
1263
1315
|
"aria-disabled": "true",
|
|
1264
1316
|
"aria-label": label,
|
|
1265
1317
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1266
|
-
children: /* @__PURE__ */
|
|
1318
|
+
children: /* @__PURE__ */ jsx21(FaPlay, { size: 10 })
|
|
1267
1319
|
}
|
|
1268
1320
|
),
|
|
1269
1321
|
text,
|
|
@@ -1276,14 +1328,14 @@ function GenrePlaylistTracks({
|
|
|
1276
1328
|
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)]" : ""}`,
|
|
1277
1329
|
children: [
|
|
1278
1330
|
leading,
|
|
1279
|
-
/* @__PURE__ */
|
|
1331
|
+
/* @__PURE__ */ jsx21(
|
|
1280
1332
|
"button",
|
|
1281
1333
|
{
|
|
1282
1334
|
type: "button",
|
|
1283
1335
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1284
1336
|
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 !== PlayStates.STOPPED ? "opacity-100" : "opacity-0 [@media(pointer:coarse)]:opacity-100"}`,
|
|
1285
1337
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1286
|
-
children: isCurrent && playState === PlayStates.LOADING ? /* @__PURE__ */
|
|
1338
|
+
children: isCurrent && playState === PlayStates.LOADING ? /* @__PURE__ */ jsx21(RingLoader, { size: 10 }) : isPlaying ? /* @__PURE__ */ jsx21(FaPause, { size: 10 }) : /* @__PURE__ */ jsx21(FaPlay, { size: 10 })
|
|
1287
1339
|
}
|
|
1288
1340
|
),
|
|
1289
1341
|
text,
|
|
@@ -1293,7 +1345,7 @@ function GenrePlaylistTracks({
|
|
|
1293
1345
|
track.uuid
|
|
1294
1346
|
);
|
|
1295
1347
|
}),
|
|
1296
|
-
hasNextPage && /* @__PURE__ */
|
|
1348
|
+
hasNextPage && /* @__PURE__ */ jsx21("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1297
1349
|
] })
|
|
1298
1350
|
] }) });
|
|
1299
1351
|
}
|
|
@@ -1301,7 +1353,7 @@ function GenrePlaylistTracks({
|
|
|
1301
1353
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1302
1354
|
import { useTrackNoun as useTrackNoun2 } from "@behindthemusictree/app-kit/track-noun";
|
|
1303
1355
|
import { SiWikidata, SiWikipedia } from "react-icons/si";
|
|
1304
|
-
import { Fragment as
|
|
1356
|
+
import { Fragment as Fragment9, jsx as jsx22, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
1305
1357
|
function GenreDetailExtras({
|
|
1306
1358
|
genreUuid,
|
|
1307
1359
|
genrePlaylist,
|
|
@@ -1327,16 +1379,16 @@ function GenreDetailExtras({
|
|
|
1327
1379
|
criteriaOverviewSchema
|
|
1328
1380
|
);
|
|
1329
1381
|
if (isPending) {
|
|
1330
|
-
return /* @__PURE__ */ jsxs13(
|
|
1331
|
-
/* @__PURE__ */
|
|
1382
|
+
return /* @__PURE__ */ jsxs13(Fragment9, { children: [
|
|
1383
|
+
/* @__PURE__ */ jsx22(PanelSection2, { title: "Summary", children: /* @__PURE__ */ jsx22("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ jsx22(Skeleton2, { className: "h-4 w-3/4" }) }) }),
|
|
1332
1384
|
family
|
|
1333
1385
|
] });
|
|
1334
1386
|
}
|
|
1335
|
-
if (!overview) return /* @__PURE__ */
|
|
1387
|
+
if (!overview) return /* @__PURE__ */ jsx22(Fragment9, { children: family });
|
|
1336
1388
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1337
1389
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1338
|
-
return /* @__PURE__ */ jsxs13(
|
|
1339
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */
|
|
1390
|
+
return /* @__PURE__ */ jsxs13(Fragment9, { children: [
|
|
1391
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ jsx22(PanelSection2, { title: "Links", children: /* @__PURE__ */ jsxs13("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1340
1392
|
summarySourceUrl && /* @__PURE__ */ jsxs13(
|
|
1341
1393
|
"a",
|
|
1342
1394
|
{
|
|
@@ -1345,7 +1397,7 @@ function GenreDetailExtras({
|
|
|
1345
1397
|
rel: "noopener noreferrer",
|
|
1346
1398
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1347
1399
|
children: [
|
|
1348
|
-
/* @__PURE__ */
|
|
1400
|
+
/* @__PURE__ */ jsx22(SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1349
1401
|
"Wikipedia"
|
|
1350
1402
|
]
|
|
1351
1403
|
}
|
|
@@ -1358,17 +1410,17 @@ function GenreDetailExtras({
|
|
|
1358
1410
|
rel: "noopener noreferrer",
|
|
1359
1411
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1360
1412
|
children: [
|
|
1361
|
-
/* @__PURE__ */
|
|
1413
|
+
/* @__PURE__ */ jsx22(SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1362
1414
|
"Wikidata"
|
|
1363
1415
|
]
|
|
1364
1416
|
}
|
|
1365
1417
|
)
|
|
1366
1418
|
] }) }),
|
|
1367
|
-
/* @__PURE__ */
|
|
1419
|
+
/* @__PURE__ */ jsx22(PanelSection2, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ jsx22(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1368
1420
|
family,
|
|
1369
1421
|
renderGenreDetailExtras?.(overview),
|
|
1370
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */
|
|
1371
|
-
/* @__PURE__ */
|
|
1422
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ jsx22(PanelSection2, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ jsx22("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ jsx22("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ jsx22("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
1423
|
+
/* @__PURE__ */ jsx22(
|
|
1372
1424
|
GenrePlaylistTracks,
|
|
1373
1425
|
{
|
|
1374
1426
|
genreUuid,
|
|
@@ -1386,28 +1438,10 @@ function GenreDetailExtras({
|
|
|
1386
1438
|
}
|
|
1387
1439
|
|
|
1388
1440
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1389
|
-
import { Fragment as
|
|
1441
|
+
import { Fragment as Fragment10, jsx as jsx23, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
1390
1442
|
import { createElement } from "react";
|
|
1391
1443
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
1392
|
-
|
|
1393
|
-
const isCurrentTrackList = playback.playingNodeId === genrePlaylist.uuid;
|
|
1394
|
-
const handlePlayPause = () => {
|
|
1395
|
-
if (isCurrentTrackList) {
|
|
1396
|
-
setIsPlaying(!isPlaying);
|
|
1397
|
-
return;
|
|
1398
|
-
}
|
|
1399
|
-
playback.play(genrePlaylist).catch((error) => {
|
|
1400
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
1401
|
-
});
|
|
1402
|
-
};
|
|
1403
|
-
return /* @__PURE__ */ jsx19(
|
|
1404
|
-
GenreActionBand,
|
|
1405
|
-
{
|
|
1406
|
-
...bandProps,
|
|
1407
|
-
onPlayPause: ("genreOnlyTracksCount" in genrePlaylist ? genreMusicCount(genrePlaylist) : genrePlaylist.tracksCount) > 0 ? handlePlayPause : void 0,
|
|
1408
|
-
isPlaying: isCurrentTrackList && isPlaying
|
|
1409
|
-
}
|
|
1410
|
-
);
|
|
1444
|
+
return /* @__PURE__ */ jsx23(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ jsx23(GenrePlayActions, { genrePlaylist, playback }) });
|
|
1411
1445
|
}
|
|
1412
1446
|
function GenreInfoPanelBody({
|
|
1413
1447
|
toolbar,
|
|
@@ -1415,7 +1449,6 @@ function GenreInfoPanelBody({
|
|
|
1415
1449
|
genreUuid,
|
|
1416
1450
|
genrePlaylist,
|
|
1417
1451
|
catalogue,
|
|
1418
|
-
countsContext,
|
|
1419
1452
|
wikidataId,
|
|
1420
1453
|
scope,
|
|
1421
1454
|
getBackendBaseUrl,
|
|
@@ -1423,32 +1456,11 @@ function GenreInfoPanelBody({
|
|
|
1423
1456
|
band,
|
|
1424
1457
|
extras
|
|
1425
1458
|
}) {
|
|
1426
|
-
const noun = useTrackNoun3();
|
|
1427
1459
|
const summary = scope === "reference" ? GenreCatalogueCountsSchema2.parse(genrePlaylist ?? catalogue) : void 0;
|
|
1428
1460
|
const selection = summary ? defaultGenreMusicSelection2(summary) : void 0;
|
|
1429
|
-
|
|
1430
|
-
const scopes = counts.genreAndSubgenresTracksCount;
|
|
1431
|
-
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`;
|
|
1432
|
-
};
|
|
1433
|
-
return /* @__PURE__ */ jsxs14(Fragment9, { children: [
|
|
1461
|
+
return /* @__PURE__ */ jsxs14(Fragment10, { children: [
|
|
1434
1462
|
toolbar,
|
|
1435
|
-
genrePlaylist ? /* @__PURE__ */
|
|
1436
|
-
summary && catalogue && /* @__PURE__ */ jsxs14("div", { className: "px-3.5 py-3 text-body text-[var(--color-text)]", children: [
|
|
1437
|
-
/* @__PURE__ */ jsxs14("p", { children: [
|
|
1438
|
-
"Catalogue ",
|
|
1439
|
-
noun.plural,
|
|
1440
|
-
countsContext ? ` (${countsContext})` : "",
|
|
1441
|
-
": ",
|
|
1442
|
-
describeCounts(catalogue)
|
|
1443
|
-
] }),
|
|
1444
|
-
genrePlaylist && /* @__PURE__ */ jsxs14("p", { children: [
|
|
1445
|
-
"Playlist ",
|
|
1446
|
-
noun.plural,
|
|
1447
|
-
countsContext ? ` (${countsContext})` : "",
|
|
1448
|
-
": ",
|
|
1449
|
-
describeCounts(summary)
|
|
1450
|
-
] })
|
|
1451
|
-
] }),
|
|
1463
|
+
genrePlaylist ? /* @__PURE__ */ jsx23(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ jsx23(GenreActionBand, { ...band }),
|
|
1452
1464
|
/* @__PURE__ */ createElement(
|
|
1453
1465
|
GenreDetailExtras,
|
|
1454
1466
|
{
|
|
@@ -1468,7 +1480,7 @@ function GenreInfoPanelBody({
|
|
|
1468
1480
|
}
|
|
1469
1481
|
|
|
1470
1482
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
1471
|
-
import { Fragment as
|
|
1483
|
+
import { Fragment as Fragment11, jsx as jsx24, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
1472
1484
|
var RELATIVE_ITEM_COUNT = 1;
|
|
1473
1485
|
function toNode(genre, parentId) {
|
|
1474
1486
|
return {
|
|
@@ -1490,7 +1502,8 @@ function useGenreDetailContent({
|
|
|
1490
1502
|
playback: hostPlayback,
|
|
1491
1503
|
trailing,
|
|
1492
1504
|
genrePlaylist: hostPlaylist,
|
|
1493
|
-
expanded
|
|
1505
|
+
expanded,
|
|
1506
|
+
treeRelations
|
|
1494
1507
|
}) {
|
|
1495
1508
|
const { data: detail, isPending, isError } = useFetchGenreDetail(genreUuid, scope, getBackendBaseUrl);
|
|
1496
1509
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: [], artist: extras?.artist });
|
|
@@ -1498,12 +1511,19 @@ function useGenreDetailContent({
|
|
|
1498
1511
|
const view = useMemo6(() => {
|
|
1499
1512
|
if (!detail) return null;
|
|
1500
1513
|
const rootColor = getGenreTreeColor2(detail.root.wikidataId);
|
|
1514
|
+
const treeStyles = /* @__PURE__ */ new Map();
|
|
1515
|
+
if (treeRelations) {
|
|
1516
|
+
const drawn = [treeRelations, treeRelations.parentNode, ...treeRelations.childNodes, ...treeRelations.ancestorNodes];
|
|
1517
|
+
for (const entry of drawn) {
|
|
1518
|
+
if (entry) treeStyles.set(entry.node.id, { fill: entry.fill, textColor: entry.textColor });
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1501
1521
|
const relative = (genre, parentId) => ({
|
|
1502
1522
|
node: toNode(genre, parentId),
|
|
1503
|
-
fill: tintSurface(rootColor),
|
|
1504
|
-
textColor: TEXT_COLOR
|
|
1523
|
+
...treeStyles.get(genre.uuid) ?? { fill: tintSurface(rootColor), textColor: TEXT_COLOR }
|
|
1505
1524
|
});
|
|
1506
1525
|
const ancestors2 = [...detail.ascendants].sort((a, b) => b.degree - a.degree);
|
|
1526
|
+
const own = treeStyles.get(detail.uuid) ?? { fill: rootColor, textColor: getTextColorOnFill(rootColor) };
|
|
1507
1527
|
return {
|
|
1508
1528
|
node: {
|
|
1509
1529
|
id: detail.uuid,
|
|
@@ -1512,58 +1532,58 @@ function useGenreDetailContent({
|
|
|
1512
1532
|
itemCount: scope === "reference" ? genreMusicCount2(detail.criteriaPlaylist ? GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist) : GenreCatalogueCountsSchema3.parse(detail.catalogue)) : detail.tracksCount,
|
|
1513
1533
|
wikidataId: detail.wikidataId
|
|
1514
1534
|
},
|
|
1515
|
-
fill:
|
|
1535
|
+
fill: own.fill,
|
|
1536
|
+
textColor: own.textColor,
|
|
1516
1537
|
parentNode: detail.parent ? relative(detail.parent, null) : null,
|
|
1517
1538
|
childNodes: detail.children.map((child) => relative(child, detail.uuid)),
|
|
1518
1539
|
ancestorNodes: ancestors2.map(
|
|
1519
1540
|
({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
|
|
1520
1541
|
)
|
|
1521
1542
|
};
|
|
1522
|
-
}, [detail, scope]);
|
|
1543
|
+
}, [detail, scope, treeRelations]);
|
|
1523
1544
|
if (isError) return {
|
|
1524
1545
|
name: null,
|
|
1525
1546
|
title: "Genre unavailable",
|
|
1526
|
-
content: /* @__PURE__ */
|
|
1547
|
+
content: /* @__PURE__ */ jsx24("p", { role: "alert", className: "text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
1527
1548
|
};
|
|
1528
1549
|
if (isPending || !detail || !view) return {
|
|
1529
1550
|
name: null,
|
|
1530
1551
|
title: "Loading genre\u2026",
|
|
1531
|
-
content: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3
|
|
1532
|
-
/* @__PURE__ */
|
|
1533
|
-
/* @__PURE__ */
|
|
1534
|
-
/* @__PURE__ */
|
|
1552
|
+
content: /* @__PURE__ */ jsxs15("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
1553
|
+
/* @__PURE__ */ jsx24(Skeleton3, { className: "h-6 w-2/3" }),
|
|
1554
|
+
/* @__PURE__ */ jsx24(Skeleton3, { className: "h-4 w-full" }),
|
|
1555
|
+
/* @__PURE__ */ jsx24(Skeleton3, { className: "h-4 w-3/4" })
|
|
1535
1556
|
] })
|
|
1536
1557
|
};
|
|
1537
1558
|
const selectGenre = (nodeId) => onSelectGenre(GenreUuidSchema.parse(nodeId));
|
|
1538
|
-
const family = /* @__PURE__ */
|
|
1559
|
+
const family = /* @__PURE__ */ jsx24(
|
|
1539
1560
|
GenreNodeFamily,
|
|
1540
1561
|
{
|
|
1541
1562
|
node: view.node,
|
|
1542
1563
|
fill: view.fill,
|
|
1543
|
-
textColor:
|
|
1564
|
+
textColor: view.textColor,
|
|
1544
1565
|
parentNode: view.parentNode,
|
|
1545
1566
|
childNodes: view.childNodes,
|
|
1546
1567
|
onSelectNode: selectGenre
|
|
1547
1568
|
}
|
|
1548
1569
|
);
|
|
1549
|
-
const ancestors = /* @__PURE__ */
|
|
1570
|
+
const ancestors = /* @__PURE__ */ jsx24(GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
1550
1571
|
return {
|
|
1551
1572
|
name: detail.name,
|
|
1552
1573
|
title: detail.name,
|
|
1553
|
-
headerAccent: { background: view.fill, color:
|
|
1574
|
+
headerAccent: { background: view.fill, color: view.textColor },
|
|
1554
1575
|
aside: expanded ? ancestors : void 0,
|
|
1555
|
-
content: /* @__PURE__ */ jsxs15(
|
|
1556
|
-
/* @__PURE__ */
|
|
1576
|
+
content: /* @__PURE__ */ jsxs15(Fragment11, { children: [
|
|
1577
|
+
/* @__PURE__ */ jsx24(
|
|
1557
1578
|
GenreInfoPanelBody,
|
|
1558
1579
|
{
|
|
1559
|
-
family: /* @__PURE__ */ jsxs15(
|
|
1580
|
+
family: /* @__PURE__ */ jsxs15(Fragment11, { children: [
|
|
1560
1581
|
family,
|
|
1561
1582
|
!expanded && ancestors
|
|
1562
1583
|
] }),
|
|
1563
1584
|
genreUuid: detail.uuid,
|
|
1564
1585
|
genrePlaylist: hostPlaylist ?? (detail.criteriaPlaylist === null ? null : scope === "reference" ? { ...GenrePlaylistSummarySchema.parse(detail.criteriaPlaylist), criteria: CriteriaMinimumSchema.parse(detail) } : { ...detail.criteriaPlaylist, criteria: CriteriaMinimumSchema.parse(detail), tracksCount: detail.tracksCount }),
|
|
1565
1586
|
catalogue: detail.catalogue,
|
|
1566
|
-
countsContext: !hostPlaylist && extras?.artist ? "all artists" : void 0,
|
|
1567
1587
|
wikidataId: detail.wikidataId,
|
|
1568
1588
|
scope,
|
|
1569
1589
|
getBackendBaseUrl,
|
|
@@ -1601,7 +1621,7 @@ function GenreDetailPanel({
|
|
|
1601
1621
|
expanded,
|
|
1602
1622
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
1603
1623
|
});
|
|
1604
|
-
return /* @__PURE__ */
|
|
1624
|
+
return /* @__PURE__ */ jsx24(
|
|
1605
1625
|
DetailPanel,
|
|
1606
1626
|
{
|
|
1607
1627
|
side: "left",
|
|
@@ -1614,19 +1634,19 @@ function GenreDetailPanel({
|
|
|
1614
1634
|
edgeTab,
|
|
1615
1635
|
aside: panel.aside,
|
|
1616
1636
|
titleInSearch,
|
|
1617
|
-
headerActions: onExpandedChange ? /* @__PURE__ */
|
|
1637
|
+
headerActions: onExpandedChange ? /* @__PURE__ */ jsx24(IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ jsx24(Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ jsx24(Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
1618
1638
|
children: panel.content
|
|
1619
1639
|
}
|
|
1620
1640
|
);
|
|
1621
1641
|
}
|
|
1622
1642
|
|
|
1623
1643
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
1624
|
-
import { useEffect as
|
|
1644
|
+
import { useEffect as useEffect5, useMemo as useMemo7 } from "react";
|
|
1625
1645
|
import {
|
|
1626
1646
|
getReparentCandidates,
|
|
1627
1647
|
useUpdateGenre
|
|
1628
1648
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
1629
|
-
import { jsx as
|
|
1649
|
+
import { jsx as jsx25, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
1630
1650
|
function ChangeParentPopup({
|
|
1631
1651
|
genrePlaylist,
|
|
1632
1652
|
genrePlaylists,
|
|
@@ -1654,7 +1674,7 @@ function ChangeParentPopup({
|
|
|
1654
1674
|
}
|
|
1655
1675
|
);
|
|
1656
1676
|
};
|
|
1657
|
-
|
|
1677
|
+
useEffect5(() => {
|
|
1658
1678
|
const handleKeyDown = (event) => {
|
|
1659
1679
|
if (event.key === "Escape") onClose();
|
|
1660
1680
|
};
|
|
@@ -1666,7 +1686,7 @@ function ChangeParentPopup({
|
|
|
1666
1686
|
"Current parent: ",
|
|
1667
1687
|
genrePlaylist.parent?.name ?? "none"
|
|
1668
1688
|
] }),
|
|
1669
|
-
/* @__PURE__ */
|
|
1689
|
+
/* @__PURE__ */ jsx25("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ jsx25(
|
|
1670
1690
|
GenreSearch,
|
|
1671
1691
|
{
|
|
1672
1692
|
genrePlaylists: candidates,
|
|
@@ -1674,7 +1694,7 @@ function ChangeParentPopup({
|
|
|
1674
1694
|
placeholder: "Search a new parent\u2026"
|
|
1675
1695
|
}
|
|
1676
1696
|
) }),
|
|
1677
|
-
formErrors.length > 0 && /* @__PURE__ */
|
|
1697
|
+
formErrors.length > 0 && /* @__PURE__ */ jsx25("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
1678
1698
|
] });
|
|
1679
1699
|
}
|
|
1680
1700
|
|
|
@@ -1682,6 +1702,43 @@ function ChangeParentPopup({
|
|
|
1682
1702
|
import { Skeleton as Skeleton5 } from "@behindthemusictree/ui";
|
|
1683
1703
|
import { useArtist } from "@behindthemusictree/app-kit/genre-tree";
|
|
1684
1704
|
|
|
1705
|
+
// src/genre-tree/artist/ArtistActionBand.tsx
|
|
1706
|
+
import { Pause as Pause2, Play as Play2 } from "lucide-react";
|
|
1707
|
+
import { ActionBand as ActionBand2, ActionButton as ActionButton4, PanelBleed as PanelBleed2 } from "@behindthemusictree/ui";
|
|
1708
|
+
import { TrackListOriginType as TrackListOriginType2, useTrackList as useTrackList3 } from "@behindthemusictree/app-kit/genre-tree";
|
|
1709
|
+
import { usePlayer as usePlayer6 } from "@behindthemusictree/app-kit/player";
|
|
1710
|
+
import { jsx as jsx26, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
1711
|
+
function ArtistActionBand({ artist, share }) {
|
|
1712
|
+
const { trackList, playNewTrackListFromArtist } = useTrackList3();
|
|
1713
|
+
const { isPlaying, setIsPlaying } = usePlayer6();
|
|
1714
|
+
const origin = trackList?.origin;
|
|
1715
|
+
const isCurrent = origin?.type === TrackListOriginType2.ARTIST && origin.uuid === artist.uuid;
|
|
1716
|
+
const playing = isCurrent && isPlaying;
|
|
1717
|
+
const handleClick = () => {
|
|
1718
|
+
if (isCurrent) {
|
|
1719
|
+
setIsPlaying(!isPlaying);
|
|
1720
|
+
return;
|
|
1721
|
+
}
|
|
1722
|
+
playNewTrackListFromArtist({ uuid: artist.uuid, name: artist.name }, "reference", { ordering: "title" }).catch((error) => {
|
|
1723
|
+
console.error("Failed to load artist tracks:", error);
|
|
1724
|
+
});
|
|
1725
|
+
};
|
|
1726
|
+
return /* @__PURE__ */ jsx26(PanelBleed2, { children: /* @__PURE__ */ jsxs17(ActionBand2, { children: [
|
|
1727
|
+
/* @__PURE__ */ jsx26(
|
|
1728
|
+
ActionButton4,
|
|
1729
|
+
{
|
|
1730
|
+
icon: playing ? /* @__PURE__ */ jsx26(Pause2, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ jsx26(Play2, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1731
|
+
label: playing ? "Pause" : "Play",
|
|
1732
|
+
caption: String(artist.playableTracksCount),
|
|
1733
|
+
disabled: artist.playableTracksCount === 0,
|
|
1734
|
+
title: artist.playableTracksCount === 0 ? "No playable songs" : void 0,
|
|
1735
|
+
onClick: handleClick
|
|
1736
|
+
}
|
|
1737
|
+
),
|
|
1738
|
+
share
|
|
1739
|
+
] }) });
|
|
1740
|
+
}
|
|
1741
|
+
|
|
1685
1742
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
1686
1743
|
import { FieldList } from "@behindthemusictree/ui";
|
|
1687
1744
|
|
|
@@ -1698,7 +1755,7 @@ import {
|
|
|
1698
1755
|
SiYoutube
|
|
1699
1756
|
} from "react-icons/si";
|
|
1700
1757
|
import { Chip } from "@behindthemusictree/ui";
|
|
1701
|
-
import { jsx as
|
|
1758
|
+
import { jsx as jsx27 } from "react/jsx-runtime";
|
|
1702
1759
|
var LINK_KINDS = {
|
|
1703
1760
|
official: { label: "Official website", Icon: Globe },
|
|
1704
1761
|
wikipedia: { label: "Wikipedia", Icon: SiWikipedia2 },
|
|
@@ -1735,7 +1792,7 @@ function artistLinks(artist) {
|
|
|
1735
1792
|
return links;
|
|
1736
1793
|
}
|
|
1737
1794
|
function ArtistLinks({ links }) {
|
|
1738
|
-
return /* @__PURE__ */
|
|
1795
|
+
return /* @__PURE__ */ jsx27("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ jsx27("li", { children: /* @__PURE__ */ jsx27(Chip, { href: url, icon: /* @__PURE__ */ jsx27(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
1739
1796
|
}
|
|
1740
1797
|
|
|
1741
1798
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -1746,7 +1803,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
1746
1803
|
}
|
|
1747
1804
|
|
|
1748
1805
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
1749
|
-
import { jsx as
|
|
1806
|
+
import { jsx as jsx28 } from "react/jsx-runtime";
|
|
1750
1807
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
1751
1808
|
function ArtistHeader({ artist }) {
|
|
1752
1809
|
const fields = [];
|
|
@@ -1756,35 +1813,35 @@ function ArtistHeader({ artist }) {
|
|
|
1756
1813
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
1757
1814
|
if (years) fields.push({ label: "Active", value: years });
|
|
1758
1815
|
const links = artistLinks(artist);
|
|
1759
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */
|
|
1816
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ jsx28(ArtistLinks, { links }) });
|
|
1760
1817
|
if (fields.length === 0) return null;
|
|
1761
|
-
return /* @__PURE__ */
|
|
1818
|
+
return /* @__PURE__ */ jsx28(FieldList, { items: fields });
|
|
1762
1819
|
}
|
|
1763
1820
|
|
|
1764
1821
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
1765
|
-
import { jsx as
|
|
1822
|
+
import { jsx as jsx29, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
1766
1823
|
function ExternalLink({ href, children }) {
|
|
1767
|
-
return /* @__PURE__ */
|
|
1824
|
+
return /* @__PURE__ */ jsx29("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
1768
1825
|
}
|
|
1769
1826
|
function ArtistPhoto({ image, name }) {
|
|
1770
|
-
return /* @__PURE__ */
|
|
1771
|
-
/* @__PURE__ */
|
|
1772
|
-
/* @__PURE__ */
|
|
1827
|
+
return /* @__PURE__ */ jsxs18("figure", { className: "flex flex-col gap-1.5", children: [
|
|
1828
|
+
/* @__PURE__ */ jsx29("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
1829
|
+
/* @__PURE__ */ jsxs18("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
1773
1830
|
"Photo: ",
|
|
1774
|
-
/* @__PURE__ */
|
|
1831
|
+
/* @__PURE__ */ jsx29(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
1775
1832
|
",",
|
|
1776
1833
|
" ",
|
|
1777
|
-
image.licenseUrl ? /* @__PURE__ */
|
|
1834
|
+
image.licenseUrl ? /* @__PURE__ */ jsx29(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
1778
1835
|
] })
|
|
1779
1836
|
] });
|
|
1780
1837
|
}
|
|
1781
1838
|
|
|
1782
1839
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
1783
1840
|
import { PanelGroup, PanelSection as PanelSection3 } from "@behindthemusictree/ui";
|
|
1784
|
-
import { jsx as
|
|
1841
|
+
import { jsx as jsx30, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
1785
1842
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
1786
1843
|
if (memberships.length === 0) return null;
|
|
1787
|
-
return /* @__PURE__ */
|
|
1844
|
+
return /* @__PURE__ */ jsx30(PanelGroup, { title, children: /* @__PURE__ */ jsx30("ul", { children: memberships.map((membership, index) => {
|
|
1788
1845
|
const details = [
|
|
1789
1846
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
1790
1847
|
...membership.roles
|
|
@@ -1792,9 +1849,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
1792
1849
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
1793
1850
|
return (
|
|
1794
1851
|
// A member can have several periods in the same group.
|
|
1795
|
-
/* @__PURE__ */
|
|
1796
|
-
/* @__PURE__ */
|
|
1797
|
-
detailsText && /* @__PURE__ */
|
|
1852
|
+
/* @__PURE__ */ jsxs19("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
1853
|
+
/* @__PURE__ */ jsx30("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
1854
|
+
detailsText && /* @__PURE__ */ jsxs19("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
1798
1855
|
" \u2014 ",
|
|
1799
1856
|
detailsText
|
|
1800
1857
|
] })
|
|
@@ -1805,9 +1862,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
1805
1862
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
1806
1863
|
if (memberships.length === 0) return null;
|
|
1807
1864
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
1808
|
-
return /* @__PURE__ */
|
|
1809
|
-
/* @__PURE__ */
|
|
1810
|
-
/* @__PURE__ */
|
|
1865
|
+
return /* @__PURE__ */ jsxs19(PanelSection3, { title, children: [
|
|
1866
|
+
/* @__PURE__ */ jsx30(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
1867
|
+
/* @__PURE__ */ jsx30(
|
|
1811
1868
|
MembershipList,
|
|
1812
1869
|
{
|
|
1813
1870
|
title: "Past",
|
|
@@ -1820,7 +1877,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
1820
1877
|
|
|
1821
1878
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
1822
1879
|
import { PanelGroup as PanelGroup2, PanelSection as PanelSection4 } from "@behindthemusictree/ui";
|
|
1823
|
-
import { jsx as
|
|
1880
|
+
import { jsx as jsx31, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
1824
1881
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
1825
1882
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
1826
1883
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -1840,60 +1897,60 @@ function byYear(a, b) {
|
|
|
1840
1897
|
function ArtistDiscography({ albums }) {
|
|
1841
1898
|
if (albums.length === 0) return null;
|
|
1842
1899
|
const sorted = [...albums].sort(byYear);
|
|
1843
|
-
return /* @__PURE__ */
|
|
1900
|
+
return /* @__PURE__ */ jsx31(PanelSection4, { title: "Discography", children: GROUPS.map((group) => {
|
|
1844
1901
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
1845
1902
|
if (groupAlbums.length === 0) return null;
|
|
1846
|
-
return /* @__PURE__ */
|
|
1847
|
-
/* @__PURE__ */
|
|
1848
|
-
/* @__PURE__ */
|
|
1903
|
+
return /* @__PURE__ */ jsx31(PanelGroup2, { title: group, children: /* @__PURE__ */ jsx31("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ jsxs20("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
1904
|
+
/* @__PURE__ */ jsx31("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
1905
|
+
/* @__PURE__ */ jsx31("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
1849
1906
|
] }, album.uuid)) }) }, group);
|
|
1850
1907
|
}) });
|
|
1851
1908
|
}
|
|
1852
1909
|
|
|
1853
1910
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
1854
|
-
import { useState as
|
|
1911
|
+
import { useState as useState8 } from "react";
|
|
1855
1912
|
import { keepPreviousData } from "@tanstack/react-query";
|
|
1856
|
-
import { Play as
|
|
1913
|
+
import { Play as Play3 } from "lucide-react";
|
|
1857
1914
|
import { Pagination, PanelSection as PanelSection5, Skeleton as Skeleton4 } from "@behindthemusictree/ui";
|
|
1858
|
-
import { usePlayer as
|
|
1915
|
+
import { usePlayer as usePlayer9 } from "@behindthemusictree/app-kit/player";
|
|
1859
1916
|
import {
|
|
1860
1917
|
SongDetailedSchema as SongDetailedSchema2,
|
|
1861
1918
|
libraryEndpoints as libraryEndpoints2,
|
|
1862
1919
|
songUnplayableReason as songUnplayableReason3,
|
|
1863
|
-
useTrackList as
|
|
1920
|
+
useTrackList as useTrackList5
|
|
1864
1921
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
1865
1922
|
import { PaginatedResponseSchema as PaginatedResponseSchema2, usePlaybackQuery } from "@behindthemusictree/app-kit/transport";
|
|
1866
1923
|
|
|
1867
1924
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
1868
|
-
import { usePlayer as
|
|
1869
|
-
import { useTrackList as
|
|
1925
|
+
import { usePlayer as usePlayer8 } from "@behindthemusictree/app-kit/player";
|
|
1926
|
+
import { useTrackList as useTrackList4 } from "@behindthemusictree/app-kit/genre-tree";
|
|
1870
1927
|
|
|
1871
1928
|
// src/genre-tree/TrackPositionPlayPause.tsx
|
|
1872
1929
|
import { FaPlay as FaPlay2, FaPause as FaPause2 } from "react-icons/fa";
|
|
1873
|
-
import { usePlayer as
|
|
1930
|
+
import { usePlayer as usePlayer7 } from "@behindthemusictree/app-kit/player";
|
|
1874
1931
|
import { PlayStates as PlayStates2 } from "@behindthemusictree/app-kit/player";
|
|
1875
|
-
import { jsx as
|
|
1932
|
+
import { jsx as jsx32, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
1876
1933
|
function TrackPositionPlayPause({
|
|
1877
1934
|
position,
|
|
1878
1935
|
uuid,
|
|
1879
1936
|
handlePlayPauseClick,
|
|
1880
1937
|
isSelected = false
|
|
1881
1938
|
}) {
|
|
1882
|
-
const { playerTrackObject, playbackConfirmedTrackId, playState, isLoading: isPlayerLoading } =
|
|
1939
|
+
const { playerTrackObject, playbackConfirmedTrackId, playState, isLoading: isPlayerLoading } = usePlayer7();
|
|
1883
1940
|
const isThisTrack = playerTrackObject?.track.id === uuid;
|
|
1884
1941
|
const isConfirmedPlayable = playbackConfirmedTrackId === uuid;
|
|
1885
1942
|
const isAwaitingPlayback = (isSelected || isThisTrack) && !isConfirmedPlayable && !(isThisTrack && playerTrackObject?.loadError) && (!isThisTrack || isPlayerLoading || playState === PlayStates2.LOADING || playState === PlayStates2.PLAYING);
|
|
1886
1943
|
const isPlaying = isThisTrack && isConfirmedPlayable && playState === PlayStates2.PLAYING;
|
|
1887
1944
|
const isPaused = isThisTrack && isConfirmedPlayable && playState === PlayStates2.PAUSED;
|
|
1888
1945
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
1889
|
-
return /* @__PURE__ */
|
|
1946
|
+
return /* @__PURE__ */ jsxs21(
|
|
1890
1947
|
"div",
|
|
1891
1948
|
{
|
|
1892
1949
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
1893
1950
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
1894
1951
|
onClick: handlePlayPauseClick,
|
|
1895
1952
|
children: [
|
|
1896
|
-
/* @__PURE__ */
|
|
1953
|
+
/* @__PURE__ */ jsx32("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ jsx32("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ jsxs21(
|
|
1897
1954
|
"span",
|
|
1898
1955
|
{
|
|
1899
1956
|
className: "track-position-play-pause__bars",
|
|
@@ -1901,18 +1958,18 @@ function TrackPositionPlayPause({
|
|
|
1901
1958
|
role: "img",
|
|
1902
1959
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
1903
1960
|
children: [
|
|
1904
|
-
/* @__PURE__ */
|
|
1905
|
-
/* @__PURE__ */
|
|
1906
|
-
/* @__PURE__ */
|
|
1961
|
+
/* @__PURE__ */ jsx32("span", { className: "track-position-play-pause__bar" }),
|
|
1962
|
+
/* @__PURE__ */ jsx32("span", { className: "track-position-play-pause__bar" }),
|
|
1963
|
+
/* @__PURE__ */ jsx32("span", { className: "track-position-play-pause__bar" })
|
|
1907
1964
|
]
|
|
1908
1965
|
}
|
|
1909
1966
|
) : position }),
|
|
1910
|
-
/* @__PURE__ */
|
|
1967
|
+
/* @__PURE__ */ jsx32(
|
|
1911
1968
|
"div",
|
|
1912
1969
|
{
|
|
1913
1970
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
1914
1971
|
"aria-hidden": "true",
|
|
1915
|
-
children: isAwaitingPlayback ? /* @__PURE__ */
|
|
1972
|
+
children: isAwaitingPlayback ? /* @__PURE__ */ jsx32("span", { className: "track-position-play-pause__spinner" }) : isPlaying ? /* @__PURE__ */ jsx32(FaPause2, {}) : /* @__PURE__ */ jsx32(FaPlay2, {})
|
|
1916
1973
|
}
|
|
1917
1974
|
)
|
|
1918
1975
|
]
|
|
@@ -1923,7 +1980,7 @@ function TrackPositionPlayPause({
|
|
|
1923
1980
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
1924
1981
|
import { isSong as isSong2, songUnplayableReason as songUnplayableReason2 } from "@behindthemusictree/app-kit/genre-tree";
|
|
1925
1982
|
import { ArtistNames as ArtistNames2 } from "@behindthemusictree/app-kit/genre-tree";
|
|
1926
|
-
import { jsx as
|
|
1983
|
+
import { jsx as jsx33, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
1927
1984
|
function TrackItem({
|
|
1928
1985
|
track,
|
|
1929
1986
|
position,
|
|
@@ -1932,8 +1989,8 @@ function TrackItem({
|
|
|
1932
1989
|
renderArtistLink,
|
|
1933
1990
|
renderSongLink
|
|
1934
1991
|
}) {
|
|
1935
|
-
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } =
|
|
1936
|
-
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } =
|
|
1992
|
+
const { handlePlayPauseAction, playerTrackObject, loadTrackForPlayer } = usePlayer8();
|
|
1993
|
+
const { trackList, selectedTrack, toTrackAtPosition, runtimeUnplayableTrackIds } = useTrackList4();
|
|
1937
1994
|
const scope = trackList?.origin?.scope ?? null;
|
|
1938
1995
|
const isCurrentTrack = playerTrackObject?.track.id === track.uuid;
|
|
1939
1996
|
const hasPlaybackError = isCurrentTrack && !!playerTrackObject?.loadError;
|
|
@@ -1947,12 +2004,12 @@ function TrackItem({
|
|
|
1947
2004
|
loadTrackForPlayer(track.uuid);
|
|
1948
2005
|
}
|
|
1949
2006
|
};
|
|
1950
|
-
return /* @__PURE__ */
|
|
2007
|
+
return /* @__PURE__ */ jsxs22(
|
|
1951
2008
|
"div",
|
|
1952
2009
|
{
|
|
1953
2010
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
1954
2011
|
children: [
|
|
1955
|
-
isUnplayable ? /* @__PURE__ */
|
|
2012
|
+
isUnplayable ? /* @__PURE__ */ jsx33(
|
|
1956
2013
|
"div",
|
|
1957
2014
|
{
|
|
1958
2015
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -1960,7 +2017,7 @@ function TrackItem({
|
|
|
1960
2017
|
"aria-disabled": "true",
|
|
1961
2018
|
children: position
|
|
1962
2019
|
}
|
|
1963
|
-
) : /* @__PURE__ */
|
|
2020
|
+
) : /* @__PURE__ */ jsx33(
|
|
1964
2021
|
TrackPositionPlayPause,
|
|
1965
2022
|
{
|
|
1966
2023
|
position,
|
|
@@ -1969,12 +2026,12 @@ function TrackItem({
|
|
|
1969
2026
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
1970
2027
|
}
|
|
1971
2028
|
),
|
|
1972
|
-
/* @__PURE__ */
|
|
1973
|
-
/* @__PURE__ */
|
|
1974
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */
|
|
2029
|
+
/* @__PURE__ */ jsxs22("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2030
|
+
/* @__PURE__ */ jsx33("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ jsx33("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : isSong2(track) ? /* @__PURE__ */ jsx33(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2031
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ jsx33("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ jsx33(ArtistNames2, { artists: track.artists, renderArtistLink }) }) : ""
|
|
1975
2032
|
] }),
|
|
1976
|
-
/* @__PURE__ */
|
|
1977
|
-
renderDuration && /* @__PURE__ */
|
|
2033
|
+
/* @__PURE__ */ jsx33("div", { className: "genre-name-container flex items-center justify-start w-[21.6%] min-w-0 shrink-0", children: track.genre ? /* @__PURE__ */ jsx33("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2034
|
+
renderDuration && /* @__PURE__ */ jsx33(
|
|
1978
2035
|
"div",
|
|
1979
2036
|
{
|
|
1980
2037
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -1982,24 +2039,24 @@ function TrackItem({
|
|
|
1982
2039
|
children: renderDuration(track)
|
|
1983
2040
|
}
|
|
1984
2041
|
),
|
|
1985
|
-
renderActions && /* @__PURE__ */
|
|
2042
|
+
renderActions && /* @__PURE__ */ jsx33("div", { className: "edit flex text-base w-6 items-center justify-center mr-2 cursor-pointer", children: renderActions(track) })
|
|
1986
2043
|
]
|
|
1987
2044
|
}
|
|
1988
2045
|
);
|
|
1989
2046
|
}
|
|
1990
2047
|
|
|
1991
2048
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
1992
|
-
import { Fragment as
|
|
2049
|
+
import { Fragment as Fragment12, jsx as jsx34, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
1993
2050
|
var SongPageSchema2 = PaginatedResponseSchema2(SongDetailedSchema2);
|
|
1994
2051
|
var SORTS = [
|
|
1995
2052
|
{ ordering: "title", label: "Title" },
|
|
1996
2053
|
{ ordering: "-albumYear", label: "Year" }
|
|
1997
2054
|
];
|
|
1998
2055
|
function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLink }) {
|
|
1999
|
-
const [page, setPage] =
|
|
2000
|
-
const [ordering, setOrdering] =
|
|
2001
|
-
const { playNewTrackListFromArtist } =
|
|
2002
|
-
const { playerTrackObject } =
|
|
2056
|
+
const [page, setPage] = useState8(1);
|
|
2057
|
+
const [ordering, setOrdering] = useState8("title");
|
|
2058
|
+
const { playNewTrackListFromArtist } = useTrackList5();
|
|
2059
|
+
const { playerTrackObject } = usePlayer9();
|
|
2003
2060
|
const { data, isPending, isError } = usePlaybackQuery({
|
|
2004
2061
|
getBackendBaseUrl,
|
|
2005
2062
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
@@ -2022,21 +2079,21 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2022
2079
|
event.stopPropagation();
|
|
2023
2080
|
void play(song.uuid);
|
|
2024
2081
|
};
|
|
2025
|
-
return /* @__PURE__ */
|
|
2026
|
-
/* @__PURE__ */
|
|
2027
|
-
/* @__PURE__ */
|
|
2082
|
+
return /* @__PURE__ */ jsx34(PanelSection5, { title: "Songs", children: isPending ? /* @__PURE__ */ jsx34(Skeleton4, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ jsx34("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ jsx34("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ jsxs23(Fragment12, { children: [
|
|
2083
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-2", children: [
|
|
2084
|
+
/* @__PURE__ */ jsxs23(
|
|
2028
2085
|
"button",
|
|
2029
2086
|
{
|
|
2030
2087
|
type: "button",
|
|
2031
2088
|
onClick: () => void play(),
|
|
2032
2089
|
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",
|
|
2033
2090
|
children: [
|
|
2034
|
-
/* @__PURE__ */
|
|
2091
|
+
/* @__PURE__ */ jsx34(Play3, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2035
2092
|
"Play all"
|
|
2036
2093
|
]
|
|
2037
2094
|
}
|
|
2038
2095
|
),
|
|
2039
|
-
/* @__PURE__ */
|
|
2096
|
+
/* @__PURE__ */ jsx34("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ jsx34(
|
|
2040
2097
|
"button",
|
|
2041
2098
|
{
|
|
2042
2099
|
type: "button",
|
|
@@ -2051,7 +2108,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2051
2108
|
sort.ordering
|
|
2052
2109
|
)) })
|
|
2053
2110
|
] }),
|
|
2054
|
-
/* @__PURE__ */
|
|
2111
|
+
/* @__PURE__ */ jsx34("ul", { className: "overflow-hidden mb-2 bg-zinc-950 rounded-lg", children: data.results.map((song, index) => /* @__PURE__ */ jsx34("li", { onClickCapture: (event) => handleRowClickCapture(event, song), children: /* @__PURE__ */ jsx34(
|
|
2055
2112
|
TrackItem,
|
|
2056
2113
|
{
|
|
2057
2114
|
track: song,
|
|
@@ -2060,12 +2117,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2060
2117
|
renderSongLink
|
|
2061
2118
|
}
|
|
2062
2119
|
) }, song.uuid)) }),
|
|
2063
|
-
/* @__PURE__ */
|
|
2120
|
+
/* @__PURE__ */ jsx34(Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2064
2121
|
] }) });
|
|
2065
2122
|
}
|
|
2066
2123
|
|
|
2067
2124
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2068
|
-
import { Fragment as
|
|
2125
|
+
import { Fragment as Fragment13, jsx as jsx35, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
2069
2126
|
function useArtistPanel({
|
|
2070
2127
|
uuid,
|
|
2071
2128
|
scope,
|
|
@@ -2086,26 +2143,26 @@ function useArtistPanel({
|
|
|
2086
2143
|
return {
|
|
2087
2144
|
...panel,
|
|
2088
2145
|
title: "Artist",
|
|
2089
|
-
content: /* @__PURE__ */
|
|
2090
|
-
/* @__PURE__ */
|
|
2091
|
-
/* @__PURE__ */
|
|
2092
|
-
/* @__PURE__ */
|
|
2093
|
-
/* @__PURE__ */
|
|
2094
|
-
/* @__PURE__ */
|
|
2095
|
-
/* @__PURE__ */
|
|
2146
|
+
content: /* @__PURE__ */ jsxs24("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2147
|
+
/* @__PURE__ */ jsx35(Skeleton5, { className: "h-3 w-16" }),
|
|
2148
|
+
/* @__PURE__ */ jsx35(Skeleton5, { className: "h-4 w-32" }),
|
|
2149
|
+
/* @__PURE__ */ jsx35(Skeleton5, { className: "h-3 w-16" }),
|
|
2150
|
+
/* @__PURE__ */ jsx35(Skeleton5, { className: "h-4 w-24" }),
|
|
2151
|
+
/* @__PURE__ */ jsx35(Skeleton5, { className: "h-16 mt-2.5" }),
|
|
2152
|
+
/* @__PURE__ */ jsx35(Skeleton5, { className: "h-16" })
|
|
2096
2153
|
] })
|
|
2097
2154
|
};
|
|
2098
2155
|
case "not-found":
|
|
2099
2156
|
return {
|
|
2100
2157
|
...panel,
|
|
2101
2158
|
title: "Artist not found",
|
|
2102
|
-
content: /* @__PURE__ */
|
|
2159
|
+
content: /* @__PURE__ */ jsx35("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2103
2160
|
};
|
|
2104
2161
|
case "error":
|
|
2105
2162
|
return {
|
|
2106
2163
|
...panel,
|
|
2107
2164
|
title: "Artist",
|
|
2108
|
-
content: /* @__PURE__ */
|
|
2165
|
+
content: /* @__PURE__ */ jsx35("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2109
2166
|
};
|
|
2110
2167
|
case "success": {
|
|
2111
2168
|
const { artist } = result;
|
|
@@ -2114,13 +2171,19 @@ function useArtistPanel({
|
|
|
2114
2171
|
return {
|
|
2115
2172
|
...panel,
|
|
2116
2173
|
title: artist.name,
|
|
2117
|
-
content: /* @__PURE__ */
|
|
2118
|
-
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2123
|
-
|
|
2174
|
+
content: /* @__PURE__ */ jsxs24(Fragment13, { children: [
|
|
2175
|
+
/* @__PURE__ */ jsx35(
|
|
2176
|
+
ArtistActionBand,
|
|
2177
|
+
{
|
|
2178
|
+
artist,
|
|
2179
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ jsx35(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2180
|
+
}
|
|
2181
|
+
),
|
|
2182
|
+
artist.image && /* @__PURE__ */ jsx35(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2183
|
+
/* @__PURE__ */ jsx35(ArtistHeader, { artist }),
|
|
2184
|
+
/* @__PURE__ */ jsx35(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2185
|
+
/* @__PURE__ */ jsx35(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2186
|
+
artist.tracksCount > 0 && /* @__PURE__ */ jsx35(
|
|
2124
2187
|
ArtistSongs,
|
|
2125
2188
|
{
|
|
2126
2189
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2130,7 +2193,7 @@ function useArtistPanel({
|
|
|
2130
2193
|
}
|
|
2131
2194
|
)
|
|
2132
2195
|
] }),
|
|
2133
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */
|
|
2196
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ jsx35(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2134
2197
|
};
|
|
2135
2198
|
}
|
|
2136
2199
|
}
|
|
@@ -2143,59 +2206,52 @@ import {
|
|
|
2143
2206
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
2144
2207
|
|
|
2145
2208
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2146
|
-
import { useState as
|
|
2147
|
-
import { Pause as
|
|
2148
|
-
import { FieldList as FieldList2, PanelSection as PanelSection6, Skeleton as Skeleton6 } from "@behindthemusictree/ui";
|
|
2149
|
-
import { PlayStates as PlayStates3, usePlayer as
|
|
2209
|
+
import { useState as useState9 } from "react";
|
|
2210
|
+
import { Pause as Pause3, Play as Play4 } from "lucide-react";
|
|
2211
|
+
import { ActionBand as ActionBand3, ActionButton as ActionButton5, FieldList as FieldList2, PANEL_LABEL_CLASS, PanelBleed as PanelBleed3, PanelSection as PanelSection6, Skeleton as Skeleton6 } from "@behindthemusictree/ui";
|
|
2212
|
+
import { PlayStates as PlayStates3, usePlayer as usePlayer10 } from "@behindthemusictree/app-kit/player";
|
|
2150
2213
|
import {
|
|
2151
2214
|
ArtistNames as ArtistNames3,
|
|
2152
2215
|
musicBrainzRecordingUrl as musicBrainzRecordingUrl2,
|
|
2153
2216
|
songUnplayableReason as songUnplayableReason4,
|
|
2154
2217
|
useSongHistory,
|
|
2155
|
-
useTrackList as
|
|
2218
|
+
useTrackList as useTrackList6
|
|
2156
2219
|
} from "@behindthemusictree/app-kit/genre-tree";
|
|
2157
|
-
import { Fragment as
|
|
2220
|
+
import { Fragment as Fragment14, jsx as jsx36, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
2158
2221
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2159
2222
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2160
2223
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
2161
2224
|
function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
2162
|
-
const [open, setOpen] =
|
|
2225
|
+
const [open, setOpen] = useState9(false);
|
|
2163
2226
|
const history = useSongHistory(uuid, getBackendBaseUrl, open);
|
|
2164
2227
|
let body = null;
|
|
2165
|
-
if (history.status === "loading") body = /* @__PURE__ */
|
|
2166
|
-
else if (history.status === "error") body = /* @__PURE__ */
|
|
2228
|
+
if (history.status === "loading") body = /* @__PURE__ */ jsx36(Skeleton6, { className: "h-10", "aria-busy": "true" });
|
|
2229
|
+
else if (history.status === "error") body = /* @__PURE__ */ jsx36("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2167
2230
|
else if (history.status === "success")
|
|
2168
|
-
body = history.entries.length === 0 ? /* @__PURE__ */
|
|
2169
|
-
/* @__PURE__ */
|
|
2170
|
-
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */
|
|
2231
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ jsx36("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ jsx36("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ jsxs25("li", { className: "py-1.5 text-body", children: [
|
|
2232
|
+
/* @__PURE__ */ jsx36("span", { className: "font-medium", children: entry.action }),
|
|
2233
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ jsxs25("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2171
2234
|
" ",
|
|
2172
2235
|
"\u2014 ",
|
|
2173
2236
|
entry.oldValue ?? "none",
|
|
2174
2237
|
" \u2192 ",
|
|
2175
2238
|
entry.newValue ?? "none"
|
|
2176
2239
|
] }) : null,
|
|
2177
|
-
/* @__PURE__ */
|
|
2240
|
+
/* @__PURE__ */ jsxs25("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2178
2241
|
entry.actorPseudo ?? "Anonymous",
|
|
2179
2242
|
" \xB7 ",
|
|
2180
2243
|
dateFormat.format(new Date(entry.createdOn))
|
|
2181
2244
|
] })
|
|
2182
2245
|
] }, entry.uuid)) });
|
|
2183
|
-
return /* @__PURE__ */
|
|
2184
|
-
"
|
|
2185
|
-
{
|
|
2186
|
-
|
|
2187
|
-
className: "px-6 pb-2.5 mt-2.5 border-t border-[var(--color-border)]",
|
|
2188
|
-
children: [
|
|
2189
|
-
/* @__PURE__ */ jsx31("summary", { className: "mt-2.5 cursor-pointer text-[0.6875rem] font-semibold uppercase text-[var(--color-text-muted)]", children: "History" }),
|
|
2190
|
-
/* @__PURE__ */ jsx31("div", { className: "mt-1.5", children: body })
|
|
2191
|
-
]
|
|
2192
|
-
}
|
|
2193
|
-
);
|
|
2246
|
+
return /* @__PURE__ */ jsx36(PanelBleed3, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ jsxs25("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2247
|
+
/* @__PURE__ */ jsx36("summary", { className: `mt-2.5 cursor-pointer ${PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2248
|
+
/* @__PURE__ */ jsx36("div", { className: "mt-1.5", children: body })
|
|
2249
|
+
] }) });
|
|
2194
2250
|
}
|
|
2195
2251
|
function SongPanelContent(props) {
|
|
2196
2252
|
const { song, scope, getBackendBaseUrl, shareUrl, renderArtistLink } = props;
|
|
2197
|
-
const { playNewTrackListFromTrackUuid } =
|
|
2198
|
-
const { playerTrackObject, playState, handlePlayPauseAction } =
|
|
2253
|
+
const { playNewTrackListFromTrackUuid } = useTrackList6();
|
|
2254
|
+
const { playerTrackObject, playState, handlePlayPauseAction } = usePlayer10();
|
|
2199
2255
|
const unplayableReason = songUnplayableReason4(song);
|
|
2200
2256
|
const isCurrent = playerTrackObject?.track.id === song.uuid;
|
|
2201
2257
|
const isPlaying = isCurrent && playState === PlayStates3.PLAYING;
|
|
@@ -2208,13 +2264,13 @@ function SongPanelContent(props) {
|
|
|
2208
2264
|
const genre = song.genre;
|
|
2209
2265
|
fields.push({
|
|
2210
2266
|
label: "Genre",
|
|
2211
|
-
value: onSelectGenre ? /* @__PURE__ */
|
|
2212
|
-
index > 0 && /* @__PURE__ */
|
|
2213
|
-
/* @__PURE__ */
|
|
2267
|
+
value: onSelectGenre ? /* @__PURE__ */ jsx36("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ jsx36("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ jsxs25("span", { children: [
|
|
2268
|
+
index > 0 && /* @__PURE__ */ jsx36("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2269
|
+
/* @__PURE__ */ jsx36("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2214
2270
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2215
2271
|
});
|
|
2216
2272
|
} else {
|
|
2217
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */
|
|
2273
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ jsx36("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2218
2274
|
}
|
|
2219
2275
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2220
2276
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2224,11 +2280,11 @@ function SongPanelContent(props) {
|
|
|
2224
2280
|
const links = [];
|
|
2225
2281
|
if (musicBrainzUrl)
|
|
2226
2282
|
links.push(
|
|
2227
|
-
/* @__PURE__ */
|
|
2283
|
+
/* @__PURE__ */ jsx36("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2228
2284
|
);
|
|
2229
2285
|
if (song.youtubeVideo)
|
|
2230
2286
|
links.push(
|
|
2231
|
-
/* @__PURE__ */
|
|
2287
|
+
/* @__PURE__ */ jsx36(
|
|
2232
2288
|
"a",
|
|
2233
2289
|
{
|
|
2234
2290
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2243,33 +2299,31 @@ function SongPanelContent(props) {
|
|
|
2243
2299
|
if (links.length > 0)
|
|
2244
2300
|
fields.push({
|
|
2245
2301
|
label: "Links",
|
|
2246
|
-
value: /* @__PURE__ */
|
|
2302
|
+
value: /* @__PURE__ */ jsx36("span", { className: "flex gap-3", children: links })
|
|
2247
2303
|
});
|
|
2248
|
-
return /* @__PURE__ */
|
|
2249
|
-
/* @__PURE__ */
|
|
2250
|
-
|
|
2251
|
-
|
|
2304
|
+
return /* @__PURE__ */ jsxs25(Fragment14, { children: [
|
|
2305
|
+
/* @__PURE__ */ jsx36(PanelBleed3, { children: /* @__PURE__ */ jsxs25(ActionBand3, { children: [
|
|
2306
|
+
/* @__PURE__ */ jsx36(
|
|
2307
|
+
ActionButton5,
|
|
2252
2308
|
{
|
|
2253
|
-
|
|
2254
|
-
|
|
2255
|
-
|
|
2256
|
-
|
|
2257
|
-
|
|
2258
|
-
isPlaying ? "Pause" : "Play"
|
|
2259
|
-
]
|
|
2309
|
+
icon: isPlaying ? /* @__PURE__ */ jsx36(Pause3, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ jsx36(Play4, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2310
|
+
label: isPlaying ? "Pause" : "Play",
|
|
2311
|
+
disabled: !!unplayableReason,
|
|
2312
|
+
title: unplayableReason ?? void 0,
|
|
2313
|
+
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2260
2314
|
}
|
|
2261
2315
|
),
|
|
2262
|
-
shareUrl && /* @__PURE__ */
|
|
2316
|
+
shareUrl && /* @__PURE__ */ jsx36(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2263
2317
|
] }) }),
|
|
2264
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */
|
|
2265
|
-
/* @__PURE__ */
|
|
2266
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */
|
|
2267
|
-
/* @__PURE__ */
|
|
2318
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ jsx36("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ jsx36(ArtistNames3, { artists: song.artists, renderArtistLink }) }),
|
|
2319
|
+
/* @__PURE__ */ jsx36(FieldList2, { items: fields }),
|
|
2320
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ jsx36(PanelSection6, { title: "Essential in", children: /* @__PURE__ */ jsx36("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ jsx36("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2321
|
+
/* @__PURE__ */ jsx36(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2268
2322
|
] });
|
|
2269
2323
|
}
|
|
2270
2324
|
|
|
2271
2325
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2272
|
-
import { jsx as
|
|
2326
|
+
import { jsx as jsx37, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
2273
2327
|
function useSongPanel({
|
|
2274
2328
|
uuid,
|
|
2275
2329
|
scope,
|
|
@@ -2290,24 +2344,24 @@ function useSongPanel({
|
|
|
2290
2344
|
return {
|
|
2291
2345
|
...panel,
|
|
2292
2346
|
title: "Song",
|
|
2293
|
-
content: /* @__PURE__ */
|
|
2294
|
-
/* @__PURE__ */
|
|
2295
|
-
/* @__PURE__ */
|
|
2296
|
-
/* @__PURE__ */
|
|
2297
|
-
/* @__PURE__ */
|
|
2347
|
+
content: /* @__PURE__ */ jsxs26("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2348
|
+
/* @__PURE__ */ jsx37(Skeleton7, { className: "h-3 w-16" }),
|
|
2349
|
+
/* @__PURE__ */ jsx37(Skeleton7, { className: "h-4 w-32" }),
|
|
2350
|
+
/* @__PURE__ */ jsx37(Skeleton7, { className: "h-3 w-16" }),
|
|
2351
|
+
/* @__PURE__ */ jsx37(Skeleton7, { className: "h-4 w-24" })
|
|
2298
2352
|
] })
|
|
2299
2353
|
};
|
|
2300
2354
|
case "not-found":
|
|
2301
2355
|
return {
|
|
2302
2356
|
...panel,
|
|
2303
2357
|
title: "Song not found",
|
|
2304
|
-
content: /* @__PURE__ */
|
|
2358
|
+
content: /* @__PURE__ */ jsx37("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2305
2359
|
};
|
|
2306
2360
|
case "error":
|
|
2307
2361
|
return {
|
|
2308
2362
|
...panel,
|
|
2309
2363
|
title: "Song",
|
|
2310
|
-
content: /* @__PURE__ */
|
|
2364
|
+
content: /* @__PURE__ */ jsx37("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2311
2365
|
};
|
|
2312
2366
|
case "success": {
|
|
2313
2367
|
const { song } = result;
|
|
@@ -2315,7 +2369,7 @@ function useSongPanel({
|
|
|
2315
2369
|
return {
|
|
2316
2370
|
...panel,
|
|
2317
2371
|
title: song.title,
|
|
2318
|
-
content: /* @__PURE__ */
|
|
2372
|
+
content: /* @__PURE__ */ jsx37(
|
|
2319
2373
|
SongPanelContent,
|
|
2320
2374
|
{
|
|
2321
2375
|
song,
|
|
@@ -2368,12 +2422,12 @@ function useEntityPanel({
|
|
|
2368
2422
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2369
2423
|
import { MdMusicNote, MdVisibility } from "react-icons/md";
|
|
2370
2424
|
import { SegmentedControl } from "@behindthemusictree/ui";
|
|
2371
|
-
import { jsx as
|
|
2425
|
+
import { jsx as jsx38 } from "react/jsx-runtime";
|
|
2372
2426
|
function SizeMetricToggle({
|
|
2373
2427
|
value,
|
|
2374
2428
|
onChange
|
|
2375
2429
|
}) {
|
|
2376
|
-
return /* @__PURE__ */
|
|
2430
|
+
return /* @__PURE__ */ jsx38(
|
|
2377
2431
|
SegmentedControl,
|
|
2378
2432
|
{
|
|
2379
2433
|
variant: "floating",
|
|
@@ -2381,15 +2435,15 @@ function SizeMetricToggle({
|
|
|
2381
2435
|
value,
|
|
2382
2436
|
onChange,
|
|
2383
2437
|
options: [
|
|
2384
|
-
{ value: "songs", label: /* @__PURE__ */
|
|
2385
|
-
{ value: "views", label: /* @__PURE__ */
|
|
2438
|
+
{ value: "songs", label: /* @__PURE__ */ jsx38(MdMusicNote, { size: 18, "aria-hidden": true }), "aria-label": "Size by songs", title: "Node size by song count" },
|
|
2439
|
+
{ value: "views", label: /* @__PURE__ */ jsx38(MdVisibility, { size: 18, "aria-hidden": true }), "aria-label": "Size by views", title: "Node size by song views" }
|
|
2386
2440
|
]
|
|
2387
2441
|
}
|
|
2388
2442
|
);
|
|
2389
2443
|
}
|
|
2390
2444
|
|
|
2391
2445
|
// src/genre-tree/GenreTreeView.tsx
|
|
2392
|
-
import { Fragment as
|
|
2446
|
+
import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
2393
2447
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2394
2448
|
var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
|
|
2395
2449
|
var noop = () => {
|
|
@@ -2453,17 +2507,17 @@ function GenreTreeView({
|
|
|
2453
2507
|
}) {
|
|
2454
2508
|
const getShareUrlRef = useRef3(getShareUrl);
|
|
2455
2509
|
getShareUrlRef.current = getShareUrl;
|
|
2456
|
-
const [internalArtistUuid, setInternalArtistUuid] =
|
|
2510
|
+
const [internalArtistUuid, setInternalArtistUuid] = useState10(null);
|
|
2457
2511
|
const isArtistControlled = controlledArtistUuid !== void 0;
|
|
2458
2512
|
const artistUuid = isArtistControlled ? controlledArtistUuid : internalArtistUuid;
|
|
2459
|
-
const [internalSongUuid, setInternalSongUuid] =
|
|
2513
|
+
const [internalSongUuid, setInternalSongUuid] = useState10(null);
|
|
2460
2514
|
const isSongControlled = controlledSongUuid !== void 0;
|
|
2461
2515
|
const songUuid = isSongControlled ? controlledSongUuid : internalSongUuid;
|
|
2462
2516
|
const changeSong = (uuid) => {
|
|
2463
2517
|
if (!isSongControlled) setInternalSongUuid(uuid);
|
|
2464
2518
|
onSongUuidChange?.(uuid);
|
|
2465
2519
|
};
|
|
2466
|
-
const [internalSizeMetric, setInternalSizeMetric] =
|
|
2520
|
+
const [internalSizeMetric, setInternalSizeMetric] = useState10("songs");
|
|
2467
2521
|
const sizeMetric = controlledSizeMetric ?? internalSizeMetric;
|
|
2468
2522
|
const deferredSizeMetric = useDeferredValue2(sizeMetric);
|
|
2469
2523
|
const changeSizeMetric = (metric) => {
|
|
@@ -2481,6 +2535,7 @@ function GenreTreeView({
|
|
|
2481
2535
|
isFetching: isTreeFetching,
|
|
2482
2536
|
genrePlaylistByNodeId,
|
|
2483
2537
|
visibleGenrePlaylists,
|
|
2538
|
+
focusUuids,
|
|
2484
2539
|
groupedGenrePlaylistsByRoot,
|
|
2485
2540
|
selectedGenreUuid,
|
|
2486
2541
|
selectGenre,
|
|
@@ -2506,7 +2561,7 @@ function GenreTreeView({
|
|
|
2506
2561
|
artistUuid
|
|
2507
2562
|
});
|
|
2508
2563
|
const restoreRevision = viewportRestore?.revision;
|
|
2509
|
-
const [stackedRestoreOwner, setStackedRestoreOwner] =
|
|
2564
|
+
const [stackedRestoreOwner, setStackedRestoreOwner] = useState10({ revision: restoreRevision, rootUuid: selectedGenrePlaylist?.root.uuid });
|
|
2510
2565
|
let restoreRootUuid = stackedRestoreOwner.rootUuid;
|
|
2511
2566
|
if (stackedRestoreOwner.revision !== restoreRevision) {
|
|
2512
2567
|
restoreRootUuid = selectedGenrePlaylist?.root.uuid;
|
|
@@ -2540,14 +2595,14 @@ function GenreTreeView({
|
|
|
2540
2595
|
const openSongRef = useRef3(openSong);
|
|
2541
2596
|
openSongRef.current = openSong;
|
|
2542
2597
|
const resolvedRenderSongLink = useCallback6(
|
|
2543
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */
|
|
2598
|
+
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ jsx39("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
|
|
2544
2599
|
[renderSongLink]
|
|
2545
2600
|
);
|
|
2546
|
-
const [expandedSongUuid, setExpandedSongUuid] =
|
|
2547
|
-
const [expandedArtistUuid, setExpandedArtistUuid] =
|
|
2601
|
+
const [expandedSongUuid, setExpandedSongUuid] = useState10(null);
|
|
2602
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = useState10(null);
|
|
2548
2603
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
2549
2604
|
const songBaseUrl = getBackendBaseUrl;
|
|
2550
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */
|
|
2605
|
+
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ jsx39("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
2551
2606
|
const getGenrePath = (genre) => {
|
|
2552
2607
|
const path = [];
|
|
2553
2608
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -2589,9 +2644,9 @@ function GenreTreeView({
|
|
|
2589
2644
|
selectGenrePlaylist(genrePlaylist2);
|
|
2590
2645
|
}
|
|
2591
2646
|
});
|
|
2592
|
-
const
|
|
2593
|
-
const [uncontrolledCollapsed, setUncontrolledCollapsed] =
|
|
2594
|
-
const [uncontrolledExpanded, setUncontrolledExpanded] =
|
|
2647
|
+
const otherPanel = overlayPanel ?? (selectedGenreUuid !== null ? void 0 : entityPanel);
|
|
2648
|
+
const [uncontrolledCollapsed, setUncontrolledCollapsed] = useState10(false);
|
|
2649
|
+
const [uncontrolledExpanded, setUncontrolledExpanded] = useState10(false);
|
|
2595
2650
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
2596
2651
|
const isExpanded = expanded ?? uncontrolledExpanded;
|
|
2597
2652
|
const changeCollapsed = (next) => {
|
|
@@ -2602,13 +2657,13 @@ function GenreTreeView({
|
|
|
2602
2657
|
setUncontrolledExpanded(next);
|
|
2603
2658
|
onExpandedChange?.(next);
|
|
2604
2659
|
};
|
|
2605
|
-
|
|
2660
|
+
useEffect6(() => {
|
|
2606
2661
|
setUncontrolledCollapsed(false);
|
|
2607
2662
|
}, [selectedGenreUuid, artistUuid, songUuid]);
|
|
2608
|
-
const [isWheelRevealed, setIsWheelRevealed] =
|
|
2663
|
+
const [isWheelRevealed, setIsWheelRevealed] = useState10(false);
|
|
2609
2664
|
const usesHandoff = viewMode === "wheel" || viewMode === "pop-core";
|
|
2610
2665
|
const isTreeReady = !isLoading && !isError && (!usesHandoff || isWheelRevealed);
|
|
2611
|
-
const [resolveStyle, setResolveStyle] =
|
|
2666
|
+
const [resolveStyle, setResolveStyle] = useState10(null);
|
|
2612
2667
|
const handleNodeStyleResolverChange = useCallback6(
|
|
2613
2668
|
(resolver) => setResolveStyle(() => resolver),
|
|
2614
2669
|
[]
|
|
@@ -2617,18 +2672,18 @@ function GenreTreeView({
|
|
|
2617
2672
|
const obscuredInset = useObscuredInset(panelRef);
|
|
2618
2673
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
2619
2674
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
2620
|
-
const treeNodes = useMemo8(() => toTreeNodes(visibleGenrePlaylists, nodeMetric), [visibleGenrePlaylists, nodeMetric]);
|
|
2675
|
+
const treeNodes = useMemo8(() => toTreeNodes(visibleGenrePlaylists, nodeMetric, focusUuids), [visibleGenrePlaylists, nodeMetric, focusUuids]);
|
|
2621
2676
|
const relations = useGenreNodeRelations(
|
|
2622
2677
|
treeNodes,
|
|
2623
2678
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
2624
2679
|
resolveStyle
|
|
2625
2680
|
);
|
|
2626
|
-
const [selectionHistory, setSelectionHistory] =
|
|
2681
|
+
const [selectionHistory, setSelectionHistory] = useState10({ current: selectedGenreUuid, previous: null });
|
|
2627
2682
|
if (selectionHistory.current !== selectedGenreUuid) {
|
|
2628
2683
|
setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
2629
2684
|
}
|
|
2630
2685
|
const handlePrevious = selectionHistory.previous ? () => selectGenre(selectionHistory.previous) : void 0;
|
|
2631
|
-
const { showPopup, hidePopup } =
|
|
2686
|
+
const { showPopup, hidePopup } = usePopup4();
|
|
2632
2687
|
const reopenPanel = () => {
|
|
2633
2688
|
setUncontrolledCollapsed(false);
|
|
2634
2689
|
onCollapsedChange?.(false);
|
|
@@ -2668,6 +2723,7 @@ function GenreTreeView({
|
|
|
2668
2723
|
selectGenre(uuid);
|
|
2669
2724
|
},
|
|
2670
2725
|
expanded: isExpanded,
|
|
2726
|
+
treeRelations: relations,
|
|
2671
2727
|
playback,
|
|
2672
2728
|
genrePlaylist: selectedGenrePlaylist,
|
|
2673
2729
|
band: {
|
|
@@ -2678,7 +2734,7 @@ function GenreTreeView({
|
|
|
2678
2734
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
2679
2735
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
2680
2736
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
2681
|
-
/* @__PURE__ */
|
|
2737
|
+
/* @__PURE__ */ jsx39(
|
|
2682
2738
|
ChangeParentPopup,
|
|
2683
2739
|
{
|
|
2684
2740
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -2712,15 +2768,15 @@ function GenreTreeView({
|
|
|
2712
2768
|
const isRotationControlled = controlledAllowWheelRotation !== void 0;
|
|
2713
2769
|
const allowWheelRotation = controlledAllowWheelRotation ?? internalAllowWheelRotation;
|
|
2714
2770
|
let activePanel = null;
|
|
2715
|
-
if (
|
|
2771
|
+
if (otherPanel) {
|
|
2716
2772
|
activePanel = {
|
|
2717
|
-
title:
|
|
2718
|
-
content:
|
|
2719
|
-
aside:
|
|
2720
|
-
expanded:
|
|
2721
|
-
onExpandedChange:
|
|
2722
|
-
onClose:
|
|
2723
|
-
|
|
2773
|
+
title: otherPanel.title,
|
|
2774
|
+
content: otherPanel.content,
|
|
2775
|
+
aside: otherPanel.extraContent,
|
|
2776
|
+
expanded: otherPanel.expanded ?? false,
|
|
2777
|
+
onExpandedChange: otherPanel.onExpandedChange,
|
|
2778
|
+
onClose: otherPanel.onClose,
|
|
2779
|
+
searchName: otherPanel.title
|
|
2724
2780
|
};
|
|
2725
2781
|
} else if (selectedGenreUuid) {
|
|
2726
2782
|
activePanel = {
|
|
@@ -2730,18 +2786,8 @@ function GenreTreeView({
|
|
|
2730
2786
|
expanded: isExpanded,
|
|
2731
2787
|
onExpandedChange: changeExpanded,
|
|
2732
2788
|
onClose: clearSelection,
|
|
2733
|
-
|
|
2734
|
-
headerAccent:
|
|
2735
|
-
};
|
|
2736
|
-
} else if (builtInPanel) {
|
|
2737
|
-
activePanel = {
|
|
2738
|
-
title: builtInPanel.title,
|
|
2739
|
-
content: builtInPanel.content,
|
|
2740
|
-
aside: builtInPanel.extraContent,
|
|
2741
|
-
expanded: builtInPanel.expanded,
|
|
2742
|
-
onExpandedChange: builtInPanel.onExpandedChange,
|
|
2743
|
-
onClose: builtInPanel.onClose,
|
|
2744
|
-
titleInSearch: true
|
|
2789
|
+
searchName: genreContent.name,
|
|
2790
|
+
headerAccent: genreContent.headerAccent
|
|
2745
2791
|
};
|
|
2746
2792
|
}
|
|
2747
2793
|
const isPanelShown = activePanel !== null && (selectedGenreUuid !== null || isTreeReady);
|
|
@@ -2749,19 +2795,19 @@ function GenreTreeView({
|
|
|
2749
2795
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
2750
2796
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
2751
2797
|
} : void 0;
|
|
2752
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */
|
|
2798
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ jsx39(
|
|
2753
2799
|
IconButton2,
|
|
2754
2800
|
{
|
|
2755
2801
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
2756
2802
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
2757
2803
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
2758
|
-
children: activePanel.expanded ? /* @__PURE__ */
|
|
2804
|
+
children: activePanel.expanded ? /* @__PURE__ */ jsx39(Minimize22, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ jsx39(Maximize22, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
2759
2805
|
}
|
|
2760
2806
|
) : null;
|
|
2761
2807
|
const renderArtistFilter = () => {
|
|
2762
2808
|
if (isLoading || !filterArtist) return null;
|
|
2763
|
-
return /* @__PURE__ */
|
|
2764
|
-
/* @__PURE__ */
|
|
2809
|
+
return /* @__PURE__ */ jsxs27("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
2810
|
+
/* @__PURE__ */ jsx39(
|
|
2765
2811
|
"button",
|
|
2766
2812
|
{
|
|
2767
2813
|
type: "button",
|
|
@@ -2773,7 +2819,7 @@ function GenreTreeView({
|
|
|
2773
2819
|
children: filterArtist.name
|
|
2774
2820
|
}
|
|
2775
2821
|
),
|
|
2776
|
-
/* @__PURE__ */
|
|
2822
|
+
/* @__PURE__ */ jsx39(
|
|
2777
2823
|
"button",
|
|
2778
2824
|
{
|
|
2779
2825
|
type: "button",
|
|
@@ -2785,8 +2831,8 @@ function GenreTreeView({
|
|
|
2785
2831
|
)
|
|
2786
2832
|
] });
|
|
2787
2833
|
};
|
|
2788
|
-
const actions = /* @__PURE__ */
|
|
2789
|
-
!isLoading && !isError && /* @__PURE__ */
|
|
2834
|
+
const actions = /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
2835
|
+
!isLoading && !isError && /* @__PURE__ */ jsx39(
|
|
2790
2836
|
GenreTreeSearch,
|
|
2791
2837
|
{
|
|
2792
2838
|
artistBaseUrl,
|
|
@@ -2809,9 +2855,9 @@ function GenreTreeView({
|
|
|
2809
2855
|
if (songUuid) changeSong(null);
|
|
2810
2856
|
selectGenre(uuid);
|
|
2811
2857
|
},
|
|
2812
|
-
selectedName:
|
|
2858
|
+
selectedName: activePanel?.searchName ?? null,
|
|
2813
2859
|
onClear: activePanel?.onClose,
|
|
2814
|
-
showClear: activePanel
|
|
2860
|
+
showClear: activePanel !== null,
|
|
2815
2861
|
clearLabel: "Close panel",
|
|
2816
2862
|
onPrevious: handlePrevious,
|
|
2817
2863
|
onQueryChange: onSearchQueryChange,
|
|
@@ -2819,9 +2865,9 @@ function GenreTreeView({
|
|
|
2819
2865
|
extraGroups: extraSearchGroups
|
|
2820
2866
|
}
|
|
2821
2867
|
),
|
|
2822
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */
|
|
2823
|
-
/* @__PURE__ */
|
|
2824
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */
|
|
2868
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ jsx39("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
2869
|
+
/* @__PURE__ */ jsxs27("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: [
|
|
2870
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ jsx39(
|
|
2825
2871
|
SegmentedControl2,
|
|
2826
2872
|
{
|
|
2827
2873
|
"aria-label": "Tree view mode",
|
|
@@ -2835,13 +2881,13 @@ function GenreTreeView({
|
|
|
2835
2881
|
]
|
|
2836
2882
|
}
|
|
2837
2883
|
),
|
|
2838
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */
|
|
2884
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ jsx39(
|
|
2839
2885
|
"div",
|
|
2840
2886
|
{
|
|
2841
2887
|
className: "flex items-center gap-1",
|
|
2842
2888
|
role: "group",
|
|
2843
2889
|
"aria-label": "Tree display options",
|
|
2844
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */
|
|
2890
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ jsx39(
|
|
2845
2891
|
Button,
|
|
2846
2892
|
{
|
|
2847
2893
|
variant: allowWheelRotation ? "default" : "outline",
|
|
@@ -2852,7 +2898,7 @@ function GenreTreeView({
|
|
|
2852
2898
|
)
|
|
2853
2899
|
}
|
|
2854
2900
|
),
|
|
2855
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */
|
|
2901
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ jsx39(
|
|
2856
2902
|
IconTextButton,
|
|
2857
2903
|
{
|
|
2858
2904
|
icon: Plus2,
|
|
@@ -2862,42 +2908,43 @@ function GenreTreeView({
|
|
|
2862
2908
|
)
|
|
2863
2909
|
] })
|
|
2864
2910
|
] });
|
|
2865
|
-
return /* @__PURE__ */
|
|
2911
|
+
return /* @__PURE__ */ jsxs27(
|
|
2866
2912
|
"div",
|
|
2867
2913
|
{
|
|
2868
2914
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
2869
2915
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
2870
2916
|
children: [
|
|
2871
|
-
/* @__PURE__ */
|
|
2917
|
+
/* @__PURE__ */ jsx39(
|
|
2872
2918
|
"div",
|
|
2873
2919
|
{
|
|
2874
2920
|
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"}`,
|
|
2875
2921
|
children: actions
|
|
2876
2922
|
}
|
|
2877
2923
|
),
|
|
2878
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */
|
|
2924
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ jsx39(
|
|
2879
2925
|
"div",
|
|
2880
2926
|
{
|
|
2881
2927
|
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"}`,
|
|
2882
2928
|
children: renderArtistFilter()
|
|
2883
2929
|
}
|
|
2884
2930
|
),
|
|
2885
|
-
/* @__PURE__ */
|
|
2886
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */
|
|
2887
|
-
isLoading ? /* @__PURE__ */
|
|
2931
|
+
/* @__PURE__ */ jsx39("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ jsxs27("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
2932
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ jsx39("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
2933
|
+
isLoading ? /* @__PURE__ */ jsx39(GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ jsxs27("p", { role: "alert", className: "m-auto text-center", children: [
|
|
2888
2934
|
"Couldn't load the genre tree.",
|
|
2889
2935
|
" ",
|
|
2890
|
-
/* @__PURE__ */
|
|
2936
|
+
/* @__PURE__ */ jsx39("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
2891
2937
|
] }) : viewMode === "wheel" ? (
|
|
2892
2938
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
2893
2939
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
2894
2940
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
2895
2941
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
2896
|
-
/* @__PURE__ */
|
|
2942
|
+
/* @__PURE__ */ jsx39("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ jsx39(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ jsx39(GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ jsx39(
|
|
2897
2943
|
GenrePlaylistTreeWheel,
|
|
2898
2944
|
{
|
|
2899
2945
|
scope,
|
|
2900
2946
|
genrePlaylists: visibleGenrePlaylists,
|
|
2947
|
+
focusUuids,
|
|
2901
2948
|
handleGenreCreationAction,
|
|
2902
2949
|
handleGenreRenameAction,
|
|
2903
2950
|
additionalActions,
|
|
@@ -2910,9 +2957,9 @@ function GenreTreeView({
|
|
|
2910
2957
|
allowWheelRotation,
|
|
2911
2958
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
2912
2959
|
busy,
|
|
2913
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */
|
|
2960
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
|
|
2914
2961
|
floatingControlsLeading,
|
|
2915
|
-
canSizeByViews && /* @__PURE__ */
|
|
2962
|
+
canSizeByViews && /* @__PURE__ */ jsx39(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
2916
2963
|
] }) : void 0,
|
|
2917
2964
|
defaultViewport,
|
|
2918
2965
|
viewportRestore,
|
|
@@ -2921,11 +2968,12 @@ function GenreTreeView({
|
|
|
2921
2968
|
) }) })
|
|
2922
2969
|
) : viewMode === "pop-core" ? (
|
|
2923
2970
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
2924
|
-
/* @__PURE__ */
|
|
2971
|
+
/* @__PURE__ */ jsx39("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ jsx39(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ jsx39(GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ jsx39(
|
|
2925
2972
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
2926
2973
|
{
|
|
2927
2974
|
scope,
|
|
2928
2975
|
genrePlaylists: visibleGenrePlaylists,
|
|
2976
|
+
focusUuids,
|
|
2929
2977
|
handleGenreCreationAction,
|
|
2930
2978
|
handleGenreRenameAction,
|
|
2931
2979
|
additionalActions,
|
|
@@ -2938,9 +2986,9 @@ function GenreTreeView({
|
|
|
2938
2986
|
allowWheelRotation,
|
|
2939
2987
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
2940
2988
|
busy,
|
|
2941
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */
|
|
2989
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ jsxs27("div", { className: "flex items-center gap-2", children: [
|
|
2942
2990
|
floatingControlsLeading,
|
|
2943
|
-
canSizeByViews && /* @__PURE__ */
|
|
2991
|
+
canSizeByViews && /* @__PURE__ */ jsx39(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
2944
2992
|
] }) : void 0,
|
|
2945
2993
|
defaultViewport,
|
|
2946
2994
|
viewportRestore,
|
|
@@ -2948,12 +2996,13 @@ function GenreTreeView({
|
|
|
2948
2996
|
...focus
|
|
2949
2997
|
}
|
|
2950
2998
|
) }) })
|
|
2951
|
-
) : viewMode === "outline" ? /* @__PURE__ */
|
|
2999
|
+
) : viewMode === "outline" ? /* @__PURE__ */ jsx39("div", { className: "tree-container flex-1 min-h-0 w-full overflow-y-auto relative", children: /* @__PURE__ */ jsx39(
|
|
2952
3000
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
2953
3001
|
{
|
|
2954
3002
|
outline: true,
|
|
2955
3003
|
scope,
|
|
2956
3004
|
genrePlaylists: visibleGenrePlaylists,
|
|
3005
|
+
focusUuids,
|
|
2957
3006
|
handleGenreCreationAction,
|
|
2958
3007
|
handleGenreRenameAction,
|
|
2959
3008
|
additionalActions,
|
|
@@ -2964,13 +3013,13 @@ function GenreTreeView({
|
|
|
2964
3013
|
selectedNodeId,
|
|
2965
3014
|
readOnly
|
|
2966
3015
|
}
|
|
2967
|
-
) }) : /* @__PURE__ */
|
|
3016
|
+
) }) : /* @__PURE__ */ jsx39("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(
|
|
2968
3017
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
2969
|
-
return /* @__PURE__ */
|
|
3018
|
+
return /* @__PURE__ */ jsx39(
|
|
2970
3019
|
"div",
|
|
2971
3020
|
{
|
|
2972
3021
|
className: "tree-per-root-container relative shrink-0 h-[28rem] mt-2 mr-16 p-2 bg-[var(--color-neutral-100)] rounded-lg",
|
|
2973
|
-
children: /* @__PURE__ */
|
|
3022
|
+
children: /* @__PURE__ */ jsx39("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ jsx39(
|
|
2974
3023
|
GenrePlaylistTreePerRoot,
|
|
2975
3024
|
{
|
|
2976
3025
|
scope,
|
|
@@ -2983,6 +3032,7 @@ function GenreTreeView({
|
|
|
2983
3032
|
onNodeHover: handleNodeHover,
|
|
2984
3033
|
...hostPanel,
|
|
2985
3034
|
playback,
|
|
3035
|
+
focusUuids,
|
|
2986
3036
|
selectedNodeId: uuid === selectedGenrePlaylist?.root.uuid ? selectedNodeId : null,
|
|
2987
3037
|
readOnly,
|
|
2988
3038
|
wheelZoom: "modifier",
|
|
@@ -2996,13 +3046,13 @@ function GenreTreeView({
|
|
|
2996
3046
|
);
|
|
2997
3047
|
}
|
|
2998
3048
|
) }),
|
|
2999
|
-
/* @__PURE__ */
|
|
3049
|
+
/* @__PURE__ */ jsx39(
|
|
3000
3050
|
DetailPanel2,
|
|
3001
3051
|
{
|
|
3002
3052
|
ref: panelRef,
|
|
3003
3053
|
side: "left",
|
|
3004
3054
|
title: activePanel?.title ?? "",
|
|
3005
|
-
titleInSearch:
|
|
3055
|
+
titleInSearch: !isLoading && !isError,
|
|
3006
3056
|
headerAccent: activePanel?.headerAccent,
|
|
3007
3057
|
headerActions: expandButton,
|
|
3008
3058
|
onClose: activePanel?.onClose ?? noop,
|
|
@@ -3011,8 +3061,7 @@ function GenreTreeView({
|
|
|
3011
3061
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3012
3062
|
aside: activePanel?.aside,
|
|
3013
3063
|
edgeTab: detailTab,
|
|
3014
|
-
|
|
3015
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ jsxs26(Fragment14, { children: [
|
|
3064
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ jsxs27(Fragment15, { children: [
|
|
3016
3065
|
activePanel.content,
|
|
3017
3066
|
activePanel.aside
|
|
3018
3067
|
] }) : activePanel?.content
|
|
@@ -3033,13 +3082,13 @@ import {
|
|
|
3033
3082
|
} from "@behindthemusictree/genre-tree-view";
|
|
3034
3083
|
|
|
3035
3084
|
// src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
|
|
3036
|
-
import { useEffect as
|
|
3085
|
+
import { useEffect as useEffect7, useLayoutEffect as useLayoutEffect2, useRef as useRef4 } from "react";
|
|
3037
3086
|
import { ListMusic } from "lucide-react";
|
|
3038
|
-
import { useTrackList as
|
|
3039
|
-
import { TrackListOriginType as
|
|
3040
|
-
import { useTrackNoun as
|
|
3041
|
-
import { jsx as
|
|
3042
|
-
var useBrowserLayoutEffect = typeof window === "undefined" ?
|
|
3087
|
+
import { useTrackList as useTrackList7 } from "@behindthemusictree/app-kit/genre-tree";
|
|
3088
|
+
import { TrackListOriginType as TrackListOriginType3 } from "@behindthemusictree/app-kit/genre-tree";
|
|
3089
|
+
import { useTrackNoun as useTrackNoun3 } from "@behindthemusictree/app-kit/track-noun";
|
|
3090
|
+
import { jsx as jsx40, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
3091
|
+
var useBrowserLayoutEffect = typeof window === "undefined" ? useEffect7 : useLayoutEffect2;
|
|
3043
3092
|
function TrackListSidebar({
|
|
3044
3093
|
className: className2 = "",
|
|
3045
3094
|
renderDuration,
|
|
@@ -3051,8 +3100,8 @@ function TrackListSidebar({
|
|
|
3051
3100
|
renderArtistLink,
|
|
3052
3101
|
renderSongLink
|
|
3053
3102
|
}) {
|
|
3054
|
-
const { trackList, loadMore, autoAdvanceScrollRequest } =
|
|
3055
|
-
const trackNoun =
|
|
3103
|
+
const { trackList, loadMore, autoAdvanceScrollRequest } = useTrackList7();
|
|
3104
|
+
const trackNoun = useTrackNoun3();
|
|
3056
3105
|
const trackListRef = useRef4(null);
|
|
3057
3106
|
const previousOriginRef = useRef4(trackList?.origin ?? null);
|
|
3058
3107
|
const handledAutoAdvanceRequestIdRef = useRef4(null);
|
|
@@ -3062,7 +3111,7 @@ function TrackListSidebar({
|
|
|
3062
3111
|
const userScrollIntentTimerRef = useRef4(null);
|
|
3063
3112
|
const loadMoreSentinelRef = useRef4(null);
|
|
3064
3113
|
const hasMore = !!trackList && trackList.nextPage !== null;
|
|
3065
|
-
|
|
3114
|
+
useEffect7(() => {
|
|
3066
3115
|
const sentinel = loadMoreSentinelRef.current;
|
|
3067
3116
|
if (!hasMore || !sentinel) return;
|
|
3068
3117
|
const observer = new IntersectionObserver((entries) => {
|
|
@@ -3082,11 +3131,11 @@ function TrackListSidebar({
|
|
|
3082
3131
|
programmaticScrollTopRef.current = null;
|
|
3083
3132
|
if (trackListRef.current) trackListRef.current.scrollTop = 0;
|
|
3084
3133
|
}, [trackList?.origin]);
|
|
3085
|
-
|
|
3134
|
+
useEffect7(() => {
|
|
3086
3135
|
const list = trackListRef.current;
|
|
3087
3136
|
if (!isCollapsed && list?.scrollTop === 0) shouldFollowPlaybackRef.current = true;
|
|
3088
3137
|
}, [isCollapsed]);
|
|
3089
|
-
|
|
3138
|
+
useEffect7(
|
|
3090
3139
|
() => () => {
|
|
3091
3140
|
if (userScrollIntentTimerRef.current !== null) clearTimeout(userScrollIntentTimerRef.current);
|
|
3092
3141
|
},
|
|
@@ -3140,25 +3189,25 @@ function TrackListSidebar({
|
|
|
3140
3189
|
}
|
|
3141
3190
|
};
|
|
3142
3191
|
const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
|
|
3143
|
-
return trackList ? /* @__PURE__ */
|
|
3192
|
+
return trackList ? /* @__PURE__ */ jsxs28(
|
|
3144
3193
|
"div",
|
|
3145
3194
|
{
|
|
3146
3195
|
"data-theme": "dark",
|
|
3147
3196
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3148
3197
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3149
3198
|
children: [
|
|
3150
|
-
/* @__PURE__ */
|
|
3151
|
-
/* @__PURE__ */
|
|
3152
|
-
/* @__PURE__ */
|
|
3153
|
-
/* @__PURE__ */
|
|
3154
|
-
/* @__PURE__ */
|
|
3199
|
+
/* @__PURE__ */ jsxs28("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3200
|
+
/* @__PURE__ */ jsxs28("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3201
|
+
/* @__PURE__ */ jsxs28("div", { className: "origin flex text-xl", children: [
|
|
3202
|
+
/* @__PURE__ */ jsx40("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3203
|
+
/* @__PURE__ */ jsx40("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__ */ jsx40("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3155
3204
|
] }),
|
|
3156
|
-
/* @__PURE__ */
|
|
3157
|
-
trackList.origin.type ===
|
|
3205
|
+
/* @__PURE__ */ jsxs28("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3206
|
+
trackList.origin.type === TrackListOriginType3.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === TrackListOriginType3.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
|
|
3158
3207
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3159
3208
|
] })
|
|
3160
3209
|
] }),
|
|
3161
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */
|
|
3210
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ jsx40(
|
|
3162
3211
|
"button",
|
|
3163
3212
|
{
|
|
3164
3213
|
type: "button",
|
|
@@ -3167,11 +3216,11 @@ function TrackListSidebar({
|
|
|
3167
3216
|
"aria-expanded": !isCollapsed,
|
|
3168
3217
|
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"}`,
|
|
3169
3218
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3170
|
-
children: /* @__PURE__ */
|
|
3219
|
+
children: /* @__PURE__ */ jsx40(ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3171
3220
|
}
|
|
3172
3221
|
)
|
|
3173
3222
|
] }),
|
|
3174
|
-
!isCollapsed && /* @__PURE__ */
|
|
3223
|
+
!isCollapsed && /* @__PURE__ */ jsxs28(
|
|
3175
3224
|
"ul",
|
|
3176
3225
|
{
|
|
3177
3226
|
ref: trackListRef,
|
|
@@ -3181,7 +3230,7 @@ function TrackListSidebar({
|
|
|
3181
3230
|
onPointerDown: markUserScrollIntent,
|
|
3182
3231
|
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",
|
|
3183
3232
|
children: [
|
|
3184
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */
|
|
3233
|
+
trackList.tracks.map((track, index) => /* @__PURE__ */ jsx40("li", { "data-track-uuid": track.uuid, children: /* @__PURE__ */ jsx40(
|
|
3185
3234
|
TrackItem,
|
|
3186
3235
|
{
|
|
3187
3236
|
track,
|
|
@@ -3192,7 +3241,7 @@ function TrackListSidebar({
|
|
|
3192
3241
|
renderSongLink
|
|
3193
3242
|
}
|
|
3194
3243
|
) }, track.uuid)),
|
|
3195
|
-
hasMore && /* @__PURE__ */
|
|
3244
|
+
hasMore && /* @__PURE__ */ jsx40("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3196
3245
|
]
|
|
3197
3246
|
}
|
|
3198
3247
|
)
|
|
@@ -3202,10 +3251,10 @@ function TrackListSidebar({
|
|
|
3202
3251
|
}
|
|
3203
3252
|
|
|
3204
3253
|
// src/genre-tree/PlayerPanel.tsx
|
|
3205
|
-
import { useEffect as
|
|
3254
|
+
import { useEffect as useEffect8, useState as useState11 } from "react";
|
|
3206
3255
|
import { twMerge } from "tailwind-merge";
|
|
3207
3256
|
import {
|
|
3208
|
-
usePlayer as
|
|
3257
|
+
usePlayer as usePlayer12,
|
|
3209
3258
|
PlayerVideoSurface
|
|
3210
3259
|
} from "@behindthemusictree/app-kit/player";
|
|
3211
3260
|
import {
|
|
@@ -3214,10 +3263,10 @@ import {
|
|
|
3214
3263
|
import { PanelEdgeTab } from "@behindthemusictree/ui";
|
|
3215
3264
|
|
|
3216
3265
|
// src/genre-tree/PlayerControls.tsx
|
|
3217
|
-
import { Pause as
|
|
3218
|
-
import { formatTime, useTrackList as
|
|
3219
|
-
import { PlayStates as PlayStates4, useCurrentTime, usePlayer as
|
|
3220
|
-
import { jsx as
|
|
3266
|
+
import { Pause as Pause4, Play as Play5, SkipBack, SkipForward, Volume2, VolumeX } from "lucide-react";
|
|
3267
|
+
import { formatTime, useTrackList as useTrackList8 } from "@behindthemusictree/app-kit/genre-tree";
|
|
3268
|
+
import { PlayStates as PlayStates4, useCurrentTime, usePlayer as usePlayer11 } from "@behindthemusictree/app-kit/player";
|
|
3269
|
+
import { jsx as jsx41, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
3221
3270
|
function PlayerControls() {
|
|
3222
3271
|
const {
|
|
3223
3272
|
duration,
|
|
@@ -3228,23 +3277,23 @@ function PlayerControls() {
|
|
|
3228
3277
|
seekTo,
|
|
3229
3278
|
setVolume,
|
|
3230
3279
|
volume
|
|
3231
|
-
} =
|
|
3232
|
-
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } =
|
|
3280
|
+
} = usePlayer11();
|
|
3281
|
+
const { hasNextTrack, hasPreviousTrack, playNextTrack, playPreviousTrack } = useTrackList8();
|
|
3233
3282
|
const currentTime = useCurrentTime();
|
|
3234
3283
|
const isBusy = isLoading || playState === PlayStates4.LOADING;
|
|
3235
3284
|
const isReady = !!playerTrackObject?.isReady && !isBusy && !playerTrackObject.loadError;
|
|
3236
3285
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3237
3286
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3238
3287
|
const isPlaying = playState === PlayStates4.PLAYING;
|
|
3239
|
-
return /* @__PURE__ */
|
|
3288
|
+
return /* @__PURE__ */ jsxs29(
|
|
3240
3289
|
"section",
|
|
3241
3290
|
{
|
|
3242
3291
|
"aria-label": "Player controls",
|
|
3243
3292
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3244
3293
|
children: [
|
|
3245
|
-
/* @__PURE__ */
|
|
3246
|
-
/* @__PURE__ */
|
|
3247
|
-
/* @__PURE__ */
|
|
3294
|
+
/* @__PURE__ */ jsxs29("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3295
|
+
/* @__PURE__ */ jsx41("span", { "aria-label": "Elapsed time", children: formatTime(safeCurrentTime) }),
|
|
3296
|
+
/* @__PURE__ */ jsx41(
|
|
3248
3297
|
"input",
|
|
3249
3298
|
{
|
|
3250
3299
|
"aria-label": "Seek",
|
|
@@ -3258,11 +3307,11 @@ function PlayerControls() {
|
|
|
3258
3307
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3259
3308
|
}
|
|
3260
3309
|
),
|
|
3261
|
-
/* @__PURE__ */
|
|
3310
|
+
/* @__PURE__ */ jsx41("span", { "aria-label": "Duration", children: formatTime(safeDuration) })
|
|
3262
3311
|
] }),
|
|
3263
|
-
/* @__PURE__ */
|
|
3264
|
-
/* @__PURE__ */
|
|
3265
|
-
/* @__PURE__ */
|
|
3312
|
+
/* @__PURE__ */ jsxs29("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3313
|
+
/* @__PURE__ */ jsxs29("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3314
|
+
/* @__PURE__ */ jsx41(
|
|
3266
3315
|
"button",
|
|
3267
3316
|
{
|
|
3268
3317
|
type: "button",
|
|
@@ -3271,10 +3320,10 @@ function PlayerControls() {
|
|
|
3271
3320
|
disabled: !isReady || !hasPreviousTrack,
|
|
3272
3321
|
onClick: playPreviousTrack,
|
|
3273
3322
|
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",
|
|
3274
|
-
children: /* @__PURE__ */
|
|
3323
|
+
children: /* @__PURE__ */ jsx41(SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3275
3324
|
}
|
|
3276
3325
|
),
|
|
3277
|
-
/* @__PURE__ */
|
|
3326
|
+
/* @__PURE__ */ jsx41(
|
|
3278
3327
|
"button",
|
|
3279
3328
|
{
|
|
3280
3329
|
type: "button",
|
|
@@ -3283,10 +3332,10 @@ function PlayerControls() {
|
|
|
3283
3332
|
disabled: !isReady,
|
|
3284
3333
|
onClick: handlePlayPauseAction,
|
|
3285
3334
|
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",
|
|
3286
|
-
children: isPlaying ? /* @__PURE__ */
|
|
3335
|
+
children: isPlaying ? /* @__PURE__ */ jsx41(Pause4, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ jsx41(Play5, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3287
3336
|
}
|
|
3288
3337
|
),
|
|
3289
|
-
/* @__PURE__ */
|
|
3338
|
+
/* @__PURE__ */ jsx41(
|
|
3290
3339
|
"button",
|
|
3291
3340
|
{
|
|
3292
3341
|
type: "button",
|
|
@@ -3295,14 +3344,14 @@ function PlayerControls() {
|
|
|
3295
3344
|
disabled: !isReady || !hasNextTrack,
|
|
3296
3345
|
onClick: playNextTrack,
|
|
3297
3346
|
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",
|
|
3298
|
-
children: /* @__PURE__ */
|
|
3347
|
+
children: /* @__PURE__ */ jsx41(SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3299
3348
|
}
|
|
3300
3349
|
)
|
|
3301
3350
|
] }),
|
|
3302
|
-
/* @__PURE__ */
|
|
3303
|
-
volume === 0 ? /* @__PURE__ */
|
|
3304
|
-
/* @__PURE__ */
|
|
3305
|
-
/* @__PURE__ */
|
|
3351
|
+
/* @__PURE__ */ jsxs29("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: [
|
|
3352
|
+
volume === 0 ? /* @__PURE__ */ jsx41(VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ jsx41(Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3353
|
+
/* @__PURE__ */ jsx41("span", { className: "sr-only", children: "Volume" }),
|
|
3354
|
+
/* @__PURE__ */ jsx41(
|
|
3306
3355
|
"input",
|
|
3307
3356
|
{
|
|
3308
3357
|
"aria-label": "Volume",
|
|
@@ -3324,7 +3373,7 @@ function PlayerControls() {
|
|
|
3324
3373
|
}
|
|
3325
3374
|
|
|
3326
3375
|
// src/genre-tree/PlayerPanel.tsx
|
|
3327
|
-
import { jsx as
|
|
3376
|
+
import { jsx as jsx42, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
3328
3377
|
var PANEL_ID = "player-panel";
|
|
3329
3378
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3330
3379
|
function PlayerPanel({
|
|
@@ -3336,14 +3385,14 @@ function PlayerPanel({
|
|
|
3336
3385
|
renderArtistLink,
|
|
3337
3386
|
renderSongLink
|
|
3338
3387
|
}) {
|
|
3339
|
-
const { playerTrackObject, retryPlayback } =
|
|
3388
|
+
const { playerTrackObject, retryPlayback } = usePlayer12();
|
|
3340
3389
|
const { toggleTrackListSidebar, isTrackListSidebarVisible } = useTrackListSidebarVisibility();
|
|
3341
|
-
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] =
|
|
3390
|
+
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = useState11("");
|
|
3342
3391
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
3343
|
-
|
|
3392
|
+
useEffect8(() => {
|
|
3344
3393
|
if (loadedTrackTitle) setLastLoadedTrackTitle(loadedTrackTitle);
|
|
3345
3394
|
}, [loadedTrackTitle]);
|
|
3346
|
-
const [uncontrolledExtended, setUncontrolledExtended] =
|
|
3395
|
+
const [uncontrolledExtended, setUncontrolledExtended] = useState11(false);
|
|
3347
3396
|
const isExtendRequested = expanded ?? uncontrolledExtended;
|
|
3348
3397
|
const setIsExtendRequested = (next) => {
|
|
3349
3398
|
setUncontrolledExtended(next);
|
|
@@ -3364,7 +3413,7 @@ function PlayerPanel({
|
|
|
3364
3413
|
onClick: () => setIsExtendRequested(true),
|
|
3365
3414
|
expanded: false
|
|
3366
3415
|
} : null;
|
|
3367
|
-
return /* @__PURE__ */
|
|
3416
|
+
return /* @__PURE__ */ jsxs30(
|
|
3368
3417
|
"div",
|
|
3369
3418
|
{
|
|
3370
3419
|
id: PANEL_ID,
|
|
@@ -3377,7 +3426,7 @@ function PlayerPanel({
|
|
|
3377
3426
|
),
|
|
3378
3427
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3379
3428
|
children: [
|
|
3380
|
-
/* @__PURE__ */
|
|
3429
|
+
/* @__PURE__ */ jsx42(
|
|
3381
3430
|
PanelEdgeTab,
|
|
3382
3431
|
{
|
|
3383
3432
|
side: "right",
|
|
@@ -3387,7 +3436,7 @@ function PlayerPanel({
|
|
|
3387
3436
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3388
3437
|
}
|
|
3389
3438
|
),
|
|
3390
|
-
/* @__PURE__ */
|
|
3439
|
+
/* @__PURE__ */ jsxs30(
|
|
3391
3440
|
"div",
|
|
3392
3441
|
{
|
|
3393
3442
|
className: twMerge(
|
|
@@ -3395,20 +3444,20 @@ function PlayerPanel({
|
|
|
3395
3444
|
isExtended ? "flex-row" : "flex-col"
|
|
3396
3445
|
),
|
|
3397
3446
|
children: [
|
|
3398
|
-
/* @__PURE__ */
|
|
3399
|
-
/* @__PURE__ */
|
|
3400
|
-
/* @__PURE__ */
|
|
3401
|
-
/* @__PURE__ */
|
|
3402
|
-
playerTrackObject?.loadError && /* @__PURE__ */
|
|
3447
|
+
/* @__PURE__ */ jsxs30("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3448
|
+
/* @__PURE__ */ jsx42("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ jsx42("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
|
|
3449
|
+
/* @__PURE__ */ jsxs30("div", { className: "relative w-full shrink-0", children: [
|
|
3450
|
+
/* @__PURE__ */ jsx42(PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3451
|
+
playerTrackObject?.loadError && /* @__PURE__ */ jsxs30("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3403
3452
|
playerTrackObject.loadError,
|
|
3404
|
-
/* @__PURE__ */
|
|
3453
|
+
/* @__PURE__ */ jsx42("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3405
3454
|
void retryPlayback();
|
|
3406
3455
|
}, children: "Retry" })
|
|
3407
3456
|
] })
|
|
3408
3457
|
] }),
|
|
3409
|
-
/* @__PURE__ */
|
|
3458
|
+
/* @__PURE__ */ jsx42(PlayerControls, {})
|
|
3410
3459
|
] }),
|
|
3411
|
-
/* @__PURE__ */
|
|
3460
|
+
/* @__PURE__ */ jsx42(
|
|
3412
3461
|
TrackListSidebar,
|
|
3413
3462
|
{
|
|
3414
3463
|
layout: "inline",
|
|
@@ -3435,11 +3484,11 @@ function PlayerPanel({
|
|
|
3435
3484
|
import { v4 as uuidv4 } from "uuid";
|
|
3436
3485
|
import { AiFillStar, AiOutlineStar } from "react-icons/ai";
|
|
3437
3486
|
import { FORM_RATING_NULL_VALUE } from "@behindthemusictree/app-kit/genre-tree";
|
|
3438
|
-
import { jsx as
|
|
3487
|
+
import { jsx as jsx43, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
3439
3488
|
function Rating({ rating, handleChange }) {
|
|
3440
3489
|
const instanceId = uuidv4();
|
|
3441
|
-
return /* @__PURE__ */
|
|
3442
|
-
/* @__PURE__ */
|
|
3490
|
+
return /* @__PURE__ */ jsx43("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ jsxs31("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
|
|
3491
|
+
/* @__PURE__ */ jsx43(
|
|
3443
3492
|
"input",
|
|
3444
3493
|
{
|
|
3445
3494
|
id: `star-${instanceId}-${i}`,
|
|
@@ -3451,16 +3500,16 @@ function Rating({ rating, handleChange }) {
|
|
|
3451
3500
|
onChange: handleChange
|
|
3452
3501
|
}
|
|
3453
3502
|
),
|
|
3454
|
-
/* @__PURE__ */
|
|
3455
|
-
/* @__PURE__ */
|
|
3503
|
+
/* @__PURE__ */ jsx43("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ jsxs31("div", { className: "flex", children: [
|
|
3504
|
+
/* @__PURE__ */ jsx43(
|
|
3456
3505
|
AiOutlineStar,
|
|
3457
3506
|
{
|
|
3458
3507
|
className: `w-7 h-7 absolute top-0 left-0 ${rating === FORM_RATING_NULL_VALUE ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
3459
3508
|
}
|
|
3460
3509
|
),
|
|
3461
|
-
/* @__PURE__ */
|
|
3510
|
+
/* @__PURE__ */ jsx43("span", { className: "flex-grow w-8" }),
|
|
3462
3511
|
" "
|
|
3463
|
-
] }) : /* @__PURE__ */
|
|
3512
|
+
] }) : /* @__PURE__ */ jsx43(
|
|
3464
3513
|
AiFillStar,
|
|
3465
3514
|
{
|
|
3466
3515
|
className: `w-7 h-7 absolute top-0 left-0 ${(rating ?? -1) >= i ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
@@ -3470,9 +3519,9 @@ function Rating({ rating, handleChange }) {
|
|
|
3470
3519
|
}
|
|
3471
3520
|
|
|
3472
3521
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
3473
|
-
import { useState as
|
|
3522
|
+
import { useState as useState12 } from "react";
|
|
3474
3523
|
import { DetailPanel as DetailPanel3 } from "@behindthemusictree/ui";
|
|
3475
|
-
import { Fragment as
|
|
3524
|
+
import { Fragment as Fragment16, jsx as jsx44, jsxs as jsxs32 } from "react/jsx-runtime";
|
|
3476
3525
|
function EntityDetailPanel({
|
|
3477
3526
|
scope,
|
|
3478
3527
|
getBackendBaseUrl,
|
|
@@ -3488,15 +3537,15 @@ function EntityDetailPanel({
|
|
|
3488
3537
|
edgeTab,
|
|
3489
3538
|
...navigation
|
|
3490
3539
|
}) {
|
|
3491
|
-
const [expandedSongUuid, setExpandedSongUuid] =
|
|
3492
|
-
const [expandedArtistUuid, setExpandedArtistUuid] =
|
|
3540
|
+
const [expandedSongUuid, setExpandedSongUuid] = useState12(null);
|
|
3541
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = useState12(null);
|
|
3493
3542
|
const panel = useEntityPanel({
|
|
3494
3543
|
scope,
|
|
3495
3544
|
getBackendBaseUrl,
|
|
3496
3545
|
getArtistBackendBaseUrl,
|
|
3497
3546
|
getShareUrl,
|
|
3498
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */
|
|
3499
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */
|
|
3547
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ jsx44("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
3548
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ jsx44("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
3500
3549
|
song: {
|
|
3501
3550
|
uuid: songUuid,
|
|
3502
3551
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -3512,7 +3561,7 @@ function EntityDetailPanel({
|
|
|
3512
3561
|
...navigation
|
|
3513
3562
|
});
|
|
3514
3563
|
if (!panel) return null;
|
|
3515
|
-
return /* @__PURE__ */
|
|
3564
|
+
return /* @__PURE__ */ jsx44(
|
|
3516
3565
|
DetailPanel3,
|
|
3517
3566
|
{
|
|
3518
3567
|
side: "left",
|
|
@@ -3524,7 +3573,7 @@ function EntityDetailPanel({
|
|
|
3524
3573
|
onExpandedChange: panel.onExpandedChange,
|
|
3525
3574
|
aside: panel.extraContent,
|
|
3526
3575
|
edgeTab,
|
|
3527
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */
|
|
3576
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ jsxs32(Fragment16, { children: [
|
|
3528
3577
|
panel.content,
|
|
3529
3578
|
panel.extraContent
|
|
3530
3579
|
] }) : panel.content
|
|
@@ -3558,4 +3607,4 @@ export {
|
|
|
3558
3607
|
GenreTreeViewSkeleton2 as GenreTreeViewSkeleton,
|
|
3559
3608
|
GenreTreeOutlineSkeleton
|
|
3560
3609
|
};
|
|
3561
|
-
//# sourceMappingURL=chunk-
|
|
3610
|
+
//# sourceMappingURL=chunk-I2TEOHVG.js.map
|