Example #1
0
        <footer className="login-footer">
          New here, <a href="#" onClick={this.goToSignUpPage.bind(this)}>Create an account</a>
        </footer>
      </div>
    );
  }

  render() {
    return (
      <div className="auth">
        <div className="auth-box-wrapper">
          {this.renderAuthBox()}
        </div>
      </div>
    );
  }
}

LogInPage.propTypes = {
  dispatch: PropTypes.func.isRequired,
  auth: PropTypes.shape({
    authenticated: PropTypes.bool.isRequired,
    errors: PropTypes.object.isRequired,
    isProcessing: PropTypes.bool,
  }),
};

export default LogInPage;


Example #2
0
                defaultMessage="Directory"
              />
            </h1>
          </EuiTitle>
          <EuiSpacer size="m" />
          <EuiTabs className="homeDirectoryTabs">
            {this.renderTabs()}
          </EuiTabs>
          <EuiSpacer />
          <EuiFlexGrid columns={4}>
            { this.renderDirectories() }
          </EuiFlexGrid>
        </EuiPageBody>
      </EuiPage>
    );
  }
}

FeatureDirectory.propTypes = {
  addBasePath: PropTypes.func.isRequired,
  directories: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.string.isRequired,
    title: PropTypes.string.isRequired,
    description: PropTypes.string.isRequired,
    icon: PropTypes.string.isRequired,
    path: PropTypes.string.isRequired,
    showOnHomePage: PropTypes.bool.isRequired,
    category: PropTypes.string.isRequired
  }))
};
      selected={isHighlighted}
      component="div"
      style={{
        fontWeight: isSelected ? 500 : 400,
      }}
    >
      {suggestion.label}
    </MenuItem>
  );
}
renderSuggestion.propTypes = {
  highlightedIndex: PropTypes.number,
  index: PropTypes.number,
  itemProps: PropTypes.object,
  selectedItem: PropTypes.string,
  suggestion: PropTypes.shape({ label: PropTypes.string }).isRequired,
};

function getSuggestions(inputValue) {
  let count = 0;

  return suggestions.filter(suggestion => {
    const keep =
      (!inputValue || suggestion.label.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1) &&
      count < 5;

    if (keep) {
      count += 1;
    }

    return keep;
Example #4
0
    this.props.actions.fetchTodos()
  }
  render() {
    const { todos } = this.props
    const { updateTodo } = this.props.actions
    return (
      <ul>
        {todos.map(todo =>
          <Todo
            key={todo.id}
            {...todo}
            onClick={() => updateTodo(todo.id, { is_completed: !todo.isCompleted })}
          />
        )}
      </ul>
    )
  }
}

TodoList.propTypes = {
  todos: PropTypes.arrayOf(PropTypes.shape({
    id: PropTypes.number.isRequired,
    isCompleted: PropTypes.bool.isRequired,
    text: PropTypes.string.isRequired
  }).isRequired).isRequired,
  actions: PropTypes.shape({
    updateTodo: PropTypes.func.isRequired,
    fetchTodos: PropTypes.func.isRequired,
  })
}
    children: PropTypes.element.isRequired,
    crudGetMatching: PropTypes.func.isRequired,
    crudGetMany: PropTypes.func.isRequired,
    filter: PropTypes.object,
    filterToQuery: PropTypes.func.isRequired,
    input: PropTypes.object.isRequired,
    label: PropTypes.string,
    matchingReferences: PropTypes.array,
    meta: PropTypes.object,
    onChange: PropTypes.func,
    perPage: PropTypes.number,
    reference: PropTypes.string.isRequired,
    referenceRecords: PropTypes.array,
    resource: PropTypes.string.isRequired,
    sort: PropTypes.shape({
        field: PropTypes.string,
        order: PropTypes.oneOf(['ASC', 'DESC']),
    }),
    source: PropTypes.string,
};

ReferenceArrayInput.defaultProps = {
    allowEmpty: false,
    filter: {},
    filterToQuery: searchText => ({ q: searchText }),
    matchingReferences: [],
    perPage: 25,
    sort: { field: 'id', order: 'DESC' },
    referenceRecords: [],
};

function mapStateToProps(state, props) {
Example #6
0
import PropTypes from 'prop-types';

export default PropTypes.shape({
  disabled: PropTypes.bool,
  label: PropTypes.string,
  value: PropTypes.string,
});
Example #7
0
File: row.js Project: juju/juju-gui
      </tr>);
  }
}

BasicTableRow.defaultProps = {
  classes: []
};

BasicTableRow.propTypes = {
  // The extra classes to apply to an individual row.
  classes: PropTypes.array,
  // A function to call when a row is clicked.
  clickURL: PropTypes.string,
  columns: PropTypes.arrayOf(PropTypes.shape({
    content: PropTypes.node,
    // The extra classes to apply to the column.
    classes: PropTypes.arrayOf(PropTypes.string)
  }).isRequired
  ).isRequired,
  // Content to be displayed when the row is toggled.
  expandedContent: PropTypes.any,
  // Set the expanded content state from outside the table.
  expandedContentExpanded: PropTypes.bool,
  // Extra data that can be used when ordering, sorting etc.
  extraData: PropTypes.any,
  // The extra classes to apply to all header columns.
  headerColumnClasses: PropTypes.array,
  // Whether this is a header row.
  isHeader: PropTypes.bool,
  // A URL to navigate to when a row is clicked.
  onClick: PropTypes.func,
Example #8
0
            </li>
          )
        })}
      </ul>
      {/*
              This links to a page that does not yet exist.
              We'll come back to it!
            */}
      <Link to="/tags">All tags</Link>
    </div>
  )
}

Tags.propTypes = {
  pageContext: PropTypes.shape({
    tag: PropTypes.string.isRequired,
  }),
  data: PropTypes.shape({
    allMarkdownRemark: PropTypes.shape({
      totalCount: PropTypes.number.isRequired,
      edges: PropTypes.arrayOf(
        PropTypes.shape({
          node: PropTypes.shape({
            frontmatter: PropTypes.shape({
              title: PropTypes.string.isRequired,
            }),
            fields: PropTypes.shape({
              slug: PropTypes.string.isRequired,
            }),
          }),
        }).isRequired
Example #9
0
            .attr("height", function (d) { return d.height + 2 * labelPadding; });

        chart.append('g')// 输出标题
            .attr('class', 'line-title')
            .append('text')
            .attr('fill', '#000')
            .attr('font-weight', '700')
            .attr("transform", "translate(" + (width / 2 + margin.left) + "," + 20 + ")")
            .attr('text-anchor', 'middle')
            .attr('x', 0)
            .attr('y', 0)
            .text('最近几年XX本地年产苹果香蕉数量');      
    }
    render() {
        return (
            <div className="line-chart--simple">
                <svg ref={(r) => this.chartRef = r}></svg>
            </div>
        )
    }
}
D3SimpleLineChart.propTypes = {
  data: PropTypes.arrayOf(PropTypes.shape({
    date:PropTypes.string.isRequired,
    apple:PropTypes.number.isRequired,
    banana:PropTypes.number.isRequired
  }).isRequired).isRequired,
}


export default D3SimpleLineChart;
Example #10
0
)

const normaliseSpecies = mapProps(
	props => Object.assign({}, props, {species: props.species.toLowerCase().replace(/ +/, `_`)})
)

const addDefaultCallbacks = defaultProps({
    onMouseOver: () => {},
    onMouseOut: () => {},
    onClick: () => {}
})

const definePropTypes = setPropTypes({
  atlasUrl: PropTypes.string.isRequired,
	species: PropTypes.string.isRequired,
	idsWithMarkup: PropTypes.arrayOf(PropTypes.shape({
		id: PropTypes.string.isRequired,
		markupNormal: PropTypes.object.isRequired,
		markupUnderFocus: PropTypes.object.isRequired
	})).isRequired,
	onMouseOver: PropTypes.func.isRequired,
	onMouseOut: PropTypes.func.isRequired,
	onClick: PropTypes.func.isRequired
})

const defineDefaultProps = defaultProps({
  atlasUrl: `https://www.ebi.ac.uk/gxa/`
})

export default compose(addColoringScheme, onlyUpdateForPropTypes, definePropTypes, defineDefaultProps, addDefaultCallbacks, normaliseSpecies)(Anatomogram)
Example #11
0
  fontSize: '12px',
  color: '#555',
});

const BooleanType = ({ knob, onChange }) => (
  <Input
    id={knob.name}
    type="checkbox"
    onChange={e => onChange(e.target.checked)}
    checked={knob.value}
  />
);

BooleanType.defaultProps = {
  knob: {},
  onChange: value => value,
};

BooleanType.propTypes = {
  knob: PropTypes.shape({
    name: PropTypes.string,
    value: PropTypes.bool,
  }),
  onChange: PropTypes.func,
};

BooleanType.serialize = value => (value ? String(value) : null);
BooleanType.deserialize = value => value === 'true';

export default BooleanType;
Example #12
0
      <div style={styles.article}>
        <div style={styles.title}>{article.title}</div>
        <div style={styles.date}>
          {dateDisplay(article.date)}
        </div>
        <div style={styles.author}>
          <a href={author.website}>
            {author.firstName} {author.lastName}
          </a>
        </div>
        <div style={styles.body}>{article.body}</div>
      </div>
    );
  }
}

Article.propTypes = {
  article: PropTypes.shape({
    title: PropTypes.string.isRequired,
    body: PropTypes.string.isRequired,
    date: PropTypes.string.isRequired,
  })
};

function extraProps(store, originalProps) {
  return {
    author: store.lookupAuthor(originalProps.article.authorId),
  };
}

export default storeProvider(extraProps)(Article);
            </text>
            <text
                className={ valueClassName }
                x={ half }
                y="60%"
                textAnchor="middle">
                { formatValues(value, total) }
            </text>
        </g>;
    }
}

DonutInnerText.propTypes = {
    item: PropTypes.shape({
        value: PropTypes.number.isRequired,
        label: PropTypes.string.isRequired,
        className: PropTypes.string,
        isEmpty: PropTypes.boolean
    }).isRequired,
    className: PropTypes.string,
    total: PropTypes.number,
    width: PropTypes.number,
    formatValues: PropTypes.func
};

DonutInnerText.defaultProps = {
    item: {
        label: '',
        value: 100,
        isEmpty: true
    },
    total: 100,
Example #14
0
        direction="row"
        justify="space-between"
        alignItems="center"
        className={classes.heroContentGrid}
      >
        <HeroTitleGrid>
          <HeroTitle>Discover the stories behind the data.</HeroTitle>

          <HeroDescription>
            Dominion makes data available to help add context and authority to
            public discourse and policy-making on vital issues of land
            ownership.
          </HeroDescription>

          <HeroButton onClick={toggleModal('portal')}>
            Select a Country
          </HeroButton>
        </HeroTitleGrid>
        <HomeHeroMap />
      </Grid>
    </Hero>
  );
}

HomeHero.propTypes = {
  classes: PropTypes.shape({}).isRequired,
  toggleModal: PropTypes.func.isRequired
};

export default withStyles(styles)(HomeHero);
Example #15
0
 * Copyright (C) 2017 - present Instructure, Inc.
 *
 * This file is part of Canvas.
 *
 * Canvas is free software: you can redistribute it and/or modify it under
 * the terms of the GNU Affero General Public License as published by the Free
 * Software Foundation, version 3 of the License.
 *
 * Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
 * A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
 * details.
 *
 * You should have received a copy of the GNU Affero General Public License along
 * with this program. If not, see <http://www.gnu.org/licenses/>.
 */

import { shape, arrayOf, string, number } from 'prop-types'

const propTypes = {}

propTypes.section = shape({
  id: string.isRequired,
  name: string.isRequired,
  user_count: number
})

propTypes.sectionList = arrayOf(propTypes.section)

export default propTypes
import PropTypes from 'prop-types';
import React from 'react';
import cn from 'classnames';
import { prefix, bsClass, splitBsProps } from './utils/bootstrapUtils';

const contextTypes = {
  $bs_panel: PropTypes.shape({
    bsClass: PropTypes.string
  })
};

class PanelFooter extends React.Component {
  render() {
    let { children, className } = this.props;
    let { bsClass: _bsClass } = this.context.$bs_panel || {};

    const [bsProps, elementProps] = splitBsProps(this.props);
    bsProps.bsClass = _bsClass || bsProps.bsClass;

    return (
      <div
        {...elementProps}
        className={cn(className, prefix(bsProps, 'footer'))}
      >
        {children}
      </div>
    );
  }
}

PanelFooter.contextTypes = contextTypes;
Example #17
0
        onClick: function onClick(event) {
          return _this.handleClick(event, context.history);
        },
        href: href,
        ref: innerRef
      }));
    });
  };

  return Link;
}(React.Component);

if (process.env.NODE_ENV !== "production") {
  var toType = PropTypes.oneOfType([PropTypes.string, PropTypes.object]);
  var innerRefType = PropTypes.oneOfType([PropTypes.string, PropTypes.func, PropTypes.shape({
    current: PropTypes.any
  })]);
  Link.propTypes = {
    innerRef: innerRefType,
    onClick: PropTypes.func,
    replace: PropTypes.bool,
    target: PropTypes.string,
    to: toType.isRequired
  };
}

function joinClassnames() {
  for (var _len = arguments.length, classnames = new Array(_len), _key = 0; _key < _len; _key++) {
    classnames[_key] = arguments[_key];
  }
          tabIndex="0"
          onClick={onClick}
          disabled={disabled}
        />
      </p>
    </div>
  );
}

if (process.env.NODE_ENV !== "production") {
  ArrayField.propTypes = {
    schema: PropTypes.object.isRequired,
    uiSchema: PropTypes.shape({
      "ui:options": PropTypes.shape({
        addable: PropTypes.bool,
        orderable: PropTypes.bool,
        removable: PropTypes.bool,
      }),
    }),
    idSchema: PropTypes.object,
    errorSchema: PropTypes.object,
    onChange: PropTypes.func.isRequired,
    onBlur: PropTypes.func,
    onFocus: PropTypes.func,
    formData: PropTypes.array,
    required: PropTypes.bool,
    disabled: PropTypes.bool,
    readonly: PropTypes.bool,
    autofocus: PropTypes.bool,
    registry: PropTypes.shape({
      widgets: PropTypes.objectOf(
Example #19
0
import center from '@turf/center';
import StyleSwitcher from './style-switcher';
import MapTaskPopover from './map-task-popover';
import { addMapControls } from '../utils/map';
import { setMapSize } from '../actions/map-actions';
import { setMapBaseLayer } from '../actions';
import { taskPolygons, taskPolygonsHighlight, taskStatusStyles }
  from '../utils/styleManager';

export const RequestMap = React.createClass({
  propTypes: {
    style: PropTypes.object.isRequired,
    className: PropTypes.string,
    baseLayers: PropTypes.array.isRequired,
    baseLayer: PropTypes.shape({
      id: PropTypes.string.isRequired,
      name: PropTypes.string.isRequired
    }).isRequired,
    setMapSize: PropTypes.func.isRequired,
    setMapBaseLayer: PropTypes.func.isRequired
  },

  componentDidMount: function () {
    this.map = new mapboxgl.Map({
      container: this.mapDiv,
      style: this.props.style
    });
    this.map.on('mousemove', (event) => {
      if (!this.map.getLayer(taskPolygons)) {
        return;
      }
      const features = this.map
  return {
    parentBlock,
    isInfo,
    paneTitle,
    statePopoutFlag,
  };
};

const mapDispatchToProps = dispatch => ({
  setIsPopout: () => {
    dispatch(flagAsPopout());
  },
});

MalcolmPopOut.propTypes = {
  paneTitle: PropTypes.string.isRequired,
  classes: PropTypes.shape({
    container: PropTypes.string,
    toolbar: PropTypes.string,
    title: PropTypes.string,
  }).isRequired,
  isInfo: PropTypes.bool.isRequired,
  setIsPopout: PropTypes.func.isRequired,
  statePopoutFlag: PropTypes.bool.isRequired,
};

export default withStyles(styles, { withTheme: true })(
  connect(mapStateToProps, mapDispatchToProps)(MalcolmPopOut)
);
Example #21
0
			label={action.label}
			icon={action.icon}
			onClick={onClick}
			disabled={action.disabled}
			tooltipPlacement="bottom"
			inProgress={action.inProgress}
			hideLabel
			link
		/>
	);
}

function HeaderSelected({ headerSelected, nbItemsSelected }) {
	let txtHeader = `${nbItemsSelected} selected value`;
	txtHeader = nbItemsSelected > 1 ? `${txtHeader}s` : txtHeader;

	return (
		<header className={headerClasses()}>
			<span>{txtHeader}</span>
			{headerSelected.map(getAction)}
		</header>
	);
}

HeaderSelected.propTypes = {
	headerSelected: PropTypes.arrayOf(PropTypes.shape(Action.propTypes)).isRequired,
	nbItemsSelected: PropTypes.number,
};

export default HeaderSelected;
Example #22
0
import type {ImageProps as ImagePropsType} from 'ImageProps';

let _requestId = 1;
function generateRequestId() {
  return _requestId++;
}

const ImageProps = {
  ...DeprecatedViewPropTypes,
  style: DeprecatedStyleSheetPropType(DeprecatedImageStylePropTypes),
  /**
   * See https://facebook.github.io/react-native/docs/image.html#source
   */
  source: PropTypes.oneOfType([
    PropTypes.shape({
      uri: PropTypes.string,
      headers: PropTypes.objectOf(PropTypes.string),
    }),
    // Opaque type returned by require('./image.jpg')
    PropTypes.number,
    // Multiple sources
    PropTypes.arrayOf(
      PropTypes.shape({
        uri: PropTypes.string,
        width: PropTypes.number,
        height: PropTypes.number,
        headers: PropTypes.objectOf(PropTypes.string),
      }),
    ),
  ]),
  /**
   * blurRadius: the blur radius of the blur filter added to the image
Example #23
0
			);
		}
	}]);
	return Lightbox;
}(Component);

Lightbox.propTypes = {
	backdropClosesModal: PropTypes.bool,
	closeButtonTitle: PropTypes.string,
	currentImage: PropTypes.number,
	customControls: PropTypes.arrayOf(PropTypes.node),
	enableKeyboardInput: PropTypes.bool,
	imageCountSeparator: PropTypes.string,
	images: PropTypes.arrayOf(PropTypes.shape({
		src: PropTypes.string.isRequired,
		srcSet: PropTypes.array,
		caption: PropTypes.oneOfType([PropTypes.string, PropTypes.element]),
		thumbnail: PropTypes.string
	})).isRequired,
	isOpen: PropTypes.bool,
	leftArrowTitle: PropTypes.string,
	onClickImage: PropTypes.func,
	onClickNext: PropTypes.func,
	onClickPrev: PropTypes.func,
	onClose: PropTypes.func.isRequired,
	preloadNextImage: PropTypes.bool,
	preventScroll: PropTypes.bool,
	rightArrowTitle: PropTypes.string,
	showCloseButton: PropTypes.bool,
	showImageCount: PropTypes.bool,
	showThumbnails: PropTypes.bool,
	spinner: PropTypes.func,
const PropTypes = require('prop-types');
const ReactNative = require('../../Renderer/shims/ReactNative');
const Touchable = require('./Touchable');
const TouchableWithoutFeedback = require('./TouchableWithoutFeedback');
const UIManager = require('../../ReactNative/UIManager');
const View = require('../View/View');

const createReactClass = require('create-react-class');
const ensurePositiveDelayProps = require('./ensurePositiveDelayProps');
const processColor = require('../../StyleSheet/processColor');

import type {PressEvent} from '../../Types/CoreEventTypes';

const rippleBackgroundPropType = PropTypes.shape({
  type: PropTypes.oneOf(['RippleAndroid']),
  color: PropTypes.number,
  borderless: PropTypes.bool,
});

const themeAttributeBackgroundPropType = PropTypes.shape({
  type: PropTypes.oneOf(['ThemeAttrAndroid']),
  attribute: PropTypes.string.isRequired,
});

const backgroundPropType = PropTypes.oneOfType([
  rippleBackgroundPropType,
  themeAttributeBackgroundPropType,
]);

const PRESS_RETENTION_OFFSET = {top: 20, left: 20, right: 20, bottom: 30};
Example #25
0
/* eslint-enable no-unused-vars */

const UserCell = ({ user, align, left, small }) => (
  <div>
    <UserCellWrapper align={align} left={left}>
      <Avatar src={user.avatar} alt={user.nickname} small={small} />
      <NickName>{user.nickname}</NickName>
    </UserCellWrapper>
  </div>
)

UserCell.propTypes = {
  // https://www.npmjs.com/package/prop-types
  user: PropTypes.shape({
    id: PropTypes.string,
    avatar: PropTypes.string,
    nickname: PropTypes.string,
  }).isRequired,
  align: PropTypes.string,
  left: PropTypes.string,
  small: PropTypes.bool,
}

UserCell.defaultProps = {
  align: 'left',
  left: '10px',
  small: false,
}

export default UserCell
Example #26
0
        {hasSuspectedWords(actions) && (
          <FlagLabel iconName="sms_failed">
            {t('flags.reasons.comment.suspect_word')}
          </FlagLabel>
        )}
        {hasHistoryFlag(actions) && (
          <FlagLabel iconName="sentiment_very_dissatisfied">
            {t('flags.reasons.comment.trust')}
          </FlagLabel>
        )}
      </div>
      <Slot
        className={styles.slot}
        fill="adminCommentLabels"
        passthrough={slotPassthrough}
      />
    </div>
  );
};

CommentLabels.propTypes = {
  comment: PropTypes.shape({
    className: PropTypes.string,
    status: PropTypes.string,
    actions: PropTypes.array,
    hasParent: PropTypes.bool,
  }),
};

export default CommentLabels;
Example #27
0
/* global graphql */
import React, { Fragment } from 'react';
import PropTypes from 'prop-types';
import Helmet from 'react-helmet';

import FullWidthRow from '../../components/util/FullWidthRow';
import { MarkdownRemark } from '../../redux/propTypes';

const propTypes = {
  data: PropTypes.shape({
    markdownRemark: MarkdownRemark
  })
};

function SuperBlockIntroductionPage({ data: { markdownRemark } }) {
  const { html, frontmatter: { superBlock } } = markdownRemark;
  return (
    <Fragment>
      <Helmet>
        <title>{superBlock} | freeCodeCamp</title>
      </Helmet>
      <FullWidthRow>
        <div
          className='intro-layout'
          dangerouslySetInnerHTML={{ __html: html }}
        />
      </FullWidthRow>
    </Fragment>
  );
}
Example #28
0
    />
    <link rel="manifest" href={'/meta/manifest.json'} />
    <link
      rel="mask-icon"
      href={'/meta/safari-pinned-tab.svg'}
      color="#5bbad5"
    />
    <meta name="theme-color" content="#ffffff" />
  </Helmet>
)

MetaTags.propTypes = {
  title: PropTypes.string.isRequired,
  description: PropTypes.string.isRequired,
  twitter: PropTypes.string,
  updateTime: PropTypes.string,
  previewImage: PropTypes.shape({
    url: PropTypes.string.isRequired,
    alt: PropTypes.string.isRequired
  }),
  url: PropTypes.string,
  type: PropTypes.string,
  author: PropTypes.string
}

MetaTags.defaultProps = {
  type: 'website'
}

export default MetaTags
Example #29
0
  /**
   * The width of the left most (or right most) area in pixels where the
   * drawer can be swiped open from.
   */
  swipeAreaWidth: PropTypes.number,
  /**
   * @ignore
   */
  theme: PropTypes.object.isRequired,
  /**
   * The duration for the transition, in milliseconds.
   * You may specify a single timeout for all transitions, or individually with an object.
   */
  transitionDuration: PropTypes.oneOfType([
    PropTypes.number,
    PropTypes.shape({ enter: PropTypes.number, exit: PropTypes.number }),
  ]),
  /**
   * @ignore
   */
  variant: PropTypes.oneOf(['permanent', 'persistent', 'temporary']),
};

SwipeableDrawer.defaultProps = {
  anchor: 'left',
  disableBackdropTransition: false,
  disableDiscovery: false,
  disableSwipeToOpen:
    typeof navigator !== 'undefined' && /iPad|iPhone|iPod/.test(navigator.userAgent),
  swipeAreaWidth: 20,
  transitionDuration: { enter: duration.enteringScreen, exit: duration.leavingScreen },
  console.log(imageInfo);
  const imageStyle = { borderRadius: '5px' }
  const { alt = '', childImageSharp, image } = imageInfo

  if (!!image && !!image.childImageSharp) {
    return (
      <Img style={imageStyle} fluid={image.childImageSharp.fluid} alt={alt} />
    )
  }

  if (!!childImageSharp) {
    return <Img style={imageStyle} fluid={childImageSharp.fluid} alt={alt} />
  }

  if (!!image && typeof image === 'string')
    return <img style={imageStyle} src={image} alt={alt} />

  return null
}

PreviewCompatibleImage.propTypes = {
  imageInfo: PropTypes.shape({
    alt: PropTypes.string,
    childImageSharp: PropTypes.object,
    image: PropTypes.oneOfType([PropTypes.object, PropTypes.string]).isRequired,
    style: PropTypes.object,
  }).isRequired,
}

export default PreviewCompatibleImage