-
Notifications
You must be signed in to change notification settings - Fork 921
/
PluginSearchPage.jsx
120 lines (113 loc) · 3.56 KB
/
PluginSearchPage.jsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
import {h, Fragment} from 'preact';
import {useEffect, useState} from 'preact/hooks';
import Styles from './PluginSearchPage.module.css';
async function searchPlugins(val) {
const params3 = new URLSearchParams([
['q', 'snowpack plugin ' + (val || '')],
['count', '100'],
]);
const res = await fetch(`https://api.skypack.dev/v1/search?${params3.toString()}`);
const jsonres = await res.json();
return jsonres.results;
}
function Card({result}) {
const updatedAtFormatted = Intl.DateTimeFormat('en', {
month: 'long',
day: 'numeric',
year: 'numeric',
}).format(Date.parse(result.updatedAt));
return (
<li class={Styles.Card}>
<img class={Styles.Icon__Plugin} src="/img/plug-light.svg" />
<header class={Styles.CardHeader}>
<h3 class={Styles.CardName}>
<a href={`https://www.npmjs.com/package/${result.name}`} target="_blank">
<span itemprop="name">{result.name}</span>
</a>
</h3>
</header>
<p class={Styles.CardDesc} itemprop="description">
{result.description.split('. ')[0]}
</p>
<p class={Styles.CardSubtitle}>
Updated
<time class="" datetime={result.updatedAt}>
{updatedAtFormatted}
</time>
</p>
</li>
);
}
if (window === undefined) {
window = {location: {search}}; // Astro fix
}
function PluginSearchPageLive() {
const searchParams = new URLSearchParams(window.location.search);
const [results, setResults] = useState(null);
const [searchQuery, setSearchQuery] = useState(searchParams.get('q'));
useEffect(() => {
(async () => {
setResults(await searchPlugins(searchParams.get('q')));
})();
}, []);
async function onFormSubmit(e) {
e.preventDefault();
const form = new FormData(e.target);
const formula = form.get('q');
// document.getElementById('loading-message').style.display = 'block';
const searchParams = new URLSearchParams(window.location.search);
searchParams.set('q', formula);
window.history.pushState(null, null, '?' + searchParams.toString());
setSearchQuery(formula);
setResults(await searchPlugins(formula));
return false;
}
return (
<>
<form
name="myform"
id="myform"
class={Styles.Form}
action="https://www.npmjs.com/search"
method="GET"
onSubmit={onFormSubmit}
>
<input
type="search"
name="q"
defaultValue={searchQuery}
placeholder="search Sass, sitemaps, image optimization..."
class={Styles.Input}
/>
<button type="submit" class={Styles.Submit}>
Search
</button>
</form>
<div class={Styles.Count} id="total-result-count">
{!searchQuery && results && results.length > 50 && `${results.length}+ plugins available!`}
</div>
<section id="search-results" class={Styles.Results}>
{!results && (
<div id="loading-message" class={Styles.Loading}>
Loading...
</div>
)}
{results && results.length === 0 && (
<ul class={Styles.CardList}>
<li style="margin: 1rem; text-align: center;">No results found.</li>
</ul>
)}
{results && results.length > 0 && (
<ul class={Styles.CardList}>
{results.map((r) => (
<Card result={r} />
))}
</ul>
)}
</section>
</>
);
}
export default function PluginSearchPage(props) {
return import.meta.env.astro ? <div>Loading...</div> : <PluginSearchPageLive {...props} />;
}