├── .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 | [](https://github.com/uiwjs/react-use-online/actions/workflows/ci.yml)
5 | [](https://uiwjs.github.io/react-use-online/coverage/lcov-report/)
6 | [](https://www.npmjs.com/package/@uiw/react-use-online)
7 | [](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 |
--------------------------------------------------------------------------------