Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | 58x 58x 58x 58x 10x 10x 58x 16x 16x 58x 5x 5x 5x 58x 1x 1x 58x 58x 1x 58x | import React, { useEffect, useRef, useState } from 'react';
import globals from './lib/globals';
import { InlineEditDisplay } from './lib/InlineEditDisplay/InlineEditDisplay';
import { InlineEditInputFactory } from './lib/InlineEditInputFactory/InlineEditInputFactory';
import { StyleWrapper } from './StyleWrapper';
// InlineEdit is a component that allows you to edit a value in place
// It consists of 2 sub-components: InlineEditDisplay and InlineEditInput
// inspired by Atlassian Inline Edit component
// https://atlassian.design/components/inline-edit/examples#default
// Also inspired by react-easy-edit
// https://github.com/giorgosart/react-easy-edit
// Tutorial for packages from:
// https://www.youtube.com/watch?v=hf6Z8OZanec
/**
*
* @callback onSave - callback function after onBlur or Enter
* @callback displayRenderer - custom display render props
* @param {String} initialValue - initial value to display / edit
* @param {String} defaultValue - default value (will be used if user clicks Undo)
* @param {Number} maxLength - max length of input
* @param {String} inputComponent - 'input' or 'textarea'
* @param {Boolean} startWithEditViewOpen - whether to start with edit view open (default: false)
* @param {String} displayPlaceholder - placeholder for display view when value is empty
* @param {Object} textAreaProps - props to override antd's Input.TextArea
* @returns {ReactDOM}
*/
function InlineEdit({
onSave = () => {},
displayRenderer = () => {},
initialValue = null,
defaultValue = null,
maxLength = globals.DEFAULT_INPUT_MAX_LENGTH,
inputComponent = 'input', // 'input' | 'textarea'
startWithEditViewOpen = false,
displayPlaceholder = globals.DEFAULT_PLACEHOLDER,
textAreaProps = {},
}) {
const [isEditing, setIsEditing] = useState(startWithEditViewOpen);
const [label, setLabel] = useState(initialValue);
const inputRef = useRef();
// const [form] = useForm();
// to deal with i18n related changes in initialValue
useEffect(() => {
setLabel(initialValue);
return () => {};
}, [initialValue]);
// to autofocus on input when first click
useEffect(() => {
if (isEditing && inputRef.current) { inputRef.current.focus({ cursor: 'all' }); }
return () => {};
}, [isEditing, inputRef]);
const onSaveValue = (value) => {
onSave(value);
setLabel(value);
setIsEditing(false);
};
const onUndoClick = (e) => {
e.preventDefault();
onSaveValue(defaultValue);
};
// INPUT: to save on enter / blur
// Factory to create different input types (input / textarea)
const editDOM = (
<div className="inline-edit__input-wrapper">
<InlineEditInputFactory
label={label}
initialLabel={initialValue}
defaultLabel={defaultValue}
onSave={onSaveValue}
setLabel={setLabel}
inputRef={inputRef}
onUndoClick={onUndoClick}
maxLength={maxLength}
component={inputComponent}
textAreaProps={textAreaProps}
/>
</div>
);
const displayDOM = (
<InlineEditDisplay
onClick={() => {
setIsEditing(true);
}}
label={label}
placeholder={displayPlaceholder}
displayRenderer={displayRenderer}
/>
);
// DISPLAY: to display the value
return (
<StyleWrapper>
{isEditing ? editDOM : displayDOM}
</StyleWrapper>
);
}
export default InlineEdit;
|