@behindthemusictree/app-kit-ui 40.0.0 → 40.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.
@@ -50,8 +50,8 @@ module.exports = __toCommonJS(genre_tree_exports);
50
50
  // src/genre-tree/GenreTreeView.tsx
51
51
  var import_react19 = require("react");
52
52
  var import_react_query3 = require("@tanstack/react-query");
53
+ var import_lucide_react13 = require("lucide-react");
53
54
  var import_lucide_react14 = require("lucide-react");
54
- 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");
@@ -85,6 +85,21 @@ function toTreeNodes(genrePlaylists, sizeMetric, focusUuids) {
85
85
  }));
86
86
  }
87
87
 
88
+ // src/genre-tree/playlist-tree/toGenreNodeStyles.ts
89
+ function toGenreNodeStyles(relations, genrePlaylists) {
90
+ const styles = /* @__PURE__ */ new Map();
91
+ if (!relations) return styles;
92
+ const genreUuidByPlaylistUuid = new Map(
93
+ genrePlaylists.flatMap((genrePlaylist) => genrePlaylist.criteria ? [[genrePlaylist.uuid, genrePlaylist.criteria.uuid]] : [])
94
+ );
95
+ const drawn = [relations, relations.parentNode, ...relations.childNodes, ...relations.ancestorNodes];
96
+ for (const entry of drawn) {
97
+ const genreUuid = entry && genreUuidByPlaylistUuid.get(entry.node.id);
98
+ if (entry && genreUuid) styles.set(genreUuid, { fill: entry.fill, textColor: entry.textColor });
99
+ }
100
+ return styles;
101
+ }
102
+
88
103
  // src/genre-tree/playlist-tree/TreePerRoot.tsx
89
104
  var import_genre_tree3 = require("@behindthemusictree/app-kit/genre-tree");
90
105
  var import_react3 = require("react");
@@ -1745,7 +1760,7 @@ function useGenreDetailContent({
1745
1760
  trailing,
1746
1761
  genrePlaylist: hostPlaylist,
1747
1762
  expanded,
1748
- treeRelations
1763
+ treeStyles
1749
1764
  }) {
1750
1765
  const { data: detail, isPending, isError } = (0, import_genre_tree20.useFetchGenreDetail)(genreUuid, scope, getBackendBaseUrl);
1751
1766
  const defaultPlayback = useGenrePlaylistPlayback({ scope, genrePlaylists: [], artist: extras?.artist });
@@ -1753,19 +1768,12 @@ function useGenreDetailContent({
1753
1768
  const view = (0, import_react15.useMemo)(() => {
1754
1769
  if (!detail) return null;
1755
1770
  const rootColor = (0, import_genre_tree_view4.getGenreTreeColor)(detail.root.wikidataId);
1756
- const treeStyles = /* @__PURE__ */ new Map();
1757
- if (treeRelations) {
1758
- const drawn = [treeRelations, treeRelations.parentNode, ...treeRelations.childNodes, ...treeRelations.ancestorNodes];
1759
- for (const entry of drawn) {
1760
- if (entry) treeStyles.set(entry.node.id, { fill: entry.fill, textColor: entry.textColor });
1761
- }
1762
- }
1763
1771
  const relative = (genre, parentId) => ({
1764
1772
  node: toNode(genre, parentId),
1765
- ...treeStyles.get(genre.uuid) ?? { fill: (0, import_genre_tree_view4.tintSurface)(rootColor), textColor: import_genre_tree_view4.TEXT_COLOR }
1773
+ ...treeStyles?.get(genre.uuid) ?? { fill: (0, import_genre_tree_view4.tintSurface)(rootColor), textColor: import_genre_tree_view4.TEXT_COLOR }
1766
1774
  });
1767
1775
  const ancestors2 = [...detail.ascendants].sort((a, b) => b.degree - a.degree);
1768
- const own = treeStyles.get(detail.uuid) ?? { fill: rootColor, textColor: (0, import_genre_tree_view4.getTextColorOnFill)(rootColor) };
1776
+ const own = treeStyles?.get(detail.uuid) ?? { fill: rootColor, textColor: (0, import_genre_tree_view4.getTextColorOnFill)(rootColor) };
1769
1777
  return {
1770
1778
  node: {
1771
1779
  id: detail.uuid,
@@ -1782,7 +1790,7 @@ function useGenreDetailContent({
1782
1790
  ({ ascendant }, index) => relative(ascendant, index === 0 ? null : ancestors2[index - 1].ascendant.uuid)
1783
1791
  )
1784
1792
  };
1785
- }, [detail, scope, treeRelations]);
1793
+ }, [detail, scope, treeStyles]);
1786
1794
  if (isError) return {
1787
1795
  name: null,
1788
1796
  title: "Genre unavailable",
@@ -2140,7 +2148,6 @@ function ArtistDiscography({ albums }) {
2140
2148
  // src/genre-tree/artist/ArtistSongs.tsx
2141
2149
  var import_react17 = require("react");
2142
2150
  var import_react_query2 = require("@tanstack/react-query");
2143
- var import_lucide_react12 = require("lucide-react");
2144
2151
  var import_ui16 = require("@behindthemusictree/ui");
2145
2152
  var import_player11 = require("@behindthemusictree/app-kit/player");
2146
2153
  var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
@@ -2305,34 +2312,20 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
2305
2312
  void play(song.uuid);
2306
2313
  };
2307
2314
  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)(
2310
- "button",
2311
- {
2312
- type: "button",
2313
- onClick: () => void play(),
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",
2315
- children: [
2316
- /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_lucide_react12.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
2317
- "Play all"
2318
- ]
2319
- }
2320
- ),
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)(
2322
- "button",
2323
- {
2324
- type: "button",
2325
- "aria-pressed": ordering === sort.ordering,
2326
- onClick: () => {
2327
- setOrdering(sort.ordering);
2328
- setPage(1);
2329
- },
2330
- className: "px-2.5 py-0.5 text-[var(--color-text)] rounded-full hover:bg-[var(--color-surface-muted)] aria-pressed:bg-gray-900 aria-pressed:text-white",
2331
- children: sort.label
2315
+ /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-2 mb-2", children: /* @__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)(
2316
+ "button",
2317
+ {
2318
+ type: "button",
2319
+ "aria-pressed": ordering === sort.ordering,
2320
+ onClick: () => {
2321
+ setOrdering(sort.ordering);
2322
+ setPage(1);
2332
2323
  },
2333
- sort.ordering
2334
- )) })
2335
- ] }),
2324
+ className: "px-2.5 py-0.5 text-[var(--color-text)] rounded-full hover:bg-[var(--color-surface-muted)] aria-pressed:bg-gray-900 aria-pressed:text-white",
2325
+ children: sort.label
2326
+ },
2327
+ sort.ordering
2328
+ )) }) }),
2336
2329
  /* @__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)(
2337
2330
  TrackItem,
2338
2331
  {
@@ -2430,7 +2423,7 @@ var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
2430
2423
 
2431
2424
  // src/genre-tree/song/SongPanelContent.tsx
2432
2425
  var import_react18 = require("react");
2433
- var import_lucide_react13 = require("lucide-react");
2426
+ var import_lucide_react12 = require("lucide-react");
2434
2427
  var import_ui18 = require("@behindthemusictree/ui");
2435
2428
  var import_player12 = require("@behindthemusictree/app-kit/player");
2436
2429
  var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
@@ -2523,7 +2516,7 @@ function SongPanelContent(props) {
2523
2516
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
2524
2517
  import_ui18.ActionButton,
2525
2518
  {
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" }),
2519
+ icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react12.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_lucide_react12.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
2527
2520
  label: isPlaying ? "Pause" : "Play",
2528
2521
  disabled: !!unplayableReason,
2529
2522
  title: unplayableReason ?? void 0,
@@ -2895,6 +2888,7 @@ function GenreTreeView({
2895
2888
  !overlayPanel && hasSelectedGenreNode ? selectedNodeId : null,
2896
2889
  resolveStyle
2897
2890
  );
2891
+ const treeStyles = (0, import_react19.useMemo)(() => toGenreNodeStyles(relations, visibleGenrePlaylists), [relations, visibleGenrePlaylists]);
2898
2892
  const [selectionHistory, setSelectionHistory] = (0, import_react19.useState)({ current: selectedGenreUuid, previous: null });
2899
2893
  if (selectionHistory.current !== selectedGenreUuid) {
2900
2894
  setSelectionHistory({ current: selectedGenreUuid, previous: selectionHistory.current ?? selectionHistory.previous });
@@ -2940,7 +2934,7 @@ function GenreTreeView({
2940
2934
  selectGenre(uuid);
2941
2935
  },
2942
2936
  expanded: isExpanded,
2943
- treeRelations: relations,
2937
+ treeStyles,
2944
2938
  playback,
2945
2939
  genrePlaylist: selectedGenrePlaylist,
2946
2940
  band: {
@@ -3018,7 +3012,7 @@ function GenreTreeView({
3018
3012
  "aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
3019
3013
  style: activePanel.headerAccent && { color: "inherit" },
3020
3014
  onClick: () => activePanel.onExpandedChange?.(!activePanel.expanded),
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" })
3015
+ children: activePanel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react14.Minimize2, { "aria-hidden": "true", className: "h-4 w-4" }) : /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(import_lucide_react14.Maximize2, { "aria-hidden": "true", className: "h-4 w-4" })
3022
3016
  }
3023
3017
  ) : null;
3024
3018
  const renderArtistFilter = () => {
@@ -3118,7 +3112,7 @@ function GenreTreeView({
3118
3112
  !isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime45.jsx)(
3119
3113
  import_ui21.IconTextButton,
3120
3114
  {
3121
- icon: import_lucide_react14.Plus,
3115
+ icon: import_lucide_react13.Plus,
3122
3116
  text: "Add root",
3123
3117
  onClick: () => handleGenreCreationAction(null)
3124
3118
  }
@@ -3295,7 +3289,7 @@ var import_genre_tree_view6 = require("@behindthemusictree/genre-tree-view");
3295
3289
 
3296
3290
  // src/genre-tree/track-list-sidebar/TrackListSidebar.tsx
3297
3291
  var import_react20 = require("react");
3298
- var import_lucide_react16 = require("lucide-react");
3292
+ var import_lucide_react15 = require("lucide-react");
3299
3293
  var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
3300
3294
  var import_genre_tree32 = require("@behindthemusictree/app-kit/genre-tree");
3301
3295
  var import_track_noun3 = require("@behindthemusictree/app-kit/track-noun");
@@ -3428,7 +3422,7 @@ function TrackListSidebar({
3428
3422
  "aria-expanded": !isCollapsed,
3429
3423
  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"}`,
3430
3424
  onClick: isCollapsed ? onExpand : onMinimize,
3431
- children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react16.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
3425
+ children: /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(import_lucide_react15.ListMusic, { "aria-hidden": "true", className: "h-5 w-5" })
3432
3426
  }
3433
3427
  )
3434
3428
  ] }),
@@ -3470,7 +3464,7 @@ var import_genre_tree34 = require("@behindthemusictree/app-kit/genre-tree");
3470
3464
  var import_ui22 = require("@behindthemusictree/ui");
3471
3465
 
3472
3466
  // src/genre-tree/PlayerControls.tsx
3473
- var import_lucide_react17 = require("lucide-react");
3467
+ var import_lucide_react16 = require("lucide-react");
3474
3468
  var import_genre_tree33 = require("@behindthemusictree/app-kit/genre-tree");
3475
3469
  var import_player13 = require("@behindthemusictree/app-kit/player");
3476
3470
  var import_jsx_runtime47 = require("react/jsx-runtime");
@@ -3527,7 +3521,7 @@ function PlayerControls() {
3527
3521
  disabled: !isReady || !hasPreviousTrack,
3528
3522
  onClick: playPreviousTrack,
3529
3523
  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",
3530
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
3524
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react16.SkipBack, { "aria-hidden": "true", className: "h-4 w-4" })
3531
3525
  }
3532
3526
  ),
3533
3527
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
@@ -3539,7 +3533,7 @@ function PlayerControls() {
3539
3533
  disabled: !isReady,
3540
3534
  onClick: handlePlayPauseAction,
3541
3535
  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",
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" })
3536
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react16.Pause, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react16.Play, { "aria-hidden": "true", className: "h-4 w-4", fill: "currentColor" })
3543
3537
  }
3544
3538
  ),
3545
3539
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
@@ -3551,12 +3545,12 @@ function PlayerControls() {
3551
3545
  disabled: !isReady || !hasNextTrack,
3552
3546
  onClick: playNextTrack,
3553
3547
  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",
3554
- children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react17.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
3548
+ children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react16.SkipForward, { "aria-hidden": "true", className: "h-4 w-4" })
3555
3549
  }
3556
3550
  )
3557
3551
  ] }),
3558
3552
  /* @__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" }),
3553
+ volume === 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react16.VolumeX, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_lucide_react16.Volume2, { "aria-hidden": "true", className: "h-[0.7rem] w-[0.7rem] shrink-0" }),
3560
3554
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("span", { className: "sr-only", children: "Volume" }),
3561
3555
  /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
3562
3556
  "input",