@uniformdev/search 0.0.1 → 0.0.2
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/LICENSE +1 -1
- package/README.md +129 -0
- package/dist/{chunk-ZABEFR2D.mjs → chunk-RMUYFKZO.mjs} +11 -4
- package/dist/chunk-RMUYFKZO.mjs.map +1 -0
- package/dist/{client-DrL-8TfY.d.mts → client-CtTcEJUy.d.mts} +14 -12
- package/dist/{client-DrL-8TfY.d.ts → client-CtTcEJUy.d.ts} +14 -12
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +18 -6
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +9 -4
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +40 -13
- package/dist/react.d.ts +40 -13
- package/dist/react.js +162 -116
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +148 -121
- package/dist/react.mjs.map +1 -1
- package/package.json +23 -2
- package/dist/chunk-ZABEFR2D.mjs.map +0 -1
package/dist/react.mjs
CHANGED
|
@@ -8,56 +8,36 @@ import {
|
|
|
8
8
|
buildOrderByQuery,
|
|
9
9
|
flattenBlockParams,
|
|
10
10
|
getSearchParamsFromUrl
|
|
11
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-RMUYFKZO.mjs";
|
|
12
12
|
|
|
13
13
|
// src/react/SearchProvider.tsx
|
|
14
|
-
import {
|
|
15
|
-
createContext,
|
|
16
|
-
useMemo,
|
|
17
|
-
useCallback,
|
|
18
|
-
useState,
|
|
19
|
-
useEffect,
|
|
20
|
-
useRef
|
|
21
|
-
} from "react";
|
|
14
|
+
import { createContext, useMemo, useCallback, useState, useEffect, useRef } from "react";
|
|
22
15
|
import { jsx } from "react/jsx-runtime";
|
|
23
|
-
var ALL_COLLECTIONS = ["entries", "compositions", "assets"];
|
|
24
16
|
var SearchContext = createContext(null);
|
|
25
17
|
var SearchProvider = ({
|
|
26
18
|
children,
|
|
27
19
|
performSearch,
|
|
28
|
-
contentType,
|
|
29
|
-
filterBy: filterByRaw,
|
|
30
20
|
orderBy: orderByRaw,
|
|
31
|
-
|
|
21
|
+
baseFilterString,
|
|
32
22
|
pageSizes: pageSizesRaw,
|
|
33
|
-
|
|
34
|
-
searchDebounceMs = 300
|
|
23
|
+
queryBy,
|
|
24
|
+
searchDebounceMs = 300,
|
|
25
|
+
locale,
|
|
26
|
+
maxFacetValues = 100
|
|
35
27
|
}) => {
|
|
36
28
|
var _a;
|
|
37
|
-
const filterBy =
|
|
38
|
-
const
|
|
29
|
+
const [filterBy, setFilterOptions] = useState([]);
|
|
30
|
+
const registerFilterOption = useCallback((filter) => {
|
|
31
|
+
if (!(filter == null ? void 0 : filter.fieldKey)) return;
|
|
32
|
+
setFilterOptions((prev) => [...prev.filter((f) => f.fieldKey !== filter.fieldKey), filter]);
|
|
33
|
+
}, []);
|
|
34
|
+
const unregisterFilterOption = useCallback((fieldKey) => {
|
|
35
|
+
setFilterOptions((prev) => prev.filter((f) => f.fieldKey !== fieldKey));
|
|
36
|
+
}, []);
|
|
39
37
|
const orderByFlat = useMemo(() => flattenBlockParams(orderByRaw), [orderByRaw]);
|
|
40
38
|
const pageSizesFlat = useMemo(() => flattenBlockParams(pageSizesRaw), [pageSizesRaw]);
|
|
41
|
-
const initCollections = useMemo(() => {
|
|
42
|
-
if (!collectionsRaw) return void 0;
|
|
43
|
-
const items = Array.isArray(collectionsRaw) ? collectionsRaw : collectionsRaw.split(",").map((s) => s.trim());
|
|
44
|
-
const valid = items.filter(
|
|
45
|
-
(c) => ["entries", "compositions", "assets"].includes(c)
|
|
46
|
-
);
|
|
47
|
-
return valid.length > 0 ? valid : void 0;
|
|
48
|
-
}, [collectionsRaw]);
|
|
49
|
-
const baseFilterQuery = useMemo(
|
|
50
|
-
() => baseFiltersFlat.reduce((acc, filter) => {
|
|
51
|
-
if (!(filter == null ? void 0 : filter.fieldKey) || !Array.isArray(filter.values)) return acc;
|
|
52
|
-
return {
|
|
53
|
-
...acc,
|
|
54
|
-
[`${filter.fieldKey}[eq]`]: filter.values.map((v) => v.value)
|
|
55
|
-
};
|
|
56
|
-
}, {}),
|
|
57
|
-
[baseFiltersFlat]
|
|
58
|
-
);
|
|
59
39
|
const facetBy = useMemo(
|
|
60
|
-
() => filterBy.filter((f) =>
|
|
40
|
+
() => filterBy.filter((f) => f == null ? void 0 : f.fieldKey).map((f) => f.fieldKey).join(","),
|
|
61
41
|
[filterBy]
|
|
62
42
|
);
|
|
63
43
|
const defaultOrderByQuery = useMemo(
|
|
@@ -69,18 +49,13 @@ var SearchProvider = ({
|
|
|
69
49
|
[orderByFlat]
|
|
70
50
|
);
|
|
71
51
|
const initPerPage = ((_a = pageSizesFlat[0]) == null ? void 0 : _a.size) || DEFAULT_PAGE_SIZE;
|
|
72
|
-
const hasFetchedInitial = useRef(false);
|
|
73
52
|
const searchDebounceRef = useRef(null);
|
|
74
|
-
const
|
|
75
|
-
initCollections || ALL_COLLECTIONS
|
|
76
|
-
);
|
|
53
|
+
const searchRequestIdRef = useRef(0);
|
|
77
54
|
const [urlParams, setUrlParams] = useState(() => {
|
|
78
55
|
if (typeof window === "undefined") return {};
|
|
79
56
|
return getSearchParamsFromUrl(window.location.href);
|
|
80
57
|
});
|
|
81
|
-
const [searchBoxValue, setSearchBoxValue] = useState(
|
|
82
|
-
(urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_QUERY_KEY]) || ""
|
|
83
|
-
);
|
|
58
|
+
const [searchBoxValue, setSearchBoxValue] = useState((urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_QUERY_KEY]) || "");
|
|
84
59
|
const [isLoading, setIsLoading] = useState(true);
|
|
85
60
|
const [entries, setEntries] = useState({
|
|
86
61
|
items: [],
|
|
@@ -90,17 +65,16 @@ var SearchProvider = ({
|
|
|
90
65
|
totalPages: 0
|
|
91
66
|
});
|
|
92
67
|
const [facets, setFacets] = useState({});
|
|
93
|
-
const [collectionResults, setCollectionResults] = useState({});
|
|
94
68
|
const pathname = useMemo(() => {
|
|
95
69
|
if (typeof window === "undefined") return "/";
|
|
96
70
|
return window.location.pathname;
|
|
97
71
|
}, []);
|
|
98
|
-
const page = Number(urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_PAGE_KEY]) - 1
|
|
72
|
+
const page = Number(urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_PAGE_KEY]) - 1 > 0 ? Number(urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_PAGE_KEY]) - 1 : FIRST_PAGE;
|
|
99
73
|
const search = (urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_QUERY_KEY]) || "";
|
|
100
74
|
const perPage = Number(urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_PAGE_SIZE_KEY]) || initPerPage;
|
|
101
75
|
const selectedFilters = useMemo(
|
|
102
76
|
() => filterBy.reduce((acc, filter) => {
|
|
103
|
-
const value2 = urlParams == null ? void 0 : urlParams[filter.
|
|
77
|
+
const value2 = urlParams == null ? void 0 : urlParams[filter.fieldKey];
|
|
104
78
|
if (value2) {
|
|
105
79
|
acc[filter.fieldKey] = Array.isArray(value2) ? value2 : [value2];
|
|
106
80
|
}
|
|
@@ -109,10 +83,13 @@ var SearchProvider = ({
|
|
|
109
83
|
[filterBy, urlParams]
|
|
110
84
|
);
|
|
111
85
|
useEffect(() => {
|
|
86
|
+
const requestId = ++searchRequestIdRef.current;
|
|
112
87
|
const doFetch = async () => {
|
|
113
|
-
var _a2;
|
|
114
|
-
const
|
|
88
|
+
var _a2, _b;
|
|
89
|
+
const currentOrderByQuery = (urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_ORDER_BY_KEY]) || defaultOrderByQuery;
|
|
90
|
+
const buildFilters = (excludeField) => Object.entries(selectedFilters).reduce((acc, [fieldKey, values]) => {
|
|
115
91
|
var _a3;
|
|
92
|
+
if (excludeField && fieldKey === excludeField) return acc;
|
|
116
93
|
if (!values || values.length === 0) return acc;
|
|
117
94
|
const filterType = (_a3 = filterBy.find((f) => f.fieldKey === fieldKey)) == null ? void 0 : _a3.type;
|
|
118
95
|
if (filterType === "range") {
|
|
@@ -121,65 +98,69 @@ var SearchProvider = ({
|
|
|
121
98
|
}
|
|
122
99
|
return { ...acc, [`${fieldKey}[in]`]: values };
|
|
123
100
|
}, {});
|
|
124
|
-
const
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
...filterQuery
|
|
128
|
-
};
|
|
129
|
-
if (contentType) {
|
|
130
|
-
filters["contentType[eq]"] = contentType;
|
|
131
|
-
}
|
|
132
|
-
const { results } = await performSearch({
|
|
133
|
-
page,
|
|
134
|
-
perPage,
|
|
135
|
-
filters,
|
|
136
|
-
facetBy,
|
|
137
|
-
search,
|
|
138
|
-
orderBy: currentOrderByQuery,
|
|
139
|
-
collections: selectedCollections
|
|
101
|
+
const selectedFacetFields = Object.keys(selectedFilters).filter((k) => {
|
|
102
|
+
var _a3;
|
|
103
|
+
return ((_a3 = selectedFilters[k]) == null ? void 0 : _a3.length) > 0;
|
|
140
104
|
});
|
|
141
|
-
|
|
142
|
-
const
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
105
|
+
const queryByString = (queryBy == null ? void 0 : queryBy.length) ? queryBy.join(",") : void 0;
|
|
106
|
+
const [mainResult, ...disjunctiveResults] = await Promise.all([
|
|
107
|
+
performSearch({
|
|
108
|
+
page,
|
|
109
|
+
perPage,
|
|
110
|
+
filters: buildFilters(),
|
|
111
|
+
baseFilterBy: baseFilterString,
|
|
112
|
+
facetBy,
|
|
113
|
+
queryBy: queryByString,
|
|
114
|
+
search,
|
|
115
|
+
orderBy: currentOrderByQuery,
|
|
116
|
+
locale,
|
|
117
|
+
maxFacetValues
|
|
118
|
+
}),
|
|
119
|
+
...selectedFacetFields.map(
|
|
120
|
+
(field) => performSearch({
|
|
121
|
+
page: 0,
|
|
122
|
+
perPage: 0,
|
|
123
|
+
filters: buildFilters(field),
|
|
124
|
+
baseFilterBy: baseFilterString,
|
|
125
|
+
facetBy: field,
|
|
126
|
+
queryBy: queryByString,
|
|
127
|
+
search,
|
|
128
|
+
orderBy: currentOrderByQuery,
|
|
129
|
+
locale,
|
|
130
|
+
maxFacetValues
|
|
131
|
+
})
|
|
132
|
+
)
|
|
133
|
+
]);
|
|
134
|
+
if (requestId !== searchRequestIdRef.current) return;
|
|
135
|
+
const mergedFacets = { ...(_a2 = mainResult.facets) != null ? _a2 : {} };
|
|
136
|
+
selectedFacetFields.forEach((field, i) => {
|
|
137
|
+
var _a3, _b2;
|
|
138
|
+
const counts = (_b2 = (_a3 = disjunctiveResults[i]) == null ? void 0 : _a3.facets) == null ? void 0 : _b2[field];
|
|
139
|
+
if (counts) mergedFacets[field] = counts;
|
|
161
140
|
});
|
|
141
|
+
setEntries((_b = mainResult.data) != null ? _b : { items: [], total: 0, page, perPage, totalPages: 0 });
|
|
162
142
|
setFacets(mergedFacets);
|
|
163
143
|
};
|
|
164
144
|
setIsLoading(true);
|
|
165
|
-
doFetch().catch((error) => console.error("[alex] Search fetch error:", error)).finally(() =>
|
|
166
|
-
setIsLoading(false);
|
|
167
|
-
hasFetchedInitial.current = true;
|
|
168
|
-
});
|
|
145
|
+
doFetch().catch((error) => console.error("[alex] Search fetch error:", error)).finally(() => setIsLoading(false));
|
|
169
146
|
}, [
|
|
170
|
-
|
|
171
|
-
contentType,
|
|
147
|
+
baseFilterString,
|
|
172
148
|
defaultOrderByQuery,
|
|
173
149
|
facetBy,
|
|
174
150
|
filterBy,
|
|
151
|
+
locale,
|
|
175
152
|
urlParams,
|
|
176
153
|
page,
|
|
177
154
|
perPage,
|
|
178
155
|
performSearch,
|
|
179
156
|
search,
|
|
180
|
-
selectedCollections,
|
|
181
157
|
selectedFilters
|
|
182
158
|
]);
|
|
159
|
+
useEffect(() => {
|
|
160
|
+
return () => {
|
|
161
|
+
if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
|
|
162
|
+
};
|
|
163
|
+
}, []);
|
|
183
164
|
const updateUrl = useCallback(
|
|
184
165
|
(params, { replace = false } = {}) => {
|
|
185
166
|
const qs = params.toString();
|
|
@@ -209,26 +190,15 @@ var SearchProvider = ({
|
|
|
209
190
|
const setSearchQuery = useCallback(
|
|
210
191
|
(value2) => {
|
|
211
192
|
setSearchBoxValue(value2);
|
|
212
|
-
if (searchDebounceRef.current)
|
|
213
|
-
clearTimeout(searchDebounceRef.current);
|
|
214
|
-
}
|
|
193
|
+
if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
|
|
215
194
|
if (!value2) {
|
|
216
195
|
commitSearchToUrl(value2);
|
|
217
196
|
} else {
|
|
218
|
-
searchDebounceRef.current = setTimeout(() =>
|
|
219
|
-
commitSearchToUrl(value2);
|
|
220
|
-
}, searchDebounceMs);
|
|
197
|
+
searchDebounceRef.current = setTimeout(() => commitSearchToUrl(value2), searchDebounceMs);
|
|
221
198
|
}
|
|
222
199
|
},
|
|
223
200
|
[commitSearchToUrl, searchDebounceMs]
|
|
224
201
|
);
|
|
225
|
-
useEffect(() => {
|
|
226
|
-
return () => {
|
|
227
|
-
if (searchDebounceRef.current) {
|
|
228
|
-
clearTimeout(searchDebounceRef.current);
|
|
229
|
-
}
|
|
230
|
-
};
|
|
231
|
-
}, []);
|
|
232
202
|
const setPage = useCallback(
|
|
233
203
|
(p) => {
|
|
234
204
|
const params = new URLSearchParams(window.location.search);
|
|
@@ -261,28 +231,22 @@ var SearchProvider = ({
|
|
|
261
231
|
);
|
|
262
232
|
const setSelectedFilters = useCallback(
|
|
263
233
|
(nextSelected) => {
|
|
264
|
-
const params = new URLSearchParams();
|
|
234
|
+
const params = new URLSearchParams(window.location.search);
|
|
265
235
|
params.delete(UNIFORM_SEARCH_PAGE_KEY);
|
|
266
|
-
|
|
267
|
-
params.set(UNIFORM_SEARCH_QUERY_KEY, search);
|
|
268
|
-
}
|
|
236
|
+
filterBy.forEach((f) => params.delete(f.fieldKey));
|
|
269
237
|
Object.entries(nextSelected).forEach(([key, value2]) => {
|
|
270
238
|
const filter = filterBy.find((f) => f.fieldKey === key);
|
|
271
239
|
if (!filter) return;
|
|
272
|
-
value2.forEach((v) =>
|
|
273
|
-
params.append(filter.fieldId, v);
|
|
274
|
-
});
|
|
240
|
+
value2.forEach((v) => params.append(key, v));
|
|
275
241
|
});
|
|
276
242
|
updateUrl(params);
|
|
277
243
|
},
|
|
278
|
-
[filterBy,
|
|
244
|
+
[filterBy, updateUrl]
|
|
279
245
|
);
|
|
280
246
|
const clearFilters = useCallback(() => {
|
|
281
247
|
setIsLoading(true);
|
|
282
248
|
setSearchBoxValue("");
|
|
283
|
-
if (searchDebounceRef.current)
|
|
284
|
-
clearTimeout(searchDebounceRef.current);
|
|
285
|
-
}
|
|
249
|
+
if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);
|
|
286
250
|
window.history.pushState({}, "", pathname);
|
|
287
251
|
setUrlParams(getSearchParamsFromUrl(window.location.href));
|
|
288
252
|
}, [pathname]);
|
|
@@ -307,7 +271,6 @@ var SearchProvider = ({
|
|
|
307
271
|
results: entries,
|
|
308
272
|
facets,
|
|
309
273
|
isLoading,
|
|
310
|
-
collectionResults,
|
|
311
274
|
searchBoxValue,
|
|
312
275
|
setSearchQuery,
|
|
313
276
|
page,
|
|
@@ -319,20 +282,23 @@ var SearchProvider = ({
|
|
|
319
282
|
selectedOrderBy: (urlParams == null ? void 0 : urlParams[UNIFORM_SEARCH_ORDER_BY_KEY]) || defaultOrderByQuery,
|
|
320
283
|
setOrderBy,
|
|
321
284
|
filterOptions: filterBy,
|
|
285
|
+
setFilterOptions,
|
|
286
|
+
registerFilterOption,
|
|
287
|
+
unregisterFilterOption,
|
|
322
288
|
selectedFilters,
|
|
323
289
|
setSelectedFilters,
|
|
324
290
|
clearFilters,
|
|
325
|
-
selectedCollections,
|
|
326
|
-
setSelectedCollections,
|
|
327
291
|
formatResultsSummary
|
|
328
292
|
}),
|
|
329
293
|
[
|
|
330
294
|
clearFilters,
|
|
331
|
-
collectionResults,
|
|
332
295
|
defaultOrderByQuery,
|
|
333
296
|
entries,
|
|
334
297
|
facets,
|
|
335
298
|
filterBy,
|
|
299
|
+
setFilterOptions,
|
|
300
|
+
registerFilterOption,
|
|
301
|
+
unregisterFilterOption,
|
|
336
302
|
formatResultsSummary,
|
|
337
303
|
isLoading,
|
|
338
304
|
orderByOptions,
|
|
@@ -340,7 +306,6 @@ var SearchProvider = ({
|
|
|
340
306
|
pageSizesFlat,
|
|
341
307
|
perPage,
|
|
342
308
|
searchBoxValue,
|
|
343
|
-
selectedCollections,
|
|
344
309
|
selectedFilters,
|
|
345
310
|
setOrderBy,
|
|
346
311
|
setPage,
|
|
@@ -441,11 +406,73 @@ function useSearchPagination(siblingCount) {
|
|
|
441
406
|
isLoading
|
|
442
407
|
};
|
|
443
408
|
}
|
|
409
|
+
|
|
410
|
+
// src/react/SearchItemUrlResolver.tsx
|
|
411
|
+
import { createContext as createContext2, useContext as useContext2 } from "react";
|
|
412
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
413
|
+
var NOOP_RESOLVER = () => void 0;
|
|
414
|
+
var UserUrlResolverContext = createContext2(null);
|
|
415
|
+
var DefaultUrlResolverContext = createContext2(NOOP_RESOLVER);
|
|
416
|
+
var SearchItemUrlResolverProvider = ({
|
|
417
|
+
resolver,
|
|
418
|
+
children
|
|
419
|
+
}) => /* @__PURE__ */ jsx2(UserUrlResolverContext.Provider, { value: resolver, children });
|
|
420
|
+
var SearchItemDefaultUrlResolverProvider = ({
|
|
421
|
+
resolver,
|
|
422
|
+
children
|
|
423
|
+
}) => /* @__PURE__ */ jsx2(DefaultUrlResolverContext.Provider, { value: resolver, children });
|
|
424
|
+
function useUrlResolver() {
|
|
425
|
+
const user = useContext2(UserUrlResolverContext);
|
|
426
|
+
const def = useContext2(DefaultUrlResolverContext);
|
|
427
|
+
return user != null ? user : def;
|
|
428
|
+
}
|
|
429
|
+
function resolveField(obj, path) {
|
|
430
|
+
return path.split(".").reduce((current, key) => {
|
|
431
|
+
if (current == null) {
|
|
432
|
+
return void 0;
|
|
433
|
+
}
|
|
434
|
+
if (Array.isArray(current)) {
|
|
435
|
+
current = current[0];
|
|
436
|
+
}
|
|
437
|
+
return current == null ? void 0 : current[key];
|
|
438
|
+
}, obj);
|
|
439
|
+
}
|
|
440
|
+
function createDefaultUrlResolver(configs, options = {}) {
|
|
441
|
+
const { pathsByNodeId = {}, locale } = options;
|
|
442
|
+
return (hit) => {
|
|
443
|
+
var _a;
|
|
444
|
+
const hitSource = typeof hit.source === "string" ? hit.source : "";
|
|
445
|
+
const hitType = typeof hit.type === "string" ? hit.type : "";
|
|
446
|
+
const config = configs.find((c) => c.source === hitSource && c.type === hitType);
|
|
447
|
+
if (config) {
|
|
448
|
+
const template = (_a = config.nodeId ? pathsByNodeId[config.nodeId] : void 0) != null ? _a : config.urlTemplate;
|
|
449
|
+
if (template) {
|
|
450
|
+
return template.replace(/:([a-zA-Z0-9_-]+)/g, (_, token) => {
|
|
451
|
+
var _a2, _b;
|
|
452
|
+
if (token === "locale") return locale != null ? locale : "";
|
|
453
|
+
const fieldKey = (_a2 = config.tokenMapping) == null ? void 0 : _a2[token];
|
|
454
|
+
if (!fieldKey) return "";
|
|
455
|
+
const val = resolveField(hit, fieldKey);
|
|
456
|
+
return Array.isArray(val) ? String((_b = val[0]) != null ? _b : "") : String(val != null ? val : "");
|
|
457
|
+
});
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
if (hitSource === "composition" && typeof hit.path === "string") {
|
|
461
|
+
return hit.path;
|
|
462
|
+
}
|
|
463
|
+
return void 0;
|
|
464
|
+
};
|
|
465
|
+
}
|
|
444
466
|
export {
|
|
445
467
|
DOTS,
|
|
468
|
+
SearchContext,
|
|
469
|
+
SearchItemDefaultUrlResolverProvider,
|
|
470
|
+
SearchItemUrlResolverProvider,
|
|
446
471
|
SearchProvider,
|
|
472
|
+
createDefaultUrlResolver,
|
|
447
473
|
usePagination,
|
|
448
474
|
useSearch,
|
|
449
|
-
useSearchPagination
|
|
475
|
+
useSearchPagination,
|
|
476
|
+
useUrlResolver
|
|
450
477
|
};
|
|
451
478
|
//# sourceMappingURL=react.mjs.map
|
package/dist/react.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/react/SearchProvider.tsx","../src/react/useSearch.ts","../src/react/usePagination.ts","../src/react/useSearchPagination.ts"],"sourcesContent":["import {\n createContext,\n FC,\n useMemo,\n useCallback,\n useState,\n useEffect,\n useRef,\n type ReactNode,\n} from 'react';\n\nimport {\n DEFAULT_PAGE_SIZE,\n UNIFORM_SEARCH_ORDER_BY_KEY,\n UNIFORM_SEARCH_PAGE_KEY,\n UNIFORM_SEARCH_PAGE_SIZE_KEY,\n UNIFORM_SEARCH_QUERY_KEY,\n FIRST_PAGE,\n} from '../constants';\nimport { getSearchParamsFromUrl, buildOrderByQuery } from '../utils';\nimport { flattenBlockParams } from '../flattenBlockParams';\nimport type {\n SearchCollection,\n SearchHit,\n FilterBy,\n Pagination,\n Facets,\n OrderBy,\n PageSize,\n FilterQuery,\n MultiSearchResult,\n} from '../types';\nimport type { SearchParams } from '../client';\n\nconst ALL_COLLECTIONS: SearchCollection[] = ['entries', 'compositions', 'assets'];\n\nexport interface SearchProviderProps {\n children: ReactNode;\n performSearch: (params: SearchParams) => Promise<{ results: MultiSearchResult }>;\n contentType?: string;\n filterBy?: unknown;\n orderBy?: unknown;\n baseFilters?: unknown;\n pageSizes?: unknown;\n collections?: string | string[];\n searchDebounceMs?: number;\n}\n\nexport interface UseSearchReturn {\n results: Pagination<SearchHit>;\n facets: Facets | null;\n isLoading: boolean;\n collectionResults: MultiSearchResult;\n\n searchBoxValue: string;\n setSearchQuery: (value: string) => void;\n\n page: number;\n setPage: (page: number) => void;\n pageSize: number;\n setPageSize: (size: number) => void;\n pageSizes: PageSize[];\n\n orderByOptions: Array<{ title: string; value: string }>;\n selectedOrderBy: string;\n setOrderBy: (query: string) => void;\n\n filterOptions: FilterBy[];\n selectedFilters: Record<string, string[]>;\n setSelectedFilters: (filters: Record<string, string[]>) => void;\n clearFilters: () => void;\n\n selectedCollections: SearchCollection[];\n setSelectedCollections: (collections: SearchCollection[]) => void;\n\n formatResultsSummary: (template: string) => string;\n}\n\nexport const SearchContext = createContext<UseSearchReturn | null>(null);\n\nexport const SearchProvider: FC<SearchProviderProps> = ({\n children,\n performSearch,\n contentType,\n filterBy: filterByRaw,\n orderBy: orderByRaw,\n baseFilters: baseFiltersRaw,\n pageSizes: pageSizesRaw,\n collections: collectionsRaw,\n searchDebounceMs = 300,\n}) => {\n const filterBy = useMemo(() => flattenBlockParams<FilterBy>(filterByRaw), [filterByRaw]);\n const baseFiltersFlat = useMemo(() => flattenBlockParams<FilterBy>(baseFiltersRaw), [baseFiltersRaw]);\n const orderByFlat = useMemo(() => flattenBlockParams<OrderBy>(orderByRaw), [orderByRaw]);\n const pageSizesFlat = useMemo(() => flattenBlockParams<PageSize>(pageSizesRaw), [pageSizesRaw]);\n\n const initCollections = useMemo<SearchCollection[] | undefined>(() => {\n if (!collectionsRaw) return undefined;\n const items = Array.isArray(collectionsRaw)\n ? collectionsRaw\n : collectionsRaw.split(',').map(s => s.trim());\n const valid: SearchCollection[] = items.filter(\n (c): c is SearchCollection => ['entries', 'compositions', 'assets'].includes(c)\n );\n return valid.length > 0 ? valid : undefined;\n }, [collectionsRaw]);\n\n const baseFilterQuery = useMemo(\n () =>\n baseFiltersFlat.reduce<FilterQuery>((acc, filter) => {\n if (!filter?.fieldKey || !Array.isArray(filter.values)) return acc;\n return {\n ...acc,\n [`${filter.fieldKey}[eq]`]: filter.values.map(v => v.value),\n };\n }, {}),\n [baseFiltersFlat]\n );\n\n const facetBy = useMemo(\n () =>\n filterBy\n .filter(f => f?.enableFaceting && f?.fieldKey)\n .map(f => f.fieldKey)\n .join(','),\n [filterBy]\n );\n\n const defaultOrderByQuery = useMemo(\n () => (orderByFlat[0] ? buildOrderByQuery(orderByFlat[0]) : 'created_at_DESC'),\n [orderByFlat]\n );\n\n const orderByOptions = useMemo(\n () => orderByFlat.map(o => ({ title: o.title, value: buildOrderByQuery(o) })),\n [orderByFlat]\n );\n\n const initPerPage = pageSizesFlat[0]?.size || DEFAULT_PAGE_SIZE;\n\n const hasFetchedInitial = useRef(false);\n const searchDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n\n const [selectedCollections, setSelectedCollections] = useState<SearchCollection[]>(\n initCollections || ALL_COLLECTIONS\n );\n\n const [urlParams, setUrlParams] = useState<Record<string, string | string[]>>(() => {\n if (typeof window === 'undefined') return {};\n return getSearchParamsFromUrl(window.location.href);\n });\n\n const [searchBoxValue, setSearchBoxValue] = useState(\n (urlParams?.[UNIFORM_SEARCH_QUERY_KEY] as string) || ''\n );\n const [isLoading, setIsLoading] = useState(true);\n const [entries, setEntries] = useState<Pagination<SearchHit>>({\n items: [],\n page: FIRST_PAGE,\n perPage: initPerPage,\n total: 0,\n totalPages: 0,\n });\n const [facets, setFacets] = useState<Facets>({});\n const [collectionResults, setCollectionResults] = useState<MultiSearchResult>({});\n\n const pathname = useMemo(() => {\n if (typeof window === 'undefined') return '/';\n return window.location.pathname;\n }, []);\n\n const page =\n Number(urlParams?.[UNIFORM_SEARCH_PAGE_KEY]) - 1 && Number(urlParams?.[UNIFORM_SEARCH_PAGE_KEY]) - 1 > 0\n ? Number(urlParams?.[UNIFORM_SEARCH_PAGE_KEY]) - 1\n : FIRST_PAGE;\n const search = (urlParams?.[UNIFORM_SEARCH_QUERY_KEY] as string) || '';\n const perPage = Number(urlParams?.[UNIFORM_SEARCH_PAGE_SIZE_KEY]) || initPerPage;\n\n const selectedFilters = useMemo(\n () =>\n filterBy.reduce<Record<string, string[]>>((acc, filter) => {\n const value = urlParams?.[filter.fieldId];\n if (value) {\n acc[filter.fieldKey] = Array.isArray(value) ? value : [value];\n }\n return acc;\n }, {}),\n [filterBy, urlParams]\n );\n\n useEffect(() => {\n const doFetch = async () => {\n const filterQuery = Object.entries(selectedFilters).reduce<Record<string, unknown>>((acc, [fieldKey, values]) => {\n if (!values || values.length === 0) return acc;\n const filterType = filterBy.find(f => f.fieldKey === fieldKey)?.type;\n\n if (filterType === 'range') {\n const [min, max] = values;\n return { ...acc, [`${fieldKey}[gte]`]: min, [`${fieldKey}[lte]`]: max };\n }\n\n return { ...acc, [`${fieldKey}[in]`]: values };\n }, {});\n\n const currentOrderByQuery = (urlParams?.[UNIFORM_SEARCH_ORDER_BY_KEY] as string) || defaultOrderByQuery;\n\n const filters: Record<string, unknown> = {\n ...baseFilterQuery,\n ...filterQuery,\n };\n\n if (contentType) {\n filters['contentType[eq]'] = contentType;\n }\n\n const { results } = await performSearch({\n page,\n perPage,\n filters,\n facetBy,\n search,\n orderBy: currentOrderByQuery,\n collections: selectedCollections,\n });\n\n setCollectionResults(results || {});\n\n const allItems: SearchHit[] = [];\n let totalCount = 0;\n let mergedFacets: Facets = {};\n\n for (const col of selectedCollections) {\n const colResult = results?.[col];\n if (colResult?.data?.items) {\n allItems.push(...colResult.data.items);\n totalCount += colResult.data.total || 0;\n }\n if (colResult?.facets) {\n mergedFacets = { ...mergedFacets, ...colResult.facets };\n }\n }\n\n setEntries({\n items: allItems,\n total: totalCount,\n page,\n perPage,\n totalPages: Math.ceil(totalCount / perPage),\n });\n setFacets(mergedFacets);\n };\n\n setIsLoading(true);\n doFetch()\n .catch(error => console.error('[alex] Search fetch error:', error))\n .finally(() => {\n setIsLoading(false);\n hasFetchedInitial.current = true;\n });\n }, [\n baseFilterQuery,\n contentType,\n defaultOrderByQuery,\n facetBy,\n filterBy,\n urlParams,\n page,\n perPage,\n performSearch,\n search,\n selectedCollections,\n selectedFilters,\n ]);\n\n const updateUrl = useCallback(\n (params: URLSearchParams, { replace = false }: { replace?: boolean } = {}) => {\n const qs = params.toString();\n const url = qs ? `${pathname}?${qs}` : pathname;\n if (replace) {\n window.history.replaceState({}, '', url);\n } else {\n window.history.pushState({}, '', url);\n }\n setUrlParams(getSearchParamsFromUrl(window.location.href));\n },\n [pathname]\n );\n\n const commitSearchToUrl = useCallback(\n (value: string) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n if (!value) {\n params.delete(UNIFORM_SEARCH_QUERY_KEY);\n } else {\n params.set(UNIFORM_SEARCH_QUERY_KEY, value);\n }\n updateUrl(params, { replace: true });\n },\n [updateUrl]\n );\n\n const setSearchQuery = useCallback(\n (value: string) => {\n setSearchBoxValue(value);\n if (searchDebounceRef.current) {\n clearTimeout(searchDebounceRef.current);\n }\n if (!value) {\n commitSearchToUrl(value);\n } else {\n searchDebounceRef.current = setTimeout(() => {\n commitSearchToUrl(value);\n }, searchDebounceMs);\n }\n },\n [commitSearchToUrl, searchDebounceMs]\n );\n\n useEffect(() => {\n return () => {\n if (searchDebounceRef.current) {\n clearTimeout(searchDebounceRef.current);\n }\n };\n }, []);\n\n const setPage = useCallback(\n (p: number) => {\n const params = new URLSearchParams(window.location.search);\n if (p === 0) {\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n } else {\n params.set(UNIFORM_SEARCH_PAGE_KEY, (p + 1).toString());\n }\n updateUrl(params);\n },\n [updateUrl]\n );\n\n const setPageSize = useCallback(\n (size: number) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n params.set(UNIFORM_SEARCH_PAGE_SIZE_KEY, size.toString());\n updateUrl(params);\n },\n [updateUrl]\n );\n\n const setOrderBy = useCallback(\n (orderByQuery: string) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n params.set(UNIFORM_SEARCH_ORDER_BY_KEY, orderByQuery);\n updateUrl(params);\n },\n [updateUrl]\n );\n\n const setSelectedFilters = useCallback(\n (nextSelected: Record<string, string[]>) => {\n const params = new URLSearchParams();\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n if (search) {\n params.set(UNIFORM_SEARCH_QUERY_KEY, search);\n }\n Object.entries(nextSelected).forEach(([key, value]) => {\n const filter = filterBy.find(f => f.fieldKey === key);\n if (!filter) return;\n value.forEach(v => {\n params.append(filter.fieldId, v);\n });\n });\n updateUrl(params);\n },\n [filterBy, search, updateUrl]\n );\n\n const clearFilters = useCallback(() => {\n setIsLoading(true);\n setSearchBoxValue('');\n if (searchDebounceRef.current) {\n clearTimeout(searchDebounceRef.current);\n }\n window.history.pushState({}, '', pathname);\n setUrlParams(getSearchParamsFromUrl(window.location.href));\n }, [pathname]);\n\n const formatResultsSummary = useCallback(\n (template: string) => {\n if (!template) return '';\n const vars: Record<string, number | undefined> = {\n page: entries.page,\n perPage: entries.perPage,\n totalItems: entries.total,\n totalPages: entries.totalPages,\n };\n return template.replace(/{(\\w+)}/g, (match, key) => {\n const val = vars[key];\n return val != null ? String(val) : match;\n });\n },\n [entries]\n );\n\n const value: UseSearchReturn = useMemo(\n () => ({\n results: entries,\n facets,\n isLoading,\n collectionResults,\n\n searchBoxValue,\n setSearchQuery,\n\n page,\n setPage,\n pageSize: perPage,\n setPageSize,\n pageSizes: pageSizesFlat,\n\n orderByOptions,\n selectedOrderBy: (urlParams?.[UNIFORM_SEARCH_ORDER_BY_KEY] as string) || defaultOrderByQuery,\n setOrderBy,\n\n filterOptions: filterBy,\n selectedFilters,\n setSelectedFilters,\n clearFilters,\n\n selectedCollections,\n setSelectedCollections,\n\n formatResultsSummary,\n }),\n [\n clearFilters,\n collectionResults,\n defaultOrderByQuery,\n entries,\n facets,\n filterBy,\n formatResultsSummary,\n isLoading,\n orderByOptions,\n page,\n pageSizesFlat,\n perPage,\n searchBoxValue,\n selectedCollections,\n selectedFilters,\n setOrderBy,\n setPage,\n setPageSize,\n setSearchQuery,\n setSelectedFilters,\n urlParams,\n ]\n );\n\n return <SearchContext.Provider value={value}>{children}</SearchContext.Provider>;\n};\n","import { useContext } from 'react';\nimport { SearchContext } from './SearchProvider';\nimport type { UseSearchReturn } from './SearchProvider';\n\nexport function useSearch(): UseSearchReturn {\n const context = useContext(SearchContext);\n if (!context) {\n throw new Error('useSearch must be used within a <SearchProvider>');\n }\n return context;\n}\n","import { useMemo } from 'react';\n\nexport const DOTS = '...';\n\ninterface UsePaginationParams {\n currentPage: number;\n totalCount: number;\n perPage: number;\n siblingCount?: number;\n}\n\nconst range = (start: number, end: number) => {\n const length = end - start + 1;\n return Array.from({ length }, (_, idx) => idx + start);\n};\n\nexport const usePagination = ({ totalCount, perPage, siblingCount = 1, currentPage }: UsePaginationParams) =>\n useMemo(() => {\n const totalPageCount = Math.ceil(totalCount / perPage);\n const totalPageNumbers = siblingCount + 5;\n\n if (totalPageNumbers >= totalPageCount) {\n return range(1, totalPageCount);\n }\n\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);\n const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPageCount);\n\n const shouldShowLeftDots = leftSiblingIndex > 2;\n const shouldShowRightDots = rightSiblingIndex < totalPageCount - 2;\n\n const firstPageIndex = 1;\n const lastPageIndex = totalPageCount;\n\n if (!shouldShowLeftDots && shouldShowRightDots) {\n const leftItemCount = 2 + 2 * siblingCount;\n const leftRange = range(1, leftItemCount);\n return [...leftRange, DOTS, totalPageCount];\n }\n\n if (shouldShowLeftDots && !shouldShowRightDots) {\n const rightItemCount = 2 + 2 * siblingCount;\n const rightRange = range(totalPageCount - rightItemCount + 1, totalPageCount);\n return [firstPageIndex, DOTS, ...rightRange];\n }\n\n if (shouldShowLeftDots && shouldShowRightDots) {\n const middleRange = range(leftSiblingIndex, rightSiblingIndex);\n return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex];\n }\n }, [totalCount, perPage, siblingCount, currentPage]);\n","import { useMemo, useCallback } from 'react';\nimport { useSearch } from './useSearch';\nimport { usePagination, DOTS } from './usePagination';\n\nexport interface UseSearchPaginationReturn {\n pages: (number | string)[];\n currentPage: number;\n hasPrev: boolean;\n hasNext: boolean;\n goToPage: (page: number) => void;\n goToPrev: () => void;\n goToNext: () => void;\n isLoading: boolean;\n}\n\nexport function useSearchPagination(siblingCount?: number): UseSearchPaginationReturn {\n const { page, pageSize, results, setPage, isLoading } = useSearch();\n\n const pages = usePagination({\n currentPage: page,\n totalCount: results.total,\n perPage: pageSize,\n siblingCount,\n }) || [];\n\n const lastPage = useMemo(\n () => Number(pages[pages.length - 1]) || 0,\n [pages]\n );\n\n const goToPage = useCallback(\n (p: number) => { if (!isLoading) setPage(p); },\n [isLoading, setPage]\n );\n\n const goToPrev = useCallback(\n () => { if (page > 0 && !isLoading) setPage(page - 1); },\n [page, isLoading, setPage]\n );\n\n const goToNext = useCallback(\n () => { if (page < lastPage && !isLoading) setPage(page + 1); },\n [page, lastPage, isLoading, setPage]\n );\n\n return {\n pages,\n currentPage: page,\n hasPrev: page > 0,\n hasNext: page < lastPage,\n goToPage,\n goToPrev,\n goToNext,\n isLoading,\n };\n}\n\nexport { DOTS };\n"],"mappings":"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","names":["value","_a","useMemo","useMemo","useCallback","useMemo","useCallback"]}
|
|
1
|
+
{"version":3,"sources":["../src/react/SearchProvider.tsx","../src/react/useSearch.ts","../src/react/usePagination.ts","../src/react/useSearchPagination.ts","../src/react/SearchItemUrlResolver.tsx"],"sourcesContent":["import { createContext, FC, useMemo, useCallback, useState, useEffect, useRef, type ReactNode } from 'react';\n\nimport {\n DEFAULT_PAGE_SIZE,\n UNIFORM_SEARCH_ORDER_BY_KEY,\n UNIFORM_SEARCH_PAGE_KEY,\n UNIFORM_SEARCH_PAGE_SIZE_KEY,\n UNIFORM_SEARCH_QUERY_KEY,\n FIRST_PAGE,\n} from '../constants';\nimport { getSearchParamsFromUrl, buildOrderByQuery } from '../utils';\nimport { flattenBlockParams } from '../flattenBlockParams';\nimport type {\n SearchHit,\n FacetBy,\n FilterByItem,\n Pagination,\n Facets,\n OrderBy,\n PageSize,\n FilterQuery,\n CollectionResult,\n} from '../types';\nimport type { SearchParams } from '../client';\n\nexport interface SearchProviderProps {\n children: ReactNode;\n performSearch: (params: SearchParams) => Promise<CollectionResult>;\n orderBy?: unknown;\n baseFilterString?: string;\n pageSizes?: unknown;\n queryBy?: string[];\n searchDebounceMs?: number;\n locale?: string;\n maxFacetValues?: number;\n}\n\nexport interface UseSearchReturn {\n results: Pagination<SearchHit>;\n facets: Facets | null;\n isLoading: boolean;\n\n searchBoxValue: string;\n setSearchQuery: (value: string) => void;\n\n page: number;\n setPage: (page: number) => void;\n pageSize: number;\n setPageSize: (size: number) => void;\n pageSizes: PageSize[];\n\n orderByOptions: Array<{ title: string; value: string }>;\n selectedOrderBy: string;\n setOrderBy: (query: string) => void;\n\n filterOptions: FacetBy[];\n setFilterOptions: (filters: FacetBy[]) => void;\n /** Additive registration of a single facet option (keyed by fieldKey). Used by facet\n * components that mount independently (e.g. App Router slots) rather than being\n * enumerated by a parent. */\n registerFilterOption: (filter: FacetBy) => void;\n unregisterFilterOption: (fieldKey: string) => void;\n selectedFilters: Record<string, string[]>;\n setSelectedFilters: (filters: Record<string, string[]>) => void;\n clearFilters: () => void;\n\n formatResultsSummary: (template: string) => string;\n}\n\nexport const SearchContext = createContext<UseSearchReturn | null>(null);\n\nexport const SearchProvider: FC<SearchProviderProps> = ({\n children,\n performSearch,\n orderBy: orderByRaw,\n baseFilterString,\n pageSizes: pageSizesRaw,\n queryBy,\n searchDebounceMs = 300,\n locale,\n maxFacetValues = 100,\n}) => {\n const [filterBy, setFilterOptions] = useState<FacetBy[]>([]);\n\n const registerFilterOption = useCallback((filter: FacetBy) => {\n if (!filter?.fieldKey) return;\n setFilterOptions((prev) => [...prev.filter((f) => f.fieldKey !== filter.fieldKey), filter]);\n }, []);\n\n const unregisterFilterOption = useCallback((fieldKey: string) => {\n setFilterOptions((prev) => prev.filter((f) => f.fieldKey !== fieldKey));\n }, []);\n\n const orderByFlat = useMemo(() => flattenBlockParams<OrderBy>(orderByRaw), [orderByRaw]);\n const pageSizesFlat = useMemo(() => flattenBlockParams<PageSize>(pageSizesRaw), [pageSizesRaw]);\n\n const facetBy = useMemo(\n () =>\n filterBy\n .filter((f) => f?.fieldKey)\n .map((f) => f.fieldKey)\n .join(','),\n [filterBy]\n );\n\n const defaultOrderByQuery = useMemo(\n () => (orderByFlat[0] ? buildOrderByQuery(orderByFlat[0]) : 'created_at_DESC'),\n [orderByFlat]\n );\n\n const orderByOptions = useMemo(\n () => orderByFlat.map((o) => ({ title: o.title, value: buildOrderByQuery(o) })),\n [orderByFlat]\n );\n\n const initPerPage = pageSizesFlat[0]?.size || DEFAULT_PAGE_SIZE;\n\n const searchDebounceRef = useRef<ReturnType<typeof setTimeout> | null>(null);\n const searchRequestIdRef = useRef(0);\n\n const [urlParams, setUrlParams] = useState<Record<string, string | string[]>>(() => {\n if (typeof window === 'undefined') return {};\n return getSearchParamsFromUrl(window.location.href);\n });\n\n const [searchBoxValue, setSearchBoxValue] = useState((urlParams?.[UNIFORM_SEARCH_QUERY_KEY] as string) || '');\n const [isLoading, setIsLoading] = useState(true);\n const [entries, setEntries] = useState<Pagination<SearchHit>>({\n items: [],\n page: FIRST_PAGE,\n perPage: initPerPage,\n total: 0,\n totalPages: 0,\n });\n const [facets, setFacets] = useState<Facets>({});\n\n const pathname = useMemo(() => {\n if (typeof window === 'undefined') return '/';\n return window.location.pathname;\n }, []);\n\n const page =\n Number(urlParams?.[UNIFORM_SEARCH_PAGE_KEY]) - 1 > 0\n ? Number(urlParams?.[UNIFORM_SEARCH_PAGE_KEY]) - 1\n : FIRST_PAGE;\n const search = (urlParams?.[UNIFORM_SEARCH_QUERY_KEY] as string) || '';\n const perPage = Number(urlParams?.[UNIFORM_SEARCH_PAGE_SIZE_KEY]) || initPerPage;\n\n const selectedFilters = useMemo(\n () =>\n filterBy.reduce<Record<string, string[]>>((acc, filter) => {\n const value = urlParams?.[filter.fieldKey];\n if (value) {\n acc[filter.fieldKey] = Array.isArray(value) ? value : [value];\n }\n return acc;\n }, {}),\n [filterBy, urlParams]\n );\n\n useEffect(() => {\n const requestId = ++searchRequestIdRef.current;\n\n const doFetch = async () => {\n const currentOrderByQuery = (urlParams?.[UNIFORM_SEARCH_ORDER_BY_KEY] as string) || defaultOrderByQuery;\n\n const buildFilters = (excludeField?: string) =>\n Object.entries(selectedFilters).reduce<Record<string, unknown>>((acc, [fieldKey, values]) => {\n if (excludeField && fieldKey === excludeField) return acc;\n if (!values || values.length === 0) return acc;\n const filterType = filterBy.find((f) => f.fieldKey === fieldKey)?.type;\n if (filterType === 'range') {\n const [min, max] = values;\n return { ...acc, [`${fieldKey}[gte]`]: min, [`${fieldKey}[lte]`]: max };\n }\n return { ...acc, [`${fieldKey}[in]`]: values };\n }, {});\n\n // Fields that have active selections need disjunctive queries so their\n // option lists stay complete (user can add more values via OR logic).\n const selectedFacetFields = Object.keys(selectedFilters).filter((k) => selectedFilters[k]?.length > 0);\n const queryByString = queryBy?.length ? queryBy.join(',') : undefined;\n const [mainResult, ...disjunctiveResults] = await Promise.all([\n performSearch({\n page,\n perPage,\n filters: buildFilters(),\n baseFilterBy: baseFilterString,\n facetBy,\n queryBy: queryByString,\n search,\n orderBy: currentOrderByQuery,\n locale,\n maxFacetValues,\n }),\n ...selectedFacetFields.map((field) =>\n performSearch({\n page: 0,\n perPage: 0,\n filters: buildFilters(field),\n baseFilterBy: baseFilterString,\n facetBy: field,\n queryBy: queryByString,\n search,\n orderBy: currentOrderByQuery,\n locale,\n maxFacetValues,\n })\n ),\n ]);\n\n if (requestId !== searchRequestIdRef.current) return;\n\n // Replace main facet counts for selected fields with their disjunctive counts.\n const mergedFacets = { ...(mainResult.facets ?? {}) };\n selectedFacetFields.forEach((field, i) => {\n const counts = disjunctiveResults[i]?.facets?.[field];\n if (counts) mergedFacets[field] = counts;\n });\n\n setEntries(mainResult.data ?? { items: [], total: 0, page, perPage, totalPages: 0 });\n setFacets(mergedFacets);\n };\n\n setIsLoading(true);\n doFetch()\n .catch((error) => console.error('[alex] Search fetch error:', error))\n .finally(() => setIsLoading(false));\n }, [\n baseFilterString,\n defaultOrderByQuery,\n facetBy,\n filterBy,\n locale,\n urlParams,\n page,\n perPage,\n performSearch,\n search,\n selectedFilters,\n ]);\n\n useEffect(() => {\n return () => {\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n };\n }, []);\n\n const updateUrl = useCallback(\n (params: URLSearchParams, { replace = false }: { replace?: boolean } = {}) => {\n const qs = params.toString();\n const url = qs ? `${pathname}?${qs}` : pathname;\n if (replace) {\n window.history.replaceState({}, '', url);\n } else {\n window.history.pushState({}, '', url);\n }\n setUrlParams(getSearchParamsFromUrl(window.location.href));\n },\n [pathname]\n );\n\n const commitSearchToUrl = useCallback(\n (value: string) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n if (!value) {\n params.delete(UNIFORM_SEARCH_QUERY_KEY);\n } else {\n params.set(UNIFORM_SEARCH_QUERY_KEY, value);\n }\n updateUrl(params, { replace: true });\n },\n [updateUrl]\n );\n\n const setSearchQuery = useCallback(\n (value: string) => {\n setSearchBoxValue(value);\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n if (!value) {\n commitSearchToUrl(value);\n } else {\n searchDebounceRef.current = setTimeout(() => commitSearchToUrl(value), searchDebounceMs);\n }\n },\n [commitSearchToUrl, searchDebounceMs]\n );\n\n const setPage = useCallback(\n (p: number) => {\n const params = new URLSearchParams(window.location.search);\n if (p === 0) {\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n } else {\n params.set(UNIFORM_SEARCH_PAGE_KEY, (p + 1).toString());\n }\n updateUrl(params);\n },\n [updateUrl]\n );\n\n const setPageSize = useCallback(\n (size: number) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n params.set(UNIFORM_SEARCH_PAGE_SIZE_KEY, size.toString());\n updateUrl(params);\n },\n [updateUrl]\n );\n\n const setOrderBy = useCallback(\n (orderByQuery: string) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n params.set(UNIFORM_SEARCH_ORDER_BY_KEY, orderByQuery);\n updateUrl(params);\n },\n [updateUrl]\n );\n\n const setSelectedFilters = useCallback(\n (nextSelected: Record<string, string[]>) => {\n const params = new URLSearchParams(window.location.search);\n params.delete(UNIFORM_SEARCH_PAGE_KEY);\n filterBy.forEach((f) => params.delete(f.fieldKey));\n Object.entries(nextSelected).forEach(([key, value]) => {\n const filter = filterBy.find((f) => f.fieldKey === key);\n if (!filter) return;\n value.forEach((v) => params.append(key, v));\n });\n updateUrl(params);\n },\n [filterBy, updateUrl]\n );\n\n const clearFilters = useCallback(() => {\n setIsLoading(true);\n setSearchBoxValue('');\n if (searchDebounceRef.current) clearTimeout(searchDebounceRef.current);\n window.history.pushState({}, '', pathname);\n setUrlParams(getSearchParamsFromUrl(window.location.href));\n }, [pathname]);\n\n const formatResultsSummary = useCallback(\n (template: string) => {\n if (!template) return '';\n const vars: Record<string, number | undefined> = {\n page: entries.page,\n perPage: entries.perPage,\n totalItems: entries.total,\n totalPages: entries.totalPages,\n };\n return template.replace(/{(\\w+)}/g, (match, key) => {\n const val = vars[key];\n return val != null ? String(val) : match;\n });\n },\n [entries]\n );\n\n const value: UseSearchReturn = useMemo(\n () => ({\n results: entries,\n facets,\n isLoading,\n\n searchBoxValue,\n setSearchQuery,\n\n page,\n setPage,\n pageSize: perPage,\n setPageSize,\n pageSizes: pageSizesFlat,\n\n orderByOptions,\n selectedOrderBy: (urlParams?.[UNIFORM_SEARCH_ORDER_BY_KEY] as string) || defaultOrderByQuery,\n setOrderBy,\n\n filterOptions: filterBy,\n setFilterOptions,\n registerFilterOption,\n unregisterFilterOption,\n selectedFilters,\n setSelectedFilters,\n clearFilters,\n\n formatResultsSummary,\n }),\n [\n clearFilters,\n defaultOrderByQuery,\n entries,\n facets,\n filterBy,\n setFilterOptions,\n registerFilterOption,\n unregisterFilterOption,\n formatResultsSummary,\n isLoading,\n orderByOptions,\n page,\n pageSizesFlat,\n perPage,\n searchBoxValue,\n selectedFilters,\n setOrderBy,\n setPage,\n setPageSize,\n setSearchQuery,\n setSelectedFilters,\n urlParams,\n ]\n );\n\n return <SearchContext.Provider value={value}>{children}</SearchContext.Provider>;\n};\n","import { useContext } from 'react';\nimport { SearchContext } from './SearchProvider';\nimport type { UseSearchReturn } from './SearchProvider';\n\nexport function useSearch(): UseSearchReturn {\n const context = useContext(SearchContext);\n if (!context) {\n throw new Error('useSearch must be used within a <SearchProvider>');\n }\n return context;\n}\n","import { useMemo } from 'react';\n\nexport const DOTS = '...';\n\ninterface UsePaginationParams {\n currentPage: number;\n totalCount: number;\n perPage: number;\n siblingCount?: number;\n}\n\nconst range = (start: number, end: number) => {\n const length = end - start + 1;\n return Array.from({ length }, (_, idx) => idx + start);\n};\n\nexport const usePagination = ({ totalCount, perPage, siblingCount = 1, currentPage }: UsePaginationParams) =>\n useMemo(() => {\n const totalPageCount = Math.ceil(totalCount / perPage);\n const totalPageNumbers = siblingCount + 5;\n\n if (totalPageNumbers >= totalPageCount) {\n return range(1, totalPageCount);\n }\n\n const leftSiblingIndex = Math.max(currentPage - siblingCount, 1);\n const rightSiblingIndex = Math.min(currentPage + siblingCount, totalPageCount);\n\n const shouldShowLeftDots = leftSiblingIndex > 2;\n const shouldShowRightDots = rightSiblingIndex < totalPageCount - 2;\n\n const firstPageIndex = 1;\n const lastPageIndex = totalPageCount;\n\n if (!shouldShowLeftDots && shouldShowRightDots) {\n const leftItemCount = 2 + 2 * siblingCount;\n const leftRange = range(1, leftItemCount);\n return [...leftRange, DOTS, totalPageCount];\n }\n\n if (shouldShowLeftDots && !shouldShowRightDots) {\n const rightItemCount = 2 + 2 * siblingCount;\n const rightRange = range(totalPageCount - rightItemCount + 1, totalPageCount);\n return [firstPageIndex, DOTS, ...rightRange];\n }\n\n if (shouldShowLeftDots && shouldShowRightDots) {\n const middleRange = range(leftSiblingIndex, rightSiblingIndex);\n return [firstPageIndex, DOTS, ...middleRange, DOTS, lastPageIndex];\n }\n }, [totalCount, perPage, siblingCount, currentPage]);\n","import { useMemo, useCallback } from 'react';\nimport { useSearch } from './useSearch';\nimport { usePagination, DOTS } from './usePagination';\n\nexport interface UseSearchPaginationReturn {\n pages: (number | string)[];\n currentPage: number;\n hasPrev: boolean;\n hasNext: boolean;\n goToPage: (page: number) => void;\n goToPrev: () => void;\n goToNext: () => void;\n isLoading: boolean;\n}\n\nexport function useSearchPagination(siblingCount?: number): UseSearchPaginationReturn {\n const { page, pageSize, results, setPage, isLoading } = useSearch();\n\n const pages = usePagination({\n currentPage: page,\n totalCount: results.total,\n perPage: pageSize,\n siblingCount,\n }) || [];\n\n const lastPage = useMemo(\n () => Number(pages[pages.length - 1]) || 0,\n [pages]\n );\n\n const goToPage = useCallback(\n (p: number) => { if (!isLoading) setPage(p); },\n [isLoading, setPage]\n );\n\n const goToPrev = useCallback(\n () => { if (page > 0 && !isLoading) setPage(page - 1); },\n [page, isLoading, setPage]\n );\n\n const goToNext = useCallback(\n () => { if (page < lastPage && !isLoading) setPage(page + 1); },\n [page, lastPage, isLoading, setPage]\n );\n\n return {\n pages,\n currentPage: page,\n hasPrev: page > 0,\n hasNext: page < lastPage,\n goToPage,\n goToPrev,\n goToNext,\n isLoading,\n };\n}\n\nexport { DOTS };\n","import { createContext, useContext, type FC, type ReactNode } from 'react';\nimport type { SearchHit, SearchItemConfig } from '../types';\n\nexport type UrlResolver = (hit: SearchHit) => string | undefined;\n\nconst NOOP_RESOLVER: UrlResolver = () => undefined;\n\n// Set by the user to override URL resolution for the entire subtree.\nconst UserUrlResolverContext = createContext<UrlResolver | null>(null);\n\n// Set by SearchList to provide config-driven defaults within its subtree.\nconst DefaultUrlResolverContext = createContext<UrlResolver>(NOOP_RESOLVER);\n\n/** Wrap your search tree to override URL building for all hits. */\nexport const SearchItemUrlResolverProvider: FC<{ resolver: UrlResolver; children: ReactNode }> = ({\n resolver,\n children,\n}) => (\n <UserUrlResolverContext.Provider value={resolver}>\n {children}\n </UserUrlResolverContext.Provider>\n);\n\n/** Used internally by SearchList to register the Canvas-config-driven default. */\nexport const SearchItemDefaultUrlResolverProvider: FC<{ resolver: UrlResolver; children: ReactNode }> = ({\n resolver,\n children,\n}) => (\n <DefaultUrlResolverContext.Provider value={resolver}>\n {children}\n </DefaultUrlResolverContext.Provider>\n);\n\n/**\n * Always returns a resolver. User-provided resolver (SearchItemUrlResolverProvider)\n * takes priority over the default registered by SearchList.\n */\nexport function useUrlResolver(): UrlResolver {\n const user = useContext(UserUrlResolverContext);\n const def = useContext(DefaultUrlResolverContext);\n return user ?? def;\n}\n\nexport interface UrlResolverOptions {\n /** nodeId → resolved locale-specific path (from project map). */\n pathsByNodeId?: Record<string, string>;\n /** Current locale, used as fallback for legacy :locale token in urlTemplate. */\n locale?: string;\n}\n\n/**\n * Builds the default URL resolver from Canvas SearchItem configs.\n * Exported so custom resolvers can compose with it.\n */\nfunction resolveField<T = unknown>(obj: SearchHit, path: string): T | undefined {\n return path\n .split(\".\")\n .reduce<any>((current, key) => {\n if (current == null) {\n return undefined;\n }\n\n // If current value is an array, use first item\n if (Array.isArray(current)) {\n current = current[0];\n }\n\n return current?.[key];\n }, obj);\n\n}\n\nexport function createDefaultUrlResolver(\n configs: SearchItemConfig[],\n options: UrlResolverOptions = {}\n): UrlResolver {\n const { pathsByNodeId = {}, locale } = options;\n\n return (hit: SearchHit): string | undefined => {\n const hitSource = typeof hit.source === 'string' ? hit.source : '';\n const hitType = typeof hit.type === 'string' ? hit.type : '';\n const config = configs.find(c => c.source === hitSource && c.type === hitType);\n if (config) {\n const template =\n (config.nodeId ? pathsByNodeId[config.nodeId] : undefined) ?? config.urlTemplate;\n\n if (template) {\n return template.replace(/:([a-zA-Z0-9_-]+)/g, (_, token) => {\n if (token === 'locale') return locale ?? '';\n const fieldKey = config.tokenMapping?.[token];\n if (!fieldKey) return '';\n const val = resolveField(hit, fieldKey);\n return Array.isArray(val) ? String(val[0] ?? '') : String(val ?? '');\n });\n }\n }\n\n if (hitSource === 'composition' && typeof hit.path === 'string') {\n return hit.path;\n }\n\n return undefined;\n };\n}\n"],"mappings":"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","names":["value","_a","_b","useMemo","useMemo","useCallback","useMemo","useCallback","createContext","useContext","jsx","_a"]}
|
package/package.json
CHANGED
|
@@ -1,7 +1,28 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uniformdev/search",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.2",
|
|
4
4
|
"description": "Uniform Search client with optional React bindings",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Uniform Systems, Inc.",
|
|
7
|
+
"homepage": "https://github.com/uniform-collab/search-starter/tree/main/packages/search#readme",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "git+https://github.com/uniform-collab/search-starter.git",
|
|
11
|
+
"directory": "packages/search"
|
|
12
|
+
},
|
|
13
|
+
"bugs": {
|
|
14
|
+
"url": "https://github.com/uniform-collab/search-starter/issues"
|
|
15
|
+
},
|
|
16
|
+
"keywords": [
|
|
17
|
+
"uniform",
|
|
18
|
+
"uniformdev",
|
|
19
|
+
"search",
|
|
20
|
+
"faceted-search",
|
|
21
|
+
"typesense",
|
|
22
|
+
"react",
|
|
23
|
+
"headless-cms"
|
|
24
|
+
],
|
|
25
|
+
"sideEffects": false,
|
|
5
26
|
"main": "dist/index.js",
|
|
6
27
|
"module": "dist/index.mjs",
|
|
7
28
|
"types": "dist/index.d.ts",
|
|
@@ -39,7 +60,7 @@
|
|
|
39
60
|
"devDependencies": {
|
|
40
61
|
"@types/react": "^19.2.3",
|
|
41
62
|
"react": "^19.2.3",
|
|
42
|
-
"tsup": "^8.
|
|
63
|
+
"tsup": "^8.5.1",
|
|
43
64
|
"typescript": "^5"
|
|
44
65
|
}
|
|
45
66
|
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/constants.ts","../src/utils.ts","../src/flattenBlockParams.ts"],"sourcesContent":["export const UNIFORM_SEARCH_QUERY_KEY = 'search';\nexport const UNIFORM_SEARCH_PAGE_KEY = 'page';\nexport const UNIFORM_SEARCH_PAGE_SIZE_KEY = 'pageSize';\nexport const UNIFORM_SEARCH_ORDER_BY_KEY = 'orderBy';\nexport const FIRST_PAGE = 0;\nexport const DEFAULT_PAGE_SIZE = 10;\n","import type { OrderBy } from './types';\n\nexport const buildOrderByQuery = (orderBy: OrderBy) => {\n return `${orderBy.field}_${orderBy.direction}`;\n};\n\nexport const getSearchParamsFromUrl = (urlString: string): Record<string, string | string[]> => {\n if (!urlString) {\n return {};\n }\n\n const url = new URL(urlString);\n const params: Record<string, string | string[]> = {};\n\n url.searchParams.forEach((value, key) => {\n if (params[key]) {\n params[key] = Array.isArray(params[key])\n ? [...(params[key] as string[]), value]\n : [params[key] as string, value];\n } else {\n params[key] = value;\n }\n });\n\n return params;\n};\n","type RawField = {\n type?: string;\n value?: unknown;\n locales?: Record<string, unknown>;\n};\n\ntype RawBlockItem = {\n type?: string;\n fields?: Record<string, RawField>;\n};\n\nfunction resolveFieldValue(field: RawField, locale = 'en-us'): unknown {\n if (!field || typeof field !== 'object') return field;\n\n if (field.type === '$block' && Array.isArray(field.value)) {\n return flattenBlockParams(field.value as RawBlockItem[], locale);\n }\n\n if (field.locales && typeof field.locales === 'object') {\n return field.locales[locale] ?? Object.values(field.locales)[0] ?? field.value;\n }\n\n return field.value;\n}\n\nexport function flattenBlockParams<T = Record<string, unknown>>(\n items: unknown,\n locale = 'en-us'\n): T[] {\n if (!Array.isArray(items)) return [];\n return items.map(item => {\n const result: Record<string, unknown> = {};\n const blockItem = item as RawBlockItem;\n if (blockItem.fields) {\n for (const [key, field] of Object.entries(blockItem.fields)) {\n result[key] = resolveFieldValue(field, locale);\n }\n }\n return result as T;\n });\n}\n"],"mappings":";AAAO,IAAM,2BAA2B;AACjC,IAAM,0BAA0B;AAChC,IAAM,+BAA+B;AACrC,IAAM,8BAA8B;AACpC,IAAM,aAAa;AACnB,IAAM,oBAAoB;;;ACH1B,IAAM,oBAAoB,CAAC,YAAqB;AACrD,SAAO,GAAG,QAAQ,KAAK,IAAI,QAAQ,SAAS;AAC9C;AAEO,IAAM,yBAAyB,CAAC,cAAyD;AAC9F,MAAI,CAAC,WAAW;AACd,WAAO,CAAC;AAAA,EACV;AAEA,QAAM,MAAM,IAAI,IAAI,SAAS;AAC7B,QAAM,SAA4C,CAAC;AAEnD,MAAI,aAAa,QAAQ,CAAC,OAAO,QAAQ;AACvC,QAAI,OAAO,GAAG,GAAG;AACf,aAAO,GAAG,IAAI,MAAM,QAAQ,OAAO,GAAG,CAAC,IACnC,CAAC,GAAI,OAAO,GAAG,GAAgB,KAAK,IACpC,CAAC,OAAO,GAAG,GAAa,KAAK;AAAA,IACnC,OAAO;AACL,aAAO,GAAG,IAAI;AAAA,IAChB;AAAA,EACF,CAAC;AAED,SAAO;AACT;;;ACdA,SAAS,kBAAkB,OAAiB,SAAS,SAAkB;AAXvE;AAYE,MAAI,CAAC,SAAS,OAAO,UAAU,SAAU,QAAO;AAEhD,MAAI,MAAM,SAAS,YAAY,MAAM,QAAQ,MAAM,KAAK,GAAG;AACzD,WAAO,mBAAmB,MAAM,OAAyB,MAAM;AAAA,EACjE;AAEA,MAAI,MAAM,WAAW,OAAO,MAAM,YAAY,UAAU;AACtD,YAAO,iBAAM,QAAQ,MAAM,MAApB,YAAyB,OAAO,OAAO,MAAM,OAAO,EAAE,CAAC,MAAvD,YAA4D,MAAM;AAAA,EAC3E;AAEA,SAAO,MAAM;AACf;AAEO,SAAS,mBACd,OACA,SAAS,SACJ;AACL,MAAI,CAAC,MAAM,QAAQ,KAAK,EAAG,QAAO,CAAC;AACnC,SAAO,MAAM,IAAI,UAAQ;AACvB,UAAM,SAAkC,CAAC;AACzC,UAAM,YAAY;AAClB,QAAI,UAAU,QAAQ;AACpB,iBAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,UAAU,MAAM,GAAG;AAC3D,eAAO,GAAG,IAAI,kBAAkB,OAAO,MAAM;AAAA,MAC/C;AAAA,IACF;AACA,WAAO;AAAA,EACT,CAAC;AACH;","names":[]}
|