Socket
Socket
Sign inDemoInstall

react-autocomplete-hint

Package Overview
Dependencies
3
Maintainers
1
Versions
9
Alerts
File Explorer

Advanced tools

Install Socket

Detect and block malicious and high-risk dependencies

Install

Comparing version 1.0.1 to 1.1.0

4

dist/src/index.d.ts

@@ -1,6 +0,8 @@

import React from 'react';
import React, { ReactElement } from 'react';
export interface IHintProps {
options: Array<string>;
disableHint?: boolean;
children: ReactElement;
allowTabFill?: boolean;
}
export declare const Hint: React.FC<IHintProps>;

@@ -37,7 +37,11 @@ "use strict";

exports.Hint = function (props) {
var options = props.options, child = props.children, disableHint = props.disableHint;
var child = react_1.default.Children.only(props.children);
var options = props.options, disableHint = props.disableHint, allowTabFill = props.allowTabFill;
var childProps = child.props;
var mainInputRef = react_1.useRef(null);
var hintWrapperRef = react_1.useRef(null);
var hintRef = react_1.useRef(null);
var _a = react_1.useState(''), hint = _a[0], setHint = _a[1];
var _a = react_1.useState(''), text = _a[0], setText = _a[1];
var _b = react_1.useState(''), hint = _b[0], setHint = _b[1];
var _c = react_1.useState(), changeEvent = _c[0], setChangeEvent = _c[1];
react_1.useEffect(function () {

@@ -48,3 +52,3 @@ if (disableHint) {

var inputStyle = mainInputRef.current && window.getComputedStyle(mainInputRef.current);
inputStyle && styleHint(hintRef, inputStyle);
inputStyle && styleHint(hintWrapperRef, hintRef, inputStyle);
});

@@ -58,34 +62,57 @@ var getHint = function (text) {

.sort()[0];
// While Text matching is case-insensitive, the casing entered by the user so far should be
// preserved in the hint for UX benefits and also without the preservation, the hint won't
// overlap well if user types a different case from the selected option.
return match
? text + match.slice(text.length)
? match.slice(text.length)
: '';
};
var styleHint = function (hintRef, inputStyle) {
var _a;
if ((_a = hintRef === null || hintRef === void 0 ? void 0 : hintRef.current) === null || _a === void 0 ? void 0 : _a.style) {
var setAvailableHint = function () {
if (hint !== '') {
if (changeEvent) {
changeEvent.target.value = text + hint;
childProps.onChange && childProps.onChange(changeEvent);
setHint('');
}
}
};
var styleHint = function (hintWrapperRef, hintRef, inputStyle) {
var _a, _b;
if ((_a = hintWrapperRef === null || hintWrapperRef === void 0 ? void 0 : hintWrapperRef.current) === null || _a === void 0 ? void 0 : _a.style) {
hintWrapperRef.current.style.fontFamily = inputStyle.fontFamily;
hintWrapperRef.current.style.fontSize = inputStyle.fontSize;
hintWrapperRef.current.style.width = inputStyle.width;
hintWrapperRef.current.style.height = inputStyle.height;
hintWrapperRef.current.style.lineHeight = inputStyle.lineHeight;
hintWrapperRef.current.style.boxSizing = inputStyle.boxSizing;
hintWrapperRef.current.style.margin = utils_1.interpolateStyle(inputStyle, 'margin');
hintWrapperRef.current.style.padding = utils_1.interpolateStyle(inputStyle, 'padding');
hintWrapperRef.current.style.borderStyle = utils_1.interpolateStyle(inputStyle, 'border', 'style');
hintWrapperRef.current.style.borderWidth = utils_1.interpolateStyle(inputStyle, 'border', 'width');
}
if ((_b = hintRef === null || hintRef === void 0 ? void 0 : hintRef.current) === null || _b === void 0 ? void 0 : _b.style) {
hintRef.current.style.fontFamily = inputStyle.fontFamily;
hintRef.current.style.fontSize = inputStyle.fontSize;
hintRef.current.style.width = inputStyle.width;
hintRef.current.style.height = inputStyle.height;
hintRef.current.style.lineHeight = inputStyle.lineHeight;
hintRef.current.style.boxSizing = inputStyle.boxSizing;
hintRef.current.style.margin = utils_1.interpolateStyle(inputStyle, 'margin');
hintRef.current.style.padding = utils_1.interpolateStyle(inputStyle, 'padding');
hintRef.current.style.borderStyle = utils_1.interpolateStyle(inputStyle, 'border', 'style');
hintRef.current.style.borderWidth = utils_1.interpolateStyle(inputStyle, 'border', 'width');
}
};
var onChange = function (e) {
setChangeEvent(e);
e.persist();
setText(e.target.value);
setHint(getHint(e.target.value));
childProps.onChange && childProps.onChange(e);
};
var onFocus = function (e) {
setHint(getHint(e.target.value));
childProps.onFocus && childProps.onFocus(e);
};
var onBlur = function (e) {
setHint('');
childProps.onBlur && childProps.onBlur(e);
//Only blur it if the new focus isn't the the hint input
if ((hintRef === null || hintRef === void 0 ? void 0 : hintRef.current) !== e.relatedTarget) {
setHint('');
childProps.onBlur && childProps.onBlur(e);
}
};
var RIGHT = 39;
var ARROWRIGHT = 'ArrowRight';
var TAB = 'Tab';
var onKeyDown = function (e) {
if (e.keyCode === RIGHT) {
var caretIsAtTextEnd = (function () {
// For selectable input types ("text", "search"), only select the hint if

@@ -95,16 +122,43 @@ // it's at the end of the input value. For non-selectable types ("email",

var isNonSelectableType = e.currentTarget.selectionEnd == null;
var cursorIsAtTextEnd = isNonSelectableType
var caretIsAtTextEnd = isNonSelectableType
? true
: e.currentTarget.selectionEnd === e.currentTarget.value.length;
if (cursorIsAtTextEnd && hint !== '' && e.currentTarget.value !== hint) {
e.currentTarget.value = hint;
childProps.onChange(e);
setHint('');
}
return caretIsAtTextEnd;
})();
if (caretIsAtTextEnd && e.key === ARROWRIGHT) {
setAvailableHint();
}
else if (caretIsAtTextEnd && allowTabFill && e.key === TAB && hint !== '') {
e.preventDefault();
setAvailableHint();
}
childProps.onKeyDown && childProps.onKeyDown(e);
};
var mainInput = react_1.cloneElement(child, __assign(__assign({}, childProps), { onChange: onChange,
var onHintClick = function (e) {
var _a;
var hintCaretPosition = e.currentTarget.selectionEnd || 0;
// If user clicks the position before the first character of the hint,
// move focus to the end of the mainInput text
if (hintCaretPosition === 0) {
(_a = mainInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
return;
}
if (!!hint && hint !== '') {
setAvailableHint();
setTimeout(function () {
var _a, _b;
(_a = mainInputRef.current) === null || _a === void 0 ? void 0 : _a.focus();
var caretPosition = text.length + hintCaretPosition;
(_b = mainInputRef.current) === null || _b === void 0 ? void 0 : _b.setSelectionRange(caretPosition, caretPosition);
}, 0);
}
};
var mainInput = react_1.cloneElement(child, __assign(__assign({}, childProps), { style: {
boxSizing: 'border-box'
}, onChange: onChange,
onBlur: onBlur,
onKeyDown: onKeyDown, ref: utils_1.mergeRefs(childProps.ref, mainInputRef) }));
onFocus: onFocus,
onKeyDown: onKeyDown, ref: childProps.ref && typeof childProps.ref !== 'string'
? utils_1.mergeRefs(childProps.ref, mainInputRef)
: mainInputRef }));
return (react_1.default.createElement("div", { className: "rah-input-wrapper", style: {

@@ -117,12 +171,30 @@ position: 'relative',

mainInput,
react_1.default.createElement("input", { className: "rah-input-hint", defaultValue: hint, ref: hintRef, style: {
react_1.default.createElement("span", { className: "rah-hint-wrapper", ref: hintWrapperRef, style: {
display: 'flex',
pointerEvents: 'none',
backgroundColor: 'transparent',
borderColor: 'transparent',
boxSizing: 'border-box',
boxShadow: 'none',
color: 'rgba(0, 0, 0, 0.35)',
pointerEvents: 'none',
position: 'absolute',
top: 0,
left: 0
}, tabIndex: -1 })))));
left: 0,
} },
react_1.default.createElement("span", { style: {
visibility: 'hidden',
pointerEvents: 'none'
} }, text),
react_1.default.createElement("input", { className: "rah-hint", ref: hintRef, onClick: onHintClick, style: {
pointerEvents: !hint || hint === '' ? 'none' : 'visible',
background: 'transparent',
width: '100%',
outline: 'none',
border: 'none',
boxShadow: 'none',
padding: 0,
margin: 0,
color: 'rgba(0, 0, 0, 0.35)',
caretColor: 'transparent'
}, value: hint, onChange: function () { return null; }, tabIndex: -1 }))))));
};
{
"name": "react-autocomplete-hint",
"version": "1.0.1",
"version": "1.1.0",
"description": "A React component for Autocomplete hint",

@@ -16,3 +16,4 @@ "main": "dist/src/index.js",

"start": "npm run build && npm run start:dev",
"test": "echo \"Error: no test specified\" && exit 1",
"jest": "./node_modules/jest/bin/jest.js",
"test": "jest --watch",
"prepublishOnly": "tsc"

@@ -31,13 +32,20 @@ },

"devDependencies": {
"@types/react": "^16.9.43",
"@testing-library/dom": "^7.26.3",
"@testing-library/jest-dom": "^5.11.4",
"@testing-library/react": "^11.0.4",
"@testing-library/user-event": "^12.1.10",
"@types/jest": "^26.0.14",
"@types/react": "^16.9.51",
"@types/react-dom": "^16.9.8",
"css-loader": "^3.6.0",
"jest": "^26.5.2",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"sass": "^1.26.10",
"sass-loader": "^9.0.2",
"style-loader": "^1.2.1",
"ts-loader": "^8.0.1",
"sass": "^1.27.0",
"sass-loader": "^9.0.3",
"style-loader": "^1.3.0",
"ts-jest": "^26.4.1",
"ts-loader": "^8.0.4",
"typescript": "^3.9.7",
"webpack": "^4.44.0",
"webpack": "^4.44.2",
"webpack-cli": "^3.3.12",

@@ -44,0 +52,0 @@ "webpack-dev-server": "^3.11.0"

@@ -31,5 +31,6 @@ # react-autocomplete-hint

</Hint>
```
Use your keyboard **Right key** to fill your input with the suggested hint.
Click on the hint or use your keyboard **Right** key or **Tab** key(if `allowTabFill` is set to true) to fill your input with the suggested hint.

@@ -41,8 +42,10 @@

List of options for autocomplete.
#### disableHint (optional): `Boolean`
#### allowTabFill (optional):`Boolean`
## License
[MIT](LICENSE)
[MIT](LICENSE)
Inspired by [React Bootstrap Typeahead](https://github.com/ericgio/react-bootstrap-typeahead).
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc