@stapel/search-react 0.3.0 → 0.4.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 +35 -0
- package/MODULE.md +43 -4
- package/dist/api/generated/schema.d.ts +5 -1
- package/dist/api/generated/schema.d.ts.map +1 -1
- package/dist/default/DegradationNotice.d.ts +27 -0
- package/dist/default/DegradationNotice.d.ts.map +1 -1
- package/dist/default/DegradationNotice.js +17 -6
- package/dist/default/DegradationNotice.js.map +1 -1
- package/dist/default/SearchPage.d.ts +4 -0
- package/dist/default/SearchPage.d.ts.map +1 -1
- package/dist/default/SearchPage.js +4 -2
- package/dist/default/SearchPage.js.map +1 -1
- package/dist/default/SearchResultsPane.d.ts +12 -0
- package/dist/default/SearchResultsPane.d.ts.map +1 -1
- package/dist/default/SearchResultsPane.js +8 -5
- package/dist/default/SearchResultsPane.js.map +1 -1
- package/dist/default/index.d.ts +1 -1
- package/dist/default/index.d.ts.map +1 -1
- package/dist/default/index.js.map +1 -1
- package/dist/headless/SearchResults.d.ts +20 -3
- package/dist/headless/SearchResults.d.ts.map +1 -1
- package/dist/headless/SearchResults.js +3 -1
- package/dist/headless/SearchResults.js.map +1 -1
- package/dist/i18n/es.d.ts.map +1 -1
- package/dist/i18n/es.js +2 -0
- package/dist/i18n/es.js.map +1 -1
- package/dist/i18n/keys.d.ts +11 -2
- package/dist/i18n/keys.d.ts.map +1 -1
- package/dist/i18n/keys.js +14 -2
- package/dist/i18n/keys.js.map +1 -1
- package/dist/i18n/ru.d.ts.map +1 -1
- package/dist/i18n/ru.js +4 -0
- package/dist/i18n/ru.js.map +1 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/state/degradations.d.ts +41 -0
- package/dist/state/degradations.d.ts.map +1 -1
- package/dist/state/degradations.js +41 -0
- package/dist/state/degradations.js.map +1 -1
- package/llms.txt +2 -2
- package/manifest.json +8 -2
- package/nav-manifest.json +1 -1
- package/package.json +4 -4
- package/src/analytics/generated/events.json +1 -1
- package/src/api/generated/schema.ts +5 -1
- package/src/default/DegradationNotice.tsx +61 -13
- package/src/default/SearchPage.tsx +8 -0
- package/src/default/SearchResultsPane.tsx +27 -6
- package/src/default/index.ts +4 -1
- package/src/headless/SearchResults.tsx +32 -4
- package/src/i18n/es.ts +2 -0
- package/src/i18n/keys.ts +14 -2
- package/src/i18n/ru.ts +4 -0
- package/src/index.ts +8 -1
- package/src/state/degradations.ts +60 -0
package/src/i18n/keys.ts
CHANGED
|
@@ -28,9 +28,18 @@ export const SEARCH_I18N_KEYS = {
|
|
|
28
28
|
resultsLoadFailed: "search.results.load_failed",
|
|
29
29
|
resultsEmpty: "search.results.empty",
|
|
30
30
|
resultsRetry: "search.results.retry",
|
|
31
|
-
/**
|
|
32
|
-
*
|
|
31
|
+
/**
|
|
32
|
+
* "About N results" — the sentence for an ESTIMATED count. A PLURAL
|
|
33
|
+
* FAMILY: render with `tPlural`, never `t` (see SEARCH_I18N_PLURAL_KEYS).
|
|
34
|
+
*
|
|
35
|
+
* @deprecated stapel-search 0.2.0 stopped producing estimates: a count is
|
|
36
|
+
* exact, a FLOOR (`resultsCountAtLeast`), or absent. Kept so a host that
|
|
37
|
+
* translated it keeps a working key, and no longer rendered by the skin.
|
|
38
|
+
*/
|
|
33
39
|
resultsCountApproximate: "search.results.count_approximate",
|
|
40
|
+
/** "N+ results" — a LOWER BOUND: at least this many match, possibly more.
|
|
41
|
+
* A PLURAL FAMILY. Never render a floor as a plain number. */
|
|
42
|
+
resultsCountAtLeast: "search.results.count_at_least",
|
|
34
43
|
/** "N results" — only when `exact_total` is true. A PLURAL FAMILY. */
|
|
35
44
|
resultsCountExact: "search.results.count_exact",
|
|
36
45
|
resultsTookMs: "search.results.took_ms",
|
|
@@ -129,6 +138,7 @@ export type SearchI18nKey =
|
|
|
129
138
|
*/
|
|
130
139
|
export const SEARCH_I18N_PLURAL_KEYS: readonly SearchI18nKey[] = [
|
|
131
140
|
SEARCH_I18N_KEYS.resultsCountApproximate,
|
|
141
|
+
SEARCH_I18N_KEYS.resultsCountAtLeast,
|
|
132
142
|
SEARCH_I18N_KEYS.resultsCountExact,
|
|
133
143
|
];
|
|
134
144
|
|
|
@@ -149,6 +159,8 @@ export const searchI18nBundleEn: Record<string, string> = {
|
|
|
149
159
|
"search.results.retry": "Try again",
|
|
150
160
|
"search.results.count_approximate.one": "About {count} result",
|
|
151
161
|
"search.results.count_approximate.other": "About {count} results",
|
|
162
|
+
"search.results.count_at_least.one": "{count}+ result",
|
|
163
|
+
"search.results.count_at_least.other": "{count}+ results",
|
|
152
164
|
"search.results.count_exact.one": "{count} result",
|
|
153
165
|
"search.results.count_exact.other": "{count} results",
|
|
154
166
|
"search.results.took_ms": "{ms} ms",
|
package/src/i18n/ru.ts
CHANGED
|
@@ -41,6 +41,10 @@ export const searchI18nBundleRu: I18nDictionary = {
|
|
|
41
41
|
"search.results.count_approximate.few": "Примерно {count} объявления",
|
|
42
42
|
"search.results.count_approximate.many": "Примерно {count} объявлений",
|
|
43
43
|
"search.results.count_approximate.other": "Примерно {count} объявления",
|
|
44
|
+
"search.results.count_at_least.one": "{count}+ объявление",
|
|
45
|
+
"search.results.count_at_least.few": "{count}+ объявления",
|
|
46
|
+
"search.results.count_at_least.many": "{count}+ объявлений",
|
|
47
|
+
"search.results.count_at_least.other": "{count}+ объявления",
|
|
44
48
|
"search.results.count_exact.one": "{count} объявление",
|
|
45
49
|
"search.results.count_exact.few": "{count} объявления",
|
|
46
50
|
"search.results.count_exact.many": "{count} объявлений",
|
package/src/index.ts
CHANGED
|
@@ -86,7 +86,14 @@ export type {
|
|
|
86
86
|
SearchStatePatch,
|
|
87
87
|
} from "./state/urlState.js";
|
|
88
88
|
|
|
89
|
-
export {
|
|
89
|
+
export {
|
|
90
|
+
countIsEstimate,
|
|
91
|
+
countKind,
|
|
92
|
+
degradationMessageKey,
|
|
93
|
+
isCountNuanceOnly,
|
|
94
|
+
parseDegradations,
|
|
95
|
+
} from "./state/degradations.js";
|
|
96
|
+
export type { SearchCountKind } from "./state/degradations.js";
|
|
90
97
|
|
|
91
98
|
export { buildFacetGroups, facetOptionLabel } from "./state/facets.js";
|
|
92
99
|
export type {
|
|
@@ -66,6 +66,11 @@ export function parseDegradations(
|
|
|
66
66
|
* the envelope's own `exact_total: false`, and the `"exact_total"`
|
|
67
67
|
* degradation. They agree in practice; treating either as decisive is what
|
|
68
68
|
* keeps "≈1 200" from ever being rendered as "1 200".
|
|
69
|
+
*
|
|
70
|
+
* @deprecated Since stapel-search 0.2.0 the envelope answers this directly
|
|
71
|
+
* with `count_is_lower_bound`, and "not exact" now means a FLOOR rather than
|
|
72
|
+
* a fuzzy number. Use {@link countKind}, which reads the wire field and also
|
|
73
|
+
* handles `count: null`.
|
|
69
74
|
*/
|
|
70
75
|
export function countIsEstimate(
|
|
71
76
|
exactTotal: boolean,
|
|
@@ -73,3 +78,58 @@ export function countIsEstimate(
|
|
|
73
78
|
): boolean {
|
|
74
79
|
return !exactTotal || degradations.some((d) => d.kind === "exact_total");
|
|
75
80
|
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* How a count may be spoken: as a number, as a floor, or not at all.
|
|
84
|
+
*
|
|
85
|
+
* The three states stapel-search 0.2.0 made explicit, because the version
|
|
86
|
+
* before it had only two and used `0` for both "none match" and "we do not
|
|
87
|
+
* know" — which is how a storefront came to print "About 0 listings" over
|
|
88
|
+
* four visible cards.
|
|
89
|
+
*/
|
|
90
|
+
export type SearchCountKind = "exact" | "at_least" | "unknown";
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Read the envelope's three count fields as one decision.
|
|
94
|
+
*
|
|
95
|
+
* `null` is UNKNOWN and renders as no count line — never as `0`, and never
|
|
96
|
+
* as "about 0". Anything the server declines to call exact is rendered as a
|
|
97
|
+
* floor ("N+"), including the defensive case of an `exact_total: false` from
|
|
98
|
+
* a server that predates `count_is_lower_bound`: claiming "at least N" over
|
|
99
|
+
* a page that shows N rows is the one reading that cannot be contradicted by
|
|
100
|
+
* what the reader can see.
|
|
101
|
+
*/
|
|
102
|
+
export function countKind(
|
|
103
|
+
count: number | null | undefined,
|
|
104
|
+
isLowerBound: boolean | undefined,
|
|
105
|
+
exactTotal: boolean,
|
|
106
|
+
degradations: readonly SearchDegradation[]
|
|
107
|
+
): SearchCountKind {
|
|
108
|
+
if (count === null || count === undefined) return "unknown";
|
|
109
|
+
if (isLowerBound === true) return "at_least";
|
|
110
|
+
return countIsEstimate(exactTotal, degradations) ? "at_least" : "exact";
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Is `exact_total` the ONLY thing the engine could not do?
|
|
115
|
+
*
|
|
116
|
+
* It is a count NUANCE, not a failed search: the answer is complete, the
|
|
117
|
+
* rows are the right rows, and the single consequence — that the total is a
|
|
118
|
+
* floor — is already spoken by the count itself as "N+". Raising a warning
|
|
119
|
+
* banner over it teaches a reader that a perfectly good result page is
|
|
120
|
+
* broken, and a banner that cries wolf on every landing page is a banner
|
|
121
|
+
* nobody reads on the day `category_rollup` shows up in it.
|
|
122
|
+
*
|
|
123
|
+
* Every other degradation changes what the page MEANS ("typos were not
|
|
124
|
+
* corrected", "subcategories may be missing", "counts are approximate") and
|
|
125
|
+
* still renders. So does `exact_total` when it arrives BESIDE one of them —
|
|
126
|
+
* the list is then a description of a genuinely degraded answer.
|
|
127
|
+
*/
|
|
128
|
+
export function isCountNuanceOnly(
|
|
129
|
+
degradations: readonly SearchDegradation[]
|
|
130
|
+
): boolean {
|
|
131
|
+
return (
|
|
132
|
+
degradations.length > 0 &&
|
|
133
|
+
degradations.every((degradation) => degradation.kind === "exact_total")
|
|
134
|
+
);
|
|
135
|
+
}
|