@behindthemusictree/app-kit-ui 33.0.0 → 33.2.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.
@@ -3,7 +3,7 @@ import { ReactNode, 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, GenrePlaylistUuid, ArtistSearchResult, CriteriaMinimum, SongSearchResult } from '@behindthemusictree/app-kit/genre-tree';
6
+ import { TrackBase, CriteriaOverview, GenreUuid, CriteriaPlaylistMinimum, RenderArtistLink, RenderSongLink, CriteriaPlaylistSimple, ArtistSearchResult, SongSearchResult, UseGenreRemoteSearchOptions, GenreSearchResult, GenrePlaylistUuid, CriteriaMinimum } from '@behindthemusictree/app-kit/genre-tree';
7
7
  import { Scope } from '@behindthemusictree/app-kit/transport';
8
8
  import { DetailPanel } from '@behindthemusictree/ui';
9
9
 
@@ -97,6 +97,64 @@ type GenreFocusProps = {
97
97
  onFocusGenreChange: (uuid: string | null, reason: FocusChangeReason) => void;
98
98
  };
99
99
 
100
+ type SearchGroupItem = {
101
+ key: string;
102
+ content: ReactNode;
103
+ onSelect: () => void;
104
+ };
105
+ /** One headed list of results in a `SearchBox`, resolved by the host or by a group hook. */
106
+ type SearchGroup = {
107
+ key: string;
108
+ /** Heading of the group; omitted when it is the only one. */
109
+ label?: string;
110
+ items: SearchGroupItem[];
111
+ /** Announced politely, e.g. "No artists found". */
112
+ status?: string;
113
+ /** Shows a spinner in place of the search icon while this group resolves. */
114
+ loading?: boolean;
115
+ };
116
+ declare const SEARCH_FAILED_STATUS = "Search failed";
117
+ /** "Search failed" on error, "No <noun> found" once settled and empty, else "". */
118
+ declare const searchStatus: (state: {
119
+ isError: boolean;
120
+ settled: boolean;
121
+ }, count: number, noun: string) => string;
122
+
123
+ type SearchBoxProps = {
124
+ /** Accessible name of the input and the list. */
125
+ label: string;
126
+ placeholder?: string;
127
+ value: string;
128
+ onValueChange: (value: string) => void;
129
+ groups: SearchGroup[];
130
+ /** Called after the group item is picked and the list closed. */
131
+ onPicked?: (groupKey: string, itemKey: string) => void;
132
+ /** Shows the clear button when set. */
133
+ onClear?: () => void;
134
+ /** An action left of the text, e.g. a Previous button. */
135
+ leading?: ReactNode;
136
+ className?: string;
137
+ /** Called when the input gains focus, e.g. to load an index lazily. */
138
+ onFocus?: () => void;
139
+ };
140
+ /** A search pill over any number of result groups; picking an item calls that item's `onSelect`. */
141
+ declare function SearchBox({ label, placeholder, value, onValueChange, groups, onPicked, onClear, leading, className, onFocus, }: SearchBoxProps): react.JSX.Element;
142
+
143
+ declare function useArtistSearchGroup(getBaseUrl: () => string, text: string, onSelect: (artist: ArtistSearchResult) => void, enabled?: boolean): SearchGroup | undefined;
144
+
145
+ declare function useSongSearchGroup(getBaseUrl: () => string, text: string, onSelect: (song: SongSearchResult) => void, enabled?: boolean): SearchGroup | undefined;
146
+
147
+ type UseGenreRemoteSearchGroupOptions = UseGenreRemoteSearchOptions & {
148
+ key?: string;
149
+ label?: string;
150
+ /** Drops hits the host already lists elsewhere. */
151
+ filter?: (genre: GenreSearchResult) => boolean;
152
+ /** Extra secondary text per hit, e.g. the region. */
153
+ describe?: (genre: GenreSearchResult) => string | undefined;
154
+ };
155
+ /** Genres from the API's ranked `genres/search/`, rendered with the umbrella tag and the tree they live in. */
156
+ declare function useGenreRemoteSearchGroup(getBaseUrl: () => string, text: string, onSelect: (genre: GenreSearchResult) => void, { key, label, filter, describe, ...options }?: UseGenreRemoteSearchGroupOptions): SearchGroup;
157
+
100
158
  type ParentChange = {
101
159
  genre: GenreUuid;
102
160
  from: GenreUuid | null;
@@ -167,6 +225,8 @@ type GenreTreeViewProps<O extends CriteriaOverview = CriteriaOverview> = {
167
225
  /** When true, hides the "Add root" button and suppresses per-node
168
226
  * create/rename affordances, for a read-only consumer. Defaults to false. */
169
227
  readOnly?: boolean;
228
+ /** Further result groups (e.g. places) shown in the search box next to genres, artists and songs. */
229
+ extraSearchGroups?: SearchGroup[];
170
230
  /** Root element classes; the component adds no outer margin. */
171
231
  className?: string;
172
232
  /** Shows the "Tree display options" group (e.g. Rotation). Defaults to true. */
@@ -226,7 +286,7 @@ type GenreTreeViewProps<O extends CriteriaOverview = CriteriaOverview> = {
226
286
  collapsed?: boolean;
227
287
  onCollapsedChange?: (collapsed: boolean) => void;
228
288
  };
229
- 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, 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;
289
+ 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, 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;
230
290
 
231
291
  type GenreActionBandProps = {
232
292
  node: GenreTreeNode;
@@ -329,20 +389,8 @@ type GenrePlaylistTreePerRootProps<T extends TrackBase> = {
329
389
  } & HostPanelProps;
330
390
  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;
331
391
 
332
- type GenreSearchExtraGroup = {
333
- key: string;
334
- /** Heading of this group; genre matches then get a "Genres" heading too. */
335
- label: string;
336
- items: {
337
- key: string;
338
- content: ReactNode;
339
- onSelect: () => void;
340
- }[];
341
- /** Announced politely, e.g. "No artists found". */
342
- status?: string;
343
- /** Shows a spinner in place of the search icon while the host resolves this group. */
344
- loading?: boolean;
345
- };
392
+ /** @deprecated Use `SearchGroup`. */
393
+ type GenreSearchExtraGroup = SearchGroup;
346
394
  type GenreSearchProps<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple> = {
347
395
  genrePlaylists: T[];
348
396
  onSelect: (genrePlaylist: T) => void;
@@ -355,10 +403,12 @@ type GenreSearchProps<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple>
355
403
  placeholder?: string;
356
404
  /** Called with what the user types, and with "" on clear or pick; never when `selectedName` refills the input. */
357
405
  onQueryChange?: (query: string) => void;
358
- /** Further result groups (artists, songs) the host resolves from `onQueryChange`. */
359
- extraGroups?: GenreSearchExtraGroup[];
406
+ /** Further result groups (places, artists, songs) the host resolves from `onQueryChange`. */
407
+ extraGroups?: SearchGroup[];
408
+ /** Called when the input gains focus. */
409
+ onFocus?: () => void;
360
410
  };
361
- declare function GenreSearch<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple>({ genrePlaylists, onSelect, selectedName, onClear, onPrevious, placeholder, onQueryChange, extraGroups, }: GenreSearchProps<T>): react.JSX.Element;
411
+ declare function GenreSearch<T extends CriteriaPlaylistSimple = CriteriaPlaylistSimple>({ genrePlaylists, onSelect, selectedName, onClear, onPrevious, placeholder, onQueryChange, extraGroups, onFocus, }: GenreSearchProps<T>): react.JSX.Element;
362
412
 
363
413
  interface TrackListSidebarProps<T extends TrackBase> {
364
414
  className?: string;
@@ -418,4 +468,4 @@ interface RatingProps {
418
468
  }
419
469
  declare function Rating({ rating, handleChange }: RatingProps): react.JSX.Element;
420
470
 
421
- 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, TrackItem, type TrackItemProps, TrackListSidebar, type TrackListSidebarProps, TrackPositionPlayPause, type TrackPositionPlayPauseProps, type UseGenrePlaylistPlaybackOptions, useGenrePlaylistPlayback };
471
+ 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 };
@@ -11,11 +11,17 @@ import {
11
11
  GenreTreeWheelSkeleton,
12
12
  PlayerPanel,
13
13
  Rating,
14
+ SEARCH_FAILED_STATUS,
15
+ SearchBox,
14
16
  TrackItem,
15
17
  TrackListSidebar,
16
18
  TrackPositionPlayPause,
17
- useGenrePlaylistPlayback
18
- } from "../chunk-GHFKICEB.js";
19
+ searchStatus,
20
+ useArtistSearchGroup,
21
+ useGenrePlaylistPlayback,
22
+ useGenreRemoteSearchGroup,
23
+ useSongSearchGroup
24
+ } from "../chunk-FHGQGTCN.js";
19
25
  import "../chunk-DKQQLLMY.js";
20
26
  export {
21
27
  GenreDetailPanel,
@@ -30,9 +36,15 @@ export {
30
36
  GenreTreeWheelSkeleton,
31
37
  PlayerPanel,
32
38
  Rating,
39
+ SEARCH_FAILED_STATUS,
40
+ SearchBox,
33
41
  TrackItem,
34
42
  TrackListSidebar,
35
43
  TrackPositionPlayPause,
36
- useGenrePlaylistPlayback
44
+ searchStatus,
45
+ useArtistSearchGroup,
46
+ useGenrePlaylistPlayback,
47
+ useGenreRemoteSearchGroup,
48
+ useSongSearchGroup
37
49
  };
38
50
  //# sourceMappingURL=index.js.map