{"action":"created","comment":{"url":"https://api.github.com/repos/appnexus/lucid/pulls/comments/81006031","pull_request_review_id":2018880,"id":81006031,"diff_hunk":"@@ -0,0 +1,427 @@\n+import React from 'react';\n+import _ from 'lodash';\n+import { createClass, findTypes } from '../../util/component-types';\n+import { lucidClassNames } from '../../util/style-helpers';\n+import { partitionText } from '../../util/text-manipulation';\n+import * as reducers from './SearchableSelect.reducers';\n+import CaretIcon from '../Icon/CaretIcon/CaretIcon';\n+import DropMenu from '../DropMenu/DropMenu';\n+import LoadingIcon from '../Icon/LoadingIcon/LoadingIcon';\n+import SearchField from '../SearchField/SearchField';\n+\n+const cx = lucidClassNames.bind('&-SearchableSelect');\n+\n+const {\n+\tany,\n+\tbool,\n+\tfunc,\n+\tnode,\n+\tnumber,\n+\tobject,\n+\tshape,\n+\tstring,\n+\toneOfType,\n+} = React.PropTypes;\n+\n+/**\n+ *\n+ * {\"categories\": [\"controls\", \"selectors\"], \"madeFrom\": [\"DropMenu\"]}\n+ *\n+ * A selector control (like native `<select>`) which is used to select a single option from a dropdown list.\n+ * Supports option groups with and without labels.\n+ */\n+const SearchableSelect = createClass({\n+\tdisplayName: 'SearchableSelect',\n+\n+\treducers,\n+\n+\tcomponents: {\n+\t\t/**\n+\t\t * Content this is displayed when nothing is selected.\n+\t\t */\n+\t\tPlaceholder: createClass({\n+\t\t\tdisplayName: 'SearchableSelect.Placeholder',\n+\t\t\tpropName: 'Placeholder',\n+\t\t}),\n+\t\t/**\n+\t\t * A selectable option in the list.\n+\t\t */\n+\t\tOption: createClass({\n+\t\t\tdisplayName: 'SearchableSelect.Option',\n+\t\t\tpropName: 'Option',\n+\t\t\tpropTypes: DropMenu.Option.propTypes,\n+\t\t}),\n+\t\t/**\n+\t\t * Groups `Option`s together with a non-selectable heading.\n+\t\t */\n+\t\tOptionGroup: createClass({\n+\t\t\tdisplayName: 'SearchableSelect.OptionGroup',\n+\t\t\tpropName: 'OptionGroup',\n+\t\t\tpropTypes: DropMenu.OptionGroup.propTypes,\n+\t\t}),\n+\t},\n+\n+\tpropTypes: {\n+\t\t/**\n+\t\t * Should be instances of {`SearchableSelect.Placeholder`, `SearchableSelect.Option`, `SearchableSelect.OptionGroup`}. Other direct child elements will not render.\n+\t\t */\n+\t\tchildren: node,\n+\t\t/**\n+\t\t * Appended to the component-specific class names set on the root elements. Applies to *both* the control and the flyout menu.\n+\t\t */\n+\t\tclassName: string,\n+\t\t/**\n+\t\t * Styles that are passed through to root element.\n+\t\t */\n+\t\tstyle: object,\n+\t\t/**\n+\t\t * Allows user to reset the `optionIndex` to `null` if they select the placeholder at the top of the options list.\n+\t\t * If `false`, it will not render the placeholder in the menu.\n+\t\t */\n+\t\thasReset: bool,\n+\t\t/**\n+\t\t * Disables the SearchableSelect from being clicked or focused.\n+\t\t */\n+\t\tisDisabled: bool,\n+\t\t/**\n+\t\t * Displays a centered LoadingIcon to allow for asynchronous loading of options.\n+\t\t */\n+\t\tisLoading: bool,\n+\t\t/**\n+\t\t * Applies primary color styling to the control when an item is selected. Defaults to true.\n+\t\t */\n+\t\tisSelectionHighlighted: bool,\n+\t\t/**\n+\t\t * The max height of the fly-out menu.\n+\t\t */\n+\t\tmaxMenuHeight: oneOfType([number, string]),\n+\t\t/**\n+\t\t * Called when the user enters a value to search for; the set of visible Options will be filtered using the value.\n+\t\t * Has the signature `(searchText, {props, event}) => {}` where `searchText` is the new `searchText` or `null`.\n+\t\t */\n+\t\tonSearch: func,\n+\t\t/**\n+\t\t * Called when an option is selected.\n+\t\t * Has the signature `(optionIndex, {props, event}) => {}` where `optionIndex` is the new `selectedIndex` or `null`.\n+\t\t */\n+\t\tonSelect: func,\n+\t\t/**\n+\t\t * The function that will be run against each Option's props to determine whether it should be visible or not.\n+\t\t * The default behavior of the function is to match, ignoring case, against any text node descendant of the `Option`.\n+\t\t *\n+\t\t * Has the signature `(searchText, optionProps)`\n+\t\t * If `true`, option will be visible. If `false`, the option will not be visible.\n+\t\t */\n+\t\toptionFilter: func,\n+\t\t/**\n+\t\t * This function will be run against Options with Rich Content for children to allow for special 'underlining' behavior.\n+\t\t * The default behavior of the function is to just return the rich content as is.\n+\t\t *\n+\t\t * Has the signature `(children, searchText)`\n+\t\t */\n+\t\trichChildRenderer: func,\n+\t\t/**\n+\t\t * The current search text to filter the list of options by.\n+\t\t */\n+\t\tsearchText: string,\n+\t\t/**\n+\t\t * The currently selected `SearchableSelect.Option` index or `null` if nothing is selected.\n+\t\t */\n+\t\tselectedIndex: number,\n+\t\t/**\n+\t\t * Object of DropMenu props which are passed thru to the underlying DropMenu component.\n+\t\t */\n+\t\tDropMenu: shape(DropMenu.propTypes),\n+\t\t/**\n+\t\t * *Child Element* - The content rendered in the control when there is no option is selected. Also rendered in the option list to remove current selection.\n+\t\t */\n+\t\tPlaceholder: any,\n+\t\t/**\n+\t\t * *Child Element* - These are menu options. The `optionIndex` is in-order of rendering regardless of group nesting, starting with index `0`.\n+\t\t * Each `Option` may be passed a prop called `isDisabled` to disable selection of that `Option`.\n+\t\t * Any other props pass to Option will be available from the `onSelect` handler.\n+\t\t */\n+\t\tOption: any,\n+\t\t/**\n+\t\t * *Child Element* - Used to group `Option`s within the menu. Any non-`Option`s passed in will be rendered as a label for the group.\n+\t\t */\n+\t\tOptionGroup: any,\n+\t},\n+\n+\tgetDefaultProps() {\n+\t\treturn {\n+\t\t\thasReset: true,\n+\t\t\tisSelectionHighlighted: true,\n+\t\t\tisDisabled: false,\n+\t\t\tisLoading: false,\n+\t\t\toptionFilter: this.defaultOptionFilter,\n+\t\t\trichChildRenderer: _.identity,\n+\t\t\tsearchText: null,\n+\t\t\tselectedIndex: null,\n+\t\t\tDropMenu: DropMenu.getDefaultProps(),\n+\t\t};\n+\t},\n+\n+\tgetInitialState() {\n+\t\treturn {\n+\t\t\toptionGroups: [],\n+\t\t\tflattenedOptionsData: [],\n+\t\t\tungroupedOptionData: [],\n+\t\t\toptionGroupDataLookup: {},\n+\t\t\tsearchCache: {},\n+\t\t}\n+\t},\n+\n+\tstatics: {\n+\t\tgetCombinedChildText(node) {\n+\t\t\tif (!node.children) {\n+\t\t\t\treturn '';\n+\t\t\t}\n+\n+\t\t\tif (_.isString(node.children)) {\n+\t\t\t\treturn node.children;\n+\t\t\t}\n+\n+\t\t\treturn node.children\n+\t\t\t\t\t\t\t.filter(child => !_.isString(child))\n+\t\t\t\t\t\t\t.map(child => this.getCombinedChildText(child.props))\n+\t\t\t\t\t\t\t.reduce(((combinedText, childText) => combinedText + childText), node.children.find(_.isString) || '');\n+\t\t},\n+\n+\t\tdefaultOptionFilter(searchText, optionProps, optionIndex, state) {\n+\t\t\tif (!searchText) {\n+\t\t\t\treturn true;\n+\t\t\t}\n+\n+\t\t\treturn state.searchCache[optionIndex].visible;\n+\t\t},\n+\n+\t\tpreprocessOptionData(props) {\n+\t\t\tconst {\n+\t\t\t\tsearchText,\n+\t\t\t} = props;\n+\n+\t\t\tconst {\n+\t\t\t\tflattenedOptionsData,\n+\t\t\t\tnullOptions,\n+\t\t\t\toptionGroupDataLookup,\n+\t\t\t\toptionGroups,\n+\t\t\t\tungroupedOptionData,\n+\t\t\t} = DropMenu.preprocessOptionData(props, SearchableSelect);\n+\n+\t\t\tconst searchCache = _.keyBy(_.map(flattenedOptionsData, ({optionIndex, optionProps}) => {\n+\t\t\t\treturn {\n+\t\t\t\t\toptionIndex,\n+\t\t\t\t\tcombinedText: this.getCombinedChildText(optionProps),\n+\t\t\t\t};\n+\t\t\t}), 'optionIndex');\n+\n+\t\t\t// If there isn't any searchText, just return the existing list of options.\n+\t\t\tif (_.isEmpty(searchText)) {\n+\t\t\t\treturn {\n+\t\t\t\t\tflattenedOptionsData,\n+\t\t\t\t\tnullOptions,\n+\t\t\t\t\toptionGroupDataLookup,\n+\t\t\t\t\toptionGroups,\n+\t\t\t\t\tsearchCache,\n+\t\t\t\t\tungroupedOptionData,\n+\t\t\t\t};\n+\t\t\t}\n+\n+\t\t\tconst searchPattern = new RegExp(_.escapeRegExp(searchText), 'i');\n+\n+\t\t\tconst filteredFlattenedOptionsData = _.filter(flattenedOptionsData, ({optionIndex}) => {\n+\t\t\t\tconst visible = searchPattern.test(searchCache[optionIndex].combinedText);\n+\t\t\t\tsearchCache[optionIndex].visible = visible;\n+\t\t\t\treturn visible;\n+\t\t\t});\n+\n+\t\t\treturn {\n+\t\t\t\tflattenedOptionsData: filteredFlattenedOptionsData,\n+\t\t\t\tnullOptions,\n+\t\t\t\toptionGroupDataLookup,\n+\t\t\t\toptionGroups,\n+\t\t\t\tsearchCache,\n+\t\t\t\tungroupedOptionData,\n+\t\t\t};\n+\t\t},\n+\t},\n+\n+\tcomponentWillMount() {\n+\t\t// preprocess the options data before rendering\n+\t\tconst preProcessedOptionData = SearchableSelect.preprocessOptionData(this.props);\n+\t\tthis.setState({\n+\t\t\t...preProcessedOptionData,\n+\t\t});\n+\t},\n+\n+\tcomponentWillReceiveProps(nextProps) {\n+\t\t// only preprocess options data when it changes (via new props) - better performance than doing this each render\n+\t\tif (this.props.children !== nextProps.children || this.props.searchText !== nextProps.searchText) {\n+\t\t\tconst preProcessedOptionData = SearchableSelect.preprocessOptionData(nextProps);\n+\t\t\tthis.setState({\n+\t\t\t\t...preProcessedOptionData,\n+\t\t\t});\n+\t\t}\n+\t},\n+\n+\thandleClickSearchField(event) {\n+\t\tevent.stopPropagation();\n+\t},\n+\n+\trenderUnderlinedChildren(childText, searchText) {\n+\t\tconst [pre, match, post] = partitionText(childText, new RegExp(_.escapeRegExp(searchText), 'i'), searchText.length);\n+\n+\t\treturn (\n+\t\t\t[\n+\t\t\t\tpre && <span key='pre' className={cx('&-Option-underline-pre')}>{pre}</span>,\n+\t\t\t\tmatch && <span key='match' className={cx('&-Option-underline-match')}>{match}</span>,\n+\t\t\t\tpost && <span key='post' className={cx('&-Option-underline-post')}>{post}</span>,\n+\t\t\t]\n+\t\t);\n+\t},\n+\n+\trenderOption(optionProps, optionIndex) {\n+\t\tconst {\n+\t\t\tisLoading,\n+\t\t\toptionFilter,\n+\t\t\trichChildRenderer,\n+\t\t\tsearchText,\n+\t\t} = this.props;\n+\n+\t\tif (searchText) {\n+\t\t\treturn optionFilter(searchText, optionProps, optionIndex, this.state) && (\n+\t\t\t\t<DropMenu.Option isDisabled={isLoading} key={'SearchableSelectOption' + optionIndex} {..._.omit(optionProps, ['children'])}>\n+\t\t\t\t\t{_.isString(optionProps.children) ?\n+\t\t\t\t\t\tthis.renderUnderlinedChildren(optionProps.children, searchText)\n+\t\t\t\t\t\t: richChildRenderer(optionProps.children, searchText)}\n+\t\t\t\t</DropMenu.Option>\n+\t\t\t);\n+\t\t}\n+\n+\t\treturn (\n+\t\t\t<DropMenu.Option isDisabled={isLoading} key={'SearchableSelectOption' + optionIndex} {...optionProps} />\n+\t\t);\n+\t},\n+\n+\trenderOptions() {\n+\t\tconst {\n+\t\t\tsearchText,\n+\t\t} = this.props;\n+\n+\t\tconst {\n+\t\t\toptionGroups,\n+\t\t\toptionGroupDataLookup,\n+\t\t\tungroupedOptionData,\n+\t\t} = this.state;\n+\n+\t\t// for each option group passed in, render a DropMenu.OptionGroup, any label will be included in it's children, render each option inside the group\n+\t\tconst options = _.map(optionGroups, (optionGroupProps, optionGroupIndex) => {\n+\t\t\tconst childOptions = _.map(_.get(optionGroupDataLookup, optionGroupIndex), ({ optionProps, optionIndex }) => (\n+\t\t\t\tthis.renderOption(optionProps, optionIndex)\n+\t\t\t)).filter(childOption => childOption);\n+\n+\t\t\treturn (\n+\t\t\t\tchildOptions.length > 0 &&\n+\t\t\t\t<DropMenu.OptionGroup key={'SearchableSelectOptionGroup' + optionGroupIndex} {...optionGroupProps}>\n+\t\t\t\t\t{optionGroupProps.children}\n+\t\t\t\t\t{childOptions}\n+\t\t\t\t</DropMenu.OptionGroup>\n+\t\t\t);\n+\t\t// then render all the ungrouped options at the end\n+\t\t}).concat(_.map(ungroupedOptionData, ({ optionProps, optionIndex }) => (\n+\t\t\tthis.renderOption(optionProps, optionIndex)\n+\t\t))).filter(option => option);\n+\n+\t\treturn (\n+\t\t\toptions.length > 0 ? options : <DropMenu.Option isDisabled><span className={cx('&-noresults')}>No results match \"{searchText}\"</span></DropMenu.Option>\n+\t\t);\n+\t},\n+\n+\trender() {\n+\t\tconst {\n+\t\t\tstyle,\n+\t\t\tclassName,\n+\t\t\thasReset,\n+\t\t\tisDisabled,\n+\t\t\tisLoading,\n+\t\t\tisSelectionHighlighted,\n+\t\t\tmaxMenuHeight,\n+\t\t\tsearchText,\n+\t\t\tselectedIndex,\n+\t\t\tonSearch,\n+\t\t\tonSelect,\n+\t\t\tDropMenu: dropMenuProps,\n+\t\t} = this.props;\n+\n+\t\tconst {\n+\t\t\tdirection,\n+\t\t\tflyOutStyle,\n+\t\t\tisExpanded,\n+\t\t} = dropMenuProps;\n+\n+\t\tconst {\n+\t\t\tflattenedOptionsData,\n+\t\t} = this.state;\n+\n+\t\tconst placeholderProps = _.first(_.map(findTypes(this.props, SearchableSelect.Placeholder), 'props'));\n+\t\tconst placeholder = _.get(placeholderProps, 'children', 'Select');\n+\t\tconst isItemSelected = _.isNumber(selectedIndex);\n+\n+\t\treturn (\n+\t\t\t<DropMenu\n+\t\t\t\t{...dropMenuProps}\n+\t\t\t\tclassName={cx('&', className)}\n+\t\t\t\tflyOutStyle={_.assign({}, flyOutStyle, !_.isNil(maxMenuHeight) ? { maxHeight: maxMenuHeight } : null)}\n+\t\t\t\tisDisabled={isDisabled}\n+\t\t\t\tisLoading={isLoading}\n+\t\t\t\tonSelect={onSelect}\n+\t\t\t\tselectedIndices={isItemSelected ? [selectedIndex] : []}\n+\t\t\t\tstyle={style}\n+\t\t\t>\n+\t\t\t\t<DropMenu.Control>\n+\t\t\t\t\t<div\n+\t\t\t\t\t\ttabIndex={0}\n+\t\t\t\t\t\tclassName={cx('&-Control', {\n+\t\t\t\t\t\t\t'&-Control-is-highlighted': (!isDisabled && isItemSelected && isSelectionHighlighted) || (isExpanded && isSelectionHighlighted),\n+\t\t\t\t\t\t\t'&-Control-is-selected': (!isDisabled && isItemSelected && isSelectionHighlighted) || (isExpanded && isSelectionHighlighted),\n+\t\t\t\t\t\t\t'&-Control-is-expanded': isExpanded,\n+\t\t\t\t\t\t\t'&-Control-is-disabled': isDisabled,\n+\t\t\t\t\t\t})\n+\t\t\t\t\t}>\n+\t\t\t\t\t\t<span\n+\t\t\t\t\t\t\t{...(!isItemSelected ? placeholderProps : null)}\n+\t\t\t\t\t\t\tclassName={cx(\n+\t\t\t\t\t\t\t\t\t'&-Control-content',\n+\t\t\t\t\t\t\t\t\t(!isItemSelected ? _.get(placeholderProps, 'className') : null)\n+\t\t\t\t\t\t\t)}\n+\t\t\t\t\t\t>\n+\t\t\t\t\t\t\t{isItemSelected ? flattenedOptionsData[selectedIndex].optionProps.children : placeholder}\n+\t\t\t\t\t\t</span>\n+\t\t\t\t\t\t<CaretIcon direction={isExpanded ? direction : 'down'} />\n+\t\t\t\t\t</div>\n+\t\t\t\t\t{\n+\t\t\t\t\t\tisExpanded &&\n+\t\t\t\t\t\t<div className={cx('&-Search-container')} onClick={this.handleClickSearchField}>\n+\t\t\t\t\t\t\t<SearchField","path":"src/components/SearchableSelect/SearchableSelect.jsx","position":406,"original_position":406,"commit_id":"174d08d52faa462f07926cd56b8a9d4170644bde","original_commit_id":"fcd64f7ffac4ac553059fc2ec2e1addd7633d201","user":{"login":"mute","id":730349,"avatar_url":"https://avatars.githubusercontent.com/u/730349?v=3","gravatar_id":"","url":"https://api.github.com/users/mute","html_url":"https://github.com/mute","followers_url":"https://api.github.com/users/mute/followers","following_url":"https://api.github.com/users/mute/following{/other_user}","gists_url":"https://api.github.com/users/mute/gists{/gist_id}","starred_url":"https://api.github.com/users/mute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mute/subscriptions","organizations_url":"https://api.github.com/users/mute/orgs","repos_url":"https://api.github.com/users/mute/repos","events_url":"https://api.github.com/users/mute/events{/privacy}","received_events_url":"https://api.github.com/users/mute/received_events","type":"User","site_admin":false},"body":"Maybe I should expose a prop that allows for passing through `SearchField` props so that users of the component can have more control over the SearchField itself?","created_at":"2016-09-28T20:10:14Z","updated_at":"2016-09-28T20:10:14Z","html_url":"https://github.com/appnexus/lucid/pull/542#discussion_r81006031","pull_request_url":"https://api.github.com/repos/appnexus/lucid/pulls/542","_links":{"self":{"href":"https://api.github.com/repos/appnexus/lucid/pulls/comments/81006031"},"html":{"href":"https://github.com/appnexus/lucid/pull/542#discussion_r81006031"},"pull_request":{"href":"https://api.github.com/repos/appnexus/lucid/pulls/542"}}},"pull_request":{"url":"https://api.github.com/repos/appnexus/lucid/pulls/542","id":87190156,"html_url":"https://github.com/appnexus/lucid/pull/542","diff_url":"https://github.com/appnexus/lucid/pull/542.diff","patch_url":"https://github.com/appnexus/lucid/pull/542.patch","issue_url":"https://api.github.com/repos/appnexus/lucid/issues/542","number":542,"state":"open","locked":false,"title":"Adds a Searchable SingleSelect","user":{"login":"mute","id":730349,"avatar_url":"https://avatars.githubusercontent.com/u/730349?v=3","gravatar_id":"","url":"https://api.github.com/users/mute","html_url":"https://github.com/mute","followers_url":"https://api.github.com/users/mute/followers","following_url":"https://api.github.com/users/mute/following{/other_user}","gists_url":"https://api.github.com/users/mute/gists{/gist_id}","starred_url":"https://api.github.com/users/mute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mute/subscriptions","organizations_url":"https://api.github.com/users/mute/orgs","repos_url":"https://api.github.com/users/mute/repos","events_url":"https://api.github.com/users/mute/events{/privacy}","received_events_url":"https://api.github.com/users/mute/received_events","type":"User","site_admin":false},"body":"## PR Checklist\r\n\r\n- Manually tested across supported browsers\r\n  - [x] Chrome\r\n  - [x] Firefox\r\n  - [x] Safari\r\n  - [ ] IE11 (Win 7)\r\n  - [x] Edge (Win 10)\r\n- [x] Unit tests written (`common` at minimum)\r\n- [x] PR has one of the `semver-` labels\r\n- [ ] Two core team engineer approvals\r\n- [ ] One core team UX approval\r\n\r\nFixes #479.\r\n","created_at":"2016-09-28T20:01:36Z","updated_at":"2016-09-28T20:10:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f93af0a843cbaec415974e49c67ee7d57e336a02","assignee":{"login":"mute","id":730349,"avatar_url":"https://avatars.githubusercontent.com/u/730349?v=3","gravatar_id":"","url":"https://api.github.com/users/mute","html_url":"https://github.com/mute","followers_url":"https://api.github.com/users/mute/followers","following_url":"https://api.github.com/users/mute/following{/other_user}","gists_url":"https://api.github.com/users/mute/gists{/gist_id}","starred_url":"https://api.github.com/users/mute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mute/subscriptions","organizations_url":"https://api.github.com/users/mute/orgs","repos_url":"https://api.github.com/users/mute/repos","events_url":"https://api.github.com/users/mute/events{/privacy}","received_events_url":"https://api.github.com/users/mute/received_events","type":"User","site_admin":false},"assignees":[{"login":"mute","id":730349,"avatar_url":"https://avatars.githubusercontent.com/u/730349?v=3","gravatar_id":"","url":"https://api.github.com/users/mute","html_url":"https://github.com/mute","followers_url":"https://api.github.com/users/mute/followers","following_url":"https://api.github.com/users/mute/following{/other_user}","gists_url":"https://api.github.com/users/mute/gists{/gist_id}","starred_url":"https://api.github.com/users/mute/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mute/subscriptions","organizations_url":"https://api.github.com/users/mute/orgs","repos_url":"https://api.github.com/users/mute/repos","events_url":"https://api.github.com/users/mute/events{/privacy}","received_events_url":"https://api.github.com/users/mute/received_events","type":"User","site_admin":false}],"milestone":null,"commits_url":"https://api.github.com/repos/appnexus/lucid/pulls/542/commits","review_comments_url":"https://api.github.com/repos/appnexus/lucid/pulls/542/comments","review_comment_url":"https://api.github.com/repos/appnexus/lucid/pulls/comments{/number}","comments_url":"https://api.github.com/repos/appnexus/lucid/issues/542/comments","statuses_url":"https://api.github.com/repos/appnexus/lucid/statuses/174d08d52faa462f07926cd56b8a9d4170644bde","head":{"label":"appnexus:479-single-select-w-search","ref":"479-single-select-w-search","sha":"174d08d52faa462f07926cd56b8a9d4170644bde","user":{"login":"appnexus","id":1664176,"avatar_url":"https://avatars.githubusercontent.com/u/1664176?v=3","gravatar_id":"","url":"https://api.github.com/users/appnexus","html_url":"https://github.com/appnexus","followers_url":"https://api.github.com/users/appnexus/followers","following_url":"https://api.github.com/users/appnexus/following{/other_user}","gists_url":"https://api.github.com/users/appnexus/gists{/gist_id}","starred_url":"https://api.github.com/users/appnexus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appnexus/subscriptions","organizations_url":"https://api.github.com/users/appnexus/orgs","repos_url":"https://api.github.com/users/appnexus/repos","events_url":"https://api.github.com/users/appnexus/events{/privacy}","received_events_url":"https://api.github.com/users/appnexus/received_events","type":"Organization","site_admin":false},"repo":{"id":51951143,"name":"lucid","full_name":"appnexus/lucid","owner":{"login":"appnexus","id":1664176,"avatar_url":"https://avatars.githubusercontent.com/u/1664176?v=3","gravatar_id":"","url":"https://api.github.com/users/appnexus","html_url":"https://github.com/appnexus","followers_url":"https://api.github.com/users/appnexus/followers","following_url":"https://api.github.com/users/appnexus/following{/other_user}","gists_url":"https://api.github.com/users/appnexus/gists{/gist_id}","starred_url":"https://api.github.com/users/appnexus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appnexus/subscriptions","organizations_url":"https://api.github.com/users/appnexus/orgs","repos_url":"https://api.github.com/users/appnexus/repos","events_url":"https://api.github.com/users/appnexus/events{/privacy}","received_events_url":"https://api.github.com/users/appnexus/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/appnexus/lucid","description":"A UI component library from AppNexus.","fork":false,"url":"https://api.github.com/repos/appnexus/lucid","forks_url":"https://api.github.com/repos/appnexus/lucid/forks","keys_url":"https://api.github.com/repos/appnexus/lucid/keys{/key_id}","collaborators_url":"https://api.github.com/repos/appnexus/lucid/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/appnexus/lucid/teams","hooks_url":"https://api.github.com/repos/appnexus/lucid/hooks","issue_events_url":"https://api.github.com/repos/appnexus/lucid/issues/events{/number}","events_url":"https://api.github.com/repos/appnexus/lucid/events","assignees_url":"https://api.github.com/repos/appnexus/lucid/assignees{/user}","branches_url":"https://api.github.com/repos/appnexus/lucid/branches{/branch}","tags_url":"https://api.github.com/repos/appnexus/lucid/tags","blobs_url":"https://api.github.com/repos/appnexus/lucid/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/appnexus/lucid/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/appnexus/lucid/git/refs{/sha}","trees_url":"https://api.github.com/repos/appnexus/lucid/git/trees{/sha}","statuses_url":"https://api.github.com/repos/appnexus/lucid/statuses/{sha}","languages_url":"https://api.github.com/repos/appnexus/lucid/languages","stargazers_url":"https://api.github.com/repos/appnexus/lucid/stargazers","contributors_url":"https://api.github.com/repos/appnexus/lucid/contributors","subscribers_url":"https://api.github.com/repos/appnexus/lucid/subscribers","subscription_url":"https://api.github.com/repos/appnexus/lucid/subscription","commits_url":"https://api.github.com/repos/appnexus/lucid/commits{/sha}","git_commits_url":"https://api.github.com/repos/appnexus/lucid/git/commits{/sha}","comments_url":"https://api.github.com/repos/appnexus/lucid/comments{/number}","issue_comment_url":"https://api.github.com/repos/appnexus/lucid/issues/comments{/number}","contents_url":"https://api.github.com/repos/appnexus/lucid/contents/{+path}","compare_url":"https://api.github.com/repos/appnexus/lucid/compare/{base}...{head}","merges_url":"https://api.github.com/repos/appnexus/lucid/merges","archive_url":"https://api.github.com/repos/appnexus/lucid/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/appnexus/lucid/downloads","issues_url":"https://api.github.com/repos/appnexus/lucid/issues{/number}","pulls_url":"https://api.github.com/repos/appnexus/lucid/pulls{/number}","milestones_url":"https://api.github.com/repos/appnexus/lucid/milestones{/number}","notifications_url":"https://api.github.com/repos/appnexus/lucid/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/appnexus/lucid/labels{/name}","releases_url":"https://api.github.com/repos/appnexus/lucid/releases{/id}","deployments_url":"https://api.github.com/repos/appnexus/lucid/deployments","created_at":"2016-02-17T19:59:27Z","updated_at":"2016-09-27T14:11:46Z","pushed_at":"2016-09-28T20:01:50Z","git_url":"git://github.com/appnexus/lucid.git","ssh_url":"git@github.com:appnexus/lucid.git","clone_url":"https://github.com/appnexus/lucid.git","svn_url":"https://github.com/appnexus/lucid","homepage":"http://appnexus.github.io/lucid","size":4161,"stargazers_count":43,"watchers_count":43,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":14,"mirror_url":null,"open_issues_count":59,"forks":14,"open_issues":59,"watchers":43,"default_branch":"master"}},"base":{"label":"appnexus:master","ref":"master","sha":"cbdf70b8fd735e163bd573fc717d4836512341b6","user":{"login":"appnexus","id":1664176,"avatar_url":"https://avatars.githubusercontent.com/u/1664176?v=3","gravatar_id":"","url":"https://api.github.com/users/appnexus","html_url":"https://github.com/appnexus","followers_url":"https://api.github.com/users/appnexus/followers","following_url":"https://api.github.com/users/appnexus/following{/other_user}","gists_url":"https://api.github.com/users/appnexus/gists{/gist_id}","starred_url":"https://api.github.com/users/appnexus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appnexus/subscriptions","organizations_url":"https://api.github.com/users/appnexus/orgs","repos_url":"https://api.github.com/users/appnexus/repos","events_url":"https://api.github.com/users/appnexus/events{/privacy}","received_events_url":"https://api.github.com/users/appnexus/received_events","type":"Organization","site_admin":false},"repo":{"id":51951143,"name":"lucid","full_name":"appnexus/lucid","owner":{"login":"appnexus","id":1664176,"avatar_url":"https://avatars.githubusercontent.com/u/1664176?v=3","gravatar_id":"","url":"https://api.github.com/users/appnexus","html_url":"https://github.com/appnexus","followers_url":"https://api.github.com/users/appnexus/followers","following_url":"https://api.github.com/users/appnexus/following{/other_user}","gists_url":"https://api.github.com/users/appnexus/gists{/gist_id}","starred_url":"https://api.github.com/users/appnexus/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/appnexus/subscriptions","organizations_url":"https://api.github.com/users/appnexus/orgs","repos_url":"https://api.github.com/users/appnexus/repos","events_url":"https://api.github.com/users/appnexus/events{/privacy}","received_events_url":"https://api.github.com/users/appnexus/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/appnexus/lucid","description":"A UI component library from AppNexus.","fork":false,"url":"https://api.github.com/repos/appnexus/lucid","forks_url":"https://api.github.com/repos/appnexus/lucid/forks","keys_url":"https://api.github.com/repos/appnexus/lucid/keys{/key_id}","collaborators_url":"https://api.github.com/repos/appnexus/lucid/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/appnexus/lucid/teams","hooks_url":"https://api.github.com/repos/appnexus/lucid/hooks","issue_events_url":"https://api.github.com/repos/appnexus/lucid/issues/events{/number}","events_url":"https://api.github.com/repos/appnexus/lucid/events","assignees_url":"https://api.github.com/repos/appnexus/lucid/assignees{/user}","branches_url":"https://api.github.com/repos/appnexus/lucid/branches{/branch}","tags_url":"https://api.github.com/repos/appnexus/lucid/tags","blobs_url":"https://api.github.com/repos/appnexus/lucid/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/appnexus/lucid/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/appnexus/lucid/git/refs{/sha}","trees_url":"https://api.github.com/repos/appnexus/lucid/git/trees{/sha}","statuses_url":"https://api.github.com/repos/appnexus/lucid/statuses/{sha}","languages_url":"https://api.github.com/repos/appnexus/lucid/languages","stargazers_url":"https://api.github.com/repos/appnexus/lucid/stargazers","contributors_url":"https://api.github.com/repos/appnexus/lucid/contributors","subscribers_url":"https://api.github.com/repos/appnexus/lucid/subscribers","subscription_url":"https://api.github.com/repos/appnexus/lucid/subscription","commits_url":"https://api.github.com/repos/appnexus/lucid/commits{/sha}","git_commits_url":"https://api.github.com/repos/appnexus/lucid/git/commits{/sha}","comments_url":"https://api.github.com/repos/appnexus/lucid/comments{/number}","issue_comment_url":"https://api.github.com/repos/appnexus/lucid/issues/comments{/number}","contents_url":"https://api.github.com/repos/appnexus/lucid/contents/{+path}","compare_url":"https://api.github.com/repos/appnexus/lucid/compare/{base}...{head}","merges_url":"https://api.github.com/repos/appnexus/lucid/merges","archive_url":"https://api.github.com/repos/appnexus/lucid/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/appnexus/lucid/downloads","issues_url":"https://api.github.com/repos/appnexus/lucid/issues{/number}","pulls_url":"https://api.github.com/repos/appnexus/lucid/pulls{/number}","milestones_url":"https://api.github.com/repos/appnexus/lucid/milestones{/number}","notifications_url":"https://api.github.com/repos/appnexus/lucid/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/appnexus/lucid/labels{/name}","releases_url":"https://api.github.com/repos/appnexus/lucid/releases{/id}","deployments_url":"https://api.github.com/repos/appnexus/lucid/deployments","created_at":"2016-02-17T19:59:27Z","updated_at":"2016-09-27T14:11:46Z","pushed_at":"2016-09-28T20:01:50Z","git_url":"git://github.com/appnexus/lucid.git","ssh_url":"git@github.com:appnexus/lucid.git","clone_url":"https://github.com/appnexus/lucid.git","svn_url":"https://github.com/appnexus/lucid","homepage":"http://appnexus.github.io/lucid","size":4161,"stargazers_count":43,"watchers_count":43,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":14,"mirror_url":null,"open_issues_count":59,"forks":14,"open_issues":59,"watchers":43,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/appnexus/lucid/pulls/542"},"html":{"href":"https://github.com/appnexus/lucid/pull/542"},"issue":{"href":"https://api.github.com/repos/appnexus/lucid/issues/542"},"comments":{"href":"https://api.github.com/repos/appnexus/lucid/issues/542/comments"},"review_comments":{"href":"https://api.github.com/repos/appnexus/lucid/pulls/542/comments"},"review_comment":{"href":"https://api.github.com/repos/appnexus/lucid/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/appnexus/lucid/pulls/542/commits"},"statuses":{"href":"https://api.github.com/repos/appnexus/lucid/statuses/174d08d52faa462f07926cd56b8a9d4170644bde"}}}}
{"actor":{"display_login":"mute"}}