` tag we check the equality
* of the VNodes corresponding to the `
` tags and, since they are the
* same tag in the same position, we'd be able to avoid completely
* re-rendering the subtree under them with a new DOM element and would just
* call out to `patch` to handle reconciling their children and so on.
*
* 3. Check, for both windows, to see if the element at the beginning of the
* window corresponds to the element at the end of the other window. This is
* a heuristic which will let us identify _some_ situations in which
* elements have changed position, for instance it _should_ detect that the
* children nodes themselves have not changed but merely moved in the
* following example:
*
* oldVNode: `
`
* newVNode: `
`
*
* If we find cases like this then we also need to move the concrete DOM
* elements corresponding to the moved children to write the re-order to the
* DOM.
*
* 4. Finally, if VNodes have the `key` attribute set on them we check for any
* nodes in the old children which have the same key as the first element in
* our window on the new children. If we find such a node we handle calling
* out to `patch`, moving relevant DOM nodes, and so on, in accordance with
* what we find.
*
* Finally, once we've narrowed our 'windows' to the point that either of them
* collapse (i.e. they have length 0) we then handle any remaining VNode
* insertion or deletion that needs to happen to get a DOM state that correctly
* reflects the new child VNodes. If, for instance, after our window on the old
* children has collapsed we still have more nodes on the new children that
* we haven't dealt with yet then we need to add them, or if the new children
* collapse but we still have unhandled _old_ children then we need to make
* sure the corresponding DOM nodes are removed.
*
* @param parentElm the node into which the parent VNode is rendered
* @param oldCh the old children of the parent node
* @param newVNode the new VNode which will replace the parent
* @param newCh the new children of the parent node
*/
const updateChildren = (parentElm, oldCh, newVNode, newCh) => {
let oldStartIdx = 0;
let newStartIdx = 0;
let idxInOld = 0;
let i = 0;
let oldEndIdx = oldCh.length - 1;
let oldStartVnode = oldCh[0];
let oldEndVnode = oldCh[oldEndIdx];
let newEndIdx = newCh.length - 1;
let newStartVnode = newCh[0];
let newEndVnode = newCh[newEndIdx];
let node;
let elmToMove;
while (oldStartIdx <= oldEndIdx && newStartIdx <= newEndIdx) {
if (oldStartVnode == null) {
// VNode might have been moved left
oldStartVnode = oldCh[++oldStartIdx];
}
else if (oldEndVnode == null) {
oldEndVnode = oldCh[--oldEndIdx];
}
else if (newStartVnode == null) {
newStartVnode = newCh[++newStartIdx];
}
else if (newEndVnode == null) {
newEndVnode = newCh[--newEndIdx];
}
else if (isSameVnode(oldStartVnode, newStartVnode)) {
// if the start nodes are the same then we should patch the new VNode
// onto the old one, and increment our `newStartIdx` and `oldStartIdx`
// indices to reflect that. We don't need to move any DOM Nodes around
// since things are matched up in order.
patch(oldStartVnode, newStartVnode);
oldStartVnode = oldCh[++oldStartIdx];
newStartVnode = newCh[++newStartIdx];
}
else if (isSameVnode(oldEndVnode, newEndVnode)) {
// likewise, if the end nodes are the same we patch new onto old and
// decrement our end indices, and also likewise in this case we don't
// need to move any DOM Nodes.
patch(oldEndVnode, newEndVnode);
oldEndVnode = oldCh[--oldEndIdx];
newEndVnode = newCh[--newEndIdx];
}
else if (isSameVnode(oldStartVnode, newEndVnode)) {
// case: "Vnode moved right"
//
// We've found that the last node in our window on the new children is
// the same VNode as the _first_ node in our window on the old children
// we're dealing with now. Visually, this is the layout of these two
// nodes:
//
// newCh: [..., newStartVnode , ... , newEndVnode , ...]
// ^^^^^^^^^^^
// oldCh: [..., oldStartVnode , ... , oldEndVnode , ...]
// ^^^^^^^^^^^^^
//
// In this situation we need to patch `newEndVnode` onto `oldStartVnode`
// and move the DOM element for `oldStartVnode`.
if ((oldStartVnode.$tag$ === 'slot' || newEndVnode.$tag$ === 'slot')) {
putBackInOriginalLocation(oldStartVnode.$elm$.parentNode, false);
}
patch(oldStartVnode, newEndVnode);
// We need to move the element for `oldStartVnode` into a position which
// will be appropriate for `newEndVnode`. For this we can use
// `.insertBefore` and `oldEndVnode.$elm$.nextSibling`. If there is a
// sibling for `oldEndVnode.$elm$` then we want to move the DOM node for
// `oldStartVnode` between `oldEndVnode` and it's sibling, like so:
//
//
//
//
//
//
//
// ```
// In this case if we do not un-shadow here and use the value of the shadowing property, attributeChangedCallback
// will be called with `newValue = "some-value"` and will set the shadowed property (this.someAttribute = "another-value")
// to the value that was set inline i.e. "some-value" from above example. When
// the connectedCallback attempts to un-shadow it will use "some-value" as the initial value rather than "another-value"
//
// The case where the attribute was NOT set inline but was not set programmatically shall be handled/un-shadowed
// by connectedCallback as this attributeChangedCallback will not fire.
//
// https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
//
// TODO(STENCIL-16) we should think about whether or not we actually want to be reflecting the attributes to
// properties here given that this goes against best practices outlined here
// https://developers.google.com/web/fundamentals/web-components/best-practices#avoid-reentrancy
if (this.hasOwnProperty(propName)) {
newValue = this[propName];
delete this[propName];
}
else if (prototype.hasOwnProperty(propName) &&
typeof this[propName] === 'number' &&
this[propName] == newValue) {
// if the propName exists on the prototype of `Cstr`, this update may be a result of Stencil using native
// APIs to reflect props as attributes. Calls to `setAttribute(someElement, propName)` will result in
// `propName` to be converted to a `DOMString`, which may not be what we want for other primitive props.
return;
}
else if (propName == null) {
// At this point we should know this is not a "member", so we can treat it like watching an attribute
// on a vanilla web component
const hostRef = getHostRef(this);
const flags = hostRef === null || hostRef === void 0 ? void 0 : hostRef.$flags$;
// We only want to trigger the callback(s) if:
// 1. The instance is ready
// 2. The watchers are ready
// 3. The value has changed
if (flags &&
!(flags & 8 /* HOST_FLAGS.isConstructingInstance */) &&
flags & 128 /* HOST_FLAGS.isWatchReady */ &&
newValue !== oldValue) {
const elm = this;
const instance = elm;
const entry = (_a = cmpMeta.$watchers$) === null || _a === void 0 ? void 0 : _a[attrName];
entry === null || entry === void 0 ? void 0 : entry.forEach((callbackName) => {
if (instance[callbackName] != null) {
instance[callbackName].call(instance, newValue, oldValue, attrName);
}
});
}
return;
}
this[propName] = newValue === null && typeof this[propName] === 'boolean' ? false : newValue;
});
};
// Create an array of attributes to observe
// This list in comprised of all strings used within a `@Watch()` decorator
// on a component as well as any Stencil-specific "members" (`@Prop()`s and `@State()`s).
// As such, there is no way to guarantee type-safety here that a user hasn't entered
// an invalid attribute.
Cstr.observedAttributes = Array.from(new Set([
...Object.keys((_a = cmpMeta.$watchers$) !== null && _a !== void 0 ? _a : {}),
...members
.filter(([_, m]) => m[0] & 15 /* MEMBER_FLAGS.HasAttribute */)
.map(([propName, m]) => {
var _a;
const attrName = m[1] || propName;
attrNameToPropName.set(attrName, propName);
if (m[0] & 512 /* MEMBER_FLAGS.ReflectAttr */) {
(_a = cmpMeta.$attrsToReflect$) === null || _a === void 0 ? void 0 : _a.push([propName, attrName]);
}
return attrName;
}),
]));
}
}
return Cstr;
};
/**
* Initialize a Stencil component given a reference to its host element, its
* runtime bookkeeping data structure, runtime metadata about the component,
* and (optionally) an HMR version ID.
*
* @param elm a host element
* @param hostRef the element's runtime bookkeeping object
* @param cmpMeta runtime metadata for the Stencil component
* @param hmrVersionId an (optional) HMR version ID
*/
const initializeComponent = async (elm, hostRef, cmpMeta, hmrVersionId) => {
let Cstr;
// initializeComponent
if ((hostRef.$flags$ & 32 /* HOST_FLAGS.hasInitializedComponent */) === 0) {
// Let the runtime know that the component has been initialized
hostRef.$flags$ |= 32 /* HOST_FLAGS.hasInitializedComponent */;
{
// sync constructor component
Cstr = elm.constructor;
// wait for the CustomElementRegistry to mark the component as ready before setting `isWatchReady`. Otherwise,
// watchers may fire prematurely if `customElements.get()`/`customElements.whenDefined()` resolves _before_
// Stencil has completed instantiating the component.
customElements.whenDefined(cmpMeta.$tagName$).then(() => (hostRef.$flags$ |= 128 /* HOST_FLAGS.isWatchReady */));
}
if (Cstr.style) {
// this component has styles but we haven't registered them yet
let style = Cstr.style;
if (typeof style !== 'string') {
style = style[(hostRef.$modeName$ = computeMode(elm))];
}
const scopeId = getScopeId(cmpMeta, hostRef.$modeName$);
if (!styles.has(scopeId)) {
const endRegisterStyles = createTime('registerStyles', cmpMeta.$tagName$);
registerStyle(scopeId, style, !!(cmpMeta.$flags$ & 1 /* CMP_FLAGS.shadowDomEncapsulation */));
endRegisterStyles();
}
}
}
// we've successfully created a lazy instance
hostRef.$ancestorComponent$;
const schedule = () => scheduleUpdate(hostRef, true);
{
schedule();
}
};
const fireConnectedCallback = (instance) => {
};
const connectedCallback = (elm) => {
if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
const hostRef = getHostRef(elm);
const cmpMeta = hostRef.$cmpMeta$;
const endConnected = createTime('connectedCallback', cmpMeta.$tagName$);
if (!(hostRef.$flags$ & 1 /* HOST_FLAGS.hasConnected */)) {
// first time this component has connected
hostRef.$flags$ |= 1 /* HOST_FLAGS.hasConnected */;
{
// initUpdate
// if the slot polyfill is required we'll need to put some nodes
// in here to act as original content anchors as we move nodes around
// host element has been connected to the DOM
if ((// TODO(STENCIL-854): Remove code related to legacy shadowDomShim field
cmpMeta.$flags$ & (4 /* CMP_FLAGS.hasSlotRelocation */ | 8 /* CMP_FLAGS.needsShadowDomShim */))) {
setContentReference(elm);
}
}
// Lazy properties
// https://developers.google.com/web/fundamentals/web-components/best-practices#lazy-properties
if (cmpMeta.$members$) {
Object.entries(cmpMeta.$members$).map(([memberName, [memberFlags]]) => {
if (memberFlags & 31 /* MEMBER_FLAGS.Prop */ && elm.hasOwnProperty(memberName)) {
const value = elm[memberName];
delete elm[memberName];
elm[memberName] = value;
}
});
}
{
initializeComponent(elm, hostRef, cmpMeta);
}
}
else {
// not the first time this has connected
// reattach any event listeners to the host
// since they would have been removed when disconnected
addHostEventListeners(elm, hostRef, cmpMeta.$listeners$);
// fire off connectedCallback() on component instance
if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$lazyInstance$) {
fireConnectedCallback(hostRef.$lazyInstance$);
}
else if (hostRef === null || hostRef === void 0 ? void 0 : hostRef.$onReadyPromise$) {
hostRef.$onReadyPromise$.then(() => fireConnectedCallback(hostRef.$lazyInstance$));
}
}
endConnected();
}
};
const setContentReference = (elm) => {
// only required when we're NOT using native shadow dom (slot)
// or this browser doesn't support native shadow dom
// and this host element was NOT created with SSR
// let's pick out the inner content for slot projection
// create a node to represent where the original
// content was first placed, which is useful later on
const contentRefElm = (elm['s-cr'] = doc$1.createComment(''));
contentRefElm['s-cn'] = true;
elm.insertBefore(contentRefElm, elm.firstChild);
};
const disconnectedCallback = async (elm) => {
if ((plt.$flags$ & 1 /* PLATFORM_FLAGS.isTmpDisconnected */) === 0) {
const hostRef = getHostRef(elm);
{
if (hostRef.$rmListeners$) {
hostRef.$rmListeners$.map((rmListener) => rmListener());
hostRef.$rmListeners$ = undefined;
}
}
}
};
const proxyCustomElement = (Cstr, compactMeta) => {
const cmpMeta = {
$flags$: compactMeta[0],
$tagName$: compactMeta[1],
};
{
cmpMeta.$members$ = compactMeta[2];
}
{
cmpMeta.$listeners$ = compactMeta[3];
}
{
cmpMeta.$watchers$ = Cstr.$watchers$;
}
{
cmpMeta.$attrsToReflect$ = [];
}
const originalConnectedCallback = Cstr.prototype.connectedCallback;
const originalDisconnectedCallback = Cstr.prototype.disconnectedCallback;
Object.assign(Cstr.prototype, {
__registerHost() {
registerHost(this, cmpMeta);
},
connectedCallback() {
connectedCallback(this);
if (originalConnectedCallback) {
originalConnectedCallback.call(this);
}
},
disconnectedCallback() {
disconnectedCallback(this);
if (originalDisconnectedCallback) {
originalDisconnectedCallback.call(this);
}
},
__attachShadow() {
{
{
this.attachShadow({
mode: 'open',
delegatesFocus: !!(cmpMeta.$flags$ & 16 /* CMP_FLAGS.shadowDelegatesFocus */),
});
}
}
},
});
Cstr.is = cmpMeta.$tagName$;
return proxyComponent(Cstr, cmpMeta);
};
const addHostEventListeners = (elm, hostRef, listeners, attachParentListeners) => {
if (listeners) {
listeners.map(([flags, name, method]) => {
const target = getHostListenerTarget(elm, flags) ;
const handler = hostListenerProxy(hostRef, method);
const opts = hostListenerOpts(flags);
plt.ael(target, name, handler, opts);
(hostRef.$rmListeners$ = hostRef.$rmListeners$ || []).push(() => plt.rel(target, name, handler, opts));
});
}
};
const hostListenerProxy = (hostRef, methodName) => (ev) => {
try {
if (BUILD.lazyLoad) ;
else {
hostRef.$hostElement$[methodName](ev);
}
}
catch (e) {
consoleError(e);
}
};
const getHostListenerTarget = (elm, flags) => {
if (flags & 4 /* LISTENER_FLAGS.TargetDocument */)
return doc$1;
if (flags & 8 /* LISTENER_FLAGS.TargetWindow */)
return win;
if (flags & 16 /* LISTENER_FLAGS.TargetBody */)
return doc$1.body;
return elm;
};
// prettier-ignore
const hostListenerOpts = (flags) => supportsListenerOptions
? ({
passive: (flags & 1 /* LISTENER_FLAGS.Passive */) !== 0,
capture: (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0,
})
: (flags & 2 /* LISTENER_FLAGS.Capture */) !== 0;
/**
* A WeakMap mapping runtime component references to their corresponding host reference
* instances.
*/
const hostRefs = /*@__PURE__*/ new WeakMap();
/**
* Given a {@link d.RuntimeRef} retrieve the corresponding {@link d.HostRef}
*
* @param ref the runtime ref of interest
* @returns the Host reference (if found) or undefined
*/
const getHostRef = (ref) => hostRefs.get(ref);
/**
* Register a host element for a Stencil component, setting up various metadata
* and callbacks based on {@link BUILD} flags as well as the component's runtime
* metadata.
*
* @param hostElement the host element to register
* @param cmpMeta runtime metadata for that component
* @returns a reference to the host ref WeakMap
*/
const registerHost = (hostElement, cmpMeta) => {
const hostRef = {
$flags$: 0,
$hostElement$: hostElement,
$cmpMeta$: cmpMeta,
$instanceValues$: new Map(),
};
addHostEventListeners(hostElement, hostRef, cmpMeta.$listeners$);
return hostRefs.set(hostElement, hostRef);
};
const isMemberInElement = (elm, memberName) => memberName in elm;
const consoleError = (e, el) => (0, console.error)(e, el);
const styles = /*@__PURE__*/ new Map();
const modeResolutionChain = [];
const win = typeof window !== 'undefined' ? window : {};
const doc$1 = win.document || { head: {} };
const H = (win.HTMLElement || class {
});
const plt = {
$flags$: 0,
$resourcesUrl$: '',
jmp: (h) => h(),
raf: (h) => requestAnimationFrame(h),
ael: (el, eventName, listener, opts) => el.addEventListener(eventName, listener, opts),
rel: (el, eventName, listener, opts) => el.removeEventListener(eventName, listener, opts),
ce: (eventName, opts) => new CustomEvent(eventName, opts),
};
const supportsListenerOptions = /*@__PURE__*/ (() => {
let supportsListenerOptions = false;
try {
doc$1.addEventListener('e', null, Object.defineProperty({}, 'passive', {
get() {
supportsListenerOptions = true;
},
}));
}
catch (e) { }
return supportsListenerOptions;
})();
const promiseResolve = (v) => Promise.resolve(v);
const supportsConstructableStylesheets = /*@__PURE__*/ (() => {
try {
new CSSStyleSheet();
return typeof new CSSStyleSheet().replaceSync === 'function';
}
catch (e) { }
return false;
})()
;
const queueDomReads = [];
const queueDomWrites = [];
const queueTask = (queue, write) => (cb) => {
queue.push(cb);
if (!queuePending) {
queuePending = true;
if (write && plt.$flags$ & 4 /* PLATFORM_FLAGS.queueSync */) {
nextTick(flush);
}
else {
plt.raf(flush);
}
}
};
const consume = (queue) => {
for (let i = 0; i < queue.length; i++) {
try {
queue[i](performance.now());
}
catch (e) {
consoleError(e);
}
}
queue.length = 0;
};
const flush = () => {
// always force a bunch of medium callbacks to run, but still have
// a throttle on how many can run in a certain time
// DOM READS!!!
consume(queueDomReads);
// DOM WRITES!!!
{
consume(queueDomWrites);
if ((queuePending = queueDomReads.length > 0)) {
// still more to do yet, but we've run out of time
// let's let this thing cool off and try again in the next tick
plt.raf(flush);
}
}
};
const nextTick = (cb) => promiseResolve().then(cb);
const writeTask = /*@__PURE__*/ queueTask(queueDomWrites, true);
const filePreviewCss = ":host{display:block;font-size:13px}img,video{max-width:100%;margin-top:10px}";
const FilePreview$1 = /*@__PURE__*/ proxyCustomElement(class FilePreview extends H {
constructor() {
super();
this.__registerHost();
this.__attachShadow();
this.src = undefined;
this.filetype = undefined;
}
render() {
return (h(Host, { class: this.computeClass() }, this.isImage() && h("img", { src: this.src }), this.isVideo() && h("video", { src: this.src, onClick: toggle }), this.isOther() && "This file does not offer a preview", h("slot", null)));
}
computeClass() {
if (this.isImage())
return "image";
if (this.isVideo())
return "video";
return "other";
}
isImage() {
return this.filetype == "image";
}
isVideo() {
return this.filetype == "video";
}
isOther() {
return !this.isImage() && !this.isVideo();
}
static get style() { return filePreviewCss; }
}, [1, "file-preview", {
"src": [513],
"filetype": [513]
}]);
const toggle = function () { this.paused ? this.play() : this.pause(); return false; };
const progressBarCss = ":host{display:block;position:relative;padding:0 20px;border:1px solid rgba(0, 0, 0, 0.3);border-radius:3px;line-height:2;flex:1 0;box-sizing:border-box;text-align:left;font-size:13px}.bar{position:absolute;top:0;left:0;bottom:0;background:rgba(57, 137, 39, 1);transition:width 120ms ease-out, opacity 60ms 60ms ease-in;transform:translate3d(0, 0, 0)}.content{position:relative;color:#fff;font-size:1em}";
const ProgressBar$1 = /*@__PURE__*/ proxyCustomElement(class ProgressBar extends H {
constructor() {
super();
this.__registerHost();
this.__attachShadow();
this.percent = 0;
}
render() {
return (h(Host, null, h("div", { class: "bar", style: { width: `${this.percent}%` } }), h("span", { class: "content" }, h("slot", null))));
}
static get style() { return progressBarCss; }
}, [1, "progress-bar", {
"percent": [514]
}]);
var sparkMd5 = {
exports: {}
};
(function(module, exports) {
(function(factory) {
{
module.exports = factory();
}
})((function(undefined$1) {
var hex_chr = [ "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "a", "b", "c", "d", "e", "f" ];
function md5cycle(x, k) {
var a = x[0], b = x[1], c = x[2], d = x[3];
a += (b & c | ~b & d) + k[0] - 680876936 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[1] - 389564586 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[2] + 606105819 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[3] - 1044525330 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & c | ~b & d) + k[4] - 176418897 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[5] + 1200080426 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[6] - 1473231341 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[7] - 45705983 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & c | ~b & d) + k[8] + 1770035416 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[9] - 1958414417 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[10] - 42063 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[11] - 1990404162 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & c | ~b & d) + k[12] + 1804603682 | 0;
a = (a << 7 | a >>> 25) + b | 0;
d += (a & b | ~a & c) + k[13] - 40341101 | 0;
d = (d << 12 | d >>> 20) + a | 0;
c += (d & a | ~d & b) + k[14] - 1502002290 | 0;
c = (c << 17 | c >>> 15) + d | 0;
b += (c & d | ~c & a) + k[15] + 1236535329 | 0;
b = (b << 22 | b >>> 10) + c | 0;
a += (b & d | c & ~d) + k[1] - 165796510 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[6] - 1069501632 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[11] + 643717713 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[0] - 373897302 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b & d | c & ~d) + k[5] - 701558691 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[10] + 38016083 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[15] - 660478335 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[4] - 405537848 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b & d | c & ~d) + k[9] + 568446438 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[14] - 1019803690 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[3] - 187363961 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[8] + 1163531501 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b & d | c & ~d) + k[13] - 1444681467 | 0;
a = (a << 5 | a >>> 27) + b | 0;
d += (a & c | b & ~c) + k[2] - 51403784 | 0;
d = (d << 9 | d >>> 23) + a | 0;
c += (d & b | a & ~b) + k[7] + 1735328473 | 0;
c = (c << 14 | c >>> 18) + d | 0;
b += (c & a | d & ~a) + k[12] - 1926607734 | 0;
b = (b << 20 | b >>> 12) + c | 0;
a += (b ^ c ^ d) + k[5] - 378558 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[8] - 2022574463 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[11] + 1839030562 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[14] - 35309556 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (b ^ c ^ d) + k[1] - 1530992060 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[4] + 1272893353 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[7] - 155497632 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[10] - 1094730640 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (b ^ c ^ d) + k[13] + 681279174 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[0] - 358537222 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[3] - 722521979 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[6] + 76029189 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (b ^ c ^ d) + k[9] - 640364487 | 0;
a = (a << 4 | a >>> 28) + b | 0;
d += (a ^ b ^ c) + k[12] - 421815835 | 0;
d = (d << 11 | d >>> 21) + a | 0;
c += (d ^ a ^ b) + k[15] + 530742520 | 0;
c = (c << 16 | c >>> 16) + d | 0;
b += (c ^ d ^ a) + k[2] - 995338651 | 0;
b = (b << 23 | b >>> 9) + c | 0;
a += (c ^ (b | ~d)) + k[0] - 198630844 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[7] + 1126891415 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[14] - 1416354905 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[5] - 57434055 | 0;
b = (b << 21 | b >>> 11) + c | 0;
a += (c ^ (b | ~d)) + k[12] + 1700485571 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[3] - 1894986606 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[10] - 1051523 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[1] - 2054922799 | 0;
b = (b << 21 | b >>> 11) + c | 0;
a += (c ^ (b | ~d)) + k[8] + 1873313359 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[15] - 30611744 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[6] - 1560198380 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[13] + 1309151649 | 0;
b = (b << 21 | b >>> 11) + c | 0;
a += (c ^ (b | ~d)) + k[4] - 145523070 | 0;
a = (a << 6 | a >>> 26) + b | 0;
d += (b ^ (a | ~c)) + k[11] - 1120210379 | 0;
d = (d << 10 | d >>> 22) + a | 0;
c += (a ^ (d | ~b)) + k[2] + 718787259 | 0;
c = (c << 15 | c >>> 17) + d | 0;
b += (d ^ (c | ~a)) + k[9] - 343485551 | 0;
b = (b << 21 | b >>> 11) + c | 0;
x[0] = a + x[0] | 0;
x[1] = b + x[1] | 0;
x[2] = c + x[2] | 0;
x[3] = d + x[3] | 0;
}
function md5blk(s) {
var md5blks = [], i;
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = s.charCodeAt(i) + (s.charCodeAt(i + 1) << 8) + (s.charCodeAt(i + 2) << 16) + (s.charCodeAt(i + 3) << 24);
}
return md5blks;
}
function md5blk_array(a) {
var md5blks = [], i;
for (i = 0; i < 64; i += 4) {
md5blks[i >> 2] = a[i] + (a[i + 1] << 8) + (a[i + 2] << 16) + (a[i + 3] << 24);
}
return md5blks;
}
function md51(s) {
var n = s.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk(s.substring(i - 64, i)));
}
s = s.substring(i - 64);
length = s.length;
tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= s.charCodeAt(i) << (i % 4 << 3);
}
tail[i >> 2] |= 128 << (i % 4 << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
tmp = n * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(state, tail);
return state;
}
function md51_array(a) {
var n = a.length, state = [ 1732584193, -271733879, -1732584194, 271733878 ], i, length, tail, tmp, lo, hi;
for (i = 64; i <= n; i += 64) {
md5cycle(state, md5blk_array(a.subarray(i - 64, i)));
}
a = i - 64 < n ? a.subarray(i - 64) : new Uint8Array(0);
length = a.length;
tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= a[i] << (i % 4 << 3);
}
tail[i >> 2] |= 128 << (i % 4 << 3);
if (i > 55) {
md5cycle(state, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
tmp = n * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(state, tail);
return state;
}
function rhex(n) {
var s = "", j;
for (j = 0; j < 4; j += 1) {
s += hex_chr[n >> j * 8 + 4 & 15] + hex_chr[n >> j * 8 & 15];
}
return s;
}
function hex(x) {
var i;
for (i = 0; i < x.length; i += 1) {
x[i] = rhex(x[i]);
}
return x.join("");
}
if (hex(md51("hello")) !== "5d41402abc4b2a76b9719d911017c592") ;
if (typeof ArrayBuffer !== "undefined" && !ArrayBuffer.prototype.slice) {
(function() {
function clamp(val, length) {
val = val | 0 || 0;
if (val < 0) {
return Math.max(val + length, 0);
}
return Math.min(val, length);
}
ArrayBuffer.prototype.slice = function(from, to) {
var length = this.byteLength, begin = clamp(from, length), end = length, num, target, targetArray, sourceArray;
if (to !== undefined$1) {
end = clamp(to, length);
}
if (begin > end) {
return new ArrayBuffer(0);
}
num = end - begin;
target = new ArrayBuffer(num);
targetArray = new Uint8Array(target);
sourceArray = new Uint8Array(this, begin, num);
targetArray.set(sourceArray);
return target;
};
})();
}
function toUtf8(str) {
if (/[\u0080-\uFFFF]/.test(str)) {
str = unescape(encodeURIComponent(str));
}
return str;
}
function utf8Str2ArrayBuffer(str, returnUInt8Array) {
var length = str.length, buff = new ArrayBuffer(length), arr = new Uint8Array(buff), i;
for (i = 0; i < length; i += 1) {
arr[i] = str.charCodeAt(i);
}
return returnUInt8Array ? arr : buff;
}
function arrayBuffer2Utf8Str(buff) {
return String.fromCharCode.apply(null, new Uint8Array(buff));
}
function concatenateArrayBuffers(first, second, returnUInt8Array) {
var result = new Uint8Array(first.byteLength + second.byteLength);
result.set(new Uint8Array(first));
result.set(new Uint8Array(second), first.byteLength);
return returnUInt8Array ? result : result.buffer;
}
function hexToBinaryString(hex) {
var bytes = [], length = hex.length, x;
for (x = 0; x < length - 1; x += 2) {
bytes.push(parseInt(hex.substr(x, 2), 16));
}
return String.fromCharCode.apply(String, bytes);
}
function SparkMD5() {
this.reset();
}
SparkMD5.prototype.append = function(str) {
this.appendBinary(toUtf8(str));
return this;
};
SparkMD5.prototype.appendBinary = function(contents) {
this._buff += contents;
this._length += contents.length;
var length = this._buff.length, i;
for (i = 64; i <= length; i += 64) {
md5cycle(this._hash, md5blk(this._buff.substring(i - 64, i)));
}
this._buff = this._buff.substring(i - 64);
return this;
};
SparkMD5.prototype.end = function(raw) {
var buff = this._buff, length = buff.length, i, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], ret;
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff.charCodeAt(i) << (i % 4 << 3);
}
this._finish(tail, length);
ret = hex(this._hash);
if (raw) {
ret = hexToBinaryString(ret);
}
this.reset();
return ret;
};
SparkMD5.prototype.reset = function() {
this._buff = "";
this._length = 0;
this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
return this;
};
SparkMD5.prototype.getState = function() {
return {
buff: this._buff,
length: this._length,
hash: this._hash.slice()
};
};
SparkMD5.prototype.setState = function(state) {
this._buff = state.buff;
this._length = state.length;
this._hash = state.hash;
return this;
};
SparkMD5.prototype.destroy = function() {
delete this._hash;
delete this._buff;
delete this._length;
};
SparkMD5.prototype._finish = function(tail, length) {
var i = length, tmp, lo, hi;
tail[i >> 2] |= 128 << (i % 4 << 3);
if (i > 55) {
md5cycle(this._hash, tail);
for (i = 0; i < 16; i += 1) {
tail[i] = 0;
}
}
tmp = this._length * 8;
tmp = tmp.toString(16).match(/(.*?)(.{0,8})$/);
lo = parseInt(tmp[2], 16);
hi = parseInt(tmp[1], 16) || 0;
tail[14] = lo;
tail[15] = hi;
md5cycle(this._hash, tail);
};
SparkMD5.hash = function(str, raw) {
return SparkMD5.hashBinary(toUtf8(str), raw);
};
SparkMD5.hashBinary = function(content, raw) {
var hash = md51(content), ret = hex(hash);
return raw ? hexToBinaryString(ret) : ret;
};
SparkMD5.ArrayBuffer = function() {
this.reset();
};
SparkMD5.ArrayBuffer.prototype.append = function(arr) {
var buff = concatenateArrayBuffers(this._buff.buffer, arr, true), length = buff.length, i;
this._length += arr.byteLength;
for (i = 64; i <= length; i += 64) {
md5cycle(this._hash, md5blk_array(buff.subarray(i - 64, i)));
}
this._buff = i - 64 < length ? new Uint8Array(buff.buffer.slice(i - 64)) : new Uint8Array(0);
return this;
};
SparkMD5.ArrayBuffer.prototype.end = function(raw) {
var buff = this._buff, length = buff.length, tail = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ], i, ret;
for (i = 0; i < length; i += 1) {
tail[i >> 2] |= buff[i] << (i % 4 << 3);
}
this._finish(tail, length);
ret = hex(this._hash);
if (raw) {
ret = hexToBinaryString(ret);
}
this.reset();
return ret;
};
SparkMD5.ArrayBuffer.prototype.reset = function() {
this._buff = new Uint8Array(0);
this._length = 0;
this._hash = [ 1732584193, -271733879, -1732584194, 271733878 ];
return this;
};
SparkMD5.ArrayBuffer.prototype.getState = function() {
var state = SparkMD5.prototype.getState.call(this);
state.buff = arrayBuffer2Utf8Str(state.buff);
return state;
};
SparkMD5.ArrayBuffer.prototype.setState = function(state) {
state.buff = utf8Str2ArrayBuffer(state.buff, true);
return SparkMD5.prototype.setState.call(this, state);
};
SparkMD5.ArrayBuffer.prototype.destroy = SparkMD5.prototype.destroy;
SparkMD5.ArrayBuffer.prototype._finish = SparkMD5.prototype._finish;
SparkMD5.ArrayBuffer.hash = function(arr, raw) {
var hash = md51_array(new Uint8Array(arr)), ret = hex(hash);
return raw ? hexToBinaryString(ret) : ret;
};
return SparkMD5;
}));
})(sparkMd5);
var SparkMD5 = sparkMd5.exports;
const fileSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
class FileChecksum {
static create(file, callback) {
const instance = new FileChecksum(file);
instance.create(callback);
}
constructor(file) {
this.file = file;
this.chunkSize = 2097152;
this.chunkCount = Math.ceil(this.file.size / this.chunkSize);
this.chunkIndex = 0;
}
create(callback) {
this.callback = callback;
this.md5Buffer = new SparkMD5.ArrayBuffer;
this.fileReader = new FileReader;
this.fileReader.addEventListener("load", (event => this.fileReaderDidLoad(event)));
this.fileReader.addEventListener("error", (event => this.fileReaderDidError(event)));
this.readNextChunk();
}
fileReaderDidLoad(event) {
this.md5Buffer.append(event.target.result);
if (!this.readNextChunk()) {
const binaryDigest = this.md5Buffer.end(true);
const base64digest = btoa(binaryDigest);
this.callback(null, base64digest);
}
}
fileReaderDidError(event) {
this.callback(`Error reading ${this.file.name}`);
}
readNextChunk() {
if (this.chunkIndex < this.chunkCount || this.chunkIndex == 0 && this.chunkCount == 0) {
const start = this.chunkIndex * this.chunkSize;
const end = Math.min(start + this.chunkSize, this.file.size);
const bytes = fileSlice.call(this.file, start, end);
this.fileReader.readAsArrayBuffer(bytes);
this.chunkIndex++;
return true;
} else {
return false;
}
}
}
function getMetaValue(name) {
const element = findElement(document.head, `meta[name="${name}"]`);
if (element) {
return element.getAttribute("content");
}
}
function findElements(root, selector) {
if (typeof root == "string") {
selector = root;
root = document;
}
const elements = root.querySelectorAll(selector);
return toArray(elements);
}
function findElement(root, selector) {
if (typeof root == "string") {
selector = root;
root = document;
}
return root.querySelector(selector);
}
function dispatchEvent$1(element, type, eventInit = {}) {
const {disabled: disabled} = element;
const {bubbles: bubbles, cancelable: cancelable, detail: detail} = eventInit;
const event = document.createEvent("Event");
event.initEvent(type, bubbles || true, cancelable || true);
event.detail = detail || {};
try {
element.disabled = false;
element.dispatchEvent(event);
} finally {
element.disabled = disabled;
}
return event;
}
function toArray(value) {
if (Array.isArray(value)) {
return value;
} else if (Array.from) {
return Array.from(value);
} else {
return [].slice.call(value);
}
}
class BlobRecord {
constructor(file, checksum, url, customHeaders = {}) {
this.file = file;
this.attributes = {
filename: file.name,
content_type: file.type || "application/octet-stream",
byte_size: file.size,
checksum: checksum
};
this.xhr = new XMLHttpRequest;
this.xhr.open("POST", url, true);
this.xhr.responseType = "json";
this.xhr.setRequestHeader("Content-Type", "application/json");
this.xhr.setRequestHeader("Accept", "application/json");
this.xhr.setRequestHeader("X-Requested-With", "XMLHttpRequest");
Object.keys(customHeaders).forEach((headerKey => {
this.xhr.setRequestHeader(headerKey, customHeaders[headerKey]);
}));
const csrfToken = getMetaValue("csrf-token");
if (csrfToken != undefined) {
this.xhr.setRequestHeader("X-CSRF-Token", csrfToken);
}
this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
this.xhr.addEventListener("error", (event => this.requestDidError(event)));
}
get status() {
return this.xhr.status;
}
get response() {
const {responseType: responseType, response: response} = this.xhr;
if (responseType == "json") {
return response;
} else {
return JSON.parse(response);
}
}
create(callback) {
this.callback = callback;
this.xhr.send(JSON.stringify({
blob: this.attributes
}));
}
requestDidLoad(event) {
if (this.status >= 200 && this.status < 300) {
const {response: response} = this;
const {direct_upload: direct_upload} = response;
delete response.direct_upload;
this.attributes = response;
this.directUploadData = direct_upload;
this.callback(null, this.toJSON());
} else {
this.requestDidError(event);
}
}
requestDidError(event) {
this.callback(`Error creating Blob for "${this.file.name}". Status: ${this.status}`);
}
toJSON() {
const result = {};
for (const key in this.attributes) {
result[key] = this.attributes[key];
}
return result;
}
}
class BlobUpload {
constructor(blob) {
this.blob = blob;
this.file = blob.file;
const {url: url, headers: headers} = blob.directUploadData;
this.xhr = new XMLHttpRequest;
this.xhr.open("PUT", url, true);
this.xhr.responseType = "text";
for (const key in headers) {
this.xhr.setRequestHeader(key, headers[key]);
}
this.xhr.addEventListener("load", (event => this.requestDidLoad(event)));
this.xhr.addEventListener("error", (event => this.requestDidError(event)));
}
create(callback) {
this.callback = callback;
this.xhr.send(this.file.slice());
}
requestDidLoad(event) {
const {status: status, response: response} = this.xhr;
if (status >= 200 && status < 300) {
this.callback(null, response);
} else {
this.requestDidError(event);
}
}
requestDidError(event) {
this.callback(`Error storing "${this.file.name}". Status: ${this.xhr.status}`);
}
}
let id = 0;
class DirectUpload {
constructor(file, url, delegate, customHeaders = {}) {
this.id = ++id;
this.file = file;
this.url = url;
this.delegate = delegate;
this.customHeaders = customHeaders;
}
create(callback) {
FileChecksum.create(this.file, ((error, checksum) => {
if (error) {
callback(error);
return;
}
const blob = new BlobRecord(this.file, checksum, this.url, this.customHeaders);
notify(this.delegate, "directUploadWillCreateBlobWithXHR", blob.xhr);
blob.create((error => {
if (error) {
callback(error);
} else {
const upload = new BlobUpload(blob);
notify(this.delegate, "directUploadWillStoreFileWithXHR", upload.xhr);
upload.create((error => {
if (error) {
callback(error);
} else {
callback(null, blob.toJSON());
}
}));
}
}));
}));
}
}
function notify(object, methodName, ...messages) {
if (object && typeof object[methodName] == "function") {
return object[methodName](...messages);
}
}
class DirectUploadController$1 {
constructor(input, file) {
this.input = input;
this.file = file;
this.directUpload = new DirectUpload(this.file, this.url, this);
this.dispatch("initialize");
}
start(callback) {
const hiddenInput = document.createElement("input");
hiddenInput.type = "hidden";
hiddenInput.name = this.input.name;
this.input.insertAdjacentElement("beforebegin", hiddenInput);
this.dispatch("start");
this.directUpload.create(((error, attributes) => {
if (error) {
hiddenInput.parentNode.removeChild(hiddenInput);
this.dispatchError(error);
} else {
hiddenInput.value = attributes.signed_id;
}
this.dispatch("end");
callback(error);
}));
}
uploadRequestDidProgress(event) {
const progress = event.loaded / event.total * 100;
if (progress) {
this.dispatch("progress", {
progress: progress
});
}
}
get url() {
return this.input.getAttribute("data-direct-upload-url");
}
dispatch(name, detail = {}) {
detail.file = this.file;
detail.id = this.directUpload.id;
return dispatchEvent$1(this.input, `direct-upload:${name}`, {
detail: detail
});
}
dispatchError(error) {
const event = this.dispatch("error", {
error: error
});
if (!event.defaultPrevented) {
alert(error);
}
}
directUploadWillCreateBlobWithXHR(xhr) {
this.dispatch("before-blob-request", {
xhr: xhr
});
}
directUploadWillStoreFileWithXHR(xhr) {
this.dispatch("before-storage-request", {
xhr: xhr
});
xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
}
}
const inputSelector = "input[type=file][data-direct-upload-url]:not([disabled])";
class DirectUploadsController {
constructor(form) {
this.form = form;
this.inputs = findElements(form, inputSelector).filter((input => input.files.length));
}
start(callback) {
const controllers = this.createDirectUploadControllers();
const startNextController = () => {
const controller = controllers.shift();
if (controller) {
controller.start((error => {
if (error) {
callback(error);
this.dispatch("end");
} else {
startNextController();
}
}));
} else {
callback();
this.dispatch("end");
}
};
this.dispatch("start");
startNextController();
}
createDirectUploadControllers() {
const controllers = [];
this.inputs.forEach((input => {
toArray(input.files).forEach((file => {
const controller = new DirectUploadController$1(input, file);
controllers.push(controller);
}));
}));
return controllers;
}
dispatch(name, detail = {}) {
return dispatchEvent$1(this.form, `direct-uploads:${name}`, {
detail: detail
});
}
}
const processingAttribute = "data-direct-uploads-processing";
const submitButtonsByForm = new WeakMap;
let started = false;
function start() {
if (!started) {
started = true;
document.addEventListener("click", didClick, true);
document.addEventListener("submit", didSubmitForm, true);
document.addEventListener("ajax:before", didSubmitRemoteElement);
}
}
function didClick(event) {
const {target: target} = event;
if ((target.tagName == "INPUT" || target.tagName == "BUTTON") && target.type == "submit" && target.form) {
submitButtonsByForm.set(target.form, target);
}
}
function didSubmitForm(event) {
handleFormSubmissionEvent(event);
}
function didSubmitRemoteElement(event) {
if (event.target.tagName == "FORM") {
handleFormSubmissionEvent(event);
}
}
function handleFormSubmissionEvent(event) {
const form = event.target;
if (form.hasAttribute(processingAttribute)) {
event.preventDefault();
return;
}
const controller = new DirectUploadsController(form);
const {inputs: inputs} = controller;
if (inputs.length) {
event.preventDefault();
form.setAttribute(processingAttribute, "");
inputs.forEach(disable);
controller.start((error => {
form.removeAttribute(processingAttribute);
if (error) {
inputs.forEach(enable);
} else {
submitForm(form);
}
}));
}
}
function submitForm(form) {
let button = submitButtonsByForm.get(form) || findElement(form, "input[type=submit], button[type=submit]");
if (button) {
const {disabled: disabled} = button;
button.disabled = false;
button.focus();
button.click();
button.disabled = disabled;
} else {
button = document.createElement("input");
button.type = "submit";
button.style.display = "none";
form.appendChild(button);
button.click();
form.removeChild(button);
}
submitButtonsByForm.delete(form);
}
function disable(input) {
input.disabled = true;
}
function enable(input) {
input.disabled = false;
}
function autostart() {
if (window.ActiveStorage) {
start();
}
}
setTimeout(autostart, 1);
class DirectUploadController {
uploadedFile;
file;
directUpload;
recordXHR;
uploadXHR;
callback = null;
constructor(uploadedFile) {
this.uploadedFile = uploadedFile;
this.file = this.uploadedFile["file"];
this.directUpload = new DirectUpload(this.file, this.uploadedFile.url, this);
}
cancel() {
this.directUpload.url = null;
this.abortXHR(this.recordXHR);
this.abortXHR(this.uploadXHR);
}
abortXHR(xhr) {
if (!xhr)
return;
xhr.addEventListener("abort", () => {
this.complete("aborted", {});
});
xhr.abort();
}
start(callback) {
this.callback = callback;
this.dispatch("start");
this.directUpload.create((error, attributes) => {
this.complete(error, attributes);
});
}
complete(error, _attributes) {
if (error) {
this.dispatchError(error);
}
this.dispatch("end");
this.callback(error);
}
uploadRequestDidProgress(event) {
const progress = event.loaded / event.total * 100;
if (progress) {
this.dispatch("progress", {
progress: progress
});
}
}
dispatch(name, detail = {}) {
return dispatchEvent(this.uploadedFile, `direct-upload:${name}`, {
detail: {
...detail,
file: this.file,
id: this.directUpload.id,
}
});
}
dispatchError(error) {
this.dispatch("error", {
error: error
});
}
directUploadWillCreateBlobWithXHR(xhr) {
this.recordXHR = xhr;
this.dispatch("before-blob-request", {
xhr: xhr
});
}
directUploadWillStoreFileWithXHR(xhr) {
this.uploadXHR = xhr;
this.uploadedFile.value = this.recordXHR.response.signed_id;
this.dispatch("before-storage-request", {
xhr: xhr
});
xhr.upload.addEventListener("progress", (event => this.uploadRequestDidProgress(event)));
}
}
function dispatchEvent(element, type, eventInit = {}) {
const { disabled: disabled } = element;
const { bubbles: bubbles, cancelable: cancelable, detail: detail } = eventInit;
const event = document.createEvent("Event");
event.initEvent(type, bubbles || true, cancelable || true);
event.detail = detail || {};
try {
element.disabled = false;
element.dispatchEvent(event);
}
finally {
element.disabled = disabled;
}
return event;
}
class Max {
uploadedFile;
constructor(uploadedFile) {
this.uploadedFile = uploadedFile;
}
get errors() {
if (this.#errors)
return this.#errors;
this.#errors = [];
if (!this.checkValidity()) {
this.#errors.push(this.errorMessage);
}
return this.#errors;
}
#errors;
checkValidity() {
if (!this.uploadedFile.max)
return true;
return this.uploadedFile.size <= this.uploadedFile.max;
}
get errorMessage() {
return [
`Must be smaller than ${this.formatBytes(this.uploadedFile.max)},`,
`and "${this.uploadedFile.filename}" is ${this.formatBytes(this.uploadedFile.size)}.`,
`Please attach a smaller file.`,
].join(" ");
}
formatBytes(bytes, decimals = 2) {
if (bytes === 0)
return '0 Bytes';
const k = 1024;
const dm = decimals < 0 ? 0 : decimals;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i];
}
}
class Accepts {
uploadedFile;
constructor(uploadedFile) {
this.uploadedFile = uploadedFile;
}
get errors() {
if (this.#errors)
return this.#errors;
this.#errors = [];
const accepts = this.uploadedFile.accepts ? this.uploadedFile.accepts.split(/,\s*/) : [];
if (accepts.length > 0 && !accepts.includes(this.uploadedFile.filetype)) {
this.#errors.push(`Must be a ${this.joinWords(accepts)}.`);
}
return this.#errors;
}
#errors;
joinWords(words) {
if (words.length >= 3) {
return (words.slice(0, -1) + [`or ${words.at(-1)}`]).join(", ");
}
else {
return words.join(" or ");
}
}
}
const Extensions = {
image: ["ase", "art", "bmp", "blp", "cd5", "cit", "cpt", "cr2", "cut", "dds", "dib", "djvu", "egt", "exif", "gif", "gpl", "grf", "icns", "ico", "iff", "jng", "jpeg", "jpg", "jfif", "jp2", "jps", "lbm", "max", "miff", "mng", "msp", "nef", "nitf", "ota", "pbm", "pc1", "pc2", "pc3", "pcf", "pcx", "pdn", "pgm", "PI1", "PI2", "PI3", "pict", "pct", "pnm", "pns", "ppm", "psb", "psd", "pdd", "psp", "px", "pxm", "pxr", "qfx", "raw", "rle", "sct", "sgi", "rgb", "int", "bw", "tga", "tiff", "tif", "vtf", "xbm", "xcf", "xpm", "3dv", "amf", "ai", "awg", "cgm", "cdr", "cmx", "dxf", "e2d", "egt", "eps", "fs", "gbr", "odg", "svg", "stl", "vrml", "x3d", "sxd", "v2d", "vnd", "wmf", "emf", "art", "xar", "png", "webp", "jxr", "hdp", "wdp", "cur", "ecw", "iff", "lbm", "liff", "nrrd", "pam", "pcx", "pgf", "sgi", "rgb", "rgba", "bw", "int", "inta", "sid", "ras", "sun", "tga", "heic", "heif"],
video: ["3g2", "3gp", "3gpp", "aaf", "asf", "avchd", "avi", "drc", "flv", "m2v", "m3u8", "m4p", "m4v", "mkv", "mng", "mov", "mp2", "mp4", "mpe", "mpeg", "mpg", "mpv", "mxf", "nsv", "ogg", "ogv", "qt", "rm", "rmvb", "roq", "svi", "vob", "webm", "wmv", "yuv"],
pdf: ["pdf"],
getFileType: function (filename) {
const normalized = filename.toString().split(".").at(-1).toLowerCase().trim();
if (this.video.includes(normalized))
return "video";
if (this.image.includes(normalized))
return "image";
if (this.pdf.includes(normalized))
return "pdf";
return "unknown";
}
};
class FetchResponse {
constructor (response) {
this.response = response;
}
get statusCode () {
return this.response.status
}
get redirected () {
return this.response.redirected
}
get ok () {
return this.response.ok
}
get unauthenticated () {
return this.statusCode === 401
}
get unprocessableEntity () {
return this.statusCode === 422
}
get authenticationURL () {
return this.response.headers.get('WWW-Authenticate')
}
get contentType () {
const contentType = this.response.headers.get('Content-Type') || '';
return contentType.replace(/;.*$/, '')
}
get headers () {
return this.response.headers
}
get html () {
if (this.contentType.match(/^(application|text)\/(html|xhtml\+xml)$/)) {
return this.text
}
return Promise.reject(new Error(`Expected an HTML response but got "${this.contentType}" instead`))
}
get json () {
if (this.contentType.match(/^application\/.*json$/)) {
return this.responseJson || (this.responseJson = this.response.json())
}
return Promise.reject(new Error(`Expected a JSON response but got "${this.contentType}" instead`))
}
get text () {
return this.responseText || (this.responseText = this.response.text())
}
get isTurboStream () {
return this.contentType.match(/^text\/vnd\.turbo-stream\.html/)
}
async renderTurboStream () {
if (this.isTurboStream) {
if (window.Turbo) {
await window.Turbo.renderStreamMessage(await this.text);
} else {
console.warn('You must set `window.Turbo = Turbo` to automatically process Turbo Stream events with request.js');
}
} else {
return Promise.reject(new Error(`Expected a Turbo Stream response but got "${this.contentType}" instead`))
}
}
}
class RequestInterceptor {
static register (interceptor) {
this.interceptor = interceptor;
}
static get () {
return this.interceptor
}
static reset () {
this.interceptor = undefined;
}
}
function getCookie (name) {
const cookies = document.cookie ? document.cookie.split('; ') : [];
const prefix = `${encodeURIComponent(name)}=`;
const cookie = cookies.find(cookie => cookie.startsWith(prefix));
if (cookie) {
const value = cookie.split('=').slice(1).join('=');
if (value) {
return decodeURIComponent(value)
}
}
}
function compact (object) {
const result = {};
for (const key in object) {
const value = object[key];
if (value !== undefined) {
result[key] = value;
}
}
return result
}
function metaContent (name) {
const element = document.head.querySelector(`meta[name="${name}"]`);
return element && element.content
}
function stringEntriesFromFormData (formData) {
return [...formData].reduce((entries, [name, value]) => {
return entries.concat(typeof value === 'string' ? [[name, value]] : [])
}, [])
}
function mergeEntries (searchParams, entries) {
for (const [name, value] of entries) {
if (value instanceof window.File) continue
if (searchParams.has(name)) {
searchParams.delete(name);
searchParams.set(name, value);
} else {
searchParams.append(name, value);
}
}
}
class FetchRequest {
constructor (method, url, options = {}) {
this.method = method;
this.options = options;
this.originalUrl = url.toString();
}
async perform () {
try {
const requestInterceptor = RequestInterceptor.get();
if (requestInterceptor) {
await requestInterceptor(this);
}
} catch (error) {
console.error(error);
}
const response = new FetchResponse(await window.fetch(this.url, this.fetchOptions));
if (response.unauthenticated && response.authenticationURL) {
return Promise.reject(window.location.href = response.authenticationURL)
}
if (response.ok && response.isTurboStream) {
await response.renderTurboStream();
}
return response
}
addHeader (key, value) {
const headers = this.additionalHeaders;
headers[key] = value;
this.options.headers = headers;
}
get fetchOptions () {
return {
method: this.method.toUpperCase(),
headers: this.headers,
body: this.formattedBody,
signal: this.signal,
credentials: 'same-origin',
redirect: this.redirect
}
}
get headers () {
return compact(
Object.assign({
'X-Requested-With': 'XMLHttpRequest',
'X-CSRF-Token': this.csrfToken,
'Content-Type': this.contentType,
Accept: this.accept
},
this.additionalHeaders)
)
}
get csrfToken () {
return getCookie(metaContent('csrf-param')) || metaContent('csrf-token')
}
get contentType () {
if (this.options.contentType) {
return this.options.contentType
} else if (this.body == null || this.body instanceof window.FormData) {
return undefined
} else if (this.body instanceof window.File) {
return this.body.type
}
return 'application/json'
}
get accept () {
switch (this.responseKind) {
case 'html':
return 'text/html, application/xhtml+xml'
case 'turbo-stream':
return 'text/vnd.turbo-stream.html, text/html, application/xhtml+xml'
case 'json':
return 'application/json, application/vnd.api+json'
default:
return '*/*'
}
}
get body () {
return this.options.body
}
get query () {
const originalQuery = (this.originalUrl.split('?')[1] || '').split('#')[0];
const params = new URLSearchParams(originalQuery);
let requestQuery = this.options.query;
if (requestQuery instanceof window.FormData) {
requestQuery = stringEntriesFromFormData(requestQuery);
} else if (requestQuery instanceof window.URLSearchParams) {
requestQuery = requestQuery.entries();
} else {
requestQuery = Object.entries(requestQuery || {});
}
mergeEntries(params, requestQuery);
const query = params.toString();
return (query.length > 0 ? `?${query}` : '')
}
get url () {
return (this.originalUrl.split('?')[0]).split('#')[0] + this.query
}
get responseKind () {
return this.options.responseKind || 'html'
}
get signal () {
return this.options.signal
}
get redirect () {
return this.options.redirect || 'follow'
}
get additionalHeaders () {
return this.options.headers || {}
}
get formattedBody () {
const bodyIsAString = Object.prototype.toString.call(this.body) === '[object String]';
const contentTypeIsJson = this.headers['Content-Type'] === 'application/json';
if (contentTypeIsJson && !bodyIsAString) {
return JSON.stringify(this.body)
}
return this.body
}
}
const request = (verb, url, payload) => {
const req = new FetchRequest(verb, url, {
headers: { Accept: "application/json" },
body: payload,
});
return req.perform().then(response => {
if(response.response.ok) {
return response.json
} else {
return response
}
})
};
const get = (url, payload) => request('get', url, payload);
var DOCUMENT_FRAGMENT_NODE = 11;
function morphAttrs(fromNode, toNode) {
var toNodeAttrs = toNode.attributes;
var attr;
var attrName;
var attrNamespaceURI;
var attrValue;
var fromValue;
// document-fragments dont have attributes so lets not do anything
if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE || fromNode.nodeType === DOCUMENT_FRAGMENT_NODE) {
return;
}
// update attributes on original DOM element
for (var i = toNodeAttrs.length - 1; i >= 0; i--) {
attr = toNodeAttrs[i];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
attrValue = attr.value;
if (attrNamespaceURI) {
attrName = attr.localName || attrName;
fromValue = fromNode.getAttributeNS(attrNamespaceURI, attrName);
if (fromValue !== attrValue) {
if (attr.prefix === 'xmlns'){
attrName = attr.name; // It's not allowed to set an attribute with the XMLNS namespace without specifying the `xmlns` prefix
}
fromNode.setAttributeNS(attrNamespaceURI, attrName, attrValue);
}
} else {
fromValue = fromNode.getAttribute(attrName);
if (fromValue !== attrValue) {
fromNode.setAttribute(attrName, attrValue);
}
}
}
// Remove any extra attributes found on the original DOM element that
// weren't found on the target element.
var fromNodeAttrs = fromNode.attributes;
for (var d = fromNodeAttrs.length - 1; d >= 0; d--) {
attr = fromNodeAttrs[d];
attrName = attr.name;
attrNamespaceURI = attr.namespaceURI;
if (attrNamespaceURI) {
attrName = attr.localName || attrName;
if (!toNode.hasAttributeNS(attrNamespaceURI, attrName)) {
fromNode.removeAttributeNS(attrNamespaceURI, attrName);
}
} else {
if (!toNode.hasAttribute(attrName)) {
fromNode.removeAttribute(attrName);
}
}
}
}
var range; // Create a range object for efficently rendering strings to elements.
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
var doc = typeof document === 'undefined' ? undefined : document;
var HAS_TEMPLATE_SUPPORT = !!doc && 'content' in doc.createElement('template');
var HAS_RANGE_SUPPORT = !!doc && doc.createRange && 'createContextualFragment' in doc.createRange();
function createFragmentFromTemplate(str) {
var template = doc.createElement('template');
template.innerHTML = str;
return template.content.childNodes[0];
}
function createFragmentFromRange(str) {
if (!range) {
range = doc.createRange();
range.selectNode(doc.body);
}
var fragment = range.createContextualFragment(str);
return fragment.childNodes[0];
}
function createFragmentFromWrap(str) {
var fragment = doc.createElement('body');
fragment.innerHTML = str;
return fragment.childNodes[0];
}
/**
* This is about the same
* var html = new DOMParser().parseFromString(str, 'text/html');
* return html.body.firstChild;
*
* @method toElement
* @param {String} str
*/
function toElement(str) {
str = str.trim();
if (HAS_TEMPLATE_SUPPORT) {
// avoid restrictions on content for things like `
Hi ` which
// createContextualFragment doesn't support
//
support not available in IE
return createFragmentFromTemplate(str);
} else if (HAS_RANGE_SUPPORT) {
return createFragmentFromRange(str);
}
return createFragmentFromWrap(str);
}
/**
* Returns true if two node's names are the same.
*
* NOTE: We don't bother checking `namespaceURI` because you will never find two HTML elements with the same
* nodeName and different namespace URIs.
*
* @param {Element} a
* @param {Element} b The target element
* @return {boolean}
*/
function compareNodeNames(fromEl, toEl) {
var fromNodeName = fromEl.nodeName;
var toNodeName = toEl.nodeName;
var fromCodeStart, toCodeStart;
if (fromNodeName === toNodeName) {
return true;
}
fromCodeStart = fromNodeName.charCodeAt(0);
toCodeStart = toNodeName.charCodeAt(0);
// If the target element is a virtual DOM node or SVG node then we may
// need to normalize the tag name before comparing. Normal HTML elements that are
// in the "http://www.w3.org/1999/xhtml"
// are converted to upper case
if (fromCodeStart <= 90 && toCodeStart >= 97) { // from is upper and to is lower
return fromNodeName === toNodeName.toUpperCase();
} else if (toCodeStart <= 90 && fromCodeStart >= 97) { // to is upper and from is lower
return toNodeName === fromNodeName.toUpperCase();
} else {
return false;
}
}
/**
* Create an element, optionally with a known namespace URI.
*
* @param {string} name the element name, e.g. 'div' or 'svg'
* @param {string} [namespaceURI] the element's namespace URI, i.e. the value of
* its `xmlns` attribute or its inferred namespace.
*
* @return {Element}
*/
function createElementNS(name, namespaceURI) {
return !namespaceURI || namespaceURI === NS_XHTML ?
doc.createElement(name) :
doc.createElementNS(namespaceURI, name);
}
/**
* Copies the children of one DOM element to another DOM element
*/
function moveChildren(fromEl, toEl) {
var curChild = fromEl.firstChild;
while (curChild) {
var nextChild = curChild.nextSibling;
toEl.appendChild(curChild);
curChild = nextChild;
}
return toEl;
}
function syncBooleanAttrProp(fromEl, toEl, name) {
if (fromEl[name] !== toEl[name]) {
fromEl[name] = toEl[name];
if (fromEl[name]) {
fromEl.setAttribute(name, '');
} else {
fromEl.removeAttribute(name);
}
}
}
var specialElHandlers = {
OPTION: function(fromEl, toEl) {
var parentNode = fromEl.parentNode;
if (parentNode) {
var parentName = parentNode.nodeName.toUpperCase();
if (parentName === 'OPTGROUP') {
parentNode = parentNode.parentNode;
parentName = parentNode && parentNode.nodeName.toUpperCase();
}
if (parentName === 'SELECT' && !parentNode.hasAttribute('multiple')) {
if (fromEl.hasAttribute('selected') && !toEl.selected) {
// Workaround for MS Edge bug where the 'selected' attribute can only be
// removed if set to a non-empty value:
// https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/12087679/
fromEl.setAttribute('selected', 'selected');
fromEl.removeAttribute('selected');
}
// We have to reset select element's selectedIndex to -1, otherwise setting
// fromEl.selected using the syncBooleanAttrProp below has no effect.
// The correct selectedIndex will be set in the SELECT special handler below.
parentNode.selectedIndex = -1;
}
}
syncBooleanAttrProp(fromEl, toEl, 'selected');
},
/**
* The "value" attribute is special for the element since it sets
* the initial value. Changing the "value" attribute without changing the
* "value" property will have no effect since it is only used to the set the
* initial value. Similar for the "checked" attribute, and "disabled".
*/
INPUT: function(fromEl, toEl) {
syncBooleanAttrProp(fromEl, toEl, 'checked');
syncBooleanAttrProp(fromEl, toEl, 'disabled');
if (fromEl.value !== toEl.value) {
fromEl.value = toEl.value;
}
if (!toEl.hasAttribute('value')) {
fromEl.removeAttribute('value');
}
},
TEXTAREA: function(fromEl, toEl) {
var newValue = toEl.value;
if (fromEl.value !== newValue) {
fromEl.value = newValue;
}
var firstChild = fromEl.firstChild;
if (firstChild) {
// Needed for IE. Apparently IE sets the placeholder as the
// node value and vise versa. This ignores an empty update.
var oldValue = firstChild.nodeValue;
if (oldValue == newValue || (!newValue && oldValue == fromEl.placeholder)) {
return;
}
firstChild.nodeValue = newValue;
}
},
SELECT: function(fromEl, toEl) {
if (!toEl.hasAttribute('multiple')) {
var selectedIndex = -1;
var i = 0;
// We have to loop through children of fromEl, not toEl since nodes can be moved
// from toEl to fromEl directly when morphing.
// At the time this special handler is invoked, all children have already been morphed
// and appended to / removed from fromEl, so using fromEl here is safe and correct.
var curChild = fromEl.firstChild;
var optgroup;
var nodeName;
while(curChild) {
nodeName = curChild.nodeName && curChild.nodeName.toUpperCase();
if (nodeName === 'OPTGROUP') {
optgroup = curChild;
curChild = optgroup.firstChild;
} else {
if (nodeName === 'OPTION') {
if (curChild.hasAttribute('selected')) {
selectedIndex = i;
break;
}
i++;
}
curChild = curChild.nextSibling;
if (!curChild && optgroup) {
curChild = optgroup.nextSibling;
optgroup = null;
}
}
}
fromEl.selectedIndex = selectedIndex;
}
}
};
var ELEMENT_NODE = 1;
var DOCUMENT_FRAGMENT_NODE$1 = 11;
var TEXT_NODE = 3;
var COMMENT_NODE = 8;
function noop() {}
function defaultGetNodeKey(node) {
if (node) {
return (node.getAttribute && node.getAttribute('id')) || node.id;
}
}
function morphdomFactory(morphAttrs) {
return function morphdom(fromNode, toNode, options) {
if (!options) {
options = {};
}
if (typeof toNode === 'string') {
if (fromNode.nodeName === '#document' || fromNode.nodeName === 'HTML' || fromNode.nodeName === 'BODY') {
var toNodeHtml = toNode;
toNode = doc.createElement('html');
toNode.innerHTML = toNodeHtml;
} else {
toNode = toElement(toNode);
}
} else if (toNode.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
toNode = toNode.firstElementChild;
}
var getNodeKey = options.getNodeKey || defaultGetNodeKey;
var onBeforeNodeAdded = options.onBeforeNodeAdded || noop;
var onNodeAdded = options.onNodeAdded || noop;
var onBeforeElUpdated = options.onBeforeElUpdated || noop;
var onElUpdated = options.onElUpdated || noop;
var onBeforeNodeDiscarded = options.onBeforeNodeDiscarded || noop;
var onNodeDiscarded = options.onNodeDiscarded || noop;
var onBeforeElChildrenUpdated = options.onBeforeElChildrenUpdated || noop;
var skipFromChildren = options.skipFromChildren || noop;
var addChild = options.addChild || function(parent, child){ return parent.appendChild(child); };
var childrenOnly = options.childrenOnly === true;
// This object is used as a lookup to quickly find all keyed elements in the original DOM tree.
var fromNodesLookup = Object.create(null);
var keyedRemovalList = [];
function addKeyedRemoval(key) {
keyedRemovalList.push(key);
}
function walkDiscardedChildNodes(node, skipKeyedNodes) {
if (node.nodeType === ELEMENT_NODE) {
var curChild = node.firstChild;
while (curChild) {
var key = undefined;
if (skipKeyedNodes && (key = getNodeKey(curChild))) {
// If we are skipping keyed nodes then we add the key
// to a list so that it can be handled at the very end.
addKeyedRemoval(key);
} else {
// Only report the node as discarded if it is not keyed. We do this because
// at the end we loop through all keyed elements that were unmatched
// and then discard them in one final pass.
onNodeDiscarded(curChild);
if (curChild.firstChild) {
walkDiscardedChildNodes(curChild, skipKeyedNodes);
}
}
curChild = curChild.nextSibling;
}
}
}
/**
* Removes a DOM node out of the original DOM
*
* @param {Node} node The node to remove
* @param {Node} parentNode The nodes parent
* @param {Boolean} skipKeyedNodes If true then elements with keys will be skipped and not discarded.
* @return {undefined}
*/
function removeNode(node, parentNode, skipKeyedNodes) {
if (onBeforeNodeDiscarded(node) === false) {
return;
}
if (parentNode) {
parentNode.removeChild(node);
}
onNodeDiscarded(node);
walkDiscardedChildNodes(node, skipKeyedNodes);
}
// // TreeWalker implementation is no faster, but keeping this around in case this changes in the future
// function indexTree(root) {
// var treeWalker = document.createTreeWalker(
// root,
// NodeFilter.SHOW_ELEMENT);
//
// var el;
// while((el = treeWalker.nextNode())) {
// var key = getNodeKey(el);
// if (key) {
// fromNodesLookup[key] = el;
// }
// }
// }
// // NodeIterator implementation is no faster, but keeping this around in case this changes in the future
//
// function indexTree(node) {
// var nodeIterator = document.createNodeIterator(node, NodeFilter.SHOW_ELEMENT);
// var el;
// while((el = nodeIterator.nextNode())) {
// var key = getNodeKey(el);
// if (key) {
// fromNodesLookup[key] = el;
// }
// }
// }
function indexTree(node) {
if (node.nodeType === ELEMENT_NODE || node.nodeType === DOCUMENT_FRAGMENT_NODE$1) {
var curChild = node.firstChild;
while (curChild) {
var key = getNodeKey(curChild);
if (key) {
fromNodesLookup[key] = curChild;
}
// Walk recursively
indexTree(curChild);
curChild = curChild.nextSibling;
}
}
}
indexTree(fromNode);
function handleNodeAdded(el) {
onNodeAdded(el);
var curChild = el.firstChild;
while (curChild) {
var nextSibling = curChild.nextSibling;
var key = getNodeKey(curChild);
if (key) {
var unmatchedFromEl = fromNodesLookup[key];
// if we find a duplicate #id node in cache, replace `el` with cache value
// and morph it to the child node.
if (unmatchedFromEl && compareNodeNames(curChild, unmatchedFromEl)) {
curChild.parentNode.replaceChild(unmatchedFromEl, curChild);
morphEl(unmatchedFromEl, curChild);
} else {
handleNodeAdded(curChild);
}
} else {
// recursively call for curChild and it's children to see if we find something in
// fromNodesLookup
handleNodeAdded(curChild);
}
curChild = nextSibling;
}
}
function cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey) {
// We have processed all of the "to nodes". If curFromNodeChild is
// non-null then we still have some from nodes left over that need
// to be removed
while (curFromNodeChild) {
var fromNextSibling = curFromNodeChild.nextSibling;
if ((curFromNodeKey = getNodeKey(curFromNodeChild))) {
// Since the node is keyed it might be matched up later so we defer
// the actual removal to later
addKeyedRemoval(curFromNodeKey);
} else {
// NOTE: we skip nested keyed nodes from being removed since there is
// still a chance they will be matched up later
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
}
curFromNodeChild = fromNextSibling;
}
}
function morphEl(fromEl, toEl, childrenOnly) {
var toElKey = getNodeKey(toEl);
if (toElKey) {
// If an element with an ID is being morphed then it will be in the final
// DOM so clear it out of the saved elements collection
delete fromNodesLookup[toElKey];
}
if (!childrenOnly) {
// optional
if (onBeforeElUpdated(fromEl, toEl) === false) {
return;
}
// update attributes on original DOM element first
morphAttrs(fromEl, toEl);
// optional
onElUpdated(fromEl);
if (onBeforeElChildrenUpdated(fromEl, toEl) === false) {
return;
}
}
if (fromEl.nodeName !== 'TEXTAREA') {
morphChildren(fromEl, toEl);
} else {
specialElHandlers.TEXTAREA(fromEl, toEl);
}
}
function morphChildren(fromEl, toEl) {
var skipFrom = skipFromChildren(fromEl, toEl);
var curToNodeChild = toEl.firstChild;
var curFromNodeChild = fromEl.firstChild;
var curToNodeKey;
var curFromNodeKey;
var fromNextSibling;
var toNextSibling;
var matchingFromEl;
// walk the children
outer: while (curToNodeChild) {
toNextSibling = curToNodeChild.nextSibling;
curToNodeKey = getNodeKey(curToNodeChild);
// walk the fromNode children all the way through
while (!skipFrom && curFromNodeChild) {
fromNextSibling = curFromNodeChild.nextSibling;
if (curToNodeChild.isSameNode && curToNodeChild.isSameNode(curFromNodeChild)) {
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
curFromNodeKey = getNodeKey(curFromNodeChild);
var curFromNodeType = curFromNodeChild.nodeType;
// this means if the curFromNodeChild doesnt have a match with the curToNodeChild
var isCompatible = undefined;
if (curFromNodeType === curToNodeChild.nodeType) {
if (curFromNodeType === ELEMENT_NODE) {
// Both nodes being compared are Element nodes
if (curToNodeKey) {
// The target node has a key so we want to match it up with the correct element
// in the original DOM tree
if (curToNodeKey !== curFromNodeKey) {
// The current element in the original DOM tree does not have a matching key so
// let's check our lookup to see if there is a matching element in the original
// DOM tree
if ((matchingFromEl = fromNodesLookup[curToNodeKey])) {
if (fromNextSibling === matchingFromEl) {
// Special case for single element removals. To avoid removing the original
// DOM node out of the tree (since that can break CSS transitions, etc.),
// we will instead discard the current node and wait until the next
// iteration to properly match up the keyed target element with its matching
// element in the original tree
isCompatible = false;
} else {
// We found a matching keyed element somewhere in the original DOM tree.
// Let's move the original DOM node into the current position and morph
// it.
// NOTE: We use insertBefore instead of replaceChild because we want to go through
// the `removeNode()` function for the node that is being discarded so that
// all lifecycle hooks are correctly invoked
fromEl.insertBefore(matchingFromEl, curFromNodeChild);
// fromNextSibling = curFromNodeChild.nextSibling;
if (curFromNodeKey) {
// Since the node is keyed it might be matched up later so we defer
// the actual removal to later
addKeyedRemoval(curFromNodeKey);
} else {
// NOTE: we skip nested keyed nodes from being removed since there is
// still a chance they will be matched up later
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
}
curFromNodeChild = matchingFromEl;
}
} else {
// The nodes are not compatible since the "to" node has a key and there
// is no matching keyed node in the source tree
isCompatible = false;
}
}
} else if (curFromNodeKey) {
// The original has a key
isCompatible = false;
}
isCompatible = isCompatible !== false && compareNodeNames(curFromNodeChild, curToNodeChild);
if (isCompatible) {
// We found compatible DOM elements so transform
// the current "from" node to match the current
// target DOM node.
// MORPH
morphEl(curFromNodeChild, curToNodeChild);
}
} else if (curFromNodeType === TEXT_NODE || curFromNodeType == COMMENT_NODE) {
// Both nodes being compared are Text or Comment nodes
isCompatible = true;
// Simply update nodeValue on the original node to
// change the text value
if (curFromNodeChild.nodeValue !== curToNodeChild.nodeValue) {
curFromNodeChild.nodeValue = curToNodeChild.nodeValue;
}
}
}
if (isCompatible) {
// Advance both the "to" child and the "from" child since we found a match
// Nothing else to do as we already recursively called morphChildren above
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
continue outer;
}
// No compatible match so remove the old node from the DOM and continue trying to find a
// match in the original DOM. However, we only do this if the from node is not keyed
// since it is possible that a keyed node might match up with a node somewhere else in the
// target tree and we don't want to discard it just yet since it still might find a
// home in the final DOM tree. After everything is done we will remove any keyed nodes
// that didn't find a home
if (curFromNodeKey) {
// Since the node is keyed it might be matched up later so we defer
// the actual removal to later
addKeyedRemoval(curFromNodeKey);
} else {
// NOTE: we skip nested keyed nodes from being removed since there is
// still a chance they will be matched up later
removeNode(curFromNodeChild, fromEl, true /* skip keyed nodes */);
}
curFromNodeChild = fromNextSibling;
} // END: while(curFromNodeChild) {}
// If we got this far then we did not find a candidate match for
// our "to node" and we exhausted all of the children "from"
// nodes. Therefore, we will just append the current "to" node
// to the end
if (curToNodeKey && (matchingFromEl = fromNodesLookup[curToNodeKey]) && compareNodeNames(matchingFromEl, curToNodeChild)) {
// MORPH
if(!skipFrom){ addChild(fromEl, matchingFromEl); }
morphEl(matchingFromEl, curToNodeChild);
} else {
var onBeforeNodeAddedResult = onBeforeNodeAdded(curToNodeChild);
if (onBeforeNodeAddedResult !== false) {
if (onBeforeNodeAddedResult) {
curToNodeChild = onBeforeNodeAddedResult;
}
if (curToNodeChild.actualize) {
curToNodeChild = curToNodeChild.actualize(fromEl.ownerDocument || doc);
}
addChild(fromEl, curToNodeChild);
handleNodeAdded(curToNodeChild);
}
}
curToNodeChild = toNextSibling;
curFromNodeChild = fromNextSibling;
}
cleanupFromEl(fromEl, curFromNodeChild, curFromNodeKey);
var specialElHandler = specialElHandlers[fromEl.nodeName];
if (specialElHandler) {
specialElHandler(fromEl, toEl);
}
} // END: morphChildren(...)
var morphedNode = fromNode;
var morphedNodeType = morphedNode.nodeType;
var toNodeType = toNode.nodeType;
if (!childrenOnly) {
// Handle the case where we are given two DOM nodes that are not
// compatible (e.g. -->
or --> TEXT)
if (morphedNodeType === ELEMENT_NODE) {
if (toNodeType === ELEMENT_NODE) {
if (!compareNodeNames(fromNode, toNode)) {
onNodeDiscarded(fromNode);
morphedNode = moveChildren(fromNode, createElementNS(toNode.nodeName, toNode.namespaceURI));
}
} else {
// Going from an element node to a text node
morphedNode = toNode;
}
} else if (morphedNodeType === TEXT_NODE || morphedNodeType === COMMENT_NODE) { // Text or comment node
if (toNodeType === morphedNodeType) {
if (morphedNode.nodeValue !== toNode.nodeValue) {
morphedNode.nodeValue = toNode.nodeValue;
}
return morphedNode;
} else {
// Text node to something else
morphedNode = toNode;
}
}
}
if (morphedNode === toNode) {
// The "to node" was not compatible with the "from node" so we had to
// toss out the "from node" and use the "to node"
onNodeDiscarded(fromNode);
} else {
if (toNode.isSameNode && toNode.isSameNode(morphedNode)) {
return;
}
morphEl(morphedNode, toNode, childrenOnly);
// We now need to loop over any keyed nodes that might need to be
// removed. We only do the removal if we know that the keyed node
// never found a match. When a keyed node is matched up we remove
// it out of fromNodesLookup and we use fromNodesLookup to determine
// if a keyed node has been matched up or not
if (keyedRemovalList) {
for (var i=0, len=keyedRemovalList.length; i${html}
`);
return el.children[0];
}
function arrayRemove(arr, e) {
const index = arr.findIndex(x => x === e);
if (index !== -1) {
arr.splice(index, 1);
}
}
const uploadedFileCss = ":host{display:block;width:100%;max-width:100%;font-size:13px}figure{margin:0}.progress-details{position:relative;display:flex;align-items:center}progress-bar{flex:1 0;padding:0 10px}progress-bar.pending{opacity:0.5}progress-bar.complete{opacity:0.8}progress-bar:not(.complete)+.progress-icon{display:none}progress-bar.complete+.progress-icon{content:url('data:image/svg+xml;utf8, ');filter:invert(100%)}.progress-icon{display:inline-block;flex:0 0 20px;width:28px;height:28px;background-size:contain;position:absolute;right:30px;z-index:1}progress-bar.error{background:#f8b3b1;background:rgba(74, 70, 70, 0.25);opacity:1}.progress-bar a{color:#fff}.download-link{padding-right:20px;color:#fff}.remove-media{display:inline-block;content:url('data:image/svg+xml;utf8, ');flex:0 0 25px;width:25px;height:20px;align-items:center;opacity:0.25}.remove-media:hover{opacity:1;filter:invert(50%)sepia(100%)saturate(10000%)}.remove-media span{display:inline-block;text-indent:-9999px;color:transparent}";
let uid = 0;
const UploadedFile$1 = /*@__PURE__*/ proxyCustomElement(class UploadedFile extends H {
get el() { return this; }
removeEvent;
removeClicked = event => {
event.stopPropagation();
event.preventDefault();
this.controller?.cancel();
this.removeEvent.emit(this);
};
inputTarget;
controller;
_file;
uid;
constructor() {
super();
this.__registerHost();
this.__attachShadow();
this.removeEvent = createEvent(this, "uploaded-file:remove", 7);
this.name = undefined;
this.accepts = undefined;
this.max = undefined;
this.url = undefined;
this.value = "";
this.filename = undefined;
this.src = undefined;
this.filetype = undefined;
this.size = undefined;
this.state = "complete";
this.percent = 100;
this.preview = true;
this.validationMessage = undefined;
this.uid = uid++;
this.inputTarget = html(` `);
}
componentWillLoad() {
this.el.appendChild(this.inputTarget);
this.setMissingFiletype();
}
get file() {
return this._file;
}
set file(file) {
this.src = URL.createObjectURL(file);
this.filename = file.name;
this.size = file.size;
this.state = "pending";
this.percent = 0;
this._file = file;
}
set signedId(val) {
if (this.value !== val) {
get(`/rails/active_storage/blobs/info/${val}`).then(blob => {
this.src = `/rails/active_storage/blobs/redirect/${val}/${blob.filename}`;
this.filename = blob.filename;
this.size = blob.byte_size;
this.state = "complete";
this.percent = 100;
this.value = val;
});
}
}
setMissingFiletype(_value, _previousValue) {
if (!this.filetype && this.filename) {
this.filetype = Extensions.getFileType(this.filename);
}
}
start(_event) {
this.state = "pending";
this.percent = 0;
}
progress(event) {
const { progress } = event.detail;
this.percent = progress;
}
error(event) {
event.preventDefault();
const { error } = event.detail;
this.state = "error";
this.inputTarget.setCustomValidity(error);
}
end(_event) {
if (this.state !== "error") {
this.state = "complete";
this.percent = 100;
}
}
render() {
return (h(Host, null, h("slot", null), h("figure", null, h("div", { class: "progress-details" }, h("progress-bar", { percent: this.percent, class: this.state }, h("a", { class: "download-link", href: this.src, download: this.filename, onClick: e => e.stopPropagation() }, this.filename)), h("span", { class: "progress-icon" }), h("a", { class: "remove-media", onClick: this.removeClicked, href: "#" }, h("span", null, "Remove media"))), this.preview ? h("file-preview", { src: this.src, filetype: this.filetype }) : '')));
}
componentDidRender() {
morphdom(this.inputTarget, `
`);
}
componentDidLoad() {
if (this.checkValidity() && this.state == "pending") {
this.controller = new DirectUploadController(this.el);
this.controller.dispatch("initialize", { controller: this.controller });
}
}
checkValidity() {
let errors = [];
errors.push(...new Accepts(this).errors);
errors.push(...new Max(this).errors);
this.inputTarget.setCustomValidity(errors.join(" "));
this.inputTarget.reportValidity();
return errors.length === 0;
}
static get watchers() { return {
"filename": ["setMissingFiletype"]
}; }
static get style() { return uploadedFileCss; }
}, [1, "uploaded-file", {
"name": [1537],
"accepts": [1537],
"max": [1538],
"url": [1537],
"value": [1537],
"filename": [1537],
"src": [1537],
"filetype": [1537],
"size": [1538],
"state": [1537],
"percent": [1538],
"preview": [1540],
"validationMessage": [1, "validation-message"]
}, [[0, "direct-upload:initialize", "start"], [0, "direct-upload:start", "start"], [0, "direct-upload:progress", "progress"], [0, "direct-upload:error", "error"], [0, "direct-upload:end", "end"]], {
"filename": ["setMissingFiletype"]
}]);
const fileDropCss = "file-drop{display:flex;flex-direction:column;justify-content:center;align-items:center;box-sizing:border-box;min-height:60px;outline-offset:-10px;padding:20px;background:rgba(255, 255, 255, 0.25);text-align:center;transition:all 0.15s ease 0s;outline:rgba(0, 0, 0, 0.25) dashed 2px;font-size:13px}";
const FileDrop$1 = /*@__PURE__*/ proxyCustomElement(class FileDrop extends H {
constructor() {
super();
this.__registerHost();
this.for = undefined;
}
get el() { return this; }
get fileTarget() {
return document.querySelector(`#${this.for}`);
}
openFilePicker(_event) {
this.fileTarget.click();
}
highlight(event) {
event.preventDefault();
this.el.classList.add("-dragover");
}
unhighlight(_event) {
this.el.classList.remove("-dragover");
}
drop(event) {
event.preventDefault();
this.el.classList.remove("-dragover");
this.fileTarget.files = event.dataTransfer.files;
const changeEvent = new Event("change", { bubbles: true });
this.fileTarget.dispatchEvent(changeEvent);
}
static get style() { return fileDropCss; }
}, [0, "file-drop", {
"for": [1537]
}, [[0, "click", "openFilePicker"], [0, "dragover", "highlight"], [0, "dragleave", "unhighlight"], [0, "drop", "drop"]]]);
class FormController {
static instance(form) {
return form.bardFileFormController ||= new FormController(form);
}
progressContainerTarget;
dialog;
element;
progressTargetMap;
controllers;
submitted;
processing;
errors;
constructor(form) {
this.element = form;
this.progressTargetMap = {};
this.controllers = [];
this.submitted = false;
this.processing = false;
this.errors = false;
this.element.insertAdjacentHTML("beforeend", `
`);
this.dialog = this.element.querySelector("#form-controller-dialog");
this.progressContainerTarget = this.dialog.querySelector("#progress-container");
if (this.element.dataset.remote !== "true" && !window.Turbo?.session?.enabled) {
this.element.addEventListener("submit", event => this.submit(event));
}
window.addEventListener("beforeunload", event => this.beforeUnload(event));
this.element.addEventListener("direct-upload:initialize", event => this.init(event));
this.element.addEventListener("direct-upload:start", event => this.start(event));
this.element.addEventListener("direct-upload:progress", event => this.progress(event));
this.element.addEventListener("direct-upload:error", event => this.error(event));
this.element.addEventListener("direct-upload:end", event => this.end(event));
this.element.addEventListener("uploaded-file:remove", event => this.removeUploadedFile(event));
}
beforeUnload(event) {
if (this.processing) {
event.preventDefault();
return (event.returnValue = "");
}
}
submit(event) {
event.preventDefault();
this.submitted = true;
this.startNextController();
if (this.processing) {
this.dialog.showModal();
}
}
startNextController() {
if (this.processing)
return;
const controller = this.controllers.shift();
if (controller) {
this.processing = true;
controller.start(error => {
if (error) {
Array.from(this.element.querySelectorAll("input[type=file]"))
.forEach((e) => e.disabled = false);
}
this.processing = false;
this.startNextController();
});
}
else {
this.submitForm();
}
}
submitForm() {
if (this.submitted) {
Array.from(this.element.querySelectorAll("input[type=file]"))
.forEach((e) => e.disabled = true);
window.setTimeout(() => {
this.element.submit();
}, 10);
}
}
init(event) {
const { id, file, controller } = event.detail;
this.progressContainerTarget.insertAdjacentHTML("beforebegin", `
${file.name}
`);
const progressTarget = document.getElementById(`direct-upload-${id}`);
this.progressTargetMap[id] = progressTarget;
this.controllers.push(controller);
this.startNextController();
}
start(event) {
this.progressTargetMap[event.detail.id].classList.remove("direct-upload--pending");
}
progress(event) {
const { id, progress } = event.detail;
this.progressTargetMap[id].percent = progress;
}
error(event) {
event.preventDefault();
const { id, error } = event.detail;
const target = this.progressTargetMap[id];
target.classList.add("direct-upload--error");
target.title = error;
}
end(event) {
this.progressTargetMap[event.detail.id].classList.add("direct-upload--complete");
}
removeUploadedFile(event) {
const uploadedFile = event.detail;
const id = uploadedFile.controller?.directUpload?.id;
if (id) {
document.getElementById(`direct-upload-${id}`).remove();
delete this.progressTargetMap[id];
}
}
}
const bardFileCss = ":host{display:block;padding:25px;color:var(--bard-file-text-color, #000);font-size:13px}:host *{box-sizing:border-box;position:relative}drag-and-drop{display:block;outline-offset:-10px;background:rgba(255,255,255, 0.25);margin:0;text-align:center;transition:all 0.15s;outline:2px dashed rgba(0,0,0,0.25);color:#444;font-size:14px}p{padding:10px 20px;margin:0}drag-and-drop.-full{width:100%}.-dragover{background:rgba(255,255,255,0.5);outline:2px dashed rgba(0,0,0,0.25)}.media-preview{display:flex;flex-wrap:wrap;align-items:flex-start;justify-content:center}// UPLOADER .direct-upload-wrapper{position:fixed;z-index:9999;top:0;left:0;width:100vw;height:100vh;display:flex;align-items:center;justify-content:center;background:rgba(#333, 0.9)}.direct-upload-content{display:block;background:#fcfcfc;padding:40px 60px 60px;border-radius:3px;width:60vw}.direct-upload-content h3{border-bottom:2px solid #1f1f1f;margin-bottom:20px}.separate-upload{padding:0 10px;margin-top:10px;font-size:0.9em}.direct-upload--pending{opacity:0.6}.direct-upload--complete{opacity:0.4}.direct-upload--error{border-color:red}input[type=file][data-direct-upload-url][disabled]{display:none}:host.separate-upload{padding:0 10px;margin-top:10px;font-size:0.9em}";
const BardFile$1 = /*@__PURE__*/ proxyCustomElement(class BardFile extends H {
get el() { return this; }
forceUpdate() { this._forceUpdate = !this._forceUpdate; }
fileTargetId;
fileTarget;
hiddenTargetId;
hiddenTarget;
_files = [];
constructor() {
super();
this.__registerHost();
this.__attachShadow();
this.name = undefined;
this.directupload = undefined;
this.multiple = false;
this.required = false;
this.accepts = undefined;
this.max = undefined;
this.preview = true;
this._forceUpdate = false;
this.fileTargetId = this.el.id;
this.fileTarget = html(` `);
this.hiddenTargetId = `hidden-target-${this.el.getAttribute("name")}`;
this.hiddenTarget = html(` `);
}
componentWillLoad() {
this.el.removeAttribute("id");
FormController.instance(this.el.closest("form"));
const existingFiles = Array.from(this.el.children).filter(e => e.tagName == "UPLOADED-FILE");
if (existingFiles.length > 0)
this.files = existingFiles;
}
// Methods
get files() {
return this._files;
}
set files(val) {
this._files = val;
if (!this.multiple)
this._files = this._files.slice(-1);
this.forceUpdate();
this.fireChangeEvent();
}
get value() {
return this.files.map(e => e.value);
}
set value(val) {
const newValue = val || [];
if (JSON.stringify(this.value) !== JSON.stringify(newValue)) { // this is insane. javascript is fucking garbage.
this.files = newValue.map(signedId => Object.assign(new UploadedFile$1(), {
name: this.name,
preview: this.preview,
signedId,
}));
}
}
fileTargetChanged(event) {
if (event.target !== this.fileTarget)
return;
this.files.push(...Array.from(this.fileTarget.files).map(file => Object.assign(new UploadedFile$1(), {
name: this.name,
preview: this.preview,
url: this.directupload,
accepts: this.accepts,
max: this.max,
file,
})));
this.files = this.files;
this.fileTarget.value = null;
}
removeUploadedFile(event) {
arrayRemove(this.files, event.detail);
this.files = this.files;
}
fireChangeEvent() {
requestAnimationFrame(() => this.el.dispatchEvent(new Event("change", { bubbles: true })));
}
// Rendering
render() {
return (h(Host, null, h("file-drop", { for: this.fileTargetId }, h("p", { part: "title" }, h("strong", null, "Choose ", this.multiple ? "files" : "file", " "), h("span", null, "or drag ", this.multiple ? "them" : "it", " here.")), h("div", { class: `media-preview ${this.multiple ? '-stacked' : ''}` }, h("slot", null)))));
}
componentDidRender() {
morphdom(this.fileTarget, `
`);
morphdom(this.hiddenTarget, `
0 ? "disabled" : ""}
>`);
const wrapper = document.createElement("div");
wrapper.replaceChildren(this.fileTarget, this.hiddenTarget, ...this.files);
morphdom(this.el, wrapper, { childrenOnly: true });
}
// Validations
checkValidity() {
return this.fileTarget.checkValidity();
}
setCustomValidity(msg) {
this.fileTarget.setCustomValidity(msg);
}
reportValidity() {
this.fileTarget.reportValidity();
}
get validationMessage() {
return this.fileTarget.validationMessage;
}
static get style() { return bardFileCss; }
}, [1, "bard-file", {
"name": [1],
"directupload": [1],
"multiple": [4],
"required": [4],
"accepts": [1],
"max": [2],
"preview": [4],
"_forceUpdate": [32]
}, [[0, "change", "fileTargetChanged"], [0, "uploaded-file:remove", "removeUploadedFile"], [0, "direct-upload:end", "fireChangeEvent"]]]);
const BardFile = BardFile$1;
const FileDrop = FileDrop$1;
const FilePreview = FilePreview$1;
const ProgressBar = ProgressBar$1;
const UploadedFile = UploadedFile$1;
const defineCustomElements = (opts) => {
if (typeof customElements !== 'undefined') {
[
BardFile,
FileDrop,
FilePreview,
ProgressBar,
UploadedFile,
].forEach(cmp => {
if (!customElements.get(cmp.is)) {
customElements.define(cmp.is, cmp, opts);
}
});
}
};
defineCustomElements();