diff --git a/gh-pages/views/examples/Advanced.js b/gh-pages/views/examples/Advanced.js index df8da81d..e5b9df62 100644 --- a/gh-pages/views/examples/Advanced.js +++ b/gh-pages/views/examples/Advanced.js @@ -9,7 +9,7 @@ import { provideExampleValue } from './higher-order' import defaultStyle from './defaultStyle' import defaultMentionStyle from './defaultMentionStyle' -const style = merge({}, defaultStyle(), { +const style = merge({}, defaultStyle, { suggestions: { list: { maxHeight: 100, diff --git a/gh-pages/views/examples/Examples.js b/gh-pages/views/examples/Examples.js index b82f3bf4..9347e34b 100644 --- a/gh-pages/views/examples/Examples.js +++ b/gh-pages/views/examples/Examples.js @@ -1,4 +1,6 @@ import React from 'react' +import { EnhancerProvider } from 'substyle' +import Radium from 'radium' import MultipleTrigger from './MultipleTrigger' import SingleLine from './SingleLine' @@ -37,20 +39,22 @@ const users = [ export default function Examples() { return ( -
-
-
- + +
+
+
+ +
-
-
-
- -
-
- +
+
+ +
+
+ +
-
+
) } diff --git a/gh-pages/views/examples/MultipleTrigger.js b/gh-pages/views/examples/MultipleTrigger.js index 2532d911..389f2c40 100644 --- a/gh-pages/views/examples/MultipleTrigger.js +++ b/gh-pages/views/examples/MultipleTrigger.js @@ -20,7 +20,7 @@ function MultipleTriggers({ value, data, onChange, onAdd }) { diff --git a/gh-pages/views/examples/SingleLine.js b/gh-pages/views/examples/SingleLine.js index 265393a7..0ea8b64b 100644 --- a/gh-pages/views/examples/SingleLine.js +++ b/gh-pages/views/examples/SingleLine.js @@ -16,7 +16,7 @@ function SingleLine({ value, data, onChange, onAdd }) { singleLine value={ value } onChange={ onChange } - style={ defaultStyle({ singleLine: true }) } + style={ defaultStyle } placeholder={"Mention people using '@'"} > ({ +export default ({ control: { backgroundColor: '#fff', diff --git a/package.json b/package.json index 23007020..9302b75a 100644 --- a/package.json +++ b/package.json @@ -77,7 +77,7 @@ "dependencies": { "babel-runtime": "^6.22.0", "lodash": "^4.5.1", - "substyle": "^3.0.1" + "substyle": "^5.1.0" }, "peerDependencies": { "react": ">=0.14.0", diff --git a/src/Highlighter.js b/src/Highlighter.js index a508eb00..03bc91ec 100644 --- a/src/Highlighter.js +++ b/src/Highlighter.js @@ -1,7 +1,5 @@ import React, { Component, PropTypes, Children } from 'react'; -import Radium from './OptionalRadium'; -import defaultStyle from 'substyle'; - +import { defaultStyle } from 'substyle'; import isEqual from "lodash/isEqual"; import utils from './utils'; @@ -77,7 +75,7 @@ class Highlighter extends Component { } render() { - let { selection, value, markup, displayTransform, inputStyle } = this.props; + let { selection, value, markup, displayTransform, style, inputStyle } = this.props; // If there's a caret (i.e. no range selection), map the caret position into the marked up value var caretPositionInMarkup; @@ -133,14 +131,12 @@ class Highlighter extends Component { ); } - let { style, className } = substyle(this.props, getModifiers(this.props)); - return (
{ resultComponents } @@ -151,7 +147,7 @@ class Highlighter extends Component { renderSubstring(string, key) { // set substring span to hidden, so that Emojis are not shown double in Mobile Safari return ( - + { string } ); @@ -198,39 +194,33 @@ class Highlighter extends Component { // Renders an component to be inserted in the highlighter at the current caret position renderHighlighterCaret(children) { return ( - + { children } ); } } -export default Radium(Highlighter); - -const getModifiers = (props, ...modifiers) => ({ - ...modifiers.reduce((result, modifier) => ({ ...result, [modifier]: true }), {}), - - '&singleLine': props.singleLine, -}); +const styled = defaultStyle({ + position: 'relative', + width: 'inherit', + color: 'transparent', -const substyle = defaultStyle({ - style: { - position: 'relative', - width: 'inherit', - color: 'transparent', + overflow: 'hidden', - overflow: 'hidden', + whiteSpace: 'pre-wrap', + wordWrap: 'break-word', - whiteSpace: 'pre-wrap', - wordWrap: 'break-word', + '&singleLine': { + whiteSpace: 'pre', + wordWrap: null + }, - '&singleLine': { - whiteSpace: 'pre', - wordWrap: null - }, - - substring: { - visibility: 'hidden' - } + substring: { + visibility: 'hidden' } -}); +}, (props) => ({ + '&singleLine': props.singleLine, +})); + +export default styled(Highlighter); diff --git a/src/LoadingIndicator.js b/src/LoadingIndicator.js index 696dbc86..ef0cf201 100644 --- a/src/LoadingIndicator.js +++ b/src/LoadingIndicator.js @@ -1,25 +1,19 @@ import React from 'react'; -import Radium from './OptionalRadium'; import substyle from 'substyle'; -function Spinner(props) { +function LoadingIndicator({ style }) { + const spinnerStyle = style("spinner") return ( -
-
-
-
-
-
+
+
+
+
+
+
+
+
); }; -function LoadingIndicator(props) { - return ( -
- -
- ); -}; - -export default Radium(LoadingIndicator); +export default substyle(LoadingIndicator); diff --git a/src/Mention.js b/src/Mention.js index dff9a1c6..43b0f448 100644 --- a/src/Mention.js +++ b/src/Mention.js @@ -1,18 +1,15 @@ import React, { PropTypes } from 'react'; -import Radium from './OptionalRadium'; - -import utils from './utils'; - -function Mention({ display, className, style }) { - return ( - - { display } - - ); -}; +import { defaultStyle } from 'substyle'; + +const styled = defaultStyle({ + fontWeight: "inherit" +}); + +const Mention = styled(({ display, style }) => ( + + { display } + +)); Mention.propTypes = { /** @@ -37,8 +34,6 @@ Mention.propTypes = { ]), isLoading: PropTypes.bool, - className: PropTypes.string, - style: PropTypes.object }; Mention.defaultProps = { @@ -51,8 +46,4 @@ Mention.defaultProps = { appendSpaceOnAdd: false }; -const defaultStyle = { - fontWeight: "inherit" -} - -export default Radium(Mention); +export default Mention; diff --git a/src/MentionsInput.js b/src/MentionsInput.js index 82d1cd2f..fede784a 100644 --- a/src/MentionsInput.js +++ b/src/MentionsInput.js @@ -1,13 +1,12 @@ import React, { PropTypes } from 'react'; import ReactDOM from 'react-dom'; -import Radium from './OptionalRadium'; import keys from 'lodash/keys'; import values from 'lodash/values'; import omit from 'lodash/omit'; import isEqual from 'lodash/isEqual'; -import defaultStyle from 'substyle'; +import { defaultStyle } from 'substyle'; import utils from './utils'; import SuggestionsOverlay from './SuggestionsOverlay'; @@ -84,8 +83,7 @@ const MentionsInput = React.createClass({ }, onKeyDown: () => null, onSelect: () => null, - onBlur: () => null, - style: {} + onBlur: () => null }; }, @@ -107,7 +105,7 @@ const MentionsInput = React.createClass({ render: function() { return ( -
+
{ this.renderControl() } { this.renderSuggestionsOverlay() }
@@ -115,15 +113,14 @@ const MentionsInput = React.createClass({ }, getInputProps: function(isTextarea) { - let { readOnly, disabled } = this.props; + let { readOnly, disabled, style } = this.props; // pass all props that we don't use through to the input control - let props = omit(this.props, keys(MentionsInput.propTypes)); + let props = omit(this.props, 'style', keys(MentionsInput.propTypes)); return { ...props, - - ...substyle(this.props, getModifiers(this.props, "input")), + ...style("input"), value: this.getPlainText(), @@ -139,11 +136,11 @@ const MentionsInput = React.createClass({ }, renderControl: function() { - let { singleLine } = this.props; + let { singleLine, style } = this.props; let inputProps = this.getInputProps(!singleLine); return ( -
+
{ this.renderHighlighter(inputProps.style) } { singleLine ? this.renderInput(inputProps) : this.renderTextarea(inputProps) }
@@ -151,7 +148,6 @@ const MentionsInput = React.createClass({ }, renderInput: function(props) { - return ( startOfMention) { // only if a deletion has taken place @@ -285,11 +275,11 @@ const MentionsInput = React.createClass({ setSelectionAfterMentionChange: setSelectionAfterMentionChange, }); - var mentions = utils.getMentions(newValue, this.props.markup); + let mentions = utils.getMentions(newValue, this.props.markup); // Propagate change - // var handleChange = this.getOnChange(this.props) || emptyFunction; - var eventMock = { target: { value: newValue } }; + // let handleChange = this.getOnChange(this.props) || emptyFunction; + let eventMock = { target: { value: newValue } }; // this.props.onChange.call(this, eventMock, newValue, newPlainTextValue, mentions); this.executeOnChange(eventMock, newValue, newPlainTextValue, mentions); }, @@ -615,52 +605,45 @@ const MentionsInput = React.createClass({ _queryId: 0 - -}); - -export default Radium(MentionsInput); - -const getModifiers = (props, ...modifiers) => ({ - ...modifiers.reduce((result, modifier) => ({ ...result, [modifier]: true }), {}), - - "&singleLine": props.singleLine, - "&multiLine": !props.singleLine, }); const isMobileSafari = typeof navigator !== 'undefined' && /iPhone|iPad|iPod/i.test(navigator.userAgent); -const substyle = defaultStyle({ - style: { - position: "relative", - overflowY: "visible", +const styled = defaultStyle({ + position: "relative", + overflowY: "visible", - input: { - display: "block", - position: "absolute", + input: { + display: "block", + position: "absolute", - top: 0, + top: 0, - boxSizing: "border-box", + boxSizing: "border-box", - backgroundColor: "transparent", + backgroundColor: "transparent", - width: "inherit", - }, - - '&multiLine': { - input: { - width: "100%", - height: "100%", - bottom: 0, - overflow: "hidden", - resize: "none", + width: "inherit", + }, - // fix weird textarea padding in mobile Safari (see: http://stackoverflow.com/questions/6890149/remove-3-pixels-in-ios-webkit-textarea) - ...(isMobileSafari ? { - marginTop: 1, - marginLeft: -3, - } : null) - } + '&multiLine': { + input: { + width: "100%", + height: "100%", + bottom: 0, + overflow: "hidden", + resize: "none", + + // fix weird textarea padding in mobile Safari (see: http://stackoverflow.com/questions/6890149/remove-3-pixels-in-ios-webkit-textarea) + ...(isMobileSafari ? { + marginTop: 1, + marginLeft: -3, + } : null) } } -}); +}, ({ singleLine }) => ({ + "&singleLine": singleLine, + "&multiLine": !singleLine, +})); + +export default styled(MentionsInput); diff --git a/src/OptionalRadium.js b/src/OptionalRadium.js deleted file mode 100644 index 816bd364..00000000 --- a/src/OptionalRadium.js +++ /dev/null @@ -1,14 +0,0 @@ -import identity from 'lodash/identity' - -let Radium -try { - Radium = require('radium') -} catch(err) { - if (err.code === "MODULE_NOT_FOUND") { - Radium = identity - } else { - throw err; - } -} - -export default Radium \ No newline at end of file diff --git a/src/Suggestion.js b/src/Suggestion.js index 66eeb725..dc60e317 100644 --- a/src/Suggestion.js +++ b/src/Suggestion.js @@ -1,10 +1,8 @@ import React, { Component, PropTypes } from 'react'; -import Radium from './OptionalRadium'; +import { defaultStyle } from 'substyle'; import omit from 'lodash/omit'; import keys from 'lodash/keys'; -import defaultStyle from "substyle"; - class Suggestion extends Component { static propTypes = { @@ -25,12 +23,13 @@ class Suggestion extends Component { }; render() { - let rest = omit(this.props, keys(Suggestion.propTypes)); + let rest = omit(this.props, 'style', keys(Suggestion.propTypes)); return (
  • + { ...this.props.style } + > { this.renderContent() }
  • @@ -67,18 +66,18 @@ class Suggestion extends Component { } renderHighlightedDisplay(display) { - let { query } = this.props; + const { query, style } = this.props; let i = display.toLowerCase().indexOf(query.toLowerCase()); if(i === -1) { - return { display }; + return { display }; } return ( - + { display.substring(0, i) } - + { display.substring(i, i+query.length) } { display.substring(i+query.length) } @@ -88,10 +87,8 @@ class Suggestion extends Component { } -export default Radium(Suggestion); +const styled = defaultStyle({ + cursor: "pointer" +}, (props) => ({ "&focused": props.focused })) -const substyle = defaultStyle({ - style: { - cursor: "pointer" - } -}) +export default styled(Suggestion); diff --git a/src/SuggestionsOverlay.js b/src/SuggestionsOverlay.js index f98fc03f..68d12bdd 100644 --- a/src/SuggestionsOverlay.js +++ b/src/SuggestionsOverlay.js @@ -1,6 +1,5 @@ import React, { Component, PropTypes } from 'react'; -import Radium from './OptionalRadium'; -import defaultStyle from 'substyle'; +import { defaultStyle } from 'substyle'; import utils from './utils'; @@ -33,7 +32,7 @@ class SuggestionsOverlay extends Component { const { top: topContainer } = suggestions.getBoundingClientRect(); top = top - topContainer + scrollTop; bottom = bottom - topContainer + scrollTop; - + if(top < scrollTop) { suggestions.scrollTop = top } else if(bottom > suggestions.offsetHeight) { @@ -42,18 +41,23 @@ class SuggestionsOverlay extends Component { } render() { + const { suggestions, isLoading, style, onMouseDown } = this.props; + // do not show suggestions until there is some data - if(utils.countSuggestions(this.props.suggestions) === 0 && !this.props.isLoading) { + if(utils.countSuggestions(suggestions) === 0 && !isLoading) { return null; } return (
    - -
      + {...style} + onMouseDown={onMouseDown} + > + +
        { this.renderSuggestions() }
      @@ -81,7 +85,8 @@ class SuggestionsOverlay extends Component { let { mentionDescriptor, query } = descriptor; return ( - + return } handleMouseEnter(index, ev) { @@ -123,20 +128,19 @@ class SuggestionsOverlay extends Component { }; -export default Radium(SuggestionsOverlay); - -const substyle = defaultStyle({ - style: { - position: "absolute", - zIndex: 1, - backgroundColor: "white", - marginTop: 14, - minWidth: 100, - - list: { - margin: 0, - padding: 0, - listStyleType: "none", - } +const styled = defaultStyle(({ position }) => ({ + position: "absolute", + zIndex: 1, + backgroundColor: "white", + marginTop: 14, + minWidth: 100, + ...position, + + list: { + margin: 0, + padding: 0, + listStyleType: "none", } -}); +})); + +export default styled(SuggestionsOverlay);