@stapel/search-react 0.11.0 → 0.12.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 +120 -0
- package/MODULE.md +111 -0
- 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/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/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 +7 -0
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/keys.d.ts +45 -0
- package/dist/i18n/keys.d.ts.map +1 -1
- package/dist/i18n/keys.js +54 -0
- package/dist/i18n/keys.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +9 -0
- package/dist/i18n/ru.js.map +1 -1
- package/dist/index.d.ts +6 -4
- 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/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 +2 -2
- package/manifest.json +22 -2
- 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/SearchResultsPane.tsx +48 -11
- package/src/default/SortSelect.tsx +70 -9
- 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 +8 -0
- package/src/i18n/keys.ts +56 -0
- package/src/i18n/ru.ts +10 -0
- package/src/index.ts +21 -3
- package/src/model/queries.ts +6 -5
- package/src/model/queryKeys.ts +23 -0
- 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":"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"}
|
package/llms.txt
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
# @stapel/search-react 0.
|
|
1
|
+
# @stapel/search-react 0.12.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
|
|
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.12.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",
|
|
@@ -703,6 +703,10 @@
|
|
|
703
703
|
"error.500.internal",
|
|
704
704
|
"error.503.mandate_unavailable",
|
|
705
705
|
"error.503.search_backend_unavailable",
|
|
706
|
+
"search.box.categories",
|
|
707
|
+
"search.box.category_count",
|
|
708
|
+
"search.box.category_count.one",
|
|
709
|
+
"search.box.category_count.other",
|
|
706
710
|
"search.box.clear",
|
|
707
711
|
"search.box.label",
|
|
708
712
|
"search.box.placeholder",
|
|
@@ -745,6 +749,7 @@
|
|
|
745
749
|
"search.filters.chips_label",
|
|
746
750
|
"search.filters.dismiss",
|
|
747
751
|
"search.filters.open",
|
|
752
|
+
"search.filters.short",
|
|
748
753
|
"search.filters.show_count",
|
|
749
754
|
"search.filters.show_count.one",
|
|
750
755
|
"search.filters.show_count.other",
|
|
@@ -763,6 +768,9 @@
|
|
|
763
768
|
"search.limit.from_link",
|
|
764
769
|
"search.limit.label",
|
|
765
770
|
"search.limit.option",
|
|
771
|
+
"search.nav.ranking",
|
|
772
|
+
"search.nav.ranking.short",
|
|
773
|
+
"search.nav.results",
|
|
766
774
|
"search.range.price",
|
|
767
775
|
"search.ranking.applies_to",
|
|
768
776
|
"search.ranking.empty",
|
|
@@ -819,6 +827,7 @@
|
|
|
819
827
|
],
|
|
820
828
|
"exports": {
|
|
821
829
|
"runtime": [
|
|
830
|
+
"FACETABLE_FEATURE_TYPES",
|
|
822
831
|
"FILTER_PREFIX",
|
|
823
832
|
"FacetPanel",
|
|
824
833
|
"RANGE_FEATURE_TYPES",
|
|
@@ -839,6 +848,8 @@
|
|
|
839
848
|
"SEARCH_QUERY_MAX_CHARS",
|
|
840
849
|
"SEARCH_SORTS",
|
|
841
850
|
"SEARCH_WINDOW_EXCEEDED",
|
|
851
|
+
"SUGGEST_DEGRADED_CATEGORIES",
|
|
852
|
+
"SUGGEST_DEGRADED_ROLLUP",
|
|
842
853
|
"SUGGEST_MAX_LIMIT",
|
|
843
854
|
"SUGGEST_MIN_CHARS",
|
|
844
855
|
"SearchProvider",
|
|
@@ -860,9 +871,11 @@
|
|
|
860
871
|
"explainSearchError",
|
|
861
872
|
"facetOptionLabel",
|
|
862
873
|
"isCountNuanceOnly",
|
|
874
|
+
"isFacetableFeature",
|
|
863
875
|
"isRangeFeature",
|
|
864
876
|
"isRangeUsable",
|
|
865
877
|
"navEntries",
|
|
878
|
+
"offerableCategories",
|
|
866
879
|
"ownsParam",
|
|
867
880
|
"parseDegradations",
|
|
868
881
|
"parseSearchState",
|
|
@@ -875,9 +888,11 @@
|
|
|
875
888
|
"searchQueryParams",
|
|
876
889
|
"setFilterValues",
|
|
877
890
|
"setRangeValue",
|
|
891
|
+
"suggestTerms",
|
|
878
892
|
"toggleFilterValue",
|
|
879
893
|
"useAppliedSort",
|
|
880
894
|
"useFacetPanel",
|
|
895
|
+
"useHostFacetLabels",
|
|
881
896
|
"useRankingDisclosure",
|
|
882
897
|
"useSearchAnalytics",
|
|
883
898
|
"useSearchApi",
|
|
@@ -894,6 +909,8 @@
|
|
|
894
909
|
"BuildRangeGroupsInput",
|
|
895
910
|
"CreateSearchRuntimeOptions",
|
|
896
911
|
"FacetGroup",
|
|
912
|
+
"FacetLabelRequest",
|
|
913
|
+
"FacetLabelResolver",
|
|
897
914
|
"FacetMeta",
|
|
898
915
|
"FacetOption",
|
|
899
916
|
"FacetPanelBag",
|
|
@@ -934,6 +951,9 @@
|
|
|
934
951
|
"SearchStateIssueCode",
|
|
935
952
|
"SearchStatePatch",
|
|
936
953
|
"SearchStateProviderProps",
|
|
954
|
+
"SuggestAnswer",
|
|
955
|
+
"SuggestCategory",
|
|
956
|
+
"SuggestCategoryMatch",
|
|
937
957
|
"SuggestParams",
|
|
938
958
|
"SuggestResponse",
|
|
939
959
|
"UseSearchBoxOptions",
|
package/nav-manifest.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"package": "@stapel/search-react",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.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.12.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, ranking) must stay out of the main bundle",
|
|
61
61
|
"path": "dist/default/index.js",
|
|
62
|
-
"limit": "
|
|
62
|
+
"limit": "19.5 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
|