@rpldy/upload-preview
Advanced tools
Comparing version 0.2.3 to 0.2.4
// @flow | ||
import * as React from "react"; | ||
import type { BatchItem } from "@rpldy/shared"; | ||
import { PREVIEW_TYPES } from "./consts"; | ||
import type { BatchItem } from "@rpldy/shared"; | ||
import type { RefObject } from "@rpldy/shared-ui"; | ||
export type PreviewType = $Values<typeof PREVIEW_TYPES>; | ||
export type PreviewData = { | ||
export type PreviewItem = { | ||
id: string, | ||
@@ -16,4 +18,9 @@ url: string, | ||
export type FallbackType = string | PreviewData; | ||
export type PreviewData = { | ||
previews: PreviewItem[], | ||
clearPreviews: () => void, | ||
}; | ||
export type FallbackType = string | PreviewItem; | ||
export type FallbackMethod = (file: Object) => ?FallbackType; | ||
@@ -23,2 +30,6 @@ | ||
export type PreviewMethods = { | ||
clear: () => void, | ||
}; | ||
export type PreviewOptions = {| | ||
@@ -47,6 +58,10 @@ //whether to show previous batches' previews as opposed to just the last (default: false) | ||
...PreviewOptions, | ||
PreviewComponent?: React.ComponentType<any>, | ||
//custom component to render the preview (default: img tag) | ||
PreviewComponent?: React.ComponentType<$Shape<PreviewItem>>, | ||
//ref will be set with API methods (PreviewMethods) | ||
previewMethodsRef?: RefObject<PreviewMethods>, | ||
//callback that will be called when preview items are loaded or changed | ||
onPreviewsChanged?: (PreviewItem[]) => void, | ||
|}; | ||
// export type MandatoryPreviewOptions = $Exact<$ObjMap<PreviewProps, NonMaybeTypeFunc>>; | ||
export type MandatoryPreviewOptions = {| | ||
@@ -53,0 +68,0 @@ loadFirstOnly: boolean, |
"use strict"; | ||
function _typeof(obj) { if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
function _typeof(obj) { "@babel/helpers - typeof"; if (typeof Symbol === "function" && typeof Symbol.iterator === "symbol") { _typeof = function _typeof(obj) { return typeof obj; }; } else { _typeof = function _typeof(obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; } return _typeof(obj); } | ||
@@ -12,4 +12,6 @@ Object.defineProperty(exports, "__esModule", { | ||
var _usePreviewsLoader = _interopRequireDefault(require("./usePreviewsLoader")); | ||
var _sharedUi = require("@rpldy/shared-ui"); | ||
var _usePreviewsLoader2 = _interopRequireDefault(require("./usePreviewsLoader")); | ||
var _utils = require("./utils"); | ||
@@ -32,7 +34,7 @@ | ||
var showBasicPreview = function showBasicPreview(type, url, previewProps, onImgError) { | ||
return type === _consts.PREVIEW_TYPES.VIDEO ? _react["default"].createElement("video", _extends({ | ||
return type === _consts.PREVIEW_TYPES.VIDEO ? /*#__PURE__*/_react["default"].createElement("video", _extends({ | ||
key: url, | ||
src: url, | ||
controls: true | ||
}, previewProps)) : _react["default"].createElement("img", _extends({ | ||
}, previewProps)) : /*#__PURE__*/_react["default"].createElement("img", _extends({ | ||
key: url, | ||
@@ -44,7 +46,33 @@ onError: onImgError, | ||
var usePreviewMethods = function usePreviewMethods(previews, clearPreviews, previewMethodsRef, onPreviewsChanged) { | ||
var previewMethods = (0, _react.useMemo)(function () { | ||
return { | ||
clear: clearPreviews | ||
}; | ||
}, [clearPreviews]); | ||
var _useWithForwardRef = (0, _sharedUi.useWithForwardRef)(previewMethodsRef), | ||
setPreviewMethods = _useWithForwardRef.setRef; | ||
if ((previewMethodsRef === null || previewMethodsRef === void 0 ? void 0 : previewMethodsRef.current) !== previewMethods) { | ||
setPreviewMethods(previewMethods); | ||
} | ||
(0, _react.useEffect)(function () { | ||
if (onPreviewsChanged) { | ||
onPreviewsChanged(previews); | ||
} | ||
}, [previews, onPreviewsChanged]); | ||
}; | ||
var UploadPreview = function UploadPreview(props) { | ||
var PreviewComponent = props.PreviewComponent, | ||
previewOptions = _objectWithoutProperties(props, ["PreviewComponent"]); | ||
previewMethodsRef = props.previewMethodsRef, | ||
onPreviewsChanged = props.onPreviewsChanged, | ||
previewOptions = _objectWithoutProperties(props, ["PreviewComponent", "previewMethodsRef", "onPreviewsChanged"]); | ||
var previews = (0, _usePreviewsLoader["default"])(previewOptions); | ||
var _usePreviewsLoader = (0, _usePreviewsLoader2["default"])(previewOptions), | ||
previews = _usePreviewsLoader.previews, | ||
clearPreviews = _usePreviewsLoader.clearPreviews; | ||
var onImagePreviewLoadError = (0, _react.useCallback)(function (e) { | ||
@@ -58,2 +86,3 @@ var img = e.target; | ||
}, [props.fallbackUrl]); | ||
usePreviewMethods(previews, clearPreviews, previewMethodsRef, onPreviewsChanged); | ||
return previews.map(function (data) { | ||
@@ -65,3 +94,3 @@ var id = data.id, | ||
previewProps = data.props; | ||
return PreviewComponent ? _react["default"].createElement(PreviewComponent, _extends({ | ||
return PreviewComponent ? /*#__PURE__*/_react["default"].createElement(PreviewComponent, _extends({ | ||
key: id + url, | ||
@@ -68,0 +97,0 @@ id: id, |
@@ -18,8 +18,12 @@ "use strict"; | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } | ||
function _iterableToArrayLimit(arr, i) { if (!(Symbol.iterator in Object(arr) || Object.prototype.toString.call(arr) === "[object Arguments]")) { return; } var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); } | ||
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) { arr2[i] = arr[i]; } return arr2; } | ||
function _iterableToArrayLimit(arr, i) { if (typeof Symbol === "undefined" || !(Symbol.iterator in Object(arr))) return; var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
@@ -29,3 +33,3 @@ | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
@@ -67,3 +71,3 @@ 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; } | ||
return data && _objectSpread({}, data, { | ||
return data && _objectSpread(_objectSpread({}, data), {}, { | ||
id: item.id, | ||
@@ -98,2 +102,5 @@ props: props | ||
var previewOptions = (0, _utils.getWithMandatoryOptions)(props); | ||
var clearPreviews = (0, _react.useCallback)(function () { | ||
setPreviews([]); | ||
}, []); | ||
(0, _sharedUi.useBatchStartListener)(function (batch) { | ||
@@ -106,5 +113,8 @@ var items = previewOptions.loadFirstOnly ? batch.items.slice(0, 1) : batch.items; | ||
}); | ||
return previews; | ||
return { | ||
previews: previews, | ||
clearPreviews: clearPreviews | ||
}; | ||
}; | ||
exports["default"] = _default; |
@@ -16,3 +16,3 @@ "use strict"; | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(Object(source), true).forEach(function (key) { _defineProperty(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; } | ||
@@ -22,3 +22,3 @@ 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; } | ||
var getWithMandatoryOptions = function getWithMandatoryOptions(options) { | ||
return _objectSpread({}, _defaults.PREVIEW_DEFAULTS, {}, options); | ||
return _objectSpread(_objectSpread({}, _defaults.PREVIEW_DEFAULTS), options); | ||
}; | ||
@@ -25,0 +25,0 @@ |
{ | ||
"version": "0.2.3", | ||
"version": "0.2.4", | ||
"name": "@rpldy/upload-preview", | ||
@@ -20,11 +20,11 @@ "description": "preview component to show image or video being uploaded", | ||
"dependencies": { | ||
"@rpldy/shared": "^0.2.3", | ||
"@rpldy/shared-ui": "^0.2.3" | ||
"@rpldy/shared": "^0.2.4", | ||
"@rpldy/shared-ui": "^0.2.4" | ||
}, | ||
"devDependencies": { | ||
"@rpldy/upload-button": "^0.2.3", | ||
"@rpldy/upload-url-input": "^0.2.3", | ||
"@storybook/addon-knobs": "^5.3.18", | ||
"flow-bin": "^0.123.0", | ||
"styled-components": "^4.4.1" | ||
"@rpldy/upload-button": "^0.2.4", | ||
"@rpldy/upload-url-input": "^0.2.4", | ||
"@storybook/addon-knobs": "^5.3.19", | ||
"flow-bin": "^0.126.1", | ||
"styled-components": "^5.1.1" | ||
}, | ||
@@ -38,3 +38,3 @@ "peerDependencies": { | ||
}, | ||
"gitHead": "ae30dff0980d764282621e8fbead581ba4f1386b" | ||
"gitHead": "8c954910416ffd3c3522807b2ea5b58d94e7e208" | ||
} |
@@ -41,2 +41,4 @@ <a href="https://badge.fury.io/js/%40rpldy%2Fupload-preview"> | ||
| rememberPreviousBatches | boolean | false | show previous batches' previews as opposed to just the last | ||
| previewMethodsRef | React Ref | undefined | ref will be set with preview helper [methods](src/types.js#L29) | ||
| onPreviewsChanged | (PreviewItem[]) => void | undefined | callback will be called whenever preview items array changes | ||
@@ -52,4 +54,3 @@ ## Example | ||
export const App = () => ( | ||
<Uploady> | ||
<Uploady destination={{ url: "my-server.com/upload" }}> | ||
<UploadPreview | ||
@@ -61,2 +62,55 @@ fallbackUrl="https://icon-library.net/images/image-placeholder-icon/image-placeholder-icon-6.jpg"/> | ||
### Advanced Usage | ||
_The props _rememberPreviousBatches_, _previewMethodsRef_, and _onPreviewsChanged_ make it possible to do more with previews. | ||
Specifically, the make it possible to create a visual queue of the uploads. | ||
This is especially useful when adding other features such as abort and [retry](../retry-hooks). | ||
The code below shows how to clear the previews with a button click: | ||
```javascript | ||
import React from "react"; | ||
import Uploady from "@rpldy/uploady"; | ||
import UploadPreview from "@rpldy/upload-preview"; | ||
import UploadButton from "@rpldy/upload-button"; | ||
const PreviewsWithClear = () => { | ||
const previewMethodsRef = useRef(); | ||
const [previews, setPreviews] = useState([]); | ||
const onPreviewsChanged = useCallback((previews) => { | ||
setPreviews(previews); | ||
}, []); | ||
const onClear = useCallback(() => { | ||
if (previewMethodsRef.current?.clear) { | ||
previewMethodsRef.current.clear(); | ||
} | ||
}, [previewMethodsRef]); | ||
return <> | ||
<button onClick={onClear}> | ||
Clear {previews.length} previews | ||
</button> | ||
<br/> | ||
<UploadPreview | ||
rememberPreviousBatches | ||
previewMethodsRef={previewMethodsRef} | ||
onPreviewsChanged={onPreviewsChanged} | ||
/> | ||
</>; | ||
}; | ||
export const App = () => { | ||
return <Uploady destination={{ url: "my-server.com/upload" }}> | ||
<UploadButton /> | ||
<PreviewsWithClear /> | ||
</Uploady>; | ||
}; | ||
``` | ||
### Custom Preview | ||
For an example of using a custom preview component see [this story](http://localhost:9111/?path=/story/upload-preview--with-progress). | ||
@@ -63,0 +117,0 @@ |
import * as React from "react"; | ||
import { BatchItem } from "@rpldy/shared"; | ||
import { BatchItem, FileLike } from "@rpldy/shared"; | ||
@@ -9,18 +9,27 @@ export enum PreviewType { | ||
export type PreviewData = { | ||
export type PreviewItem = { | ||
id: string; | ||
url: string; | ||
name: string; | ||
url: string; | ||
type: PreviewType; | ||
props: object; | ||
props: Record<string, unknown>; | ||
}; | ||
export type PreviewData = { | ||
previews: PreviewItem[]; | ||
clearPreviews: () => void; | ||
}; | ||
export type FallbackType = string | PreviewData; | ||
export type FallbackMethod = (file: object) => FallbackType | void; | ||
export type FallbackMethod = (file: FileLike) => FallbackType | void; | ||
export type PreviewComponentPropsMethod = (item: BatchItem, url: string, type: PreviewType) => object; | ||
export type PreviewComponentPropsMethod = (item: BatchItem, url: string, type: PreviewType) => Record<string, unknown>; | ||
export type PreviewComponentPropsOrMethod = object | PreviewComponentPropsMethod; | ||
export type PreviewComponentPropsOrMethod = Record<string, unknown> | PreviewComponentPropsMethod; | ||
export type PreviewMethods = { | ||
clear: () => void; | ||
}; | ||
export interface PreviewOptions { | ||
@@ -45,2 +54,4 @@ rememberPreviousBatches?: boolean; | ||
PreviewComponent?: React.ComponentType<PreviewComponentProps>; | ||
previewMethodsRef?: React.RefObject<PreviewMethods>; | ||
onPreviewsChanged?: (previews: PreviewItem[]) => void; | ||
} | ||
@@ -47,0 +58,0 @@ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
35631
377
130
Updated@rpldy/shared@^0.2.4
Updated@rpldy/shared-ui@^0.2.4