diff --git a/CHANGELOG.md b/CHANGELOG.md index 10f9c15..f05b144 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,10 +15,13 @@ easy to spot when bumping. - `GenreTreeView` (wheel, pop-core): genre-tree-view's "Previous" button now sits inside the search field, left of the genre name, and fades in sliding from the left; the field's left padding widens to make room. - `GenreActionBand`: Google Maps-style band under the detail panel header (icon over label) holding Play/Pause, Focus, Add, Rename, Parent and the `additionalActions`; genre-tree-view's own toolbar and its ⋮ menu are hidden. +- `TrackNounProvider` / `useTrackNoun()` (`@behindthemusictree/app-kit/track-noun`) and a `capitalize` helper: the app supplies the noun its UI uses for tracks (`{ singular, plural }`). ### Breaking - `GenreSearch`: `onZoomIn`, `onPlayPause` and `isPlaying` are removed; those actions moved to the detail panel's action band. The search icon now sits right of the field's text, left of the clear button. +- App-kit-ui components no longer hardcode "track(s)": `TrackListSidebar`, `GenreDetailExtras` (the "Essential …" heading), `GenrePlaylistTracks`, `TrackUploadPopup` and the genre tree components read the noun from `useTrackNoun()`, which throws outside a `TrackNounProvider`. Wrap the app in `` (grow) or `singular="track" plural="tracks"` (hear). +- Requires `@behindthemusictree/genre-tree-view` 3.0.0; the tree components pass it `itemCountLabel` (e.g. "Song count"). ## [13.5.0] - 2026-10-26 diff --git a/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.test.tsx b/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.test.tsx index ea8ef68..2cf6255 100644 --- a/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.test.tsx +++ b/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.test.tsx @@ -1,5 +1,6 @@ import { describe, it, expect, vi, beforeEach } from "vitest"; -import { render, screen } from "@testing-library/react"; +import { screen } from "@testing-library/react"; +import { render } from "../test-utils"; const { useFetchGenreOverviewMock, tracksPropsMock } = vi.hoisted(() => ({ useFetchGenreOverviewMock: vi.fn(), diff --git a/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.tsx b/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.tsx index 4212b16..6ba1d23 100644 --- a/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.tsx +++ b/packages/app-kit-ui/src/genre-tree/GenreDetailExtras.tsx @@ -9,11 +9,12 @@ import { useFetchGenreOverview } from "@behindthemusictree/app-kit/genre-tree"; import { CriteriaPlaylistMinimum } from "@behindthemusictree/app-kit/genre-tree"; import { GenrePlaylistTracks, type GenrePlaylistTracksSlots } from "./GenrePlaylistTracks"; import { RenderArtistLink } from "@behindthemusictree/app-kit/genre-tree"; +import { useTrackNoun } from "@behindthemusictree/app-kit/track-noun"; export type GenreDetailSlots = { /** Replaces the default Summary section. */ renderSummary?: (overview: O) => ReactNode; - /** Replaces the default Essential tracks section. */ + /** Replaces the default Essential section (e.g. "Essential songs"). */ renderEssentialTracks?: (overview: O) => ReactNode; }; @@ -41,6 +42,7 @@ export function GenreDetailExtras({ renderEssentialTracks, ...trackSlots }: GenreDetailExtrasProps) { + const trackNoun = useTrackNoun(); const { data: overview, isPending } = useFetchGenreOverview( genreUuid, scope, @@ -87,7 +89,7 @@ export function GenreDetailExtras({ ) : ( essentialTracks && (
- Essential tracks + Essential {trackNoun.plural} {essentialTracks.length > 0 ? (
    {essentialTracks.map((track) => ( diff --git a/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.test.tsx b/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.test.tsx index dc760bc..fdaf827 100644 --- a/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.test.tsx +++ b/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.test.tsx @@ -1,5 +1,6 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; -import { render, screen, fireEvent, act } from "@testing-library/react"; +import { screen, fireEvent, act } from "@testing-library/react"; +import { render } from "../test-utils"; import { QueryClient, QueryClientProvider } from "@tanstack/react-query"; const { useTrackListMock, usePlayerMock, fetchMock, showPopupMock } = vi.hoisted(() => ({ diff --git a/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.tsx b/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.tsx index d3cb42a..8c7dc3e 100644 --- a/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.tsx +++ b/packages/app-kit-ui/src/genre-tree/GenrePlaylistTracks.tsx @@ -24,6 +24,7 @@ import { isRecording, recordingUnplayableReason, RecordingDetailedSchema } from import { GenrePlaylistTracksPage, useTrackList } from "@behindthemusictree/app-kit/genre-tree"; import { MusicBrainzRecordingLink } from "./MusicBrainzRecordingLink"; import { ArtistNames, RenderArtistLink } from "@behindthemusictree/app-kit/genre-tree"; +import { capitalize, useTrackNoun } from "@behindthemusictree/app-kit/track-noun"; const CATALOGUE_PAGE_SIZE = 100; // withTotal=false: the backend skips COUNT(*) and pages by keyset cursor, so huge genre subtrees @@ -87,6 +88,7 @@ export function GenrePlaylistTracks({ const { session, sessionRestored } = useSession(); const { playerTrackObject, playState, handlePlayPauseAction } = usePlayer(); const { showPopup } = usePopup(); + const trackNoun = useTrackNoun(); const { uuid } = genrePlaylist; const { fetch } = useFetchWrapper(getBackendBaseUrl); @@ -139,13 +141,13 @@ export function GenrePlaylistTracks({ return (
    - Tracks{total !== undefined && ` (${total})`} + {capitalize(trackNoun.plural)}{total !== undefined && ` (${total})`} {renderTracksToolbar?.()} {isPending ? (
    ) : isError && tracks.length === 0 ? (

    - Couldn't load tracks.{" "} + Couldn't load {trackNoun.plural}.{" "} @@ -153,7 +155,7 @@ export function GenrePlaylistTracks({ ) : tracks.length === 0 ? (

    —

    ) : ( -
      +
        {tracks.map((track, index) => { const label = track.artists?.length ? `${track.title} — ${track.artists.map((artist) => artist.name).join(", ")}` diff --git a/packages/app-kit-ui/src/genre-tree/GenreTreeView.test.tsx b/packages/app-kit-ui/src/genre-tree/GenreTreeView.test.tsx index 8f6c163..bd4d131 100644 --- a/packages/app-kit-ui/src/genre-tree/GenreTreeView.test.tsx +++ b/packages/app-kit-ui/src/genre-tree/GenreTreeView.test.tsx @@ -1,5 +1,6 @@ import { describe, it, expect, beforeEach, afterEach, vi } from "vitest"; -import { render, screen, fireEvent, act, cleanup, waitFor } from "@testing-library/react"; +import { screen, fireEvent, act, cleanup, waitFor } from "@testing-library/react"; +import { render } from "../test-utils"; import { z } from "zod"; const { diff --git a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.test.tsx b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.test.tsx index 4699c1c..9f6ef81 100644 --- a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.test.tsx +++ b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.test.tsx @@ -1,4 +1,4 @@ -import { render } from "@testing-library/react"; +import { render } from "../../test-utils"; import { describe, expect, it, vi, beforeEach } from "vitest"; import GenrePlaylistTreePerRoot from "./TreePerRoot"; diff --git a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.tsx b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.tsx index 032dff6..9882b47 100644 --- a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.tsx +++ b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreePerRoot.tsx @@ -23,6 +23,7 @@ import { CriteriaPlaylistSimple } from "@behindthemusictree/app-kit/genre-tree"; import { CriteriaMinimum } from "@behindthemusictree/app-kit/genre-tree"; import { Scope } from "@behindthemusictree/app-kit/transport"; import type { InfoPanelCurationProps } from "./infoPanelCurationProps"; +import { capitalize, useTrackNoun } from "@behindthemusictree/app-kit/track-noun"; export type GenrePlaylistTreePerRootProps = { scope: Scope; @@ -82,6 +83,7 @@ export default function GenrePlaylistTreePerRoot({ }: GenrePlaylistTreePerRootProps) { const { isPlaying, setIsPlaying } = usePlayer(); const { trackList, playNewTrackListFromGenrePlaylist } = useTrackList(); + const trackNoun = useTrackNoun(); const { showPopup } = usePopup(); const nodes: GenreTreeNode[] = useMemo( @@ -171,6 +173,7 @@ export default function GenrePlaylistTreePerRoot({ = { scope: Scope; @@ -80,6 +81,7 @@ export default function GenrePlaylistTreeWheel({ }: GenrePlaylistTreeWheelProps) { const { isPlaying, setIsPlaying } = usePlayer(); const { trackList, playNewTrackListFromGenrePlaylist } = useTrackList(); + const trackNoun = useTrackNoun(); const { showPopup } = usePopup(); const nodes: GenreTreeNode[] = useMemo( @@ -168,6 +170,7 @@ export default function GenrePlaylistTreeWheel({ ({ ...(await importOriginal>()), diff --git a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.test.tsx b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.test.tsx index a80710a..c86a16f 100644 --- a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.test.tsx +++ b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.test.tsx @@ -1,5 +1,5 @@ import { describe, it, expect, beforeEach, vi } from "vitest"; -import { render } from "@testing-library/react"; +import { render } from "../../test-utils"; const { genreTreeWheelRadialPopCorePropsMock, diff --git a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.tsx b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.tsx index 96595b9..9114c33 100644 --- a/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.tsx +++ b/packages/app-kit-ui/src/genre-tree/playlist-tree/TreeWheelRadialPopCore.tsx @@ -20,6 +20,7 @@ import { CriteriaPlaylistSimple } from "@behindthemusictree/app-kit/genre-tree"; import { CriteriaMinimum } from "@behindthemusictree/app-kit/genre-tree"; import { Scope } from "@behindthemusictree/app-kit/transport"; import type { InfoPanelCurationProps } from "./infoPanelCurationProps"; +import { capitalize, useTrackNoun } from "@behindthemusictree/app-kit/track-noun"; /** Pop-core focus is controlled-only: pass both props or neither. Ignored in outline mode. */ export type GenreFocusProps = @@ -112,6 +113,7 @@ export default function GenrePlaylistTreeWheelRadialPopCore }; const { isPlaying, setIsPlaying } = usePlayer(); const { trackList, playNewTrackListFromGenrePlaylist } = useTrackList(); + const trackNoun = useTrackNoun(); const nodes: GenreTreeNode[] = useMemo( () => @@ -191,6 +193,7 @@ export default function GenrePlaylistTreeWheelRadialPopCore const treeProps = { className, nodes, + itemCountLabel: `${capitalize(trackNoun.singular)} count`, playingNodeId, playState: isPlaying ? ("playing" as const) : ("paused" as const), reparentingNodeId: reparentingGenreUuid, diff --git a/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.test.tsx b/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.test.tsx index c073172..aa4e249 100644 --- a/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.test.tsx +++ b/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.test.tsx @@ -1,5 +1,7 @@ import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"; -import { render, screen, fireEvent } from "@testing-library/react"; +import { screen, fireEvent } from "@testing-library/react"; +import { render } from "../../test-utils"; +import { TrackNounProvider } from "@behindthemusictree/app-kit/track-noun"; const { useTrackListMock, useTrackListSidebarVisibilityMock } = vi.hoisted(() => ({ useTrackListMock: vi.fn(), @@ -84,6 +86,25 @@ describe("TrackListSidebar", () => { expect(screen.getByText(/1 track /)).toBeInTheDocument(); }); + it("uses the noun supplied by the TrackNounProvider", () => { + useTrackListMock.mockReturnValue({ + trackList: makeTrackList({ + origin: { label: "Single Track", type: TrackListOriginType.TRACK }, + tracks: [{ uuid: "t1", title: "Only Song" }], + total: 2, + }), + }); + + render( + + + , + ); + + expect(screen.getByText(/song playlist/)).toBeInTheDocument(); + expect(screen.getByText(/2 songs /)).toBeInTheDocument(); + }); + it("labels an artist origin and passes renderArtistLink to each track", () => { useTrackListMock.mockReturnValue({ trackList: makeTrackList({ origin: { label: "Miles Davis", type: TrackListOriginType.ARTIST } }), diff --git a/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.tsx b/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.tsx index 3ebbb66..60fcc63 100644 --- a/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.tsx +++ b/packages/app-kit-ui/src/genre-tree/track-list-sidebar/TrackListSidebar.tsx @@ -8,6 +8,7 @@ import { useTrackListSidebarVisibility } from "@behindthemusictree/app-kit/genre import { TrackListOriginType } from "@behindthemusictree/app-kit/genre-tree"; import { TrackBase } from "@behindthemusictree/app-kit/genre-tree"; import { RenderArtistLink } from "@behindthemusictree/app-kit/genre-tree"; +import { useTrackNoun } from "@behindthemusictree/app-kit/track-noun"; export interface TrackListSidebarProps { className?: string; @@ -26,6 +27,7 @@ export default function TrackListSidebar({ renderArtistLink, }: TrackListSidebarProps) { const { trackList, loadMore } = useTrackList(); + const trackNoun = useTrackNoun(); const loadMoreSentinelRef = useRef(null); const hasMore = !!trackList && trackList.nextPage !== null; @@ -64,8 +66,8 @@ export default function TrackListSidebar({ ? "• Genre playlist • " : trackList.origin.type === TrackListOriginType.ARTIST ? "• Artist • " - : "• track playlist • "} - {trackList.total + " track" + (trackList.total > 1 ? "s •" : " •")} + : `• ${trackNoun.singular} playlist • `} + {`${trackList.total} ${trackList.total > 1 ? trackNoun.plural : trackNoun.singular} •`}
    void; reject: (reason: Error) => void }; diff --git a/packages/app-kit-ui/src/popup/TrackUploadPopup.tsx b/packages/app-kit-ui/src/popup/TrackUploadPopup.tsx index 8eea081..0aec2a1 100644 --- a/packages/app-kit-ui/src/popup/TrackUploadPopup.tsx +++ b/packages/app-kit-ui/src/popup/TrackUploadPopup.tsx @@ -3,6 +3,7 @@ import { MdError, MdCheckCircle, MdUpload } from "react-icons/md"; import { useTrackUpload, type UploadStatus, type UseTrackUploadOptions } from "@behindthemusictree/app-kit/popup"; import { BasePopup, BasePopupProps } from "./BasePopup"; +import { capitalize, useTrackNoun } from "@behindthemusictree/app-kit/track-noun"; type TrackUploadPopupProps = Omit & UseTrackUploadOptions & { @@ -53,12 +54,13 @@ export default function TrackUploadPopup({ }); const displayTotal = items.length > 0 ? items.length : files.length; + const trackNoun = useTrackNoun(); return ( + {children} + + ); +} + +export function render(ui: ReactElement, options?: Omit): RenderResult { + return rtlRender(ui, { wrapper: TrackNounWrapper, ...options }); +} diff --git a/packages/app-kit/package.json b/packages/app-kit/package.json index 3e934a7..b567b9f 100644 --- a/packages/app-kit/package.json +++ b/packages/app-kit/package.json @@ -34,6 +34,11 @@ "import": "./dist/popup/index.js", "require": "./dist/popup/index.cjs" }, + "./track-noun": { + "types": "./dist/track-noun/index.d.ts", + "import": "./dist/track-noun/index.js", + "require": "./dist/track-noun/index.cjs" + }, "./player": { "types": "./dist/player/index.d.ts", "import": "./dist/player/index.js", diff --git a/packages/app-kit/src/index.ts b/packages/app-kit/src/index.ts index 47cce18..8d294a4 100644 --- a/packages/app-kit/src/index.ts +++ b/packages/app-kit/src/index.ts @@ -1,5 +1,6 @@ export * from "./transport"; export * from "./auth"; export * from "./popup"; +export * from "./track-noun"; export * from "./player"; export * from "./genre-tree"; diff --git a/packages/app-kit/src/track-noun/TrackNounContext.test.tsx b/packages/app-kit/src/track-noun/TrackNounContext.test.tsx new file mode 100644 index 0000000..4635ab6 --- /dev/null +++ b/packages/app-kit/src/track-noun/TrackNounContext.test.tsx @@ -0,0 +1,28 @@ +import { renderHook } from "@testing-library/react"; +import { describe, expect, it, vi } from "vitest"; +import { capitalize, TrackNounProvider, useTrackNoun } from "./TrackNounContext"; + +describe("useTrackNoun", () => { + it("returns the noun supplied by the provider", () => { + const { result } = renderHook(() => useTrackNoun(), { + wrapper: ({ children }) => ( + + {children} + + ), + }); + expect(result.current).toEqual({ singular: "song", plural: "songs" }); + }); + + it("throws without a provider", () => { + const errorSpy = vi.spyOn(console, "error").mockImplementation(() => undefined); + expect(() => renderHook(() => useTrackNoun())).toThrow("useTrackNoun must be used within a TrackNounProvider"); + errorSpy.mockRestore(); + }); +}); + +describe("capitalize", () => { + it("uppercases the first letter", () => { + expect(capitalize("song")).toBe("Song"); + }); +}); diff --git a/packages/app-kit/src/track-noun/TrackNounContext.tsx b/packages/app-kit/src/track-noun/TrackNounContext.tsx new file mode 100644 index 0000000..abbd07d --- /dev/null +++ b/packages/app-kit/src/track-noun/TrackNounContext.tsx @@ -0,0 +1,31 @@ +"use client"; + +import { createContext, useContext, useMemo, ReactNode } from "react"; + +export interface TrackNoun { + singular: string; + plural: string; +} + +const TrackNounContext = createContext(undefined); + +interface TrackNounProviderProps extends TrackNoun { + children: ReactNode; +} + +export function TrackNounProvider({ singular, plural, children }: TrackNounProviderProps) { + const value = useMemo(() => ({ singular, plural }), [singular, plural]); + return {children}; +} + +export function useTrackNoun() { + const context = useContext(TrackNounContext); + if (context === undefined) { + throw new Error("useTrackNoun must be used within a TrackNounProvider"); + } + return context; +} + +export function capitalize(word: string) { + return word.charAt(0).toUpperCase() + word.slice(1); +} diff --git a/packages/app-kit/src/track-noun/index.test.ts b/packages/app-kit/src/track-noun/index.test.ts new file mode 100644 index 0000000..21fa274 --- /dev/null +++ b/packages/app-kit/src/track-noun/index.test.ts @@ -0,0 +1,10 @@ +import { describe, it, expect } from "vitest"; + +import * as trackNoun from "./index"; + +describe("track-noun barrel", () => { + it("re-exports the package's public track-noun surface", () => { + expect(trackNoun.TrackNounProvider).toBeTypeOf("function"); + expect(trackNoun.useTrackNoun).toBeTypeOf("function"); + }); +}); diff --git a/packages/app-kit/src/track-noun/index.ts b/packages/app-kit/src/track-noun/index.ts new file mode 100644 index 0000000..7eac475 --- /dev/null +++ b/packages/app-kit/src/track-noun/index.ts @@ -0,0 +1 @@ +export * from "./TrackNounContext"; diff --git a/packages/app-kit/tsup.config.ts b/packages/app-kit/tsup.config.ts index 10f2d9a..6ee7c9d 100644 --- a/packages/app-kit/tsup.config.ts +++ b/packages/app-kit/tsup.config.ts @@ -5,6 +5,7 @@ const entry = { "transport/index": "src/transport/index.ts", "auth/index": "src/auth/index.ts", "popup/index": "src/popup/index.ts", + "track-noun/index": "src/track-noun/index.ts", "player/index": "src/player/index.ts", "genre-tree/index": "src/genre-tree/index.ts", }; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d982235..ecd270c 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -10,8 +10,8 @@ catalogs: specifier: ^12.0.0 version: 12.0.0 '@behindthemusictree/genre-tree-view': - specifier: 2.9.0 - version: 2.9.0 + specifier: 3.0.0 + version: 3.0.0 '@behindthemusictree/ui': specifier: ^0.2.0 version: 0.2.0 @@ -45,7 +45,7 @@ importers: version: 12.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@behindthemusictree/genre-tree-view': specifier: 'catalog:' - version: 2.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) '@behindthemusictree/ui': specifier: 'catalog:' version: 0.2.0(@behindthemusictree/brand@12.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1))(react-dom@18.3.1(react@18.3.1))(react@18.3.1) @@ -149,7 +149,7 @@ importers: dependencies: '@behindthemusictree/genre-tree-view': specifier: 'catalog:' - version: 2.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) + version: 3.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1) clsx: specifier: ^2.1.1 version: 2.1.1 @@ -341,8 +341,8 @@ packages: react: '>=18.0.0' react-dom: '>=18.0.0' - '@behindthemusictree/genre-tree-view@2.9.0': - resolution: {integrity: sha512-6q/kfwvFJJ946tzaPOyRJcKmaa/I5SzwiVu+eGsSegO7NyrEFu/PrFcju+X8Q4WwZmU345/fM3RjB1Z70V53uA==, tarball: https://npm.pkg.github.com/download/@behindthemusictree/genre-tree-view/2.9.0/dd6991cb65b34f71e62882b0ac9935af5719b210} + '@behindthemusictree/genre-tree-view@3.0.0': + resolution: {integrity: sha512-vv+3O/JU+ziPjh77wbrHjfrMR7bl0fkpKzLwHRqYxaV9p2Fwgxqirp9VTiOHGZZ7NnTW6y4U9zJh/A9lgBOxIA==, tarball: https://npm.pkg.github.com/download/@behindthemusictree/genre-tree-view/3.0.0/78cfb8b9ce7edc2feab294757fc01bb26ece619e} peerDependencies: react: '>=18.0.0' react-dom: '>=18.0.0' @@ -2308,7 +2308,7 @@ snapshots: react: 18.3.1 react-dom: 18.3.1(react@18.3.1) - '@behindthemusictree/genre-tree-view@2.9.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': + '@behindthemusictree/genre-tree-view@3.0.0(react-dom@18.3.1(react@18.3.1))(react@18.3.1)': dependencies: d3: 7.9.0 react: 18.3.1 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index f6f0ec3..bed85eb 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -4,7 +4,7 @@ packages: catalog: "@behindthemusictree/brand": ^12.0.0 - "@behindthemusictree/genre-tree-view": "2.9.0" + "@behindthemusictree/genre-tree-view": "3.0.0" "@behindthemusictree/ui": ^0.2.0 allowBuilds: