@tsproxy/react 0.0.2 → 0.0.3
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 +24 -1
- package/dist/index.js +144 -0
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -174,4 +174,27 @@ interface HitsSkeletonProps {
|
|
|
174
174
|
}
|
|
175
175
|
declare function HitsSkeleton({ count, overrides }: HitsSkeletonProps): react_jsx_runtime.JSX.Element;
|
|
176
176
|
|
|
177
|
-
|
|
177
|
+
type AutocompleteElements = {
|
|
178
|
+
Root: "div";
|
|
179
|
+
Input: "input";
|
|
180
|
+
List: "ul";
|
|
181
|
+
Item: "li";
|
|
182
|
+
Highlight: "span";
|
|
183
|
+
};
|
|
184
|
+
interface Suggestion {
|
|
185
|
+
objectID: string;
|
|
186
|
+
query: string;
|
|
187
|
+
highlight: string;
|
|
188
|
+
}
|
|
189
|
+
interface AutocompleteProps {
|
|
190
|
+
serverUrl: string;
|
|
191
|
+
collection?: string;
|
|
192
|
+
limit?: number;
|
|
193
|
+
placeholder?: string;
|
|
194
|
+
debounce?: number;
|
|
195
|
+
onSelect?: (suggestion: Suggestion) => void;
|
|
196
|
+
overrides?: Overrides<AutocompleteElements>;
|
|
197
|
+
}
|
|
198
|
+
declare function Autocomplete({ serverUrl, collection, limit, placeholder, debounce, onSelect, overrides, }: AutocompleteProps): react_jsx_runtime.JSX.Element;
|
|
199
|
+
|
|
200
|
+
export { Autocomplete, type AutocompleteElements, type AutocompleteProps, 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, type Suggestion, getOverride, useLocale };
|
package/dist/index.js
CHANGED
|
@@ -376,7 +376,151 @@ function HitsSkeleton({ count = 8, overrides }) {
|
|
|
376
376
|
] })
|
|
377
377
|
] }) }, i)) }) });
|
|
378
378
|
}
|
|
379
|
+
|
|
380
|
+
// src/components/Autocomplete.tsx
|
|
381
|
+
import { useState as useState3, useRef as useRef2, useEffect as useEffect2, useCallback as useCallback2 } from "react";
|
|
382
|
+
import { jsx as jsx12, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
383
|
+
function Autocomplete({
|
|
384
|
+
serverUrl,
|
|
385
|
+
collection = "products",
|
|
386
|
+
limit = 5,
|
|
387
|
+
placeholder = "Search...",
|
|
388
|
+
debounce = 200,
|
|
389
|
+
onSelect,
|
|
390
|
+
overrides
|
|
391
|
+
}) {
|
|
392
|
+
const [query, setQuery] = useState3("");
|
|
393
|
+
const [suggestions, setSuggestions] = useState3([]);
|
|
394
|
+
const [open, setOpen] = useState3(false);
|
|
395
|
+
const [activeIndex, setActiveIndex] = useState3(-1);
|
|
396
|
+
const timerRef = useRef2(void 0);
|
|
397
|
+
const inputRef = useRef2(null);
|
|
398
|
+
const root = getOverride("div", overrides?.Root);
|
|
399
|
+
const input = getOverride("input", overrides?.Input);
|
|
400
|
+
const list = getOverride("ul", overrides?.List);
|
|
401
|
+
const item = getOverride("li", overrides?.Item);
|
|
402
|
+
const highlight = getOverride("span", overrides?.Highlight);
|
|
403
|
+
const fetchSuggestions = useCallback2(
|
|
404
|
+
async (q) => {
|
|
405
|
+
if (!q.trim()) {
|
|
406
|
+
setSuggestions([]);
|
|
407
|
+
setOpen(false);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
try {
|
|
411
|
+
const res = await fetch(
|
|
412
|
+
`${serverUrl}/api/suggestions?q=${encodeURIComponent(q)}&collection=${collection}&limit=${limit}`
|
|
413
|
+
);
|
|
414
|
+
const data = await res.json();
|
|
415
|
+
setSuggestions(data.suggestions || []);
|
|
416
|
+
setOpen((data.suggestions || []).length > 0);
|
|
417
|
+
setActiveIndex(-1);
|
|
418
|
+
} catch {
|
|
419
|
+
setSuggestions([]);
|
|
420
|
+
}
|
|
421
|
+
},
|
|
422
|
+
[serverUrl, collection, limit]
|
|
423
|
+
);
|
|
424
|
+
const handleChange = (e) => {
|
|
425
|
+
const value = e.target.value;
|
|
426
|
+
setQuery(value);
|
|
427
|
+
clearTimeout(timerRef.current);
|
|
428
|
+
timerRef.current = setTimeout(() => fetchSuggestions(value), debounce);
|
|
429
|
+
};
|
|
430
|
+
const handleSelect = (suggestion) => {
|
|
431
|
+
setQuery(suggestion.query);
|
|
432
|
+
setOpen(false);
|
|
433
|
+
onSelect?.(suggestion);
|
|
434
|
+
};
|
|
435
|
+
const handleKeyDown = (e) => {
|
|
436
|
+
if (!open) return;
|
|
437
|
+
if (e.key === "ArrowDown") {
|
|
438
|
+
e.preventDefault();
|
|
439
|
+
setActiveIndex((i) => Math.min(i + 1, suggestions.length - 1));
|
|
440
|
+
} else if (e.key === "ArrowUp") {
|
|
441
|
+
e.preventDefault();
|
|
442
|
+
setActiveIndex((i) => Math.max(i - 1, 0));
|
|
443
|
+
} else if (e.key === "Enter" && activeIndex >= 0) {
|
|
444
|
+
e.preventDefault();
|
|
445
|
+
const s = suggestions[activeIndex];
|
|
446
|
+
if (s) handleSelect(s);
|
|
447
|
+
} else if (e.key === "Escape") {
|
|
448
|
+
setOpen(false);
|
|
449
|
+
}
|
|
450
|
+
};
|
|
451
|
+
useEffect2(() => {
|
|
452
|
+
const handleClickOutside = () => setOpen(false);
|
|
453
|
+
document.addEventListener("click", handleClickOutside);
|
|
454
|
+
return () => document.removeEventListener("click", handleClickOutside);
|
|
455
|
+
}, []);
|
|
456
|
+
return /* @__PURE__ */ jsxs6(
|
|
457
|
+
root.Component,
|
|
458
|
+
{
|
|
459
|
+
...root.resolveProps({
|
|
460
|
+
style: { position: "relative" },
|
|
461
|
+
onClick: (e) => e.stopPropagation()
|
|
462
|
+
}),
|
|
463
|
+
children: [
|
|
464
|
+
/* @__PURE__ */ jsx12(
|
|
465
|
+
input.Component,
|
|
466
|
+
{
|
|
467
|
+
...input.resolveProps({
|
|
468
|
+
ref: inputRef,
|
|
469
|
+
type: "search",
|
|
470
|
+
value: query,
|
|
471
|
+
onChange: handleChange,
|
|
472
|
+
onKeyDown: handleKeyDown,
|
|
473
|
+
onFocus: () => suggestions.length > 0 && setOpen(true),
|
|
474
|
+
placeholder,
|
|
475
|
+
autoComplete: "off",
|
|
476
|
+
role: "combobox",
|
|
477
|
+
"aria-expanded": open,
|
|
478
|
+
"aria-autocomplete": "list"
|
|
479
|
+
})
|
|
480
|
+
}
|
|
481
|
+
),
|
|
482
|
+
open && suggestions.length > 0 && /* @__PURE__ */ jsx12(
|
|
483
|
+
list.Component,
|
|
484
|
+
{
|
|
485
|
+
...list.resolveProps({
|
|
486
|
+
role: "listbox",
|
|
487
|
+
style: {
|
|
488
|
+
position: "absolute",
|
|
489
|
+
top: "100%",
|
|
490
|
+
left: 0,
|
|
491
|
+
right: 0,
|
|
492
|
+
zIndex: 50
|
|
493
|
+
}
|
|
494
|
+
}),
|
|
495
|
+
children: suggestions.map((s, i) => /* @__PURE__ */ jsx12(
|
|
496
|
+
item.Component,
|
|
497
|
+
{
|
|
498
|
+
...item.resolveProps({
|
|
499
|
+
role: "option",
|
|
500
|
+
"aria-selected": i === activeIndex,
|
|
501
|
+
"data-active": i === activeIndex || void 0,
|
|
502
|
+
onClick: () => handleSelect(s),
|
|
503
|
+
onMouseEnter: () => setActiveIndex(i)
|
|
504
|
+
}),
|
|
505
|
+
children: /* @__PURE__ */ jsx12(
|
|
506
|
+
highlight.Component,
|
|
507
|
+
{
|
|
508
|
+
...highlight.resolveProps({
|
|
509
|
+
dangerouslySetInnerHTML: { __html: s.highlight }
|
|
510
|
+
})
|
|
511
|
+
}
|
|
512
|
+
)
|
|
513
|
+
},
|
|
514
|
+
s.objectID
|
|
515
|
+
))
|
|
516
|
+
}
|
|
517
|
+
)
|
|
518
|
+
]
|
|
519
|
+
}
|
|
520
|
+
);
|
|
521
|
+
}
|
|
379
522
|
export {
|
|
523
|
+
Autocomplete,
|
|
380
524
|
Hits,
|
|
381
525
|
HitsSkeleton,
|
|
382
526
|
LocaleContext,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tsproxy/react",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.3",
|
|
4
4
|
"description": "Headless React components for tsproxy with BaseUI-style overrides",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -36,7 +36,7 @@
|
|
|
36
36
|
"typecheck": "tsc --noEmit"
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"@tsproxy/js": "^0.0.
|
|
39
|
+
"@tsproxy/js": "^0.0.3"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
42
|
"react": "^18.0.0 || ^19.0.0",
|