@behindthemusictree/app-kit-ui 37.0.0 → 38.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-DKQQLLMY.js → chunk-2GH7CSCE.js} +3 -3
- package/dist/{chunk-DKQQLLMY.js.map → chunk-2GH7CSCE.js.map} +1 -1
- package/dist/{chunk-FTYMRCJS.js → chunk-F7H5XPWU.js} +169 -80
- package/dist/chunk-F7H5XPWU.js.map +1 -0
- package/dist/{chunk-K4WMHUNM.js → chunk-NJYEQ3RS.js} +8 -8
- package/dist/chunk-NJYEQ3RS.js.map +1 -0
- package/dist/genre-tree/index.cjs +171 -80
- package/dist/genre-tree/index.cjs.map +1 -1
- package/dist/genre-tree/index.d.ts +53 -1
- package/dist/genre-tree/index.js +6 -2
- package/dist/index.cjs +177 -86
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +7 -3
- package/dist/popup/index.cjs +8 -8
- package/dist/popup/index.cjs.map +1 -1
- package/dist/popup/index.js +2 -2
- package/package.json +5 -5
- package/dist/chunk-FTYMRCJS.js.map +0 -1
- package/dist/chunk-K4WMHUNM.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -24,6 +24,7 @@ __export(src_exports, {
|
|
|
24
24
|
AuthErrorPopup: () => AuthErrorPopup,
|
|
25
25
|
AuthPopup: () => AuthPopup,
|
|
26
26
|
BasePopup: () => BasePopup,
|
|
27
|
+
EntityDetailPanel: () => EntityDetailPanel,
|
|
27
28
|
GenreDetailPanel: () => GenreDetailPanel,
|
|
28
29
|
GenreInfoPanelBody: () => GenreInfoPanelBody,
|
|
29
30
|
GenreNodeActionBand: () => GenreNodeActionBand,
|
|
@@ -50,6 +51,7 @@ __export(src_exports, {
|
|
|
50
51
|
TrackUploadPopup: () => TrackUploadPopup,
|
|
51
52
|
searchStatus: () => searchStatus,
|
|
52
53
|
useArtistSearchGroup: () => useArtistSearchGroup,
|
|
54
|
+
useEntityPanel: () => useEntityPanel,
|
|
53
55
|
useGenrePlaylistPlayback: () => useGenrePlaylistPlayback,
|
|
54
56
|
useGenreRemoteSearchGroup: () => useGenreRemoteSearchGroup,
|
|
55
57
|
useSongSearchGroup: () => useSongSearchGroup
|
|
@@ -258,7 +260,7 @@ function Toast({ message, onClose, durationMs = 2200 }) {
|
|
|
258
260
|
role: "status",
|
|
259
261
|
"aria-live": "polite",
|
|
260
262
|
"aria-atomic": "true",
|
|
261
|
-
className: "pointer-events-auto w-full max-w-md rounded-md bg-[var(--color-surface)] px-4 py-4 text-
|
|
263
|
+
className: "pointer-events-auto w-full max-w-md rounded-md bg-[var(--color-surface)] px-4 py-4 text-body text-[var(--color-text)] shadow-lg ring-1 ring-black/10",
|
|
262
264
|
children: message
|
|
263
265
|
}
|
|
264
266
|
) }),
|
|
@@ -330,14 +332,14 @@ function TrackUploadPopup({
|
|
|
330
332
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center space-x-3", children: [
|
|
331
333
|
getStatusIcon(item.status),
|
|
332
334
|
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
|
|
333
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "font-medium text-
|
|
334
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-
|
|
335
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "font-medium text-body truncate max-w-xs", title: item.file.name, children: item.file.name }),
|
|
336
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-caption text-[var(--color-neutral-500)]", children: [
|
|
335
337
|
(item.file.size / 1024 / 1024).toFixed(1),
|
|
336
338
|
" MB"
|
|
337
339
|
] })
|
|
338
340
|
] })
|
|
339
341
|
] }),
|
|
340
|
-
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-
|
|
342
|
+
/* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-body text-[var(--color-neutral-600)]", children: getStatusText(item.status) })
|
|
341
343
|
] }),
|
|
342
344
|
item.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-full bg-[var(--color-neutral-200)] rounded-full h-2", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
|
|
343
345
|
"div",
|
|
@@ -346,9 +348,9 @@ function TrackUploadPopup({
|
|
|
346
348
|
style: { width: `${item.progress}%` }
|
|
347
349
|
}
|
|
348
350
|
) }),
|
|
349
|
-
item.status === "error" && item.error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-[var(--color-red-500)] text-
|
|
351
|
+
item.status === "error" && item.error && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "text-[var(--color-red-500)] text-body mt-2", children: item.error.name === "InvalidInputError" ? "Upload failed due to invalid file data. Please check your file and try again." : item.error.name === "ZodError" ? "Upload failed due to a server error. Please try again later." : item.error.message })
|
|
350
352
|
] }, item.id)),
|
|
351
|
-
allComplete && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-
|
|
353
|
+
allComplete && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex justify-between items-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "text-body text-[var(--color-neutral-600)]", children: [
|
|
352
354
|
successfulCount,
|
|
353
355
|
" successful, ",
|
|
354
356
|
errorCount,
|
|
@@ -397,7 +399,7 @@ function InternalErrorPopup({ errorCode, contactEmail, ...rest }) {
|
|
|
397
399
|
" ",
|
|
398
400
|
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("a", { href: `mailto:${contactEmail}`, className: "text-[var(--color-primary)] hover:text-[var(--color-primary-hover)]", children: contactEmail })
|
|
399
401
|
] }) }),
|
|
400
|
-
errorCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "text-
|
|
402
|
+
errorCode && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "text-body text-[var(--color-neutral-500)] bg-[var(--color-neutral-100)] p-3 rounded-lg border border-[var(--color-neutral-100)]", children: [
|
|
401
403
|
"Error Code: ",
|
|
402
404
|
errorCode
|
|
403
405
|
] })
|
|
@@ -513,7 +515,7 @@ function SpotifyAuthErrorPopup({
|
|
|
513
515
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)(import_fa2.FaSpotify, { className: "text-[#1DB954] text-7xl" }),
|
|
514
516
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-3 text-center", children: [
|
|
515
517
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-xl font-medium text-[var(--color-text)]", children: message }),
|
|
516
|
-
details && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-
|
|
518
|
+
details && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-body text-[var(--color-neutral-500)] bg-[var(--color-neutral-100)] p-3 rounded-lg border border-[var(--color-neutral-100)]", children: details }),
|
|
517
519
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "space-y-2 text-center", children: [
|
|
518
520
|
/* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-base text-[var(--color-neutral-700)]", children: "The Spotify app is in development mode, so only allowlisted accounts can connect." }),
|
|
519
521
|
requestAccessHref && contactEmail ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("p", { className: "text-base text-[var(--color-neutral-700)]", children: [
|
|
@@ -1109,7 +1111,7 @@ function useArtistSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1109
1111
|
artist.disambiguation
|
|
1110
1112
|
] })
|
|
1111
1113
|
] }),
|
|
1112
|
-
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "block truncate text-
|
|
1114
|
+
artist.matchedAlias && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: [
|
|
1113
1115
|
"also known as ",
|
|
1114
1116
|
artist.matchedAlias
|
|
1115
1117
|
] })
|
|
@@ -1134,7 +1136,7 @@ function useSongSearchGroup(getBaseUrl, text, onSelect, enabled = true) {
|
|
|
1134
1136
|
key: song.uuid,
|
|
1135
1137
|
content: /* @__PURE__ */ (0, import_jsx_runtime18.jsxs)("span", { className: (0, import_genre_tree7.isSongSearchResultPlayable)(song) ? void 0 : "opacity-60", children: [
|
|
1136
1138
|
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate font-medium", children: song.title }),
|
|
1137
|
-
/* @__PURE__ */ (0, import_jsx_runtime18.jsx)("span", { className: "block truncate text-
|
|
1139
|
+
/* @__PURE__ */ (0, import_jsx_runtime18.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 ") })
|
|
1138
1140
|
] }),
|
|
1139
1141
|
onSelect: () => onSelect(song)
|
|
1140
1142
|
})),
|
|
@@ -1157,9 +1159,9 @@ function useGenreRemoteSearchGroup(getBaseUrl, text, onSelect, { key = "genres",
|
|
|
1157
1159
|
content: /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(import_jsx_runtime19.Fragment, { children: [
|
|
1158
1160
|
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "block truncate font-medium", children: [
|
|
1159
1161
|
genre.name,
|
|
1160
|
-
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ml-2 text-
|
|
1162
|
+
genre.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "ml-2 text-caption font-normal italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1161
1163
|
] }),
|
|
1162
|
-
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate text-
|
|
1164
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsx)("span", { className: "block truncate text-caption text-[var(--color-neutral-500)]", children: describe?.(genre) ?? `${genre.treeName} \xB7 ${genre.root.name}` })
|
|
1163
1165
|
] }),
|
|
1164
1166
|
onSelect: () => onSelect(genre)
|
|
1165
1167
|
})),
|
|
@@ -1200,7 +1202,7 @@ function GenreSearch({
|
|
|
1200
1202
|
key: genrePlaylist.uuid,
|
|
1201
1203
|
content: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)(import_jsx_runtime20.Fragment, { children: [
|
|
1202
1204
|
genrePlaylist.name,
|
|
1203
|
-
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ml-2 text-
|
|
1205
|
+
genrePlaylist.isUmbrella && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("span", { className: "ml-2 text-caption italic text-[var(--color-text-muted)]", children: "umbrella" })
|
|
1204
1206
|
] }),
|
|
1205
1207
|
onSelect: () => select(genrePlaylist)
|
|
1206
1208
|
}))
|
|
@@ -1301,7 +1303,7 @@ var import_si = require("react-icons/si");
|
|
|
1301
1303
|
|
|
1302
1304
|
// src/genre-tree/ShareDestinationButton.tsx
|
|
1303
1305
|
var import_jsx_runtime22 = require("react/jsx-runtime");
|
|
1304
|
-
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-
|
|
1306
|
+
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";
|
|
1305
1307
|
function Contents({ icon, label }) {
|
|
1306
1308
|
return /* @__PURE__ */ (0, import_jsx_runtime22.jsxs)(import_jsx_runtime22.Fragment, { children: [
|
|
1307
1309
|
/* @__PURE__ */ (0, import_jsx_runtime22.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 }),
|
|
@@ -1331,9 +1333,9 @@ function SharePreviewCard({ target, url }) {
|
|
|
1331
1333
|
return /* @__PURE__ */ (0, import_jsx_runtime23.jsx)("div", { className: "rounded-3xl bg-[var(--color-surface-muted)] p-4", children: /* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex min-h-32 overflow-hidden rounded-2xl bg-[var(--color-surface)] shadow-lg", children: [
|
|
1332
1334
|
/* @__PURE__ */ (0, import_jsx_runtime23.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_runtime23.jsx)(Icon, { "aria-hidden": "true", className: "h-10 w-10" }) }),
|
|
1333
1335
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsxs)("div", { className: "flex min-w-0 flex-1 flex-col justify-center gap-1 p-4", children: [
|
|
1334
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-
|
|
1336
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "text-caption font-medium uppercase tracking-wide text-[var(--color-text-muted)]", children: typeLabel }),
|
|
1335
1337
|
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-base font-semibold text-[var(--color-text)]", title: target.name, children: target.name }),
|
|
1336
|
-
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-
|
|
1338
|
+
/* @__PURE__ */ (0, import_jsx_runtime23.jsx)("span", { className: "truncate text-body text-[var(--color-primary)]", title: url, children: url })
|
|
1337
1339
|
] })
|
|
1338
1340
|
] }) });
|
|
1339
1341
|
}
|
|
@@ -1474,8 +1476,8 @@ function SharePopup({ target, url, onClose }) {
|
|
|
1474
1476
|
}
|
|
1475
1477
|
)
|
|
1476
1478
|
] }),
|
|
1477
|
-
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-
|
|
1478
|
-
shareError && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-
|
|
1479
|
+
copyStatus === "failed" && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: "Could not copy the link." }),
|
|
1480
|
+
shareError && /* @__PURE__ */ (0, import_jsx_runtime24.jsx)("p", { role: "alert", className: "text-center text-body text-[var(--color-red-500)]", children: shareError })
|
|
1479
1481
|
] })
|
|
1480
1482
|
}
|
|
1481
1483
|
),
|
|
@@ -1495,7 +1497,7 @@ function ShareActionButton({ target, url }) {
|
|
|
1495
1497
|
{
|
|
1496
1498
|
type: "button",
|
|
1497
1499
|
onClick: openSharePopup,
|
|
1498
|
-
className: "group flex flex-col items-center gap-1 w-16 text-
|
|
1500
|
+
className: "group flex flex-col items-center gap-1 w-16 text-caption text-center text-[var(--color-text)] focus-visible:outline-none",
|
|
1499
1501
|
"aria-label": `Share ${target.name}`,
|
|
1500
1502
|
title: `Share ${target.name}`,
|
|
1501
1503
|
children: [
|
|
@@ -1577,7 +1579,7 @@ function GenreActionBand({
|
|
|
1577
1579
|
disabled: item.disabled,
|
|
1578
1580
|
title: item.title,
|
|
1579
1581
|
onClick: item.onClick,
|
|
1580
|
-
className: "group flex flex-col items-center gap-1 w-16 text-
|
|
1582
|
+
className: "group flex flex-col items-center gap-1 w-16 text-caption text-center text-[var(--color-text)] focus-visible:outline-none disabled:opacity-50",
|
|
1581
1583
|
children: [
|
|
1582
1584
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("span", { className: "flex items-center justify-center w-10 h-10 rounded-full group-focus-visible:ring-2 group-focus-visible:ring-[var(--color-focus-ring)] bg-[var(--color-surface-muted)] transition-colors group-hover:bg-[var(--color-border)] group-disabled:group-hover:bg-[var(--color-surface-muted)]", children: item.icon }),
|
|
1583
1585
|
item.label
|
|
@@ -1596,7 +1598,7 @@ function GenreActionBand({
|
|
|
1596
1598
|
"aria-label": "Admin actions",
|
|
1597
1599
|
className: `px-3.5 py-3 ${items.length > 0 ? "border-t border-[var(--color-border)]" : ""}`,
|
|
1598
1600
|
children: [
|
|
1599
|
-
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "mb-2 text-
|
|
1601
|
+
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("h3", { className: "mb-2 text-caption font-semibold uppercase tracking-wide text-[var(--color-text-muted)]", children: "Admin" }),
|
|
1600
1602
|
/* @__PURE__ */ (0, import_jsx_runtime26.jsx)("div", { className: "flex flex-wrap gap-1", children: renderItems(adminItems) })
|
|
1601
1603
|
]
|
|
1602
1604
|
}
|
|
@@ -1628,7 +1630,7 @@ function ClampedText({ children, className: className2 = "" }) {
|
|
|
1628
1630
|
type: "button",
|
|
1629
1631
|
"aria-expanded": expanded,
|
|
1630
1632
|
onClick: () => setExpanded((value) => !value),
|
|
1631
|
-
className: "mt-1 text-
|
|
1633
|
+
className: "mt-1 text-caption text-[var(--color-text-muted)] underline hover:text-[var(--color-text)]",
|
|
1632
1634
|
children: expanded ? "Show less" : "Show more"
|
|
1633
1635
|
}
|
|
1634
1636
|
)
|
|
@@ -1779,7 +1781,7 @@ function GenrePlaylistTracks({
|
|
|
1779
1781
|
".",
|
|
1780
1782
|
" ",
|
|
1781
1783
|
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)("button", { type: "button", className: "underline", onClick: () => void refetch(), children: "Retry" })
|
|
1782
|
-
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-
|
|
1784
|
+
] }) : tracks.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("p", { children: "\u2014" }) : /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)("ul", { className: "mt-1 max-h-64 overflow-y-auto text-body [container-type:inline-size]", "aria-label": `${genreName} ${trackNoun.plural}`, children: [
|
|
1783
1785
|
tracks.map((track, index) => {
|
|
1784
1786
|
const label = track.artists?.length ? `${track.title} \u2014 ${track.artists.map((artist2) => artist2.name).join(", ")}` : track.title;
|
|
1785
1787
|
const isCurrent = playerTrackObject?.track.id === track.uuid;
|
|
@@ -1877,7 +1879,7 @@ function GenreDetailExtras({
|
|
|
1877
1879
|
const { summary, summarySourceUrl, essentialSongs } = overview;
|
|
1878
1880
|
const wikidataUrl = wikidataId ? `https://www.wikidata.org/wiki/${encodeURIComponent(wikidataId)}` : null;
|
|
1879
1881
|
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
1880
|
-
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui9.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-
|
|
1882
|
+
(summarySourceUrl || wikidataUrl) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui9.PanelSection, { title: "Links", children: /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)("div", { className: "flex flex-wrap gap-x-3 gap-y-1 text-caption text-[var(--color-text)]", children: [
|
|
1881
1883
|
summarySourceUrl && /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
1882
1884
|
"a",
|
|
1883
1885
|
{
|
|
@@ -1905,10 +1907,10 @@ function GenreDetailExtras({
|
|
|
1905
1907
|
}
|
|
1906
1908
|
)
|
|
1907
1909
|
] }) }),
|
|
1908
|
-
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui9.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ClampedText, { className: "text-
|
|
1910
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui9.PanelSection, { title: "Summary", children: renderSummary ? renderSummary(overview) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(ClampedText, { className: "text-body text-[var(--color-text)]", children: summary ?? "\u2014" }, genreUuid) }),
|
|
1909
1911
|
family,
|
|
1910
1912
|
renderGenreDetailExtras?.(overview),
|
|
1911
|
-
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui9.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("ul", { className: "text-
|
|
1913
|
+
(renderEssentialTracks || essentialSongs) && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(import_ui9.PanelSection, { title: `Essential ${trackNoun.plural}`, children: renderEssentialTracks ? renderEssentialTracks(overview) : essentialSongs && essentialSongs.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("ul", { className: "text-body text-[var(--color-text)]", children: essentialSongs.map((track) => /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("li", { className: "py-1", children: track.title }, track.uuid)) }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsx)("p", { className: "text-body text-[var(--color-text)]", children: "\u2014" }) }),
|
|
1912
1914
|
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
1913
1915
|
GenrePlaylistTracks,
|
|
1914
1916
|
{
|
|
@@ -1974,7 +1976,7 @@ function GenreInfoPanelBody({
|
|
|
1974
1976
|
return /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)(import_jsx_runtime31.Fragment, { children: [
|
|
1975
1977
|
toolbar,
|
|
1976
1978
|
genrePlaylist ? /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(GenreNodeActionBand, { ...band, genrePlaylist, playback }) : /* @__PURE__ */ (0, import_jsx_runtime31.jsx)(GenreActionBand, { ...band }),
|
|
1977
|
-
summary && catalogue && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "px-3.5 py-3 text-
|
|
1979
|
+
summary && catalogue && /* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("div", { className: "px-3.5 py-3 text-body text-[var(--color-text)]", children: [
|
|
1978
1980
|
/* @__PURE__ */ (0, import_jsx_runtime31.jsxs)("p", { children: [
|
|
1979
1981
|
"Catalogue ",
|
|
1980
1982
|
noun.plural,
|
|
@@ -2064,7 +2066,7 @@ function useGenreDetailContent({
|
|
|
2064
2066
|
if (isError) return {
|
|
2065
2067
|
name: null,
|
|
2066
2068
|
title: "Genre unavailable",
|
|
2067
|
-
content: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { role: "alert", className: "p-4 text-
|
|
2069
|
+
content: /* @__PURE__ */ (0, import_jsx_runtime32.jsx)("p", { role: "alert", className: "p-4 text-body text-[var(--color-text)]", children: "This genre could not be loaded." })
|
|
2068
2070
|
};
|
|
2069
2071
|
if (isPending || !detail || !view) return {
|
|
2070
2072
|
name: null,
|
|
@@ -2200,7 +2202,7 @@ function ChangeParentPopup({
|
|
|
2200
2202
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
2201
2203
|
}, [onClose]);
|
|
2202
2204
|
return /* @__PURE__ */ (0, import_jsx_runtime33.jsxs)(BasePopup_default, { title: `Change parent of ${genrePlaylist.name}`, onClose, showCancelButton: true, fitContent: true, children: [
|
|
2203
|
-
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { className: "mb-3 text-
|
|
2205
|
+
/* @__PURE__ */ (0, import_jsx_runtime33.jsxs)("p", { className: "mb-3 text-body text-[var(--color-text-muted)]", children: [
|
|
2204
2206
|
"Current parent: ",
|
|
2205
2207
|
genrePlaylist.parent?.name ?? "none"
|
|
2206
2208
|
] }),
|
|
@@ -2212,7 +2214,7 @@ function ChangeParentPopup({
|
|
|
2212
2214
|
placeholder: "Search a new parent\u2026"
|
|
2213
2215
|
}
|
|
2214
2216
|
) }),
|
|
2215
|
-
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { role: "alert", className: "mt-3 text-
|
|
2217
|
+
formErrors.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime33.jsx)("p", { role: "alert", className: "mt-3 text-body text-[var(--color-red-500)]", children: formErrors.map(({ message }) => message).join(" ") })
|
|
2216
2218
|
] });
|
|
2217
2219
|
}
|
|
2218
2220
|
|
|
@@ -2298,7 +2300,7 @@ function ExternalLink({ href, children }) {
|
|
|
2298
2300
|
function ArtistPhoto({ image, name }) {
|
|
2299
2301
|
return /* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("figure", { className: "flex flex-col gap-1.5 px-6 py-2.5", children: [
|
|
2300
2302
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)("img", { src: image.url, alt: name, className: "h-64 w-full object-contain bg-[var(--color-surface-muted)] rounded" }),
|
|
2301
|
-
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("figcaption", { className: "text-
|
|
2303
|
+
/* @__PURE__ */ (0, import_jsx_runtime36.jsxs)("figcaption", { className: "text-caption text-[var(--color-text-muted)]", children: [
|
|
2302
2304
|
"Photo: ",
|
|
2303
2305
|
/* @__PURE__ */ (0, import_jsx_runtime36.jsx)(ExternalLink, { href: image.pageUrl, children: image.author ?? "Wikimedia Commons" }),
|
|
2304
2306
|
",",
|
|
@@ -2497,7 +2499,7 @@ function TrackItem({
|
|
|
2497
2499
|
/* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "flex max-w-full items-center gap-2", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "title text-lg font-bold text-[var(--color-text)] max-w-full truncate", children: renderSongLink ? renderSongLink(track) : (0, import_genre_tree22.isSong)(track) ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(MusicBrainzRecordingLink, { song: track, className: "hover:underline focus-visible:underline", children: track.title }) : track.title }) }),
|
|
2498
2500
|
track.artists && track.artists.length > 0 ? /* @__PURE__ */ (0, import_jsx_runtime40.jsx)("div", { className: "artist text-base max-w-full truncate text-[var(--color-text-muted)]", children: /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(import_genre_tree23.ArtistNames, { artists: track.artists, renderArtistLink }) }) : ""
|
|
2499
2501
|
] }),
|
|
2500
|
-
/* @__PURE__ */ (0, import_jsx_runtime40.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_runtime40.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-
|
|
2502
|
+
/* @__PURE__ */ (0, import_jsx_runtime40.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_runtime40.jsx)("div", { className: "genre-name max-w-full whitespace-normal break-words p-1 text-caption font-bold", children: track.genre.name }) : "" }),
|
|
2501
2503
|
renderDuration && /* @__PURE__ */ (0, import_jsx_runtime40.jsx)(
|
|
2502
2504
|
"div",
|
|
2503
2505
|
{
|
|
@@ -2553,14 +2555,14 @@ function ArtistSongs({ artist, getBackendBaseUrl, renderArtistLink, renderSongLi
|
|
|
2553
2555
|
{
|
|
2554
2556
|
type: "button",
|
|
2555
2557
|
onClick: () => void play(),
|
|
2556
|
-
className: "flex w-fit items-center gap-1.5 px-3 py-1 text-
|
|
2558
|
+
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",
|
|
2557
2559
|
children: [
|
|
2558
2560
|
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)(import_lucide_react14.Play, { className: "h-3.5 w-3.5", "aria-hidden": "true" }),
|
|
2559
2561
|
"Play all"
|
|
2560
2562
|
]
|
|
2561
2563
|
}
|
|
2562
2564
|
),
|
|
2563
|
-
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-
|
|
2565
|
+
/* @__PURE__ */ (0, import_jsx_runtime41.jsx)("div", { role: "group", "aria-label": "Sort songs by", className: "flex gap-1 text-caption", children: SORTS.map((sort) => /* @__PURE__ */ (0, import_jsx_runtime41.jsx)(
|
|
2564
2566
|
"button",
|
|
2565
2567
|
{
|
|
2566
2568
|
type: "button",
|
|
@@ -2681,7 +2683,7 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2681
2683
|
if (history.status === "loading") body = /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_ui17.Skeleton, { className: "h-10", "aria-busy": "true" });
|
|
2682
2684
|
else if (history.status === "error") body = /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-red-600", children: "Could not load the history." });
|
|
2683
2685
|
else if (history.status === "success")
|
|
2684
|
-
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "py-1.5 text-
|
|
2686
|
+
body = history.entries.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "text-[var(--color-text-muted)]", children: "No changes yet." }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("ul", { className: "divide-y divide-[var(--color-border)]", children: history.entries.map((entry) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("li", { className: "py-1.5 text-body", children: [
|
|
2685
2687
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "font-medium", children: entry.action }),
|
|
2686
2688
|
entry.oldValue !== null || entry.newValue !== null ? /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "text-[var(--color-text-muted)]", children: [
|
|
2687
2689
|
" ",
|
|
@@ -2690,7 +2692,7 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2690
2692
|
" \u2192 ",
|
|
2691
2693
|
entry.newValue ?? "none"
|
|
2692
2694
|
] }) : null,
|
|
2693
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "block text-
|
|
2695
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { className: "block text-caption text-[var(--color-text-muted)]", children: [
|
|
2694
2696
|
entry.actorPseudo ?? "Anonymous",
|
|
2695
2697
|
" \xB7 ",
|
|
2696
2698
|
dateFormat.format(new Date(entry.createdOn))
|
|
@@ -2708,15 +2710,8 @@ function SongHistory({ uuid, getBackendBaseUrl }) {
|
|
|
2708
2710
|
}
|
|
2709
2711
|
);
|
|
2710
2712
|
}
|
|
2711
|
-
function SongPanelContent({
|
|
2712
|
-
song,
|
|
2713
|
-
scope,
|
|
2714
|
-
getBackendBaseUrl,
|
|
2715
|
-
shareUrl,
|
|
2716
|
-
renderArtistLink,
|
|
2717
|
-
genrePath,
|
|
2718
|
-
onSelectGenre
|
|
2719
|
-
}) {
|
|
2713
|
+
function SongPanelContent(props) {
|
|
2714
|
+
const { song, scope, getBackendBaseUrl, shareUrl, renderArtistLink } = props;
|
|
2720
2715
|
const { playNewTrackListFromTrackUuid } = (0, import_genre_tree26.useTrackList)();
|
|
2721
2716
|
const { playerTrackObject, playState, handlePlayPauseAction } = (0, import_player11.usePlayer)();
|
|
2722
2717
|
const unplayableReason = (0, import_genre_tree26.songUnplayableReason)(song);
|
|
@@ -2726,12 +2721,14 @@ function SongPanelContent({
|
|
|
2726
2721
|
const musicBrainzUrl = (0, import_genre_tree26.musicBrainzRecordingUrl)(song);
|
|
2727
2722
|
const fields = [];
|
|
2728
2723
|
if (song.genre) {
|
|
2729
|
-
const path = genrePath.length > 0 ? genrePath : null;
|
|
2724
|
+
const path = props.genrePath && props.genrePath.length > 0 ? props.genrePath : null;
|
|
2725
|
+
const { onSelectGenre } = props;
|
|
2726
|
+
const genre = song.genre;
|
|
2730
2727
|
fields.push({
|
|
2731
2728
|
label: "Genre",
|
|
2732
|
-
value: path ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { children: [
|
|
2729
|
+
value: onSelectGenre ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", onClick: () => onSelectGenre(genre), className: "hover:underline", children: genre.name }) : path ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex flex-wrap items-center gap-x-1", children: path.map((genrePlaylist, index) => /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("span", { children: [
|
|
2733
2730
|
index > 0 && /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { "aria-hidden": "true", children: "\u203A " }),
|
|
2734
|
-
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", onClick: () =>
|
|
2731
|
+
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("button", { type: "button", onClick: () => props.onSelectGenrePlaylist?.(genrePlaylist), className: "hover:underline", children: genrePlaylist.name })
|
|
2735
2732
|
] }, genrePlaylist.uuid)) }) : song.genre.name
|
|
2736
2733
|
});
|
|
2737
2734
|
} else {
|
|
@@ -2768,12 +2765,12 @@ function SongPanelContent({
|
|
|
2768
2765
|
});
|
|
2769
2766
|
return /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(import_jsx_runtime43.Fragment, { children: [
|
|
2770
2767
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("div", { className: "genre-action-band border-b border-[var(--color-border)]", children: /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)("div", { className: "flex flex-wrap gap-1 px-3.5 py-3", children: [
|
|
2771
|
-
unplayableReason ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "flex items-center px-2.5 text-
|
|
2768
|
+
unplayableReason ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)("p", { className: "flex items-center px-2.5 text-body text-[var(--color-text-muted)]", children: unplayableReason }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsxs)(
|
|
2772
2769
|
"button",
|
|
2773
2770
|
{
|
|
2774
2771
|
type: "button",
|
|
2775
2772
|
onClick: () => isCurrent ? handlePlayPauseAction() : playNewTrackListFromTrackUuid(song, scope),
|
|
2776
|
-
className: "group flex flex-col items-center gap-1 w-16 text-
|
|
2773
|
+
className: "group flex flex-col items-center gap-1 w-16 text-caption text-center text-[var(--color-text)] focus-visible:outline-none",
|
|
2777
2774
|
children: [
|
|
2778
2775
|
/* @__PURE__ */ (0, import_jsx_runtime43.jsx)("span", { className: "flex items-center justify-center w-10 h-10 rounded-full group-focus-visible:ring-2 group-focus-visible:ring-[var(--color-focus-ring)] bg-[var(--color-surface-muted)] transition-colors group-hover:bg-[var(--color-border)]", children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react15.Pause, { "aria-hidden": "true", className: "w-5 h-5" }) : /* @__PURE__ */ (0, import_jsx_runtime43.jsx)(import_lucide_react15.Play, { "aria-hidden": "true", className: "w-5 h-5" }) }),
|
|
2779
2776
|
isPlaying ? "Pause" : "Play"
|
|
@@ -2797,11 +2794,10 @@ function useSongPanel({
|
|
|
2797
2794
|
getBackendBaseUrl,
|
|
2798
2795
|
getShareUrl,
|
|
2799
2796
|
renderArtistLink,
|
|
2800
|
-
getGenrePath,
|
|
2801
|
-
onSelectGenre,
|
|
2802
2797
|
expanded,
|
|
2803
2798
|
onExpandedChange,
|
|
2804
|
-
onClose
|
|
2799
|
+
onClose,
|
|
2800
|
+
...navigation
|
|
2805
2801
|
}) {
|
|
2806
2802
|
const result = (0, import_genre_tree27.useSong)(uuid, getBackendBaseUrl);
|
|
2807
2803
|
const panel = { expanded, onExpandedChange, onClose };
|
|
@@ -2845,8 +2841,10 @@ function useSongPanel({
|
|
|
2845
2841
|
getBackendBaseUrl,
|
|
2846
2842
|
shareUrl: shareUrl ?? void 0,
|
|
2847
2843
|
renderArtistLink,
|
|
2848
|
-
|
|
2849
|
-
|
|
2844
|
+
...navigation.getGenrePath ? {
|
|
2845
|
+
genrePath: song.genre ? navigation.getGenrePath(song.genre) : [],
|
|
2846
|
+
onSelectGenrePlaylist: navigation.onSelectGenrePlaylist
|
|
2847
|
+
} : { onSelectGenre: navigation.onSelectGenre }
|
|
2850
2848
|
}
|
|
2851
2849
|
)
|
|
2852
2850
|
};
|
|
@@ -2854,6 +2852,37 @@ function useSongPanel({
|
|
|
2854
2852
|
}
|
|
2855
2853
|
}
|
|
2856
2854
|
|
|
2855
|
+
// src/genre-tree/useEntityPanel.tsx
|
|
2856
|
+
function useEntityPanel({
|
|
2857
|
+
scope,
|
|
2858
|
+
getBackendBaseUrl,
|
|
2859
|
+
getArtistBackendBaseUrl,
|
|
2860
|
+
getShareUrl,
|
|
2861
|
+
renderArtistLink,
|
|
2862
|
+
renderSongLink,
|
|
2863
|
+
song,
|
|
2864
|
+
artist,
|
|
2865
|
+
...navigation
|
|
2866
|
+
}) {
|
|
2867
|
+
const songPanel = useSongPanel({
|
|
2868
|
+
...song,
|
|
2869
|
+
scope,
|
|
2870
|
+
getBackendBaseUrl,
|
|
2871
|
+
getShareUrl,
|
|
2872
|
+
renderArtistLink,
|
|
2873
|
+
...navigation
|
|
2874
|
+
});
|
|
2875
|
+
const artistPanel = useArtistPanel({
|
|
2876
|
+
...artist,
|
|
2877
|
+
scope,
|
|
2878
|
+
getBackendBaseUrl: getArtistBackendBaseUrl ?? getBackendBaseUrl,
|
|
2879
|
+
getShareUrl,
|
|
2880
|
+
renderArtistLink,
|
|
2881
|
+
renderSongLink
|
|
2882
|
+
});
|
|
2883
|
+
return songPanel ?? artistPanel;
|
|
2884
|
+
}
|
|
2885
|
+
|
|
2857
2886
|
// src/genre-tree/SizeMetricToggle.tsx
|
|
2858
2887
|
var import_md2 = require("react-icons/md");
|
|
2859
2888
|
var import_ui19 = require("@behindthemusictree/ui");
|
|
@@ -3036,20 +3065,6 @@ function GenreTreeView({
|
|
|
3036
3065
|
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react18.useState)(null);
|
|
3037
3066
|
const artistBaseUrl = artistSearchBaseUrl ?? getBackendBaseUrl;
|
|
3038
3067
|
const songBaseUrl = getBackendBaseUrl;
|
|
3039
|
-
const artistPanel = useArtistPanel({
|
|
3040
|
-
uuid: artistUuid,
|
|
3041
|
-
scope,
|
|
3042
|
-
getBackendBaseUrl: artistBaseUrl,
|
|
3043
|
-
getShareUrl: getShareUrlRef.current,
|
|
3044
|
-
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
3045
|
-
expanded: controlledArtistExpanded ?? (artistUuid !== null && expandedArtistUuid === artistUuid),
|
|
3046
|
-
onExpandedChange: (on) => {
|
|
3047
|
-
if (controlledArtistExpanded === void 0) setExpandedArtistUuid(on ? artistUuid : null);
|
|
3048
|
-
onArtistExpandedChange?.(on);
|
|
3049
|
-
},
|
|
3050
|
-
renderSongLink: resolvedRenderSongLink,
|
|
3051
|
-
onClose: () => changeArtist(null)
|
|
3052
|
-
});
|
|
3053
3068
|
const resolvedRenderArtistLink = renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime46.jsx)("button", { type: "button", onClick: () => openArtist(artist.uuid), className: "hover:underline", children: artist.name }));
|
|
3054
3069
|
const getGenrePath = (genre) => {
|
|
3055
3070
|
const path = [];
|
|
@@ -3061,27 +3076,38 @@ function GenreTreeView({
|
|
|
3061
3076
|
}
|
|
3062
3077
|
return path;
|
|
3063
3078
|
};
|
|
3064
|
-
const
|
|
3065
|
-
uuid: songUuid,
|
|
3079
|
+
const entityPanel = useEntityPanel({
|
|
3066
3080
|
scope,
|
|
3067
3081
|
getBackendBaseUrl: songBaseUrl,
|
|
3082
|
+
getArtistBackendBaseUrl: artistBaseUrl,
|
|
3068
3083
|
getShareUrl: getShareUrlRef.current,
|
|
3069
3084
|
renderArtistLink: resolvedRenderArtistLink,
|
|
3085
|
+
renderSongLink: resolvedRenderSongLink,
|
|
3086
|
+
song: {
|
|
3087
|
+
uuid: songUuid,
|
|
3088
|
+
expanded: controlledSongExpanded ?? (songUuid !== null && expandedSongUuid === songUuid),
|
|
3089
|
+
onExpandedChange: (on) => {
|
|
3090
|
+
if (controlledSongExpanded === void 0) setExpandedSongUuid(on ? songUuid : null);
|
|
3091
|
+
onSongExpandedChange?.(on);
|
|
3092
|
+
},
|
|
3093
|
+
onClose: () => changeSong(null)
|
|
3094
|
+
},
|
|
3095
|
+
artist: {
|
|
3096
|
+
uuid: artistUuid,
|
|
3097
|
+
expanded: controlledArtistExpanded ?? (artistUuid !== null && expandedArtistUuid === artistUuid),
|
|
3098
|
+
onExpandedChange: (on) => {
|
|
3099
|
+
if (controlledArtistExpanded === void 0) setExpandedArtistUuid(on ? artistUuid : null);
|
|
3100
|
+
onArtistExpandedChange?.(on);
|
|
3101
|
+
},
|
|
3102
|
+
onClose: () => changeArtist(null)
|
|
3103
|
+
},
|
|
3070
3104
|
getGenrePath,
|
|
3071
|
-
|
|
3105
|
+
onSelectGenrePlaylist: (genrePlaylist2) => {
|
|
3072
3106
|
changeSong(null);
|
|
3073
3107
|
selectGenrePlaylist(genrePlaylist2);
|
|
3074
|
-
}
|
|
3075
|
-
expanded: controlledSongExpanded ?? (songUuid !== null && expandedSongUuid === songUuid),
|
|
3076
|
-
onExpandedChange: (on) => {
|
|
3077
|
-
if (controlledSongExpanded === void 0) setExpandedSongUuid(on ? songUuid : null);
|
|
3078
|
-
onSongExpandedChange?.(on);
|
|
3079
|
-
},
|
|
3080
|
-
onClose: () => changeSong(null)
|
|
3108
|
+
}
|
|
3081
3109
|
});
|
|
3082
|
-
const
|
|
3083
|
-
const builtInArtistPanel = overlayPanel || selectedGenreUuid !== null || builtInSongPanel ? void 0 : artistPanel;
|
|
3084
|
-
const builtInPanel = builtInSongPanel ?? builtInArtistPanel;
|
|
3110
|
+
const builtInPanel = overlayPanel || selectedGenreUuid !== null ? void 0 : entityPanel;
|
|
3085
3111
|
const [uncontrolledCollapsed, setUncontrolledCollapsed] = (0, import_react18.useState)(false);
|
|
3086
3112
|
const [uncontrolledExpanded, setUncontrolledExpanded] = (0, import_react18.useState)(false);
|
|
3087
3113
|
const isCollapsed = collapsed ?? uncontrolledCollapsed;
|
|
@@ -3252,7 +3278,7 @@ function GenreTreeView({
|
|
|
3252
3278
|
) : null;
|
|
3253
3279
|
const renderArtistFilter = () => {
|
|
3254
3280
|
if (isLoading || !filterArtist) return null;
|
|
3255
|
-
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-
|
|
3281
|
+
return /* @__PURE__ */ (0, import_jsx_runtime46.jsxs)("span", { className: "inline-flex items-center overflow-hidden rounded-full bg-[var(--color-neutral-100)] text-body", children: [
|
|
3256
3282
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3257
3283
|
"button",
|
|
3258
3284
|
{
|
|
@@ -3363,14 +3389,14 @@ function GenreTreeView({
|
|
|
3363
3389
|
/* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3364
3390
|
"div",
|
|
3365
3391
|
{
|
|
3366
|
-
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))] 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"}`,
|
|
3392
|
+
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"}`,
|
|
3367
3393
|
children: actions
|
|
3368
3394
|
}
|
|
3369
3395
|
),
|
|
3370
3396
|
!isLoading && !isError && filterArtist && /* @__PURE__ */ (0, import_jsx_runtime46.jsx)(
|
|
3371
3397
|
"div",
|
|
3372
3398
|
{
|
|
3373
|
-
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))]" : "top-5"}`,
|
|
3399
|
+
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"}`,
|
|
3374
3400
|
children: renderArtistFilter()
|
|
3375
3401
|
}
|
|
3376
3402
|
),
|
|
@@ -3640,7 +3666,7 @@ function TrackListSidebar({
|
|
|
3640
3666
|
/* @__PURE__ */ (0, import_jsx_runtime47.jsx)("div", { className: "from h-auto flex flex-col justify-center items-center mr-2", children: "From" }),
|
|
3641
3667
|
/* @__PURE__ */ (0, import_jsx_runtime47.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_runtime47.jsx)("div", { className: "name max-w-full truncate", children: trackList.origin.label }) })
|
|
3642
3668
|
] }),
|
|
3643
|
-
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "info flex items-center text-
|
|
3669
|
+
/* @__PURE__ */ (0, import_jsx_runtime47.jsxs)("div", { className: "info flex items-center text-body text-[var(--color-text-muted)]", children: [
|
|
3644
3670
|
trackList.origin.type === import_genre_tree30.TrackListOriginType.GENRE_PLAYLIST ? "Genre \u2022 " : trackList.origin.type === import_genre_tree30.TrackListOriginType.ARTIST ? "Artist \u2022 " : `${trackNoun.singular} playlist \u2022 `,
|
|
3645
3671
|
`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular}`
|
|
3646
3672
|
] })
|
|
@@ -3950,12 +3976,76 @@ function Rating({ rating, handleChange }) {
|
|
|
3950
3976
|
) })
|
|
3951
3977
|
] }, i)) });
|
|
3952
3978
|
}
|
|
3979
|
+
|
|
3980
|
+
// src/genre-tree/EntityDetailPanel.tsx
|
|
3981
|
+
var import_react21 = require("react");
|
|
3982
|
+
var import_ui22 = require("@behindthemusictree/ui");
|
|
3983
|
+
var import_jsx_runtime51 = require("react/jsx-runtime");
|
|
3984
|
+
function EntityDetailPanel({
|
|
3985
|
+
scope,
|
|
3986
|
+
getBackendBaseUrl,
|
|
3987
|
+
getArtistBackendBaseUrl,
|
|
3988
|
+
getShareUrl,
|
|
3989
|
+
songUuid,
|
|
3990
|
+
onSongUuidChange,
|
|
3991
|
+
artistUuid,
|
|
3992
|
+
onArtistUuidChange,
|
|
3993
|
+
renderArtistLink,
|
|
3994
|
+
renderSongLink,
|
|
3995
|
+
collapsed,
|
|
3996
|
+
edgeTab,
|
|
3997
|
+
...navigation
|
|
3998
|
+
}) {
|
|
3999
|
+
const [expandedSongUuid, setExpandedSongUuid] = (0, import_react21.useState)(null);
|
|
4000
|
+
const [expandedArtistUuid, setExpandedArtistUuid] = (0, import_react21.useState)(null);
|
|
4001
|
+
const panel = useEntityPanel({
|
|
4002
|
+
scope,
|
|
4003
|
+
getBackendBaseUrl,
|
|
4004
|
+
getArtistBackendBaseUrl,
|
|
4005
|
+
getShareUrl,
|
|
4006
|
+
renderArtistLink: renderArtistLink ?? ((artist) => artist.isSpecialPurpose ? artist.name : /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", onClick: () => onArtistUuidChange(artist.uuid), className: "hover:underline", children: artist.name })),
|
|
4007
|
+
renderSongLink: renderSongLink ?? ((song) => /* @__PURE__ */ (0, import_jsx_runtime51.jsx)("button", { type: "button", onClick: () => onSongUuidChange(song.uuid), className: "hover:underline", children: song.title })),
|
|
4008
|
+
song: {
|
|
4009
|
+
uuid: songUuid,
|
|
4010
|
+
expanded: songUuid !== null && expandedSongUuid === songUuid,
|
|
4011
|
+
onExpandedChange: (on) => setExpandedSongUuid(on ? songUuid : null),
|
|
4012
|
+
onClose: () => onSongUuidChange(null)
|
|
4013
|
+
},
|
|
4014
|
+
artist: {
|
|
4015
|
+
uuid: artistUuid,
|
|
4016
|
+
expanded: artistUuid !== null && expandedArtistUuid === artistUuid,
|
|
4017
|
+
onExpandedChange: (on) => setExpandedArtistUuid(on ? artistUuid : null),
|
|
4018
|
+
onClose: () => onArtistUuidChange(null)
|
|
4019
|
+
},
|
|
4020
|
+
...navigation
|
|
4021
|
+
});
|
|
4022
|
+
if (!panel) return null;
|
|
4023
|
+
return /* @__PURE__ */ (0, import_jsx_runtime51.jsx)(
|
|
4024
|
+
import_ui22.DetailPanel,
|
|
4025
|
+
{
|
|
4026
|
+
side: "left",
|
|
4027
|
+
title: panel.title,
|
|
4028
|
+
titleInSearch: true,
|
|
4029
|
+
onClose: panel.onClose,
|
|
4030
|
+
collapsed,
|
|
4031
|
+
expanded: panel.expanded,
|
|
4032
|
+
onExpandedChange: panel.onExpandedChange,
|
|
4033
|
+
aside: panel.extraContent,
|
|
4034
|
+
edgeTab,
|
|
4035
|
+
children: panel.extraContent && !panel.expanded ? /* @__PURE__ */ (0, import_jsx_runtime51.jsxs)(import_jsx_runtime51.Fragment, { children: [
|
|
4036
|
+
panel.content,
|
|
4037
|
+
panel.extraContent
|
|
4038
|
+
] }) : panel.content
|
|
4039
|
+
}
|
|
4040
|
+
);
|
|
4041
|
+
}
|
|
3953
4042
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3954
4043
|
0 && (module.exports = {
|
|
3955
4044
|
AuthCallbackHandler,
|
|
3956
4045
|
AuthErrorPopup,
|
|
3957
4046
|
AuthPopup,
|
|
3958
4047
|
BasePopup,
|
|
4048
|
+
EntityDetailPanel,
|
|
3959
4049
|
GenreDetailPanel,
|
|
3960
4050
|
GenreInfoPanelBody,
|
|
3961
4051
|
GenreNodeActionBand,
|
|
@@ -3982,6 +4072,7 @@ function Rating({ rating, handleChange }) {
|
|
|
3982
4072
|
TrackUploadPopup,
|
|
3983
4073
|
searchStatus,
|
|
3984
4074
|
useArtistSearchGroup,
|
|
4075
|
+
useEntityPanel,
|
|
3985
4076
|
useGenrePlaylistPlayback,
|
|
3986
4077
|
useGenreRemoteSearchGroup,
|
|
3987
4078
|
useSongSearchGroup
|