@sitecore-content-sdk/react 1.3.0-canary.31 → 1.3.0-canary.35

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.
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useInfiniteSearch = exports.useSearch = void 0;
4
+ var useSearch_1 = require("./useSearch");
5
+ Object.defineProperty(exports, "useSearch", { enumerable: true, get: function () { return useSearch_1.useSearch; } });
6
+ var useInfiniteSearch_1 = require("./useInfiniteSearch");
7
+ Object.defineProperty(exports, "useInfiniteSearch", { enumerable: true, get: function () { return useInfiniteSearch_1.useInfiniteSearch; } });
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useInfiniteSearch = void 0;
4
+ /* eslint-disable no-unused-vars */
5
+ const react_1 = require("react");
6
+ const utils_1 = require("./utils");
7
+ /**
8
+ * React hook for performing infinite search queries.
9
+ * @param {UseInfiniteSearchOptions} options - Configuration options for the infinite search hook.
10
+ * @returns {UseInfiniteSearchState} The infinite search state.
11
+ * @throws {Error} if the search index ID is not provided.
12
+ * @public
13
+ */
14
+ const useInfiniteSearch = (options) => {
15
+ const { query, searchIndexId, pageSize = utils_1.DEFAULT_PAGE_SIZE, sort, enabled = true } = options;
16
+ const [state, setState] = (0, react_1.useState)(() => {
17
+ const error = !searchIndexId
18
+ ? new Error('useInfiniteSearch: searchIndexId is required when initializing the hook')
19
+ : null;
20
+ const status = !searchIndexId ? 'error' : 'idle';
21
+ return {
22
+ results: [],
23
+ total: 0,
24
+ totalPages: 0,
25
+ error,
26
+ offset: 0,
27
+ status,
28
+ loadMoreStatus: 'idle',
29
+ };
30
+ });
31
+ const hasNextPage = (0, react_1.useMemo)(() => state.results.length < state.total, [state.results.length, state.total]);
32
+ const searchService = (0, utils_1.useSearchService)();
33
+ const abortControllerRef = (0, react_1.useRef)(null);
34
+ const search = (0, react_1.useCallback)(async (offset, isLoadingMore = false) => {
35
+ if (!searchService || !searchIndexId) {
36
+ return;
37
+ }
38
+ abortControllerRef.current = new AbortController();
39
+ const signal = abortControllerRef.current.signal;
40
+ if (isLoadingMore) {
41
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, loadMoreStatus: 'loading' })));
42
+ }
43
+ else {
44
+ setState({
45
+ results: [],
46
+ total: 0,
47
+ totalPages: 0,
48
+ error: null,
49
+ offset: 0,
50
+ status: 'loading',
51
+ loadMoreStatus: 'idle',
52
+ });
53
+ }
54
+ try {
55
+ const searchParams = {
56
+ searchIndexId,
57
+ keyphrase: query,
58
+ limit: pageSize,
59
+ offset,
60
+ sort,
61
+ };
62
+ const { results: searchResults, total: totalResults } = await searchService.search(searchParams, { signal });
63
+ if (signal.aborted) {
64
+ return;
65
+ }
66
+ setState((prev) => {
67
+ const results = isLoadingMore ? [...prev.results, ...searchResults] : searchResults;
68
+ const totalPages = Math.ceil(totalResults / pageSize);
69
+ return {
70
+ results,
71
+ error: null,
72
+ offset,
73
+ status: 'success',
74
+ loadMoreStatus: 'idle',
75
+ total: totalResults,
76
+ totalPages,
77
+ };
78
+ });
79
+ }
80
+ catch (err) {
81
+ // Don't set error if request was aborted
82
+ if (signal.aborted) {
83
+ return;
84
+ }
85
+ const errorMessage = err instanceof Error ? err : new Error(JSON.stringify(err));
86
+ // Don't clean up existing results if appending results
87
+ if (isLoadingMore) {
88
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, loadMoreStatus: 'error' })));
89
+ }
90
+ else {
91
+ setState({
92
+ results: [],
93
+ total: 0,
94
+ totalPages: 0,
95
+ error: errorMessage,
96
+ offset: 0,
97
+ status: 'error',
98
+ loadMoreStatus: 'idle',
99
+ });
100
+ }
101
+ }
102
+ }, [searchService, pageSize, sort, query, searchIndexId]);
103
+ (0, react_1.useEffect)(() => {
104
+ if (enabled) {
105
+ search(0, false);
106
+ }
107
+ return () => {
108
+ var _a;
109
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
110
+ };
111
+ }, [search, enabled]);
112
+ const loadMore = (0, react_1.useCallback)(() => {
113
+ // Don't load more if already loading or no more pages
114
+ if (state.loadMoreStatus === 'loading' || !hasNextPage) {
115
+ return;
116
+ }
117
+ const nextOffset = state.offset + pageSize;
118
+ search(nextOffset, true);
119
+ }, [search, pageSize, state.offset, hasNextPage, state.loadMoreStatus]);
120
+ return (0, react_1.useMemo)(() => ({
121
+ results: state.results,
122
+ status: state.status,
123
+ loadMoreStatus: state.loadMoreStatus,
124
+ total: state.total,
125
+ totalPages: state.totalPages,
126
+ error: state.error,
127
+ loadMore,
128
+ hasNextPage,
129
+ isLoading: state.status === 'loading',
130
+ isSuccess: state.status === 'success',
131
+ isError: state.status === 'error',
132
+ isLoadingMore: state.loadMoreStatus === 'loading',
133
+ isLoadingMoreError: state.loadMoreStatus === 'error',
134
+ }), [state, loadMore, hasNextPage]);
135
+ };
136
+ exports.useInfiniteSearch = useInfiniteSearch;
@@ -0,0 +1,107 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useSearch = void 0;
4
+ const react_1 = require("react");
5
+ const utils_1 = require("./utils");
6
+ /**
7
+ * React hook for performing search queries with pagination.
8
+ * @param {UseSearchOptions} options - Configuration options for the search hook.
9
+ * @returns {UseSearchState} The search state.
10
+ * @throws {Error} if the search index ID is not provided.
11
+ * @public
12
+ */
13
+ const useSearch = (options) => {
14
+ const { query, page = 1, searchIndexId, pageSize = utils_1.DEFAULT_PAGE_SIZE, sort, enabled = true, keepPreviousData = false, } = options;
15
+ const [state, setState] = (0, react_1.useState)(() => {
16
+ const error = !searchIndexId
17
+ ? new Error('useSearch: searchIndexId is required when initializing the hook')
18
+ : null;
19
+ const status = !searchIndexId ? 'error' : 'idle';
20
+ return {
21
+ results: [],
22
+ total: 0,
23
+ totalPages: 0,
24
+ error,
25
+ status,
26
+ previousStatus: 'idle',
27
+ };
28
+ });
29
+ const searchService = (0, utils_1.useSearchService)();
30
+ const abortControllerRef = (0, react_1.useRef)(null);
31
+ const search = (0, react_1.useCallback)(async () => {
32
+ if (!searchService || !searchIndexId) {
33
+ return;
34
+ }
35
+ abortControllerRef.current = new AbortController();
36
+ const signal = abortControllerRef.current.signal;
37
+ setState((prev) => ({
38
+ results: keepPreviousData ? prev.results : [],
39
+ status: 'loading',
40
+ total: keepPreviousData ? prev.total : 0,
41
+ totalPages: keepPreviousData ? prev.totalPages : 0,
42
+ error: null,
43
+ previousStatus: prev.status,
44
+ }));
45
+ try {
46
+ const offset = (0, utils_1.getOffset)(page, pageSize);
47
+ const searchParams = {
48
+ searchIndexId,
49
+ keyphrase: query,
50
+ limit: pageSize,
51
+ offset,
52
+ sort,
53
+ };
54
+ const { results: searchResults, total } = await searchService.search(searchParams, {
55
+ signal,
56
+ });
57
+ if (signal.aborted) {
58
+ return;
59
+ }
60
+ const totalPages = Math.ceil(total / pageSize);
61
+ setState({
62
+ results: searchResults,
63
+ total,
64
+ totalPages,
65
+ status: 'success',
66
+ error: null,
67
+ previousStatus: 'success',
68
+ });
69
+ }
70
+ catch (err) {
71
+ // Don't set error if request was aborted
72
+ if (signal.aborted) {
73
+ return;
74
+ }
75
+ const errorMessage = err instanceof Error ? err : new Error(JSON.stringify(err));
76
+ setState({
77
+ results: [],
78
+ total: 0,
79
+ totalPages: 0,
80
+ status: 'error',
81
+ error: errorMessage,
82
+ previousStatus: 'error',
83
+ });
84
+ }
85
+ }, [searchService, searchIndexId, page, pageSize, sort, query, keepPreviousData]);
86
+ (0, react_1.useEffect)(() => {
87
+ if (enabled) {
88
+ search();
89
+ }
90
+ return () => {
91
+ var _a;
92
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
93
+ };
94
+ }, [search, enabled]);
95
+ return (0, react_1.useMemo)(() => ({
96
+ error: state.error,
97
+ results: state.results,
98
+ total: state.total,
99
+ totalPages: state.totalPages,
100
+ status: state.status,
101
+ isLoading: state.status === 'loading',
102
+ isSuccess: state.status === 'success',
103
+ isError: state.status === 'error',
104
+ isPreviousData: keepPreviousData && state.previousStatus === 'success' && state.status === 'loading',
105
+ }), [state, keepPreviousData]);
106
+ };
107
+ exports.useSearch = useSearch;
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getOffset = exports.DEFAULT_PAGE_SIZE = void 0;
4
+ exports.useSearchService = useSearchService;
5
+ const search_1 = require("@sitecore-content-sdk/search");
6
+ const react_1 = require("react");
7
+ const withSitecore_1 = require("../enhancers/withSitecore");
8
+ exports.DEFAULT_PAGE_SIZE = 10;
9
+ /**
10
+ * Hook to initialize and manage SearchService.
11
+ */
12
+ function useSearchService() {
13
+ var _a, _b;
14
+ const { api } = (0, withSitecore_1.useSitecore)();
15
+ return (0, react_1.useMemo)(() => {
16
+ var _a;
17
+ if (!((_a = api === null || api === void 0 ? void 0 : api.edge) === null || _a === void 0 ? void 0 : _a.clientContextId)) {
18
+ return null;
19
+ }
20
+ return new search_1.SearchService({
21
+ contextId: api.edge.clientContextId,
22
+ edgeUrl: api.edge.edgeUrl,
23
+ });
24
+ }, [(_a = api === null || api === void 0 ? void 0 : api.edge) === null || _a === void 0 ? void 0 : _a.clientContextId, (_b = api === null || api === void 0 ? void 0 : api.edge) === null || _b === void 0 ? void 0 : _b.edgeUrl]);
25
+ }
26
+ /**
27
+ * Calculates the number of items to skip before returning results.
28
+ * @param {number} page - The current page number (1-indexed).
29
+ * @param {number} pageSize - The number of results per page.
30
+ * @returns The number of items to skip before returning results.
31
+ */
32
+ const getOffset = (page, pageSize) => {
33
+ return page === 1 ? 0 : pageSize * (page - 1);
34
+ };
35
+ exports.getOffset = getOffset;
@@ -0,0 +1,2 @@
1
+ export { useSearch } from './useSearch';
2
+ export { useInfiniteSearch, } from './useInfiniteSearch';
@@ -0,0 +1,132 @@
1
+ /* eslint-disable no-unused-vars */
2
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
3
+ import { DEFAULT_PAGE_SIZE, useSearchService } from './utils';
4
+ /**
5
+ * React hook for performing infinite search queries.
6
+ * @param {UseInfiniteSearchOptions} options - Configuration options for the infinite search hook.
7
+ * @returns {UseInfiniteSearchState} The infinite search state.
8
+ * @throws {Error} if the search index ID is not provided.
9
+ * @public
10
+ */
11
+ export const useInfiniteSearch = (options) => {
12
+ const { query, searchIndexId, pageSize = DEFAULT_PAGE_SIZE, sort, enabled = true } = options;
13
+ const [state, setState] = useState(() => {
14
+ const error = !searchIndexId
15
+ ? new Error('useInfiniteSearch: searchIndexId is required when initializing the hook')
16
+ : null;
17
+ const status = !searchIndexId ? 'error' : 'idle';
18
+ return {
19
+ results: [],
20
+ total: 0,
21
+ totalPages: 0,
22
+ error,
23
+ offset: 0,
24
+ status,
25
+ loadMoreStatus: 'idle',
26
+ };
27
+ });
28
+ const hasNextPage = useMemo(() => state.results.length < state.total, [state.results.length, state.total]);
29
+ const searchService = useSearchService();
30
+ const abortControllerRef = useRef(null);
31
+ const search = useCallback(async (offset, isLoadingMore = false) => {
32
+ if (!searchService || !searchIndexId) {
33
+ return;
34
+ }
35
+ abortControllerRef.current = new AbortController();
36
+ const signal = abortControllerRef.current.signal;
37
+ if (isLoadingMore) {
38
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: null, loadMoreStatus: 'loading' })));
39
+ }
40
+ else {
41
+ setState({
42
+ results: [],
43
+ total: 0,
44
+ totalPages: 0,
45
+ error: null,
46
+ offset: 0,
47
+ status: 'loading',
48
+ loadMoreStatus: 'idle',
49
+ });
50
+ }
51
+ try {
52
+ const searchParams = {
53
+ searchIndexId,
54
+ keyphrase: query,
55
+ limit: pageSize,
56
+ offset,
57
+ sort,
58
+ };
59
+ const { results: searchResults, total: totalResults } = await searchService.search(searchParams, { signal });
60
+ if (signal.aborted) {
61
+ return;
62
+ }
63
+ setState((prev) => {
64
+ const results = isLoadingMore ? [...prev.results, ...searchResults] : searchResults;
65
+ const totalPages = Math.ceil(totalResults / pageSize);
66
+ return {
67
+ results,
68
+ error: null,
69
+ offset,
70
+ status: 'success',
71
+ loadMoreStatus: 'idle',
72
+ total: totalResults,
73
+ totalPages,
74
+ };
75
+ });
76
+ }
77
+ catch (err) {
78
+ // Don't set error if request was aborted
79
+ if (signal.aborted) {
80
+ return;
81
+ }
82
+ const errorMessage = err instanceof Error ? err : new Error(JSON.stringify(err));
83
+ // Don't clean up existing results if appending results
84
+ if (isLoadingMore) {
85
+ setState((prev) => (Object.assign(Object.assign({}, prev), { error: errorMessage, loadMoreStatus: 'error' })));
86
+ }
87
+ else {
88
+ setState({
89
+ results: [],
90
+ total: 0,
91
+ totalPages: 0,
92
+ error: errorMessage,
93
+ offset: 0,
94
+ status: 'error',
95
+ loadMoreStatus: 'idle',
96
+ });
97
+ }
98
+ }
99
+ }, [searchService, pageSize, sort, query, searchIndexId]);
100
+ useEffect(() => {
101
+ if (enabled) {
102
+ search(0, false);
103
+ }
104
+ return () => {
105
+ var _a;
106
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
107
+ };
108
+ }, [search, enabled]);
109
+ const loadMore = useCallback(() => {
110
+ // Don't load more if already loading or no more pages
111
+ if (state.loadMoreStatus === 'loading' || !hasNextPage) {
112
+ return;
113
+ }
114
+ const nextOffset = state.offset + pageSize;
115
+ search(nextOffset, true);
116
+ }, [search, pageSize, state.offset, hasNextPage, state.loadMoreStatus]);
117
+ return useMemo(() => ({
118
+ results: state.results,
119
+ status: state.status,
120
+ loadMoreStatus: state.loadMoreStatus,
121
+ total: state.total,
122
+ totalPages: state.totalPages,
123
+ error: state.error,
124
+ loadMore,
125
+ hasNextPage,
126
+ isLoading: state.status === 'loading',
127
+ isSuccess: state.status === 'success',
128
+ isError: state.status === 'error',
129
+ isLoadingMore: state.loadMoreStatus === 'loading',
130
+ isLoadingMoreError: state.loadMoreStatus === 'error',
131
+ }), [state, loadMore, hasNextPage]);
132
+ };
@@ -0,0 +1,103 @@
1
+ import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
2
+ import { DEFAULT_PAGE_SIZE, getOffset, useSearchService } from './utils';
3
+ /**
4
+ * React hook for performing search queries with pagination.
5
+ * @param {UseSearchOptions} options - Configuration options for the search hook.
6
+ * @returns {UseSearchState} The search state.
7
+ * @throws {Error} if the search index ID is not provided.
8
+ * @public
9
+ */
10
+ export const useSearch = (options) => {
11
+ const { query, page = 1, searchIndexId, pageSize = DEFAULT_PAGE_SIZE, sort, enabled = true, keepPreviousData = false, } = options;
12
+ const [state, setState] = useState(() => {
13
+ const error = !searchIndexId
14
+ ? new Error('useSearch: searchIndexId is required when initializing the hook')
15
+ : null;
16
+ const status = !searchIndexId ? 'error' : 'idle';
17
+ return {
18
+ results: [],
19
+ total: 0,
20
+ totalPages: 0,
21
+ error,
22
+ status,
23
+ previousStatus: 'idle',
24
+ };
25
+ });
26
+ const searchService = useSearchService();
27
+ const abortControllerRef = useRef(null);
28
+ const search = useCallback(async () => {
29
+ if (!searchService || !searchIndexId) {
30
+ return;
31
+ }
32
+ abortControllerRef.current = new AbortController();
33
+ const signal = abortControllerRef.current.signal;
34
+ setState((prev) => ({
35
+ results: keepPreviousData ? prev.results : [],
36
+ status: 'loading',
37
+ total: keepPreviousData ? prev.total : 0,
38
+ totalPages: keepPreviousData ? prev.totalPages : 0,
39
+ error: null,
40
+ previousStatus: prev.status,
41
+ }));
42
+ try {
43
+ const offset = getOffset(page, pageSize);
44
+ const searchParams = {
45
+ searchIndexId,
46
+ keyphrase: query,
47
+ limit: pageSize,
48
+ offset,
49
+ sort,
50
+ };
51
+ const { results: searchResults, total } = await searchService.search(searchParams, {
52
+ signal,
53
+ });
54
+ if (signal.aborted) {
55
+ return;
56
+ }
57
+ const totalPages = Math.ceil(total / pageSize);
58
+ setState({
59
+ results: searchResults,
60
+ total,
61
+ totalPages,
62
+ status: 'success',
63
+ error: null,
64
+ previousStatus: 'success',
65
+ });
66
+ }
67
+ catch (err) {
68
+ // Don't set error if request was aborted
69
+ if (signal.aborted) {
70
+ return;
71
+ }
72
+ const errorMessage = err instanceof Error ? err : new Error(JSON.stringify(err));
73
+ setState({
74
+ results: [],
75
+ total: 0,
76
+ totalPages: 0,
77
+ status: 'error',
78
+ error: errorMessage,
79
+ previousStatus: 'error',
80
+ });
81
+ }
82
+ }, [searchService, searchIndexId, page, pageSize, sort, query, keepPreviousData]);
83
+ useEffect(() => {
84
+ if (enabled) {
85
+ search();
86
+ }
87
+ return () => {
88
+ var _a;
89
+ (_a = abortControllerRef.current) === null || _a === void 0 ? void 0 : _a.abort();
90
+ };
91
+ }, [search, enabled]);
92
+ return useMemo(() => ({
93
+ error: state.error,
94
+ results: state.results,
95
+ total: state.total,
96
+ totalPages: state.totalPages,
97
+ status: state.status,
98
+ isLoading: state.status === 'loading',
99
+ isSuccess: state.status === 'success',
100
+ isError: state.status === 'error',
101
+ isPreviousData: keepPreviousData && state.previousStatus === 'success' && state.status === 'loading',
102
+ }), [state, keepPreviousData]);
103
+ };
@@ -0,0 +1,30 @@
1
+ import { SearchService } from '@sitecore-content-sdk/search';
2
+ import { useMemo } from 'react';
3
+ import { useSitecore } from '../enhancers/withSitecore';
4
+ export const DEFAULT_PAGE_SIZE = 10;
5
+ /**
6
+ * Hook to initialize and manage SearchService.
7
+ */
8
+ export function useSearchService() {
9
+ var _a, _b;
10
+ const { api } = useSitecore();
11
+ return useMemo(() => {
12
+ var _a;
13
+ if (!((_a = api === null || api === void 0 ? void 0 : api.edge) === null || _a === void 0 ? void 0 : _a.clientContextId)) {
14
+ return null;
15
+ }
16
+ return new SearchService({
17
+ contextId: api.edge.clientContextId,
18
+ edgeUrl: api.edge.edgeUrl,
19
+ });
20
+ }, [(_a = api === null || api === void 0 ? void 0 : api.edge) === null || _a === void 0 ? void 0 : _a.clientContextId, (_b = api === null || api === void 0 ? void 0 : api.edge) === null || _b === void 0 ? void 0 : _b.edgeUrl]);
21
+ }
22
+ /**
23
+ * Calculates the number of items to skip before returning results.
24
+ * @param {number} page - The current page number (1-indexed).
25
+ * @param {number} pageSize - The number of results per page.
26
+ * @returns The number of items to skip before returning results.
27
+ */
28
+ export const getOffset = (page, pageSize) => {
29
+ return page === 1 ? 0 : pageSize * (page - 1);
30
+ };
package/global.d.ts ADDED
@@ -0,0 +1,17 @@
1
+ declare module 'style-attr' {
2
+ export const parse: (
3
+ style: string,
4
+ config: { preserveNumbers: boolean }
5
+ ) => { [key: string]: unknown };
6
+ }
7
+
8
+ declare namespace NodeJS {
9
+ export interface Global {
10
+ [key: string]: unknown;
11
+ requestAnimationFrame: (callback: () => void) => void;
12
+ window: Window;
13
+ document: Document;
14
+ navigator: Navigator;
15
+ HTMLElement: HTMLElement;
16
+ }
17
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sitecore-content-sdk/react",
3
- "version": "1.3.0-canary.31",
3
+ "version": "1.3.0-canary.35",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "sideEffects": false,
@@ -76,16 +76,30 @@
76
76
  "react-dom": "^19.1.0"
77
77
  },
78
78
  "dependencies": {
79
- "@sitecore-content-sdk/core": "1.3.0-canary.31",
79
+ "@sitecore-content-sdk/core": "1.3.0-canary.35",
80
+ "@sitecore-content-sdk/search": "1.3.0-canary.35",
80
81
  "fast-deep-equal": "^3.1.3"
81
82
  },
82
83
  "description": "",
83
84
  "types": "types/index.d.ts",
84
- "gitHead": "721a4d75a24fca90fb0cbd3c051db90325f8f086",
85
+ "gitHead": "11355ebc3060a277b17c0c4283ad36afabfc2b0e",
85
86
  "files": [
86
87
  "dist",
87
- "types"
88
+ "types",
89
+ "/*.d.ts"
88
90
  ],
91
+ "exports": {
92
+ ".": {
93
+ "import": "./dist/esm/index.js",
94
+ "require": "./dist/cjs/index.js",
95
+ "types": "./types/index.d.ts"
96
+ },
97
+ "./search": {
98
+ "import": "./dist/esm/search/index.js",
99
+ "require": "./dist/cjs/search/index.js",
100
+ "types": "./types/search/index.d.ts"
101
+ }
102
+ },
89
103
  "imports": {
90
104
  "#rsc-env": {
91
105
  "react-server": {
package/search.d.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './types/search/index';
@@ -0,0 +1,4 @@
1
+ export { useSearch, UseSearchState, UseSearchOptions } from './useSearch';
2
+ export { useInfiniteSearch, UseInfiniteSearchState, UseInfiniteSearchOptions, } from './useInfiniteSearch';
3
+ export { SearchStatus } from './utils';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/search/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAC1E,OAAO,EACL,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC"}
@@ -0,0 +1,116 @@
1
+ import { SearchStatus } from './utils';
2
+ import { SearchDocument, SearchParameters } from '@sitecore-content-sdk/search';
3
+ /**
4
+ * Options for the useInfiniteSearch hook.
5
+ * @public
6
+ */
7
+ export interface UseInfiniteSearchOptions<T extends SearchDocument = SearchDocument> {
8
+ /**
9
+ * The query string to search for.
10
+ * By default empty string is used.
11
+ */
12
+ query?: string;
13
+ /**
14
+ * The ID of the search index to use.
15
+ */
16
+ searchIndexId: string;
17
+ /**
18
+ * Number of results per page.
19
+ * @default 10
20
+ */
21
+ pageSize?: number;
22
+ /**
23
+ * Specifies the sorting of the search results.
24
+ */
25
+ sort?: SearchParameters<T>['sort'];
26
+ /**
27
+ * Specifies whether the search should automatically run.
28
+ * @default true
29
+ */
30
+ enabled?: boolean;
31
+ }
32
+ /**
33
+ * The state of the useInfiniteSearch hook.
34
+ * @public
35
+ */
36
+ export type UseInfiniteSearchState<T extends SearchDocument = SearchDocument> = Omit<InternalInfiniteSearchState<T>, 'offset'> & {
37
+ /**
38
+ * Load the next page of results.
39
+ */
40
+ loadMore: () => void;
41
+ /**
42
+ * Whether there are more results available.
43
+ */
44
+ hasNextPage: boolean;
45
+ /**
46
+ * Whether a search request is currently in progress.
47
+ */
48
+ isLoading: boolean;
49
+ /**
50
+ * Whether the search request was successful.
51
+ */
52
+ isSuccess: boolean;
53
+ /**
54
+ * Whether the search request failed.
55
+ */
56
+ isError: boolean;
57
+ /**
58
+ * Whether a search request for more results is currently in progress.
59
+ */
60
+ isLoadingMore: boolean;
61
+ /**
62
+ * Whether the search request for more results failed.
63
+ */
64
+ isLoadingMoreError: boolean;
65
+ };
66
+ type InternalInfiniteSearchState<T extends SearchDocument = SearchDocument> = {
67
+ /**
68
+ * The search results.
69
+ */
70
+ results: T[];
71
+ /**
72
+ * Total number of results across all pages.
73
+ */
74
+ total: number;
75
+ /**
76
+ * Total number of pages available based on `total` and `pageSize`.
77
+ */
78
+ totalPages: number;
79
+ /**
80
+ * The error object if the last search request failed, or null if no error occurred.
81
+ */
82
+ error: Error | null;
83
+ /**
84
+ * The current offset of the search results.
85
+ */
86
+ offset: number;
87
+ /**
88
+ * The status of the initial search request.
89
+ * It will be set to:
90
+ * - 'idle' if no search request has been made yet.
91
+ * - 'loading' if a search request is currently in progress.
92
+ * - 'success' if a search request was successful.
93
+ * - 'error' if a search request failed.
94
+ * @default 'idle'
95
+ */
96
+ status: SearchStatus;
97
+ /**
98
+ * The status of the "load more" request.
99
+ * It will be set to:
100
+ * - 'idle' if no "load more" request has been made yet.
101
+ * - 'loading' if a "load more" request is currently in progress.
102
+ * - 'error' if a "load more" request failed.
103
+ * @default 'idle'
104
+ */
105
+ loadMoreStatus: Omit<SearchStatus, 'success'>;
106
+ };
107
+ /**
108
+ * React hook for performing infinite search queries.
109
+ * @param {UseInfiniteSearchOptions} options - Configuration options for the infinite search hook.
110
+ * @returns {UseInfiniteSearchState} The infinite search state.
111
+ * @throws {Error} if the search index ID is not provided.
112
+ * @public
113
+ */
114
+ export declare const useInfiniteSearch: <T extends SearchDocument = SearchDocument>(options: UseInfiniteSearchOptions<T>) => UseInfiniteSearchState<T>;
115
+ export {};
116
+ //# sourceMappingURL=useInfiniteSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useInfiniteSearch.d.ts","sourceRoot":"","sources":["../../src/search/useInfiniteSearch.ts"],"names":[],"mappings":"AAEA,OAAO,EAAqB,YAAY,EAAoB,MAAM,SAAS,CAAC;AAC5E,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAEhF;;;GAGG;AACH,MAAM,WAAW,wBAAwB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;IACjF;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;GAGG;AACH,MAAM,MAAM,sBAAsB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI,IAAI,CAClF,2BAA2B,CAAC,CAAC,CAAC,EAC9B,QAAQ,CACT,GAAG;IACF;;OAEG;IACH,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB;;OAEG;IACH,WAAW,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;OAEG;IACH,aAAa,EAAE,OAAO,CAAC;IACvB;;OAEG;IACH,kBAAkB,EAAE,OAAO,CAAC;CAC7B,CAAC;AAEF,KAAK,2BAA2B,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI;IAC5E;;OAEG;IACH,OAAO,EAAE,CAAC,EAAE,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;OAQG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;;;;;;OAOG;IACH,cAAc,EAAE,IAAI,CAAC,YAAY,EAAE,SAAS,CAAC,CAAC;CAC/C,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EACzE,SAAS,wBAAwB,CAAC,CAAC,CAAC,KACnC,sBAAsB,CAAC,CAAC,CA6J1B,CAAC"}
@@ -0,0 +1,107 @@
1
+ import { SearchDocument, SearchParameters } from '@sitecore-content-sdk/search';
2
+ import { SearchStatus } from './utils';
3
+ /**
4
+ * Options for the useSearch hook.
5
+ * @public
6
+ */
7
+ export interface UseSearchOptions<T extends SearchDocument = SearchDocument> {
8
+ /**
9
+ * The query string to search for.
10
+ * By default empty string is used.
11
+ */
12
+ query?: string;
13
+ /**
14
+ * The current page number (1-indexed).
15
+ * If not provided, the search will start on page 1.
16
+ */
17
+ page?: number;
18
+ /**
19
+ * The ID of the search index to use.
20
+ */
21
+ searchIndexId: string;
22
+ /**
23
+ * Number of results per page.
24
+ * @default 10
25
+ */
26
+ pageSize?: number;
27
+ /**
28
+ * Specifies the sorting of the search results.
29
+ */
30
+ sort?: SearchParameters<T>['sort'];
31
+ /**
32
+ * Specifies whether the search should automatically run.
33
+ * @default true
34
+ */
35
+ enabled?: boolean;
36
+ /**
37
+ * Specifies whether the previous search results should be kept when fetching new results.
38
+ * @default false
39
+ */
40
+ keepPreviousData?: boolean;
41
+ }
42
+ type InternalState<T extends SearchDocument = SearchDocument> = {
43
+ /**
44
+ * The search results.
45
+ */
46
+ results: T[];
47
+ /**
48
+ * Total number of results across all pages.
49
+ */
50
+ total: number;
51
+ /**
52
+ * Total number of pages available based on `total` and `pageSize`.
53
+ */
54
+ totalPages: number;
55
+ /**
56
+ * The error object if the last search request failed, or null if no error occurred.
57
+ */
58
+ error: Error | null;
59
+ /**
60
+ * The status of the search.
61
+ * It will be set to:
62
+ * - 'idle' if no search request has been made yet.
63
+ * - 'loading' if a search request is currently in progress.
64
+ * - 'success' if a search request was successful.
65
+ * - 'error' if a search request failed.
66
+ * @default 'idle'
67
+ */
68
+ status: SearchStatus;
69
+ /**
70
+ * The status of the previous search request.
71
+ * @default 'idle'
72
+ */
73
+ previousStatus: SearchStatus;
74
+ };
75
+ /**
76
+ * The state of the useSearch hook.
77
+ * @public
78
+ */
79
+ export type UseSearchState<T extends SearchDocument = SearchDocument> = Omit<InternalState<T>, 'previousStatus'> & {
80
+ /**
81
+ * Whether a search request is currently in progress.
82
+ */
83
+ isLoading: boolean;
84
+ /**
85
+ * Whether the search request was successful.
86
+ */
87
+ isSuccess: boolean;
88
+ /**
89
+ * Whether the search request failed.
90
+ */
91
+ isError: boolean;
92
+ /**
93
+ * Whether the search results from the previous query are returned.
94
+ * Will be `true` if `keepPreviousData` is set.
95
+ */
96
+ isPreviousData: boolean;
97
+ };
98
+ /**
99
+ * React hook for performing search queries with pagination.
100
+ * @param {UseSearchOptions} options - Configuration options for the search hook.
101
+ * @returns {UseSearchState} The search state.
102
+ * @throws {Error} if the search index ID is not provided.
103
+ * @public
104
+ */
105
+ export declare const useSearch: <T extends SearchDocument = SearchDocument>(options: UseSearchOptions<T>) => UseSearchState<T>;
106
+ export {};
107
+ //# sourceMappingURL=useSearch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useSearch.d.ts","sourceRoot":"","sources":["../../src/search/useSearch.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChF,OAAO,EAAgC,YAAY,EAAoB,MAAM,SAAS,CAAC;AAEvF;;;GAGG;AACH,MAAM,WAAW,gBAAgB,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc;IACzE;;;OAGG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;OAGG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;OAEG;IACH,IAAI,CAAC,EAAE,gBAAgB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;IACnC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;OAGG;IACH,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B;AAED,KAAK,aAAa,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI;IAC9D;;OAEG;IACH,OAAO,EAAE,CAAC,EAAE,CAAC;IACb;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IACnB;;OAEG;IACH,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB;;;;;;;;OAQG;IACH,MAAM,EAAE,YAAY,CAAC;IACrB;;;OAGG;IACH,cAAc,EAAE,YAAY,CAAC;CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,SAAS,cAAc,GAAG,cAAc,IAAI,IAAI,CAC1E,aAAa,CAAC,CAAC,CAAC,EAChB,gBAAgB,CACjB,GAAG;IACF;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,SAAS,EAAE,OAAO,CAAC;IACnB;;OAEG;IACH,OAAO,EAAE,OAAO,CAAC;IACjB;;;OAGG;IACH,cAAc,EAAE,OAAO,CAAC;CACzB,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAI,CAAC,SAAS,cAAc,GAAG,cAAc,EACjE,SAAS,gBAAgB,CAAC,CAAC,CAAC,KAC3B,cAAc,CAAC,CAAC,CAwHlB,CAAC"}
@@ -0,0 +1,19 @@
1
+ import { SearchService } from '@sitecore-content-sdk/search';
2
+ export declare const DEFAULT_PAGE_SIZE = 10;
3
+ /**
4
+ * The status of a search request.
5
+ * @public
6
+ */
7
+ export type SearchStatus = 'idle' | 'loading' | 'success' | 'error';
8
+ /**
9
+ * Hook to initialize and manage SearchService.
10
+ */
11
+ export declare function useSearchService(): SearchService;
12
+ /**
13
+ * Calculates the number of items to skip before returning results.
14
+ * @param {number} page - The current page number (1-indexed).
15
+ * @param {number} pageSize - The number of results per page.
16
+ * @returns The number of items to skip before returning results.
17
+ */
18
+ export declare const getOffset: (page: number, pageSize: number) => number;
19
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/search/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;AAI7D,eAAO,MAAM,iBAAiB,KAAK,CAAC;AAEpC;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,OAAO,CAAC;AAEpE;;GAEG;AACH,wBAAgB,gBAAgB,kBAa/B;AAED;;;;;GAKG;AACH,eAAO,MAAM,SAAS,GAAI,MAAM,MAAM,EAAE,UAAU,MAAM,WAEvD,CAAC"}