@stapel/search-react 0.32.7 → 0.33.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/CHANGELOG.md +72 -0
- package/README.md +66 -3
- package/dist/default/PartitionChips.d.ts +7 -8
- package/dist/default/PartitionChips.d.ts.map +1 -1
- package/dist/default/PartitionChips.js +54 -32
- package/dist/default/PartitionChips.js.map +1 -1
- package/dist/default/SearchPage.d.ts +59 -2
- package/dist/default/SearchPage.d.ts.map +1 -1
- package/dist/default/SearchPage.js +24 -4
- package/dist/default/SearchPage.js.map +1 -1
- package/dist/default/SearchResultsPane.d.ts +55 -0
- package/dist/default/SearchResultsPane.d.ts.map +1 -1
- package/dist/default/SearchResultsPane.js +91 -2
- package/dist/default/SearchResultsPane.js.map +1 -1
- package/dist/default/index.d.ts +3 -3
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js +2 -2
- package/dist/default/index.js.map +1 -1
- package/llms.txt +3 -3
- package/manifest.json +3 -1
- package/nav-manifest.json +1 -1
- package/package.json +4 -4
- package/src/analytics/generated/events.json +1 -1
- package/src/default/PartitionChips.tsx +84 -44
- package/src/default/SearchPage.tsx +73 -1
- package/src/default/SearchResultsPane.tsx +153 -6
- package/src/default/index.ts +3 -0
|
@@ -94,6 +94,7 @@ import { SearchResultsPane } from "./SearchResultsPane.js";
|
|
|
94
94
|
import type {
|
|
95
95
|
ResultsColumns,
|
|
96
96
|
SearchResultsWrapper,
|
|
97
|
+
SearchToolbarPin,
|
|
97
98
|
} from "./SearchResultsPane.js";
|
|
98
99
|
import { SortSelect } from "./SortSelect.js";
|
|
99
100
|
import { SEARCH_BUILTIN_VIEWS, ViewSwitch, resolveView } from "./ViewSwitch.js";
|
|
@@ -283,6 +284,24 @@ const RAIL: CSSProperties = {
|
|
|
283
284
|
paddingBlockEnd: spacing[2],
|
|
284
285
|
};
|
|
285
286
|
|
|
287
|
+
/**
|
|
288
|
+
* The rail with a host's own offset under it.
|
|
289
|
+
*
|
|
290
|
+
* `top` and the height cap move TOGETHER, and that is the whole reason this is
|
|
291
|
+
* a function rather than one property: a rail pushed 64px down the window whose
|
|
292
|
+
* cap is still `100dvh` ends 64px past the foot of the screen, so its last
|
|
293
|
+
* control is unreachable — the internal scroll has scrolled past the window.
|
|
294
|
+
*
|
|
295
|
+
* A number is pixels; a string is taken as written, so
|
|
296
|
+
* `railTop="var(--stapel-header-height)"` reads the height `<PublicShell>`
|
|
297
|
+
* publishes instead of restating it.
|
|
298
|
+
*/
|
|
299
|
+
export function railStyle(top: number | string | undefined): CSSProperties {
|
|
300
|
+
if (top === undefined) return RAIL;
|
|
301
|
+
const offset = typeof top === "number" ? `${String(top)}px` : top;
|
|
302
|
+
return { ...RAIL, top, maxHeight: `calc(100dvh - ${offset})` };
|
|
303
|
+
}
|
|
304
|
+
|
|
286
305
|
/** The results take what is left. `minWidth: 0` so a long word inside a card
|
|
287
306
|
* cannot push the grid wider than its column. */
|
|
288
307
|
const RESULTS_COLUMN: CSSProperties = { flex: "1 1 auto", minWidth: 0 };
|
|
@@ -522,6 +541,50 @@ export interface SearchPageProps extends ThemeModeProp, ParseSearchStateOptions
|
|
|
522
541
|
* rail beside a 110px result column.
|
|
523
542
|
*/
|
|
524
543
|
readonly filtersLayout?: SearchFiltersLayout;
|
|
544
|
+
/**
|
|
545
|
+
* WHERE the filter rail's sticky top edge is — the offset of whatever chrome
|
|
546
|
+
* is pinned above this page.
|
|
547
|
+
*
|
|
548
|
+
* ```tsx
|
|
549
|
+
* // the height <PublicShell> publishes, read rather than restated
|
|
550
|
+
* <SearchPage railTop="var(--stapel-header-height)" />
|
|
551
|
+
* ```
|
|
552
|
+
*
|
|
553
|
+
* The rail is `position: sticky; top: 0` written INLINE, and an inline
|
|
554
|
+
* declaration is beaten by nothing but `!important` — so a host with a fixed
|
|
555
|
+
* header had exactly one way to say "start below it", and the fleet's
|
|
556
|
+
* storefront carried that `!important` as the only one in the repo aimed at a
|
|
557
|
+
* pair's own geometry. Every deployment with a pinned header has this
|
|
558
|
+
* problem; none of them could state it.
|
|
559
|
+
*
|
|
560
|
+
* A number is pixels; a string is taken as written (a `var()`, a `calc()`,
|
|
561
|
+
* `"4rem"`). The internal scroll cap moves with it — see {@link railStyle} —
|
|
562
|
+
* so the rail still ends at the foot of the window rather than that far past
|
|
563
|
+
* it. Default `0`, which is where the rail has always started.
|
|
564
|
+
*
|
|
565
|
+
* The phone SHEET is unaffected: it is a dialog, not a column, and it has no
|
|
566
|
+
* header to clear.
|
|
567
|
+
*/
|
|
568
|
+
readonly railTop?: number | string;
|
|
569
|
+
/**
|
|
570
|
+
* PIN the results toolbar under whatever chrome is above this page — the
|
|
571
|
+
* other column's half of {@link railTop}.
|
|
572
|
+
*
|
|
573
|
+
* ```tsx
|
|
574
|
+
* <SearchPage
|
|
575
|
+
* railTop="var(--stapel-header-height)"
|
|
576
|
+
* stickyToolbar={{ top: "var(--stapel-header-height)" }}
|
|
577
|
+
* />
|
|
578
|
+
* ```
|
|
579
|
+
*
|
|
580
|
+
* Handed straight to `<SearchResultsPane stickyToolbar>`, which pins the row
|
|
581
|
+
* it actually drew — the whole header block in the wide shape, the toolbar
|
|
582
|
+
* alone in the compact one. There is exactly one sort control on a results
|
|
583
|
+
* page and this pins it where it stands; a host that draws a bar of its own
|
|
584
|
+
* over the page ends up with two, and the one a person presses is whichever
|
|
585
|
+
* the layout put under their thumb.
|
|
586
|
+
*/
|
|
587
|
+
readonly stickyToolbar?: SearchToolbarPin;
|
|
525
588
|
/**
|
|
526
589
|
* The host's own exits from an empty result — sibling sections with their
|
|
527
590
|
* counts. A SLOT for the same reason `breadcrumb` is one: walking the tree
|
|
@@ -639,6 +702,8 @@ interface SearchPageBodyProps {
|
|
|
639
702
|
readonly degradationNotice?: DegradationNoticeVariant;
|
|
640
703
|
readonly railFrom?: SearchRailFrom;
|
|
641
704
|
readonly filtersLayout?: SearchFiltersLayout;
|
|
705
|
+
readonly railTop?: number | string;
|
|
706
|
+
readonly stickyToolbar?: SearchToolbarPin;
|
|
642
707
|
readonly defaultFiltersOpen?: boolean;
|
|
643
708
|
readonly pageSize?: boolean;
|
|
644
709
|
readonly breadcrumb?: ReactNode;
|
|
@@ -838,6 +903,9 @@ function SearchPageBody(props: SearchPageBodyProps): ReactElement {
|
|
|
838
903
|
toolbar={toolbar}
|
|
839
904
|
{...(props.resultsLead !== undefined ? { lead: props.resultsLead } : {})}
|
|
840
905
|
{...(phoneToolbar ? { header: "compact" as const } : {})}
|
|
906
|
+
{...(props.stickyToolbar !== undefined
|
|
907
|
+
? { stickyToolbar: props.stickyToolbar }
|
|
908
|
+
: {})}
|
|
841
909
|
headingLevel={props.resultsHeadingLevel ?? 1}
|
|
842
910
|
{...(view.render !== undefined ? { renderResults: view.render } : {})}
|
|
843
911
|
{...(props.wrapResults !== undefined ? { wrapResults: props.wrapResults } : {})}
|
|
@@ -998,7 +1066,7 @@ function SearchPageBody(props: SearchPageBodyProps): ReactElement {
|
|
|
998
1066
|
</>
|
|
999
1067
|
) : showFilters ? (
|
|
1000
1068
|
<Flex align="flex-start" gap={spacing[5]} data-testid="search-page-columns">
|
|
1001
|
-
<div className={RAIL_CLASS} style={
|
|
1069
|
+
<div className={RAIL_CLASS} style={railStyle(props.railTop)}>
|
|
1002
1070
|
{/* The rail's scrollbar, in the gutter and in the token palette —
|
|
1003
1071
|
see `railScrollbarCss`. Hoisted, deduped by `href`. */}
|
|
1004
1072
|
<style href={RAIL_STYLE_HREF} precedence="default">
|
|
@@ -1050,6 +1118,8 @@ export function SearchPage(props: SearchPageProps): ReactElement {
|
|
|
1050
1118
|
degradationNotice,
|
|
1051
1119
|
railFrom,
|
|
1052
1120
|
filtersLayout,
|
|
1121
|
+
railTop,
|
|
1122
|
+
stickyToolbar,
|
|
1053
1123
|
defaultFiltersOpen,
|
|
1054
1124
|
pageSize,
|
|
1055
1125
|
breadcrumb,
|
|
@@ -1102,6 +1172,8 @@ export function SearchPage(props: SearchPageProps): ReactElement {
|
|
|
1102
1172
|
{...(degradationNotice !== undefined ? { degradationNotice } : {})}
|
|
1103
1173
|
{...(railFrom !== undefined ? { railFrom } : {})}
|
|
1104
1174
|
{...(filtersLayout !== undefined ? { filtersLayout } : {})}
|
|
1175
|
+
{...(railTop !== undefined ? { railTop } : {})}
|
|
1176
|
+
{...(stickyToolbar !== undefined ? { stickyToolbar } : {})}
|
|
1105
1177
|
{...(defaultFiltersOpen !== undefined ? { defaultFiltersOpen } : {})}
|
|
1106
1178
|
{...(pageSize !== undefined ? { pageSize } : {})}
|
|
1107
1179
|
{...(breadcrumb !== undefined ? { breadcrumb } : {})}
|
|
@@ -35,7 +35,7 @@ import {
|
|
|
35
35
|
SkinTheme,
|
|
36
36
|
visuallyHidden,
|
|
37
37
|
} from "@stapel/tokens-antd/skin";
|
|
38
|
-
import { breakpoints, spacing } from "@stapel/tokens";
|
|
38
|
+
import { breakpoints, cssVar, spacing } from "@stapel/tokens";
|
|
39
39
|
import type { FeatureDef } from "@stapel/attributes-react";
|
|
40
40
|
import type { SearchItem } from "../api/types.js";
|
|
41
41
|
import { SearchResults } from "../headless/SearchResults.js";
|
|
@@ -109,6 +109,101 @@ export type SearchResultsWrapper = (
|
|
|
109
109
|
*/
|
|
110
110
|
export const RESULTS_MAX_WIDTH = 1400;
|
|
111
111
|
|
|
112
|
+
/**
|
|
113
|
+
* The class on the row that carries the results toolbar — the sort control, the
|
|
114
|
+
* view switch, the page size, the count and the surface's own action.
|
|
115
|
+
*
|
|
116
|
+
* The row had no element of its own: no class, no `data-testid`, and in the
|
|
117
|
+
* compact header it was one child of a 112px vertical stack. A host that wanted
|
|
118
|
+
* it pinned under a fixed header therefore had to reach it with a `:has()` on
|
|
119
|
+
* the heading beside it, a `display: contents` to drop the stack's box, and the
|
|
120
|
+
* pane's own breakpoint restated in a media query — three rules aimed at a
|
|
121
|
+
* shape the pane could change under them at any release.
|
|
122
|
+
*
|
|
123
|
+
* It is the same class in BOTH header shapes, and in both it names the row that
|
|
124
|
+
* would pin: the WIDE header block (heading, count and toolbar on one line —
|
|
125
|
+
* the block IS the row) and, in `header="compact"`, the toolbar alone, because
|
|
126
|
+
* pinning the compact stack would put ~112px of chrome under a 56px header on a
|
|
127
|
+
* 390px screen.
|
|
128
|
+
*/
|
|
129
|
+
export const RESULTS_TOOLBAR_CLASS = "stapel-search-results-toolbar";
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* Where {@link SearchResultsPaneProps.stickyToolbar} pins the row.
|
|
133
|
+
*
|
|
134
|
+
* `top` is a CSS length — a number is pixels, a string is taken as written, so
|
|
135
|
+
* `top: "var(--stapel-header-height)"` reads the height `<PublicShell>`
|
|
136
|
+
* publishes rather than restating it. Default `0`.
|
|
137
|
+
*/
|
|
138
|
+
export interface SearchToolbarPin {
|
|
139
|
+
readonly top?: number | string;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The controls' own line: it may not become two.
|
|
144
|
+
*
|
|
145
|
+
* A wrapping row changes height when the count lands — the count arrives with
|
|
146
|
+
* the answer, one render after the toolbar was already on screen — and a bar
|
|
147
|
+
* that grows while it is pinned pushes the first cards of the feed down under
|
|
148
|
+
* the reader's eye. `nowrap` makes the height a constant; `min-inline-size: 0`
|
|
149
|
+
* plus `overflow-x: auto` is what a row that cannot wrap does with the overflow
|
|
150
|
+
* instead, which on a phone is the scroll strip every sort row already is.
|
|
151
|
+
*/
|
|
152
|
+
const TOOLBAR_ROW: CSSProperties = {
|
|
153
|
+
flexWrap: "nowrap",
|
|
154
|
+
minInlineSize: 0,
|
|
155
|
+
overflowX: "auto",
|
|
156
|
+
// Thin, and only when there is something to scroll to — the same reason the
|
|
157
|
+
// filter rail states its own: an invisible scroll port is indistinguishable
|
|
158
|
+
// from a row that ends where it was cut.
|
|
159
|
+
scrollbarWidth: "thin",
|
|
160
|
+
};
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* The compact header's stack, WITHOUT its box.
|
|
164
|
+
*
|
|
165
|
+
* `position: sticky` travels inside its parent, so a toolbar nested in a 112px
|
|
166
|
+
* stack can move 112px and no further — the parent has to be the results
|
|
167
|
+
* column, which is as tall as the feed. `display: contents` drops the stack's
|
|
168
|
+
* box and hands its three rows straight to that column, which is the same
|
|
169
|
+
* device the fleet's storefront was writing in its own sheet.
|
|
170
|
+
*
|
|
171
|
+
* The one visible consequence: the gap between heading, toolbar and count
|
|
172
|
+
* becomes the column's rather than the stack's.
|
|
173
|
+
*/
|
|
174
|
+
const COMPACT_STACK: CSSProperties = { display: "contents" };
|
|
175
|
+
|
|
176
|
+
/** The compact shape's toolbar box — the row the pin acts on. */
|
|
177
|
+
const COMPACT_TOOLBAR: CSSProperties = {
|
|
178
|
+
display: "flex",
|
|
179
|
+
alignItems: "center",
|
|
180
|
+
...TOOLBAR_ROW,
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* The pin itself, and it is NET-ZERO in flow: `position` and a layer and a
|
|
185
|
+
* background, and not one pixel of padding.
|
|
186
|
+
*
|
|
187
|
+
* A pinned bar that grows padding to breathe over the cards passing under it
|
|
188
|
+
* has to take the same padding back as negative margin or the column pays for
|
|
189
|
+
* it, and the pair does not know which of those two a host's spacing wants. A
|
|
190
|
+
* row that occupies exactly the box it already occupied cannot shift anything.
|
|
191
|
+
*/
|
|
192
|
+
function toolbarPinStyle(pin: SearchToolbarPin | undefined): CSSProperties | undefined {
|
|
193
|
+
if (pin === undefined) return undefined;
|
|
194
|
+
return {
|
|
195
|
+
position: "sticky",
|
|
196
|
+
top: pin.top ?? 0,
|
|
197
|
+
// Over the cards, under the page's own chrome — and under antd's popups,
|
|
198
|
+
// so the sort select still opens over its own bar.
|
|
199
|
+
zIndex: 1,
|
|
200
|
+
// Opaque, or the cards scroll THROUGH the bar. The theme's own surface
|
|
201
|
+
// role, resolved at paint time, so it follows the brand and the dark side
|
|
202
|
+
// without a second colour being written here.
|
|
203
|
+
background: cssVar("surface"),
|
|
204
|
+
};
|
|
205
|
+
}
|
|
206
|
+
|
|
112
207
|
/**
|
|
113
208
|
* The results grid. `auto-fill` + `minmax(260px, 1fr)`: as many columns as fit,
|
|
114
209
|
* each at least a readable card and never wider than its share — and the same
|
|
@@ -396,6 +491,33 @@ export interface SearchResultsPaneProps extends ThemeModeProp {
|
|
|
396
491
|
* viewport is not spent saying "Results" over a list of results.
|
|
397
492
|
*/
|
|
398
493
|
readonly header?: "banner" | "compact";
|
|
494
|
+
/**
|
|
495
|
+
* PIN the toolbar row under whatever chrome is above this pane.
|
|
496
|
+
*
|
|
497
|
+
* ```tsx
|
|
498
|
+
* // the height <PublicShell> publishes, read rather than restated
|
|
499
|
+
* <SearchResultsPane stickyToolbar={{ top: "var(--stapel-header-height)" }} />
|
|
500
|
+
* ```
|
|
501
|
+
*
|
|
502
|
+
* A catalogue page is thirty cards long and the control that reorders them is
|
|
503
|
+
* at the top of it, so by the fourth row the sort is a screenful above the
|
|
504
|
+
* list it sorts — the same argument that made the filter rail sticky, applied
|
|
505
|
+
* to the other column.
|
|
506
|
+
*
|
|
507
|
+
* It pins the row the pane ACTUALLY DREW, which is why this is a prop and not
|
|
508
|
+
* a host's stylesheet: the pane knows which of its two header shapes it is in
|
|
509
|
+
* and a sheet has to guess. In `"banner"` the whole header block pins (it is
|
|
510
|
+
* one line: heading, count, toolbar). In `"compact"` the toolbar alone pins —
|
|
511
|
+
* one row, the height of one phone control — because the stack it sits in is
|
|
512
|
+
* ~112px and that is not a bar anybody can pin under a 56px header.
|
|
513
|
+
*
|
|
514
|
+
* Two things it does NOT do, both deliberate: it adds no padding (see
|
|
515
|
+
* {@link toolbarPinStyle} — a pinned bar that grows to breathe has to give
|
|
516
|
+
* the room back, and which spacing that is belongs to the host), and it draws
|
|
517
|
+
* no second sort control. There is exactly one on a results page, and this
|
|
518
|
+
* pins it where it stands.
|
|
519
|
+
*/
|
|
520
|
+
readonly stickyToolbar?: SearchToolbarPin;
|
|
399
521
|
/**
|
|
400
522
|
* The category's feature schema, used ONLY to name an applied filter in the
|
|
401
523
|
* empty state's exits ("Without Brand" rather than "Without vendor").
|
|
@@ -503,6 +625,7 @@ export function SearchResultsPane(props: SearchResultsPaneProps): ReactElement {
|
|
|
503
625
|
// The compact arm's caption: the host's word is drawn, the pair's own is
|
|
504
626
|
// not, and `headingVisible` overrides either way — see that prop.
|
|
505
627
|
const compactHeadingSeen = props.headingVisible ?? props.heading !== undefined;
|
|
628
|
+
const toolbarPin = toolbarPinStyle(props.stickyToolbar);
|
|
506
629
|
const columnRules =
|
|
507
630
|
props.columns === undefined || props.layout === "list"
|
|
508
631
|
? null
|
|
@@ -542,7 +665,15 @@ export function SearchResultsPane(props: SearchResultsPaneProps): ReactElement {
|
|
|
542
665
|
<div data-testid="search-results-lead">{props.lead}</div>
|
|
543
666
|
)}
|
|
544
667
|
{props.header === "compact" ? (
|
|
545
|
-
|
|
668
|
+
/* No box of its own — see `COMPACT_STACK`. The three rows are
|
|
669
|
+
items of the results COLUMN, so the toolbar between them has a
|
|
670
|
+
parent as tall as the feed to travel in. */
|
|
671
|
+
<Flex
|
|
672
|
+
vertical
|
|
673
|
+
gap={spacing[2]}
|
|
674
|
+
style={COMPACT_STACK}
|
|
675
|
+
data-testid="search-results-header-compact"
|
|
676
|
+
>
|
|
546
677
|
<Typography.Title
|
|
547
678
|
level={props.headingLevel ?? 4}
|
|
548
679
|
style={compactHeadingSeen ? { margin: 0 } : visuallyHidden}
|
|
@@ -551,19 +682,35 @@ export function SearchResultsPane(props: SearchResultsPaneProps): ReactElement {
|
|
|
551
682
|
>
|
|
552
683
|
{props.heading ?? t(SEARCH_I18N_KEYS.resultsTitle)}
|
|
553
684
|
</Typography.Title>
|
|
554
|
-
|
|
685
|
+
<div
|
|
686
|
+
className={RESULTS_TOOLBAR_CLASS}
|
|
687
|
+
data-testid="search-results-toolbar"
|
|
688
|
+
style={{ ...COMPACT_TOOLBAR, ...toolbarPin }}
|
|
689
|
+
>
|
|
690
|
+
{props.toolbar}
|
|
691
|
+
</div>
|
|
555
692
|
<Count bag={bag} />
|
|
556
693
|
</Flex>
|
|
557
694
|
) : (
|
|
558
|
-
|
|
695
|
+
/* The wide shape's header block IS the toolbar row: one line,
|
|
696
|
+
heading at one end, count and controls at the other, and a
|
|
697
|
+
direct child of the results column — so it pins as it stands. */
|
|
698
|
+
<Flex
|
|
699
|
+
justify="space-between"
|
|
700
|
+
align="center"
|
|
701
|
+
gap={spacing[2]}
|
|
702
|
+
className={RESULTS_TOOLBAR_CLASS}
|
|
703
|
+
data-testid="search-results-toolbar"
|
|
704
|
+
{...(toolbarPin !== undefined ? { style: toolbarPin } : {})}
|
|
705
|
+
>
|
|
559
706
|
<Typography.Title
|
|
560
707
|
level={props.headingLevel ?? 4}
|
|
561
|
-
style={{ margin: 0 }}
|
|
708
|
+
style={{ margin: 0, minInlineSize: 0 }}
|
|
562
709
|
data-testid="search-results-heading"
|
|
563
710
|
>
|
|
564
711
|
{props.heading ?? t(SEARCH_I18N_KEYS.resultsTitle)}
|
|
565
712
|
</Typography.Title>
|
|
566
|
-
<Flex align="center"
|
|
713
|
+
<Flex align="center" gap={spacing[3]} style={TOOLBAR_ROW}>
|
|
567
714
|
<Count bag={bag} />
|
|
568
715
|
{props.toolbar}
|
|
569
716
|
</Flex>
|
package/src/default/index.ts
CHANGED
|
@@ -45,6 +45,7 @@ export {
|
|
|
45
45
|
RAIL_CLASS,
|
|
46
46
|
RAIL_STYLE_HREF,
|
|
47
47
|
railScrollbarCss,
|
|
48
|
+
railStyle,
|
|
48
49
|
} from "./SearchPage.js";
|
|
49
50
|
export type {
|
|
50
51
|
SearchPageProps,
|
|
@@ -73,6 +74,7 @@ export {
|
|
|
73
74
|
RESULTS_AUTO_FILL_COLUMNS,
|
|
74
75
|
RESULTS_COLUMNS_CLASS,
|
|
75
76
|
RESULTS_COLUMNS_STYLE_HREF,
|
|
77
|
+
RESULTS_TOOLBAR_CLASS,
|
|
76
78
|
resultsColumnsCss,
|
|
77
79
|
} from "./SearchResultsPane.js";
|
|
78
80
|
export type {
|
|
@@ -80,6 +82,7 @@ export type {
|
|
|
80
82
|
SearchResultsPaneProps,
|
|
81
83
|
SearchResultsRenderer,
|
|
82
84
|
SearchResultsWrapper,
|
|
85
|
+
SearchToolbarPin,
|
|
83
86
|
} from "./SearchResultsPane.js";
|
|
84
87
|
|
|
85
88
|
export {
|