content: function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
  
  function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; var ownKeys = Object.keys(source); if (typeof Object.getOwnPropertySymbols === 'function') { ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function (sym) { return Object.getOwnPropertyDescriptor(source, sym).enumerable; })); } ownKeys.forEach(function (key) { _defineProperty(target, key, source[key]); }); } return target; }
  
  function _defineProperty(obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
  
  function _objectWithoutPropertiesLoose(source, excluded) { if (source == null) return {}; var target = {}; var sourceKeys = Object.keys(source); var key, i; for (i = 0; i < sourceKeys.length; i++) { key = sourceKeys[i]; if (excluded.indexOf(key) >= 0) continue; target[key] = source[key]; } return target; }
  
  function _inheritsLoose(subClass, superClass) { subClass.prototype = Object.create(superClass.prototype); subClass.prototype.constructor = subClass; subClass.__proto__ = superClass; }
  
  /**
   * Copyright (c) Nicolas Gallagher.
   * Copyright (c) Facebook, Inc. and its affiliates.
   *
   * This source code is licensed under the MIT license found in the
   * LICENSE file in the root directory of this source tree.
   *
   * 
   */
  import applyNativeMethods from '../../modules/applyNativeMethods';
  import createElement from '../createElement';
  import css from '../StyleSheet/css';
  import { getAssetByID } from '../../modules/AssetRegistry';
  import resolveShadowValue from '../StyleSheet/resolveShadowValue';
  import ImageLoader from '../../modules/ImageLoader';
  import ImageResizeMode from './ImageResizeMode';
  import ImageSourcePropType from './ImageSourcePropType';
  import ImageStylePropTypes from './ImageStylePropTypes';
  import ImageUriCache from './ImageUriCache';
  import StyleSheet from '../StyleSheet';
  import StyleSheetPropType from '../../modules/StyleSheetPropType';
  import View from '../View';
  import ViewPropTypes from '../ViewPropTypes';
  import { bool, func, number, oneOf, shape } from 'prop-types';
  import React, { Component } from 'react';
  var emptyObject = {};
  var STATUS_ERRORED = 'ERRORED';
  var STATUS_LOADED = 'LOADED';
  var STATUS_LOADING = 'LOADING';
  var STATUS_PENDING = 'PENDING';
  var STATUS_IDLE = 'IDLE';
  
  var getImageState = function getImageState(uri, shouldDisplaySource) {
    return shouldDisplaySource ? STATUS_LOADED : uri ? STATUS_PENDING : STATUS_IDLE;
  };
  
  var resolveAssetDimensions = function resolveAssetDimensions(source) {
    if (typeof source === 'number') {
      var _getAssetByID = getAssetByID(source),
          height = _getAssetByID.height,
          width = _getAssetByID.width;
  
      return {
        height: height,
        width: width
      };
    } else if (typeof source === 'object') {
      var _height = source.height,
          _width = source.width;
      return {
        height: _height,
        width: _width
      };
    }
  };
  
  var svgDataUriPattern = /^(data:image\/svg\+xml;utf8,)(.*)/;
  
  var resolveAssetUri = function resolveAssetUri(source) {
    var uri = '';
  
    if (typeof source === 'number') {
      // get the URI from the packager
      var asset = getAssetByID(source);
      var scale = asset.scales[0];
      var scaleSuffix = scale !== 1 ? "@" + scale + "x" : '';
      uri = asset ? asset.httpServerLocation + "/" + asset.name + scaleSuffix + "." + asset.type : '';
    } else if (typeof source === 'string') {
      uri = source;
    } else if (source && typeof source.uri === 'string') {
      uri = source.uri;
    }
  
    if (uri) {
      var match = uri.match(svgDataUriPattern); // inline SVG markup may contain characters (e.g., #, ") that need to be escaped
  
      if (match) {
        var prefix = match[1],
            svg = match[2];
        var encodedSvg = encodeURIComponent(svg);
        return "" + prefix + encodedSvg;
      }
    }
  
    return uri;
  };
  
  var filterId = 0;
  
  var createTintColorSVG = function createTintColorSVG(tintColor, id) {
    return tintColor && id != null ? React.createElement("svg", {
      style: {
        position: 'absolute',
        height: 0,
        visibility: 'hidden',
        width: 0
      }
    }, React.createElement("defs", null, React.createElement("filter", {
      id: "tint-" + id
    }, React.createElement("feFlood", {
      floodColor: "" + tintColor
    }), React.createElement("feComposite", {
      in2: "SourceAlpha",
      operator: "atop"
    })))) : null;
  };
  
  var Image =
  /*#__PURE__*/
  function (_Component) {
    _inheritsLoose(Image, _Component);
  
    Image.getSize = function getSize(uri, success, failure) {
      ImageLoader.getSize(uri, success, failure);
    };
  
    Image.prefetch = function prefetch(uri) {
      return ImageLoader.prefetch(uri).then(function () {
        // Add the uri to the cache so it can be immediately displayed when used
        // but also immediately remove it to correctly reflect that it has no active references
        ImageUriCache.add(uri);
        ImageUriCache.remove(uri);
      });
    };
  
    Image.queryCache = function queryCache(uris) {
      var result = {};
      uris.forEach(function (u) {
        if (ImageUriCache.has(u)) {
          result[u] = 'disk/memory';
        }
      });
      return Promise.resolve(result);
    };
  
    function Image(props, context) {
      var _this;
  
      _this = _Component.call(this, props, context) || this; // If an image has been loaded before, render it immediately
  
      _this._filterId = 0;
      _this._imageRef = null;
      _this._imageRequestId = null;
      _this._imageState = null;
      _this._isMounted = false;
  
      _this._createLayoutHandler = function (resizeMode) {
        var onLayout = _this.props.onLayout;
  
        if (resizeMode === 'center' || resizeMode === 'repeat' || onLayout) {
          return function (e) {
            var layout = e.nativeEvent.layout;
            onLayout && onLayout(e);
  
            _this.setState(function () {
              return {
                layout: layout
              };
            });
          };
        }
      };
  
      _this._getBackgroundSize = function (resizeMode) {
        if (_this._imageRef && (resizeMode === 'center' || resizeMode === 'repeat')) {
          var _this$_imageRef = _this._imageRef,
              naturalHeight = _this$_imageRef.naturalHeight,
              naturalWidth = _this$_imageRef.naturalWidth;
          var _this$state$layout = _this.state.layout,
              height = _this$state$layout.height,
              width = _this$state$layout.width;
  
          if (naturalHeight && naturalWidth && height && width) {
            var scaleFactor = Math.min(1, width / naturalWidth, height / naturalHeight);
            var x = Math.ceil(scaleFactor * naturalWidth);
            var y = Math.ceil(scaleFactor * naturalHeight);
            return {
              backgroundSize: x + "px " + y + "px"
            };
          }
        }
      };
  
      _this._onError = function () {
        var _this$props = _this.props,
            onError = _this$props.onError,
            source = _this$props.source;
  
        _this._updateImageState(STATUS_ERRORED);
  
        if (onError) {
          onError({
            nativeEvent: {
              error: "Failed to load resource " + resolveAssetUri(source) + " (404)"
            }
          });
        }
  
        _this._onLoadEnd();
      };
  
      _this._onLoad = function (e) {
        var _this$props2 = _this.props,
            onLoad = _this$props2.onLoad,
            source = _this$props2.source;
        var event = {
          nativeEvent: e
        };
        ImageUriCache.add(resolveAssetUri(source));
  
        _this._updateImageState(STATUS_LOADED);
  
        if (onLoad) {
          onLoad(event);
        }
  
        _this._onLoadEnd();
      };
  
      _this._setImageRef = function (ref) {
        _this._imageRef = ref;
      };
  
      var uri = resolveAssetUri(props.source);
      var shouldDisplaySource = ImageUriCache.has(uri);
      _this.state = {
        layout: {},
        shouldDisplaySource: shouldDisplaySource
      };
      _this._imageState = getImageState(uri, shouldDisplaySource);
      _this._filterId = filterId;
      filterId++;
      return _this;
    }
  
    var _proto = Image.prototype;
  
    _proto.componentDidMount = function componentDidMount() {
      this._isMounted = true;
  
      if (this._imageState === STATUS_PENDING) {
        this._createImageLoader();
      } else if (this._imageState === STATUS_LOADED) {
        this._onLoad({
          target: this._imageRef
        });
      }
    };
  
    _proto.componentDidUpdate = function componentDidUpdate(prevProps) {
      var prevUri = resolveAssetUri(prevProps.source);
      var uri = resolveAssetUri(this.props.source);
      var hasDefaultSource = this.props.defaultSource != null;
  
      if (prevUri !== uri) {
        ImageUriCache.remove(prevUri);
        var isPreviouslyLoaded = ImageUriCache.has(uri);
        isPreviouslyLoaded && ImageUriCache.add(uri);
  
        this._updateImageState(getImageState(uri, isPreviouslyLoaded), hasDefaultSource);
      } else if (hasDefaultSource && prevProps.defaultSource !== this.props.defaultSource) {
        this._updateImageState(this._imageState, hasDefaultSource);
      }
  
      if (this._imageState === STATUS_PENDING) {
        this._createImageLoader();
      }
    };
  
    _proto.componentWillUnmount = function componentWillUnmount() {
      var uri = resolveAssetUri(this.props.source);
      ImageUriCache.remove(uri);
  
      this._destroyImageLoader();
  
      this._isMounted = false;
    };
  
    _proto.render = function render() {
      var shouldDisplaySource = this.state.shouldDisplaySource;
  
      var _this$props3 = this.props,
          accessibilityLabel = _this$props3.accessibilityLabel,
          accessible = _this$props3.accessible,
          blurRadius = _this$props3.blurRadius,
          defaultSource = _this$props3.defaultSource,
          draggable = _this$props3.draggable,
          source = _this$props3.source,
          testID = _this$props3.testID,
          capInsets = _this$props3.capInsets,
          onError = _this$props3.onError,
          onLayout = _this$props3.onLayout,
          onLoad = _this$props3.onLoad,
          onLoadEnd = _this$props3.onLoadEnd,
          onLoadStart = _this$props3.onLoadStart,
          resizeMethod = _this$props3.resizeMethod,
          resizeMode = _this$props3.resizeMode,
          other = _objectWithoutPropertiesLoose(_this$props3, ["accessibilityLabel", "accessible", "blurRadius", "defaultSource", "draggable", "source", "testID", "capInsets", "onError", "onLayout", "onLoad", "onLoadEnd", "onLoadStart", "resizeMethod", "resizeMode"]);
  
      if (process.env.NODE_ENV !== 'production') {
        if (this.props.src) {
          console.warn('The <Image> component requires a `source` property rather than `src`.');
        }
  
        if (this.props.children) {
          throw new Error('The <Image> component cannot contain children. If you want to render content on top of the image, consider using the <ImageBackground> component or absolute positioning.');
        }
      }
  
      var selectedSource = shouldDisplaySource ? source : defaultSource;
      var displayImageUri = resolveAssetUri(selectedSource);
      var imageSizeStyle = resolveAssetDimensions(selectedSource);
      var backgroundImage = displayImageUri ? "url(\"" + displayImageUri + "\")" : null;
  
      var flatStyle = _objectSpread({}, StyleSheet.flatten(this.props.style));
  
      var finalResizeMode = resizeMode || flatStyle.resizeMode || ImageResizeMode.cover; // CSS filters
  
      var filters = [];
      var tintColor = flatStyle.tintColor;
  
      if (flatStyle.filter) {
        filters.push(flatStyle.filter);
      }
  
      if (blurRadius) {
        filters.push("blur(" + blurRadius + "px)");
      }
  
      if (flatStyle.shadowOffset) {
        var shadowString = resolveShadowValue(flatStyle);
  
        if (shadowString) {
          filters.push("drop-shadow(" + shadowString + ")");
        }
      }
  
      if (flatStyle.tintColor) {
        filters.push("url(#tint-" + this._filterId + ")");
      } // these styles were converted to filters
  
  
      delete flatStyle.shadowColor;
      delete flatStyle.shadowOpacity;
      delete flatStyle.shadowOffset;
      delete flatStyle.shadowRadius;
      delete flatStyle.tintColor; // these styles are not supported on View
  
      delete flatStyle.overlayColor;
      delete flatStyle.resizeMode; // Accessibility image allows users to trigger the browser's image context menu
  
      var hiddenImage = displayImageUri ? createElement('img', {
        alt: accessibilityLabel || '',
        classList: [classes.accessibilityImage],
        draggable: draggable || false,
        ref: this._setImageRef,
        src: displayImageUri
      }) : null;
      return React.createElement(View, _extends({}, other, {
        accessibilityLabel: accessibilityLabel,
        accessible: accessible,
        onLayout: this._createLayoutHandler(finalResizeMode),
        style: [styles.root, this.context.isInAParentText && styles.inline, imageSizeStyle, flatStyle],
        testID: testID
      }), React.createElement(View, {
        style: [styles.image, resizeModeStyles[finalResizeMode], this._getBackgroundSize(finalResizeMode), backgroundImage && {
          backgroundImage: backgroundImage
        }, filters.length > 0 && {
          filter: filters.join(' ')
        }]
      }), hiddenImage, createTintColorSVG(tintColor, this._filterId));
    };
  
    _proto._createImageLoader = function _createImageLoader() {
      var source = this.props.source;
  
      this._destroyImageLoader();
  
      var uri = resolveAssetUri(source);
      this._imageRequestId = ImageLoader.load(uri, this._onLoad, this._onError);
  
      this._onLoadStart();
    };
  
    _proto._destroyImageLoader = function _destroyImageLoader() {
      if (this._imageRequestId) {
        ImageLoader.abort(this._imageRequestId);
        this._imageRequestId = null;
      }
    };
  
    _proto._onLoadEnd = function _onLoadEnd() {
      var onLoadEnd = this.props.onLoadEnd;
  
      if (onLoadEnd) {
        onLoadEnd();
      }
    };
  
    _proto._onLoadStart = function _onLoadStart() {
      var _this$props4 = this.props,
          defaultSource = _this$props4.defaultSource,
          onLoadStart = _this$props4.onLoadStart;
  
      this._updateImageState(STATUS_LOADING, defaultSource != null);
  
      if (onLoadStart) {
        onLoadStart();
      }
    };
  
    _proto._updateImageState = function _updateImageState(status, hasDefaultSource) {
      if (hasDefaultSource === void 0) {
        hasDefaultSource = false;
      }
  
      this._imageState = status;
      var shouldDisplaySource = this._imageState === STATUS_LOADED || this._imageState === STATUS_LOADING && !hasDefaultSource; // only triggers a re-render when the image is loading and has no default image (to support PJPEG), loaded, or failed
  
      if (shouldDisplaySource !== this.state.shouldDisplaySource) {
        if (this._isMounted) {
          this.setState(function () {
            return {
              shouldDisplaySource: shouldDisplaySource
            };
          });
        }
      }
    };
  
    return Image;
  }(Component);
  
  Image.displayName = 'Image';
  Image.contextTypes = {
    isInAParentText: bool
  };
  Image.defaultProps = {
    style: emptyObject
  };
  Image.propTypes = process.env.NODE_ENV !== "production" ? _objectSpread({}, ViewPropTypes, {
    blurRadius: number,
    defaultSource: ImageSourcePropType,
    draggable: bool,
    onError: func,
    onLayout: func,
    onLoad: func,
    onLoadEnd: func,
    onLoadStart: func,
    resizeMode: oneOf(Object.keys(ImageResizeMode)),
    source: ImageSourcePropType,
    style: StyleSheetPropType(ImageStylePropTypes),
    // compatibility with React Native
  
    /* eslint-disable react/sort-prop-types */
    capInsets: shape({
      top: number,
      left: number,
      bottom: number,
      right: number
    }),
    resizeMethod: oneOf(['auto', 'resize', 'scale'])
    /* eslint-enable react/sort-prop-types */
  
  }) : {};
  var classes = css.create({
    accessibilityImage: _objectSpread({}, StyleSheet.absoluteFillObject, {
      height: '100%',
      opacity: 0,
      width: '100%',
      zIndex: -1
    })
  });
  var styles = StyleSheet.create({
    root: {
      flexBasis: 'auto',
      overflow: 'hidden',
      zIndex: 0
    },
    inline: {
      display: 'inline-flex'
    },
    image: _objectSpread({}, StyleSheet.absoluteFillObject, {
      backgroundColor: 'transparent',
      backgroundPosition: 'center',
      backgroundRepeat: 'no-repeat',
      backgroundSize: 'cover',
      height: '100%',
      width: '100%',
      zIndex: -1
    })
  });
  var resizeModeStyles = StyleSheet.create({
    center: {
      backgroundSize: 'auto'
    },
    contain: {
      backgroundSize: 'contain'
    },
    cover: {
      backgroundSize: 'cover'
    },
    none: {
      backgroundPosition: '0 0',
      backgroundSize: 'auto'
    },
    repeat: {
      backgroundPosition: '0 0',
      backgroundRepeat: 'repeat',
      backgroundSize: 'auto'
    },
    stretch: {
      backgroundSize: '100% 100%'
    }
  });
  export default applyNativeMethods(Image);