UNPKG

4.54 kBJavaScriptView Raw
1import _objectWithoutPropertiesLoose from "@babel/runtime/helpers/objectWithoutPropertiesLoose";
2import _extends from "@babel/runtime/helpers/extends";
3import invariant from 'invariant';
4import React, { cloneElement, useEffect, useRef } from 'react';
5import { useTypeaheadContext } from '../core/Context';
6import { isSelectable } from '../utils';
7import { RETURN, RIGHT, TAB } from '../constants';
8
9// IE doesn't seem to get the composite computed value (eg: 'padding',
10// 'borderStyle', etc.), so generate these from the individual values.
11function interpolateStyle(styles, attr, subattr) {
12 if (subattr === void 0) {
13 subattr = '';
14 }
15
16 // Title-case the sub-attribute.
17 if (subattr) {
18 /* eslint-disable-next-line no-param-reassign */
19 subattr = subattr.replace(subattr[0], subattr[0].toUpperCase());
20 }
21
22 return ['Top', 'Right', 'Bottom', 'Left'].map(function (dir) {
23 return styles[attr + dir + subattr];
24 }).join(' ');
25}
26
27function copyStyles(inputNode, hintNode) {
28 if (!inputNode || !hintNode) {
29 return;
30 }
31
32 var inputStyle = window.getComputedStyle(inputNode);
33 /* eslint-disable no-param-reassign */
34
35 hintNode.style.borderStyle = interpolateStyle(inputStyle, 'border', 'style');
36 hintNode.style.borderWidth = interpolateStyle(inputStyle, 'border', 'width');
37 hintNode.style.fontSize = inputStyle.fontSize;
38 hintNode.style.height = inputStyle.height;
39 hintNode.style.lineHeight = inputStyle.lineHeight;
40 hintNode.style.margin = interpolateStyle(inputStyle, 'margin');
41 hintNode.style.padding = interpolateStyle(inputStyle, 'padding');
42 /* eslint-enable no-param-reassign */
43}
44
45export function defaultShouldSelect(e, state) {
46 var shouldSelectHint = false;
47 var currentTarget = e.currentTarget,
48 keyCode = e.keyCode;
49
50 if (keyCode === RIGHT) {
51 // For selectable input types ("text", "search"), only select the hint if
52 // it's at the end of the input value. For non-selectable types ("email",
53 // "number"), always select the hint.
54 shouldSelectHint = isSelectable(currentTarget) ? currentTarget.selectionStart === currentTarget.value.length : true;
55 }
56
57 if (keyCode === TAB) {
58 // Prevent input from blurring on TAB.
59 e.preventDefault();
60 shouldSelectHint = true;
61 }
62
63 if (keyCode === RETURN) {
64 shouldSelectHint = !!state.selectHintOnEnter;
65 }
66
67 return typeof state.shouldSelect === 'function' ? state.shouldSelect(shouldSelectHint, e) : shouldSelectHint;
68}
69export var useHint = function useHint(_ref) {
70 var children = _ref.children,
71 shouldSelect = _ref.shouldSelect;
72 !(React.Children.count(children) === 1) ? process.env.NODE_ENV !== "production" ? invariant(false, '`useHint` expects one child.') : invariant(false) : void 0;
73
74 var _useTypeaheadContext = useTypeaheadContext(),
75 hintText = _useTypeaheadContext.hintText,
76 initialItem = _useTypeaheadContext.initialItem,
77 inputNode = _useTypeaheadContext.inputNode,
78 onAdd = _useTypeaheadContext.onAdd,
79 selectHintOnEnter = _useTypeaheadContext.selectHintOnEnter;
80
81 var hintRef = useRef(null);
82
83 var onKeyDown = function onKeyDown(e) {
84 if (hintText && initialItem && defaultShouldSelect(e, {
85 selectHintOnEnter: selectHintOnEnter,
86 shouldSelect: shouldSelect
87 })) {
88 onAdd(initialItem);
89 }
90
91 children.props.onKeyDown && children.props.onKeyDown(e);
92 };
93
94 useEffect(function () {
95 copyStyles(inputNode, hintRef.current);
96 });
97 return {
98 child: /*#__PURE__*/cloneElement(children, _extends({}, children.props, {
99 onKeyDown: onKeyDown
100 })),
101 hintRef: hintRef,
102 hintText: hintText
103 };
104};
105
106var Hint = function Hint(_ref2) {
107 var className = _ref2.className,
108 props = _objectWithoutPropertiesLoose(_ref2, ["className"]);
109
110 var _useHint = useHint(props),
111 child = _useHint.child,
112 hintRef = _useHint.hintRef,
113 hintText = _useHint.hintText;
114
115 return /*#__PURE__*/React.createElement("div", {
116 className: className,
117 style: {
118 display: 'flex',
119 flex: 1,
120 height: '100%',
121 position: 'relative'
122 }
123 }, child, /*#__PURE__*/React.createElement("input", {
124 "aria-hidden": true,
125 className: "rbt-input-hint",
126 ref: hintRef,
127 readOnly: true,
128 style: {
129 backgroundColor: 'transparent',
130 borderColor: 'transparent',
131 boxShadow: 'none',
132 color: 'rgba(0, 0, 0, 0.35)',
133 left: 0,
134 pointerEvents: 'none',
135 position: 'absolute',
136 top: 0,
137 width: '100%'
138 },
139 tabIndex: -1,
140 value: hintText
141 }));
142};
143
144export default Hint;
\No newline at end of file