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) {