@uppy/informer
Version:
A notification and error pop-up bar for Uppy.
262 lines (259 loc) • 8.59 kB
JavaScript
// INFO: not typing copy pasted libarary code
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-nocheck
/* eslint-disable */
/**
* @source https://github.com/developit/preact-transition-group
*/
import { Component, cloneElement, h, toChildArray } from 'preact';
function assign(obj, props) {
return Object.assign(obj, props);
}
function getKey(vnode, fallback) {
var _vnode$key;
return (_vnode$key = vnode == null ? void 0 : vnode.key) != null ? _vnode$key : fallback;
}
function linkRef(component, name) {
const cache = component._ptgLinkedRefs || (component._ptgLinkedRefs = {});
return cache[name] || (cache[name] = c => {
component.refs[name] = c;
});
}
function getChildMapping(children) {
const out = {};
for (let i = 0; i < children.length; i++) {
if (children[i] != null) {
const key = getKey(children[i], i.toString(36));
out[key] = children[i];
}
}
return out;
}
function mergeChildMappings(prev, next) {
prev = prev || {};
next = next || {};
const getValueForKey = key => next.hasOwnProperty(key) ? next[key] : prev[key];
// For each key of `next`, the list of keys to insert before that key in
// the combined list
const nextKeysPending = {};
let pendingKeys = [];
for (const prevKey in prev) {
if (next.hasOwnProperty(prevKey)) {
if (pendingKeys.length) {
nextKeysPending[prevKey] = pendingKeys;
pendingKeys = [];
}
} else {
pendingKeys.push(prevKey);
}
}
const childMapping = {};
for (const nextKey in next) {
if (nextKeysPending.hasOwnProperty(nextKey)) {
for (let i = 0; i < nextKeysPending[nextKey].length; i++) {
const pendingNextKey = nextKeysPending[nextKey][i];
childMapping[nextKeysPending[nextKey][i]] = getValueForKey(pendingNextKey);
}
}
childMapping[nextKey] = getValueForKey(nextKey);
}
// Finally, add the keys which didn't appear before any key in `next`
for (let i = 0; i < pendingKeys.length; i++) {
childMapping[pendingKeys[i]] = getValueForKey(pendingKeys[i]);
}
return childMapping;
}
const identity = i => i;
class TransitionGroup extends Component {
constructor(props, context) {
super(props, context);
this.refs = {};
this.state = {
children: getChildMapping(toChildArray(toChildArray(this.props.children)) || [])
};
this.performAppear = this.performAppear.bind(this);
this.performEnter = this.performEnter.bind(this);
this.performLeave = this.performLeave.bind(this);
}
componentWillMount() {
this.currentlyTransitioningKeys = {};
this.keysToAbortLeave = [];
this.keysToEnter = [];
this.keysToLeave = [];
}
componentDidMount() {
const initialChildMapping = this.state.children;
for (const key in initialChildMapping) {
if (initialChildMapping[key]) {
// this.performAppear(getKey(initialChildMapping[key], key));
this.performAppear(key);
}
}
}
componentWillReceiveProps(nextProps) {
const nextChildMapping = getChildMapping(toChildArray(nextProps.children) || []);
const prevChildMapping = this.state.children;
this.setState(prevState => ({
children: mergeChildMappings(prevState.children, nextChildMapping)
}));
let key;
for (key in nextChildMapping) {
if (nextChildMapping.hasOwnProperty(key)) {
const hasPrev = prevChildMapping && prevChildMapping.hasOwnProperty(key);
// We should re-enter the component and abort its leave function
if (nextChildMapping[key] && hasPrev && this.currentlyTransitioningKeys[key]) {
this.keysToEnter.push(key);
this.keysToAbortLeave.push(key);
} else if (nextChildMapping[key] && !hasPrev && !this.currentlyTransitioningKeys[key]) {
this.keysToEnter.push(key);
}
}
}
for (key in prevChildMapping) {
if (prevChildMapping.hasOwnProperty(key)) {
const hasNext = nextChildMapping && nextChildMapping.hasOwnProperty(key);
if (prevChildMapping[key] && !hasNext && !this.currentlyTransitioningKeys[key]) {
this.keysToLeave.push(key);
}
}
}
}
componentDidUpdate() {
const {
keysToEnter
} = this;
this.keysToEnter = [];
keysToEnter.forEach(this.performEnter);
const {
keysToLeave
} = this;
this.keysToLeave = [];
keysToLeave.forEach(this.performLeave);
}
_finishAbort(key) {
const idx = this.keysToAbortLeave.indexOf(key);
if (idx !== -1) {
this.keysToAbortLeave.splice(idx, 1);
}
}
performAppear(key) {
this.currentlyTransitioningKeys[key] = true;
const component = this.refs[key];
if (component != null && component.componentWillAppear) {
component.componentWillAppear(this._handleDoneAppearing.bind(this, key));
} else {
this._handleDoneAppearing(key);
}
}
_handleDoneAppearing(key) {
const component = this.refs[key];
if (component != null && component.componentDidAppear) {
component.componentDidAppear();
}
delete this.currentlyTransitioningKeys[key];
this._finishAbort(key);
const currentChildMapping = getChildMapping(toChildArray(this.props.children) || []);
if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
// This was removed before it had fully appeared. Remove it.
this.performLeave(key);
}
}
performEnter(key) {
this.currentlyTransitioningKeys[key] = true;
const component = this.refs[key];
if (component != null && component.componentWillEnter) {
component.componentWillEnter(this._handleDoneEntering.bind(this, key));
} else {
this._handleDoneEntering(key);
}
}
_handleDoneEntering(key) {
const component = this.refs[key];
if (component != null && component.componentDidEnter) {
component.componentDidEnter();
}
delete this.currentlyTransitioningKeys[key];
this._finishAbort(key);
const currentChildMapping = getChildMapping(toChildArray(this.props.children) || []);
if (!currentChildMapping || !currentChildMapping.hasOwnProperty(key)) {
// This was removed before it had fully entered. Remove it.
this.performLeave(key);
}
}
performLeave(key) {
// If we should immediately abort this leave function,
// don't run the leave transition at all.
const idx = this.keysToAbortLeave.indexOf(key);
if (idx !== -1) {
return;
}
this.currentlyTransitioningKeys[key] = true;
const component = this.refs[key];
if (component != null && component.componentWillLeave) {
component.componentWillLeave(this._handleDoneLeaving.bind(this, key));
} else {
// Note that this is somewhat dangerous b/c it calls setState()
// again, effectively mutating the component before all the work
// is done.
this._handleDoneLeaving(key);
}
}
_handleDoneLeaving(key) {
// If we should immediately abort the leave,
// then skip this altogether
const idx = this.keysToAbortLeave.indexOf(key);
if (idx !== -1) {
return;
}
const component = this.refs[key];
if (component != null && component.componentDidLeave) {
component.componentDidLeave();
}
delete this.currentlyTransitioningKeys[key];
const currentChildMapping = getChildMapping(toChildArray(this.props.children) || []);
if (currentChildMapping && currentChildMapping.hasOwnProperty(key)) {
// This entered again before it fully left. Add it again.
this.performEnter(key);
} else {
const children = assign({}, this.state.children);
delete children[key];
this.setState({
children
});
}
}
render(_ref, _ref2) {
let {
childFactory,
transitionLeave,
transitionName,
transitionAppear,
transitionEnter,
transitionLeaveTimeout,
transitionEnterTimeout,
transitionAppearTimeout,
component,
...props
} = _ref;
let {
children
} = _ref2;
// TODO: we could get rid of the need for the wrapper node
// by cloning a single child
const childrenToRender = Object.entries(children).map(_ref3 => {
let [key, child] = _ref3;
if (!child) return undefined;
const ref = linkRef(this, key);
return cloneElement(childFactory(child), {
ref,
key
});
}).filter(Boolean);
return h(component, props, childrenToRender);
}
}
TransitionGroup.defaultProps = {
component: 'span',
childFactory: identity
};
export default TransitionGroup;