Skip to content

Commit

Permalink
React 18 (#1)
Browse files Browse the repository at this point in the history
  • Loading branch information
adhamu authored Apr 18, 2022
1 parent 9c58d65 commit 0cb7dc0
Show file tree
Hide file tree
Showing 17 changed files with 1,405 additions and 1,404 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ yarn add react-input-suggestions
## Usage

```jsx
import React from 'react'
import { InputSuggestions } from 'react-input-suggestions'

const MyComponent = () => (
Expand Down Expand Up @@ -79,7 +78,6 @@ The markup is very simple. You bring what populates each search suggestion. In t
If you wanted to do something else `onClick` or `onKeyDown`, you could do something like:

```jsx
import React from 'react'
import { InputSuggestions } from 'react-input-suggestions'

const customFunction = (arg: string) => {
Expand Down
75 changes: 75 additions & 0 deletions esbuild.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
const path = require('path')

const chokidar = require('chokidar')
const esbuild = require('esbuild')
const liveServer = require('live-server')

const root = './public'

const build = process.argv[2] === 'build' || false
const dev = process.argv[2] === 'dev' || false
const watch = (dev && process.argv[3] === '--watch') || false

const common = {
bundle: true,
inject: [path.join(__dirname, './react-shim.js')],
sourcemap: false,
}

if (build) {
const options = {
...common,
entryPoints: ['./src/index.ts'],
external: Object.keys(require('./package.json').dependencies || {}),
logLevel: 'info',
minify: true,
target: ['esnext'],
}

esbuild.build({
...options,
format: 'esm',
outfile: './dist/index.esm.js',
})

esbuild.build({
...options,
format: 'cjs',
outfile: './dist/index.js',
})
}

if (dev) {
;(async () => {
const builder = await esbuild.build({
...common,
define: {
'process.env.NODE_ENV': JSON.stringify(
process.env.NODE_ENV || 'development'
),
},
entryPoints: ['./src/example/index.tsx'],
incremental: true,
minify: !watch,
outfile: `./${root}/script.js`,
})

if (!watch) {
process.exit(0)
}

chokidar
.watch('./src/**/*.{ts,tsx}', {
interval: 0,
})
.on('all', () => {
builder.rebuild()
})

liveServer.start({
open: true,
port: +process.env.PORT || 8080,
root,
})
})()
}
25 changes: 0 additions & 25 deletions esbuild/build.js

This file was deleted.

43 changes: 0 additions & 43 deletions esbuild/dev.js

This file was deleted.

37 changes: 18 additions & 19 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "react-input-suggestions",
"version": "1.0.2",
"version": "2.0.0",
"description": "A React input component with pluggable suggestions and autocomplete",
"keywords": [
"react",
Expand All @@ -26,11 +26,11 @@
],
"scripts": {
"prebuild": "npx rimraf dist",
"build": "node esbuild/build.js",
"build": "node esbuild.config.js build",
"postbuild": "tsc --project tsconfig.build.json",
"predeploy": "node esbuild/dev.js",
"predeploy": "node esbuild.config.js dev",
"deploy": "gh-pages -d public",
"dev": "node esbuild/dev.js --watch",
"dev": "node esbuild.config.js dev --watch",
"lint": "yarn lint:scripts && yarn lint:styles",
"lint:scripts": "eslint 'src/**/*.ts*' --ignore-path=.eslintignore --config=.eslintrc.json",
"lint:styles": "stylelint 'src/**/*.ts*'",
Expand All @@ -39,34 +39,33 @@
"type": "tsc --noEmit"
},
"dependencies": {
"@emotion/react": "^11.8.1",
"@emotion/react": "^11.8.2",
"@emotion/styled": "^11.8.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react": "^18.0.0",
"react-dom": "^18.0.0",
"react-string-replace": "^1.0.0"
},
"devDependencies": {
"@adhamu/zero": "^3.0.1",
"@adhamu/zero": "^4.0.0",
"@emotion/jest": "^11.8.0",
"@stylelint/postcss-css-in-js": "^0.37.2",
"@testing-library/jest-dom": "^5.16.2",
"@testing-library/react": "^12.1.4",
"@testing-library/react-hooks": "^7.0.2",
"@testing-library/user-event": "^13.5.0",
"@testing-library/jest-dom": "^5.16.4",
"@testing-library/react": "^13.1.1",
"@testing-library/user-event": "^14.1.1",
"@types/jest": "^27.4.1",
"@types/react": "^17.0.39",
"@types/react-dom": "^17.0.13",
"@types/react": "^18.0.5",
"@types/react-dom": "^18.0.1",
"chokidar": "^3.5.3",
"esbuild": "^0.14.25",
"esbuild": "^0.14.36",
"gh-pages": "^3.2.3",
"jest": "^27.5.1",
"live-server": "^1.2.1",
"postcss-syntax": "^0.36.2",
"ts-jest": "^27.1.3",
"typescript": "^4.6.2"
"ts-jest": "^27.1.4",
"typescript": "^4.6.3"
},
"peerDependencies": {
"react": "^17.0.2",
"react-dom": "^17.0.2"
"react": "^18.0.0",
"react-dom": "^18.0.0"
}
}
4 changes: 4 additions & 0 deletions react-shim.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import * as React from 'react'

// eslint-disable-next-line import/prefer-default-export
export { React }
9 changes: 5 additions & 4 deletions src/InputSuggestions.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'
import type { ReactNode } from 'react'
import { useRef, useState } from 'react'

import type { Props } from './types'

Expand All @@ -18,9 +19,9 @@ const InputSuggestions = ({
onChange,
highlightKeywords = false,
}: Props): JSX.Element => {
const [results, setResults] = React.useState<React.ReactNode[]>(suggestions)
const inputSearchRef = React.useRef<HTMLInputElement>(null)
const searchSuggestionsRef = React.useRef<HTMLUListElement>(null)
const [results, setResults] = useState<ReactNode[]>(suggestions)
const inputSearchRef = useRef<HTMLInputElement>(null)
const searchSuggestionsRef = useRef<HTMLUListElement>(null)

const {
selectInitialResult,
Expand Down
42 changes: 23 additions & 19 deletions src/__tests__/InputSuggestions.test.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react'

import { render, screen } from '@testing-library/react'
import { render, screen, waitFor } from '@testing-library/react'
import userEvent from '@testing-library/user-event'

import InputSuggestions from '../InputSuggestions'
Expand Down Expand Up @@ -125,16 +123,16 @@ describe('InputSuggestions', () => {
expect(container.firstChild).toHaveClass('react-search')
})

it('calls wrapElementText when highlightKeywords provided', () => {
it('calls wrapElementText when highlightKeywords provided', async () => {
render(<InputSuggestions suggestions={suggestions} highlightKeywords />)

userEvent.type(screen.getByRole('searchbox'), 't')

expect(mockWrapElementText).toHaveBeenCalledTimes(2)
await waitFor(() => expect(mockWrapElementText).toHaveBeenCalledTimes(2))
})
})

it('fires an onChange event if provided', () => {
it('fires an onChange event if provided', async () => {
const mockOnChange = jest.fn()

render(
Expand All @@ -145,31 +143,37 @@ describe('InputSuggestions', () => {

userEvent.type(screen.getByRole('searchbox'), 't')

expect(mockOnChange).toHaveBeenCalled()
expect(mockGetElementText).toHaveBeenCalled()
await waitFor(() => expect(mockOnChange).toHaveBeenCalled())
await waitFor(() => expect(mockGetElementText).toHaveBeenCalled())
})

it('shows filtered search suggestions based on input entered', () => {
it('shows filtered search suggestions based on input entered', async () => {
render(<InputSuggestions suggestions={suggestions} />)

expect(screen.queryByRole('list')).not.toBeInTheDocument()

userEvent.type(screen.getByRole('searchbox'), 't')

expect(screen.getByRole('list')).toBeInTheDocument()
expect(await screen.findByRole('list')).toBeInTheDocument()

expect(screen.getByRole('link', { name: 'reddit' })).toHaveAttribute(
'href',
'https://reddit.com'
await waitFor(() =>
expect(screen.getByRole('link', { name: 'reddit' })).toHaveAttribute(
'href',
'https://reddit.com'
)
)

expect(screen.getByRole('link', { name: 'twitter' })).toHaveAttribute(
'href',
'https://twitter.com'
await waitFor(() =>
expect(screen.getByRole('link', { name: 'twitter' })).toHaveAttribute(
'href',
'https://twitter.com'
)
)

expect(
screen.queryByRole('link', { name: 'facebook' })
).not.toBeInTheDocument()
await waitFor(() =>
expect(
screen.queryByRole('link', { name: 'facebook' })
).not.toBeInTheDocument()
)
})
})
2 changes: 0 additions & 2 deletions src/__tests__/elementText.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react'

import { render } from '@testing-library/react'

import { getElementText, wrapElementText } from '../elementText'
Expand Down
2 changes: 0 additions & 2 deletions src/__tests__/styled.test.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import React from 'react'

import { render } from '@testing-library/react'

import { Styled } from '../styled'
Expand Down
5 changes: 1 addition & 4 deletions src/__tests__/useSuggestions.test.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import React from 'react'

import { screen } from '@testing-library/react'
import { renderHook } from '@testing-library/react-hooks'
import { renderHook, screen } from '@testing-library/react'

import { useSuggestions } from '../useSuggestions'

Expand Down
13 changes: 7 additions & 6 deletions src/elementText.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import React from 'react'
import type { ReactElement } from 'react'
import React, { Children, cloneElement } from 'react'

import reactStringReplace from 'react-string-replace'

Expand All @@ -12,7 +13,7 @@ export const getElementText = (node: React.ReactNode): string | undefined => {
}

if (typeof node === 'object' && node) {
return getElementText((node as React.ReactElement).props.children)
return getElementText((node as ReactElement).props.children)
}

return undefined
Expand All @@ -23,10 +24,10 @@ const highlightKeyword = (content: string, keyword: string) =>
<mark key={key}>{match}</mark>
))

const cloneChildren = (children: React.ReactElement[], keyword: string): any =>
React.Children.map(children, child =>
const cloneChildren = (children: ReactElement[], keyword: string): any =>
Children.map(children, child =>
child.props
? React.cloneElement(child, {
? cloneElement(child, {
children: highlightKeyword(
cloneChildren(child.props.children, keyword),
keyword
Expand All @@ -38,7 +39,7 @@ const cloneChildren = (children: React.ReactElement[], keyword: string): any =>
export const wrapElementText = (
node: React.ReactNode,
keyword: string
): React.ReactElement | React.ReactNode => {
): ReactElement | React.ReactNode => {
const n = node as React.ReactElement
const {
props: { children },
Expand Down
Loading

0 comments on commit 0cb7dc0

Please sign in to comment.