Skip to content

Commit e6e165b

Browse files
committed
feat(@clayui/form): LPD-53483 Add ClayInput.InlineText
1 parent ddb077c commit e6e165b

File tree

1 file changed

+94
-0
lines changed

1 file changed

+94
-0
lines changed

packages/clay-form/src/Input.tsx

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
* SPDX-License-Identifier: BSD-3-Clause
44
*/
55

6+
import ClayIcon from '@clayui/icon';
67
import classNames from 'classnames';
78
import React from 'react';
89

@@ -155,6 +156,97 @@ const GroupInsetItem = React.forwardRef<
155156

156157
GroupInsetItem.displayName = 'ClayInputGroupInsetItem';
157158

159+
interface IInlineTextProps
160+
extends React.HTMLAttributes<
161+
HTMLDivElement | HTMLSpanElement | HTMLLabelElement
162+
> {
163+
/**
164+
* The id of the component
165+
*/
166+
id?: string;
167+
168+
/**
169+
* Text that hints at the expected data type to be entered.
170+
*/
171+
placeholder?: string;
172+
173+
/**
174+
* A flag that sets the component as noneditable.
175+
*/
176+
readOnly?: boolean;
177+
178+
/**
179+
* Path to the spritemap that Icon should use when referencing symbols.
180+
*/
181+
spritemap?: string;
182+
}
183+
184+
const InlineText = React.forwardRef<
185+
HTMLDivElement | HTMLSpanElement | HTMLLabelElement,
186+
IInlineTextProps
187+
>(
188+
({
189+
children,
190+
className,
191+
id,
192+
placeholder,
193+
readOnly,
194+
spritemap,
195+
...otherProps
196+
}: IInlineTextProps) => {
197+
const inputRef = React.useRef<HTMLDivElement>(null);
198+
199+
const [inputValue, setInputValue] = React.useState('');
200+
201+
return (
202+
<div className="form-control-fit-content inline-text-input">
203+
<div className={classNames('form-control', className)}>
204+
<Input
205+
aria-hidden
206+
className="form-control-hidden"
207+
id={id}
208+
onFocus={() => {
209+
inputRef.current?.focus();
210+
}}
211+
readOnly
212+
tabIndex={-1}
213+
type="text"
214+
value={inputValue}
215+
/>
216+
<span
217+
className="form-control-inset"
218+
// @ts-ignore
219+
contentEditable={readOnly ? false : 'plaintext-only'}
220+
onBlur={(event) => {
221+
if (inputValue.trim() === '') {
222+
const input = event.target as HTMLElement;
223+
224+
input.innerHTML = '';
225+
}
226+
}}
227+
onInput={(event) => {
228+
const input = event.target as HTMLElement;
229+
230+
setInputValue(input.innerText);
231+
}}
232+
placeholder={placeholder}
233+
ref={inputRef}
234+
role="textbox"
235+
tabIndex={0}
236+
{...otherProps}
237+
/>
238+
<span className="form-control-indicator form-control-item">
239+
<ClayIcon spritemap={spritemap} symbol="pencil" />
240+
</span>
241+
{children}
242+
</div>
243+
</div>
244+
);
245+
}
246+
);
247+
248+
InlineText.displayName = 'ClayInlineText';
249+
158250
interface IProps extends React.InputHTMLAttributes<HTMLInputElement> {
159251
/**
160252
* Input component to render. Can either be a string like 'input' or 'textarea' or a component.
@@ -183,6 +275,7 @@ interface IForwardRef<T, P = {}>
183275
GroupInsetItem: typeof GroupInsetItem;
184276
GroupItem: typeof GroupItem;
185277
GroupText: typeof GroupText;
278+
InlineText: typeof InlineText;
186279
}
187280

188281
function forwardRef<T, P = {}>(component: React.RefForwardingComponent<T, P>) {
@@ -221,5 +314,6 @@ Input.Group = Group;
221314
Input.GroupInsetItem = GroupInsetItem;
222315
Input.GroupItem = GroupItem;
223316
Input.GroupText = GroupText;
317+
Input.InlineText = InlineText;
224318

225319
export default Input;

0 commit comments

Comments
 (0)