Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor TextWidget #6020

Merged
merged 10 commits into from
May 29, 2024
1 change: 1 addition & 0 deletions packages/volto/news/6020.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Refactor TextWidget. @Tishasoumya-02
216 changes: 92 additions & 124 deletions packages/volto/src/components/manage/Widgets/TextWidget.jsx
Original file line number Diff line number Diff line change
@@ -1,136 +1,104 @@
/**
* TextWidget component.
* @module components/manage/Widgets/TextWidget
*/

import React, { Component } from 'react';
import { useEffect, useRef } from 'react';
import PropTypes from 'prop-types';
import { Input } from 'semantic-ui-react';

import { injectIntl } from 'react-intl';
import { Icon } from '@plone/volto/components';
import FormFieldWrapper from '@plone/volto/components/manage/Widgets/FormFieldWrapper';

/**
* The simple text widget.
*
* It is the default fallback widget, so if no other widget is found based on
* passed field properties, it will be used.
*/
class TextWidget extends Component {
/**
* Property types.
* @property {Object} propTypes Property types.
* @static
*/
static propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onBlur: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
icon: PropTypes.shape({
xmlns: PropTypes.string,
viewBox: PropTypes.string,
content: PropTypes.string,
}),
iconAction: PropTypes.func,
minLength: PropTypes.number,
maxLength: PropTypes.number,
wrapped: PropTypes.bool,
placeholder: PropTypes.string,
};
const TextWidget = (props) => {
const {
id,
value,
onChange,
onBlur,
onClick,
icon,
iconAction,
minLength,
maxLength,
placeholder,
isDisabled,
focus,
} = props;

/**
* Default properties.
* @property {Object} defaultProps Default properties.
* @static
*/
static defaultProps = {
description: null,
required: false,
error: [],
value: null,
onChange: () => {},
onBlur: () => {},
onClick: () => {},
onEdit: null,
onDelete: null,
focus: false,
icon: null,
iconAction: null,
minLength: null,
maxLength: null,
};
const ref = useRef();

/**
* Component did mount lifecycle method
* @method componentDidMount
* @returns {undefined}
*/
componentDidMount() {
if (this.props.focus) {
this.node.focus();
useEffect(() => {
if (focus) {
ref.current.focus();
}
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);

return (
<FormFieldWrapper {...props} className="text">
<Input
id={`field-${id}`}
name={id}
value={value || ''}
disabled={isDisabled}
icon={icon || null}
placeholder={placeholder}
onChange={({ target }) =>
onChange(id, target.value === '' ? undefined : target.value)
}
ref={ref}
onBlur={({ target }) =>
onBlur(id, target.value === '' ? undefined : target.value)
}
onClick={() => onClick()}
minLength={minLength || null}
maxLength={maxLength || null}
/>
{icon && iconAction && (
<button className={`field-${id}-action-button`} onClick={iconAction}>
<Icon name={icon} size="18px" />
</button>
)}
</FormFieldWrapper>
);
};

/**
* Render method.
* @method render
* @returns {string} Markup for the component.
*/
render() {
const {
id,
value,
onChange,
onBlur,
onClick,
icon,
iconAction,
minLength,
maxLength,
placeholder,
isDisabled,
} = this.props;
export default TextWidget;

return (
<FormFieldWrapper {...this.props} className="text">
<Input
id={`field-${id}`}
name={id}
value={value || ''}
disabled={isDisabled}
icon={icon || null}
placeholder={placeholder}
onChange={({ target }) =>
onChange(id, target.value === '' ? undefined : target.value)
}
ref={(node) => {
this.node = node;
}}
onBlur={({ target }) =>
onBlur(id, target.value === '' ? undefined : target.value)
}
onClick={() => onClick()}
minLength={minLength || null}
maxLength={maxLength || null}
/>
{icon && iconAction && (
<button className={`field-${id}-action-button`} onClick={iconAction}>
<Icon name={icon} size="18px" />
</button>
)}
</FormFieldWrapper>
);
}
}
TextWidget.propTypes = {
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
description: PropTypes.string,
required: PropTypes.bool,
error: PropTypes.arrayOf(PropTypes.string),
value: PropTypes.string,
focus: PropTypes.bool,
onChange: PropTypes.func,
onBlur: PropTypes.func,
onClick: PropTypes.func,
onEdit: PropTypes.func,
onDelete: PropTypes.func,
icon: PropTypes.shape({
xmlns: PropTypes.string,
viewBox: PropTypes.string,
content: PropTypes.string,
}),
iconAction: PropTypes.func,
minLength: PropTypes.number,
maxLength: PropTypes.number,
wrapped: PropTypes.bool,
placeholder: PropTypes.string,
};

export default injectIntl(TextWidget);
TextWidget.defaultProps = {
description: null,
required: false,
error: [],
value: null,
onChange: () => {},
onBlur: () => {},
onClick: () => {},
onEdit: null,
onDelete: null,
focus: false,
icon: null,
iconAction: null,
minLength: null,
maxLength: null,
};
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import React from 'react';
import TextWidget from './TextWidget';
import WidgetStory from './story';

export const Text = WidgetStory.bind({
props: { id: 'text', title: 'Text' },
widget: TextWidget,
});

Text.args = {
description: 'description',
placeholder: 'placeholder',
};
export default {
title: 'Edit Widgets/Text',
component: TextWidget,
Expand All @@ -17,5 +19,14 @@ export default {
</div>
),
],
argTypes: {},
argTypes: {
description: {
control: 'text',
description: 'description',
},
placeholder: {
control: 'text',
description: 'placeholder',
},
},
};
Loading