@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 CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Uniform
3
+ Copyright (c) 2026 Uniform Systems, Inc.
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md ADDED
@@ -0,0 +1,129 @@
1
+ # @uniformdev/search
2
+
3
+ A lightweight client for [Uniform Search](https://uniform.dev) with optional React bindings for building faceted search experiences (filters, sorting, pagination, and URL-synced state).
4
+
5
+ The core client is framework-agnostic. The React bindings are exposed from a separate `@uniformdev/search/react` entry point and `react` is an optional peer dependency, so you only pull in React if you use them.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @uniformdev/search
11
+ # or
12
+ pnpm add @uniformdev/search
13
+ # or
14
+ yarn add @uniformdev/search
15
+ ```
16
+
17
+ To use the React bindings, make sure React 18+ is installed in your app:
18
+
19
+ ```bash
20
+ npm install react
21
+ ```
22
+
23
+ ## Quick start
24
+
25
+ ### 1. Create a search client
26
+
27
+ The client posts to `${apiUrl}/api/search` and (optionally) attaches an `x-api-key` header. Configure it with your Uniform Search service URL, API key, and project ID:
28
+
29
+ ```ts
30
+ import { createSearchClient } from '@uniformdev/search';
31
+
32
+ const client = createSearchClient({
33
+ apiUrl: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_URL!, // https://<your-project>.search.uniform.app
34
+ apiKey: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_KEY,
35
+ projectId: process.env.NEXT_PUBLIC_UNIFORM_PROJECT_ID,
36
+ });
37
+
38
+ const result = await client.performSearch({
39
+ search: 'hello world',
40
+ page: 0,
41
+ perPage: 10,
42
+ });
43
+
44
+ console.log(result.data.items, result.data.total, result.facets);
45
+ ```
46
+
47
+ `performSearch` never throws — on a network or non-2xx error it logs and returns an empty result shape so your UI can render safely.
48
+
49
+ ### 2. (React) Wire up the provider
50
+
51
+ ```tsx
52
+ import { SearchProvider, useSearch } from '@uniformdev/search/react';
53
+ import { createSearchClient } from '@uniformdev/search';
54
+
55
+ const client = createSearchClient({
56
+ apiUrl: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_URL!,
57
+ apiKey: process.env.NEXT_PUBLIC_UNIFORM_SEARCH_API_KEY,
58
+ projectId: process.env.NEXT_PUBLIC_UNIFORM_PROJECT_ID,
59
+ });
60
+
61
+ export function SearchPage() {
62
+ return (
63
+ <SearchProvider performSearch={client.performSearch}>
64
+ <SearchBox />
65
+ <Results />
66
+ </SearchProvider>
67
+ );
68
+ }
69
+
70
+ function SearchBox() {
71
+ const { searchBoxValue, setSearchQuery } = useSearch();
72
+ return (
73
+ <input
74
+ value={searchBoxValue}
75
+ onChange={(e) => setSearchQuery(e.target.value)}
76
+ placeholder="Search…"
77
+ />
78
+ );
79
+ }
80
+
81
+ function Results() {
82
+ const { results, isLoading } = useSearch();
83
+ if (isLoading) return <p>Loading…</p>;
84
+ return (
85
+ <ul>
86
+ {results.items.map((item) => (
87
+ <li key={item.id}>{String(item.title ?? item.id)}</li>
88
+ ))}
89
+ </ul>
90
+ );
91
+ }
92
+ ```
93
+
94
+ The provider keeps search state (query, page, page size, sort, and selected filters) in sync with the URL query string and debounces text input.
95
+
96
+ ## API
97
+
98
+ ### Core (`@uniformdev/search`)
99
+
100
+ | Export | Description |
101
+ |---|---|
102
+ | `createSearchClient(config)` | Creates a `SearchClient` with a `performSearch(params)` method. |
103
+ | `getSearchParamsFromUrl(url)` | Parses a URL's query string into a params object. |
104
+ | `buildOrderByQuery(orderBy)` | Builds an `orderBy` query string (e.g. `created_at_DESC`). |
105
+ | `flattenBlockParams(value)` | Normalizes Uniform block parameter values into a flat array. |
106
+ | Types | `SearchParams`, `SearchClient`, `CollectionResult`, `SearchHit`, `Pagination`, `Facets`, `FacetBy`, `OrderBy`, `PageSize`, and more. |
107
+
108
+ ### React (`@uniformdev/search/react`)
109
+
110
+ | Export | Description |
111
+ |---|---|
112
+ | `SearchProvider` | Context provider that owns search state and runs queries. |
113
+ | `useSearch()` | Hook returning results, facets, loading state, and state setters. Must be used inside a `SearchProvider`. |
114
+ | `usePagination`, `useSearchPagination`, `DOTS` | Pagination helpers. |
115
+ | `SearchItemUrlResolverProvider`, `useUrlResolver`, `createDefaultUrlResolver` | Resolve result items to URLs. |
116
+
117
+ ## Configuration
118
+
119
+ `createSearchClient` accepts:
120
+
121
+ | Option | Required | Description |
122
+ |---|---|---|
123
+ | `apiUrl` | yes | Base URL of your Uniform Search service. `/api/search` is appended automatically. |
124
+ | `apiKey` | no | Sent as the `x-api-key` header. |
125
+ | `projectId` | no | Default project ID, merged into each request body. |
126
+
127
+ ## License
128
+
129
+ MIT
@@ -8,7 +8,14 @@ var DEFAULT_PAGE_SIZE = 10;
8
8
 
9
9
  // src/utils.ts
10
10
  var buildOrderByQuery = (orderBy) => {
11
- return `${orderBy.field}_${orderBy.direction}`;
11
+ var _a;
12
+ const field = orderBy.field;
13
+ if (field && typeof field === "object" && "field" in field) {
14
+ const sv = field;
15
+ return `${sv.field}_${sv.direction.toUpperCase()}`;
16
+ }
17
+ if (!field || field === "relevance") return "";
18
+ return `${field}_${(_a = orderBy.direction) != null ? _a : "ASC"}`;
12
19
  };
13
20
  var getSearchParamsFromUrl = (urlString) => {
14
21
  if (!urlString) {
@@ -28,13 +35,13 @@ var getSearchParamsFromUrl = (urlString) => {
28
35
 
29
36
  // src/flattenBlockParams.ts
30
37
  function resolveFieldValue(field, locale = "en-us") {
31
- var _a, _b;
38
+ var _a;
32
39
  if (!field || typeof field !== "object") return field;
33
40
  if (field.type === "$block" && Array.isArray(field.value)) {
34
41
  return flattenBlockParams(field.value, locale);
35
42
  }
36
43
  if (field.locales && typeof field.locales === "object") {
37
- return (_b = (_a = field.locales[locale]) != null ? _a : Object.values(field.locales)[0]) != null ? _b : field.value;
44
+ return (_a = field.locales[locale]) != null ? _a : field.value;
38
45
  }
39
46
  return field.value;
40
47
  }
@@ -63,4 +70,4 @@ export {
63
70
  getSearchParamsFromUrl,
64
71
  flattenBlockParams
65
72
  };
66
- //# sourceMappingURL=chunk-ZABEFR2D.mjs.map
73
+ //# sourceMappingURL=chunk-RMUYFKZO.mjs.map
@@ -0,0 +1 @@
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 const field = orderBy.field as unknown;\n // sortByConfig produces an object value: { field: string; direction: 'asc' | 'desc' }\n if (field && typeof field === 'object' && 'field' in (field as object)) {\n const sv = field as { field: string; direction: string };\n return `${sv.field}_${sv.direction.toUpperCase()}`;\n }\n // Plain string \"relevance\" or missing direction → no sort\n if (!field || field === 'relevance') return '';\n return `${field}_${orderBy.direction ?? 'ASC'}`;\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] ?? 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;AAFvD;AAGE,QAAM,QAAQ,QAAQ;AAEtB,MAAI,SAAS,OAAO,UAAU,YAAY,WAAY,OAAkB;AACtE,UAAM,KAAK;AACX,WAAO,GAAG,GAAG,KAAK,IAAI,GAAG,UAAU,YAAY,CAAC;AAAA,EAClD;AAEA,MAAI,CAAC,SAAS,UAAU,YAAa,QAAO;AAC5C,SAAO,GAAG,KAAK,KAAI,aAAQ,cAAR,YAAqB,KAAK;AAC/C;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;;;ACtBA,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,WAAM,QAAQ,MAAM,MAApB,YAAyB,MAAM;AAAA,EACxC;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":[]}
@@ -15,20 +15,14 @@ type CollectionResult = {
15
15
  data: Pagination<SearchHit>;
16
16
  facets: Facets;
17
17
  };
18
- type MultiSearchResult = {
19
- [K in SearchCollection]?: CollectionResult;
20
- };
21
18
  type FilterByItem = {
22
19
  title: string;
23
20
  value: string;
24
21
  };
25
- type FilterBy = {
22
+ type FacetBy = {
26
23
  type: 'select' | 'multiSelect' | 'range';
27
24
  title: string;
28
- fieldId: string;
29
25
  fieldKey: string;
30
- enableFaceting: boolean;
31
- values: FilterByItem[];
32
26
  };
33
27
  type OrderBy = {
34
28
  title: string;
@@ -46,21 +40,29 @@ type Facets = {
46
40
  type FilterQuery = {
47
41
  [K: string]: string[];
48
42
  };
43
+ type SearchItemConfig = {
44
+ source: string;
45
+ type: string;
46
+ nodeId?: string;
47
+ urlTemplate?: string;
48
+ tokenMapping?: Record<string, string>;
49
+ };
49
50
 
50
51
  interface SearchParams {
51
52
  projectId?: string;
52
53
  page?: number;
53
54
  perPage?: number;
54
55
  filters?: Record<string, unknown>;
56
+ baseFilterBy?: string;
55
57
  facetBy?: string;
58
+ queryBy?: string;
56
59
  search?: string;
57
60
  orderBy?: string;
58
- collections?: SearchCollection[];
61
+ locale?: string;
62
+ maxFacetValues?: number;
59
63
  }
60
64
  interface SearchClient {
61
- performSearch(params: SearchParams): Promise<{
62
- results: MultiSearchResult;
63
- }>;
65
+ performSearch(params: SearchParams): Promise<CollectionResult>;
64
66
  }
65
67
  declare function createSearchClient(config: {
66
68
  apiUrl: string;
@@ -68,4 +70,4 @@ declare function createSearchClient(config: {
68
70
  projectId?: string;
69
71
  }): SearchClient;
70
72
 
71
- export { type CollectionResult as C, type Facets as F, type MultiSearchResult as M, type OrderBy as O, type PageSize as P, type SearchClient as S, type FilterBy as a, type FilterByItem as b, type FilterQuery as c, type Pagination as d, type SearchCollection as e, type SearchHit as f, type SearchParams as g, createSearchClient as h };
73
+ export { type CollectionResult as C, type FacetBy as F, type OrderBy as O, type PageSize as P, type SearchClient as S, type Facets as a, type FilterByItem as b, type FilterQuery as c, type Pagination as d, type SearchCollection as e, type SearchHit as f, type SearchItemConfig as g, type SearchParams as h, createSearchClient as i };
@@ -15,20 +15,14 @@ type CollectionResult = {
15
15
  data: Pagination<SearchHit>;
16
16
  facets: Facets;
17
17
  };
18
- type MultiSearchResult = {
19
- [K in SearchCollection]?: CollectionResult;
20
- };
21
18
  type FilterByItem = {
22
19
  title: string;
23
20
  value: string;
24
21
  };
25
- type FilterBy = {
22
+ type FacetBy = {
26
23
  type: 'select' | 'multiSelect' | 'range';
27
24
  title: string;
28
- fieldId: string;
29
25
  fieldKey: string;
30
- enableFaceting: boolean;
31
- values: FilterByItem[];
32
26
  };
33
27
  type OrderBy = {
34
28
  title: string;
@@ -46,21 +40,29 @@ type Facets = {
46
40
  type FilterQuery = {
47
41
  [K: string]: string[];
48
42
  };
43
+ type SearchItemConfig = {
44
+ source: string;
45
+ type: string;
46
+ nodeId?: string;
47
+ urlTemplate?: string;
48
+ tokenMapping?: Record<string, string>;
49
+ };
49
50
 
50
51
  interface SearchParams {
51
52
  projectId?: string;
52
53
  page?: number;
53
54
  perPage?: number;
54
55
  filters?: Record<string, unknown>;
56
+ baseFilterBy?: string;
55
57
  facetBy?: string;
58
+ queryBy?: string;
56
59
  search?: string;
57
60
  orderBy?: string;
58
- collections?: SearchCollection[];
61
+ locale?: string;
62
+ maxFacetValues?: number;
59
63
  }
60
64
  interface SearchClient {
61
- performSearch(params: SearchParams): Promise<{
62
- results: MultiSearchResult;
63
- }>;
65
+ performSearch(params: SearchParams): Promise<CollectionResult>;
64
66
  }
65
67
  declare function createSearchClient(config: {
66
68
  apiUrl: string;
@@ -68,4 +70,4 @@ declare function createSearchClient(config: {
68
70
  projectId?: string;
69
71
  }): SearchClient;
70
72
 
71
- export { type CollectionResult as C, type Facets as F, type MultiSearchResult as M, type OrderBy as O, type PageSize as P, type SearchClient as S, type FilterBy as a, type FilterByItem as b, type FilterQuery as c, type Pagination as d, type SearchCollection as e, type SearchHit as f, type SearchParams as g, createSearchClient as h };
73
+ export { type CollectionResult as C, type FacetBy as F, type OrderBy as O, type PageSize as P, type SearchClient as S, type Facets as a, type FilterByItem as b, type FilterQuery as c, type Pagination as d, type SearchCollection as e, type SearchHit as f, type SearchItemConfig as g, type SearchParams as h, createSearchClient as i };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { O as OrderBy } from './client-DrL-8TfY.mjs';
2
- export { C as CollectionResult, F as Facets, a as FilterBy, b as FilterByItem, c as FilterQuery, M as MultiSearchResult, P as PageSize, d as Pagination, S as SearchClient, e as SearchCollection, f as SearchHit, g as SearchParams, h as createSearchClient } from './client-DrL-8TfY.mjs';
1
+ import { O as OrderBy } from './client-CtTcEJUy.mjs';
2
+ export { C as CollectionResult, F as FacetBy, a as Facets, b as FilterByItem, c as FilterQuery, P as PageSize, d as Pagination, S as SearchClient, e as SearchCollection, f as SearchHit, g as SearchItemConfig, h as SearchParams, i as createSearchClient } from './client-CtTcEJUy.mjs';
3
3
 
4
4
  declare const UNIFORM_SEARCH_QUERY_KEY = "search";
5
5
  declare const UNIFORM_SEARCH_PAGE_KEY = "page";
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { O as OrderBy } from './client-DrL-8TfY.js';
2
- export { C as CollectionResult, F as Facets, a as FilterBy, b as FilterByItem, c as FilterQuery, M as MultiSearchResult, P as PageSize, d as Pagination, S as SearchClient, e as SearchCollection, f as SearchHit, g as SearchParams, h as createSearchClient } from './client-DrL-8TfY.js';
1
+ import { O as OrderBy } from './client-CtTcEJUy.js';
2
+ export { C as CollectionResult, F as FacetBy, a as Facets, b as FilterByItem, c as FilterQuery, P as PageSize, d as Pagination, S as SearchClient, e as SearchCollection, f as SearchHit, g as SearchItemConfig, h as SearchParams, i as createSearchClient } from './client-CtTcEJUy.js';
3
3
 
4
4
  declare const UNIFORM_SEARCH_QUERY_KEY = "search";
5
5
  declare const UNIFORM_SEARCH_PAGE_KEY = "page";
package/dist/index.js CHANGED
@@ -42,7 +42,12 @@ var FIRST_PAGE = 0;
42
42
  var DEFAULT_PAGE_SIZE = 10;
43
43
 
44
44
  // src/client.ts
45
+ var emptyResult = () => ({
46
+ data: { items: [], total: 0, page: 0, perPage: 10, totalPages: 0 },
47
+ facets: {}
48
+ });
45
49
  function createSearchClient(config) {
50
+ const baseUrl = config.apiUrl.replace(/\/+$/, "");
46
51
  return {
47
52
  async performSearch(params) {
48
53
  const headers = {
@@ -56,19 +61,19 @@ function createSearchClient(config) {
56
61
  projectId: params.projectId || config.projectId
57
62
  };
58
63
  try {
59
- const response = await fetch(`${config.apiUrl}/api/search`, {
64
+ const response = await fetch(`${baseUrl}/api/search`, {
60
65
  method: "POST",
61
66
  headers,
62
67
  body: JSON.stringify(body)
63
68
  });
64
69
  if (!response.ok) {
65
70
  console.error(`[alex] Search API error: ${response.status}`);
66
- return { results: {} };
71
+ return emptyResult();
67
72
  }
68
73
  return response.json();
69
74
  } catch (error) {
70
75
  console.error("[alex] Search fetch error:", error);
71
- return { results: {} };
76
+ return emptyResult();
72
77
  }
73
78
  }
74
79
  };
@@ -76,7 +81,14 @@ function createSearchClient(config) {
76
81
 
77
82
  // src/utils.ts
78
83
  var buildOrderByQuery = (orderBy) => {
79
- return `${orderBy.field}_${orderBy.direction}`;
84
+ var _a;
85
+ const field = orderBy.field;
86
+ if (field && typeof field === "object" && "field" in field) {
87
+ const sv = field;
88
+ return `${sv.field}_${sv.direction.toUpperCase()}`;
89
+ }
90
+ if (!field || field === "relevance") return "";
91
+ return `${field}_${(_a = orderBy.direction) != null ? _a : "ASC"}`;
80
92
  };
81
93
  var getSearchParamsFromUrl = (urlString) => {
82
94
  if (!urlString) {
@@ -96,13 +108,13 @@ var getSearchParamsFromUrl = (urlString) => {
96
108
 
97
109
  // src/flattenBlockParams.ts
98
110
  function resolveFieldValue(field, locale = "en-us") {
99
- var _a, _b;
111
+ var _a;
100
112
  if (!field || typeof field !== "object") return field;
101
113
  if (field.type === "$block" && Array.isArray(field.value)) {
102
114
  return flattenBlockParams(field.value, locale);
103
115
  }
104
116
  if (field.locales && typeof field.locales === "object") {
105
- return (_b = (_a = field.locales[locale]) != null ? _a : Object.values(field.locales)[0]) != null ? _b : field.value;
117
+ return (_a = field.locales[locale]) != null ? _a : field.value;
106
118
  }
107
119
  return field.value;
108
120
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/client.ts","../src/utils.ts","../src/flattenBlockParams.ts"],"sourcesContent":["export * from './types';\nexport * from './constants';\nexport * from './client';\nexport * from './utils';\nexport * from './flattenBlockParams';\n","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 { SearchCollection, MultiSearchResult } from './types';\n\nexport interface SearchParams {\n projectId?: string;\n page?: number;\n perPage?: number;\n filters?: Record<string, unknown>;\n facetBy?: string;\n search?: string;\n orderBy?: string;\n collections?: SearchCollection[];\n}\n\nexport interface SearchClient {\n performSearch(params: SearchParams): Promise<{ results: MultiSearchResult }>;\n}\n\nexport function createSearchClient(config: {\n apiUrl: string;\n apiKey?: string;\n projectId?: string;\n}): SearchClient {\n return {\n async performSearch(params) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (config.apiKey) {\n headers['x-api-key'] = config.apiKey;\n }\n\n const body = {\n ...params,\n projectId: params.projectId || config.projectId,\n };\n\n try {\n const response = await fetch(`${config.apiUrl}/api/search`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n console.error(`[alex] Search API error: ${response.status}`);\n return { results: {} };\n }\n\n return response.json();\n } catch (error) {\n console.error('[alex] Search fetch error:', error);\n return { results: {} };\n }\n },\n };\n}\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":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACAO,IAAM,2BAA2B;AACjC,IAAM,0BAA0B;AAChC,IAAM,+BAA+B;AACrC,IAAM,8BAA8B;AACpC,IAAM,aAAa;AACnB,IAAM,oBAAoB;;;ACY1B,SAAS,mBAAmB,QAIlB;AACf,SAAO;AAAA,IACL,MAAM,cAAc,QAAQ;AAC1B,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,MAClB;AACA,UAAI,OAAO,QAAQ;AACjB,gBAAQ,WAAW,IAAI,OAAO;AAAA,MAChC;AAEA,YAAM,OAAO;AAAA,QACX,GAAG;AAAA,QACH,WAAW,OAAO,aAAa,OAAO;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,MAAM,eAAe;AAAA,UAC1D,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,kBAAQ,MAAM,4BAA4B,SAAS,MAAM,EAAE;AAC3D,iBAAO,EAAE,SAAS,CAAC,EAAE;AAAA,QACvB;AAEA,eAAO,SAAS,KAAK;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,MAAM,8BAA8B,KAAK;AACjD,eAAO,EAAE,SAAS,CAAC,EAAE;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;;;ACrDO,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":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/constants.ts","../src/client.ts","../src/utils.ts","../src/flattenBlockParams.ts"],"sourcesContent":["export * from './types';\nexport * from './constants';\nexport * from './client';\nexport * from './utils';\nexport * from './flattenBlockParams';\n","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 { CollectionResult } from './types';\n\nexport interface SearchParams {\n projectId?: string;\n page?: number;\n perPage?: number;\n filters?: Record<string, unknown>;\n baseFilterBy?: string;\n facetBy?: string;\n queryBy?: string;\n search?: string;\n orderBy?: string;\n locale?: string;\n maxFacetValues?: number;\n}\n\nexport interface SearchClient {\n performSearch(params: SearchParams): Promise<CollectionResult>;\n}\n\nconst emptyResult = (): CollectionResult => ({\n data: { items: [], total: 0, page: 0, perPage: 10, totalPages: 0 },\n facets: {},\n});\n\nexport function createSearchClient(config: { apiUrl: string; apiKey?: string; projectId?: string }): SearchClient {\n const baseUrl = config.apiUrl.replace(/\\/+$/, '');\n return {\n async performSearch(params) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (config.apiKey) {\n headers['x-api-key'] = config.apiKey;\n }\n\n const body = {\n ...params,\n projectId: params.projectId || config.projectId,\n };\n\n try {\n const response = await fetch(`${baseUrl}/api/search`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n console.error(`[alex] Search API error: ${response.status}`);\n return emptyResult();\n }\n\n return response.json();\n } catch (error) {\n console.error('[alex] Search fetch error:', error);\n return emptyResult();\n }\n },\n };\n}\n","import type { OrderBy } from './types';\n\nexport const buildOrderByQuery = (orderBy: OrderBy) => {\n const field = orderBy.field as unknown;\n // sortByConfig produces an object value: { field: string; direction: 'asc' | 'desc' }\n if (field && typeof field === 'object' && 'field' in (field as object)) {\n const sv = field as { field: string; direction: string };\n return `${sv.field}_${sv.direction.toUpperCase()}`;\n }\n // Plain string \"relevance\" or missing direction → no sort\n if (!field || field === 'relevance') return '';\n return `${field}_${orderBy.direction ?? 'ASC'}`;\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] ?? 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":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -8,10 +8,15 @@ import {
8
8
  buildOrderByQuery,
9
9
  flattenBlockParams,
10
10
  getSearchParamsFromUrl
11
- } from "./chunk-ZABEFR2D.mjs";
11
+ } from "./chunk-RMUYFKZO.mjs";
12
12
 
13
13
  // src/client.ts
14
+ var emptyResult = () => ({
15
+ data: { items: [], total: 0, page: 0, perPage: 10, totalPages: 0 },
16
+ facets: {}
17
+ });
14
18
  function createSearchClient(config) {
19
+ const baseUrl = config.apiUrl.replace(/\/+$/, "");
15
20
  return {
16
21
  async performSearch(params) {
17
22
  const headers = {
@@ -25,19 +30,19 @@ function createSearchClient(config) {
25
30
  projectId: params.projectId || config.projectId
26
31
  };
27
32
  try {
28
- const response = await fetch(`${config.apiUrl}/api/search`, {
33
+ const response = await fetch(`${baseUrl}/api/search`, {
29
34
  method: "POST",
30
35
  headers,
31
36
  body: JSON.stringify(body)
32
37
  });
33
38
  if (!response.ok) {
34
39
  console.error(`[alex] Search API error: ${response.status}`);
35
- return { results: {} };
40
+ return emptyResult();
36
41
  }
37
42
  return response.json();
38
43
  } catch (error) {
39
44
  console.error("[alex] Search fetch error:", error);
40
- return { results: {} };
45
+ return emptyResult();
41
46
  }
42
47
  }
43
48
  };
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { SearchCollection, MultiSearchResult } from './types';\n\nexport interface SearchParams {\n projectId?: string;\n page?: number;\n perPage?: number;\n filters?: Record<string, unknown>;\n facetBy?: string;\n search?: string;\n orderBy?: string;\n collections?: SearchCollection[];\n}\n\nexport interface SearchClient {\n performSearch(params: SearchParams): Promise<{ results: MultiSearchResult }>;\n}\n\nexport function createSearchClient(config: {\n apiUrl: string;\n apiKey?: string;\n projectId?: string;\n}): SearchClient {\n return {\n async performSearch(params) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (config.apiKey) {\n headers['x-api-key'] = config.apiKey;\n }\n\n const body = {\n ...params,\n projectId: params.projectId || config.projectId,\n };\n\n try {\n const response = await fetch(`${config.apiUrl}/api/search`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n console.error(`[alex] Search API error: ${response.status}`);\n return { results: {} };\n }\n\n return response.json();\n } catch (error) {\n console.error('[alex] Search fetch error:', error);\n return { results: {} };\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAiBO,SAAS,mBAAmB,QAIlB;AACf,SAAO;AAAA,IACL,MAAM,cAAc,QAAQ;AAC1B,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,MAClB;AACA,UAAI,OAAO,QAAQ;AACjB,gBAAQ,WAAW,IAAI,OAAO;AAAA,MAChC;AAEA,YAAM,OAAO;AAAA,QACX,GAAG;AAAA,QACH,WAAW,OAAO,aAAa,OAAO;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,MAAM,eAAe;AAAA,UAC1D,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,kBAAQ,MAAM,4BAA4B,SAAS,MAAM,EAAE;AAC3D,iBAAO,EAAE,SAAS,CAAC,EAAE;AAAA,QACvB;AAEA,eAAO,SAAS,KAAK;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,MAAM,8BAA8B,KAAK;AACjD,eAAO,EAAE,SAAS,CAAC,EAAE;AAAA,MACvB;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import type { CollectionResult } from './types';\n\nexport interface SearchParams {\n projectId?: string;\n page?: number;\n perPage?: number;\n filters?: Record<string, unknown>;\n baseFilterBy?: string;\n facetBy?: string;\n queryBy?: string;\n search?: string;\n orderBy?: string;\n locale?: string;\n maxFacetValues?: number;\n}\n\nexport interface SearchClient {\n performSearch(params: SearchParams): Promise<CollectionResult>;\n}\n\nconst emptyResult = (): CollectionResult => ({\n data: { items: [], total: 0, page: 0, perPage: 10, totalPages: 0 },\n facets: {},\n});\n\nexport function createSearchClient(config: { apiUrl: string; apiKey?: string; projectId?: string }): SearchClient {\n const baseUrl = config.apiUrl.replace(/\\/+$/, '');\n return {\n async performSearch(params) {\n const headers: Record<string, string> = {\n 'Content-Type': 'application/json',\n };\n if (config.apiKey) {\n headers['x-api-key'] = config.apiKey;\n }\n\n const body = {\n ...params,\n projectId: params.projectId || config.projectId,\n };\n\n try {\n const response = await fetch(`${baseUrl}/api/search`, {\n method: 'POST',\n headers,\n body: JSON.stringify(body),\n });\n\n if (!response.ok) {\n console.error(`[alex] Search API error: ${response.status}`);\n return emptyResult();\n }\n\n return response.json();\n } catch (error) {\n console.error('[alex] Search fetch error:', error);\n return emptyResult();\n }\n },\n };\n}\n"],"mappings":";;;;;;;;;;;;;AAoBA,IAAM,cAAc,OAAyB;AAAA,EAC3C,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,GAAG,MAAM,GAAG,SAAS,IAAI,YAAY,EAAE;AAAA,EACjE,QAAQ,CAAC;AACX;AAEO,SAAS,mBAAmB,QAA+E;AAChH,QAAM,UAAU,OAAO,OAAO,QAAQ,QAAQ,EAAE;AAChD,SAAO;AAAA,IACL,MAAM,cAAc,QAAQ;AAC1B,YAAM,UAAkC;AAAA,QACtC,gBAAgB;AAAA,MAClB;AACA,UAAI,OAAO,QAAQ;AACjB,gBAAQ,WAAW,IAAI,OAAO;AAAA,MAChC;AAEA,YAAM,OAAO;AAAA,QACX,GAAG;AAAA,QACH,WAAW,OAAO,aAAa,OAAO;AAAA,MACxC;AAEA,UAAI;AACF,cAAM,WAAW,MAAM,MAAM,GAAG,OAAO,eAAe;AAAA,UACpD,QAAQ;AAAA,UACR;AAAA,UACA,MAAM,KAAK,UAAU,IAAI;AAAA,QAC3B,CAAC;AAED,YAAI,CAAC,SAAS,IAAI;AAChB,kBAAQ,MAAM,4BAA4B,SAAS,MAAM,EAAE;AAC3D,iBAAO,YAAY;AAAA,QACrB;AAEA,eAAO,SAAS,KAAK;AAAA,MACvB,SAAS,OAAO;AACd,gBAAQ,MAAM,8BAA8B,KAAK;AACjD,eAAO,YAAY;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AACF;","names":[]}
package/dist/react.d.mts CHANGED
@@ -1,24 +1,22 @@
1
+ import * as react from 'react';
1
2
  import { FC, ReactNode } from 'react';
2
- import { g as SearchParams, M as MultiSearchResult, d as Pagination, f as SearchHit, F as Facets, P as PageSize, a as FilterBy, e as SearchCollection } from './client-DrL-8TfY.mjs';
3
+ import { d as Pagination, f as SearchHit, a as Facets, P as PageSize, F as FacetBy, h as SearchParams, C as CollectionResult, g as SearchItemConfig } from './client-CtTcEJUy.mjs';
3
4
 
4
5
  interface SearchProviderProps {
5
6
  children: ReactNode;
6
- performSearch: (params: SearchParams) => Promise<{
7
- results: MultiSearchResult;
8
- }>;
9
- contentType?: string;
10
- filterBy?: unknown;
7
+ performSearch: (params: SearchParams) => Promise<CollectionResult>;
11
8
  orderBy?: unknown;
12
- baseFilters?: unknown;
9
+ baseFilterString?: string;
13
10
  pageSizes?: unknown;
14
- collections?: string | string[];
11
+ queryBy?: string[];
15
12
  searchDebounceMs?: number;
13
+ locale?: string;
14
+ maxFacetValues?: number;
16
15
  }
17
16
  interface UseSearchReturn {
18
17
  results: Pagination<SearchHit>;
19
18
  facets: Facets | null;
20
19
  isLoading: boolean;
21
- collectionResults: MultiSearchResult;
22
20
  searchBoxValue: string;
23
21
  setSearchQuery: (value: string) => void;
24
22
  page: number;
@@ -32,14 +30,19 @@ interface UseSearchReturn {
32
30
  }>;
33
31
  selectedOrderBy: string;
34
32
  setOrderBy: (query: string) => void;
35
- filterOptions: FilterBy[];
33
+ filterOptions: FacetBy[];
34
+ setFilterOptions: (filters: FacetBy[]) => void;
35
+ /** Additive registration of a single facet option (keyed by fieldKey). Used by facet
36
+ * components that mount independently (e.g. App Router slots) rather than being
37
+ * enumerated by a parent. */
38
+ registerFilterOption: (filter: FacetBy) => void;
39
+ unregisterFilterOption: (fieldKey: string) => void;
36
40
  selectedFilters: Record<string, string[]>;
37
41
  setSelectedFilters: (filters: Record<string, string[]>) => void;
38
42
  clearFilters: () => void;
39
- selectedCollections: SearchCollection[];
40
- setSelectedCollections: (collections: SearchCollection[]) => void;
41
43
  formatResultsSummary: (template: string) => string;
42
44
  }
45
+ declare const SearchContext: react.Context<UseSearchReturn | null>;
43
46
  declare const SearchProvider: FC<SearchProviderProps>;
44
47
 
45
48
  declare function useSearch(): UseSearchReturn;
@@ -65,4 +68,28 @@ interface UseSearchPaginationReturn {
65
68
  }
66
69
  declare function useSearchPagination(siblingCount?: number): UseSearchPaginationReturn;
67
70
 
68
- export { DOTS, SearchProvider, type SearchProviderProps, type UseSearchPaginationReturn, type UseSearchReturn, usePagination, useSearch, useSearchPagination };
71
+ type UrlResolver = (hit: SearchHit) => string | undefined;
72
+ /** Wrap your search tree to override URL building for all hits. */
73
+ declare const SearchItemUrlResolverProvider: FC<{
74
+ resolver: UrlResolver;
75
+ children: ReactNode;
76
+ }>;
77
+ /** Used internally by SearchList to register the Canvas-config-driven default. */
78
+ declare const SearchItemDefaultUrlResolverProvider: FC<{
79
+ resolver: UrlResolver;
80
+ children: ReactNode;
81
+ }>;
82
+ /**
83
+ * Always returns a resolver. User-provided resolver (SearchItemUrlResolverProvider)
84
+ * takes priority over the default registered by SearchList.
85
+ */
86
+ declare function useUrlResolver(): UrlResolver;
87
+ interface UrlResolverOptions {
88
+ /** nodeId → resolved locale-specific path (from project map). */
89
+ pathsByNodeId?: Record<string, string>;
90
+ /** Current locale, used as fallback for legacy :locale token in urlTemplate. */
91
+ locale?: string;
92
+ }
93
+ declare function createDefaultUrlResolver(configs: SearchItemConfig[], options?: UrlResolverOptions): UrlResolver;
94
+
95
+ export { DOTS, SearchContext, SearchItemDefaultUrlResolverProvider, SearchItemUrlResolverProvider, SearchProvider, type SearchProviderProps, type UrlResolver, type UseSearchPaginationReturn, type UseSearchReturn, createDefaultUrlResolver, usePagination, useSearch, useSearchPagination, useUrlResolver };
package/dist/react.d.ts CHANGED
@@ -1,24 +1,22 @@
1
+ import * as react from 'react';
1
2
  import { FC, ReactNode } from 'react';
2
- import { g as SearchParams, M as MultiSearchResult, d as Pagination, f as SearchHit, F as Facets, P as PageSize, a as FilterBy, e as SearchCollection } from './client-DrL-8TfY.js';
3
+ import { d as Pagination, f as SearchHit, a as Facets, P as PageSize, F as FacetBy, h as SearchParams, C as CollectionResult, g as SearchItemConfig } from './client-CtTcEJUy.js';
3
4
 
4
5
  interface SearchProviderProps {
5
6
  children: ReactNode;
6
- performSearch: (params: SearchParams) => Promise<{
7
- results: MultiSearchResult;
8
- }>;
9
- contentType?: string;
10
- filterBy?: unknown;
7
+ performSearch: (params: SearchParams) => Promise<CollectionResult>;
11
8
  orderBy?: unknown;
12
- baseFilters?: unknown;
9
+ baseFilterString?: string;
13
10
  pageSizes?: unknown;
14
- collections?: string | string[];
11
+ queryBy?: string[];
15
12
  searchDebounceMs?: number;
13
+ locale?: string;
14
+ maxFacetValues?: number;
16
15
  }
17
16
  interface UseSearchReturn {
18
17
  results: Pagination<SearchHit>;
19
18
  facets: Facets | null;
20
19
  isLoading: boolean;
21
- collectionResults: MultiSearchResult;
22
20
  searchBoxValue: string;
23
21
  setSearchQuery: (value: string) => void;
24
22
  page: number;
@@ -32,14 +30,19 @@ interface UseSearchReturn {
32
30
  }>;
33
31
  selectedOrderBy: string;
34
32
  setOrderBy: (query: string) => void;
35
- filterOptions: FilterBy[];
33
+ filterOptions: FacetBy[];
34
+ setFilterOptions: (filters: FacetBy[]) => void;
35
+ /** Additive registration of a single facet option (keyed by fieldKey). Used by facet
36
+ * components that mount independently (e.g. App Router slots) rather than being
37
+ * enumerated by a parent. */
38
+ registerFilterOption: (filter: FacetBy) => void;
39
+ unregisterFilterOption: (fieldKey: string) => void;
36
40
  selectedFilters: Record<string, string[]>;
37
41
  setSelectedFilters: (filters: Record<string, string[]>) => void;
38
42
  clearFilters: () => void;
39
- selectedCollections: SearchCollection[];
40
- setSelectedCollections: (collections: SearchCollection[]) => void;
41
43
  formatResultsSummary: (template: string) => string;
42
44
  }
45
+ declare const SearchContext: react.Context<UseSearchReturn | null>;
43
46
  declare const SearchProvider: FC<SearchProviderProps>;
44
47
 
45
48
  declare function useSearch(): UseSearchReturn;
@@ -65,4 +68,28 @@ interface UseSearchPaginationReturn {
65
68
  }
66
69
  declare function useSearchPagination(siblingCount?: number): UseSearchPaginationReturn;
67
70
 
68
- export { DOTS, SearchProvider, type SearchProviderProps, type UseSearchPaginationReturn, type UseSearchReturn, usePagination, useSearch, useSearchPagination };
71
+ type UrlResolver = (hit: SearchHit) => string | undefined;
72
+ /** Wrap your search tree to override URL building for all hits. */
73
+ declare const SearchItemUrlResolverProvider: FC<{
74
+ resolver: UrlResolver;
75
+ children: ReactNode;
76
+ }>;
77
+ /** Used internally by SearchList to register the Canvas-config-driven default. */
78
+ declare const SearchItemDefaultUrlResolverProvider: FC<{
79
+ resolver: UrlResolver;
80
+ children: ReactNode;
81
+ }>;
82
+ /**
83
+ * Always returns a resolver. User-provided resolver (SearchItemUrlResolverProvider)
84
+ * takes priority over the default registered by SearchList.
85
+ */
86
+ declare function useUrlResolver(): UrlResolver;
87
+ interface UrlResolverOptions {
88
+ /** nodeId → resolved locale-specific path (from project map). */
89
+ pathsByNodeId?: Record<string, string>;
90
+ /** Current locale, used as fallback for legacy :locale token in urlTemplate. */
91
+ locale?: string;
92
+ }
93
+ declare function createDefaultUrlResolver(configs: SearchItemConfig[], options?: UrlResolverOptions): UrlResolver;
94
+
95
+ export { DOTS, SearchContext, SearchItemDefaultUrlResolverProvider, SearchItemUrlResolverProvider, SearchProvider, type SearchProviderProps, type UrlResolver, type UseSearchPaginationReturn, type UseSearchReturn, createDefaultUrlResolver, usePagination, useSearch, useSearchPagination, useUrlResolver };