├── .github ├── FUNDING.yml └── workflows │ └── ci.yml ├── .gitignore ├── .husky └── pre-commit ├── .prettierignore ├── .prettierrc ├── LICENSE ├── README.md ├── core ├── README.md ├── package.json ├── src │ └── index.tsx └── tsconfig.json ├── lerna.json ├── package.json ├── renovate.json ├── test └── index.test.tsx ├── tsconfig.json └── website ├── .kktrc.ts ├── README.md ├── package.json ├── public ├── favicon.ico └── index.html ├── src ├── index.tsx └── react-app-env.d.ts └── tsconfig.json /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [jaywcjlove] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: #npm/kkt 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | custom: # https://jaywcjlove.github.io/sponsor.html 10 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | # env: 8 | # SKIP_PREFLIGHT_CHECK: true 9 | jobs: 10 | build: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - uses: actions/checkout@v3 14 | - uses: actions/setup-node@v3 15 | with: 16 | node-version: 16 17 | registry-url: 'https://registry.npmjs.org' 18 | 19 | - run: npm install --unsafe-perm 20 | # - run: npm run hoist 21 | - run: npm run build 22 | - run: npm run coverage 23 | - run: npm run doc 24 | 25 | - name: Generate Contributors Images 26 | uses: jaywcjlove/github-action-contributors@main 27 | with: 28 | filter-author: (renovate\[bot\]|renovate-bot|dependabot\[bot\]) 29 | output: website/build/CONTRIBUTORS.svg 30 | avatarSize: 42 31 | 32 | - name: Create Coverage Badges 33 | uses: jaywcjlove/coverage-badges-cli@main 34 | with: 35 | output: website/build/badges.svg 36 | 37 | - run: cp -rp coverage website/build 38 | 39 | - name: Is a tag created auto? 40 | id: create_tag 41 | uses: jaywcjlove/create-tag-action@main 42 | with: 43 | token: ${{ secrets.GITHUB_TOKEN }} 44 | package-path: ./core/package.json 45 | 46 | - name: get tag version 47 | id: tag_version 48 | uses: jaywcjlove/changelog-generator@main 49 | 50 | - name: Deploy 51 | uses: peaceiris/actions-gh-pages@v3 52 | with: 53 | commit_message: ${{steps.tag_version.outputs.tag}} ${{ github.event.head_commit.message }} 54 | github_token: ${{ secrets.GITHUB_TOKEN }} 55 | publish_dir: ./website/build 56 | 57 | - name: Generate Changelog 58 | id: changelog 59 | uses: jaywcjlove/changelog-generator@main 60 | if: steps.create_tag.outputs.successful 61 | with: 62 | head-ref: ${{ steps.create_tag.outputs.version }} 63 | filter-author: (小弟调调™|Renovate Bot|renovate-bot) 64 | filter: '[R|r]elease[d]\s+[v|V]\d(\.\d+){0,2}' 65 | 66 | - name: Create Release 67 | uses: ncipollo/release-action@v1 68 | if: steps.create_tag.outputs.successful 69 | with: 70 | token: ${{ secrets.GITHUB_TOKEN }} 71 | name: ${{ steps.changelog.outputs.tag }} 72 | tag: ${{ steps.changelog.outputs.tag }} 73 | body: | 74 | Documentation ${{ steps.changelog.outputs.tag }}: https://raw.githack.com/uiwjs/react-use-online/${{ steps.changelog.outputs.gh-pages-short-hash }}/index.html 75 | Comparing Changes: ${{ steps.changelog.outputs.compareurl }} 76 | 77 | ${{ steps.changelog.outputs.changelog }} 78 | 79 | - run: npm publish --access public 80 | name: 📦 @uiw/react-use-online to NPM 81 | working-directory: core 82 | continue-on-error: true 83 | env: 84 | NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }} 85 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | coverage 3 | dist 4 | build 5 | lib 6 | esm 7 | cjs 8 | 9 | 10 | # Log files 11 | npm-debug.log* 12 | yarn.lock 13 | yarn-debug.log* 14 | yarn-error.log* 15 | pnpm-debug.log* 16 | package-lock.json 17 | 18 | # local env files 19 | .env.local 20 | .env.*.local 21 | 22 | # Editor directories and files 23 | .DS_Store 24 | .idea 25 | .lerna_backup 26 | .vscode 27 | *.suo 28 | *.ntvs* 29 | *.njsproj 30 | *.sln 31 | *.sw? 32 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install lint-staged -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | **/*.md 2 | **/*.svg 3 | **/*.ejs 4 | **/*.yml 5 | package.json 6 | node_modules 7 | dist 8 | build 9 | lib 10 | esm 11 | cjs 12 | test -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "singleQuote": true, 3 | "trailingComma": "all", 4 | "printWidth": 120, 5 | "overrides": [ 6 | { 7 | "files": ".prettierrc", 8 | "options": { "parser": "json" } 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 uiw 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 | core/README.md -------------------------------------------------------------------------------- /core/README.md: -------------------------------------------------------------------------------- 1 | React useOnline Hook 2 | === 3 | 4 | [![Build & Deploy](https://github.com/uiwjs/react-use-online/actions/workflows/ci.yml/badge.svg)](https://github.com/uiwjs/react-use-online/actions/workflows/ci.yml) 5 | [![Coverage Status](https://uiwjs.github.io/react-use-online/badges.svg)](https://uiwjs.github.io/react-use-online/coverage/lcov-report/) 6 | [![NPM Version](https://img.shields.io/npm/v/@uiw/react-use-online.svg)](https://www.npmjs.com/package/@uiw/react-use-online) 7 | [![react@^18](https://shields.io/badge/react-^18-green?style=flat&logo=react)](https://github.com/facebook/react/releases) 8 | 9 | `useOnline` is a tiny, zero-dependency, SSR hook for responding to online/offline changes. 10 | 11 | ## Quick Start 12 | 13 | ```bash 14 | npm install @uiw/react-use-online 15 | ``` 16 | 17 | ## Using 18 | 19 | You can use the Chrome Browser Debug Tool(**f11**) to set up **offLine** and **onLine** test hooks. 20 | 21 | ```jsx mdx:preview 22 | import React from "react"; 23 | import { useOnline } from '@uiw/react-use-online'; 24 | 25 | export default function App() { 26 | const isOnline = useOnline(); 27 | return ( 28 |
29 |

useOnline

30 |
{isOnline ? '✅ You are online' : '❌ You are offline'}
31 |
32 | ); 33 | } 34 | ``` 35 | 36 | ## Related 37 | 38 | - [useColorScheme](https://github.com/uiwjs/react-use-colorscheme) `useColorScheme()` is a tiny, zero-dependency, SSR hook for responding to devices color scheme changes. 39 | 40 | ## Contributors 41 | 42 | As always, thanks to our amazing contributors! 43 | 44 | 45 | 46 | 47 | 48 | Made with [contributors](https://github.com/jaywcjlove/github-action-contributors). 49 | 50 | ## License 51 | 52 | Licensed under the MIT License. 53 | -------------------------------------------------------------------------------- /core/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@uiw/react-use-online", 3 | "version": "1.0.0", 4 | "description": "useOnline is a tiny, zero-dependency hook for responding to online/offline changes.", 5 | "author": "Kenny Wong ", 6 | "homepage": "https://uiwjs.github.io/react-use-online", 7 | "repository": { 8 | "type": "git", 9 | "url": "https://github.com/uiwjs/react-use-online.git" 10 | }, 11 | "license": "MIT", 12 | "main": "./cjs/index.js", 13 | "module": "./esm/index.js", 14 | "files": [ 15 | "cjs", 16 | "esm", 17 | "src" 18 | ], 19 | "publishConfig": { 20 | "access": "public" 21 | }, 22 | "keywords": [ 23 | "react-use-online", 24 | "react.js", 25 | "react", 26 | "online", 27 | "network", 28 | "hook", 29 | "hooks", 30 | "reacthook", 31 | "uiw", 32 | "uiw-react", 33 | "react-component", 34 | "component", 35 | "components", 36 | "ui", 37 | "framework" 38 | ], 39 | "peerDependencies": { 40 | "react": ">=16.9.0", 41 | "react-dom": ">=16.9.0" 42 | }, 43 | "devDependencies": { 44 | "@babel/runtime": "^7.18.9", 45 | "react": "^18.2.0", 46 | "react-dom": "^18.2.0" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /core/src/index.tsx: -------------------------------------------------------------------------------- 1 | import React, { useSyncExternalStore } from 'react'; 2 | 3 | function getSnapshot() { 4 | return navigator.onLine; 5 | } 6 | 7 | function getServerSnapshot() { 8 | return true; 9 | } 10 | 11 | function subscribe(callback: () => void) { 12 | window.addEventListener('online', callback); 13 | window.addEventListener('offline', callback); 14 | return () => { 15 | window.removeEventListener('online', callback); 16 | window.removeEventListener('offline', callback); 17 | }; 18 | } 19 | 20 | export function useOnline() { 21 | return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); 22 | } 23 | -------------------------------------------------------------------------------- /core/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "include": ["src"], 4 | "compilerOptions": { 5 | "outDir": "./cjs", 6 | "baseUrl": ".", 7 | "noEmit": false 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lerna.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "1.0.0", 3 | "packages": ["website", "core"] 4 | } 5 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "scripts": { 4 | "⬇️⬇️⬇️⬇️⬇️ package ⬇️⬇️⬇️⬇️⬇️": "▼▼▼▼▼ package ▼▼▼▼▼", 5 | "build": "lerna exec --scope @uiw/* -- tsbb build src/*.tsx --use-babel --cjs cjs --bail", 6 | "watch": "lerna exec \"tsbb watch src/*.tsx --use-babel --cjs cjs\" --scope @uiw/*", 7 | "⬆️⬆️⬆️⬆️⬆️ package ⬆️⬆️⬆️⬆️⬆️": "▲▲▲▲▲ package ▲▲▲▲▲", 8 | "start": "lerna exec --scope website -- npm run start", 9 | "doc": "lerna exec --scope website -- npm run build", 10 | "bootstrap": "lerna bootstrap", 11 | "hoist": "lerna bootstrap --hoist", 12 | "test": "tsbb test", 13 | "coverage": "tsbb test --coverage --bail", 14 | "prepare": "husky install", 15 | "version": "lerna version --exact --force-publish --no-push --no-git-tag-version", 16 | "prettier": "prettier --write '**/*.{js,jsx,tsx,ts,less,md,json}'", 17 | "remove": "npm run clean && lerna exec \"rm -rf package-lock.json\" --scope @uiw/* --scope website", 18 | "clean": "lerna clean --yes" 19 | }, 20 | "lint-staged": { 21 | "*.{js,jsx,ts,tsx,less,md,json}": [ 22 | "prettier --write" 23 | ] 24 | }, 25 | "jest": { 26 | "collectCoverageFrom": [ 27 | "/core/src/**/*.{js,jsx,ts,tsx}" 28 | ], 29 | "testMatch": [ 30 | "/test/*.{ts,tsx}" 31 | ], 32 | "transformIgnorePatterns": [ 33 | "/node_modules/?!(.*)" 34 | ] 35 | }, 36 | "workspaces": [ 37 | "website", 38 | "core" 39 | ], 40 | "engines": { 41 | "node": ">=16.0.0" 42 | }, 43 | "devDependencies": { 44 | "@testing-library/react": "^14.0.0", 45 | "@types/react": "^18.0.17", 46 | "@types/react-dom": "^18.0.6", 47 | "react": "^18.2.0", 48 | "react-dom": "^18.2.0", 49 | "husky": "^8.0.1", 50 | "jest": "^29.5.0", 51 | "jest-environment-jsdom": "^29.6.0", 52 | "jest-environment-node": "^29.5.0", 53 | "jest-watch-typeahead": "^2.2.2", 54 | "lerna": "^7.1.4", 55 | "lint-staged": "^13.0.3", 56 | "prettier": "^3.0.1", 57 | "tsbb": "^4.1.14" 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /renovate.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://docs.renovatebot.com/renovate-schema.json", 3 | "extends": ["config:base"], 4 | "packageRules": [ 5 | { 6 | "matchPackagePatterns": ["*"], 7 | "rangeStrategy": "replace" 8 | } 9 | ] 10 | } 11 | -------------------------------------------------------------------------------- /test/index.test.tsx: -------------------------------------------------------------------------------- 1 | import { renderHook } from '@testing-library/react'; 2 | import { useOnline } from '../core/src'; 3 | 4 | describe('useOnline', () => { 5 | it('should return true when online status is true', () => { 6 | jest.spyOn(navigator, 'onLine', 'get').mockReturnValueOnce(true); 7 | const { result } = renderHook(() => useOnline()); 8 | expect(result.current).toBe(true); 9 | }); 10 | it('should return true when online status is false', () => { 11 | jest.spyOn(navigator, 'onLine', 'get').mockReturnValue(false); 12 | const { result } = renderHook(() => useOnline()); 13 | expect(result.current).toBe(false); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "jsx": "react", 4 | "target": "esnext", 5 | "lib": ["dom", "dom.iterable", "esnext"], 6 | "allowJs": true, 7 | "skipLibCheck": true, 8 | "esModuleInterop": true, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "declaration": true, 17 | "baseUrl": ".", 18 | "noFallthroughCasesInSwitch": true, 19 | "noEmit": true 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /website/.kktrc.ts: -------------------------------------------------------------------------------- 1 | import webpack from 'webpack'; 2 | import { WebpackConfiguration, LoaderConfOptions } from 'kkt'; 3 | import { mdCodeModulesLoader } from 'markdown-react-code-preview-loader'; 4 | import pkg from './package.json'; 5 | 6 | export default (conf: WebpackConfiguration, env: 'development' | 'production', options: LoaderConfOptions) => { 7 | conf = mdCodeModulesLoader(conf); 8 | conf.plugins!.push( 9 | new webpack.DefinePlugin({ 10 | VERSION: JSON.stringify(pkg.version), 11 | }), 12 | ); 13 | 14 | conf.module!.exprContextCritical = false; 15 | if (env === 'production') { 16 | conf.output = { ...conf.output, publicPath: './' }; 17 | conf.optimization = { 18 | ...conf.optimization, 19 | splitChunks: { 20 | cacheGroups: { 21 | reactvendor: { 22 | test: /[\\/]node_modules[\\/](react|react-dom)[\\/]/, 23 | name: 'react-vendor', 24 | chunks: 'all', 25 | }, 26 | refractor: { 27 | test: /[\\/]node_modules[\\/](refractor)[\\/]/, 28 | name: 'refractor-prismjs-vendor', 29 | chunks: 'all', 30 | }, 31 | }, 32 | }, 33 | }; 34 | } 35 | 36 | return conf; 37 | }; 38 | -------------------------------------------------------------------------------- /website/README.md: -------------------------------------------------------------------------------- 1 | Document Website 2 | === 3 | 4 | https://uiwjs.github.io/react-monorepo-template -------------------------------------------------------------------------------- /website/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "website", 3 | "version": "1.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "kkt start", 7 | "build": "kkt build" 8 | }, 9 | "license": "MIT", 10 | "dependencies": { 11 | "@uiw/react-markdown-preview-example": "^1.5.6", 12 | "@uiw/react-use-online": "1.0.0", 13 | "react": "^18.2.0", 14 | "react-dom": "^18.2.0" 15 | }, 16 | "devDependencies": { 17 | "@types/react": "^18.0.17", 18 | "@types/react-dom": "^18.0.6", 19 | "kkt": "^7.4.9", 20 | "markdown-react-code-preview-loader": "^2.1.2" 21 | }, 22 | "eslintConfig": { 23 | "extends": [ 24 | "react-app", 25 | "react-app/jest" 26 | ] 27 | }, 28 | "browserslist": { 29 | "production": [ 30 | ">0.2%", 31 | "not dead", 32 | "not op_mini all" 33 | ], 34 | "development": [ 35 | "last 1 chrome version", 36 | "last 1 firefox version", 37 | "last 1 safari version" 38 | ] 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /website/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/uiwjs/react-use-online/dae573a83e5a702d5d6040b66909d7db9c6d97ee/website/public/favicon.ico -------------------------------------------------------------------------------- /website/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | React useOnline Hook 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 24 | 25 | -------------------------------------------------------------------------------- /website/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { createRoot } from 'react-dom/client'; 2 | import MarkdownPreviewExample from '@uiw/react-markdown-preview-example'; 3 | import pkg from '@uiw/react-use-online/package.json'; 4 | import data from '@uiw/react-use-online/README.md'; 5 | 6 | const Github = MarkdownPreviewExample.Github; 7 | 8 | const container = document.getElementById('root'); 9 | const root = createRoot(container!); 10 | root.render( 11 | 19 | 20 | , 21 | ); 22 | -------------------------------------------------------------------------------- /website/src/react-app-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | 3 | declare var VERSION: string; 4 | 5 | declare module '*.md' { 6 | import { CodeBlockData } from 'markdown-react-code-preview-loader'; 7 | const src: CodeBlockData; 8 | export default src; 9 | } 10 | -------------------------------------------------------------------------------- /website/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "../tsconfig", 3 | "include": [".kktrc.ts", "src"], 4 | "compilerOptions": { 5 | "jsx": "react-jsx", 6 | "baseUrl": "./src", 7 | "noEmit": true 8 | } 9 | } 10 | --------------------------------------------------------------------------------