| 1 |
import { __, _n, sprintf } from "@wordpress/i18n"; |
| 2 |
import { useTableStore } from "../../store"; |
| 3 |
import { getMatchingRowCount } from "../../search"; |
| 4 |
import { isProAvailable } from "../../pro-status"; |
| 5 |
|
| 6 |
export function SearchInput() { |
| 7 |
const isPro = isProAvailable(); |
| 8 |
const searchTerm = useTableStore(state => state.searchTerm); |
| 9 |
const setSearchTerm = useTableStore(state => state.setSearchTerm); |
| 10 |
const table = useTableStore(state => state.table); |
| 11 |
const cells = useTableStore(state => state.cells); |
| 12 |
const searchConfig = table.search; |
| 13 |
|
| 14 |
if (!isPro || !searchConfig?.enabled) { |
| 15 |
return null; |
| 16 |
} |
| 17 |
|
| 18 |
const placeholder = searchConfig.placeholder; |
| 19 |
const position = searchConfig.position || "left"; |
| 20 |
|
| 21 |
const matchingCount = searchTerm.trim() |
| 22 |
? getMatchingRowCount(cells, table.rows, table.cols, table, searchTerm) |
| 23 |
: null; |
| 24 |
|
| 25 |
const handleClear = () => { |
| 26 |
setSearchTerm(""); |
| 27 |
}; |
| 28 |
|
| 29 |
return ( |
| 30 |
<div |
| 31 |
className="tableberg-search" |
| 32 |
style={{ |
| 33 |
justifyContent: |
| 34 |
position === "right" ? "flex-end" : "flex-start", |
| 35 |
}} |
| 36 |
> |
| 37 |
<div className="tableberg-search__input-wrapper"> |
| 38 |
<svg |
| 39 |
className="tableberg-search__icon" |
| 40 |
width="16" |
| 41 |
height="16" |
| 42 |
viewBox="0 0 24 24" |
| 43 |
fill="none" |
| 44 |
stroke="currentColor" |
| 45 |
strokeWidth="2" |
| 46 |
strokeLinecap="round" |
| 47 |
strokeLinejoin="round" |
| 48 |
> |
| 49 |
<circle cx="11" cy="11" r="8" /> |
| 50 |
<path d="M21 21l-4.35-4.35" /> |
| 51 |
</svg> |
| 52 |
<input |
| 53 |
type="text" |
| 54 |
className="tableberg-search__input" |
| 55 |
placeholder={placeholder} |
| 56 |
value={searchTerm} |
| 57 |
onChange={e => setSearchTerm(e.target.value)} |
| 58 |
/> |
| 59 |
{searchTerm && ( |
| 60 |
<button |
| 61 |
type="button" |
| 62 |
className="tableberg-search__clear" |
| 63 |
onClick={handleClear} |
| 64 |
aria-label={__("Clear search", "tableberg")} |
| 65 |
> |
| 66 |
<svg |
| 67 |
width="16" |
| 68 |
height="16" |
| 69 |
viewBox="0 0 24 24" |
| 70 |
fill="currentColor" |
| 71 |
> |
| 72 |
<path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" /> |
| 73 |
</svg> |
| 74 |
</button> |
| 75 |
)} |
| 76 |
</div> |
| 77 |
{matchingCount !== null && ( |
| 78 |
<span className="tableberg-search__results"> |
| 79 |
{matchingCount === 0 |
| 80 |
? __("No results found", "tableberg") |
| 81 |
: /* translators: %d is the number of matching rows */ |
| 82 |
sprintf( |
| 83 |
_n( |
| 84 |
"%d result", |
| 85 |
"%d results", |
| 86 |
matchingCount, |
| 87 |
"tableberg" |
| 88 |
), |
| 89 |
matchingCount |
| 90 |
)} |
| 91 |
</span> |
| 92 |
)} |
| 93 |
</div> |
| 94 |
); |
| 95 |
} |
| 96 |
|