├── .husky ├── .gitignore ├── pre-commit └── commit-msg ├── apps └── web │ ├── src │ ├── modules │ │ ├── index.ts │ │ └── server │ │ │ ├── index.ts │ │ │ └── docs │ │ │ ├── getDocsFolder.ts │ │ │ ├── index.ts │ │ │ ├── getMetaFile.ts │ │ │ ├── getParsedDocPaths.ts │ │ │ ├── getAllDocs.ts │ │ │ ├── getAllMDXFilePaths.ts │ │ │ ├── getDoc.ts │ │ │ ├── getDocPaginationNavigator.ts │ │ │ └── getDocLinks.ts │ ├── components │ │ ├── Modals │ │ │ ├── index.ts │ │ │ └── ExitIntent │ │ │ │ ├── index.tsx │ │ │ │ └── styles.ts │ │ ├── Docs │ │ │ ├── index.ts │ │ │ ├── MDXComponents │ │ │ │ ├── styles.ts │ │ │ │ ├── index.tsx │ │ │ │ └── CodeBox │ │ │ │ │ ├── styles.ts │ │ │ │ │ └── index.tsx │ │ │ ├── LinkTree │ │ │ │ ├── Link │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── styles.ts │ │ │ │ ├── Tree │ │ │ │ │ └── index.tsx │ │ │ │ └── index.tsx │ │ │ └── PaginationNavigator │ │ │ │ ├── styles.ts │ │ │ │ └── index.tsx │ │ ├── Icons │ │ │ ├── index.tsx │ │ │ ├── Spinner │ │ │ │ ├── styles.ts │ │ │ │ └── index.tsx │ │ │ ├── Menu.tsx │ │ │ ├── Clipboard.tsx │ │ │ ├── Checkmark.tsx │ │ │ └── GitHub.tsx │ │ ├── Header │ │ │ ├── styles.ts │ │ │ └── index.tsx │ │ ├── LibraryVersion │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── ExternalLink │ │ │ └── index.tsx │ │ ├── FixedHeader │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── Layout │ │ │ ├── Box │ │ │ │ └── index.ts │ │ │ ├── OuterClickArea │ │ │ │ └── index.ts │ │ │ ├── RootContainer │ │ │ │ └── index.ts │ │ │ ├── Description │ │ │ │ └── index.ts │ │ │ ├── Title │ │ │ │ └── index.ts │ │ │ ├── Background │ │ │ │ └── index.ts │ │ │ ├── Separator │ │ │ │ └── index.ts │ │ │ ├── index.ts │ │ │ └── Button │ │ │ │ └── index.ts │ │ ├── index.ts │ │ ├── Footer │ │ │ ├── index.tsx │ │ │ └── styles.ts │ │ ├── Head │ │ │ └── index.tsx │ │ └── InstallationBox │ │ │ ├── styles.ts │ │ │ └── index.tsx │ ├── templates │ │ ├── index.ts │ │ ├── Home │ │ │ ├── index.tsx │ │ │ ├── Overview │ │ │ │ ├── styles.ts │ │ │ │ └── index.tsx │ │ │ └── Playground │ │ │ │ ├── styles.ts │ │ │ │ └── index.tsx │ │ └── Docs │ │ │ ├── index.tsx │ │ │ └── styles.ts │ ├── shared │ │ ├── utils │ │ │ ├── getPublicPath.ts │ │ │ ├── unslugify.ts │ │ │ ├── index.ts │ │ │ ├── queueTimeouts.ts │ │ │ ├── createDebounce.ts │ │ │ ├── getType.ts │ │ │ └── toObjectTree.ts │ │ ├── constants │ │ │ ├── intersection.ts │ │ │ ├── sizes.ts │ │ │ ├── index.ts │ │ │ ├── commands.ts │ │ │ ├── library.ts │ │ │ ├── meta.ts │ │ │ └── codes.ts │ │ └── types │ │ │ └── index.ts │ ├── pages │ │ ├── index.tsx │ │ ├── _app.tsx │ │ ├── _document.tsx │ │ └── docs │ │ │ └── [...doc].tsx │ ├── hooks │ │ ├── index.ts │ │ ├── useDisclosure.ts │ │ ├── useMatchMedia.ts │ │ ├── usePackageManagerSelection.ts │ │ └── useElementIntersection.ts │ └── styles │ │ ├── keyframes.ts │ │ ├── index.ts │ │ ├── global.ts │ │ └── lib │ │ └── react-syntax-highlighter │ │ └── theme.ts │ ├── .eslintrc.json │ ├── public │ ├── logo.png │ ├── social.png │ ├── favicon.ico │ ├── sparkles.png │ ├── abstract-background.jpg │ ├── link.svg │ ├── background.svg │ └── banner.svg │ ├── docs │ ├── meta.json │ ├── API │ │ ├── properties │ │ │ ├── is-triggered.mdx │ │ │ ├── will-be-triggered.mdx │ │ │ ├── is-unsubscribed.mdx │ │ │ └── settings.mdx │ │ └── methods │ │ │ ├── reset-settings.mdx │ │ │ ├── reset-state.mdx │ │ │ ├── unsubscribe.mdx │ │ │ ├── update-settings.mdx │ │ │ └── register-handler.mdx │ ├── settings │ │ ├── cookie.mdx │ │ ├── mobile.mdx │ │ └── desktop.mdx │ └── getting-started │ │ ├── overview.mdx │ │ └── installation.mdx │ ├── next-env.d.ts │ ├── tsconfig.json │ ├── next.config.mjs │ ├── package.json │ └── README.md ├── commitlint.config.js ├── packages ├── use-exit-intent │ ├── .eslintrc.json │ ├── src │ │ ├── utils │ │ │ ├── factories │ │ │ │ ├── index.ts │ │ │ │ ├── debounce.ts │ │ │ │ └── idleEvents.ts │ │ │ ├── is │ │ │ │ ├── clientSide.ts │ │ │ │ ├── index.ts │ │ │ │ ├── desktop.ts │ │ │ │ └── mobile.ts │ │ │ ├── secondsToMiliseconds.ts │ │ │ ├── index.ts │ │ │ ├── processHandlersByDeviceContext.ts │ │ │ └── constants.ts │ │ ├── types │ │ │ └── index.ts │ │ └── index.ts │ ├── .npmignore │ ├── tsconfig.json │ ├── CHANGELOG.md │ ├── rollup.config.js │ ├── package.json │ └── README.md ├── ts-config │ ├── package.json │ ├── next.json │ └── base.json └── eslint-config │ ├── package.json │ └── index.js ├── .github ├── FUNDING.yml └── workflows │ ├── release-npm.yml │ └── gh-page.yml ├── .editorconfig ├── turbo.json ├── .changeset ├── config.json └── README.md ├── .gitignore ├── LICENSE ├── package.json └── README.md /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ 2 | -------------------------------------------------------------------------------- /apps/web/src/modules/index.ts: -------------------------------------------------------------------------------- 1 | export * from './server' 2 | -------------------------------------------------------------------------------- /apps/web/src/modules/server/index.ts: -------------------------------------------------------------------------------- 1 | export * from './docs' 2 | -------------------------------------------------------------------------------- /apps/web/src/components/Modals/index.ts: -------------------------------------------------------------------------------- 1 | export * from './ExitIntent' 2 | -------------------------------------------------------------------------------- /apps/web/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@daltonmenezes/eslint-config" 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/templates/index.ts: -------------------------------------------------------------------------------- 1 | export * from './Docs' 2 | export * from './Home' 3 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx lint-staged 5 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] } 2 | -------------------------------------------------------------------------------- /packages/use-exit-intent/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@daltonmenezes/eslint-config" 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/shared/utils/getPublicPath.ts: -------------------------------------------------------------------------------- 1 | export const getPublicPath = (assetUrl: string) => assetUrl 2 | -------------------------------------------------------------------------------- /apps/web/public/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daltonmenezes/use-exit-intent/HEAD/apps/web/public/logo.png -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx --no-install commitlint --edit "$1" 5 | -------------------------------------------------------------------------------- /apps/web/public/social.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daltonmenezes/use-exit-intent/HEAD/apps/web/public/social.png -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/factories/index.ts: -------------------------------------------------------------------------------- 1 | export * from './idleEvents' 2 | export * from './debounce' 3 | -------------------------------------------------------------------------------- /apps/web/docs/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "order": [ 3 | "getting-started", 4 | "settings", 5 | "API" 6 | ] 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daltonmenezes/use-exit-intent/HEAD/apps/web/public/favicon.ico -------------------------------------------------------------------------------- /apps/web/public/sparkles.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daltonmenezes/use-exit-intent/HEAD/apps/web/public/sparkles.png -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: daltonmenezes 2 | patreon: daltonmenezes 3 | issuehunt: daltonmenezes/use-exit-intent?tab=idle 4 | -------------------------------------------------------------------------------- /apps/web/src/shared/utils/unslugify.ts: -------------------------------------------------------------------------------- 1 | export function unslugify(slug: string) { 2 | return slug.replace(/\-/g, ' ') 3 | } 4 | -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/is/clientSide.ts: -------------------------------------------------------------------------------- 1 | export function isClientSide() { 2 | return typeof window !== 'undefined' 3 | } 4 | -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/is/index.ts: -------------------------------------------------------------------------------- 1 | export * from './clientSide' 2 | export * from './desktop' 3 | export * from './mobile' 4 | -------------------------------------------------------------------------------- /apps/web/public/abstract-background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/daltonmenezes/use-exit-intent/HEAD/apps/web/public/abstract-background.jpg -------------------------------------------------------------------------------- /apps/web/src/components/Docs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './PaginationNavigator' 2 | export * from './MDXComponents' 3 | export * from './LinkTree' 4 | -------------------------------------------------------------------------------- /apps/web/src/pages/index.tsx: -------------------------------------------------------------------------------- 1 | import { HomeTemplate } from 'templates' 2 | 3 | export default function App() { 4 | return 5 | } 6 | -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/secondsToMiliseconds.ts: -------------------------------------------------------------------------------- 1 | export function secondsToMiliseconds(seconds: number) { 2 | return seconds * 1000 3 | } 4 | -------------------------------------------------------------------------------- /apps/web/src/shared/constants/intersection.ts: -------------------------------------------------------------------------------- 1 | export const intersection = { 2 | options: { 3 | timeout: 200, 4 | offset: 200, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /packages/ts-config/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "private": true, 3 | "name": "@daltonmenezes/ts-config", 4 | "version": "1.0.0", 5 | "license": "MIT" 6 | } 7 | -------------------------------------------------------------------------------- /packages/use-exit-intent/.npmignore: -------------------------------------------------------------------------------- 1 | /src 2 | rollup.config.js 3 | tsconfig.json 4 | .eslintrc* 5 | .editorconfig 6 | commitlint.config.js 7 | rollup.config.js 8 | /.husky 9 | -------------------------------------------------------------------------------- /apps/web/src/components/Icons/index.tsx: -------------------------------------------------------------------------------- 1 | export * from './Checkmark' 2 | export * from './Clipboard' 3 | export * from './Spinner' 4 | export * from './GitHub' 5 | export * from './Menu' 6 | -------------------------------------------------------------------------------- /apps/web/src/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from './usePackageManagerSelection' 2 | export * from './useElementIntersection' 3 | export * from './useDisclosure' 4 | export * from './useMatchMedia' 5 | -------------------------------------------------------------------------------- /apps/web/src/components/Icons/Spinner/styles.ts: -------------------------------------------------------------------------------- 1 | import { styled, animations } from 'styles' 2 | 3 | export const SVG = styled('svg', { 4 | animation: `${animations.spin} 1s linear infinite`, 5 | }) 6 | -------------------------------------------------------------------------------- /apps/web/src/shared/constants/sizes.ts: -------------------------------------------------------------------------------- 1 | import { config } from 'styles' 2 | 3 | export const sizes = { 4 | breakpoints: { 5 | mobile: `${config.media.bp4.replace(/\D/g, '')}`, 6 | }, 7 | } as const 8 | -------------------------------------------------------------------------------- /apps/web/src/components/Header/styles.ts: -------------------------------------------------------------------------------- 1 | import { BaseLayout } from 'components/Layout' 2 | import { styled } from 'styles' 3 | 4 | export const Layout = styled(BaseLayout, { 5 | alignItems: 'center', 6 | }) 7 | -------------------------------------------------------------------------------- /apps/web/src/shared/constants/index.ts: -------------------------------------------------------------------------------- 1 | export * from './intersection' 2 | export * from './commands' 3 | export * from './library' 4 | export * from './codes' 5 | export * from './sizes' 6 | export * from './meta' 7 | -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './processHandlersByDeviceContext' 2 | export * from './secondsToMiliseconds' 3 | export * from './factories' 4 | export * from './constants' 5 | export * from './is' 6 | -------------------------------------------------------------------------------- /apps/web/next-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | /// 3 | 4 | // NOTE: This file should not be edited 5 | // see https://nextjs.org/docs/basic-features/typescript for more information. 6 | -------------------------------------------------------------------------------- /apps/web/src/shared/utils/index.ts: -------------------------------------------------------------------------------- 1 | export * from './createDebounce' 2 | export * from './queueTimeouts' 3 | export * from './getPublicPath' 4 | export * from './toObjectTree' 5 | export * from './unslugify' 6 | export * from './getType' 7 | -------------------------------------------------------------------------------- /apps/web/src/shared/constants/commands.ts: -------------------------------------------------------------------------------- 1 | import { library } from './library' 2 | 3 | export const commands = { 4 | npm: `npm i ${library.name}`, 5 | pnpm: `pnpm i ${library.name}`, 6 | yarn: `yarn add ${library.name}`, 7 | } as const 8 | -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/is/desktop.ts: -------------------------------------------------------------------------------- 1 | import { isClientSide } from './clientSide' 2 | import { isMobile } from './mobile' 3 | 4 | export function isDesktop() { 5 | if (!isClientSide()) return 6 | 7 | return !isMobile() 8 | } 9 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /apps/web/src/modules/server/docs/getDocsFolder.ts: -------------------------------------------------------------------------------- 1 | import { resolve } from 'node:path' 2 | 3 | import packageJSON from '../../../../package.json' 4 | 5 | export function getDocsFolder() { 6 | return resolve(packageJSON?.docsFolder || 'docs') 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/components/LibraryVersion/index.tsx: -------------------------------------------------------------------------------- 1 | import { library } from 'shared/constants' 2 | 3 | import { LibraryVersionContainer } from './styles' 4 | 5 | export function LibraryVersion() { 6 | return v{library.version} 7 | } 8 | -------------------------------------------------------------------------------- /packages/ts-config/next.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "./base.json", 3 | "include": [ 4 | "next-env.d.ts", 5 | "**/*.ts", 6 | "**/*.tsx" 7 | ], 8 | "compilerOptions": { 9 | "module": "esnext", 10 | "jsx": "preserve", 11 | "noEmit": true 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /apps/web/src/components/ExternalLink/index.tsx: -------------------------------------------------------------------------------- 1 | import { AnchorHTMLAttributes, PropsWithChildren } from 'react' 2 | 3 | export function ExternalLink( 4 | props: PropsWithChildren> 5 | ) { 6 | return 7 | } 8 | -------------------------------------------------------------------------------- /apps/web/src/modules/server/docs/index.ts: -------------------------------------------------------------------------------- 1 | export * from './getDocPaginationNavigator' 2 | export * from './getAllMDXFilePaths' 3 | export * from './getDocLinks' 4 | export * from './getParsedDocPaths' 5 | export * from './getMetaFile' 6 | export * from './getAllDocs' 7 | export * from './getDoc' 8 | -------------------------------------------------------------------------------- /packages/use-exit-intent/src/utils/is/mobile.ts: -------------------------------------------------------------------------------- 1 | import { isClientSide } from './clientSide' 2 | 3 | export function isMobile() { 4 | if (!isClientSide()) return 5 | 6 | return ( 7 | window.matchMedia('(hover: none)').matches || 8 | navigator.userAgent.toLowerCase().includes('mobile') 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /packages/use-exit-intent/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@daltonmenezes/ts-config/base.json", 3 | "include": [ 4 | "src", 5 | ], 6 | "compilerOptions": { 7 | "declaration": true, 8 | "declarationDir": "dist/esm", 9 | "emitDeclarationOnly": true, 10 | "outDir": "dist/esm", 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /apps/web/docs/API/properties/is-triggered.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: isTriggered 3 | --- 4 | 5 | # isTriggered 6 | type: **Boolean** 7 | 8 |
9 | 10 | A boolean that indicates if the exit intent was triggered. 11 | 12 |
13 | 14 | ## Example 15 | 16 | ```tsx 17 | const { isTriggered } = useExitIntent() 18 | ``` 19 | -------------------------------------------------------------------------------- /apps/web/src/components/FixedHeader/index.tsx: -------------------------------------------------------------------------------- 1 | import { HeaderContent, HeaderContainer } from './styles' 2 | 3 | export function FixedHeader({ children }: { children: React.ReactNode }) { 4 | return ( 5 | 6 | {children} 7 | 8 | ) 9 | } 10 | -------------------------------------------------------------------------------- /apps/web/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "@daltonmenezes/ts-config/base.json", 3 | "include": [ 4 | "next-env.d.ts", 5 | "**/*.ts", 6 | "**/*.tsx" 7 | ], 8 | "compilerOptions": { 9 | "module": "esnext", 10 | "jsx": "preserve", 11 | "noEmit": true, 12 | "baseUrl": "./src" 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turborepo.org/schema.json", 3 | "pipeline": { 4 | "build": { 5 | "dependsOn": ["^build"], 6 | "outputs": ["dist/**", ".next/**"] 7 | }, 8 | "lint": { 9 | "outputs": [] 10 | }, 11 | "dev": { 12 | "cache": false 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /apps/web/src/components/Docs/MDXComponents/styles.ts: -------------------------------------------------------------------------------- 1 | import { BoxStyles } from 'components/Layout' 2 | import { styled } from 'styles' 3 | 4 | export const SingleTick = styled('span', { 5 | ...BoxStyles, 6 | 7 | width: 'fit-content', 8 | padding: '0.3rem', 9 | backgroundColor: '$border-primary', 10 | borderRadius: 4, 11 | }) 12 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.2.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["web"] 11 | } 12 | -------------------------------------------------------------------------------- /apps/web/docs/API/properties/will-be-triggered.mdx: -------------------------------------------------------------------------------- 1 | --- 2 | title: willBeTriggered 3 | --- 4 | 5 | # willBeTriggered 6 | type: **Boolean** 7 | 8 |
9 | 10 | A boolean that indicates if the exit intent will be triggered. 11 | 12 |
13 | 14 | ## Example 15 | 16 | ```tsx 17 | const { willBeTriggered } = useExitIntent() 18 | ``` 19 | -------------------------------------------------------------------------------- /apps/web/src/components/Docs/LinkTree/Link/index.tsx: -------------------------------------------------------------------------------- 1 | import NextLink from 'next/link' 2 | 3 | import { Button, ButtonProps } from './styles' 4 | 5 | export function Link({ href, ...restOfProps }: ButtonProps) { 6 | return ( 7 | 8 |