diff --git a/README.md b/README.md index 3173927..0ec7159 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,11 @@ # React Native Highlight Words -React Native component used to highlight words within a larger body of text. This is a port of [react-highlight-words](https://github.com/bvaughn/react-highlight-words). -Check out a [demo](https://getexponent.com/@clauderic/react-native-highlight-words) using Exponent. +React Native component used to highlight words within a larger body of text. This is a port of [react-highlight-words](https://github.com/bvaughn/react-highlight-words). ## Installation -Using [npm](https://www.npmjs.com/package/react-native-highlight-words): + ``` -npm i --save react-native-highlight-words +npm i --save @javier.alejandro.castro/react-native-highlight-words ``` ## Usage @@ -14,7 +13,7 @@ npm i --save react-native-highlight-words To use it, just provide it with an array of search terms and a body of text to highlight: ```jsx -import Highlighter from 'react-native-highlight-words'; +import Highlighter from '@javier.alejandro.castro/react-native-highlight-words'; - ## Props -| Property | Type | Required? | Description | -|:----------------|:--------------|:---------:|:------------------------------------------------------------------------------------------------------------------------| -| autoEscape | Boolean | | Escape characters which are meaningful in regular expressions | -| highlightStyle | Object | | Styles applied to highlighted text | -| sanitize | Function | | Process each search word and text to highlight before comparing (eg remove accents); signature `(text: string): string` | -| searchWords | Array | ✓ | Array of search words | -| style | Object | | Styles applied to the text wrapper | -| textToHighlight | String | ✓ | Text to highlight matches in | +| Property | Type | Required? | Description | +| :----------------- | :------------ | :-------: | :---------------------------------------------------------------------------------------------------------------------- | +| autoEscape | Boolean | | Escape characters which are meaningful in regular expressions | +| highlightStyle | Object | | Styles applied to highlighted text | +| sanitize | Function | | Process each search word and text to highlight before comparing (eg remove accents); signature `(text: string): string` | +| searchWords | Array | ✓ | Array of search words | +| style | Object | | Styles applied to the text wrapper | +| textToHighlight | String | ✓ | Text to highlight matches in | +| onPress | Function | | onPress event for normal text | +| onPressHighlighted | Function | | onPress event for highlighted text (returns text that clicked) | ## License + MIT License - fork, modify and use however you want. diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..3e9e1df --- /dev/null +++ b/index.d.ts @@ -0,0 +1,47 @@ +import { TextStyle, StyleProp, TextProps } from "react-native"; +import React from "react"; + +type HighlighterProps = { + /** + * Escape characters which are meaningful in regular expressions + */ + autoEscape?: boolean; + + /** + * Styles applied to highlighted text + */ + highlightStyle?: StyleProp; + + /** + * Process each search word and text to highlight before comparing (eg remove accents); + */ + sanitize?: (text: string) => string; + + /** + * This function is called on press. + */ + onPress?: ((event: GestureResponderEvent) => void) | undefined; + + /** + * This function is called on press of the highlighted text. + */ + onPressHighlighted?: ((text: string) => void) | undefined; + + /** + * Array of search words + */ + searchWords: string[]; + + /** + * Styles applied to the text wrapper + */ + style?: StyleProp; + + /** + * Text to highlight matches in + */ + textToHighlight: string; +} & TextProps; + +declare const Highlighter: React.FC; +export default Highlighter; diff --git a/index.js b/index.js index e15cc90..acff3d7 100644 --- a/index.js +++ b/index.js @@ -1,47 +1,66 @@ -import React from 'react'; -import {Text} from 'react-native'; -import {findAll} from 'highlight-words-core'; -import PropTypes from 'prop-types'; +import React from "react"; +import { Text } from "react-native"; +import { findAll } from "highlight-words-core"; +import PropTypes, { oneOfType } from "prop-types"; +import { TextPropTypes } from "deprecated-react-native-prop-types"; Highlighter.propTypes = { autoEscape: PropTypes.bool, - highlightStyle: Text.propTypes.style, - searchWords: PropTypes.arrayOf(PropTypes.string).isRequired, + highlightStyle: TextPropTypes.style, + searchWords: oneOfType([ + PropTypes.arrayOf(PropTypes.string), + PropTypes.arrayOf(PropTypes.instanceOf(RegExp)) + ]).isRequired, textToHighlight: PropTypes.string.isRequired, sanitize: PropTypes.func, - style: Text.propTypes.style + style: TextPropTypes.style }; /** -* Highlights all occurrences of search terms (searchText) within a string (textToHighlight). -* This function returns an array of strings and elements (wrapping highlighted words). -*/ + * Highlights all occurrences of search terms (searchText) within a string (textToHighlight). + * This function returns an array of strings and elements (wrapping highlighted words). + */ export default function Highlighter({ autoEscape, highlightStyle, searchWords, textToHighlight, sanitize, + onPress, + onPressHighlighted, style, ...props }) { - const chunks = findAll({textToHighlight, searchWords, sanitize, autoEscape}); + const chunks = findAll({ + textToHighlight, + searchWords, + sanitize, + autoEscape + }); return ( - + {chunks.map((chunk, index) => { - const text = textToHighlight.substr(chunk.start, chunk.end - chunk.start); + const text = textToHighlight.substr( + chunk.start, + chunk.end - chunk.start + ); - return (!chunk.highlight) - ? text - : ( - - {text} - - ); + return !chunk.highlight ? ( + text + ) : ( + onPressHighlighted(text) + : undefined + } + > + {text} + + ); })} ); diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..91a40be --- /dev/null +++ b/package-lock.json @@ -0,0 +1,231 @@ +{ + "name": "react-native-highlight-words", + "version": "2.0.1", + "lockfileVersion": 2, + "requires": true, + "packages": { + "": { + "name": "react-native-highlight-words", + "version": "2.0.1", + "license": "MIT", + "dependencies": { + "deprecated-react-native-prop-types": "^2.3.0", + "highlight-words-core": "^1.2.2", + "prop-types": "^15.8.1" + }, + "devDependencies": { + "@types/react": "^18.0.21", + "@types/react-native": "^0.70.6" + }, + "peerDependencies": { + "react": "^18.0.0" + } + }, + "node_modules/@react-native/normalize-color": { + "version": "2.0.0", + "license": "MIT" + }, + "node_modules/@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "node_modules/@types/react": { + "version": "18.0.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", + "integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==", + "dev": true, + "dependencies": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "node_modules/@types/react-native": { + "version": "0.70.6", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.6.tgz", + "integrity": "sha512-ynQ2jj0km9d7dbnyKqVdQ6Nti7VQ8SLTA/KKkkS5+FnvGyvij2AOo1/xnkBR/jnSNXuzrvGVzw2n0VWfppmfKw==", + "dev": true, + "dependencies": { + "@types/react": "*" + } + }, + "node_modules/@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, + "node_modules/csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "dev": true + }, + "node_modules/deprecated-react-native-prop-types": { + "version": "2.3.0", + "license": "MIT", + "dependencies": { + "@react-native/normalize-color": "*", + "invariant": "*", + "prop-types": "*" + } + }, + "node_modules/highlight-words-core": { + "version": "1.2.2", + "license": "MIT" + }, + "node_modules/invariant": { + "version": "2.2.4", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "license": "MIT" + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "license": "MIT", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/prop-types": { + "version": "15.8.1", + "license": "MIT", + "dependencies": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "node_modules/react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "dependencies": { + "loose-envify": "^1.1.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/react-is": { + "version": "16.13.1", + "license": "MIT" + } + }, + "dependencies": { + "@react-native/normalize-color": { + "version": "2.0.0" + }, + "@types/prop-types": { + "version": "15.7.5", + "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz", + "integrity": "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==", + "dev": true + }, + "@types/react": { + "version": "18.0.21", + "resolved": "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz", + "integrity": "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==", + "dev": true, + "requires": { + "@types/prop-types": "*", + "@types/scheduler": "*", + "csstype": "^3.0.2" + } + }, + "@types/react-native": { + "version": "0.70.6", + "resolved": "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.6.tgz", + "integrity": "sha512-ynQ2jj0km9d7dbnyKqVdQ6Nti7VQ8SLTA/KKkkS5+FnvGyvij2AOo1/xnkBR/jnSNXuzrvGVzw2n0VWfppmfKw==", + "dev": true, + "requires": { + "@types/react": "*" + } + }, + "@types/scheduler": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz", + "integrity": "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==", + "dev": true + }, + "csstype": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz", + "integrity": "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==", + "dev": true + }, + "deprecated-react-native-prop-types": { + "version": "2.3.0", + "requires": { + "@react-native/normalize-color": "*", + "invariant": "*", + "prop-types": "*" + } + }, + "highlight-words-core": { + "version": "1.2.2" + }, + "invariant": { + "version": "2.2.4", + "requires": { + "loose-envify": "^1.0.0" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + }, + "loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "requires": { + "js-tokens": "^3.0.0 || ^4.0.0" + } + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + }, + "prop-types": { + "version": "15.8.1", + "requires": { + "loose-envify": "^1.4.0", + "object-assign": "^4.1.1", + "react-is": "^16.13.1" + } + }, + "react": { + "version": "18.2.0", + "resolved": "https://registry.npmjs.org/react/-/react-18.2.0.tgz", + "integrity": "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==", + "peer": true, + "requires": { + "loose-envify": "^1.1.0" + } + }, + "react-is": { + "version": "16.13.1" + } + } +} diff --git a/package.json b/package.json index 8d99126..1f8b691 100644 --- a/package.json +++ b/package.json @@ -1,14 +1,16 @@ { - "name": "react-native-highlight-words", - "version": "1.0.1", + "name": "@javier.alejandro.castro/react-native-highlight-words", + "version": "2.0.1", + "private": false, "description": "A React Native port of react-highlight-words. This component is used to highlight words within a larger body of text.", "main": "index.js", + "types": "index.d.ts", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": { "type": "git", - "url": "https://github.com/clauderic/react-native-highlight-words.git" + "url": "https://github.com/jacargentina/react-native-highlight-words.git" }, "keywords": [ "react-native", @@ -24,17 +26,26 @@ "occurrences", "search" ], - "author": "Clauderic Demers", + "author": "Claudéric Demers", "license": "MIT", "bugs": { - "url": "https://github.com/clauderic/react-native-highlight-words/issues" + "url": "https://github.com/jacargentina/react-native-highlight-words/issues" }, - "homepage": "https://github.com/clauderic/react-native-highlight-words", + "contributors": [ + "Javier Castro ", + "Davidson Nascimento " + ], + "homepage": "https://github.com/jacargentina/react-native-highlight-words", "dependencies": { - "highlight-words-core": "^1.0.3", - "prop-types": "^15.5.7" + "deprecated-react-native-prop-types": "^2.3.0", + "highlight-words-core": "^1.2.2", + "prop-types": "^15.8.1" + }, + "devDependencies": { + "@types/react": "^18.0.21", + "@types/react-native": "^0.70.6" }, "peerDependencies": { - "react": "^15.5.0 || ^16" + "react": "^18.x" } } diff --git a/yarn.lock b/yarn.lock new file mode 100644 index 0000000..4c5b7db --- /dev/null +++ b/yarn.lock @@ -0,0 +1,83 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@react-native/normalize-color@*": + "version" "2.0.0" + +"@types/prop-types@*": + "integrity" "sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==" + "resolved" "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.5.tgz" + "version" "15.7.5" + +"@types/react-native@^0.70.6": + "integrity" "sha512-ynQ2jj0km9d7dbnyKqVdQ6Nti7VQ8SLTA/KKkkS5+FnvGyvij2AOo1/xnkBR/jnSNXuzrvGVzw2n0VWfppmfKw==" + "resolved" "https://registry.npmjs.org/@types/react-native/-/react-native-0.70.6.tgz" + "version" "0.70.6" + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@^18.0.21": + "integrity" "sha512-7QUCOxvFgnD5Jk8ZKlUAhVcRj7GuJRjnjjiY/IUBWKgOlnvDvTMLD4RTF7NPyVmbRhNrbomZiOepg7M/2Kj1mA==" + "resolved" "https://registry.npmjs.org/@types/react/-/react-18.0.21.tgz" + "version" "18.0.21" + dependencies: + "@types/prop-types" "*" + "@types/scheduler" "*" + "csstype" "^3.0.2" + +"@types/scheduler@*": + "integrity" "sha512-hppQEBDmlwhFAXKJX2KnWLYu5yMfi91yazPb2l+lbJiwW+wdo1gNeRA+3RgNSO39WYX2euey41KEwnqesU2Jew==" + "resolved" "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.2.tgz" + "version" "0.16.2" + +"csstype@^3.0.2": + "integrity" "sha512-DJR/VvkAvSZW9bTouZue2sSxDwdTN92uHjqeKVm+0dAqdfNykRzQ95tay8aXMBAAPpUiq4Qcug2L7neoRh2Egw==" + "resolved" "https://registry.npmjs.org/csstype/-/csstype-3.1.1.tgz" + "version" "3.1.1" + +"deprecated-react-native-prop-types@^2.3.0": + "version" "2.3.0" + dependencies: + "@react-native/normalize-color" "*" + "invariant" "*" + "prop-types" "*" + +"highlight-words-core@^1.2.2": + "version" "1.2.2" + +"invariant@*": + "version" "2.2.4" + dependencies: + "loose-envify" "^1.0.0" + +"js-tokens@^3.0.0 || ^4.0.0": + "resolved" "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz" + "version" "4.0.0" + +"loose-envify@^1.0.0", "loose-envify@^1.1.0", "loose-envify@^1.4.0": + "resolved" "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz" + "version" "1.4.0" + dependencies: + "js-tokens" "^3.0.0 || ^4.0.0" + +"object-assign@^4.1.1": + "resolved" "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz" + "version" "4.1.1" + +"prop-types@*", "prop-types@^15.8.1": + "version" "15.8.1" + dependencies: + "loose-envify" "^1.4.0" + "object-assign" "^4.1.1" + "react-is" "^16.13.1" + +"react-is@^16.13.1": + "version" "16.13.1" + +"react@^18.0.0": + "integrity" "sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==" + "resolved" "https://registry.npmjs.org/react/-/react-18.2.0.tgz" + "version" "18.2.0" + dependencies: + "loose-envify" "^1.1.0"