├── filepicker.png
├── .eslintignore
├── .babelrc
├── src
├── demo.css
├── options.js
├── demo.jsx
└── ReactFilepicker.jsx
├── index.html
├── .eslintrc
├── .gitignore
├── package.json
├── webpack.config.js
├── README.md
└── dist
└── react-filepicker.js
/filepicker.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ZeroCho/react-filepicker/HEAD/filepicker.png
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | webpack.config.js
3 | dist/
4 | node_modules/
--------------------------------------------------------------------------------
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": [
3 | ["es2015", { "modules": false }],
4 | "react",
5 | "stage-1"
6 | ]
7 | }
--------------------------------------------------------------------------------
/src/demo.css:
--------------------------------------------------------------------------------
1 | .customButton {
2 | background: white;
3 | border: 1px solid black;
4 | cursor: pointer;
5 | border-radius:3px;
6 | }
7 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | React-filepicker
5 |
6 |
7 |
8 |
9 |
10 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "parser": "babel-eslint",
3 | "extends": "airbnb",
4 | "parserOptions": {
5 | "ecmaVersion": 2017,
6 | "sourceType": "module",
7 | "ecmaFeatures": {
8 | "jsx": true,
9 | "experimentalObjectRestSpread": true
10 | }
11 | },
12 | "rules": {
13 | "import/no-unresolved": 0,
14 | "global-require": 0,
15 | "no-console": 0,
16 | "max-len": 0,
17 | "no-param-reassign": [
18 | "error",
19 | {
20 | "props": false
21 | }
22 | ],
23 | "object-curly-newline": ["error", { "multiline": true }]
24 | },
25 | "plugins": [
26 | "react",
27 | "jsx-a11y",
28 | "babel"
29 | ],
30 | "env": {
31 | "browser": true,
32 | "node": true
33 | }
34 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 | logs
3 | *.log
4 | npm-debug.log*
5 | pids
6 | *.pid
7 | *.seed
8 | lib-cov
9 | .grunt
10 | .lock-wscript
11 | build/Release
12 | node_modules
13 | .idea
14 | jspm_packages
15 | .npm
16 | .node_repl_history
17 | .idea/tasks.xml
18 | .idea/dataSources.ids
19 | .idea/dataSources.xml
20 | .idea/dataSources.local.xml
21 | .idea/sqlDataSources.xml
22 | .idea/dynamic.xml
23 | .idea/uiDesigner.xml
24 | .idea/gradle.xml
25 | .idea/libraries
26 | .idea/mongoSettings.xml
27 | *.iws
28 | /out/
29 | .idea_modules/
30 | atlassian-ide-plugin.xml
31 | com_crashlytics_export_strings.xml
32 | crashlytics.properties
33 | crashlytics-build.properties
34 | fabric.properties
35 | /dist/react-filepicker.js.map
36 | /dist/demo.js.map
37 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "react-filepicker",
3 | "version": "0.11.0",
4 | "main": "dist/react-filepicker.js",
5 | "description": "react component for filepicker(a.k.a filestack)",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "rimraf dist && webpack --colors --debug --display-error-details",
9 | "prepublishOnly": "npm run build",
10 | "lint": "eslint"
11 | },
12 | "repository": {
13 | "type": "git",
14 | "url": "git+https://github.com/zerocho/react-filepicker.git"
15 | },
16 | "keywords": [
17 | "react-filepicker",
18 | "filestack",
19 | "filepicker",
20 | "react",
21 | "uploader",
22 | "upload",
23 | "file",
24 | "image",
25 | "ssr",
26 | "server"
27 | ],
28 | "author": "ZeroCho",
29 | "license": "MIT",
30 | "bugs": {
31 | "url": "https://github.com/zerocho/react-filepicker/issues"
32 | },
33 | "homepage": "https://github.com/zerocho/react-filepicker#readme",
34 | "dependencies": {
35 | "filepicker-js": "^2.4.18",
36 | "prop-types": "^15.5.10"
37 | },
38 | "devDependencies": {
39 | "babel-cli": "^6.24.0",
40 | "babel-core": "^6.24.0",
41 | "babel-eslint": "^8.2.1",
42 | "babel-loader": "^7.0.0",
43 | "babel-preset-es2015": "^6.24.0",
44 | "babel-preset-react": "^6.23.0",
45 | "babel-preset-stage-1": "^6.22.0",
46 | "css-loader": "^0.28.4",
47 | "eslint": "^4.17.0",
48 | "eslint-config-airbnb": "^16.1.0",
49 | "eslint-plugin-babel": "^4.1.1",
50 | "eslint-plugin-import": "^2.3.0",
51 | "eslint-plugin-jsx-a11y": "^6.0.3",
52 | "eslint-plugin-react": "^7.0.1",
53 | "imports-loader": "^0.7.1",
54 | "raw-loader": "^0.5.1",
55 | "react": "^16.2.0",
56 | "react-dom": "^16.2.0",
57 | "rimraf": "^2.6.1",
58 | "style-loader": "^0.18.1",
59 | "webpack": "^3.11.0"
60 | },
61 | "peerDependencies": {
62 | "react": "^15.3.0 || ^16",
63 | "react-dom": "^15.3.0 || ^16"
64 | }
65 | }
66 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path');
2 | const webpack = require('webpack');
3 | const fs = require('fs');
4 |
5 | const rules = [
6 | { test: /\.jsx?$/, loader: 'babel-loader', exclude: /node_modules/ },
7 | {
8 | test: /\.css/,
9 | use: [
10 | 'style-loader?sourcemap', 'css-loader?modules&importLoaders=1',
11 | ],
12 | },
13 | ];
14 |
15 | module.exports = [{
16 | entry: './src/ReactFilepicker',
17 | output: {
18 | path: path.join(__dirname, 'dist'),
19 | filename: 'react-filepicker.js',
20 | libraryTarget: 'commonjs2',
21 | },
22 | devtool: 'source-map',
23 | resolve: {
24 | modules: ['node_modules', 'src'],
25 | extensions: ['.js', '.json', '.jsx'],
26 | },
27 | module: { rules },
28 | plugins: [
29 | new webpack.LoaderOptionsPlugin({
30 | minimize: true,
31 | }),
32 | new webpack.DefinePlugin({
33 | 'process.env.NODE_ENV': JSON.stringify('production'),
34 | }),
35 | new webpack.optimize.UglifyJsPlugin({
36 | sourceMap: true,
37 | compress: {
38 | warnings: false,
39 | },
40 | }),
41 | new webpack.ProvidePlugin({
42 | filepicker: 'filepicker-js',
43 | 'window.filepicker': 'filepicker-js'
44 | }),
45 | ],
46 | }, {
47 | entry: './src/demo.jsx',
48 | output: {
49 | path: path.join(__dirname, 'dist'),
50 | filename: 'demo.js'
51 | },
52 | devtool: 'source-map',
53 | resolve: {
54 | modules: ['node_modules', 'src'],
55 | extensions: ['.json', '.js', '.jsx'],
56 | },
57 | module: { rules },
58 | plugins: [
59 | new webpack.LoaderOptionsPlugin({
60 | minimize: true,
61 | }),
62 | new webpack.DefinePlugin({
63 | 'process.env.NODE_ENV': JSON.stringify('production'),
64 | }),
65 | new webpack.optimize.UglifyJsPlugin({
66 | sourceMap: true,
67 | compress: {
68 | warnings: false,
69 | },
70 | }),
71 | new webpack.ProvidePlugin({
72 | filepicker: 'filepicker-js',
73 | 'window.filepicker': 'filepicker-js'
74 | }),
75 | ],
76 | }];
77 |
--------------------------------------------------------------------------------
/src/options.js:
--------------------------------------------------------------------------------
1 | function setAttrIfExists(key, options, attrname, dom) {
2 | if (options[key]) {
3 | dom.setAttribute(attrname, options[key]);
4 | }
5 | }
6 |
7 | function setAttrIfExistsArray(fpoptions, domElement, optionsObj) {
8 | Object.keys(optionsObj).forEach((option) => {
9 | setAttrIfExists(optionsObj[option], fpoptions, option, domElement);
10 | });
11 | }
12 |
13 | function joinIfExist(key, options) {
14 | if (options[key]) {
15 | options[key] = options[key].join();
16 | }
17 | }
18 |
19 | export default function applyOptions(domElement, options, mode = 'pick') {
20 | const generalOptionsMap = {
21 | 'data-fp-container': 'container',
22 | 'data-fp-mimetype': 'mimetype',
23 | 'data-fp-extension': 'extension',
24 | 'data-fp-openTo': 'openTo',
25 | 'data-fp-debug': 'debug',
26 | 'data-fp-signature': 'signature',
27 | 'data-fp-policy': 'policy',
28 | 'data-fp-language': 'language',
29 | 'data-fp-background-upload': 'backgroundUpload',
30 | 'data-fp-hide': 'hide',
31 | 'data-fp-custom-css': 'customCss',
32 | 'data-fp-crop-force': 'cropForce',
33 | 'data-fp-crop-ratio': 'cropRatio',
34 | 'data-fp-crop-dim': 'cropDim',
35 | 'data-fp-crop-max': 'cropMax',
36 | 'data-fp-crop-min': 'cropMin',
37 | 'data-fp-show-close': 'showClose',
38 | 'data-fp-conversions': 'conversions',
39 | 'data-fp-custom-text': 'customText',
40 | 'data-fp-custom-source-container': 'customSourceContainer',
41 | 'data-fp-custom-source-path': 'customSourcePath',
42 | };
43 | const pickOnlyOptionsMap = {
44 | 'data-fp-mimetypes': 'mimetypes',
45 | 'data-fp-extensions': 'extensions',
46 | 'data-fp-maxSize': 'maxSize',
47 | 'data-fp-maxFiles': 'maxFiles',
48 | 'data-fp-store-location': 'storeLocation',
49 | 'data-fp-store-path': 'storePath',
50 | 'data-fp-store-container': 'storeContainer',
51 | 'data-fp-store-region': 'storeRegion',
52 | 'data-fp-store-access': 'storeAccess',
53 | 'data-fp-image-quality': 'imageQuality',
54 | 'data-fp-image-dim': 'imageDim',
55 | 'data-fp-image-max': 'imageMax',
56 | 'data-fp-image-min': 'imageMin',
57 | };
58 | const webcamOptionsMap = {
59 | 'data-fp-video-recording-resolution': 'videoRes',
60 | 'data-fp-webcam-dim': 'webcamDim',
61 | 'data-fp-video-length': 'videoLen',
62 | 'data-fp-audio-length': 'audioLen',
63 | };
64 | setAttrIfExistsArray(options, domElement, generalOptionsMap);
65 | if (mode === 'export') {
66 | setAttrIfExists('suggestedFilename', options, 'data-fp-suggestedFilename', domElement);
67 | } else if (mode === 'pick' || mode === 'pickMultiple') {
68 | setAttrIfExistsArray(options, domElement, pickOnlyOptionsMap);
69 | options.webcam = {};
70 | setAttrIfExistsArray(options.webcam, domElement, webcamOptionsMap);
71 | }
72 | if (options.services) {
73 | domElement.setAttribute('data-fp-services', options.services.join());
74 | }
75 | if (options.service) {
76 | domElement.setAttribute('data-fp-service', options.service);
77 | }
78 | const arrayToJoin = ['extensions', 'mimetypes', 'imageDim', 'imageMin', 'imageMax', 'cropDim', 'cropMax', 'cropMin', 'webcamDim', 'conversions'];
79 | Object.keys(arrayToJoin).forEach((key) => {
80 | joinIfExist(arrayToJoin[key], options);
81 | });
82 | if (options.folders === true) {
83 | domElement.setAttribute('data-fp-folders', 'true');
84 | }
85 | if (options.multiple === true || mode === 'pickMultiple') {
86 | return domElement.setAttribute('data-fp-multiple', 'true');
87 | }
88 | return domElement;
89 | }
90 |
--------------------------------------------------------------------------------
/src/demo.jsx:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import ReactFilepicker from './ReactFilepicker';
4 | import styles from './demo.css';
5 |
6 | document.addEventListener('DOMContentLoaded', () => {
7 | const rootNode = document.createElement('div');
8 | document.body.appendChild(rootNode);
9 | const apikey = 'Acu94EFL1STGYvkM6a8usz';
10 | const dragDropOptions = {
11 | buttonText: 'I can handle drag&drop!',
12 | multiple: true,
13 | mimetype: 'image/*',
14 | container: 'window',
15 | webcamDim: [1280, 720],
16 | webcam: {
17 | videoRes: '1280x720',
18 | },
19 | services: ['COMPUTER', 'FACEBOOK', 'CLOUDAPP'],
20 | };
21 | const convertOptions = {
22 | width: 200,
23 | height: 200,
24 | };
25 | const customOptions = {
26 | buttonText: 'I\'m customized',
27 | buttonClass: styles.customButton,
28 | multiple: true,
29 | mimetype: 'image/*',
30 | container: 'window',
31 | services: ['COMPUTER', 'FACEBOOK', 'CLOUDAPP'],
32 | };
33 | const blob = {
34 | url: 'https://www.filestackapi.com/api/file/9BWnyKPBQI23ukbT7sZA',
35 | filename: 'robot.png',
36 | mimetype: 'image/png',
37 | isWriteable: false,
38 | size: 28683,
39 | };
40 | const pickAndStoreOptions = {
41 | buttonText: 'PickAndStore',
42 | location: 'S3',
43 | };
44 | const exportOptions = {
45 | url: 'https://www.filestackapi.com/api/file/lQ9LalJTKmuou4WSw9LM',
46 | mimetype: 'image/png',
47 | buttonText: 'Export',
48 | suggestedFilename: 'newFile',
49 | };
50 | const callback = (fpfiles) => {
51 | console.log('fpfiles', fpfiles);
52 | };
53 | ReactDOM.render(
54 |
55 |
59 |
60 |
64 |
65 |
69 |
70 |
74 |
75 |
79 |
80 |
84 |
85 |
95 |
96 |
106 |
107 |
119 |
,
120 | rootNode,
121 | );
122 | });
123 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # React Filepicker
2 | react component for **filepicker**
3 |
4 | ## How to install
5 |
6 | **This is for v2 old filepicker api. If you want latest v3 filestack api, go [here](https://npmjs.com/package/react-filestack)**
7 |
8 | [Live Demo](https://zerocho.herokuapp.com/portfolio/ReactFilepicker)
9 | [NPM](https://npmjs.com/package/react-filepicker)
10 | [Github](https://github.com/zerocho/react-filepicker)
11 | ```
12 | npm install react-filepicker
13 | ```
14 | ## Import
15 | ```
16 | var ReactFilepicker = require('react-filepicker');
17 | ```
18 | In ES2015
19 | ```
20 | import ReactFilepicker from 'react-filepicker';
21 | ```
22 | ## Usage
23 | You should register for [Filestack(filepicker)](https://www.filestack.com) and get an **API key** first!
24 |
25 | **Default FileStack widget**
26 | ```
27 |
28 | ```
29 |
30 | **Custom Designed button**
31 | ```
32 |
33 | ```
34 |
35 | **Other mode than 'pick'**
36 | ```
37 |
38 | ```
39 | Available modes:
40 | * convert
41 | * export
42 | * pickAndStore
43 | * pickMultiple (Instead, you can use pick mode and put 'multiple: true' in **options** object)
44 | * read
45 | * store
46 | * storeUrl
47 | * write
48 | * writeUrl
49 | * stat
50 |
51 | make your own options and callback function, connect it to the component and get the results(either fpfiles or blob object)
52 | ```
53 | const options = {
54 | buttonText: 'Pick Me',
55 | buttonClass: 'filepicker',
56 | mimetype: 'image/*',
57 | container: 'window',
58 | services: ['COMPUTER', 'FACEBOOK', 'CLOUDAPP']
59 | };
60 | yourCallbackFunction(fpfiles) {
61 | // handle fpfiles or blob object
62 | }
63 | ```
64 |
65 | **Link instead of button**
66 | if you want a custom button to be a link, just put **link** props
67 | ```
68 |
69 | ```
70 |
71 | ## Result
72 | 
73 | Works well with IE...
74 |
75 | ## Demo
76 | git clone this project and open index.html
77 | You can also see live demo here
78 | [Link](https://zerocho.herokuapp.com/portfolio/ReactFilepicker)
79 |
80 | ## Props
81 | [Official Filestack Documentation](https://filestack.com/docs)
82 |
83 | > ### apikey
84 | > **required** string. An API key for filestack
85 |
86 | > ### defaultWidget
87 | > **optional** boolean. **default** true. choose between the default widget and the custom button
88 |
89 | > ### mode
90 | > **optional** string. **default** 'pick'. **options** `['pick', 'dragdrop', 'convert', 'export']`. convert and export modes are for custom button.
91 |
92 | > ### blob
93 | > **optional** object. use if you need to insert blob object for convert, export, stat, write or writeUrl mode.
94 |
95 | > ### input
96 | > **optional** object. use this for read, store, storeUrl or write mode.
97 |
98 | > ### log
99 | > **optional** object. **default** false. choose whether to console.log filepicker process
100 |
101 | > ### onSuccess
102 | > **optional** function. get result(fpfiles or blob object) after upload is done.
103 |
104 | > ### onError
105 | > **optional** function. send error object as callback parameter
106 |
107 | > ### onProgress
108 | > **optional** function. send progress object as callback parameter
109 |
110 | > ### options
111 | > **optional** object. **Detailed options for button. See Javascript API of [official documentation](https://filestack.com/docs). Put everything in it if you think you have to**
112 |
113 | > ### buttonText
114 | > **optional** string. When using custom button, you can set your own text. It is included in **options** prop(as options.buttonText), so use only when it's necessary.
115 |
116 | > ### buttonClass
117 | > **optional** string. When using custom button, you can set className. It is included in **options** prop(as options.buttonClass), so use only when it's necessary.
118 |
119 | ## Wanna Contribute?
120 | Please contribute to this package via **Pull Request**, or you can open **Issues**!
121 | ```
122 | npm install && npm run build
123 | run index.html
124 | ```
125 |
126 | ## Contributors
127 | - Zero Cho
128 | - Łukasz Kornek
129 |
130 | ## License
131 | MIT
132 |
--------------------------------------------------------------------------------
/src/ReactFilepicker.jsx:
--------------------------------------------------------------------------------
1 | import React, { Component } from 'react';
2 | import PropTypes from 'prop-types';
3 | import applyOptions from './options';
4 |
5 | class ReactFilepicker extends Component {
6 | static defaultProps = {
7 | blob: null,
8 | input: null,
9 | link: false,
10 | buttonText: '',
11 | buttonClass: '',
12 | onSuccess: null,
13 | onProgress: null,
14 | onError: null,
15 | defaultWidget: true,
16 | mode: 'pick',
17 | log: false,
18 | options: {
19 | folders: false,
20 | buttonText: 'Pick File',
21 | container: 'modal',
22 | language: 'en',
23 | webcam: {
24 | videoRes: '640x480',
25 | audioLen: '3600',
26 | vidioLen: '3600',
27 | },
28 | backgroundUpload: true,
29 | hide: false,
30 | imageQuality: 100,
31 | cropForce: false,
32 | },
33 | };
34 |
35 | static propTypes = {
36 | blob: PropTypes.objectOf(PropTypes.any),
37 | input: PropTypes.objectOf(PropTypes.any),
38 | apikey: PropTypes.string.isRequired,
39 | defaultWidget: PropTypes.bool,
40 | link: PropTypes.bool,
41 | mode: PropTypes.string,
42 | buttonText: PropTypes.string,
43 | buttonClass: PropTypes.string,
44 | onSuccess: PropTypes.func,
45 | onError: PropTypes.func,
46 | log: PropTypes.bool,
47 | onProgress: PropTypes.func,
48 | options: PropTypes.shape({
49 | url: PropTypes.string,
50 | filename: PropTypes.string,
51 | suggestedFilename: PropTypes.string,
52 | buttonText: PropTypes.string,
53 | buttonClass: PropTypes.string,
54 | mimetype: PropTypes.string,
55 | mimetypes: PropTypes.arrayOf(PropTypes.string),
56 | extension: PropTypes.string,
57 | extensions: PropTypes.arrayOf(PropTypes.string),
58 | multiple: PropTypes.bool,
59 | maxSize: PropTypes.number,
60 | maxFiles: PropTypes.number,
61 | folders: PropTypes.bool,
62 | container: PropTypes.string,
63 | language: PropTypes.string,
64 | service: PropTypes.string,
65 | services: PropTypes.arrayOf(PropTypes.string),
66 | openTo: PropTypes.string,
67 | webcamDim: PropTypes.arrayOf(PropTypes.number),
68 | webcam: PropTypes.shape({
69 | videoRes: PropTypes.string,
70 | audioLen: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
71 | videoLen: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
72 | }),
73 | customSourceContainer: PropTypes.string,
74 | customSourcePath: PropTypes.string,
75 | debug: PropTypes.bool,
76 | policy: PropTypes.string,
77 | signature: PropTypes.string,
78 | backgroundUpload: PropTypes.bool,
79 | hide: PropTypes.bool,
80 | customCss: PropTypes.string,
81 | customText: PropTypes.string,
82 | imageQuality: PropTypes.number,
83 | imageDim: PropTypes.arrayOf(PropTypes.number),
84 | imageMax: PropTypes.arrayOf(PropTypes.number),
85 | imageMin: PropTypes.arrayOf(PropTypes.number),
86 | conversions: PropTypes.arrayOf(PropTypes.string),
87 | cropRatio: PropTypes.number,
88 | cropDim: PropTypes.arrayOf(PropTypes.number),
89 | cropMax: PropTypes.arrayOf(PropTypes.number),
90 | cropMin: PropTypes.arrayOf(PropTypes.number),
91 | cropForce: PropTypes.bool,
92 | width: PropTypes.number,
93 | height: PropTypes.number,
94 | fit: PropTypes.oneOf(['clip', 'crop', 'scale', 'max']),
95 | align: PropTypes.oneOf(['top', 'bottom', 'left', 'right', 'faces']),
96 | crop: PropTypes.arrayOf(PropTypes.number),
97 | crop_first: PropTypes.bool,
98 | format: PropTypes.string,
99 | filter: PropTypes.oneOf(['blur', 'sharpen']),
100 | compress: PropTypes.bool,
101 | quality: PropTypes.number,
102 | rotate: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
103 | watermark: PropTypes.string,
104 | watermark_position: PropTypes.string,
105 | watermark_size: PropTypes.number,
106 | location: PropTypes.string,
107 | path: PropTypes.string,
108 | storeRegion: PropTypes.string,
109 | storeContainer: PropTypes.string,
110 | access: PropTypes.string,
111 | base64encode: PropTypes.bool,
112 | base64decode: PropTypes.bool,
113 | asText: PropTypes.bool,
114 | cache: PropTypes.bool,
115 | uploaded: PropTypes.bool,
116 | writeable: PropTypes.bool,
117 | md5: PropTypes.bool,
118 | }),
119 | };
120 |
121 | componentDidMount() {
122 | const filepicker = require('filepicker-js');
123 |
124 | const { apikey, buttonText, buttonClass, onSuccess, options, mode, log } = this.props;
125 | const custom = this.fpButton;
126 | if (!custom) { // if using default widget
127 | const element = this.target;
128 | if (mode === 'dragdrop') {
129 | element.setAttribute('type', 'filepicker-dragdrop');
130 | } else if (mode === 'pickMultiple') {
131 | options.multiple = true;
132 | }
133 | applyOptions(element, options, mode);
134 | element.setAttribute('data-fp-apikey', apikey);
135 | element.setAttribute('data-fp-button-text', buttonText || options.buttonText || 'Pick File');
136 | element.setAttribute('data-fp-button-class', buttonClass || options.buttonClass || 'fp__btn');
137 | element.onchange = (e) => {
138 | if (typeof onSuccess === 'function') {
139 | onSuccess(e.fpfiles.length === 1 ? e.fpfile : e.fpfiles);
140 | }
141 | if (log) {
142 | console.log(e.fpfile);
143 | }
144 | };
145 | filepicker.constructWidget(element);
146 | element.setAttribute('type', '');
147 | }
148 | }
149 |
150 | onClickPick = (e) => {
151 | const filepicker = require('filepicker-js');
152 |
153 | e.stopPropagation();
154 | e.preventDefault();
155 | const { apikey, onSuccess, onError, onProgress, options, mode, blob, input, log } = this.props;
156 | const onFinished = (result) => {
157 | if (typeof onSuccess === 'function') {
158 | onSuccess(result);
159 | }
160 | if (log) {
161 | console.log(result);
162 | }
163 | };
164 | const onFail = (error) => {
165 | if (typeof onError === 'function') {
166 | onError(error);
167 | }
168 | if (log) {
169 | console.error(error);
170 | }
171 | };
172 | const onUploading = (progress) => {
173 | if (typeof onProgress === 'function') {
174 | onProgress(progress);
175 | }
176 | if (log) {
177 | console.log(progress);
178 | }
179 | };
180 | filepicker.setKey(apikey);
181 | if (mode === 'export') {
182 | filepicker.exportFile(blob || options.url, options, onFinished, onFail, onUploading);
183 | } else if (mode === 'convert') {
184 | filepicker.convert(blob, options, options, onFinished, onFail, onUploading);
185 | } else if (mode === 'pickAndStore') {
186 | filepicker.pickAndStore(options, options, onFinished, onFail, onUploading);
187 | } else if (mode === 'pickMultiple' || options.multiple) {
188 | filepicker.pickMultiple(options, onFinished, onFail, onUploading);
189 | } else if (mode === 'read') {
190 | filepicker.read(input || options.url, options, onFinished, onError, onUploading);
191 | } else if (mode === 'store') {
192 | filepicker.store(input, options, onFinished, onError, onUploading);
193 | } else if (mode === 'storeUrl') {
194 | filepicker.storeUrl(options.url, options, onFinished, onError, onUploading);
195 | } else if (mode === 'stat') {
196 | filepicker.stat(blob, options, onFinished, onError);
197 | } else if (mode === 'write') {
198 | filepicker.write(blob, input, options, onFinished, onError, onUploading);
199 | } else if (mode === 'writeUrl') {
200 | filepicker.writeUrl(blob, options.url, options, onFinished, onError, onUploading);
201 | } else {
202 | filepicker.pick(options, onFinished, onFail, onUploading);
203 | }
204 | };
205 |
206 | render() {
207 | const { defaultWidget, buttonClass, buttonText, link, options } = this.props;
208 | if (defaultWidget) {
209 | return (
210 | {
212 | this.target = c;
213 | }}
214 | type="filepicker"
215 | />
216 | );
217 | }
218 | const Tag = link ? 'a' : 'button';
219 | return (
220 | {
222 | this.fpButton = c;
223 | }}
224 | onClick={this.onClickPick}
225 | className={buttonClass || options.buttonClass}
226 | >
227 | {buttonText || options.buttonText}
228 |
229 | );
230 | }
231 | }
232 |
233 | export default ReactFilepicker;
234 |
--------------------------------------------------------------------------------
/dist/react-filepicker.js:
--------------------------------------------------------------------------------
1 | module.exports=function(e){function t(n){if(r[n])return r[n].exports;var o=r[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,t),o.l=!0,o.exports}var r={};return t.m=e,t.c=r,t.d=function(e,r,n){t.o(e,r)||Object.defineProperty(e,r,{configurable:!1,enumerable:!0,get:n})},t.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return t.d(r,"a",r),r},t.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},t.p="",t(t.s=1)}([function(e,t,r){(function(t){r(13),e.exports=t}).call(t,r(0))},function(e,t,r){"use strict";function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function o(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function i(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(t,"__esModule",{value:!0});var a=r(2),c=r.n(a),s=r(7),l=r.n(s),u=r(12),p=function(){function e(e,t){for(var r=0;rN.length&&N.push(e)}function d(e,t,r,o){var i=typeof e;"undefined"!==i&&"boolean"!==i||(e=null);var a=!1;if(null===e)a=!0;else switch(i){case"string":case"number":a=!0;break;case"object":switch(e.$$typeof){case k:case E:case A:case F:a=!0}}if(a)return r(o,e,""===t?"."+m(e,0):t),1;if(a=0,t=""===t?".":t+":",Array.isArray(e))for(var c=0;c2&&void 0!==arguments[2]?arguments[2]:"pick",a={"data-fp-container":"container","data-fp-mimetype":"mimetype","data-fp-extension":"extension","data-fp-openTo":"openTo","data-fp-debug":"debug","data-fp-signature":"signature","data-fp-policy":"policy","data-fp-language":"language","data-fp-background-upload":"backgroundUpload","data-fp-hide":"hide","data-fp-custom-css":"customCss","data-fp-crop-force":"cropForce","data-fp-crop-ratio":"cropRatio","data-fp-crop-dim":"cropDim","data-fp-crop-max":"cropMax","data-fp-crop-min":"cropMin","data-fp-show-close":"showClose","data-fp-conversions":"conversions","data-fp-custom-text":"customText","data-fp-custom-source-container":"customSourceContainer","data-fp-custom-source-path":"customSourcePath"},c={"data-fp-mimetypes":"mimetypes","data-fp-extensions":"extensions","data-fp-maxSize":"maxSize","data-fp-maxFiles":"maxFiles","data-fp-store-location":"storeLocation","data-fp-store-path":"storePath","data-fp-store-container":"storeContainer","data-fp-store-region":"storeRegion","data-fp-store-access":"storeAccess","data-fp-image-quality":"imageQuality","data-fp-image-dim":"imageDim","data-fp-image-max":"imageMax","data-fp-image-min":"imageMin"},s={"data-fp-video-recording-resolution":"videoRes","data-fp-webcam-dim":"webcamDim","data-fp-video-length":"videoLen","data-fp-audio-length":"audioLen"};o(t,e,a),"export"===r?n("suggestedFilename",t,"data-fp-suggestedFilename",e):"pick"!==r&&"pickMultiple"!==r||(o(t,e,c),t.webcam={},o(t.webcam,e,s)),t.services&&e.setAttribute("data-fp-services",t.services.join()),t.service&&e.setAttribute("data-fp-service",t.service);var l=["extensions","mimetypes","imageDim","imageMin","imageMax","cropDim","cropMax","cropMin","webcamDim","conversions"];return Object.keys(l).forEach(function(e){i(l[e],t)}),!0===t.folders&&e.setAttribute("data-fp-folders","true"),!0===t.multiple||"pickMultiple"===r?e.setAttribute("data-fp-multiple","true"):e}t.a=a},function(module,exports,__webpack_require__){"use strict";(function(__webpack_provided_window_dot_filepicker,filepicker){!function(){var e=function(){var e={},t=function(t,r,n){for(var o=t.split("."),i=0;i-1){var l=e.util.parseUrl(s).params;l=e.conversions.mapRestParams(l),l.crop&&e.util.setDefault(l,"crop_first",!0);for(var u in l)e.util.setDefault(c,u,l[u])}e.conversions.convert(e.util.trimConvert(s),c,o,i,a)},w=function(t){return e.widgets.constructWidget(t)},y=function(t,r){return e.dragdrop.makeDropPane(t,r)};return{setKey:t,setResponsiveOptions:function(t){return e.responsiveImages.setResponsiveOptions(t)},pick:n,pickFolder:a,pickMultiple:o,pickAndStore:i,read:c,write:l,writeUrl:u,export:p,exportFile:p,processImage:f,store:d,storeUrl:m,stat:h,metadata:h,remove:g,convert:v,constructWidget:w,makeDropPane:y,FilepickerException:r,responsive:function(){e.responsiveImages.update.apply(null,arguments)},logout:function(t){t=t||{},e.ajax.get(e.urls.LOGOUT,{success:t.onSuccess,error:t.onError,withCredentials:!0})},version:"2.4.18"}},!0),filepicker.extend("mimetypes",function(){var e=this,t={".stl":"application/sla",".hbs":"text/html",".pdf":"application/pdf",".jpg":"image/jpeg",".jpeg":"image/jpeg",".jpe":"image/jpeg",".imp":"application/x-impressionist",".vob":"video/dvd"},r=["application/octet-stream","application/download","application/force-download","octet/stream","application/unknown","application/x-download","application/x-msdownload","application/x-secure-download"];return{getMimetype:function(e){if(e.type){var n=e.type;n=n.toLowerCase();for(var o=!1,i=0;i=0||o.indexOf("?")>=0)&&(o=encodeURIComponent(o)),l+e(t,r)+"&curl="+o+n(t.conversions)},h=function(t,r){return u+e(t,r)},g=function(t,r,n){return(t.indexOf("&")>=0||t.indexOf("?")>=0)&&(t=encodeURIComponent(t)),s+e(r,n)+"&url="+t+(void 0!==r.mimetype?"&m="+r.mimetype:"")+(void 0!==r.extension?"&ext="+r.extension:"")+(r.suggestedFilename?"&defaultSaveasName="+r.suggestedFilename:"")},v=function(e){return p+e.location+"?key="+o.apikey+(e.base64decode?"&base64decode=true":"")+(e.mimetype?"&mimetype="+e.mimetype:"")+(e.filename?"&filename="+encodeURIComponent(e.filename):"")+(e.path?"&path="+e.path:"")+(e.container?"&container="+e.container:"")+(e.access?"&access="+e.access:"")+t(e)+"&plugin="+r()};return{BASE:i,DIALOG_BASE:a,API_COMM:i+"/dialog/comm_iframe/",COMM:a+"/dialog/comm_iframe/",FP_COMM_FALLBACK:a+"/dialog/comm_hash_iframe/",STORE:p,PICK:c,EXPORT:s,LOGOUT:i+"/api/clients/unauth",constructPickUrl:d,constructConvertUrl:m,constructPickFolderUrl:h,constructExportUrl:g,constructWriteUrl:function(e,n){return e+"?nonce=fp"+(n.base64decode?"&base64decode=true":"")+(n.mimetype?"&mimetype="+n.mimetype:"")+t(n)+"&plugin="+r()},constructStoreUrl:v,constructHostCommFallback:function(){return o.util.parseUrl(window.location.href).origin+"/404"},getPlugin:r}}),filepicker.extend("ajax",function(){var e=this,t=function(e,t){t.method="GET",i(e,t)},r=function(t,r){r.method="POST",t+=(t.indexOf("?")>=0?"&":"?")+"_cacheBust="+e.util.getId(),i(t,r)},n=function(t,r){var o=[];for(var i in t){var a=t[i];r&&(i=r+". + key + ");var c;switch(e.util.typeOf(a)){case"object":c=n(a,i);break;case"array":for(var s={},l=0;l=0?"&":"?")+"plugin="+e.urls.getPlugin(),u&&p&&(u=n(r.data));var v;if(r.xhr)v=r.xhr;else if(!(v=o()))return r.error("Ajax not allowed"),v;if(h&&window.XDomainRequest&&!("withCredentials"in v))return new a(t,r);r.progress&&v.upload&&v.upload.addEventListener("progress",function(e){e.lengthComputable&&r.progress(Math.round(95*e.loaded/e.total))},!1);var w=function(){if(4==v.readyState&&!g)if(r.progress&&r.progress(100),v.status>=200&&v.status<300){var t=v.responseText;if(r.json)try{t=e.json.decode(t)}catch(e){return void y.call(v,"Invalid json: "+t)}c(t,v.status,v),g=!0}else y.call(v,v.responseText),g=!0};v.onreadystatechange=w;var y=function(e){if(!g)return r.progress&&r.progress(100),g=!0,400==this.status?void s("bad_params",this.status,this):403==this.status?void s("not_authorized",this.status,this):404==this.status?void s("not_found",this.status,this):h?4==this.readyState&&0===this.status?void s("CORS_not_allowed",this.status,this):void s("CORS_error",this.status,this):void s(e,this.status,this)};v.onerror=y,u&&"GET"==i&&(t+=(-1!==t.indexOf("?")?"&":"?")+u,u=null),r.withCredentials&&(v.withCredentials=!0),v.open(i,t,l),r.json?v.setRequestHeader("Accept","application/json, text/javascript"):v.setRequestHeader("Accept","text/javascript, text/html, application/xml, text/xml, */*");var b=f["Content-Type"]||f["content-type"];if(u&&p&&("POST"==i||"PUT"==i)&&void 0===b&&v.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=utf-8"),f)for(var x in f)v.setRequestHeader(x,f[x]);return v.send(u),v},a=function(t,r){if(!window.XDomainRequest)return null;var o=r.method?r.method.toUpperCase():"POST",i=r.success||function(){},a=r.error||function(){},c=r.data||{};if("http:"==window.location.protocol?t=t.replace("https:","http:"):"https:"==window.location.protocol&&(t=t.replace("http:","https:")),r.async)throw new e.FilepickerException("Asyncronous Cross-domain requests are not supported");"GET"!==o&&"POST"!==o&&(c._method=o,o="POST"),!1!==r.processData&&(c=c?n(c):null),c&&"GET"==o&&(t+=(t.indexOf("?")>=0?"&":"?")+c,c=null),t+=(t.indexOf("?")>=0?"&":"?")+"_xdr=true&_cacheBust="+e.util.getId();var s=new window.XDomainRequest;return s.onload=function(){var t=s.responseText;if(r.progress&&r.progress(100),r.json)try{t=e.json.decode(t)}catch(e){return void a("Invalid json: "+t,200,s)}i(t,200,s)},s.onerror=function(){r.progress&&r.progress(100),a(s.responseText||"CORS_error",this.status||500,this)},s.onprogress=function(){},s.ontimeout=function(){},s.timeout=3e4,s.open(o,t,!0),s.send(c),s};return{get:t,post:r,request:i}}),filepicker.extend("files",function(){var e=this,t=function(t,n,o,i,a){var c=void 0===n.base64encode;c&&(n.base64encode=!0),n.base64encode=!1!==n.base64encode;var s=function(t){c&&(t=e.base64.decode(t,!!n.asText)),o(t)};r.call(this,t,n,s,i,a)},r=function(t,r,n,o,i){!0!==r.cache&&(r._cacheBust=e.util.getId()),e.ajax.get(t,{data:r,headers:{"X-NO-STREAM":!0},success:n,error:function(t,r,n){o("CORS_not_allowed"===t?new e.errors.FPError(113):"CORS_error"===t?new e.errors.FPError(114):"not_found"===t?new e.errors.FPError(115):"bad_params"===t?new e.errors.FPError(400):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(118))},progress:i})},n=function(t,r,n,o,i){if(!(window.File&&window.FileReader&&window.FileList&&window.Blob))return i(10),void e.files.storeFile(t,{},function(t){i(50),e.files.readFromFPUrl(t.url,r,n,o,function(e){i(50+e/2)})},o,function(e){i(e/2)});var a=!!r.base64encode,c=!!r.asText,s=new FileReader;s.onprogress=function(e){e.lengthComputable&&i(Math.round(e.loaded/e.total*100))},s.onload=function(t){i(100),n(a?e.base64.encode(t.target.result,c):t.target.result)},s.onerror=function(t){switch(t.target.error.code){case t.target.error.NOT_FOUND_ERR:o(new e.errors.FPError(115));break;case t.target.error.NOT_READABLE_ERR:o(new e.errors.FPError(116));break;case t.target.error.ABORT_ERR:o(new e.errors.FPError(117));break;default:o(new e.errors.FPError(118))}},c||!s.readAsBinaryString?s.readAsText(t):s.readAsBinaryString(t)},o=function(t,r,n,o,i,a){var c=n.mimetype||"text/plain";e.ajax.post(e.urls.constructWriteUrl(t,n),{headers:{"Content-Type":c},data:r,processData:!1,json:!0,success:function(t){o(e.util.standardizeFPFile(t))},error:function(t,r,n){i("not_found"===t?new e.errors.FPError(121):"bad_params"===t?new e.errors.FPError(122):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(123))},progress:a})},i=function(t,r,n,o,i,a){var c=function(t,r,n){i("not_found"===t?new e.errors.FPError(121):"bad_params"===t?new e.errors.FPError(122):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(123))},s=function(t){o(e.util.standardizeFPFile(t))};u(r,e.urls.constructWriteUrl(t,n),s,c,a)},a=function(t,r,n,o,i,a){var c=function(t,r,n){i("not_found"===t?new e.errors.FPError(121):"bad_params"===t?new e.errors.FPError(122):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(123))},s=function(t){o(e.util.standardizeFPFile(t))};n.mimetype=r.type,u(r,e.urls.constructWriteUrl(t,n),s,c,a)},c=function(t,r,n,o,i,a){e.ajax.post(e.urls.constructWriteUrl(t,n),{data:{url:r},json:!0,success:function(t){o(e.util.standardizeFPFile(t))},error:function(t,r,n){i("not_found"===t?new e.errors.FPError(121):"bad_params"===t?new e.errors.FPError(122):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(123))},progress:a})},s=function(t,r,n,o,i){if(t.files)return void(0===t.files.length?o(new e.errors.FPError(115)):l(t.files[0],r,n,o,i));e.util.setDefault(r,"location","S3"),r.filename||(r.filename=t.value.replace("C:\\fakepath\\","")||t.name);var a=t.name;t.name="fileUpload",e.iframeAjax.post(e.urls.constructStoreUrl(r),{data:t,processData:!1,json:!0,success:function(r){t.name=a,n(e.util.standardizeFPFile(r))},error:function(t,r,n){o("not_found"===t?new e.errors.FPError(121):"bad_params"===t?new e.errors.FPError(122):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(123))}})},l=function(t,r,n,o,i){e.util.setDefault(r,"location","S3");var a=function(t,r,n){"not_found"===t?o(new e.errors.FPError(121)):"bad_params"===t?o(new e.errors.FPError(122)):"not_authorized"===t?o(new e.errors.FPError(403)):(e.util.console.error(t),o(new e.errors.FPError(123)))},c=function(t){n(e.util.standardizeFPFile(t))};r.filename||(r.filename=t.name||t.fileName),u(t,e.urls.constructStoreUrl(r),c,a,i)},u=function(t,r,n,o,i){if(t.files&&(t=t.files[0]),!window.FormData||!window.XMLHttpRequest)e.iframeAjax.post(r,{data:t,json:!0,success:n,error:o});else{var a=new window.FormData;a.append("fileUpload",t),e.ajax.post(r,{json:!0,processData:!1,data:a,success:n,error:o,progress:i})}},p=function(t,r,n,o,i){e.util.setDefault(r,"location","S3"),e.util.setDefault(r,"mimetype","text/plain"),e.ajax.post(e.urls.constructStoreUrl(r),{headers:{"Content-Type":r.mimetype},data:t,processData:!1,json:!0,success:function(t){n(e.util.standardizeFPFile(t))},error:function(t,r,n){o("not_found"===t?new e.errors.FPError(121):"bad_params"===t?new e.errors.FPError(122):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(123))},progress:i})};return{readFromUrl:r,readFromFile:n,readFromFPUrl:t,writeDataToFPUrl:o,writeFileToFPUrl:a,writeFileInputToFPUrl:i,writeUrlToFPUrl:c,storeFileInput:s,storeFile:l,storeUrl:function(t,r,n,o,i){e.util.setDefault(r,"location","S3"),e.ajax.post(e.urls.constructStoreUrl(r),{data:{url:e.util.getFPUrl(t)},json:!0,success:function(t){n(e.util.standardizeFPFile(t))},error:function(t,r,n){o("not_found"===t?new e.errors.FPError(151):"bad_params"===t?new e.errors.FPError(152):"not_authorized"===t?new e.errors.FPError(403):new e.errors.FPError(153))},progress:i})},storeData:p,stat:function(t,r,n,o){var i=["uploaded","modified","created"];!0!==r.cache&&(r._cacheBust=e.util.getId()),e.ajax.get(t+"/metadata",{json:!0,data:r,success:function(e){for(var t=0;t=0?"&":"?")+"_cacheBust="+e.util.getId(),a(t,r)},i=function(){if(t.length>0){var e=t.shift();a(e.url,e.options)}},a=function(n,o){if(r)return void t.push({url:n,options:o});n+=(n.indexOf("?")>=0?"&":"?")+"plugin="+e.urls.getPlugin()+"&_cacheBust="+e.util.getId(),n+="&Content-Type=text%2Fhtml",e.comm.openChannel();var i;try{i=document.createElement('