@behindthemusictree/app-kit-ui 39.0.0 → 40.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-2K2SQOUJ.js → chunk-I2TEOHVG.js} +345 -371
- package/dist/chunk-I2TEOHVG.js.map +1 -0
- package/dist/genre-tree/index.cjs +426 -453
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +12 -5
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +421 -448
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +6 -6
- package/dist/chunk-2K2SQOUJ.js.map +0 -1
|
@@ -55,7 +55,7 @@ var import_lucide_react15 = require("lucide-react");
|
|
|
55
55
|
var import_ui21 = require("@behindthemusictree/ui");
|
|
56
56
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
57
57
|
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
58
|
-
var
|
|
58
|
+
var import_popup4 = require("@behindthemusictree/app-kit/popup");
|
|
59
59
|
|
|
60
60
|
// src/genre-tree/playlist-tree/size-metric.ts
|
|
61
61
|
var import_genre_tree = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -69,7 +69,7 @@ var genrePlaylistSize = (genrePlaylist, metric) => {
|
|
|
69
69
|
};
|
|
70
70
|
|
|
71
71
|
// src/genre-tree/playlist-tree/toTreeNodes.ts
|
|
72
|
-
function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
72
|
+
function toTreeNodes(genrePlaylists, sizeMetric, focusUuids) {
|
|
73
73
|
return genrePlaylists.map((genrePlaylist) => ({
|
|
74
74
|
id: genrePlaylist.uuid,
|
|
75
75
|
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
@@ -80,7 +80,8 @@ function toTreeNodes(genrePlaylists, sizeMetric) {
|
|
|
80
80
|
side: genrePlaylist.criteria?.side ?? void 0,
|
|
81
81
|
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
82
82
|
umbrella: genrePlaylist.isUmbrella,
|
|
83
|
-
scene: genrePlaylist.scene ?? void 0
|
|
83
|
+
scene: genrePlaylist.scene ?? void 0,
|
|
84
|
+
muted: focusUuids ? !focusUuids.has(genrePlaylist.uuid) : void 0
|
|
84
85
|
}));
|
|
85
86
|
}
|
|
86
87
|
|
|
@@ -89,7 +90,12 @@ var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
89
90
|
var import_react3 = require("react");
|
|
90
91
|
var import_genre_tree_view = require("@behindthemusictree/genre-tree-view");
|
|
91
92
|
var import_player = require("@behindthemusictree/app-kit/player");
|
|
93
|
+
|
|
94
|
+
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.tsx
|
|
95
|
+
var import_react2 = require("react");
|
|
96
|
+
var import_genre_tree2 = require("@behindthemusictree/app-kit/genre-tree");
|
|
92
97
|
var import_popup = require("@behindthemusictree/app-kit/popup");
|
|
98
|
+
var import_transport = require("@behindthemusictree/app-kit/transport");
|
|
93
99
|
|
|
94
100
|
// src/popup/InternalErrorPopup.tsx
|
|
95
101
|
var import_lucide_react2 = require("lucide-react");
|
|
@@ -305,18 +311,15 @@ function InternalErrorPopup({ errorCode, contactEmail, ...rest }) {
|
|
|
305
311
|
);
|
|
306
312
|
}
|
|
307
313
|
|
|
308
|
-
// src/genre-tree/playlist-tree/
|
|
309
|
-
var
|
|
310
|
-
|
|
311
|
-
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.ts
|
|
312
|
-
var import_react2 = require("react");
|
|
313
|
-
var import_genre_tree2 = require("@behindthemusictree/app-kit/genre-tree");
|
|
314
|
+
// src/genre-tree/playlist-tree/useGenrePlaylistPlayback.tsx
|
|
315
|
+
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
314
316
|
function useGenrePlaylistPlayback({
|
|
315
317
|
scope,
|
|
316
318
|
genrePlaylists,
|
|
317
319
|
artist = null
|
|
318
320
|
}) {
|
|
319
321
|
const { trackList, playNewTrackListFromGenrePlaylist } = (0, import_genre_tree2.useTrackList)();
|
|
322
|
+
const { showPopup } = (0, import_popup.usePopup)();
|
|
320
323
|
const origin = trackList?.origin;
|
|
321
324
|
const playing = (0, import_react2.useMemo)(() => {
|
|
322
325
|
if (!origin || origin.type !== import_genre_tree2.TrackListOriginType.GENRE_PLAYLIST || origin.scope !== scope) return null;
|
|
@@ -328,14 +331,20 @@ function useGenrePlaylistPlayback({
|
|
|
328
331
|
}, [origin, artist, genrePlaylists, scope]);
|
|
329
332
|
const play = (0, import_react2.useCallback)(async (playlist, requested) => {
|
|
330
333
|
if (artist && !playlist.criteria) return;
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
+
try {
|
|
335
|
+
const selection = scope === "reference" && playlist.criteria !== null ? requested ?? (0, import_genre_tree2.defaultGenreMusicSelection)(import_genre_tree2.GenreCatalogueCountsSchema.parse(playlist)) : void 0;
|
|
336
|
+
await (selection || artist ? playNewTrackListFromGenrePlaylist(playlist, scope, { selection, ...artist && { artistUuid: artist.uuid } }) : playNewTrackListFromGenrePlaylist(playlist, scope));
|
|
337
|
+
} catch (error) {
|
|
338
|
+
console.error("Failed to load genre playlist tracks:", error);
|
|
339
|
+
if (error instanceof import_genre_tree2.TracksFailureAlreadyReportedError) return;
|
|
340
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport.AppError ? error.code : import_transport.ErrorCode.CLIENT_UNKNOWN }));
|
|
341
|
+
}
|
|
342
|
+
}, [artist, scope, playNewTrackListFromGenrePlaylist, showPopup]);
|
|
334
343
|
return (0, import_react2.useMemo)(() => ({ playing, play }), [playing, play]);
|
|
335
344
|
}
|
|
336
345
|
|
|
337
346
|
// src/genre-tree/playlist-tree/TreePerRoot.tsx
|
|
338
|
-
var
|
|
347
|
+
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
339
348
|
function GenrePlaylistTreePerRoot({
|
|
340
349
|
scope,
|
|
341
350
|
className: className2,
|
|
@@ -354,25 +363,16 @@ function GenrePlaylistTreePerRoot({
|
|
|
354
363
|
viewportRestore,
|
|
355
364
|
onViewportChange,
|
|
356
365
|
playback,
|
|
366
|
+
focusUuids,
|
|
357
367
|
...hostPanel
|
|
358
368
|
}) {
|
|
359
369
|
const { isPlaying, setIsPlaying } = (0, import_player.usePlayer)();
|
|
360
370
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: genrePlaylistTreePerRoot });
|
|
361
371
|
const { playing, play } = playback ?? defaultPlayback;
|
|
362
372
|
const playingNodeId = playing?.uuid ?? null;
|
|
363
|
-
const { showPopup } = (0, import_popup.usePopup)();
|
|
364
373
|
const nodes = (0, import_react3.useMemo)(
|
|
365
|
-
() => genrePlaylistTreePerRoot
|
|
366
|
-
|
|
367
|
-
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
368
|
-
name: genrePlaylist.name,
|
|
369
|
-
itemCount: (0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist),
|
|
370
|
-
actionable: Boolean(genrePlaylist.criteria),
|
|
371
|
-
side: genrePlaylist.criteria?.side ?? void 0,
|
|
372
|
-
wikidataId: genrePlaylist.criteria?.wikidataId ?? null,
|
|
373
|
-
umbrella: genrePlaylist.isUmbrella
|
|
374
|
-
})),
|
|
375
|
-
[genrePlaylistTreePerRoot]
|
|
374
|
+
() => toTreeNodes(genrePlaylistTreePerRoot, "songs", focusUuids),
|
|
375
|
+
[genrePlaylistTreePerRoot, focusUuids]
|
|
376
376
|
);
|
|
377
377
|
const handlePlayPause = (0, import_react3.useCallback)(
|
|
378
378
|
(nodeId) => {
|
|
@@ -385,18 +385,14 @@ function GenrePlaylistTreePerRoot({
|
|
|
385
385
|
if ((0, import_genre_tree3.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
386
386
|
return;
|
|
387
387
|
}
|
|
388
|
-
play(genrePlaylist)
|
|
389
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
390
|
-
showPopup(/* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InternalErrorPopup, { errorCode: import_transport.ErrorCode.CLIENT_UNKNOWN }));
|
|
391
|
-
});
|
|
388
|
+
void play(genrePlaylist);
|
|
392
389
|
},
|
|
393
390
|
[
|
|
394
391
|
genrePlaylistTreePerRoot,
|
|
395
392
|
playingNodeId,
|
|
396
393
|
isPlaying,
|
|
397
394
|
setIsPlaying,
|
|
398
|
-
play
|
|
399
|
-
showPopup
|
|
395
|
+
play
|
|
400
396
|
]
|
|
401
397
|
);
|
|
402
398
|
const handleAddChild = (0, import_react3.useCallback)(
|
|
@@ -419,7 +415,7 @@ function GenrePlaylistTreePerRoot({
|
|
|
419
415
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
420
416
|
}
|
|
421
417
|
}, []);
|
|
422
|
-
return /* @__PURE__ */ (0,
|
|
418
|
+
return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
|
|
423
419
|
import_genre_tree_view.GenreTree,
|
|
424
420
|
{
|
|
425
421
|
className: className2,
|
|
@@ -450,9 +446,7 @@ var import_genre_tree4 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
450
446
|
var import_react4 = require("react");
|
|
451
447
|
var import_genre_tree_view2 = require("@behindthemusictree/genre-tree-view");
|
|
452
448
|
var import_player2 = require("@behindthemusictree/app-kit/player");
|
|
453
|
-
var
|
|
454
|
-
var import_transport2 = require("@behindthemusictree/app-kit/transport");
|
|
455
|
-
var import_jsx_runtime6 = require("react/jsx-runtime");
|
|
449
|
+
var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
456
450
|
function GenrePlaylistTreeWheel({
|
|
457
451
|
scope,
|
|
458
452
|
className: className2,
|
|
@@ -473,24 +467,16 @@ function GenrePlaylistTreeWheel({
|
|
|
473
467
|
viewportRestore,
|
|
474
468
|
onViewportChange,
|
|
475
469
|
playback,
|
|
470
|
+
focusUuids,
|
|
476
471
|
...hostPanel
|
|
477
472
|
}) {
|
|
478
473
|
const { isPlaying, setIsPlaying } = (0, import_player2.usePlayer)();
|
|
479
474
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
480
475
|
const { playing, play } = playback ?? defaultPlayback;
|
|
481
476
|
const playingNodeId = playing?.uuid ?? null;
|
|
482
|
-
const { showPopup } = (0, import_popup2.usePopup)();
|
|
483
477
|
const nodes = (0, import_react4.useMemo)(
|
|
484
|
-
() => genrePlaylists
|
|
485
|
-
|
|
486
|
-
parentId: genrePlaylist.parent?.uuid ?? null,
|
|
487
|
-
name: genrePlaylist.name,
|
|
488
|
-
itemCount: genrePlaylistSize(genrePlaylist, sizeMetric),
|
|
489
|
-
actionable: Boolean(genrePlaylist.criteria),
|
|
490
|
-
side: genrePlaylist.criteria?.side ?? void 0,
|
|
491
|
-
wikidataId: genrePlaylist.criteria?.wikidataId ?? null
|
|
492
|
-
})),
|
|
493
|
-
[genrePlaylists, sizeMetric]
|
|
478
|
+
() => toTreeNodes(genrePlaylists, sizeMetric, focusUuids),
|
|
479
|
+
[genrePlaylists, sizeMetric, focusUuids]
|
|
494
480
|
);
|
|
495
481
|
const handlePlayPause = (0, import_react4.useCallback)(
|
|
496
482
|
(nodeId) => {
|
|
@@ -503,18 +489,14 @@ function GenrePlaylistTreeWheel({
|
|
|
503
489
|
if ((0, import_genre_tree4.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
504
490
|
return;
|
|
505
491
|
}
|
|
506
|
-
play(genrePlaylist)
|
|
507
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
508
|
-
showPopup(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)(InternalErrorPopup, { errorCode: import_transport2.ErrorCode.CLIENT_UNKNOWN }));
|
|
509
|
-
});
|
|
492
|
+
void play(genrePlaylist);
|
|
510
493
|
},
|
|
511
494
|
[
|
|
512
495
|
genrePlaylists,
|
|
513
496
|
playingNodeId,
|
|
514
497
|
isPlaying,
|
|
515
498
|
setIsPlaying,
|
|
516
|
-
play
|
|
517
|
-
showPopup
|
|
499
|
+
play
|
|
518
500
|
]
|
|
519
501
|
);
|
|
520
502
|
const handleAddChild = (0, import_react4.useCallback)(
|
|
@@ -537,7 +519,7 @@ function GenrePlaylistTreeWheel({
|
|
|
537
519
|
if (confirm(`Are you sure you want to delete "${node.name}"?`)) {
|
|
538
520
|
}
|
|
539
521
|
}, []);
|
|
540
|
-
return /* @__PURE__ */ (0,
|
|
522
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
541
523
|
import_genre_tree_view2.GenreTreeWheel,
|
|
542
524
|
{
|
|
543
525
|
className: className2,
|
|
@@ -569,7 +551,7 @@ var import_genre_tree5 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
569
551
|
var import_react5 = require("react");
|
|
570
552
|
var import_genre_tree_view3 = require("@behindthemusictree/genre-tree-view");
|
|
571
553
|
var import_player3 = require("@behindthemusictree/app-kit/player");
|
|
572
|
-
var
|
|
554
|
+
var import_jsx_runtime8 = require("react/jsx-runtime");
|
|
573
555
|
function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
574
556
|
const {
|
|
575
557
|
scope,
|
|
@@ -602,7 +584,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
602
584
|
const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists });
|
|
603
585
|
const { playing, play } = playback ?? defaultPlayback;
|
|
604
586
|
const playingNodeId = playing?.uuid ?? null;
|
|
605
|
-
const nodes = (0, import_react5.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric), [genrePlaylists, sizeMetric]);
|
|
587
|
+
const nodes = (0, import_react5.useMemo)(() => toTreeNodes(genrePlaylists, sizeMetric, props.focusUuids), [genrePlaylists, sizeMetric, props.focusUuids]);
|
|
606
588
|
const handlePlayPause = (0, import_react5.useCallback)(
|
|
607
589
|
(nodeId) => {
|
|
608
590
|
const genrePlaylist = genrePlaylists.find((g) => g.uuid === nodeId);
|
|
@@ -614,9 +596,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
614
596
|
if ((0, import_genre_tree5.genrePlaylistTrackCount)(genrePlaylist) === 0) {
|
|
615
597
|
return;
|
|
616
598
|
}
|
|
617
|
-
play(genrePlaylist)
|
|
618
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
619
|
-
});
|
|
599
|
+
void play(genrePlaylist);
|
|
620
600
|
},
|
|
621
601
|
[genrePlaylists, playingNodeId, isPlaying, setIsPlaying, play]
|
|
622
602
|
);
|
|
@@ -656,7 +636,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
656
636
|
onSelectedNodeChange,
|
|
657
637
|
...hostPanel
|
|
658
638
|
};
|
|
659
|
-
return outline ? /* @__PURE__ */ (0,
|
|
639
|
+
return outline ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_genre_tree_view3.GenreTreeOutline, { ...treeProps }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
|
|
660
640
|
import_genre_tree_view3.GenreTreeWheelRadialPopCore,
|
|
661
641
|
{
|
|
662
642
|
...treeProps,
|
|
@@ -673,7 +653,7 @@ function GenrePlaylistTreeWheelRadialPopCore(props) {
|
|
|
673
653
|
|
|
674
654
|
// src/genre-tree/GenreTreeWheelHandoff.tsx
|
|
675
655
|
var import_react6 = require("react");
|
|
676
|
-
var
|
|
656
|
+
var import_jsx_runtime9 = require("react/jsx-runtime");
|
|
677
657
|
function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
678
658
|
const [revealed, setRevealed] = (0, import_react6.useState)(false);
|
|
679
659
|
const onRevealedChangeRef = (0, import_react6.useRef)(onRevealedChange);
|
|
@@ -692,8 +672,8 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
692
672
|
cancelAnimationFrame(innerFrame);
|
|
693
673
|
};
|
|
694
674
|
}, []);
|
|
695
|
-
return /* @__PURE__ */ (0,
|
|
696
|
-
/* @__PURE__ */ (0,
|
|
675
|
+
return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { className: "relative w-full h-full", children: [
|
|
676
|
+
/* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
|
|
697
677
|
"div",
|
|
698
678
|
{
|
|
699
679
|
className: "absolute inset-0 transition-opacity duration-150 ease-out",
|
|
@@ -702,7 +682,7 @@ function GenreTreeWheelHandoff({ skeleton, children, onRevealedChange }) {
|
|
|
702
682
|
children
|
|
703
683
|
}
|
|
704
684
|
),
|
|
705
|
-
!revealed && /* @__PURE__ */ (0,
|
|
685
|
+
!revealed && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { className: "absolute inset-0", "aria-hidden": "true", children: skeleton })
|
|
706
686
|
] });
|
|
707
687
|
}
|
|
708
688
|
|
|
@@ -717,7 +697,7 @@ var import_genre_tree9 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
717
697
|
// src/genre-tree/search/SearchBox.tsx
|
|
718
698
|
var import_react7 = require("react");
|
|
719
699
|
var import_ui3 = require("@behindthemusictree/ui");
|
|
720
|
-
var
|
|
700
|
+
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
721
701
|
function SearchBox({
|
|
722
702
|
label,
|
|
723
703
|
placeholder,
|
|
@@ -739,7 +719,7 @@ function SearchBox({
|
|
|
739
719
|
groups.find((group) => group.key === groupKey)?.items.find((item) => item.key === itemKey)?.onSelect();
|
|
740
720
|
onPicked?.(groupKey, itemKey);
|
|
741
721
|
};
|
|
742
|
-
return /* @__PURE__ */ (0,
|
|
722
|
+
return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: className2, onFocusCapture: onFocus, children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
|
|
743
723
|
import_ui3.SearchCombobox,
|
|
744
724
|
{
|
|
745
725
|
ariaLabel: label,
|
|
@@ -771,7 +751,7 @@ var searchStatus = (state, count, noun) => state.isError ? SEARCH_FAILED_STATUS
|
|
|
771
751
|
|
|
772
752
|
// src/genre-tree/search/useArtistSearchGroup.tsx
|
|
773
753
|
var import_genre_tree6 = require("@behindthemusictree/app-kit/genre-tree");
|
|
774
|
-
var
|
|
754
|
+
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
775
755
|
function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
776
756
|
const search = (0, import_genre_tree6.useArtistSearch)(getBaseUrl, enabled ? text : "");
|
|
777
757
|
if (!enabled) return void 0;
|
|
@@ -780,15 +760,15 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
780
760
|
label: "Artists",
|
|
781
761
|
items: search.artists.map((artist) => ({
|
|
782
762
|
key: artist.uuid,
|
|
783
|
-
content: /* @__PURE__ */ (0,
|
|
784
|
-
/* @__PURE__ */ (0,
|
|
763
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(import_jsx_runtime11.Fragment, { children: [
|
|
764
|
+
/* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
785
765
|
artist.name,
|
|
786
|
-
artist.disambiguation && /* @__PURE__ */ (0,
|
|
766
|
+
artist.disambiguation && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "font-normal text-[var(--color-neutral-500)]", children: [
|
|
787
767
|
" \xB7 ",
|
|
788
768
|
artist.disambiguation
|
|
789
769
|
] })
|
|
790
770
|
] }),
|
|
791
|
-
artist.matchedAlias && /* @__PURE__ */ (0,
|
|
771
|
+
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [
|
|
792
772
|
"also known as ",
|
|
793
773
|
artist.matchedAlias
|
|
794
774
|
] })
|
|
@@ -802,7 +782,7 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
802
782
|
|
|
803
783
|
// src/genre-tree/search/useSongSearchGroup.tsx
|
|
804
784
|
var import_genre_tree7 = require("@behindthemusictree/app-kit/genre-tree");
|
|
805
|
-
var
|
|
785
|
+
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
806
786
|
function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
807
787
|
const search = (0, import_genre_tree7.useSongSearch)(getBaseUrl, enabled ? text : "");
|
|
808
788
|
if (!enabled) return void 0;
|
|
@@ -811,9 +791,9 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
811
791
|
label: "Songs",
|
|
812
792
|
items: search.songs.map((song) => ({
|
|
813
793
|
key: song.uuid,
|
|
814
|
-
content: /* @__PURE__ */ (0,
|
|
815
|
-
/* @__PURE__ */ (0,
|
|
816
|
-
/* @__PURE__ */ (0,
|
|
794
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
795
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
796
|
+
/* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [song.artists.map((artist) => artist.name).join(", "), song.genre?.name ?? "No genre"].filter(Boolean).join(" \xB7 ") })
|
|
817
797
|
] }),
|
|
818
798
|
onSelect: () => onSelect(song)
|
|
819
799
|
})),
|
|
@@ -824,7 +804,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
824
804
|
|
|
825
805
|
// src/genre-tree/search/useGenreRemoteSearchGroup.tsx
|
|
826
806
|
var import_genre_tree8 = require("@behindthemusictree/app-kit/genre-tree");
|
|
827
|
-
var
|
|
807
|
+
var import_jsx_runtime13 = require("react/jsx-runtime");
|
|
828
808
|
function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres", label = "Genres", filter, describe, ...options } = {}) {
|
|
829
809
|
const search = (0, import_genre_tree8.useGenreRemoteSearch)(getBaseUrl, text, options);
|
|
830
810
|
const genres = filter ? search.genres.filter(filter) : search.genres;
|
|
@@ -833,12 +813,12 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
833
813
|
label,
|
|
834
814
|
items: genres.map((genre) => ({
|
|
835
815
|
key: genre.uuid,
|
|
836
|
-
content: /* @__PURE__ */ (0,
|
|
837
|
-
/* @__PURE__ */ (0,
|
|
816
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(import_jsx_runtime13.Fragment, { children: [
|
|
817
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
838
818
|
genre.name,
|
|
839
|
-
genre.isUmbrella && /* @__PURE__ */ (0,
|
|
819
|
+
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "ml-2 text-caption font-normal italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
840
820
|
] }),
|
|
841
|
-
/* @__PURE__ */ (0,
|
|
821
|
+
/* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: describe?.(genre) ?? `${genre.treeName} \xB7 ${genre.root.name}` })
|
|
842
822
|
] }),
|
|
843
823
|
onSelect: () => onSelect(genre)
|
|
844
824
|
})),
|
|
@@ -848,7 +828,7 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
848
828
|
}
|
|
849
829
|
|
|
850
830
|
// src/genre-tree/GenreSearch.tsx
|
|
851
|
-
var
|
|
831
|
+
var import_jsx_runtime14 = require("react/jsx-runtime");
|
|
852
832
|
function GenreSearch({
|
|
853
833
|
genrePlaylists,
|
|
854
834
|
onSelect,
|
|
@@ -877,9 +857,9 @@ function GenreSearch({
|
|
|
877
857
|
label: hasExtras ? "Genres" : void 0,
|
|
878
858
|
items: results.map((genrePlaylist) => ({
|
|
879
859
|
key: genrePlaylist.uuid,
|
|
880
|
-
content: /* @__PURE__ */ (0,
|
|
860
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
|
|
881
861
|
genrePlaylist.name,
|
|
882
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */ (0,
|
|
862
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
883
863
|
] }),
|
|
884
864
|
onSelect: () => select(genrePlaylist)
|
|
885
865
|
}))
|
|
@@ -888,7 +868,7 @@ function GenreSearch({
|
|
|
888
868
|
(group) => active ? group : { ...group, items: [], status: "", loading: false }
|
|
889
869
|
)
|
|
890
870
|
];
|
|
891
|
-
return /* @__PURE__ */ (0,
|
|
871
|
+
return /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("div", { className: "genre-search w-[calc(var(--layout-detail-panel-w,25.5rem)-2*var(--layout-panel-inset,1rem))] shrink-0 max-md:w-full", children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
|
|
892
872
|
SearchBox,
|
|
893
873
|
{
|
|
894
874
|
label,
|
|
@@ -908,14 +888,14 @@ function GenreSearch({
|
|
|
908
888
|
clear();
|
|
909
889
|
onQueryChange?.("");
|
|
910
890
|
} : void 0,
|
|
911
|
-
leading: onPrevious && /* @__PURE__ */ (0,
|
|
891
|
+
leading: onPrevious && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("button", { type: "button", "aria-label": "Previous", title: "Previous", className: import_ui4.SEARCH_LEADING_BUTTON_CLASS, onClick: onPrevious, children: /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react3.ArrowLeft, { "aria-hidden": "true", className: "h-4 w-4" }) }),
|
|
912
892
|
onFocus
|
|
913
893
|
}
|
|
914
894
|
) });
|
|
915
895
|
}
|
|
916
896
|
|
|
917
897
|
// src/genre-tree/GenreTreeSearch.tsx
|
|
918
|
-
var
|
|
898
|
+
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
919
899
|
function GenreTreeSearch({
|
|
920
900
|
artistBaseUrl,
|
|
921
901
|
songBaseUrl,
|
|
@@ -935,7 +915,7 @@ function GenreTreeSearch({
|
|
|
935
915
|
const deferredQuery = (0, import_react8.useDeferredValue)(query);
|
|
936
916
|
const artistGroup = useArtistSearchGroup(artistBaseUrl, deferredQuery, onArtistSelect, artistSearch);
|
|
937
917
|
const songGroup = useSongSearchGroup(songBaseUrl, deferredQuery, onSongSelect, songSearch);
|
|
938
|
-
const render = (hostGroups) => /* @__PURE__ */ (0,
|
|
918
|
+
const render = (hostGroups) => /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(
|
|
939
919
|
GenreSearch,
|
|
940
920
|
{
|
|
941
921
|
...props,
|
|
@@ -950,7 +930,7 @@ function GenreTreeSearch({
|
|
|
950
930
|
extraGroups: [...extraGroups, ...hostGroups, artistGroup, songGroup].filter((group) => group !== void 0)
|
|
951
931
|
}
|
|
952
932
|
);
|
|
953
|
-
return SearchGroups ? /* @__PURE__ */ (0,
|
|
933
|
+
return SearchGroups ? /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(SearchGroups, { query: deferredQuery, focused, onSelectGenre, children: render }) : render([]);
|
|
954
934
|
}
|
|
955
935
|
|
|
956
936
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
@@ -970,7 +950,7 @@ var import_ui6 = require("@behindthemusictree/ui");
|
|
|
970
950
|
// src/genre-tree/ShareActionButton.tsx
|
|
971
951
|
var import_lucide_react6 = require("lucide-react");
|
|
972
952
|
var import_ui5 = require("@behindthemusictree/ui");
|
|
973
|
-
var
|
|
953
|
+
var import_popup2 = require("@behindthemusictree/app-kit/popup");
|
|
974
954
|
|
|
975
955
|
// src/genre-tree/SharePopup.tsx
|
|
976
956
|
var import_react10 = require("react");
|
|
@@ -981,7 +961,7 @@ var import_si = require("react-icons/si");
|
|
|
981
961
|
// src/popup/Toast.tsx
|
|
982
962
|
var import_react9 = require("react");
|
|
983
963
|
var import_react_dom2 = require("react-dom");
|
|
984
|
-
var
|
|
964
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
985
965
|
function Toast({ message, onClose, durationMs = 2200 }) {
|
|
986
966
|
const [mounted, setMounted] = (0, import_react9.useState)(false);
|
|
987
967
|
(0, import_react9.useEffect)(() => {
|
|
@@ -991,7 +971,7 @@ function Toast({ message, onClose, durationMs = 2200 }) {
|
|
|
991
971
|
}, [durationMs, onClose]);
|
|
992
972
|
if (!mounted) return null;
|
|
993
973
|
return (0, import_react_dom2.createPortal)(
|
|
994
|
-
/* @__PURE__ */ (0,
|
|
974
|
+
/* @__PURE__ */ (0, import_jsx_runtime16.jsx)("div", { className: "pointer-events-none fixed inset-x-0 bottom-8 z-[60] flex justify-center px-4", children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
995
975
|
"div",
|
|
996
976
|
{
|
|
997
977
|
role: "status",
|
|
@@ -1006,12 +986,12 @@ function Toast({ message, onClose, durationMs = 2200 }) {
|
|
|
1006
986
|
}
|
|
1007
987
|
|
|
1008
988
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
1009
|
-
var
|
|
989
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1010
990
|
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";
|
|
1011
991
|
function Contents({ icon, label }) {
|
|
1012
|
-
return /* @__PURE__ */ (0,
|
|
1013
|
-
/* @__PURE__ */ (0,
|
|
1014
|
-
/* @__PURE__ */ (0,
|
|
992
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(import_jsx_runtime17.Fragment, { children: [
|
|
993
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "flex h-12 w-12 items-center justify-center rounded-full bg-[var(--color-surface-muted)] transition-colors group-hover:bg-[var(--color-border)]", children: icon }),
|
|
994
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "max-w-full truncate", children: label })
|
|
1015
995
|
] });
|
|
1016
996
|
}
|
|
1017
997
|
function ShareDestinationButton({
|
|
@@ -1023,29 +1003,29 @@ function ShareDestinationButton({
|
|
|
1023
1003
|
ariaLabel
|
|
1024
1004
|
}) {
|
|
1025
1005
|
if (href) {
|
|
1026
|
-
return /* @__PURE__ */ (0,
|
|
1006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", "aria-label": ariaLabel, className, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Contents, { icon, label }) });
|
|
1027
1007
|
}
|
|
1028
|
-
return /* @__PURE__ */ (0,
|
|
1008
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("button", { type: "button", onClick, disabled, "aria-label": ariaLabel, className, children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(Contents, { icon, label }) });
|
|
1029
1009
|
}
|
|
1030
1010
|
|
|
1031
1011
|
// src/genre-tree/SharePreviewCard.tsx
|
|
1032
1012
|
var import_lucide_react4 = require("lucide-react");
|
|
1033
|
-
var
|
|
1013
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1034
1014
|
function SharePreviewCard({ target, url }) {
|
|
1035
1015
|
const Icon = { genre: import_lucide_react4.Music2, artist: import_lucide_react4.UserRound, song: import_lucide_react4.Music }[target.kind];
|
|
1036
1016
|
const typeLabel = { genre: "Genre", artist: "Artist", song: "Song" }[target.kind];
|
|
1037
|
-
return /* @__PURE__ */ (0,
|
|
1038
|
-
/* @__PURE__ */ (0,
|
|
1039
|
-
/* @__PURE__ */ (0,
|
|
1040
|
-
/* @__PURE__ */ (0,
|
|
1041
|
-
/* @__PURE__ */ (0,
|
|
1042
|
-
/* @__PURE__ */ (0,
|
|
1017
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "rounded-3xl bg-[var(--color-surface-muted)] p-4", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex min-h-32 overflow-hidden rounded-2xl bg-[var(--color-surface)] shadow-lg", children: [
|
|
1018
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "flex w-28 shrink-0 items-center justify-center bg-[var(--color-primary)]/15 text-[var(--color-primary)]", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(Icon, { "aria-hidden": "true", className: "h-10 w-10" }) }),
|
|
1019
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
1020
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
1021
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
1022
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
1043
1023
|
] })
|
|
1044
1024
|
] }) });
|
|
1045
1025
|
}
|
|
1046
1026
|
|
|
1047
1027
|
// src/genre-tree/SharePopup.tsx
|
|
1048
|
-
var
|
|
1028
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1049
1029
|
function resolveAbsoluteUrl(url) {
|
|
1050
1030
|
try {
|
|
1051
1031
|
const parsed = new URL(url, window.location.href);
|
|
@@ -1120,8 +1100,8 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1120
1100
|
setShareError("Could not open the share options.");
|
|
1121
1101
|
}
|
|
1122
1102
|
};
|
|
1123
|
-
return /* @__PURE__ */ (0,
|
|
1124
|
-
/* @__PURE__ */ (0,
|
|
1103
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
1104
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1125
1105
|
BasePopup_default,
|
|
1126
1106
|
{
|
|
1127
1107
|
title: "Share",
|
|
@@ -1136,70 +1116,70 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1136
1116
|
titleTextClassName: "!text-xl !font-semibold !text-[var(--color-text)]",
|
|
1137
1117
|
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)]",
|
|
1138
1118
|
contentClassName: "!rounded-none !bg-transparent !px-6 !pb-6 !pt-2",
|
|
1139
|
-
children: /* @__PURE__ */ (0,
|
|
1140
|
-
/* @__PURE__ */ (0,
|
|
1141
|
-
/* @__PURE__ */ (0,
|
|
1142
|
-
/* @__PURE__ */ (0,
|
|
1119
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "flex flex-col gap-4", children: [
|
|
1120
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(SharePreviewCard, { target, url: absoluteUrl || url }),
|
|
1121
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("div", { className: "grid grid-cols-3 gap-1 rounded-3xl bg-[var(--color-surface)] p-3 sm:grid-cols-4", children: [
|
|
1122
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1143
1123
|
ShareDestinationButton,
|
|
1144
1124
|
{
|
|
1145
1125
|
label: "Copy Link",
|
|
1146
|
-
icon: /* @__PURE__ */ (0,
|
|
1126
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react5.Link2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
1147
1127
|
onClick: () => void handleCopy(),
|
|
1148
1128
|
ariaLabel: "Copy link",
|
|
1149
1129
|
disabled: !absoluteUrl
|
|
1150
1130
|
}
|
|
1151
1131
|
),
|
|
1152
|
-
/* @__PURE__ */ (0,
|
|
1132
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1153
1133
|
ShareDestinationButton,
|
|
1154
1134
|
{
|
|
1155
1135
|
label: "WhatsApp",
|
|
1156
|
-
icon: /* @__PURE__ */ (0,
|
|
1136
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_fa.FaWhatsapp, { "aria-hidden": "true", className: "h-9 w-9 text-[#25D366]" }),
|
|
1157
1137
|
href: destinationUrls?.whatsapp,
|
|
1158
1138
|
ariaLabel: `Share ${target.name} via WhatsApp`,
|
|
1159
1139
|
disabled: !absoluteUrl
|
|
1160
1140
|
}
|
|
1161
1141
|
),
|
|
1162
|
-
/* @__PURE__ */ (0,
|
|
1142
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1163
1143
|
ShareDestinationButton,
|
|
1164
1144
|
{
|
|
1165
1145
|
label: "Gmail",
|
|
1166
|
-
icon: /* @__PURE__ */ (0,
|
|
1146
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_si.SiGmail, { "aria-hidden": "true", className: "h-8 w-8 text-[#EA4335]" }),
|
|
1167
1147
|
href: destinationUrls?.gmail,
|
|
1168
1148
|
ariaLabel: `Email ${target.name} with Gmail`,
|
|
1169
1149
|
disabled: !absoluteUrl
|
|
1170
1150
|
}
|
|
1171
1151
|
),
|
|
1172
|
-
canUseNativeShare && /* @__PURE__ */ (0,
|
|
1152
|
+
canUseNativeShare && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(
|
|
1173
1153
|
ShareDestinationButton,
|
|
1174
1154
|
{
|
|
1175
1155
|
label: "More",
|
|
1176
|
-
icon: /* @__PURE__ */ (0,
|
|
1156
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(import_lucide_react5.Share2, { "aria-hidden": "true", className: "h-6 w-6" }),
|
|
1177
1157
|
onClick: () => void handleNativeShare(),
|
|
1178
1158
|
ariaLabel: "More sharing options",
|
|
1179
1159
|
disabled: !absoluteUrl
|
|
1180
1160
|
}
|
|
1181
1161
|
)
|
|
1182
1162
|
] }),
|
|
1183
|
-
copyStatus === "failed" && /* @__PURE__ */ (0,
|
|
1184
|
-
shareError && /* @__PURE__ */ (0,
|
|
1163
|
+
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: "Could not copy the link." }),
|
|
1164
|
+
shareError && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
1185
1165
|
] })
|
|
1186
1166
|
}
|
|
1187
1167
|
),
|
|
1188
|
-
toastId > 0 && /* @__PURE__ */ (0,
|
|
1168
|
+
toastId > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)(Toast, { message: "Link copied", onClose: dismissToast }, toastId)
|
|
1189
1169
|
] });
|
|
1190
1170
|
}
|
|
1191
1171
|
|
|
1192
1172
|
// src/genre-tree/ShareActionButton.tsx
|
|
1193
|
-
var
|
|
1173
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1194
1174
|
function ShareActionButton({ target, url }) {
|
|
1195
|
-
const { showPopup, hidePopup } = (0,
|
|
1175
|
+
const { showPopup, hidePopup } = (0, import_popup2.usePopup)();
|
|
1196
1176
|
const openSharePopup = () => {
|
|
1197
|
-
showPopup(/* @__PURE__ */ (0,
|
|
1177
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime20.jsx)(SharePopup, { target, url, onClose: hidePopup }));
|
|
1198
1178
|
};
|
|
1199
|
-
return /* @__PURE__ */ (0,
|
|
1179
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1200
1180
|
import_ui5.ActionButton,
|
|
1201
1181
|
{
|
|
1202
|
-
icon: /* @__PURE__ */ (0,
|
|
1182
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(import_lucide_react6.Share2, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1203
1183
|
label: "Share",
|
|
1204
1184
|
"aria-label": `Share ${target.name}`,
|
|
1205
1185
|
title: `Share ${target.name}`,
|
|
@@ -1209,7 +1189,7 @@ function ShareActionButton({ target, url }) {
|
|
|
1209
1189
|
}
|
|
1210
1190
|
|
|
1211
1191
|
// src/genre-tree/GenreActionBand.tsx
|
|
1212
|
-
var
|
|
1192
|
+
var import_jsx_runtime21 = require("react/jsx-runtime");
|
|
1213
1193
|
function GenreActionBand({
|
|
1214
1194
|
node,
|
|
1215
1195
|
playActions,
|
|
@@ -1230,24 +1210,24 @@ function GenreActionBand({
|
|
|
1230
1210
|
items.push({
|
|
1231
1211
|
key: "zoom-in",
|
|
1232
1212
|
label: "Focus",
|
|
1233
|
-
icon: /* @__PURE__ */ (0,
|
|
1213
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.ZoomIn, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1234
1214
|
onClick: onZoomIn
|
|
1235
1215
|
});
|
|
1236
1216
|
}
|
|
1237
1217
|
if (onAddChild) {
|
|
1238
|
-
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */ (0,
|
|
1218
|
+
adminItems.push({ key: "add-child", label: "Add", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.Plus, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onAddChild });
|
|
1239
1219
|
}
|
|
1240
1220
|
if (onRename) {
|
|
1241
|
-
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */ (0,
|
|
1221
|
+
adminItems.push({ key: "rename", label: "Rename", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.Pencil, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onRename });
|
|
1242
1222
|
}
|
|
1243
1223
|
if (onChangeParent) {
|
|
1244
|
-
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */ (0,
|
|
1224
|
+
adminItems.push({ key: "change-parent", label: "Parent", icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.MoveUpRight, { "aria-hidden": "true", className: "w-5 h-5" }), onClick: onChangeParent });
|
|
1245
1225
|
}
|
|
1246
1226
|
if (onToggleSide) {
|
|
1247
1227
|
adminItems.push({
|
|
1248
1228
|
key: "toggle-side",
|
|
1249
1229
|
label: side === "pop" ? "Make core" : "Make pop",
|
|
1250
|
-
icon: /* @__PURE__ */ (0,
|
|
1230
|
+
icon: /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_lucide_react7.ArrowLeftRight, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1251
1231
|
onClick: onToggleSide,
|
|
1252
1232
|
disabled: !!toggleSideDisabledReason,
|
|
1253
1233
|
title: toggleSideDisabledReason
|
|
@@ -1262,9 +1242,9 @@ function GenreActionBand({
|
|
|
1262
1242
|
disabled: action.enabled ? !action.enabled(node) : false
|
|
1263
1243
|
});
|
|
1264
1244
|
}
|
|
1265
|
-
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0,
|
|
1245
|
+
const renderItems = (list) => list.map((item) => /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ui6.ActionButton, { icon: item.icon, label: item.label, disabled: item.disabled, title: item.title, onClick: item.onClick }, item.key));
|
|
1266
1246
|
if (!playActions && items.length === 0 && adminItems.length === 0 && !(shareTarget && shareUrl)) return null;
|
|
1267
|
-
return /* @__PURE__ */ (0,
|
|
1247
|
+
return /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(import_ui6.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime21.jsxs)(
|
|
1268
1248
|
import_ui6.ActionBand,
|
|
1269
1249
|
{
|
|
1270
1250
|
className: "genre-action-band",
|
|
@@ -1272,7 +1252,7 @@ function GenreActionBand({
|
|
|
1272
1252
|
children: [
|
|
1273
1253
|
playActions,
|
|
1274
1254
|
renderItems(items),
|
|
1275
|
-
shareTarget && shareUrl && /* @__PURE__ */ (0,
|
|
1255
|
+
shareTarget && shareUrl && /* @__PURE__ */ (0, import_jsx_runtime21.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
1276
1256
|
]
|
|
1277
1257
|
}
|
|
1278
1258
|
) });
|
|
@@ -1296,7 +1276,7 @@ var REGION_GLOBE_PATHS = {
|
|
|
1296
1276
|
var REGION_GLOBES = ["africa", "americas", "asia"];
|
|
1297
1277
|
|
|
1298
1278
|
// src/genre-tree/RegionGlobeIcon.tsx
|
|
1299
|
-
var
|
|
1279
|
+
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1300
1280
|
var ROTATION_INTERVAL_MS = 3e3;
|
|
1301
1281
|
function RegionGlobeIcon({ className: className2 }) {
|
|
1302
1282
|
const [index, setIndex] = (0, import_react11.useState)(0);
|
|
@@ -1314,29 +1294,29 @@ function RegionGlobeIcon({ className: className2 }) {
|
|
|
1314
1294
|
clearInterval(timer);
|
|
1315
1295
|
};
|
|
1316
1296
|
}, []);
|
|
1317
|
-
return /* @__PURE__ */ (0,
|
|
1297
|
+
return /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("svg", { viewBox: "0 0 512 512", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime22.jsx)("path", { "data-testid": "region-globe-path", d: REGION_GLOBE_PATHS[REGION_GLOBES[index]] }) });
|
|
1318
1298
|
}
|
|
1319
1299
|
|
|
1320
1300
|
// src/genre-tree/treeMarkPath.ts
|
|
1321
1301
|
var TREE_MARK_PATH = "M3171 5598 c-5 -13 -5 -24 0 -26 5 -2 9 -16 9 -31 0 -25 -3 -28 -25 -23 l-25 4 0 -116 c0 -64 3 -116 8 -116 10 0 32 51 26 61 -3 5 -1 9 4 9 5 0 15 12 21 28 7 15 26 36 43 47 30 20 88 105 71 105 -4 0 -33 -21 -62 -47 l-54 -47 6 63 c4 35 7 72 7 82 0 10 9 19 23 22 16 3 13 5 -11 6 -25 1 -35 -4 -41 -21z M2893 5485 c8 -76 24 -100 71 -100 l36 0 0 53 c0 58 -15 69 -28 20 -8 -29 -10 -30 -16 -13 -15 43 -42 89 -55 93 -11 4 -13 -6 -8 -53z M2484 5438 c8 -70 49 -169 54 -131 2 12 10 27 18 33 17 15 19 84 3 129 -9 27 -16 31 -46 31 l-36 0 7 -62z M2625 5448 c-7 -22 -24 -121 -31 -179 l-6 -57 -27 11 c-15 5 -32 19 -37 31 -9 21 -88 86 -105 86 -39 0 38 -104 118 -158 17 -12 56 -59 86 -105 30 -45 67 -92 81 -104 14 -13 26 -30 26 -38 0 -13 -9 -11 -45 11 -67 39 -58 10 21 -66 67 -65 96 -110 108 -167 4 -17 13 -34 20 -36 20 -8 66 -186 75 -289 13 -161 -8 -272 -72 -365 -12 -18 -30 -33 -39 -33 -23 0 -53 33 -79 89 -25 54 -69 112 -121 162 -35 33 -38 40 -38 92 0 58 36 172 79 252 25 47 29 125 6 125 -19 0 -30 -22 -50 -100 -9 -35 -24 -78 -32 -94 l-16 -30 -19 24 -20 25 7 -58 c8 -62 0 -127 -16 -127 -19 0 -122 107 -166 172 -52 79 -68 150 -60 273 8 108 17 129 67 149 58 23 97 64 105 109 9 47 -5 49 -63 6 l-42 -30 15 35 c17 41 20 102 5 111 -18 11 -45 -4 -64 -36 -11 -19 -20 -60 -23 -110 -4 -54 -10 -79 -18 -79 -20 0 -27 28 -30 108 -2 40 -6 76 -9 79 -3 4 -6 51 -6 105 0 86 -3 101 -21 119 -27 27 -42 20 -53 -24 -7 -28 -5 -51 7 -90 9 -30 17 -76 17 -103 l0 -49 -29 51 c-29 49 -92 114 -111 114 -6 0 -10 -11 -10 -25 0 -14 5 -25 10 -25 6 0 10 -6 10 -13 0 -7 23 -44 51 -82 61 -84 59 -82 52 -57 -3 14 2 24 15 31 12 6 23 23 25 38 2 16 5 2 6 -29 1 -46 -2 -58 -14 -58 -21 0 -19 -13 10 -70 22 -44 25 -61 25 -165 l0 -116 -47 27 c-65 36 -142 118 -176 187 -15 31 -37 62 -49 68 -21 11 -21 10 -15 -41 l6 -52 -29 6 c-37 7 -39 -7 -4 -31 14 -10 53 -40 86 -68 92 -76 130 -104 163 -119 39 -19 101 -84 109 -116 10 -42 50 -88 217 -245 50 -47 94 -102 134 -167 33 -54 65 -98 71 -98 17 0 45 -79 51 -145 4 -47 0 -76 -20 -135 -14 -41 -39 -121 -56 -177 -18 -57 -35 -103 -40 -103 -4 0 -26 13 -49 30 -31 22 -50 49 -82 117 -99 209 -116 241 -185 337 -123 172 -123 173 -128 311 -5 140 -29 245 -57 245 -12 0 -20 -11 -24 -31 -9 -46 -7 -108 3 -127 14 -26 25 -162 14 -162 -20 0 -160 99 -192 135 -19 22 -42 58 -52 80 -10 23 -27 52 -37 66 -10 13 -26 38 -34 54 -9 17 -23 45 -33 64 -15 29 -16 40 -6 80 31 116 34 139 27 205 -7 57 -11 69 -28 74 -14 3 -32 30 -54 79 -21 46 -39 73 -47 70 -13 -5 -14 -15 -3 -65 l8 -33 -49 25 c-61 31 -93 40 -93 27 0 -13 43 -41 122 -79 47 -22 72 -41 83 -61 19 -38 19 -51 0 -51 -12 0 -15 -15 -16 -72 -1 -79 -12 -134 -22 -108 -3 8 -10 48 -16 89 -14 89 -25 111 -54 111 -38 0 -50 -15 -45 -54 4 -40 2 -42 -26 -21 -29 22 -36 19 -36 -20 0 -39 39 -85 125 -145 38 -27 62 -56 99 -120 45 -79 82 -177 70 -189 -2 -3 -42 3 -87 13 -45 10 -99 21 -119 26 -47 9 -103 51 -125 93 -24 44 -83 203 -94 252 -5 25 -4 59 3 91 14 68 3 140 -23 155 -12 6 -23 8 -27 5 -14 -15 -13 -115 2 -159 39 -116 0 -116 -70 1 -22 36 -31 42 -59 42 -20 0 -35 6 -39 15 -6 16 -56 21 -56 6 0 -5 23 -25 51 -44 53 -36 158 -156 188 -216 10 -20 26 -60 36 -88 11 -29 25 -53 32 -53 8 0 13 -12 13 -30 0 -26 -4 -30 -27 -31 l-28 -1 25 -7 c26 -8 177 -87 196 -102 5 -4 50 -18 100 -29 122 -29 277 -78 300 -95 10 -8 26 -15 34 -15 35 0 160 -166 160 -212 0 -22 -32 -24 -50 -4 -11 14 -100 46 -165 61 -16 3 -68 25 -115 48 -102 49 -163 56 -168 19 -9 -62 58 -104 178 -112 63 -5 103 -14 155 -37 39 -16 91 -38 117 -47 26 -9 74 -35 106 -56 52 -33 65 -48 96 -112 20 -40 39 -95 43 -122 6 -47 6 -48 -18 -41 -33 10 -69 33 -69 45 0 6 -10 10 -23 10 -13 0 -27 4 -32 9 -6 5 -27 14 -47 20 -20 7 -53 23 -73 37 -43 29 -45 29 -45 7 0 -26 80 -96 145 -127 119 -56 274 -185 311 -259 55 -107 104 -410 104 -640 0 -162 -22 -325 -45 -333 -25 -10 -72 25 -168 123 -129 131 -140 148 -182 274 -20 60 -50 142 -66 181 -16 39 -45 131 -65 202 -24 93 -55 173 -104 274 -77 158 -78 166 -32 256 31 64 27 129 -12 181 -31 40 -39 42 -65 18 -51 -49 -55 -120 -11 -208 37 -74 37 -85 3 -85 -36 0 -94 65 -137 154 -18 39 -37 80 -40 92 -3 11 -14 29 -24 40 -10 10 -28 35 -42 54 -13 19 -40 55 -61 80 -20 25 -41 63 -47 85 -6 22 -16 62 -23 89 -20 81 -95 147 -113 100 -18 -47 -6 -92 39 -147 25 -31 45 -61 45 -67 0 -15 -42 -3 -116 31 -94 44 -156 124 -184 235 -9 36 -13 41 -38 40 -39 -2 -144 113 -186 205 -31 66 -33 68 -53 54 -11 -8 -24 -11 -27 -7 -4 4 11 -24 33 -62 39 -67 43 -86 18 -86 -8 0 -8 3 1 9 11 6 9 9 -7 14 -11 3 -25 -1 -31 -7 -7 -10 0 -16 29 -24 39 -12 203 -147 215 -178 13 -34 4 -35 -48 -6 -64 37 -126 51 -126 30 0 -26 55 -67 125 -92 46 -16 80 -36 100 -58 l29 -33 -54 -3 c-79 -5 -203 14 -249 38 -47 24 -70 54 -105 140 -43 105 -115 163 -103 83 3 -21 9 -47 13 -57 4 -11 -15 4 -42 32 -62 64 -84 67 -84 14 0 -41 24 -76 61 -87 16 -6 18 -9 8 -15 -23 -15 15 -45 117 -91 52 -24 93 -48 91 -54 -10 -28 -150 -28 -190 0 -21 15 -47 5 -47 -17 0 -5 -10 -19 -22 -29 -23 -20 -23 -20 112 -14 174 8 208 8 430 0 l185 -7 84 -41 c115 -57 180 -118 225 -212 20 -41 36 -77 36 -80 0 -14 89 -126 150 -190 74 -78 120 -144 120 -175 0 -30 10 -33 -201 52 -94 38 -131 71 -218 195 -27 37 -59 77 -71 88 l-23 20 7 -40 c4 -22 12 -44 17 -49 13 -14 11 -26 -4 -26 -7 0 -29 21 -48 48 -33 45 -34 51 -39 159 -4 89 -9 116 -22 130 -17 16 -18 16 -18 0 0 -9 -7 -17 -16 -17 -14 0 -16 -9 -11 -62 3 -35 8 -74 12 -88 l7 -25 -25 27 c-41 44 -127 118 -137 118 -18 0 -10 -57 12 -85 18 -24 20 -32 10 -57 -10 -28 -9 -30 22 -43 18 -8 54 -19 79 -26 36 -9 60 -24 99 -66 80 -83 80 -83 1 -83 -80 0 -176 21 -236 51 -107 54 -234 169 -252 228 -4 14 -12 29 -17 35 -5 6 -18 25 -28 43 -24 40 -90 64 -116 42 -22 -18 -13 -84 17 -116 13 -13 42 -32 64 -42 22 -10 74 -53 115 -96 l75 -77 -75 5 c-135 8 -243 76 -336 207 -31 44 -65 87 -77 95 -37 26 -34 -9 7 -88 20 -39 34 -72 31 -75 -2 -2 -26 11 -52 31 -90 65 -143 83 -143 49 0 -32 71 -88 150 -117 41 -15 113 -47 159 -71 46 -24 99 -46 118 -50 18 -3 33 -12 33 -18 0 -12 -111 -46 -149 -46 -12 0 -29 -8 -39 -17 -10 -10 -27 -19 -37 -19 -11 -1 -45 -9 -75 -17 -58 -16 -110 -62 -110 -97 0 -39 116 -45 167 -9 11 8 34 31 52 51 28 32 50 43 144 74 145 47 222 48 404 5 70 -17 177 -38 237 -47 128 -19 202 -43 250 -79 18 -14 73 -42 122 -61 164 -66 208 -112 243 -251 36 -141 27 -167 -44 -123 -19 12 -63 23 -111 28 -117 13 -134 25 -275 193 -63 74 -193 151 -266 157 -29 2 -66 -1 -81 -7 -24 -10 -37 -9 -80 8 -66 26 -70 9 -11 -44 72 -65 119 -80 239 -78 60 1 109 -2 117 -8 6 -6 26 -35 42 -64 17 -30 46 -64 64 -77 19 -13 49 -40 67 -61 l34 -39 -79 3 c-57 3 -80 0 -83 -9 -3 -10 -7 -10 -18 -1 -8 6 -11 15 -8 20 3 5 0 9 -5 9 -16 0 -13 -16 6 -36 36 -36 78 -44 227 -44 119 0 152 -3 188 -19 56 -24 95 -64 125 -126 13 -27 35 -68 48 -90 14 -22 25 -53 25 -69 l0 -29 -107 5 c-131 6 -193 28 -290 100 -37 28 -82 56 -98 63 -75 32 -176 123 -277 247 -34 42 -122 98 -134 85 -5 -5 103 -138 184 -226 52 -57 46 -61 -49 -31 -87 28 -173 85 -325 214 -144 123 -189 151 -254 159 -25 2 -39 3 -32 0 6 -3 12 -16 12 -29 0 -17 -4 -23 -12 -19 -7 4 -1 -5 15 -19 15 -14 46 -30 70 -36 23 -6 60 -17 82 -25 l40 -13 -52 -1 c-49 -1 -53 -3 -53 -25 0 -28 28 -36 122 -36 54 0 62 -3 91 -32 l32 -33 -52 -3 c-88 -5 -75 -26 39 -62 130 -41 178 -63 206 -93 l22 -24 -20 -18 c-12 -11 -41 -20 -74 -23 -48 -4 -60 0 -116 32 -118 69 -241 96 -279 62 -13 -12 -40 -16 -104 -16 -48 0 -95 4 -105 9 -9 5 -34 16 -55 25 -20 9 -76 53 -122 97 -47 45 -88 79 -91 76 -12 -12 6 -54 41 -100 l36 -47 -74 0 c-88 0 -112 15 -78 49 26 26 21 39 -34 84 -87 73 -132 32 -50 -45 25 -23 45 -46 45 -50 0 -4 -21 2 -46 12 -45 20 -114 27 -114 12 0 -4 16 -22 35 -40 39 -38 78 -47 255 -61 164 -14 178 -17 172 -47 -2 -13 -2 -30 2 -39 5 -13 9 -13 40 2 19 9 33 20 30 25 -4 5 4 4 15 -4 21 -13 20 -15 -44 -74 -36 -33 -65 -66 -65 -72 0 -21 68 15 142 74 38 30 84 62 103 70 73 30 203 11 312 -46 32 -17 82 -33 111 -37 l53 -6 -28 -30 c-15 -16 -44 -40 -63 -52 -63 -42 -100 -82 -100 -111 0 -25 2 -26 37 -21 28 5 47 17 73 49 65 78 175 183 224 216 34 22 61 32 88 32 43 0 122 -36 152 -69 10 -11 39 -32 62 -46 43 -25 53 -46 36 -72 -11 -17 -200 -86 -232 -85 -28 1 -122 -47 -127 -65 -3 -8 14 -13 54 -15 l58 -3 -65 -44 c-36 -25 -68 -49 -71 -53 -11 -17 -115 -10 -188 12 -105 32 -112 11 -14 -39 l56 -28 -40 -6 c-52 -9 -96 0 -154 29 -31 15 -50 19 -60 13 -15 -10 -16 -10 44 -47 20 -13 37 -27 37 -31 0 -15 -144 -71 -205 -81 -33 -5 -85 -10 -116 -10 -32 0 -63 -6 -75 -14 -18 -13 -15 -15 34 -22 l53 -7 -31 -18 c-18 -12 -30 -27 -30 -40 0 -21 4 -21 61 -16 50 4 75 14 145 57 46 28 112 63 146 77 62 24 191 62 215 63 22 0 -47 -103 -107 -161 -42 -41 -60 -66 -65 -92 -10 -49 0 -60 47 -54 65 9 99 53 124 160 20 83 49 133 94 163 22 15 40 30 40 34 0 4 8 10 18 13 9 3 31 15 49 27 31 21 31 21 26 0 -3 -11 -21 -37 -40 -58 -43 -45 -72 -106 -73 -150 0 -39 18 -49 56 -30 38 18 63 64 75 137 13 82 40 142 89 194 22 24 40 49 40 54 0 6 24 21 53 34 49 22 63 23 237 20 193 -2 278 -14 348 -50 21 -11 44 -27 52 -36 7 -9 32 -27 55 -41 49 -28 138 -147 184 -243 16 -35 42 -114 57 -175 35 -147 31 -268 -14 -436 -17 -63 -37 -166 -45 -227 -12 -94 -21 -127 -54 -195 -22 -46 -52 -94 -67 -108 -15 -14 -46 -44 -68 -67 -23 -24 -47 -43 -53 -43 -7 0 -25 -12 -41 -26 -129 -121 -526 -267 -721 -268 -104 0 -109 -15 -19 -57 75 -35 67 -35 221 -10 125 21 235 27 235 13 0 -16 -66 -72 -85 -72 -24 0 -85 -36 -85 -49 0 -14 12 -19 58 -27 35 -5 42 -4 42 10 0 9 5 17 10 17 28 4 74 20 80 29 9 14 226 119 288 139 63 21 215 43 239 34 32 -12 12 -50 -52 -102 -36 -28 -73 -55 -83 -58 -17 -7 -66 -39 -92 -60 -8 -7 -38 -32 -67 -57 l-52 -45 42 -6 c36 -6 54 -1 122 33 44 22 120 56 169 76 112 45 222 107 289 164 46 40 84 62 107 62 18 0 130 -83 130 -96 0 -8 4 -14 10 -14 5 0 39 -26 75 -59 36 -32 96 -76 132 -97 36 -21 68 -46 71 -56 5 -19 21 -22 59 -12 18 5 20 9 10 19 -7 7 -69 71 -139 143 -147 149 -161 179 -80 168 136 -19 195 -39 378 -128 78 -37 147 -68 152 -68 6 0 15 -7 20 -16 8 -14 14 -15 46 -4 l38 12 -104 57 c-125 69 -148 84 -148 93 0 16 94 7 223 -22 74 -17 146 -30 160 -30 14 0 29 -4 32 -10 7 -11 54 6 115 43 l40 24 -38 1 c-22 1 -68 11 -103 21 -35 11 -107 30 -159 41 -131 31 -295 99 -406 171 -235 153 -355 366 -357 634 -1 211 65 343 285 568 117 119 206 167 368 198 153 29 267 59 328 86 80 35 166 44 264 27 148 -26 167 -38 251 -169 71 -110 136 -165 196 -165 26 0 31 4 31 23 -1 32 -28 62 -87 91 -39 20 -66 45 -118 112 -95 123 -95 135 -5 92 25 -12 77 -31 116 -43 56 -17 76 -19 97 -10 27 11 26 11 -25 29 -113 39 -138 49 -138 57 0 14 91 55 153 68 33 7 75 10 95 7 27 -4 31 -3 17 4 -19 8 -19 9 3 9 12 1 22 7 22 15 0 10 7 12 22 8 12 -3 17 -7 10 -10 -6 -2 -12 -10 -12 -18 0 -8 -6 -14 -12 -15 -27 -2 39 -17 80 -18 29 -1 42 3 42 13 0 20 -19 32 -67 45 -49 13 -53 22 -20 44 49 32 128 39 235 21 56 -9 112 -14 126 -10 26 6 96 69 96 86 0 6 -32 10 -77 10 -84 0 -126 -7 -118 -20 9 -14 -17 -24 -67 -24 -34 -1 -48 3 -48 13 0 8 -7 11 -20 8 -17 -4 -18 -2 -9 14 5 11 14 17 20 14 5 -4 9 0 9 8 0 8 16 35 35 60 35 45 35 46 14 57 -18 10 -23 8 -37 -12 -67 -95 -162 -167 -297 -225 -55 -23 -99 -47 -98 -53 2 -5 -6 -10 -18 -10 -27 0 -23 8 31 71 100 117 116 131 161 155 80 40 80 70 1 41 l-47 -18 36 38 c47 49 59 73 59 120 0 67 -24 80 -82 46 -49 -29 -76 -85 -89 -183 -10 -81 -9 -80 -89 -174 -20 -22 -43 -53 -53 -68 -28 -45 -89 -61 -217 -56 -70 2 -114 8 -118 15 -4 6 -28 13 -54 15 l-46 3 53 71 c51 68 100 104 140 104 50 0 125 73 125 122 0 30 0 31 -45 26 -28 -4 -59 -16 -82 -34 -30 -23 -35 -24 -28 -8 22 51 37 105 31 111 -13 13 -47 -34 -105 -146 -72 -138 -171 -248 -261 -292 -62 -30 -164 -44 -242 -34 -48 7 -50 8 -45 34 14 70 51 144 95 190 42 43 56 51 127 69 44 12 98 24 120 27 99 15 155 57 155 117 l0 31 -51 -5 c-40 -4 -58 -12 -87 -40 -56 -52 -66 -58 -131 -78 l-60 -18 10 27 c6 14 36 62 68 106 70 96 91 136 91 170 0 41 -18 29 -50 -35 -30 -59 -31 -60 -74 -60 -56 0 -71 -18 -101 -115 -23 -75 -43 -114 -72 -145 -8 -8 -41 -61 -73 -117 -35 -59 -75 -113 -95 -128 -37 -29 -177 -85 -210 -85 -35 0 -222 -134 -282 -202 -31 -35 -64 -64 -72 -66 -22 -4 -68 116 -88 223 -20 113 -5 256 37 340 37 76 124 182 195 238 140 110 221 137 416 137 136 0 171 6 186 28 9 15 2 17 -76 18 -47 0 -127 4 -178 9 -167 15 -274 -28 -423 -170 -72 -68 -114 -95 -128 -81 -12 12 17 138 44 194 64 132 229 243 439 298 182 46 319 21 425 -80 68 -65 144 -115 202 -135 119 -41 155 -32 72 17 -88 52 -224 144 -224 152 0 14 51 20 210 22 115 2 160 0 175 -10 19 -12 18 -13 -8 -9 -36 6 -45 -9 -11 -17 56 -15 117 -51 183 -110 66 -59 119 -86 169 -86 54 0 31 59 -35 90 -167 77 -176 82 -158 93 25 13 138 -8 201 -37 27 -13 67 -43 89 -66 50 -53 84 -70 134 -70 37 0 71 19 71 40 0 24 -62 57 -129 70 -40 7 -74 17 -77 22 -3 4 24 8 60 8 36 0 68 -4 71 -10 3 -5 26 -10 51 -10 50 0 57 15 23 46 -24 21 -113 25 -226 10 -50 -7 -65 -6 -77 7 -19 18 -100 37 -160 37 -74 0 -136 12 -136 26 0 17 11 23 53 28 32 4 83 29 97 47 8 10 71 40 99 47 28 7 159 8 309 1 50 -2 92 -1 92 4 0 4 14 7 30 7 23 0 30 -4 30 -20 0 -15 -7 -20 -25 -20 -42 0 -28 -17 30 -39 75 -28 103 -27 117 4 8 18 19 25 38 25 34 0 47 35 23 62 -24 27 -70 31 -190 18 -101 -11 -112 -10 -173 10 -36 12 -104 24 -152 27 -49 3 -88 9 -88 13 0 8 35 26 66 35 12 3 37 21 55 40 19 20 67 58 106 86 57 39 86 52 134 60 71 11 170 58 193 91 34 49 10 51 -66 5 -52 -31 -154 -65 -165 -54 -11 12 9 25 67 47 33 12 60 26 60 30 0 5 15 17 34 28 31 18 67 84 53 98 -15 15 -69 -17 -124 -75 -35 -36 -63 -63 -63 -58 0 4 14 31 30 60 43 77 39 180 -7 151 -39 -24 -56 -62 -63 -141 -7 -87 -27 -127 -98 -200 -50 -52 -120 -103 -139 -103 -8 0 -22 -8 -31 -17 -31 -31 -26 11 12 94 33 74 61 171 53 180 -3 2 -17 1 -32 -3 -38 -10 -65 -74 -75 -185 -9 -97 -31 -147 -79 -176 -31 -20 -81 -71 -81 -83 0 -5 -24 -16 -52 -26 -29 -9 -58 -24 -64 -32 -7 -9 -33 -17 -70 -19 l-59 -4 55 48 c120 105 133 126 66 103 -19 -6 -58 -36 -88 -66 -29 -30 -72 -64 -96 -76 -41 -19 -50 -20 -163 -9 -168 16 -237 52 -196 103 21 27 121 88 143 88 60 0 183 34 234 65 30 18 74 36 97 40 85 14 180 99 131 118 -16 5 -19 13 -14 33 7 25 5 25 -26 19 -52 -11 -83 -31 -122 -76 -54 -63 -94 -86 -197 -109 -52 -12 -102 -24 -111 -26 -28 -8 -22 22 10 44 15 11 35 34 45 51 16 27 16 31 2 31 -8 0 -18 -7 -22 -16 -8 -23 -23 2 -23 40 0 23 -3 27 -12 18 -14 -14 -42 -16 -33 -2 3 6 4 10 1 10 -9 0 -37 -61 -62 -133 -29 -84 -85 -162 -137 -189 -24 -12 -67 -21 -110 -24 -40 -2 -100 -6 -134 -9 l-62 -4 36 72 c20 39 48 84 62 98 29 29 86 122 96 157 9 32 -20 29 -42 -5 -17 -27 -128 -174 -222 -297 -45 -58 -101 -96 -141 -96 -48 0 -9 184 59 284 41 59 113 107 234 156 51 20 141 67 198 102 57 36 118 72 134 80 40 21 155 46 240 53 48 5 82 14 113 32 58 34 150 44 258 28 41 -6 57 -4 75 9 17 12 46 16 111 16 88 0 116 12 57 24 -17 3 -48 6 -69 6 -21 0 -43 6 -49 14 -14 17 -8 22 40 31 30 5 36 10 32 26 -4 13 0 19 12 19 23 0 95 44 129 79 34 35 30 67 -6 55 -13 -4 -31 -7 -41 -6 -11 0 -38 -25 -68 -64 -28 -35 -53 -64 -55 -64 -2 0 7 22 21 50 14 27 25 60 25 74 0 14 5 37 11 53 7 19 7 29 0 31 -6 2 -11 17 -11 33 0 16 -4 29 -10 29 -5 0 -10 -19 -10 -42 0 -50 -37 -158 -74 -222 -28 -48 -90 -86 -141 -86 l-29 0 36 38 c20 20 43 52 52 70 16 31 16 32 -5 32 -25 0 -94 -47 -109 -75 -19 -35 -161 -104 -245 -120 -42 -8 -85 -15 -96 -15 -18 0 -18 1 -2 35 9 19 20 35 25 35 4 0 8 6 8 13 0 7 13 34 30 60 30 48 75 77 182 117 58 21 112 66 176 146 26 31 57 57 84 69 124 52 167 75 177 93 17 33 -14 35 -71 6 -29 -14 -69 -32 -89 -39 l-38 -14 20 51 c11 28 24 59 29 68 10 19 -20 60 -45 60 -18 0 -21 46 -4 52 6 2 14 26 16 53 4 43 2 52 -16 63 -20 11 -21 10 -21 -25 -1 -209 -5 -248 -32 -305 -34 -73 -116 -188 -133 -188 -8 0 -20 -6 -27 -13 -7 -7 -29 -18 -48 -24 -19 -6 -52 -18 -72 -27 -34 -15 -38 -15 -38 -1 0 35 32 73 89 109 60 37 77 51 45 39 -14 -5 -14 -3 -3 14 7 13 9 28 4 39 -5 11 -7 24 -6 29 1 6 -19 -11 -44 -37 -25 -26 -45 -44 -45 -40 0 4 18 34 40 67 30 45 40 69 40 100 0 53 -11 67 -46 63 -22 -2 -34 -13 -53 -47 -14 -25 -26 -40 -29 -33 -2 7 -10 12 -17 12 -10 0 -14 -33 -17 -142 l-4 -143 -63 -127 c-39 -81 -74 -137 -94 -154 -51 -43 -167 -87 -167 -63 0 6 26 38 58 72 32 34 66 73 75 87 18 26 23 100 8 100 -5 0 -22 -19 -38 -42 -15 -23 -52 -60 -81 -82 -31 -25 -61 -59 -74 -85 -37 -75 -125 -156 -220 -201 -46 -22 -101 -43 -121 -47 -32 -5 -37 -3 -37 13 0 36 50 229 70 269 10 23 38 95 61 160 39 116 84 211 117 248 12 13 13 20 4 29 -9 9 -21 5 -49 -18 -58 -46 -166 -272 -249 -519 -37 -110 -73 -207 -80 -216 -8 -8 -14 -21 -14 -28 0 -8 -19 -54 -41 -105 -23 -50 -61 -146 -84 -212 -49 -144 -77 -193 -152 -274 -71 -77 -89 -77 -115 2 -11 33 -27 59 -36 62 -19 6 -21 27 -23 201 -2 197 49 394 151 580 33 61 72 135 86 165 118 253 140 288 273 462 87 112 121 167 121 195 0 37 -25 27 -75 -29 -42 -48 -45 -50 -38 -23 13 50 9 145 -8 156 -19 12 -30 7 -50 -22 -23 -33 -15 -116 12 -124 28 -9 35 -49 12 -73 -10 -11 -36 -45 -58 -76 -22 -31 -44 -56 -48 -56 -12 0 -3 78 17 160 8 36 15 84 16 107 0 23 4 44 9 47 4 3 11 37 14 75 3 39 14 86 26 109 26 50 80 97 94 83 16 -16 59 -13 85 5 30 21 52 66 52 109 0 33 -2 35 -32 35 -59 0 -78 -12 -118 -69 -21 -31 -55 -74 -74 -96 l-35 -40 -1 41 c0 23 7 60 15 83 15 43 92 151 124 173 20 14 55 77 48 85 -3 2 -8 -5 -12 -16 -7 -24 -35 -17 -35 9 0 23 -13 32 -35 24 -9 -4 -12 -9 -7 -13 17 -10 2 -62 -16 -59 -11 2 -30 -24 -61 -87 -34 -68 -46 -84 -49 -67 -2 12 -8 22 -13 22 -5 0 -9 -10 -9 -22 -1 -23 -1 -23 -16 -3 -9 11 -24 37 -34 58 -11 24 -20 34 -23 25 -3 -7 -6 25 -6 72 -1 105 -21 98 -26 -10 -3 -43 -9 -76 -16 -81 -10 -6 -10 -11 0 -23 14 -16 3 -22 -15 -8 -5 4 2 -2 15 -13 51 -41 78 -76 96 -128 26 -70 25 -187 -3 -292 -13 -49 -21 -109 -20 -155 0 -104 -54 -310 -81 -310 -6 0 -11 3 -11 8 -1 44 -24 191 -41 259 l-22 85 27 108 c30 123 34 211 10 231 -20 16 -40 5 -72 -42 -21 -30 -23 -42 -18 -97 3 -36 1 -60 -4 -57 -17 11 -34 81 -34 150 -1 64 2 76 39 140 22 39 45 84 52 100 17 43 16 92 -2 98 -17 7 -17 8 -44 -73 -12 -36 -34 -87 -50 -113 -33 -56 -41 -48 -41 39 0 41 -4 54 -15 54 -11 0 -15 -18 -17 -80 -2 -45 -7 -80 -13 -80 -5 0 -10 4 -10 8 0 5 -8 16 -18 26 -58 58 -70 132 -53 314 7 69 6 92 -3 92 -6 0 -13 -6 -16 -12z m321 -503 c3 -20 4 -39 0 -42 -3 -4 -6 6 -6 20 0 17 -5 27 -15 27 -16 0 -20 12 -8 23 14 14 22 6 29 -28z m-1006 -80 c0 -8 -9 -15 -19 -15 -29 0 -35 18 -9 23 13 2 24 5 26 6 1 0 2 -6 2 -14z m327 -27 c-3 -7 -5 -2 -5 12 0 14 2 19 5 13 2 -7 2 -19 0 -25z m-462 -358 c3 -5 1 -10 -4 -10 -6 0 -11 5 -11 10 0 6 2 10 4 10 3 0 8 -4 11 -10z m-835 -40 c-6 -11 -15 -20 -19 -20 -5 0 -7 9 -4 20 3 11 12 20 20 20 11 0 11 -4 3 -20z m864 -25 c3 -9 0 -15 -9 -15 -9 0 -15 -10 -16 -27 0 -27 -1 -27 -13 7 -10 25 -10 37 -2 42 18 12 33 9 40 -7z m-892 -863 c38 2 68 0 68 -4 0 -5 -33 -8 -73 -8 -49 0 -80 -5 -95 -16 -21 -14 -22 -14 -22 5 0 14 -6 21 -20 21 -11 0 -20 2 -20 4 0 2 -3 12 -6 21 -6 13 1 13 47 -5 40 -16 70 -21 121 -18z m3218 -91 c0 -10 -7 -21 -15 -25 -11 -4 -15 1 -15 19 0 16 6 25 15 25 8 0 15 -9 15 -19z m-3479 -32 c-14 -5 -30 -14 -37 -20 -8 -7 -13 -3 -17 11 -5 18 0 20 36 19 38 0 40 -1 18 -10z m3359 -572 c0 -7 -7 -22 -15 -33 -13 -17 -14 -16 -4 14 11 33 19 41 19 19z m-3345 -198 c7 -22 -7 -39 -33 -39 -10 0 -10 4 0 20 11 17 10 22 -2 30 -12 8 -11 10 7 10 13 0 24 -8 28 -21z m445 -37 c0 -23 -35 -8 -38 16 -3 21 -2 22 17 10 12 -7 21 -19 21 -26z m-310 -647 c-28 -30 -60 -33 -60 -7 0 26 9 32 48 32 l35 0 -23 -25z M3684 5414 c-14 -21 -16 -41 -10 -124 4 -62 2 -100 -3 -100 -9 0 -17 26 -25 84 -1 11 -8 22 -14 24 -9 3 -12 -27 -12 -105 0 -69 -6 -130 -16 -164 -24 -86 -24 -85 -33 -70 -6 9 -10 3 -14 -17 -4 -20 -23 -43 -59 -72 -29 -23 -54 -46 -54 -51 -1 -5 -3 -39 -4 -76 -1 -46 -4 -60 -9 -43 -6 21 -9 15 -20 -35 -16 -74 -29 -99 -97 -197 -35 -49 -54 -86 -54 -105 0 -31 59 -200 60 -171 0 9 6 21 14 25 13 7 13 16 0 68 -17 72 -12 78 75 93 106 19 127 33 145 95 20 70 65 111 186 172 83 42 89 47 75 62 -9 8 -14 23 -11 32 5 14 5 14 -6 1 -7 -8 -41 -25 -75 -37 -54 -19 -61 -19 -56 -5 10 26 43 72 91 126 46 53 77 104 68 114 -6 6 -95 -81 -143 -141 l-30 -38 -7 80 c-4 45 -5 89 -1 98 3 10 31 34 63 53 61 37 147 112 164 144 21 38 -53 8 -126 -52 -98 -80 -100 -81 -92 -46 12 47 54 133 81 166 14 16 25 42 25 56 l-1 27 -25 -30 -26 -30 6 53 c3 28 9 74 12 100 5 40 3 50 -10 55 -10 4 -22 -2 -32 -19z m-79 -654 c0 -125 0 -126 -33 -176 -22 -36 -56 -67 -109 -103 -42 -28 -82 -51 -90 -51 -20 0 -16 22 11 59 13 18 30 46 36 62 7 16 16 29 20 29 5 0 13 33 20 73 16 102 29 149 40 142 6 -4 10 -2 10 3 0 5 13 25 30 43 16 19 30 38 30 42 0 5 8 7 18 5 15 -3 17 -17 17 -128z M2287 5348 c-10 -10 -22 -16 -27 -13 -5 3 -8 -3 -8 -12 1 -10 -2 -37 -6 -59 -6 -32 -4 -43 7 -47 23 -9 67 61 67 105 0 44 -9 51 -33 26z M1853 5256 c4 -22 11 -42 17 -46 7 -4 14 -26 17 -49 3 -22 10 -41 15 -41 5 0 7 12 4 28 -3 15 -8 46 -11 69 -4 23 -16 49 -27 60 -21 18 -21 18 -15 -21z M1780 5267 c0 -47 15 -79 42 -93 l30 -16 -7 34 c-4 18 -12 44 -19 58 -12 28 -46 40 -46 17z M1960 5120 c0 -21 30 -70 49 -80 27 -14 31 -13 31 10 0 11 5 20 10 20 6 0 8 -11 4 -25 -6 -23 -4 -25 30 -25 20 0 36 4 36 8 0 18 -68 72 -109 87 -52 18 -51 18 -51 5z M4127 5076 c-4 -10 -7 -45 -7 -79 0 -42 -6 -70 -18 -88 -56 -85 -73 -107 -106 -138 -20 -19 -36 -39 -36 -43 0 -18 34 -6 62 23 29 28 34 30 84 24 41 -6 59 -3 83 11 37 22 44 37 28 59 -16 21 -72 22 -95 2 -21 -19 -32 -22 -32 -7 0 5 38 35 84 66 77 51 106 84 106 119 0 26 -43 16 -77 -17 l-33 -32 0 47 c0 34 -4 47 -14 47 -8 0 -16 5 -18 12 -3 7 -7 5 -11 -6z M1049 5043 c-8 -10 -9 -14 -2 -10 7 5 28 -18 57 -63 48 -74 62 -86 52 -45 -4 15 -2 25 4 25 15 0 -17 72 -41 93 -27 22 -53 22 -70 0z M3400 4964 c-14 -37 -12 -60 6 -75 14 -11 18 -10 30 6 19 26 18 81 -2 89 -23 9 -24 8 -34 -20z M3910 4933 c-29 -20 -40 -33 -40 -50 0 -33 63 6 75 45 8 26 -2 28 -35 5z M3401 4844 c0 -11 3 -14 6 -6 3 7 2 16 -1 19 -3 4 -6 -2 -5 -13z M4532 4829 c-8 -12 -9 -18 -3 -14 7 4 11 -8 12 -32 1 -21 4 -51 8 -68 6 -26 8 -22 13 29 5 39 3 67 -5 83 l-12 23 -13 -21z M1017 4820 c-8 -30 16 -52 65 -60 41 -6 45 -5 40 12 -5 20 -68 68 -88 68 -6 0 -14 -9 -17 -20z M2529 4778 c-11 -21 -7 -134 7 -185 8 -30 24 -19 24 17 0 16 7 35 15 44 18 17 20 70 4 115 -13 36 -33 40 -50 9z M830 4767 c0 -24 30 -116 40 -122 11 -7 1 92 -12 118 -10 20 -28 23 -28 4z M4660 4751 c0 -5 -9 -12 -19 -16 -23 -7 -101 -81 -101 -95 0 -26 50 -6 98 38 51 47 67 82 37 82 -8 0 -15 -4 -15 -9z M764 4719 c-7 -13 82 -106 92 -96 11 11 -9 43 -46 75 -27 23 -41 29 -46 21z M1887 4634 c-18 -18 -6 -91 21 -131 79 -118 125 -171 138 -159 10 9 8 18 -9 46 -12 19 -25 37 -29 38 -4 2 -8 25 -8 50 0 60 -15 115 -38 135 -20 19 -65 31 -75 21z M1030 4579 c0 -35 54 -169 68 -169 6 0 12 -8 12 -17 1 -17 2 -17 15 0 11 16 11 26 -5 71 -25 75 -47 114 -70 126 -17 9 -20 8 -20 -11z M697 4553 c19 -54 69 -92 112 -85 36 5 46 34 20 58 -11 9 -22 14 -25 11 -4 -4 -18 3 -32 13 -32 26 -84 28 -75 3z M1150 4486 c0 -36 52 -76 101 -76 47 0 57 29 12 32 -16 1 6 4 47 8 l75 6 -75 2 c-41 1 -85 8 -96 15 -12 6 -31 18 -43 25 -19 12 -21 11 -21 -12z M3909 4427 c-16 -27 -19 -51 -19 -149 0 -111 1 -118 20 -118 15 0 24 14 40 68 39 124 39 215 -1 225 -15 4 -25 -2 -40 -26z M4723 4375 c-30 -13 -33 -18 -33 -60 l0 -45 24 15 c27 18 49 48 60 83 9 26 -4 28 -51 7z M5002 4348 c-5 -7 -23 -40 -40 -73 -32 -65 -106 -146 -156 -172 -17 -9 -51 -21 -75 -28 -46 -11 -63 -28 -38 -38 7 -3 47 2 87 10 58 12 85 13 128 4 96 -19 162 -13 162 15 0 11 -19 14 -82 15 -46 0 -91 4 -101 8 -17 6 -17 8 2 25 11 10 44 25 73 32 34 8 43 13 27 13 -31 1 -44 24 -23 41 8 7 14 21 14 31 0 11 10 36 23 57 33 52 39 72 23 72 -7 0 -18 -6 -24 -12z M3632 4290 c-52 -37 -68 -69 -74 -145 -3 -33 -3 -54 0 -47 3 10 7 9 16 -4 12 -15 18 -14 79 15 69 33 101 66 95 98 -4 22 -37 30 -49 11 -6 -8 -7 10 -3 45 8 68 -2 72 -64 27z M5016 4271 c-11 -12 -16 -24 -12 -28 9 -9 39 22 34 37 -2 7 -10 4 -22 -9z M470 4264 c0 -9 8 -28 18 -42 10 -15 22 -33 27 -40 8 -15 -67 31 -102 62 -13 11 -23 14 -23 8 0 -7 -7 -12 -15 -12 -19 0 -19 -15 2 -50 20 -35 48 -48 118 -56 37 -5 55 -11 55 -20 0 -8 11 -14 25 -14 14 0 25 4 25 10 0 5 -22 43 -50 84 -49 73 -80 100 -80 70z M2382 4102 c-5 -9 -12 -42 -14 -72 -9 -96 18 -125 39 -43 17 66 17 120 -2 127 -8 3 -19 -2 -23 -12z M4235 3850 c36 -39 118 -80 162 -80 30 0 93 41 93 61 0 5 -14 15 -30 24 -25 13 -44 14 -107 6 -43 -5 -80 -6 -83 -1 -3 5 -19 12 -35 16 l-30 7 30 -33z M133 3667 c-19 -41 -15 -59 18 -86 30 -24 135 -55 151 -45 11 7 10 42 -2 49 -5 3 -10 11 -10 17 0 6 7 5 17 -3 12 -10 15 -10 9 -1 -13 22 -84 52 -125 52 -33 0 -40 4 -43 22 -3 21 -4 21 -15 -5z M5265 3631 c-16 -10 -43 -33 -60 -51 l-30 -32 83 4 c77 3 86 6 107 30 35 41 24 68 -29 68 -23 0 -54 -8 -71 -19z M400 3512 c0 -5 -53 -12 -117 -16 -64 -4 -120 -9 -125 -12 -16 -10 -8 -53 13 -65 51 -27 183 0 213 43 13 17 19 18 68 9 29 -5 66 -13 81 -16 22 -6 26 -4 21 9 -5 12 0 16 17 17 13 1 -3 7 -36 14 -106 22 -135 26 -135 17z M5090 3480 c0 -5 9 -10 20 -10 11 0 47 -13 80 -30 57 -29 121 -39 147 -22 22 14 19 45 -7 59 -30 15 -240 18 -240 3z M926 3272 c-12 -11 -6 -94 9 -122 16 -31 39 -47 86 -60 24 -7 29 -5 39 21 19 44 5 94 -34 124 -35 27 -90 47 -100 37z M500 3049 c0 -23 9 -62 20 -85 17 -33 30 -46 70 -62 34 -14 56 -32 70 -54 16 -28 109 -108 125 -108 3 0 5 7 5 15 0 12 7 14 28 9 15 -3 -8 11 -50 32 -42 20 -80 44 -83 53 -4 9 -9 46 -12 84 -5 61 -9 70 -41 98 -34 30 -59 43 -107 55 -24 6 -25 4 -25 -37z M5203 2779 c-18 -11 -35 -29 -38 -40 -7 -22 -20 -25 -32 -6 -8 13 -20 -26 -22 -74 -1 -30 25 -36 35 -7 4 15 9 17 20 7 8 -6 14 -18 14 -26 0 -11 7 -9 27 7 43 33 63 71 63 118 0 49 -14 53 -67 21z M5307 2622 c-34 -32 -86 -72 -115 -88 -51 -29 -61 -46 -29 -52 25 -5 198 81 229 114 15 16 30 41 33 57 7 25 5 27 -24 27 -25 0 -45 -13 -94 -58z M447 2652 c-10 -10 -15 -21 -12 -24 7 -7 75 24 75 34 0 15 -47 8 -63 -10z M263 2600 c-12 -5 -26 -18 -32 -28 -8 -15 -6 -24 13 -41 33 -31 84 -27 160 13 68 36 68 47 1 51 -16 1 -50 5 -75 8 -25 4 -55 3 -67 -3z M996 2540 c-37 -11 -102 -74 -115 -112 l-10 -28 58 0 c48 0 65 5 98 29 49 35 87 86 79 106 -6 17 -62 19 -110 5z M673 2324 c-43 -18 -42 -43 1 -88 33 -35 35 -36 114 -36 70 0 80 2 78 18 0 10 6 16 16 16 13 -1 9 8 -18 40 -19 22 -45 46 -57 53 -29 16 -94 15 -134 -3z M4790 2120 c-9 -17 -5 -20 43 -29 72 -15 166 -19 169 -9 2 5 11 6 21 3 20 -8 23 -35 5 -35 -7 -1 -2 -7 12 -15 29 -17 113 -20 141 -5 24 13 25 36 2 48 -10 5 -58 12 -108 15 -49 3 -117 12 -150 20 -110 28 -124 28 -135 7z M4881 2021 c6 -17 30 -50 53 -75 33 -36 49 -46 74 -46 25 0 32 4 32 19 0 25 -60 77 -99 86 -17 4 -36 15 -41 26 -17 30 -30 23 -19 -10z";
|
|
1322
1302
|
|
|
1323
1303
|
// src/genre-tree/TreeMarkIcon.tsx
|
|
1324
|
-
var
|
|
1304
|
+
var import_jsx_runtime23 = require("react/jsx-runtime");
|
|
1325
1305
|
function TreeMarkIcon({ className: className2 }) {
|
|
1326
|
-
return /* @__PURE__ */ (0,
|
|
1306
|
+
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("svg", { viewBox: "0 0 551 567", fill: "currentColor", className: className2, "aria-hidden": true, children: /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("path", { transform: "translate(0 567) scale(0.1 -0.1)", d: TREE_MARK_PATH }) });
|
|
1327
1307
|
}
|
|
1328
1308
|
|
|
1329
1309
|
// src/genre-tree/GenrePlayActions.tsx
|
|
1330
|
-
var
|
|
1310
|
+
var import_jsx_runtime24 = require("react/jsx-runtime");
|
|
1331
1311
|
function PlayIcon({ kind }) {
|
|
1332
|
-
return /* @__PURE__ */ (0,
|
|
1333
|
-
kind === "tree" && /* @__PURE__ */ (0,
|
|
1334
|
-
kind === "map" && /* @__PURE__ */ (0,
|
|
1335
|
-
kind === "tree-map" && /* @__PURE__ */ (0,
|
|
1336
|
-
/* @__PURE__ */ (0,
|
|
1337
|
-
/* @__PURE__ */ (0,
|
|
1312
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)("span", { "aria-hidden": "true", className: "relative flex items-center justify-center w-5 h-5", children: [
|
|
1313
|
+
kind === "tree" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1314
|
+
kind === "map" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35" }),
|
|
1315
|
+
kind === "tree-map" && /* @__PURE__ */ (0, import_jsx_runtime24.jsxs)(import_jsx_runtime24.Fragment, { children: [
|
|
1316
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(TreeMarkIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_50%_0_0)]" }),
|
|
1317
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(RegionGlobeIcon, { className: "absolute -left-1.5 -top-1.5 w-8 h-8 opacity-35 [clip-path:inset(0_0_0_50%)]" })
|
|
1338
1318
|
] }),
|
|
1339
|
-
/* @__PURE__ */ (0,
|
|
1319
|
+
/* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react8.Play, { className: "relative w-5 h-5 fill-[var(--color-surface)]" })
|
|
1340
1320
|
] });
|
|
1341
1321
|
}
|
|
1342
1322
|
function playOptions(playlist) {
|
|
@@ -1352,13 +1332,13 @@ function playOptions(playlist) {
|
|
|
1352
1332
|
function GenrePlayActions({ genrePlaylist, playback }) {
|
|
1353
1333
|
const { isPlaying, setIsPlaying } = (0, import_player4.usePlayer)();
|
|
1354
1334
|
const options = playOptions(genrePlaylist);
|
|
1355
|
-
return /* @__PURE__ */ (0,
|
|
1335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_jsx_runtime24.Fragment, { children: options.map((option) => {
|
|
1356
1336
|
const isCurrent = playback.playing?.uuid === genrePlaylist.uuid && (option.selection === void 0 || playback.playing.selectionKey === "" || playback.playing.selectionKey === (0, import_genre_tree10.genreMusicSelectionKey)(option.selection).join());
|
|
1357
1337
|
const playing = isCurrent && isPlaying;
|
|
1358
|
-
return /* @__PURE__ */ (0,
|
|
1338
|
+
return /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(
|
|
1359
1339
|
import_ui7.ActionButton,
|
|
1360
1340
|
{
|
|
1361
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
1341
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(import_lucide_react8.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime24.jsx)(PlayIcon, { kind: option.icon }),
|
|
1362
1342
|
label: playing ? "Pause" : option.label,
|
|
1363
1343
|
caption: String(option.count),
|
|
1364
1344
|
disabled: option.count === 0,
|
|
@@ -1368,9 +1348,7 @@ function GenrePlayActions({ genrePlaylist, playback }) {
|
|
|
1368
1348
|
setIsPlaying(!isPlaying);
|
|
1369
1349
|
return;
|
|
1370
1350
|
}
|
|
1371
|
-
playback.play(genrePlaylist, option.selection)
|
|
1372
|
-
console.error("Failed to load genre playlist tracks:", error);
|
|
1373
|
-
});
|
|
1351
|
+
void playback.play(genrePlaylist, option.selection);
|
|
1374
1352
|
}
|
|
1375
1353
|
},
|
|
1376
1354
|
option.key
|
|
@@ -1384,7 +1362,7 @@ var import_genre_tree18 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1384
1362
|
|
|
1385
1363
|
// src/genre-tree/ClampedText.tsx
|
|
1386
1364
|
var import_react12 = require("react");
|
|
1387
|
-
var
|
|
1365
|
+
var import_jsx_runtime25 = require("react/jsx-runtime");
|
|
1388
1366
|
function ClampedText({ children, className: className2 = "" }) {
|
|
1389
1367
|
const ref = (0, import_react12.useRef)(null);
|
|
1390
1368
|
const [expanded, setExpanded] = (0, import_react12.useState)(false);
|
|
@@ -1394,9 +1372,9 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1394
1372
|
if (!element || expanded) return;
|
|
1395
1373
|
setOverflows(element.scrollHeight > element.clientHeight);
|
|
1396
1374
|
}, [children, expanded]);
|
|
1397
|
-
return /* @__PURE__ */ (0,
|
|
1398
|
-
/* @__PURE__ */ (0,
|
|
1399
|
-
(overflows || expanded) && /* @__PURE__ */ (0,
|
|
1375
|
+
return /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(import_jsx_runtime25.Fragment, { children: [
|
|
1376
|
+
/* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { ref, className: `${className2} ${expanded ? "" : "line-clamp-3"}`, children }),
|
|
1377
|
+
(overflows || expanded) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
|
|
1400
1378
|
"button",
|
|
1401
1379
|
{
|
|
1402
1380
|
type: "button",
|
|
@@ -1416,13 +1394,13 @@ var import_zod = require("zod");
|
|
|
1416
1394
|
var import_fa2 = require("react-icons/fa");
|
|
1417
1395
|
var import_ui8 = require("@behindthemusictree/ui");
|
|
1418
1396
|
var import_auth = require("@behindthemusictree/app-kit/auth");
|
|
1397
|
+
var import_transport2 = require("@behindthemusictree/app-kit/transport");
|
|
1419
1398
|
var import_transport3 = require("@behindthemusictree/app-kit/transport");
|
|
1420
1399
|
var import_transport4 = require("@behindthemusictree/app-kit/transport");
|
|
1421
|
-
var import_transport5 = require("@behindthemusictree/app-kit/transport");
|
|
1422
1400
|
var import_player5 = require("@behindthemusictree/app-kit/player");
|
|
1423
1401
|
var import_player6 = require("@behindthemusictree/app-kit/player");
|
|
1424
|
-
var
|
|
1425
|
-
var
|
|
1402
|
+
var import_popup3 = require("@behindthemusictree/app-kit/popup");
|
|
1403
|
+
var import_transport5 = require("@behindthemusictree/app-kit/transport");
|
|
1426
1404
|
var import_genre_tree12 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1427
1405
|
var import_genre_tree13 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1428
1406
|
var import_genre_tree14 = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -1431,15 +1409,15 @@ var import_genre_tree16 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
1431
1409
|
|
|
1432
1410
|
// src/genre-tree/MusicBrainzRecordingLink.tsx
|
|
1433
1411
|
var import_genre_tree11 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1434
|
-
var
|
|
1412
|
+
var import_jsx_runtime26 = require("react/jsx-runtime");
|
|
1435
1413
|
function MusicBrainzRecordingLink({
|
|
1436
1414
|
song,
|
|
1437
1415
|
children,
|
|
1438
1416
|
className: className2 = ""
|
|
1439
1417
|
}) {
|
|
1440
1418
|
const url = (0, import_genre_tree11.musicBrainzRecordingUrl)(song);
|
|
1441
|
-
if (!url) return /* @__PURE__ */ (0,
|
|
1442
|
-
return /* @__PURE__ */ (0,
|
|
1419
|
+
if (!url) return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(import_jsx_runtime26.Fragment, { children });
|
|
1420
|
+
return /* @__PURE__ */ (0, import_jsx_runtime26.jsx)(
|
|
1443
1421
|
"a",
|
|
1444
1422
|
{
|
|
1445
1423
|
href: url,
|
|
@@ -1456,9 +1434,9 @@ function MusicBrainzRecordingLink({
|
|
|
1456
1434
|
// src/genre-tree/GenrePlaylistTracks.tsx
|
|
1457
1435
|
var import_genre_tree17 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1458
1436
|
var import_track_noun = require("@behindthemusictree/app-kit/track-noun");
|
|
1459
|
-
var
|
|
1437
|
+
var import_jsx_runtime27 = require("react/jsx-runtime");
|
|
1460
1438
|
var CATALOGUE_PAGE_SIZE = 100;
|
|
1461
|
-
var SongPageSchema = (0,
|
|
1439
|
+
var SongPageSchema = (0, import_transport3.PaginatedResponseSchema)(import_genre_tree15.SongDetailedSchema).extend({
|
|
1462
1440
|
overallTotal: import_zod.z.number().nullable(),
|
|
1463
1441
|
page: import_zod.z.number().nullable(),
|
|
1464
1442
|
totalPages: import_zod.z.number().nullable()
|
|
@@ -1490,12 +1468,12 @@ function GenrePlaylistTracks({
|
|
|
1490
1468
|
const { fetchGenrePlaylistTracksPage, playNewTrackListFromGenrePlaylist, playNewTrackListFromArtist, playNewTrackListFromGenreCatalogue } = (0, import_genre_tree16.useTrackList)();
|
|
1491
1469
|
const { session, sessionRestored } = (0, import_auth.useSession)();
|
|
1492
1470
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player5.usePlayer)();
|
|
1493
|
-
const { showPopup } = (0,
|
|
1471
|
+
const { showPopup } = (0, import_popup3.usePopup)();
|
|
1494
1472
|
const trackNoun = (0, import_track_noun.useTrackNoun)();
|
|
1495
1473
|
const uuid = genrePlaylist?.uuid;
|
|
1496
1474
|
const genreName = selectedGenreName ?? genrePlaylist?.name ?? "Genre";
|
|
1497
|
-
const { fetchBound } = (0,
|
|
1498
|
-
const playback = (0,
|
|
1475
|
+
const { fetchBound } = (0, import_transport2.usePlaybackFetch)(getBackendBaseUrl);
|
|
1476
|
+
const playback = (0, import_transport2.usePlaybackContext)();
|
|
1499
1477
|
const { data, isPending, isError, refetch, hasNextPage, isFetchingNextPage, fetchNextPage } = (0, import_react_query.useInfiniteQuery)({
|
|
1500
1478
|
queryKey: [...scope === "me" ? uuid ? import_genre_tree13.genrePlaylistQueryKeys.me.tracks(uuid) : ["missing-personal-genre-playlist", genreUuid] : artist ? [...import_genre_tree14.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), "artist", artist.uuid] : import_genre_tree14.libraryQueryKeys.reference.songs.byGenre(getBackendBaseUrl(), genreUuid, selection), ...playback.key ? [playback.key] : []],
|
|
1501
1479
|
queryFn: async ({ pageParam }) => {
|
|
@@ -1510,7 +1488,7 @@ function GenrePlaylistTracks({
|
|
|
1510
1488
|
{},
|
|
1511
1489
|
{ genre: genreUuid, ...(0, import_genre_tree12.genreMusicQueryParams)(selection), ...artist && { artist: artist.uuid }, pageSize: CATALOGUE_PAGE_SIZE, withTotal: false, ...pageParam && { cursor: pageParam } }
|
|
1512
1490
|
);
|
|
1513
|
-
const parsed = (0,
|
|
1491
|
+
const parsed = (0, import_transport4.parseWithLog)(SongPageSchema, response, "GenrePlaylistTracks");
|
|
1514
1492
|
return { tracks: parsed.results, total: parsed.overallTotal, nextPage: parsed.next ? nextCursor(parsed.next) : null };
|
|
1515
1493
|
},
|
|
1516
1494
|
initialPageParam: scope === "me" ? 1 : "",
|
|
@@ -1542,35 +1520,36 @@ function GenrePlaylistTracks({
|
|
|
1542
1520
|
}) : 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"));
|
|
1543
1521
|
started.catch((error) => {
|
|
1544
1522
|
console.error("Failed to play genre playlist:", error);
|
|
1545
|
-
|
|
1523
|
+
if (error instanceof import_genre_tree16.TracksFailureAlreadyReportedError) return;
|
|
1524
|
+
showPopup(/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(InternalErrorPopup, { errorCode: error instanceof import_transport5.AppError ? error.code : import_transport5.ErrorCode.CLIENT_UNKNOWN }));
|
|
1546
1525
|
});
|
|
1547
1526
|
};
|
|
1548
|
-
return /* @__PURE__ */ (0,
|
|
1527
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui8.PanelSection, { title: `${(0, import_track_noun.capitalize)(trackNoun.plural)}${total !== void 0 ? ` (${total})` : ""}`, children: /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("div", { children: [
|
|
1549
1528
|
renderTracksToolbar?.(),
|
|
1550
|
-
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0,
|
|
1529
|
+
scope === "me" && !genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { children: "\u2014" }) : isPending ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui8.Skeleton, { className: "h-4 w-3/4", "aria-busy": "true" }) : isError && tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("p", { role: "alert", children: [
|
|
1551
1530
|
"Couldn't load ",
|
|
1552
1531
|
trackNoun.plural,
|
|
1553
1532
|
".",
|
|
1554
1533
|
" ",
|
|
1555
|
-
/* @__PURE__ */ (0,
|
|
1556
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0,
|
|
1534
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1535
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1557
1536
|
tracks.map((track, index) => {
|
|
1558
1537
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1559
1538
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
1560
1539
|
const isPlaying = isCurrent && playState === import_player6.PlayStates.PLAYING;
|
|
1561
|
-
const text = /* @__PURE__ */ (0,
|
|
1562
|
-
/* @__PURE__ */ (0,
|
|
1563
|
-
track.artists?.length ? /* @__PURE__ */ (0,
|
|
1564
|
-
/* @__PURE__ */ (0,
|
|
1565
|
-
track.album && /* @__PURE__ */ (0,
|
|
1540
|
+
const text = /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("span", { className: TEXT_CELL, children: [
|
|
1541
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: TITLE_CELL, children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree15.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }),
|
|
1542
|
+
track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: SEPARATOR, children: " \u2014 " }) : null,
|
|
1543
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: COLUMN_CELL, children: track.artists?.length ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_genre_tree17.ArtistNames, { artists: track.artists, renderArtistLink }) : null }),
|
|
1544
|
+
track.album && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("span", { className: ALBUM_CELL, children: track.album.name })
|
|
1566
1545
|
] });
|
|
1567
1546
|
const leading = renderSongLeading?.(track, index);
|
|
1568
1547
|
const actions = renderSongActions?.(track);
|
|
1569
1548
|
const isUnplayable = (0, import_genre_tree15.isSong)(track) && (0, import_genre_tree15.songUnplayableReason)(track) !== null;
|
|
1570
1549
|
if (isUnplayable) {
|
|
1571
|
-
return /* @__PURE__ */ (0,
|
|
1550
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)("li", { className: "flex min-h-8 items-center gap-1 px-1 opacity-50", children: [
|
|
1572
1551
|
leading,
|
|
1573
|
-
/* @__PURE__ */ (0,
|
|
1552
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1574
1553
|
"button",
|
|
1575
1554
|
{
|
|
1576
1555
|
type: "button",
|
|
@@ -1578,27 +1557,27 @@ function GenrePlaylistTracks({
|
|
|
1578
1557
|
"aria-disabled": "true",
|
|
1579
1558
|
"aria-label": label,
|
|
1580
1559
|
className: "flex h-6 w-6 shrink-0 items-center justify-center rounded-full opacity-0 cursor-not-allowed",
|
|
1581
|
-
children: /* @__PURE__ */ (0,
|
|
1560
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fa2.FaPlay, { size: 10 })
|
|
1582
1561
|
}
|
|
1583
1562
|
),
|
|
1584
1563
|
text,
|
|
1585
1564
|
actions
|
|
1586
1565
|
] }, track.uuid);
|
|
1587
1566
|
}
|
|
1588
|
-
return /* @__PURE__ */ (0,
|
|
1567
|
+
return /* @__PURE__ */ (0, import_jsx_runtime27.jsxs)(
|
|
1589
1568
|
"li",
|
|
1590
1569
|
{
|
|
1591
1570
|
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)]" : ""}`,
|
|
1592
1571
|
children: [
|
|
1593
1572
|
leading,
|
|
1594
|
-
/* @__PURE__ */ (0,
|
|
1573
|
+
/* @__PURE__ */ (0, import_jsx_runtime27.jsx)(
|
|
1595
1574
|
"button",
|
|
1596
1575
|
{
|
|
1597
1576
|
type: "button",
|
|
1598
1577
|
"aria-label": `${isPlaying ? "Pause" : "Play"} ${label}`,
|
|
1599
1578
|
className: `flex h-6 w-6 shrink-0 items-center justify-center rounded-full cursor-pointer group-hover:opacity-100 focus-visible:opacity-100 ${isCurrent && playState !== import_player6.PlayStates.STOPPED ? "opacity-100" : "opacity-0 [@media(pointer:coarse)]:opacity-100"}`,
|
|
1600
1579
|
onClick: () => isCurrent ? handlePlayPauseAction() : play(track.uuid),
|
|
1601
|
-
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0,
|
|
1580
|
+
children: isCurrent && playState === import_player6.PlayStates.LOADING ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_ui8.RingLoader, { size: 10 }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fa2.FaPause, { size: 10 }) : /* @__PURE__ */ (0, import_jsx_runtime27.jsx)(import_fa2.FaPlay, { size: 10 })
|
|
1602
1581
|
}
|
|
1603
1582
|
),
|
|
1604
1583
|
text,
|
|
@@ -1608,7 +1587,7 @@ function GenrePlaylistTracks({
|
|
|
1608
1587
|
track.uuid
|
|
1609
1588
|
);
|
|
1610
1589
|
}),
|
|
1611
|
-
hasNextPage && /* @__PURE__ */ (0,
|
|
1590
|
+
hasNextPage && /* @__PURE__ */ (0, import_jsx_runtime27.jsx)("li", { ref: setSentinel, "aria-hidden": "true", className: "h-4" })
|
|
1612
1591
|
] })
|
|
1613
1592
|
] }) });
|
|
1614
1593
|
}
|
|
@@ -1616,7 +1595,7 @@ function GenrePlaylistTracks({
|
|
|
1616
1595
|
// src/genre-tree/GenreDetailExtras.tsx
|
|
1617
1596
|
var import_track_noun2 = require("@behindthemusictree/app-kit/track-noun");
|
|
1618
1597
|
var import_si2 = require("react-icons/si");
|
|
1619
|
-
var
|
|
1598
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
1620
1599
|
function GenreDetailExtras({
|
|
1621
1600
|
genreUuid,
|
|
1622
1601
|
genrePlaylist,
|
|
@@ -1642,17 +1621,17 @@ function GenreDetailExtras({
|
|
|
1642
1621
|
criteriaOverviewSchema
|
|
1643
1622
|
);
|
|
1644
1623
|
if (isPending) {
|
|
1645
|
-
return /* @__PURE__ */ (0,
|
|
1646
|
-
/* @__PURE__ */ (0,
|
|
1624
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
1625
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui9.PanelSection, { title: "Summary", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("div", { "aria-busy": "true", "data-testid": "genre-detail-extras-skeleton", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui9.Skeleton, { className: "h-4 w-3/4" }) }) }),
|
|
1647
1626
|
family
|
|
1648
1627
|
] });
|
|
1649
1628
|
}
|
|
1650
|
-
if (!overview) return /* @__PURE__ */ (0,
|
|
1629
|
+
if (!overview) return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_jsx_runtime28.Fragment, { children: family });
|
|
1651
1630
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1652
1631
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1653
|
-
return /* @__PURE__ */ (0,
|
|
1654
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0,
|
|
1655
|
-
summarySourceUrl && /* @__PURE__ */ (0,
|
|
1632
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
1633
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui9.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1634
|
+
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1656
1635
|
"a",
|
|
1657
1636
|
{
|
|
1658
1637
|
href: summarySourceUrl,
|
|
@@ -1660,12 +1639,12 @@ function GenreDetailExtras({
|
|
|
1660
1639
|
rel: "noopener noreferrer",
|
|
1661
1640
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1662
1641
|
children: [
|
|
1663
|
-
/* @__PURE__ */ (0,
|
|
1642
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_si2.SiWikipedia, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1664
1643
|
"Wikipedia"
|
|
1665
1644
|
]
|
|
1666
1645
|
}
|
|
1667
1646
|
),
|
|
1668
|
-
wikidataUrl && /* @__PURE__ */ (0,
|
|
1647
|
+
wikidataUrl && /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
|
|
1669
1648
|
"a",
|
|
1670
1649
|
{
|
|
1671
1650
|
href: wikidataUrl,
|
|
@@ -1673,17 +1652,17 @@ function GenreDetailExtras({
|
|
|
1673
1652
|
rel: "noopener noreferrer",
|
|
1674
1653
|
className: "inline-flex items-center gap-1.5 text-[var(--color-text-muted)] hover:text-[var(--color-text)]",
|
|
1675
1654
|
children: [
|
|
1676
|
-
/* @__PURE__ */ (0,
|
|
1655
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_si2.SiWikidata, { "aria-hidden": "true", className: "h-3.5 w-3.5" }),
|
|
1677
1656
|
"Wikidata"
|
|
1678
1657
|
]
|
|
1679
1658
|
}
|
|
1680
1659
|
)
|
|
1681
1660
|
] }) }),
|
|
1682
|
-
/* @__PURE__ */ (0,
|
|
1661
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui9.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1683
1662
|
family,
|
|
1684
1663
|
renderGenreDetailExtras?.(overview),
|
|
1685
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0,
|
|
1686
|
-
/* @__PURE__ */ (0,
|
|
1664
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_ui9.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
1665
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
1687
1666
|
GenrePlaylistTracks,
|
|
1688
1667
|
{
|
|
1689
1668
|
genreUuid,
|
|
@@ -1701,10 +1680,10 @@ function GenreDetailExtras({
|
|
|
1701
1680
|
}
|
|
1702
1681
|
|
|
1703
1682
|
// src/genre-tree/GenreInfoPanelBody.tsx
|
|
1704
|
-
var
|
|
1683
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
1705
1684
|
var import_react14 = require("react");
|
|
1706
1685
|
function GenreNodeActionBand({ genrePlaylist, playback, ...bandProps }) {
|
|
1707
|
-
return /* @__PURE__ */ (0,
|
|
1686
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(GenreActionBand, { ...bandProps, playActions: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(GenrePlayActions, { genrePlaylist, playback }) });
|
|
1708
1687
|
}
|
|
1709
1688
|
function GenreInfoPanelBody({
|
|
1710
1689
|
toolbar,
|
|
@@ -1721,9 +1700,9 @@ function GenreInfoPanelBody({
|
|
|
1721
1700
|
}) {
|
|
1722
1701
|
const summary = scope === "reference" ? import_genre_tree19.GenreCatalogueCountsSchema.parse(genrePlaylist ?? catalogue) : void 0;
|
|
1723
1702
|
const selection = summary ? (0, import_genre_tree19.defaultGenreMusicSelection)(summary) : void 0;
|
|
1724
|
-
return /* @__PURE__ */ (0,
|
|
1703
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_jsx_runtime29.Fragment, { children: [
|
|
1725
1704
|
toolbar,
|
|
1726
|
-
genrePlaylist ? /* @__PURE__ */ (0,
|
|
1705
|
+
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(GenreActionBand, { ...band }),
|
|
1727
1706
|
/* @__PURE__ */ (0, import_react14.createElement)(
|
|
1728
1707
|
GenreDetailExtras,
|
|
1729
1708
|
{
|
|
@@ -1743,7 +1722,7 @@ function GenreInfoPanelBody({
|
|
|
1743
1722
|
}
|
|
1744
1723
|
|
|
1745
1724
|
// src/genre-tree/GenreDetailPanel.tsx
|
|
1746
|
-
var
|
|
1725
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
1747
1726
|
var RELATIVE_ITEM_COUNT = 1;
|
|
1748
1727
|
function toNode(genre, parentId) {
|
|
1749
1728
|
return {
|
|
@@ -1807,19 +1786,19 @@ function useGenreDetailContent({
|
|
|
1807
1786
|
if (isError) return {
|
|
1808
1787
|
name: null,
|
|
1809
1788
|
title: "Genre unavailable",
|
|
1810
|
-
content: /* @__PURE__ */ (0,
|
|
1789
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { role: "alert", className: "text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
1811
1790
|
};
|
|
1812
1791
|
if (isPending || !detail || !view) return {
|
|
1813
1792
|
name: null,
|
|
1814
1793
|
title: "Loading genre\u2026",
|
|
1815
|
-
content: /* @__PURE__ */ (0,
|
|
1816
|
-
/* @__PURE__ */ (0,
|
|
1817
|
-
/* @__PURE__ */ (0,
|
|
1818
|
-
/* @__PURE__ */ (0,
|
|
1794
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-col gap-3", "aria-busy": "true", "data-testid": "genre-detail-panel-skeleton", children: [
|
|
1795
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui10.Skeleton, { className: "h-6 w-2/3" }),
|
|
1796
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui10.Skeleton, { className: "h-4 w-full" }),
|
|
1797
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui10.Skeleton, { className: "h-4 w-3/4" })
|
|
1819
1798
|
] })
|
|
1820
1799
|
};
|
|
1821
1800
|
const selectGenre = (nodeId) => onSelectGenre(import_genre_tree20.GenreUuidSchema.parse(nodeId));
|
|
1822
|
-
const family = /* @__PURE__ */ (0,
|
|
1801
|
+
const family = /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1823
1802
|
import_genre_tree_view4.GenreNodeFamily,
|
|
1824
1803
|
{
|
|
1825
1804
|
node: view.node,
|
|
@@ -1830,17 +1809,17 @@ function useGenreDetailContent({
|
|
|
1830
1809
|
onSelectNode: selectGenre
|
|
1831
1810
|
}
|
|
1832
1811
|
);
|
|
1833
|
-
const ancestors = /* @__PURE__ */ (0,
|
|
1812
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_genre_tree_view4.GenreNodeAncestors, { ancestorNodes: view.ancestorNodes, onSelectNode: selectGenre });
|
|
1834
1813
|
return {
|
|
1835
1814
|
name: detail.name,
|
|
1836
1815
|
title: detail.name,
|
|
1837
1816
|
headerAccent: { background: view.fill, color: view.textColor },
|
|
1838
1817
|
aside: expanded ? ancestors : void 0,
|
|
1839
|
-
content: /* @__PURE__ */ (0,
|
|
1840
|
-
/* @__PURE__ */ (0,
|
|
1818
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1819
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1841
1820
|
GenreInfoPanelBody,
|
|
1842
1821
|
{
|
|
1843
|
-
family: /* @__PURE__ */ (0,
|
|
1822
|
+
family: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1844
1823
|
family,
|
|
1845
1824
|
!expanded && ancestors
|
|
1846
1825
|
] }),
|
|
@@ -1884,7 +1863,7 @@ function GenreDetailPanel({
|
|
|
1884
1863
|
expanded,
|
|
1885
1864
|
band: { onZoomIn, shareUrl, shareTarget: shareUrl ? shareTarget : void 0 }
|
|
1886
1865
|
});
|
|
1887
|
-
return /* @__PURE__ */ (0,
|
|
1866
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1888
1867
|
import_ui10.DetailPanel,
|
|
1889
1868
|
{
|
|
1890
1869
|
side: "left",
|
|
@@ -1897,7 +1876,7 @@ function GenreDetailPanel({
|
|
|
1897
1876
|
edgeTab,
|
|
1898
1877
|
aside: panel.aside,
|
|
1899
1878
|
titleInSearch,
|
|
1900
|
-
headerActions: onExpandedChange ? /* @__PURE__ */ (0,
|
|
1879
|
+
headerActions: onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui10.IconButton, { "aria-label": expanded ? "Shrink panel" : "Extend panel", onClick: () => onExpandedChange(!expanded), children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react9.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_lucide_react9.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" }) }) : void 0,
|
|
1901
1880
|
children: panel.content
|
|
1902
1881
|
}
|
|
1903
1882
|
);
|
|
@@ -1906,7 +1885,7 @@ function GenreDetailPanel({
|
|
|
1906
1885
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
1907
1886
|
var import_react16 = require("react");
|
|
1908
1887
|
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1909
|
-
var
|
|
1888
|
+
var import_jsx_runtime31 = require("react/jsx-runtime");
|
|
1910
1889
|
function ChangeParentPopup({
|
|
1911
1890
|
genrePlaylist,
|
|
1912
1891
|
genrePlaylists,
|
|
@@ -1941,12 +1920,12 @@ function ChangeParentPopup({
|
|
|
1941
1920
|
window.addEventListener("keydown", handleKeyDown);
|
|
1942
1921
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
1943
1922
|
}, [onClose]);
|
|
1944
|
-
return /* @__PURE__ */ (0,
|
|
1945
|
-
/* @__PURE__ */ (0,
|
|
1923
|
+
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
1924
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
1946
1925
|
"Current parent: ",
|
|
1947
1926
|
genrePlaylist.parent?.name ?? "none"
|
|
1948
1927
|
] }),
|
|
1949
|
-
/* @__PURE__ */ (0,
|
|
1928
|
+
/* @__PURE__ */ (0, import_jsx_runtime31.jsx)("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(
|
|
1950
1929
|
GenreSearch,
|
|
1951
1930
|
{
|
|
1952
1931
|
genrePlaylists: candidates,
|
|
@@ -1954,7 +1933,7 @@ function ChangeParentPopup({
|
|
|
1954
1933
|
placeholder: "Search a new parent\u2026"
|
|
1955
1934
|
}
|
|
1956
1935
|
) }),
|
|
1957
|
-
formErrors.length > 0 && /* @__PURE__ */ (0,
|
|
1936
|
+
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime31.jsx)("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
1958
1937
|
] });
|
|
1959
1938
|
}
|
|
1960
1939
|
|
|
@@ -1967,7 +1946,7 @@ var import_lucide_react10 = require("lucide-react");
|
|
|
1967
1946
|
var import_ui11 = require("@behindthemusictree/ui");
|
|
1968
1947
|
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
1969
1948
|
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
1970
|
-
var
|
|
1949
|
+
var import_jsx_runtime32 = require("react/jsx-runtime");
|
|
1971
1950
|
function ArtistActionBand({ artist, share }) {
|
|
1972
1951
|
const { trackList, playNewTrackListFromArtist } = (0, import_genre_tree22.useTrackList)();
|
|
1973
1952
|
const { isPlaying, setIsPlaying } = (0, import_player7.usePlayer)();
|
|
@@ -1983,11 +1962,11 @@ function ArtistActionBand({ artist, share }) {
|
|
|
1983
1962
|
console.error("Failed to load artist tracks:", error);
|
|
1984
1963
|
});
|
|
1985
1964
|
};
|
|
1986
|
-
return /* @__PURE__ */ (0,
|
|
1987
|
-
/* @__PURE__ */ (0,
|
|
1965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_ui11.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime32.jsxs)(import_ui11.ActionBand, { children: [
|
|
1966
|
+
/* @__PURE__ */ (0, import_jsx_runtime32.jsx)(
|
|
1988
1967
|
import_ui11.ActionButton,
|
|
1989
1968
|
{
|
|
1990
|
-
icon: playing ? /* @__PURE__ */ (0,
|
|
1969
|
+
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react10.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime32.jsx)(import_lucide_react10.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
1991
1970
|
label: playing ? "Pause" : "Play",
|
|
1992
1971
|
caption: String(artist.playableTracksCount),
|
|
1993
1972
|
disabled: artist.playableTracksCount === 0,
|
|
@@ -2006,7 +1985,7 @@ var import_ui13 = require("@behindthemusictree/ui");
|
|
|
2006
1985
|
var import_lucide_react11 = require("lucide-react");
|
|
2007
1986
|
var import_si3 = require("react-icons/si");
|
|
2008
1987
|
var import_ui12 = require("@behindthemusictree/ui");
|
|
2009
|
-
var
|
|
1988
|
+
var import_jsx_runtime33 = require("react/jsx-runtime");
|
|
2010
1989
|
var LINK_KINDS = {
|
|
2011
1990
|
official: { label: "Official website", Icon: import_lucide_react11.Globe },
|
|
2012
1991
|
wikipedia: { label: "Wikipedia", Icon: import_si3.SiWikipedia },
|
|
@@ -2043,7 +2022,7 @@ function artistLinks(artist) {
|
|
|
2043
2022
|
return links;
|
|
2044
2023
|
}
|
|
2045
2024
|
function ArtistLinks({ links }) {
|
|
2046
|
-
return /* @__PURE__ */ (0,
|
|
2025
|
+
return /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(import_ui12.Chip, { href: url, icon: /* @__PURE__ */ (0, import_jsx_runtime33.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
2047
2026
|
}
|
|
2048
2027
|
|
|
2049
2028
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -2054,7 +2033,7 @@ function formatYears(beginYear, endYear, ended) {
|
|
|
2054
2033
|
}
|
|
2055
2034
|
|
|
2056
2035
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2057
|
-
var
|
|
2036
|
+
var import_jsx_runtime34 = require("react/jsx-runtime");
|
|
2058
2037
|
var countryNames = new Intl.DisplayNames(["en"], { type: "region" });
|
|
2059
2038
|
function ArtistHeader({ artist }) {
|
|
2060
2039
|
const fields = [];
|
|
@@ -2064,35 +2043,35 @@ function ArtistHeader({ artist }) {
|
|
|
2064
2043
|
const years = formatYears(artist.beginYear, artist.endYear, artist.ended);
|
|
2065
2044
|
if (years) fields.push({ label: "Active", value: years });
|
|
2066
2045
|
const links = artistLinks(artist);
|
|
2067
|
-
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0,
|
|
2046
|
+
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(ArtistLinks, { links }) });
|
|
2068
2047
|
if (fields.length === 0) return null;
|
|
2069
|
-
return /* @__PURE__ */ (0,
|
|
2048
|
+
return /* @__PURE__ */ (0, import_jsx_runtime34.jsx)(import_ui13.FieldList, { items: fields });
|
|
2070
2049
|
}
|
|
2071
2050
|
|
|
2072
2051
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
2073
|
-
var
|
|
2052
|
+
var import_jsx_runtime35 = require("react/jsx-runtime");
|
|
2074
2053
|
function ExternalLink({ href, children }) {
|
|
2075
|
-
return /* @__PURE__ */ (0,
|
|
2054
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsx)("a", { href, target: "_blank", rel: "noopener noreferrer", className: "underline-offset-2 hover:underline", children });
|
|
2076
2055
|
}
|
|
2077
2056
|
function ArtistPhoto({ image, name }) {
|
|
2078
|
-
return /* @__PURE__ */ (0,
|
|
2079
|
-
/* @__PURE__ */ (0,
|
|
2080
|
-
/* @__PURE__ */ (0,
|
|
2057
|
+
return /* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("figure", { className: "flex flex-col gap-1.5", children: [
|
|
2058
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
2059
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2081
2060
|
"Photo: ",
|
|
2082
|
-
/* @__PURE__ */ (0,
|
|
2061
|
+
/* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2083
2062
|
",",
|
|
2084
2063
|
" ",
|
|
2085
|
-
image.licenseUrl ? /* @__PURE__ */ (0,
|
|
2064
|
+
image.licenseUrl ? /* @__PURE__ */ (0, import_jsx_runtime35.jsx)(ExternalLink, { href: image.licenseUrl, children: image.license }) : image.license
|
|
2086
2065
|
] })
|
|
2087
2066
|
] });
|
|
2088
2067
|
}
|
|
2089
2068
|
|
|
2090
2069
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2091
2070
|
var import_ui14 = require("@behindthemusictree/ui");
|
|
2092
|
-
var
|
|
2071
|
+
var import_jsx_runtime36 = require("react/jsx-runtime");
|
|
2093
2072
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2094
2073
|
if (memberships.length === 0) return null;
|
|
2095
|
-
return /* @__PURE__ */ (0,
|
|
2074
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsx)(import_ui14.PanelGroup, { title, children: /* @__PURE__ */ (0, import_jsx_runtime36.jsx)("ul", { children: memberships.map((membership, index) => {
|
|
2096
2075
|
const details = [
|
|
2097
2076
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2098
2077
|
...membership.roles
|
|
@@ -2100,9 +2079,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2100
2079
|
const detailsText = details.filter(Boolean).join(" \xB7 ");
|
|
2101
2080
|
return (
|
|
2102
2081
|
// A member can have several periods in the same group.
|
|
2103
|
-
/* @__PURE__ */ (0,
|
|
2104
|
-
/* @__PURE__ */ (0,
|
|
2105
|
-
detailsText && /* @__PURE__ */ (0,
|
|
2082
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("li", { className: "truncate py-0.5", title: detailsText || void 0, children: [
|
|
2083
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("span", { className: "font-medium text-[var(--color-text)]", children: renderArtistLink(membership.artist) }),
|
|
2084
|
+
detailsText && /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2106
2085
|
" \u2014 ",
|
|
2107
2086
|
detailsText
|
|
2108
2087
|
] })
|
|
@@ -2113,9 +2092,9 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2113
2092
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2114
2093
|
if (memberships.length === 0) return null;
|
|
2115
2094
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2116
|
-
return /* @__PURE__ */ (0,
|
|
2117
|
-
/* @__PURE__ */ (0,
|
|
2118
|
-
/* @__PURE__ */ (0,
|
|
2095
|
+
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)(import_ui14.PanelSection, { title, children: [
|
|
2096
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2097
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(
|
|
2119
2098
|
MembershipList,
|
|
2120
2099
|
{
|
|
2121
2100
|
title: "Past",
|
|
@@ -2128,7 +2107,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2128
2107
|
|
|
2129
2108
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2130
2109
|
var import_ui15 = require("@behindthemusictree/ui");
|
|
2131
|
-
var
|
|
2110
|
+
var import_jsx_runtime37 = require("react/jsx-runtime");
|
|
2132
2111
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2133
2112
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
2134
2113
|
function discographyGroup({ primaryType, secondaryTypes }) {
|
|
@@ -2148,12 +2127,12 @@ function byYear(a, b) {
|
|
|
2148
2127
|
function ArtistDiscography({ albums }) {
|
|
2149
2128
|
if (albums.length === 0) return null;
|
|
2150
2129
|
const sorted = [...albums].sort(byYear);
|
|
2151
|
-
return /* @__PURE__ */ (0,
|
|
2130
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui15.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2152
2131
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2153
2132
|
if (groupAlbums.length === 0) return null;
|
|
2154
|
-
return /* @__PURE__ */ (0,
|
|
2155
|
-
/* @__PURE__ */ (0,
|
|
2156
|
-
/* @__PURE__ */ (0,
|
|
2133
|
+
return /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(import_ui15.PanelGroup, { title: group, children: /* @__PURE__ */ (0, import_jsx_runtime37.jsx)("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
2134
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2135
|
+
/* @__PURE__ */ (0, import_jsx_runtime37.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2157
2136
|
] }, album.uuid)) }) }, group);
|
|
2158
2137
|
}) });
|
|
2159
2138
|
}
|
|
@@ -2165,7 +2144,7 @@ var import_lucide_react12 = require("lucide-react");
|
|
|
2165
2144
|
var import_ui16 = require("@behindthemusictree/ui");
|
|
2166
2145
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2167
2146
|
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2168
|
-
var
|
|
2147
|
+
var import_transport6 = require("@behindthemusictree/app-kit/transport");
|
|
2169
2148
|
|
|
2170
2149
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2171
2150
|
var import_player10 = require("@behindthemusictree/app-kit/player");
|
|
@@ -2175,7 +2154,7 @@ var import_genre_tree23 = require("@behindthemusictree/app-kit/genre-tree");
|
|
|
2175
2154
|
var import_fa3 = require("react-icons/fa");
|
|
2176
2155
|
var import_player8 = require("@behindthemusictree/app-kit/player");
|
|
2177
2156
|
var import_player9 = require("@behindthemusictree/app-kit/player");
|
|
2178
|
-
var
|
|
2157
|
+
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2179
2158
|
function TrackPositionPlayPause({
|
|
2180
2159
|
position,
|
|
2181
2160
|
uuid,
|
|
@@ -2189,14 +2168,14 @@ function TrackPositionPlayPause({
|
|
|
2189
2168
|
const isPlaying = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PLAYING;
|
|
2190
2169
|
const isPaused = isThisTrack && isConfirmedPlayable && playState === import_player9.PlayStates.PAUSED;
|
|
2191
2170
|
const isCurrentTrackActive = isPlaying || isPaused;
|
|
2192
|
-
return /* @__PURE__ */ (0,
|
|
2171
|
+
return /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2193
2172
|
"div",
|
|
2194
2173
|
{
|
|
2195
2174
|
className: "track-position-play-pause relative flex items-center justify-center gap-2 text-lg w-16 cursor-pointer",
|
|
2196
2175
|
style: { minWidth: "4rem", maxWidth: "4rem" },
|
|
2197
2176
|
onClick: handlePlayPauseClick,
|
|
2198
2177
|
children: [
|
|
2199
|
-
/* @__PURE__ */ (0,
|
|
2178
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "track-position-play-pause__status group-hover:hidden flex items-center justify-center", children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "track-position-play-pause__spinner", role: "status", "aria-label": "Loading track" }) : isCurrentTrackActive ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(
|
|
2200
2179
|
"span",
|
|
2201
2180
|
{
|
|
2202
2181
|
className: "track-position-play-pause__bars",
|
|
@@ -2204,18 +2183,18 @@ function TrackPositionPlayPause({
|
|
|
2204
2183
|
role: "img",
|
|
2205
2184
|
"aria-label": isPlaying ? "Playing" : "Paused",
|
|
2206
2185
|
children: [
|
|
2207
|
-
/* @__PURE__ */ (0,
|
|
2208
|
-
/* @__PURE__ */ (0,
|
|
2209
|
-
/* @__PURE__ */ (0,
|
|
2186
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2187
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "track-position-play-pause__bar" }),
|
|
2188
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "track-position-play-pause__bar" })
|
|
2210
2189
|
]
|
|
2211
2190
|
}
|
|
2212
2191
|
) : position }),
|
|
2213
|
-
/* @__PURE__ */ (0,
|
|
2192
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2214
2193
|
"div",
|
|
2215
2194
|
{
|
|
2216
2195
|
className: `hidden group-hover:flex items-center justify-center ${isCurrentTrackActive ? "" : "absolute inset-0"}`,
|
|
2217
2196
|
"aria-hidden": "true",
|
|
2218
|
-
children: isAwaitingPlayback ? /* @__PURE__ */ (0,
|
|
2197
|
+
children: isAwaitingPlayback ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("span", { className: "track-position-play-pause__spinner" }) : isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_fa3.FaPause, {}) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_fa3.FaPlay, {})
|
|
2219
2198
|
}
|
|
2220
2199
|
)
|
|
2221
2200
|
]
|
|
@@ -2226,7 +2205,7 @@ function TrackPositionPlayPause({
|
|
|
2226
2205
|
// src/genre-tree/track-list-sidebar/TrackItem.tsx
|
|
2227
2206
|
var import_genre_tree24 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2228
2207
|
var import_genre_tree25 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2229
|
-
var
|
|
2208
|
+
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
2230
2209
|
function TrackItem({
|
|
2231
2210
|
track,
|
|
2232
2211
|
position,
|
|
@@ -2250,12 +2229,12 @@ function TrackItem({
|
|
|
2250
2229
|
loadTrackForPlayer(track.uuid);
|
|
2251
2230
|
}
|
|
2252
2231
|
};
|
|
2253
|
-
return /* @__PURE__ */ (0,
|
|
2232
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(
|
|
2254
2233
|
"div",
|
|
2255
2234
|
{
|
|
2256
2235
|
className: `track-item flex h-14 text-[var(--color-text)] ${isUnplayable ? "opacity-50" : "hover:bg-[var(--color-surface-muted)] group"}`,
|
|
2257
2236
|
children: [
|
|
2258
|
-
isUnplayable ? /* @__PURE__ */ (0,
|
|
2237
|
+
isUnplayable ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2259
2238
|
"div",
|
|
2260
2239
|
{
|
|
2261
2240
|
className: "flex items-center justify-center text-lg w-16",
|
|
@@ -2263,7 +2242,7 @@ function TrackItem({
|
|
|
2263
2242
|
"aria-disabled": "true",
|
|
2264
2243
|
children: position
|
|
2265
2244
|
}
|
|
2266
|
-
) : /* @__PURE__ */ (0,
|
|
2245
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2267
2246
|
TrackPositionPlayPause,
|
|
2268
2247
|
{
|
|
2269
2248
|
position,
|
|
@@ -2272,12 +2251,12 @@ function TrackItem({
|
|
|
2272
2251
|
isSelected: selectedTrack?.uuid === track.uuid
|
|
2273
2252
|
}
|
|
2274
2253
|
),
|
|
2275
|
-
/* @__PURE__ */ (0,
|
|
2276
|
-
/* @__PURE__ */ (0,
|
|
2277
|
-
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0,
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsxs)("div", { className: "title-artist-container flex flex-col items-start justify-center min-w-0 flex-1", children: [
|
|
2255
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree24.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2256
|
+
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_genre_tree25.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2278
2257
|
] }),
|
|
2279
|
-
/* @__PURE__ */ (0,
|
|
2280
|
-
renderDuration && /* @__PURE__ */ (0,
|
|
2258
|
+
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "genre-name-container flex items-center justify-start w-[21.6%] min-w-0 shrink-0", children: track.genre ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2259
|
+
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2281
2260
|
"div",
|
|
2282
2261
|
{
|
|
2283
2262
|
className: "duration flex text-base w-16 items-center justify-center",
|
|
@@ -2285,15 +2264,15 @@ function TrackItem({
|
|
|
2285
2264
|
children: renderDuration(track)
|
|
2286
2265
|
}
|
|
2287
2266
|
),
|
|
2288
|
-
renderActions && /* @__PURE__ */ (0,
|
|
2267
|
+
renderActions && /* @__PURE__ */ (0, import_jsx_runtime39.jsx)("div", { className: "edit flex text-base w-6 items-center justify-center mr-2 cursor-pointer", children: renderActions(track) })
|
|
2289
2268
|
]
|
|
2290
2269
|
}
|
|
2291
2270
|
);
|
|
2292
2271
|
}
|
|
2293
2272
|
|
|
2294
2273
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2295
|
-
var
|
|
2296
|
-
var SongPageSchema2 = (0,
|
|
2274
|
+
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2275
|
+
var SongPageSchema2 = (0, import_transport6.PaginatedResponseSchema)(import_genre_tree26.SongDetailedSchema);
|
|
2297
2276
|
var SORTS = [
|
|
2298
2277
|
{ ordering: "title", label: "Title" },
|
|
2299
2278
|
{ ordering: "-albumYear", label: "Year" }
|
|
@@ -2303,7 +2282,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2303
2282
|
const [ordering, setOrdering] = (0, import_react17.useState)("title");
|
|
2304
2283
|
const { playNewTrackListFromArtist } = (0, import_genre_tree26.useTrackList)();
|
|
2305
2284
|
const { playerTrackObject } = (0, import_player11.usePlayer)();
|
|
2306
|
-
const { data, isPending, isError } = (0,
|
|
2285
|
+
const { data, isPending, isError } = (0, import_transport6.usePlaybackQuery)({
|
|
2307
2286
|
getBackendBaseUrl,
|
|
2308
2287
|
queryKey: ["referenceSongs", "artist", artist.uuid, ordering, page],
|
|
2309
2288
|
queryFn: (fetchBound) => fetchBound(import_genre_tree26.libraryEndpoints.reference.songs.list(), true, false, void 0, {
|
|
@@ -2325,21 +2304,21 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2325
2304
|
event.stopPropagation();
|
|
2326
2305
|
void play(song.uuid);
|
|
2327
2306
|
};
|
|
2328
|
-
return /* @__PURE__ */ (0,
|
|
2329
|
-
/* @__PURE__ */ (0,
|
|
2330
|
-
/* @__PURE__ */ (0,
|
|
2307
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui16.PanelSection, { title: "Songs", children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui16.Skeleton, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(import_jsx_runtime40.Fragment, { children: [
|
|
2308
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)("div", { className: "flex flex-wrap items-center justify-between gap-2 mb-2", children: [
|
|
2309
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsxs)(
|
|
2331
2310
|
"button",
|
|
2332
2311
|
{
|
|
2333
2312
|
type: "button",
|
|
2334
2313
|
onClick: () => void play(),
|
|
2335
2314
|
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",
|
|
2336
2315
|
children: [
|
|
2337
|
-
/* @__PURE__ */ (0,
|
|
2316
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react12.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2338
2317
|
"Play all"
|
|
2339
2318
|
]
|
|
2340
2319
|
}
|
|
2341
2320
|
),
|
|
2342
|
-
/* @__PURE__ */ (0,
|
|
2321
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2343
2322
|
"button",
|
|
2344
2323
|
{
|
|
2345
2324
|
type: "button",
|
|
@@ -2354,7 +2333,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2354
2333
|
sort.ordering
|
|
2355
2334
|
)) })
|
|
2356
2335
|
] }),
|
|
2357
|
-
/* @__PURE__ */ (0,
|
|
2336
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "overflow-hidden mb-2 bg-zinc-950 rounded-lg", children: data.results.map((song, index) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("li", { onClickCapture: (event) => handleRowClickCapture(event, song), children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2358
2337
|
TrackItem,
|
|
2359
2338
|
{
|
|
2360
2339
|
track: song,
|
|
@@ -2363,12 +2342,12 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2363
2342
|
renderSongLink
|
|
2364
2343
|
}
|
|
2365
2344
|
) }, song.uuid)) }),
|
|
2366
|
-
/* @__PURE__ */ (0,
|
|
2345
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui16.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2367
2346
|
] }) });
|
|
2368
2347
|
}
|
|
2369
2348
|
|
|
2370
2349
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2371
|
-
var
|
|
2350
|
+
var import_jsx_runtime41 = require("react/jsx-runtime");
|
|
2372
2351
|
function useArtistPanel({
|
|
2373
2352
|
uuid,
|
|
2374
2353
|
scope,
|
|
@@ -2389,26 +2368,26 @@ function useArtistPanel({
|
|
|
2389
2368
|
return {
|
|
2390
2369
|
...panel,
|
|
2391
2370
|
title: "Artist",
|
|
2392
|
-
content: /* @__PURE__ */ (0,
|
|
2393
|
-
/* @__PURE__ */ (0,
|
|
2394
|
-
/* @__PURE__ */ (0,
|
|
2395
|
-
/* @__PURE__ */ (0,
|
|
2396
|
-
/* @__PURE__ */ (0,
|
|
2397
|
-
/* @__PURE__ */ (0,
|
|
2398
|
-
/* @__PURE__ */ (0,
|
|
2371
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2372
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.Skeleton, { className: "h-3 w-16" }),
|
|
2373
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.Skeleton, { className: "h-4 w-32" }),
|
|
2374
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.Skeleton, { className: "h-3 w-16" }),
|
|
2375
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.Skeleton, { className: "h-4 w-24" }),
|
|
2376
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2377
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.Skeleton, { className: "h-16" })
|
|
2399
2378
|
] })
|
|
2400
2379
|
};
|
|
2401
2380
|
case "not-found":
|
|
2402
2381
|
return {
|
|
2403
2382
|
...panel,
|
|
2404
2383
|
title: "Artist not found",
|
|
2405
|
-
content: /* @__PURE__ */ (0,
|
|
2384
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This artist does not exist." })
|
|
2406
2385
|
};
|
|
2407
2386
|
case "error":
|
|
2408
2387
|
return {
|
|
2409
2388
|
...panel,
|
|
2410
2389
|
title: "Artist",
|
|
2411
|
-
content: /* @__PURE__ */ (0,
|
|
2390
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)("p", { className: "text-red-600", children: "Could not load this artist." })
|
|
2412
2391
|
};
|
|
2413
2392
|
case "success": {
|
|
2414
2393
|
const { artist } = result;
|
|
@@ -2417,19 +2396,19 @@ function useArtistPanel({
|
|
|
2417
2396
|
return {
|
|
2418
2397
|
...panel,
|
|
2419
2398
|
title: artist.name,
|
|
2420
|
-
content: /* @__PURE__ */ (0,
|
|
2421
|
-
/* @__PURE__ */ (0,
|
|
2399
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime41.jsxs)(import_jsx_runtime41.Fragment, { children: [
|
|
2400
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2422
2401
|
ArtistActionBand,
|
|
2423
2402
|
{
|
|
2424
2403
|
artist,
|
|
2425
|
-
share: shareTarget && shareUrl ? /* @__PURE__ */ (0,
|
|
2404
|
+
share: shareTarget && shareUrl ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl }) : void 0
|
|
2426
2405
|
}
|
|
2427
2406
|
),
|
|
2428
|
-
artist.image && /* @__PURE__ */ (0,
|
|
2429
|
-
/* @__PURE__ */ (0,
|
|
2430
|
-
/* @__PURE__ */ (0,
|
|
2431
|
-
/* @__PURE__ */ (0,
|
|
2432
|
-
artist.tracksCount > 0 && /* @__PURE__ */ (0,
|
|
2407
|
+
artist.image && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistPhoto, { image: artist.image, name: artist.name }),
|
|
2408
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistHeader, { artist }),
|
|
2409
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistMembers, { title: "Members", memberships: artist.members, renderArtistLink }),
|
|
2410
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistMembers, { title: "Member of", memberships: artist.memberOf, renderArtistLink }),
|
|
2411
|
+
artist.tracksCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2433
2412
|
ArtistSongs,
|
|
2434
2413
|
{
|
|
2435
2414
|
artist: { uuid: artist.uuid, name: artist.name },
|
|
@@ -2439,7 +2418,7 @@ function useArtistPanel({
|
|
|
2439
2418
|
}
|
|
2440
2419
|
)
|
|
2441
2420
|
] }),
|
|
2442
|
-
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0,
|
|
2421
|
+
extraContent: artist.albums.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistDiscography, { albums: artist.albums }) : void 0
|
|
2443
2422
|
};
|
|
2444
2423
|
}
|
|
2445
2424
|
}
|
|
@@ -2455,7 +2434,7 @@ var import_lucide_react13 = require("lucide-react");
|
|
|
2455
2434
|
var import_ui18 = require("@behindthemusictree/ui");
|
|
2456
2435
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2457
2436
|
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2458
|
-
var
|
|
2437
|
+
var import_jsx_runtime42 = require("react/jsx-runtime");
|
|
2459
2438
|
var numberFormat = new Intl.NumberFormat("en");
|
|
2460
2439
|
var dateFormat = new Intl.DateTimeFormat("en", { dateStyle: "medium" });
|
|
2461
2440
|
var externalLink = "text-[var(--color-primary)] hover:underline focus-visible:underline";
|
|
@@ -2463,27 +2442,27 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2463
2442
|
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2464
2443
|
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2465
2444
|
let body = null;
|
|
2466
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0,
|
|
2467
|
-
else if (history.status === "error") body = /* @__PURE__ */ (0,
|
|
2445
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2446
|
+
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2468
2447
|
else if (history.status === "success")
|
|
2469
|
-
body = history.entries.length === 0 ? /* @__PURE__ */ (0,
|
|
2470
|
-
/* @__PURE__ */ (0,
|
|
2471
|
-
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0,
|
|
2448
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
2449
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2450
|
+
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2472
2451
|
" ",
|
|
2473
2452
|
"\u2014 ",
|
|
2474
2453
|
entry.oldValue ?? "none",
|
|
2475
2454
|
" \u2192 ",
|
|
2476
2455
|
entry.newValue ?? "none"
|
|
2477
2456
|
] }) : null,
|
|
2478
|
-
/* @__PURE__ */ (0,
|
|
2457
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2479
2458
|
entry.actorPseudo ?? "Anonymous",
|
|
2480
2459
|
" \xB7 ",
|
|
2481
2460
|
dateFormat.format(new Date(entry.createdOn))
|
|
2482
2461
|
] })
|
|
2483
2462
|
] }, entry.uuid)) });
|
|
2484
|
-
return /* @__PURE__ */ (0,
|
|
2485
|
-
/* @__PURE__ */ (0,
|
|
2486
|
-
/* @__PURE__ */ (0,
|
|
2463
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.PanelBleed, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2464
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui18.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2465
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "mt-1.5", children: body })
|
|
2487
2466
|
] }) });
|
|
2488
2467
|
}
|
|
2489
2468
|
function SongPanelContent(props) {
|
|
@@ -2502,13 +2481,13 @@ function SongPanelContent(props) {
|
|
|
2502
2481
|
const genre = song.genre;
|
|
2503
2482
|
fields.push({
|
|
2504
2483
|
label: "Genre",
|
|
2505
|
-
value: onSelectGenre ? /* @__PURE__ */ (0,
|
|
2506
|
-
index > 0 && /* @__PURE__ */ (0,
|
|
2507
|
-
/* @__PURE__ */ (0,
|
|
2484
|
+
value: onSelectGenre ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { children: [
|
|
2485
|
+
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2486
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2508
2487
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2509
2488
|
});
|
|
2510
2489
|
} else {
|
|
2511
|
-
fields.push({ label: "Genre", value: /* @__PURE__ */ (0,
|
|
2490
|
+
fields.push({ label: "Genre", value: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "text-[var(--color-text-muted)]", children: "No genre" }) });
|
|
2512
2491
|
}
|
|
2513
2492
|
if (song.firstReleaseYear) fields.push({ label: "First released", value: song.firstReleaseYear });
|
|
2514
2493
|
const viewCount = song.youtubeVideo?.viewCount;
|
|
@@ -2518,11 +2497,11 @@ function SongPanelContent(props) {
|
|
|
2518
2497
|
const links = [];
|
|
2519
2498
|
if (musicBrainzUrl)
|
|
2520
2499
|
links.push(
|
|
2521
|
-
/* @__PURE__ */ (0,
|
|
2500
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)("a", { href: musicBrainzUrl, target: "_blank", rel: "noopener noreferrer", className: externalLink, children: "MusicBrainz" }, "mb")
|
|
2522
2501
|
);
|
|
2523
2502
|
if (song.youtubeVideo)
|
|
2524
2503
|
links.push(
|
|
2525
|
-
/* @__PURE__ */ (0,
|
|
2504
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2526
2505
|
"a",
|
|
2527
2506
|
{
|
|
2528
2507
|
href: `https://www.youtube.com/watch?v=${encodeURIComponent(song.youtubeVideo.id)}`,
|
|
@@ -2537,31 +2516,31 @@ function SongPanelContent(props) {
|
|
|
2537
2516
|
if (links.length > 0)
|
|
2538
2517
|
fields.push({
|
|
2539
2518
|
label: "Links",
|
|
2540
|
-
value: /* @__PURE__ */ (0,
|
|
2519
|
+
value: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("span", { className: "flex gap-3", children: links })
|
|
2541
2520
|
});
|
|
2542
|
-
return /* @__PURE__ */ (0,
|
|
2543
|
-
/* @__PURE__ */ (0,
|
|
2544
|
-
/* @__PURE__ */ (0,
|
|
2521
|
+
return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
|
|
2522
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_ui18.ActionBand, { children: [
|
|
2523
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
|
|
2545
2524
|
import_ui18.ActionButton,
|
|
2546
2525
|
{
|
|
2547
|
-
icon: isPlaying ? /* @__PURE__ */ (0,
|
|
2526
|
+
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react13.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react13.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2548
2527
|
label: isPlaying ? "Pause" : "Play",
|
|
2549
2528
|
disabled: !!unplayableReason,
|
|
2550
2529
|
title: unplayableReason ?? void 0,
|
|
2551
2530
|
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope)
|
|
2552
2531
|
}
|
|
2553
2532
|
),
|
|
2554
|
-
shareUrl && /* @__PURE__ */ (0,
|
|
2533
|
+
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2555
2534
|
] }) }),
|
|
2556
|
-
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0,
|
|
2557
|
-
/* @__PURE__ */ (0,
|
|
2558
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0,
|
|
2559
|
-
/* @__PURE__ */ (0,
|
|
2535
|
+
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_genre_tree28.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2536
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.FieldList, { items: fields }),
|
|
2537
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_ui18.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2538
|
+
/* @__PURE__ */ (0, import_jsx_runtime42.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2560
2539
|
] });
|
|
2561
2540
|
}
|
|
2562
2541
|
|
|
2563
2542
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2564
|
-
var
|
|
2543
|
+
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2565
2544
|
function useSongPanel({
|
|
2566
2545
|
uuid,
|
|
2567
2546
|
scope,
|
|
@@ -2582,24 +2561,24 @@ function useSongPanel({
|
|
|
2582
2561
|
return {
|
|
2583
2562
|
...panel,
|
|
2584
2563
|
title: "Song",
|
|
2585
|
-
content: /* @__PURE__ */ (0,
|
|
2586
|
-
/* @__PURE__ */ (0,
|
|
2587
|
-
/* @__PURE__ */ (0,
|
|
2588
|
-
/* @__PURE__ */ (0,
|
|
2589
|
-
/* @__PURE__ */ (0,
|
|
2564
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui19.Skeleton, { className: "h-3 w-16" }),
|
|
2566
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui19.Skeleton, { className: "h-4 w-32" }),
|
|
2567
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui19.Skeleton, { className: "h-3 w-16" }),
|
|
2568
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui19.Skeleton, { className: "h-4 w-24" })
|
|
2590
2569
|
] })
|
|
2591
2570
|
};
|
|
2592
2571
|
case "not-found":
|
|
2593
2572
|
return {
|
|
2594
2573
|
...panel,
|
|
2595
2574
|
title: "Song not found",
|
|
2596
|
-
content: /* @__PURE__ */ (0,
|
|
2575
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "This song does not exist." })
|
|
2597
2576
|
};
|
|
2598
2577
|
case "error":
|
|
2599
2578
|
return {
|
|
2600
2579
|
...panel,
|
|
2601
2580
|
title: "Song",
|
|
2602
|
-
content: /* @__PURE__ */ (0,
|
|
2581
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-red-600", children: "Could not load this song." })
|
|
2603
2582
|
};
|
|
2604
2583
|
case "success": {
|
|
2605
2584
|
const { song } = result;
|
|
@@ -2607,7 +2586,7 @@ function useSongPanel({
|
|
|
2607
2586
|
return {
|
|
2608
2587
|
...panel,
|
|
2609
2588
|
title: song.title,
|
|
2610
|
-
content: /* @__PURE__ */ (0,
|
|
2589
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2611
2590
|
SongPanelContent,
|
|
2612
2591
|
{
|
|
2613
2592
|
song,
|
|
@@ -2660,12 +2639,12 @@ function useEntityPanel({
|
|
|
2660
2639
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2661
2640
|
var import_md = require("react-icons/md");
|
|
2662
2641
|
var import_ui20 = require("@behindthemusictree/ui");
|
|
2663
|
-
var
|
|
2642
|
+
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2664
2643
|
function SizeMetricToggle({
|
|
2665
2644
|
value,
|
|
2666
2645
|
onChange
|
|
2667
2646
|
}) {
|
|
2668
|
-
return /* @__PURE__ */ (0,
|
|
2647
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2669
2648
|
import_ui20.SegmentedControl,
|
|
2670
2649
|
{
|
|
2671
2650
|
variant: "floating",
|
|
@@ -2673,15 +2652,15 @@ function SizeMetricToggle({
|
|
|
2673
2652
|
value,
|
|
2674
2653
|
onChange,
|
|
2675
2654
|
options: [
|
|
2676
|
-
{ value: "songs", label: /* @__PURE__ */ (0,
|
|
2677
|
-
{ value: "views", label: /* @__PURE__ */ (0,
|
|
2655
|
+
{ value: "songs", label: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_md.MdMusicNote, { size: 18, "aria-hidden": true }), "aria-label": "Size by songs", title: "Node size by song count" },
|
|
2656
|
+
{ value: "views", label: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_md.MdVisibility, { size: 18, "aria-hidden": true }), "aria-label": "Size by views", title: "Node size by song views" }
|
|
2678
2657
|
]
|
|
2679
2658
|
}
|
|
2680
2659
|
);
|
|
2681
2660
|
}
|
|
2682
2661
|
|
|
2683
2662
|
// src/genre-tree/GenreTreeView.tsx
|
|
2684
|
-
var
|
|
2663
|
+
var import_jsx_runtime45 = require("react/jsx-runtime");
|
|
2685
2664
|
var NO_POP_ROOT_TITLE = "This genre tree has no 'Mainstream Pop' root yet";
|
|
2686
2665
|
var REGIONS_CLASS = "[--gtv-center-left:var(--layout-center-left)] [--gtv-center-right:var(--layout-center-right)] [--gtv-center-top:var(--layout-band-top)]";
|
|
2687
2666
|
var noop = () => {
|
|
@@ -2773,6 +2752,7 @@ function GenreTreeView({
|
|
|
2773
2752
|
isFetching: isTreeFetching,
|
|
2774
2753
|
genrePlaylistByNodeId,
|
|
2775
2754
|
visibleGenrePlaylists,
|
|
2755
|
+
focusUuids,
|
|
2776
2756
|
groupedGenrePlaylistsByRoot,
|
|
2777
2757
|
selectedGenreUuid,
|
|
2778
2758
|
selectGenre,
|
|
@@ -2832,14 +2812,14 @@ function GenreTreeView({
|
|
|
2832
2812
|
const openSongRef = (0, import_react19.useRef)(openSong);
|
|
2833
2813
|
openSongRef.current = openSong;
|
|
2834
2814
|
const resolvedRenderSongLink = (0, import_react19.useCallback)(
|
|
2835
|
-
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0,
|
|
2815
|
+
(song) => renderSongLink ? renderSongLink(song) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", onClick: () => openSongRef.current(song.uuid), className: "hover:underline", children: song.title }),
|
|
2836
2816
|
[renderSongLink]
|
|
2837
2817
|
);
|
|
2838
2818
|
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react19.useState)(null);
|
|
2839
2819
|
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react19.useState)(null);
|
|
2840
2820
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
2841
2821
|
const songBaseUrl = getBackendBaseUrl;
|
|
2842
|
-
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
2822
|
+
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
2843
2823
|
const getGenrePath = (genre) => {
|
|
2844
2824
|
const path = [];
|
|
2845
2825
|
let current = visibleGenrePlaylists.find((playlist) => playlist.criteria?.uuid === genre.uuid);
|
|
@@ -2881,7 +2861,7 @@ function GenreTreeView({
|
|
|
2881
2861
|
selectGenrePlaylist(genrePlaylist2);
|
|
2882
2862
|
}
|
|
2883
2863
|
});
|
|
2884
|
-
const
|
|
2864
|
+
const otherPanel = overlayPanel ?? (selectedGenreUuid !== null ? void 0 : entityPanel);
|
|
2885
2865
|
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react19.useState)(false);
|
|
2886
2866
|
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react19.useState)(false);
|
|
2887
2867
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
@@ -2909,7 +2889,7 @@ function GenreTreeView({
|
|
|
2909
2889
|
const obscuredInset = (0, import_ui21.useObscuredInset)(panelRef);
|
|
2910
2890
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
2911
2891
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
2912
|
-
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric), [visibleGenrePlaylists, nodeMetric]);
|
|
2892
|
+
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric, focusUuids), [visibleGenrePlaylists, nodeMetric, focusUuids]);
|
|
2913
2893
|
const relations = (0, import_genre_tree_view5.useGenreNodeRelations)(
|
|
2914
2894
|
treeNodes,
|
|
2915
2895
|
!overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
|
|
@@ -2920,7 +2900,7 @@ function GenreTreeView({
|
|
|
2920
2900
|
setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
|
|
2921
2901
|
}
|
|
2922
2902
|
const handlePrevious = selectionHistory.previous ? () => selectGenre(selectionHistory.previous) : void 0;
|
|
2923
|
-
const { showPopup, hidePopup } = (0,
|
|
2903
|
+
const { showPopup, hidePopup } = (0, import_popup4.usePopup)();
|
|
2924
2904
|
const reopenPanel = () => {
|
|
2925
2905
|
setUncontrolledCollapsed(false);
|
|
2926
2906
|
onCollapsedChange?.(false);
|
|
@@ -2971,7 +2951,7 @@ function GenreTreeView({
|
|
|
2971
2951
|
onAddChild: readOnly || !criteria ? void 0 : () => handleGenreCreationAction(criteria),
|
|
2972
2952
|
onRename: readOnly || !criteria ? void 0 : () => handleGenreRenameAction(criteria),
|
|
2973
2953
|
onChangeParent: readOnly || !genrePlaylist || !criteria ? void 0 : () => showPopup(
|
|
2974
|
-
/* @__PURE__ */ (0,
|
|
2954
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
2975
2955
|
ChangeParentPopup,
|
|
2976
2956
|
{
|
|
2977
2957
|
genrePlaylist: { ...genrePlaylist, criteria },
|
|
@@ -3005,15 +2985,15 @@ function GenreTreeView({
|
|
|
3005
2985
|
const isRotationControlled = controlledAllowWheelRotation !== void 0;
|
|
3006
2986
|
const allowWheelRotation = controlledAllowWheelRotation ?? internalAllowWheelRotation;
|
|
3007
2987
|
let activePanel = null;
|
|
3008
|
-
if (
|
|
2988
|
+
if (otherPanel) {
|
|
3009
2989
|
activePanel = {
|
|
3010
|
-
title:
|
|
3011
|
-
content:
|
|
3012
|
-
aside:
|
|
3013
|
-
expanded:
|
|
3014
|
-
onExpandedChange:
|
|
3015
|
-
onClose:
|
|
3016
|
-
|
|
2990
|
+
title: otherPanel.title,
|
|
2991
|
+
content: otherPanel.content,
|
|
2992
|
+
aside: otherPanel.extraContent,
|
|
2993
|
+
expanded: otherPanel.expanded ?? false,
|
|
2994
|
+
onExpandedChange: otherPanel.onExpandedChange,
|
|
2995
|
+
onClose: otherPanel.onClose,
|
|
2996
|
+
searchName: otherPanel.title
|
|
3017
2997
|
};
|
|
3018
2998
|
} else if (selectedGenreUuid) {
|
|
3019
2999
|
activePanel = {
|
|
@@ -3023,38 +3003,28 @@ function GenreTreeView({
|
|
|
3023
3003
|
expanded: isExpanded,
|
|
3024
3004
|
onExpandedChange: changeExpanded,
|
|
3025
3005
|
onClose: clearSelection,
|
|
3026
|
-
|
|
3006
|
+
searchName: genreContent.name,
|
|
3027
3007
|
headerAccent: genreContent.headerAccent
|
|
3028
3008
|
};
|
|
3029
|
-
} else if (builtInPanel) {
|
|
3030
|
-
activePanel = {
|
|
3031
|
-
title: builtInPanel.title,
|
|
3032
|
-
content: builtInPanel.content,
|
|
3033
|
-
aside: builtInPanel.extraContent,
|
|
3034
|
-
expanded: builtInPanel.expanded,
|
|
3035
|
-
onExpandedChange: builtInPanel.onExpandedChange,
|
|
3036
|
-
onClose: builtInPanel.onClose,
|
|
3037
|
-
titleInSearch: true
|
|
3038
|
-
};
|
|
3039
3009
|
}
|
|
3040
3010
|
const isPanelShown = activePanel !== null && (selectedGenreUuid !== null || isTreeReady);
|
|
3041
3011
|
const detailTab = placement === "regions" && activePanel?.onExpandedChange ? {
|
|
3042
3012
|
edge: activePanel.expanded ? { label: "Shrink panel", onClick: () => activePanel.onExpandedChange?.(false) } : isCollapsed ? null : { label: "Hide panel", onClick: () => changeCollapsed(true) },
|
|
3043
3013
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
3044
3014
|
} : void 0;
|
|
3045
|
-
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0,
|
|
3015
|
+
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3046
3016
|
import_ui21.IconButton,
|
|
3047
3017
|
{
|
|
3048
3018
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
3049
3019
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
3050
3020
|
onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
|
|
3051
|
-
children: activePanel.expanded ? /* @__PURE__ */ (0,
|
|
3021
|
+
children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react15.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react15.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3052
3022
|
}
|
|
3053
3023
|
) : null;
|
|
3054
3024
|
const renderArtistFilter = () => {
|
|
3055
3025
|
if (isLoading || !filterArtist) return null;
|
|
3056
|
-
return /* @__PURE__ */ (0,
|
|
3057
|
-
/* @__PURE__ */ (0,
|
|
3026
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
3027
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3058
3028
|
"button",
|
|
3059
3029
|
{
|
|
3060
3030
|
type: "button",
|
|
@@ -3066,7 +3036,7 @@ function GenreTreeView({
|
|
|
3066
3036
|
children: filterArtist.name
|
|
3067
3037
|
}
|
|
3068
3038
|
),
|
|
3069
|
-
/* @__PURE__ */ (0,
|
|
3039
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3070
3040
|
"button",
|
|
3071
3041
|
{
|
|
3072
3042
|
type: "button",
|
|
@@ -3078,8 +3048,8 @@ function GenreTreeView({
|
|
|
3078
3048
|
)
|
|
3079
3049
|
] });
|
|
3080
3050
|
};
|
|
3081
|
-
const actions = /* @__PURE__ */ (0,
|
|
3082
|
-
!isLoading && !isError && /* @__PURE__ */ (0,
|
|
3051
|
+
const actions = /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
|
|
3052
|
+
!isLoading && !isError && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3083
3053
|
GenreTreeSearch,
|
|
3084
3054
|
{
|
|
3085
3055
|
artistBaseUrl,
|
|
@@ -3102,9 +3072,9 @@ function GenreTreeView({
|
|
|
3102
3072
|
if (songUuid) changeSong(null);
|
|
3103
3073
|
selectGenre(uuid);
|
|
3104
3074
|
},
|
|
3105
|
-
selectedName:
|
|
3075
|
+
selectedName: activePanel?.searchName ?? null,
|
|
3106
3076
|
onClear: activePanel?.onClose,
|
|
3107
|
-
showClear: activePanel
|
|
3077
|
+
showClear: activePanel !== null,
|
|
3108
3078
|
clearLabel: "Close panel",
|
|
3109
3079
|
onPrevious: handlePrevious,
|
|
3110
3080
|
onQueryChange: onSearchQueryChange,
|
|
@@ -3112,9 +3082,9 @@ function GenreTreeView({
|
|
|
3112
3082
|
extraGroups: extraSearchGroups
|
|
3113
3083
|
}
|
|
3114
3084
|
),
|
|
3115
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3116
|
-
/* @__PURE__ */ (0,
|
|
3117
|
-
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0,
|
|
3085
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3086
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "contents max-md:flex max-md:w-full max-md:items-center max-md:gap-2 max-md:overflow-x-auto max-md:[scrollbar-width:none] max-md:[&>*]:shrink-0", children: [
|
|
3087
|
+
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3118
3088
|
import_ui21.SegmentedControl,
|
|
3119
3089
|
{
|
|
3120
3090
|
"aria-label": "Tree view mode",
|
|
@@ -3128,13 +3098,13 @@ function GenreTreeView({
|
|
|
3128
3098
|
]
|
|
3129
3099
|
}
|
|
3130
3100
|
),
|
|
3131
|
-
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0,
|
|
3101
|
+
!isLoading && !isError && showDisplayOptions && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3132
3102
|
"div",
|
|
3133
3103
|
{
|
|
3134
3104
|
className: "flex items-center gap-1",
|
|
3135
3105
|
role: "group",
|
|
3136
3106
|
"aria-label": "Tree display options",
|
|
3137
|
-
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0,
|
|
3107
|
+
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3138
3108
|
import_ui21.Button,
|
|
3139
3109
|
{
|
|
3140
3110
|
variant: allowWheelRotation ? "default" : "outline",
|
|
@@ -3145,7 +3115,7 @@ function GenreTreeView({
|
|
|
3145
3115
|
)
|
|
3146
3116
|
}
|
|
3147
3117
|
),
|
|
3148
|
-
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0,
|
|
3118
|
+
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3149
3119
|
import_ui21.IconTextButton,
|
|
3150
3120
|
{
|
|
3151
3121
|
icon: import_lucide_react14.Plus,
|
|
@@ -3155,42 +3125,43 @@ function GenreTreeView({
|
|
|
3155
3125
|
)
|
|
3156
3126
|
] })
|
|
3157
3127
|
] });
|
|
3158
|
-
return /* @__PURE__ */ (0,
|
|
3128
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(
|
|
3159
3129
|
"div",
|
|
3160
3130
|
{
|
|
3161
3131
|
"data-left-panel": isPanelShown && !isCollapsed ? void 0 : "hidden",
|
|
3162
3132
|
className: ["genre-tree-view relative flex flex-col h-full", placement === "regions" && REGIONS_CLASS, className2].filter(Boolean).join(" "),
|
|
3163
3133
|
children: [
|
|
3164
|
-
/* @__PURE__ */ (0,
|
|
3134
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3165
3135
|
"div",
|
|
3166
3136
|
{
|
|
3167
3137
|
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"}`,
|
|
3168
3138
|
children: actions
|
|
3169
3139
|
}
|
|
3170
3140
|
),
|
|
3171
|
-
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0,
|
|
3141
|
+
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3172
3142
|
"div",
|
|
3173
3143
|
{
|
|
3174
3144
|
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"}`,
|
|
3175
3145
|
children: renderArtistFilter()
|
|
3176
3146
|
}
|
|
3177
3147
|
),
|
|
3178
|
-
/* @__PURE__ */ (0,
|
|
3179
|
-
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0,
|
|
3180
|
-
isLoading ? /* @__PURE__ */ (0,
|
|
3148
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "content-container flex-1 min-h-0 flex flex-row gap-4", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "tree-view-container relative flex-1 min-w-0 flex flex-col h-full", children: [
|
|
3149
|
+
!isLoading && !isError && viewMode === "outline" && floatingControlsLeading && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "absolute bottom-3 right-3 z-10", children: floatingControlsLeading }),
|
|
3150
|
+
isLoading ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_genre_tree_view5.GenreTreeViewSkeleton, { viewMode }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("p", { role: "alert", className: "m-auto text-center", children: [
|
|
3181
3151
|
"Couldn't load the genre tree.",
|
|
3182
3152
|
" ",
|
|
3183
|
-
/* @__PURE__ */ (0,
|
|
3153
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("button", { type: "button", className: "underline", onClick: refetch, children: "Retry" })
|
|
3184
3154
|
] }) : viewMode === "wheel" ? (
|
|
3185
3155
|
// The info panel's top edge aligns with the tree's; the search bar floats `--layout-panel-inset` below it,
|
|
3186
3156
|
// and the header inset (the bar's height plus that inset) extends the header's fill behind the bar,
|
|
3187
3157
|
// Google Maps style; the 8px bottom padding mirrors the inset above the bar, and the hidden title's height is zeroed.
|
|
3188
3158
|
// The panel's own Zoom in button is hidden: the search bar carries it.
|
|
3189
|
-
/* @__PURE__ */ (0,
|
|
3159
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3190
3160
|
GenrePlaylistTreeWheel,
|
|
3191
3161
|
{
|
|
3192
3162
|
scope,
|
|
3193
3163
|
genrePlaylists: visibleGenrePlaylists,
|
|
3164
|
+
focusUuids,
|
|
3194
3165
|
handleGenreCreationAction,
|
|
3195
3166
|
handleGenreRenameAction,
|
|
3196
3167
|
additionalActions,
|
|
@@ -3203,9 +3174,9 @@ function GenreTreeView({
|
|
|
3203
3174
|
allowWheelRotation,
|
|
3204
3175
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3205
3176
|
busy,
|
|
3206
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3177
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3207
3178
|
floatingControlsLeading,
|
|
3208
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3179
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3209
3180
|
] }) : void 0,
|
|
3210
3181
|
defaultViewport,
|
|
3211
3182
|
viewportRestore,
|
|
@@ -3214,11 +3185,12 @@ function GenreTreeView({
|
|
|
3214
3185
|
) }) })
|
|
3215
3186
|
) : viewMode === "pop-core" ? (
|
|
3216
3187
|
// Same as the wheel: the header inset extends its fill behind the floating search bar, Google Maps style.
|
|
3217
|
-
/* @__PURE__ */ (0,
|
|
3188
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "tree-container search-overlay relative flex-1 w-full min-h-0 ", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(GenreTreeWheelHandoff, { skeleton: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_genre_tree_view5.GenreTreeWheelSkeleton, {}), onRevealedChange: setIsWheelRevealed, children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3218
3189
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3219
3190
|
{
|
|
3220
3191
|
scope,
|
|
3221
3192
|
genrePlaylists: visibleGenrePlaylists,
|
|
3193
|
+
focusUuids,
|
|
3222
3194
|
handleGenreCreationAction,
|
|
3223
3195
|
handleGenreRenameAction,
|
|
3224
3196
|
additionalActions,
|
|
@@ -3231,9 +3203,9 @@ function GenreTreeView({
|
|
|
3231
3203
|
allowWheelRotation,
|
|
3232
3204
|
sizeMetric: isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric,
|
|
3233
3205
|
busy,
|
|
3234
|
-
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0,
|
|
3206
|
+
floatingControlsLeading: floatingControlsLeading || canSizeByViews ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)("div", { className: "flex items-center gap-2", children: [
|
|
3235
3207
|
floatingControlsLeading,
|
|
3236
|
-
canSizeByViews && /* @__PURE__ */ (0,
|
|
3208
|
+
canSizeByViews && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(SizeMetricToggle, { value: sizeMetric, onChange: changeSizeMetric })
|
|
3237
3209
|
] }) : void 0,
|
|
3238
3210
|
defaultViewport,
|
|
3239
3211
|
viewportRestore,
|
|
@@ -3241,12 +3213,13 @@ function GenreTreeView({
|
|
|
3241
3213
|
...focus
|
|
3242
3214
|
}
|
|
3243
3215
|
) }) })
|
|
3244
|
-
) : viewMode === "outline" ? /* @__PURE__ */ (0,
|
|
3216
|
+
) : viewMode === "outline" ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "tree-container flex-1 min-h-0 w-full overflow-y-auto relative", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3245
3217
|
GenrePlaylistTreeWheelRadialPopCore,
|
|
3246
3218
|
{
|
|
3247
3219
|
outline: true,
|
|
3248
3220
|
scope,
|
|
3249
3221
|
genrePlaylists: visibleGenrePlaylists,
|
|
3222
|
+
focusUuids,
|
|
3250
3223
|
handleGenreCreationAction,
|
|
3251
3224
|
handleGenreRenameAction,
|
|
3252
3225
|
additionalActions,
|
|
@@ -3257,13 +3230,13 @@ function GenreTreeView({
|
|
|
3257
3230
|
selectedNodeId,
|
|
3258
3231
|
readOnly
|
|
3259
3232
|
}
|
|
3260
|
-
) }) : /* @__PURE__ */ (0,
|
|
3233
|
+
) }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "tree-container relative flex flex-col gap-4 w-full pt-14 overflow-x-auto overflow-y-auto text-[var(--color-text)]", children: Object.entries(groupedGenrePlaylistsByRoot).map(
|
|
3261
3234
|
([uuid, genrePlaylistTreePerRoot]) => {
|
|
3262
|
-
return /* @__PURE__ */ (0,
|
|
3235
|
+
return /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3263
3236
|
"div",
|
|
3264
3237
|
{
|
|
3265
3238
|
className: "tree-per-root-container relative shrink-0 h-[28rem] mt-2 mr-16 p-2 bg-[var(--color-neutral-100)] rounded-lg",
|
|
3266
|
-
children: /* @__PURE__ */ (0,
|
|
3239
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)("div", { className: "graph-container relative z-10 h-full", children: /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3267
3240
|
GenrePlaylistTreePerRoot,
|
|
3268
3241
|
{
|
|
3269
3242
|
scope,
|
|
@@ -3276,6 +3249,7 @@ function GenreTreeView({
|
|
|
3276
3249
|
onNodeHover: handleNodeHover,
|
|
3277
3250
|
...hostPanel,
|
|
3278
3251
|
playback,
|
|
3252
|
+
focusUuids,
|
|
3279
3253
|
selectedNodeId: uuid === selectedGenrePlaylist?.root.uuid ? selectedNodeId : null,
|
|
3280
3254
|
readOnly,
|
|
3281
3255
|
wheelZoom: "modifier",
|
|
@@ -3289,13 +3263,13 @@ function GenreTreeView({
|
|
|
3289
3263
|
);
|
|
3290
3264
|
}
|
|
3291
3265
|
) }),
|
|
3292
|
-
/* @__PURE__ */ (0,
|
|
3266
|
+
/* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
|
|
3293
3267
|
import_ui21.DetailPanel,
|
|
3294
3268
|
{
|
|
3295
3269
|
ref: panelRef,
|
|
3296
3270
|
side: "left",
|
|
3297
3271
|
title: activePanel?.title ?? "",
|
|
3298
|
-
titleInSearch:
|
|
3272
|
+
titleInSearch: !isLoading && !isError,
|
|
3299
3273
|
headerAccent: activePanel?.headerAccent,
|
|
3300
3274
|
headerActions: expandButton,
|
|
3301
3275
|
onClose: activePanel?.onClose ?? noop,
|
|
@@ -3304,8 +3278,7 @@ function GenreTreeView({
|
|
|
3304
3278
|
onExpandedChange: activePanel?.onExpandedChange,
|
|
3305
3279
|
aside: activePanel?.aside,
|
|
3306
3280
|
edgeTab: detailTab,
|
|
3307
|
-
|
|
3308
|
-
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)(import_jsx_runtime44.Fragment, { children: [
|
|
3281
|
+
children: activePanel?.aside && !activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime45.jsxs)(import_jsx_runtime45.Fragment, { children: [
|
|
3309
3282
|
activePanel.content,
|
|
3310
3283
|
activePanel.aside
|
|
3311
3284
|
] }) : activePanel?.content
|
|
@@ -3326,7 +3299,7 @@ var import_lucide_react16 = require("lucide-react");
|
|
|
3326
3299
|
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3327
3300
|
var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3328
3301
|
var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
|
|
3329
|
-
var
|
|
3302
|
+
var import_jsx_runtime46 = require("react/jsx-runtime");
|
|
3330
3303
|
var useBrowserLayoutEffect = typeof window === "undefined" ? import_react20.useEffect : import_react20.useLayoutEffect;
|
|
3331
3304
|
function TrackListSidebar({
|
|
3332
3305
|
className: className2 = "",
|
|
@@ -3428,25 +3401,25 @@ function TrackListSidebar({
|
|
|
3428
3401
|
}
|
|
3429
3402
|
};
|
|
3430
3403
|
const positionClasses = layout === "inline" ? "relative w-full flex h-full flex-col" : "fixed right-0 w-[50rem] flex flex-col";
|
|
3431
|
-
return trackList ? /* @__PURE__ */ (0,
|
|
3404
|
+
return trackList ? /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
3432
3405
|
"div",
|
|
3433
3406
|
{
|
|
3434
3407
|
"data-theme": "dark",
|
|
3435
3408
|
className: `track-list-sidebar ${positionClasses} rounded-2xl bg-[var(--color-surface)] pb-1 ${className2}`,
|
|
3436
3409
|
style: layout === "fixed" ? { top: "63.5px", maxHeight: "calc(100vh - 63.5px - 79px)" } : void 0,
|
|
3437
3410
|
children: [
|
|
3438
|
-
/* @__PURE__ */ (0,
|
|
3439
|
-
/* @__PURE__ */ (0,
|
|
3440
|
-
/* @__PURE__ */ (0,
|
|
3441
|
-
/* @__PURE__ */ (0,
|
|
3442
|
-
/* @__PURE__ */ (0,
|
|
3411
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "header flex h-16 items-center px-4 py-2 text-[var(--color-text)]", children: [
|
|
3412
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "min-w-0 flex flex-1 flex-col justify-center", children: [
|
|
3413
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "origin flex text-xl", children: [
|
|
3414
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3415
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "name-container flex flex-col justify-center items-center text-[var(--color-text)] font-bold pr-2 max-w-[27.5rem]", children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3443
3416
|
] }),
|
|
3444
|
-
/* @__PURE__ */ (0,
|
|
3417
|
+
/* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3445
3418
|
trackList.origin.type === import_genre_tree32.TrackListOriginType.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === import_genre_tree32.TrackListOriginType.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
|
|
3446
3419
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3447
3420
|
] })
|
|
3448
3421
|
] }),
|
|
3449
|
-
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0,
|
|
3422
|
+
(isCollapsed && onExpand || !isCollapsed && onMinimize) && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3450
3423
|
"button",
|
|
3451
3424
|
{
|
|
3452
3425
|
type: "button",
|
|
@@ -3455,11 +3428,11 @@ function TrackListSidebar({
|
|
|
3455
3428
|
"aria-expanded": !isCollapsed,
|
|
3456
3429
|
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"}`,
|
|
3457
3430
|
onClick: isCollapsed ? onExpand : onMinimize,
|
|
3458
|
-
children: /* @__PURE__ */ (0,
|
|
3431
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react16.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
|
|
3459
3432
|
}
|
|
3460
3433
|
)
|
|
3461
3434
|
] }),
|
|
3462
|
-
!isCollapsed && /* @__PURE__ */ (0,
|
|
3435
|
+
!isCollapsed && /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)(
|
|
3463
3436
|
"ul",
|
|
3464
3437
|
{
|
|
3465
3438
|
ref: trackListRef,
|
|
@@ -3469,7 +3442,7 @@ function TrackListSidebar({
|
|
|
3469
3442
|
onPointerDown: markUserScrollIntent,
|
|
3470
3443
|
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",
|
|
3471
3444
|
children: [
|
|
3472
|
-
trackList.tracks.map((track, index) => /* @__PURE__ */ (0,
|
|
3445
|
+
trackList.tracks.map((track, index) => /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("li", { "data-track-uuid": track.uuid, children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3473
3446
|
TrackItem,
|
|
3474
3447
|
{
|
|
3475
3448
|
track,
|
|
@@ -3480,7 +3453,7 @@ function TrackListSidebar({
|
|
|
3480
3453
|
renderSongLink
|
|
3481
3454
|
}
|
|
3482
3455
|
) }, track.uuid)),
|
|
3483
|
-
hasMore && /* @__PURE__ */ (0,
|
|
3456
|
+
hasMore && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("li", { ref: loadMoreSentinelRef, "aria-hidden": "true", className: "h-px" })
|
|
3484
3457
|
]
|
|
3485
3458
|
}
|
|
3486
3459
|
)
|
|
@@ -3500,7 +3473,7 @@ var import_ui22 = require("@behindthemusictree/ui");
|
|
|
3500
3473
|
var import_lucide_react17 = require("lucide-react");
|
|
3501
3474
|
var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3502
3475
|
var import_player13 = require("@behindthemusictree/app-kit/player");
|
|
3503
|
-
var
|
|
3476
|
+
var import_jsx_runtime47 = require("react/jsx-runtime");
|
|
3504
3477
|
function PlayerControls() {
|
|
3505
3478
|
const {
|
|
3506
3479
|
duration,
|
|
@@ -3519,15 +3492,15 @@ function PlayerControls() {
|
|
|
3519
3492
|
const safeDuration = Number.isFinite(duration) && duration > 0 ? duration : 0;
|
|
3520
3493
|
const safeCurrentTime = Number.isFinite(currentTime) ? Math.max(0, Math.min(currentTime, safeDuration)) : 0;
|
|
3521
3494
|
const isPlaying = playState === import_player13.PlayStates.PLAYING;
|
|
3522
|
-
return /* @__PURE__ */ (0,
|
|
3495
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(
|
|
3523
3496
|
"section",
|
|
3524
3497
|
{
|
|
3525
3498
|
"aria-label": "Player controls",
|
|
3526
3499
|
className: "player-controls flex shrink-0 flex-col gap-2 border-b border-zinc-800 px-3 py-2 text-zinc-200",
|
|
3527
3500
|
children: [
|
|
3528
|
-
/* @__PURE__ */ (0,
|
|
3529
|
-
/* @__PURE__ */ (0,
|
|
3530
|
-
/* @__PURE__ */ (0,
|
|
3501
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "flex min-w-0 items-center gap-2 text-xs tabular-nums text-zinc-400", children: [
|
|
3502
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-label": "Elapsed time", children: (0, import_genre_tree33.formatTime)(safeCurrentTime) }),
|
|
3503
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3531
3504
|
"input",
|
|
3532
3505
|
{
|
|
3533
3506
|
"aria-label": "Seek",
|
|
@@ -3541,11 +3514,11 @@ function PlayerControls() {
|
|
|
3541
3514
|
onChange: (event) => seekTo(Number(event.currentTarget.value))
|
|
3542
3515
|
}
|
|
3543
3516
|
),
|
|
3544
|
-
/* @__PURE__ */ (0,
|
|
3517
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { "aria-label": "Duration", children: (0, import_genre_tree33.formatTime)(safeDuration) })
|
|
3545
3518
|
] }),
|
|
3546
|
-
/* @__PURE__ */ (0,
|
|
3547
|
-
/* @__PURE__ */ (0,
|
|
3548
|
-
/* @__PURE__ */ (0,
|
|
3519
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "grid min-h-9 grid-cols-[1fr_auto_1fr] items-center gap-3", children: [
|
|
3520
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "col-start-2 flex items-center justify-center gap-2", children: [
|
|
3521
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3549
3522
|
"button",
|
|
3550
3523
|
{
|
|
3551
3524
|
type: "button",
|
|
@@ -3554,10 +3527,10 @@ function PlayerControls() {
|
|
|
3554
3527
|
disabled: !isReady || !hasPreviousTrack,
|
|
3555
3528
|
onClick: playPreviousTrack,
|
|
3556
3529
|
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",
|
|
3557
|
-
children: /* @__PURE__ */ (0,
|
|
3530
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3558
3531
|
}
|
|
3559
3532
|
),
|
|
3560
|
-
/* @__PURE__ */ (0,
|
|
3533
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3561
3534
|
"button",
|
|
3562
3535
|
{
|
|
3563
3536
|
type: "button",
|
|
@@ -3566,10 +3539,10 @@ function PlayerControls() {
|
|
|
3566
3539
|
disabled: !isReady,
|
|
3567
3540
|
onClick: handlePlayPauseAction,
|
|
3568
3541
|
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",
|
|
3569
|
-
children: isPlaying ? /* @__PURE__ */ (0,
|
|
3542
|
+
children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
|
|
3570
3543
|
}
|
|
3571
3544
|
),
|
|
3572
|
-
/* @__PURE__ */ (0,
|
|
3545
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3573
3546
|
"button",
|
|
3574
3547
|
{
|
|
3575
3548
|
type: "button",
|
|
@@ -3578,14 +3551,14 @@ function PlayerControls() {
|
|
|
3578
3551
|
disabled: !isReady || !hasNextTrack,
|
|
3579
3552
|
onClick: playNextTrack,
|
|
3580
3553
|
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",
|
|
3581
|
-
children: /* @__PURE__ */ (0,
|
|
3554
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
|
|
3582
3555
|
}
|
|
3583
3556
|
)
|
|
3584
3557
|
] }),
|
|
3585
|
-
/* @__PURE__ */ (0,
|
|
3586
|
-
volume === 0 ? /* @__PURE__ */ (0,
|
|
3587
|
-
/* @__PURE__ */ (0,
|
|
3588
|
-
/* @__PURE__ */ (0,
|
|
3558
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("label", { className: "col-start-3 flex w-[4.2rem] shrink-0 items-center gap-[0.35rem] justify-self-end text-zinc-400 sm:w-[4.9rem]", children: [
|
|
3559
|
+
volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
|
|
3560
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "sr-only", children: "Volume" }),
|
|
3561
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
3589
3562
|
"input",
|
|
3590
3563
|
{
|
|
3591
3564
|
"aria-label": "Volume",
|
|
@@ -3607,7 +3580,7 @@ function PlayerControls() {
|
|
|
3607
3580
|
}
|
|
3608
3581
|
|
|
3609
3582
|
// src/genre-tree/PlayerPanel.tsx
|
|
3610
|
-
var
|
|
3583
|
+
var import_jsx_runtime48 = require("react/jsx-runtime");
|
|
3611
3584
|
var PANEL_ID = "player-panel";
|
|
3612
3585
|
var DEFAULT_EXTENDED_WIDTH = "calc(100vw - var(--layout-center-left) - var(--layout-gutter))";
|
|
3613
3586
|
function PlayerPanel({
|
|
@@ -3647,7 +3620,7 @@ function PlayerPanel({
|
|
|
3647
3620
|
onClick: () => setIsExtendRequested(true),
|
|
3648
3621
|
expanded: false
|
|
3649
3622
|
} : null;
|
|
3650
|
-
return /* @__PURE__ */ (0,
|
|
3623
|
+
return /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3651
3624
|
"div",
|
|
3652
3625
|
{
|
|
3653
3626
|
id: PANEL_ID,
|
|
@@ -3660,7 +3633,7 @@ function PlayerPanel({
|
|
|
3660
3633
|
),
|
|
3661
3634
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3662
3635
|
children: [
|
|
3663
|
-
/* @__PURE__ */ (0,
|
|
3636
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3664
3637
|
import_ui22.PanelEdgeTab,
|
|
3665
3638
|
{
|
|
3666
3639
|
side: "right",
|
|
@@ -3670,7 +3643,7 @@ function PlayerPanel({
|
|
|
3670
3643
|
className: "absolute right-full top-1/2 -translate-y-1/2"
|
|
3671
3644
|
}
|
|
3672
3645
|
),
|
|
3673
|
-
/* @__PURE__ */ (0,
|
|
3646
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)(
|
|
3674
3647
|
"div",
|
|
3675
3648
|
{
|
|
3676
3649
|
className: (0, import_tailwind_merge.twMerge)(
|
|
@@ -3678,20 +3651,20 @@ function PlayerPanel({
|
|
|
3678
3651
|
isExtended ? "flex-row" : "flex-col"
|
|
3679
3652
|
),
|
|
3680
3653
|
children: [
|
|
3681
|
-
/* @__PURE__ */ (0,
|
|
3682
|
-
/* @__PURE__ */ (0,
|
|
3683
|
-
/* @__PURE__ */ (0,
|
|
3684
|
-
/* @__PURE__ */ (0,
|
|
3685
|
-
playerTrackObject?.loadError && /* @__PURE__ */ (0,
|
|
3654
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3655
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: /* @__PURE__ */ (0, import_jsx_runtime48.jsx)("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }) }),
|
|
3656
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
3657
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
3658
|
+
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
3686
3659
|
playerTrackObject.loadError,
|
|
3687
|
-
/* @__PURE__ */ (0,
|
|
3660
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)("button", { type: "button", className: "ml-2 underline", onClick: () => {
|
|
3688
3661
|
void retryPlayback();
|
|
3689
3662
|
}, children: "Retry" })
|
|
3690
3663
|
] })
|
|
3691
3664
|
] }),
|
|
3692
|
-
/* @__PURE__ */ (0,
|
|
3665
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(PlayerControls, {})
|
|
3693
3666
|
] }),
|
|
3694
|
-
/* @__PURE__ */ (0,
|
|
3667
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
3695
3668
|
TrackListSidebar,
|
|
3696
3669
|
{
|
|
3697
3670
|
layout: "inline",
|
|
@@ -3718,11 +3691,11 @@ function PlayerPanel({
|
|
|
3718
3691
|
var import_uuid = require("uuid");
|
|
3719
3692
|
var import_ai = require("react-icons/ai");
|
|
3720
3693
|
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3721
|
-
var
|
|
3694
|
+
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
3722
3695
|
function Rating({ rating, handleChange }) {
|
|
3723
3696
|
const instanceId = (0, import_uuid.v4)();
|
|
3724
|
-
return /* @__PURE__ */ (0,
|
|
3725
|
-
/* @__PURE__ */ (0,
|
|
3697
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "flex items-center", children: [...Array(6)].map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: `relative ${i === 0 ? "mr-4" : "mr-1"}`, children: [
|
|
3698
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3726
3699
|
"input",
|
|
3727
3700
|
{
|
|
3728
3701
|
id: `star-${instanceId}-${i}`,
|
|
@@ -3734,16 +3707,16 @@ function Rating({ rating, handleChange }) {
|
|
|
3734
3707
|
onChange: handleChange
|
|
3735
3708
|
}
|
|
3736
3709
|
),
|
|
3737
|
-
/* @__PURE__ */ (0,
|
|
3738
|
-
/* @__PURE__ */ (0,
|
|
3710
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("label", { htmlFor: `star-${instanceId}-${i}`, className: "cursor-pointer", children: i === 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("div", { className: "flex", children: [
|
|
3711
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3739
3712
|
import_ai.AiOutlineStar,
|
|
3740
3713
|
{
|
|
3741
3714
|
className: `w-7 h-7 absolute top-0 left-0 ${rating === import_genre_tree35.FORM_RATING_NULL_VALUE ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
3742
3715
|
}
|
|
3743
3716
|
),
|
|
3744
|
-
/* @__PURE__ */ (0,
|
|
3717
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex-grow w-8" }),
|
|
3745
3718
|
" "
|
|
3746
|
-
] }) : /* @__PURE__ */ (0,
|
|
3719
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
3747
3720
|
import_ai.AiFillStar,
|
|
3748
3721
|
{
|
|
3749
3722
|
className: `w-7 h-7 absolute top-0 left-0 ${(rating ?? -1) >= i ? "text-[var(--color-accent-rating)]" : "text-[var(--color-text-muted)]"}`
|
|
@@ -3755,7 +3728,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3755
3728
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
3756
3729
|
var import_react22 = require("react");
|
|
3757
3730
|
var import_ui23 = require("@behindthemusictree/ui");
|
|
3758
|
-
var
|
|
3731
|
+
var import_jsx_runtime50 = require("react/jsx-runtime");
|
|
3759
3732
|
function EntityDetailPanel({
|
|
3760
3733
|
scope,
|
|
3761
3734
|
getBackendBaseUrl,
|
|
@@ -3778,8 +3751,8 @@ function EntityDetailPanel({
|
|
|
3778
3751
|
getBackendBaseUrl,
|
|
3779
3752
|
getArtistBackendBaseUrl,
|
|
3780
3753
|
getShareUrl,
|
|
3781
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0,
|
|
3782
|
-
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0,
|
|
3754
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
3755
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime50.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
3783
3756
|
song: {
|
|
3784
3757
|
uuid: songUuid,
|
|
3785
3758
|
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
@@ -3795,7 +3768,7 @@ function EntityDetailPanel({
|
|
|
3795
3768
|
...navigation
|
|
3796
3769
|
});
|
|
3797
3770
|
if (!panel) return null;
|
|
3798
|
-
return /* @__PURE__ */ (0,
|
|
3771
|
+
return /* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
3799
3772
|
import_ui23.DetailPanel,
|
|
3800
3773
|
{
|
|
3801
3774
|
side: "left",
|
|
@@ -3807,7 +3780,7 @@ function EntityDetailPanel({
|
|
|
3807
3780
|
onExpandedChange: panel.onExpandedChange,
|
|
3808
3781
|
aside: panel.extraContent,
|
|
3809
3782
|
edgeTab,
|
|
3810
|
-
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0,
|
|
3783
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)(import_jsx_runtime50.Fragment, { children: [
|
|
3811
3784
|
panel.content,
|
|
3812
3785
|
panel.extraContent
|
|
3813
3786
|
] }) : panel.content
|