@athoscommerce/snap-store-mobx 1.0.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 (183) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +17 -0
  3. package/dist/cjs/Abstract/AbstractStore.d.ts +17 -0
  4. package/dist/cjs/Abstract/AbstractStore.d.ts.map +1 -0
  5. package/dist/cjs/Abstract/AbstractStore.js +28 -0
  6. package/dist/cjs/Autocomplete/AutocompleteStore.d.ts +40 -0
  7. package/dist/cjs/Autocomplete/AutocompleteStore.d.ts.map +1 -0
  8. package/dist/cjs/Autocomplete/AutocompleteStore.js +246 -0
  9. package/dist/cjs/Autocomplete/Stores/AutocompleteFacetStore.d.ts +13 -0
  10. package/dist/cjs/Autocomplete/Stores/AutocompleteFacetStore.d.ts.map +1 -0
  11. package/dist/cjs/Autocomplete/Stores/AutocompleteFacetStore.js +67 -0
  12. package/dist/cjs/Autocomplete/Stores/AutocompleteHistoryStore.d.ts +19 -0
  13. package/dist/cjs/Autocomplete/Stores/AutocompleteHistoryStore.d.ts.map +1 -0
  14. package/dist/cjs/Autocomplete/Stores/AutocompleteHistoryStore.js +57 -0
  15. package/dist/cjs/Autocomplete/Stores/AutocompleteQueryStore.d.ts +25 -0
  16. package/dist/cjs/Autocomplete/Stores/AutocompleteQueryStore.d.ts.map +1 -0
  17. package/dist/cjs/Autocomplete/Stores/AutocompleteQueryStore.js +34 -0
  18. package/dist/cjs/Autocomplete/Stores/AutocompleteStateStore.d.ts +29 -0
  19. package/dist/cjs/Autocomplete/Stores/AutocompleteStateStore.d.ts.map +1 -0
  20. package/dist/cjs/Autocomplete/Stores/AutocompleteStateStore.js +54 -0
  21. package/dist/cjs/Autocomplete/Stores/AutocompleteTermStore.d.ts +47 -0
  22. package/dist/cjs/Autocomplete/Stores/AutocompleteTermStore.d.ts.map +1 -0
  23. package/dist/cjs/Autocomplete/Stores/AutocompleteTermStore.js +102 -0
  24. package/dist/cjs/Autocomplete/Stores/AutocompleteTrendingStore.d.ts +20 -0
  25. package/dist/cjs/Autocomplete/Stores/AutocompleteTrendingStore.d.ts.map +1 -0
  26. package/dist/cjs/Autocomplete/Stores/AutocompleteTrendingStore.js +58 -0
  27. package/dist/cjs/Autocomplete/Stores/index.d.ts +7 -0
  28. package/dist/cjs/Autocomplete/Stores/index.d.ts.map +1 -0
  29. package/dist/cjs/Autocomplete/Stores/index.js +16 -0
  30. package/dist/cjs/Cart/CartStore.d.ts +15 -0
  31. package/dist/cjs/Cart/CartStore.d.ts.map +1 -0
  32. package/dist/cjs/Cart/CartStore.js +109 -0
  33. package/dist/cjs/Finder/FinderStore.d.ts +27 -0
  34. package/dist/cjs/Finder/FinderStore.d.ts.map +1 -0
  35. package/dist/cjs/Finder/FinderStore.js +156 -0
  36. package/dist/cjs/Finder/Stores/FinderSelectionStore.d.ts +73 -0
  37. package/dist/cjs/Finder/Stores/FinderSelectionStore.d.ts.map +1 -0
  38. package/dist/cjs/Finder/Stores/FinderSelectionStore.js +320 -0
  39. package/dist/cjs/Finder/Stores/index.d.ts +2 -0
  40. package/dist/cjs/Finder/Stores/index.d.ts.map +1 -0
  41. package/dist/cjs/Finder/Stores/index.js +5 -0
  42. package/dist/cjs/Meta/MetaStore.d.ts +20 -0
  43. package/dist/cjs/Meta/MetaStore.d.ts.map +1 -0
  44. package/dist/cjs/Meta/MetaStore.js +55 -0
  45. package/dist/cjs/Recommendation/RecommendationStore.d.ts +19 -0
  46. package/dist/cjs/Recommendation/RecommendationStore.d.ts.map +1 -0
  47. package/dist/cjs/Recommendation/RecommendationStore.js +97 -0
  48. package/dist/cjs/Recommendation/Stores/RecommendationProfileStore.d.ts +15 -0
  49. package/dist/cjs/Recommendation/Stores/RecommendationProfileStore.d.ts.map +1 -0
  50. package/dist/cjs/Recommendation/Stores/RecommendationProfileStore.js +30 -0
  51. package/dist/cjs/Recommendation/Stores/index.d.ts +2 -0
  52. package/dist/cjs/Recommendation/Stores/index.d.ts.map +1 -0
  53. package/dist/cjs/Recommendation/Stores/index.js +5 -0
  54. package/dist/cjs/Search/SearchStore.d.ts +27 -0
  55. package/dist/cjs/Search/SearchStore.d.ts.map +1 -0
  56. package/dist/cjs/Search/SearchStore.js +125 -0
  57. package/dist/cjs/Search/Stores/SearchFacetStore.d.ts +89 -0
  58. package/dist/cjs/Search/Stores/SearchFacetStore.d.ts.map +1 -0
  59. package/dist/cjs/Search/Stores/SearchFacetStore.js +368 -0
  60. package/dist/cjs/Search/Stores/SearchFilterStore.d.ts +44 -0
  61. package/dist/cjs/Search/Stores/SearchFilterStore.d.ts.map +1 -0
  62. package/dist/cjs/Search/Stores/SearchFilterStore.js +102 -0
  63. package/dist/cjs/Search/Stores/SearchHistoryStore.d.ts +20 -0
  64. package/dist/cjs/Search/Stores/SearchHistoryStore.d.ts.map +1 -0
  65. package/dist/cjs/Search/Stores/SearchHistoryStore.js +106 -0
  66. package/dist/cjs/Search/Stores/SearchMerchandisingStore.d.ts +36 -0
  67. package/dist/cjs/Search/Stores/SearchMerchandisingStore.d.ts.map +1 -0
  68. package/dist/cjs/Search/Stores/SearchMerchandisingStore.js +90 -0
  69. package/dist/cjs/Search/Stores/SearchPaginationStore.d.ts +57 -0
  70. package/dist/cjs/Search/Stores/SearchPaginationStore.d.ts.map +1 -0
  71. package/dist/cjs/Search/Stores/SearchPaginationStore.js +212 -0
  72. package/dist/cjs/Search/Stores/SearchQueryStore.d.ts +23 -0
  73. package/dist/cjs/Search/Stores/SearchQueryStore.d.ts.map +1 -0
  74. package/dist/cjs/Search/Stores/SearchQueryStore.js +41 -0
  75. package/dist/cjs/Search/Stores/SearchResultStore.d.ts +175 -0
  76. package/dist/cjs/Search/Stores/SearchResultStore.d.ts.map +1 -0
  77. package/dist/cjs/Search/Stores/SearchResultStore.js +749 -0
  78. package/dist/cjs/Search/Stores/SearchSortingStore.d.ts +32 -0
  79. package/dist/cjs/Search/Stores/SearchSortingStore.d.ts.map +1 -0
  80. package/dist/cjs/Search/Stores/SearchSortingStore.js +77 -0
  81. package/dist/cjs/Search/Stores/index.d.ts +9 -0
  82. package/dist/cjs/Search/Stores/index.d.ts.map +1 -0
  83. package/dist/cjs/Search/Stores/index.js +30 -0
  84. package/dist/cjs/Storage/StorageStore.d.ts +27 -0
  85. package/dist/cjs/Storage/StorageStore.d.ts.map +1 -0
  86. package/dist/cjs/Storage/StorageStore.js +176 -0
  87. package/dist/cjs/index.d.ts +12 -0
  88. package/dist/cjs/index.d.ts.map +1 -0
  89. package/dist/cjs/index.js +37 -0
  90. package/dist/cjs/types.d.ts +170 -0
  91. package/dist/cjs/types.d.ts.map +1 -0
  92. package/dist/cjs/types.js +9 -0
  93. package/dist/esm/Abstract/AbstractStore.d.ts +17 -0
  94. package/dist/esm/Abstract/AbstractStore.d.ts.map +1 -0
  95. package/dist/esm/Abstract/AbstractStore.js +22 -0
  96. package/dist/esm/Autocomplete/AutocompleteStore.d.ts +40 -0
  97. package/dist/esm/Autocomplete/AutocompleteStore.d.ts.map +1 -0
  98. package/dist/esm/Autocomplete/AutocompleteStore.js +210 -0
  99. package/dist/esm/Autocomplete/Stores/AutocompleteFacetStore.d.ts +13 -0
  100. package/dist/esm/Autocomplete/Stores/AutocompleteFacetStore.d.ts.map +1 -0
  101. package/dist/esm/Autocomplete/Stores/AutocompleteFacetStore.js +35 -0
  102. package/dist/esm/Autocomplete/Stores/AutocompleteHistoryStore.d.ts +19 -0
  103. package/dist/esm/Autocomplete/Stores/AutocompleteHistoryStore.d.ts.map +1 -0
  104. package/dist/esm/Autocomplete/Stores/AutocompleteHistoryStore.js +27 -0
  105. package/dist/esm/Autocomplete/Stores/AutocompleteQueryStore.d.ts +25 -0
  106. package/dist/esm/Autocomplete/Stores/AutocompleteQueryStore.d.ts.map +1 -0
  107. package/dist/esm/Autocomplete/Stores/AutocompleteQueryStore.js +28 -0
  108. package/dist/esm/Autocomplete/Stores/AutocompleteStateStore.d.ts +29 -0
  109. package/dist/esm/Autocomplete/Stores/AutocompleteStateStore.d.ts.map +1 -0
  110. package/dist/esm/Autocomplete/Stores/AutocompleteStateStore.js +42 -0
  111. package/dist/esm/Autocomplete/Stores/AutocompleteTermStore.d.ts +47 -0
  112. package/dist/esm/Autocomplete/Stores/AutocompleteTermStore.d.ts.map +1 -0
  113. package/dist/esm/Autocomplete/Stores/AutocompleteTermStore.js +56 -0
  114. package/dist/esm/Autocomplete/Stores/AutocompleteTrendingStore.d.ts +20 -0
  115. package/dist/esm/Autocomplete/Stores/AutocompleteTrendingStore.d.ts.map +1 -0
  116. package/dist/esm/Autocomplete/Stores/AutocompleteTrendingStore.js +27 -0
  117. package/dist/esm/Autocomplete/Stores/index.d.ts +7 -0
  118. package/dist/esm/Autocomplete/Stores/index.d.ts.map +1 -0
  119. package/dist/esm/Autocomplete/Stores/index.js +6 -0
  120. package/dist/esm/Cart/CartStore.d.ts +15 -0
  121. package/dist/esm/Cart/CartStore.d.ts.map +1 -0
  122. package/dist/esm/Cart/CartStore.js +74 -0
  123. package/dist/esm/Finder/FinderStore.d.ts +27 -0
  124. package/dist/esm/Finder/FinderStore.d.ts.map +1 -0
  125. package/dist/esm/Finder/FinderStore.js +118 -0
  126. package/dist/esm/Finder/Stores/FinderSelectionStore.d.ts +73 -0
  127. package/dist/esm/Finder/Stores/FinderSelectionStore.d.ts.map +1 -0
  128. package/dist/esm/Finder/Stores/FinderSelectionStore.js +258 -0
  129. package/dist/esm/Finder/Stores/index.d.ts +2 -0
  130. package/dist/esm/Finder/Stores/index.d.ts.map +1 -0
  131. package/dist/esm/Finder/Stores/index.js +1 -0
  132. package/dist/esm/Meta/MetaStore.d.ts +20 -0
  133. package/dist/esm/Meta/MetaStore.d.ts.map +1 -0
  134. package/dist/esm/Meta/MetaStore.js +45 -0
  135. package/dist/esm/Recommendation/RecommendationStore.d.ts +19 -0
  136. package/dist/esm/Recommendation/RecommendationStore.d.ts.map +1 -0
  137. package/dist/esm/Recommendation/RecommendationStore.js +71 -0
  138. package/dist/esm/Recommendation/Stores/RecommendationProfileStore.d.ts +15 -0
  139. package/dist/esm/Recommendation/Stores/RecommendationProfileStore.d.ts.map +1 -0
  140. package/dist/esm/Recommendation/Stores/RecommendationProfileStore.js +25 -0
  141. package/dist/esm/Recommendation/Stores/index.d.ts +2 -0
  142. package/dist/esm/Recommendation/Stores/index.d.ts.map +1 -0
  143. package/dist/esm/Recommendation/Stores/index.js +1 -0
  144. package/dist/esm/Search/SearchStore.d.ts +27 -0
  145. package/dist/esm/Search/SearchStore.d.ts.map +1 -0
  146. package/dist/esm/Search/SearchStore.js +102 -0
  147. package/dist/esm/Search/Stores/SearchFacetStore.d.ts +89 -0
  148. package/dist/esm/Search/Stores/SearchFacetStore.d.ts.map +1 -0
  149. package/dist/esm/Search/Stores/SearchFacetStore.js +292 -0
  150. package/dist/esm/Search/Stores/SearchFilterStore.d.ts +44 -0
  151. package/dist/esm/Search/Stores/SearchFilterStore.d.ts.map +1 -0
  152. package/dist/esm/Search/Stores/SearchFilterStore.js +70 -0
  153. package/dist/esm/Search/Stores/SearchHistoryStore.d.ts +20 -0
  154. package/dist/esm/Search/Stores/SearchHistoryStore.d.ts.map +1 -0
  155. package/dist/esm/Search/Stores/SearchHistoryStore.js +85 -0
  156. package/dist/esm/Search/Stores/SearchMerchandisingStore.d.ts +36 -0
  157. package/dist/esm/Search/Stores/SearchMerchandisingStore.d.ts.map +1 -0
  158. package/dist/esm/Search/Stores/SearchMerchandisingStore.js +61 -0
  159. package/dist/esm/Search/Stores/SearchPaginationStore.d.ts +57 -0
  160. package/dist/esm/Search/Stores/SearchPaginationStore.d.ts.map +1 -0
  161. package/dist/esm/Search/Stores/SearchPaginationStore.js +163 -0
  162. package/dist/esm/Search/Stores/SearchQueryStore.d.ts +23 -0
  163. package/dist/esm/Search/Stores/SearchQueryStore.d.ts.map +1 -0
  164. package/dist/esm/Search/Stores/SearchQueryStore.js +33 -0
  165. package/dist/esm/Search/Stores/SearchResultStore.d.ts +175 -0
  166. package/dist/esm/Search/Stores/SearchResultStore.d.ts.map +1 -0
  167. package/dist/esm/Search/Stores/SearchResultStore.js +648 -0
  168. package/dist/esm/Search/Stores/SearchSortingStore.d.ts +32 -0
  169. package/dist/esm/Search/Stores/SearchSortingStore.d.ts.map +1 -0
  170. package/dist/esm/Search/Stores/SearchSortingStore.js +67 -0
  171. package/dist/esm/Search/Stores/index.d.ts +9 -0
  172. package/dist/esm/Search/Stores/index.d.ts.map +1 -0
  173. package/dist/esm/Search/Stores/index.js +8 -0
  174. package/dist/esm/Storage/StorageStore.d.ts +27 -0
  175. package/dist/esm/Storage/StorageStore.d.ts.map +1 -0
  176. package/dist/esm/Storage/StorageStore.js +169 -0
  177. package/dist/esm/index.d.ts +12 -0
  178. package/dist/esm/index.d.ts.map +1 -0
  179. package/dist/esm/index.js +11 -0
  180. package/dist/esm/types.d.ts +170 -0
  181. package/dist/esm/types.d.ts.map +1 -0
  182. package/dist/esm/types.js +6 -0
  183. package/package.json +35 -0
@@ -0,0 +1,292 @@
1
+ import deepmerge from 'deepmerge';
2
+ import { makeObservable, observable, action, computed, reaction } from 'mobx';
3
+ export class SearchFacetStore extends Array {
4
+ static get [Symbol.species]() {
5
+ return Array;
6
+ }
7
+ constructor(params) {
8
+ const config = params?.config || {};
9
+ const { services, stores, data } = params || {};
10
+ const { search, meta } = data || {};
11
+ const { facets, merchandising, pagination } = search || {};
12
+ const { storage } = stores || {};
13
+ const facetsArr = facets
14
+ ?.filter((facet) => {
15
+ const facetMeta = facet.field && meta.facets && meta.facets[facet.field];
16
+ // exclude facets that have no meta data
17
+ if (!facetMeta)
18
+ return false;
19
+ // exclude facets that have mismatched meta data
20
+ if ((facetMeta.display == 'slider' && facet.type !== 'range') || (facet.type == 'range' && facetMeta.display !== 'slider')) {
21
+ return false;
22
+ }
23
+ // trim facets - remove facets that have no use
24
+ const facetConfig = config.settings?.facets?.fields && facet.field && config.settings?.facets?.fields[facet.field];
25
+ const shouldTrim = typeof facetConfig?.trim == 'boolean' ? facetConfig?.trim : config.settings?.facets?.trim;
26
+ if (shouldTrim) {
27
+ if (facet.type === 'range' &&
28
+ facet?.range?.low == facet?.range?.high) {
29
+ return false;
30
+ }
31
+ else if (facet.values?.length == 0) {
32
+ return false;
33
+ }
34
+ else if (!facet.filtered && facet.values?.length == 1) {
35
+ if (merchandising?.content?.inline) {
36
+ return facet.values[0].count + merchandising.content?.inline.length != pagination.totalResults;
37
+ }
38
+ else {
39
+ return facet.values[0].count != pagination.totalResults;
40
+ }
41
+ }
42
+ }
43
+ return true;
44
+ })
45
+ .map((facet) => {
46
+ const facetMeta = facet.field && meta.facets && meta.facets[facet.field];
47
+ const facetConfig = deepmerge({ ...config.settings?.facets, fields: undefined }, (config.settings?.facets?.fields && facet.field && config.settings?.facets?.fields[facet.field]) || {});
48
+ delete facetConfig.fields;
49
+ switch (facet.type) {
50
+ case 'range':
51
+ return new RangeFacet(services, storage, facet, facetMeta || {}, facetConfig);
52
+ case 'value':
53
+ case 'range-buckets':
54
+ default:
55
+ return new ValueFacet(services, storage, facet, facetMeta || {}, facetConfig);
56
+ }
57
+ }) || [];
58
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
59
+ // @ts-ignore
60
+ super(...facetsArr);
61
+ }
62
+ }
63
+ export class Facet {
64
+ constructor(services, storage, facet, facetMeta, config) {
65
+ this.filtered = false;
66
+ this.custom = {};
67
+ this.collapsed = false;
68
+ this.display = '';
69
+ this.label = '';
70
+ this.services = services;
71
+ this.storage = storage;
72
+ Object.assign(this, facetMeta, facet);
73
+ makeObservable(this, {
74
+ type: observable,
75
+ field: observable,
76
+ filtered: observable,
77
+ custom: observable,
78
+ collapsed: observable,
79
+ display: observable,
80
+ label: observable,
81
+ clear: computed,
82
+ toggleCollapse: action,
83
+ });
84
+ const collapseData = this.storage.get(`facets.${this.field}.collapsed`);
85
+ this.collapsed = collapseData ?? this.collapsed;
86
+ if (this.filtered && this.collapsed && typeof collapseData == 'undefined' && config.autoOpenActive) {
87
+ this.toggleCollapse();
88
+ }
89
+ }
90
+ get clear() {
91
+ return {
92
+ url: this.services.urlManager.remove('page').remove(`filter.${this.field}`),
93
+ };
94
+ }
95
+ toggleCollapse() {
96
+ this.collapsed = !this.collapsed;
97
+ this.storage.set(`facets.${this.field}.collapsed`, this.collapsed);
98
+ }
99
+ }
100
+ export class RangeFacet extends Facet {
101
+ constructor(services, storage, facet, facetMeta, config) {
102
+ super(services, storage, facet, facetMeta, config);
103
+ this.range = {
104
+ low: 0,
105
+ high: 0,
106
+ };
107
+ this.active = {
108
+ low: 0,
109
+ high: 0,
110
+ };
111
+ this.step = facet?.step;
112
+ const storedRange = config.storeRange && this.storage.get(`facets.${this.field}.range`);
113
+ if (storedRange && facet.filtered && (facet.range?.low > storedRange.low || facet.range?.high < storedRange.high)) {
114
+ // range from API has shrunk
115
+ this.range = this.storage.get(`facets.${this.field}.range`);
116
+ }
117
+ else {
118
+ this.storage.set(`facets.${this.field}.range`, facet.range);
119
+ this.range = facet.range;
120
+ }
121
+ // TODO: Fix api
122
+ // needed when API returns no active (only seems to be when range.low == range.high)
123
+ this.active = facet.active || facet.range;
124
+ this.formatSeparator = facetMeta?.formatSeparator || '-';
125
+ this.formatValue = facetMeta?.formatValue || '%01.2f';
126
+ makeObservable(this, {
127
+ step: observable,
128
+ range: observable,
129
+ active: observable,
130
+ formatSeparator: observable,
131
+ formatValue: observable,
132
+ });
133
+ }
134
+ get filteredCount() {
135
+ return Number(this.filtered);
136
+ }
137
+ }
138
+ export class ValueFacet extends Facet {
139
+ constructor(services, storage, facet, facetMeta, config) {
140
+ super(services, storage, facet, facetMeta, config);
141
+ this.values = [];
142
+ this.search = {
143
+ input: '',
144
+ };
145
+ this.overflow = {
146
+ enabled: false,
147
+ limited: true,
148
+ limit: 0,
149
+ remaining: undefined,
150
+ setLimit: function (limit) {
151
+ if (limit != this.limit) {
152
+ this.enabled = true;
153
+ this.limit = limit;
154
+ this.calculate();
155
+ }
156
+ },
157
+ toggle: (val) => {
158
+ if (typeof val != 'undefined') {
159
+ this.overflow.limited = val;
160
+ }
161
+ else {
162
+ this.overflow.limited = !this.overflow.limited;
163
+ }
164
+ this.storage.set(`facets.${this.field}.overflow.limited`, this.overflow.limited);
165
+ this.overflow.calculate();
166
+ },
167
+ calculate: () => {
168
+ if (this.overflow.limit > 0) {
169
+ const remaining = this.values.length - this.overflow.limit;
170
+ if (remaining > 0 && !this.search.input) {
171
+ this.overflow.enabled = true;
172
+ if (this.overflow.limited) {
173
+ this.overflow.remaining = remaining;
174
+ }
175
+ else {
176
+ this.overflow.remaining = 0;
177
+ }
178
+ }
179
+ else {
180
+ this.overflow.enabled = false;
181
+ }
182
+ }
183
+ },
184
+ };
185
+ this.multiple = this.multiple;
186
+ this.values =
187
+ (facet.values &&
188
+ facet.values.map((value) => {
189
+ switch (facet.type) {
190
+ case 'value':
191
+ if (facetMeta.display === 'hierarchy') {
192
+ const filteredValues = facet?.values?.filter((value) => value.filtered) || [];
193
+ return new FacetHierarchyValue(services, this, value, filteredValues);
194
+ }
195
+ else {
196
+ // converting values to strings to ensure UrlManager state matches state created from URL
197
+ value.value = value?.value?.toString();
198
+ return new FacetValue(services, this, value);
199
+ }
200
+ case 'range-buckets':
201
+ return new FacetRangeValue(services, this, value);
202
+ }
203
+ })) ||
204
+ [];
205
+ if (config.pinFiltered && facetMeta.display !== 'hierarchy') {
206
+ this.values.sort((a, b) => Number(b.filtered) - Number(a.filtered));
207
+ }
208
+ const overflowLimitedState = this.storage.get(`facets.${this.field}.overflow.limited`);
209
+ if (typeof overflowLimitedState != 'undefined') {
210
+ this.overflow.toggle(overflowLimitedState);
211
+ }
212
+ makeObservable(this, {
213
+ values: observable,
214
+ search: observable,
215
+ multiple: observable,
216
+ overflow: observable,
217
+ refinedValues: computed,
218
+ });
219
+ reaction(() => this.search.input, () => {
220
+ this.overflow.calculate();
221
+ });
222
+ }
223
+ get filteredCount() {
224
+ return this.values.filter((value) => value?.filtered).length;
225
+ }
226
+ get refinedValues() {
227
+ let values = this.values || [];
228
+ if (this.search.input) {
229
+ const search = new RegExp(escapeRegExp(this.search.input), 'i');
230
+ values = this.values.filter((value) => String(value?.label || '').match(search));
231
+ }
232
+ if (this.overflow.enabled && this.overflow.limited) {
233
+ values = values.slice(0, this.overflow.limit);
234
+ }
235
+ return values;
236
+ }
237
+ }
238
+ export class FacetValue {
239
+ constructor(services, facet, value) {
240
+ Object.assign(this, value);
241
+ if (this.filtered) {
242
+ this.url = services.urlManager.remove('page').remove(`filter.${facet.field}`, value.value);
243
+ }
244
+ else {
245
+ let valueUrl = services.urlManager.remove('page');
246
+ if (facet.multiple == 'single') {
247
+ valueUrl = valueUrl?.remove(`filter.${facet.field}`);
248
+ }
249
+ this.url = valueUrl?.merge(`filter.${facet.field}`, value.value);
250
+ }
251
+ }
252
+ }
253
+ export class FacetHierarchyValue extends FacetValue {
254
+ constructor(services, facet, value, filteredValues) {
255
+ super(services, facet, value);
256
+ this.level = 0;
257
+ this.history = false;
258
+ if (value.value && facet.hierarchyDelimiter) {
259
+ this.level = value.value.split(facet.hierarchyDelimiter).length;
260
+ }
261
+ if (facet.filtered && filteredValues?.length) {
262
+ const filteredLevel = facet?.hierarchyDelimiter && filteredValues[0].value?.split(facet.hierarchyDelimiter).length;
263
+ if (filteredLevel && this.level <= filteredLevel) {
264
+ this.history = true;
265
+ }
266
+ }
267
+ if (value.value) {
268
+ this.url = services.urlManager.remove('page').set(`filter.${facet.field}`, value.value);
269
+ }
270
+ else {
271
+ this.url = services.urlManager.remove('page').remove(`filter.${facet.field}`);
272
+ }
273
+ }
274
+ }
275
+ export class FacetRangeValue {
276
+ constructor(services, facet, value) {
277
+ Object.assign(this, value);
278
+ if (this.filtered) {
279
+ this.url = services.urlManager.remove('page').remove(`filter.${facet.field}`, [{ low: this.low, high: this.high }]);
280
+ }
281
+ else {
282
+ let valueUrl = services.urlManager.remove('page');
283
+ if (facet.multiple == 'single') {
284
+ valueUrl = valueUrl?.remove(`filter.${facet.field}`);
285
+ }
286
+ this.url = valueUrl?.merge(`filter.${facet.field}`, [{ low: this.low, high: this.high }]);
287
+ }
288
+ }
289
+ }
290
+ function escapeRegExp(string) {
291
+ return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); // $& means the whole matched string
292
+ }
@@ -0,0 +1,44 @@
1
+ import type { UrlManager } from '@athoscommerce/snap-url-manager';
2
+ import type { AutocompleteStoreConfig, SearchStoreConfig, StoreServices } from '../../types';
3
+ import type { SearchResponseModelFilterRange, SearchResponseModelFilterValue, MetaResponseModelFacetDefaults, MetaResponseModelFacet, SearchResponseModel, MetaResponseModel } from '@athoscommerce/snapi-types';
4
+ type SearchFilterStoreConfig = {
5
+ services: StoreServices;
6
+ config?: SearchStoreConfig | AutocompleteStoreConfig;
7
+ data: {
8
+ search?: SearchResponseModel;
9
+ meta: MetaResponseModel;
10
+ };
11
+ };
12
+ export declare class SearchFilterStore extends Array<RangeFilter | Filter> {
13
+ static get [Symbol.species](): ArrayConstructor;
14
+ constructor(params: SearchFilterStoreConfig);
15
+ }
16
+ export declare class Filter {
17
+ label: string;
18
+ facet: {
19
+ field?: string;
20
+ label?: string;
21
+ };
22
+ value: {
23
+ value?: string;
24
+ label?: string;
25
+ };
26
+ url: UrlManager;
27
+ constructor(services: StoreServices, filter: SearchResponseModelFilterValue, meta: MetaResponseModelFacet & MetaResponseModelFacetDefaults);
28
+ }
29
+ export declare class RangeFilter {
30
+ label: string;
31
+ facet: {
32
+ field?: string;
33
+ label?: string;
34
+ };
35
+ value: {
36
+ low?: number;
37
+ high?: number;
38
+ label: string;
39
+ };
40
+ url: UrlManager;
41
+ constructor(services: StoreServices, filter: SearchResponseModelFilterRange, meta: MetaResponseModelFacet & MetaResponseModelFacetDefaults);
42
+ }
43
+ export {};
44
+ //# sourceMappingURL=SearchFilterStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchFilterStore.d.ts","sourceRoot":"","sources":["../../../../src/Search/Stores/SearchFilterStore.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAClE,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,KAAK,EACX,8BAA8B,EAC9B,8BAA8B,EAC9B,8BAA8B,EAC9B,sBAAsB,EACtB,mBAAmB,EACnB,iBAAiB,EACjB,MAAM,4BAA4B,CAAC;AAGpC,KAAK,uBAAuB,GAAG;IAC9B,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,CAAC,EAAE,iBAAiB,GAAG,uBAAuB,CAAC;IACrD,IAAI,EAAE;QACL,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B,IAAI,EAAE,iBAAiB,CAAC;KACxB,CAAC;CACF,CAAC;AAEF,qBAAa,iBAAkB,SAAQ,KAAK,CAAC,WAAW,GAAG,MAAM,CAAC;IACjE,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,gBAAgB,CAE9C;gBAEW,MAAM,EAAE,uBAAuB;CA8B3C;AAED,qBAAa,MAAM;IACX,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACK,KAAK,EAAE;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IAEK,GAAG,EAAE,UAAU,CAAC;gBAEX,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,8BAA8B,EAAE,IAAI,EAAE,sBAAsB,GAAG,8BAA8B;CAmB1I;AAED,qBAAa,WAAW;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE;QACb,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACK,KAAK,EAAE;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,EAAE,MAAM,CAAC;KACd,CAAC;IAEK,GAAG,EAAE,UAAU,CAAC;gBAEX,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,8BAA8B,EAAE,IAAI,EAAE,sBAAsB,GAAG,8BAA8B;CAoB1I"}
@@ -0,0 +1,70 @@
1
+ import { makeObservable, observable } from 'mobx';
2
+ import { sprintf } from '@athoscommerce/snap-toolbox';
3
+ export class SearchFilterStore extends Array {
4
+ static get [Symbol.species]() {
5
+ return Array;
6
+ }
7
+ constructor(params) {
8
+ const { services, data, config } = params || {};
9
+ const { search, meta } = data || {};
10
+ const { filters } = search || {};
11
+ const filtersArr = filters?.map((filter) => {
12
+ const field = filter.field;
13
+ const facetMeta = meta.facets && meta.facets[field];
14
+ switch (filter.type) {
15
+ case 'range':
16
+ const rangeFilter = filter;
17
+ const format = config?.settings?.filters?.fields?.[filter.field]?.rangeFormatValue ||
18
+ config?.settings?.filters?.rangeFormatValue;
19
+ if (format) {
20
+ rangeFilter.label = sprintf(format, rangeFilter.value?.low, rangeFilter.value?.high);
21
+ }
22
+ return new RangeFilter(services, rangeFilter, facetMeta);
23
+ case 'value':
24
+ default:
25
+ const valueFilter = filter;
26
+ return new Filter(services, valueFilter, facetMeta);
27
+ }
28
+ }) || [];
29
+ super(...filtersArr);
30
+ }
31
+ }
32
+ export class Filter {
33
+ constructor(services, filter, meta) {
34
+ this.facet = {
35
+ field: filter.field,
36
+ label: meta?.label || filter.field,
37
+ };
38
+ this.value = {
39
+ value: filter.value,
40
+ label: filter.label,
41
+ };
42
+ this.label = `${this.facet.label}: ${this.value.label}`;
43
+ this.url = services?.urlManager?.remove('page').remove(`filter.${this.facet.field}`, this.value.value);
44
+ makeObservable(this, {
45
+ facet: observable,
46
+ value: observable,
47
+ label: observable,
48
+ });
49
+ }
50
+ }
51
+ export class RangeFilter {
52
+ constructor(services, filter, meta) {
53
+ this.facet = {
54
+ field: filter.field,
55
+ label: meta?.label || filter.field,
56
+ };
57
+ this.value = {
58
+ low: filter?.value?.low,
59
+ high: filter?.value?.high,
60
+ label: filter.label || `${filter?.value?.low} - ${filter?.value?.high}`,
61
+ };
62
+ this.label = `${this.facet.label}: ${this.value.label}`;
63
+ this.url = services?.urlManager?.remove('page').remove(`filter.${this.facet.field}`, { low: this.value.low, high: this.value.high });
64
+ makeObservable(this, {
65
+ facet: observable,
66
+ value: observable,
67
+ label: observable,
68
+ });
69
+ }
70
+ }
@@ -0,0 +1,20 @@
1
+ import type { AutocompleteStoreConfig, SearchStoreConfig, StoreServices } from '../../types';
2
+ import { Query } from './SearchQueryStore';
3
+ type SearchHistoryStoreConfig = {
4
+ services: StoreServices;
5
+ config: Partial<AutocompleteStoreConfig | SearchStoreConfig>;
6
+ };
7
+ export declare class SearchHistoryStore {
8
+ private config;
9
+ private storage;
10
+ private services;
11
+ private max;
12
+ constructor(params: SearchHistoryStoreConfig);
13
+ get queries(): Query[];
14
+ save(term: string): void;
15
+ remove(term: string): void;
16
+ reset(): void;
17
+ getStoredData(limit?: number): string[];
18
+ }
19
+ export {};
20
+ //# sourceMappingURL=SearchHistoryStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchHistoryStore.d.ts","sourceRoot":"","sources":["../../../../src/Search/Stores/SearchHistoryStore.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,uBAAuB,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7F,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C,KAAK,wBAAwB,GAAG;IAC/B,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,OAAO,CAAC,uBAAuB,GAAG,iBAAiB,CAAC,CAAC;CAC7D,CAAC;AAEF,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,MAAM,CAAuD;IACrE,OAAO,CAAC,OAAO,CAAe;IAC9B,OAAO,CAAC,QAAQ,CAAgB;IAChC,OAAO,CAAC,GAAG,CAAS;gBAER,MAAM,EAAE,wBAAwB;IAoC5C,IAAI,OAAO,IAAI,KAAK,EAAE,CAGrB;IAEM,IAAI,CAAC,IAAI,EAAE,MAAM;IAoBjB,MAAM,CAAC,IAAI,EAAE,MAAM;IAWnB,KAAK,IAAI,IAAI;IAIb,aAAa,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE;CAmB9C"}
@@ -0,0 +1,85 @@
1
+ import { StorageStore } from '../../Storage/StorageStore';
2
+ import { Query } from './SearchQueryStore';
3
+ export class SearchHistoryStore {
4
+ constructor(params) {
5
+ const { services, config } = params || {};
6
+ this.config = config;
7
+ this.services = services;
8
+ this.max = this.config.settings?.history?.max ?? 25;
9
+ if (this.config.settings?.history?.url) {
10
+ this.services.urlManager = this.services.urlManager.withConfig((translatorConfig) => {
11
+ return {
12
+ ...translatorConfig,
13
+ urlRoot: this.config.settings?.history?.url,
14
+ };
15
+ });
16
+ }
17
+ this.storage = new StorageStore({
18
+ type: 'local',
19
+ key: `athos-history${this.config.globals?.siteId ? `-${this.config.globals?.siteId}` : ``}`,
20
+ });
21
+ // reset to zero to clear any potentially existing terms
22
+ if (this.max === 0) {
23
+ this.reset();
24
+ }
25
+ // trim history if the current queries are more than config max
26
+ if (this.queries.length > this.max) {
27
+ this.getStoredData().forEach((term, index) => {
28
+ if (index > this.max - 1) {
29
+ this.remove(term);
30
+ }
31
+ });
32
+ }
33
+ }
34
+ get queries() {
35
+ const queries = this.getStoredData();
36
+ return queries.map((query) => new Query(this.services, query));
37
+ }
38
+ save(term) {
39
+ // adding term to array if max is not zero
40
+ if (this.max) {
41
+ const history = this.getStoredData();
42
+ // removing term if already present
43
+ const index = history.indexOf(term);
44
+ if (index != -1) {
45
+ history.splice(index, 1);
46
+ }
47
+ history.unshift(term);
48
+ if (history.length > this.max) {
49
+ history.pop();
50
+ }
51
+ this.storage.set('history', JSON.stringify(history));
52
+ }
53
+ }
54
+ remove(term) {
55
+ const history = this.getStoredData();
56
+ // removing term if already present
57
+ const index = history.indexOf(term);
58
+ if (index != -1) {
59
+ history.splice(index, 1);
60
+ this.storage.set('history', JSON.stringify(history));
61
+ }
62
+ }
63
+ reset() {
64
+ this.storage.clear();
65
+ }
66
+ getStoredData(limit) {
67
+ const storedHistory = this.storage.get('history');
68
+ if (storedHistory) {
69
+ try {
70
+ const history = JSON.parse(storedHistory);
71
+ if (Array.isArray(history)) {
72
+ if (limit && Number.isInteger(limit)) {
73
+ return history.slice(0, limit);
74
+ }
75
+ return history;
76
+ }
77
+ }
78
+ catch (err) {
79
+ // storage corrupted - resetting it
80
+ this.reset();
81
+ }
82
+ }
83
+ return [];
84
+ }
85
+ }
@@ -0,0 +1,36 @@
1
+ import type { SearchResponseModelMerchandisingCampaigns, SearchResponseModel, SearchResponseModelMerchandisingExperiments, SearchResponseModelTracking } from '@athoscommerce/snapi-types';
2
+ export declare enum ContentType {
3
+ HEADER = "header",
4
+ BANNER = "banner",
5
+ FOOTER = "footer",
6
+ LEFT = "left",
7
+ INLINE = "inline"
8
+ }
9
+ export type BannerContent = Partial<Record<ContentType, Content>>;
10
+ type SearchMerchandisingStoreConfig = {
11
+ data: {
12
+ search?: SearchResponseModel;
13
+ tracking?: SearchResponseModelTracking;
14
+ };
15
+ };
16
+ export declare class SearchMerchandisingStore {
17
+ redirect: string;
18
+ responseId: string;
19
+ content: BannerContent;
20
+ campaigns: SearchResponseModelMerchandisingCampaigns[];
21
+ landingPage?: SearchResponseModelMerchandisingCampaigns;
22
+ personalized?: boolean;
23
+ experiments: SearchResponseModelMerchandisingExperiments[];
24
+ constructor(params: SearchMerchandisingStoreConfig);
25
+ }
26
+ export type MerchandisingContentBanner = {
27
+ value: string[];
28
+ uid: string;
29
+ responseId: string;
30
+ };
31
+ declare class Content extends Array<MerchandisingContentBanner> {
32
+ static get [Symbol.species](): ArrayConstructor;
33
+ constructor(content: MerchandisingContentBanner[]);
34
+ }
35
+ export {};
36
+ //# sourceMappingURL=SearchMerchandisingStore.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SearchMerchandisingStore.d.ts","sourceRoot":"","sources":["../../../../src/Search/Stores/SearchMerchandisingStore.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACX,yCAAyC,EACzC,mBAAmB,EACnB,2CAA2C,EAC3C,2BAA2B,EAC3B,MAAM,4BAA4B,CAAC;AAEpC,oBAAY,WAAW;IACtB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,MAAM,WAAW;IACjB,IAAI,SAAS;IACb,MAAM,WAAW;CACjB;AAED,MAAM,MAAM,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC,CAAC;AAElE,KAAK,8BAA8B,GAAG;IACrC,IAAI,EAAE;QACL,MAAM,CAAC,EAAE,mBAAmB,CAAC;QAC7B,QAAQ,CAAC,EAAE,2BAA2B,CAAC;KACvC,CAAC;CACF,CAAC;AAEF,qBAAa,wBAAwB;IAC7B,QAAQ,SAAM;IACd,UAAU,SAAM;IAChB,OAAO,EAAE,aAAa,CAAM;IAC5B,SAAS,EAAE,yCAAyC,EAAE,CAAM;IAC5D,WAAW,CAAC,EAAE,yCAAyC,CAAC;IACxD,YAAY,CAAC,EAAE,OAAO,CAAS;IAC/B,WAAW,EAAE,2CAA2C,EAAE,CAAM;gBAE3D,MAAM,EAAE,8BAA8B;CAyClD;AAED,MAAM,MAAM,0BAA0B,GAAG;IACxC,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;CACnB,CAAC;AACF,cAAM,OAAQ,SAAQ,KAAK,CAAC,0BAA0B,CAAC;IACtD,MAAM,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,gBAAgB,CAE9C;gBAEW,OAAO,EAAE,0BAA0B,EAAE;CAGjD"}
@@ -0,0 +1,61 @@
1
+ export var ContentType;
2
+ (function (ContentType) {
3
+ ContentType["HEADER"] = "header";
4
+ ContentType["BANNER"] = "banner";
5
+ ContentType["FOOTER"] = "footer";
6
+ ContentType["LEFT"] = "left";
7
+ ContentType["INLINE"] = "inline";
8
+ })(ContentType || (ContentType = {}));
9
+ export class SearchMerchandisingStore {
10
+ constructor(params) {
11
+ this.redirect = '';
12
+ this.responseId = '';
13
+ this.content = {};
14
+ this.campaigns = [];
15
+ this.personalized = false;
16
+ this.experiments = [];
17
+ const { merchandising } = params?.data?.search || {};
18
+ if (merchandising) {
19
+ this.redirect = merchandising.redirect || '';
20
+ this.responseId = params?.data?.search?.tracking?.responseId || params?.data?.tracking?.responseId || ''; // Autocomplete 'beforeSubmit' doesn't have a response reference
21
+ if (merchandising.content) {
22
+ Object.values(ContentType).forEach((type) => {
23
+ if (merchandising.content && merchandising.content[type]) {
24
+ // Extract data-banner-id from the HTML string
25
+ const htmlString = merchandising.content[type]?.[0] || '';
26
+ const match = typeof htmlString === 'string' && htmlString.match(/data-banner-id="(\d+)"/);
27
+ const uid = match ? match[1] : '';
28
+ this.content[type] = new Content([
29
+ {
30
+ value: merchandising.content[type],
31
+ uid,
32
+ responseId: this.responseId,
33
+ },
34
+ ]);
35
+ }
36
+ });
37
+ }
38
+ if (merchandising.campaigns) {
39
+ this.campaigns = merchandising.campaigns;
40
+ // if we find a 'landing-page', get landingPage details from merchandising.campaigns
41
+ merchandising.campaigns.forEach((campaign) => {
42
+ if (campaign.type == 'landing-page') {
43
+ this.landingPage = campaign;
44
+ }
45
+ });
46
+ }
47
+ if (merchandising.experiments) {
48
+ this.experiments = merchandising.experiments;
49
+ }
50
+ this.personalized = !!merchandising.personalized;
51
+ }
52
+ }
53
+ }
54
+ class Content extends Array {
55
+ static get [Symbol.species]() {
56
+ return Array;
57
+ }
58
+ constructor(content) {
59
+ super(...content);
60
+ }
61
+ }
@@ -0,0 +1,57 @@
1
+ import type { StoreServices, SearchStoreConfig } from '../../types';
2
+ import type { UrlManager } from '@athoscommerce/snap-url-manager';
3
+ import { MetaResponseModel, SearchResponseModel } from '@athoscommerce/snapi-types';
4
+ type SearchPaginationStoreConfig = {
5
+ config?: SearchStoreConfig;
6
+ services: StoreServices;
7
+ data: {
8
+ search?: SearchResponseModel;
9
+ meta: MetaResponseModel;
10
+ };
11
+ };
12
+ export declare class SearchPaginationStore {
13
+ services: StoreServices;
14
+ page: number;
15
+ pageSize: number;
16
+ pageSizeOption?: PageSizeOption;
17
+ pageSizeOptions: PageSizeOption[];
18
+ defaultPageSize: number;
19
+ totalResults: number;
20
+ totalPages: number;
21
+ controllerConfig?: SearchStoreConfig;
22
+ constructor(params: SearchPaginationStoreConfig);
23
+ get begin(): number;
24
+ get end(): number;
25
+ get multiplePages(): boolean;
26
+ get current(): Page;
27
+ get first(): Page;
28
+ get last(): Page;
29
+ get next(): Page | undefined;
30
+ get previous(): Page | undefined;
31
+ getPages(min?: number, max?: number): Page[];
32
+ setPageSize(num: number): void;
33
+ }
34
+ export declare class PageSizeOption {
35
+ private services;
36
+ value: number;
37
+ label: string;
38
+ url: UrlManager;
39
+ active: boolean;
40
+ constructor(services: StoreServices, currentPageSize: number, option: {
41
+ value: number;
42
+ label: string;
43
+ });
44
+ }
45
+ export declare class Page {
46
+ private services;
47
+ number: number;
48
+ active: boolean;
49
+ url: UrlManager;
50
+ key: string;
51
+ constructor(services: StoreServices, page: {
52
+ number: number;
53
+ active?: boolean;
54
+ });
55
+ }
56
+ export {};
57
+ //# sourceMappingURL=SearchPaginationStore.d.ts.map