@behindthemusictree/app-kit-ui 37.0.0 → 37.1.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.
@@ -2192,15 +2192,8 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
2192
2192
  }
2193
2193
  );
2194
2194
  }
2195
- function SongPanelContent({
2196
- song,
2197
- scope,
2198
- getBackendBaseUrl,
2199
- shareUrl,
2200
- renderArtistLink,
2201
- genrePath,
2202
- onSelectGenre
2203
- }) {
2195
+ function SongPanelContent(props) {
2196
+ const { song, scope, getBackendBaseUrl, shareUrl, renderArtistLink } = props;
2204
2197
  const { playNewTrackListFromTrackUuid } = useTrackList5();
2205
2198
  const { playerTrackObject, playState, handlePlayPauseAction } = usePlayer9();
2206
2199
  const unplayableReason = songUnplayableReason4(song);
@@ -2210,12 +2203,14 @@ function SongPanelContent({
2210
2203
  const musicBrainzUrl = musicBrainzRecordingUrl2(song);
2211
2204
  const fields = [];
2212
2205
  if (song.genre) {
2213
- const path = genrePath.length > 0 ? genrePath : null;
2206
+ const path = props.genrePath && props.genrePath.length > 0 ? props.genrePath : null;
2207
+ const { onSelectGenre } = props;
2208
+ const genre = song.genre;
2214
2209
  fields.push({
2215
2210
  label: "Genre",
2216
- value: path ? /* @__PURE__ */ jsx31("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ jsxs24("span", { children: [
2211
+ value: onSelectGenre ? /* @__PURE__ */ jsx31("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ jsx31("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ jsxs24("span", { children: [
2217
2212
  index > 0 && /* @__PURE__ */ jsx31("span", { "aria-hidden": "true", children: "\u203A " }),
2218
- /* @__PURE__ */ jsx31("button", { type: "button", onClick: () => onSelectGenre(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
2213
+ /* @__PURE__ */ jsx31("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
2219
2214
  ] }, genrePlaylist.uuid)) }) : song.genre.name
2220
2215
  });
2221
2216
  } else {
@@ -2281,11 +2276,10 @@ function useSongPanel({
2281
2276
  getBackendBaseUrl,
2282
2277
  getShareUrl,
2283
2278
  renderArtistLink,
2284
- getGenrePath,
2285
- onSelectGenre,
2286
2279
  expanded,
2287
2280
  onExpandedChange,
2288
- onClose
2281
+ onClose,
2282
+ ...navigation
2289
2283
  }) {
2290
2284
  const result = useSong(uuid, getBackendBaseUrl);
2291
2285
  const panel = { expanded, onExpandedChange, onClose };
@@ -2329,8 +2323,10 @@ function useSongPanel({
2329
2323
  getBackendBaseUrl,
2330
2324
  shareUrl: shareUrl ?? void 0,
2331
2325
  renderArtistLink,
2332
- genrePath: song.genre ? getGenrePath(song.genre) : [],
2333
- onSelectGenre
2326
+ ...navigation.getGenrePath ? {
2327
+ genrePath: song.genre ? navigation.getGenrePath(song.genre) : [],
2328
+ onSelectGenrePlaylist: navigation.onSelectGenrePlaylist
2329
+ } : { onSelectGenre: navigation.onSelectGenre }
2334
2330
  }
2335
2331
  )
2336
2332
  };
@@ -2338,6 +2334,37 @@ function useSongPanel({
2338
2334
  }
2339
2335
  }
2340
2336
 
2337
+ // src/genre-tree/useEntityPanel.tsx
2338
+ function useEntityPanel({
2339
+ scope,
2340
+ getBackendBaseUrl,
2341
+ getArtistBackendBaseUrl,
2342
+ getShareUrl,
2343
+ renderArtistLink,
2344
+ renderSongLink,
2345
+ song,
2346
+ artist,
2347
+ ...navigation
2348
+ }) {
2349
+ const songPanel = useSongPanel({
2350
+ ...song,
2351
+ scope,
2352
+ getBackendBaseUrl,
2353
+ getShareUrl,
2354
+ renderArtistLink,
2355
+ ...navigation
2356
+ });
2357
+ const artistPanel = useArtistPanel({
2358
+ ...artist,
2359
+ scope,
2360
+ getBackendBaseUrl: getArtistBackendBaseUrl ?? getBackendBaseUrl,
2361
+ getShareUrl,
2362
+ renderArtistLink,
2363
+ renderSongLink
2364
+ });
2365
+ return songPanel ?? artistPanel;
2366
+ }
2367
+
2341
2368
  // src/genre-tree/SizeMetricToggle.tsx
2342
2369
  import { MdMusicNote, MdVisibility } from "react-icons/md";
2343
2370
  import { SegmentedControl } from "@behindthemusictree/ui";
@@ -2520,20 +2547,6 @@ function GenreTreeView({
2520
2547
  const [expandedArtistUuid, setExpandedArtistUuid] = useState9(null);
2521
2548
  const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
2522
2549
  const songBaseUrl = getBackendBaseUrl;
2523
- const artistPanel = useArtistPanel({
2524
- uuid: artistUuid,
2525
- scope,
2526
- getBackendBaseUrl: artistBaseUrl,
2527
- getShareUrl: getShareUrlRef.current,
2528
- renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ jsx34("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name })),
2529
- expanded: controlledArtistExpanded ?? (artistUuid !== null && expandedArtistUuid === artistUuid),
2530
- onExpandedChange: (on) => {
2531
- if (controlledArtistExpanded === void 0) setExpandedArtistUuid(on ? artistUuid : null);
2532
- onArtistExpandedChange?.(on);
2533
- },
2534
- renderSongLink: resolvedRenderSongLink,
2535
- onClose: () => changeArtist(null)
2536
- });
2537
2550
  const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ jsx34("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
2538
2551
  const getGenrePath = (genre) => {
2539
2552
  const path = [];
@@ -2545,27 +2558,38 @@ function GenreTreeView({
2545
2558
  }
2546
2559
  return path;
2547
2560
  };
2548
- const songPanel = useSongPanel({
2549
- uuid: songUuid,
2561
+ const entityPanel = useEntityPanel({
2550
2562
  scope,
2551
2563
  getBackendBaseUrl: songBaseUrl,
2564
+ getArtistBackendBaseUrl: artistBaseUrl,
2552
2565
  getShareUrl: getShareUrlRef.current,
2553
2566
  renderArtistLink: resolvedRenderArtistLink,
2567
+ renderSongLink: resolvedRenderSongLink,
2568
+ song: {
2569
+ uuid: songUuid,
2570
+ expanded: controlledSongExpanded ?? (songUuid !== null && expandedSongUuid === songUuid),
2571
+ onExpandedChange: (on) => {
2572
+ if (controlledSongExpanded === void 0) setExpandedSongUuid(on ? songUuid : null);
2573
+ onSongExpandedChange?.(on);
2574
+ },
2575
+ onClose: () => changeSong(null)
2576
+ },
2577
+ artist: {
2578
+ uuid: artistUuid,
2579
+ expanded: controlledArtistExpanded ?? (artistUuid !== null && expandedArtistUuid === artistUuid),
2580
+ onExpandedChange: (on) => {
2581
+ if (controlledArtistExpanded === void 0) setExpandedArtistUuid(on ? artistUuid : null);
2582
+ onArtistExpandedChange?.(on);
2583
+ },
2584
+ onClose: () => changeArtist(null)
2585
+ },
2554
2586
  getGenrePath,
2555
- onSelectGenre: (genrePlaylist2) => {
2587
+ onSelectGenrePlaylist: (genrePlaylist2) => {
2556
2588
  changeSong(null);
2557
2589
  selectGenrePlaylist(genrePlaylist2);
2558
- },
2559
- expanded: controlledSongExpanded ?? (songUuid !== null && expandedSongUuid === songUuid),
2560
- onExpandedChange: (on) => {
2561
- if (controlledSongExpanded === void 0) setExpandedSongUuid(on ? songUuid : null);
2562
- onSongExpandedChange?.(on);
2563
- },
2564
- onClose: () => changeSong(null)
2590
+ }
2565
2591
  });
2566
- const builtInSongPanel = overlayPanel || selectedGenreUuid !== null ? void 0 : songPanel;
2567
- const builtInArtistPanel = overlayPanel || selectedGenreUuid !== null || builtInSongPanel ? void 0 : artistPanel;
2568
- const builtInPanel = builtInSongPanel ?? builtInArtistPanel;
2592
+ const builtInPanel = overlayPanel || selectedGenreUuid !== null ? void 0 : entityPanel;
2569
2593
  const [uncontrolledCollapsed, setUncontrolledCollapsed] = useState9(false);
2570
2594
  const [uncontrolledExpanded, setUncontrolledExpanded] = useState9(false);
2571
2595
  const isCollapsed = collapsed ?? uncontrolledCollapsed;
@@ -3445,6 +3469,69 @@ function Rating({ rating, handleChange }) {
3445
3469
  ] }, i)) });
3446
3470
  }
3447
3471
 
3472
+ // src/genre-tree/EntityDetailPanel.tsx
3473
+ import { useState as useState11 } from "react";
3474
+ import { DetailPanel as DetailPanel3 } from "@behindthemusictree/ui";
3475
+ import { Fragment as Fragment15, jsx as jsx39, jsxs as jsxs31 } from "react/jsx-runtime";
3476
+ function EntityDetailPanel({
3477
+ scope,
3478
+ getBackendBaseUrl,
3479
+ getArtistBackendBaseUrl,
3480
+ getShareUrl,
3481
+ songUuid,
3482
+ onSongUuidChange,
3483
+ artistUuid,
3484
+ onArtistUuidChange,
3485
+ renderArtistLink,
3486
+ renderSongLink,
3487
+ collapsed,
3488
+ edgeTab,
3489
+ ...navigation
3490
+ }) {
3491
+ const [expandedSongUuid, setExpandedSongUuid] = useState11(null);
3492
+ const [expandedArtistUuid, setExpandedArtistUuid] = useState11(null);
3493
+ const panel = useEntityPanel({
3494
+ scope,
3495
+ getBackendBaseUrl,
3496
+ getArtistBackendBaseUrl,
3497
+ getShareUrl,
3498
+ renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ jsx39("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
3499
+ renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ jsx39("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
3500
+ song: {
3501
+ uuid: songUuid,
3502
+ expanded: songUuid !== null && expandedSongUuid === songUuid,
3503
+ onExpandedChange: (on) => setExpandedSongUuid(on ? songUuid : null),
3504
+ onClose: () => onSongUuidChange(null)
3505
+ },
3506
+ artist: {
3507
+ uuid: artistUuid,
3508
+ expanded: artistUuid !== null && expandedArtistUuid === artistUuid,
3509
+ onExpandedChange: (on) => setExpandedArtistUuid(on ? artistUuid : null),
3510
+ onClose: () => onArtistUuidChange(null)
3511
+ },
3512
+ ...navigation
3513
+ });
3514
+ if (!panel) return null;
3515
+ return /* @__PURE__ */ jsx39(
3516
+ DetailPanel3,
3517
+ {
3518
+ side: "left",
3519
+ title: panel.title,
3520
+ titleInSearch: true,
3521
+ onClose: panel.onClose,
3522
+ collapsed,
3523
+ expanded: panel.expanded,
3524
+ onExpandedChange: panel.onExpandedChange,
3525
+ aside: panel.extraContent,
3526
+ edgeTab,
3527
+ children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ jsxs31(Fragment15, { children: [
3528
+ panel.content,
3529
+ panel.extraContent
3530
+ ] }) : panel.content
3531
+ }
3532
+ );
3533
+ }
3534
+
3448
3535
  export {
3449
3536
  useGenrePlaylistPlayback,
3450
3537
  GenrePlaylistTreePerRoot,
@@ -3460,13 +3547,15 @@ export {
3460
3547
  GenreDetailPanel,
3461
3548
  TrackPositionPlayPause,
3462
3549
  TrackItem,
3550
+ useEntityPanel,
3463
3551
  GenreTreeView,
3464
3552
  TrackListSidebar,
3465
3553
  PlayerPanel,
3466
3554
  Rating,
3555
+ EntityDetailPanel,
3467
3556
  GenreTreeSkeleton,
3468
3557
  GenreTreeWheelSkeleton2 as GenreTreeWheelSkeleton,
3469
3558
  GenreTreeViewSkeleton2 as GenreTreeViewSkeleton,
3470
3559
  GenreTreeOutlineSkeleton
3471
3560
  };
3472
- //# sourceMappingURL=chunk-FTYMRCJS.js.map
3561
+ //# sourceMappingURL=chunk-57OI426Y.js.map