@mux/mux-uploader
Advanced tools
Comparing version 0.1.0-canary.10-b1efffb to 0.1.0-canary.10-b676200
@@ -6,2 +6,61 @@ # Change Log | ||
# [0.1.0-beta.7](https://github.com/muxinc/elements/compare/@mux/mux-uploader@0.1.0-beta.6...@mux/mux-uploader@0.1.0-beta.7) (2022-08-04) | ||
### Bug Fixes | ||
- **mux-uploader:** use narrower type def for uploadstart to avoid type mismatches in dist. ([a56cc06](https://github.com/muxinc/elements/commit/a56cc0609b1051513f5df3eb7e9cb21410fc7bb5)) | ||
# [0.1.0-beta.6](https://github.com/muxinc/elements/compare/@mux/mux-uploader@0.1.0-beta.5...@mux/mux-uploader@0.1.0-beta.6) (2022-08-03) | ||
### Features | ||
- **mux-uploader:** Upchunk event type defs. ([248e0e1](https://github.com/muxinc/elements/commit/248e0e1a9edf648113fd6bc7bdf6505c7df8cc4b)) | ||
# [0.1.0-beta.5](https://github.com/muxinc/elements/compare/@mux/mux-uploader@0.1.0-beta.4...@mux/mux-uploader@0.1.0-beta.5) (2022-08-02) | ||
### Bug Fixes | ||
- **mux-uploader:** Fix attempt and chunkSuccess event details not being passed. Also make the data passed consistent by using event for all params. ([09d4cf8](https://github.com/muxinc/elements/commit/09d4cf8e22d8de919e175d039c5f0eb9a42b2591)) | ||
- **mux-uploader:** Update event and event handler typedefs for greater accuracy of types. ([92f28a5](https://github.com/muxinc/elements/commit/92f28a5828ea3c046fa5a1aa711a038a7444f0dc)) | ||
### Features | ||
- **mux-uploader:** Add CSS variables for button border and padding. ([359cd89](https://github.com/muxinc/elements/commit/359cd89472781fc41e33e95574c0d9c845b1d081)) | ||
- **mux-uploader:** Add custom event for when upload starts. ([9fd1efc](https://github.com/muxinc/elements/commit/9fd1efc943bcb60efdb51b455d5b9642af86b920)) | ||
- **mux-uploader:** Support Upchunk's attempt and chunkSuccess events. ([739a88e](https://github.com/muxinc/elements/commit/739a88e5eda697b8344ef14e3a20b1bef19e1a41)) | ||
# [0.1.0-beta.4](https://github.com/muxinc/elements/compare/@mux/mux-uploader@0.1.0-beta.3...@mux/mux-uploader@0.1.0-beta.4) (2022-07-21) | ||
### Bug Fixes | ||
- **mux-uploader, mux-uploader-react:** Add support for endpoint to react version. Clean up type defs, including css vars (drop component only). Remove unnecessary capture for DandD events. ([c12ded5](https://github.com/muxinc/elements/commit/c12ded5188a3d97d48dc335a98d8537b6fa57443)) | ||
### Features | ||
- add defaultMuted, defaultPlaybackRate props ([#252](https://github.com/muxinc/elements/issues/252)) ([1a72165](https://github.com/muxinc/elements/commit/1a7216545cba27b34bc743cf5dd6225d4dcae738)) | ||
- **mux-uploader, mux-uploader-react:** Reset state to allow users to re-select same file when retrying a failed upload. Add error messaging for when url is unset. ([94d000a](https://github.com/muxinc/elements/commit/94d000a396f9a10406bd6959e8aec3cb96c7e775)) | ||
- **mux-uploader:** Add endpoint support for promise callback. ([fc7b381](https://github.com/muxinc/elements/commit/fc7b38171337401f6c0ef8be2fa4e741a0e7a3fd)) | ||
- **mux-uploader:** Clean up mux-uploader-drop + overlay and active logic now that we support descendants. ([83777d2](https://github.com/muxinc/elements/commit/83777d24f1b024b7eba83c98c7a8eb20f9db59e6)) | ||
- **mux-uploader:** Support endoing. ([86ae488](https://github.com/muxinc/elements/commit/86ae488dd22dbd1b7c773d3e13ce9cb99605d0f5)) | ||
# [0.1.0-beta.3](https://github.com/muxinc/elements/compare/@mux/mux-uploader@0.1.0-beta.2...@mux/mux-uploader@0.1.0-beta.3) (2022-07-11) | ||
### Bug Fixes | ||
- **mux-uploader:** Fix default format progress to include percent symbol. Move to module fn. ([6f519f7](https://github.com/muxinc/elements/commit/6f519f7335c62b031781d9d68de4aadab39b2089)) | ||
- **mux-uploader:** Fix syntax in README for components. ([affb4ca](https://github.com/muxinc/elements/commit/affb4ca365f7a9410d03b9d4bfe69eac3d40dca3)) | ||
- **mux-uploader:** handle slotted/changing buttons. rename slot per informal conventions on other projects ([1829fd9](https://github.com/muxinc/elements/commit/1829fd9817976750797cae4de0054d0e165bb269)) | ||
- **mux-uploader:** Polyfill for SSR. ([f559f68](https://github.com/muxinc/elements/commit/f559f68b3f3746d74155a3db919521aa864a7321)) | ||
- **mux-uploader:** re-add drop import to ensure custom element registration. Start work on overlay css. ([1ae4a2e](https://github.com/muxinc/elements/commit/1ae4a2e3e83467fa97fe86aadfe9fbeed09981c5)) | ||
- **mux-uploader:** Refactor overlay behavior for drop. Remove z-index assumptions from uploader. Rename overlay text attr to overlay-text for clarity. ([dcf2c80](https://github.com/muxinc/elements/commit/dcf2c8052581e8174bed59a01a1ca30a7780fa93)) | ||
- **mux-uploader:** Refactor so that drop can only be done with mux-uploader-drop. ([59ddb56](https://github.com/muxinc/elements/commit/59ddb56f22a59b8ba8d4f83cab5653097781bd16)) | ||
- **mux-uploader:** Simplify drop internal DOM structure to have more predictable layout & styling. ([ec108ba](https://github.com/muxinc/elements/commit/ec108bae3c047b35c7316b350ee69d8dc2beffd7)) | ||
### Features | ||
- Add formatProgress method for customization. Bugfix for default uploader button. ([e7860e9](https://github.com/muxinc/elements/commit/e7860e910df648355f1a18c51d248e088f7d3221)) | ||
- **mux-uploader:** Add events that correspond to upchunk events. Early bail when no URL is provided. ([740aa96](https://github.com/muxinc/elements/commit/740aa96455c910f16c88b440dc78f8321a3c3d44)) | ||
- **mux-uploader:** move some dom elements around to make eventual overlay (re)styling a bit easier. ([919072a](https://github.com/muxinc/elements/commit/919072a8ba0788c4f154684415db21ec37d2e5df)) | ||
- **mux-uploader:** Simplify mux-uploader-drop styling. Update vanilla uploader example to demo usage with simplified styling. ([8029a1d](https://github.com/muxinc/elements/commit/8029a1d48cf9a1651b26d7a4740abb4d0ef182a4)) | ||
# 0.1.0-beta.2 (2022-07-05) | ||
@@ -8,0 +67,0 @@ |
{ | ||
"name": "@mux/mux-uploader", | ||
"version": "0.1.0-canary.10-b1efffb", | ||
"version": "0.1.0-canary.10-b676200", | ||
"description": "An uploader elements to be used with Mux Direct Uploads", | ||
@@ -31,3 +31,3 @@ "main": "./dist/index.cjs", | ||
"clean": "shx rm -rf dist/", | ||
"test": "web-test-runner **/*test.js --port 8002 --coverage --config test/web-test-runner.config.mjs --root-dir ../..", | ||
"test": "web-test-runner **/*test.js --port 8005 --coverage --config test/web-test-runner.config.mjs --root-dir ../..", | ||
"posttest": "replace 'SF:src/' 'SF:packages/mux-uploader/src/' coverage/lcov.info --silent", | ||
@@ -34,0 +34,0 @@ "dev:iife": "open-process | yarn build:iife --watch", |
109
README.md
@@ -10,5 +10,5 @@ <p align="center"> | ||
`<mux-uploader></mux-uploader>` is web component for uploading files to Mux. | ||
`<mux-uploader>` is web component for uploading files to Mux. | ||
`mux-uploader-drop` is an optional supporting web component for drop-in drag and drop and overlay. You can always configure your own drag and drop with `mux-uploader`. | ||
`<mux-uploader-drop>` is an optional supporting container-style web component for drag and drop. You can always configure your own drag and drop with `<mux-uploader>`. | ||
@@ -50,3 +50,3 @@ If you are looking for a direct upload interface and a progress bar, you're in the right place. | ||
```html | ||
<script src="https://unpkg.com/@mux/mux-uploader@0.1.0-beta.0"></script> | ||
<script src="https://unpkg.com/@mux/mux-uploader"></script> | ||
``` | ||
@@ -57,3 +57,3 @@ | ||
```html | ||
<script type="module" src="https://unpkg.com/@mux/mux-uploader@0.1.0-beta.0/dist/mux-uploader.mjs"></script> | ||
<script type="module" src="https://unpkg.com/@mux/mux-uploader/dist/mux-uploader.mjs"></script> | ||
``` | ||
@@ -71,6 +71,7 @@ | ||
<!-- Upload button with access to additional drag and drop features via slots i.e. fullscreen drag and drop with text overlay (work-in-progress).--> | ||
<mux-uploader url="authenticated-url"> | ||
<mux-uploader-drop slot="dropzone" text="Upload to stream.new" fullscreen overlay></mux-uploader-drop> | ||
</mux-uploader> | ||
<!-- Upload button with access to optional supplentary drag and drop features..--> | ||
<mux-uploader-drop mux-uploader="uploader" overlay overlay-text="Show this while dragging file over me"> | ||
<mux-uploader id="uploader" url="authenticated-url"></mux-uploader> | ||
<div>Other stuff you want in the mux-uploader-drop drop zone container</div> | ||
</mux-uploader-drop> | ||
</body> | ||
@@ -81,3 +82,4 @@ ``` | ||
The `mux-uploader`, whether you use `mux-uploader-drop` and its additional features or not i.e. fullscreen and text overlay, has basic drag and drop functionality available to it by default. If you'd rather shop your own drag and drop solution, you can disable the default drag and drop on `mux-uploader` and dispatch a custom `file-ready` event when you need to upload. `mux-uploader` will handle the upload upon receiving the event. | ||
`<mux-uploader-drop>` is available for drag and drop functionality. It works like a `<div>` or other "container" element in the sense that you can style it and populate it with whatever children you see fit (including but not necessarily a `<mux-uploader>`). Similar to `<input>` and `<label>` relationships, you associate a `<mux-uploader-drop>` with its corresponding `<mux-uploader>` via `id` using the `mux-uploader` attribute (See example above). When a file is dropped, this will dispatch a custom `file-ready` event to the corresponding `<mux-uploader>` with the relevant file. | ||
This also means you can implement your own drag and drop (or other) components for specific use cases, so long as you dispatch a custom `file-ready` event when you need to upload. `<mux-uploader>` will handle the upload upon receiving the event. | ||
@@ -101,49 +103,66 @@ ```html | ||
#### `mux-uploader` | ||
#### `<mux-uploader>` | ||
| Attribute | Type | Description | Default | | ||
| -------------------- | --------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | ||
| `url` | `string` | The authenticated URL that your file will be uploaded to. Check out the [direct uploads docs](https://docs.mux.com/guides/video/upload-files-directly#1-create-an-authenticated-mux-url) for how to create one. Required. | `undefined` | | ||
| `id` | `string` | An ID that allows `mux-uploader-drop` to locate `mux-uploader`. Not necessary unless the unlikely scenario you need to nest `mux-uploader` inside `mux-uploader-drop`. | N/A | | ||
| `type` | `"bar"` | Specifies the visual type of progress bar. A radial type is in-progress. | "bar" | | ||
| `upload-in-progress` | `boolean` | Toggles visual status of progress bar while upload is in progress. Can be targeted with CSS if you want to control styles while in progress i.e. mux-uploader[upload-in-progress]. | false | | ||
| `upload-error` | `boolean` | Toggles visual status of progress bar when upload encounters an error. Can be targeted with CSS if you want to control styles when an error occurs i.e. mux-uploader[upload-error]. | false | | ||
| `status` | `boolean` | Toggles text status visibility of progress bar. The text that is displayed is a percentage by default. If you prefer just the progress bar with no text upload status, don't include this attribute. | false | | ||
| Attribute | Type | Description | Default | | ||
| -------------------- | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- | | ||
| `endpoint` | `string \| Promise` | Either a) the authenticated URL that your file will be uploaded to or b) an async function that yields a promise that resolves to that url. Check out the [direct uploads docs](https://docs.mux.com/guides/video/upload-files-directly#1-create-an-authenticated-mux-url). Required. | `undefined` | | ||
| `id` | `string` | An ID that allows `mux-uploader-drop` to locate `mux-uploader`. Required if you use `mux-uploader-drop`. | N/A | | ||
| `type` | `"bar"` | Specifies the visual type of progress bar. A radial type is in-progress. | "bar" | | ||
| `upload-in-progress` | `boolean` | (Read-only) Toggles visual status of progress bar while upload is in progress. Can be targeted with CSS if you want to control styles while in progress i.e. mux-uploader[upload-in-progress]. | false | | ||
| `upload-error` | `boolean` | (Read-only) Toggles visual status of progress bar when upload encounters an error. Can be targeted with CSS if you want to control styles when an error occurs i.e. mux-uploader[upload-error]. | false | | ||
| `status` | `boolean` | Toggles text status visibility of progress bar. The text that is displayed is a percentage by default. If you prefer just the progress bar with no text upload status, don't include this attribute. | false | | ||
#### `mux-uploader-drop` | ||
#### `<mux-uploader-drop>` | ||
| Attribute | Type | Description | Default | | ||
| --------------- | --------- | ------------------------------------------------------ | ------- | | ||
| `fullscreen` | `boolean` | Toggles fullscreen drag and drop (work-in-progress). | false | | ||
| `overlay` | `boolean` | Toggles fullscreen overlay on dragover. | false | | ||
| `disable-drop ` | `boolean` | Toggles off drag and drop which is enabled by default. | false | | ||
| Attribute | Type | Description | Default | | ||
| -------------- | --------- | ---------------------------------------------------------- | ------- | | ||
| `overlay` | `boolean` | Toggles showing an overlay on dragover. | `false` | | ||
| `overlay-text` | `string` | Optional text to display on dragover when `overlay` is on. | `''` | | ||
| `mux-uploader` | `string ` | Must match the `id` on `MuxUploader`. Required. | N/A | | ||
### Methods | ||
### Properties | ||
| Method | Description | | ||
| ---------------- | --------------------------- | | ||
| `handleUpload()` | Begins upload of the media. | | ||
#### `<mux-uploader>` | ||
| Property | Type | Description | Default | | ||
| ---------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------- | | ||
| `formatProgress` | `function` | A function that accepts numeric percent and is expected to return a string. Allows for customizing how the progress should be rendered - whether you want to display only the number or a sentence with the number etc. i.e. `formatProgress={(percent: number) => `${percent} percent uploaded`}` | A function that yields only the percent as a string i.e. `"60%"` | | ||
### Events | ||
#### `<mux-uploader>` | ||
`<mux-uploader>` has a handful of events - using [Upchunk](https://github.com/muxinc/upchunk/blob/master/README.md) under the hood - to monitor uploading state. | ||
| Event | Description | | ||
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | ||
| `uploadstart` | Fired when the upload begins. | | ||
| `chunkattempt` | Fired immediately before a chunk upload is attempted. | | ||
| `chunksuccess` | Fired when an indvidual chunk is successfully uploaded. Sample response: `{ detail: { chunk: Integer, attempts: Integer, response: XhrResponse } }` | | ||
| `error` | Fired when an error occurs in the chunked upload process. | | ||
| `progress` | Fired continuously with incremental upload progress. This returns the current percentage of the file that's been uploaded. Sample response: `{ detail: [0..100] }` | | ||
| `success` | Fired when the entire file has successfully completed uploading. | | ||
### Styling | ||
`mux-uploader` can be styled with CSS variables. | ||
`<mux-uploader>` and `<mux-uploader-drop>` can be styled with standard CSS, but also includes these CSS variables for "under the hood" styling. | ||
#### Elements | ||
#### `<mux-uploader>` | ||
- `<mux-uploader/>` | ||
| Name | CSS Property | Default Value | Description | Notes | | ||
| ------------------------------ | ------------------ | ------------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | ||
| `--uploader-font-family` | `font-family` | `Arial` | font family of the component | Applies to other elements as well: upload status and error status | | ||
| `--uploader-font-size` | `font-size` | `16px` | font size for text within the component | Also applies to `<mux-uploader-drop>` i.e. overlay text | | ||
| `--uploader-background-color` | `background-color` | `inherit` | background color of area surrounding the upload | | | ||
| `--button-background-color` | `background` | `#fff` | background color of upload button | | | ||
| `--button-border-radius` | `border-radius` | `4px` | border radius of the upload button | | | ||
| `--button-border` | `border` | `1px solid #000000` | border of the upload button | | | ||
| `--button-padding` | `padding` | `16px 24px` | padding of the upload button | | | ||
| `--button-hover-text` | `color` | `#fff` | text color of upload button on button hover | | | ||
| `--button-hover-background` | `background` | `#404040` | background color of upload button on button hover | | | ||
| `--button-active-text` | `color` | `#fff` | color of upload button text when button is active | | | ||
| `--button-active-background` | `background` | `#000000` | background color of upload button when button is active | Applied via `:active` [pseudo selector](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) | | ||
| `--progress-bar-fill-color` | `background` | `#000000` | background color for progress bar div | | | ||
| `--progress-radial-fill-color` | `stroke` | `black` | stroke color for circle SVG (wip) | | | ||
| Name | CSS Property | Default Value | Description | Notes | | ||
| ------------------------------ | ------------------ | ------------- | ------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | | ||
| `--uploader-font-family` | `font-family` | `Arial` | font family of the component | Applies to other elements as well: upload status and error status | | ||
| `--uploader-font-size` | `font-size` | `16px` | font size for text within the component | Also applies to `<mux-uploader-drop>` i.e. overlay text | | ||
| `--uploader-background-color` | `background-color` | `inherit` | background color of area surrounding the upload | | | ||
| `--button-background-color` | `background` | `#fff` | background color of upload button | | | ||
| `--button-border-radius` | `border-radius` | `4px` | border ardius of the upload button | | | ||
| `--button-hover-text` | `color` | `#fff` | text color of upload button on button hover | | | ||
| `--button-hover-background` | `background` | `#404040` | background color of upload button on button hover | | | ||
| `--button-active-text` | `color` | `#fff` | color of upload button text when button is active | | | ||
| `--button-active-background` | `background` | `#000000` | background color of upload button when button is active | Applied via `:active` [pseudo selector](https://developer.mozilla.org/en-US/docs/Web/CSS/:active) | | ||
| `--progress-bar-fill-color` | `background` | `#000000` | background color for progress bar div | | | ||
| `--progress-radial-fill-color` | `stroke` | `black` | stroke color for circle SVG (wip) | | | ||
- `<mux-uploader-drop/>` | ||
@@ -150,0 +169,0 @@ |
259
src/index.ts
import '@mux/polyfills'; | ||
// Still need to import this to ensure component registration occurs when using the main module. | ||
// Consider refactoring module structure to avoid this. (CJP) | ||
import './mux-uploader-drop'; | ||
import * as UpChunk from '@mux/upchunk'; | ||
import './mux-uploader-drop'; | ||
@@ -33,5 +35,5 @@ const styles = ` | ||
background: var(--button-background-color, #fff); | ||
border: 1px solid #000000; | ||
border: var(--button-border, 1px solid #000000); | ||
color: #000000; | ||
padding: 16px 24px; | ||
padding: var(--button-padding, 16px 24px); | ||
border-radius: var(--button-border-radius, 4px); | ||
@@ -42,3 +44,2 @@ -webkit-transition: all 0.2s ease; | ||
font-size: inherit; | ||
z-index: 10; | ||
position: relative; | ||
@@ -81,3 +82,2 @@ } | ||
cursor: pointer; | ||
z-index: 10; | ||
position: relative; | ||
@@ -182,4 +182,2 @@ } | ||
<p class="upload-instruction" id="upload-instruction">Drop file to upload</p> | ||
<div class="sr-only" id="sr-only" aria-live="polite"></div> | ||
@@ -192,6 +190,5 @@ | ||
<input type="file" /> | ||
<!--TO-DO: Slots not receiving events or not having the right visual behaviour as the original elements. (TD).--> | ||
<slot name="custom-button"><button type="button">Upload video</button></slot> | ||
<slot name="custom-progress"><p class="upload-status" id="upload-status"></p></slot> | ||
<input id="hidden-file-input" type="file" /> | ||
<slot name="upload-button"><button type="button">Upload video</button></slot> | ||
<p class="upload-status" id="upload-status"></p> | ||
@@ -214,6 +211,2 @@ <div class="bar-type"> | ||
</div> | ||
<slot name="dropzone"> | ||
<mux-uploader-drop></mux-uploader-drop> | ||
</slot> | ||
`; | ||
@@ -227,2 +220,4 @@ | ||
const defaultFormatProgress = (percent: number) => `${Math.floor(percent)}%`; | ||
const getRadius = (el: MuxUploaderElement) => Number(el.svgCircle?.getAttribute('r')); | ||
@@ -236,5 +231,55 @@ | ||
class MuxUploaderElement extends HTMLElement { | ||
hiddenFileInput: HTMLInputElement | null | undefined; | ||
filePickerButton: HTMLButtonElement | null | undefined; | ||
type Endpoint = UpChunk.UpChunk['endpoint'] | undefined | null; | ||
type ErrorDetail = { | ||
message: string; | ||
chunkNumber?: number; | ||
attempts?: number; | ||
}; | ||
// NOTE: error and progress events are already determined on HTMLElement but have inconsistent types. Should consider renaming events (CJP) | ||
export interface MuxUploaderElementEventMap extends Omit<HTMLElementEventMap, 'error' | 'progress'> { | ||
uploadstart: CustomEvent<{ file: File; chunkSize: number }>; | ||
chunkattempt: CustomEvent<{ | ||
chunkNumber: number; | ||
chunkSize: number; | ||
}>; | ||
chunksuccess: CustomEvent<{ | ||
chunk: number; | ||
attempts: number; | ||
// Note: This should be more explicitly typed in Upchunk. (TD). | ||
response: any; | ||
}>; | ||
error: CustomEvent<ErrorDetail>; | ||
progress: CustomEvent<number>; | ||
success: CustomEvent<undefined | null>; | ||
} | ||
interface MuxUploaderElement extends HTMLElement { | ||
addEventListener<K extends keyof MuxUploaderElementEventMap>( | ||
type: K, | ||
listener: (this: HTMLMediaElement, ev: MuxUploaderElementEventMap[K]) => any, | ||
options?: boolean | AddEventListenerOptions | ||
): void; | ||
addEventListener( | ||
type: string, | ||
listener: EventListenerOrEventListenerObject, | ||
options?: boolean | AddEventListenerOptions | ||
): void; | ||
removeEventListener<K extends keyof MuxUploaderElementEventMap>( | ||
type: K, | ||
listener: (this: HTMLMediaElement, ev: MuxUploaderElementEventMap[K]) => any, | ||
options?: boolean | EventListenerOptions | ||
): void; | ||
removeEventListener( | ||
type: string, | ||
listener: EventListenerOrEventListenerObject, | ||
options?: boolean | EventListenerOptions | ||
): void; | ||
} | ||
class MuxUploaderElement extends HTMLElement implements MuxUploaderElement { | ||
protected _formatProgress: ((percent: number) => string) | null | undefined; | ||
protected _filePickerButton: HTMLElement | null | undefined; | ||
protected _endpoint: Endpoint; | ||
svgCircle: SVGCircleElement | null | undefined; | ||
@@ -250,2 +295,6 @@ progressBar: HTMLElement | null | undefined; | ||
// NOTE: Binding this so that we have a reference to remove the event listener | ||
// but can still reference `this` in the method. (CJP) | ||
this.handleFilePickerButtonClick = this.handleFilePickerButtonClick.bind(this); | ||
const shadow = this.attachShadow({ mode: 'open' }); | ||
@@ -255,4 +304,5 @@ const uploaderHtml = template.content.cloneNode(true); | ||
this.hiddenFileInput = this.shadowRoot?.querySelector('input[type="file"]'); | ||
this.filePickerButton = this.shadowRoot?.querySelector('button'); | ||
// Since we have a "default slotted" element, we still need to initialize the slottable elements | ||
// (Note the difference in selectors and related code in 'slotchange' handler, below) | ||
this.filePickerButton = this.shadowRoot?.querySelector('slot[name=upload-button] > *'); | ||
this.svgCircle = this.shadowRoot?.querySelector('circle'); | ||
@@ -266,2 +316,22 @@ this.progressBar = this.shadowRoot?.getElementById('progress-bar'); | ||
this.progressBar?.setAttribute('aria-description', ariaDescription); | ||
// These should only ever be setup once on instantiation/construction. | ||
this.hiddenFileInput?.addEventListener('change', (evt) => { | ||
const file = this.hiddenFileInput?.files?.[0]; | ||
if (file) { | ||
this.dispatchEvent( | ||
new CustomEvent('file-ready', { | ||
composed: true, | ||
bubbles: true, | ||
detail: file, | ||
}) | ||
); | ||
} | ||
}); | ||
this.shadowRoot?.querySelector('slot[name=upload-button]')?.addEventListener('slotchange', () => { | ||
this.filePickerButton = ( | ||
this.shadowRoot?.querySelector('slot[name=upload-button]') as HTMLSlotElement | ||
)?.assignedNodes()[0] as HTMLButtonElement; | ||
}); | ||
} | ||
@@ -271,15 +341,5 @@ | ||
this.setDefaultType(); | ||
this.setupFilePickerButton(); | ||
this.setupRetry(); | ||
this.setupDropHandler(); | ||
// TO-DO: Might want to standardize if we prefer to have users disable or enable things. (TD). | ||
// Edge case: User wants to use the uploader without drag. | ||
// Because we slot a default mux-uploader-drop if they don't slot one, | ||
// in order to disable drop, the user has to pass disable-drop to mux-uploader and mux-uploader-drop | ||
// must apply it in order to disable the drop. It currently requires you to explicit pass "true". | ||
if (this.hasAttribute('disable-drop')) { | ||
const muxUploaderDrop = this.shadowRoot?.querySelector('mux-uploader-drop'); | ||
muxUploaderDrop?.setAttribute('disable-drop', ''); | ||
} | ||
//@ts-ignore | ||
this.addEventListener('file-ready', this.handleUpload); | ||
} | ||
@@ -292,10 +352,50 @@ | ||
get url() { | ||
return this.getAttribute('url') as string; | ||
protected get filePickerButton() { | ||
return this._filePickerButton; | ||
} | ||
set url(value: string) { | ||
this.setAttribute('url', value); | ||
protected set filePickerButton(value: HTMLElement | null | undefined) { | ||
if (value === this._filePickerButton) return; | ||
if (this._filePickerButton) { | ||
this._filePickerButton.removeEventListener('click', this.handleFilePickerButtonClick); | ||
} | ||
this._filePickerButton = value; | ||
if (this._filePickerButton) { | ||
this._filePickerButton.addEventListener('click', this.handleFilePickerButtonClick); | ||
} | ||
} | ||
protected get hiddenFileInput() { | ||
return this.shadowRoot?.querySelector('#hidden-file-input') as HTMLInputElement; | ||
} | ||
handleFilePickerButtonClick(e: MouseEvent) { | ||
// TO-DO: Allow user to reattempt uploading the same file after an error. | ||
// Note: Apparently Chrome and Firefox do not allow changing an indexed property on FileList...(TD). | ||
// Source: https://stackoverflow.com/a/46689013 | ||
this.hiddenFileInput.click(); | ||
} | ||
get endpoint(): Endpoint { | ||
return this.getAttribute('endpoint') ?? this._endpoint; | ||
} | ||
set endpoint(value: Endpoint) { | ||
if (value === this.endpoint) return; | ||
if (typeof value === 'string') { | ||
this.setAttribute('endpoint', value); | ||
} else if (value == undefined) { | ||
this.removeAttribute('endpoint'); | ||
} | ||
this._endpoint = value; | ||
} | ||
get formatProgress(): (percent: number) => string { | ||
return this._formatProgress ?? defaultFormatProgress; | ||
} | ||
set formatProgress(value: ((percent: number) => string) | null | undefined) { | ||
this._formatProgress = value; | ||
} | ||
setDefaultType() { | ||
@@ -350,10 +450,7 @@ const currentType = this.getAttribute('type'); | ||
setupDropHandler() { | ||
//@ts-ignore | ||
this.addEventListener('file-ready', this.handleUpload); | ||
} | ||
resetState() { | ||
this.removeAttribute('upload-error'); | ||
this.removeAttribute('upload-in-progress'); | ||
// Reset file to ensure change/input events will fire, even if selecting the same file (CJP). | ||
this.hiddenFileInput.value = ''; | ||
if (this.statusMessage) this.statusMessage.innerHTML = ''; | ||
@@ -363,33 +460,4 @@ if (this.uploadPercentage) this.uploadPercentage.innerHTML = ''; | ||
setupFilePickerButton() { | ||
// TO-DO: Troubleshoot click event when user clicks custom button. Currently not getting the slotted element. (TD). | ||
this.shadowRoot?.querySelector('slot[name=custom-button]')?.addEventListener('slotchange', () => { | ||
this.filePickerButton = this.shadowRoot?.querySelector('slot[name=custom-button]'); | ||
}); | ||
this.filePickerButton?.addEventListener('click', () => { | ||
// TO-DO: Allow user to reattempt uploading the same file after an error. | ||
// Note: Apparently Chrome and Firefox do not allow changing an indexed property on FileList...(TD). | ||
// Source: https://stackoverflow.com/a/46689013 | ||
this.hiddenFileInput?.click(); | ||
}); | ||
this.hiddenFileInput?.addEventListener('change', (evt) => { | ||
const file = this.hiddenFileInput?.files?.[0]; | ||
if (file) { | ||
this.dispatchEvent( | ||
new CustomEvent('file-ready', { | ||
composed: true, | ||
bubbles: true, | ||
detail: file, | ||
}) | ||
); | ||
} | ||
}); | ||
} | ||
setProgress(percent: number) { | ||
if (this.uploadPercentage) this.uploadPercentage.innerHTML = `${Math.floor(percent)}%`; | ||
if (this.uploadPercentage) this.uploadPercentage.innerHTML = this.formatProgress(percent); | ||
this.progressBar?.setAttribute('aria-valuenow', `${Math.floor(percent)}`); | ||
@@ -414,15 +482,19 @@ | ||
handleUpload(evt: CustomEvent) { | ||
const url = this.url; | ||
const invalidUrlMessage = 'No url attribute specified -- cannot handleUpload'; | ||
const endpoint = this.endpoint; | ||
if (!url) { | ||
if (this.statusMessage) this.statusMessage.innerHTML = invalidUrlMessage; | ||
if (!endpoint) { | ||
const invalidUrlMessage = 'No url or endpoint specified -- cannot handleUpload'; | ||
if (this.statusMessage) { | ||
this.statusMessage.innerHTML = invalidUrlMessage; | ||
} | ||
this.setAttribute('upload-error', ''); | ||
console.error(invalidUrlMessage); | ||
this.dispatchEvent(new CustomEvent('error', { detail: { message: invalidUrlMessage } })); | ||
// Bail early if no endpoint. | ||
return; | ||
} else { | ||
if (this.statusMessage) this.statusMessage.innerHTML = ''; | ||
} | ||
if (this.statusMessage) { | ||
this.removeAttribute('upload-error'); | ||
this.statusMessage.innerHTML = ''; | ||
if (this.statusMessage) { | ||
this.statusMessage.innerHTML = ''; | ||
} | ||
} | ||
@@ -434,9 +506,17 @@ | ||
const upload = UpChunk.createUpload({ | ||
endpoint: | ||
url || | ||
'https://storage.googleapis.com/video-storage-us-east1-uploads/B6vYEZ9utvayi7tJlcwjG4ckho8W5100QHse5OEIyOqg?Expires=1654714562&GoogleAccessId=direct-uploads-writer-prod%40mux-cloud.iam.gserviceaccount.com&Signature=ZQLdkP8u432oNZ5WtQwPB22qR%2B03BWd0DOdEFohak0dNG2fzJpE9RLCyAb8uJo3N8YH62UecxJs%2FefKFETicJd978Dldh3E4yTJQLWFR%2B%2FpCrYdS6EQRG7D08Vb9yz82jRJRgJ37cnJgNCzUFUx8AFX%2FG0o8BA3Wcm2AkdcLRWhvt2tj5wTzbxm8ZBflhYckJs7kNaiKEfIXk0UzNBPRJPGzyjzKUyyU1Keu0rERepH7BM8wJeGiw7KrD1TkqeMcA2NSpht4COKXYp3aNrryLGYfx%2B362U3KR0TaRalskKdqODbhBtTlLbFRALog3mGFq3CVJ2CG5Vztq6rXa00VRQ%3D%3D&upload_id=ADPycdsGqgIsU8tBAiu2k4Gt5hPa4QUaURD71neXpjQMfoQUeFGVDvE3qyAN7kzAVUcbSfK6tDhHwpSNiQMSvW41tPiTxw', | ||
endpoint, | ||
file: evt.detail, | ||
}); | ||
upload.on('error', (err) => { | ||
this.dispatchEvent(new CustomEvent('uploadstart', { detail: { file: upload.file, chunkSize: upload.chunkSize } })); | ||
upload.on('attempt', (event) => { | ||
this.dispatchEvent(new CustomEvent('chunkattempt', event)); | ||
}); | ||
upload.on('chunkSuccess', (event) => { | ||
this.dispatchEvent(new CustomEvent('chunksuccess', event)); | ||
}); | ||
upload.on('error', (event) => { | ||
const errorMessage = 'An error has occurred'; | ||
@@ -450,10 +530,12 @@ | ||
console.error(err.detail.message); | ||
console.error(event.detail.message); | ||
this.dispatchEvent(new CustomEvent('error', event)); | ||
}); | ||
upload.on('progress', (progress) => { | ||
this.setProgress(progress.detail); | ||
upload.on('progress', (event) => { | ||
this.setProgress(event.detail); | ||
this.dispatchEvent(new CustomEvent('progress', event)); | ||
}); | ||
upload.on('success', () => { | ||
upload.on('success', (event) => { | ||
const successMessage = 'Upload complete!'; | ||
@@ -472,2 +554,3 @@ | ||
console.info(successMessage); | ||
this.dispatchEvent(new CustomEvent('success', event)); | ||
}); | ||
@@ -474,0 +557,0 @@ } |
@@ -0,29 +1,13 @@ | ||
import '@mux/polyfills'; | ||
const template = document.createElement('template'); | ||
/** @todo: Currently removing all styles. Follow up on overlay styling (CJP) */ | ||
template.innerHTML = ` | ||
<style> | ||
/* These styles simulate a user passing these via props. Until | ||
that's implemented, we just hardcode it for non-full-screen demo purposes. (TD). | ||
*/ | ||
.dropzone { | ||
position: absolute; | ||
top: 0; | ||
left: 0; | ||
right: 0; | ||
bottom: 0; | ||
height: 100%; | ||
width: 100%; | ||
:host { | ||
position: relative; | ||
} | ||
/* TO-DO: Make default dropzone hover more apparent. (TD).*/ | ||
:host([disable-drop]) .dropzone { | ||
#overlay { | ||
display: none; | ||
} | ||
.overlay { | ||
display: none; | ||
} | ||
:host([fullscreen]) .dropzone { | ||
position: absolute; | ||
@@ -36,20 +20,6 @@ top: 0; | ||
width: 100%; | ||
z-index: 1; | ||
} | ||
:host([fullscreen][overlay]) .overlay { | ||
position: absolute; | ||
top: 0; | ||
bottom: 0; | ||
right: 0; | ||
left: 0; | ||
height: 100%; | ||
width: 100%; | ||
z-index: -1; | ||
} | ||
:host([active][fullscreen][overlay]) .overlay { | ||
z-index: 10; | ||
background-color: var(--overlay-background-color, rgba(226, 253, 255, 0.95)); | ||
:host([active][overlay]) > #overlay { | ||
background: var(--overlay-background-color, rgba(226, 253, 255, 0.95)); | ||
display: flex; | ||
@@ -60,22 +30,17 @@ flex-direction: column; | ||
} | ||
h1 { | ||
display: none; | ||
} | ||
:host([active][overlay]) h1 { | ||
display: block; | ||
} | ||
</style> | ||
<div class="overlay" id="overlay"> | ||
<h1 id="overlay-text"></h1> | ||
<slot></slot> | ||
<div id="overlay"> | ||
<h1 id="overlay-label"></h1> | ||
</div> | ||
<div class="dropzone" id="dropzone"> | ||
</div> | ||
`; | ||
const Attributes = { | ||
MUX_UPLOADER: 'mux-uploader', | ||
OVERLAY_TEXT: 'overlay-text', | ||
}; | ||
class MuxUploaderDropElement extends HTMLElement { | ||
overlay: HTMLElement | null | undefined; | ||
overlayText: HTMLElement | null | undefined; | ||
overlayText: HTMLElement; | ||
@@ -87,4 +52,3 @@ constructor() { | ||
this.overlay = shadowRoot.getElementById('overlay'); | ||
this.overlayText = shadowRoot.getElementById('overlay-text'); | ||
this.overlayText = shadowRoot.getElementById('overlay-label') as HTMLElement; | ||
} | ||
@@ -96,42 +60,26 @@ | ||
attributeChangedCallback() { | ||
//@ts-ignore | ||
this.shadowRoot.getElementById('overlay-text').innerHTML = this.getAttribute('text'); | ||
attributeChangedCallback(attributeName: string, oldValue: string | null, newValue: string | null) { | ||
if (attributeName === Attributes.OVERLAY_TEXT && oldValue !== newValue) { | ||
this.overlayText.innerHTML = newValue ?? ''; | ||
} else if (attributeName === 'active') { | ||
if (this.getAttribute('overlay') && newValue != null) { | ||
this._currentDragTarget = this; | ||
} | ||
} | ||
} | ||
static get observedAttributes() { | ||
return ['text', 'mux-uploader']; | ||
return [Attributes.OVERLAY_TEXT, Attributes.MUX_UPLOADER, 'active']; | ||
} | ||
get muxUploader() { | ||
const uploaderId = this.getAttribute('mux-uploader'); | ||
const uploaderId = this.getAttribute(Attributes.MUX_UPLOADER); | ||
return uploaderId ? document.getElementById(uploaderId) : null; | ||
} | ||
/* TO-DO: Maybe use something like this from player so allow users to fully customize the dropzone | ||
without having to make a ton of CSS variables available i.e. position absolute. (TD). | ||
protected _currentDragTarget?: Node; | ||
kebabCase(string: String) { | ||
return string.replace(/[A-Z]/g, (match) => `-${match.toLowerCase()}`); | ||
} | ||
stylePropsToString(props: any) { | ||
let style = ''; | ||
Object.entries(props).forEach(([key, value]) => { | ||
style += `${this.kebabCase(key)}: ${value}; `; | ||
}); | ||
return style ? style.trim() : undefined; | ||
} | ||
customizeDropzone() { | ||
if(this.getAttribute('props')) { | ||
// change .dropzone to use styles returned from stylePropsToString; | ||
// this.setClass('dropzone', this.stylePropsToString(this.getAttribute('props'))); | ||
} | ||
} | ||
*/ | ||
setupDragEvents() { | ||
this.addEventListener('dragenter', (evt) => { | ||
this._currentDragTarget = evt.target as Node; | ||
evt.preventDefault(); | ||
@@ -143,3 +91,6 @@ evt.stopPropagation(); | ||
this.addEventListener('dragleave', (evt) => { | ||
this.removeAttribute('active'); | ||
if (this._currentDragTarget === evt.target) { | ||
this._currentDragTarget = undefined; | ||
this.removeAttribute('active'); | ||
} | ||
}); | ||
@@ -146,0 +97,0 @@ |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
2
167
44231
8
614
1