From 7265cb41da4a6ccfae586538f3803b937ae0b016 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonatan=20Garci=CC=81a=20Clavo?= Date: Thu, 7 Apr 2016 10:26:54 +0200 Subject: [PATCH] New feature, new props added to override styles, change all css styles to inline styles, create new file with TagComponent, modify config and builds to support new TagComponent file. Bug fix, added missing this.refs.input.focus() on _handleClickOnWrapper, added tags as second param on every onRemoveTag. --- README.md | 27 ++++++++++++++- css/react-tagged-input.css | 42 ------------------------ dist/TagComponent.js | 67 ++++++++++++++++++++++++++++++++++++++ dist/TaggedInput.js | 53 +++++++++++++++++------------- examples/index.css | 42 ------------------------ grunt/react.js | 3 +- src/TagComponent.jsx | 67 ++++++++++++++++++++++++++++++++++++++ src/TaggedInput.jsx | 51 ++++++++++++++++------------- 8 files changed, 221 insertions(+), 131 deletions(-) create mode 100644 dist/TagComponent.js create mode 100644 src/TagComponent.jsx diff --git a/README.md b/README.md index 4deb65c..fccbfa5 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ npm run dev ### Contributing -If you intend to contribute, make your changes, then do +If you intend to contribute, make your changes, then do ```sh npm run build @@ -64,6 +64,11 @@ ReactDOM.render( removeTagLabel={"\u274C"} // Unicode of a symbol or an Object click to delete tags. Defaults to 'x', onBeforeAddTag={function (tagText) {return true;}} // Returning true from this function causes the tag to itself handle adding tags. Return false if you want a parent to pass in updated tags in props. onBeforeRemoveTag={function (tagText) {return true;}} // Returning true causes the tag to itself handle removing tags. Return false if you want a parent to pass in updated tags in props. + tagRootContainerStyle={/*object*/} // Object with root container styles + tagContainerStyle={/*object*/} // Object with tag container styles + tagTextStyle={/*object*/} // Object with tag text styles + tagRemoveStyle={/*object*/} // Object with tag remove styles + inputStyle={/*object*/} // Object with tag input styles />, mountPoint ); ``` @@ -140,6 +145,26 @@ Type: function function (tagText) {return true;}} Returning true causes the Component to continue handle removing tags. Return false if you want a parent to pass down updated tags in the props. +#### tagRootContainerStyle +Type: object +Override the inline-styles of the tag root container element. + +#### tagContainerStyle +Type: object +Override the inline-styles of the tag container element. + +#### tagTextStyle +Type: object +Override the inline-styles of the tag text element. + +#### tagRemoveStyle +Type: object +Override the inline-styles of the tag remove element. + +#### inputStyle +Type: object +Override the inline-styles of the tag input element. + --- ## License diff --git a/css/react-tagged-input.css b/css/react-tagged-input.css index 8bc4b6a..5c47cc7 100644 --- a/css/react-tagged-input.css +++ b/css/react-tagged-input.css @@ -1,45 +1,3 @@ -.tagged-input-wrapper { - border-width: 1px; - border-style: solid; - border-color: #dadada; - padding: 2px; -} - -.tagged-input-wrapper .tagged-input { - border: none; - outline: none; -} - -.tagged-input-wrapper .tag .tag-text { - padding-left: 5px; -} - -.tagged-input-wrapper .tag { - display: inline-block; - background-color: #E9E9E9; - padding: 2px 0px 2px 2px; - border-radius: 2px; - margin-left: 2px; - margin-right: 2px; -} - -.tagged-input-wrapper .tag.duplicate { - background: #FFDB7B; -} - -.tagged-input-wrapper .tag .remove { - color: #a0a0a0; - padding: 0px 4px; - font-size: 75%; - line-height: 100%; - cursor: pointer; -} - .tagged-input-wrapper .tag .remove:hover { color: red; } - -.tagged-input-wrapper .tag .remove, -.tagged-input-wrapper .tag .tag-text { - display: inline-block; -} diff --git a/dist/TagComponent.js b/dist/TagComponent.js new file mode 100644 index 0000000..ead29ef --- /dev/null +++ b/dist/TagComponent.js @@ -0,0 +1,67 @@ +'use-strict'; +var React = require('react'); + +var styles = { + tagContainerStyle: { + display: 'inline-block', + backgroundColor: '#E9E9E9', + padding: '2px 0px 2px 2px', + borderRadius: '2px', + marginLeft: '2px', + marginRight: '2px' + }, + duplicatedColor: { + backgroundColor: '#FFDB7B' + }, + tagTextStyle: { + paddingLeft: '5px', + display: 'inline-block' + }, + tagRemoveStyle: { + color: '#a0a0a0', + padding: '0px 4px', + fontSize: '75%', + lineHeight: '100%', + cursor: 'pointer', + display: 'inline-block' + } +}; + +module.exports = React.createClass({ + displayName: 'TagComponent', + + propTypes: { + classes: React.PropTypes.string, + onEdit: React.PropTypes.func, + item: React.PropTypes.string, + onRemove: React.PropTypes.func, + removeTagLabel: React.PropTypes.string, + duplicated: React.PropTypes.bool, + tagContainerStyle: React.PropTypes.object, + tagTextStyle: React.PropTypes.object, + tagRemoveStyle: React.PropTypes.object + }, + + _getTagContainerStyle: function () { + var p = this.props; + var duplicatedBacgroundColor = p.duplicated ? {backgroundColor: p.duplicatedColor || styles.duplicatedColor.backgroundColor} : {}; + return Object.assign({}, styles.tagContainerStyle, p.tagContainerStyle || {}, duplicatedBacgroundColor); + }, + + render: function () { + var p = this.props; + var className = 'tag' + (p.classes ? (' ' + p.classes) : ''); + var tagTextStyle = Object.assign({}, styles.tagTextStyle, p.tagTextStyle || {}); + var tagRemoveStyle = Object.assign({}, styles.tagRemoveStyle, p.tagRemoveStyle || {}); + + return ( + React.createElement("div", {className: className, style: this._getTagContainerStyle()}, + React.createElement("div", {className: "tag-text", style: tagTextStyle, onClick: p.onEdit}, p.item), + React.createElement("div", {className: "remove", style: tagRemoveStyle, onClick: p.onRemove}, + p.removeTagLabel + ) + ) + ); + } +}); + diff --git a/dist/TaggedInput.js b/dist/TaggedInput.js index 7001e7d..e2b4ad3 100644 --- a/dist/TaggedInput.js +++ b/dist/TaggedInput.js @@ -1,27 +1,24 @@ 'use-strict'; var React = require('react'); +var TagComponent = require('./TagComponent'); var KEY_CODES = { ENTER: 13, BACKSPACE: 8 }; -var DefaultTagComponent = React.createClass({displayName: "DefaultTagComponent", - render: function () { - var self = this, p = self.props; - var className = 'tag' + (p.classes ? (' ' + p.classes) : ''); - - return ( - React.createElement("div", {className: className}, - React.createElement("div", {className: "tag-text", onClick: p.onEdit}, p.item), - React.createElement("div", {className: "remove", onClick: p.onRemove}, - p.removeTagLabel - ) - ) - ); +var styles = { + tagRootContainerStyle: { + borderWidth: '1px', + borderStyle: 'solid', + borderColor: '#dadada', + padding: '2px', + }, + inputStyle: { + border: 'none', + outline: 'none' } - -}); +} module.exports = React.createClass({ displayName: 'TaggedInput', @@ -45,7 +42,12 @@ module.exports = React.createClass({ }), tagOnBlur: React.PropTypes.bool, tabIndex: React.PropTypes.number, - clickTagToEdit: React.PropTypes.bool + clickTagToEdit: React.PropTypes.bool, + tagRootContainerStyle: React.PropTypes.object, + tagContainerStyle: React.PropTypes.object, + tagTextStyle: React.PropTypes.object, + tagRemoveStyle: React.PropTypes.object, + inputStyle: React.PropTypes.object }, getDefaultProps: function () { @@ -88,8 +90,6 @@ module.exports = React.createClass({ placeholder = p.placeholder; } - var TagComponent = DefaultTagComponent; - for (i = 0; i < s.tags.length; i++) { tagComponents.push( React.createElement(TagComponent, { @@ -98,8 +98,12 @@ module.exports = React.createClass({ itemIndex: i, onRemove: self._handleRemoveTag.bind(this, i), onEdit: p.clickTagToEdit ? self._handleEditTag.bind(this, i) : null, - classes: p.unique && (i === s.duplicateIndex) ? 'duplicate' : '', - removeTagLabel: p.removeTagLabel || "\u274C"} + duplicated: p.unique && (i === s.duplicateIndex), + removeTagLabel: p.removeTagLabel || "\u274C", + tagContainerStyle: p.tagContainerStyle, + tagTextStyle: p.tagTextStyle, + tagRemoveStyle: p.tagRemoveStyle, + duplicatedColor: p.duplicatedColor} ) ); } @@ -107,6 +111,7 @@ module.exports = React.createClass({ var input = ( React.createElement("input", {type: "text", className: "tagged-input", + style: Object.assign({}, styles.inputStyle, p.inputStyle || {}), ref: "input", onKeyUp: this._handleKeyUp, onKeyDown: this._handleKeyDown, @@ -118,8 +123,10 @@ module.exports = React.createClass({ ) ); + var tagRootContainerStyle = Object.assign({}, styles.tagRootContainerStyle , p.tagRootContainerStyle || {}); + return ( - React.createElement("div", {className: classes, onClick: self._handleClickOnWrapper}, + React.createElement("div", {className: classes, style: tagRootContainerStyle, onClick: self._handleClickOnWrapper}, tagComponents, input ) @@ -215,7 +222,7 @@ module.exports = React.createClass({ duplicateIndex: null }); if (p.onRemoveTag && poppedValue) { - p.onRemoveTag(poppedValue); + p.onRemoveTag(poppedValue, s.tags); } } } @@ -247,7 +254,7 @@ module.exports = React.createClass({ }, _handleClickOnWrapper: function (e) { - this.refs.input; + this.refs.input.focus(); }, _validateAndTag: function (tagText, callback) { diff --git a/examples/index.css b/examples/index.css index 8bc4b6a..5c47cc7 100644 --- a/examples/index.css +++ b/examples/index.css @@ -1,45 +1,3 @@ -.tagged-input-wrapper { - border-width: 1px; - border-style: solid; - border-color: #dadada; - padding: 2px; -} - -.tagged-input-wrapper .tagged-input { - border: none; - outline: none; -} - -.tagged-input-wrapper .tag .tag-text { - padding-left: 5px; -} - -.tagged-input-wrapper .tag { - display: inline-block; - background-color: #E9E9E9; - padding: 2px 0px 2px 2px; - border-radius: 2px; - margin-left: 2px; - margin-right: 2px; -} - -.tagged-input-wrapper .tag.duplicate { - background: #FFDB7B; -} - -.tagged-input-wrapper .tag .remove { - color: #a0a0a0; - padding: 0px 4px; - font-size: 75%; - line-height: 100%; - cursor: pointer; -} - .tagged-input-wrapper .tag .remove:hover { color: red; } - -.tagged-input-wrapper .tag .remove, -.tagged-input-wrapper .tag .tag-text { - display: inline-block; -} diff --git a/grunt/react.js b/grunt/react.js index 5fb2865..0fa62fe 100644 --- a/grunt/react.js +++ b/grunt/react.js @@ -1,3 +1,4 @@ module.exports = { - 'dist/TaggedInput.js': 'src/TaggedInput.jsx' + 'dist/TaggedInput.js': 'src/TaggedInput.jsx', + 'dist/TagComponent.js': 'src/TagComponent.jsx' }; diff --git a/src/TagComponent.jsx b/src/TagComponent.jsx new file mode 100644 index 0000000..99691d7 --- /dev/null +++ b/src/TagComponent.jsx @@ -0,0 +1,67 @@ +'use-strict'; +var React = require('react'); + +var styles = { + tagContainerStyle: { + display: 'inline-block', + backgroundColor: '#E9E9E9', + padding: '2px 0px 2px 2px', + borderRadius: '2px', + marginLeft: '2px', + marginRight: '2px' + }, + duplicatedColor: { + backgroundColor: '#FFDB7B' + }, + tagTextStyle: { + paddingLeft: '5px', + display: 'inline-block' + }, + tagRemoveStyle: { + color: '#a0a0a0', + padding: '0px 4px', + fontSize: '75%', + lineHeight: '100%', + cursor: 'pointer', + display: 'inline-block' + } +}; + +module.exports = React.createClass({ + displayName: 'TagComponent', + + propTypes: { + classes: React.PropTypes.string, + onEdit: React.PropTypes.func, + item: React.PropTypes.string, + onRemove: React.PropTypes.func, + removeTagLabel: React.PropTypes.string, + duplicated: React.PropTypes.bool, + tagContainerStyle: React.PropTypes.object, + tagTextStyle: React.PropTypes.object, + tagRemoveStyle: React.PropTypes.object + }, + + _getTagContainerStyle: function () { + var p = this.props; + var duplicatedBacgroundColor = p.duplicated ? {backgroundColor: p.duplicatedColor || styles.duplicatedColor.backgroundColor} : {}; + return Object.assign({}, styles.tagContainerStyle, p.tagContainerStyle || {}, duplicatedBacgroundColor); + }, + + render: function () { + var p = this.props; + var className = 'tag' + (p.classes ? (' ' + p.classes) : ''); + var tagTextStyle = Object.assign({}, styles.tagTextStyle, p.tagTextStyle || {}); + var tagRemoveStyle = Object.assign({}, styles.tagRemoveStyle, p.tagRemoveStyle || {}); + + return ( +
+
{p.item}
+
+ {p.removeTagLabel} +
+
+ ); + } +}); + diff --git a/src/TaggedInput.jsx b/src/TaggedInput.jsx index b92d7ac..bfa96f7 100644 --- a/src/TaggedInput.jsx +++ b/src/TaggedInput.jsx @@ -1,27 +1,24 @@ 'use-strict'; var React = require('react'); +var TagComponent = require('./TagComponent'); var KEY_CODES = { ENTER: 13, BACKSPACE: 8 }; -var DefaultTagComponent = React.createClass({ - render: function () { - var self = this, p = self.props; - var className = 'tag' + (p.classes ? (' ' + p.classes) : ''); - - return ( -
-
{p.item}
-
- {p.removeTagLabel} -
-
- ); +var styles = { + tagRootContainerStyle: { + borderWidth: '1px', + borderStyle: 'solid', + borderColor: '#dadada', + padding: '2px', + }, + inputStyle: { + border: 'none', + outline: 'none' } - -}); +} module.exports = React.createClass({ displayName: 'TaggedInput', @@ -45,7 +42,12 @@ module.exports = React.createClass({ }), tagOnBlur: React.PropTypes.bool, tabIndex: React.PropTypes.number, - clickTagToEdit: React.PropTypes.bool + clickTagToEdit: React.PropTypes.bool, + tagRootContainerStyle: React.PropTypes.object, + tagContainerStyle: React.PropTypes.object, + tagTextStyle: React.PropTypes.object, + tagRemoveStyle: React.PropTypes.object, + inputStyle: React.PropTypes.object }, getDefaultProps: function () { @@ -88,8 +90,6 @@ module.exports = React.createClass({ placeholder = p.placeholder; } - var TagComponent = DefaultTagComponent; - for (i = 0; i < s.tags.length; i++) { tagComponents.push( ); } @@ -107,6 +111,7 @@ module.exports = React.createClass({ var input = ( ); + var tagRootContainerStyle = Object.assign({}, styles.tagRootContainerStyle , p.tagRootContainerStyle || {}); + return ( -
+
{tagComponents} {input}
@@ -215,7 +222,7 @@ module.exports = React.createClass({ duplicateIndex: null }); if (p.onRemoveTag && poppedValue) { - p.onRemoveTag(poppedValue); + p.onRemoveTag(poppedValue, s.tags); } } } @@ -247,7 +254,7 @@ module.exports = React.createClass({ }, _handleClickOnWrapper: function (e) { - this.refs.input; + this.refs.input.focus(); }, _validateAndTag: function (tagText, callback) {