@fountain-ui/core 2.0.0-beta.36 → 2.0.0-beta.37

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,7 +5,7 @@ Object.defineProperty(exports, "__esModule", {
5
5
  });
6
6
  exports.default = Image;
7
7
 
8
- var _react = _interopRequireDefault(require("react"));
8
+ var _react = _interopRequireWildcard(require("react"));
9
9
 
10
10
  var _reactNative = require("react-native");
11
11
 
@@ -15,6 +15,10 @@ var _styles = require("../styles");
15
15
 
16
16
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
17
 
18
+ function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
19
+
20
+ function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
21
+
18
22
  function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); }
19
23
 
20
24
  const useStyles = function () {
@@ -50,6 +54,7 @@ function Image(props) {
50
54
  size,
51
55
  onLoad,
52
56
  onError,
57
+ Placeholder: PlaceholderComponent,
53
58
  ...otherProps
54
59
  } = props;
55
60
 
@@ -65,12 +70,28 @@ function Image(props) {
65
70
  setFailed(true);
66
71
  };
67
72
 
73
+ const Placeholder = _ref => {
74
+ let {
75
+ failed,
76
+ children
77
+ } = _ref;
78
+ return PlaceholderComponent ? /*#__PURE__*/_react.default.createElement(PlaceholderComponent, {
79
+ children: children,
80
+ failed: failed
81
+ }) : children;
82
+ };
83
+
68
84
  const sourceWithSizeParam = { ...source,
69
85
  uri: size ? `${source.uri}?size=${size}` : source.uri
70
86
  };
87
+ (0, _react.useEffect)(() => {
88
+ setFailed(false);
89
+ }, [sourceWithSizeParam.uri]);
71
90
  return /*#__PURE__*/_react.default.createElement(_reactNative.View, _extends({
72
91
  style: (0, _styles.css)([styles.root, !disableOutline ? styles.outlined : undefined, !disablePlaceholder ? styles.placeholder : undefined, !square ? styles.rounded : undefined, style])
73
- }, otherProps), failed ? /*#__PURE__*/_react.default.createElement(_reactNative.Text, null, alt) : /*#__PURE__*/_react.default.createElement(_ImageCore.default, {
92
+ }, otherProps), /*#__PURE__*/_react.default.createElement(Placeholder, {
93
+ failed: failed
94
+ }, !failed ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_ImageCore.default, {
74
95
  alt: alt,
75
96
  height: '100%',
76
97
  loading: loading,
@@ -81,7 +102,7 @@ function Image(props) {
81
102
  width: '100%'
82
103
  }), overlaidChildren ? /*#__PURE__*/_react.default.createElement(_reactNative.View, {
83
104
  style: _styles.StyleSheet.absoluteFill
84
- }, overlaidChildren) : null);
105
+ }, overlaidChildren) : null) : null));
85
106
  }
86
107
 
87
108
  ;
@@ -1 +1 @@
1
- {"version":3,"names":["useStyles","theme","useTheme","root","rounded","borderRadius","shape","roundness","overflow","placeholder","backgroundColor","palette","paper","grey","outlined","borderWidth","StyleSheet","hairlineWidth","borderStyle","borderColor","Image","props","alt","disableOutline","disablePlaceholder","loading","overlaidChildren","resizeMode","source","style","square","size","onLoad","onError","otherProps","failed","setFailed","React","useState","styles","handleError","sourceWithSizeParam","uri","css","undefined","absoluteFill"],"sources":["Image.tsx"],"sourcesContent":["import React from 'react';\nimport { Text, View } from 'react-native';\nimport type { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport ImageCore from '../ImageCore';\nimport { css, StyleSheet, useTheme } from '../styles';\nimport type ImageProps from './ImageProps';\n\ntype ImageStyleKeys =\n | 'root'\n | 'rounded'\n | 'placeholder'\n | 'outlined';\n\ntype ImageStyles = NamedStylesStringUnion<ImageStyleKeys>;\n\nconst useStyles: UseStyles<ImageStyles> = function (): ImageStyles {\n const theme = useTheme();\n\n return {\n root: {},\n rounded: {\n borderRadius: theme.shape.roundness,\n overflow: 'hidden',\n },\n placeholder: {\n backgroundColor: theme.palette.paper.grey,\n },\n outlined: {\n borderWidth: StyleSheet.hairlineWidth,\n borderStyle: 'solid',\n borderColor: theme.palette.paper.grey,\n },\n };\n};\n\nexport default function Image(props: ImageProps) {\n const {\n alt,\n disableOutline,\n disablePlaceholder,\n loading = 'lazy',\n overlaidChildren,\n resizeMode = 'cover',\n source,\n style,\n square = false,\n size,\n onLoad,\n onError,\n ...otherProps\n } = props;\n\n const [failed, setFailed] = React.useState(false);\n\n const styles = useStyles();\n\n const handleError = () => {\n if(onError){\n onError();\n }\n\n setFailed(true);\n }\n\n const sourceWithSizeParam = {\n ...source,\n uri: size ? `${source.uri}?size=${size}` : source.uri,\n };\n\n return (\n <View\n style={css([\n styles.root,\n !disableOutline ? styles.outlined : undefined,\n !disablePlaceholder ? styles.placeholder : undefined,\n !square ? styles.rounded : undefined,\n style,\n ])}\n {...otherProps}\n >\n {failed ? (\n <Text>{alt}</Text>\n ) : (\n <ImageCore\n alt={alt}\n height={'100%'}\n loading={loading}\n onError={handleError}\n onLoad={onLoad}\n resizeMode={resizeMode}\n source={sourceWithSizeParam}\n width={'100%'}\n />\n )}\n\n {overlaidChildren ? (\n <View style={StyleSheet.absoluteFill}>\n {overlaidChildren}\n </View>\n ) : null}\n </View>\n );\n};\n"],"mappings":";;;;;;;AAAA;;AACA;;AAEA;;AACA;;;;;;AAWA,MAAMA,SAAiC,GAAG,YAAyB;EAC/D,MAAMC,KAAK,GAAG,IAAAC,gBAAA,GAAd;EAEA,OAAO;IACHC,IAAI,EAAE,EADH;IAEHC,OAAO,EAAE;MACLC,YAAY,EAAEJ,KAAK,CAACK,KAAN,CAAYC,SADrB;MAELC,QAAQ,EAAE;IAFL,CAFN;IAMHC,WAAW,EAAE;MACTC,eAAe,EAAET,KAAK,CAACU,OAAN,CAAcC,KAAd,CAAoBC;IAD5B,CANV;IASHC,QAAQ,EAAE;MACNC,WAAW,EAAEC,kBAAA,CAAWC,aADlB;MAENC,WAAW,EAAE,OAFP;MAGNC,WAAW,EAAElB,KAAK,CAACU,OAAN,CAAcC,KAAd,CAAoBC;IAH3B;EATP,CAAP;AAeH,CAlBD;;AAoBe,SAASO,KAAT,CAAeC,KAAf,EAAkC;EAC7C,MAAM;IACFC,GADE;IAEFC,cAFE;IAGFC,kBAHE;IAIFC,OAAO,GAAG,MAJR;IAKFC,gBALE;IAMFC,UAAU,GAAG,OANX;IAOFC,MAPE;IAQFC,KARE;IASFC,MAAM,GAAG,KATP;IAUFC,IAVE;IAWFC,MAXE;IAYFC,OAZE;IAaF,GAAGC;EAbD,IAcFb,KAdJ;;EAgBA,MAAM,CAACc,MAAD,EAASC,SAAT,IAAsBC,cAAA,CAAMC,QAAN,CAAe,KAAf,CAA5B;;EAEA,MAAMC,MAAM,GAAGvC,SAAS,EAAxB;;EAEA,MAAMwC,WAAW,GAAG,MAAM;IACtB,IAAGP,OAAH,EAAW;MACPA,OAAO;IACV;;IAEDG,SAAS,CAAC,IAAD,CAAT;EACH,CAND;;EAQA,MAAMK,mBAAmB,GAAG,EACxB,GAAGb,MADqB;IAExBc,GAAG,EAAEX,IAAI,GAAI,GAAEH,MAAM,CAACc,GAAI,SAAQX,IAAK,EAA9B,GAAkCH,MAAM,CAACc;EAF1B,CAA5B;EAKA,oBACI,6BAAC,iBAAD;IACI,KAAK,EAAE,IAAAC,WAAA,EAAI,CACPJ,MAAM,CAACpC,IADA,EAEP,CAACoB,cAAD,GAAkBgB,MAAM,CAACzB,QAAzB,GAAoC8B,SAF7B,EAGP,CAACpB,kBAAD,GAAsBe,MAAM,CAAC9B,WAA7B,GAA2CmC,SAHpC,EAIP,CAACd,MAAD,GAAUS,MAAM,CAACnC,OAAjB,GAA2BwC,SAJpB,EAKPf,KALO,CAAJ;EADX,GAQQK,UARR,GAUKC,MAAM,gBACH,6BAAC,iBAAD,QAAOb,GAAP,CADG,gBAGH,6BAAC,kBAAD;IACI,GAAG,EAAEA,GADT;IAEI,MAAM,EAAE,MAFZ;IAGI,OAAO,EAAEG,OAHb;IAII,OAAO,EAAEe,WAJb;IAKI,MAAM,EAAER,MALZ;IAMI,UAAU,EAAEL,UANhB;IAOI,MAAM,EAAEc,mBAPZ;IAQI,KAAK,EAAE;EARX,EAbR,EAyBKf,gBAAgB,gBACb,6BAAC,iBAAD;IAAM,KAAK,EAAEV,kBAAA,CAAW6B;EAAxB,GACKnB,gBADL,CADa,GAIb,IA7BR,CADJ;AAiCH;;AAAA"}
1
+ {"version":3,"names":["useStyles","theme","useTheme","root","rounded","borderRadius","shape","roundness","overflow","placeholder","backgroundColor","palette","paper","grey","outlined","borderWidth","StyleSheet","hairlineWidth","borderStyle","borderColor","Image","props","alt","disableOutline","disablePlaceholder","loading","overlaidChildren","resizeMode","source","style","square","size","onLoad","onError","Placeholder","PlaceholderComponent","otherProps","failed","setFailed","React","useState","styles","handleError","children","sourceWithSizeParam","uri","useEffect","css","undefined","absoluteFill"],"sources":["Image.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\nimport { View } from 'react-native';\nimport type { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport ImageCore from '../ImageCore';\nimport { css, StyleSheet, useTheme } from '../styles';\nimport type ImageProps from './ImageProps';\nimport { PlaceholderProps } from './ImageProps';\n\ntype ImageStyleKeys =\n | 'root'\n | 'rounded'\n | 'placeholder'\n | 'outlined';\n\ntype ImageStyles = NamedStylesStringUnion<ImageStyleKeys>;\n\nconst useStyles: UseStyles<ImageStyles> = function (): ImageStyles {\n const theme = useTheme();\n\n return {\n root: {},\n rounded: {\n borderRadius: theme.shape.roundness,\n overflow: 'hidden',\n },\n placeholder: {\n backgroundColor: theme.palette.paper.grey,\n },\n outlined: {\n borderWidth: StyleSheet.hairlineWidth,\n borderStyle: 'solid',\n borderColor: theme.palette.paper.grey,\n },\n };\n};\n\nexport default function Image(props: ImageProps) {\n const {\n alt,\n disableOutline,\n disablePlaceholder,\n loading = 'lazy',\n overlaidChildren,\n resizeMode = 'cover',\n source,\n style,\n square = false,\n size,\n onLoad,\n onError,\n Placeholder: PlaceholderComponent,\n ...otherProps\n } = props;\n\n const [failed, setFailed] = React.useState(false);\n\n const styles = useStyles();\n\n const handleError = () => {\n if (onError) {\n onError();\n }\n\n setFailed(true);\n };\n\n const Placeholder = ({\n failed,\n children,\n }: PlaceholderProps) => PlaceholderComponent ? (\n <PlaceholderComponent\n children={children}\n failed={failed}\n />\n ) : children;\n\n const sourceWithSizeParam = {\n ...source,\n uri: size ? `${source.uri}?size=${size}` : source.uri,\n };\n\n useEffect(() => {\n setFailed(false);\n }, [sourceWithSizeParam.uri]);\n\n return (\n <View\n style={css([\n styles.root,\n !disableOutline ? styles.outlined : undefined,\n !disablePlaceholder ? styles.placeholder : undefined,\n !square ? styles.rounded : undefined,\n style,\n ])}\n {...otherProps}\n >\n <Placeholder failed={failed}>\n {!failed ? (\n <React.Fragment>\n <ImageCore\n alt={alt}\n height={'100%'}\n loading={loading}\n onError={handleError}\n onLoad={onLoad}\n resizeMode={resizeMode}\n source={sourceWithSizeParam}\n width={'100%'}\n />\n\n {overlaidChildren ? (\n <View style={StyleSheet.absoluteFill}>\n {overlaidChildren}\n </View>\n ) : null}\n </React.Fragment>\n ) : null}\n </Placeholder>\n </View>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["ImageProps.ts"],"sourcesContent":["import React from 'react';\nimport type { ViewProps } from 'react-native';\nimport type { OverridableComponentProps } from '../types';\nimport type { ImageSource, Loading, ResizeMode } from '../ImageCore';\n\nexport default interface ImageProps extends OverridableComponentProps<ViewProps, {\n /**\n * Indicating the alternate fallback content to be displayed\n * if the image has not been loaded.\n */\n alt?: string;\n\n /**\n * If `true`, the image outline is not rendered.\n * @default false\n */\n disableOutline?: boolean;\n\n /**\n * If `true`, the placeholder is not rendered.\n * @default false\n */\n disablePlaceholder?: boolean;\n\n /**\n * Web only. Loading the document by determining whether to load\n * the image immediately (`eager`) or on an as-needed basis (`lazy`).\n * On React Native, it always works as `lazy`.\n * @default 'lazy'\n */\n loading?: Loading;\n\n /**\n * error event handler\n */\n onError?: () => void;\n\n /**\n * image loaded event handler\n */\n onLoad?: () => void;\n\n /**\n * The children on top this image.\n */\n overlaidChildren?: React.ReactNode;\n\n /**\n * Determines how to resize the image when the frame doesn't match the raw image dimensions.\n * @default 'cover'\n */\n resizeMode?: ResizeMode;\n\n /**\n * The image source.\n */\n source: ImageSource;\n\n /**\n * If `true`, rounded corners are disabled.\n * @default false\n */\n square?: boolean;\n\n size?: 'small' | 'medium' | 'large';\n}> {}\n"],"mappings":""}
1
+ {"version":3,"names":[],"sources":["ImageProps.ts"],"sourcesContent":["import React from 'react';\nimport type { ViewProps } from 'react-native';\nimport type { OverridableComponentProps } from '../types';\nimport type { ImageSource, Loading, ResizeMode } from '../ImageCore';\n\nexport interface PlaceholderProps {\n failed: boolean;\n children: React.ReactElement | null;\n}\n\nexport default interface ImageProps extends OverridableComponentProps<ViewProps, {\n /**\n * Indicating the alternate fallback content to be displayed\n * if the image has not been loaded.\n */\n alt?: string;\n\n /**\n * If `true`, the image outline is not rendered.\n * @default false\n */\n disableOutline?: boolean;\n\n /**\n * If `true`, the placeholder is not rendered.\n * @default false\n */\n disablePlaceholder?: boolean;\n\n /**\n * Web only. Loading the document by determining whether to load\n * the image immediately (`eager`) or on an as-needed basis (`lazy`).\n * On React Native, it always works as `lazy`.\n * @default 'lazy'\n */\n loading?: Loading;\n\n /**\n * error event handler\n */\n onError?: () => void;\n\n /**\n * image loaded event handler\n */\n onLoad?: () => void;\n\n /**\n * The children on top this image.\n */\n overlaidChildren?: React.ReactNode;\n\n /**\n * Determines how to resize the image when the frame doesn't match the raw image dimensions.\n * @default 'cover'\n */\n resizeMode?: ResizeMode;\n\n /**\n * The image source.\n */\n source: ImageSource;\n\n /**\n * If `true`, rounded corners are disabled.\n * @default false\n */\n square?: boolean;\n\n /**\n * Image file size.\n * Request image by query string.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * The Custom image placeholder component with condition.\n */\n Placeholder?: (props: PlaceholderProps) => JSX.Element | null;\n}> {}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export { default } from './Image';\nexport type { default as ImageProps } from './ImageProps';"],"mappings":";;;;;;;;;;;;AAAA"}
1
+ {"version":3,"names":[],"sources":["index.ts"],"sourcesContent":["export { default } from './Image';\nexport type { default as ImageProps } from './ImageProps';\nexport type { PlaceholderProps } from './ImageProps';"],"mappings":";;;;;;;;;;;;AAAA"}
@@ -1,7 +1,7 @@
1
1
  function _extends() { _extends = Object.assign ? Object.assign.bind() : 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); }
2
2
 
3
- import React from 'react';
4
- import { Text, View } from 'react-native';
3
+ import React, { useEffect } from 'react';
4
+ import { View } from 'react-native';
5
5
  import ImageCore from '../ImageCore';
6
6
  import { css, StyleSheet, useTheme } from '../styles';
7
7
 
@@ -38,6 +38,7 @@ export default function Image(props) {
38
38
  size,
39
39
  onLoad,
40
40
  onError,
41
+ Placeholder: PlaceholderComponent,
41
42
  ...otherProps
42
43
  } = props;
43
44
  const [failed, setFailed] = React.useState(false);
@@ -51,12 +52,28 @@ export default function Image(props) {
51
52
  setFailed(true);
52
53
  };
53
54
 
55
+ const Placeholder = _ref => {
56
+ let {
57
+ failed,
58
+ children
59
+ } = _ref;
60
+ return PlaceholderComponent ? /*#__PURE__*/React.createElement(PlaceholderComponent, {
61
+ children: children,
62
+ failed: failed
63
+ }) : children;
64
+ };
65
+
54
66
  const sourceWithSizeParam = { ...source,
55
67
  uri: size ? `${source.uri}?size=${size}` : source.uri
56
68
  };
69
+ useEffect(() => {
70
+ setFailed(false);
71
+ }, [sourceWithSizeParam.uri]);
57
72
  return /*#__PURE__*/React.createElement(View, _extends({
58
73
  style: css([styles.root, !disableOutline ? styles.outlined : undefined, !disablePlaceholder ? styles.placeholder : undefined, !square ? styles.rounded : undefined, style])
59
- }, otherProps), failed ? /*#__PURE__*/React.createElement(Text, null, alt) : /*#__PURE__*/React.createElement(ImageCore, {
74
+ }, otherProps), /*#__PURE__*/React.createElement(Placeholder, {
75
+ failed: failed
76
+ }, !failed ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(ImageCore, {
60
77
  alt: alt,
61
78
  height: '100%',
62
79
  loading: loading,
@@ -67,7 +84,7 @@ export default function Image(props) {
67
84
  width: '100%'
68
85
  }), overlaidChildren ? /*#__PURE__*/React.createElement(View, {
69
86
  style: StyleSheet.absoluteFill
70
- }, overlaidChildren) : null);
87
+ }, overlaidChildren) : null) : null));
71
88
  }
72
89
  ;
73
90
  //# sourceMappingURL=Image.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","Text","View","ImageCore","css","StyleSheet","useTheme","useStyles","theme","root","rounded","borderRadius","shape","roundness","overflow","placeholder","backgroundColor","palette","paper","grey","outlined","borderWidth","hairlineWidth","borderStyle","borderColor","Image","props","alt","disableOutline","disablePlaceholder","loading","overlaidChildren","resizeMode","source","style","square","size","onLoad","onError","otherProps","failed","setFailed","useState","styles","handleError","sourceWithSizeParam","uri","undefined","absoluteFill"],"sources":["Image.tsx"],"sourcesContent":["import React from 'react';\nimport { Text, View } from 'react-native';\nimport type { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport ImageCore from '../ImageCore';\nimport { css, StyleSheet, useTheme } from '../styles';\nimport type ImageProps from './ImageProps';\n\ntype ImageStyleKeys =\n | 'root'\n | 'rounded'\n | 'placeholder'\n | 'outlined';\n\ntype ImageStyles = NamedStylesStringUnion<ImageStyleKeys>;\n\nconst useStyles: UseStyles<ImageStyles> = function (): ImageStyles {\n const theme = useTheme();\n\n return {\n root: {},\n rounded: {\n borderRadius: theme.shape.roundness,\n overflow: 'hidden',\n },\n placeholder: {\n backgroundColor: theme.palette.paper.grey,\n },\n outlined: {\n borderWidth: StyleSheet.hairlineWidth,\n borderStyle: 'solid',\n borderColor: theme.palette.paper.grey,\n },\n };\n};\n\nexport default function Image(props: ImageProps) {\n const {\n alt,\n disableOutline,\n disablePlaceholder,\n loading = 'lazy',\n overlaidChildren,\n resizeMode = 'cover',\n source,\n style,\n square = false,\n size,\n onLoad,\n onError,\n ...otherProps\n } = props;\n\n const [failed, setFailed] = React.useState(false);\n\n const styles = useStyles();\n\n const handleError = () => {\n if(onError){\n onError();\n }\n\n setFailed(true);\n }\n\n const sourceWithSizeParam = {\n ...source,\n uri: size ? `${source.uri}?size=${size}` : source.uri,\n };\n\n return (\n <View\n style={css([\n styles.root,\n !disableOutline ? styles.outlined : undefined,\n !disablePlaceholder ? styles.placeholder : undefined,\n !square ? styles.rounded : undefined,\n style,\n ])}\n {...otherProps}\n >\n {failed ? (\n <Text>{alt}</Text>\n ) : (\n <ImageCore\n alt={alt}\n height={'100%'}\n loading={loading}\n onError={handleError}\n onLoad={onLoad}\n resizeMode={resizeMode}\n source={sourceWithSizeParam}\n width={'100%'}\n />\n )}\n\n {overlaidChildren ? (\n <View style={StyleSheet.absoluteFill}>\n {overlaidChildren}\n </View>\n ) : null}\n </View>\n );\n};\n"],"mappings":";;AAAA,OAAOA,KAAP,MAAkB,OAAlB;AACA,SAASC,IAAT,EAAeC,IAAf,QAA2B,cAA3B;AAEA,OAAOC,SAAP,MAAsB,cAAtB;AACA,SAASC,GAAT,EAAcC,UAAd,EAA0BC,QAA1B,QAA0C,WAA1C;;AAWA,MAAMC,SAAiC,GAAG,YAAyB;EAC/D,MAAMC,KAAK,GAAGF,QAAQ,EAAtB;EAEA,OAAO;IACHG,IAAI,EAAE,EADH;IAEHC,OAAO,EAAE;MACLC,YAAY,EAAEH,KAAK,CAACI,KAAN,CAAYC,SADrB;MAELC,QAAQ,EAAE;IAFL,CAFN;IAMHC,WAAW,EAAE;MACTC,eAAe,EAAER,KAAK,CAACS,OAAN,CAAcC,KAAd,CAAoBC;IAD5B,CANV;IASHC,QAAQ,EAAE;MACNC,WAAW,EAAEhB,UAAU,CAACiB,aADlB;MAENC,WAAW,EAAE,OAFP;MAGNC,WAAW,EAAEhB,KAAK,CAACS,OAAN,CAAcC,KAAd,CAAoBC;IAH3B;EATP,CAAP;AAeH,CAlBD;;AAoBA,eAAe,SAASM,KAAT,CAAeC,KAAf,EAAkC;EAC7C,MAAM;IACFC,GADE;IAEFC,cAFE;IAGFC,kBAHE;IAIFC,OAAO,GAAG,MAJR;IAKFC,gBALE;IAMFC,UAAU,GAAG,OANX;IAOFC,MAPE;IAQFC,KARE;IASFC,MAAM,GAAG,KATP;IAUFC,IAVE;IAWFC,MAXE;IAYFC,OAZE;IAaF,GAAGC;EAbD,IAcFb,KAdJ;EAgBA,MAAM,CAACc,MAAD,EAASC,SAAT,IAAsBzC,KAAK,CAAC0C,QAAN,CAAe,KAAf,CAA5B;EAEA,MAAMC,MAAM,GAAGpC,SAAS,EAAxB;;EAEA,MAAMqC,WAAW,GAAG,MAAM;IACtB,IAAGN,OAAH,EAAW;MACPA,OAAO;IACV;;IAEDG,SAAS,CAAC,IAAD,CAAT;EACH,CAND;;EAQA,MAAMI,mBAAmB,GAAG,EACxB,GAAGZ,MADqB;IAExBa,GAAG,EAAEV,IAAI,GAAI,GAAEH,MAAM,CAACa,GAAI,SAAQV,IAAK,EAA9B,GAAkCH,MAAM,CAACa;EAF1B,CAA5B;EAKA,oBACI,oBAAC,IAAD;IACI,KAAK,EAAE1C,GAAG,CAAC,CACPuC,MAAM,CAAClC,IADA,EAEP,CAACmB,cAAD,GAAkBe,MAAM,CAACvB,QAAzB,GAAoC2B,SAF7B,EAGP,CAAClB,kBAAD,GAAsBc,MAAM,CAAC5B,WAA7B,GAA2CgC,SAHpC,EAIP,CAACZ,MAAD,GAAUQ,MAAM,CAACjC,OAAjB,GAA2BqC,SAJpB,EAKPb,KALO,CAAD;EADd,GAQQK,UARR,GAUKC,MAAM,gBACH,oBAAC,IAAD,QAAOb,GAAP,CADG,gBAGH,oBAAC,SAAD;IACI,GAAG,EAAEA,GADT;IAEI,MAAM,EAAE,MAFZ;IAGI,OAAO,EAAEG,OAHb;IAII,OAAO,EAAEc,WAJb;IAKI,MAAM,EAAEP,MALZ;IAMI,UAAU,EAAEL,UANhB;IAOI,MAAM,EAAEa,mBAPZ;IAQI,KAAK,EAAE;EARX,EAbR,EAyBKd,gBAAgB,gBACb,oBAAC,IAAD;IAAM,KAAK,EAAE1B,UAAU,CAAC2C;EAAxB,GACKjB,gBADL,CADa,GAIb,IA7BR,CADJ;AAiCH;AAAA"}
1
+ {"version":3,"names":["React","useEffect","View","ImageCore","css","StyleSheet","useTheme","useStyles","theme","root","rounded","borderRadius","shape","roundness","overflow","placeholder","backgroundColor","palette","paper","grey","outlined","borderWidth","hairlineWidth","borderStyle","borderColor","Image","props","alt","disableOutline","disablePlaceholder","loading","overlaidChildren","resizeMode","source","style","square","size","onLoad","onError","Placeholder","PlaceholderComponent","otherProps","failed","setFailed","useState","styles","handleError","children","sourceWithSizeParam","uri","undefined","absoluteFill"],"sources":["Image.tsx"],"sourcesContent":["import React, { useEffect } from 'react';\nimport { View } from 'react-native';\nimport type { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';\nimport ImageCore from '../ImageCore';\nimport { css, StyleSheet, useTheme } from '../styles';\nimport type ImageProps from './ImageProps';\nimport { PlaceholderProps } from './ImageProps';\n\ntype ImageStyleKeys =\n | 'root'\n | 'rounded'\n | 'placeholder'\n | 'outlined';\n\ntype ImageStyles = NamedStylesStringUnion<ImageStyleKeys>;\n\nconst useStyles: UseStyles<ImageStyles> = function (): ImageStyles {\n const theme = useTheme();\n\n return {\n root: {},\n rounded: {\n borderRadius: theme.shape.roundness,\n overflow: 'hidden',\n },\n placeholder: {\n backgroundColor: theme.palette.paper.grey,\n },\n outlined: {\n borderWidth: StyleSheet.hairlineWidth,\n borderStyle: 'solid',\n borderColor: theme.palette.paper.grey,\n },\n };\n};\n\nexport default function Image(props: ImageProps) {\n const {\n alt,\n disableOutline,\n disablePlaceholder,\n loading = 'lazy',\n overlaidChildren,\n resizeMode = 'cover',\n source,\n style,\n square = false,\n size,\n onLoad,\n onError,\n Placeholder: PlaceholderComponent,\n ...otherProps\n } = props;\n\n const [failed, setFailed] = React.useState(false);\n\n const styles = useStyles();\n\n const handleError = () => {\n if (onError) {\n onError();\n }\n\n setFailed(true);\n };\n\n const Placeholder = ({\n failed,\n children,\n }: PlaceholderProps) => PlaceholderComponent ? (\n <PlaceholderComponent\n children={children}\n failed={failed}\n />\n ) : children;\n\n const sourceWithSizeParam = {\n ...source,\n uri: size ? `${source.uri}?size=${size}` : source.uri,\n };\n\n useEffect(() => {\n setFailed(false);\n }, [sourceWithSizeParam.uri]);\n\n return (\n <View\n style={css([\n styles.root,\n !disableOutline ? styles.outlined : undefined,\n !disablePlaceholder ? styles.placeholder : undefined,\n !square ? styles.rounded : undefined,\n style,\n ])}\n {...otherProps}\n >\n <Placeholder failed={failed}>\n {!failed ? (\n <React.Fragment>\n <ImageCore\n alt={alt}\n height={'100%'}\n loading={loading}\n onError={handleError}\n onLoad={onLoad}\n resizeMode={resizeMode}\n source={sourceWithSizeParam}\n width={'100%'}\n />\n\n {overlaidChildren ? (\n <View style={StyleSheet.absoluteFill}>\n {overlaidChildren}\n </View>\n ) : null}\n </React.Fragment>\n ) : null}\n </Placeholder>\n </View>\n );\n};\n"],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"names":[],"sources":["ImageProps.ts"],"sourcesContent":["import React from 'react';\nimport type { ViewProps } from 'react-native';\nimport type { OverridableComponentProps } from '../types';\nimport type { ImageSource, Loading, ResizeMode } from '../ImageCore';\n\nexport default interface ImageProps extends OverridableComponentProps<ViewProps, {\n /**\n * Indicating the alternate fallback content to be displayed\n * if the image has not been loaded.\n */\n alt?: string;\n\n /**\n * If `true`, the image outline is not rendered.\n * @default false\n */\n disableOutline?: boolean;\n\n /**\n * If `true`, the placeholder is not rendered.\n * @default false\n */\n disablePlaceholder?: boolean;\n\n /**\n * Web only. Loading the document by determining whether to load\n * the image immediately (`eager`) or on an as-needed basis (`lazy`).\n * On React Native, it always works as `lazy`.\n * @default 'lazy'\n */\n loading?: Loading;\n\n /**\n * error event handler\n */\n onError?: () => void;\n\n /**\n * image loaded event handler\n */\n onLoad?: () => void;\n\n /**\n * The children on top this image.\n */\n overlaidChildren?: React.ReactNode;\n\n /**\n * Determines how to resize the image when the frame doesn't match the raw image dimensions.\n * @default 'cover'\n */\n resizeMode?: ResizeMode;\n\n /**\n * The image source.\n */\n source: ImageSource;\n\n /**\n * If `true`, rounded corners are disabled.\n * @default false\n */\n square?: boolean;\n\n size?: 'small' | 'medium' | 'large';\n}> {}\n"],"mappings":""}
1
+ {"version":3,"names":[],"sources":["ImageProps.ts"],"sourcesContent":["import React from 'react';\nimport type { ViewProps } from 'react-native';\nimport type { OverridableComponentProps } from '../types';\nimport type { ImageSource, Loading, ResizeMode } from '../ImageCore';\n\nexport interface PlaceholderProps {\n failed: boolean;\n children: React.ReactElement | null;\n}\n\nexport default interface ImageProps extends OverridableComponentProps<ViewProps, {\n /**\n * Indicating the alternate fallback content to be displayed\n * if the image has not been loaded.\n */\n alt?: string;\n\n /**\n * If `true`, the image outline is not rendered.\n * @default false\n */\n disableOutline?: boolean;\n\n /**\n * If `true`, the placeholder is not rendered.\n * @default false\n */\n disablePlaceholder?: boolean;\n\n /**\n * Web only. Loading the document by determining whether to load\n * the image immediately (`eager`) or on an as-needed basis (`lazy`).\n * On React Native, it always works as `lazy`.\n * @default 'lazy'\n */\n loading?: Loading;\n\n /**\n * error event handler\n */\n onError?: () => void;\n\n /**\n * image loaded event handler\n */\n onLoad?: () => void;\n\n /**\n * The children on top this image.\n */\n overlaidChildren?: React.ReactNode;\n\n /**\n * Determines how to resize the image when the frame doesn't match the raw image dimensions.\n * @default 'cover'\n */\n resizeMode?: ResizeMode;\n\n /**\n * The image source.\n */\n source: ImageSource;\n\n /**\n * If `true`, rounded corners are disabled.\n * @default false\n */\n square?: boolean;\n\n /**\n * Image file size.\n * Request image by query string.\n */\n size?: 'small' | 'medium' | 'large';\n\n /**\n * The Custom image placeholder component with condition.\n */\n Placeholder?: (props: PlaceholderProps) => JSX.Element | null;\n}> {}\n"],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"names":["default"],"sources":["index.ts"],"sourcesContent":["export { default } from './Image';\nexport type { default as ImageProps } from './ImageProps';"],"mappings":"AAAA,SAASA,OAAT,QAAwB,SAAxB"}
1
+ {"version":3,"names":["default"],"sources":["index.ts"],"sourcesContent":["export { default } from './Image';\nexport type { default as ImageProps } from './ImageProps';\nexport type { PlaceholderProps } from './ImageProps';"],"mappings":"AAAA,SAASA,OAAT,QAAwB,SAAxB"}
@@ -2,6 +2,10 @@ import React from 'react';
2
2
  import type { ViewProps } from 'react-native';
3
3
  import type { OverridableComponentProps } from '../types';
4
4
  import type { ImageSource, Loading, ResizeMode } from '../ImageCore';
5
+ export interface PlaceholderProps {
6
+ failed: boolean;
7
+ children: React.ReactElement | null;
8
+ }
5
9
  export default interface ImageProps extends OverridableComponentProps<ViewProps, {
6
10
  /**
7
11
  * Indicating the alternate fallback content to be displayed
@@ -51,6 +55,14 @@ export default interface ImageProps extends OverridableComponentProps<ViewProps,
51
55
  * @default false
52
56
  */
53
57
  square?: boolean;
58
+ /**
59
+ * Image file size.
60
+ * Request image by query string.
61
+ */
54
62
  size?: 'small' | 'medium' | 'large';
63
+ /**
64
+ * The Custom image placeholder component with condition.
65
+ */
66
+ Placeholder?: (props: PlaceholderProps) => JSX.Element | null;
55
67
  }> {
56
68
  }
@@ -1,2 +1,3 @@
1
1
  export { default } from './Image';
2
2
  export type { default as ImageProps } from './ImageProps';
3
+ export type { PlaceholderProps } from './ImageProps';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@fountain-ui/core",
3
- "version": "2.0.0-beta.36",
3
+ "version": "2.0.0-beta.37",
4
4
  "author": "Fountain-UI Team",
5
5
  "description": "React components that implement Tappytoon's Fountain Design.",
6
6
  "license": "MIT",
@@ -67,5 +67,5 @@
67
67
  "publishConfig": {
68
68
  "access": "public"
69
69
  },
70
- "gitHead": "019b85d550c729ccca7f3877d6aebe3fa02bd2ec"
70
+ "gitHead": "0c9f01b22179356577219f06bc6a21f6eb3f554c"
71
71
  }
@@ -1,9 +1,10 @@
1
- import React from 'react';
2
- import { Text, View } from 'react-native';
1
+ import React, { useEffect } from 'react';
2
+ import { View } from 'react-native';
3
3
  import type { NamedStylesStringUnion, UseStyles } from '@fountain-ui/styles';
4
4
  import ImageCore from '../ImageCore';
5
5
  import { css, StyleSheet, useTheme } from '../styles';
6
6
  import type ImageProps from './ImageProps';
7
+ import { PlaceholderProps } from './ImageProps';
7
8
 
8
9
  type ImageStyleKeys =
9
10
  | 'root'
@@ -47,6 +48,7 @@ export default function Image(props: ImageProps) {
47
48
  size,
48
49
  onLoad,
49
50
  onError,
51
+ Placeholder: PlaceholderComponent,
50
52
  ...otherProps
51
53
  } = props;
52
54
 
@@ -55,18 +57,32 @@ export default function Image(props: ImageProps) {
55
57
  const styles = useStyles();
56
58
 
57
59
  const handleError = () => {
58
- if(onError){
60
+ if (onError) {
59
61
  onError();
60
62
  }
61
63
 
62
64
  setFailed(true);
63
- }
65
+ };
66
+
67
+ const Placeholder = ({
68
+ failed,
69
+ children,
70
+ }: PlaceholderProps) => PlaceholderComponent ? (
71
+ <PlaceholderComponent
72
+ children={children}
73
+ failed={failed}
74
+ />
75
+ ) : children;
64
76
 
65
77
  const sourceWithSizeParam = {
66
78
  ...source,
67
79
  uri: size ? `${source.uri}?size=${size}` : source.uri,
68
80
  };
69
81
 
82
+ useEffect(() => {
83
+ setFailed(false);
84
+ }, [sourceWithSizeParam.uri]);
85
+
70
86
  return (
71
87
  <View
72
88
  style={css([
@@ -78,26 +94,28 @@ export default function Image(props: ImageProps) {
78
94
  ])}
79
95
  {...otherProps}
80
96
  >
81
- {failed ? (
82
- <Text>{alt}</Text>
83
- ) : (
84
- <ImageCore
85
- alt={alt}
86
- height={'100%'}
87
- loading={loading}
88
- onError={handleError}
89
- onLoad={onLoad}
90
- resizeMode={resizeMode}
91
- source={sourceWithSizeParam}
92
- width={'100%'}
93
- />
94
- )}
97
+ <Placeholder failed={failed}>
98
+ {!failed ? (
99
+ <React.Fragment>
100
+ <ImageCore
101
+ alt={alt}
102
+ height={'100%'}
103
+ loading={loading}
104
+ onError={handleError}
105
+ onLoad={onLoad}
106
+ resizeMode={resizeMode}
107
+ source={sourceWithSizeParam}
108
+ width={'100%'}
109
+ />
95
110
 
96
- {overlaidChildren ? (
97
- <View style={StyleSheet.absoluteFill}>
98
- {overlaidChildren}
99
- </View>
100
- ) : null}
111
+ {overlaidChildren ? (
112
+ <View style={StyleSheet.absoluteFill}>
113
+ {overlaidChildren}
114
+ </View>
115
+ ) : null}
116
+ </React.Fragment>
117
+ ) : null}
118
+ </Placeholder>
101
119
  </View>
102
120
  );
103
121
  };
@@ -3,6 +3,11 @@ import type { ViewProps } from 'react-native';
3
3
  import type { OverridableComponentProps } from '../types';
4
4
  import type { ImageSource, Loading, ResizeMode } from '../ImageCore';
5
5
 
6
+ export interface PlaceholderProps {
7
+ failed: boolean;
8
+ children: React.ReactElement | null;
9
+ }
10
+
6
11
  export default interface ImageProps extends OverridableComponentProps<ViewProps, {
7
12
  /**
8
13
  * Indicating the alternate fallback content to be displayed
@@ -62,5 +67,14 @@ export default interface ImageProps extends OverridableComponentProps<ViewProps,
62
67
  */
63
68
  square?: boolean;
64
69
 
70
+ /**
71
+ * Image file size.
72
+ * Request image by query string.
73
+ */
65
74
  size?: 'small' | 'medium' | 'large';
75
+
76
+ /**
77
+ * The Custom image placeholder component with condition.
78
+ */
79
+ Placeholder?: (props: PlaceholderProps) => JSX.Element | null;
66
80
  }> {}
@@ -1,2 +1,3 @@
1
1
  export { default } from './Image';
2
- export type { default as ImageProps } from './ImageProps';
2
+ export type { default as ImageProps } from './ImageProps';
3
+ export type { PlaceholderProps } from './ImageProps';