@tsproxy/react 0.0.1
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/dist/index.d.ts +177 -0
- package/dist/index.js +410 -0
- package/package.json +54 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
export { FacetValue, Hit, SearchClient, SearchRequest, SearchResponse, SearchResponseResult, createSearchClient } from '@tsproxy/js';
|
|
2
|
+
import * as react from 'react';
|
|
3
|
+
import { ElementType, ComponentType, ComponentPropsWithRef, ReactNode } from 'react';
|
|
4
|
+
import * as react_jsx_runtime from 'react/jsx-runtime';
|
|
5
|
+
import { UseRefinementListProps } from 'react-instantsearch';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Override for a single sub-element.
|
|
9
|
+
* - component: replace the default element entirely
|
|
10
|
+
* - props: merge additional props (static object or function of computed props)
|
|
11
|
+
*/
|
|
12
|
+
type Override<DefaultComponent extends ElementType> = {
|
|
13
|
+
component?: ComponentType<ComponentPropsWithRef<DefaultComponent>>;
|
|
14
|
+
props?: Partial<ComponentPropsWithRef<DefaultComponent>> | ((props: ComponentPropsWithRef<DefaultComponent>) => Partial<ComponentPropsWithRef<DefaultComponent>>);
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Build an overrides map from a record of default element types.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* type SearchBoxOverrides = Overrides<{ Root: "div"; Input: "input" }>;
|
|
21
|
+
* // { Root?: Override<"div">; Input?: Override<"input"> }
|
|
22
|
+
*/
|
|
23
|
+
type Overrides<T extends Record<string, ElementType>> = {
|
|
24
|
+
[K in keyof T]?: Override<T[K]>;
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Resolve the component and props for a sub-element, applying any overrides.
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* const root = getOverride("div", overrides?.Root);
|
|
32
|
+
* <root.Component {...root.resolveProps({ className: "default" })} />
|
|
33
|
+
*/
|
|
34
|
+
declare function getOverride<D extends ElementType>(defaultComponent: D, override?: Override<D>): {
|
|
35
|
+
readonly Component: ElementType;
|
|
36
|
+
readonly resolveProps: (defaultProps: ComponentPropsWithRef<D>) => ComponentPropsWithRef<D>;
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
interface LocaleContextValue {
|
|
40
|
+
locale: string | undefined;
|
|
41
|
+
setLocale: (locale: string) => void;
|
|
42
|
+
}
|
|
43
|
+
declare const LocaleContext: react.Context<LocaleContextValue | null>;
|
|
44
|
+
declare function useLocale(): LocaleContextValue;
|
|
45
|
+
interface LocaleProviderProps {
|
|
46
|
+
initialLocale?: string;
|
|
47
|
+
children: ReactNode;
|
|
48
|
+
}
|
|
49
|
+
declare function LocaleProvider({ initialLocale, children }: LocaleProviderProps): react_jsx_runtime.JSX.Element;
|
|
50
|
+
|
|
51
|
+
interface SearchProviderProps {
|
|
52
|
+
serverUrl: string;
|
|
53
|
+
indexName: string;
|
|
54
|
+
locale?: string;
|
|
55
|
+
children: ReactNode;
|
|
56
|
+
}
|
|
57
|
+
declare function SearchProvider({ serverUrl, indexName, locale, children, }: SearchProviderProps): react_jsx_runtime.JSX.Element;
|
|
58
|
+
|
|
59
|
+
type SearchBoxElements = {
|
|
60
|
+
Root: "div";
|
|
61
|
+
Form: "form";
|
|
62
|
+
Input: "input";
|
|
63
|
+
SubmitButton: "button";
|
|
64
|
+
ResetButton: "button";
|
|
65
|
+
};
|
|
66
|
+
interface SearchBoxProps {
|
|
67
|
+
placeholder?: string;
|
|
68
|
+
autoFocus?: boolean;
|
|
69
|
+
overrides?: Overrides<SearchBoxElements>;
|
|
70
|
+
queryHook?: (query: string, search: (value: string) => void) => void;
|
|
71
|
+
}
|
|
72
|
+
declare function SearchBox({ placeholder, autoFocus, overrides, queryHook, }: SearchBoxProps): react_jsx_runtime.JSX.Element;
|
|
73
|
+
|
|
74
|
+
type HitsElements = {
|
|
75
|
+
Root: "div";
|
|
76
|
+
List: "ol";
|
|
77
|
+
Item: "li";
|
|
78
|
+
};
|
|
79
|
+
interface HitsProps {
|
|
80
|
+
hitComponent: (props: {
|
|
81
|
+
hit: Record<string, unknown>;
|
|
82
|
+
}) => ReactNode;
|
|
83
|
+
overrides?: Overrides<HitsElements>;
|
|
84
|
+
}
|
|
85
|
+
declare function Hits({ hitComponent: HitComponent, overrides }: HitsProps): react_jsx_runtime.JSX.Element;
|
|
86
|
+
|
|
87
|
+
type RefinementListElements = {
|
|
88
|
+
Root: "div";
|
|
89
|
+
List: "ul";
|
|
90
|
+
Item: "li";
|
|
91
|
+
Label: "label";
|
|
92
|
+
Checkbox: "input";
|
|
93
|
+
LabelText: "span";
|
|
94
|
+
Count: "span";
|
|
95
|
+
};
|
|
96
|
+
interface RefinementListProps extends UseRefinementListProps {
|
|
97
|
+
overrides?: Overrides<RefinementListElements>;
|
|
98
|
+
}
|
|
99
|
+
declare function RefinementList({ overrides, ...hookProps }: RefinementListProps): react_jsx_runtime.JSX.Element;
|
|
100
|
+
|
|
101
|
+
type PaginationElements = {
|
|
102
|
+
Root: "nav";
|
|
103
|
+
List: "ul";
|
|
104
|
+
Item: "li";
|
|
105
|
+
Link: "a";
|
|
106
|
+
};
|
|
107
|
+
interface PaginationProps {
|
|
108
|
+
padding?: number;
|
|
109
|
+
overrides?: Overrides<PaginationElements>;
|
|
110
|
+
}
|
|
111
|
+
declare function Pagination({ padding, overrides }: PaginationProps): react_jsx_runtime.JSX.Element | null;
|
|
112
|
+
|
|
113
|
+
type StatsElements = {
|
|
114
|
+
Root: "div";
|
|
115
|
+
Text: "span";
|
|
116
|
+
};
|
|
117
|
+
interface StatsProps {
|
|
118
|
+
overrides?: Overrides<StatsElements>;
|
|
119
|
+
formatText?: (nbHits: number, processingTimeMS: number) => string;
|
|
120
|
+
}
|
|
121
|
+
declare function Stats({ overrides, formatText }: StatsProps): react_jsx_runtime.JSX.Element;
|
|
122
|
+
|
|
123
|
+
type SortByElements = {
|
|
124
|
+
Root: "div";
|
|
125
|
+
Select: "select";
|
|
126
|
+
Option: "option";
|
|
127
|
+
};
|
|
128
|
+
interface SortByItem {
|
|
129
|
+
value: string;
|
|
130
|
+
label: string;
|
|
131
|
+
}
|
|
132
|
+
interface SortByProps {
|
|
133
|
+
items: SortByItem[];
|
|
134
|
+
overrides?: Overrides<SortByElements>;
|
|
135
|
+
}
|
|
136
|
+
declare function SortBy({ items, overrides }: SortByProps): react_jsx_runtime.JSX.Element;
|
|
137
|
+
|
|
138
|
+
type LocaleSelectorElements = {
|
|
139
|
+
Root: "div";
|
|
140
|
+
Select: "select";
|
|
141
|
+
Option: "option";
|
|
142
|
+
};
|
|
143
|
+
interface LocaleOption {
|
|
144
|
+
code: string;
|
|
145
|
+
label: string;
|
|
146
|
+
}
|
|
147
|
+
interface LocaleSelectorProps {
|
|
148
|
+
locales: LocaleOption[];
|
|
149
|
+
overrides?: Overrides<LocaleSelectorElements>;
|
|
150
|
+
}
|
|
151
|
+
declare function LocaleSelector({ locales, overrides }: LocaleSelectorProps): react_jsx_runtime.JSX.Element;
|
|
152
|
+
|
|
153
|
+
type NoResultsElements = {
|
|
154
|
+
Root: "div";
|
|
155
|
+
Title: "p";
|
|
156
|
+
Message: "p";
|
|
157
|
+
};
|
|
158
|
+
interface NoResultsProps {
|
|
159
|
+
title?: string;
|
|
160
|
+
message?: string;
|
|
161
|
+
children?: ReactNode;
|
|
162
|
+
overrides?: Overrides<NoResultsElements>;
|
|
163
|
+
}
|
|
164
|
+
declare function NoResults({ title, message, children, overrides, }: NoResultsProps): react_jsx_runtime.JSX.Element | null;
|
|
165
|
+
|
|
166
|
+
type HitsSkeletonElements = {
|
|
167
|
+
Root: "div";
|
|
168
|
+
List: "div";
|
|
169
|
+
Item: "div";
|
|
170
|
+
};
|
|
171
|
+
interface HitsSkeletonProps {
|
|
172
|
+
count?: number;
|
|
173
|
+
overrides?: Overrides<HitsSkeletonElements>;
|
|
174
|
+
}
|
|
175
|
+
declare function HitsSkeleton({ count, overrides }: HitsSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
176
|
+
|
|
177
|
+
export { Hits, type HitsElements, type HitsProps, HitsSkeleton, type HitsSkeletonElements, type HitsSkeletonProps, LocaleContext, type LocaleOption, LocaleProvider, LocaleSelector, type LocaleSelectorElements, type LocaleSelectorProps, NoResults, type NoResultsElements, type NoResultsProps, type Override, type Overrides, Pagination, type PaginationElements, type PaginationProps, RefinementList, type RefinementListElements, type RefinementListProps, SearchBox, type SearchBoxElements, type SearchBoxProps, SearchProvider, SortBy, type SortByElements, type SortByItem, type SortByProps, Stats, type StatsElements, type StatsProps, getOverride, useLocale };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
// src/index.ts
|
|
2
|
+
import { createSearchClient as createSearchClient2 } from "@tsproxy/js";
|
|
3
|
+
|
|
4
|
+
// src/overrides/getOverride.ts
|
|
5
|
+
function getOverride(defaultComponent, override) {
|
|
6
|
+
const Component = override?.component ?? defaultComponent;
|
|
7
|
+
function resolveProps(defaultProps) {
|
|
8
|
+
if (!override?.props) return defaultProps;
|
|
9
|
+
const extra = typeof override.props === "function" ? override.props(defaultProps) : override.props;
|
|
10
|
+
return { ...defaultProps, ...extra };
|
|
11
|
+
}
|
|
12
|
+
return { Component, resolveProps };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
// src/context/LocaleContext.tsx
|
|
16
|
+
import { createContext, useContext, useState, useCallback, useMemo } from "react";
|
|
17
|
+
import { jsx } from "react/jsx-runtime";
|
|
18
|
+
var LocaleContext = createContext(null);
|
|
19
|
+
function useLocale() {
|
|
20
|
+
const context = useContext(LocaleContext);
|
|
21
|
+
if (!context) {
|
|
22
|
+
throw new Error("useLocale must be used within a LocaleProvider or SearchProvider");
|
|
23
|
+
}
|
|
24
|
+
return context;
|
|
25
|
+
}
|
|
26
|
+
function LocaleProvider({ initialLocale, children }) {
|
|
27
|
+
const [locale, setLocaleState] = useState(initialLocale);
|
|
28
|
+
const setLocale = useCallback((newLocale) => {
|
|
29
|
+
setLocaleState(newLocale);
|
|
30
|
+
}, []);
|
|
31
|
+
const value = useMemo(
|
|
32
|
+
() => ({ locale, setLocale }),
|
|
33
|
+
[locale, setLocale]
|
|
34
|
+
);
|
|
35
|
+
return /* @__PURE__ */ jsx(LocaleContext.Provider, { value, children });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// src/components/SearchProvider.tsx
|
|
39
|
+
import { useMemo as useMemo2 } from "react";
|
|
40
|
+
import { InstantSearch } from "react-instantsearch";
|
|
41
|
+
import { createSearchClient } from "@tsproxy/js";
|
|
42
|
+
import { jsx as jsx2 } from "react/jsx-runtime";
|
|
43
|
+
function SearchProviderInner({
|
|
44
|
+
serverUrl,
|
|
45
|
+
indexName,
|
|
46
|
+
children
|
|
47
|
+
}) {
|
|
48
|
+
const { locale } = useLocale();
|
|
49
|
+
const searchClient = useMemo2(
|
|
50
|
+
() => createSearchClient({
|
|
51
|
+
url: serverUrl,
|
|
52
|
+
...locale ? { locale } : {},
|
|
53
|
+
cache: true
|
|
54
|
+
}),
|
|
55
|
+
[serverUrl, locale]
|
|
56
|
+
);
|
|
57
|
+
return /* @__PURE__ */ jsx2(
|
|
58
|
+
InstantSearch,
|
|
59
|
+
{
|
|
60
|
+
searchClient,
|
|
61
|
+
indexName,
|
|
62
|
+
children
|
|
63
|
+
}
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
function SearchProvider({
|
|
67
|
+
serverUrl,
|
|
68
|
+
indexName,
|
|
69
|
+
locale,
|
|
70
|
+
children
|
|
71
|
+
}) {
|
|
72
|
+
return /* @__PURE__ */ jsx2(LocaleProvider, { initialLocale: locale, children: /* @__PURE__ */ jsx2(SearchProviderInner, { serverUrl, indexName, children }) });
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// src/components/SearchBox.tsx
|
|
76
|
+
import { useSearchBox } from "react-instantsearch";
|
|
77
|
+
import { useRef, useState as useState2, useEffect } from "react";
|
|
78
|
+
import { jsx as jsx3, jsxs } from "react/jsx-runtime";
|
|
79
|
+
function SearchBox({
|
|
80
|
+
placeholder = "Search...",
|
|
81
|
+
autoFocus = false,
|
|
82
|
+
overrides,
|
|
83
|
+
queryHook
|
|
84
|
+
}) {
|
|
85
|
+
const { query, refine, clear } = useSearchBox({ queryHook });
|
|
86
|
+
const inputRef = useRef(null);
|
|
87
|
+
const [inputValue, setInputValue] = useState2(query);
|
|
88
|
+
const isTypingRef = useRef(false);
|
|
89
|
+
useEffect(() => {
|
|
90
|
+
if (!isTypingRef.current) {
|
|
91
|
+
setInputValue(query);
|
|
92
|
+
}
|
|
93
|
+
}, [query]);
|
|
94
|
+
const root = getOverride("div", overrides?.Root);
|
|
95
|
+
const form = getOverride("form", overrides?.Form);
|
|
96
|
+
const input = getOverride("input", overrides?.Input);
|
|
97
|
+
const submit = getOverride("button", overrides?.SubmitButton);
|
|
98
|
+
const reset = getOverride("button", overrides?.ResetButton);
|
|
99
|
+
const handleSubmit = (e) => {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
};
|
|
102
|
+
const handleReset = () => {
|
|
103
|
+
setInputValue("");
|
|
104
|
+
clear();
|
|
105
|
+
inputRef.current?.focus();
|
|
106
|
+
};
|
|
107
|
+
const handleChange = (e) => {
|
|
108
|
+
const value = e.currentTarget.value;
|
|
109
|
+
setInputValue(value);
|
|
110
|
+
isTypingRef.current = true;
|
|
111
|
+
refine(value);
|
|
112
|
+
setTimeout(() => {
|
|
113
|
+
isTypingRef.current = false;
|
|
114
|
+
}, 500);
|
|
115
|
+
};
|
|
116
|
+
return /* @__PURE__ */ jsx3(root.Component, { ...root.resolveProps({}), children: /* @__PURE__ */ jsxs(
|
|
117
|
+
form.Component,
|
|
118
|
+
{
|
|
119
|
+
...form.resolveProps({
|
|
120
|
+
onSubmit: handleSubmit,
|
|
121
|
+
role: "search",
|
|
122
|
+
noValidate: true
|
|
123
|
+
}),
|
|
124
|
+
children: [
|
|
125
|
+
/* @__PURE__ */ jsx3(
|
|
126
|
+
input.Component,
|
|
127
|
+
{
|
|
128
|
+
...input.resolveProps({
|
|
129
|
+
ref: inputRef,
|
|
130
|
+
type: "search",
|
|
131
|
+
placeholder,
|
|
132
|
+
autoFocus,
|
|
133
|
+
value: inputValue,
|
|
134
|
+
onChange: handleChange,
|
|
135
|
+
autoComplete: "off",
|
|
136
|
+
autoCorrect: "off",
|
|
137
|
+
spellCheck: false
|
|
138
|
+
})
|
|
139
|
+
}
|
|
140
|
+
),
|
|
141
|
+
/* @__PURE__ */ jsx3(
|
|
142
|
+
submit.Component,
|
|
143
|
+
{
|
|
144
|
+
...submit.resolveProps({ type: "submit", children: "Search" })
|
|
145
|
+
}
|
|
146
|
+
),
|
|
147
|
+
/* @__PURE__ */ jsx3(
|
|
148
|
+
reset.Component,
|
|
149
|
+
{
|
|
150
|
+
...reset.resolveProps({
|
|
151
|
+
type: "reset",
|
|
152
|
+
onClick: handleReset,
|
|
153
|
+
hidden: !inputValue,
|
|
154
|
+
children: "Reset"
|
|
155
|
+
})
|
|
156
|
+
}
|
|
157
|
+
)
|
|
158
|
+
]
|
|
159
|
+
}
|
|
160
|
+
) });
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// src/components/Hits.tsx
|
|
164
|
+
import { useHits } from "react-instantsearch";
|
|
165
|
+
import { jsx as jsx4 } from "react/jsx-runtime";
|
|
166
|
+
function Hits({ hitComponent: HitComponent, overrides }) {
|
|
167
|
+
const { items } = useHits();
|
|
168
|
+
const root = getOverride("div", overrides?.Root);
|
|
169
|
+
const list = getOverride("ol", overrides?.List);
|
|
170
|
+
const item = getOverride("li", overrides?.Item);
|
|
171
|
+
return /* @__PURE__ */ jsx4(root.Component, { ...root.resolveProps({}), children: /* @__PURE__ */ jsx4(list.Component, { ...list.resolveProps({}), children: items.map((hit) => /* @__PURE__ */ jsx4(item.Component, { ...item.resolveProps({}), children: /* @__PURE__ */ jsx4(HitComponent, { hit }) }, hit.objectID)) }) });
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// src/components/RefinementList.tsx
|
|
175
|
+
import { useRefinementList } from "react-instantsearch";
|
|
176
|
+
import { jsx as jsx5, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
177
|
+
function RefinementList({ overrides, ...hookProps }) {
|
|
178
|
+
const { items, refine, canToggleShowMore, isShowingMore, toggleShowMore } = useRefinementList(hookProps);
|
|
179
|
+
const root = getOverride("div", overrides?.Root);
|
|
180
|
+
const list = getOverride("ul", overrides?.List);
|
|
181
|
+
const item = getOverride("li", overrides?.Item);
|
|
182
|
+
const label = getOverride("label", overrides?.Label);
|
|
183
|
+
const checkbox = getOverride("input", overrides?.Checkbox);
|
|
184
|
+
const labelText = getOverride("span", overrides?.LabelText);
|
|
185
|
+
const count = getOverride("span", overrides?.Count);
|
|
186
|
+
return /* @__PURE__ */ jsxs2(root.Component, { ...root.resolveProps({}), children: [
|
|
187
|
+
/* @__PURE__ */ jsx5(list.Component, { ...list.resolveProps({}), children: items.map((facetItem) => /* @__PURE__ */ jsx5(
|
|
188
|
+
item.Component,
|
|
189
|
+
{
|
|
190
|
+
...item.resolveProps({
|
|
191
|
+
"data-refined": facetItem.isRefined || void 0
|
|
192
|
+
}),
|
|
193
|
+
children: /* @__PURE__ */ jsxs2(label.Component, { ...label.resolveProps({}), children: [
|
|
194
|
+
/* @__PURE__ */ jsx5(
|
|
195
|
+
checkbox.Component,
|
|
196
|
+
{
|
|
197
|
+
...checkbox.resolveProps({
|
|
198
|
+
type: "checkbox",
|
|
199
|
+
checked: facetItem.isRefined,
|
|
200
|
+
onChange: () => refine(facetItem.value)
|
|
201
|
+
})
|
|
202
|
+
}
|
|
203
|
+
),
|
|
204
|
+
/* @__PURE__ */ jsx5(
|
|
205
|
+
labelText.Component,
|
|
206
|
+
{
|
|
207
|
+
...labelText.resolveProps({ children: facetItem.label })
|
|
208
|
+
}
|
|
209
|
+
),
|
|
210
|
+
/* @__PURE__ */ jsx5(
|
|
211
|
+
count.Component,
|
|
212
|
+
{
|
|
213
|
+
...count.resolveProps({ children: facetItem.count })
|
|
214
|
+
}
|
|
215
|
+
)
|
|
216
|
+
] })
|
|
217
|
+
},
|
|
218
|
+
facetItem.value
|
|
219
|
+
)) }),
|
|
220
|
+
canToggleShowMore && /* @__PURE__ */ jsx5("button", { type: "button", onClick: toggleShowMore, children: isShowingMore ? "Show less" : "Show more" })
|
|
221
|
+
] });
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// src/components/Pagination.tsx
|
|
225
|
+
import { usePagination } from "react-instantsearch";
|
|
226
|
+
import { jsx as jsx6, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
227
|
+
function Pagination({ padding = 3, overrides }) {
|
|
228
|
+
const {
|
|
229
|
+
pages,
|
|
230
|
+
currentRefinement,
|
|
231
|
+
nbPages,
|
|
232
|
+
refine,
|
|
233
|
+
isFirstPage,
|
|
234
|
+
isLastPage
|
|
235
|
+
} = usePagination({ padding });
|
|
236
|
+
const root = getOverride("nav", overrides?.Root);
|
|
237
|
+
const list = getOverride("ul", overrides?.List);
|
|
238
|
+
const item = getOverride("li", overrides?.Item);
|
|
239
|
+
const link = getOverride("a", overrides?.Link);
|
|
240
|
+
if (nbPages <= 1) return null;
|
|
241
|
+
function renderItem(label, page, disabled, isCurrent = false) {
|
|
242
|
+
return /* @__PURE__ */ jsx6(
|
|
243
|
+
item.Component,
|
|
244
|
+
{
|
|
245
|
+
...item.resolveProps({
|
|
246
|
+
"data-current": isCurrent || void 0,
|
|
247
|
+
"data-disabled": disabled || void 0
|
|
248
|
+
}),
|
|
249
|
+
children: /* @__PURE__ */ jsx6(
|
|
250
|
+
link.Component,
|
|
251
|
+
{
|
|
252
|
+
...link.resolveProps({
|
|
253
|
+
href: "#",
|
|
254
|
+
"aria-label": label,
|
|
255
|
+
"aria-current": isCurrent ? "page" : void 0,
|
|
256
|
+
onClick: (e) => {
|
|
257
|
+
e.preventDefault();
|
|
258
|
+
if (!disabled) refine(page);
|
|
259
|
+
},
|
|
260
|
+
children: label
|
|
261
|
+
})
|
|
262
|
+
}
|
|
263
|
+
)
|
|
264
|
+
},
|
|
265
|
+
label
|
|
266
|
+
);
|
|
267
|
+
}
|
|
268
|
+
return /* @__PURE__ */ jsx6(root.Component, { ...root.resolveProps({ "aria-label": "Pagination" }), children: /* @__PURE__ */ jsxs3(list.Component, { ...list.resolveProps({}), children: [
|
|
269
|
+
renderItem("\xAB", 0, isFirstPage),
|
|
270
|
+
renderItem("\u2039", currentRefinement - 1, isFirstPage),
|
|
271
|
+
pages.map(
|
|
272
|
+
(page) => renderItem(
|
|
273
|
+
String(page + 1),
|
|
274
|
+
page,
|
|
275
|
+
false,
|
|
276
|
+
page === currentRefinement
|
|
277
|
+
)
|
|
278
|
+
),
|
|
279
|
+
renderItem("\u203A", currentRefinement + 1, isLastPage),
|
|
280
|
+
renderItem("\xBB", nbPages - 1, isLastPage)
|
|
281
|
+
] }) });
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
// src/components/Stats.tsx
|
|
285
|
+
import { useStats } from "react-instantsearch";
|
|
286
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
287
|
+
function Stats({ overrides, formatText }) {
|
|
288
|
+
const { nbHits, processingTimeMS } = useStats();
|
|
289
|
+
const root = getOverride("div", overrides?.Root);
|
|
290
|
+
const text = getOverride("span", overrides?.Text);
|
|
291
|
+
const content = formatText ? formatText(nbHits ?? 0, processingTimeMS ?? 0) : `${(nbHits ?? 0).toLocaleString()} results found in ${processingTimeMS ?? 0}ms`;
|
|
292
|
+
return /* @__PURE__ */ jsx7(root.Component, { ...root.resolveProps({}), children: /* @__PURE__ */ jsx7(text.Component, { ...text.resolveProps({ children: content }) }) });
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
// src/components/SortBy.tsx
|
|
296
|
+
import { useSortBy } from "react-instantsearch";
|
|
297
|
+
import { jsx as jsx8 } from "react/jsx-runtime";
|
|
298
|
+
function SortBy({ items, overrides }) {
|
|
299
|
+
const { currentRefinement, refine } = useSortBy({ items });
|
|
300
|
+
const root = getOverride("div", overrides?.Root);
|
|
301
|
+
const select = getOverride("select", overrides?.Select);
|
|
302
|
+
const option = getOverride("option", overrides?.Option);
|
|
303
|
+
return /* @__PURE__ */ jsx8(root.Component, { ...root.resolveProps({}), children: /* @__PURE__ */ jsx8(
|
|
304
|
+
select.Component,
|
|
305
|
+
{
|
|
306
|
+
...select.resolveProps({
|
|
307
|
+
value: currentRefinement,
|
|
308
|
+
onChange: (e) => refine(e.target.value),
|
|
309
|
+
"aria-label": "Sort by"
|
|
310
|
+
}),
|
|
311
|
+
children: items.map((sortItem) => /* @__PURE__ */ jsx8(
|
|
312
|
+
option.Component,
|
|
313
|
+
{
|
|
314
|
+
...option.resolveProps({
|
|
315
|
+
value: sortItem.value,
|
|
316
|
+
children: sortItem.label
|
|
317
|
+
})
|
|
318
|
+
},
|
|
319
|
+
sortItem.value
|
|
320
|
+
))
|
|
321
|
+
}
|
|
322
|
+
) });
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// src/components/LocaleSelector.tsx
|
|
326
|
+
import { jsx as jsx9 } from "react/jsx-runtime";
|
|
327
|
+
function LocaleSelector({ locales, overrides }) {
|
|
328
|
+
const { locale, setLocale } = useLocale();
|
|
329
|
+
const root = getOverride("div", overrides?.Root);
|
|
330
|
+
const select = getOverride("select", overrides?.Select);
|
|
331
|
+
const option = getOverride("option", overrides?.Option);
|
|
332
|
+
return /* @__PURE__ */ jsx9(root.Component, { ...root.resolveProps({}), children: /* @__PURE__ */ jsx9(
|
|
333
|
+
select.Component,
|
|
334
|
+
{
|
|
335
|
+
...select.resolveProps({
|
|
336
|
+
value: locale ?? "",
|
|
337
|
+
onChange: (e) => setLocale(e.target.value),
|
|
338
|
+
"aria-label": "Select locale"
|
|
339
|
+
}),
|
|
340
|
+
children: locales.map((loc) => /* @__PURE__ */ jsx9(
|
|
341
|
+
option.Component,
|
|
342
|
+
{
|
|
343
|
+
...option.resolveProps({
|
|
344
|
+
value: loc.code,
|
|
345
|
+
children: loc.label
|
|
346
|
+
})
|
|
347
|
+
},
|
|
348
|
+
loc.code
|
|
349
|
+
))
|
|
350
|
+
}
|
|
351
|
+
) });
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
// src/components/NoResults.tsx
|
|
355
|
+
import { useInstantSearch } from "react-instantsearch";
|
|
356
|
+
import { jsx as jsx10, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
357
|
+
function NoResults({
|
|
358
|
+
title = "No results found",
|
|
359
|
+
message = "Try adjusting your search or filters.",
|
|
360
|
+
children,
|
|
361
|
+
overrides
|
|
362
|
+
}) {
|
|
363
|
+
const { results } = useInstantSearch();
|
|
364
|
+
if (results.__isArtificial || results.nbHits > 0) {
|
|
365
|
+
return null;
|
|
366
|
+
}
|
|
367
|
+
const root = getOverride("div", overrides?.Root);
|
|
368
|
+
const titleEl = getOverride("p", overrides?.Title);
|
|
369
|
+
const messageEl = getOverride("p", overrides?.Message);
|
|
370
|
+
if (children) {
|
|
371
|
+
return /* @__PURE__ */ jsx10(root.Component, { ...root.resolveProps({}), children });
|
|
372
|
+
}
|
|
373
|
+
return /* @__PURE__ */ jsxs4(root.Component, { ...root.resolveProps({}), children: [
|
|
374
|
+
/* @__PURE__ */ jsx10(titleEl.Component, { ...titleEl.resolveProps({ children: title }) }),
|
|
375
|
+
/* @__PURE__ */ jsx10(messageEl.Component, { ...messageEl.resolveProps({ children: message }) })
|
|
376
|
+
] });
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// src/components/HitsSkeleton.tsx
|
|
380
|
+
import { jsx as jsx11, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
381
|
+
function HitsSkeleton({ count = 8, overrides }) {
|
|
382
|
+
const root = getOverride("div", overrides?.Root);
|
|
383
|
+
const list = getOverride("div", overrides?.List);
|
|
384
|
+
const item = getOverride("div", overrides?.Item);
|
|
385
|
+
return /* @__PURE__ */ jsx11(root.Component, { ...root.resolveProps({ role: "status", "aria-label": "Loading" }), children: /* @__PURE__ */ jsx11(list.Component, { ...list.resolveProps({}), children: Array.from({ length: count }, (_, i) => /* @__PURE__ */ jsx11(item.Component, { ...item.resolveProps({}), children: /* @__PURE__ */ jsxs5("div", { className: "animate-pulse", children: [
|
|
386
|
+
/* @__PURE__ */ jsx11("div", { className: "aspect-square rounded-lg bg-gray-200" }),
|
|
387
|
+
/* @__PURE__ */ jsxs5("div", { className: "mt-2 space-y-2", children: [
|
|
388
|
+
/* @__PURE__ */ jsx11("div", { className: "h-4 w-3/4 rounded bg-gray-200" }),
|
|
389
|
+
/* @__PURE__ */ jsx11("div", { className: "h-3 w-1/2 rounded bg-gray-200" }),
|
|
390
|
+
/* @__PURE__ */ jsx11("div", { className: "h-5 w-1/3 rounded bg-gray-200" })
|
|
391
|
+
] })
|
|
392
|
+
] }) }, i)) }) });
|
|
393
|
+
}
|
|
394
|
+
export {
|
|
395
|
+
Hits,
|
|
396
|
+
HitsSkeleton,
|
|
397
|
+
LocaleContext,
|
|
398
|
+
LocaleProvider,
|
|
399
|
+
LocaleSelector,
|
|
400
|
+
NoResults,
|
|
401
|
+
Pagination,
|
|
402
|
+
RefinementList,
|
|
403
|
+
SearchBox,
|
|
404
|
+
SearchProvider,
|
|
405
|
+
SortBy,
|
|
406
|
+
Stats,
|
|
407
|
+
createSearchClient2 as createSearchClient,
|
|
408
|
+
getOverride,
|
|
409
|
+
useLocale
|
|
410
|
+
};
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tsproxy/react",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "Headless React components for tsproxy with BaseUI-style overrides",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/index.js",
|
|
7
|
+
"types": "./dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"publishConfig": {
|
|
18
|
+
"access": "public"
|
|
19
|
+
},
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "https://github.com/akshitkrnagpal/tsproxy.git",
|
|
23
|
+
"directory": "packages/web"
|
|
24
|
+
},
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"keywords": [
|
|
27
|
+
"typesense",
|
|
28
|
+
"react",
|
|
29
|
+
"instantsearch",
|
|
30
|
+
"headless",
|
|
31
|
+
"search"
|
|
32
|
+
],
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@tsproxy/js": "0.0.1"
|
|
35
|
+
},
|
|
36
|
+
"peerDependencies": {
|
|
37
|
+
"react": "^18.0.0 || ^19.0.0",
|
|
38
|
+
"react-dom": "^18.0.0 || ^19.0.0",
|
|
39
|
+
"react-instantsearch": "^7.0.0"
|
|
40
|
+
},
|
|
41
|
+
"devDependencies": {
|
|
42
|
+
"@types/react": "^18.3.0",
|
|
43
|
+
"@types/react-dom": "^18.3.0",
|
|
44
|
+
"react": "^18.3.0",
|
|
45
|
+
"react-dom": "^18.3.0",
|
|
46
|
+
"react-instantsearch": "^7.29.0",
|
|
47
|
+
"tsup": "^8.4.0",
|
|
48
|
+
"typescript": "^5.5.3"
|
|
49
|
+
},
|
|
50
|
+
"scripts": {
|
|
51
|
+
"build": "tsup src/index.ts --format esm --dts --external react --external react-dom --external react-instantsearch --external @tsproxy/js --tsconfig tsconfig.build.json",
|
|
52
|
+
"typecheck": "tsc --noEmit"
|
|
53
|
+
}
|
|
54
|
+
}
|