@stapel/search-react 0.11.0 → 0.13.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 +178 -0
- package/MODULE.md +118 -3
- package/README.md +42 -0
- package/dist/api/generated/schema.d.ts +60 -6
- package/dist/api/generated/schema.d.ts.map +1 -1
- package/dist/api/searchApi.d.ts +13 -6
- package/dist/api/searchApi.d.ts.map +1 -1
- package/dist/api/searchApi.js.map +1 -1
- package/dist/api/types.d.ts +107 -1
- package/dist/api/types.d.ts.map +1 -1
- package/dist/api/types.js +29 -0
- package/dist/api/types.js.map +1 -1
- package/dist/default/FacetPanelPane.d.ts +13 -2
- package/dist/default/FacetPanelPane.d.ts.map +1 -1
- package/dist/default/FacetPanelPane.js +3 -1
- package/dist/default/FacetPanelPane.js.map +1 -1
- package/dist/default/FilterChips.d.ts +88 -3
- package/dist/default/FilterChips.d.ts.map +1 -1
- package/dist/default/FilterChips.js +161 -13
- package/dist/default/FilterChips.js.map +1 -1
- package/dist/default/LocationSummaryLine.d.ts.map +1 -1
- package/dist/default/LocationSummaryLine.js +1 -1
- package/dist/default/LocationSummaryLine.js.map +1 -1
- package/dist/default/SearchBox.d.ts.map +1 -1
- package/dist/default/SearchBox.js +74 -4
- package/dist/default/SearchBox.js.map +1 -1
- package/dist/default/SearchPage.d.ts +29 -1
- package/dist/default/SearchPage.d.ts.map +1 -1
- package/dist/default/SearchPage.js +25 -10
- package/dist/default/SearchPage.js.map +1 -1
- package/dist/default/SearchResultCard.d.ts.map +1 -1
- package/dist/default/SearchResultCard.js +83 -37
- package/dist/default/SearchResultCard.js.map +1 -1
- package/dist/default/SearchResultsPane.d.ts +22 -0
- package/dist/default/SearchResultsPane.d.ts.map +1 -1
- package/dist/default/SearchResultsPane.js +2 -2
- package/dist/default/SearchResultsPane.js.map +1 -1
- package/dist/default/SortSelect.d.ts +23 -0
- package/dist/default/SortSelect.d.ts.map +1 -1
- package/dist/default/SortSelect.js +29 -9
- package/dist/default/SortSelect.js.map +1 -1
- package/dist/default/cardPhotos.d.ts +65 -0
- package/dist/default/cardPhotos.d.ts.map +1 -0
- package/dist/default/cardPhotos.js +127 -0
- package/dist/default/cardPhotos.js.map +1 -0
- package/dist/default/index.d.ts +2 -2
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js +1 -1
- package/dist/default/index.js.map +1 -1
- package/dist/headless/FacetPanel.d.ts +10 -0
- package/dist/headless/FacetPanel.d.ts.map +1 -1
- package/dist/headless/FacetPanel.js +9 -1
- package/dist/headless/FacetPanel.js.map +1 -1
- package/dist/headless/useFacetLabels.d.ts +39 -0
- package/dist/headless/useFacetLabels.d.ts.map +1 -0
- package/dist/headless/useFacetLabels.js +129 -0
- package/dist/headless/useFacetLabels.js.map +1 -0
- package/dist/headless/useSearchBox.d.ts +71 -0
- package/dist/headless/useSearchBox.d.ts.map +1 -1
- package/dist/headless/useSearchBox.js +67 -2
- package/dist/headless/useSearchBox.js.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +10 -0
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/keys.d.ts +55 -0
- package/dist/i18n/keys.d.ts.map +1 -1
- package/dist/i18n/keys.js +67 -0
- package/dist/i18n/keys.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +12 -0
- package/dist/i18n/ru.js.map +1 -1
- package/dist/index.d.ts +7 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -3
- package/dist/index.js.map +1 -1
- package/dist/model/queries.d.ts +6 -5
- package/dist/model/queries.d.ts.map +1 -1
- package/dist/model/queries.js +4 -3
- package/dist/model/queries.js.map +1 -1
- package/dist/model/queryKeys.d.ts +12 -0
- package/dist/model/queryKeys.d.ts.map +1 -1
- package/dist/model/queryKeys.js +7 -0
- package/dist/model/queryKeys.js.map +1 -1
- package/dist/model/runtime.d.ts +40 -3
- package/dist/model/runtime.d.ts.map +1 -1
- package/dist/model/runtime.js +2 -1
- package/dist/model/runtime.js.map +1 -1
- package/dist/nav/manifest.d.ts +21 -0
- package/dist/nav/manifest.d.ts.map +1 -1
- package/dist/nav/manifest.js +3 -2
- package/dist/nav/manifest.js.map +1 -1
- package/dist/state/facets.d.ts +56 -15
- package/dist/state/facets.d.ts.map +1 -1
- package/dist/state/facets.js +101 -27
- package/dist/state/facets.js.map +1 -1
- package/llms.txt +3 -3
- package/manifest.json +33 -4
- package/nav-manifest.json +4 -3
- package/package.json +11 -11
- package/src/analytics/generated/events.json +1 -1
- package/src/api/generated/schema.ts +60 -6
- package/src/api/searchApi.ts +13 -6
- package/src/api/types.ts +115 -1
- package/src/default/FacetPanelPane.tsx +16 -2
- package/src/default/FilterChips.tsx +285 -38
- package/src/default/LocationSummaryLine.tsx +6 -1
- package/src/default/SearchBox.tsx +134 -6
- package/src/default/SearchPage.tsx +79 -5
- package/src/default/SearchResultCard.tsx +157 -71
- package/src/default/SearchResultsPane.tsx +48 -11
- package/src/default/SortSelect.tsx +70 -9
- package/src/default/cardPhotos.ts +195 -0
- package/src/default/index.ts +10 -2
- package/src/headless/FacetPanel.tsx +20 -1
- package/src/headless/useFacetLabels.ts +172 -0
- package/src/headless/useSearchBox.ts +132 -5
- package/src/i18n/es.ts +11 -0
- package/src/i18n/keys.ts +69 -0
- package/src/i18n/ru.ts +13 -0
- package/src/index.ts +22 -3
- package/src/model/queries.ts +6 -5
- package/src/model/queryKeys.ts +23 -0
- package/src/model/runtime.ts +43 -4
- package/src/nav/manifest.ts +24 -2
- package/src/state/facets.ts +123 -39
package/dist/state/facets.js
CHANGED
|
@@ -8,27 +8,86 @@
|
|
|
8
8
|
* they would have if you swapped to them. A panel that greys the siblings
|
|
9
9
|
* out has silently converted a drill-down facet into a naive one, and the
|
|
10
10
|
* e2e leg in the spec (§7.2) exists to catch exactly that.
|
|
11
|
-
* 2. **Option LABELS
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
*
|
|
18
|
-
* a
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
11
|
+
* 2. **Option LABELS have one stated order: ANSWER, then schema, then the
|
|
12
|
+
* raw value** — with a host resolver between the last two, applied by
|
|
13
|
+
* `useHostFacetLabels` on what this module could not name.
|
|
14
|
+
*
|
|
15
|
+
* The answer leads because it is the only source that always exists and
|
|
16
|
+
* the only one that has RESOLVED anything: `categoryFeatures` is an
|
|
17
|
+
* optional slot a live classified board never filled, and even where it is
|
|
18
|
+
* filled a `ref_select` config carries a pointer to a vocabulary and no
|
|
19
|
+
* option table at all — so the schema cannot name `apple` or `chernyy` no
|
|
20
|
+
* matter who threads it through. `facet_labels` (stapel-search 0.4.0+,
|
|
21
|
+
* vocabulary-backed from 0.6.0) is the server reading that vocabulary
|
|
22
|
+
* against the snapshot the documents were written with, and answering in
|
|
23
|
+
* the request's own language. The schema is the floor under it, for a
|
|
24
|
+
* server too old to send captions and for a slug the answer omits.
|
|
25
|
+
*
|
|
26
|
+
* Neither invents a label: a value nobody names renders as itself. A page
|
|
27
|
+
* against a pre-0.4.0 server therefore behaves exactly as it did — the key
|
|
28
|
+
* is absent, every option falls through to the schema, and nothing
|
|
29
|
+
* crashes on the missing key.
|
|
25
30
|
*
|
|
26
31
|
* A slug the server SKIPPED (`facet_meta.skipped`, dropped at
|
|
27
32
|
* `MAX_FACET_FIELDS`) is not counted at all. Its options carry `count: null`,
|
|
28
33
|
* never `0` — "we did not count this" and "there are none" are different
|
|
29
34
|
* sentences and the honest one has to survive to the screen.
|
|
35
|
+
*
|
|
36
|
+
* 3. **Not every counted slug is a FILTER.** The plan is built from the leaf
|
|
37
|
+
* category's feature defs and the counter counts whatever is indexed, so a
|
|
38
|
+
* live classified deployment answers with `imei: {"355971829187494": 1}`
|
|
39
|
+
* and `video_file_url: {}` beside its brand and its condition. Neither is
|
|
40
|
+
* something a person narrows by — one is unique per document, the other is
|
|
41
|
+
* a URL — and on a 390px chip row a chip offering one IMEI with a count of
|
|
42
|
+
* one pushes the chips that DO narrow off the screen. Which slugs can be
|
|
43
|
+
* chipped is therefore decided from the category's own feature defs, by
|
|
44
|
+
* value TYPE (see {@link FACETABLE_FEATURE_TYPES}), not by what came back.
|
|
45
|
+
*/
|
|
46
|
+
import { VOCABULARY_BACKED_TYPES, featureConfig, featureName, featureType, formatFeatureValue, } from "@stapel/attributes-react";
|
|
47
|
+
/**
|
|
48
|
+
* Value types whose values are a BOUNDED OPTION SET — the only kind of
|
|
49
|
+
* feature a person can be offered as a filter.
|
|
50
|
+
*
|
|
51
|
+
* The list is not invented here: the ref/vocabulary-backed half is
|
|
52
|
+
* `@stapel/attributes-react`'s own `VOCABULARY_BACKED_TYPES` (the one place
|
|
53
|
+
* that knows which types are drawn from a vocabulary), and the rest are the
|
|
54
|
+
* select family plus `bool`. Everything else a category can declare — a
|
|
55
|
+
* `string`, an `int`, a `date`, a `hex_color`, a `group` — enumerates as many
|
|
56
|
+
* terms as there are documents, which is a list, not a choice.
|
|
57
|
+
*
|
|
58
|
+
* `int`/`float`/`convertible_unit` are absent here and present in
|
|
59
|
+
* `RANGE_FEATURE_TYPES` (`state/ranges.ts`): a number is narrowed with two
|
|
60
|
+
* bounds, not with a checkbox per value. They are not dropped from the panel,
|
|
61
|
+
* they are drawn by the other half of the model.
|
|
30
62
|
*/
|
|
31
|
-
|
|
63
|
+
export const FACETABLE_FEATURE_TYPES = [
|
|
64
|
+
"bool",
|
|
65
|
+
"hierarchical_select",
|
|
66
|
+
...VOCABULARY_BACKED_TYPES,
|
|
67
|
+
"select",
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* Can a person filter by the slug this feature def describes?
|
|
71
|
+
*
|
|
72
|
+
* **A missing feature def is not a "no".** `categoryFeatures` is an OPTIONAL
|
|
73
|
+
* slot and a whole deployment can run without it; a feature can also be
|
|
74
|
+
* retired between the write that indexed a value and the read that counts it.
|
|
75
|
+
* Answering "not facetable" for an absent def would blank the entire chip row
|
|
76
|
+
* for every host that never threaded the schema through — the same empty row
|
|
77
|
+
* this rule exists to fix, arrived at from the other side. So the schema can
|
|
78
|
+
* only ever REMOVE a chip it names and disowns; silence removes nothing.
|
|
79
|
+
*
|
|
80
|
+
* The same reasoning covers a def with no `config.type` at all: an untyped
|
|
81
|
+
* feature is a def that says nothing, and nothing is not a verdict.
|
|
82
|
+
*/
|
|
83
|
+
export function isFacetableFeature(feature) {
|
|
84
|
+
if (feature === undefined)
|
|
85
|
+
return true;
|
|
86
|
+
const type = featureType(feature);
|
|
87
|
+
if (type === undefined)
|
|
88
|
+
return true;
|
|
89
|
+
return FACETABLE_FEATURE_TYPES.includes(type);
|
|
90
|
+
}
|
|
32
91
|
function translate(t, key) {
|
|
33
92
|
if (t === undefined)
|
|
34
93
|
return key;
|
|
@@ -78,20 +137,23 @@ function declaredOptionValues(feature) {
|
|
|
78
137
|
return out;
|
|
79
138
|
}
|
|
80
139
|
/**
|
|
81
|
-
* One option's caption:
|
|
82
|
-
*
|
|
83
|
-
*
|
|
84
|
-
*
|
|
85
|
-
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
140
|
+
* One option's caption: the ANSWER, then the schema, then the raw value.
|
|
141
|
+
*
|
|
142
|
+
* The answer leads because it is the source that always exists and the only
|
|
143
|
+
* one that can name a vocabulary-backed value at all: a `ref_select`'s config
|
|
144
|
+
* is a POINTER (`optionsRef`), so a host who threaded the whole schema through
|
|
145
|
+
* still has nothing to print for `apple`. The server read that vocabulary
|
|
146
|
+
* against the snapshot the documents carry and answered in the request's own
|
|
147
|
+
* language, which is a strictly better-informed caption than the option table
|
|
148
|
+
* the schema may or may not hold.
|
|
149
|
+
*
|
|
150
|
+
* The schema is the floor: a server too old to send `facet_labels`, a slug the
|
|
151
|
+
* answer omits, a value the vocabulary has since dropped. Below both, the raw
|
|
152
|
+
* value — never a blank, and never a guess.
|
|
89
153
|
*/
|
|
90
154
|
function resolveLabel(input, feature, slug, value, labelOptions) {
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return viaSchema;
|
|
94
|
-
return serverLabel(input.facetLabels, slug, value, input.t) ?? viaSchema;
|
|
155
|
+
return (serverLabel(input.facetLabels, slug, value, input.t) ??
|
|
156
|
+
facetOptionLabel(feature, value, labelOptions));
|
|
95
157
|
}
|
|
96
158
|
/**
|
|
97
159
|
* A facet value as a person reads it, through
|
|
@@ -145,6 +207,13 @@ export function facetOptionLabel(feature, value, options) {
|
|
|
145
207
|
* person has filtered on — the last one matters: a filter whose slug fell out
|
|
146
208
|
* of the plan must stay visible, or it becomes a constraint with no control to
|
|
147
209
|
* remove it.
|
|
210
|
+
*
|
|
211
|
+
* A slug the category schema names and types as something no one can choose
|
|
212
|
+
* from (see {@link isFacetableFeature}) produces no group at all — not an
|
|
213
|
+
* empty one, because an empty group is still a heading in the panel and still
|
|
214
|
+
* a chip in the row. The APPLIED-filter clause outranks the type rule: a
|
|
215
|
+
* constraint the URL carries always gets its control back, whatever the schema
|
|
216
|
+
* now says about it, or a person is left holding a filter they cannot clear.
|
|
148
217
|
*/
|
|
149
218
|
export function buildFacetGroups(input) {
|
|
150
219
|
const bySlug = new Map();
|
|
@@ -161,6 +230,11 @@ export function buildFacetGroups(input) {
|
|
|
161
230
|
if (seen.has(slug))
|
|
162
231
|
continue;
|
|
163
232
|
seen.add(slug);
|
|
233
|
+
// Applied first, type second — in that order, so an `imei` somebody
|
|
234
|
+
// somehow got into a link keeps the control that removes it.
|
|
235
|
+
const applied = (input.state.filters[slug] ?? []).length > 0;
|
|
236
|
+
if (!applied && !isFacetableFeature(bySlug.get(slug)))
|
|
237
|
+
continue;
|
|
164
238
|
slugs.push(slug);
|
|
165
239
|
}
|
|
166
240
|
return slugs.map((slug) => {
|
package/dist/state/facets.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"facets.js","sourceRoot":"","sources":["../../src/state/facets.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"facets.js","sourceRoot":"","sources":["../../src/state/facets.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,OAAO,EACL,uBAAuB,EACvB,aAAa,EACb,WAAW,EACX,WAAW,EACX,kBAAkB,GACnB,MAAM,0BAA0B,CAAC;AAIlC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAsB;IACxD,MAAM;IACN,qBAAqB;IACrB,GAAG,uBAAuB;IAC1B,QAAQ;CACT,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA+B;IAChE,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACvC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACpC,OAAO,uBAAuB,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;AAChD,CAAC;AAsED,SAAS,SAAS,CAAC,CAAwC,EAAE,GAAW;IACtE,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,GAAG,CAAC;IAChC,MAAM,QAAQ,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;IACxB,OAAO,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC;AAC9C,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,WAAW,CAClB,MAA4C,EAC5C,IAAY,EACZ,KAAa,EACb,CAAwC;IAExC,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,CAAC;IAC7B,MAAM,OAAO,GAAG,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC;IACrC,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,SAAS,CAAC;IACpE,OAAO,KAAK,EAAE,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;AACxE,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,oBAAoB,CAAC,OAA+B;IAC3D,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrC,MAAM,GAAG,GAAG,aAAa,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAAE,OAAO,EAAE,CAAC;IACnC,MAAM,GAAG,GAAa,EAAE,CAAC;IACzB,KAAK,MAAM,MAAM,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,MAAM,KAAK,IAAI,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YAClD,MAAM,KAAK,GAAI,MAA8B,CAAC,KAAK,CAAC;YACpD,IAAI,KAAK,KAAK,SAAS,IAAI,KAAK,KAAK,IAAI;gBAAE,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACrE,CAAC;aAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;YACtC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACnB,CAAC;IACH,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,YAAY,CACnB,KAA4B,EAC5B,OAA+B,EAC/B,IAAY,EACZ,KAAa,EACb,YAA8D;IAE9D,OAAO,CACL,WAAW,CAAC,KAAK,CAAC,WAAW,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;QACpD,gBAAgB,CAAC,OAAO,EAAE,KAAK,EAAE,YAAY,CAAC,CAC/C,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAA+B,EAC/B,KAAa,EACb,OAA4E;IAE5E,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IACxC,MAAM,IAAI,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IAClC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,KAAK,CAAC;IAErC,IAAI,OAAO,GAAY,KAAK,CAAC;IAC7B,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC;QACd,KAAK,qBAAqB;YACxB,OAAO,GAAG,CAAC,KAAK,CAAC,CAAC;YAClB,MAAM;QACR,KAAK,KAAK,CAAC;QACX,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC,CAAC,CAAC;YACZ,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,OAAO,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;YACnD,MAAM;QACR,CAAC;QACD,KAAK,MAAM;YACT,OAAO,GAAG,KAAK,KAAK,MAAM,IAAI,KAAK,KAAK,GAAG,CAAC;YAC5C,MAAM;QACR;YACE,OAAO,GAAG,KAAK,CAAC;IACpB,CAAC;IAED,MAAM,SAAS,GAAG,kBAAkB,CAClC,OAAO,EACP,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,EACxB;QACE,GAAG,CAAC,OAAO,EAAE,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACrD,GAAG,CAAC,OAAO,EAAE,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KACrE,CACF,CAAC;IACF,OAAO,SAAS,KAAK,SAAS,IAAI,SAAS,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC;AAC7E,CAAC;AAED;;;;;;;;;;;;;;;GAeG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA4B;IAC3D,MAAM,MAAM,GAAG,IAAI,GAAG,EAAsB,CAAC;IAC7C,KAAK,MAAM,OAAO,IAAI,KAAK,CAAC,gBAAgB,IAAI,EAAE;QAAE,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAEtF,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,KAAK,MAAM,IAAI,IAAI;QACjB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC;QAC5B,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO;QACrB,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC;KACpC,EAAE,CAAC;QACF,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,SAAS;QAC7B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,oEAAoE;QACpE,6DAA6D;QAC7D,MAAM,OAAO,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC;QAC7D,IAAI,CAAC,OAAO,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAAE,SAAS;QAChE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACnB,CAAC;IAED,OAAO,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACxB,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjC,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACxC,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,IAAI,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC;QAC3D,MAAM,QAAQ,GAAG,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAEjD,wEAAwE;QACxE,sEAAsE;QACtE,yEAAyE;QACzE,oBAAoB;QACpB,MAAM,UAAU,GAAG,oBAAoB,CAAC,OAAO,CAAC,CAAC;QACjD,MAAM,QAAQ,GACZ,UAAU,CAAC,MAAM,GAAG,CAAC;YACnB,CAAC,CAAC,UAAU;YACZ,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,IAAI,CAAC,EAAE,MAAM,IAAI,EAAE,CAAC,CAAC;QAC3D,MAAM,MAAM,GAAa,EAAE,CAAC;QAC5B,MAAM,IAAI,GAAG,CAAC,KAAa,EAAQ,EAAE;YACnC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAClD,CAAC,CAAC;QACF,qEAAqE;QACrE,mEAAmE;QACnE,KAAK,MAAM,KAAK,IAAI,QAAQ;YAAE,IAAI,KAAK,IAAI,MAAM;gBAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/D,MAAM,SAAS,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC;aAClC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;aAC5C,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,KAAK,MAAM,KAAK,IAAI,SAAS;YAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAC3C,KAAK,MAAM,KAAK,IAAI,QAAQ;YAAE,IAAI,CAAC,KAAK,CAAC,CAAC;QAE1C,MAAM,YAAY,GAAG;YACnB,GAAG,CAAC,KAAK,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAChD,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAChE,CAAC;QAEF,OAAO;YACL,IAAI;YACJ,KAAK,EACH,OAAO,KAAK,SAAS;gBACnB,CAAC,CAAC,IAAI;gBACN,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,WAAW,CAAC,OAAO,CAAC,CAAC;YAC9C,OAAO;YACP,OAAO;YACP,QAAQ;YACR,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;gBAC9B,KAAK;gBACL,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI;gBAC5C,mEAAmE;gBACnE,mEAAmE;gBACnE,qEAAqE;gBACrE,kEAAkE;gBAClE,8DAA8D;gBAC9D,KAAK,EAAE,YAAY,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,YAAY,CAAC;gBAC9D,QAAQ,EAAE,QAAQ,CAAC,QAAQ,CAAC,KAAK,CAAC;aACnC,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC,CAAC,CAAC;AACL,CAAC"}
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# @stapel/search-react 0.
|
|
1
|
+
# @stapel/search-react 0.13.0
|
|
2
2
|
|
|
3
|
-
Headless React flow pair for stapel-search (contract >=0.
|
|
3
|
+
Headless React flow pair for stapel-search (contract >=0.7 <0.8) — business + state, zero visual opinion.
|
|
4
4
|
Built on @stapel/core: typed client + StapelApiError envelope, auth token refresh,
|
|
5
5
|
verification-403 interception, i18n engine, analytics facade, TanStack Query layer.
|
|
6
6
|
|
|
@@ -86,7 +86,7 @@ const { tracked } = useTracked();
|
|
|
86
86
|
- search.page-size-select → <PageSizeSelect> [ladder|off-ladder] demo/PageSizeSelect.demo.tsx
|
|
87
87
|
- search.range-filter-row → <RangeFilterRow> [untouched|applied] demo/RangeFilterRow.demo.tsx
|
|
88
88
|
- search.ranking-pane → <RankingDisclosurePane> [desktop|phone] demo/RankingDisclosurePane.demo.tsx
|
|
89
|
-
- search.result-card → <SearchResultCard> [promoted|plain] demo/SearchResultCard.demo.tsx
|
|
89
|
+
- search.result-card → <SearchResultCard> [gallery|promoted|unresolved|plain] demo/SearchResultCard.demo.tsx
|
|
90
90
|
- search.results-pane → <SearchResultsPane> [desktop|phone|empty] demo/SearchResultsPane.demo.tsx
|
|
91
91
|
- search.sort-select → <SortSelect> [no-centre|with-centre] demo/SortSelect.demo.tsx
|
|
92
92
|
- search.url-issue-notice → <UrlIssueNotice> [two-issues|one-issue] demo/UrlIssueNotice.demo.tsx
|
package/manifest.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"$generated": "by scripts/gen-manifest.mjs — do not edit; drift-gated (pnpm gen:manifest:check)",
|
|
3
3
|
"package": "@stapel/search-react",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.13.0",
|
|
5
5
|
"backend": {
|
|
6
6
|
"module": "stapel-search",
|
|
7
|
-
"contract": ">=0.
|
|
7
|
+
"contract": ">=0.7 <0.8"
|
|
8
8
|
},
|
|
9
9
|
"layers": [
|
|
10
10
|
"api",
|
|
@@ -586,16 +586,21 @@
|
|
|
586
586
|
{
|
|
587
587
|
"id": "search.result-card",
|
|
588
588
|
"title": "Result card",
|
|
589
|
-
"description": "The default card a doc type gets for free:
|
|
589
|
+
"description": "The default card a doc type gets for free: the card's whole photo gallery as a swipeable strip (references resolved through the runtime's resolveImage seam and drawn by @stapel/image, so the 4:3 well lands before the network does), the title, the price with its currency, the location and distance — and the promoted marking painted from a token role rather than an antd preset, with its explanation as ordinary text beneath it.",
|
|
590
590
|
"component": "SearchResultCard",
|
|
591
591
|
"tokens": [
|
|
592
592
|
"warning-bg",
|
|
593
593
|
"warning-on",
|
|
594
594
|
"warning-border",
|
|
595
|
-
"surface-sunken"
|
|
595
|
+
"surface-sunken",
|
|
596
|
+
"text-muted",
|
|
597
|
+
"border",
|
|
598
|
+
"focus-ring"
|
|
596
599
|
],
|
|
597
600
|
"variants": [
|
|
601
|
+
"gallery",
|
|
598
602
|
"promoted",
|
|
603
|
+
"unresolved",
|
|
599
604
|
"plain"
|
|
600
605
|
],
|
|
601
606
|
"source": "demo/SearchResultCard.demo.tsx"
|
|
@@ -703,6 +708,10 @@
|
|
|
703
708
|
"error.500.internal",
|
|
704
709
|
"error.503.mandate_unavailable",
|
|
705
710
|
"error.503.search_backend_unavailable",
|
|
711
|
+
"search.box.categories",
|
|
712
|
+
"search.box.category_count",
|
|
713
|
+
"search.box.category_count.one",
|
|
714
|
+
"search.box.category_count.other",
|
|
706
715
|
"search.box.clear",
|
|
707
716
|
"search.box.label",
|
|
708
717
|
"search.box.placeholder",
|
|
@@ -745,6 +754,7 @@
|
|
|
745
754
|
"search.filters.chips_label",
|
|
746
755
|
"search.filters.dismiss",
|
|
747
756
|
"search.filters.open",
|
|
757
|
+
"search.filters.short",
|
|
748
758
|
"search.filters.show_count",
|
|
749
759
|
"search.filters.show_count.one",
|
|
750
760
|
"search.filters.show_count.other",
|
|
@@ -763,6 +773,9 @@
|
|
|
763
773
|
"search.limit.from_link",
|
|
764
774
|
"search.limit.label",
|
|
765
775
|
"search.limit.option",
|
|
776
|
+
"search.nav.ranking",
|
|
777
|
+
"search.nav.ranking.short",
|
|
778
|
+
"search.nav.results",
|
|
766
779
|
"search.range.price",
|
|
767
780
|
"search.ranking.applies_to",
|
|
768
781
|
"search.ranking.empty",
|
|
@@ -793,6 +806,9 @@
|
|
|
793
806
|
"search.results.loading",
|
|
794
807
|
"search.results.next",
|
|
795
808
|
"search.results.open",
|
|
809
|
+
"search.results.photo_alt",
|
|
810
|
+
"search.results.photo_unavailable",
|
|
811
|
+
"search.results.photos",
|
|
796
812
|
"search.results.prev",
|
|
797
813
|
"search.results.promoted",
|
|
798
814
|
"search.results.promoted_hint",
|
|
@@ -819,6 +835,7 @@
|
|
|
819
835
|
],
|
|
820
836
|
"exports": {
|
|
821
837
|
"runtime": [
|
|
838
|
+
"FACETABLE_FEATURE_TYPES",
|
|
822
839
|
"FILTER_PREFIX",
|
|
823
840
|
"FacetPanel",
|
|
824
841
|
"RANGE_FEATURE_TYPES",
|
|
@@ -839,6 +856,8 @@
|
|
|
839
856
|
"SEARCH_QUERY_MAX_CHARS",
|
|
840
857
|
"SEARCH_SORTS",
|
|
841
858
|
"SEARCH_WINDOW_EXCEEDED",
|
|
859
|
+
"SUGGEST_DEGRADED_CATEGORIES",
|
|
860
|
+
"SUGGEST_DEGRADED_ROLLUP",
|
|
842
861
|
"SUGGEST_MAX_LIMIT",
|
|
843
862
|
"SUGGEST_MIN_CHARS",
|
|
844
863
|
"SearchProvider",
|
|
@@ -860,9 +879,11 @@
|
|
|
860
879
|
"explainSearchError",
|
|
861
880
|
"facetOptionLabel",
|
|
862
881
|
"isCountNuanceOnly",
|
|
882
|
+
"isFacetableFeature",
|
|
863
883
|
"isRangeFeature",
|
|
864
884
|
"isRangeUsable",
|
|
865
885
|
"navEntries",
|
|
886
|
+
"offerableCategories",
|
|
866
887
|
"ownsParam",
|
|
867
888
|
"parseDegradations",
|
|
868
889
|
"parseSearchState",
|
|
@@ -875,9 +896,11 @@
|
|
|
875
896
|
"searchQueryParams",
|
|
876
897
|
"setFilterValues",
|
|
877
898
|
"setRangeValue",
|
|
899
|
+
"suggestTerms",
|
|
878
900
|
"toggleFilterValue",
|
|
879
901
|
"useAppliedSort",
|
|
880
902
|
"useFacetPanel",
|
|
903
|
+
"useHostFacetLabels",
|
|
881
904
|
"useRankingDisclosure",
|
|
882
905
|
"useSearchAnalytics",
|
|
883
906
|
"useSearchApi",
|
|
@@ -894,6 +917,8 @@
|
|
|
894
917
|
"BuildRangeGroupsInput",
|
|
895
918
|
"CreateSearchRuntimeOptions",
|
|
896
919
|
"FacetGroup",
|
|
920
|
+
"FacetLabelRequest",
|
|
921
|
+
"FacetLabelResolver",
|
|
897
922
|
"FacetMeta",
|
|
898
923
|
"FacetOption",
|
|
899
924
|
"FacetPanelBag",
|
|
@@ -920,6 +945,7 @@
|
|
|
920
945
|
"SearchGeoBox",
|
|
921
946
|
"SearchGeoCenter",
|
|
922
947
|
"SearchI18nKey",
|
|
948
|
+
"SearchImageResolver",
|
|
923
949
|
"SearchItem",
|
|
924
950
|
"SearchPageInfo",
|
|
925
951
|
"SearchParamsAdapter",
|
|
@@ -934,6 +960,9 @@
|
|
|
934
960
|
"SearchStateIssueCode",
|
|
935
961
|
"SearchStatePatch",
|
|
936
962
|
"SearchStateProviderProps",
|
|
963
|
+
"SuggestAnswer",
|
|
964
|
+
"SuggestCategory",
|
|
965
|
+
"SuggestCategoryMatch",
|
|
937
966
|
"SuggestParams",
|
|
938
967
|
"SuggestResponse",
|
|
939
968
|
"UseSearchBoxOptions",
|
package/nav-manifest.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@stapel/search-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"entries": [
|
|
5
5
|
{
|
|
6
6
|
"id": "search.results",
|
|
7
|
-
"labelKey": "search.results
|
|
7
|
+
"labelKey": "search.nav.results",
|
|
8
8
|
"icon": "SearchOutlined",
|
|
9
9
|
"route": {
|
|
10
10
|
"path": "/s"
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
},
|
|
24
24
|
{
|
|
25
25
|
"id": "search.ranking",
|
|
26
|
-
"labelKey": "search.ranking
|
|
26
|
+
"labelKey": "search.nav.ranking",
|
|
27
|
+
"shortLabelKey": "search.nav.ranking.short",
|
|
27
28
|
"icon": "OrderedListOutlined",
|
|
28
29
|
"route": {
|
|
29
30
|
"path": "/ranking-disclosure"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stapel/search-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Headless React pair for stapel-search: a typed query client, TanStack Query hooks, and a URL-first state codec that makes a search shareable by construction (filters, ranges, geo, sort and the keyset cursor all live in the query string). Drill-down facets rendered with their remaining counts and with the server's own honesty flags — approximate, skipped, degraded — never swallowed; keyset pagination with the window refusal named; DSA Art. 26 `promoted` marking carried into every card slot and the P2B Art. 5 ranking disclosure exposed as data. Zero visual opinion in the main entry; an opt-in /default subpath ships the antd skin, and /router binds the codec to react-router's useSearchParams.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -52,14 +52,14 @@
|
|
|
52
52
|
],
|
|
53
53
|
"size-limit": [
|
|
54
54
|
{
|
|
55
|
-
"name": "index — the headless pair (client + hooks + URL codec + facet model): no antd, no react-router",
|
|
55
|
+
"name": "index — the headless pair (client + hooks + URL codec + facet model incl. the facetability rule and the host label seam): no antd, no react-router",
|
|
56
56
|
"path": "dist/index.js",
|
|
57
|
-
"limit": "10 KB"
|
|
57
|
+
"limit": "10.5 KB"
|
|
58
58
|
},
|
|
59
59
|
{
|
|
60
|
-
"name": "default — the antd skin (query box + typeahead, filters incl. ranges/geo/category slots + the phone chip row and the location summary row, results incl. the view switch, ranking) must stay out of the main bundle",
|
|
60
|
+
"name": "default — the antd skin (query box + a typeahead that offers CATEGORY destinations with their live counts, filters incl. ranges/geo/category slots + the phone chip row with its leading category chip and the location summary row, results incl. the view switch, the card photo GALLERY as a SkinCarousel strip, ranking) must stay out of the main bundle",
|
|
61
61
|
"path": "dist/default/index.js",
|
|
62
|
-
"limit": "
|
|
62
|
+
"limit": "20 KB"
|
|
63
63
|
},
|
|
64
64
|
{
|
|
65
65
|
"name": "router — the react-router binding is opt-in; the main entry must never pull a router",
|
|
@@ -78,10 +78,10 @@
|
|
|
78
78
|
}
|
|
79
79
|
],
|
|
80
80
|
"peerDependencies": {
|
|
81
|
-
"@stapel/attributes-react": ">=0.
|
|
81
|
+
"@stapel/attributes-react": ">=0.4.0",
|
|
82
82
|
"@stapel/core": ">=0.18.1 <1.0.0",
|
|
83
83
|
"@stapel/image": ">=0.3.0",
|
|
84
|
-
"@stapel/tokens-antd": ">=0.
|
|
84
|
+
"@stapel/tokens-antd": ">=0.11.0",
|
|
85
85
|
"@tanstack/react-query": "^5.0.0",
|
|
86
86
|
"antd": ">=5.20.0 <7",
|
|
87
87
|
"react": ">=19",
|
|
@@ -115,12 +115,12 @@
|
|
|
115
115
|
"size-limit": "^11.2.0",
|
|
116
116
|
"typescript": "^5.8.3",
|
|
117
117
|
"vitest": "^3.2.4",
|
|
118
|
-
"@stapel/attributes-react": "^0.
|
|
119
|
-
"@stapel/core": "^0.
|
|
118
|
+
"@stapel/attributes-react": "^0.6.0",
|
|
119
|
+
"@stapel/core": "^0.22.0",
|
|
120
120
|
"@stapel/image": "^0.4.2",
|
|
121
|
+
"@stapel/showcase": "^0.3.0",
|
|
121
122
|
"@stapel/tokens": "^0.6.0",
|
|
122
|
-
"@stapel/tokens-antd": "^0.
|
|
123
|
-
"@stapel/showcase": "^0.3.0"
|
|
123
|
+
"@stapel/tokens-antd": "^0.11.0"
|
|
124
124
|
},
|
|
125
125
|
"engines": {
|
|
126
126
|
"node": ">=22"
|
|
@@ -102,13 +102,24 @@ export interface paths {
|
|
|
102
102
|
cookie?: never;
|
|
103
103
|
};
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
106
|
-
* @description ``GET /search/api/v1/suggest`` —
|
|
105
|
+
* Type-ahead: category paths with live counts, plus title prefixes
|
|
106
|
+
* @description ``GET /search/api/v1/suggest`` — what to offer under the search box.
|
|
107
107
|
*
|
|
108
|
-
*
|
|
108
|
+
* ``categories`` is the primary half: each row is a destination with its
|
|
109
|
+
* full ancestor path and the number of listings a buyer would actually
|
|
110
|
+
* see there, ranked by that number. ``terms`` is the title-prefix half.
|
|
111
|
+
*
|
|
112
|
+
* Neither comes from a query log: no query log is kept, which is a privacy
|
|
109
113
|
* decision before it is a product one, and on day one there would be
|
|
110
114
|
* nothing in it anyway.
|
|
111
115
|
*
|
|
116
|
+
* The answer is public, identical for every reader and requested on every
|
|
117
|
+
* keystroke, so it carries ``Cache-Control: public`` and an ``ETag``. This
|
|
118
|
+
* is the module's first conditional read — ``query`` has none, because a
|
|
119
|
+
* SERP answer embeds ``took_ms`` and a cursor and would revalidate to a
|
|
120
|
+
* miss every time. Here the payload is deliberately free of anything that
|
|
121
|
+
* varies with the clock.
|
|
122
|
+
*
|
|
112
123
|
* **Permissions:** `AllowAny`
|
|
113
124
|
*/
|
|
114
125
|
get: operations["search_api_v1_suggest_retrieve"];
|
|
@@ -124,6 +135,30 @@ export interface paths {
|
|
|
124
135
|
export type webhooks = Record<string, never>;
|
|
125
136
|
export interface components {
|
|
126
137
|
schemas: {
|
|
138
|
+
/** @description One destination in the dropdown, ready to render and ready to follow. */
|
|
139
|
+
CategorySuggestion: {
|
|
140
|
+
/** @description Category id. */
|
|
141
|
+
id: number;
|
|
142
|
+
/** @description Category slug. */
|
|
143
|
+
slug: string;
|
|
144
|
+
/** @description The category's own display name. */
|
|
145
|
+
name: string;
|
|
146
|
+
/** @description Display names root->leaf, e.g. ['Мужская одежда', 'Шорты']. This is what distinguishes three categories that share a name. */
|
|
147
|
+
path: string[];
|
|
148
|
+
/** @description The ancestry as ids joined with '/'. Pass it verbatim as the `category` parameter of /query — do not re-join path segments yourself. */
|
|
149
|
+
category: string;
|
|
150
|
+
/** @description Live listings a buyer would see under this category, descendants included — the same number the SERP reports for it. */
|
|
151
|
+
count: number;
|
|
152
|
+
/** @description Number of segments in `path`. */
|
|
153
|
+
depth: number;
|
|
154
|
+
/**
|
|
155
|
+
* @description How the name matched. Informational; ranking is by `count`.
|
|
156
|
+
*
|
|
157
|
+
* * `prefix` - prefix
|
|
158
|
+
* * `substring` - substring
|
|
159
|
+
*/
|
|
160
|
+
match: components["schemas"]["MatchEnum"];
|
|
161
|
+
};
|
|
127
162
|
/** @description Captions for one slug's option codes. */
|
|
128
163
|
FacetLabels: {
|
|
129
164
|
/** @description True when `values` holds translation KEYS to run through the catalogue; false when it holds literal captions. The reader cannot tell by looking — `b.apple` and `Б/у` are both strings. */
|
|
@@ -155,6 +190,12 @@ export interface components {
|
|
|
155
190
|
lag_seconds?: number | null;
|
|
156
191
|
stale_reason?: string;
|
|
157
192
|
};
|
|
193
|
+
/**
|
|
194
|
+
* @description * `prefix` - prefix
|
|
195
|
+
* * `substring` - substring
|
|
196
|
+
* @enum {string}
|
|
197
|
+
*/
|
|
198
|
+
MatchEnum: "prefix" | "substring";
|
|
158
199
|
/** @description The P2B Art. 5 disclosure, generated from the scorer registry. */
|
|
159
200
|
RankingResponse: {
|
|
160
201
|
doc_type: string;
|
|
@@ -242,7 +283,16 @@ export interface components {
|
|
|
242
283
|
took_ms: number;
|
|
243
284
|
};
|
|
244
285
|
SuggestResponse: {
|
|
286
|
+
/** @description Destinations, ranked by live listing count desc, then depth, then name. */
|
|
287
|
+
categories: components["schemas"]["CategorySuggestion"][];
|
|
288
|
+
/** @description Title prefixes from the index. */
|
|
289
|
+
terms: string[];
|
|
290
|
+
/** @description Deprecated alias of `terms`, kept for one minor. */
|
|
245
291
|
items: string[];
|
|
292
|
+
/** @description Which dictionary answered — the same resolution /query reports. */
|
|
293
|
+
language: string;
|
|
294
|
+
/** @description What this answer could not do: `category_suggestions` (no provider for category names), `category_rollup` (no ancestry, so counts would read 0). */
|
|
295
|
+
degraded: string[];
|
|
246
296
|
backend: string;
|
|
247
297
|
};
|
|
248
298
|
};
|
|
@@ -372,11 +422,15 @@ export interface operations {
|
|
|
372
422
|
};
|
|
373
423
|
search_api_v1_suggest_retrieve: {
|
|
374
424
|
parameters: {
|
|
375
|
-
query
|
|
425
|
+
query?: {
|
|
426
|
+
/** @description Language of the query: picks the dictionary, so «shorty» reaches «шорты». Falls back to Accept-Language, then DEFAULT_LANGUAGE. */
|
|
427
|
+
lang?: string;
|
|
428
|
+
/** @description Rows per half. Capped by MAX_SUGGEST_LIMIT. */
|
|
376
429
|
limit?: number;
|
|
377
|
-
/** @description
|
|
430
|
+
/** @description What the buyer has typed so far. */
|
|
378
431
|
q?: string;
|
|
379
|
-
type
|
|
432
|
+
/** @description Registered doc_type. Optional when exactly one type is registered — a type-ahead should not have to name the only corpus there is. */
|
|
433
|
+
type?: string;
|
|
380
434
|
};
|
|
381
435
|
header?: never;
|
|
382
436
|
path?: never;
|
package/src/api/searchApi.ts
CHANGED
|
@@ -3,8 +3,8 @@ import type {
|
|
|
3
3
|
RankingResponse,
|
|
4
4
|
SearchQueryState,
|
|
5
5
|
SearchResponse,
|
|
6
|
+
SuggestAnswer,
|
|
6
7
|
SuggestParams,
|
|
7
|
-
SuggestResponse,
|
|
8
8
|
} from "./types.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
@@ -53,15 +53,22 @@ export interface SearchApi {
|
|
|
53
53
|
): Promise<SearchResponse>;
|
|
54
54
|
|
|
55
55
|
/**
|
|
56
|
-
*
|
|
57
|
-
*
|
|
58
|
-
*
|
|
59
|
-
*
|
|
56
|
+
* What to offer under the search box: CATEGORIES first, then title-prefix
|
|
57
|
+
* terms (stapel-search 0.7.0).
|
|
58
|
+
*
|
|
59
|
+
* Neither half comes from a query log — the module keeps none, which is a
|
|
60
|
+
* privacy decision before it is a product one — so every suggestion is a
|
|
61
|
+
* destination or a search that has results.
|
|
62
|
+
*
|
|
63
|
+
* Typed as {@link SuggestAnswer} rather than as the generated
|
|
64
|
+
* `SuggestResponse`: a build regenerated against a pre-0.7.0 schema would
|
|
65
|
+
* otherwise hide the categories half from the compiler. See that type for
|
|
66
|
+
* why every member but `backend` is optional.
|
|
60
67
|
*/
|
|
61
68
|
suggest(
|
|
62
69
|
params: SuggestParams,
|
|
63
70
|
options?: { readonly signal?: AbortSignal }
|
|
64
|
-
): Promise<
|
|
71
|
+
): Promise<SuggestAnswer>;
|
|
65
72
|
|
|
66
73
|
/**
|
|
67
74
|
* The P2B Art. 5 ranking disclosure for a doc type: which parameters rank
|