{"id":13447209,"url":"https://github.com/Kloudless/file-picker","last_synced_at":"2025-03-21T17:30:56.831Z","repository":{"id":21096018,"uuid":"24396071","full_name":"Kloudless/file-picker","owner":"Kloudless","description":"The Kloudless File Picker is a file chooser and uploader for apps that integrates with 20+ cloud storage services with a few lines of code","archived":true,"fork":false,"pushed_at":"2021-10-05T21:37:48.000Z","size":8937,"stargazers_count":217,"open_issues_count":55,"forks_count":53,"subscribers_count":20,"default_branch":"master","last_synced_at":"2024-04-14T12:15:11.634Z","etag":null,"topics":["cloud-storage","file-explorer","file-picker","file-transfer","file-upload","file-uploader","javascript","kloudless","picker"],"latest_commit_sha":null,"homepage":"https://kloudless.com","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Kloudless.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.AGPL-3.0-only","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-09-24T01:24:12.000Z","updated_at":"2023-03-30T17:57:57.000Z","dependencies_parsed_at":"2022-08-31T12:12:06.557Z","dependency_job_id":null,"html_url":"https://github.com/Kloudless/file-picker","commit_stats":null,"previous_names":["kloudless/file-explorer"],"tags_count":30,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kloudless%2Ffile-picker","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kloudless%2Ffile-picker/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kloudless%2Ffile-picker/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Kloudless%2Ffile-picker/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Kloudless","download_url":"https://codeload.github.com/Kloudless/file-picker/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244838081,"owners_count":20518781,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["cloud-storage","file-explorer","file-picker","file-transfer","file-upload","file-uploader","javascript","kloudless","picker"],"created_at":"2024-07-31T05:01:10.988Z","updated_at":"2025-03-21T17:30:56.241Z","avatar_url":"https://github.com/Kloudless.png","language":"JavaScript","readme":"# Kloudless File Picker\n\n**Sign up for a free account at [https://kloudless.com](https://kloudless.com) to obtain\na Kloudless App ID to initialize the File Picker with.** The File Picker is built on\nour unified Storage API abstraction layer\n([Cloud Storage REST API docs here](https://developers.kloudless.com/docs/latest/storage)).\n\nThe [Kloudless](https://kloudless.com) File Picker is a JavaScript library\nthat allows your users to browse and select files and folders from the following\nstorage services:\n\n\u003ctable\u003e\n  \u003cthead\u003e\n    \u003ctr\u003e\u003cth colspan=\"4\"\u003eServices\u003c/th\u003e\u003c/tr\u003e\n  \u003c/thead\u003e\n  \u003ctbody\u003e\n    \u003ctr\u003e\u003ctd\u003eAdobe CQ5\u003c/td\u003e\u003ctd\u003eAlfresco Cloud\u003c/td\u003e\u003ctd\u003eAlfresco\u003c/td\u003e\u003ctd\u003eAmazon S3\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003eAzure Storage\u003c/td\u003e\u003ctd\u003eBox\u003c/td\u003e\u003ctd\u003eCMIS\u003c/td\u003e\u003ctd\u003eCitrix Sharefile\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003eDropbox\u003c/td\u003e\u003ctd\u003eEgnyte\u003c/td\u003e\u003ctd\u003eEvernote\u003c/td\u003e\u003ctd\u003eFTP\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003eGoogle Drive\u003c/td\u003e\u003ctd\u003eHubSpot Files\u003c/td\u003e\u003ctd\u003eJive\u003c/td\u003e\u003ctd\u003eOneDrive for Business\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003eOneDrive\u003c/td\u003e\u003ctd\u003eSMB\u003c/td\u003e\u003ctd\u003eSalesforce Files\u003c/td\u003e\u003ctd\u003eSharePoint Online\u003c/td\u003e\u003c/tr\u003e\n    \u003ctr\u003e\u003ctd\u003eSugarSync\u003c/td\u003e\u003ctd\u003eWebDAV\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003ctd\u003e\u003c/td\u003e\u003c/tr\u003e\n  \u003c/tbody\u003e\n\u003c/table\u003e\n\n### [Click here to visit our File Picker demo!](https://output.jsbin.com/tuwodin/27)\n\n\u003cp align=\"center\"\u003e\n  \u003cimg src=\"img/demo.gif\" width=\"650\" /\u003e\n\u003c/p\u003e\n\n## Table of Contents\n\n* [Usage](#usage)\n  * [Initializing a File Picker](#initializing-a-file-picker)\n    * [Import from a script tag](#import-from-a-script-tag)\n    * [Import from an ES6 module](#import-from-an-es6-module)\n    * [Launching the File Picker](#launching-the-file-picker)\n  * [File Picker Modes](#file-picker-modes)\n    * [Chooser](#chooser)\n      * [Dropzone](#dropzone)\n    * [Saver](#saver)\n  * [Configuration](#configuration)\n    * [Script tag](#script-tag)\n    * [Chooser and Saver](#chooser-and-saver)\n    * [Chooser Options](#chooser-options)\n    * [Saver Options](#saver-options)\n  * [Events](#events)\n  * [Methods](#methods)\n  * [Script tag example](#script-tag-example)\n  * [Dropzone](#dropzone-1)\n    * [Configuration](#configuration-1)\n    * [Methods](#methods-1)\n    * [Example](#example)\n* [File Picker with Vue](#file-picker-with-vue)\n* [File Picker with React](#file-picker-with-react)\n* [Browser Support](#browser-support)\n  * [Work with mobile devices](#work-with-mobile-devices)\n* [Migration Guide](#migration-guide)\n  * [From v1 to v2](#from-v1-to-v2)\n    * [New Layout and New Options to Customize the UI](#new-layout-and-new-options-to-customize-the-ui)\n    * [File Explorer Renamed to File Picker](#file-explorer-renamed-to-file-picker)\n    * [React and Vue Wrapper Options Configuration](#react-and-vue-wrapper-options-configuration)\n    * [Incompatible Configuration Options](#incompatible-configuration-options)\n  * [From v1.0.0 to v1.0.1](#from-v100-to-v101)\n* [Contributing](#contributing)\n  * [Requirements](#requirements)\n  * [Development](#development)\n    * [TypeScript Definition](#typescript-definition)\n  * [Build](#build)\n    * [Build Options](#build-options)\n  * [Testing](#testing)\n    * [Test in Legacy Microsoft Edge or Internet Explorer 11](#test-in-legacy-microsoft-edge-or-internet-explorer-11)\n* [Self-hosting](#self-hosting)\n  * [Hosting the File Picker Page](#hosting-the-file-picker-page)\n  * [Extending the File Picker Template](#extending-the-file-picker-template)\n* [Misc. Development Notes](#misc-development-notes)\n* [Security Vulnerabilities](#security-vulnerabilities)\n* [License](#license)\n* [Support](#support)\n* [Changelog](CHANGELOG.md)\n\n## Usage\n\n### Initializing a File Picker\n\nThe File Picker JavaScript library can be imported into web applications\nand launched when a user clicks an element.\n\n#### Import from a script tag\n\nInclude the Kloudless File Picker JavaScript library on your HTML page using\na script tag that points to our CDN:\n\n```html\n\u003cscript type=\"text/javascript\"\n src=\"https://static-cdn.kloudless.com/p/platform/sdk/kloudless.picker.js\"\u003e\u003c/script\u003e\n```\n\nThis exposes a global `Kloudless.filePicker` object you can use to initialize\na File Picker. Check out the Configuration Options section further below for\na full list of configuration options.\n\n```html\n\u003cscript type=\"text/javascript\"\u003e\n  var picker = window.Kloudless.filePicker.picker({\n    // File Picker initialization options here.\n    app_id: \"Your App ID\", // Get your own at https://kloudless.com\n  });\n\u003c/script\u003e\n```\n\n#### Import from an ES6 module\n\nYou can also install the File Picker package from NPM:\n\n```\nnpm install @kloudless/file-picker\n```\n\n```javascript\nimport filePicker from '@kloudless/file-picker';\n\nconst picker = filePicker.picker({\n  app_id: \"YOUR_APP_ID\"\n});\n```\n\n#### Launching the File Picker\n\nHere is a basic example of a button that launches the File Picker\ngiven the JavaScript above that creates a `picker` object.\n\n```html\n\u003cbody\u003e\n  \u003cbutton id=\"choose-files\"\u003eChoose Files\u003c/button\u003e\n\n  \u003cscript src=\"https://static-cdn.kloudless.com/p/platform/sdk/kloudless.picker.js\"\u003e\u003c/script\u003e\n  \u003cscript\u003e\n    var picker = window.Kloudless.filePicker.picker({ app_id: \"APP_ID\" });\n    picker.choosify(document.getElementById('choose-files'));\n  \u003c/script\u003e\n\u003c/body\u003e\n```\n\nThe HTML above adds a specific `id` to an element so that we\ncan reference it later in our JavaScript that launches the File Picker\nwhen the element is clicked. A more complete example is present\n[below](#script-tag-example) after the full list of configuration options\nas well as on our [demo page](https://output.jsbin.com/tuwodin/27).\n\nBe sure to serve the page via a web server, as pages opened via the\nfile URI scheme (`file://`) cannot receive postMessage messages\nfrom the `iframe` created to display the File Picker due to security\nconcerns.\n\n### File Picker Modes\n\nThe File Picker can be configured to either be a file [chooser](#chooser) to\nselect files and folders from cloud storage or the local computer, or a file\n[saver](#saver) to export a specific file  to cloud storage.\n\n#### Chooser\n\nThe Chooser allows your application to prompt a user to select files or a folder,\nand retrieves metadata about the files or folder selected.\nIt supports choosing files from the local machine as well as cloud storage.\nYour application can also upload files to users' cloud storage using the\n[Upload API endpoint](https://developers.kloudless.com/docs/v1/storage#files-upload-a-file)\nafter prompting users to select a folder to upload data to.\n\nThe Chooser is therefore a popular option for both importing files to your\napplication as well as exporting them to specific destinations in cloud storage.\n\n###### Dropzone\n\nThe Dropzone is a variety of the Chooser that opens when files are dragged and\ndropped into it rather than only when clicked. See the [Dropzone](#dropzone-1)\nsection for more information.\n\n#### Saver\n\nThe Saver allows your application to prompt a user to select a folder to save\na specific file to. This lets your application save some work over the Chooser\nby automatically handling the upload to cloud storage given a link to the file.\nHowever, only a single file is supported at a time.\n\nThe Saver returns metadata on the newly uploaded file to the application.\n\n### Configuration\n\nThe File Picker has several configuration options. Below, we've included\noptions that can be set on the library inclusion tag itself, options that apply\nto both the Chooser and Saver modes, and options that are specific to a\nparticular mode.\n\n#### Script tag\n\nThe following attributes can be set on the `\u003cscript\u003e` tag used to include the\nFile Picker JavaScript on the page.\n\n* `data-kloudless-object` : string\n\n  _Optional_. By default, the `filePicker` object will be exposed to \n  `window.Kloudless.filePicker`.\n\n  Specifies a different name for the `filePicker` object bound to `window`.\n  e.g. `data-kloudless-object=\"filePicker2\"` would make the filePicker\n  object accessible via `window.filePicker2`. Do not use the `async` attribute\n  on the script tag if this is used.\n\n#### Chooser and Saver\n\n* `app_id` : string\n\n  Chooser: _Required_\n\n  Saver: _Required_\n\n  The application ID is specific to the developer's application and is located\n  in the developer portal on the App Details page.\n\n* `element` : string or HTMLElement\n\n  Chooser: _Optional (default: null)_\n\n  Saver: _Optional (default: null)_\n\n  Specify a CSS selector string or DOM element to attach the File Picker to\n  instead of displaying the File Picker as a modal (the default). \n  If a string is provided, it will be used to retrieve the DOM element by using\n  [document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector).\n\n* `retrieve_token` : boolean\n\n  Chooser: _Optional (default: false)_\n\n  Saver: _Optional (default: false)_\n\n  This option will include [Bearer Tokens](https://developers.kloudless.com/docs/latest/authentication)\n  in addition to the other response data, to allow you to make further requests to the API\n  or save the OAuth Tokens for future use.\n\n  ```javascript\n  // Example response with an OAuth Token in the metadata.\n  [{\n    bearer_token: {\n      key: \"the_token\",\n    },\n    ...\n  }]\n  ```\n\n  Only File Pickers launched from Trusted Domains can make use of this option.\n  You can add a Trusted Domain on the App Details page.\n\n  In addition, care should\n  be taken to ensure no malicious JavaScript or XSS vulnerabilities are present\n  on the page, as the Bearer Token provides complete access to that user's account.\n\n* `persist` : string\n\n  Chooser: \"none\", \"local\", \"session\" (default: \"local\")\n\n  Saver: \"none\", \"local\", \"session\" (default: \"local\")\n\n  This option specifies how to persist connected account information, such as\n  Bearer tokens to access the Kloudless API.\n\n  * `local`: [localStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/localStorage)\n  * `session`: [sessionStorage](https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage)\n  * `none`: No storage. Data only persists in memory, within each File\n    Picker instance.\n\n  The File Picker will fall back to `local` if an invalid option is specified,\n  and fall back to `none` if either `localStorage` or `sessionStorage` are not\n  accessible.\n\n* `services` : array\n\n  Chooser: _Optional (default: ['file_store'])_\n\n  Saver: _Optional (default: ['file_store'])_\n\n  This option specifies which services to allow a user to explore. You can enumerate\n  the specific [services](https://developers.kloudless.com/docs/latest/core#introduction-supported-services) or\n  use a service group listed below as a shortcut.\n  The default is the `file_store` service group.  If you specify an empty array,\n  no services will show up.\n  \n  Service groups:\n  \n  * `file_store`: All File Storage services.\n  * `object_store`: All Object Storage services.\n  * `construction`: All Construction services.\n  * `all`: All storage services.\n\n* `account_management` : boolean\n\n  Chooser: _Optional (default: true)_\n\n  Saver: _Optional (default: true)_\n\n  If `false`, hides the Account menu entry in the dropdown. This can be\n  combined with the `tokens` option to ensure a user only browses a pre-defined\n  list of accounts and also does not disconnect any of the accounts. If account\n  disconnection is permitted, set `services` to `[]` rather than disabling the\n  `account_management` option.\n\n* `display_backdrop` : boolean\n\n  Chooser: _Optional (default: false)_\n\n  Saver: _Optional (default: false)_\n\n  If `true`, displays a shadow backdrop behind the File Picker, and prevents the\n  page body from scrolling.\n\n\n* `locale` : string\n\n  Chooser: _Optional (default: \"en\")_\n\n  Saver: _Optional (default: \"en\")_\n\n  The Kloudless File Picker supports i18n/l10n. You can specify any of the\n  following [ISO-639-1 codes](https://en.wikipedia.org/wiki/List_of_ISO_639-1_codes):\n\n  `ar`, `az`, `bs`, `cs`, `cy`, `da`, `de`, `el`, `en`, `es`, `et`, `fa`,\n  `fi`, `fr`, `he`, `hr`, `hu`, `hy`, `id`, `it`, `ja`, `ka`, `kk`, `km`,\n  `ko`, `lt`, `lv`, `mn`, `ms`, `nl`, `pl`, `pt`, `ro`, `ru`, `sk`, `sq`,\n  `sr`, `sr`, `sv`, `th`, `tr`, `uk`, `zh-CN`, `zh-TW`\n  \n  The locale is used to identify the \n  data to retrieve from either\n  the data provided in the `translations` option below or from the out-of-the-box\n  translation data in the [messages directory](src/picker/localization/messages).\n  If no translation data is found, the File Picker uses the `en` locale.\n\n* `translations` : string or object\n\n  Chooser: _Optional (default: \"\")_\n\n  Saver: _Optional (default: \"\")_\n  \n  This option specifies either an object with translation data or a URL\n  that returns the translation data as a JSON string. The `locale` option\n  indicates which locale's translation data to use. Any translation data\n  provided here overrides Kloudless' default translation data included in the\n  [messages directory](src/picker/localization/messages).\n  See [translations-suite-sample.json](dev-server/static/translations-suite-sample.json)\n  for an example of the translation file format.\n  Any strings not translated will default to the `en` locale's representation.\n\n* `dateTimeFormat` : string\n\n  Chooser: _Optional (default: \"MMMdHm\")_\n\n  Saver: _Optional (default: \"MMMdHm\")_\n\n  This option specifies a date-time format for the `locale` above.\n  Please refer to the `skeleton` values in the\n  [globalize JS module](https://github.com/globalizejs/globalize/blob/master/doc/api/date/date-formatter.md#using-open-ended-skeletons)\n  for the formats supported.\n\n* `create_folder` : boolean\n\n  Chooser: _Optional (default: true)_\n\n  Saver: _Optional (default: true)_\n\n  If `true`, the user will be able to create folders in their cloud storage\n  accounts.\n\n* `account_key` : boolean\n\n  This option is deprecated as OAuth 2.0 Tokens are used to authenticated accounts\n  now instead of Account Keys. Please use the `retrieve_token` option below instead.\n  Existing Account Keys can be converted to OAuth Tokens using\n  [this endpoint](https://developers.kloudless.com/docs/v0/storage#account-keys-account-key-oauth-token).\n\n* `keys` : array\n\n  This option is deprecated as OAuth 2.0 Tokens are used to authenticated accounts\n  now instead of Account Keys. Please use the `tokens` option below instead.\n  Existing Account Keys can be converted to OAuth Tokens using\n  [this endpoint](https://developers.kloudless.com/docs/v0/storage#account-keys-account-key-oauth-token).\n\n* `tokens` : array\n\n  Chooser: _Optional (default: [])_\n\n  Saver: _Optional (default: [])_\n\n  This option should list [OAuth 2.0 Tokens](https://developers.kloudless.com/docs/latest/authentication)\n  for accounts the File Picker should be initialized with. The File Picker will\n  make API requests for additional information on the accounts and display them\n  in the list of accounts the user has connected.\n\n  ```javascript\n  {\n    tokens: [\"abcdefghijklmn\", \"opqrstuvwxyz\"],\n    ... // other options\n  }\n  ```\n  \n* `enable_logout` : boolean (default: true)\n\n  If `true`, allows users to log out of their accounts, which deletes the account\n  from Kloudless servers. API requests will no longer be possible to the account.\n\n* `delete_accounts_on_logout` : boolean (default: false)\n    \n  If `false`, the File Picker only removes tokens from the storage configured\n  in `persist` option when users log out. If `true`, it also deletes the accounts \n  from the Kloudless server and invalidates the OAuth tokens.\n\n* `oauth` : function (default: _see below_)\n\n  Use this parameter to customize the query parameters used in the first leg of\n  the Kloudless OAuth flow when authenticating users.\n  A full list of parameters supported is available on the\n  [OAuth docs](https://developers.kloudless.com/docs/latest/authentication#oauth-2.0-first-leg).\n\n  By default, the `scope` the File Picker uses is\n  `\"\u003cservice_id\u003e:normal.storage \u003cservice_id\u003e:normal.basic\"`. Note that the\n  following options cannot be overridden for consistency or security reasons:\n\n  * `client_id`,\n  * `response_type`\n  * `redirect_uri`\n  * `origin`\n  * `state`\n\n  Set the value of the `oauth` option to a function that accepts a string.\n  The function will be called when a user attempts to connect an account, with\n  the string argument being the\n  [identifier](https://developers.kloudless.com/docs/latest/core#introduction-supported-services)\n  of the service the user is attempting to connect. For example, `gdrive`.\n\n  The function should return an object representing the attributes to\n  include as query parameters in the OAuth flow. Don't URL-encode the values;\n  the File Picker handles that. Here is an example that customizes the\n  OAuth permissions requested if a user attempts to connect a Google Drive\n  account, and also pre-fills the server URL if a user chooses to connect an FTP\n  account:\n\n  ```javascript\n  {\n    oauth: (service) =\u003e {\n      const authOptions = {};\n\n      switch (service) {\n        case 'gdrive':\n          // Ask for read-only access to Google Drive data instead.\n          authOptions.scope = 'gdrive.storage.\"https://www.googleapis.com/auth/userinfo.email https://www.googleapis.com/auth/drive.readonly\":raw';\n          // Pass additional query parameters to Google Drive.\n          authOptions.raw = {\n            'query_name': 'query_value'\n          };\n          break;\n        case 'ftp':\n          // Set a default domain when connecting an FTP account.\n          authOptions.form_data = {\n            domain: 'ftps://ftp.example.com:21',\n          };\n          break;\n      }\n\n      return authOptions;\n    },\n    ... // other options\n  }\n  ```  \n\n  If you're familiar with the configuration options accepted by the\n  [Kloudless Authenticator](https://github.com/Kloudless/authenticator#options),\n  the File Picker requires options returned in the same format that the\n  Authenticator accepts. For convenience, the following \n  [supported parameters](https://developers.kloudless.com/docs/latest/authentication#oauth-2.0-first-leg)\n  can be specified as objects as shown in the example above:\n\n  * `form_data` (converted to a URL-encoded JSON string)\n  * `custom_properties` (converted to a URL-encoded JSON string)\n  * `raw` (converted to the `raw[key]=value` format described in the docs)\n\n* `custom_style_vars` : object\n\n  This project uses LESS as a CSS pre-processor. Since LESS can be run in the\n  browser, we support overriding CSS global variables dynamically to customize\n  styling. For example, change the primary color by setting `main_color`:\n\n  ```js\n  {\n    custom_style_vars: {\n      main_color: \"black\"\n    }\n  }\n  ```\n\n  Please refer to [variables.less](./src/picker/css/variables.less) for the\n  full list of available variables. Most are related to aspects such as colors,\n  fonts, or dimensions. Specifying the `@` prefix for each variable is optional.\n\n  For further customization, we recommend forking this project and hosting\n  the resources on your own, since we don't guarantee backward-compatibility \n  when overriding undocumented variables.\n\n* `root_folder_id`: object\n\n  Chooser: _Optional (default: {})_\n\n  Saver: _Optional (default: {})_\n\n  This option is used to specify a specific folder as the root folder\n  for any existing account browsable via the File Picker. This is helpful for\n  scenarios where the user may not have access to the root or other high-level\n  folders but does have access to specific known folders within the account.\n  This option accepts a map of the Kloudless Account ID to the Kloudless Folder\n  ID in the format `{[account_id]: \"root_folder_id\"}`, as shown below:\n\n  ```js\n  {\n    1234: \"folder_abc1234\",\n    5678: \"folder_somefolder5678\"\n  }\n  ```\n\n  The example above sets the root folder to `folder_abc1234` for account\n  `1234` and `folder_somefolder5678` for the account `5678`.\n\n  When connecting or switching to an account that has a root folder ID\n  configured, the default folder opened will be the specified folder rather \n  than the usual root folder `root`. The File Picker UI won't enable navigation\n  outside of the chosen root folder, although it may be accessible to the user\n  via direct API requests. This configuration option should therefore not be\n  used to limit access for security purposes.\n\n  For existing accounts, be sure to also use the `tokens` attribute to specify\n  the Bearer tokens to use to browse the account. If `account_management` is\n  enabled (the default), the user may also connect new accounts. Since the\n  root folder ID is not possible to provide in advance until the newly\n  connected account's ID is known, please first listen for the\n  `addAccount` [event](#events), then perform API requests to determine\n  the ID of the root folder to display, and finally call the `picker.update()`\n  [method](#methods) with the updated configuration that includes the root\n  folder ID for the newly connected account within it:\n\n  ```javascript\n  let root_folder_id = {}; // Any existing root folder IDs\n  picker.on('addAccount', account =\u003e {\n    // Set `retrieve_token: true` in the config to retrieve the Bearer token\n    // to use in API requests to determine the right root folder ID, and\n    // then include that root folder ID below.\n    root_folder_id[account.id] = 'root';\n\n    picker.update({ root_folder_id });\n  });\n  ```\n  Here is an example of limiting users connecting SharePoint accounts to only\n  selecting files from within the primary document library of the main site\n  collection: [https://jsfiddle.net/kloudless/uwax8tqy/](https://jsfiddle.net/kloudless/uwax8tqy/).\n  \n  The example above uses a known folder ID based on a consistent location within the\n  SharePoint tenant, but most folders' IDs are random and must be obtained dynamically.\n  To obtain the Kloudless Folder ID for an upstream folder path, please\n  use the\n  [Encode Raw Data API endpoint](https://developers.kloudless.com/docs/latest/core#raw-data-and-the-pass-through-api-raw-data-kloudless-id)\n  or list the contents of the account, beginning at the `root`, until the required\n  folder's metadata is obtained.\n\n  Note: Search requests may still return results outside the root folder\n  specified for services that do not support the `parents`\n  [query parameter](https://developers.kloudless.com/docs/latest/storage#locate-files-search).\n\n* `close_on_success` : boolean (default: true)\n\n  Defaults to `true`, which closes the File Picker when all the selections in\n  the Chooser have been processed successfully, or when all the files in the\n  Computer view or the Saver have been uploaded successfully.\n\n  If `false`, the user will see a success message rather than the File\n  Picker closing.\n\n  For the Chooser and the Saver, if the `element` option is specified, this\n  option will always be `false`. For the Dropzone, this option is always `true`.\n\n#### Chooser Options\n\n* `multiselect` : boolean\n\n  Chooser: _Optional (default: false)_\n\n  This option allows a user to select multiple files or folders from cloud\n  storage or their local device. The Chooser will return a list of one or more\n  entries. Selecting multiple folders is not currently supported on mobile\n  devices.\n\n\n* `computer` : boolean\n\n  Chooser: _Optional (default: false)_\n\n  Dropzone: _Always true_\n\n  This option allows users to upload files directly from their computer.\n  Note: If you plan to build and host the file-picker on your own, this option\n  is only available for the [AGPL build](#build).\n\n\n  __Configuring the Chooser's Upload Location__\n\n  The Chooser will upload files to the developer's Upload Location.\n  The Upload Location can be set in the\n  [developer portal](https://developers.kloudless.com).\n  Under 'UI Tools' tab, click 'File Picker' and follow the instructions for \n  selecting a folder in a storage service such as Amazon S3. All local files\n  from a user will be uploaded there.\n\n* `link` : boolean\n\n  Chooser: _Optional (default: false)_\n\n  If `true`, generates a link to the selected file(s). The link will be provided\n  in the `link` key of the response sent to the `success` event. For asynchronous\n  requests, the result of the [Kloudless Task](https://developers.kloudless.com/docs/latest/core#asynchronous-requests-and-the-task-api)\n  will contain the link instead.\n\n  Use with the `copy_to_upload_location` option to generate a link to the newly\n  copied file.\n\n  The Kloudless File Picker will fire the `error` event if the link\n  generation fails.\n\n  ```javascript\n  // Success event result when `link` is true:\n  [{\n    \"link\": \"https://\u003cthe file link\u003e\",\n    ...\n  }]\n  ```\n\n* `link_options` : Object\n\n  Chooser: _Optional (default: {})_\n\n  The `link_options` object provides parameters to use when the File Picker\n  creates links. See the\n  [documentation for creating links](https://developers.kloudless.com/docs/latest/storage#links-create-a-link)\n  for a full list of the possible options available.\n  Note that links to selected files are only created if the `link`\n  configuration option is set to `true`. In addition, files with the\n  `downloadable` attribute set to `false` cannot be downloaded so\n  they cannot be selected if `link_options.direct` is `true`.\n\n  For example:\n\n  ```javascript\n  {\n    link_options: {\n      direct: true,\n      expiration: \"2020-10-12T00:00:00\"\n    },\n    ... // other options\n  }\n  ```\n\n* `copy_to_upload_location` : string\n\n  Chooser: _Optional (default: null)_\n\n  If this option is set, it will copy any file or non-root folder selected by\n  the user from cloud storage to the location that files uploaded from the\n  user's computer are placed in.\n\n  Since the file must be able to be downloaded for this to occur, only files\n  with the `downloadable` attribute set to `true` can be selected when this\n  option is enabled. When copying folders, the non-downloadable files will\n  be skipped.\n\n  An Upload Location must be configured via the developer portal to make use of\n  this option.\n\n  This option accepts two values:\n  * `'async'`: Triggers an asynchronous copy and immediately returns a Task ID\n    in the `success` event callback that can be checked using the\n    [Kloudless Task API](https://developers.kloudless.com/docs/latest/core#asynchronous-requests-and-the-task-api)\n    for the copied file or folder's metadata.\n\n    The Kloudless Task API returns a Task object that includes progress\n    information until the task finishes.  \n    When the task finishes, the API endpoint returns\n    [File](https://developers.kloudless.com/docs/latest/storage#files)\n    or [Folder](https://developers.kloudless.com/docs/latest/storage#folders)\n    object instead.  \n    If the task fails, the endpoints returns an\n    [Error](https://developers.kloudless.com/docs/latest/core#error-handling-error-message-format).\n\n    Here is an example of polling for the result of a task using jQuery:\n    ```javascript\n      function pollingTask(taskId, accountToken, delay) {\n        return new Promise((resolve, reject) =\u003e {\n          setTimeout(() =\u003e {\n            $.ajax({\n              url: `https://api.kloudless.com/v1/accounts/me/tasks/${taskId}`,\n              headers: { Authorization: `Bearer ${accountToken}` },\n            }).done(resolve).fail(reject);\n          }, 5000);  // Poll every 5 seconds\n        });\n      }\n\n      picker.on('success', async (results) =\u003e {\n        // Assume the user only selects one item.\n        const [\n          {\n            id: taskId,\n            // Should enable `retrieve_token` option to get bearer_token.\n            bearer_token: { key: accountToken },\n          },\n        ] = results;\n        try {\n          let response = await pollingTask(taskId, accountToken);\n          while (response.id === taskId) {\n            // Task has not finished yet, so keep polling.\n            response = await pollingTask(taskId, accountToken);\n          }\n          // Task has finished.\n          console.log(response);\n        } catch (jqXHR) {\n          if (jqXHR.responseJSON) {\n            // Kloudless API Server returned an error.\n            console.error(response.responseJSON);\n          }\n        }\n      });\n    ```\n  * `'sync'`: Triggers a synchronous API request to copy the file or folder and\n    polls till the copying is complete. The `success` event callback receives\n    the newly uploaded file or folder's metadata.\n\n  The deprecated `true` option is only available for copying files and will\n  return the new file's hypothetical metadata even though the copy has not yet\n  completed. Please migrate to using `'sync'` instead for similar behavior with\n  a guarantee that the copy is successful.\n\n  The Kloudless File Picker will fire the `error` event if the copy\n  operation is not completely successful.\n\n* `upload_location_account` : string\n\n  Chooser: _Optional (default: null)_\n\n  If multiple Upload Locations are configured via the developer portal, this\n  specifies the Account ID of the Upload Location to use. This option is not\n  required if only one Upload Location is configured. The Account ID is a number\n  that can be found in the File Picker Upload Locations section of the\n  [Developer Portal](https://developers.kloudless.com/applications/*/ui-tools/file-picker) page.\n  `upload_location_folder` must also be provided.\n\n* `upload_location_folder` : string\n\n  Chooser: _Optional (default: null)_\n\n  If multiple Upload Locations are configured via the developer portal, this\n  specifies the Folder ID of the Upload Location to use. This option is not required\n  if only one Upload Location is configured. The Folder ID is an encoded string that\n  can be found on the File Picker Upload Locations section of the\n  [Developer Portal](https://developers.kloudless.com/applications/*/ui-tools/file-picker).\n  The ID of a sub-folder may be specified if the option is enabled in the\n  Developer Portal. `upload_location_account` must also be provided if more than\n  one upload location exists.\n\n* `uploads_pause_on_error` : boolean\n\n  Chooser: _Optional (default: true)_\n\n  If `true`, uploads using the Computer option will pause if errors are encountered,\n  giving the user the option to retry the upload by clicking 'Resume'. The user could\n  also remove the file that is failing to upload from the queue.\n  If `false`, the file that encounters errors will be skipped and excluded from the\n  list of files returned in the `success` callback.\n\n* `types` : array\n\n  Chooser: _Default: ['all']_\n\n  This option specifies which types of elements the File Picker will show to the\n  user. You can filter based on file extension or by the following categories:\n\n  * `all` This configures the File Picker to show all file types and folders.\n  The user can select either files or folders. Do not combine with other options.\n\n  * `folders` This configures the File Picker to gray out files and show folders.\n  The user can only select folders.\n\n  * `files` This configures the File Picker to show all file types. The user can\n  only select files.\n\n  * `text`\n\n  * `documents`\n\n  * `images`\n\n  * `videos`\n\n  * `audio`\n\nThe categories will be translated to the corresponding file extensions and MIME\ntypes internally. Check `TYPE_ALIAS` and `MIME_TYPE_ALIAS` in\n[constants.js](src/picker/js/constants.js) for the specific file extensions\nand MIME types mapped to.\n\nYou can also specify file extensions as well as MIME types by including them\nin the array without the period (`.`) prefix. For example, \n`['pdf', 'jpg', 'jpeg', 'png', 'application/vnd.google-apps.document']`.\n\nInclude `''` to allow files with the MIME type `application/octet-stream` or\nwithout a file extension to be selected.\n\n* `max_size` : number\n\n  Chooser: _Optional (default: 0)_\n\n  The maximum size (in bytes) of files that can be selected, or uploaded in the\n  case of local uploads via the Computer option. This limit applies per file\n  selected, and not collectively.\n\n  Set to `0` to disable this limit.\n\n  Files with an unknown size, such as Google Docs, can still be selected\n  regardless of this option.\n\n\n#### Saver Options\n\n* `files` : array\n\n  Saver: _Optional (default: [])_\n\n  This option should list files for the File Picker to save. The format\n  should be an array of Javascript Objects containing a file url and name.\n  You can specify up to 100 files. Each file will be uploaded via the Kloudless\n  API's [upload endpoint](https://developers.kloudless.com/docs/latest/storage#files-upload-a-file),\n  using the `url` attribute.\n\n  ```javascript\n  {\n    files: [{\n      url: \"http://\u003cyour image url\u003e\",\n      name: \"filename.extension\"\n    }, {\n      url: \"http://\u003cyour image url\u003e\",\n      name: \"filename.extension\"\n    }],\n    ... // other options\n  }\n  ```\n\n### Events\n\n* `success(results)`\n\n  Fired when the user's selections in the Chooser are processed successfully, or\n  files are uploaded successfully via the Chooser's Computer option or Saver.  \n  The `success` event is still fired even if only part of the items were\n  successfully chosen or saved.\n\n  `results` is an array of [File](https://developers.kloudless.com/docs/latest/storage#files)\n  or [Folder](https://developers.kloudless.com/docs/latest/storage#folders)\n  objects that were successfully selected.\n\n  When `copy_to_upload_location` is set to `async`, `results` will instead be\n  an array of Task objects returned by the\n  [Kloudless Task API](https://developers.kloudless.com/docs/latest/core#asynchronous-requests-and-the-task-api).\n\n  The File Picker closes once this event has triggered.\n\n* `cancel()`\n\n  Fired if the user decides to cancel an operation. The File Picker will\n  be closed on cancellation.\n\n* `error(results)`\n\n  Fired when any of the selections fail to process or any of the\n  files being uploaded fail to upload successfully.  \n  The `error` event is still fired even if only part of the items failed to\n  be chosen or saved.\n\n  `results` is an array of failed objects. The object structure varies based\n  on usage. For the selections in the Chooser, the object is a\n  [File](https://developers.kloudless.com/docs/latest/storage#files)\n  or [Folder](https://developers.kloudless.com/docs/latest/storage#folders)\n  object.\n\n  For uploads via the Chooser's Computer option or Saver, the object is the\n  same as that for the `startFileUpload` event mentioned below.\n\n  An additional key, `error`, is added to the object metadata and includes\n  the error returned from the\n  [Kloudless API](https://developers.kloudless.com/docs/latest/core#error-handling-error-message-format)\n  describing why the operation failed.\n\n  Here is an example of the `error` object:\n  ```json\n  {\n    \"status_code\": 404,\n    \"message\": \"File not found: 1D-QuGwx7acbeGQ3STSCphysJsQs8YHJR\",\n    \"error_code\": \"not_found\",\n    \"id\": \"9b62d9d8-7bc7-495b-b97a-33b43720274d\"\n  }\n  ```\n\n\n* `open()`\n\n  Fired when the File Picker is displayed to the user. This occurs when\n  the Chooser or Saver are opened.\n\n* `close()`\n\n  Fired when the File Picker is hidden from the user. This occurs when\n  the File Picker is closed. This could be due to either a user action,\n  such as choosing files or cancelling, or due to the `close()` method\n  being called (not to be confused with this `close` event handler).\n  The `success` or `cancel` events will also be fired if appropriate.\n\n* `selected(results)`\n\n  Fired when the user selects files or folders from the\n  File Picker, but before the list is sent to the Kloudless API for additional\n  processing. This means this event fires before the `success` event,\n  and allows you to perform any action while waiting to get the final list.\n\n  If `copy_to_upload_location` and `link` are both disabled, then this event is\n  equivalent to the `success` event (since nothing needs to happen on the\n  server after the selections are made), so this event serves no purpose then.\n\n  `results` is an array of [File](https://developers.kloudless.com/docs/latest/storage#files)\n  or [Folder](https://developers.kloudless.com/docs/latest/storage#folders)\n  objects.\n\n  This event is not fired when the user uses the Chooser's Computer option or\n  the Saver. See `startFileUpload` and `finishFileUpload` for events fired\n  in those cases.\n\n* `addAccount(account)`\n\n  Fired when a user successfully connects an account.\n  `account` is an object containing the account ID, name, and service ID.\n\n  Here is an example:\n  ```json\n  {\n    \"id\": 123456,\n    \"name\": \"user@domain.com\",\n    \"service\": \"gdrive\"\n  }\n  ```\n\n* `deleteAccount(accountId)`\n\n  Fired when a user successfully removes an account.\n\n* `startFileUpload(file)`\n\n  Fired when a file upload starts, or is requested to be retried by a user\n  after encountering errors (see the `uploads_pause_on_error` option).\n  This event is only fired when the user uploads a file via the Chooser's\n  Computer option or the Saver. \n\n  For the Chooser's Computer option, the `file` object has the following\n  attributes:\n  * `id` A randomly generated ID.\n  * `name` The uploaded file's name.\n  * `size` The uploaded file's size.\n  * `mime_type` The uploaded file's MIME type.\n\n  Here is an example:\n  ```json\n  {\n    \"id\": \"o_1efeta5ej5ac1v4t139e39l1ldka\",\n    \"mime_type\": \"image/jpeg\",\n    \"name\": \"15224125762.jpeg\",\n    \"size\": 9834\n  }\n  ```\n\n  For the Saver, the `file` object has the following attributes instead:\n  * `url` The file URL specified in the Saver's launch options.\n  * `name` The file name specified in the Saver's launch options.\n\n  Here is an example:\n  ```json\n  {\n    \"url\": \"https://s3-us-west-2.amazonaws.com/static-assets.kloudless.com/static/kloudless-logo-white.png\",\n    \"name\": \"kloudless-logo.png\"\n  }\n  ```\n\n  This event is fired once per file and not per uploaded chunk.\n\n* `finishFileUpload(file)`\n\n  Fired when a file upload completes successfully (once per file being\n  uploaded). The `file` object contains the same information as provided to\n  the `startFileUpload` event above, with an additional key `metadata`\n  whose value is the resulting [File](https://developers.kloudless.com/docs/latest/storage#files).\n\n  This event is only fired when the user uploads a file via the\n  Chooser's Computer option or the Saver.\n\n* `logout()`\n\n  Fired when the user clicks the logout link in the File Picker, which\n  clears the local state of accounts connected to the File Picker.\n\n* `drop()`\n\n  Fired when drops files into Dropzone.\n\n### Methods\n\n* `filePicker.picker(options)`\n\n  You can initialize a Kloudless File Picker using the options mentioned above.\n\n* `filePicker.getGlobalOptions()`\n\n  Get [build options](#build-options). These are options configured when\n  the File Picker JavaScript library was initially built. See the\n  [Self-Hosting](#self-hosting) section for more information.\n\n* `filePicker.setGlobalOptions(buildOptions)`\n\n  Change [build options](#build-options) during run-time. The widget is\n  configured to work with default values, so these options should only be set\n  when needed.\n\n* `picker.choose()`\n\n  This method allows you to launch a Chooser.\n\n* `picker.choosify(element)`\n\n  This method binds a click handler that launches the Chooser to the DOM element.\n\n* `picker.save(files)`\n\n  This method allows you to launch a Saver. See *Saver Options* for more information\n  on the format for `files`.\n\n* `picker.savify(element, files)`\n\n  This method binds a click handler that launches the Saver for `files` to the\n  DOM element.\n\n* `picker.on(event, callback)`\n\n  Invokes a callback method on a particular event. See the `Events` section above\n  for a list of event names, as well as the arguments the corresponding callback\n  methods will be invoked with.\n\n* `picker.close()`\n\n  This method closes the File Picker window.\n\n\n* `picker.update(options)`\n\n  Updates the configuration options the File Picker was initialized with. The\n  File Picker will immediately begin using the new configuration.\n  `options` is an Object with the new configuration. Not all options can be\n  updated in this manner. The following are not supported:\n\n  * `app_id`\n  * `types`\n  * `services`\n  * `persist`\n  * `create_folder`\n  * `account_key`\n  * `custom_style`\n  * `custom_css` (deprecated)\n  * `locale`\n  * `element`\n  * `max_size`\n  \n* `picker.logout(deleteAccount=false)`\n\n  Removes all authentication tokens for the accounts connected to the File \n  Picker as configured via the `persist` option. If `deleteAccount` is set \n  to `true`, it also deletes the accounts from the Kloudless server and \n  invalidates the OAuth tokens, rendering them unusable and the accounts\n  inaccessible.\n     \n  This method isn't impacted by the `delete_accounts_on_logout` option. \n\n* `picker.destroy()`\n  \n  Destroy the file picker instance. It includes closing the file picker, \n  removing the EventListener, and removing the DOM including the file picker\n  iframe. \n  \n  This method won't clean up localStorage/sessionStorage, so the \n  authentication tokens won't be removed.\n  \n\n### Script tag example\n\nTo start using the File Picker, simply include the JavaScript file in your\nHTML file. You can then create an element on the page to launch the File Picker.\n\n```html\n\u003cbody\u003e\n  \u003cbutton id=\"file-picker-button\"\u003eOpen File Picker\u003c/button\u003e\n  \u003cscript type=\"text/javascript\" src=\"https://static-cdn.kloudless.com/p/platform/sdk/kloudless.picker.js\"\u003e\u003c/script\u003e\n  \u003cscript type=\"text/javascript\"\u003e\n      // File Picker initialization JS here.\n  \u003c/script\u003e\n\u003c/body\u003e\n```\n\nThe next step is to customize the File Picker according to the developer's needs.\nIn this example, we've decided to disable multiselect, return links, and allow for\na few types of files.  All of this is contained within the initialization.\n\n```javascript\n// File Picker initialization JS\nvar picker = window.Kloudless.filePicker.picker({\n  app_id: 'YOUR_APP_ID',\n  multiselect: false,\n  link: true,\n  types: ['images', 'documents', 'text']\n});\n```\n\nThe final step is to launch the File Picker and handle the events returned from\nthe File Picker based on a user's actions.\n\n**[Visit our demo of the File Picker!](https://output.jsbin.com/tuwodin/27)**\n\n```javascript\n// When a user successfully selects or saves a file\npicker.on('success', function(files) {\n  // files is an array of JS objects that contain file metadata.\n  console.log('Successfully selected files: ', files);\n});\n\n// When a user cancels the File Picker\npicker.on('cancel', function() {\n  console.log('File selection cancelled.');\n});\n\n// Launching the File Picker to choose when a user clicks the 'Open File Picker'\n// button.\npicker.choosify(document.getElementById('file-picker-button'));\n\n// In addition, you can launch the File Picker programmatically with choose()\npicker.choose();\n\n// Launching the Picker to save when a user clicks the 'Open File Picker' button\n// Note: you can pass in an array of files instead of using the configuration\n// option\nvar files = [{\n  url: 'http://\u003cyour image url\u003e',\n  name: 'filename.extension'\n}, {\n  url: 'http://\u003cyour image url\u003e',\n  name: 'filename.extension'\n}];\n\npicker.savify(document.getElementById('file-picker-button'), files);\n\n// In addition, you can launch the File Picker programmatically with save()\nvar files = [{\n  url: 'http://\u003cyour image url\u003e',\n  name: 'filename.extension'\n}, {\n  url: 'http://\u003cyour image url\u003e',\n  name: 'filename.extension'\n}];\n\npicker.save(files);\n```\n\n### Dropzone\n\nThe Dropzone is a variety of the Chooser that allows users to drop files into\nit from their Computer rather than only click on it to launch the File Picker.\nIt opens in place when files are dropped into it.\n\nNote: If you plan to build and host the file-picker on your own, the Dropzone\nis only enabled for the [AGPL build](#build).\n\n#### Configuration\n\nThe configuration is similar to the Chooser's, but requires the `element` option\nto indicate where to display the Dropzone, as described below. In addition, the\n`computer` option is always set to `true`, and an Upload Location must be\nconfigured as described for the Chooser.\n\n* `element` : string or HTMLElement\n\n  Chooser: _Required_\n\n  The DOM element to bind the Dropzone to. If a CSS selector string is provided,\n  it will be used to retrieve the DOM element by using\n  [document.querySelector](https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelector).\n  The drop zone will render a 600px * 100px area for the user to drag and drop\n  files in. The area's width will adjust automatically when the viewport\n  width is lower than 600px.\n\n#### Methods\n\n* `filePicker.dropzone(options)`\n\n  Initialize a Dropzone using the options mentioned above.\n\n* `dropzone.on(event, callback)`\n\n  See `picker.on(event, callback)` for more information.\n\n* `dropzone.close()`\n\n  See `picker.close()` for more information.\n\n#### Example\n\n[Visit our JSBin example of the Dropzone!](https://output.jsbin.com/tariday)\n\nHTML\n\n```html\n\u003cdiv id=\"dropzone\" style=\"width: 600px; height: 100px;\"\u003e\u003c/div\u003e\n```\n\nJavaScript\n\n```javascript\nvar dropzone = window.Kloudless.filePicker.dropzone({\n  app_id: 'Your App ID',\n  element: '#dropzone',\n  multiselect: true, // To upload more than 1 file.\n\n  // Chooser options below:\n  computer: true,\n  link: true,\n  services: ['all'],\n  types: ['all'],\n});\n\n// All of the Chooser's events are supported.\n// For example:\ndropzone.on('success', function(files) {\n  console.log('Successfully selected files: ', files);\n});\n\n// See the File Picker's Example section for other events.\n```\n\n## File Picker with Vue\n\nSee [File Picker with Vue](./README.vue.md).\n\n## File Picker with React\n\nSee [File Picker with React](./README.react.md).\n\n## Browser Support\n\n* Chrome 56+\n* Firefox 56+\n* IE 11+\n* Edge 12+\n* Safari 8+\n* Opera 49+\n\n### Work with mobile devices\nTo use the Kloudless File Picker on devices with narrow screens, please add a\n[Viewport meta tag](https://developer.mozilla.org/en-US/docs/Mozilla/Mobile/Viewport_meta_tag)\nto the web page launching the File Picker. This ensures the File Picker uses styling\nappropriate for mobile screen sizes.\n\nThe meta tag assumes that your entire web page renders well in narrow screens \nsince it applies to your page as a whole and not just the File Picker.\nPlease test out your page's usability if you are adding the meta tag for the\nfirst time.\n\nHere is an example meta tag:\n\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1\"\u003e\n\nIf your page benefits from preventing some devices such as iPhones from\nzooming in on input fields, you can also add in the `user-scalable=no` option \nas shown below. Input fields such as `\u003cinput\u003e` and `\u003cselect\u003e` are used in the\nFile Picker as well.\n\n    \u003cmeta name=\"viewport\" content=\"width=device-width, initial-scale=1, user-scalable=no\"\u003e\n\n\n## Migration Guide\n\n### From v1 to v2\n\n#### New Layout and New Options to Customize the UI\n\nv2 represents a new layout and set of options for the File Picker, including:\n* A completely new theme for the UI with improved responsiveness, clearer HTML\n  and CSS structure with consistent naming conventions, and several bug-fixes. \n* A documented format for customizing UI styling such as colors and fonts\n  without forking the entire project.\n\nProvided your application isn't already customizing styling by using the\n`custom_css` option as detailed below, it will automatically begin using the\nnew version.\n\n#### File Explorer Renamed to File Picker\n\nThe File Explorer has been renamed to the File Picker to improve clarity.\nThe entire JS namespace, as well as any relevant method, variable, or\nconfiguration option names, have been transitioned from referencing an\n\"explorer\" to a \"picker\", while preserving backwards-compatibility.\n\nHere is a table to assist with transitioning previously publicly documented\nnames to their newer counterparts:\n  \n  Description | Old Name | New Name\n  ---|---|---\n  namespace | window.Kloudless.fileExplorer | window.Kloudless.filePicker\n  method | explorer() | picker()\n  global option | explorerUrl | pickerUrl\n  environment variable | EXPLORER_URL | PICKER_URL\n  script tag URL | https://static-cdn.kloudless.com/p/platform/sdk/kloudless.explorer.js | https://static-cdn.kloudless.com/p/platform/sdk/kloudless.picker.js\n\nForked projects that are migrating to v2 should take care to replace names\nsimilarly.\n\n#### React and Vue Wrapper Options Configuration\n\nPreviously, `getGlobalOptions` and `setGlobalOption` were imported from\n`@kloudless/file-picker` as shown below:\n\n```javascript\nimport filePicker from '@kloudless/file-picker';\n\nfilePicker.getGlobalOptions()\nfilePicker.setGlobalOptions({...})\n```\n\nNow, they can be imported from `@kloudless/file-picker/react`,\nor `@kloudless/file-picker/vue`, depending on the framework in use:\n\n```javascript\nimport { setGlobalOptions, getGlobalOptions } from '@kloudless/file-picker/react';\n// Or use the following syntax for VueJS:\n// import { setGlobalOptions, getGlobalOptions } from '@kloudless/file-picker/vue';\n\ngetGlobalOptions()\nsetGlobalOptions({...})\n```\n\n#### Incompatible Configuration Options\n\nBelow are some options that will no longer be effective, or will force the\nprevious version to continue to load instead, to maintain compatibility.\n\n* `custom_css` : string\n\n  Chooser: _Optional (default: null)_\n\n  Saver: _Optional (default: null)_\n\n  This option is deprecated and no longer supported in the latest versions\n  of the File Picker. Using this option will result in the File Picker\n  reverting to a previous layout that supported this option.\n\n  Refer to the `custom_style_vars` option to customize styling instead.\n  Alternatively, you may clone this project and self-host it to customize the\n  UI more extensively.\n  \n  **Previous Notes**\n\n  `custom_css` is an optional attribute that accepts a URL to a stylesheet for\n  the File Picker to load to override or customize styling.\n  Supports `(http|https)://domain.com/path/to.css`, `//domain.com/path/to.css`, \n  and `/path/to.css` formats.\n\n  To use the `custom_css` option, the domain the File Picker is launched from\n  must be added to the application's list of\n  [Trusted Domains](https://developers.kloudless.com/applications/*/details#trusted-domains).\n\n### From v1.0.0 to v1.0.1\n\nWhen using the script tag, the target exposed has been updated from\n`window.Kloudless` to `window.Kloudless.fileExplorer` to better scope our UI\ntools. All the exports under `window.Kloudless` are deprecated and have been\nmoved to `window.Kloudless.fileExplorer`.\n\n## Contributing\n\nContributions are welcome and appreciated. We'd love to discuss any ideas you\nhave to improve or extend the File Picker. We recommend\ncontacting us at [support@kloudless.com](mailto:support@kloudless.com)\nfirst for major modifications that you would like merged in so we can\noffer feedback on its implementation.\n\n### Requirements\n\nInstall [Node.js](https://nodejs.org/en/download/)\n(`sudo apt-get install nodejs` or equivalent)  \nMake sure you have nodejs \u003e= 10.16.0 and npm \u003e= 6.9.0.\nThen run the following commands:\n\n    npm ci\n    npm run install-deps\n\nTo develop Vue or React wrapper, you might want to install the\ncorresponding storybook:\n\n    npm ci --prefix=storybook-vue    # for Vue\n    npm ci --prefix=storybook-react  # for React\n\n### Development\n\nUse the following command to set a Kloudless App ID and run the local\ndevelopment server:\n\n```bash\nKLOUDLESS_APP_ID=\u003cyour_app_id\u003e npm run dev\n```\n\nThe File Picker that launches on the test page uses the App ID to\nconnect accounts. It must therefore be the ID of a valid Kloudless\nApplication on the Kloudless API server the File Picker accesses.\n\nBy default, the development server points to `https://api.kloudless.com`.\nHowever, you can point it to an alternate Kloudless API server using the\n`BASE_URL` environment variable [build option](#build-options) as shown below.\n\n```bash\n# Export this environment variable before the `npm run dev` command above.\nexport BASE_URL=\u003cyour_kloudless_api_server_url\u003e\n```\n\nThe development server supports automatically rebuilding the source files\nwhenever changes are saved. However, hot reloading scripts is not supported\nyet; you will need to reload the page to view your changes.\n\n#### TypeScript Definition\n\nBe sure to update **src/loader/js/interface.d.ts** if the corresponding\ninterface is changed.\n\n### Build\n\nThe command below generates a minified production build at `/dist`.\n\n```bash\nnpm run build\n```\n\nHere is an explanation of the `dist` folder's structure:\n\nFolder | Purpose\n---|---\n`loader` | Contains the script that an application includes to load the File Picker.\n`picker` | Contains the File Picker assets that the `loader` loads in an iframe. Only customize this when [self-hosting](#self-hosting) the File Picker.\n\nThe above command generates a build licensed under MIT by default. If you want\nto self-host the File Picker, please note that the Computer option and\nthe Dropzone are only available in an AGPLv3 licensed build. For more details,\nrefer to the [License](#license) section. To get an AGPLv3 licensed build, run\n\n```bash\nnpm run build:agpl\n```\n\n, or customize your build by providing the [build option](#build-options)\n`BUILD_LICENSE=AGPL`.\n\n#### Build Options\n\nThe options below can be set during the build process as environment variables\nto customize the build, or sometimes at run-time as well.\n\nBuild-time Env Var | Run-time option | Description | Default\n---|---|---|---\n`BASE_URL` | `baseUrl` | URL to the Kloudless API Server | https://api.kloudless.com\n`PICKER_URL` | `pickerUrl` | The URL that the loader loads the file picker iframe from. | https://static-cdn.kloudless.com/p/platform/file-picker/v2/index.html\n`BUILD_LICENSE` | N/A | `MIT` or `AGPL`. See the [Build](#build) section. | MIT\n\nCheck out the [Self-hosting](#self-hosting) section below for an example\nthat changes the `PICKER_URL` in order to self-host a customized fork\nof the File Picker.\n\nIn addition, here is an example that directs API requests from the File Picker\nto an alternate Kloudless server:\n\n```\nBASE_URL=\u003cyour_kloudless_api_server_url\u003e npm run build\n```\n\n### Testing\n\nTo test the build generated by `npm run build`, run the following command:\n\n```bash\nKLOUDLESS_APP_ID=\u003cyour_app_id\u003e npm run dist-test\n```\n\nTo test the TypeScript definition file, run the following command:\n```bash\nnpm run test:ts\n```\n\n#### Test in Legacy Microsoft Edge or Internet Explorer 11\n\nMicrosoft provides\n[Windows 10 virtual machines](https://developer.microsoft.com/en-us/microsoft-edge/tools/vms/)\nthat can be used to test the File Picker in Legacy Microsoft Edge and Internet\nExplorer 11. Note that the development server won't be accessible at\n`http://localhost:3000` by default because `localhost` translates to `127.0.0.1`\nwhich points to the VM itself instead of the host running the development\nserver. To work around this, determine the actual IP address of the host running\nthe development server, such as `10.0.2.2` when using VirtualBox, and edit\n`C:\\windows\\system32\\drivers\\etc\\hosts` as an Administrator to add a record\nthat maps `localhost` to that IP.\n\n## Self-hosting\n\nSelf-hosting the File Picker is one way to customize all aspects of the\nFile Picker's layout, styling, and functionality beyond what the\nconfiguration and theming options provide.\n\nYou can fork the File Picker to make the changes you need before\n[building](#build) the File Picker, which results in a JS file at\n`dist/loader/loader.min.js`. This file must be included in any page you would\nlike to use the File Picker on. It serves as a light-weight wrapper to load\nthe actual File Picker page via an iframe.\n\nBoth the loader file and the rest of the File Picker's structure are discussed\nin more detail in the [Build](#build) section above.\n\n### Hosting the File Picker Page\n\nThe build contains an `picker` folder which includes the actual\nHTML and functionality of the widget. By default, this is hosted by Kloudless.\n\nIf you would like to host this page yourself to customize the core File Picker\nsource code or styles, follow the steps below:\n\n1. Rebuild the assets while setting `PICKER_URL` to specify the File Picker\n   page URL. For example, if you'd like to host the File Picker assets at\n   `https://example.com/kloudless/index.html`, run the following command:\n\n    ```bash\n    PICKER_URL=https://example.com/kloudless/index.html npm run build\n    ```\n\n    Optionally, you can also set `Kloudless.filePicker.setGlobalOptions` at\n    run-time instead of re-building the loader:\n\n    ```js\n    Kloudless.filePicker.setGlobalOptions({\n      pickerUrl: 'https://example.com/kloudless/index.html',\n    });\n    ```\n2. Copy the entire `dist/picker` folder into your web application's assets so\n   the `dist/picker/index.html` page can be found at the URL specified in\n   the step above. In the example above, copy `dist/picker` to `/kloudless`\n   for `https://example.com/kloudless/index.html` to exist.\n\n3. Add your web app's domain to your Kloudless App's list of\n   `Trusted Domains` on the\n   [App Details Page](https://developers.kloudless.com/applications/*/details#trusted-domains).\n   This allows the hosted File Picker to receive access tokens to the Kloudless\n   API.\n  \n4. Include `dist/loader/loader.min.js` in your pages that will launch\n   File Picker as shown in the\n   [script tag example](#import-from-a-script-tag) above.\n\n### Extending the File Picker Template\n\n*This section contains advanced concepts that are not usually required in a\nfork of the File Picker.*\n\nThe `template/picker.ejs` template contains necessary styles and scripts\nfor the File Picker as well as the compiled HTML snippets.\n\nFeel free to add additional styles, scripts, or HTML elements you need.\nYou can then run `npm run build:template` to build your customized\nFile Picker template. The built page will be available at\n`dist/custom-index.html`. Replace\n`dist/picker/index.html` with this file, and follow the steps in the\n[section above](#hosting-the-file-picker-page) to host this page instead.\n\nFor an example, run `npm run build:template` without any changes and\ncheck the result at `dist/custom-index.html`.\n\n## Misc. Development Notes\n\n* In order to switch folders, we change the current() pointer and then\n  refresh(). refresh() will abort any currently active requests to prevent race\n  conditions\n* Put buttons that can be clicked repeatedly into data-bind clicks instead of\n  the router, because the hash will prevent the route from being fired twice\n  consecutively. Use the hash to switch between pages of the application.\n\n## Security Vulnerabilities\n\nIf you have discovered a security vulnerability with this library or any other\npart of Kloudless, we appreciate your help in disclosing it to us privately by\nemailing security@kloudless.com.\n\n## License\n\nThe source code is licensed under the terms of the [MIT](LICENSE.MIT). Please\nnotice that our library has an optional dependency\n[@kloudless/file-picker-plupload-module](https://github.com/kloudless/file-picker-plupload-module.git),\nwhich is licensed under [AGPLv3](LICENSE.AGPL-3.0-only). If you want to build\nthe file-picker on your own, the default build is MIT licensed, which means\nthe file upload module is excluded, and thus the Computer option and\nthe Dropzone are disabled. If you want to make an AGPLv3 build with the\n@kloudless/file-picker-upload-module, please refer to the [Build](#build)\nsection. If you want to modify the AGPLv3 licensed build without\npublishing your source code, please contact us for a commercial license.\n\n\n## Support\n\nFeel free to contact us at support@kloudless.com with any feedback or\nquestions.\n","funding_links":[],"categories":["JavaScript","javascript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FKloudless%2Ffile-picker","html_url":"https://awesome.ecosyste.ms/projects/github.com%2FKloudless%2Ffile-picker","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2FKloudless%2Ffile-picker/lists"}