@rubixstudios/payload-typesense 1.1.0 → 1.1.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/README.md +1 -16
- package/dist/components/HeadlessSearchInput.d.ts +2 -92
- package/dist/components/HeadlessSearchInput.d.ts.map +1 -1
- package/dist/components/HeadlessSearchInput.js +23 -140
- package/dist/components/ThemeProvider.d.ts +3 -2
- package/dist/components/ThemeProvider.d.ts.map +1 -1
- package/dist/components/ThemeProvider.js +1 -1
- package/dist/components/index.d.ts +5 -5
- package/dist/components/index.d.ts.map +1 -1
- package/dist/components/index.js +3 -3
- package/dist/components/themes/hooks.d.ts +5 -5
- package/dist/components/themes/hooks.d.ts.map +1 -1
- package/dist/components/themes/hooks.js +16 -16
- package/dist/components/themes/index.d.ts +4 -4
- package/dist/components/themes/index.js +4 -4
- package/dist/components/themes/themes.d.ts +1 -1
- package/dist/components/themes/themes.d.ts.map +1 -1
- package/dist/components/themes/themes.js +109 -109
- package/dist/components/themes/types.d.ts.map +1 -1
- package/dist/components/themes/utils.d.ts +1 -1
- package/dist/components/themes/utils.d.ts.map +1 -1
- package/dist/components/themes/utils.js +140 -140
- package/dist/endpoints/handler/createAdvancedSearch.d.ts +5 -0
- package/dist/endpoints/handler/createAdvancedSearch.d.ts.map +1 -0
- package/dist/endpoints/handler/createAdvancedSearch.js +40 -0
- package/dist/endpoints/handler/createCollections.d.ts +4 -0
- package/dist/endpoints/handler/createCollections.d.ts.map +1 -0
- package/dist/endpoints/handler/createCollections.js +23 -0
- package/dist/endpoints/handler/createSearch.d.ts +5 -0
- package/dist/endpoints/handler/createSearch.d.ts.map +1 -0
- package/dist/endpoints/handler/createSearch.js +119 -0
- package/dist/endpoints/handler/createSuggest.d.ts +5 -0
- package/dist/endpoints/handler/createSuggest.d.ts.map +1 -0
- package/dist/endpoints/handler/createSuggest.js +50 -0
- package/dist/endpoints/health.d.ts +4 -10
- package/dist/endpoints/health.d.ts.map +1 -1
- package/dist/endpoints/health.js +45 -103
- package/dist/endpoints/search.d.ts +4 -5
- package/dist/endpoints/search.d.ts.map +1 -1
- package/dist/endpoints/search.js +26 -355
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +6 -101
- package/dist/lib/cache.d.ts +6 -27
- package/dist/lib/cache.d.ts.map +1 -1
- package/dist/lib/cache.js +11 -29
- package/dist/lib/client.d.ts +4 -0
- package/dist/lib/client.d.ts.map +1 -0
- package/dist/lib/{typesense-client.js → client.js} +10 -18
- package/dist/lib/headlessSearch.d.ts +89 -0
- package/dist/lib/headlessSearch.d.ts.map +1 -0
- package/dist/lib/headlessSearch.js +2 -0
- package/dist/lib/hooks.d.ts +12 -3
- package/dist/lib/hooks.d.ts.map +1 -1
- package/dist/lib/hooks.js +37 -37
- package/dist/lib/initialization.d.ts +3 -3
- package/dist/lib/initialization.d.ts.map +1 -1
- package/dist/lib/initialization.js +36 -49
- package/dist/lib/schema-mapper.d.ts +17 -7
- package/dist/lib/schema-mapper.d.ts.map +1 -1
- package/dist/lib/schema-mapper.js +53 -89
- package/dist/lib/{config-validation.d.ts → validation.d.ts} +18 -22
- package/dist/lib/validation.d.ts.map +1 -0
- package/dist/lib/{config-validation.js → validation.js} +32 -49
- package/dist/{lib/types.d.ts → types.d.ts} +22 -5
- package/dist/types.d.ts.map +1 -0
- package/dist/utils/buildError.d.ts +2 -0
- package/dist/utils/buildError.d.ts.map +1 -0
- package/dist/utils/buildError.js +10 -0
- package/dist/utils/ensureCollection.d.ts +3 -0
- package/dist/utils/ensureCollection.d.ts.map +1 -0
- package/dist/utils/ensureCollection.js +13 -0
- package/dist/utils/extractText.d.ts +2 -0
- package/dist/utils/extractText.d.ts.map +1 -0
- package/dist/utils/extractText.js +20 -0
- package/dist/utils/getAllCollections.d.ts +9 -0
- package/dist/utils/getAllCollections.d.ts.map +1 -0
- package/dist/utils/getAllCollections.js +84 -0
- package/dist/utils/getCacheStats.d.ts +6 -0
- package/dist/utils/getCacheStats.d.ts.map +1 -0
- package/dist/utils/getCacheStats.js +9 -0
- package/dist/utils/getCollectionInfo.d.ts +3 -0
- package/dist/utils/getCollectionInfo.d.ts.map +1 -0
- package/dist/utils/getCollectionInfo.js +8 -0
- package/dist/utils/keyboard.d.ts +8 -0
- package/dist/utils/keyboard.d.ts.map +1 -0
- package/dist/utils/keyboard.js +41 -0
- package/dist/utils/testConnection.d.ts +3 -0
- package/dist/utils/testConnection.d.ts.map +1 -0
- package/dist/utils/testConnection.js +8 -0
- package/dist/utils/useDebounce.d.ts +2 -0
- package/dist/utils/useDebounce.d.ts.map +1 -0
- package/dist/utils/useDebounce.js +15 -0
- package/dist/utils/useSearch.d.ts +17 -0
- package/dist/utils/useSearch.d.ts.map +1 -0
- package/dist/utils/useSearch.js +78 -0
- package/package.json +14 -11
- package/dist/endpoints/customEndpointHandler.d.ts +0 -3
- package/dist/endpoints/customEndpointHandler.d.ts.map +0 -1
- package/dist/endpoints/customEndpointHandler.js +0 -5
- package/dist/lib/config-validation.d.ts.map +0 -1
- package/dist/lib/types.d.ts.map +0 -1
- package/dist/lib/typesense-client.d.ts +0 -5
- package/dist/lib/typesense-client.d.ts.map +0 -1
- /package/dist/{lib/types.js → types.js} +0 -0
package/README.md
CHANGED
|
@@ -63,8 +63,7 @@ function SearchPage() {
|
|
|
63
63
|
)
|
|
64
64
|
}
|
|
65
65
|
|
|
66
|
-
|
|
67
|
-
function MultiCollectionSearch() {
|
|
66
|
+
function CollectionSearch() {
|
|
68
67
|
return (
|
|
69
68
|
<HeadlessSearchInput
|
|
70
69
|
baseUrl="http://localhost:3000"
|
|
@@ -76,20 +75,6 @@ function MultiCollectionSearch() {
|
|
|
76
75
|
/>
|
|
77
76
|
)
|
|
78
77
|
}
|
|
79
|
-
|
|
80
|
-
// Single collection search
|
|
81
|
-
function PostSearch() {
|
|
82
|
-
return (
|
|
83
|
-
<HeadlessSearchInput
|
|
84
|
-
baseUrl="http://localhost:3000"
|
|
85
|
-
collection="posts"
|
|
86
|
-
placeholder="Search posts..."
|
|
87
|
-
onResultClick={(result) => {
|
|
88
|
-
console.log('Selected:', result.document)
|
|
89
|
-
}}
|
|
90
|
-
/>
|
|
91
|
-
)
|
|
92
|
-
}
|
|
93
78
|
```
|
|
94
79
|
|
|
95
80
|
## Features
|
|
@@ -1,96 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
import
|
|
3
|
-
|
|
4
|
-
export interface HeadlessSearchInputProps<T = Record<string, unknown>> extends BaseSearchInputProps<T> {
|
|
5
|
-
/**
|
|
6
|
-
* Collection to search in (for single collection search)
|
|
7
|
-
*/
|
|
8
|
-
collection?: string;
|
|
9
|
-
/**
|
|
10
|
-
* Collections to search in (for multi-collection search)
|
|
11
|
-
*/
|
|
12
|
-
collections?: string[];
|
|
13
|
-
/**
|
|
14
|
-
* Enable suggestions
|
|
15
|
-
*/
|
|
16
|
-
enableSuggestions?: boolean;
|
|
17
|
-
/**
|
|
18
|
-
* Number of results to show per page
|
|
19
|
-
*/
|
|
20
|
-
perPage?: number;
|
|
21
|
-
/**
|
|
22
|
-
* Show date in search results
|
|
23
|
-
*/
|
|
24
|
-
renderDate?: boolean;
|
|
25
|
-
/**
|
|
26
|
-
* Custom render function for error state
|
|
27
|
-
*/
|
|
28
|
-
renderError?: (error: string) => React.ReactNode;
|
|
29
|
-
/**
|
|
30
|
-
* Custom input element (for complete control)
|
|
31
|
-
*/
|
|
32
|
-
renderInput?: (props: {
|
|
33
|
-
className: string;
|
|
34
|
-
onBlur: (e: React.FocusEvent) => void;
|
|
35
|
-
onChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
|
|
36
|
-
onFocus: () => void;
|
|
37
|
-
onKeyDown: (e: React.KeyboardEvent) => void;
|
|
38
|
-
placeholder: string;
|
|
39
|
-
ref: React.RefObject<HTMLInputElement | null>;
|
|
40
|
-
value: string;
|
|
41
|
-
}) => React.ReactNode;
|
|
42
|
-
/**
|
|
43
|
-
* Custom render function for loading state
|
|
44
|
-
*/
|
|
45
|
-
renderLoading?: () => React.ReactNode;
|
|
46
|
-
/**
|
|
47
|
-
* Show match percentage in search results
|
|
48
|
-
*/
|
|
49
|
-
renderMatchPercentage?: boolean;
|
|
50
|
-
/**
|
|
51
|
-
* Custom render function for no results
|
|
52
|
-
*/
|
|
53
|
-
renderNoResults?: (query: string) => React.ReactNode;
|
|
54
|
-
/**
|
|
55
|
-
* Custom render function for results
|
|
56
|
-
*/
|
|
57
|
-
renderResult?: (result: SearchResult<T>, index: number, handlers: {
|
|
58
|
-
onClick: (result: SearchResult<T>) => void;
|
|
59
|
-
}) => React.ReactNode;
|
|
60
|
-
/**
|
|
61
|
-
* Custom render function for results header
|
|
62
|
-
*/
|
|
63
|
-
renderResultsHeader?: (found: number, searchTime: number) => React.ReactNode;
|
|
64
|
-
/**
|
|
65
|
-
* Custom CSS class for individual result items
|
|
66
|
-
*/
|
|
67
|
-
resultItemClassName?: string;
|
|
68
|
-
/**
|
|
69
|
-
* Custom CSS class for the results container
|
|
70
|
-
*/
|
|
71
|
-
resultsClassName?: string;
|
|
72
|
-
/**
|
|
73
|
-
* Custom CSS class for results container
|
|
74
|
-
*/
|
|
75
|
-
resultsContainerClassName?: string;
|
|
76
|
-
/**
|
|
77
|
-
* Show loading state
|
|
78
|
-
*/
|
|
79
|
-
showLoading?: boolean;
|
|
80
|
-
/**
|
|
81
|
-
* Show result count
|
|
82
|
-
*/
|
|
83
|
-
showResultCount?: boolean;
|
|
84
|
-
/**
|
|
85
|
-
* Show search time
|
|
86
|
-
*/
|
|
87
|
-
showSearchTime?: boolean;
|
|
88
|
-
/**
|
|
89
|
-
* Theme configuration
|
|
90
|
-
*/
|
|
91
|
-
theme?: string | ThemeConfig;
|
|
92
|
-
}
|
|
93
|
-
declare const HeadlessSearchInput: <T = Record<string, unknown>>({ baseUrl, className, collection, collections, debounceMs, enableSuggestions: _enableSuggestions, errorClassName, inputClassName, inputWrapperClassName, minQueryLength, noResultsClassName, onResultClick, onResults, onSearch, perPage, placeholder, renderDate, renderError, renderInput, renderMatchPercentage, renderNoResults, renderResult, renderResultsHeader, resultItemClassName, resultsClassName, resultsContainerClassName, resultsHeaderClassName, resultsListClassName, showLoading, showResultCount, showSearchTime, theme, }: HeadlessSearchInputProps<T>) => React.ReactElement;
|
|
2
|
+
import { type HeadlessSearchInputProps } from '../lib/headlessSearch.js';
|
|
3
|
+
declare const HeadlessSearchInput: <T = Record<string, unknown>>({ baseUrl, className, collections, debounceMs, enableSuggestions: _enableSuggestions, errorClassName, inputClassName, inputWrapperClassName, minQueryLength, noResultsClassName, onResultClick, onResults, onSearch, perPage, placeholder, renderDate, renderError, renderInput, renderMatchPercentage, renderNoResults, renderResult, renderResultsHeader, resultItemClassName, resultsClassName, resultsContainerClassName, resultsHeaderClassName, resultsListClassName, showLoading, showResultCount, showSearchTime, theme, }: HeadlessSearchInputProps<T>) => React.ReactElement;
|
|
94
4
|
export default HeadlessSearchInput;
|
|
95
5
|
export { HeadlessSearchInput };
|
|
96
6
|
//# sourceMappingURL=HeadlessSearchInput.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeadlessSearchInput.d.ts","sourceRoot":"","sources":["../../src/components/HeadlessSearchInput.tsx"],"names":[],"mappings":"AAEA,OAAO,
|
|
1
|
+
{"version":3,"file":"HeadlessSearchInput.d.ts","sourceRoot":"","sources":["../../src/components/HeadlessSearchInput.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAsC,MAAM,OAAO,CAAA;AAE1D,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAA;AAOxE,QAAA,MAAM,mBAAmB,GAAI,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAG,ogBAgCxD,wBAAwB,CAAC,CAAC,CAAC,KAAG,KAAK,CAAC,YAmkBtC,CAAA;AAED,eAAe,mBAAmB,CAAA;AAClC,OAAO,EAAE,mBAAmB,EAAE,CAAA"}
|
|
@@ -1,182 +1,65 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import React, {
|
|
2
|
+
import React, { useEffect, useRef, useState } from 'react';
|
|
3
|
+
import { handleKeyboard } from '../utils/keyboard.js';
|
|
4
|
+
import { useDebounce } from '../utils/useDebounce.js';
|
|
5
|
+
import { useSearch } from '../utils/useSearch.js';
|
|
3
6
|
import { useThemeConfig } from './themes/hooks.js';
|
|
4
|
-
const HeadlessSearchInput = ({ baseUrl, className = '',
|
|
7
|
+
const HeadlessSearchInput = ({ baseUrl, className = '', collections, debounceMs = 300, enableSuggestions: _enableSuggestions = true, errorClassName = '', inputClassName = '', inputWrapperClassName = '', minQueryLength = 2, noResultsClassName = '', onResultClick, onResults, onSearch, perPage = 10, placeholder = 'Search...', renderDate = true, renderError, renderInput, renderMatchPercentage = true, renderNoResults, renderResult, renderResultsHeader, resultItemClassName = '', resultsClassName = '', resultsContainerClassName = '', resultsHeaderClassName = '', resultsListClassName = '', showLoading = true, showResultCount = true, showSearchTime = true, theme = 'modern' })=>{
|
|
5
8
|
const [query, setQuery] = useState('');
|
|
6
|
-
const [results, setResults] = useState(null);
|
|
7
|
-
const [isLoading, setIsLoading] = useState(false);
|
|
8
9
|
const [isOpen, setIsOpen] = useState(false);
|
|
9
|
-
const [error, setError] = useState(null);
|
|
10
10
|
const inputRef = useRef(null);
|
|
11
11
|
const resultsRef = useRef(null);
|
|
12
|
-
const debounceRef = useRef(undefined);
|
|
13
|
-
const collectionsRef = useRef(collections);
|
|
14
12
|
const themeConfig = useThemeConfig({
|
|
15
13
|
theme: typeof theme === 'string' ? theme : theme.theme || 'modern',
|
|
16
14
|
...typeof theme === 'object' ? theme : {}
|
|
17
15
|
});
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
useEffect(()=>{
|
|
21
|
-
collectionsRef.current = collections;
|
|
22
|
-
}, [
|
|
23
|
-
collections
|
|
24
|
-
]);
|
|
25
|
-
// Debounced search function
|
|
26
|
-
const onResultsRef = useRef(onResults);
|
|
27
|
-
const onSearchRef = useRef(onSearch);
|
|
28
|
-
onResultsRef.current = onResults;
|
|
29
|
-
onSearchRef.current = onSearch;
|
|
30
|
-
const performSearch = useCallback(async (searchQuery)=>{
|
|
31
|
-
if (searchQuery.length < minQueryLength) {
|
|
32
|
-
setResults(null);
|
|
33
|
-
setIsLoading(false);
|
|
34
|
-
return;
|
|
35
|
-
}
|
|
36
|
-
setIsLoading(true);
|
|
37
|
-
setError(null);
|
|
38
|
-
try {
|
|
39
|
-
let searchUrl;
|
|
40
|
-
let searchResults;
|
|
41
|
-
if (collection) {
|
|
42
|
-
// Single collection search
|
|
43
|
-
searchUrl = `${baseUrl}/api/search/${collection}?q=${encodeURIComponent(searchQuery)}&per_page=${perPage}`;
|
|
44
|
-
} else if (collectionsRef.current && collectionsRef.current.length > 0) {
|
|
45
|
-
// Multiple collections specified - use universal search and filter client-side
|
|
46
|
-
searchUrl = `${baseUrl}/api/search?q=${encodeURIComponent(searchQuery)}&per_page=${perPage * 2}`;
|
|
47
|
-
} else {
|
|
48
|
-
// No collections specified - use universal search
|
|
49
|
-
searchUrl = `${baseUrl}/api/search?q=${encodeURIComponent(searchQuery)}&per_page=${perPage}`;
|
|
50
|
-
}
|
|
51
|
-
const response = await fetch(searchUrl);
|
|
52
|
-
if (!response.ok) {
|
|
53
|
-
throw new Error(`Search failed: ${response.status} ${response.statusText}`);
|
|
54
|
-
}
|
|
55
|
-
searchResults = await response.json();
|
|
56
|
-
if (collectionsRef.current && collectionsRef.current.length > 0) {
|
|
57
|
-
const filteredHits = searchResults.hits?.filter((hit)=>hit.collection && collectionsRef.current.includes(hit.collection)) || [];
|
|
58
|
-
const filteredCollections = searchResults.collections?.filter((col)=>col.collection && collectionsRef.current.includes(col.collection)) || [];
|
|
59
|
-
searchResults = {
|
|
60
|
-
...searchResults,
|
|
61
|
-
collections: filteredCollections,
|
|
62
|
-
found: filteredHits.length,
|
|
63
|
-
hits: filteredHits
|
|
64
|
-
};
|
|
65
|
-
}
|
|
66
|
-
setResults(searchResults);
|
|
67
|
-
onResultsRef.current?.(searchResults);
|
|
68
|
-
onSearchRef.current?.(searchQuery, searchResults);
|
|
69
|
-
} catch (err) {
|
|
70
|
-
setError(err instanceof Error ? err.message : 'Search failed');
|
|
71
|
-
setResults(null);
|
|
72
|
-
} finally{
|
|
73
|
-
setIsLoading(false);
|
|
74
|
-
}
|
|
75
|
-
}, [
|
|
16
|
+
const debouncedQuery = useDebounce(query, debounceMs);
|
|
17
|
+
const { error, isLoading, results, search } = useSearch({
|
|
76
18
|
baseUrl,
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
19
|
+
collections,
|
|
20
|
+
minQueryLength,
|
|
21
|
+
onResults,
|
|
22
|
+
onSearch,
|
|
23
|
+
perPage
|
|
24
|
+
});
|
|
81
25
|
useEffect(()=>{
|
|
82
|
-
if (
|
|
83
|
-
|
|
26
|
+
if (debouncedQuery.length >= minQueryLength) {
|
|
27
|
+
void search(debouncedQuery);
|
|
84
28
|
}
|
|
85
|
-
if (query.length >= minQueryLength) {
|
|
86
|
-
debounceRef.current = setTimeout(()=>{
|
|
87
|
-
void performSearch(query);
|
|
88
|
-
void onSearchRef.current?.(query, results || {
|
|
89
|
-
found: 0,
|
|
90
|
-
hits: [],
|
|
91
|
-
page: 1,
|
|
92
|
-
request_params: {
|
|
93
|
-
per_page: 10,
|
|
94
|
-
q: query
|
|
95
|
-
},
|
|
96
|
-
search_cutoff: false,
|
|
97
|
-
search_time_ms: 0
|
|
98
|
-
});
|
|
99
|
-
}, debounceMs);
|
|
100
|
-
} else {
|
|
101
|
-
setResults(null);
|
|
102
|
-
setIsLoading(false);
|
|
103
|
-
}
|
|
104
|
-
return ()=>{
|
|
105
|
-
if (debounceRef.current) {
|
|
106
|
-
clearTimeout(debounceRef.current);
|
|
107
|
-
}
|
|
108
|
-
};
|
|
109
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
110
29
|
}, [
|
|
111
|
-
|
|
112
|
-
debounceMs,
|
|
30
|
+
debouncedQuery,
|
|
113
31
|
minQueryLength,
|
|
114
|
-
|
|
32
|
+
search
|
|
115
33
|
]);
|
|
116
|
-
// Handle input change
|
|
117
34
|
const handleInputChange = (e)=>{
|
|
118
35
|
const value = e.target.value;
|
|
119
36
|
setQuery(value);
|
|
120
37
|
setIsOpen(value.length >= minQueryLength);
|
|
121
38
|
};
|
|
122
|
-
// Handle input focus
|
|
123
39
|
const handleInputFocus = ()=>{
|
|
124
40
|
if (query.length >= minQueryLength) {
|
|
125
41
|
setIsOpen(true);
|
|
126
42
|
}
|
|
127
43
|
};
|
|
128
|
-
// Handle input blur
|
|
129
44
|
const handleInputBlur = (_e)=>{
|
|
130
|
-
// Delay hiding results to allow clicking on them
|
|
131
45
|
setTimeout(()=>{
|
|
132
46
|
if (!resultsRef.current?.contains(document.activeElement)) {
|
|
133
47
|
setIsOpen(false);
|
|
134
48
|
}
|
|
135
49
|
}, 150);
|
|
136
50
|
};
|
|
137
|
-
// Handle result click
|
|
138
51
|
const handleResultClick = (result)=>{
|
|
139
52
|
onResultClick?.(result);
|
|
140
53
|
setIsOpen(false);
|
|
141
54
|
setQuery('');
|
|
142
55
|
};
|
|
143
|
-
// Handle keyboard navigation
|
|
144
56
|
const handleKeyDown = (e)=>{
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
}
|
|
152
|
-
const currentIndex = Array.from(resultItems).findIndex((item)=>item === document.activeElement);
|
|
153
|
-
switch(e.key){
|
|
154
|
-
case 'ArrowDown':
|
|
155
|
-
{
|
|
156
|
-
e.preventDefault();
|
|
157
|
-
const nextIndex = currentIndex < resultItems.length - 1 ? currentIndex + 1 : 0;
|
|
158
|
-
resultItems[nextIndex]?.focus();
|
|
159
|
-
break;
|
|
160
|
-
}
|
|
161
|
-
case 'ArrowUp':
|
|
162
|
-
{
|
|
163
|
-
e.preventDefault();
|
|
164
|
-
const prevIndex = currentIndex > 0 ? currentIndex - 1 : resultItems.length - 1;
|
|
165
|
-
resultItems[prevIndex]?.focus();
|
|
166
|
-
break;
|
|
167
|
-
}
|
|
168
|
-
case 'Enter':
|
|
169
|
-
e.preventDefault();
|
|
170
|
-
if (currentIndex >= 0 && resultItems[currentIndex]) {
|
|
171
|
-
;
|
|
172
|
-
resultItems[currentIndex]?.click();
|
|
173
|
-
}
|
|
174
|
-
break;
|
|
175
|
-
case 'Escape':
|
|
176
|
-
setIsOpen(false);
|
|
177
|
-
inputRef.current?.blur();
|
|
178
|
-
break;
|
|
179
|
-
}
|
|
57
|
+
handleKeyboard(e, {
|
|
58
|
+
inputRef,
|
|
59
|
+
isOpen,
|
|
60
|
+
results,
|
|
61
|
+
resultsRef
|
|
62
|
+
});
|
|
180
63
|
};
|
|
181
64
|
// Default render functions
|
|
182
65
|
const defaultRenderResult = (result, _index)=>{
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type ThemeConfig, type ThemeContextValue } from './themes/types.js';
|
|
2
3
|
interface ThemeProviderProps {
|
|
3
4
|
children: React.ReactNode;
|
|
4
5
|
config: ThemeConfig;
|
|
5
6
|
}
|
|
6
|
-
export declare function ThemeProvider({ children, config }: ThemeProviderProps):
|
|
7
|
+
export declare function ThemeProvider({ children, config }: ThemeProviderProps): React.JSX.Element;
|
|
7
8
|
export declare function useTheme(): ThemeContextValue;
|
|
8
9
|
export {};
|
|
9
10
|
//# sourceMappingURL=ThemeProvider.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/components/ThemeProvider.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ThemeProvider.d.ts","sourceRoot":"","sources":["../../src/components/ThemeProvider.tsx"],"names":[],"mappings":"AAEA,OAAO,KAA6B,MAAM,OAAO,CAAA;AAGjD,OAAO,EAAE,KAAK,WAAW,EAAE,KAAK,iBAAiB,EAAE,MAAM,mBAAmB,CAAA;AAE5E,UAAU,kBAAkB;IAC1B,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAA;IACzB,MAAM,EAAE,WAAW,CAAA;CACpB;AAID,wBAAgB,aAAa,CAAC,EAAE,QAAQ,EAAE,MAAM,EAAE,EAAE,kBAAkB,qBAIrE;AAED,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { createContext, use } from 'react';
|
|
2
|
+
import React, { createContext, use } from 'react';
|
|
3
3
|
import { useThemeConfig } from './themes/hooks.js';
|
|
4
4
|
const ThemeContext = /*#__PURE__*/ createContext(null);
|
|
5
5
|
export function ThemeProvider({ children, config }) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export
|
|
2
|
-
export {
|
|
3
|
-
export
|
|
4
|
-
export { ThemeProvider } from
|
|
5
|
-
export * from
|
|
1
|
+
export { type HeadlessSearchInputProps } from '../lib/headlessSearch.js';
|
|
2
|
+
export { type BaseSearchInputProps, type HealthCheckResponse, type SearchResponse, type SearchResult, type SearchResultProps, type TypesenseSearchConfig, } from '../types.js';
|
|
3
|
+
export { default as HeadlessSearchInput } from './HeadlessSearchInput.js';
|
|
4
|
+
export { ThemeProvider } from './ThemeProvider.js';
|
|
5
|
+
export * from './themes/index.js';
|
|
6
6
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/components/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,0BAA0B,CAAA;AACxE,OAAO,EACL,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,EACxB,KAAK,cAAc,EACnB,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,qBAAqB,GAC3B,MAAM,aAAa,CAAA;AACpB,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,0BAA0B,CAAA;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAA;AAElD,cAAc,mBAAmB,CAAA"}
|
package/dist/components/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { default as HeadlessSearchInput } from
|
|
2
|
-
export { ThemeProvider } from
|
|
3
|
-
export * from
|
|
1
|
+
export { default as HeadlessSearchInput } from './HeadlessSearchInput.js';
|
|
2
|
+
export { ThemeProvider } from './ThemeProvider.js';
|
|
3
|
+
export * from './themes/index.js';
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { Theme, ThemeConfig, ThemeContextValue } from
|
|
1
|
+
import type { Theme, ThemeConfig, ThemeContextValue } from './types.js';
|
|
2
2
|
declare const ThemeContext: import("react").Context<ThemeContextValue | null>;
|
|
3
3
|
/**
|
|
4
4
|
* Hook to access theme context
|
|
@@ -27,19 +27,19 @@ export declare function useThemeClasses(config: ThemeConfig): Record<string, str
|
|
|
27
27
|
/**
|
|
28
28
|
* Hook to get theme-aware color values
|
|
29
29
|
*/
|
|
30
|
-
export declare function useThemeColors(config: ThemeConfig): Theme[
|
|
30
|
+
export declare function useThemeColors(config: ThemeConfig): Theme['colors'];
|
|
31
31
|
/**
|
|
32
32
|
* Hook to get theme-aware spacing values
|
|
33
33
|
*/
|
|
34
|
-
export declare function useThemeSpacing(config: ThemeConfig): Theme[
|
|
34
|
+
export declare function useThemeSpacing(config: ThemeConfig): Theme['spacing'];
|
|
35
35
|
/**
|
|
36
36
|
* Hook to get theme-aware typography values
|
|
37
37
|
*/
|
|
38
|
-
export declare function useThemeTypography(config: ThemeConfig): Theme[
|
|
38
|
+
export declare function useThemeTypography(config: ThemeConfig): Theme['typography'];
|
|
39
39
|
/**
|
|
40
40
|
* Hook to detect system theme preference
|
|
41
41
|
*/
|
|
42
|
-
export declare function useSystemTheme():
|
|
42
|
+
export declare function useSystemTheme(): 'dark' | 'light';
|
|
43
43
|
/**
|
|
44
44
|
* Hook to create auto theme configuration based on system preference
|
|
45
45
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/components/themes/hooks.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAWvE,QAAA,MAAM,YAAY,mDAAgD,CAAA;AAElE;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../../src/components/themes/hooks.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAWvE,QAAA,MAAM,YAAY,mDAAgD,CAAA;AAElE;;GAEG;AACH,wBAAgB,QAAQ,IAAI,iBAAiB,CAM5C;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,iBAAiB,CAoBrE;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAK1E;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,UAAU,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,GAAG,WAAW,CA8B1F;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,WAAW,EACxB,UAAU,EAAE,WAAW,EACvB,MAAM,EAAE,OAAO,GACd,WAAW,CAIb;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc3E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAAC,QAAQ,CAAC,CAKnE;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAAC,SAAS,CAAC,CAKrE;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,WAAW,GAAG,KAAK,CAAC,YAAY,CAAC,CAK3E;AAED;;GAEG;AACH,wBAAgB,cAAc,IAAI,MAAM,GAAG,OAAO,CAQjD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,UAAU,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAM1E;AAED;;GAEG;AACH,wBAAgB,cAAc,CAC5B,aAAa,EAAE,MAAM,EACrB,SAAS,EAAE,OAAO,CAAC,WAAW,CAAC,GAC9B,WAAW,CAOb;AAGD,OAAO,EAAE,YAAY,EAAE,CAAA"}
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
import { createContext, useCallback, useContext, useMemo } from
|
|
3
|
-
import { applyTheme, generateThemeClasses, getThemeVariables, isDarkTheme, isLightTheme, mergeThemeConfig } from
|
|
1
|
+
'use client';
|
|
2
|
+
import { createContext, useCallback, useContext, useMemo } from 'react';
|
|
3
|
+
import { applyTheme, generateThemeClasses, getThemeVariables, isDarkTheme, isLightTheme, mergeThemeConfig } from './utils.js';
|
|
4
4
|
const ThemeContext = createContext(null);
|
|
5
5
|
/**
|
|
6
6
|
* Hook to access theme context
|
|
7
7
|
*/ export function useTheme() {
|
|
8
8
|
const context = useContext(ThemeContext);
|
|
9
9
|
if (!context) {
|
|
10
|
-
throw new Error(
|
|
10
|
+
throw new Error('useTheme must be used within a ThemeProvider');
|
|
11
11
|
}
|
|
12
12
|
return context;
|
|
13
13
|
}
|
|
@@ -60,18 +60,18 @@ const ThemeContext = createContext(null);
|
|
|
60
60
|
spacing: {
|
|
61
61
|
...baseConfig.spacing,
|
|
62
62
|
// Adjust spacing for mobile
|
|
63
|
-
headerPadding:
|
|
64
|
-
inputFontSize:
|
|
65
|
-
inputPadding:
|
|
66
|
-
itemPadding:
|
|
67
|
-
resultsMaxHeight:
|
|
63
|
+
headerPadding: '0.75rem 1rem',
|
|
64
|
+
inputFontSize: '16px',
|
|
65
|
+
inputPadding: '0.875rem 1rem',
|
|
66
|
+
itemPadding: '0.875rem 1rem',
|
|
67
|
+
resultsMaxHeight: '20rem'
|
|
68
68
|
},
|
|
69
69
|
// Disable animations on mobile for better performance
|
|
70
70
|
animations: isMobile ? {
|
|
71
71
|
...baseConfig.animations,
|
|
72
|
-
transitionFast:
|
|
73
|
-
transitionNormal:
|
|
74
|
-
transitionSlow:
|
|
72
|
+
transitionFast: '0s',
|
|
73
|
+
transitionNormal: '0s',
|
|
74
|
+
transitionSlow: '0s'
|
|
75
75
|
} : baseConfig.animations
|
|
76
76
|
};
|
|
77
77
|
return mobileConfig;
|
|
@@ -141,10 +141,10 @@ const ThemeContext = createContext(null);
|
|
|
141
141
|
* Hook to detect system theme preference
|
|
142
142
|
*/ export function useSystemTheme() {
|
|
143
143
|
return useMemo(()=>{
|
|
144
|
-
if (typeof window ===
|
|
145
|
-
return
|
|
144
|
+
if (typeof window === 'undefined') {
|
|
145
|
+
return 'light';
|
|
146
146
|
}
|
|
147
|
-
return window.matchMedia(
|
|
147
|
+
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
|
|
148
148
|
}, []);
|
|
149
149
|
}
|
|
150
150
|
/**
|
|
@@ -152,7 +152,7 @@ const ThemeContext = createContext(null);
|
|
|
152
152
|
*/ export function useAutoTheme(lightTheme, darkTheme) {
|
|
153
153
|
const systemTheme = useSystemTheme();
|
|
154
154
|
return useMemo(()=>{
|
|
155
|
-
return systemTheme ===
|
|
155
|
+
return systemTheme === 'dark' ? darkTheme : lightTheme;
|
|
156
156
|
}, [
|
|
157
157
|
systemTheme,
|
|
158
158
|
lightTheme,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from './hooks.js';
|
|
2
|
+
export * from './themes.js';
|
|
3
|
+
export * from './types.js';
|
|
4
|
+
export * from './utils.js';
|
|
5
5
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
export * from
|
|
2
|
-
export * from
|
|
3
|
-
export * from
|
|
4
|
-
export * from
|
|
1
|
+
export * from './hooks.js';
|
|
2
|
+
export * from './themes.js';
|
|
3
|
+
export * from './types.js';
|
|
4
|
+
export * from './utils.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../../src/components/themes/themes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;
|
|
1
|
+
{"version":3,"file":"themes.d.ts","sourceRoot":"","sources":["../../../src/components/themes/themes.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAA;AA2DvC,eAAO,MAAM,WAAW,EAAE,KAqDzB,CAAA;AAGD,eAAO,MAAM,SAAS,EAAE,KAqDvB,CAAA;AAGD,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAGxC,CAAA;AAGD,eAAO,MAAM,YAAY,OAAc,CAAA"}
|