Initial commit
This commit is contained in:
commit
c779204044
0
.gitignore
vendored
Normal file
0
.gitignore
vendored
Normal file
6
.vscode/extensions.json
vendored
Normal file
6
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"recommendations": [
|
||||||
|
"denoland.vscode-deno",
|
||||||
|
"sastan.twind-intellisense"
|
||||||
|
]
|
||||||
|
}
|
5
.vscode/settings.json
vendored
Normal file
5
.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"deno.enable": true,
|
||||||
|
"deno.lint": true,
|
||||||
|
"editor.defaultFormatter": "denoland.vscode-deno"
|
||||||
|
}
|
15
README.md
Normal file
15
README.md
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
# Search github awesome
|
||||||
|
|
||||||
|
Search github repository in awesome list.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### Usage
|
||||||
|
|
||||||
|
Start the project:
|
||||||
|
|
||||||
|
```
|
||||||
|
deno task start
|
||||||
|
```
|
||||||
|
|
||||||
|
This will watch the project directory and restart as necessary.
|
75
api/repo.ts
Normal file
75
api/repo.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
|
||||||
|
export interface RepoData {
|
||||||
|
name: string;
|
||||||
|
author: string;
|
||||||
|
description: string;
|
||||||
|
url: string;
|
||||||
|
stars: number;
|
||||||
|
forks: number;
|
||||||
|
tags: string[];
|
||||||
|
readme: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const SAMPLE_DATA: RepoData[] = [
|
||||||
|
{
|
||||||
|
name: "deno",
|
||||||
|
author: "denoland",
|
||||||
|
description: "A secure runtime for JavaScript and TypeScript.",
|
||||||
|
url: "https://github.com/denoland/deno",
|
||||||
|
stars: 10000,
|
||||||
|
forks: 1000,
|
||||||
|
tags: ["deno", "runtime", "typescript"],
|
||||||
|
readme: `# Deno 🦕
|
||||||
|
Deno is a simple, modern and secure runtime for JavaScript and TypeScript that uses V8 and is built in Rust.
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deno_std",
|
||||||
|
author: "denoland",
|
||||||
|
description: "Standard modules for the Deno runtime.",
|
||||||
|
url: "https://github.com/denoland/deno_std",
|
||||||
|
stars: 1000,
|
||||||
|
forks: 100,
|
||||||
|
tags: ["deno", "runtime", "typescript"],
|
||||||
|
readme: `# Deno Standard Modules 🦕
|
||||||
|
This repository contains the standard modules that are provided by default with Deno.
|
||||||
|
`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "deno_website2",
|
||||||
|
author: "maximousblk",
|
||||||
|
description: "The new deno.land website.",
|
||||||
|
url: "https://github.com/maximousblk/deno_website2",
|
||||||
|
stars: 100,
|
||||||
|
forks: 10,
|
||||||
|
tags: ["deno", "website", "typescript"],
|
||||||
|
readme: `# Deno Website 2 🦕
|
||||||
|
The new deno.land website.
|
||||||
|
`,
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
export const getRepos = async (): Promise<RepoData[]> => {
|
||||||
|
// return mock data for now
|
||||||
|
return SAMPLE_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface SearchOptions {
|
||||||
|
/**
|
||||||
|
* The limit of results to return.
|
||||||
|
* @default 10
|
||||||
|
* @minimum 1
|
||||||
|
* @maximum 100
|
||||||
|
*/
|
||||||
|
limit?: number;
|
||||||
|
/**
|
||||||
|
* The offset of results to return.
|
||||||
|
* @default 0
|
||||||
|
*/
|
||||||
|
offset?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function searchRepos(query: string, options?: SearchOptions): Promise<RepoData[]> {
|
||||||
|
// return mock data for now
|
||||||
|
return SAMPLE_DATA;
|
||||||
|
}
|
12
components/Button.tsx
Normal file
12
components/Button.tsx
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
import { JSX } from "preact";
|
||||||
|
import { IS_BROWSER } from "$fresh/runtime.ts";
|
||||||
|
|
||||||
|
export function Button(props: JSX.HTMLAttributes<HTMLButtonElement>) {
|
||||||
|
return (
|
||||||
|
<button
|
||||||
|
{...props}
|
||||||
|
disabled={!IS_BROWSER || props.disabled}
|
||||||
|
class="px-2 py-1 border(gray-100 2) hover:bg-gray-200"
|
||||||
|
/>
|
||||||
|
);
|
||||||
|
}
|
27
components/SearchBar.tsx
Normal file
27
components/SearchBar.tsx
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
import { useState } from "preact/hooks";
|
||||||
|
|
||||||
|
export interface SearchBarProps {
|
||||||
|
value: string;
|
||||||
|
onChange: (value: string) => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function SearchBar(props: SearchBarProps) {
|
||||||
|
const { value, onChange } = props;
|
||||||
|
const [inputValue, setInputValue] = useState(value);
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div class="flex items-center justify-center w-full p-4">
|
||||||
|
<input class="w-full flex-auto p-2 border border-gray-200 rounded
|
||||||
|
focus:outline-none focus:border-gray-600"
|
||||||
|
type="text" placeholder="Search..." value={inputValue}
|
||||||
|
onInput={e=>{
|
||||||
|
if(e.currentTarget){
|
||||||
|
setInputValue(e.currentTarget.value);
|
||||||
|
onChange(e.currentTarget.value);
|
||||||
|
}
|
||||||
|
}}/>
|
||||||
|
<button class="flex-grow-0 p-2 ml-2 text-white bg-blue-500 rounded hover:bg-blue-600"
|
||||||
|
type="submit">Submit</button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
10
deno.json
Normal file
10
deno.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"tasks": {
|
||||||
|
"start": "deno run -A --watch=static/,routes/ dev.ts"
|
||||||
|
},
|
||||||
|
"importMap": "./import_map.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
"jsx": "react-jsx",
|
||||||
|
"jsxImportSource": "preact"
|
||||||
|
}
|
||||||
|
}
|
127
deno.lock
Normal file
127
deno.lock
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"version": "2",
|
||||||
|
"remote": {
|
||||||
|
"https://deno.land/std@0.140.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
|
||||||
|
"https://deno.land/std@0.140.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49",
|
||||||
|
"https://deno.land/std@0.140.0/fs/_util.ts": "0fb24eb4bfebc2c194fb1afdb42b9c3dda12e368f43e8f2321f84fc77d42cb0f",
|
||||||
|
"https://deno.land/std@0.140.0/fs/ensure_dir.ts": "9dc109c27df4098b9fc12d949612ae5c9c7169507660dcf9ad90631833209d9d",
|
||||||
|
"https://deno.land/std@0.140.0/fs/expand_glob.ts": "0c10130d67c9b02164b03df8e43c6d6defbf8e395cb69d09e84a8586e6d72ac3",
|
||||||
|
"https://deno.land/std@0.140.0/fs/walk.ts": "117403ccd21fd322febe56ba06053b1ad5064c802170f19b1ea43214088fe95f",
|
||||||
|
"https://deno.land/std@0.140.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3",
|
||||||
|
"https://deno.land/std@0.140.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09",
|
||||||
|
"https://deno.land/std@0.140.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b",
|
||||||
|
"https://deno.land/std@0.140.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633",
|
||||||
|
"https://deno.land/std@0.140.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee",
|
||||||
|
"https://deno.land/std@0.140.0/path/mod.ts": "d3e68d0abb393fb0bf94a6d07c46ec31dc755b544b13144dee931d8d5f06a52d",
|
||||||
|
"https://deno.land/std@0.140.0/path/posix.ts": "293cdaec3ecccec0a9cc2b534302dfe308adb6f10861fa183275d6695faace44",
|
||||||
|
"https://deno.land/std@0.140.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9",
|
||||||
|
"https://deno.land/std@0.140.0/path/win32.ts": "31811536855e19ba37a999cd8d1b62078235548d67902ece4aa6b814596dd757",
|
||||||
|
"https://deno.land/std@0.150.0/_util/assert.ts": "e94f2eb37cebd7f199952e242c77654e43333c1ac4c5c700e929ea3aa5489f74",
|
||||||
|
"https://deno.land/std@0.150.0/_util/os.ts": "3b4c6e27febd119d36a416d7a97bd3b0251b77c88942c8f16ee5953ea13e2e49",
|
||||||
|
"https://deno.land/std@0.150.0/async/abortable.ts": "87aa7230be8360c24ad437212311c9e8d4328854baec27b4c7abb26e85515c06",
|
||||||
|
"https://deno.land/std@0.150.0/async/deadline.ts": "48ac998d7564969f3e6ec6b6f9bf0217ebd00239b1b2292feba61272d5dd58d0",
|
||||||
|
"https://deno.land/std@0.150.0/async/debounce.ts": "564273ef242bcfcda19a439132f940db8694173abffc159ea34f07d18fc42620",
|
||||||
|
"https://deno.land/std@0.150.0/async/deferred.ts": "bc18e28108252c9f67dfca2bbc4587c3cbf3aeb6e155f8c864ca8ecff992b98a",
|
||||||
|
"https://deno.land/std@0.150.0/async/delay.ts": "cbbdf1c87d1aed8edc7bae13592fb3e27e3106e0748f089c263390d4f49e5f6c",
|
||||||
|
"https://deno.land/std@0.150.0/async/mod.ts": "9852cd8ed897ab2d41a8fbee611d574e97898327db5c19d9d58e41126473f02c",
|
||||||
|
"https://deno.land/std@0.150.0/async/mux_async_iterator.ts": "5b4aca6781ad0f2e19ccdf1d1a1c092ccd3e00d52050d9c27c772658c8367256",
|
||||||
|
"https://deno.land/std@0.150.0/async/pool.ts": "ef9eb97b388543acbf0ac32647121e4dbe629236899586c4d4311a8770fbb239",
|
||||||
|
"https://deno.land/std@0.150.0/async/tee.ts": "bcfae0017ebb718cf4eef9e2420e8675d91cb1bcc0ed9b668681af6e6caad846",
|
||||||
|
"https://deno.land/std@0.150.0/flags/mod.ts": "594472736e24b2f2afd3451cf7ccd58a21706ce91006478a544fdfa056c69697",
|
||||||
|
"https://deno.land/std@0.150.0/fs/_util.ts": "2cf50bfb1081c2d5f2efec10ac19abbc2baf478e51cd1b057d0da2f30585b6ba",
|
||||||
|
"https://deno.land/std@0.150.0/fs/walk.ts": "6ce8d87fbaeda23383e979599ad27f3f94b3e5ff0c0cd976b5fc5c2aa0df7d92",
|
||||||
|
"https://deno.land/std@0.150.0/http/http_status.ts": "897575a7d6bc2b9123f6a38ecbc0f03d95a532c5d92029315dc9f508e12526b8",
|
||||||
|
"https://deno.land/std@0.150.0/http/server.ts": "0b0a9f3abfcfecead944b31ee9098a0c11a59b0495bf873ee200eb80e7441483",
|
||||||
|
"https://deno.land/std@0.150.0/media_types/_util.ts": "ce9b4fc4ba1c447dafab619055e20fd88236ca6bdd7834a21f98bd193c3fbfa1",
|
||||||
|
"https://deno.land/std@0.150.0/media_types/mod.ts": "2d4b6f32a087029272dc59e0a55ae3cc4d1b27b794ccf528e94b1925795b3118",
|
||||||
|
"https://deno.land/std@0.150.0/media_types/vendor/mime-db.v1.52.0.ts": "724cee25fa40f1a52d3937d6b4fbbfdd7791ff55e1b7ac08d9319d5632c7f5af",
|
||||||
|
"https://deno.land/std@0.150.0/path/_constants.ts": "df1db3ffa6dd6d1252cc9617e5d72165cd2483df90e93833e13580687b6083c3",
|
||||||
|
"https://deno.land/std@0.150.0/path/_interface.ts": "ee3b431a336b80cf445441109d089b70d87d5e248f4f90ff906820889ecf8d09",
|
||||||
|
"https://deno.land/std@0.150.0/path/_util.ts": "c1e9686d0164e29f7d880b2158971d805b6e0efc3110d0b3e24e4b8af2190d2b",
|
||||||
|
"https://deno.land/std@0.150.0/path/common.ts": "bee563630abd2d97f99d83c96c2fa0cca7cee103e8cb4e7699ec4d5db7bd2633",
|
||||||
|
"https://deno.land/std@0.150.0/path/glob.ts": "cb5255638de1048973c3e69e420c77dc04f75755524cb3b2e160fe9277d939ee",
|
||||||
|
"https://deno.land/std@0.150.0/path/mod.ts": "4945b430b759b0b3d98f2a278542cbcf95e0ad2bd8eaaed3c67322b306b2b346",
|
||||||
|
"https://deno.land/std@0.150.0/path/posix.ts": "c1f7afe274290ea0b51da07ee205653b2964bd74909a82deb07b69a6cc383aaa",
|
||||||
|
"https://deno.land/std@0.150.0/path/separator.ts": "fe1816cb765a8068afb3e8f13ad272351c85cbc739af56dacfc7d93d710fe0f9",
|
||||||
|
"https://deno.land/std@0.150.0/path/win32.ts": "bd7549042e37879c68ff2f8576a25950abbfca1d696d41d82c7bca0b7e6f452c",
|
||||||
|
"https://deno.land/std@0.150.0/semver/mod.ts": "4a5195fa81b4aede8875a386550a1119f01fb58d74aea899b2cfb136c05a7310",
|
||||||
|
"https://deno.land/std@0.152.0/async/abortable.ts": "87aa7230be8360c24ad437212311c9e8d4328854baec27b4c7abb26e85515c06",
|
||||||
|
"https://deno.land/std@0.152.0/async/deadline.ts": "48ac998d7564969f3e6ec6b6f9bf0217ebd00239b1b2292feba61272d5dd58d0",
|
||||||
|
"https://deno.land/std@0.152.0/async/debounce.ts": "564273ef242bcfcda19a439132f940db8694173abffc159ea34f07d18fc42620",
|
||||||
|
"https://deno.land/std@0.152.0/async/deferred.ts": "bc18e28108252c9f67dfca2bbc4587c3cbf3aeb6e155f8c864ca8ecff992b98a",
|
||||||
|
"https://deno.land/std@0.152.0/async/delay.ts": "cbbdf1c87d1aed8edc7bae13592fb3e27e3106e0748f089c263390d4f49e5f6c",
|
||||||
|
"https://deno.land/std@0.152.0/async/mod.ts": "dd0a8ed4f3984ffabe2fcca7c9f466b7932d57b1864ffee148a5d5388316db6b",
|
||||||
|
"https://deno.land/std@0.152.0/async/mux_async_iterator.ts": "5b4aca6781ad0f2e19ccdf1d1a1c092ccd3e00d52050d9c27c772658c8367256",
|
||||||
|
"https://deno.land/std@0.152.0/async/pool.ts": "ef9eb97b388543acbf0ac32647121e4dbe629236899586c4d4311a8770fbb239",
|
||||||
|
"https://deno.land/std@0.152.0/async/tee.ts": "bcfae0017ebb718cf4eef9e2420e8675d91cb1bcc0ed9b668681af6e6caad846",
|
||||||
|
"https://deno.land/std@0.152.0/http/server.ts": "0b0a9f3abfcfecead944b31ee9098a0c11a59b0495bf873ee200eb80e7441483",
|
||||||
|
"https://deno.land/x/code_block_writer@11.0.3/mod.ts": "2c3448060e47c9d08604c8f40dee34343f553f33edcdfebbf648442be33205e5",
|
||||||
|
"https://deno.land/x/code_block_writer@11.0.3/utils/string_utils.ts": "60cb4ec8bd335bf241ef785ccec51e809d576ff8e8d29da43d2273b69ce2a6ff",
|
||||||
|
"https://deno.land/x/denoflate@1.2.1/mod.ts": "f5628e44b80b3d80ed525afa2ba0f12408e3849db817d47a883b801f9ce69dd6",
|
||||||
|
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate.js": "b9f9ad9457d3f12f28b1fb35c555f57443427f74decb403113d67364e4f2caf4",
|
||||||
|
"https://deno.land/x/denoflate@1.2.1/pkg/denoflate_bg.wasm.js": "d581956245407a2115a3d7e8d85a9641c032940a8e810acbd59ca86afd34d44d",
|
||||||
|
"https://deno.land/x/esbuild@v0.14.51/mod.d.ts": "c142324d0383c39de0d7660cd207a7f7f52c7198a13d7d3281c0d636a070f441",
|
||||||
|
"https://deno.land/x/esbuild@v0.14.51/mod.js": "7432566c71fac77637822dc230319c7392a2d2fef51204c9d12c956d7093c279",
|
||||||
|
"https://deno.land/x/esbuild@v0.14.51/wasm.d.ts": "c142324d0383c39de0d7660cd207a7f7f52c7198a13d7d3281c0d636a070f441",
|
||||||
|
"https://deno.land/x/esbuild@v0.14.51/wasm.js": "afc1b6927543b664af60ce452c4929e5dc2bb9a0f4ed47b446a6431847c7598e",
|
||||||
|
"https://deno.land/x/esbuild_deno_loader@0.5.2/deps.ts": "bf83c27b7787b2f245fa0bc0b99f5041aa949c000a81c016cfe828d06b476d37",
|
||||||
|
"https://deno.land/x/esbuild_deno_loader@0.5.2/mod.ts": "bc111a68f323dbdb6edec68dd558ab732b27866d2ef304708872d763387b65d7",
|
||||||
|
"https://deno.land/x/esbuild_deno_loader@0.5.2/src/deno.ts": "0e83ccabbe2b004389288e38df2031b79eb347df2d139fce9394d8e88a11f259",
|
||||||
|
"https://deno.land/x/esbuild_deno_loader@0.5.2/src/native_loader.ts": "343854a566cf510cf25144f7c09fc0c1097780a31830305142a075d12bb697ba",
|
||||||
|
"https://deno.land/x/esbuild_deno_loader@0.5.2/src/portable_loader.ts": "35b6c526eed8c2c781a3256b23c30aa7cce69c0ef1d583c15528663287ba18a3",
|
||||||
|
"https://deno.land/x/esbuild_deno_loader@0.5.2/src/shared.ts": "b64749cd8c0f6252a11498bd8758ef1220003e46b2c9b68e16da63fd7e92b13a",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/dev.ts": "a66c7d64be35bcd6a8e12eec9c27ae335044c70363a241f2e36ee776db468622",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/plugins/twind.ts": "c0570d6010e29ba24ee5f43b9d3f1fe735f7fac76d9a3e680c9896373d669876",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/plugins/twind/shared.ts": "023e0ffcd66668753b5049edab0de46e6d66194fb6026c679034b9bbf04ad6f3",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/runtime.ts": "b02ec1e2e32cf73a33d262b7c9dcab9468ce16cd89fd424196c71003698a4ab0",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/server.ts": "f379c9aad24471a71e58fb887fa57e5cc27ad9df035987eb260541c78df38e84",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/dev/deps.ts": "de5470828c17839c0b52c328e6709f3477740b9800deaf724d6569b64b1d3872",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/dev/error.ts": "21a38d240c00279662e6adde41367f1da0ae7e2836d993f818ea94aabab53e7b",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/dev/mod.ts": "f5836b2eccd0efd7c0a726a121f174a974daefc22058f759f07d4df56c46e978",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/runtime/csp.ts": "9ee900e9b0b786057b1009da5976298c202d1b86d1f1e4d2510bde5f06530ac9",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/runtime/head.ts": "0f9932874497ab6e57ed1ba01d549e843523df4a5d36ef97460e7a43e3132fdc",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/runtime/utils.ts": "8320a874a44bdd5905c7d4b87a0e7a14a6c50a2ed133800e72ae57341e4d4faa",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/bundle.ts": "f529a54ea5e078b9bd94c64c2ad345a3ba763b39c25b6e61f90629bdfa39c2ff",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/constants.ts": "ad10dda1bc20c25c2926f6a8cfd79ef4368d70b4b03a645f65c04b3fa7d93a8c",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/context.ts": "b385b982de2e5ee6e543dd56aad0e88f8f8fe5d9497909cf16caaf23b4d88b62",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/default_error_page.ts": "1155ac98b3729bf2e51be730af507e431db0ee43ac84c86f1c022a831b310106",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/deps.ts": "1c4e05b7d6e4eecc0012c9ec30ee587d8f533ab67c2bcb59048ed5f76841a770",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/htmlescape.ts": "834ac7d0caa9fc38dffd9b8613fb47aeecd4f22d5d70c51d4b20a310c085835c",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/mod.ts": "72d213444334dd2e94c757a0eee0fc486c0919399ea9184d07ad042f34edd00d",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/render.ts": "6f50707bd1f6e33ed84bb71ae3b0996d202b953cefc4285f5356524c7b21f01f",
|
||||||
|
"https://deno.land/x/fresh@1.1.2/src/server/types.ts": "dde992ab4ee635df71a7fc96fe4cd85943c1a9286ea8eb586563d5f5ca154955",
|
||||||
|
"https://deno.land/x/importmap@0.2.1/_util.ts": "ada9a9618b537e6c0316c048a898352396c882b9f2de38aba18fd3f2950ede89",
|
||||||
|
"https://deno.land/x/importmap@0.2.1/mod.ts": "ae3d1cd7eabd18c01a4960d57db471126b020f23b37ef14e1359bbb949227ade",
|
||||||
|
"https://deno.land/x/rutt@0.0.13/mod.ts": "af981cfb95131152bf50fc9140fc00cb3efb6563df2eded1d408361d8577df20",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/common/DenoRuntime.ts": "537800e840d0994f9055164e11bf33eadf96419246af0d3c453793c3ae67bdb3",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/common/mod.ts": "01985d2ee7da8d1caee318a9d07664774fbee4e31602bc2bb6bb62c3489555ed",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/common/ts_morph_common.d.ts": "39f2ddefd4995e4344236c44c2bf296069149f45ef6f00440b56e7b32cb2b3bd",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/common/ts_morph_common.js": "7d908bf4f416aa96de956dc11ecc83b585bed297e16418d496ca04a3481067e0",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/common/typescript.d.ts": "df7dd83543f14081ca74918d5a80ff60f634f465746cf2aff8924b28bcc3b152",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/common/typescript.js": "5c59651248a4c41b25fa7beee8e0d0d0fab5f439fa72d478e65abd8241aa533c",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/mod.ts": "adba9b82f24865d15d2c78ef6074b9a7457011719056c9928c800f130a617c93",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/ts_morph.d.ts": "38668b0e3780282a56a805425494490b0045d1928bd040c47a94095749dab8c3",
|
||||||
|
"https://deno.land/x/ts_morph@16.0.0/ts_morph.js": "9fc0f3d6a3997c2df023fabc4e529d2117d214ffd4fd04247ca2f56c4e9cd470",
|
||||||
|
"https://esm.sh/*preact-render-to-string@5.2.4": "0a65784d053ac491a6d2397ad38c14d2fa172240734b374d354fe38a74be873d",
|
||||||
|
"https://esm.sh/preact@10.11.0": "e888b244446037c56f1881173fb51d1f5fa7aae5599e6c5154619346a6a5094e",
|
||||||
|
"https://esm.sh/preact@10.11.0/hooks": "2b8ec155eb8b87501663f074acff1d55a9114fa7d88f0b39da06c940af1ff736",
|
||||||
|
"https://esm.sh/preact@10.11.0/jsx-runtime": "5c123264f19799ab243211132dded45f6d42d594b5c78dd585f947d07bf20eae",
|
||||||
|
"https://esm.sh/stable/preact@10.11.0/deno/hooks.js": "48b7674c1f0c2a0f8a0f758b786f5bc15ba0f7a4f3a356ecc783848f1e4a1c55",
|
||||||
|
"https://esm.sh/stable/preact@10.11.0/deno/jsx-runtime.js": "b5a8e96758c20b5dea05802c6f6962b8a95bfdbd476eb4ea51cf3234f6e09271",
|
||||||
|
"https://esm.sh/stable/preact@10.11.0/deno/preact.js": "071b515099e5dff2fe56768be62644e32fab702b194171357ccc4d7d1210144a",
|
||||||
|
"https://esm.sh/twind@0.16.17": "f5bf049b0104a59c2b4651c2e09cbf9f6cd3a3110bf7b0808355e56f40bd161c",
|
||||||
|
"https://esm.sh/twind@0.16.17/sheets": "e0951fd922dd174f4ecf30e499cc044f019c0a36431e2d0aa3e7df4b10f2187c",
|
||||||
|
"https://esm.sh/v87/csstype@3.1.0/index.d.ts": "ba7617784f6b9aeac5e20c5eea869bbc3ef31b905f59c796b0fd401dae17c111",
|
||||||
|
"https://esm.sh/v87/style-vendorizer@2.2.3/deno/style-vendorizer.js": "bacdb96f034bbdae11a8d90427a6d49270d28d5939f02dbf0e7d0e52491ff9e3",
|
||||||
|
"https://esm.sh/v87/twind@0.16.17/deno/sheets.js": "f75586c3a778278f99ca9e6761e8c8a2089c66d6a503bb25e3bba38597fe1e30",
|
||||||
|
"https://esm.sh/v87/twind@0.16.17/deno/twind.js": "b9bf5d268c9d1c240a6d4485f034508924923eef88d37618cbad999e8ff80593",
|
||||||
|
"https://esm.sh/v87/twind@0.16.17/sheets/sheets.d.ts": "3948858f36c53a1d9031dc6d57bd0f28204ea85745e6a90fbbaac6b8d9386b32",
|
||||||
|
"https://esm.sh/v87/twind@0.16.17/twind.d.ts": "af3f5da08497bb6641ccf6cf71d0343e9759c4521cc21b2f71e3f774ed26e3c1",
|
||||||
|
"https://esm.sh/v99/preact-render-to-string@5.2.4/X-ZS8q/deno/preact-render-to-string.js": "75aad97b00d5ad63383de7f729a3f1fea59e69a9b876db5551d9c746ed372f82",
|
||||||
|
"https://esm.sh/v99/preact-render-to-string@5.2.4/X-ZS8q/src/index.d.ts": "b1d73703252c8570fdf2952475805f5808ba3511fefbd93a3e7bd8406de7dcd0",
|
||||||
|
"https://esm.sh/v99/preact@10.11.0/hooks/src/index.d.ts": "5c29febb624fc25d71cb0e125848c9b711e233337a08f7eacfade38fd4c14cc3",
|
||||||
|
"https://esm.sh/v99/preact@10.11.0/jsx-runtime/src/index.d.ts": "e153460ed2b3fe2ad8b93696ecd48fbf73cd628b0b0ea6692b71804a3af69dfd",
|
||||||
|
"https://esm.sh/v99/preact@10.11.0/src/index.d.ts": "1a5c331227be54be6515b0c92a469d352834fa413963ae84a39a05a3177111f6",
|
||||||
|
"https://esm.sh/v99/preact@10.11.0/src/jsx.d.ts": "c423715fd7992b2e1446fea11d2d04e8adbd66c1edca1ce5e85f90e0d26a2eb2"
|
||||||
|
}
|
||||||
|
}
|
5
dev.ts
Normal file
5
dev.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#!/usr/bin/env -S deno run -A --watch=static/,routes/
|
||||||
|
|
||||||
|
import dev from "$fresh/dev.ts";
|
||||||
|
|
||||||
|
await dev(import.meta.url, "./main.ts");
|
26
fresh.gen.ts
Normal file
26
fresh.gen.ts
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// DO NOT EDIT. This file is generated by fresh.
|
||||||
|
// This file SHOULD be checked into source version control.
|
||||||
|
// This file is automatically updated during development when running `dev.ts`.
|
||||||
|
|
||||||
|
import config from "./deno.json" assert { type: "json" };
|
||||||
|
import * as $0 from "./routes/api/_list.ts";
|
||||||
|
import * as $1 from "./routes/api/_query.ts";
|
||||||
|
import * as $2 from "./routes/index.tsx";
|
||||||
|
import * as $$0 from "./islands/Counter.tsx";
|
||||||
|
import * as $$1 from "./islands/RepoViewer.tsx";
|
||||||
|
|
||||||
|
const manifest = {
|
||||||
|
routes: {
|
||||||
|
"./routes/api/_list.ts": $0,
|
||||||
|
"./routes/api/_query.ts": $1,
|
||||||
|
"./routes/index.tsx": $2,
|
||||||
|
},
|
||||||
|
islands: {
|
||||||
|
"./islands/Counter.tsx": $$0,
|
||||||
|
"./islands/RepoViewer.tsx": $$1,
|
||||||
|
},
|
||||||
|
baseUrl: import.meta.url,
|
||||||
|
config,
|
||||||
|
};
|
||||||
|
|
||||||
|
export default manifest;
|
12
import_map.json
Normal file
12
import_map.json
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"imports": {
|
||||||
|
"$fresh/": "https://deno.land/x/fresh@1.1.2/",
|
||||||
|
"preact": "https://esm.sh/preact@10.11.0",
|
||||||
|
"preact/": "https://esm.sh/preact@10.11.0/",
|
||||||
|
"preact-render-to-string": "https://esm.sh/*preact-render-to-string@5.2.4",
|
||||||
|
"@preact/signals": "https://esm.sh/*@preact/signals@1.0.3",
|
||||||
|
"@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.0.1",
|
||||||
|
"twind": "https://esm.sh/twind@0.16.17",
|
||||||
|
"twind/": "https://esm.sh/twind@0.16.17/"
|
||||||
|
}
|
||||||
|
}
|
17
islands/Counter.tsx
Normal file
17
islands/Counter.tsx
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
import { useState } from "preact/hooks";
|
||||||
|
import { Button } from "../components/Button.tsx";
|
||||||
|
|
||||||
|
interface CounterProps {
|
||||||
|
start: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Counter(props: CounterProps) {
|
||||||
|
const [count, setCount] = useState(props.start);
|
||||||
|
return (
|
||||||
|
<div class="flex gap-2 w-full">
|
||||||
|
<p class="flex-grow-1 font-bold text-xl">{count}</p>
|
||||||
|
<Button onClick={() => setCount(count - 1)}>-1</Button>
|
||||||
|
<Button onClick={() => setCount(count + 1)}>+1</Button>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
61
islands/RepoViewer.tsx
Normal file
61
islands/RepoViewer.tsx
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
import { RepoData, getRepos, searchRepos } from "../api/repo.ts";
|
||||||
|
import { useEffect, useRef, useState } from "preact/hooks";
|
||||||
|
import { SearchBar } from "../components/SearchBar.tsx";
|
||||||
|
import { useRelativeTopOppacity } from "../util/hook.ts";
|
||||||
|
|
||||||
|
function RepoTag(props: { tag: string }) {
|
||||||
|
const { tag } = props;
|
||||||
|
return (
|
||||||
|
<a href={`https://github.com/topics/${tag}`}
|
||||||
|
class="inline-flex items-center px-2 py-1 m-1 text-xs font-medium leading-5 text-blue-800 bg-blue-100 rounded-full">
|
||||||
|
{tag}
|
||||||
|
</a>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function RepoItem(props: RepoData) {
|
||||||
|
const ref = useRef<HTMLDivElement | null>(null);
|
||||||
|
const opacity = useRelativeTopOppacity({elem: ref});
|
||||||
|
const { name, description, url, author, stars, tags, forks } = props;
|
||||||
|
return (
|
||||||
|
<div ref={ref} class="flex flex-col bg-white rounded transition-opacity"
|
||||||
|
style={`opacity: ${opacity}`}>
|
||||||
|
<div class="flex flex-col flex-grow p-4">
|
||||||
|
<a class="text-xl font-bold text-gray-900 hover:text-gray-700 flex-auto"
|
||||||
|
href={url}>{author+"/"+name}</a>
|
||||||
|
<div class="flex flex-row">
|
||||||
|
<p class="text-gray-600 ml-2 text-xs">
|
||||||
|
{forks} forks
|
||||||
|
</p>
|
||||||
|
<p class="text-gray-600 ml-2 text-xs">
|
||||||
|
{stars} stars
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<p class="mt-2 text-gray-600">{description}</p>
|
||||||
|
<div class="flex flex-wrap mt-4 -m-1">
|
||||||
|
{tags.map(tag => (
|
||||||
|
<RepoTag tag={tag} />
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function RepoViewer({repos}: {repos: RepoData[]}) {
|
||||||
|
return (
|
||||||
|
<div class="mt-4">
|
||||||
|
{repos.length > 0 ? (
|
||||||
|
<ul class="divide-y divide-gray-200">
|
||||||
|
{repos.map((repo) => (
|
||||||
|
<li class="py-4">
|
||||||
|
<RepoItem {...repo} />
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
</ul>
|
||||||
|
) : (
|
||||||
|
<p class="text-gray-500">No results found.</p>
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
13
main.ts
Normal file
13
main.ts
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
/// <reference no-default-lib="true" />
|
||||||
|
/// <reference lib="dom" />
|
||||||
|
/// <reference lib="dom.iterable" />
|
||||||
|
/// <reference lib="dom.asynciterable" />
|
||||||
|
/// <reference lib="deno.ns" />
|
||||||
|
|
||||||
|
import { start } from "$fresh/server.ts";
|
||||||
|
import manifest from "./fresh.gen.ts";
|
||||||
|
|
||||||
|
import twindPlugin from "$fresh/plugins/twind.ts";
|
||||||
|
import twindConfig from "./twind.config.ts";
|
||||||
|
|
||||||
|
await start(manifest, { plugins: [twindPlugin(twindConfig)] });
|
10
routes/api/_list.ts
Normal file
10
routes/api/_list.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { HandlerContext } from "$fresh/server.ts";
|
||||||
|
import { SAMPLE_DATA, RepoData } from "../../api/repo.ts";
|
||||||
|
|
||||||
|
export const handler = (_req: Request, _ctx: HandlerContext): Response => {
|
||||||
|
return new Response(JSON.stringify(SAMPLE_DATA), {
|
||||||
|
headers: {
|
||||||
|
"content-type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
10
routes/api/_query.ts
Normal file
10
routes/api/_query.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import { HandlerContext } from "$fresh/server.ts";
|
||||||
|
import { SAMPLE_DATA, RepoData } from "../../api/repo.ts";
|
||||||
|
|
||||||
|
export const handler = (_req: Request, _ctx: HandlerContext): Response => {
|
||||||
|
return new Response(JSON.stringify(SAMPLE_DATA), {
|
||||||
|
headers: {
|
||||||
|
"content-type": "application/json",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
};
|
42
routes/index.tsx
Normal file
42
routes/index.tsx
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
import { Head } from "$fresh/runtime.ts";
|
||||||
|
import { Handlers, PageProps } from "$fresh/server.ts";
|
||||||
|
import { RepoData, getRepos, searchRepos } from "../api/repo.ts";
|
||||||
|
import { useState } from "preact/hooks";
|
||||||
|
import { SearchBar } from "../components/SearchBar.tsx";
|
||||||
|
import RepoViewer from "../islands/RepoViewer.tsx";
|
||||||
|
|
||||||
|
export const handler: Handlers<RepoData[] | null> = {
|
||||||
|
async GET(req, ctx) {
|
||||||
|
try {
|
||||||
|
const url = new URL(req.url);
|
||||||
|
const query = url.searchParams.get("q");
|
||||||
|
if (query) {
|
||||||
|
const repos = await searchRepos(query);
|
||||||
|
return ctx.render(repos);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const repos = await getRepos();
|
||||||
|
return ctx.render(repos);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
return ctx.render(null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default function Home({ data }: PageProps<RepoData[] | null>) {
|
||||||
|
const [searchValue, setSearchValue] = useState("");
|
||||||
|
return (
|
||||||
|
<>
|
||||||
|
<Head>
|
||||||
|
<title>Search Github Awesome App</title>
|
||||||
|
</Head>
|
||||||
|
<div class="p-4 mx-auto max-w-screen-md">
|
||||||
|
<h1 class="text-4xl font-bold">Search Github Awesome App</h1>
|
||||||
|
<SearchBar value={searchValue} onChange={() => { }} />
|
||||||
|
<RepoViewer repos={data || []} />
|
||||||
|
</div>
|
||||||
|
</>
|
||||||
|
);
|
||||||
|
}
|
BIN
static/favicon.ico
Normal file
BIN
static/favicon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
6
static/logo.svg
Normal file
6
static/logo.svg
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<svg width="40" height="40" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<path d="M34.092 8.845C38.929 20.652 34.092 27 30 30.5c1 3.5-2.986 4.222-4.5 2.5-4.457 1.537-13.512 1.487-20-5C2 24.5 4.73 16.714 14 11.5c8-4.5 16-7 20.092-2.655Z" fill="#FFDB1E"/>
|
||||||
|
<path d="M14 11.5c6.848-4.497 15.025-6.38 18.368-3.47C37.5 12.5 21.5 22.612 15.5 25c-6.5 2.587-3 8.5-6.5 8.5-3 0-2.5-4-5.183-7.75C2.232 23.535 6.16 16.648 14 11.5Z" fill="#fff" stroke="#FFDB1E"/>
|
||||||
|
<path d="M28.535 8.772c4.645 1.25-.365 5.695-4.303 8.536-3.732 2.692-6.606 4.21-7.923 4.83-.366.173-1.617-2.252-1.617-1 0 .417-.7 2.238-.934 2.326-1.365.512-4.223 1.29-5.835 1.29-3.491 0-1.923-4.754 3.014-9.122.892-.789 1.478-.645 2.283-.645-.537-.773-.534-.917.403-1.546C17.79 10.64 23 8.77 25.212 8.42c.366.014.82.35.82.629.41-.14 2.095-.388 2.503-.278Z" fill="#FFE600"/>
|
||||||
|
<path d="M14.297 16.49c.985-.747 1.644-1.01 2.099-2.526.566.121.841-.08 1.29-.701.324.466 1.657.608 2.453.701-.715.451-1.057.852-1.452 2.106-1.464-.611-3.167-.302-4.39.42Z" fill="#fff"/>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
5
twind.config.ts
Normal file
5
twind.config.ts
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
import { Options } from "$fresh/plugins/twind.ts";
|
||||||
|
|
||||||
|
export default {
|
||||||
|
selfURL: import.meta.url,
|
||||||
|
} as Options;
|
73
util/hook.ts
Normal file
73
util/hook.ts
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import {useEffect, useState} from 'preact/hooks';
|
||||||
|
import {JSX, RefObject} from 'preact';
|
||||||
|
|
||||||
|
|
||||||
|
export function useIntersectionObserver({
|
||||||
|
target,
|
||||||
|
onIntersect,
|
||||||
|
threshold = 0,
|
||||||
|
rootMargin = '0px',
|
||||||
|
enabled = true,
|
||||||
|
}:{
|
||||||
|
target: RefObject<Element>;
|
||||||
|
onIntersect: () => void;
|
||||||
|
threshold?: number;
|
||||||
|
rootMargin?: string;
|
||||||
|
enabled?: boolean;
|
||||||
|
}) {
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (!enabled) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const observer = new IntersectionObserver(onIntersect, {
|
||||||
|
rootMargin,
|
||||||
|
threshold,
|
||||||
|
});
|
||||||
|
if (target.current) {
|
||||||
|
observer.observe(target.current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return () => {
|
||||||
|
if (target.current) {
|
||||||
|
observer.unobserve(target.current);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}, [target.current, onIntersect, threshold, rootMargin, enabled]);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function useRelativeTopOppacity({elem}:{elem: RefObject<Element>}) {
|
||||||
|
const [opacity, setOpacity] = useState(1);
|
||||||
|
|
||||||
|
useIntersectionObserver({
|
||||||
|
target: elem,
|
||||||
|
threshold: 0,
|
||||||
|
onIntersect: () => {
|
||||||
|
if (elem.current) {
|
||||||
|
addEventListener('scroll', updater);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return opacity;
|
||||||
|
function updater(){
|
||||||
|
if (elem.current) {
|
||||||
|
const el = elem.current;
|
||||||
|
const rect = el.getBoundingClientRect();
|
||||||
|
const upIntersect = Math.min(rect.bottom, el.clientHeight) / el.clientHeight;
|
||||||
|
const downIntersect = Math.min(window.innerHeight - rect.top, el.clientHeight) / el.clientHeight;
|
||||||
|
const intersect = Math.min(upIntersect, downIntersect);
|
||||||
|
|
||||||
|
if (intersect >= 0) {
|
||||||
|
let v = Math.min(Math.max(intersect, 0), 1);
|
||||||
|
v *= 4/3;
|
||||||
|
v = Math.min(Math.max(v, 0), 1);
|
||||||
|
setOpacity(v);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
setOpacity(1);
|
||||||
|
removeEventListener('scroll', updater);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user