@behindthemusictree/app-kit-ui 33.3.0 → 34.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  import * as react from 'react';
2
- import { ReactNode, ComponentProps } from 'react';
2
+ import { ReactNode, ComponentType, ComponentProps } from 'react';
3
3
  import { z } from 'zod';
4
4
  import { GenreTreeProps, FocusChangeReason, GenreTreeNode, GenreTreeAction, GenreTreeViewMode, GenreTreeViewport, WheelZoomMode } from '@behindthemusictree/genre-tree-view';
5
5
  export { FocusChangeReason, GenreTreeAction, GenreTreeOutlineSkeleton, GenreTreeSkeleton, GenreTreeViewMode, GenreTreeViewSkeleton, GenreTreeViewSkeletonProps, GenreTreeViewport, GenreTreeWheelSkeleton } from '@behindthemusictree/genre-tree-view';
6
- import { TrackBase, CriteriaOverview, GenreUuid, CriteriaPlaylistMinimum, RenderArtistLink, RenderSongLink, CriteriaPlaylistSimple, ArtistSearchResult, SongSearchResult, UseGenreRemoteSearchOptions, GenreSearchResult, GenrePlaylistUuid, CriteriaMinimum } from '@behindthemusictree/app-kit/genre-tree';
6
+ import { TrackBase, CriteriaOverview, GenreUuid, CriteriaPlaylistMinimum, GenreMusicSelection, RenderArtistLink, RenderSongLink, CriteriaPlaylistSimple, ArtistSearchResult, SongSearchResult, UseGenreRemoteSearchOptions, GenreSearchResult, GenrePlaylistUuid, CriteriaMinimum, GenreCatalogueCounts, GenrePlaylistSummary } from '@behindthemusictree/app-kit/genre-tree';
7
7
  import { Scope } from '@behindthemusictree/app-kit/transport';
8
8
  import { DetailPanel } from '@behindthemusictree/ui';
9
9
 
@@ -25,6 +25,7 @@ type GenreDetailSlots<O extends CriteriaOverview> = {
25
25
  type GenreDetailExtrasProps<O extends CriteriaOverview> = GenreDetailSlots<O> & GenrePlaylistTracksSlots & {
26
26
  genreUuid: GenreUuid;
27
27
  genrePlaylist: CriteriaPlaylistMinimum;
28
+ selection?: GenreMusicSelection;
28
29
  wikidataId?: string | null;
29
30
  scope: Scope;
30
31
  getBackendBaseUrl: () => string;
@@ -60,11 +61,9 @@ type HostOverlayPanel = Omit<OverlayPanel, "expanded" | "onExpandedChange"> & {
60
61
  /** The host-owned detail panel's contract with the tree: the area the panel covers, and the node-style resolver the tree publishes back. */
61
62
  type HostPanelProps = Partial<Pick<GenreTreeProps, "obscuredInset" | "onNodeStyleResolverChange">>;
62
63
 
63
- /** What a play button needs of a playlist; `criteria` is only read when playing one artist's songs in the genre. */
64
64
  type PlayableGenrePlaylistInput = CriteriaPlaylistMinimum & {
65
65
  criteria?: CriteriaPlaylistSimple["criteria"];
66
66
  };
67
- /** What a tree node's play button plays, and which node is the one currently playing. */
68
67
  type GenrePlaylistPlayback = {
69
68
  playingNodeId: string | null;
70
69
  play: (genrePlaylist: PlayableGenrePlaylistInput) => Promise<void>;
@@ -72,7 +71,6 @@ type GenrePlaylistPlayback = {
72
71
  type UseGenrePlaylistPlaybackOptions = {
73
72
  scope: Scope;
74
73
  genrePlaylists: CriteriaPlaylistSimple[];
75
- /** When set, nodes play only this artist's songs in the genre's subtree instead of the whole genre playlist. */
76
74
  artist?: {
77
75
  uuid: string;
78
76
  name: string;
@@ -155,6 +153,33 @@ type UseGenreRemoteSearchGroupOptions = UseGenreRemoteSearchOptions & {
155
153
  /** Genres from the API's ranked `genres/search/`, rendered with the umbrella tag and the tree they live in. */
156
154
  declare function useGenreRemoteSearchGroup(getBaseUrl: () => string, text: string, onSelect: (genre: GenreSearchResult) => void, { key, label, filter, describe, ...options }?: UseGenreRemoteSearchGroupOptions): SearchGroup;
157
155
 
156
+ /** @deprecated Use `SearchGroup`. */
157
+ type GenreSearchExtraGroup = SearchGroup;
158
+ type GenreSearchProps<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple> = {
159
+ genrePlaylists: T[];
160
+ onSelect: (genrePlaylist: T) => void;
161
+ /** Name of the currently selected genre; fills the input whenever it changes. */
162
+ selectedName?: string | null;
163
+ /** When set, renders a "Previous" button left of the text and makes room for it. */
164
+ onPrevious?: () => void;
165
+ /** Called by the clear button, after it empties the input. */
166
+ onClear?: () => void;
167
+ placeholder?: string;
168
+ /** Called with what the user types, and with "" on clear or pick; never when `selectedName` refills the input. */
169
+ onQueryChange?: (query: string) => void;
170
+ /** Further result groups (places, artists, songs) the host resolves from `onQueryChange`. */
171
+ extraGroups?: SearchGroup[];
172
+ /** Called when the input gains focus. */
173
+ onFocus?: () => void;
174
+ };
175
+ declare function GenreSearch<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple>({ genrePlaylists, onSelect, selectedName, onClear, onPrevious, placeholder, onQueryChange, extraGroups, onFocus, }: GenreSearchProps<T>): react.JSX.Element;
176
+
177
+ interface GenreSearchGroupsProps {
178
+ query: string;
179
+ focused: boolean;
180
+ children: (groups: SearchGroup[]) => ReactNode;
181
+ }
182
+
158
183
  type ParentChange = {
159
184
  genre: GenreUuid;
160
185
  from: GenreUuid | null;
@@ -227,6 +252,8 @@ type GenreTreeViewProps<O extends CriteriaOverview = CriteriaOverview> = {
227
252
  readOnly?: boolean;
228
253
  /** Further result groups (e.g. places) shown in the search box next to genres, artists and songs. */
229
254
  extraSearchGroups?: SearchGroup[];
255
+ /** Host search hooks run inside this subtree, so typing does not rerender the tree page. */
256
+ SearchGroups?: ComponentType<GenreSearchGroupsProps>;
230
257
  /** Fires with the typed search text (empty when cleared), so a host can drive its own `extraSearchGroups`. */
231
258
  onSearchQueryChange?: (text: string) => void;
232
259
  /** Fires when the search box gains focus, e.g. to load data for `extraSearchGroups` lazily. */
@@ -290,7 +317,7 @@ type GenreTreeViewProps<O extends CriteriaOverview = CriteriaOverview> = {
290
317
  collapsed?: boolean;
291
318
  onCollapsedChange?: (collapsed: boolean) => void;
292
319
  };
293
- declare function GenreTreeView<O extends CriteriaOverview = CriteriaOverview>({ scope, handleGenreCreationAction, handleGenreRenameAction, onParentChanged, getBackendBaseUrl, additionalActions, viewMode: controlledViewMode, selectedNodeId: controlledSelectedNodeId, onSelectedNodeIdChange, defaultViewport, viewportRestore, onViewportChange, readOnly, className, showDisplayOptions, showAddRoot, allowWheelRotation: controlledAllowWheelRotation, criteriaOverviewSchema, renderGenreDetailExtras, floatingControlsLeading, sizeMetric: controlledSizeMetric, onSizeMetricChange, renderArtistLink, artistUuid: controlledArtistUuid, onArtistUuidChange, artistExpanded: controlledArtistExpanded, onArtistExpandedChange, getShareUrl, extraSearchGroups, onSearchQueryChange, onSearchFocus, artistSearch, onArtistSelect, artistSearchBaseUrl, songUuid: controlledSongUuid, onSongUuidChange, songExpanded: controlledSongExpanded, onSongExpandedChange, songSearch, onSongSelect, renderSongLink, renderSummary, renderEssentialTracks, renderSongLeading, renderSongActions, renderTracksToolbar, renderDangerZone, expanded, onExpandedChange, collapsed, onCollapsedChange, overlayPanel, placement, ...focus }: GenreTreeViewProps<O>): react.JSX.Element;
320
+ declare function GenreTreeView<O extends CriteriaOverview = CriteriaOverview>({ scope, handleGenreCreationAction, handleGenreRenameAction, onParentChanged, getBackendBaseUrl, additionalActions, viewMode: controlledViewMode, selectedNodeId: controlledSelectedNodeId, onSelectedNodeIdChange, defaultViewport, viewportRestore, onViewportChange, readOnly, className, showDisplayOptions, showAddRoot, allowWheelRotation: controlledAllowWheelRotation, criteriaOverviewSchema, renderGenreDetailExtras, floatingControlsLeading, sizeMetric: controlledSizeMetric, onSizeMetricChange, renderArtistLink, artistUuid: controlledArtistUuid, onArtistUuidChange, artistExpanded: controlledArtistExpanded, onArtistExpandedChange, getShareUrl, extraSearchGroups, SearchGroups, onSearchQueryChange, onSearchFocus, artistSearch, onArtistSelect, artistSearchBaseUrl, songUuid: controlledSongUuid, onSongUuidChange, songExpanded: controlledSongExpanded, onSongExpandedChange, songSearch, onSongSelect, renderSongLink, renderSummary, renderEssentialTracks, renderSongLeading, renderSongActions, renderTracksToolbar, renderDangerZone, expanded, onExpandedChange, collapsed, onCollapsedChange, overlayPanel, placement, ...focus }: GenreTreeViewProps<O>): react.JSX.Element;
294
321
 
295
322
  type GenreActionBandProps = {
296
323
  node: GenreTreeNode;
@@ -317,9 +344,9 @@ type GenreActionBandProps = {
317
344
  declare function GenreActionBand({ node, onPlayPause, isPlaying, onZoomIn, onAddChild, onRename, onChangeParent, side, onToggleSide, toggleSideDisabledReason, additionalActions, shareTarget, shareUrl, }: GenreActionBandProps): react.JSX.Element | null;
318
345
 
319
346
  /** What the action band reads of a genre's playlist: enough to play it and to know whether it can be. */
320
- type PlayableGenrePlaylist = CriteriaPlaylistMinimum & {
347
+ type PlayableGenrePlaylist = (CriteriaPlaylistMinimum & {
321
348
  tracksCount: number;
322
- };
349
+ }) | GenrePlaylistSummary;
323
350
  type GenreNodeActionBandProps = Omit<ComponentProps<typeof GenreActionBand>, "onPlayPause" | "isPlaying"> & {
324
351
  genrePlaylist: PlayableGenrePlaylist;
325
352
  playback: GenrePlaylistPlayback;
@@ -330,6 +357,7 @@ type GenreInfoPanelBodyProps<O extends CriteriaOverview> = {
330
357
  toolbar?: ReactNode;
331
358
  family: ReactNode;
332
359
  genreUuid: GenreUuid;
360
+ catalogue?: GenreCatalogueCounts;
333
361
  genrePlaylist: PlayableGenrePlaylist;
334
362
  wikidataId?: string | null;
335
363
  scope: Scope;
@@ -341,7 +369,7 @@ type GenreInfoPanelBodyProps<O extends CriteriaOverview> = {
341
369
  };
342
370
  /** The body of a genre's info panel: action band, then the genre's overview, family and tracks.
343
371
  * Shared by the tree's panel and the standalone GenreDetailPanel. */
344
- declare function GenreInfoPanelBody<O extends CriteriaOverview>({ toolbar, family, genreUuid, genrePlaylist, wikidataId, scope, getBackendBaseUrl, playback, band, extras, }: GenreInfoPanelBodyProps<O>): react.JSX.Element;
372
+ declare function GenreInfoPanelBody<O extends CriteriaOverview>({ toolbar, family, genreUuid, genrePlaylist, catalogue, wikidataId, scope, getBackendBaseUrl, playback, band, extras, }: GenreInfoPanelBodyProps<O>): react.JSX.Element;
345
373
 
346
374
  type GenreDetailPanelProps<O extends CriteriaOverview> = {
347
375
  genreUuid: GenreUuid;
@@ -393,27 +421,6 @@ type GenrePlaylistTreePerRootProps<T extends TrackBase> = {
393
421
  } & HostPanelProps;
394
422
  declare function GenrePlaylistTreePerRoot<T extends TrackBase>({ scope, className, rootUuid, genrePlaylistTreePerRoot, handleGenreCreationAction, handleGenreRenameAction, additionalActions, onNodeClick, onNodeHover, selectedNodeId, onSelectedNodeChange, readOnly, wheelZoom, defaultViewport, viewportRestore, onViewportChange, playback, ...hostPanel }: GenrePlaylistTreePerRootProps<T>): react.JSX.Element;
395
423
 
396
- /** @deprecated Use `SearchGroup`. */
397
- type GenreSearchExtraGroup = SearchGroup;
398
- type GenreSearchProps<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple> = {
399
- genrePlaylists: T[];
400
- onSelect: (genrePlaylist: T) => void;
401
- /** Name of the currently selected genre; fills the input whenever it changes. */
402
- selectedName?: string | null;
403
- /** When set, renders a "Previous" button left of the text and makes room for it. */
404
- onPrevious?: () => void;
405
- /** Called by the clear button, after it empties the input. */
406
- onClear?: () => void;
407
- placeholder?: string;
408
- /** Called with what the user types, and with "" on clear or pick; never when `selectedName` refills the input. */
409
- onQueryChange?: (query: string) => void;
410
- /** Further result groups (places, artists, songs) the host resolves from `onQueryChange`. */
411
- extraGroups?: SearchGroup[];
412
- /** Called when the input gains focus. */
413
- onFocus?: () => void;
414
- };
415
- declare function GenreSearch<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple>({ genrePlaylists, onSelect, selectedName, onClear, onPrevious, placeholder, onQueryChange, extraGroups, onFocus, }: GenreSearchProps<T>): react.JSX.Element;
416
-
417
424
  interface TrackListSidebarProps<T extends TrackBase> {
418
425
  className?: string;
419
426
  renderDuration?: (track: T) => ReactNode;
@@ -472,4 +479,4 @@ interface RatingProps {
472
479
  }
473
480
  declare function Rating({ rating, handleChange }: RatingProps): react.JSX.Element;
474
481
 
475
- export { type ArtistSearchProps, GenreDetailPanel, type GenreDetailPanelProps, type GenreDetailSlots, type GenreFocusProps, GenreInfoPanelBody, type GenreInfoPanelBodyProps, GenreNodeActionBand, type GenrePlaylistPlayback, type GenrePlaylistTracksSlots, GenrePlaylistTreePerRoot, type GenrePlaylistTreePerRootProps, GenreSearch, type GenreSearchExtraGroup, type GenreSearchProps, type GenreTreeShareTarget, GenreTreeView, type GenreTreeViewProps, type GetGenreTreeShareUrl, type ParentChange, type PlayableGenrePlaylist, PlayerPanel, type PlayerPanelProps, Rating, type RatingProps, SEARCH_FAILED_STATUS, SearchBox, type SearchBoxProps, type SearchGroup, type SearchGroupItem, TrackItem, type TrackItemProps, TrackListSidebar, type TrackListSidebarProps, TrackPositionPlayPause, type TrackPositionPlayPauseProps, type UseGenrePlaylistPlaybackOptions, type UseGenreRemoteSearchGroupOptions, searchStatus, useArtistSearchGroup, useGenrePlaylistPlayback, useGenreRemoteSearchGroup, useSongSearchGroup };
482
+ export { type ArtistSearchProps, GenreDetailPanel, type GenreDetailPanelProps, type GenreDetailSlots, type GenreFocusProps, GenreInfoPanelBody, type GenreInfoPanelBodyProps, GenreNodeActionBand, type GenrePlaylistPlayback, type GenrePlaylistTracksSlots, GenrePlaylistTreePerRoot, type GenrePlaylistTreePerRootProps, GenreSearch, type GenreSearchExtraGroup, type GenreSearchGroupsProps, type GenreSearchProps, type GenreTreeShareTarget, GenreTreeView, type GenreTreeViewProps, type GetGenreTreeShareUrl, type ParentChange, type PlayableGenrePlaylist, PlayerPanel, type PlayerPanelProps, Rating, type RatingProps, SEARCH_FAILED_STATUS, SearchBox, type SearchBoxProps, type SearchGroup, type SearchGroupItem, TrackItem, type TrackItemProps, TrackListSidebar, type TrackListSidebarProps, TrackPositionPlayPause, type TrackPositionPlayPauseProps, type UseGenrePlaylistPlaybackOptions, type UseGenreRemoteSearchGroupOptions, searchStatus, useArtistSearchGroup, useGenrePlaylistPlayback, useGenreRemoteSearchGroup, useSongSearchGroup };
@@ -21,7 +21,7 @@ import {
21
21
  useGenrePlaylistPlayback,
22
22
  useGenreRemoteSearchGroup,
23
23
  useSongSearchGroup
24
- } from "../chunk-QMELESFB.js";
24
+ } from "../chunk-JP7PID7L.js";
25
25
  import "../chunk-DKQQLLMY.js";
26
26
  export {
27
27
  GenreDetailPanel,