@stapel/search-react 0.4.0 → 0.8.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.
Files changed (154) hide show
  1. package/CHANGELOG.md +191 -0
  2. package/README.md +1 -1
  3. package/dist/default/DegradationNotice.d.ts +7 -0
  4. package/dist/default/DegradationNotice.d.ts.map +1 -1
  5. package/dist/default/DegradationNotice.js +17 -6
  6. package/dist/default/DegradationNotice.js.map +1 -1
  7. package/dist/default/FacetGroupControl.d.ts +40 -0
  8. package/dist/default/FacetGroupControl.d.ts.map +1 -0
  9. package/dist/default/FacetGroupControl.js +176 -0
  10. package/dist/default/FacetGroupControl.js.map +1 -0
  11. package/dist/default/FacetPanelPane.d.ts +54 -3
  12. package/dist/default/FacetPanelPane.d.ts.map +1 -1
  13. package/dist/default/FacetPanelPane.js +116 -22
  14. package/dist/default/FacetPanelPane.js.map +1 -1
  15. package/dist/default/FilterChips.d.ts +28 -0
  16. package/dist/default/FilterChips.d.ts.map +1 -0
  17. package/dist/default/FilterChips.js +204 -0
  18. package/dist/default/FilterChips.js.map +1 -0
  19. package/dist/default/LanguageSelect.d.ts +9 -0
  20. package/dist/default/LanguageSelect.d.ts.map +1 -0
  21. package/dist/default/LanguageSelect.js +72 -0
  22. package/dist/default/LanguageSelect.js.map +1 -0
  23. package/dist/default/PageSizeSelect.d.ts +29 -0
  24. package/dist/default/PageSizeSelect.d.ts.map +1 -0
  25. package/dist/default/PageSizeSelect.js +25 -0
  26. package/dist/default/PageSizeSelect.js.map +1 -0
  27. package/dist/default/RangeFilterRow.d.ts +12 -0
  28. package/dist/default/RangeFilterRow.d.ts.map +1 -0
  29. package/dist/default/RangeFilterRow.js +75 -0
  30. package/dist/default/RangeFilterRow.js.map +1 -0
  31. package/dist/default/RankingDisclosurePane.d.ts +5 -0
  32. package/dist/default/RankingDisclosurePane.d.ts.map +1 -1
  33. package/dist/default/RankingDisclosurePane.js +15 -15
  34. package/dist/default/RankingDisclosurePane.js.map +1 -1
  35. package/dist/default/SearchBox.d.ts +13 -0
  36. package/dist/default/SearchBox.d.ts.map +1 -0
  37. package/dist/default/SearchBox.js +67 -0
  38. package/dist/default/SearchBox.js.map +1 -0
  39. package/dist/default/SearchPage.d.ts +94 -16
  40. package/dist/default/SearchPage.d.ts.map +1 -1
  41. package/dist/default/SearchPage.js +191 -8
  42. package/dist/default/SearchPage.js.map +1 -1
  43. package/dist/default/SearchResultCard.d.ts +19 -18
  44. package/dist/default/SearchResultCard.d.ts.map +1 -1
  45. package/dist/default/SearchResultCard.js +178 -5
  46. package/dist/default/SearchResultCard.js.map +1 -1
  47. package/dist/default/SearchResultsPane.d.ts +61 -3
  48. package/dist/default/SearchResultsPane.d.ts.map +1 -1
  49. package/dist/default/SearchResultsPane.js +51 -21
  50. package/dist/default/SearchResultsPane.js.map +1 -1
  51. package/dist/default/SortSelect.d.ts +10 -2
  52. package/dist/default/SortSelect.d.ts.map +1 -1
  53. package/dist/default/SortSelect.js +27 -24
  54. package/dist/default/SortSelect.js.map +1 -1
  55. package/dist/default/UrlIssueNotice.d.ts.map +1 -1
  56. package/dist/default/UrlIssueNotice.js +19 -1
  57. package/dist/default/UrlIssueNotice.js.map +1 -1
  58. package/dist/default/ViewSwitch.d.ts +66 -0
  59. package/dist/default/ViewSwitch.d.ts.map +1 -0
  60. package/dist/default/ViewSwitch.js +49 -0
  61. package/dist/default/ViewSwitch.js.map +1 -0
  62. package/dist/default/index.d.ts +38 -15
  63. package/dist/default/index.d.ts.map +1 -1
  64. package/dist/default/index.js +29 -12
  65. package/dist/default/index.js.map +1 -1
  66. package/dist/default/sortLabels.d.ts +5 -0
  67. package/dist/default/sortLabels.d.ts.map +1 -0
  68. package/dist/default/sortLabels.js +32 -0
  69. package/dist/default/sortLabels.js.map +1 -0
  70. package/dist/headless/FacetPanel.d.ts +17 -0
  71. package/dist/headless/FacetPanel.d.ts.map +1 -1
  72. package/dist/headless/FacetPanel.js +23 -2
  73. package/dist/headless/FacetPanel.js.map +1 -1
  74. package/dist/headless/useAppliedCount.d.ts +8 -0
  75. package/dist/headless/useAppliedCount.d.ts.map +1 -0
  76. package/dist/headless/useAppliedCount.js +30 -0
  77. package/dist/headless/useAppliedCount.js.map +1 -0
  78. package/dist/headless/useScorerNames.d.ts +4 -0
  79. package/dist/headless/useScorerNames.d.ts.map +1 -0
  80. package/dist/headless/useScorerNames.js +34 -0
  81. package/dist/headless/useScorerNames.js.map +1 -0
  82. package/dist/headless/useSearchBox.d.ts +44 -0
  83. package/dist/headless/useSearchBox.d.ts.map +1 -0
  84. package/dist/headless/useSearchBox.js +116 -0
  85. package/dist/headless/useSearchBox.js.map +1 -0
  86. package/dist/i18n/es.d.ts.map +1 -1
  87. package/dist/i18n/es.js +38 -4
  88. package/dist/i18n/es.js.map +1 -1
  89. package/dist/i18n/keys.d.ts +55 -0
  90. package/dist/i18n/keys.d.ts.map +1 -1
  91. package/dist/i18n/keys.js +101 -4
  92. package/dist/i18n/keys.js.map +1 -1
  93. package/dist/i18n/ru.d.ts.map +1 -1
  94. package/dist/i18n/ru.js +42 -4
  95. package/dist/i18n/ru.js.map +1 -1
  96. package/dist/index.d.ts +7 -2
  97. package/dist/index.d.ts.map +1 -1
  98. package/dist/index.js +5 -2
  99. package/dist/index.js.map +1 -1
  100. package/dist/model/queries.d.ts +26 -2
  101. package/dist/model/queries.d.ts.map +1 -1
  102. package/dist/model/queries.js +38 -1
  103. package/dist/model/queries.js.map +1 -1
  104. package/dist/state/limits.d.ts +44 -0
  105. package/dist/state/limits.d.ts.map +1 -0
  106. package/dist/state/limits.js +44 -0
  107. package/dist/state/limits.js.map +1 -0
  108. package/dist/state/ranges.d.ts +52 -0
  109. package/dist/state/ranges.d.ts.map +1 -0
  110. package/dist/state/ranges.js +108 -0
  111. package/dist/state/ranges.js.map +1 -0
  112. package/llms.txt +16 -4
  113. package/manifest.json +268 -22
  114. package/nav-manifest.json +1 -1
  115. package/package.json +15 -10
  116. package/src/analytics/generated/events.json +1 -1
  117. package/src/default/DegradationNotice.tsx +34 -12
  118. package/src/default/FacetGroupControl.tsx +312 -0
  119. package/src/default/FacetPanelPane.tsx +320 -87
  120. package/src/default/FilterChips.tsx +415 -0
  121. package/src/default/LanguageSelect.tsx +93 -0
  122. package/src/default/PageSizeSelect.tsx +80 -0
  123. package/src/default/RangeFilterRow.tsx +148 -0
  124. package/src/default/RankingDisclosurePane.tsx +67 -35
  125. package/src/default/SearchBox.tsx +130 -0
  126. package/src/default/SearchPage.tsx +454 -44
  127. package/src/default/SearchResultCard.tsx +231 -24
  128. package/src/default/SearchResultsPane.tsx +158 -71
  129. package/src/default/SortSelect.tsx +50 -37
  130. package/src/default/UrlIssueNotice.tsx +21 -3
  131. package/src/default/ViewSwitch.tsx +147 -0
  132. package/src/default/index.ts +55 -15
  133. package/src/default/sortLabels.ts +34 -0
  134. package/src/headless/FacetPanel.tsx +30 -2
  135. package/src/headless/useAppliedCount.ts +41 -0
  136. package/src/headless/useScorerNames.ts +36 -0
  137. package/src/headless/useSearchBox.ts +189 -0
  138. package/src/i18n/es.ts +46 -4
  139. package/src/i18n/keys.ts +114 -4
  140. package/src/i18n/ru.ts +50 -4
  141. package/src/index.ts +22 -2
  142. package/src/model/queries.ts +51 -1
  143. package/src/state/limits.ts +50 -0
  144. package/src/state/ranges.ts +144 -0
  145. package/dist/default/ErrorAlert.d.ts +0 -9
  146. package/dist/default/ErrorAlert.d.ts.map +0 -1
  147. package/dist/default/ErrorAlert.js +0 -27
  148. package/dist/default/ErrorAlert.js.map +0 -1
  149. package/dist/default/theme.d.ts +0 -24
  150. package/dist/default/theme.d.ts.map +0 -1
  151. package/dist/default/theme.js +0 -39
  152. package/dist/default/theme.js.map +0 -1
  153. package/src/default/ErrorAlert.tsx +0 -46
  154. package/src/default/theme.tsx +0 -66
package/CHANGELOG.md CHANGED
@@ -1,5 +1,196 @@
1
1
  # @stapel/search-react
2
2
 
3
+ ## 0.8.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 62c70ac: The classified layout, in the default skins.
8
+
9
+ Built where the doctrine says the product lives, so every future classified
10
+ deployment gets it rather than rebuilding it.
11
+
12
+ - `shell-react` — `NavDock`, a floating translucent island rather than a flat
13
+ bar: inset from every edge, real border and shadow, safe-area aware. The
14
+ glass is progressive enhancement, not the design — the opaque elevated fill
15
+ is the base and the blur is swapped in only inside an `@supports` for
16
+ `backdrop-filter`, so text contrast never depends on transparency being
17
+ available. Destinations are the first five top-level nav entries in the
18
+ order the manifest already declares, so there is no second selection axis.
19
+ Real links, `aria-current`, and the badge count folded into each link's
20
+ accessible name.
21
+ - `search-react` — a phone gets a scrollable chip row instead of one
22
+ "Filters" button, each chip opening its own `SkinDialog`, and chips carry
23
+ the CHOICE rather than the group name. A desktop gets a sticky full-height
24
+ rail. Both render through one `FacetGroupControl`, so the rail and the
25
+ sheets cannot drift into two implementations — and a group's shape is
26
+ derived from the schema keys the composer's editor already reads
27
+ (`maxSelected: 1` → pills, `hierarchical_select` → indented children)
28
+ rather than a new presentation flag. Plus a list/grid view switch, which is
29
+ not URL state because it changes how an answer is drawn and never what it
30
+ is.
31
+ - `listings-react` — the whole card is one real anchor: photo, price, title
32
+ and location inside it, the favourite heart a sibling button outside it so
33
+ the link cannot swallow it. The separate "open" control is gone and its
34
+ i18n key is retired. Middle-click, open-in-new-tab and crawlers still work,
35
+ and the anchor's accessible name is the title alone.
36
+
37
+ Parts of the reference layout that do not fit a generic contract are slots
38
+ with a stated reason rather than invented content: "notify me about new ones"
39
+ (a saved search has an owner, a schedule and a consent record this pair has
40
+ none of), the breadcrumb (a walk up a tree search cannot see), and map view
41
+ (a `SearchView` whose tiles belong to geo-react).
42
+
43
+ ## 0.7.0
44
+
45
+ ### Minor Changes
46
+
47
+ - 9545a2f: Search: the five blank stories, the phone filter path, money, and the dark scope
48
+
49
+ **Five stories rendered nothing.** `results-pane--*` and `filter-panel--*` crashed on
50
+ `data.items.filter` / `data.facet_meta.skipped` — 15 blank shots, including the designed
51
+ empty state. The seeded demos wrote the answer into the query cache and `useSearchQuery`
52
+ sets no `staleTime` (drill-down facets must never serve a stale page), so TanStack
53
+ refetched on mount and the demo `fetch`, which had no handler for a variant that seeded
54
+ instead of mocking, replaced the page with `{}`. A seed now mounts as a handler too, and
55
+ an UNMOCKED path answers 503 rather than an empty 200, so a forgotten handler renders the
56
+ pane's "we could not run this search" arm instead of a white screen.
57
+
58
+ **The phone filter sheet had no visual evidence at all** — the only filter path a phone
59
+ has, reachable only by a tap. `<SearchPage defaultFiltersOpen>` opens it on mount (for a
60
+ container that deep-links into the filters), and `search.filter-sheet` photographs it.
61
+ Its commit button now says **"Show 25+ results"** (`useAppliedCount`, cache-only — no
62
+ second request), the sheet no longer prints "Filters" twice (`FacetPanelPane heading`),
63
+ and the opener drops the "(0)" until something is applied.
64
+
65
+ **Money.** `3200 RUB` → `₽3,200`, through core's `useFormat().number` with
66
+ `style: "currency"` — the same `Intl` path `@stapel/currencies-react`'s `formatMoney`
67
+ takes. Non-numeric prices pass through; an unusable code falls back to a grouped number.
68
+
69
+ **Contrast, touch targets, orphans.** The DSA "Promoted" tag was `warning-on` (white)
70
+ over `warning-bg` (cream) — the one legally mandated string in the package, at ~1.2:1;
71
+ it is `warning` now, in both themes. Degradation banner lines drop `type="secondary"`
72
+ (grey on the warning tint failed AA). `size="small"` is gone from the range Apply/Clear,
73
+ the category/geo/clear-all buttons, so the shared skin's 44px phone control height
74
+ applies. The range Apply is primary when there is something to apply, not before. An
75
+ unfilled `renderGeoFilter` no longer leaves a "Location" heading over empty space in a
76
+ production build, and a facet group with no options draws no heading.
77
+
78
+ **Copy.** Scorer slugs are named from the ranking disclosure the pair already fetches
79
+ (`geo_decay` → "Distance"); skipped facet slugs from the category schema (`power_w` →
80
+ "Power"); `applies_to_sorts` through the sort control's own labels; the weight tag is
81
+ labelled; the unreadable-link notice says "price", not `r.price`, and no longer explains
82
+ `from..to` or `lat`/`lon`. New keys `search.filters.show_count{,_at_least}` (plural
83
+ families) and `search.limit.from_link`, in en/ru/es.
84
+
85
+ **Layout.** The desktop filter rail is a fixed 280px instead of `Col md={7}` (measured at
86
+ 45% of a 1280px page). Result cards carry the photo well filled (`fit` needs a box when
87
+ the snapshot has no aspect) and the whole row is one link when the doc type stores
88
+ `card.url`. The three superseded headless debug-dump demos are gone; their components are
89
+ covered by the skin demos that supersede them.
90
+
91
+ ## 0.6.0
92
+
93
+ ### Minor Changes
94
+
95
+ - 80617e9: The search page can start a search.
96
+
97
+ `setText` had zero callers in the entire repository: the codec carried `q`, the state
98
+ machine could set it, the request sent it, and no screen could type one. Six of the nine
99
+ state setters had no control at all. This release is the missing half of the pair.
100
+
101
+ - **`<SearchBox>`** — the query box, debounced (350ms, `replace: true`, so ten letters are
102
+ one history entry), capped at the server's own `MAX_QUERY_CHARS`, with a typeahead over
103
+ `GET /suggest` — an endpoint that had been typed and unreachable since 0.1. `useSearchBox`
104
+ is the headless half; `useSuggest` the hook. Exported, so a container's header can mount
105
+ the same box the page does (`searchBox={false}` then keeps exactly one on screen).
106
+ - **Range filters** — `r.<slug>=from..to` finally has a control. `state/ranges.ts` decides
107
+ which rows exist (numeric features of the category schema, plus any slug the URL already
108
+ constrains); `<RangeFilterRow>` commits on Apply and refuses a backwards range with the
109
+ reason beside the button instead of returning an empty page.
110
+ - **Category, location, language and page size** — `renderCategoryFilter` and
111
+ `renderGeoFilter` are named slots the categories/geo pairs fill, with `SlotPlaceholder`
112
+ where they are not; either way a constraint that arrived in a shared link now has a control
113
+ that widens it again (clear the category, adjust or clear the radius). `<LanguageSelect>`
114
+ and `<PageSizeSelect>` bind `setLanguage` and `setLimit`.
115
+ - **No reason lives in a hover any more.** The pager, the distance sort and the DSA Art. 26
116
+ `promoted` explanation were all `title=`/`<Tooltip>` — invisible on every phone and on
117
+ every disabled button. They are visible text now (`GatedButton`/`GatedControl`, and plain
118
+ copy under the marking). The pager is absent, not dead, when there is nothing to page.
119
+ - **The generic card draws `image_url`** through `@stapel/image` (new optional peer), in an
120
+ aspect box, with the promoted tag on a `--stapel-*` role instead of antd's `gold` preset.
121
+ - **On a phone the filters are a bottom sheet** behind a "Filters (N)" button, through the
122
+ shared `SkinDialog`, instead of a full-width panel stacked above the first result.
123
+ - **The pair's `theme.tsx` and `ErrorAlert.tsx` are deleted** in favour of
124
+ `@stapel/tokens-antd/skin`'s `SkinTheme` / `ErrorAlert` / `EmptyState` / `LoadList`.
125
+ `SearchSkinTheme` is no longer exported (pre-1.0 breaking = minor): import `SkinTheme`
126
+ from the substrate — same props, and a runtime `data-theme` flip repaints it.
127
+
128
+ Peers: `@stapel/core >=0.18.0`, `@stapel/tokens-antd >=0.6.0`, `@stapel/image >=0.3.0`
129
+ (optional — only the `/default` skin needs it). The `/default` size budget moves 13 KB → 16 KB.
130
+
131
+ ### Patch Changes
132
+
133
+ - 308e3d6: Every `/default` surface is drawn, seeded and photographed.
134
+
135
+ The skin shipped in the last release with one demo out of twelve names: the pair could
136
+ be read in source and not LOOKED at, which is the state §54's gate exists to end. All
137
+ twelve are covered now, and covered in the state each one is named for.
138
+
139
+ - **Eleven new skin demos** — the results pane (found / phone / a search that ran and
140
+ matched nothing), the filter panel (open, and narrowed by a shared link so every
141
+ constraint's door-out is visible), the ranking disclosure, the result card (promoted
142
+ with a photo, and plain), the query box, the sort gate (blocked and open), the page-size
143
+ ladder, the language filter, the numeric range row, the degradation notice (banner and
144
+ inline) and the unreadable-link notice. Each imports from `src/default`, each has a
145
+ `viewport: "phone"` variant, each variant declares the `step` it is seeded at.
146
+ - **Demos are SEEDED, not fetched** (`DemoSeed` in the demo harness): the answer is written
147
+ into the query cache under the key the pair's own codec derives, so a variant opens in its
148
+ state on the first frame instead of photographing the same skeleton under three names.
149
+ `assertVariantsRenderDistinctly` is wired into the demo suite and enforces it.
150
+ - **Dedicated suites** for `useSearchBox` (debounce, one history entry per word, the URL
151
+ winning whenever it moves on its own, the `MAX_QUERY_CHARS` cap), `useSuggest` (the
152
+ three-character floor, the clamped limit, a refusal that leaves the box typeable, a menu
153
+ that stays shut on an empty answer) and the range model (which slugs get a row, what the
154
+ row refuses, and that the reason stands beside the button).
155
+ - **A render matrix per surface** — each of the four surfaces in phone and desktop, light
156
+ and dark, asserting the mode is the DOCUMENT's rather than a default baked into the skin,
157
+ plus the filter surface following the viewport. `setViewport` / `setDocumentTheme` are the
158
+ test harness helpers the setup file has been pointing at.
159
+
160
+ No public API change: `src/` is untouched. The demo registry, manifest and `llms.txt` are
161
+ regenerated.
162
+
163
+ ## 0.5.0
164
+
165
+ ### Minor Changes
166
+
167
+ - d778c54: `<SearchPage>` stops laying out a column for filters that do not exist, and
168
+ stops printing a second heading over the list.
169
+
170
+ - The filter column was unconditional. On a deployment whose search plan
171
+ declares no facets that spent a quarter of `/s`, of every category page and
172
+ of every seller page on an illustration saying "no filters for this search" —
173
+ three screens with a hole in them. The page now asks the facet bag what it
174
+ has and gives the results the whole width when the answer is a LOADED zero.
175
+ `loading` and `failed` keep the column: a panel that has not answered yet is
176
+ not a panel with nothing in it, and a layout that reflowed mid-load would be
177
+ worse than the hole. An active filter keeps it too.
178
+ - `resultsHeading` / `<SearchResultsPane heading>`: what this surface calls its
179
+ list. "Results" is only right when the person performed a search — a
180
+ landing's newest-first strip, a seller's page and a category page each wrote
181
+ their own caption above the pane and got "Results" underneath it a moment
182
+ later. The name now goes INTO the heading row that already exists.
183
+ - `filtersHeader`: a slot at the top of the filter column, for a filter this
184
+ pair cannot ship. `SearchQueryState` has carried `geo` since 0.2 and
185
+ `<SortSelect>` already disables "by distance" with the reason "no centre
186
+ set", but nothing here could ever SET one — turning an address into a
187
+ coordinate needs a geocoder, and a geocoder is the deployment's. Whatever a
188
+ host renders here reads and writes the same URL state as the facets beside
189
+ it.
190
+ - `useFacetPanel()` is exported: the same bag as `<FacetPanel>`, for a caller
191
+ that must know what the panel will render before it renders it. A render prop
192
+ cannot answer a question asked one level up.
193
+
3
194
  ## 0.4.0
4
195
 
5
196
  ### Minor Changes
package/README.md CHANGED
@@ -152,7 +152,7 @@ the configured engine cannot evaluate.
152
152
  | state (pure) | `parseSearchState`, `writeSearchState`, `patchSearchState`, `toggleFilterValue`, `setFilterValues`, `setRangeValue`, `clearFilters`, `activeFilterCount`, `parseDegradations`, `countIsEstimate`, `buildFacetGroups`, `facetOptionLabel` |
153
153
  | model | `createSearchRuntime`, `searchQueryKeys`, `useSearchQuery`, `useRankingDisclosure` |
154
154
  | headless | `SearchProvider`, `SearchStateProvider`/`useSearchState`, `SearchResults`, `FacetPanel`, `RankingDisclosure` |
155
- | `./default` | `SearchPage`, `SearchResultsPane`, `FacetPanelPane`, `RankingDisclosurePane`, `SearchResultCard`, `DegradationNotice`, `UrlIssueNotice`, `SortSelect`, `SearchSkinTheme` |
155
+ | `./default` | `SearchPage`, `SearchResultsPane`, `FacetPanelPane`, `RankingDisclosurePane`, `SearchBox`, `SortSelect`, `PageSizeSelect`, `LanguageSelect`, `SearchResultCard`, `RangeFilterRow`, `DegradationNotice`, `UrlIssueNotice` (the skin themes itself through `SkinTheme` from `@stapel/tokens-antd/skin`; the pair's own `SearchSkinTheme` is gone as of 0.6.0) |
156
156
  | `./router` | `useRouterSearchParams` |
157
157
  | i18n | `registerSearchI18n` (+ `./i18n/ru`, `./i18n/es`) |
158
158
  | errors | `SEARCH_ERRORS`, `explainSearchError`, `SEARCH_WINDOW_EXCEEDED`, `SEARCH_BACKEND_UNAVAILABLE` |
@@ -41,6 +41,13 @@ export type DegradationNoticeVariant = "banner" | "inline" | "off";
41
41
  export interface DegradationNoticeProps {
42
42
  readonly degradations: readonly SearchDegradation[];
43
43
  readonly variant?: DegradationNoticeVariant;
44
+ /**
45
+ * Names a `scorer:` degradation's slug, when something on the page knows
46
+ * one. `<SearchResultsPane>` passes the ranking disclosure's own names
47
+ * (`useScorerNames`); with no answer the slug is printed, which is what a
48
+ * registry identifier is worth on its own.
49
+ */
50
+ readonly scorerName?: (slug: string) => string | undefined;
44
51
  }
45
52
  export declare function DegradationNotice(props: DegradationNoticeProps): ReactElement | null;
46
53
  //# sourceMappingURL=DegradationNotice.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"DegradationNotice.d.ts","sourceRoot":"","sources":["../../src/default/DegradationNotice.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIzD;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,wBAAwB,CAAC;CAC7C;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,YAAY,GAAG,IAAI,CA4CrB"}
1
+ {"version":3,"file":"DegradationNotice.d.ts","sourceRoot":"","sources":["../../src/default/DegradationNotice.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAI1C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAIzD;;;;;;;GAOG;AACH,MAAM,MAAM,wBAAwB,GAAG,QAAQ,GAAG,QAAQ,GAAG,KAAK,CAAC;AAEnE,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpD,QAAQ,CAAC,OAAO,CAAC,EAAE,wBAAwB,CAAC;IAC5C;;;;;OAKG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC5D;AAED,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,sBAAsB,GAC5B,YAAY,GAAG,IAAI,CA0DrB"}
@@ -1,5 +1,6 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { Alert, Flex, Typography } from "antd";
3
+ import { fontSize, spacing } from "@stapel/tokens";
3
4
  import { useT } from "@stapel/core";
4
5
  import { isCountNuanceOnly } from "../state/degradations.js";
5
6
  import { SEARCH_I18N_KEYS } from "../i18n/keys.js";
@@ -13,13 +14,23 @@ export function DegradationNotice(props) {
13
14
  // A count nuance is not a degraded search — the count already says "N+".
14
15
  if (isCountNuanceOnly(props.degradations))
15
16
  return null;
16
- const lines = props.degradations.map((degradation) => (_jsx("li", { "data-degradation": degradation.raw, children: _jsx(Typography.Text, { type: "secondary", children: t(degradation.messageKey, {
17
- scorer: degradation.scorer ?? "",
18
- raw: degradation.raw,
19
- }) }) }, degradation.raw)));
17
+ const say = (degradation) => {
18
+ const slug = degradation.scorer;
19
+ return t(degradation.messageKey, {
20
+ scorer: slug === undefined
21
+ ? ""
22
+ : (props.scorerName?.(slug) ?? slug),
23
+ raw: degradation.raw,
24
+ });
25
+ };
26
+ // NOT `type="secondary"` in the banner: antd paints a warning Alert in the
27
+ // theme's warning tint, and grey body text on it measured under 3:1 in the
28
+ // visual pass. Inside a coloured box the readable colour is the box's own
29
+ // text colour, which is what a plain `<Typography.Text>` inherits.
30
+ const lines = props.degradations.map((degradation) => (_jsx("li", { "data-degradation": degradation.raw, children: _jsx(Typography.Text, { children: say(degradation) }) }, degradation.raw)));
20
31
  if (variant === "inline") {
21
- return (_jsxs(Flex, { vertical: true, gap: 2, "data-testid": "search-degraded", "data-variant": "inline", children: [_jsx(Typography.Text, { type: "secondary", style: { fontSize: 12 }, children: t(SEARCH_I18N_KEYS.degradedTitle) }), _jsx("ul", { style: { margin: 0, paddingInlineStart: 20, fontSize: 12 }, children: lines })] }));
32
+ return (_jsxs(Flex, { vertical: true, gap: spacing[1], "data-testid": "search-degraded", "data-variant": "inline", children: [_jsx(Typography.Text, { type: "secondary", style: { fontSize: fontSize.xs.fontSize }, children: t(SEARCH_I18N_KEYS.degradedTitle) }), _jsx("ul", { style: { margin: 0, paddingInlineStart: spacing[5], fontSize: fontSize.xs.fontSize }, children: props.degradations.map((degradation) => (_jsx("li", { "data-degradation": degradation.raw, children: _jsx(Typography.Text, { type: "secondary", children: say(degradation) }) }, degradation.raw))) })] }));
22
33
  }
23
- return (_jsx(Alert, { type: "warning", showIcon: true, "data-testid": "search-degraded", "data-variant": "banner", message: t(SEARCH_I18N_KEYS.degradedTitle), description: _jsx("ul", { style: { margin: 0, paddingInlineStart: 20 }, children: lines }) }));
34
+ return (_jsx(Alert, { type: "warning", showIcon: true, "data-testid": "search-degraded", "data-variant": "banner", title: t(SEARCH_I18N_KEYS.degradedTitle), description: _jsx("ul", { style: { margin: 0, paddingInlineStart: spacing[5] }, children: lines }) }));
24
35
  }
25
36
  //# sourceMappingURL=DegradationNotice.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"DegradationNotice.js","sourceRoot":"","sources":["../../src/default/DegradationNotice.tsx"],"names":[],"mappings":";AA8BA,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,MAAM,CAAC;AAC/C,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAEpC,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAiBnD,MAAM,UAAU,iBAAiB,CAC/B,KAA6B;IAE7B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,OAAO,GAA6B,KAAK,CAAC,OAAO,IAAI,QAAQ,CAAC;IACpE,IAAI,OAAO,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,KAAK,CAAC,YAAY,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,yEAAyE;IACzE,IAAI,iBAAiB,CAAC,KAAK,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAEvD,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,EAAE,CAAC,CACpD,iCAA4C,WAAW,CAAC,GAAG,YACzD,KAAC,UAAU,CAAC,IAAI,IAAC,IAAI,EAAC,WAAW,YAC9B,CAAC,CAAC,WAAW,CAAC,UAAU,EAAE;gBACzB,MAAM,EAAE,WAAW,CAAC,MAAM,IAAI,EAAE;gBAChC,GAAG,EAAE,WAAW,CAAC,GAAG;aACrB,CAAC,GACc,IANX,WAAW,CAAC,GAAG,CAOnB,CACN,CAAC,CAAC;IAEH,IAAI,OAAO,KAAK,QAAQ,EAAE,CAAC;QACzB,OAAO,CACL,MAAC,IAAI,IAAC,QAAQ,QAAC,GAAG,EAAE,CAAC,iBAAc,iBAAiB,kBAAc,QAAQ,aACxE,KAAC,UAAU,CAAC,IAAI,IAAC,IAAI,EAAC,WAAW,EAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YACtD,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC,GAClB,EAClB,aAAI,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,YAC3D,KAAK,GACH,IACA,CACR,CAAC;IACJ,CAAC;IAED,OAAO,CACL,KAAC,KAAK,IACJ,IAAI,EAAC,SAAS,EACd,QAAQ,uBACI,iBAAiB,kBAChB,QAAQ,EACrB,OAAO,EAAE,CAAC,CAAC,gBAAgB,CAAC,aAAa,CAAC,EAC1C,WAAW,EACT,aAAI,KAAK,EAAE,EAAE,MAAM,EAAE,CAAC,EAAE,kBAAkB,EAAE,EAAE,EAAE,YAAG,KAAK,GAAM,GAEhE,CACH,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"DegradationNotice.js","sourceRoot":"","sources":["../../src/default/DegradationNotice.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,40 @@
1
+ import type { ReactElement } from "react";
2
+ import type { FacetGroup, FacetOption } from "../state/facets.js";
3
+ /**
4
+ * How many options a group shows before the rest go behind "Show all".
5
+ *
6
+ * Eight is the count at which a group stops being readable at a glance and
7
+ * starts being a scroll: it is two more than the six the visual pass measured
8
+ * as the fold on a 390px phone with the sheet's own chrome above it, which
9
+ * leaves a group of seven whole rather than truncated by one row.
10
+ */
11
+ export declare const FACET_VISIBLE_OPTIONS = 8;
12
+ /** The three shapes a facet group takes. */
13
+ export type FacetGroupShape = "segmented" | "nested" | "checkbox";
14
+ /** The option rows of a group, already nested where the schema nests them. */
15
+ export interface FacetOptionNode {
16
+ readonly option: FacetOption;
17
+ /** 0 for a root option; 1+ for a child of a `hierarchical_select` tree. */
18
+ readonly depth: number;
19
+ }
20
+ /**
21
+ * Which of the three shapes a group takes.
22
+ *
23
+ * Order matters: a hierarchical facet is nested even when it is single-choice,
24
+ * because losing the tree costs more than losing the pills.
25
+ */
26
+ export declare function facetGroupShape(group: FacetGroup): FacetGroupShape;
27
+ /** The group's options in render order, carrying the depth the schema gives. */
28
+ export declare function facetOptionNodes(group: FacetGroup): readonly FacetOptionNode[];
29
+ export interface FacetGroupControlProps {
30
+ readonly group: FacetGroup;
31
+ readonly onToggle: (slug: string, value: string) => void;
32
+ /** Draw the group's own name above its options. `false` for a surface that
33
+ * has already said it — a per-group sheet whose title IS the group. */
34
+ readonly heading?: boolean;
35
+ /** How many options before "Show all". Default {@link FACET_VISIBLE_OPTIONS};
36
+ * `null` shows every option (a sheet devoted to one group has the room). */
37
+ readonly visibleOptions?: number | null;
38
+ }
39
+ export declare function FacetGroupControl(props: FacetGroupControlProps): ReactElement;
40
+ //# sourceMappingURL=FacetGroupControl.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacetGroupControl.d.ts","sourceRoot":"","sources":["../../src/default/FacetGroupControl.tsx"],"names":[],"mappings":"AAmCA,OAAO,KAAK,EAAiB,YAAY,EAAE,MAAM,OAAO,CAAC;AAMzD,OAAO,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AAGlE;;;;;;;GAOG;AACH,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAEvC,4CAA4C;AAC5C,MAAM,MAAM,eAAe,GAAG,WAAW,GAAG,QAAQ,GAAG,UAAU,CAAC;AAElE,8EAA8E;AAC9E,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,2EAA2E;IAC3E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAwCD;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,CAMlE;AAED,gFAAgF;AAChF,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,eAAe,EAAE,CAqB9E;AA6FD,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzD;2EACuE;IACvE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;gFAC4E;IAC5E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,sBAAsB,GAAG,YAAY,CAqE7E"}
@@ -0,0 +1,176 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /**
3
+ * `<FacetGroupControl>` — ONE facet group, drawn the way its own schema says
4
+ * it should be drawn.
5
+ *
6
+ * Until this release every group was the same thing: a flat column of
7
+ * checkboxes, however many options it had and whatever the category schema
8
+ * said about it. That is wrong in three ways a person meets on the first
9
+ * screen of a real catalogue:
10
+ *
11
+ * 1. **A single-choice facet is not a checkbox list.** `maxSelected: 1` is a
12
+ * fact the schema already carries, and `@stapel/attributes-react`'s editor
13
+ * already reads it to draw a segmented control rather than a set of boxes.
14
+ * A filter that says "pick one" with controls that say "pick any" teaches
15
+ * the wrong thing before the click and surprises after it.
16
+ * 2. **A hierarchical facet is not flat.** `hierarchical_select` carries a
17
+ * TREE in `config.options`; rendering its values as one alphabetical
18
+ * column hides that "Sedan" is under "Cars" and puts a child next to its
19
+ * own parent as if they were siblings.
20
+ * 3. **A 60-option facet is not a list, it is a wall.** Every catalogue has
21
+ * one — brand, model, city — and printing all of it pushes every group
22
+ * under it off the screen.
23
+ *
24
+ * ── The presentation is DERIVED, never configured here ────────────────────
25
+ *
26
+ * {@link facetGroupShape} reads the same `config` keys the attributes editor
27
+ * reads (`maxSelected`, `type`, `options`), so a facet cannot look one way in
28
+ * the filter and another way in the composer that produced the value. There is
29
+ * no `presentation` prop on this component and there must not be one: a
30
+ * per-call-site override is how the two halves drift.
31
+ *
32
+ * A group with NO schema (the host passed no `categoryFeatures`, or the slug
33
+ * is not in it) is a flat checkbox list — the honest default, and the shape
34
+ * every group had before.
35
+ */
36
+ import { useState } from "react";
37
+ import { Button, Checkbox, Flex, Typography } from "antd";
38
+ import { useT } from "@stapel/core";
39
+ import { radii, spacing } from "@stapel/tokens";
40
+ import { featureConfig, featureType } from "@stapel/attributes-react";
41
+ import { SEARCH_I18N_KEYS } from "../i18n/keys.js";
42
+ /**
43
+ * How many options a group shows before the rest go behind "Show all".
44
+ *
45
+ * Eight is the count at which a group stops being readable at a glance and
46
+ * starts being a scroll: it is two more than the six the visual pass measured
47
+ * as the fold on a 390px phone with the sheet's own chrome above it, which
48
+ * leaves a group of seven whole rather than truncated by one row.
49
+ */
50
+ export const FACET_VISIBLE_OPTIONS = 8;
51
+ function numberish(value) {
52
+ return typeof value === "number" && Number.isFinite(value) ? value : undefined;
53
+ }
54
+ /**
55
+ * The DEPTH of every value a `hierarchical_select` config declares, walked
56
+ * once — `{value: depth}`.
57
+ *
58
+ * The tree lives in `config.options[].children[]` (the same shape
59
+ * `@stapel/attributes-react`'s `Cascader` reads). The facets themselves arrive
60
+ * FLAT from the server, because an index term has no parent; the schema is the
61
+ * only thing that knows one value sits under another.
62
+ */
63
+ function optionDepths(raw, depth = 0, into = new Map()) {
64
+ if (!Array.isArray(raw))
65
+ return into;
66
+ for (const option of raw) {
67
+ if (option === null || typeof option !== "object")
68
+ continue;
69
+ const entry = option;
70
+ if (entry.value !== undefined && entry.value !== null) {
71
+ into.set(String(entry.value), depth);
72
+ }
73
+ optionDepths(entry.children, depth + 1, into);
74
+ }
75
+ return into;
76
+ }
77
+ /** Is this feature single-choice? The schema's own answer, not a guess. */
78
+ function singleChoice(feature) {
79
+ if (feature === undefined)
80
+ return false;
81
+ // `maxSelected` ABSENT means unlimited — the engine's own default. Reading
82
+ // an absent key as 1 would turn every unconfigured facet into a radio group.
83
+ return numberish(featureConfig(feature)["maxSelected"]) === 1;
84
+ }
85
+ /**
86
+ * Which of the three shapes a group takes.
87
+ *
88
+ * Order matters: a hierarchical facet is nested even when it is single-choice,
89
+ * because losing the tree costs more than losing the pills.
90
+ */
91
+ export function facetGroupShape(group) {
92
+ const feature = group.feature;
93
+ if (feature !== undefined && featureType(feature) === "hierarchical_select") {
94
+ return "nested";
95
+ }
96
+ return singleChoice(feature) ? "segmented" : "checkbox";
97
+ }
98
+ /** The group's options in render order, carrying the depth the schema gives. */
99
+ export function facetOptionNodes(group) {
100
+ if (facetGroupShape(group) !== "nested" || group.feature === undefined) {
101
+ return group.options.map((option) => ({ option, depth: 0 }));
102
+ }
103
+ const depths = optionDepths(featureConfig(group.feature)["options"]);
104
+ // Depth alone would leave children beside strangers: the options are
105
+ // re-ordered so each child follows its own parent, and a value the schema
106
+ // does not know keeps depth 0 rather than being hidden under someone.
107
+ const byValue = new Map(group.options.map((option) => [option.value, option]));
108
+ const out = [];
109
+ const emitted = new Set();
110
+ for (const [value, depth] of depths) {
111
+ const option = byValue.get(value);
112
+ if (option === undefined)
113
+ continue;
114
+ out.push({ option, depth });
115
+ emitted.add(value);
116
+ }
117
+ for (const option of group.options) {
118
+ if (!emitted.has(option.value))
119
+ out.push({ option, depth: 0 });
120
+ }
121
+ return out;
122
+ }
123
+ /** A count, or the honest "we did not count this". Never a zero standing in
124
+ * for an absent answer. */
125
+ function OptionCount(props) {
126
+ const t = useT();
127
+ return (_jsx(Typography.Text, { type: "secondary", "data-testid": `facet-count-${props.group.slug}-${props.option.value}`, children: props.option.count === null
128
+ ? t(SEARCH_I18N_KEYS.facetsNotCounted)
129
+ : props.option.count }));
130
+ }
131
+ /** The indent one level of a hierarchical facet is drawn with. */
132
+ const NEST_STEP = spacing[5];
133
+ function CheckboxRow(props) {
134
+ const { group, node } = props;
135
+ return (_jsxs(Flex, { justify: "space-between", align: "center", gap: spacing[2], style: node.depth > 0
136
+ ? { paddingInlineStart: node.depth * NEST_STEP }
137
+ : undefined, "data-depth": node.depth, children: [_jsx(Checkbox, { checked: node.option.selected, "data-testid": `facet-option-${group.slug}-${node.option.value}`, "data-analytics": "none", "data-analytics-reason": "a filter is a read, not a flow step", onChange: () => {
138
+ props.onToggle(group.slug, node.option.value);
139
+ }, children: node.option.label }), _jsx(OptionCount, { group: group, option: node.option })] }));
140
+ }
141
+ /**
142
+ * One pill of a single-choice group.
143
+ *
144
+ * A real `<button aria-pressed>` rather than antd's `Segmented`: the count has
145
+ * to sit inside the pill (a filter without its remaining count is the
146
+ * drill-down facet turned naive), and `Segmented` takes labels, not rows.
147
+ * `aria-pressed` is what makes a styled button a TOGGLE to a screen reader
148
+ * instead of a link-shaped thing that mysteriously changes the page.
149
+ */
150
+ function OptionPill(props) {
151
+ const { group, option } = props;
152
+ const style = { borderRadius: radii.full };
153
+ return (_jsx(Button, { size: "small", shape: "round", type: option.selected ? "primary" : "default", "aria-pressed": option.selected, style: style, "data-testid": `facet-option-${group.slug}-${option.value}`, "data-analytics": "none", "data-analytics-reason": "a filter is a read, not a flow step", onClick: () => {
154
+ props.onToggle(group.slug, option.value);
155
+ }, children: option.count === null ? option.label : `${option.label} ${option.count}` }));
156
+ }
157
+ export function FacetGroupControl(props) {
158
+ const t = useT();
159
+ const { group } = props;
160
+ const [expanded, setExpanded] = useState(false);
161
+ const shape = facetGroupShape(group);
162
+ const nodes = facetOptionNodes(group);
163
+ const limit = props.visibleOptions === null
164
+ ? null
165
+ : (props.visibleOptions ?? FACET_VISIBLE_OPTIONS);
166
+ // A group one row over the limit is not truncated: hiding a single option
167
+ // behind "Show all (9)" costs a tap to reveal exactly one thing.
168
+ const collapsible = limit !== null && nodes.length > limit + 1;
169
+ const shown = collapsible && !expanded ? nodes.slice(0, limit) : nodes;
170
+ return (_jsxs(Flex, { vertical: true, gap: shape === "segmented" ? spacing[2] : spacing[1], "data-testid": `facet-group-${group.slug}`, "data-counted": group.counted ? "true" : "false", "data-shape": shape, children: [props.heading !== false && (_jsx(Typography.Text, { strong: true, children: group.label })), shape === "segmented" ? (_jsx(Flex, { wrap: true, gap: spacing[2], children: shown.map((node) => (_jsx(OptionPill, { group: group, option: node.option, onToggle: props.onToggle }, node.option.value))) })) : (shown.map((node) => (_jsx(CheckboxRow, { group: group, node: node, onToggle: props.onToggle }, node.option.value)))), collapsible && (_jsx(Button, { type: "link", size: "small", style: { alignSelf: "flex-start", paddingInline: 0 }, "data-testid": `facet-more-${group.slug}`, "data-analytics": "none", "data-analytics-reason": "expanding a filter group is a read, not a flow step", onClick: () => {
171
+ setExpanded((was) => !was);
172
+ }, children: expanded
173
+ ? t(SEARCH_I18N_KEYS.facetsShowLess)
174
+ : t(SEARCH_I18N_KEYS.facetsShowAll, { count: nodes.length }) }))] }));
175
+ }
176
+ //# sourceMappingURL=FacetGroupControl.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FacetGroupControl.js","sourceRoot":"","sources":["../../src/default/FacetGroupControl.tsx"],"names":[],"mappings":"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"}
@@ -1,5 +1,11 @@
1
1
  /**
2
- * `<FacetPanelPane>` — the antd facet panel.
2
+ * `<FacetPanelPane>` — the antd FILTER panel: everything that narrows a
3
+ * search, in the order a person narrows it.
4
+ *
5
+ * Category → language → location → numeric ranges → facet checkboxes. The last
6
+ * of those was, for three releases, the only one that existed: six of the nine
7
+ * state setters had no control at all, so a price range or a location could
8
+ * only be applied by editing the address bar (audit S-2, S-7).
3
9
  *
4
10
  * Three things it is obliged to render, all of which a naive panel drops:
5
11
  *
@@ -12,15 +18,60 @@
12
18
  * - `skipped` — the slugs the server did not count at all. Their options show
13
19
  * "not counted", never `0`. A silent zero there is the same defect class as
14
20
  * `data ?? []`: a number that looks like an answer and is not one.
21
+ *
22
+ * ── Two slots, and why they are slots ─────────────────────────────────────
23
+ *
24
+ * `renderCategoryFilter` and `renderGeoFilter` are filled by OTHER pairs:
25
+ * choosing a category means walking the catalogue tree (`categories-react`),
26
+ * and turning an address into a coordinate needs a geocoder and a map
27
+ * (`geo-react`). Neither belongs in a search package, and importing either
28
+ * would tie a storefront's search to a catalogue it might not have.
29
+ *
30
+ * What this panel does NOT do is pretend the slot is optional. An unfilled
31
+ * slot renders `SlotPlaceholder` in development — a named, visible hole rather
32
+ * than a silent absence — and, in every build, any constraint the URL already
33
+ * carries gets a control that REMOVES it. A shared link that narrows to a
34
+ * category or a point must never leave a person with no way to widen it again.
15
35
  */
16
- import type { ReactElement } from "react";
36
+ import type { ReactElement, ReactNode } from "react";
17
37
  import type { FeatureDef } from "@stapel/attributes-react";
38
+ import type { SearchGeo } from "../api/types.js";
18
39
  import type { ThemeModeProp } from "./types.js";
40
+ /** What a host's category control is handed. */
41
+ export interface CategoryFilterSlotProps {
42
+ /** The `root/leaf` path the search is narrowed to, if any. */
43
+ readonly value: string | undefined;
44
+ /** `null` widens the search back to the whole catalogue. */
45
+ readonly onChange: (path: string | null) => void;
46
+ }
47
+ /** What a host's location control is handed. */
48
+ export interface GeoFilterSlotProps {
49
+ readonly value: SearchGeo | undefined;
50
+ /** `null` clears the location constraint. */
51
+ readonly onChange: (geo: SearchGeo | null) => void;
52
+ }
19
53
  export interface FacetPanelPaneProps extends ThemeModeProp {
20
- /** The category's feature schema — the source of option LABELS. */
54
+ /** The category's feature schema — the source of option LABELS and of which
55
+ * slugs get a numeric range row. */
21
56
  readonly categoryFeatures?: readonly FeatureDef[];
22
57
  readonly locale?: string;
23
58
  readonly enabled?: boolean;
59
+ /** The catalogue picker (`categories-react`'s `CategoryPickerField`, bound
60
+ * to a path). Unfilled, an active category still gets a "clear" control. */
61
+ readonly renderCategoryFilter?: (slot: CategoryFilterSlotProps) => ReactNode;
62
+ /** The location control (`geo-react`). Unfilled, a location that arrived in
63
+ * the URL still gets its radius and a "clear" control. */
64
+ readonly renderGeoFilter?: (slot: GeoFilterSlotProps) => ReactNode;
65
+ /** BCP-47 tags this deployment indexes — see {@link LanguageSelect}. */
66
+ readonly languages?: readonly string[];
67
+ /**
68
+ * What the panel calls itself. `null` draws no title at all — for a surface
69
+ * that has ALREADY named it, which the phone sheet has: its dialog title and
70
+ * the panel's own heading both said "Filters", one under the other, in every
71
+ * shot of the open sheet. The row itself stays either way, because the
72
+ * "Clear all" control lives in it.
73
+ */
74
+ readonly heading?: ReactNode;
24
75
  }
25
76
  export declare function FacetPanelPane(props: FacetPanelPaneProps): ReactElement;
26
77
  //# sourceMappingURL=FacetPanelPane.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FacetPanelPane.d.ts","sourceRoot":"","sources":["../../src/default/FacetPanelPane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,OAAO,CAAC;AAG1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAM3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD,mEAAmE;IACnE,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;CAC5B;AAsCD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,YAAY,CAwGvE"}
1
+ {"version":3,"file":"FacetPanelPane.d.ts","sourceRoot":"","sources":["../../src/default/FacetPanelPane.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAkBrD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAQjD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,gDAAgD;AAChD,MAAM,WAAW,uBAAuB;IACtC,8DAA8D;IAC9D,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,4DAA4D;IAC5D,QAAQ,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;CAClD;AAED,gDAAgD;AAChD,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,CAAC;IACtC,6CAA6C;IAC7C,QAAQ,CAAC,QAAQ,EAAE,CAAC,GAAG,EAAE,SAAS,GAAG,IAAI,KAAK,IAAI,CAAC;CACpD;AAED,MAAM,WAAW,mBAAoB,SAAQ,aAAa;IACxD;wCACoC;IACpC,QAAQ,CAAC,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IAClD,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;gFAC4E;IAC5E,QAAQ,CAAC,oBAAoB,CAAC,EAAE,CAAC,IAAI,EAAE,uBAAuB,KAAK,SAAS,CAAC;IAC7E;8DAC0D;IAC1D,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,kBAAkB,KAAK,SAAS,CAAC;IACnE,wEAAwE;IACxE,QAAQ,CAAC,SAAS,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC;;;;;;OAMG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,SAAS,CAAC;CAC9B;AAqKD,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,GAAG,YAAY,CA4IvE"}