@stapel/search-react 0.3.1 → 0.7.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 (153) hide show
  1. package/CHANGELOG.md +180 -0
  2. package/MODULE.md +43 -4
  3. package/README.md +1 -1
  4. package/dist/api/generated/schema.d.ts +5 -1
  5. package/dist/api/generated/schema.d.ts.map +1 -1
  6. package/dist/default/DegradationNotice.d.ts +34 -0
  7. package/dist/default/DegradationNotice.d.ts.map +1 -1
  8. package/dist/default/DegradationNotice.js +28 -6
  9. package/dist/default/DegradationNotice.js.map +1 -1
  10. package/dist/default/FacetPanelPane.d.ts +54 -3
  11. package/dist/default/FacetPanelPane.d.ts.map +1 -1
  12. package/dist/default/FacetPanelPane.js +119 -19
  13. package/dist/default/FacetPanelPane.js.map +1 -1
  14. package/dist/default/LanguageSelect.d.ts +9 -0
  15. package/dist/default/LanguageSelect.d.ts.map +1 -0
  16. package/dist/default/LanguageSelect.js +72 -0
  17. package/dist/default/LanguageSelect.js.map +1 -0
  18. package/dist/default/PageSizeSelect.d.ts +29 -0
  19. package/dist/default/PageSizeSelect.d.ts.map +1 -0
  20. package/dist/default/PageSizeSelect.js +25 -0
  21. package/dist/default/PageSizeSelect.js.map +1 -0
  22. package/dist/default/RangeFilterRow.d.ts +12 -0
  23. package/dist/default/RangeFilterRow.d.ts.map +1 -0
  24. package/dist/default/RangeFilterRow.js +75 -0
  25. package/dist/default/RangeFilterRow.js.map +1 -0
  26. package/dist/default/RankingDisclosurePane.d.ts +5 -0
  27. package/dist/default/RankingDisclosurePane.d.ts.map +1 -1
  28. package/dist/default/RankingDisclosurePane.js +15 -15
  29. package/dist/default/RankingDisclosurePane.js.map +1 -1
  30. package/dist/default/SearchBox.d.ts +13 -0
  31. package/dist/default/SearchBox.d.ts.map +1 -0
  32. package/dist/default/SearchBox.js +67 -0
  33. package/dist/default/SearchBox.js.map +1 -0
  34. package/dist/default/SearchPage.d.ts +58 -16
  35. package/dist/default/SearchPage.d.ts.map +1 -1
  36. package/dist/default/SearchPage.js +155 -6
  37. package/dist/default/SearchPage.js.map +1 -1
  38. package/dist/default/SearchResultCard.d.ts +19 -18
  39. package/dist/default/SearchResultCard.d.ts.map +1 -1
  40. package/dist/default/SearchResultCard.js +178 -5
  41. package/dist/default/SearchResultCard.js.map +1 -1
  42. package/dist/default/SearchResultsPane.d.ts +54 -3
  43. package/dist/default/SearchResultsPane.d.ts.map +1 -1
  44. package/dist/default/SearchResultsPane.js +45 -25
  45. package/dist/default/SearchResultsPane.js.map +1 -1
  46. package/dist/default/SortSelect.d.ts +10 -2
  47. package/dist/default/SortSelect.d.ts.map +1 -1
  48. package/dist/default/SortSelect.js +27 -24
  49. package/dist/default/SortSelect.js.map +1 -1
  50. package/dist/default/UrlIssueNotice.d.ts.map +1 -1
  51. package/dist/default/UrlIssueNotice.js +19 -1
  52. package/dist/default/UrlIssueNotice.js.map +1 -1
  53. package/dist/default/index.d.ts +33 -16
  54. package/dist/default/index.d.ts.map +1 -1
  55. package/dist/default/index.js +26 -12
  56. package/dist/default/index.js.map +1 -1
  57. package/dist/default/sortLabels.d.ts +5 -0
  58. package/dist/default/sortLabels.d.ts.map +1 -0
  59. package/dist/default/sortLabels.js +32 -0
  60. package/dist/default/sortLabels.js.map +1 -0
  61. package/dist/headless/FacetPanel.d.ts +17 -0
  62. package/dist/headless/FacetPanel.d.ts.map +1 -1
  63. package/dist/headless/FacetPanel.js +23 -2
  64. package/dist/headless/FacetPanel.js.map +1 -1
  65. package/dist/headless/SearchResults.d.ts +20 -3
  66. package/dist/headless/SearchResults.d.ts.map +1 -1
  67. package/dist/headless/SearchResults.js +3 -1
  68. package/dist/headless/SearchResults.js.map +1 -1
  69. package/dist/headless/useAppliedCount.d.ts +8 -0
  70. package/dist/headless/useAppliedCount.d.ts.map +1 -0
  71. package/dist/headless/useAppliedCount.js +30 -0
  72. package/dist/headless/useAppliedCount.js.map +1 -0
  73. package/dist/headless/useScorerNames.d.ts +4 -0
  74. package/dist/headless/useScorerNames.d.ts.map +1 -0
  75. package/dist/headless/useScorerNames.js +34 -0
  76. package/dist/headless/useScorerNames.js.map +1 -0
  77. package/dist/headless/useSearchBox.d.ts +44 -0
  78. package/dist/headless/useSearchBox.d.ts.map +1 -0
  79. package/dist/headless/useSearchBox.js +116 -0
  80. package/dist/headless/useSearchBox.js.map +1 -0
  81. package/dist/i18n/es.d.ts.map +1 -1
  82. package/dist/i18n/es.js +32 -4
  83. package/dist/i18n/es.js.map +1 -1
  84. package/dist/i18n/keys.d.ts +46 -2
  85. package/dist/i18n/keys.d.ts.map +1 -1
  86. package/dist/i18n/keys.js +86 -6
  87. package/dist/i18n/keys.js.map +1 -1
  88. package/dist/i18n/ru.d.ts.map +1 -1
  89. package/dist/i18n/ru.js +38 -4
  90. package/dist/i18n/ru.js.map +1 -1
  91. package/dist/index.d.ts +9 -3
  92. package/dist/index.d.ts.map +1 -1
  93. package/dist/index.js +6 -3
  94. package/dist/index.js.map +1 -1
  95. package/dist/model/queries.d.ts +26 -2
  96. package/dist/model/queries.d.ts.map +1 -1
  97. package/dist/model/queries.js +38 -1
  98. package/dist/model/queries.js.map +1 -1
  99. package/dist/state/degradations.d.ts +41 -0
  100. package/dist/state/degradations.d.ts.map +1 -1
  101. package/dist/state/degradations.js +41 -0
  102. package/dist/state/degradations.js.map +1 -1
  103. package/dist/state/limits.d.ts +44 -0
  104. package/dist/state/limits.d.ts.map +1 -0
  105. package/dist/state/limits.js +44 -0
  106. package/dist/state/limits.js.map +1 -0
  107. package/dist/state/ranges.d.ts +52 -0
  108. package/dist/state/ranges.d.ts.map +1 -0
  109. package/dist/state/ranges.js +108 -0
  110. package/dist/state/ranges.js.map +1 -0
  111. package/llms.txt +16 -5
  112. package/manifest.json +245 -22
  113. package/nav-manifest.json +1 -1
  114. package/package.json +15 -10
  115. package/src/analytics/generated/events.json +1 -1
  116. package/src/api/generated/schema.ts +5 -1
  117. package/src/default/DegradationNotice.tsx +84 -14
  118. package/src/default/FacetPanelPane.tsx +343 -64
  119. package/src/default/LanguageSelect.tsx +93 -0
  120. package/src/default/PageSizeSelect.tsx +80 -0
  121. package/src/default/RangeFilterRow.tsx +148 -0
  122. package/src/default/RankingDisclosurePane.tsx +67 -35
  123. package/src/default/SearchBox.tsx +130 -0
  124. package/src/default/SearchPage.tsx +356 -41
  125. package/src/default/SearchResultCard.tsx +231 -24
  126. package/src/default/SearchResultsPane.tsx +147 -76
  127. package/src/default/SortSelect.tsx +50 -37
  128. package/src/default/UrlIssueNotice.tsx +21 -3
  129. package/src/default/index.ts +42 -16
  130. package/src/default/sortLabels.ts +34 -0
  131. package/src/headless/FacetPanel.tsx +30 -2
  132. package/src/headless/SearchResults.tsx +32 -4
  133. package/src/headless/useAppliedCount.ts +41 -0
  134. package/src/headless/useScorerNames.ts +36 -0
  135. package/src/headless/useSearchBox.ts +189 -0
  136. package/src/i18n/es.ts +39 -4
  137. package/src/i18n/keys.ts +97 -6
  138. package/src/i18n/ru.ts +45 -4
  139. package/src/index.ts +30 -3
  140. package/src/model/queries.ts +51 -1
  141. package/src/state/degradations.ts +60 -0
  142. package/src/state/limits.ts +50 -0
  143. package/src/state/ranges.ts +144 -0
  144. package/dist/default/ErrorAlert.d.ts +0 -9
  145. package/dist/default/ErrorAlert.d.ts.map +0 -1
  146. package/dist/default/ErrorAlert.js +0 -27
  147. package/dist/default/ErrorAlert.js.map +0 -1
  148. package/dist/default/theme.d.ts +0 -24
  149. package/dist/default/theme.d.ts.map +0 -1
  150. package/dist/default/theme.js +0 -39
  151. package/dist/default/theme.js.map +0 -1
  152. package/src/default/ErrorAlert.tsx +0 -46
  153. package/src/default/theme.tsx +0 -66
@@ -0,0 +1,32 @@
1
+ /**
2
+ * A sort SLUG as the skin names it, in one place.
3
+ *
4
+ * `relevance`, `price_asc`, `distance` are wire values: the URL carries them,
5
+ * the envelope reports them, and the ranking disclosure lists them per scorer.
6
+ * The sort SELECT translated them and the disclosure did not, so the same page
7
+ * offered "Most relevant" in the control and stamped "Applies to: relevance"
8
+ * under every parameter — the registry's word, in a statutory text, next to
9
+ * the human word for the same thing.
10
+ *
11
+ * A slug the pair does not ship is returned as it is. Deployments register
12
+ * their own scorers and sorts, and an unknown one is a real value that belongs
13
+ * on screen; only an invented label would be worse.
14
+ */
15
+ import { SEARCH_I18N_KEYS } from "../i18n/keys.js";
16
+ const SORT_LABEL_KEY = {
17
+ relevance: SEARCH_I18N_KEYS.sortRelevance,
18
+ newest: SEARCH_I18N_KEYS.sortNewest,
19
+ price_asc: SEARCH_I18N_KEYS.sortPriceAsc,
20
+ price_desc: SEARCH_I18N_KEYS.sortPriceDesc,
21
+ distance: SEARCH_I18N_KEYS.sortDistance,
22
+ };
23
+ /** The i18n key for a shipped sort, or `undefined` for a deployment's own. */
24
+ export function sortLabelKey(sort) {
25
+ return SORT_LABEL_KEY[sort];
26
+ }
27
+ /** The sort's name for a reader, falling back to the slug. */
28
+ export function sortLabel(t, sort) {
29
+ const key = SORT_LABEL_KEY[sort];
30
+ return key === undefined ? sort : t(key);
31
+ }
32
+ //# sourceMappingURL=sortLabels.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sortLabels.js","sourceRoot":"","sources":["../../src/default/sortLabels.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AACH,OAAO,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,cAAc,GAAqC;IACvD,SAAS,EAAE,gBAAgB,CAAC,aAAa;IACzC,MAAM,EAAE,gBAAgB,CAAC,UAAU;IACnC,SAAS,EAAE,gBAAgB,CAAC,YAAY;IACxC,UAAU,EAAE,gBAAgB,CAAC,aAAa;IAC1C,QAAQ,EAAE,gBAAgB,CAAC,YAAY;CACxC,CAAC;AAEF,8EAA8E;AAC9E,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC;AAC9B,CAAC;AAED,8DAA8D;AAC9D,MAAM,UAAU,SAAS,CAAC,CAA0B,EAAE,IAAY;IAChE,MAAM,GAAG,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;IACjC,OAAO,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;AAC3C,CAAC"}
@@ -58,4 +58,21 @@ export declare function FacetPanel(props: {
58
58
  enabled?: boolean;
59
59
  children: (bag: FacetPanelBag) => ReactNode;
60
60
  }): ReactNode;
61
+ /**
62
+ * The same bag, as a hook — for a caller that has to know what the panel WILL
63
+ * render before it renders it.
64
+ *
65
+ * The one real caller is `<SearchPage>`: a facet column is a quarter of a
66
+ * catalogue page, and on a deployment whose plan has no facets at all it was
67
+ * a quarter of every results page spent on an empty-state illustration
68
+ * repeating "no filters for this search". Whether to lay out that column is a
69
+ * LAYOUT decision, and layout is decided by the component that owns the grid
70
+ * — which therefore has to be able to ask. A render prop cannot answer a
71
+ * question asked one level up.
72
+ */
73
+ export declare function useFacetPanel(props?: {
74
+ categoryFeatures?: readonly FeatureDef[];
75
+ locale?: string;
76
+ enabled?: boolean;
77
+ }): FacetPanelBag;
61
78
  //# sourceMappingURL=FacetPanel.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FacetPanel.d.ts","sourceRoot":"","sources":["../../src/headless/FacetPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,IAAI,IAAI,CAAC;CAClB;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,SAAS,CAAC;CAC7C,GAAG,SAAS,CAuCZ"}
1
+ {"version":3,"file":"FacetPanel.d.ts","sourceRoot":"","sources":["../../src/headless/FacetPanel.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAC;AAC3D,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG9D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGrD,oDAAoD;AACpD,MAAM,WAAW,aAAa;IAC5B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACjD;;;;;OAKG;IACH,QAAQ,CAAC,WAAW,EAAE,OAAO,CAAC;IAC9B;;;;OAIG;IACH,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,+BAA+B;IAC/B,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IACpC,2EAA2E;IAC3E,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,qDAAqD;IACrD,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAAC;IACxD,KAAK,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,QAAQ,IAAI,IAAI,CAAC;CAClB;AASD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,UAAU,CAAC,KAAK,EAAE;IAChC,kEAAkE;IAClE,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,4EAA4E;IAC5E,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,SAAS,CAAC;CAC7C,GAAG,SAAS,CAUZ;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,aAAa,CAAC,KAAK,GAAE;IACnC,gBAAgB,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACzC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,OAAO,CAAC;CACd,GAAG,aAAa,CAuCrB"}
@@ -24,6 +24,27 @@ const EMPTY_META = {
24
24
  * blanks.
25
25
  */
26
26
  export function FacetPanel(props) {
27
+ return props.children(useFacetPanel({
28
+ ...(props.categoryFeatures !== undefined
29
+ ? { categoryFeatures: props.categoryFeatures }
30
+ : {}),
31
+ ...(props.locale !== undefined ? { locale: props.locale } : {}),
32
+ ...(props.enabled !== undefined ? { enabled: props.enabled } : {}),
33
+ }));
34
+ }
35
+ /**
36
+ * The same bag, as a hook — for a caller that has to know what the panel WILL
37
+ * render before it renders it.
38
+ *
39
+ * The one real caller is `<SearchPage>`: a facet column is a quarter of a
40
+ * catalogue page, and on a deployment whose plan has no facets at all it was
41
+ * a quarter of every results page spent on an empty-state illustration
42
+ * repeating "no filters for this search". Whether to lay out that column is a
43
+ * LAYOUT decision, and layout is decided by the component that owns the grid
44
+ * — which therefore has to be able to ask. A render prop cannot answer a
45
+ * question asked one level up.
46
+ */
47
+ export function useFacetPanel(props = {}) {
27
48
  const { state: searchState, setFilter, setRange, clearAll, toggleFilter, activeFilters } = useSearchState();
28
49
  const t = useT();
29
50
  const query = useSearchQuery(searchState, props.enabled !== undefined ? { enabled: props.enabled } : undefined);
@@ -39,7 +60,7 @@ export function FacetPanel(props) {
39
60
  t,
40
61
  ...(props.locale !== undefined ? { locale: props.locale } : {}),
41
62
  }));
42
- return props.children({
63
+ return {
43
64
  state: groups,
44
65
  approximate: meta.approximate,
45
66
  skipped: meta.skipped,
@@ -52,6 +73,6 @@ export function FacetPanel(props) {
52
73
  setFilter(slug, []);
53
74
  },
54
75
  clearAll,
55
- });
76
+ };
56
77
  }
57
78
  //# sourceMappingURL=FacetPanel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"FacetPanel.js","sourceRoot":"","sources":["../../src/headless/FacetPanel.tsx"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAIjE,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAEtD,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAoC1D,MAAM,UAAU,GAAc;IAC5B,WAAW,EAAE,KAAK;IAClB,UAAU,EAAE,CAAC;IACb,OAAO,EAAE,EAAE;IACX,OAAO,EAAE,EAAE;CACZ,CAAC;AAEF;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,UAAU,CAAC,KAO1B;IACC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,SAAS,EAAE,QAAQ,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,GACtF,cAAc,EAAE,CAAC;IACnB,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,KAAK,GAAG,cAAc,CAC1B,WAAW,EACX,KAAK,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,SAAS,CACrE,CAAC;IAEF,MAAM,QAAQ,GAAG,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAG,QAAQ,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU,CAAC;IAEjF,MAAM,MAAM,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC,IAAI,EAAE,EAAE,CACxC,gBAAgB,CAAC;QACf,MAAM,EAAE,IAAI,CAAC,MAAM;QACnB,IAAI,EAAE,IAAI,CAAC,UAAU;QACrB,KAAK,EAAE,WAAW;QAClB,GAAG,CAAC,KAAK,CAAC,gBAAgB,KAAK,SAAS;YACtC,CAAC,CAAC,EAAE,gBAAgB,EAAE,KAAK,CAAC,gBAAgB,EAAE;YAC9C,CAAC,CAAC,EAAE,CAAC;QACP,CAAC;QACD,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAChE,CAAC,CACH,CAAC;IAEF,OAAO,KAAK,CAAC,QAAQ,CAAC;QACpB,KAAK,EAAE,MAAM;QACb,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,OAAO,EAAE,IAAI,CAAC,OAAO;QACrB,UAAU,EAAE,IAAI,CAAC,UAAU;QAC3B,aAAa;QACb,MAAM,EAAE,YAAY;QACpB,QAAQ;QACR,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE;YACd,SAAS,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QACtB,CAAC;QACD,QAAQ;KACT,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"FacetPanel.js","sourceRoot":"","sources":["../../src/headless/FacetPanel.tsx"],"names":[],"mappings":"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"}
@@ -1,12 +1,29 @@
1
1
  import type { ReactNode } from "react";
2
2
  import type { ActionAvailability, LoadState, StapelApiError } from "@stapel/core";
3
3
  import type { SearchDegradation, SearchItem, SearchResponse } from "../api/types.js";
4
+ import type { SearchCountKind } from "../state/degradations.js";
4
5
  /** What the envelope says about this page, beside the rows. */
5
6
  export interface SearchPageInfo {
6
- /** Total matches — an ESTIMATE unless {@link SearchPageInfo.exactTotal}. */
7
- readonly count: number;
7
+ /**
8
+ * Total matches, or `null` when the engine cannot say — which is a real
9
+ * state and NOT zero. Read it together with {@link SearchPageInfo.countKind}:
10
+ * a `count` under `"at_least"` is a floor, not a total.
11
+ */
12
+ readonly count: number | null;
8
13
  readonly exactTotal: boolean;
9
- /** `true` when `count` must be rendered as approximate ("≈", "about"). */
14
+ /** The server's own word: `count` is a floor ("at least N"), not a total. */
15
+ readonly countIsLowerBound: boolean;
16
+ /**
17
+ * The one value a skin needs to choose a sentence: `"exact"` → "N",
18
+ * `"at_least"` → "N+", `"unknown"` → no count at all.
19
+ */
20
+ readonly countKind: SearchCountKind;
21
+ /**
22
+ * `true` when `count` must not be rendered as a plain number.
23
+ *
24
+ * @deprecated Equivalent to `countKind !== "exact"` and blind to
25
+ * `count: null`. Use {@link SearchPageInfo.countKind}.
26
+ */
10
27
  readonly countIsEstimate: boolean;
11
28
  readonly hasNext: boolean;
12
29
  readonly hasPrev: boolean;
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/headless/SearchResults.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,cAAc,EACf,MAAM,iBAAiB,CAAC;AAMzB,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B,4EAA4E;IAC5E,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,0EAA0E;IAC1E,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;mFAC+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACjD;qCACiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IAC7C,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpD,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;mDAE+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,SAAS,CAAC;CAChD,GAAG,SAAS,CA+DZ"}
1
+ {"version":3,"file":"SearchResults.d.ts","sourceRoot":"","sources":["../../src/headless/SearchResults.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAQvC,OAAO,KAAK,EAAE,kBAAkB,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAClF,OAAO,KAAK,EACV,iBAAiB,EACjB,UAAU,EACV,cAAc,EACf,MAAM,iBAAiB,CAAC;AAQzB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,+DAA+D;AAC/D,MAAM,WAAW,cAAc;IAC7B;;;;OAIG;IACH,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B,6EAA6E;IAC7E,QAAQ,CAAC,iBAAiB,EAAE,OAAO,CAAC;IACpC;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,eAAe,CAAC;IACpC;;;;;OAKG;IACH,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC;IAClC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;mFAC+E;IAC/E,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,uEAAuE;IACvE,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;CAChC;AAED,uDAAuD;AACvD,MAAM,WAAW,gBAAgB;IAC/B;;;;;OAKG;IACH,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAC,SAAS,UAAU,EAAE,CAAC,CAAC;IACjD;qCACiC;IACjC,QAAQ,CAAC,QAAQ,EAAE,SAAS,CAAC,cAAc,CAAC,CAAC;IAC7C,wCAAwC;IACxC,QAAQ,CAAC,IAAI,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC;;;;OAIG;IACH,QAAQ,CAAC,YAAY,EAAE,SAAS,iBAAiB,EAAE,CAAC;IACpD,0DAA0D;IAC1D,QAAQ,CAAC,UAAU,EAAE,OAAO,CAAC;IAC7B;;mDAE+C;IAC/C,QAAQ,CAAC,KAAK,EAAE,cAAc,GAAG,IAAI,CAAC;IACtC,4EAA4E;IAC5E,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,QAAQ,CAAC,IAAI,EAAE,kBAAkB,CAAC;IAClC,MAAM,IAAI,IAAI,CAAC;IACf,MAAM,IAAI,IAAI,CAAC;IACf,OAAO,IAAI,IAAI,CAAC;CACjB;AAED;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,KAAK,EAAE;IACnC,4EAA4E;IAC5E,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,EAAE,CAAC,GAAG,EAAE,gBAAgB,KAAK,SAAS,CAAC;CAChD,GAAG,SAAS,CAsEZ"}
@@ -2,7 +2,7 @@ import { useCallback } from "react";
2
2
  import { actionAvailable, actionBlocked, actionBlockedByFailure, loadStateFromQuery, mapLoad, } from "@stapel/core";
3
3
  import { SEARCH_I18N_KEYS } from "../i18n/keys.js";
4
4
  import { useSearchQuery } from "../model/queries.js";
5
- import { countIsEstimate, parseDegradations } from "../state/degradations.js";
5
+ import { countIsEstimate, countKind, parseDegradations, } from "../state/degradations.js";
6
6
  import { useSearchState } from "./SearchStateProvider.js";
7
7
  /**
8
8
  * Headless result page — the rows, the keyset controls, and the envelope's
@@ -25,6 +25,8 @@ export function SearchResults(props) {
25
25
  : {
26
26
  count: data.count,
27
27
  exactTotal: data.exact_total,
28
+ countIsLowerBound: data.count_is_lower_bound === true,
29
+ countKind: countKind(data.count, data.count_is_lower_bound, data.exact_total, degradations),
28
30
  countIsEstimate: countIsEstimate(data.exact_total, degradations),
29
31
  hasNext: data.has_next,
30
32
  hasPrev: data.has_prev,
@@ -1 +1 @@
1
- {"version":3,"file":"SearchResults.js","sourceRoot":"","sources":["../../src/headless/SearchResults.tsx"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"SearchResults.js","sourceRoot":"","sources":["../../src/headless/SearchResults.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,8 @@
1
+ import type { SearchCountKind } from "../state/degradations.js";
2
+ export interface AppliedCount {
3
+ /** `null` when the engine cannot say — never rendered as `0`. */
4
+ readonly count: number | null;
5
+ readonly kind: SearchCountKind;
6
+ }
7
+ export declare function useAppliedCount(): AppliedCount;
8
+ //# sourceMappingURL=useAppliedCount.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAppliedCount.d.ts","sourceRoot":"","sources":["../../src/headless/useAppliedCount.ts"],"names":[],"mappings":"AAiBA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAGhE,MAAM,WAAW,YAAY;IAC3B,iEAAiE;IACjE,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;CAChC;AAED,wBAAgB,eAAe,IAAI,YAAY,CAc9C"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * How many results the page currently in cache holds, and whether that number
3
+ * may be spoken as a number.
4
+ *
5
+ * The same trick as {@link useAppliedSort}: `enabled: false` on the key
6
+ * `<SearchResults>` populates, so a control that wants to SAY the count
7
+ * subscribes to the answer already on screen instead of issuing a second
8
+ * search of its own. A filter sheet whose button reads "Show 25 results" is
9
+ * the difference between committing to a change and guessing at one, and it
10
+ * must not cost a request to know that.
11
+ *
12
+ * Not exported from the package entry: it is the shape `<SearchPage>` needs to
13
+ * label one button, and a public hook would be a second, thinner way to ask
14
+ * what `<SearchResults>` already answers in full.
15
+ */
16
+ import { useSearchQuery } from "../model/queries.js";
17
+ import { countKind, parseDegradations } from "../state/degradations.js";
18
+ import { useSearchState } from "./SearchStateProvider.js";
19
+ export function useAppliedCount() {
20
+ const { state } = useSearchState();
21
+ const query = useSearchQuery(state, { enabled: false });
22
+ const data = query.data;
23
+ if (data === undefined)
24
+ return { count: null, kind: "unknown" };
25
+ return {
26
+ count: data.count,
27
+ kind: countKind(data.count, data.count_is_lower_bound, data.exact_total, parseDegradations(data.degraded)),
28
+ };
29
+ }
30
+ //# sourceMappingURL=useAppliedCount.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useAppliedCount.js","sourceRoot":"","sources":["../../src/headless/useAppliedCount.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AACH,OAAO,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAExE,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAQ1D,MAAM,UAAU,eAAe;IAC7B,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACxD,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IACxB,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,CAAC;IAChE,OAAO;QACL,KAAK,EAAE,IAAI,CAAC,KAAK;QACjB,IAAI,EAAE,SAAS,CACb,IAAI,CAAC,KAAK,EACV,IAAI,CAAC,oBAAoB,EACzB,IAAI,CAAC,WAAW,EAChB,iBAAiB,CAAC,IAAI,CAAC,QAAQ,CAAC,CACjC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,4 @@
1
+ /** `(slug) => name`, or `undefined` when nothing in cache names that slug. */
2
+ export type ScorerNameLookup = (slug: string) => string | undefined;
3
+ export declare function useScorerNames(): ScorerNameLookup;
4
+ //# sourceMappingURL=useScorerNames.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScorerNames.d.ts","sourceRoot":"","sources":["../../src/headless/useScorerNames.ts"],"names":[],"mappings":"AAqBA,8EAA8E;AAC9E,MAAM,MAAM,gBAAgB,GAAG,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;AAEpE,wBAAgB,cAAc,IAAI,gBAAgB,CAWjD"}
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Scorer SLUGS turned into the names the disclosure already gives them.
3
+ *
4
+ * `degraded[]` reports a scorer the engine could not evaluate as
5
+ * `"scorer:geo_decay"` — a registry identifier, because that is the only
6
+ * handle the query envelope has. Printed straight into a sentence it reads
7
+ * "The ranking parameter “geo_decay” was not applied", which is a developer's
8
+ * word in a shopper's banner (class C-DEVCOPY).
9
+ *
10
+ * The name is not this pair's to invent: the backend already publishes one per
11
+ * scorer on `GET /ranking` (`description_key`, a translation key). So the
12
+ * lookup goes there — through the SAME cache entry `<RankingDisclosure>`
13
+ * fills, with `enabled: false`, so a result page never issues a second request
14
+ * for a label. When the disclosure has not been read the map is empty and the
15
+ * banner falls back to the slug, which is what it said before and is at least
16
+ * traceable.
17
+ */
18
+ import { useT } from "@stapel/core";
19
+ import { useRankingDisclosure } from "../model/queries.js";
20
+ import { useSearchState } from "./SearchStateProvider.js";
21
+ export function useScorerNames() {
22
+ const t = useT();
23
+ const { state } = useSearchState();
24
+ const query = useRankingDisclosure(state.type, { enabled: false });
25
+ const scorers = query.data?.scorers;
26
+ return (slug) => {
27
+ const scorer = scorers?.find((candidate) => candidate.slug === slug);
28
+ if (scorer === undefined)
29
+ return undefined;
30
+ const named = t(scorer.description_key);
31
+ return named.length > 0 && named !== scorer.description_key ? named : undefined;
32
+ };
33
+ }
34
+ //# sourceMappingURL=useScorerNames.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useScorerNames.js","sourceRoot":"","sources":["../../src/headless/useScorerNames.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAK1D,MAAM,UAAU,cAAc;IAC5B,MAAM,CAAC,GAAG,IAAI,EAAE,CAAC;IACjB,MAAM,EAAE,KAAK,EAAE,GAAG,cAAc,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,oBAAoB,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;IACnE,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,OAAO,CAAC;IACpC,OAAO,CAAC,IAAY,EAAE,EAAE;QACtB,MAAM,MAAM,GAAG,OAAO,EAAE,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACrE,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,SAAS,CAAC;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC;QACxC,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,KAAK,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC;IAClF,CAAC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,44 @@
1
+ import type { LoadState } from "@stapel/core";
2
+ /** What a query box needs to read and move the search text. */
3
+ export interface SearchBoxBag {
4
+ /** What is in the input right now. */
5
+ readonly draft: string;
6
+ /** What the URL — and therefore the results — is about. */
7
+ readonly committed: string;
8
+ /** The draft has not reached the URL yet (a search is about to run). */
9
+ readonly pending: boolean;
10
+ /**
11
+ * Title prefixes for the typeahead — the READY answer only.
12
+ *
13
+ * A typeahead has no surface for "we could not fetch suggestions": the box
14
+ * must stay typeable and a person is mid-word. So a failed or in-flight
15
+ * suggest shows nothing, and the three answers stay distinguishable in
16
+ * {@link SearchBoxBag.suggestState} for a skin that wants to say more.
17
+ */
18
+ readonly suggestions: readonly string[];
19
+ /** The suggest read as a state, unflattened. */
20
+ readonly suggestState: LoadState<readonly string[]>;
21
+ /** A suggestion request is in flight for a prefix nothing is shown for yet. */
22
+ readonly suggestLoading: boolean;
23
+ /** Characters a prefix needs before the index is asked. */
24
+ readonly minSuggestChars: number;
25
+ readonly maxLength: number;
26
+ /** Type. Commits after {@link SEARCH_BOX_DEBOUNCE_MS} of quiet. */
27
+ setDraft(next: string): void;
28
+ /** Commit now — Enter, the Search button, or picking a suggestion. */
29
+ submit(value?: string): void;
30
+ /** Empty the box AND the search (an empty `q` is a valid browse). */
31
+ clear(): void;
32
+ }
33
+ export interface UseSearchBoxOptions {
34
+ readonly debounceMs?: number;
35
+ /** Ask the index for prefixes. Default `true`. */
36
+ readonly suggest?: boolean;
37
+ /** Quiet time before the index is asked (default
38
+ * {@link SEARCH_BOX_SUGGEST_DEBOUNCE_MS}). */
39
+ readonly suggestDebounceMs?: number;
40
+ /** How many suggestions to ask for (backend clamps to 25). Default 8. */
41
+ readonly suggestLimit?: number;
42
+ }
43
+ export declare function useSearchBox(options?: UseSearchBoxOptions): SearchBoxBag;
44
+ //# sourceMappingURL=useSearchBox.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSearchBox.d.ts","sourceRoot":"","sources":["../../src/headless/useSearchBox.ts"],"names":[],"mappings":"AA0BA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAU9C,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,sCAAsC;IACtC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,2DAA2D;IAC3D,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,wEAAwE;IACxE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IACxC,gDAAgD;IAChD,QAAQ,CAAC,YAAY,EAAE,SAAS,CAAC,SAAS,MAAM,EAAE,CAAC,CAAC;IACpD,+EAA+E;IAC/E,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;IACjC,2DAA2D;IAC3D,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAE3B,mEAAmE;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,sEAAsE;IACtE,MAAM,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,qEAAqE;IACrE,KAAK,IAAI,IAAI,CAAC;CACf;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,kDAAkD;IAClD,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAC3B;kDAC8C;IAC9C,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,CAAC;IACpC,yEAAyE;IACzE,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AAKD,wBAAgB,YAAY,CAAC,OAAO,GAAE,mBAAwB,GAAG,YAAY,CAyG5E"}
@@ -0,0 +1,116 @@
1
+ /**
2
+ * The query box, headless — the state machine behind `<SearchBox>`.
3
+ *
4
+ * ── The one legitimate second copy of the state ────────────────────────────
5
+ *
6
+ * This pair's rule is that the URL is the state and no component keeps a copy.
7
+ * A text input is the single exception the rule has to make: what a person has
8
+ * TYPED is not yet what they have SEARCHED for, and committing every keystroke
9
+ * to the URL would make the address bar (and the request, and the query cache)
10
+ * chase the keyboard. So the draft lives here, for as long as it takes to stop
11
+ * typing, and the URL is still the only place a SEARCH is recorded.
12
+ *
13
+ * Two properties keep that honest:
14
+ *
15
+ * 1. **The URL wins whenever it moves on its own.** Back, a shared link
16
+ * opening, a host calling `setText` elsewhere — the draft is reset to the
17
+ * committed `q`. The box can never show a word the results are not about.
18
+ * 2. **Committing REPLACES the history entry** (`setText` already does), so a
19
+ * ten-letter word is one entry and Back still removes the last FILTER
20
+ * rather than the last letter.
21
+ *
22
+ * The suggestion list is asked for the DEBOUNCED prefix, not the draft — one
23
+ * request per pause, not per keystroke, on an endpoint the backend throttles.
24
+ */
25
+ import { useCallback, useEffect, useRef, useState } from "react";
26
+ import { loadStateFromQuery, mapLoad } from "@stapel/core";
27
+ import { useSearchState } from "./SearchStateProvider.js";
28
+ import { useSuggest } from "../model/queries.js";
29
+ import { SEARCH_BOX_DEBOUNCE_MS, SEARCH_BOX_SUGGEST_DEBOUNCE_MS, SEARCH_QUERY_MAX_CHARS, SUGGEST_MIN_CHARS, } from "../state/limits.js";
30
+ /** One frozen empty list, so a render with no suggestions is a stable value. */
31
+ const NO_SUGGESTIONS = [];
32
+ export function useSearchBox(options = {}) {
33
+ const { state, setText } = useSearchState();
34
+ const committed = state.q;
35
+ const debounceMs = options.debounceMs ?? SEARCH_BOX_DEBOUNCE_MS;
36
+ const [draft, setDraftState] = useState(committed);
37
+ // What the URL said the last time we looked. When it changes underneath us
38
+ // — Back, a shared link, a host control — the draft follows it; when it
39
+ // changes BECAUSE we committed, `draft === committed` already and the reset
40
+ // is a no-op.
41
+ const lastCommitted = useRef(committed);
42
+ const timer = useRef(null);
43
+ if (lastCommitted.current !== committed) {
44
+ lastCommitted.current = committed;
45
+ if (draft !== committed)
46
+ setDraftState(committed);
47
+ }
48
+ const cancel = useCallback(() => {
49
+ if (timer.current !== null) {
50
+ clearTimeout(timer.current);
51
+ timer.current = null;
52
+ }
53
+ }, []);
54
+ // A pending commit must not fire into an unmounted tree, and a box that is
55
+ // unmounted mid-word has not searched for that word.
56
+ useEffect(() => cancel, [cancel]);
57
+ const commit = useCallback((value) => {
58
+ cancel();
59
+ if (value !== committed)
60
+ setText(value);
61
+ }, [cancel, committed, setText]);
62
+ const setDraft = useCallback((next) => {
63
+ const clipped = next.slice(0, SEARCH_QUERY_MAX_CHARS);
64
+ setDraftState(clipped);
65
+ cancel();
66
+ timer.current = setTimeout(() => {
67
+ timer.current = null;
68
+ if (clipped !== committed)
69
+ setText(clipped);
70
+ }, debounceMs);
71
+ }, [cancel, committed, debounceMs, setText]);
72
+ const submit = useCallback((value) => {
73
+ const next = (value ?? draft).slice(0, SEARCH_QUERY_MAX_CHARS);
74
+ setDraftState(next);
75
+ commit(next);
76
+ }, [commit, draft]);
77
+ const clear = useCallback(() => {
78
+ setDraftState("");
79
+ commit("");
80
+ }, [commit]);
81
+ // The index is asked about the SETTLED prefix, never the keystroke: one
82
+ // request per pause on an endpoint the backend throttles. `useSuggest` then
83
+ // refuses anything below `SUGGEST_MIN_CHARS` and keys the rest by prefix, so
84
+ // backspacing to a prefix already asked about costs nothing.
85
+ const suggestDebounceMs = options.suggestDebounceMs ?? SEARCH_BOX_SUGGEST_DEBOUNCE_MS;
86
+ const [suggestPrefix, setSuggestPrefix] = useState(committed);
87
+ useEffect(() => {
88
+ const handle = setTimeout(() => {
89
+ setSuggestPrefix(draft);
90
+ }, suggestDebounceMs);
91
+ return () => {
92
+ clearTimeout(handle);
93
+ };
94
+ }, [draft, suggestDebounceMs]);
95
+ const suggest = useSuggest({
96
+ type: state.type,
97
+ q: suggestPrefix,
98
+ ...(options.suggestLimit !== undefined ? { limit: options.suggestLimit } : {}),
99
+ enabled: options.suggest !== false,
100
+ });
101
+ const suggestState = mapLoad(loadStateFromQuery(suggest), (data) => data.items);
102
+ return {
103
+ draft,
104
+ committed,
105
+ pending: draft !== committed,
106
+ suggestions: suggestState.status === "ready" ? suggestState.data : NO_SUGGESTIONS,
107
+ suggestState,
108
+ suggestLoading: suggest.isLoading && suggest.fetchStatus === "fetching",
109
+ minSuggestChars: SUGGEST_MIN_CHARS,
110
+ maxLength: SEARCH_QUERY_MAX_CHARS,
111
+ setDraft,
112
+ submit,
113
+ clear,
114
+ };
115
+ }
116
+ //# sourceMappingURL=useSearchBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSearchBox.js","sourceRoot":"","sources":["../../src/headless/useSearchBox.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AAE3D,OAAO,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC1D,OAAO,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AACjD,OAAO,EACL,sBAAsB,EACtB,8BAA8B,EAC9B,sBAAsB,EACtB,iBAAiB,GAClB,MAAM,oBAAoB,CAAC;AA8C5B,gFAAgF;AAChF,MAAM,cAAc,GAAsB,EAAE,CAAC;AAE7C,MAAM,UAAU,YAAY,CAAC,UAA+B,EAAE;IAC5D,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,cAAc,EAAE,CAAC;IAC5C,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC;IAC1B,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,sBAAsB,CAAC;IAEhE,MAAM,CAAC,KAAK,EAAE,aAAa,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IACnD,2EAA2E;IAC3E,wEAAwE;IACxE,4EAA4E;IAC5E,cAAc;IACd,MAAM,aAAa,GAAG,MAAM,CAAC,SAAS,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,MAAM,CAAuC,IAAI,CAAC,CAAC;IAEjE,IAAI,aAAa,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QACxC,aAAa,CAAC,OAAO,GAAG,SAAS,CAAC;QAClC,IAAI,KAAK,KAAK,SAAS;YAAE,aAAa,CAAC,SAAS,CAAC,CAAC;IACpD,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,CAAC,GAAS,EAAE;QACpC,IAAI,KAAK,CAAC,OAAO,KAAK,IAAI,EAAE,CAAC;YAC3B,YAAY,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;YAC5B,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;QACvB,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,2EAA2E;IAC3E,qDAAqD;IACrD,SAAS,CAAC,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAElC,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,KAAa,EAAQ,EAAE;QACtB,MAAM,EAAE,CAAC;QACT,IAAI,KAAK,KAAK,SAAS;YAAE,OAAO,CAAC,KAAK,CAAC,CAAC;IAC1C,CAAC,EACD,CAAC,MAAM,EAAE,SAAS,EAAE,OAAO,CAAC,CAC7B,CAAC;IAEF,MAAM,QAAQ,GAAG,WAAW,CAC1B,CAAC,IAAY,EAAQ,EAAE;QACrB,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;QACtD,aAAa,CAAC,OAAO,CAAC,CAAC;QACvB,MAAM,EAAE,CAAC;QACT,KAAK,CAAC,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE;YAC9B,KAAK,CAAC,OAAO,GAAG,IAAI,CAAC;YACrB,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,CAAC,EAAE,UAAU,CAAC,CAAC;IACjB,CAAC,EACD,CAAC,MAAM,EAAE,SAAS,EAAE,UAAU,EAAE,OAAO,CAAC,CACzC,CAAC;IAEF,MAAM,MAAM,GAAG,WAAW,CACxB,CAAC,KAAc,EAAQ,EAAE;QACvB,MAAM,IAAI,GAAG,CAAC,KAAK,IAAI,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,sBAAsB,CAAC,CAAC;QAC/D,aAAa,CAAC,IAAI,CAAC,CAAC;QACpB,MAAM,CAAC,IAAI,CAAC,CAAC;IACf,CAAC,EACD,CAAC,MAAM,EAAE,KAAK,CAAC,CAChB,CAAC;IAEF,MAAM,KAAK,GAAG,WAAW,CAAC,GAAS,EAAE;QACnC,aAAa,CAAC,EAAE,CAAC,CAAC;QAClB,MAAM,CAAC,EAAE,CAAC,CAAC;IACb,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAEb,wEAAwE;IACxE,4EAA4E;IAC5E,6EAA6E;IAC7E,6DAA6D;IAC7D,MAAM,iBAAiB,GACrB,OAAO,CAAC,iBAAiB,IAAI,8BAA8B,CAAC;IAC9D,MAAM,CAAC,aAAa,EAAE,gBAAgB,CAAC,GAAG,QAAQ,CAAC,SAAS,CAAC,CAAC;IAC9D,SAAS,CAAC,GAAG,EAAE;QACb,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,EAAE;YAC7B,gBAAgB,CAAC,KAAK,CAAC,CAAC;QAC1B,CAAC,EAAE,iBAAiB,CAAC,CAAC;QACtB,OAAO,GAAG,EAAE;YACV,YAAY,CAAC,MAAM,CAAC,CAAC;QACvB,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,KAAK,EAAE,iBAAiB,CAAC,CAAC,CAAC;IAE/B,MAAM,OAAO,GAAG,UAAU,CAAC;QACzB,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,CAAC,EAAE,aAAa;QAChB,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9E,OAAO,EAAE,OAAO,CAAC,OAAO,KAAK,KAAK;KACnC,CAAC,CAAC;IAEH,MAAM,YAAY,GAAG,OAAO,CAC1B,kBAAkB,CAAC,OAAO,CAAC,EAC3B,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAA0B,CAC1C,CAAC;IAEF,OAAO;QACL,KAAK;QACL,SAAS;QACT,OAAO,EAAE,KAAK,KAAK,SAAS;QAC5B,WAAW,EAAE,YAAY,CAAC,MAAM,KAAK,OAAO,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,cAAc;QACjF,YAAY;QACZ,cAAc,EAAE,OAAO,CAAC,SAAS,IAAI,OAAO,CAAC,WAAW,KAAK,UAAU;QACvE,eAAe,EAAE,iBAAiB;QAClC,SAAS,EAAE,sBAAsB;QACjC,QAAQ;QACR,MAAM;QACN,KAAK;KACN,CAAC;AACJ,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,cA8FhC,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAE7D"}
1
+ {"version":3,"file":"es.d.ts","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAG/D,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;GAMG;AACH,eAAO,MAAM,kBAAkB,EAAE,cAiIhC,CAAC;AAEF,+DAA+D;AAC/D,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI,CAE7D"}
package/dist/i18n/es.js CHANGED
@@ -17,6 +17,8 @@ export const searchI18nBundleEs = {
17
17
  "search.results.retry": "Reintentar",
18
18
  "search.results.count_approximate.one": "Aproximadamente {count} resultado",
19
19
  "search.results.count_approximate.other": "Unos {count} resultados",
20
+ "search.results.count_at_least.one": "{count}+ resultado",
21
+ "search.results.count_at_least.other": "{count}+ resultados",
20
22
  "search.results.count_exact.one": "{count} resultado",
21
23
  "search.results.count_exact.other": "{count} resultados",
22
24
  "search.results.took_ms": "{ms} ms",
@@ -30,6 +32,12 @@ export const searchI18nBundleEs = {
30
32
  "search.results.distance_km": "a {km} km",
31
33
  "search.results.untitled": "Sin título",
32
34
  "search.results.open": "Abrir",
35
+ "search.results.image_alt": "Foto de {title}",
36
+ "search.box.label": "Buscar",
37
+ "search.box.placeholder": "¿Qué estás buscando?",
38
+ "search.box.submit": "Buscar",
39
+ "search.box.clear": "Borrar la búsqueda",
40
+ "search.box.suggestions": "Sugerencias",
33
41
  "search.sort.label": "Orden",
34
42
  "search.sort.relevance": "Más relevantes",
35
43
  "search.sort.newest": "Más recientes",
@@ -50,16 +58,36 @@ export const searchI18nBundleEs = {
50
58
  "search.facets.range_from": "Desde",
51
59
  "search.facets.range_to": "Hasta",
52
60
  "search.facets.range_apply": "Aplicar",
61
+ "search.facets.range_clear": "Quitar",
62
+ "search.facets.range_from_aria": "{feature}, desde",
63
+ "search.facets.range_to_aria": "{feature}, hasta",
64
+ "search.facets.range_invalid": "«Desde» es mayor que «hasta», así que nada podría coincidir. Intercámbialos para aplicar el rango.",
65
+ "search.filters.open": "Filtros ({count})",
66
+ "search.filters.apply": "Ver resultados",
67
+ "search.filters.show_count.one": "Ver {count} resultado",
68
+ "search.filters.show_count.other": "Ver {count} resultados",
69
+ "search.filters.show_count_at_least.one": "Ver {count}+ resultado",
70
+ "search.filters.show_count_at_least.other": "Ver {count}+ resultados",
71
+ "search.filters.dismiss": "Cerrar los filtros",
72
+ "search.category.title": "Categoría",
73
+ "search.category.clear": "Buscar en todo el catálogo",
74
+ "search.category.current": "Buscando dentro de {path}",
75
+ "search.language.label": "Idioma de la consulta",
76
+ "search.language.any": "Cualquier idioma",
77
+ "search.limit.label": "Por página",
78
+ "search.limit.option": "{count} por página",
79
+ "search.limit.from_link": "Este enlace fija su propio tamaño de página.",
53
80
  "search.geo.title": "Ubicación",
54
81
  "search.geo.radius_km": "A menos de {km} km",
82
+ "search.geo.radius_label": "Radio, km",
55
83
  "search.geo.clear": "En cualquier lugar",
56
84
  "search.geo.box": "Dentro del área mostrada",
57
85
  "search.geo.center": "Cerca de {lat}, {lon}",
58
86
  "search.url.issues_title": "Parte de este enlace no se pudo leer",
59
- "search.url.issue.not_a_number": "{param} no es un número y se ignoró",
60
- "search.url.issue.geo_incomplete": "la ubicación necesita lat y lon, así que se ignoró",
61
- "search.url.issue.bbox_malformed": "el área necesita cuatro números (minLat,minLon,maxLat,maxLon) y se ignoró",
62
- "search.url.issue.range_malformed": "{param} no es un rango from..to y se ignoró",
87
+ "search.url.issue.not_a_number": "«{param}» en este enlace no es un número, así que se ignoró",
88
+ "search.url.issue.geo_incomplete": "la ubicación de este enlace está incompleta, así que se ignoró",
89
+ "search.url.issue.bbox_malformed": "el área del mapa de este enlace está incompleta, así que se ignoró",
90
+ "search.url.issue.range_malformed": "al rango «{param}» de este enlace le faltan números, así que se ignoró",
63
91
  "search.degraded.title": "Lo que esta búsqueda no pudo hacer",
64
92
  "search.degraded.typo_tolerance": "No se corrigieron erratas: el motor de búsqueda configurado no puede hacerlo.",
65
93
  "search.degraded.phrase_synonyms": "No se ampliaron sinónimos: el motor de búsqueda configurado no puede hacerlo.",
@@ -1 +1 @@
1
- {"version":3,"file":"es.js","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE,OAAO,EAAE,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAEnE;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAAmB;IAChD,GAAG,mBAAmB;IAEtB,sBAAsB,EAAE,4BAA4B;IAEpD,sBAAsB,EAAE,YAAY;IACpC,wBAAwB,EAAE,WAAW;IACrC,4BAA4B,EAAE,oCAAoC;IAClE,sBAAsB,EAAE,6CAA6C;IACrE,sBAAsB,EAAE,YAAY;IACpC,sCAAsC,EAAE,mCAAmC;IAC3E,wCAAwC,EAAE,yBAAyB;IACnE,gCAAgC,EAAE,mBAAmB;IACrD,kCAAkC,EAAE,oBAAoB;IACxD,wBAAwB,EAAE,SAAS;IACnC,qBAAqB,EAAE,kBAAkB;IACzC,qBAAqB,EAAE,iBAAiB;IACxC,+BAA+B,EAAE,0BAA0B;IAC3D,iCAAiC,EAAE,2BAA2B;IAC9D,gCAAgC,EAC9B,iHAAiH;IACnH,yBAAyB,EAAE,cAAc;IACzC,8BAA8B,EAC5B,yGAAyG;IAC3G,4BAA4B,EAAE,WAAW;IACzC,yBAAyB,EAAE,YAAY;IACvC,qBAAqB,EAAE,OAAO;IAE9B,mBAAmB,EAAE,OAAO;IAC5B,uBAAuB,EAAE,gBAAgB;IACzC,oBAAoB,EAAE,eAAe;IACrC,uBAAuB,EAAE,0BAA0B;IACnD,wBAAwB,EAAE,0BAA0B;IACpD,sBAAsB,EAAE,cAAc;IACtC,0BAA0B,EAAE,qBAAqB;IAEjD,qBAAqB,EAAE,SAAS;IAChC,uBAAuB,EAAE,mBAAmB;IAC5C,2BAA2B,EAAE,gCAAgC;IAC7D,qBAAqB,EAAE,kCAAkC;IACzD,qBAAqB,EAAE,QAAQ;IAC/B,yBAAyB,EAAE,oCAAoC;IAC/D,2BAA2B,EACzB,kFAAkF;IACpF,uBAAuB,EACrB,0DAA0D;IAC5D,2BAA2B,EAAE,YAAY;IACzC,+BAA+B,EAC7B,6EAA6E;IAC/E,0BAA0B,EAAE,OAAO;IACnC,wBAAwB,EAAE,OAAO;IACjC,2BAA2B,EAAE,SAAS;IAEtC,kBAAkB,EAAE,WAAW;IAC/B,sBAAsB,EAAE,oBAAoB;IAC5C,kBAAkB,EAAE,oBAAoB;IACxC,gBAAgB,EAAE,0BAA0B;IAC5C,mBAAmB,EAAE,uBAAuB;IAE5C,yBAAyB,EAAE,sCAAsC;IACjE,+BAA+B,EAAE,qCAAqC;IACtE,iCAAiC,EAC/B,oDAAoD;IACtD,iCAAiC,EAC/B,2EAA2E;IAC7E,kCAAkC,EAChC,6CAA6C;IAE/C,uBAAuB,EAAE,oCAAoC;IAC7D,gCAAgC,EAC9B,+EAA+E;IACjF,iCAAiC,EAC/B,+EAA+E;IACjF,6BAA6B,EAAE,4CAA4C;IAC3E,oCAAoC,EAAE,2CAA2C;IACjF,iCAAiC,EAC/B,0FAA0F;IAC5F,wBAAwB,EACtB,2FAA2F;IAC7F,yBAAyB,EACvB,qFAAqF;IAEvF,sBAAsB,EAAE,kCAAkC;IAC1D,sBAAsB,EACpB,2FAA2F;IAC7F,wBAAwB,EAAE,qCAAqC;IAC/D,4BAA4B,EAAE,8CAA8C;IAC5E,sBAAsB,EAAE,oDAAoD;IAC5E,0BAA0B,EAAE,WAAW;IACvC,uBAAuB,EAAE,MAAM;IAC/B,2BAA2B,EAAE,aAAa;IAC1C,yBAAyB,EAAE,uBAAuB;IAClD,sBAAsB,EAAE,OAAO;IAC/B,qBAAqB,EAAE,kCAAkC;CAC1D,CAAC;AAEF,+DAA+D;AAC/D,MAAM,UAAU,oBAAoB,CAAC,MAAkB;IACrD,MAAM,CAAC,cAAc,CAAC,IAAI,EAAE,kBAAkB,CAAC,CAAC;AAClD,CAAC"}
1
+ {"version":3,"file":"es.js","sourceRoot":"","sources":["../../src/i18n/es.ts"],"names":[],"mappings":"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"}