├── .czrc ├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── biome.json ├── bun.lockb ├── package.json ├── src ├── index.ts ├── use-click-outside.ts ├── use-copy-clipboard.ts ├── use-debounce.ts ├── use-local-storage.ts ├── use-media-query.ts ├── use-orientation.ts ├── use-previous.ts └── use-window-size.ts ├── tsconfig.json ├── vite.config.ts └── website ├── .create-qwik-19p4ywk3pmv ├── bun.lockb └── package.json ├── .create-qwik-1dq2aazpr5n ├── bun.lockb └── package.json ├── .eslintignore ├── .eslintrc.cjs ├── .gitignore ├── .prettierignore ├── .prettierrc.js ├── README.md ├── adapters └── vercel-edge │ └── vite.config.ts ├── bun.lockb ├── package.json ├── postcss.config.cjs ├── public ├── favicon.svg ├── manifest.json └── robots.txt ├── qwik-ui.config.json ├── src ├── components │ ├── code-preview │ │ ├── code-copy.tsx │ │ ├── code-preview.tsx │ │ └── highlighter.ts │ ├── hero │ │ └── hero.tsx │ ├── hooks │ │ ├── hook-card.tsx │ │ ├── hook-code.tsx │ │ ├── hook-demo.tsx │ │ ├── hook-description.tsx │ │ ├── hook-header.tsx │ │ ├── hook-install.tsx │ │ ├── hook-params.tsx │ │ ├── hook-return.tsx │ │ └── hooks-list.tsx │ ├── install │ │ └── install.tsx │ ├── layout │ │ ├── disclaimer.tsx │ │ ├── header.tsx │ │ └── logo.tsx │ ├── router-head │ │ └── router-head.tsx │ └── ui │ │ ├── button │ │ └── button.tsx │ │ ├── card │ │ └── card.tsx │ │ └── input │ │ └── input.tsx ├── docs │ ├── click-outside │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.tsx │ ├── copy-clipboard │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.tsx │ ├── debounce │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.tsx │ ├── index.ts │ ├── local-storage │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.tsx │ ├── media-query │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.ts │ ├── previous │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.tsx │ └── window-size │ │ ├── code.ts │ │ ├── demo.tsx │ │ └── doc.tsx ├── entry.dev.tsx ├── entry.preview.tsx ├── entry.ssr.tsx ├── entry.vercel-edge.tsx ├── global.css ├── root.tsx └── routes │ ├── [hook] │ └── index.tsx │ ├── index.tsx │ ├── layout.tsx │ └── service-worker.ts ├── tailwind.config.js ├── tsconfig.json ├── vercel.json └── vite.config.ts /.czrc: -------------------------------------------------------------------------------- 1 | { 2 | "path": "cz-conventional-changelog" 3 | } 4 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore 2 | 3 | # Logs 4 | 5 | logs 6 | _.log 7 | npm-debug.log_ 8 | yarn-debug.log* 9 | yarn-error.log* 10 | lerna-debug.log* 11 | .pnpm-debug.log* 12 | 13 | # Caches 14 | 15 | .cache 16 | 17 | # Diagnostic reports (https://nodejs.org/api/report.html) 18 | 19 | report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json 20 | 21 | # Runtime data 22 | 23 | pids 24 | _.pid 25 | _.seed 26 | *.pid.lock 27 | 28 | # Directory for instrumented libs generated by jscoverage/JSCover 29 | 30 | lib-cov 31 | 32 | # Coverage directory used by tools like istanbul 33 | 34 | coverage 35 | *.lcov 36 | 37 | # nyc test coverage 38 | 39 | .nyc_output 40 | 41 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) 42 | 43 | .grunt 44 | 45 | # Bower dependency directory (https://bower.io/) 46 | 47 | bower_components 48 | 49 | # node-waf configuration 50 | 51 | .lock-wscript 52 | 53 | # Compiled binary addons (https://nodejs.org/api/addons.html) 54 | 55 | build/Release 56 | 57 | # Dependency directories 58 | 59 | node_modules/ 60 | jspm_packages/ 61 | 62 | # Snowpack dependency directory (https://snowpack.dev/) 63 | 64 | web_modules/ 65 | 66 | # TypeScript cache 67 | 68 | *.tsbuildinfo 69 | 70 | # Optional npm cache directory 71 | 72 | .npm 73 | 74 | # Optional eslint cache 75 | 76 | .eslintcache 77 | 78 | # Optional stylelint cache 79 | 80 | .stylelintcache 81 | 82 | # Microbundle cache 83 | 84 | .rpt2_cache/ 85 | .rts2_cache_cjs/ 86 | .rts2_cache_es/ 87 | .rts2_cache_umd/ 88 | 89 | # Optional REPL history 90 | 91 | .node_repl_history 92 | 93 | # Output of 'npm pack' 94 | 95 | *.tgz 96 | 97 | # Yarn Integrity file 98 | 99 | .yarn-integrity 100 | 101 | # dotenv environment variable files 102 | 103 | .env 104 | .env.development.local 105 | .env.test.local 106 | .env.production.local 107 | .env.local 108 | 109 | # parcel-bundler cache (https://parceljs.org/) 110 | 111 | .parcel-cache 112 | 113 | # Next.js build output 114 | 115 | .next 116 | out 117 | 118 | # Nuxt.js build / generate output 119 | 120 | .nuxt 121 | dist 122 | 123 | # Gatsby files 124 | 125 | # Comment in the public line in if your project uses Gatsby and not Next.js 126 | 127 | # https://nextjs.org/blog/next-9-1#public-directory-support 128 | 129 | # public 130 | 131 | # vuepress build output 132 | 133 | .vuepress/dist 134 | 135 | # vuepress v2.x temp and cache directory 136 | 137 | .temp 138 | 139 | # Docusaurus cache and generated files 140 | 141 | .docusaurus 142 | 143 | # Serverless directories 144 | 145 | .serverless/ 146 | 147 | # FuseBox cache 148 | 149 | .fusebox/ 150 | 151 | # DynamoDB Local files 152 | 153 | .dynamodb/ 154 | 155 | # TernJS port file 156 | 157 | .tern-port 158 | 159 | # Stores VSCode versions used for testing VSCode extensions 160 | 161 | .vscode-test 162 | 163 | # yarn v2 164 | 165 | .yarn/cache 166 | .yarn/unplugged 167 | .yarn/build-state.yml 168 | .yarn/install-state.gz 169 | .pnp.* 170 | 171 | # IntelliJ based IDEs 172 | .idea 173 | 174 | # Finder (MacOS) folder config 175 | .DS_Store 176 | lib 177 | 178 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | src/ 2 | website/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 qwik-hooks.vercel.app 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # qwikHooks 2 | 3 | A collection of modern qwik hooks – from the [@ditadi](https://twitter.com/victorditadi). 4 | 5 | ## Standard 6 | 7 | ### Install 8 | 9 | `npm i -D @ditadi/qwik-hooks` 10 | 11 | ### Hooks 12 | 13 | - [useDebounce](https://qwikhooks.dev/usedebounce) 14 | - [useLocalStorage](https://qwikhooks.dev/uselocalstorage) 15 | - [useCopyClipboard](https://qwikhooks.dev/usecopytoclipboard) 16 | - [useWindowSize](https://qwikhooks.dev/usewindowsize) 17 | - [usePrevious](https://qwikhooks.dev/useprevious) 18 | - [useMediaQuery](https://qwikhooks.dev/usemediaquery) 19 | - [useOrientation](https://qwikhooks.dev/useOrientation) 20 | - [useClickOutside](https://qwikhooks.dev/useClickOutside) 21 | 22 | 23 | ## License 24 | 25 | *this project was heavily inspired by usehooks.dev and built with the purpose of increasing qwik ecosystem. by: @victorditadi* 26 | 27 | [MIT](https://choosealicense.com/licenses/mit/) 28 | 29 | -------------------------------------------------------------------------------- /biome.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://biomejs.dev/schemas/1.5.3/schema.json", 3 | "files": { 4 | "include": ["**/*.ts", "**/*.tsx", "**/*.json"] 5 | }, 6 | "organizeImports": { 7 | "enabled": true 8 | }, 9 | "formatter": { 10 | "enabled": true, 11 | "formatWithErrors": true, 12 | "indentStyle": "space", 13 | "indentWidth": 4, 14 | "lineWidth": 100 15 | }, 16 | "javascript": { 17 | "formatter": { 18 | "quoteStyle": "double", 19 | "jsxQuoteStyle": "double" 20 | }, 21 | "globals": ["__DEV__"] 22 | }, 23 | "linter": { 24 | "enabled": true, 25 | "ignore": ["node_modules", "website/src/components/ui", "website/vite.config.ts"], 26 | "rules": { 27 | "recommended": true, 28 | "security": { 29 | "noDangerouslySetInnerHtml": "off" 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ditadi/qwik-hooks/845955676eaa83f8137e199d95874d3ebc16f252/bun.lockb -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@ditadi/qwik-hooks", 3 | "version": "0.1.6", 4 | "type": "module", 5 | "description": "A collection of modern, server-safe qwik hooks", 6 | "devDependencies": { 7 | "@biomejs/biome": "^1.6.3", 8 | "@commitlint/cli": "^19.2.1", 9 | "@commitlint/config-conventional": "^19.1.0", 10 | "@types/bun": "latest", 11 | "bumpp": "^9.4.0", 12 | "vite": "^5.2.7", 13 | "vite-tsconfig-paths": "^4.3.2" 14 | }, 15 | "dependencies": { 16 | "@builder.io/qwik": "^1.5.1" 17 | }, 18 | "peerDependencies": { 19 | "typescript": "^5.0.0" 20 | }, 21 | "author": { 22 | "name": "ditadi", 23 | "url": "https://github.com/ditadi" 24 | }, 25 | "repository": { 26 | "type": "git", 27 | "url": "https://github.com/ditadi/qwik-hooks" 28 | }, 29 | "scripts": { 30 | "dev": "cd website && bun run dev", 31 | "clean": "tsc --build --clean", 32 | "build": "bun run clean && bun run build.lib && bun run build.types", 33 | "build.lib": "vite build --mode lib", 34 | "build.types": "tsc --emitDeclarationOnly", 35 | "release": "bumpp --commit --tag --push && bun run build && npm publish --access public", 36 | "commit": "git-cz", 37 | "format": "bunx @biomejs/biome check --apply ." 38 | }, 39 | "main": "./lib/index.qwik.mjs", 40 | "qwik": "./lib/index.qwik.mjs", 41 | "types": "./lib/index.d.ts", 42 | "exports": { 43 | ".": { 44 | "import": "./lib/index.qwik.mjs", 45 | "require": "./lib/index.qwik.cjs", 46 | "types": "./lib/index.d.ts" 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | export { useCopyClipboard } from "./use-copy-clipboard"; 2 | export { useWindowSize } from "./use-window-size"; 3 | export { useDebounce } from "./use-debounce"; 4 | export { useLocalStorage } from "./use-local-storage"; 5 | export { usePrevious } from "./use-previous"; 6 | export { useMediaQuery } from "./use-media-query"; 7 | export { useOrientation } from "./use-orientation"; 8 | export { useClickOutside } from "./use-click-outside"; 9 | -------------------------------------------------------------------------------- /src/use-click-outside.ts: -------------------------------------------------------------------------------- 1 | import type { QRL, Signal } from "@builder.io/qwik"; 2 | import { $, useOnDocument } from "@builder.io/qwik"; 3 | 4 | /** 5 | * This code defines a function useClickOutside that listens for a click event on the document. 6 | * It checks if the clicked element is not within the specified ref element and then calls the function specified by onClickOut. 7 | * 8 | * @param {Signal} ref - The reference to the HTMLElement or undefined. 9 | * @param {QRL<() => void>} onClickOut - The QRL of the function to be called when clicked outside. 10 | */ 11 | export const useClickOutside = ( 12 | ref: Signal, 13 | onClickOut: QRL<() => void>, 14 | ) => { 15 | useOnDocument( 16 | "click", 17 | $((event) => { 18 | if (!ref.value) { 19 | return; 20 | } 21 | const target = event.target as HTMLElement; 22 | if (!ref.value.contains(target)) { 23 | onClickOut(); 24 | } 25 | }), 26 | ); 27 | }; 28 | -------------------------------------------------------------------------------- /src/use-copy-clipboard.ts: -------------------------------------------------------------------------------- 1 | import { $, type QRL, type Signal, useSignal } from "@builder.io/qwik"; 2 | 3 | const useCopyClipboard = ( 4 | timeout = 300, 5 | ): { 6 | copy: Signal; 7 | setCopy: QRL<(value: string | boolean | null) => void>; 8 | isCopying: Signal; 9 | } => { 10 | const copy = useSignal(null); 11 | const isCopying = useSignal(false); 12 | 13 | const setCopy = $((value: string | boolean | null) => { 14 | isCopying.value = true; 15 | setTimeout(async () => { 16 | try { 17 | if (navigator?.clipboard?.writeText) { 18 | await navigator.clipboard.writeText(value?.toString() ?? ""); 19 | copy.value = value; 20 | } else { 21 | throw new Error("Clipboard API not available"); 22 | } 23 | } catch (error) { 24 | copy.value = null; 25 | } 26 | isCopying.value = false; 27 | }, timeout); 28 | }); 29 | 30 | return { 31 | copy, 32 | setCopy, 33 | isCopying, 34 | }; 35 | }; 36 | 37 | export { useCopyClipboard }; 38 | -------------------------------------------------------------------------------- /src/use-debounce.ts: -------------------------------------------------------------------------------- 1 | import { type PropFunction, type Signal, useSignal, useTask$ } from "@builder.io/qwik"; 2 | 3 | const useDebounce = (input: Signal, delay: number, fn?: PropFunction<(value: T) => void>) => { 4 | const debouncedSignal = useSignal(""); 5 | const isDebouncing = useSignal(false); 6 | 7 | useTask$(({ track, cleanup }) => { 8 | track(() => input.value); 9 | 10 | if (input.value.length === 0) { 11 | return; 12 | } 13 | 14 | isDebouncing.value = true; 15 | const debounced = setTimeout(async () => { 16 | fn && (await fn(input.value)); 17 | 18 | debouncedSignal.value = input.value; 19 | isDebouncing.value = false; 20 | }, delay); 21 | 22 | cleanup(() => clearTimeout(debounced)); 23 | }); 24 | 25 | return { debouncedSignal, isDebouncing }; 26 | }; 27 | 28 | export { useDebounce }; 29 | -------------------------------------------------------------------------------- /src/use-local-storage.ts: -------------------------------------------------------------------------------- 1 | import { $, type QRL, type Signal, useOnWindow, useSignal, useTask$ } from "@builder.io/qwik"; 2 | import { isServer } from "@builder.io/qwik/build"; 3 | 4 | export type UseLocalStorageResponse = { 5 | storedValue: Signal; 6 | setStoredValue: QRL<(newValue: T | null) => void>; 7 | }; 8 | 9 | const useLocalStorage = (key: string, initialValue?: T): UseLocalStorageResponse => { 10 | const storedValue = useSignal(null); 11 | 12 | const setStoredValue = $((newValue: T | null) => { 13 | const newValueToBeStored = JSON.stringify(newValue); 14 | localStorage.setItem(key, newValueToBeStored); 15 | storedValue.value = newValue; 16 | }); 17 | 18 | const listenerLocalStorage = $((listenerKey: string | null) => { 19 | if (listenerKey !== key) return; 20 | 21 | const currentItem = localStorage.getItem(key); 22 | storedValue.value = currentItem ? JSON.parse(currentItem) : initialValue || null; 23 | }); 24 | 25 | /** 26 | * useTask$ triggers when the hooks is called after client-side routing. 27 | * useOnWindow("load") triggers when the page is loaded server-side. 28 | * useOnWindow("storage") triggers when local storage is changed from other tabs or components. 29 | */ 30 | 31 | useTask$(() => { 32 | if (isServer) return; 33 | listenerLocalStorage(key); 34 | }); 35 | 36 | useOnWindow( 37 | "load", 38 | $(() => listenerLocalStorage(key)), 39 | ); 40 | useOnWindow( 41 | "storage", 42 | $((e) => listenerLocalStorage(e.key)), 43 | ); 44 | 45 | return { storedValue, setStoredValue }; 46 | }; 47 | 48 | export { useLocalStorage }; 49 | -------------------------------------------------------------------------------- /src/use-media-query.ts: -------------------------------------------------------------------------------- 1 | import { $, useOnWindow, useSignal, useTask$ } from "@builder.io/qwik"; 2 | import { isServer } from "@builder.io/qwik/build"; 3 | 4 | const mediaQueryListCache = new Map(); 5 | 6 | const useMediaQuery = (query: string) => { 7 | const isMatched = useSignal(false); 8 | 9 | const updateMatch = $((media: MediaQueryList) => { 10 | isMatched.value = media.matches; 11 | }); 12 | 13 | const listenMediaQuery = $(() => { 14 | const mediaQueryCached = mediaQueryListCache.get(query); 15 | if (mediaQueryCached) { 16 | updateMatch(mediaQueryCached); 17 | return; 18 | } 19 | 20 | const mediaQueryUncached = window.matchMedia(query); 21 | mediaQueryListCache.set(query, mediaQueryUncached); 22 | 23 | updateMatch(mediaQueryUncached); 24 | }); 25 | 26 | useTask$(async () => { 27 | if (isServer) return; 28 | listenMediaQuery(); 29 | }); 30 | 31 | useOnWindow("load", listenMediaQuery); 32 | useOnWindow("resize", listenMediaQuery); 33 | 34 | return isMatched; 35 | }; 36 | 37 | export { useMediaQuery }; 38 | -------------------------------------------------------------------------------- /src/use-orientation.ts: -------------------------------------------------------------------------------- 1 | import { $, useOnWindow, useSignal, useTask$ } from "@builder.io/qwik"; 2 | import { isServer } from "@builder.io/qwik/build"; 3 | 4 | type Orientation = { 5 | angle: number; 6 | type: "landscape-primary" | "landscape-secondary" | "portrait-primary" | "portrait-secondary"; 7 | }; 8 | 9 | const useOrientation = () => { 10 | const orientationSignal = useSignal({ 11 | angle: 0, 12 | type: "landscape-primary", 13 | }); 14 | 15 | const handleOrientationChange = $(() => { 16 | const { orientation } = window.screen; 17 | 18 | orientationSignal.value = { 19 | angle: orientation.angle, 20 | type: orientation.type, 21 | }; 22 | }); 23 | 24 | /** 25 | * useTask$ triggers when the hooks is called after client-side routing. 26 | * useOnWindow("load") triggers when the page is loaded server-side. 27 | * useOnWindow("change") triggers when the page has orientation change. 28 | */ 29 | 30 | useTask$(() => { 31 | if (isServer) return; 32 | handleOrientationChange(); 33 | }); 34 | 35 | useOnWindow("load", handleOrientationChange); 36 | useOnWindow("change", handleOrientationChange); 37 | 38 | return orientationSignal; 39 | }; 40 | 41 | export { useOrientation }; 42 | -------------------------------------------------------------------------------- /src/use-previous.ts: -------------------------------------------------------------------------------- 1 | import { type Signal, useSignal, useTask$ } from "@builder.io/qwik"; 2 | 3 | const usePrevious = (current: Signal) => { 4 | const internalCurrent = useSignal(current.value); 5 | const previous = useSignal(null); 6 | 7 | useTask$(({ track }) => { 8 | track(() => current.value); 9 | if (internalCurrent.value !== current.value) { 10 | previous.value = internalCurrent.value; 11 | internalCurrent.value = current.value; 12 | } 13 | }); 14 | 15 | return previous; 16 | }; 17 | 18 | export { usePrevious }; 19 | -------------------------------------------------------------------------------- /src/use-window-size.ts: -------------------------------------------------------------------------------- 1 | import { $, useOnWindow, useSignal, useTask$ } from "@builder.io/qwik"; 2 | import { isServer } from "@builder.io/qwik/build"; 3 | 4 | type WindowSize = { 5 | width: number; 6 | height: number; 7 | }; 8 | 9 | const useWindowSize = () => { 10 | const size = useSignal(); 11 | 12 | const handleResize = $(() => { 13 | size.value = { 14 | width: window.innerWidth, 15 | height: window.innerHeight, 16 | }; 17 | }); 18 | 19 | /** 20 | * useTask$ triggers when the hooks is called after client-side routing. 21 | * useOnWindow("load") triggers when the page is loaded server-side. 22 | * useOnWindow("resize") triggers when the page is resized. 23 | */ 24 | 25 | useTask$(() => { 26 | if (isServer) return; 27 | handleResize(); 28 | }); 29 | 30 | useOnWindow("load", handleResize); 31 | useOnWindow("resize", handleResize); 32 | 33 | return size; 34 | }; 35 | 36 | export { useWindowSize }; 37 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ESNext", "DOM"], 4 | "target": "ESNext", 5 | "module": "ESNext", 6 | "moduleDetection": "force", 7 | "jsx": "react-jsx", 8 | "allowJs": true, 9 | "jsxImportSource": "@builder.io/qwik", 10 | "declaration": true, 11 | "declarationDir": "lib", 12 | "allowImportingTsExtensions": true, 13 | "resolveJsonModule": true, 14 | "verbatimModuleSyntax": true, 15 | "moduleResolution": "node", 16 | "noEmit": false, 17 | "skipLibCheck": true, 18 | "strict": true, 19 | "noFallthroughCasesInSwitch": true, 20 | "forceConsistentCasingInFileNames": true, 21 | "types": ["vite/client"] 22 | }, 23 | "include": ["src"] 24 | } 25 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { qwikVite } from "@builder.io/qwik/optimizer"; 2 | import { defineConfig } from "vite"; 3 | import tsconfigPaths from "vite-tsconfig-paths"; 4 | import pkg from "./package.json"; 5 | 6 | const { dependencies = {}, peerDependencies = {} } = pkg; 7 | const makeRegex = (dep) => new RegExp(`^${dep}(/.*)?$`); 8 | const excludeAll = (obj) => Object.keys(obj).map(makeRegex); 9 | 10 | export default defineConfig(() => { 11 | return { 12 | build: { 13 | target: "es2020", 14 | lib: { 15 | entry: "./src/index.ts", 16 | formats: ["es", "cjs"], 17 | fileName: (format) => `index.qwik.${format === "es" ? "mjs" : "cjs"}`, 18 | }, 19 | rollupOptions: { 20 | // externalize deps that shouldn't be bundled into the library 21 | external: [ 22 | /^node:.*/, 23 | ...excludeAll(dependencies), 24 | ...excludeAll(peerDependencies), 25 | ], 26 | }, 27 | }, 28 | plugins: [qwikVite(), tsconfigPaths()], 29 | }; 30 | }); 31 | -------------------------------------------------------------------------------- /website/.create-qwik-19p4ywk3pmv/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ditadi/qwik-hooks/845955676eaa83f8137e199d95874d3ebc16f252/website/.create-qwik-19p4ywk3pmv/bun.lockb -------------------------------------------------------------------------------- /website/.create-qwik-19p4ywk3pmv/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qwik-project-name", 3 | "scripts": { 4 | "build": "qwik build", 5 | "build.client": "vite build", 6 | "build.preview": "vite build --ssr src/entry.preview.tsx", 7 | "build.types": "tsc --incremental --noEmit", 8 | "dev": "vite --mode ssr", 9 | "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force", 10 | "fmt": "prettier --write .", 11 | "fmt.check": "prettier --check .", 12 | "lint": "eslint \"src/**/*.ts*\"", 13 | "preview": "qwik build preview && vite preview --open", 14 | "start": "vite --open --mode ssr", 15 | "deploy": "echo 'Run \"npm run qwik add\" to install a server adapter'", 16 | "qwik": "qwik" 17 | }, 18 | "devDependencies": { 19 | "@builder.io/qwik": "^1.5.1", 20 | "@builder.io/qwik-city": "^1.5.1", 21 | "@types/eslint": "^8.56.5", 22 | "@types/node": "^20.11.24", 23 | "@typescript-eslint/eslint-plugin": "^7.1.0", 24 | "@typescript-eslint/parser": "^7.1.0", 25 | "eslint": "^8.57.0", 26 | "eslint-plugin-qwik": "^1.5.1", 27 | "prettier": "^3.2.5", 28 | "typescript": "5.3.3", 29 | "undici": "*", 30 | "vite": "^5.1.4", 31 | "vite-tsconfig-paths": "^4.2.1" 32 | }, 33 | "trustedDependencies": ["sharp"], 34 | "trustedDependencies-annotation": "Needed for bun to allow running install scripts", 35 | "engines": { 36 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0", 37 | "npm": ">=10.0.0", 38 | "pnpm": ">=8.0.0", 39 | "yarn": ">=3.0.0" 40 | }, 41 | "engines-annotation": "Mostly required by sharp which needs a Node-API v9 compatible runtime", 42 | "private": true, 43 | "type": "module" 44 | } 45 | -------------------------------------------------------------------------------- /website/.create-qwik-1dq2aazpr5n/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ditadi/qwik-hooks/845955676eaa83f8137e199d95874d3ebc16f252/website/.create-qwik-1dq2aazpr5n/bun.lockb -------------------------------------------------------------------------------- /website/.create-qwik-1dq2aazpr5n/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "qwik-project-name", 3 | "scripts": { 4 | "build": "qwik build", 5 | "build.client": "vite build", 6 | "build.preview": "vite build --ssr src/entry.preview.tsx", 7 | "build.types": "tsc --incremental --noEmit", 8 | "dev": "vite --mode ssr", 9 | "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force", 10 | "fmt": "prettier --write .", 11 | "fmt.check": "prettier --check .", 12 | "lint": "eslint \"src/**/*.ts*\"", 13 | "preview": "qwik build preview && vite preview --open", 14 | "start": "vite --open --mode ssr", 15 | "deploy": "echo 'Run \"npm run qwik add\" to install a server adapter'", 16 | "qwik": "qwik" 17 | }, 18 | "devDependencies": { 19 | "@builder.io/qwik": "^1.5.1", 20 | "@builder.io/qwik-city": "^1.5.1", 21 | "@types/eslint": "^8.56.5", 22 | "@types/node": "^20.11.24", 23 | "@typescript-eslint/eslint-plugin": "^7.1.0", 24 | "@typescript-eslint/parser": "^7.1.0", 25 | "eslint": "^8.57.0", 26 | "eslint-plugin-qwik": "^1.5.1", 27 | "prettier": "^3.2.5", 28 | "typescript": "5.3.3", 29 | "undici": "*", 30 | "vite": "^5.1.4", 31 | "vite-tsconfig-paths": "^4.2.1" 32 | }, 33 | "trustedDependencies": ["sharp"], 34 | "trustedDependencies-annotation": "Needed for bun to allow running install scripts", 35 | "engines": { 36 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0", 37 | "npm": ">=10.0.0", 38 | "pnpm": ">=8.0.0", 39 | "yarn": ">=3.0.0" 40 | }, 41 | "engines-annotation": "Mostly required by sharp which needs a Node-API v9 compatible runtime", 42 | "private": true, 43 | "type": "module" 44 | } 45 | -------------------------------------------------------------------------------- /website/.eslintignore: -------------------------------------------------------------------------------- 1 | **/*.log 2 | **/.DS_Store 3 | *. 4 | .vscode/settings.json 5 | .history 6 | .yarn 7 | bazel-* 8 | bazel-bin 9 | bazel-out 10 | bazel-qwik 11 | bazel-testlogs 12 | dist 13 | dist-dev 14 | lib 15 | lib-types 16 | etc 17 | external 18 | node_modules 19 | temp 20 | tsc-out 21 | tsdoc-metadata.json 22 | target 23 | output 24 | rollup.config.js 25 | build 26 | .cache 27 | .vscode 28 | .rollup.cache 29 | dist 30 | tsconfig.tsbuildinfo 31 | vite.config.ts 32 | *.spec.tsx 33 | *.spec.ts 34 | .netlify 35 | pnpm-lock.yaml 36 | package-lock.json 37 | yarn.lock 38 | server 39 | -------------------------------------------------------------------------------- /website/.eslintrc.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | env: { 4 | browser: true, 5 | es2021: true, 6 | node: true, 7 | }, 8 | extends: [ 9 | "eslint:recommended", 10 | "plugin:@typescript-eslint/recommended", 11 | "plugin:qwik/recommended", 12 | ], 13 | parser: "@typescript-eslint/parser", 14 | parserOptions: { 15 | tsconfigRootDir: __dirname, 16 | project: ["./tsconfig.json"], 17 | ecmaVersion: 2021, 18 | sourceType: "module", 19 | ecmaFeatures: { 20 | jsx: true, 21 | }, 22 | }, 23 | plugins: ["@typescript-eslint"], 24 | rules: { 25 | "@typescript-eslint/no-explicit-any": "off", 26 | "@typescript-eslint/explicit-module-boundary-types": "off", 27 | "@typescript-eslint/no-inferrable-types": "off", 28 | "@typescript-eslint/no-non-null-assertion": "off", 29 | "@typescript-eslint/no-empty-interface": "off", 30 | "@typescript-eslint/no-namespace": "off", 31 | "@typescript-eslint/no-empty-function": "off", 32 | "@typescript-eslint/no-this-alias": "off", 33 | "@typescript-eslint/ban-types": "off", 34 | "@typescript-eslint/ban-ts-comment": "off", 35 | "prefer-spread": "off", 36 | "no-case-declarations": "off", 37 | "no-console": "off", 38 | "@typescript-eslint/no-unused-vars": ["error"], 39 | "@typescript-eslint/consistent-type-imports": "warn", 40 | "@typescript-eslint/no-unnecessary-condition": "warn", 41 | }, 42 | }; 43 | -------------------------------------------------------------------------------- /website/.gitignore: -------------------------------------------------------------------------------- 1 | # Build 2 | /dist 3 | /lib 4 | /lib-types 5 | /server 6 | 7 | # Development 8 | node_modules 9 | *.local 10 | 11 | # Cache 12 | .cache 13 | .mf 14 | .rollup.cache 15 | tsconfig.tsbuildinfo 16 | 17 | # Logs 18 | logs 19 | *.log 20 | npm-debug.log* 21 | yarn-debug.log* 22 | yarn-error.log* 23 | pnpm-debug.log* 24 | lerna-debug.log* 25 | 26 | # Editor 27 | .vscode/* 28 | !.vscode/launch.json 29 | !.vscode/*.code-snippets 30 | 31 | .idea 32 | .DS_Store 33 | *.suo 34 | *.ntvs* 35 | *.njsproj 36 | *.sln 37 | *.sw? 38 | 39 | # Yarn 40 | .yarn/* 41 | !.yarn/releases 42 | 43 | # Vercel 44 | .vercel 45 | 46 | 47 | .nx/cache -------------------------------------------------------------------------------- /website/.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.log 2 | **/.DS_Store 3 | *. 4 | .vscode/settings.json 5 | .history 6 | .yarn 7 | bazel-* 8 | bazel-bin 9 | bazel-out 10 | bazel-qwik 11 | bazel-testlogs 12 | dist 13 | dist-dev 14 | lib 15 | lib-types 16 | etc 17 | external 18 | node_modules 19 | temp 20 | tsc-out 21 | tsdoc-metadata.json 22 | target 23 | output 24 | rollup.config.js 25 | build 26 | .cache 27 | .vscode 28 | .rollup.cache 29 | tsconfig.tsbuildinfo 30 | vite.config.ts 31 | *.spec.tsx 32 | *.spec.ts 33 | .netlify 34 | pnpm-lock.yaml 35 | package-lock.json 36 | yarn.lock 37 | server 38 | -------------------------------------------------------------------------------- /website/.prettierrc.js: -------------------------------------------------------------------------------- 1 | export default { 2 | plugins: ['prettier-plugin-tailwindcss'], 3 | } -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | # Qwik City App ⚡️ 2 | 3 | - [Qwik Docs](https://qwik.builder.io/) 4 | - [Discord](https://qwik.builder.io/chat) 5 | - [Qwik GitHub](https://github.com/BuilderIO/qwik) 6 | - [@QwikDev](https://twitter.com/QwikDev) 7 | - [Vite](https://vitejs.dev/) 8 | 9 | --- 10 | 11 | ## Project Structure 12 | 13 | This project is using Qwik with [QwikCity](https://qwik.builder.io/qwikcity/overview/). QwikCity is just an extra set of tools on top of Qwik to make it easier to build a full site, including directory-based routing, layouts, and more. 14 | 15 | Inside your project, you'll see the following directory structure: 16 | 17 | ``` 18 | ├── public/ 19 | │ └── ... 20 | └── src/ 21 | ├── components/ 22 | │ └── ... 23 | └── routes/ 24 | └── ... 25 | ``` 26 | 27 | - `src/routes`: Provides the directory-based routing, which can include a hierarchy of `layout.tsx` layout files, and an `index.tsx` file as the page. Additionally, `index.ts` files are endpoints. Please see the [routing docs](https://qwik.builder.io/qwikcity/routing/overview/) for more info. 28 | 29 | - `src/components`: Recommended directory for components. 30 | 31 | - `public`: Any static assets, like images, can be placed in the public directory. Please see the [Vite public directory](https://vitejs.dev/guide/assets.html#the-public-directory) for more info. 32 | 33 | ## Add Integrations and deployment 34 | 35 | Use the `bun qwik add` command to add additional integrations. Some examples of integrations includes: Cloudflare, Netlify or Express Server, and the [Static Site Generator (SSG)](https://qwik.builder.io/qwikcity/guides/static-site-generation/). 36 | 37 | ```shell 38 | bun qwik add # or `bun qwik add` 39 | ``` 40 | 41 | ## Development 42 | 43 | Development mode uses [Vite's development server](https://vitejs.dev/). The `dev` command will server-side render (SSR) the output during development. 44 | 45 | ```shell 46 | npm start # or `bun start` 47 | ``` 48 | 49 | > Note: during dev mode, Vite may request a significant number of `.js` files. This does not represent a Qwik production build. 50 | 51 | ## Preview 52 | 53 | The preview command will create a production build of the client modules, a production build of `src/entry.preview.tsx`, and run a local server. The preview server is only for convenience to preview a production build locally and should not be used as a production server. 54 | 55 | ```shell 56 | bun preview # or `bun preview` 57 | ``` 58 | 59 | ## Production 60 | 61 | The production build will generate client and server modules by running both client and server build commands. The build command will use Typescript to run a type check on the source code. 62 | 63 | ```shell 64 | bun build # or `bun build` 65 | ``` 66 | 67 | ## Vercel Edge 68 | 69 | This starter site is configured to deploy to [Vercel Edge Functions](https://vercel.com/docs/concepts/functions/edge-functions), which means it will be rendered at an edge location near to your users. 70 | 71 | ## Installation 72 | 73 | The adaptor will add a new `vite.config.ts` within the `adapters/` directory, and a new entry file will be created, such as: 74 | 75 | ``` 76 | └── adapters/ 77 | └── vercel-edge/ 78 | └── vite.config.ts 79 | └── src/ 80 | └── entry.vercel-edge.tsx 81 | ``` 82 | 83 | Additionally, within the `package.json`, the `build.server` script will be updated with the Vercel Edge build. 84 | 85 | ## Production build 86 | 87 | To build the application for production, use the `build` command, this command will automatically run `bun build.server` and `bun build.client`: 88 | 89 | ```shell 90 | bun build 91 | ``` 92 | 93 | [Read the full guide here](https://github.com/BuilderIO/qwik/blob/main/starters/adapters/vercel-edge/README.md) 94 | 95 | ## Dev deploy 96 | 97 | To deploy the application for development: 98 | 99 | ```shell 100 | bun deploy 101 | ``` 102 | 103 | Notice that you might need a [Vercel account](https://docs.Vercel.com/get-started/) in order to complete this step! 104 | 105 | ## Production deploy 106 | 107 | The project is ready to be deployed to Vercel. However, you will need to create a git repository and push the code to it. 108 | 109 | You can [deploy your site to Vercel](https://vercel.com/docs/concepts/deployments/overview) either via a Git provider integration or through the Vercel CLI. 110 | -------------------------------------------------------------------------------- /website/adapters/vercel-edge/vite.config.ts: -------------------------------------------------------------------------------- 1 | import { vercelEdgeAdapter } from "@builder.io/qwik-city/adapters/vercel-edge/vite"; 2 | import { extendConfig } from "@builder.io/qwik-city/vite"; 3 | import baseConfig from "../../vite.config"; 4 | 5 | export default extendConfig(baseConfig, () => { 6 | return { 7 | build: { 8 | ssr: true, 9 | rollupOptions: { 10 | input: ["src/entry.vercel-edge.tsx", "@qwik-city-plan"], 11 | }, 12 | outDir: ".vercel/output/functions/_qwik-city.func", 13 | }, 14 | plugins: [vercelEdgeAdapter()], 15 | }; 16 | }); 17 | -------------------------------------------------------------------------------- /website/bun.lockb: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ditadi/qwik-hooks/845955676eaa83f8137e199d95874d3ebc16f252/website/bun.lockb -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "my-qwik-empty-starter", 3 | "description": "App with Routing built-in ready to create your app", 4 | "engines": { 5 | "node": "^18.17.0 || ^20.3.0 || >=21.0.0" 6 | }, 7 | "engines-annotation": "Mostly required by sharp which needs a Node-API v9 compatible runtime", 8 | "private": true, 9 | "trustedDependencies": ["sharp"], 10 | "trustedDependencies-annotation": "Needed for bun to allow running install scripts", 11 | "type": "module", 12 | "scripts": { 13 | "build": "qwik build", 14 | "build.client": "vite build", 15 | "build.preview": "vite build --ssr src/entry.preview.tsx", 16 | "build.server": "vite build -c adapters/vercel-edge/vite.config.ts", 17 | "build.types": "tsc --incremental --noEmit", 18 | "deploy": "vercel deploy", 19 | "dev": "vite --mode ssr", 20 | "dev.debug": "node --inspect-brk ./node_modules/vite/bin/vite.js --mode ssr --force", 21 | "fmt": "prettier --write .", 22 | "fmt.check": "prettier --check .", 23 | "lint": "eslint \"src/**/*.ts*\"", 24 | "preview": "qwik build preview && vite preview --open", 25 | "start": "vite --open --mode ssr", 26 | "qwik": "qwik" 27 | }, 28 | "devDependencies": { 29 | "@builder.io/qwik": "^1.5.1", 30 | "@builder.io/qwik-city": "^1.5.1", 31 | "@ditadi/qwik-hooks": "^0.1.6", 32 | "@fontsource-variable/fira-code": "^5.0.17", 33 | "@fontsource-variable/outfit": "^5.0.12", 34 | "@qwik-ui/headless": "^0.3.3", 35 | "@qwik-ui/styled": "^0.0.4", 36 | "@qwik-ui/utils": "^0.2.1", 37 | "@qwikest/icons": "^0.0.13", 38 | "@types/eslint": "^8.56.5", 39 | "@types/node": "^20.11.24", 40 | "@typescript-eslint/eslint-plugin": "^7.1.0", 41 | "@typescript-eslint/parser": "^7.1.0", 42 | "@vercel/analytics": "^1.2.2", 43 | "@vercel/speed-insights": "^1.0.10", 44 | "autoprefixer": "^10.4.14", 45 | "class-variance-authority": "^0.7.0", 46 | "eslint": "^8.57.0", 47 | "eslint-plugin-qwik": "^1.5.1", 48 | "nx": "^18.2.1", 49 | "postcss": "^8.4.31", 50 | "prettier": "^3.2.5", 51 | "prettier-plugin-tailwindcss": "^0.5.4", 52 | "qwik-ui": "^0.1.0", 53 | "shiki": "^1.2.1", 54 | "tailwindcss": "3.3.3", 55 | "typescript": "5.3.3", 56 | "undici": "*", 57 | "vercel": "^29.1.1", 58 | "vite": "^5.1.4", 59 | "vite-tsconfig-paths": "^4.2.1" 60 | }, 61 | "nx": {} 62 | } 63 | -------------------------------------------------------------------------------- /website/postcss.config.cjs: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /website/public/favicon.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://json.schemastore.org/web-manifest-combined.json", 3 | "name": "qwik-project-name", 4 | "short_name": "Welcome to Qwik", 5 | "start_url": ".", 6 | "display": "standalone", 7 | "background_color": "#fff", 8 | "description": "A Qwik project app." 9 | } 10 | -------------------------------------------------------------------------------- /website/public/robots.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ditadi/qwik-hooks/845955676eaa83f8137e199d95874d3ebc16f252/website/public/robots.txt -------------------------------------------------------------------------------- /website/qwik-ui.config.json: -------------------------------------------------------------------------------- 1 | { "componentsRoot": "src/components/ui" } 2 | -------------------------------------------------------------------------------- /website/src/components/code-preview/code-copy.tsx: -------------------------------------------------------------------------------- 1 | import { type PropsOf, component$ } from "@builder.io/qwik"; 2 | import { useCopyClipboard } from "@ditadi/qwik-hooks"; 3 | import { cn } from "@qwik-ui/utils"; 4 | import { Button } from "../ui/button/button"; 5 | 6 | export type CodeCopyProps = PropsOf & { 7 | code?: string; 8 | }; 9 | 10 | export const CodeCopy = component$( 11 | ({ code = "", class: outsideClass, ...props }) => { 12 | const { copy, setCopy } = useCopyClipboard(); 13 | 14 | return ( 15 | 37 | ); 38 | }, 39 | ); 40 | 41 | export function CopyIcon(props: PropsOf<"svg"> & { color?: string }, key: string) { 42 | return ( 43 | 52 | Copy to Clipboard 53 | 57 | 61 | 62 | ); 63 | } 64 | 65 | export function ClipboardCheck(props: PropsOf<"svg">, key: string) { 66 | return ( 67 | 75 | Clipboard Check 76 | 80 | 81 | ); 82 | } 83 | -------------------------------------------------------------------------------- /website/src/components/code-preview/code-preview.tsx: -------------------------------------------------------------------------------- 1 | import { 2 | $, 3 | type ClassList, 4 | type PropsOf, 5 | component$, 6 | useOnWindow, 7 | useSignal, 8 | useTask$, 9 | } from "@builder.io/qwik"; 10 | import { isServer } from "@builder.io/qwik/build"; 11 | import { cn } from "@qwik-ui/utils"; 12 | import { CodeCopy } from "./code-copy"; 13 | import { highlighter as highlighterPromise } from "./highlighter"; 14 | 15 | export type CodePreviewProps = PropsOf<"div"> & { 16 | code: string; 17 | copyCodeClass?: ClassList; 18 | language?: "tsx" | "html" | "css"; 19 | splitCommentStart?: string; 20 | splitCommentEnd?: string; 21 | }; 22 | 23 | export default component$( 24 | ({ 25 | code, 26 | copyCodeClass, 27 | language = "tsx", 28 | splitCommentStart = "{/* start */}", 29 | splitCommentEnd = "{/* end */}", 30 | ...props 31 | }: CodePreviewProps) => { 32 | const codeSig = useSignal(""); 33 | 34 | const generateHighlighter = $(async () => { 35 | const highlighter = await highlighterPromise; 36 | let modifiedCode: string = code; 37 | 38 | let partsOfCode = modifiedCode.split(splitCommentStart); 39 | if (partsOfCode.length > 1) { 40 | modifiedCode = partsOfCode[1]; 41 | } 42 | 43 | partsOfCode = modifiedCode.split(splitCommentEnd); 44 | if (partsOfCode.length > 1) { 45 | modifiedCode = partsOfCode[0]; 46 | } 47 | 48 | const str = highlighter.codeToHtml(modifiedCode, { 49 | lang: language, 50 | themes: { 51 | light: "vitesse-dark", 52 | dark: "vitesse-dark", 53 | }, 54 | }); 55 | codeSig.value = str.toString(); 56 | }); 57 | 58 | useTask$(({ track }) => { 59 | track(() => code); 60 | if (isServer || !code) return; 61 | generateHighlighter(); 62 | }); 63 | 64 | useOnWindow("load", generateHighlighter); 65 | 66 | return ( 67 |
68 | 75 |
82 |
83 |
84 |
85 | ); 86 | }, 87 | ); 88 | -------------------------------------------------------------------------------- /website/src/components/code-preview/highlighter.ts: -------------------------------------------------------------------------------- 1 | import { getHighlighterCore } from "shiki/index.mjs"; 2 | import css from "shiki/langs/css.mjs"; 3 | import html from "shiki/langs/html.mjs"; 4 | import js from "shiki/langs/javascript.mjs"; 5 | import tsx from "shiki/langs/tsx.mjs"; 6 | import ts from "shiki/langs/typescript.mjs"; 7 | import vitesseDark from "shiki/themes/vitesse-dark.mjs"; 8 | import getWasm from "shiki/wasm"; 9 | 10 | export const highlighter = getHighlighterCore({ 11 | themes: [vitesseDark], 12 | langs: [html, css, js, ts, tsx], 13 | loadWasm: getWasm, 14 | }); 15 | -------------------------------------------------------------------------------- /website/src/components/hero/hero.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import Install from "../install/install"; 3 | import QwikHooksLogo from "../layout/logo"; 4 | 5 | export default component$(() => { 6 | return ( 7 |
8 | 9 |
10 |

11 | A collection of modern qwik hooks. 12 |
13 |

14 |
15 |
16 | 17 |
18 |
19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-card.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { Link } from "@builder.io/qwik-city"; 3 | import { LuChevronRight } from "@qwikest/icons/lucide"; 4 | import { Card, CardDescription, CardFooter, CardHeader, CardTitle } from "../ui/card/card"; 5 | 6 | type HookCardProps = { 7 | hook: { 8 | key: string; 9 | title: string; 10 | highlight: string; 11 | }; 12 | }; 13 | export default component$((props) => { 14 | return ( 15 |
  • 16 | 17 | 18 | 19 | {props.hook.title} 20 | 21 | {props.hook.highlight} 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 |
  • 30 | ); 31 | }); 32 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-code.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import CodePreview from "~/components/code-preview/code-preview"; 3 | 4 | type HookCodeProps = { 5 | code: string; 6 | }; 7 | 8 | export default component$((props) => { 9 | if (!props?.code) return null; 10 | return ( 11 |
    12 | Example: 13 | 14 |
    15 | ); 16 | }); 17 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-demo.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | 3 | type HookDemoProps = { 4 | demo: any; 5 | }; 6 | 7 | export default component$((props) => { 8 | const Demo = props.demo; 9 | return ( 10 |
    11 | DEMO: 12 | {} 13 |
    14 | ); 15 | }); 16 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-description.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | type HookDescriptionProps = { 3 | description: string; 4 | }; 5 | export default component$((props) => { 6 | return ( 7 |
    8 | 9 | DESCRIPTION: 10 | 11 | {props.description} 12 |
    13 | ); 14 | }); 15 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-header.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | 3 | type HookHeaderProps = { 4 | title: string; 5 | description: string; 6 | }; 7 | export default component$((props) => { 8 | return ( 9 |
    10 |
    11 |

    12 | {props.title} 13 |

    14 |
    15 |
    16 |

    {props.description}

    17 |
    18 |
    19 | ); 20 | }); 21 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-install.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import Install from "../install/install"; 3 | 4 | export default component$(() => { 5 | return ( 6 |
    7 | 8 | INSTALL: 9 | 10 | 11 |
    12 | ); 13 | }); 14 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-params.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import type { HookParams } from "~/docs"; 3 | 4 | type HookParamsProps = { 5 | params: HookParams[] | null; 6 | }; 7 | 8 | export default component$((props) => { 9 | if (!props.params || !props?.params?.length) 10 | return ( 11 |
    12 | 13 | PARAMETERS 14 | 15 | None 16 |
    17 | ); 18 | return ( 19 |
    20 | PARAMETERS 21 |
    22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | {props.params.map((param) => ( 33 | 34 | 35 | 36 | 39 | 40 | ))} 41 | 42 |
    NameTypeDescription
    {param.name}{param.type} 37 | {param.description} 38 |
    43 |
    44 |
    45 | ); 46 | }); 47 | -------------------------------------------------------------------------------- /website/src/components/hooks/hook-return.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import type { HookReturn } from "~/docs"; 3 | 4 | type HookReturnProps = { 5 | title: string; 6 | return: HookReturn[]; 7 | }; 8 | 9 | export default component$((props) => { 10 | 11 | if (!props.return) { 12 | return null; 13 | } 14 | 15 | return ( 16 |
    17 | 18 | RETURN VALUE 19 | 20 | 21 | The{" "} 22 | 23 | {props.title} 24 | {" "} 25 | hook returns an array with the following elements: 26 | 27 |
    28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | {props.return.map((item) => ( 39 | 40 | 41 | 42 | 43 | 44 | ))} 45 | 46 |
    NameTypeDescription
    {item.name}{item.type}{item.description}
    47 |
    48 |
    49 | ); 50 | }); 51 | -------------------------------------------------------------------------------- /website/src/components/hooks/hooks-list.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import ListOfHooks from "~/docs/index"; 3 | import { Card, CardDescription, CardHeader, CardTitle } from "../ui/card/card"; 4 | import HookCard from "./hook-card"; 5 | 6 | export default component$(() => { 7 | return ( 8 |
    9 |
      10 | {ListOfHooks.map((hook) => ( 11 | 12 | ))} 13 | 14 | 15 | more to come... 16 | 17 | this a new library, more hooks will be added soon. 18 | 19 | 20 | 21 |
    22 |
    23 | ); 24 | }); 25 | -------------------------------------------------------------------------------- /website/src/components/install/install.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { useCopyClipboard } from "@ditadi/qwik-hooks"; 3 | import { LuChevronRight, LuCopy, LuLoader } from "@qwikest/icons/lucide"; 4 | import { Button } from "../ui/button/button"; 5 | 6 | interface InstallProps { 7 | path: string; 8 | bgVariant: "foreground" | "background"; 9 | } 10 | export default component$((props) => { 11 | const { copy, isCopying, setCopy } = useCopyClipboard(); 12 | return ( 13 |
    16 | 17 | 18 | {props.path} 19 | 20 | 40 |
    41 | ); 42 | }); 43 | -------------------------------------------------------------------------------- /website/src/components/layout/disclaimer.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { Link } from "@builder.io/qwik-city"; 3 | 4 | export default component$(() => { 5 | return ( 6 |
    7 |
    8 | this project was heavily inspired by{" "} 9 | 10 | usehooks.dev 11 | {" "} 12 | and built with the purpose of increasing qwik ecosystem. by:{" "} 13 | 17 | @victorditadi 18 | 19 |
    20 |
    21 | ); 22 | return ( 23 |
    24 |
    25 |
    26 | this project was heavily inspired by{" "} 27 | 28 | usehooks.dev 29 | {" "} 30 | and built with the purpose of increasing qwik ecosystem. by:{" "} 31 | 35 | @victorditadi 36 | 37 |
    38 |
    39 |
    40 | ); 41 | }); 42 | -------------------------------------------------------------------------------- /website/src/components/layout/header.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { Link, useLocation } from "@builder.io/qwik-city"; 3 | import { LuChevronLeft, LuGithub, LuTwitter } from "@qwikest/icons/lucide"; 4 | 5 | export default component$(() => { 6 | const location = useLocation(); 7 | return ( 8 |
    9 | 10 | {location.url.pathname !== "/" && ( 11 | 12 | 13 | All Hooks 14 | 15 | )} 16 | 17 |
    18 | 19 | 20 | 21 | 22 | 23 | 24 |
    25 |
    26 | ); 27 | }); 28 | -------------------------------------------------------------------------------- /website/src/components/layout/logo.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | 3 | type QwikHooksProps = { 4 | width: string; 5 | }; 6 | export default component$((props: QwikHooksProps) => { 7 | return ( 8 | 14 | qwik hooks logo 15 | 19 | 20 | 24 | 25 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | ); 37 | }); 38 | -------------------------------------------------------------------------------- /website/src/components/router-head/router-head.tsx: -------------------------------------------------------------------------------- 1 | import { component$ } from "@builder.io/qwik"; 2 | import { useDocumentHead, useLocation } from "@builder.io/qwik-city"; 3 | 4 | /** 5 | * The RouterHead component is placed inside of the document `` element. 6 | */ 7 | export const RouterHead = component$(() => { 8 | const head = useDocumentHead(); 9 | const loc = useLocation(); 10 | 11 | return ( 12 | <> 13 | {head.title} 14 | 15 | 16 | 17 | 18 | 19 | {head.meta.map((m) => ( 20 | 21 | ))} 22 | 23 | {head.links.map((l) => ( 24 | 25 | ))} 26 | 27 | {head.styles.map((s) => ( 28 |