@behindthemusictree/app-kit-ui 42.0.1 → 43.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-PVYUC2PN.js → chunk-UTUU463Q.js} +63 -34
- package/dist/chunk-UTUU463Q.js.map +1 -0
- package/dist/genre-tree/index.cjs +83 -55
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +2 -4
- package/dist/genre-tree/index.js +1 -1
- package/dist/index.cjs +83 -55
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +1 -1
- package/package.json +4 -4
- package/dist/chunk-PVYUC2PN.js.map +0 -1
|
@@ -199,7 +199,7 @@ interface GenreSearchGroupsProps {
|
|
|
199
199
|
type ParentChange = {
|
|
200
200
|
genre: GenreUuid;
|
|
201
201
|
from: GenreUuid | null;
|
|
202
|
-
to: GenreUuid;
|
|
202
|
+
to: GenreUuid | null;
|
|
203
203
|
};
|
|
204
204
|
|
|
205
205
|
/** Identifies the detail-panel entity whose current host route should be shared. */
|
|
@@ -245,7 +245,7 @@ type GenreTreeViewProps<O extends CriteriaOverview = CriteriaOverview> = {
|
|
|
245
245
|
handleGenreCreationAction: (parent: CriteriaMinimum | null) => void;
|
|
246
246
|
handleGenreRenameAction: (genre: CriteriaMinimum) => void;
|
|
247
247
|
getBackendBaseUrl: () => string;
|
|
248
|
-
/** Called after the Parent popup moved a genre; `from` and `to` are genre (criteria) uuids, `from` null for a root genre. */
|
|
248
|
+
/** Called after the Parent popup moved a genre; `from` and `to` are genre (criteria) uuids, `from` null for a root genre, `to` null when the genre was made a root. */
|
|
249
249
|
onParentChanged?: (change: ParentChange) => void;
|
|
250
250
|
additionalActions?: (node: GenreTreeNode) => GenreTreeAction[];
|
|
251
251
|
/** Controlled view mode. When provided, the internal Stacked/Wheel toggle is not rendered — the consumer owns that UI. */
|
|
@@ -466,8 +466,6 @@ interface PlayerPanelProps {
|
|
|
466
466
|
className?: string;
|
|
467
467
|
/** Hidden via CSS, never unmounted, so the video keeps playing while the host hides the panel. */
|
|
468
468
|
isVisible?: boolean;
|
|
469
|
-
/** @deprecated The player no longer closes; its header action minimizes to video-only mode. */
|
|
470
|
-
onClose?: () => void;
|
|
471
469
|
/** Controlled extended state; uncontrolled when omitted. */
|
|
472
470
|
expanded?: boolean;
|
|
473
471
|
onExpandedChange?: (expanded: boolean) => void;
|
package/dist/genre-tree/index.js
CHANGED
package/dist/index.cjs
CHANGED
|
@@ -593,7 +593,7 @@ var import_react19 = require("react");
|
|
|
593
593
|
var import_react_query3 = require("@tanstack/react-query");
|
|
594
594
|
var import_lucide_react17 = require("lucide-react");
|
|
595
595
|
var import_lucide_react18 = require("lucide-react");
|
|
596
|
-
var
|
|
596
|
+
var import_ui25 = require("@behindthemusictree/ui");
|
|
597
597
|
var import_genre_tree_view5 = require("@behindthemusictree/genre-tree-view");
|
|
598
598
|
var import_genre_tree30 = require("@behindthemusictree/app-kit/genre-tree");
|
|
599
599
|
var import_genre_tree31 = require("@behindthemusictree/app-kit/genre-tree");
|
|
@@ -2146,7 +2146,16 @@ function useGenreDetailContent({
|
|
|
2146
2146
|
onSelectNode: selectGenre
|
|
2147
2147
|
}
|
|
2148
2148
|
);
|
|
2149
|
-
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2149
|
+
const ancestors = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
|
|
2150
|
+
import_genre_tree_view4.GenreNodeAncestors,
|
|
2151
|
+
{
|
|
2152
|
+
node: view.node,
|
|
2153
|
+
fill: view.fill,
|
|
2154
|
+
textColor: view.textColor,
|
|
2155
|
+
ancestorNodes: view.ancestorNodes,
|
|
2156
|
+
onSelectNode: selectGenre
|
|
2157
|
+
}
|
|
2158
|
+
);
|
|
2150
2159
|
return {
|
|
2151
2160
|
name: detail.name,
|
|
2152
2161
|
title: detail.name,
|
|
@@ -2222,6 +2231,7 @@ function GenreDetailPanel({
|
|
|
2222
2231
|
// src/genre-tree/ChangeParentPopup.tsx
|
|
2223
2232
|
var import_react16 = require("react");
|
|
2224
2233
|
var import_genre_tree21 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2234
|
+
var import_ui14 = require("@behindthemusictree/ui");
|
|
2225
2235
|
var import_jsx_runtime38 = require("react/jsx-runtime");
|
|
2226
2236
|
function ChangeParentPopup({
|
|
2227
2237
|
genrePlaylist,
|
|
@@ -2236,20 +2246,22 @@ function ChangeParentPopup({
|
|
|
2236
2246
|
() => (0, import_genre_tree21.getReparentCandidates)(genrePlaylists, genrePlaylist.uuid),
|
|
2237
2247
|
[genrePlaylists, genrePlaylist.uuid]
|
|
2238
2248
|
);
|
|
2239
|
-
const
|
|
2249
|
+
const [confirmingRoot, setConfirmingRoot] = (0, import_react16.useState)(false);
|
|
2250
|
+
const handleMove = (to) => {
|
|
2240
2251
|
const genre = genrePlaylist.criteria.uuid;
|
|
2241
2252
|
const parentPlaylistUuid = genrePlaylist.parent?.uuid;
|
|
2242
2253
|
const from = parentPlaylistUuid ? genrePlaylists.find(({ uuid }) => uuid === parentPlaylistUuid)?.criteria?.uuid ?? null : null;
|
|
2243
2254
|
mutate(
|
|
2244
|
-
{ uuid: genre, data: { parent:
|
|
2255
|
+
{ uuid: genre, data: { parent: to } },
|
|
2245
2256
|
{
|
|
2246
2257
|
onSuccess: () => {
|
|
2247
2258
|
onClose();
|
|
2248
|
-
onParentChanged?.({ genre, from, to
|
|
2259
|
+
onParentChanged?.({ genre, from, to });
|
|
2249
2260
|
}
|
|
2250
2261
|
}
|
|
2251
2262
|
);
|
|
2252
2263
|
};
|
|
2264
|
+
const handleSelect = (newParent) => handleMove(newParent.criteria.uuid);
|
|
2253
2265
|
(0, import_react16.useEffect)(() => {
|
|
2254
2266
|
const handleKeyDown = (event) => {
|
|
2255
2267
|
if (event.key === "Escape") onClose();
|
|
@@ -2262,6 +2274,18 @@ function ChangeParentPopup({
|
|
|
2262
2274
|
"Current parent: ",
|
|
2263
2275
|
genrePlaylist.parent?.name ?? "none"
|
|
2264
2276
|
] }),
|
|
2277
|
+
genrePlaylist.parent && (confirmingRoot ? /* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("div", { className: "mb-3 text-sm", children: [
|
|
2278
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)("p", { className: "mb-2", children: [
|
|
2279
|
+
genrePlaylist.name,
|
|
2280
|
+
" and its descendants will no longer be under ",
|
|
2281
|
+
genrePlaylist.parent.name,
|
|
2282
|
+
"."
|
|
2283
|
+
] }),
|
|
2284
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsxs)(PopupButtons, { alignment: "left", children: [
|
|
2285
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_ui14.Button, { disabled: isPending, onClick: () => handleMove(null), children: "Confirm" }),
|
|
2286
|
+
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_ui14.Button, { variant: "secondary", disabled: isPending, onClick: () => setConfirmingRoot(false), children: "Back" })
|
|
2287
|
+
] })
|
|
2288
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { className: "mb-3", children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(import_ui14.Button, { variant: "secondary", onClick: () => setConfirmingRoot(true), children: "Make root" }) })),
|
|
2265
2289
|
/* @__PURE__ */ (0, import_jsx_runtime38.jsx)("div", { "aria-busy": isPending, className: isPending ? "pointer-events-none opacity-60" : void 0, children: /* @__PURE__ */ (0, import_jsx_runtime38.jsx)(
|
|
2266
2290
|
GenreSearch,
|
|
2267
2291
|
{
|
|
@@ -2275,12 +2299,12 @@ function ChangeParentPopup({
|
|
|
2275
2299
|
}
|
|
2276
2300
|
|
|
2277
2301
|
// src/genre-tree/artist/useArtistPanel.tsx
|
|
2278
|
-
var
|
|
2302
|
+
var import_ui21 = require("@behindthemusictree/ui");
|
|
2279
2303
|
var import_genre_tree27 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2280
2304
|
|
|
2281
2305
|
// src/genre-tree/artist/ArtistActionBand.tsx
|
|
2282
2306
|
var import_lucide_react14 = require("lucide-react");
|
|
2283
|
-
var
|
|
2307
|
+
var import_ui15 = require("@behindthemusictree/ui");
|
|
2284
2308
|
var import_genre_tree22 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2285
2309
|
var import_player7 = require("@behindthemusictree/app-kit/player");
|
|
2286
2310
|
var import_jsx_runtime39 = require("react/jsx-runtime");
|
|
@@ -2299,9 +2323,9 @@ function ArtistActionBand({ artist, share }) {
|
|
|
2299
2323
|
console.error("Failed to load artist tracks:", error);
|
|
2300
2324
|
});
|
|
2301
2325
|
};
|
|
2302
|
-
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2326
|
+
return /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_ui15.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime39.jsxs)(import_ui15.ActionBand, { children: [
|
|
2303
2327
|
/* @__PURE__ */ (0, import_jsx_runtime39.jsx)(
|
|
2304
|
-
|
|
2328
|
+
import_ui15.ActionButton,
|
|
2305
2329
|
{
|
|
2306
2330
|
icon: playing ? /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react14.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime39.jsx)(import_lucide_react14.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2307
2331
|
label: playing ? "Pause" : "Play",
|
|
@@ -2316,12 +2340,12 @@ function ArtistActionBand({ artist, share }) {
|
|
|
2316
2340
|
}
|
|
2317
2341
|
|
|
2318
2342
|
// src/genre-tree/artist/ArtistHeader.tsx
|
|
2319
|
-
var
|
|
2343
|
+
var import_ui17 = require("@behindthemusictree/ui");
|
|
2320
2344
|
|
|
2321
2345
|
// src/genre-tree/artist/ArtistLinks.tsx
|
|
2322
2346
|
var import_lucide_react15 = require("lucide-react");
|
|
2323
2347
|
var import_si3 = require("react-icons/si");
|
|
2324
|
-
var
|
|
2348
|
+
var import_ui16 = require("@behindthemusictree/ui");
|
|
2325
2349
|
var import_jsx_runtime40 = require("react/jsx-runtime");
|
|
2326
2350
|
var LINK_KINDS = {
|
|
2327
2351
|
official: { label: "Official website", Icon: import_lucide_react15.Globe },
|
|
@@ -2359,7 +2383,7 @@ function artistLinks(artist) {
|
|
|
2359
2383
|
return links;
|
|
2360
2384
|
}
|
|
2361
2385
|
function ArtistLinks({ links }) {
|
|
2362
|
-
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2386
|
+
return /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("ul", { className: "flex flex-wrap gap-1.5", children: links.map(({ key, url, Icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("li", { children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_ui16.Chip, { href: url, icon: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(Icon, { className: "h-3.5 w-3.5 shrink-0", "aria-hidden": "true" }), children: label }) }, key)) });
|
|
2363
2387
|
}
|
|
2364
2388
|
|
|
2365
2389
|
// src/genre-tree/artist/formatYears.ts
|
|
@@ -2408,7 +2432,7 @@ function ArtistHeader({
|
|
|
2408
2432
|
const links = artistLinks(artist);
|
|
2409
2433
|
if (links.length > 0) fields.push({ label: "Links", value: /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(ArtistLinks, { links }) });
|
|
2410
2434
|
if (fields.length === 0) return null;
|
|
2411
|
-
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2435
|
+
return /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_ui17.FieldList, { items: fields });
|
|
2412
2436
|
}
|
|
2413
2437
|
|
|
2414
2438
|
// src/genre-tree/artist/ArtistPhoto.tsx
|
|
@@ -2418,11 +2442,11 @@ function ArtistPhoto({ image, name }) {
|
|
|
2418
2442
|
}
|
|
2419
2443
|
|
|
2420
2444
|
// src/genre-tree/artist/ArtistMembers.tsx
|
|
2421
|
-
var
|
|
2445
|
+
var import_ui18 = require("@behindthemusictree/ui");
|
|
2422
2446
|
var import_jsx_runtime43 = require("react/jsx-runtime");
|
|
2423
2447
|
function MembershipList({ title, memberships, renderArtistLink }) {
|
|
2424
2448
|
if (memberships.length === 0) return null;
|
|
2425
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2449
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui18.PanelGroup, { title, children: /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { children: memberships.map((membership, index) => {
|
|
2426
2450
|
const details = [
|
|
2427
2451
|
formatYears(membership.beginYear, membership.endYear, membership.ended),
|
|
2428
2452
|
...membership.roles
|
|
@@ -2443,7 +2467,7 @@ function MembershipList({ title, memberships, renderArtistLink }) {
|
|
|
2443
2467
|
function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
2444
2468
|
if (memberships.length === 0) return null;
|
|
2445
2469
|
const isCurrent = (membership) => !membership.ended && membership.endYear === null;
|
|
2446
|
-
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2470
|
+
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_ui18.PanelSection, { title, children: [
|
|
2447
2471
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(MembershipList, { title: "Current", memberships: memberships.filter(isCurrent), renderArtistLink }),
|
|
2448
2472
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)(
|
|
2449
2473
|
MembershipList,
|
|
@@ -2457,7 +2481,7 @@ function ArtistMembers({ title, memberships, renderArtistLink }) {
|
|
|
2457
2481
|
}
|
|
2458
2482
|
|
|
2459
2483
|
// src/genre-tree/artist/ArtistDiscography.tsx
|
|
2460
|
-
var
|
|
2484
|
+
var import_ui19 = require("@behindthemusictree/ui");
|
|
2461
2485
|
var import_jsx_runtime44 = require("react/jsx-runtime");
|
|
2462
2486
|
var GROUPS = ["Albums", "EPs", "Singles", "Live", "Compilations", "Other"];
|
|
2463
2487
|
var PRIMARY_GROUPS = { album: "Albums", ep: "EPs", single: "Singles" };
|
|
@@ -2478,10 +2502,10 @@ function byYear(a, b) {
|
|
|
2478
2502
|
function ArtistDiscography({ albums }) {
|
|
2479
2503
|
if (albums.length === 0) return null;
|
|
2480
2504
|
const sorted = [...albums].sort(byYear);
|
|
2481
|
-
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2505
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_ui19.PanelSection, { title: "Discography", children: GROUPS.map((group) => {
|
|
2482
2506
|
const groupAlbums = sorted.filter((album) => discographyGroup(album) === group);
|
|
2483
2507
|
if (groupAlbums.length === 0) return null;
|
|
2484
|
-
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(
|
|
2508
|
+
return /* @__PURE__ */ (0, import_jsx_runtime44.jsx)(import_ui19.PanelGroup, { title: group, children: /* @__PURE__ */ (0, import_jsx_runtime44.jsx)("ul", { children: groupAlbums.map((album) => /* @__PURE__ */ (0, import_jsx_runtime44.jsxs)("li", { className: "grid grid-cols-[2.5rem_minmax(0,1fr)] gap-2 py-0.5", children: [
|
|
2485
2509
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "tabular-nums text-[var(--color-text-muted)]", children: album.year ?? "\u2014" }),
|
|
2486
2510
|
/* @__PURE__ */ (0, import_jsx_runtime44.jsx)("span", { className: "truncate text-[var(--color-text)]", title: album.name, children: album.name })
|
|
2487
2511
|
] }, album.uuid)) }) }, group);
|
|
@@ -2491,7 +2515,7 @@ function ArtistDiscography({ albums }) {
|
|
|
2491
2515
|
// src/genre-tree/artist/ArtistSongs.tsx
|
|
2492
2516
|
var import_react17 = require("react");
|
|
2493
2517
|
var import_react_query2 = require("@tanstack/react-query");
|
|
2494
|
-
var
|
|
2518
|
+
var import_ui20 = require("@behindthemusictree/ui");
|
|
2495
2519
|
var import_player11 = require("@behindthemusictree/app-kit/player");
|
|
2496
2520
|
var import_genre_tree26 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2497
2521
|
var import_transport8 = require("@behindthemusictree/app-kit/transport");
|
|
@@ -2654,7 +2678,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2654
2678
|
event.stopPropagation();
|
|
2655
2679
|
void play(song.uuid);
|
|
2656
2680
|
};
|
|
2657
|
-
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2681
|
+
return /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.PanelSection, { title: "Songs", children: isPending ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Skeleton, { className: "h-14", "aria-busy": "true" }) : isError ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-red-600", children: "Could not load songs." }) : data.results.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No songs yet." }) : /* @__PURE__ */ (0, import_jsx_runtime47.jsxs)(import_jsx_runtime47.Fragment, { children: [
|
|
2658
2682
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "flex flex-wrap items-center justify-end gap-2 mb-2", children: /* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2659
2683
|
"button",
|
|
2660
2684
|
{
|
|
@@ -2678,7 +2702,7 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2678
2702
|
renderSongLink
|
|
2679
2703
|
}
|
|
2680
2704
|
) }, song.uuid)) }),
|
|
2681
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(
|
|
2705
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)(import_ui20.Pagination, { currentPage: page, totalPages: data.totalPages, onPageChange: setPage })
|
|
2682
2706
|
] }) });
|
|
2683
2707
|
}
|
|
2684
2708
|
|
|
@@ -2706,12 +2730,12 @@ function useArtistPanel({
|
|
|
2706
2730
|
...panel,
|
|
2707
2731
|
title: "Artist",
|
|
2708
2732
|
content: /* @__PURE__ */ (0, import_jsx_runtime48.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2709
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2710
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2711
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2712
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2713
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2714
|
-
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(
|
|
2733
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-3 w-16" }),
|
|
2734
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-4 w-32" }),
|
|
2735
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-3 w-16" }),
|
|
2736
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-4 w-24" }),
|
|
2737
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-16 mt-2.5" }),
|
|
2738
|
+
/* @__PURE__ */ (0, import_jsx_runtime48.jsx)(import_ui21.Skeleton, { className: "h-16" })
|
|
2715
2739
|
] })
|
|
2716
2740
|
};
|
|
2717
2741
|
case "not-found":
|
|
@@ -2762,13 +2786,13 @@ function useArtistPanel({
|
|
|
2762
2786
|
}
|
|
2763
2787
|
|
|
2764
2788
|
// src/genre-tree/song/useSongPanel.tsx
|
|
2765
|
-
var
|
|
2789
|
+
var import_ui23 = require("@behindthemusictree/ui");
|
|
2766
2790
|
var import_genre_tree29 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2767
2791
|
|
|
2768
2792
|
// src/genre-tree/song/SongPanelContent.tsx
|
|
2769
2793
|
var import_react18 = require("react");
|
|
2770
2794
|
var import_lucide_react16 = require("lucide-react");
|
|
2771
|
-
var
|
|
2795
|
+
var import_ui22 = require("@behindthemusictree/ui");
|
|
2772
2796
|
var import_player12 = require("@behindthemusictree/app-kit/player");
|
|
2773
2797
|
var import_genre_tree28 = require("@behindthemusictree/app-kit/genre-tree");
|
|
2774
2798
|
var import_jsx_runtime49 = require("react/jsx-runtime");
|
|
@@ -2779,7 +2803,7 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2779
2803
|
const [open, setOpen] = (0, import_react18.useState)(false);
|
|
2780
2804
|
const history = (0, import_genre_tree28.useSongHistory)(uuid, getBackendBaseUrl, open);
|
|
2781
2805
|
let body = null;
|
|
2782
|
-
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2806
|
+
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2783
2807
|
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2784
2808
|
else if (history.status === "success")
|
|
2785
2809
|
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
@@ -2797,8 +2821,8 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2797
2821
|
dateFormat.format(new Date(entry.createdOn))
|
|
2798
2822
|
] })
|
|
2799
2823
|
] }, entry.uuid)) });
|
|
2800
|
-
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2801
|
-
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("summary", { className: `mt-2.5 cursor-pointer ${
|
|
2824
|
+
return /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.PanelBleed, { padded: true, className: "border-t border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)("details", { onToggle: (event) => setOpen(event.currentTarget.open), className: "pb-2.5", children: [
|
|
2825
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("summary", { className: `mt-2.5 cursor-pointer ${import_ui22.PANEL_LABEL_CLASS}`, children: "History" }),
|
|
2802
2826
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)("div", { className: "mt-1.5", children: body })
|
|
2803
2827
|
] }) });
|
|
2804
2828
|
}
|
|
@@ -2856,9 +2880,9 @@ function SongPanelContent(props) {
|
|
|
2856
2880
|
value: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("span", { className: "flex gap-3", children: links })
|
|
2857
2881
|
});
|
|
2858
2882
|
return /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_jsx_runtime49.Fragment, { children: [
|
|
2859
|
-
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2883
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.PanelBleed, { children: /* @__PURE__ */ (0, import_jsx_runtime49.jsxs)(import_ui22.ActionBand, { children: [
|
|
2860
2884
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2861
|
-
|
|
2885
|
+
import_ui22.ActionButton,
|
|
2862
2886
|
{
|
|
2863
2887
|
icon: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react16.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_lucide_react16.Play, { "aria-hidden": "true", className: "w-5 h-5" }),
|
|
2864
2888
|
label: isPlaying ? "Pause" : "Play",
|
|
@@ -2870,8 +2894,8 @@ function SongPanelContent(props) {
|
|
|
2870
2894
|
shareUrl && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(ShareActionButton, { target: shareTarget, url: shareUrl })
|
|
2871
2895
|
] }) }),
|
|
2872
2896
|
song.artists && song.artists.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("p", { className: "text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_genre_tree28.ArtistNames, { artists: song.artists, renderArtistLink }) }),
|
|
2873
|
-
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2874
|
-
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(
|
|
2897
|
+
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.FieldList, { items: fields }),
|
|
2898
|
+
song.essentialGenres && song.essentialGenres.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime49.jsx)(import_ui22.PanelSection, { title: "Essential in", children: /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("ul", { children: song.essentialGenres.map((genre) => /* @__PURE__ */ (0, import_jsx_runtime49.jsx)("li", { className: "py-0.5", children: genre.name }, genre.uuid)) }) }),
|
|
2875
2899
|
/* @__PURE__ */ (0, import_jsx_runtime49.jsx)(SongHistory, { uuid: song.uuid, getBackendBaseUrl })
|
|
2876
2900
|
] });
|
|
2877
2901
|
}
|
|
@@ -2899,10 +2923,10 @@ function useSongPanel({
|
|
|
2899
2923
|
...panel,
|
|
2900
2924
|
title: "Song",
|
|
2901
2925
|
content: /* @__PURE__ */ (0, import_jsx_runtime50.jsxs)("div", { "aria-busy": "true", className: "flex flex-col gap-2.5", children: [
|
|
2902
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2903
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2904
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2905
|
-
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(
|
|
2926
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui23.Skeleton, { className: "h-3 w-16" }),
|
|
2927
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui23.Skeleton, { className: "h-4 w-32" }),
|
|
2928
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui23.Skeleton, { className: "h-3 w-16" }),
|
|
2929
|
+
/* @__PURE__ */ (0, import_jsx_runtime50.jsx)(import_ui23.Skeleton, { className: "h-4 w-24" })
|
|
2906
2930
|
] })
|
|
2907
2931
|
};
|
|
2908
2932
|
case "not-found":
|
|
@@ -2977,14 +3001,14 @@ function useEntityPanel({
|
|
|
2977
3001
|
|
|
2978
3002
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2979
3003
|
var import_md2 = require("react-icons/md");
|
|
2980
|
-
var
|
|
3004
|
+
var import_ui24 = require("@behindthemusictree/ui");
|
|
2981
3005
|
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
2982
3006
|
function SizeMetricToggle({
|
|
2983
3007
|
value,
|
|
2984
3008
|
onChange
|
|
2985
3009
|
}) {
|
|
2986
3010
|
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
2987
|
-
|
|
3011
|
+
import_ui24.SegmentedControl,
|
|
2988
3012
|
{
|
|
2989
3013
|
variant: "floating",
|
|
2990
3014
|
"aria-label": "Size nodes by",
|
|
@@ -3227,7 +3251,7 @@ function GenreTreeView({
|
|
|
3227
3251
|
[]
|
|
3228
3252
|
);
|
|
3229
3253
|
const panelRef = (0, import_react19.useRef)(null);
|
|
3230
|
-
const obscuredInset = (0,
|
|
3254
|
+
const obscuredInset = (0, import_ui25.useObscuredInset)(panelRef);
|
|
3231
3255
|
const hostPanel = { obscuredInset, onNodeStyleResolverChange: handleNodeStyleResolverChange };
|
|
3232
3256
|
const nodeMetric = isArtistFiltered || !canSizeByViews ? "songs" : deferredSizeMetric;
|
|
3233
3257
|
const treeNodes = (0, import_react19.useMemo)(() => toTreeNodes(visibleGenrePlaylists, nodeMetric, focusUuids), [visibleGenrePlaylists, nodeMetric, focusUuids]);
|
|
@@ -3356,7 +3380,7 @@ function GenreTreeView({
|
|
|
3356
3380
|
center: activePanel.expanded ? null : isCollapsed ? { label: "Show panel", onClick: () => changeCollapsed(false) } : activePanel.onExpandedChange ? { label: "Extend panel", onClick: () => activePanel.onExpandedChange?.(true) } : null
|
|
3357
3381
|
} : void 0;
|
|
3358
3382
|
const expandButton = placement === "default" && activePanel?.onExpandedChange ? /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3359
|
-
|
|
3383
|
+
import_ui25.IconButton,
|
|
3360
3384
|
{
|
|
3361
3385
|
"aria-label": activePanel.expanded ? "Shrink panel" : "Extend panel",
|
|
3362
3386
|
style: activePanel.headerAccent && { color: "inherit" },
|
|
@@ -3428,7 +3452,7 @@ function GenreTreeView({
|
|
|
3428
3452
|
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)("div", { className: "hidden w-full justify-center max-md:flex", children: renderArtistFilter() }),
|
|
3429
3453
|
/* @__PURE__ */ (0, import_jsx_runtime52.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: [
|
|
3430
3454
|
!isLoading && !isError && !isControlled && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3431
|
-
|
|
3455
|
+
import_ui25.SegmentedControl,
|
|
3432
3456
|
{
|
|
3433
3457
|
"aria-label": "Tree view mode",
|
|
3434
3458
|
value: viewMode,
|
|
@@ -3448,7 +3472,7 @@ function GenreTreeView({
|
|
|
3448
3472
|
role: "group",
|
|
3449
3473
|
"aria-label": "Tree display options",
|
|
3450
3474
|
children: !isRotationControlled && viewMode !== "stacked" && viewMode !== "outline" && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3451
|
-
|
|
3475
|
+
import_ui25.Button,
|
|
3452
3476
|
{
|
|
3453
3477
|
variant: allowWheelRotation ? "default" : "outline",
|
|
3454
3478
|
size: "sm",
|
|
@@ -3459,7 +3483,7 @@ function GenreTreeView({
|
|
|
3459
3483
|
}
|
|
3460
3484
|
),
|
|
3461
3485
|
!isLoading && !isError && !readOnly && showAddRoot && /* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3462
|
-
|
|
3486
|
+
import_ui25.IconTextButton,
|
|
3463
3487
|
{
|
|
3464
3488
|
icon: import_lucide_react17.Plus,
|
|
3465
3489
|
text: "Add root",
|
|
@@ -3607,7 +3631,7 @@ function GenreTreeView({
|
|
|
3607
3631
|
}
|
|
3608
3632
|
) }),
|
|
3609
3633
|
/* @__PURE__ */ (0, import_jsx_runtime52.jsx)(
|
|
3610
|
-
|
|
3634
|
+
import_ui25.DetailPanel,
|
|
3611
3635
|
{
|
|
3612
3636
|
ref: panelRef,
|
|
3613
3637
|
side: "left",
|
|
@@ -3807,10 +3831,11 @@ function TrackListSidebar({
|
|
|
3807
3831
|
|
|
3808
3832
|
// src/genre-tree/PlayerPanel.tsx
|
|
3809
3833
|
var import_react21 = require("react");
|
|
3834
|
+
var import_lucide_react21 = require("lucide-react");
|
|
3810
3835
|
var import_tailwind_merge = require("tailwind-merge");
|
|
3811
3836
|
var import_player14 = require("@behindthemusictree/app-kit/player");
|
|
3812
3837
|
var import_genre_tree35 = require("@behindthemusictree/app-kit/genre-tree");
|
|
3813
|
-
var
|
|
3838
|
+
var import_ui26 = require("@behindthemusictree/ui");
|
|
3814
3839
|
|
|
3815
3840
|
// src/genre-tree/PlayerControls.tsx
|
|
3816
3841
|
var import_lucide_react20 = require("lucide-react");
|
|
@@ -3935,7 +3960,7 @@ function PlayerPanel({
|
|
|
3935
3960
|
renderArtistLink,
|
|
3936
3961
|
renderSongLink
|
|
3937
3962
|
}) {
|
|
3938
|
-
const { playerTrackObject, retryPlayback } = (0, import_player14.usePlayer)();
|
|
3963
|
+
const { playerTrackObject, retryPlayback, stop } = (0, import_player14.usePlayer)();
|
|
3939
3964
|
const { toggleTrackListSidebar, isTrackListSidebarVisible } = (0, import_genre_tree35.useTrackListSidebarVisibility)();
|
|
3940
3965
|
const [lastLoadedTrackTitle, setLastLoadedTrackTitle] = (0, import_react21.useState)("");
|
|
3941
3966
|
const loadedTrackTitle = playerTrackObject?.track.title;
|
|
@@ -3977,7 +4002,7 @@ function PlayerPanel({
|
|
|
3977
4002
|
style: isExtended ? { width: extendedWidth } : void 0,
|
|
3978
4003
|
children: [
|
|
3979
4004
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(
|
|
3980
|
-
|
|
4005
|
+
import_ui26.PanelEdgeTab,
|
|
3981
4006
|
{
|
|
3982
4007
|
side: "right",
|
|
3983
4008
|
edge: tabEdge,
|
|
@@ -3995,7 +4020,10 @@ function PlayerPanel({
|
|
|
3995
4020
|
),
|
|
3996
4021
|
children: [
|
|
3997
4022
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex w-[var(--layout-right-w)] shrink-0 flex-col", children: [
|
|
3998
|
-
/* @__PURE__ */ (0, import_jsx_runtime55.
|
|
4023
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "flex shrink-0 items-center justify-between gap-2 border-b border-zinc-800 p-2", children: [
|
|
4024
|
+
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)("span", { className: "min-w-0 truncate text-sm font-semibold", children: loadedTrackTitle || lastLoadedTrackTitle }),
|
|
4025
|
+
playerTrackObject && /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_ui26.IconButton, { "aria-label": "Close player", onClick: stop, children: /* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_lucide_react21.X, { "aria-hidden": "true", className: "h-4 w-4" }) })
|
|
4026
|
+
] }),
|
|
3999
4027
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("div", { className: "relative w-full shrink-0", children: [
|
|
4000
4028
|
/* @__PURE__ */ (0, import_jsx_runtime55.jsx)(import_player14.PlayerVideoSurface, { className: "aspect-video w-full bg-black" }),
|
|
4001
4029
|
playerTrackObject?.loadError && /* @__PURE__ */ (0, import_jsx_runtime55.jsxs)("span", { className: "absolute bottom-2 left-2 right-2 text-xs text-red-400", children: [
|
|
@@ -4070,7 +4098,7 @@ function Rating({ rating, handleChange }) {
|
|
|
4070
4098
|
|
|
4071
4099
|
// src/genre-tree/EntityDetailPanel.tsx
|
|
4072
4100
|
var import_react22 = require("react");
|
|
4073
|
-
var
|
|
4101
|
+
var import_ui27 = require("@behindthemusictree/ui");
|
|
4074
4102
|
var import_jsx_runtime57 = require("react/jsx-runtime");
|
|
4075
4103
|
function EntityDetailPanel({
|
|
4076
4104
|
scope,
|
|
@@ -4114,7 +4142,7 @@ function EntityDetailPanel({
|
|
|
4114
4142
|
});
|
|
4115
4143
|
if (!panel) return null;
|
|
4116
4144
|
return /* @__PURE__ */ (0, import_jsx_runtime57.jsx)(
|
|
4117
|
-
|
|
4145
|
+
import_ui27.DetailPanel,
|
|
4118
4146
|
{
|
|
4119
4147
|
side: "left",
|
|
4120
4148
|
title: panel.title,
|