3784 lines
102 KiB
JavaScript
3784 lines
102 KiB
JavaScript
/*!
|
|
* FilePondPluginImagePreview 4.6.12
|
|
* Licensed under MIT, https://opensource.org/licenses/MIT/
|
|
* Please visit https://pqina.nl/filepond/ for details.
|
|
*/
|
|
|
|
/* eslint-disable */
|
|
|
|
(function(global, factory) {
|
|
typeof exports === 'object' && typeof module !== 'undefined'
|
|
? (module.exports = factory())
|
|
: typeof define === 'function' && define.amd
|
|
? define(factory)
|
|
: ((global = global || self),
|
|
(global.FilePondPluginImagePreview = factory()));
|
|
})(this, function() {
|
|
'use strict';
|
|
|
|
// test if file is of type image and can be viewed in canvas
|
|
var isPreviewableImage = function isPreviewableImage(file) {
|
|
return /^image/.test(file.type);
|
|
};
|
|
|
|
function _typeof(obj) {
|
|
if (typeof Symbol === 'function' && typeof Symbol.iterator === 'symbol') {
|
|
_typeof = function(obj) {
|
|
return typeof obj;
|
|
};
|
|
} else {
|
|
_typeof = function(obj) {
|
|
return obj &&
|
|
typeof Symbol === 'function' &&
|
|
obj.constructor === Symbol &&
|
|
obj !== Symbol.prototype
|
|
? 'symbol'
|
|
: typeof obj;
|
|
};
|
|
}
|
|
|
|
return _typeof(obj);
|
|
}
|
|
|
|
var REACT_ELEMENT_TYPE;
|
|
|
|
function _jsx(type, props, key, children) {
|
|
if (!REACT_ELEMENT_TYPE) {
|
|
REACT_ELEMENT_TYPE =
|
|
(typeof Symbol === 'function' &&
|
|
Symbol.for &&
|
|
Symbol.for('react.element')) ||
|
|
0xeac7;
|
|
}
|
|
|
|
var defaultProps = type && type.defaultProps;
|
|
var childrenLength = arguments.length - 3;
|
|
|
|
if (!props && childrenLength !== 0) {
|
|
props = {
|
|
children: void 0
|
|
};
|
|
}
|
|
|
|
if (props && defaultProps) {
|
|
for (var propName in defaultProps) {
|
|
if (props[propName] === void 0) {
|
|
props[propName] = defaultProps[propName];
|
|
}
|
|
}
|
|
} else if (!props) {
|
|
props = defaultProps || {};
|
|
}
|
|
|
|
if (childrenLength === 1) {
|
|
props.children = children;
|
|
} else if (childrenLength > 1) {
|
|
var childArray = new Array(childrenLength);
|
|
|
|
for (var i = 0; i < childrenLength; i++) {
|
|
childArray[i] = arguments[i + 3];
|
|
}
|
|
|
|
props.children = childArray;
|
|
}
|
|
|
|
return {
|
|
$$typeof: REACT_ELEMENT_TYPE,
|
|
type: type,
|
|
key: key === undefined ? null : '' + key,
|
|
ref: null,
|
|
props: props,
|
|
_owner: null
|
|
};
|
|
}
|
|
|
|
function _asyncIterator(iterable) {
|
|
var method;
|
|
|
|
if (typeof Symbol === 'function') {
|
|
if (Symbol.asyncIterator) {
|
|
method = iterable[Symbol.asyncIterator];
|
|
if (method != null) return method.call(iterable);
|
|
}
|
|
|
|
if (Symbol.iterator) {
|
|
method = iterable[Symbol.iterator];
|
|
if (method != null) return method.call(iterable);
|
|
}
|
|
}
|
|
|
|
throw new TypeError('Object is not async iterable');
|
|
}
|
|
|
|
function _AwaitValue(value) {
|
|
this.wrapped = value;
|
|
}
|
|
|
|
function _AsyncGenerator(gen) {
|
|
var front, back;
|
|
|
|
function send(key, arg) {
|
|
return new Promise(function(resolve, reject) {
|
|
var request = {
|
|
key: key,
|
|
arg: arg,
|
|
resolve: resolve,
|
|
reject: reject,
|
|
next: null
|
|
};
|
|
|
|
if (back) {
|
|
back = back.next = request;
|
|
} else {
|
|
front = back = request;
|
|
resume(key, arg);
|
|
}
|
|
});
|
|
}
|
|
|
|
function resume(key, arg) {
|
|
try {
|
|
var result = gen[key](arg);
|
|
var value = result.value;
|
|
var wrappedAwait = value instanceof _AwaitValue;
|
|
Promise.resolve(wrappedAwait ? value.wrapped : value).then(
|
|
function(arg) {
|
|
if (wrappedAwait) {
|
|
resume('next', arg);
|
|
return;
|
|
}
|
|
|
|
settle(result.done ? 'return' : 'normal', arg);
|
|
},
|
|
function(err) {
|
|
resume('throw', err);
|
|
}
|
|
);
|
|
} catch (err) {
|
|
settle('throw', err);
|
|
}
|
|
}
|
|
|
|
function settle(type, value) {
|
|
switch (type) {
|
|
case 'return':
|
|
front.resolve({
|
|
value: value,
|
|
done: true
|
|
});
|
|
break;
|
|
|
|
case 'throw':
|
|
front.reject(value);
|
|
break;
|
|
|
|
default:
|
|
front.resolve({
|
|
value: value,
|
|
done: false
|
|
});
|
|
break;
|
|
}
|
|
|
|
front = front.next;
|
|
|
|
if (front) {
|
|
resume(front.key, front.arg);
|
|
} else {
|
|
back = null;
|
|
}
|
|
}
|
|
|
|
this._invoke = send;
|
|
|
|
if (typeof gen.return !== 'function') {
|
|
this.return = undefined;
|
|
}
|
|
}
|
|
|
|
if (typeof Symbol === 'function' && Symbol.asyncIterator) {
|
|
_AsyncGenerator.prototype[Symbol.asyncIterator] = function() {
|
|
return this;
|
|
};
|
|
}
|
|
|
|
_AsyncGenerator.prototype.next = function(arg) {
|
|
return this._invoke('next', arg);
|
|
};
|
|
|
|
_AsyncGenerator.prototype.throw = function(arg) {
|
|
return this._invoke('throw', arg);
|
|
};
|
|
|
|
_AsyncGenerator.prototype.return = function(arg) {
|
|
return this._invoke('return', arg);
|
|
};
|
|
|
|
function _wrapAsyncGenerator(fn) {
|
|
return function() {
|
|
return new _AsyncGenerator(fn.apply(this, arguments));
|
|
};
|
|
}
|
|
|
|
function _awaitAsyncGenerator(value) {
|
|
return new _AwaitValue(value);
|
|
}
|
|
|
|
function _asyncGeneratorDelegate(inner, awaitWrap) {
|
|
var iter = {},
|
|
waiting = false;
|
|
|
|
function pump(key, value) {
|
|
waiting = true;
|
|
value = new Promise(function(resolve) {
|
|
resolve(inner[key](value));
|
|
});
|
|
return {
|
|
done: false,
|
|
value: awaitWrap(value)
|
|
};
|
|
}
|
|
|
|
if (typeof Symbol === 'function' && Symbol.iterator) {
|
|
iter[Symbol.iterator] = function() {
|
|
return this;
|
|
};
|
|
}
|
|
|
|
iter.next = function(value) {
|
|
if (waiting) {
|
|
waiting = false;
|
|
return value;
|
|
}
|
|
|
|
return pump('next', value);
|
|
};
|
|
|
|
if (typeof inner.throw === 'function') {
|
|
iter.throw = function(value) {
|
|
if (waiting) {
|
|
waiting = false;
|
|
throw value;
|
|
}
|
|
|
|
return pump('throw', value);
|
|
};
|
|
}
|
|
|
|
if (typeof inner.return === 'function') {
|
|
iter.return = function(value) {
|
|
return pump('return', value);
|
|
};
|
|
}
|
|
|
|
return iter;
|
|
}
|
|
|
|
function asyncGeneratorStep(gen, resolve, reject, _next, _throw, key, arg) {
|
|
try {
|
|
var info = gen[key](arg);
|
|
var value = info.value;
|
|
} catch (error) {
|
|
reject(error);
|
|
return;
|
|
}
|
|
|
|
if (info.done) {
|
|
resolve(value);
|
|
} else {
|
|
Promise.resolve(value).then(_next, _throw);
|
|
}
|
|
}
|
|
|
|
function _asyncToGenerator(fn) {
|
|
return function() {
|
|
var self = this,
|
|
args = arguments;
|
|
return new Promise(function(resolve, reject) {
|
|
var gen = fn.apply(self, args);
|
|
|
|
function _next(value) {
|
|
asyncGeneratorStep(
|
|
gen,
|
|
resolve,
|
|
reject,
|
|
_next,
|
|
_throw,
|
|
'next',
|
|
value
|
|
);
|
|
}
|
|
|
|
function _throw(err) {
|
|
asyncGeneratorStep(gen, resolve, reject, _next, _throw, 'throw', err);
|
|
}
|
|
|
|
_next(undefined);
|
|
});
|
|
};
|
|
}
|
|
|
|
function _classCallCheck(instance, Constructor) {
|
|
if (!(instance instanceof Constructor)) {
|
|
throw new TypeError('Cannot call a class as a function');
|
|
}
|
|
}
|
|
|
|
function _defineProperties(target, props) {
|
|
for (var i = 0; i < props.length; i++) {
|
|
var descriptor = props[i];
|
|
descriptor.enumerable = descriptor.enumerable || false;
|
|
descriptor.configurable = true;
|
|
if ('value' in descriptor) descriptor.writable = true;
|
|
Object.defineProperty(target, descriptor.key, descriptor);
|
|
}
|
|
}
|
|
|
|
function _createClass(Constructor, protoProps, staticProps) {
|
|
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
return Constructor;
|
|
}
|
|
|
|
function _defineEnumerableProperties(obj, descs) {
|
|
for (var key in descs) {
|
|
var desc = descs[key];
|
|
desc.configurable = desc.enumerable = true;
|
|
if ('value' in desc) desc.writable = true;
|
|
Object.defineProperty(obj, key, desc);
|
|
}
|
|
|
|
if (Object.getOwnPropertySymbols) {
|
|
var objectSymbols = Object.getOwnPropertySymbols(descs);
|
|
|
|
for (var i = 0; i < objectSymbols.length; i++) {
|
|
var sym = objectSymbols[i];
|
|
var desc = descs[sym];
|
|
desc.configurable = desc.enumerable = true;
|
|
if ('value' in desc) desc.writable = true;
|
|
Object.defineProperty(obj, sym, desc);
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function _defaults(obj, defaults) {
|
|
var keys = Object.getOwnPropertyNames(defaults);
|
|
|
|
for (var i = 0; i < keys.length; i++) {
|
|
var key = keys[i];
|
|
var value = Object.getOwnPropertyDescriptor(defaults, key);
|
|
|
|
if (value && value.configurable && obj[key] === undefined) {
|
|
Object.defineProperty(obj, key, value);
|
|
}
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function _defineProperty(obj, key, value) {
|
|
if (key in obj) {
|
|
Object.defineProperty(obj, key, {
|
|
value: value,
|
|
enumerable: true,
|
|
configurable: true,
|
|
writable: true
|
|
});
|
|
} else {
|
|
obj[key] = value;
|
|
}
|
|
|
|
return obj;
|
|
}
|
|
|
|
function _extends() {
|
|
_extends =
|
|
Object.assign ||
|
|
function(target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i];
|
|
|
|
for (var key in source) {
|
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
}
|
|
|
|
return target;
|
|
};
|
|
|
|
return _extends.apply(this, arguments);
|
|
}
|
|
|
|
function _objectSpread(target) {
|
|
for (var i = 1; i < arguments.length; i++) {
|
|
var source = arguments[i] != null ? arguments[i] : {};
|
|
var ownKeys = Object.keys(source);
|
|
|
|
if (typeof Object.getOwnPropertySymbols === 'function') {
|
|
ownKeys = ownKeys.concat(
|
|
Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
})
|
|
);
|
|
}
|
|
|
|
ownKeys.forEach(function(key) {
|
|
_defineProperty(target, key, source[key]);
|
|
});
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
function _inherits(subClass, superClass) {
|
|
if (typeof superClass !== 'function' && superClass !== null) {
|
|
throw new TypeError('Super expression must either be null or a function');
|
|
}
|
|
|
|
subClass.prototype = Object.create(superClass && superClass.prototype, {
|
|
constructor: {
|
|
value: subClass,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
if (superClass) _setPrototypeOf(subClass, superClass);
|
|
}
|
|
|
|
function _inheritsLoose(subClass, superClass) {
|
|
subClass.prototype = Object.create(superClass.prototype);
|
|
subClass.prototype.constructor = subClass;
|
|
subClass.__proto__ = superClass;
|
|
}
|
|
|
|
function _getPrototypeOf(o) {
|
|
_getPrototypeOf = Object.setPrototypeOf
|
|
? Object.getPrototypeOf
|
|
: function _getPrototypeOf(o) {
|
|
return o.__proto__ || Object.getPrototypeOf(o);
|
|
};
|
|
return _getPrototypeOf(o);
|
|
}
|
|
|
|
function _setPrototypeOf(o, p) {
|
|
_setPrototypeOf =
|
|
Object.setPrototypeOf ||
|
|
function _setPrototypeOf(o, p) {
|
|
o.__proto__ = p;
|
|
return o;
|
|
};
|
|
|
|
return _setPrototypeOf(o, p);
|
|
}
|
|
|
|
function isNativeReflectConstruct() {
|
|
if (typeof Reflect === 'undefined' || !Reflect.construct) return false;
|
|
if (Reflect.construct.sham) return false;
|
|
if (typeof Proxy === 'function') return true;
|
|
|
|
try {
|
|
Date.prototype.toString.call(Reflect.construct(Date, [], function() {}));
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function _construct(Parent, args, Class) {
|
|
if (isNativeReflectConstruct()) {
|
|
_construct = Reflect.construct;
|
|
} else {
|
|
_construct = function _construct(Parent, args, Class) {
|
|
var a = [null];
|
|
a.push.apply(a, args);
|
|
var Constructor = Function.bind.apply(Parent, a);
|
|
var instance = new Constructor();
|
|
if (Class) _setPrototypeOf(instance, Class.prototype);
|
|
return instance;
|
|
};
|
|
}
|
|
|
|
return _construct.apply(null, arguments);
|
|
}
|
|
|
|
function _isNativeFunction(fn) {
|
|
return Function.toString.call(fn).indexOf('[native code]') !== -1;
|
|
}
|
|
|
|
function _wrapNativeSuper(Class) {
|
|
var _cache = typeof Map === 'function' ? new Map() : undefined;
|
|
|
|
_wrapNativeSuper = function _wrapNativeSuper(Class) {
|
|
if (Class === null || !_isNativeFunction(Class)) return Class;
|
|
|
|
if (typeof Class !== 'function') {
|
|
throw new TypeError(
|
|
'Super expression must either be null or a function'
|
|
);
|
|
}
|
|
|
|
if (typeof _cache !== 'undefined') {
|
|
if (_cache.has(Class)) return _cache.get(Class);
|
|
|
|
_cache.set(Class, Wrapper);
|
|
}
|
|
|
|
function Wrapper() {
|
|
return _construct(Class, arguments, _getPrototypeOf(this).constructor);
|
|
}
|
|
|
|
Wrapper.prototype = Object.create(Class.prototype, {
|
|
constructor: {
|
|
value: Wrapper,
|
|
enumerable: false,
|
|
writable: true,
|
|
configurable: true
|
|
}
|
|
});
|
|
return _setPrototypeOf(Wrapper, Class);
|
|
};
|
|
|
|
return _wrapNativeSuper(Class);
|
|
}
|
|
|
|
function _instanceof(left, right) {
|
|
if (
|
|
right != null &&
|
|
typeof Symbol !== 'undefined' &&
|
|
right[Symbol.hasInstance]
|
|
) {
|
|
return right[Symbol.hasInstance](left);
|
|
} else {
|
|
return left instanceof right;
|
|
}
|
|
}
|
|
|
|
function _interopRequireDefault(obj) {
|
|
return obj && obj.__esModule
|
|
? obj
|
|
: {
|
|
default: obj
|
|
};
|
|
}
|
|
|
|
function _interopRequireWildcard(obj) {
|
|
if (obj && obj.__esModule) {
|
|
return obj;
|
|
} else {
|
|
var newObj = {};
|
|
|
|
if (obj != null) {
|
|
for (var key in obj) {
|
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
var desc =
|
|
Object.defineProperty && Object.getOwnPropertyDescriptor
|
|
? Object.getOwnPropertyDescriptor(obj, key)
|
|
: {};
|
|
|
|
if (desc.get || desc.set) {
|
|
Object.defineProperty(newObj, key, desc);
|
|
} else {
|
|
newObj[key] = obj[key];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
newObj.default = obj;
|
|
return newObj;
|
|
}
|
|
}
|
|
|
|
function _newArrowCheck(innerThis, boundThis) {
|
|
if (innerThis !== boundThis) {
|
|
throw new TypeError('Cannot instantiate an arrow function');
|
|
}
|
|
}
|
|
|
|
function _objectDestructuringEmpty(obj) {
|
|
if (obj == null) throw new TypeError('Cannot destructure undefined');
|
|
}
|
|
|
|
function _objectWithoutPropertiesLoose(source, excluded) {
|
|
if (source == null) return {};
|
|
var target = {};
|
|
var sourceKeys = Object.keys(source);
|
|
var key, i;
|
|
|
|
for (i = 0; i < sourceKeys.length; i++) {
|
|
key = sourceKeys[i];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
target[key] = source[key];
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
function _objectWithoutProperties(source, excluded) {
|
|
if (source == null) return {};
|
|
|
|
var target = _objectWithoutPropertiesLoose(source, excluded);
|
|
|
|
var key, i;
|
|
|
|
if (Object.getOwnPropertySymbols) {
|
|
var sourceSymbolKeys = Object.getOwnPropertySymbols(source);
|
|
|
|
for (i = 0; i < sourceSymbolKeys.length; i++) {
|
|
key = sourceSymbolKeys[i];
|
|
if (excluded.indexOf(key) >= 0) continue;
|
|
if (!Object.prototype.propertyIsEnumerable.call(source, key)) continue;
|
|
target[key] = source[key];
|
|
}
|
|
}
|
|
|
|
return target;
|
|
}
|
|
|
|
function _assertThisInitialized(self) {
|
|
if (self === void 0) {
|
|
throw new ReferenceError(
|
|
"this hasn't been initialised - super() hasn't been called"
|
|
);
|
|
}
|
|
|
|
return self;
|
|
}
|
|
|
|
function _possibleConstructorReturn(self, call) {
|
|
if (call && (typeof call === 'object' || typeof call === 'function')) {
|
|
return call;
|
|
}
|
|
|
|
return _assertThisInitialized(self);
|
|
}
|
|
|
|
function _superPropBase(object, property) {
|
|
while (!Object.prototype.hasOwnProperty.call(object, property)) {
|
|
object = _getPrototypeOf(object);
|
|
if (object === null) break;
|
|
}
|
|
|
|
return object;
|
|
}
|
|
|
|
function _get(target, property, receiver) {
|
|
if (typeof Reflect !== 'undefined' && Reflect.get) {
|
|
_get = Reflect.get;
|
|
} else {
|
|
_get = function _get(target, property, receiver) {
|
|
var base = _superPropBase(target, property);
|
|
|
|
if (!base) return;
|
|
var desc = Object.getOwnPropertyDescriptor(base, property);
|
|
|
|
if (desc.get) {
|
|
return desc.get.call(receiver);
|
|
}
|
|
|
|
return desc.value;
|
|
};
|
|
}
|
|
|
|
return _get(target, property, receiver || target);
|
|
}
|
|
|
|
function set(target, property, value, receiver) {
|
|
if (typeof Reflect !== 'undefined' && Reflect.set) {
|
|
set = Reflect.set;
|
|
} else {
|
|
set = function set(target, property, value, receiver) {
|
|
var base = _superPropBase(target, property);
|
|
|
|
var desc;
|
|
|
|
if (base) {
|
|
desc = Object.getOwnPropertyDescriptor(base, property);
|
|
|
|
if (desc.set) {
|
|
desc.set.call(receiver, value);
|
|
return true;
|
|
} else if (!desc.writable) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
desc = Object.getOwnPropertyDescriptor(receiver, property);
|
|
|
|
if (desc) {
|
|
if (!desc.writable) {
|
|
return false;
|
|
}
|
|
|
|
desc.value = value;
|
|
Object.defineProperty(receiver, property, desc);
|
|
} else {
|
|
_defineProperty(receiver, property, value);
|
|
}
|
|
|
|
return true;
|
|
};
|
|
}
|
|
|
|
return set(target, property, value, receiver);
|
|
}
|
|
|
|
function _set(target, property, value, receiver, isStrict) {
|
|
var s = set(target, property, value, receiver || target);
|
|
|
|
if (!s && isStrict) {
|
|
throw new Error('failed to set property');
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function _taggedTemplateLiteral(strings, raw) {
|
|
if (!raw) {
|
|
raw = strings.slice(0);
|
|
}
|
|
|
|
return Object.freeze(
|
|
Object.defineProperties(strings, {
|
|
raw: {
|
|
value: Object.freeze(raw)
|
|
}
|
|
})
|
|
);
|
|
}
|
|
|
|
function _taggedTemplateLiteralLoose(strings, raw) {
|
|
if (!raw) {
|
|
raw = strings.slice(0);
|
|
}
|
|
|
|
strings.raw = raw;
|
|
return strings;
|
|
}
|
|
|
|
function _temporalRef(val, name) {
|
|
if (val === _temporalUndefined) {
|
|
throw new ReferenceError(name + ' is not defined - temporal dead zone');
|
|
} else {
|
|
return val;
|
|
}
|
|
}
|
|
|
|
function _readOnlyError(name) {
|
|
throw new Error('"' + name + '" is read-only');
|
|
}
|
|
|
|
function _classNameTDZError(name) {
|
|
throw new Error(
|
|
'Class "' + name + '" cannot be referenced in computed property keys.'
|
|
);
|
|
}
|
|
|
|
var _temporalUndefined = {};
|
|
|
|
function _slicedToArray(arr, i) {
|
|
return (
|
|
_arrayWithHoles(arr) ||
|
|
_iterableToArrayLimit(arr, i) ||
|
|
_nonIterableRest()
|
|
);
|
|
}
|
|
|
|
function _slicedToArrayLoose(arr, i) {
|
|
return (
|
|
_arrayWithHoles(arr) ||
|
|
_iterableToArrayLimitLoose(arr, i) ||
|
|
_nonIterableRest()
|
|
);
|
|
}
|
|
|
|
function _toArray(arr) {
|
|
return _arrayWithHoles(arr) || _iterableToArray(arr) || _nonIterableRest();
|
|
}
|
|
|
|
function _toConsumableArray(arr) {
|
|
return (
|
|
_arrayWithoutHoles(arr) || _iterableToArray(arr) || _nonIterableSpread()
|
|
);
|
|
}
|
|
|
|
function _arrayWithoutHoles(arr) {
|
|
if (Array.isArray(arr)) {
|
|
for (var i = 0, arr2 = new Array(arr.length); i < arr.length; i++)
|
|
arr2[i] = arr[i];
|
|
|
|
return arr2;
|
|
}
|
|
}
|
|
|
|
function _arrayWithHoles(arr) {
|
|
if (Array.isArray(arr)) return arr;
|
|
}
|
|
|
|
function _iterableToArray(iter) {
|
|
if (
|
|
Symbol.iterator in Object(iter) ||
|
|
Object.prototype.toString.call(iter) === '[object Arguments]'
|
|
)
|
|
return Array.from(iter);
|
|
}
|
|
|
|
function _iterableToArrayLimit(arr, i) {
|
|
var _arr = [];
|
|
var _n = true;
|
|
var _d = false;
|
|
var _e = undefined;
|
|
|
|
try {
|
|
for (
|
|
var _i = arr[Symbol.iterator](), _s;
|
|
!(_n = (_s = _i.next()).done);
|
|
_n = true
|
|
) {
|
|
_arr.push(_s.value);
|
|
|
|
if (i && _arr.length === i) break;
|
|
}
|
|
} catch (err) {
|
|
_d = true;
|
|
_e = err;
|
|
} finally {
|
|
try {
|
|
if (!_n && _i['return'] != null) _i['return']();
|
|
} finally {
|
|
if (_d) throw _e;
|
|
}
|
|
}
|
|
|
|
return _arr;
|
|
}
|
|
|
|
function _iterableToArrayLimitLoose(arr, i) {
|
|
var _arr = [];
|
|
|
|
for (
|
|
var _iterator = arr[Symbol.iterator](), _step;
|
|
!(_step = _iterator.next()).done;
|
|
|
|
) {
|
|
_arr.push(_step.value);
|
|
|
|
if (i && _arr.length === i) break;
|
|
}
|
|
|
|
return _arr;
|
|
}
|
|
|
|
function _nonIterableSpread() {
|
|
throw new TypeError('Invalid attempt to spread non-iterable instance');
|
|
}
|
|
|
|
function _nonIterableRest() {
|
|
throw new TypeError('Invalid attempt to destructure non-iterable instance');
|
|
}
|
|
|
|
function _skipFirstGeneratorNext(fn) {
|
|
return function() {
|
|
var it = fn.apply(this, arguments);
|
|
it.next();
|
|
return it;
|
|
};
|
|
}
|
|
|
|
function _toPrimitive(input, hint) {
|
|
if (typeof input !== 'object' || input === null) return input;
|
|
var prim = input[Symbol.toPrimitive];
|
|
|
|
if (prim !== undefined) {
|
|
var res = prim.call(input, hint || 'default');
|
|
if (typeof res !== 'object') return res;
|
|
throw new TypeError('@@toPrimitive must return a primitive value.');
|
|
}
|
|
|
|
return (hint === 'string' ? String : Number)(input);
|
|
}
|
|
|
|
function _toPropertyKey(arg) {
|
|
var key = _toPrimitive(arg, 'string');
|
|
|
|
return typeof key === 'symbol' ? key : String(key);
|
|
}
|
|
|
|
function _initializerWarningHelper(descriptor, context) {
|
|
throw new Error(
|
|
'Decorating class property failed. Please ensure that ' +
|
|
'proposal-class-properties is enabled and set to use loose mode. ' +
|
|
'To use proposal-class-properties in spec mode with decorators, wait for ' +
|
|
'the next major version of decorators in stage 2.'
|
|
);
|
|
}
|
|
|
|
function _initializerDefineProperty(target, property, descriptor, context) {
|
|
if (!descriptor) return;
|
|
Object.defineProperty(target, property, {
|
|
enumerable: descriptor.enumerable,
|
|
configurable: descriptor.configurable,
|
|
writable: descriptor.writable,
|
|
value: descriptor.initializer
|
|
? descriptor.initializer.call(context)
|
|
: void 0
|
|
});
|
|
}
|
|
|
|
function _applyDecoratedDescriptor(
|
|
target,
|
|
property,
|
|
decorators,
|
|
descriptor,
|
|
context
|
|
) {
|
|
var desc = {};
|
|
Object.keys(descriptor).forEach(function(key) {
|
|
desc[key] = descriptor[key];
|
|
});
|
|
desc.enumerable = !!desc.enumerable;
|
|
desc.configurable = !!desc.configurable;
|
|
|
|
if ('value' in desc || desc.initializer) {
|
|
desc.writable = true;
|
|
}
|
|
|
|
desc = decorators
|
|
.slice()
|
|
.reverse()
|
|
.reduce(function(desc, decorator) {
|
|
return decorator(target, property, desc) || desc;
|
|
}, desc);
|
|
|
|
if (context && desc.initializer !== void 0) {
|
|
desc.value = desc.initializer ? desc.initializer.call(context) : void 0;
|
|
desc.initializer = undefined;
|
|
}
|
|
|
|
if (desc.initializer === void 0) {
|
|
Object.defineProperty(target, property, desc);
|
|
desc = null;
|
|
}
|
|
|
|
return desc;
|
|
}
|
|
|
|
var id = 0;
|
|
|
|
function _classPrivateFieldLooseKey(name) {
|
|
return '__private_' + id++ + '_' + name;
|
|
}
|
|
|
|
function _classPrivateFieldLooseBase(receiver, privateKey) {
|
|
if (!Object.prototype.hasOwnProperty.call(receiver, privateKey)) {
|
|
throw new TypeError('attempted to use private field on non-instance');
|
|
}
|
|
|
|
return receiver;
|
|
}
|
|
|
|
function _classPrivateFieldGet(receiver, privateMap) {
|
|
if (!privateMap.has(receiver)) {
|
|
throw new TypeError('attempted to get private field on non-instance');
|
|
}
|
|
|
|
var descriptor = privateMap.get(receiver);
|
|
|
|
if (descriptor.get) {
|
|
return descriptor.get.call(receiver);
|
|
}
|
|
|
|
return descriptor.value;
|
|
}
|
|
|
|
function _classPrivateFieldSet(receiver, privateMap, value) {
|
|
if (!privateMap.has(receiver)) {
|
|
throw new TypeError('attempted to set private field on non-instance');
|
|
}
|
|
|
|
var descriptor = privateMap.get(receiver);
|
|
|
|
if (descriptor.set) {
|
|
descriptor.set.call(receiver, value);
|
|
} else {
|
|
if (!descriptor.writable) {
|
|
throw new TypeError('attempted to set read only private field');
|
|
}
|
|
|
|
descriptor.value = value;
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function _classStaticPrivateFieldSpecGet(
|
|
receiver,
|
|
classConstructor,
|
|
descriptor
|
|
) {
|
|
if (receiver !== classConstructor) {
|
|
throw new TypeError('Private static access of wrong provenance');
|
|
}
|
|
|
|
return descriptor.value;
|
|
}
|
|
|
|
function _classStaticPrivateFieldSpecSet(
|
|
receiver,
|
|
classConstructor,
|
|
descriptor,
|
|
value
|
|
) {
|
|
if (receiver !== classConstructor) {
|
|
throw new TypeError('Private static access of wrong provenance');
|
|
}
|
|
|
|
if (!descriptor.writable) {
|
|
throw new TypeError('attempted to set read only private field');
|
|
}
|
|
|
|
descriptor.value = value;
|
|
return value;
|
|
}
|
|
|
|
function _classStaticPrivateMethodGet(receiver, classConstructor, method) {
|
|
if (receiver !== classConstructor) {
|
|
throw new TypeError('Private static access of wrong provenance');
|
|
}
|
|
|
|
return method;
|
|
}
|
|
|
|
function _classStaticPrivateMethodSet() {
|
|
throw new TypeError('attempted to set read only static private field');
|
|
}
|
|
|
|
function _decorate(decorators, factory, superClass, mixins) {
|
|
var api = _getDecoratorsApi();
|
|
|
|
if (mixins) {
|
|
for (var i = 0; i < mixins.length; i++) {
|
|
api = mixins[i](api);
|
|
}
|
|
}
|
|
|
|
var r = factory(function initialize(O) {
|
|
api.initializeInstanceElements(O, decorated.elements);
|
|
}, superClass);
|
|
var decorated = api.decorateClass(
|
|
_coalesceClassElements(r.d.map(_createElementDescriptor)),
|
|
decorators
|
|
);
|
|
api.initializeClassElements(r.F, decorated.elements);
|
|
return api.runClassFinishers(r.F, decorated.finishers);
|
|
}
|
|
|
|
function _getDecoratorsApi() {
|
|
_getDecoratorsApi = function() {
|
|
return api;
|
|
};
|
|
|
|
var api = {
|
|
elementsDefinitionOrder: [['method'], ['field']],
|
|
initializeInstanceElements: function(O, elements) {
|
|
['method', 'field'].forEach(function(kind) {
|
|
elements.forEach(function(element) {
|
|
if (element.kind === kind && element.placement === 'own') {
|
|
this.defineClassElement(O, element);
|
|
}
|
|
}, this);
|
|
}, this);
|
|
},
|
|
initializeClassElements: function(F, elements) {
|
|
var proto = F.prototype;
|
|
['method', 'field'].forEach(function(kind) {
|
|
elements.forEach(function(element) {
|
|
var placement = element.placement;
|
|
|
|
if (
|
|
element.kind === kind &&
|
|
(placement === 'static' || placement === 'prototype')
|
|
) {
|
|
var receiver = placement === 'static' ? F : proto;
|
|
this.defineClassElement(receiver, element);
|
|
}
|
|
}, this);
|
|
}, this);
|
|
},
|
|
defineClassElement: function(receiver, element) {
|
|
var descriptor = element.descriptor;
|
|
|
|
if (element.kind === 'field') {
|
|
var initializer = element.initializer;
|
|
descriptor = {
|
|
enumerable: descriptor.enumerable,
|
|
writable: descriptor.writable,
|
|
configurable: descriptor.configurable,
|
|
value: initializer === void 0 ? void 0 : initializer.call(receiver)
|
|
};
|
|
}
|
|
|
|
Object.defineProperty(receiver, element.key, descriptor);
|
|
},
|
|
decorateClass: function(elements, decorators) {
|
|
var newElements = [];
|
|
var finishers = [];
|
|
var placements = {
|
|
static: [],
|
|
prototype: [],
|
|
own: []
|
|
};
|
|
elements.forEach(function(element) {
|
|
this.addElementPlacement(element, placements);
|
|
}, this);
|
|
elements.forEach(function(element) {
|
|
if (!_hasDecorators(element)) return newElements.push(element);
|
|
var elementFinishersExtras = this.decorateElement(
|
|
element,
|
|
placements
|
|
);
|
|
newElements.push(elementFinishersExtras.element);
|
|
newElements.push.apply(newElements, elementFinishersExtras.extras);
|
|
finishers.push.apply(finishers, elementFinishersExtras.finishers);
|
|
}, this);
|
|
|
|
if (!decorators) {
|
|
return {
|
|
elements: newElements,
|
|
finishers: finishers
|
|
};
|
|
}
|
|
|
|
var result = this.decorateConstructor(newElements, decorators);
|
|
finishers.push.apply(finishers, result.finishers);
|
|
result.finishers = finishers;
|
|
return result;
|
|
},
|
|
addElementPlacement: function(element, placements, silent) {
|
|
var keys = placements[element.placement];
|
|
|
|
if (!silent && keys.indexOf(element.key) !== -1) {
|
|
throw new TypeError('Duplicated element (' + element.key + ')');
|
|
}
|
|
|
|
keys.push(element.key);
|
|
},
|
|
decorateElement: function(element, placements) {
|
|
var extras = [];
|
|
var finishers = [];
|
|
|
|
for (
|
|
var decorators = element.decorators, i = decorators.length - 1;
|
|
i >= 0;
|
|
i--
|
|
) {
|
|
var keys = placements[element.placement];
|
|
keys.splice(keys.indexOf(element.key), 1);
|
|
var elementObject = this.fromElementDescriptor(element);
|
|
var elementFinisherExtras = this.toElementFinisherExtras(
|
|
(0, decorators[i])(elementObject) || elementObject
|
|
);
|
|
element = elementFinisherExtras.element;
|
|
this.addElementPlacement(element, placements);
|
|
|
|
if (elementFinisherExtras.finisher) {
|
|
finishers.push(elementFinisherExtras.finisher);
|
|
}
|
|
|
|
var newExtras = elementFinisherExtras.extras;
|
|
|
|
if (newExtras) {
|
|
for (var j = 0; j < newExtras.length; j++) {
|
|
this.addElementPlacement(newExtras[j], placements);
|
|
}
|
|
|
|
extras.push.apply(extras, newExtras);
|
|
}
|
|
}
|
|
|
|
return {
|
|
element: element,
|
|
finishers: finishers,
|
|
extras: extras
|
|
};
|
|
},
|
|
decorateConstructor: function(elements, decorators) {
|
|
var finishers = [];
|
|
|
|
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
var obj = this.fromClassDescriptor(elements);
|
|
var elementsAndFinisher = this.toClassDescriptor(
|
|
(0, decorators[i])(obj) || obj
|
|
);
|
|
|
|
if (elementsAndFinisher.finisher !== undefined) {
|
|
finishers.push(elementsAndFinisher.finisher);
|
|
}
|
|
|
|
if (elementsAndFinisher.elements !== undefined) {
|
|
elements = elementsAndFinisher.elements;
|
|
|
|
for (var j = 0; j < elements.length - 1; j++) {
|
|
for (var k = j + 1; k < elements.length; k++) {
|
|
if (
|
|
elements[j].key === elements[k].key &&
|
|
elements[j].placement === elements[k].placement
|
|
) {
|
|
throw new TypeError(
|
|
'Duplicated element (' + elements[j].key + ')'
|
|
);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return {
|
|
elements: elements,
|
|
finishers: finishers
|
|
};
|
|
},
|
|
fromElementDescriptor: function(element) {
|
|
var obj = {
|
|
kind: element.kind,
|
|
key: element.key,
|
|
placement: element.placement,
|
|
descriptor: element.descriptor
|
|
};
|
|
var desc = {
|
|
value: 'Descriptor',
|
|
configurable: true
|
|
};
|
|
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
|
if (element.kind === 'field') obj.initializer = element.initializer;
|
|
return obj;
|
|
},
|
|
toElementDescriptors: function(elementObjects) {
|
|
if (elementObjects === undefined) return;
|
|
return _toArray(elementObjects).map(function(elementObject) {
|
|
var element = this.toElementDescriptor(elementObject);
|
|
this.disallowProperty(
|
|
elementObject,
|
|
'finisher',
|
|
'An element descriptor'
|
|
);
|
|
this.disallowProperty(
|
|
elementObject,
|
|
'extras',
|
|
'An element descriptor'
|
|
);
|
|
return element;
|
|
}, this);
|
|
},
|
|
toElementDescriptor: function(elementObject) {
|
|
var kind = String(elementObject.kind);
|
|
|
|
if (kind !== 'method' && kind !== 'field') {
|
|
throw new TypeError(
|
|
'An element descriptor\'s .kind property must be either "method" or' +
|
|
' "field", but a decorator created an element descriptor with' +
|
|
' .kind "' +
|
|
kind +
|
|
'"'
|
|
);
|
|
}
|
|
|
|
var key = _toPropertyKey(elementObject.key);
|
|
|
|
var placement = String(elementObject.placement);
|
|
|
|
if (
|
|
placement !== 'static' &&
|
|
placement !== 'prototype' &&
|
|
placement !== 'own'
|
|
) {
|
|
throw new TypeError(
|
|
'An element descriptor\'s .placement property must be one of "static",' +
|
|
' "prototype" or "own", but a decorator created an element descriptor' +
|
|
' with .placement "' +
|
|
placement +
|
|
'"'
|
|
);
|
|
}
|
|
|
|
var descriptor = elementObject.descriptor;
|
|
this.disallowProperty(
|
|
elementObject,
|
|
'elements',
|
|
'An element descriptor'
|
|
);
|
|
var element = {
|
|
kind: kind,
|
|
key: key,
|
|
placement: placement,
|
|
descriptor: Object.assign({}, descriptor)
|
|
};
|
|
|
|
if (kind !== 'field') {
|
|
this.disallowProperty(
|
|
elementObject,
|
|
'initializer',
|
|
'A method descriptor'
|
|
);
|
|
} else {
|
|
this.disallowProperty(
|
|
descriptor,
|
|
'get',
|
|
'The property descriptor of a field descriptor'
|
|
);
|
|
this.disallowProperty(
|
|
descriptor,
|
|
'set',
|
|
'The property descriptor of a field descriptor'
|
|
);
|
|
this.disallowProperty(
|
|
descriptor,
|
|
'value',
|
|
'The property descriptor of a field descriptor'
|
|
);
|
|
element.initializer = elementObject.initializer;
|
|
}
|
|
|
|
return element;
|
|
},
|
|
toElementFinisherExtras: function(elementObject) {
|
|
var element = this.toElementDescriptor(elementObject);
|
|
|
|
var finisher = _optionalCallableProperty(elementObject, 'finisher');
|
|
|
|
var extras = this.toElementDescriptors(elementObject.extras);
|
|
return {
|
|
element: element,
|
|
finisher: finisher,
|
|
extras: extras
|
|
};
|
|
},
|
|
fromClassDescriptor: function(elements) {
|
|
var obj = {
|
|
kind: 'class',
|
|
elements: elements.map(this.fromElementDescriptor, this)
|
|
};
|
|
var desc = {
|
|
value: 'Descriptor',
|
|
configurable: true
|
|
};
|
|
Object.defineProperty(obj, Symbol.toStringTag, desc);
|
|
return obj;
|
|
},
|
|
toClassDescriptor: function(obj) {
|
|
var kind = String(obj.kind);
|
|
|
|
if (kind !== 'class') {
|
|
throw new TypeError(
|
|
'A class descriptor\'s .kind property must be "class", but a decorator' +
|
|
' created a class descriptor with .kind "' +
|
|
kind +
|
|
'"'
|
|
);
|
|
}
|
|
|
|
this.disallowProperty(obj, 'key', 'A class descriptor');
|
|
this.disallowProperty(obj, 'placement', 'A class descriptor');
|
|
this.disallowProperty(obj, 'descriptor', 'A class descriptor');
|
|
this.disallowProperty(obj, 'initializer', 'A class descriptor');
|
|
this.disallowProperty(obj, 'extras', 'A class descriptor');
|
|
|
|
var finisher = _optionalCallableProperty(obj, 'finisher');
|
|
|
|
var elements = this.toElementDescriptors(obj.elements);
|
|
return {
|
|
elements: elements,
|
|
finisher: finisher
|
|
};
|
|
},
|
|
runClassFinishers: function(constructor, finishers) {
|
|
for (var i = 0; i < finishers.length; i++) {
|
|
var newConstructor = (0, finishers[i])(constructor);
|
|
|
|
if (newConstructor !== undefined) {
|
|
if (typeof newConstructor !== 'function') {
|
|
throw new TypeError('Finishers must return a constructor.');
|
|
}
|
|
|
|
constructor = newConstructor;
|
|
}
|
|
}
|
|
|
|
return constructor;
|
|
},
|
|
disallowProperty: function(obj, name, objectType) {
|
|
if (obj[name] !== undefined) {
|
|
throw new TypeError(
|
|
objectType + " can't have a ." + name + ' property.'
|
|
);
|
|
}
|
|
}
|
|
};
|
|
return api;
|
|
}
|
|
|
|
function _createElementDescriptor(def) {
|
|
var key = _toPropertyKey(def.key);
|
|
|
|
var descriptor;
|
|
|
|
if (def.kind === 'method') {
|
|
descriptor = {
|
|
value: def.value,
|
|
writable: true,
|
|
configurable: true,
|
|
enumerable: false
|
|
};
|
|
} else if (def.kind === 'get') {
|
|
descriptor = {
|
|
get: def.value,
|
|
configurable: true,
|
|
enumerable: false
|
|
};
|
|
} else if (def.kind === 'set') {
|
|
descriptor = {
|
|
set: def.value,
|
|
configurable: true,
|
|
enumerable: false
|
|
};
|
|
} else if (def.kind === 'field') {
|
|
descriptor = {
|
|
configurable: true,
|
|
writable: true,
|
|
enumerable: true
|
|
};
|
|
}
|
|
|
|
var element = {
|
|
kind: def.kind === 'field' ? 'field' : 'method',
|
|
key: key,
|
|
placement: def.static
|
|
? 'static'
|
|
: def.kind === 'field'
|
|
? 'own'
|
|
: 'prototype',
|
|
descriptor: descriptor
|
|
};
|
|
if (def.decorators) element.decorators = def.decorators;
|
|
if (def.kind === 'field') element.initializer = def.value;
|
|
return element;
|
|
}
|
|
|
|
function _coalesceGetterSetter(element, other) {
|
|
if (element.descriptor.get !== undefined) {
|
|
other.descriptor.get = element.descriptor.get;
|
|
} else {
|
|
other.descriptor.set = element.descriptor.set;
|
|
}
|
|
}
|
|
|
|
function _coalesceClassElements(elements) {
|
|
var newElements = [];
|
|
|
|
var isSameElement = function(other) {
|
|
return (
|
|
other.kind === 'method' &&
|
|
other.key === element.key &&
|
|
other.placement === element.placement
|
|
);
|
|
};
|
|
|
|
for (var i = 0; i < elements.length; i++) {
|
|
var element = elements[i];
|
|
var other;
|
|
|
|
if (
|
|
element.kind === 'method' &&
|
|
(other = newElements.find(isSameElement))
|
|
) {
|
|
if (
|
|
_isDataDescriptor(element.descriptor) ||
|
|
_isDataDescriptor(other.descriptor)
|
|
) {
|
|
if (_hasDecorators(element) || _hasDecorators(other)) {
|
|
throw new ReferenceError(
|
|
'Duplicated methods (' + element.key + ") can't be decorated."
|
|
);
|
|
}
|
|
|
|
other.descriptor = element.descriptor;
|
|
} else {
|
|
if (_hasDecorators(element)) {
|
|
if (_hasDecorators(other)) {
|
|
throw new ReferenceError(
|
|
"Decorators can't be placed on different accessors with for " +
|
|
'the same property (' +
|
|
element.key +
|
|
').'
|
|
);
|
|
}
|
|
|
|
other.decorators = element.decorators;
|
|
}
|
|
|
|
_coalesceGetterSetter(element, other);
|
|
}
|
|
} else {
|
|
newElements.push(element);
|
|
}
|
|
}
|
|
|
|
return newElements;
|
|
}
|
|
|
|
function _hasDecorators(element) {
|
|
return element.decorators && element.decorators.length;
|
|
}
|
|
|
|
function _isDataDescriptor(desc) {
|
|
return (
|
|
desc !== undefined &&
|
|
!(desc.value === undefined && desc.writable === undefined)
|
|
);
|
|
}
|
|
|
|
function _optionalCallableProperty(obj, name) {
|
|
var value = obj[name];
|
|
|
|
if (value !== undefined && typeof value !== 'function') {
|
|
throw new TypeError("Expected '" + name + "' to be a function");
|
|
}
|
|
|
|
return value;
|
|
}
|
|
|
|
function _classPrivateMethodGet(receiver, privateSet, fn) {
|
|
if (!privateSet.has(receiver)) {
|
|
throw new TypeError('attempted to get private field on non-instance');
|
|
}
|
|
|
|
return fn;
|
|
}
|
|
|
|
function _classPrivateMethodSet() {
|
|
throw new TypeError('attempted to reassign private method');
|
|
}
|
|
|
|
function _wrapRegExp(re, groups) {
|
|
_wrapRegExp = function(re, groups) {
|
|
return new BabelRegExp(re, groups);
|
|
};
|
|
|
|
var _RegExp = _wrapNativeSuper(RegExp);
|
|
|
|
var _super = RegExp.prototype;
|
|
|
|
var _groups = new WeakMap();
|
|
|
|
function BabelRegExp(re, groups) {
|
|
var _this = _RegExp.call(this, re);
|
|
|
|
_groups.set(_this, groups);
|
|
|
|
return _this;
|
|
}
|
|
|
|
_inherits(BabelRegExp, _RegExp);
|
|
|
|
BabelRegExp.prototype.exec = function(str) {
|
|
var result = _super.exec.call(this, str);
|
|
|
|
if (result) result.groups = buildGroups(result, this);
|
|
return result;
|
|
};
|
|
|
|
BabelRegExp.prototype[Symbol.replace] = function(str, substitution) {
|
|
if (typeof substitution === 'string') {
|
|
var groups = _groups.get(this);
|
|
|
|
return _super[Symbol.replace].call(
|
|
this,
|
|
str,
|
|
substitution.replace(/\$<([^>]+)>/g, function(_, name) {
|
|
return '$' + groups[name];
|
|
})
|
|
);
|
|
} else if (typeof substitution === 'function') {
|
|
var _this = this;
|
|
|
|
return _super[Symbol.replace].call(this, str, function() {
|
|
var args = [];
|
|
args.push.apply(args, arguments);
|
|
|
|
if (typeof args[args.length - 1] !== 'object') {
|
|
args.push(buildGroups(args, _this));
|
|
}
|
|
|
|
return substitution.apply(this, args);
|
|
});
|
|
} else {
|
|
return _super[Symbol.replace].call(this, str, substitution);
|
|
}
|
|
};
|
|
|
|
function buildGroups(result, re) {
|
|
var g = _groups.get(re);
|
|
|
|
return Object.keys(g).reduce(function(groups, name) {
|
|
groups[name] = result[g[name]];
|
|
return groups;
|
|
}, Object.create(null));
|
|
}
|
|
|
|
return _wrapRegExp.apply(this, arguments);
|
|
}
|
|
|
|
var vectorMultiply = function vectorMultiply(v, amount) {
|
|
return createVector(v.x * amount, v.y * amount);
|
|
};
|
|
|
|
var vectorAdd = function vectorAdd(a, b) {
|
|
return createVector(a.x + b.x, a.y + b.y);
|
|
};
|
|
|
|
var vectorNormalize = function vectorNormalize(v) {
|
|
var l = Math.sqrt(v.x * v.x + v.y * v.y);
|
|
if (l === 0) {
|
|
return {
|
|
x: 0,
|
|
y: 0
|
|
};
|
|
}
|
|
return createVector(v.x / l, v.y / l);
|
|
};
|
|
|
|
var vectorRotate = function vectorRotate(v, radians, origin) {
|
|
var cos = Math.cos(radians);
|
|
var sin = Math.sin(radians);
|
|
var t = createVector(v.x - origin.x, v.y - origin.y);
|
|
return createVector(
|
|
origin.x + cos * t.x - sin * t.y,
|
|
origin.y + sin * t.x + cos * t.y
|
|
);
|
|
};
|
|
|
|
var createVector = function createVector() {
|
|
var x =
|
|
arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
|
|
var y =
|
|
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 0;
|
|
return { x: x, y: y };
|
|
};
|
|
|
|
var getMarkupValue = function getMarkupValue(value, size) {
|
|
var scalar =
|
|
arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
var axis = arguments.length > 3 ? arguments[3] : undefined;
|
|
if (typeof value === 'string') {
|
|
return parseFloat(value) * scalar;
|
|
}
|
|
if (typeof value === 'number') {
|
|
return value * (axis ? size[axis] : Math.min(size.width, size.height));
|
|
}
|
|
return;
|
|
};
|
|
|
|
var getMarkupStyles = function getMarkupStyles(markup, size, scale) {
|
|
var lineStyle = markup.borderStyle || markup.lineStyle || 'solid';
|
|
var fill = markup.backgroundColor || markup.fontColor || 'transparent';
|
|
var stroke = markup.borderColor || markup.lineColor || 'transparent';
|
|
var strokeWidth = getMarkupValue(
|
|
markup.borderWidth || markup.lineWidth,
|
|
size,
|
|
scale
|
|
);
|
|
var lineCap = markup.lineCap || 'round';
|
|
var lineJoin = markup.lineJoin || 'round';
|
|
var dashes =
|
|
typeof lineStyle === 'string'
|
|
? ''
|
|
: lineStyle
|
|
.map(function(v) {
|
|
return getMarkupValue(v, size, scale);
|
|
})
|
|
.join(',');
|
|
var opacity = markup.opacity || 1;
|
|
return {
|
|
'stroke-linecap': lineCap,
|
|
'stroke-linejoin': lineJoin,
|
|
'stroke-width': strokeWidth || 0,
|
|
'stroke-dasharray': dashes,
|
|
stroke: stroke,
|
|
fill: fill,
|
|
opacity: opacity
|
|
};
|
|
};
|
|
|
|
var isDefined = function isDefined(value) {
|
|
return value != null;
|
|
};
|
|
|
|
var getMarkupRect = function getMarkupRect(rect, size) {
|
|
var scalar =
|
|
arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
|
|
var left =
|
|
getMarkupValue(rect.x, size, scalar, 'width') ||
|
|
getMarkupValue(rect.left, size, scalar, 'width');
|
|
var top =
|
|
getMarkupValue(rect.y, size, scalar, 'height') ||
|
|
getMarkupValue(rect.top, size, scalar, 'height');
|
|
var width = getMarkupValue(rect.width, size, scalar, 'width');
|
|
var height = getMarkupValue(rect.height, size, scalar, 'height');
|
|
var right = getMarkupValue(rect.right, size, scalar, 'width');
|
|
var bottom = getMarkupValue(rect.bottom, size, scalar, 'height');
|
|
|
|
if (!isDefined(top)) {
|
|
if (isDefined(height) && isDefined(bottom)) {
|
|
top = size.height - height - bottom;
|
|
} else {
|
|
top = bottom;
|
|
}
|
|
}
|
|
|
|
if (!isDefined(left)) {
|
|
if (isDefined(width) && isDefined(right)) {
|
|
left = size.width - width - right;
|
|
} else {
|
|
left = right;
|
|
}
|
|
}
|
|
|
|
if (!isDefined(width)) {
|
|
if (isDefined(left) && isDefined(right)) {
|
|
width = size.width - left - right;
|
|
} else {
|
|
width = 0;
|
|
}
|
|
}
|
|
|
|
if (!isDefined(height)) {
|
|
if (isDefined(top) && isDefined(bottom)) {
|
|
height = size.height - top - bottom;
|
|
} else {
|
|
height = 0;
|
|
}
|
|
}
|
|
|
|
return {
|
|
x: left || 0,
|
|
y: top || 0,
|
|
width: width || 0,
|
|
height: height || 0
|
|
};
|
|
};
|
|
|
|
var pointsToPathShape = function pointsToPathShape(points) {
|
|
return points
|
|
.map(function(point, index) {
|
|
return ''
|
|
.concat(index === 0 ? 'M' : 'L', ' ')
|
|
.concat(point.x, ' ')
|
|
.concat(point.y);
|
|
})
|
|
.join(' ');
|
|
};
|
|
|
|
var setAttributes = function setAttributes(element, attr) {
|
|
return Object.keys(attr).forEach(function(key) {
|
|
return element.setAttribute(key, attr[key]);
|
|
});
|
|
};
|
|
|
|
var ns = 'http://www.w3.org/2000/svg';
|
|
var svg = function svg(tag, attr) {
|
|
var element = document.createElementNS(ns, tag);
|
|
if (attr) {
|
|
setAttributes(element, attr);
|
|
}
|
|
return element;
|
|
};
|
|
|
|
var updateRect = function updateRect(element) {
|
|
return setAttributes(
|
|
element,
|
|
Object.assign({}, element.rect, element.styles)
|
|
);
|
|
};
|
|
|
|
var updateEllipse = function updateEllipse(element) {
|
|
var cx = element.rect.x + element.rect.width * 0.5;
|
|
var cy = element.rect.y + element.rect.height * 0.5;
|
|
var rx = element.rect.width * 0.5;
|
|
var ry = element.rect.height * 0.5;
|
|
return setAttributes(
|
|
element,
|
|
Object.assign(
|
|
{
|
|
cx: cx,
|
|
cy: cy,
|
|
rx: rx,
|
|
ry: ry
|
|
},
|
|
element.styles
|
|
)
|
|
);
|
|
};
|
|
|
|
var IMAGE_FIT_STYLE = {
|
|
contain: 'xMidYMid meet',
|
|
cover: 'xMidYMid slice'
|
|
};
|
|
|
|
var updateImage = function updateImage(element, markup) {
|
|
setAttributes(
|
|
element,
|
|
Object.assign({}, element.rect, element.styles, {
|
|
preserveAspectRatio: IMAGE_FIT_STYLE[markup.fit] || 'none'
|
|
})
|
|
);
|
|
};
|
|
|
|
var TEXT_ANCHOR = {
|
|
left: 'start',
|
|
center: 'middle',
|
|
right: 'end'
|
|
};
|
|
|
|
var updateText = function updateText(element, markup, size, scale) {
|
|
var fontSize = getMarkupValue(markup.fontSize, size, scale);
|
|
var fontFamily = markup.fontFamily || 'sans-serif';
|
|
var fontWeight = markup.fontWeight || 'normal';
|
|
var textAlign = TEXT_ANCHOR[markup.textAlign] || 'start';
|
|
|
|
setAttributes(
|
|
element,
|
|
Object.assign({}, element.rect, element.styles, {
|
|
'stroke-width': 0,
|
|
'font-weight': fontWeight,
|
|
'font-size': fontSize,
|
|
'font-family': fontFamily,
|
|
'text-anchor': textAlign
|
|
})
|
|
);
|
|
|
|
// update text
|
|
if (element.text !== markup.text) {
|
|
element.text = markup.text;
|
|
element.textContent = markup.text.length ? markup.text : ' ';
|
|
}
|
|
};
|
|
|
|
var updateLine = function updateLine(element, markup, size, scale) {
|
|
setAttributes(
|
|
element,
|
|
Object.assign({}, element.rect, element.styles, {
|
|
fill: 'none'
|
|
})
|
|
);
|
|
|
|
var line = element.childNodes[0];
|
|
var begin = element.childNodes[1];
|
|
var end = element.childNodes[2];
|
|
|
|
var origin = element.rect;
|
|
|
|
var target = {
|
|
x: element.rect.x + element.rect.width,
|
|
y: element.rect.y + element.rect.height
|
|
};
|
|
|
|
setAttributes(line, {
|
|
x1: origin.x,
|
|
y1: origin.y,
|
|
x2: target.x,
|
|
y2: target.y
|
|
});
|
|
|
|
if (!markup.lineDecoration) return;
|
|
|
|
begin.style.display = 'none';
|
|
end.style.display = 'none';
|
|
|
|
var v = vectorNormalize({
|
|
x: target.x - origin.x,
|
|
y: target.y - origin.y
|
|
});
|
|
|
|
var l = getMarkupValue(0.05, size, scale);
|
|
|
|
if (markup.lineDecoration.indexOf('arrow-begin') !== -1) {
|
|
var arrowBeginRotationPoint = vectorMultiply(v, l);
|
|
var arrowBeginCenter = vectorAdd(origin, arrowBeginRotationPoint);
|
|
var arrowBeginA = vectorRotate(origin, 2, arrowBeginCenter);
|
|
var arrowBeginB = vectorRotate(origin, -2, arrowBeginCenter);
|
|
|
|
setAttributes(begin, {
|
|
style: 'display:block;',
|
|
d: 'M'
|
|
.concat(arrowBeginA.x, ',')
|
|
.concat(arrowBeginA.y, ' L')
|
|
.concat(origin.x, ',')
|
|
.concat(origin.y, ' L')
|
|
.concat(arrowBeginB.x, ',')
|
|
.concat(arrowBeginB.y)
|
|
});
|
|
}
|
|
|
|
if (markup.lineDecoration.indexOf('arrow-end') !== -1) {
|
|
var arrowEndRotationPoint = vectorMultiply(v, -l);
|
|
var arrowEndCenter = vectorAdd(target, arrowEndRotationPoint);
|
|
var arrowEndA = vectorRotate(target, 2, arrowEndCenter);
|
|
var arrowEndB = vectorRotate(target, -2, arrowEndCenter);
|
|
|
|
setAttributes(end, {
|
|
style: 'display:block;',
|
|
d: 'M'
|
|
.concat(arrowEndA.x, ',')
|
|
.concat(arrowEndA.y, ' L')
|
|
.concat(target.x, ',')
|
|
.concat(target.y, ' L')
|
|
.concat(arrowEndB.x, ',')
|
|
.concat(arrowEndB.y)
|
|
});
|
|
}
|
|
};
|
|
|
|
var updatePath = function updatePath(element, markup, size, scale) {
|
|
setAttributes(
|
|
element,
|
|
Object.assign({}, element.styles, {
|
|
fill: 'none',
|
|
d: pointsToPathShape(
|
|
markup.points.map(function(point) {
|
|
return {
|
|
x: getMarkupValue(point.x, size, scale, 'width'),
|
|
y: getMarkupValue(point.y, size, scale, 'height')
|
|
};
|
|
})
|
|
)
|
|
})
|
|
);
|
|
};
|
|
|
|
var createShape = function createShape(node) {
|
|
return function(markup) {
|
|
return svg(node, { id: markup.id });
|
|
};
|
|
};
|
|
|
|
var createImage = function createImage(markup) {
|
|
var shape = svg('image', {
|
|
id: markup.id,
|
|
'stroke-linecap': 'round',
|
|
'stroke-linejoin': 'round',
|
|
opacity: '0'
|
|
});
|
|
|
|
shape.onload = function() {
|
|
shape.setAttribute('opacity', markup.opacity || 1);
|
|
};
|
|
shape.setAttributeNS(
|
|
'http://www.w3.org/1999/xlink',
|
|
'xlink:href',
|
|
markup.src
|
|
);
|
|
return shape;
|
|
};
|
|
|
|
var createLine = function createLine(markup) {
|
|
var shape = svg('g', {
|
|
id: markup.id,
|
|
'stroke-linecap': 'round',
|
|
'stroke-linejoin': 'round'
|
|
});
|
|
|
|
var line = svg('line');
|
|
shape.appendChild(line);
|
|
|
|
var begin = svg('path');
|
|
shape.appendChild(begin);
|
|
|
|
var end = svg('path');
|
|
shape.appendChild(end);
|
|
|
|
return shape;
|
|
};
|
|
|
|
var CREATE_TYPE_ROUTES = {
|
|
image: createImage,
|
|
rect: createShape('rect'),
|
|
ellipse: createShape('ellipse'),
|
|
text: createShape('text'),
|
|
path: createShape('path'),
|
|
line: createLine
|
|
};
|
|
|
|
var UPDATE_TYPE_ROUTES = {
|
|
rect: updateRect,
|
|
ellipse: updateEllipse,
|
|
image: updateImage,
|
|
text: updateText,
|
|
path: updatePath,
|
|
line: updateLine
|
|
};
|
|
|
|
var createMarkupByType = function createMarkupByType(type, markup) {
|
|
return CREATE_TYPE_ROUTES[type](markup);
|
|
};
|
|
|
|
var updateMarkupByType = function updateMarkupByType(
|
|
element,
|
|
type,
|
|
markup,
|
|
size,
|
|
scale
|
|
) {
|
|
if (type !== 'path') {
|
|
element.rect = getMarkupRect(markup, size, scale);
|
|
}
|
|
element.styles = getMarkupStyles(markup, size, scale);
|
|
UPDATE_TYPE_ROUTES[type](element, markup, size, scale);
|
|
};
|
|
|
|
var MARKUP_RECT = [
|
|
'x',
|
|
'y',
|
|
'left',
|
|
'top',
|
|
'right',
|
|
'bottom',
|
|
'width',
|
|
'height'
|
|
];
|
|
|
|
var toOptionalFraction = function toOptionalFraction(value) {
|
|
return typeof value === 'string' && /%/.test(value)
|
|
? parseFloat(value) / 100
|
|
: value;
|
|
};
|
|
|
|
// adds default markup properties, clones markup
|
|
var prepareMarkup = function prepareMarkup(markup) {
|
|
var _markup = _slicedToArray(markup, 2),
|
|
type = _markup[0],
|
|
props = _markup[1];
|
|
|
|
var rect = props.points
|
|
? {}
|
|
: MARKUP_RECT.reduce(function(prev, curr) {
|
|
prev[curr] = toOptionalFraction(props[curr]);
|
|
return prev;
|
|
}, {});
|
|
|
|
return [
|
|
type,
|
|
Object.assign(
|
|
{
|
|
zIndex: 0
|
|
},
|
|
props,
|
|
rect
|
|
)
|
|
];
|
|
};
|
|
|
|
var sortMarkupByZIndex = function sortMarkupByZIndex(a, b) {
|
|
if (a[1].zIndex > b[1].zIndex) {
|
|
return 1;
|
|
}
|
|
if (a[1].zIndex < b[1].zIndex) {
|
|
return -1;
|
|
}
|
|
return 0;
|
|
};
|
|
|
|
var createMarkupView = function createMarkupView(_) {
|
|
return _.utils.createView({
|
|
name: 'image-preview-markup',
|
|
tag: 'svg',
|
|
ignoreRect: true,
|
|
mixins: {
|
|
apis: ['width', 'height', 'crop', 'markup', 'resize', 'dirty']
|
|
},
|
|
|
|
write: function write(_ref) {
|
|
var root = _ref.root,
|
|
props = _ref.props;
|
|
|
|
if (!props.dirty) return;
|
|
var crop = props.crop,
|
|
resize = props.resize,
|
|
markup = props.markup;
|
|
|
|
var viewWidth = props.width;
|
|
var viewHeight = props.height;
|
|
|
|
var cropWidth = crop.width;
|
|
var cropHeight = crop.height;
|
|
|
|
if (resize) {
|
|
var _size = resize.size;
|
|
|
|
var outputWidth = _size && _size.width;
|
|
var outputHeight = _size && _size.height;
|
|
var outputFit = resize.mode;
|
|
var outputUpscale = resize.upscale;
|
|
|
|
if (outputWidth && !outputHeight) outputHeight = outputWidth;
|
|
if (outputHeight && !outputWidth) outputWidth = outputHeight;
|
|
|
|
var shouldUpscale =
|
|
cropWidth < outputWidth && cropHeight < outputHeight;
|
|
|
|
if (!shouldUpscale || (shouldUpscale && outputUpscale)) {
|
|
var scalarWidth = outputWidth / cropWidth;
|
|
var scalarHeight = outputHeight / cropHeight;
|
|
|
|
if (outputFit === 'force') {
|
|
cropWidth = outputWidth;
|
|
cropHeight = outputHeight;
|
|
} else {
|
|
var scalar;
|
|
if (outputFit === 'cover') {
|
|
scalar = Math.max(scalarWidth, scalarHeight);
|
|
} else if (outputFit === 'contain') {
|
|
scalar = Math.min(scalarWidth, scalarHeight);
|
|
}
|
|
cropWidth = cropWidth * scalar;
|
|
cropHeight = cropHeight * scalar;
|
|
}
|
|
}
|
|
}
|
|
|
|
var size = {
|
|
width: viewWidth,
|
|
height: viewHeight
|
|
};
|
|
|
|
root.element.setAttribute('width', size.width);
|
|
root.element.setAttribute('height', size.height);
|
|
|
|
var scale = Math.min(viewWidth / cropWidth, viewHeight / cropHeight);
|
|
|
|
// clear
|
|
root.element.innerHTML = '';
|
|
|
|
// get filter
|
|
var markupFilter = root.query('GET_IMAGE_PREVIEW_MARKUP_FILTER');
|
|
|
|
// draw new
|
|
markup
|
|
.filter(markupFilter)
|
|
.map(prepareMarkup)
|
|
.sort(sortMarkupByZIndex)
|
|
.forEach(function(markup) {
|
|
var _markup = _slicedToArray(markup, 2),
|
|
type = _markup[0],
|
|
settings = _markup[1];
|
|
|
|
// create
|
|
var element = createMarkupByType(type, settings);
|
|
|
|
// update
|
|
updateMarkupByType(element, type, settings, size, scale);
|
|
|
|
// add
|
|
root.element.appendChild(element);
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
var createVector$1 = function createVector(x, y) {
|
|
return { x: x, y: y };
|
|
};
|
|
|
|
var vectorDot = function vectorDot(a, b) {
|
|
return a.x * b.x + a.y * b.y;
|
|
};
|
|
|
|
var vectorSubtract = function vectorSubtract(a, b) {
|
|
return createVector$1(a.x - b.x, a.y - b.y);
|
|
};
|
|
|
|
var vectorDistanceSquared = function vectorDistanceSquared(a, b) {
|
|
return vectorDot(vectorSubtract(a, b), vectorSubtract(a, b));
|
|
};
|
|
|
|
var vectorDistance = function vectorDistance(a, b) {
|
|
return Math.sqrt(vectorDistanceSquared(a, b));
|
|
};
|
|
|
|
var getOffsetPointOnEdge = function getOffsetPointOnEdge(length, rotation) {
|
|
var a = length;
|
|
|
|
var A = 1.5707963267948966;
|
|
var B = rotation;
|
|
var C = 1.5707963267948966 - rotation;
|
|
|
|
var sinA = Math.sin(A);
|
|
var sinB = Math.sin(B);
|
|
var sinC = Math.sin(C);
|
|
var cosC = Math.cos(C);
|
|
var ratio = a / sinA;
|
|
var b = ratio * sinB;
|
|
var c = ratio * sinC;
|
|
|
|
return createVector$1(cosC * b, cosC * c);
|
|
};
|
|
|
|
var getRotatedRectSize = function getRotatedRectSize(rect, rotation) {
|
|
var w = rect.width;
|
|
var h = rect.height;
|
|
|
|
var hor = getOffsetPointOnEdge(w, rotation);
|
|
var ver = getOffsetPointOnEdge(h, rotation);
|
|
|
|
var tl = createVector$1(rect.x + Math.abs(hor.x), rect.y - Math.abs(hor.y));
|
|
|
|
var tr = createVector$1(
|
|
rect.x + rect.width + Math.abs(ver.y),
|
|
rect.y + Math.abs(ver.x)
|
|
);
|
|
|
|
var bl = createVector$1(
|
|
rect.x - Math.abs(ver.y),
|
|
rect.y + rect.height - Math.abs(ver.x)
|
|
);
|
|
|
|
return {
|
|
width: vectorDistance(tl, tr),
|
|
height: vectorDistance(tl, bl)
|
|
};
|
|
};
|
|
|
|
var calculateCanvasSize = function calculateCanvasSize(
|
|
image,
|
|
canvasAspectRatio
|
|
) {
|
|
var zoom =
|
|
arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 1;
|
|
|
|
var imageAspectRatio = image.height / image.width;
|
|
|
|
// determine actual pixels on x and y axis
|
|
var canvasWidth = 1;
|
|
var canvasHeight = canvasAspectRatio;
|
|
var imgWidth = 1;
|
|
var imgHeight = imageAspectRatio;
|
|
if (imgHeight > canvasHeight) {
|
|
imgHeight = canvasHeight;
|
|
imgWidth = imgHeight / imageAspectRatio;
|
|
}
|
|
|
|
var scalar = Math.max(canvasWidth / imgWidth, canvasHeight / imgHeight);
|
|
var width = image.width / (zoom * scalar * imgWidth);
|
|
var height = width * canvasAspectRatio;
|
|
|
|
return {
|
|
width: width,
|
|
height: height
|
|
};
|
|
};
|
|
|
|
var getImageRectZoomFactor = function getImageRectZoomFactor(
|
|
imageRect,
|
|
cropRect,
|
|
rotation,
|
|
center
|
|
) {
|
|
// calculate available space round image center position
|
|
var cx = center.x > 0.5 ? 1 - center.x : center.x;
|
|
var cy = center.y > 0.5 ? 1 - center.y : center.y;
|
|
var imageWidth = cx * 2 * imageRect.width;
|
|
var imageHeight = cy * 2 * imageRect.height;
|
|
|
|
// calculate rotated crop rectangle size
|
|
var rotatedCropSize = getRotatedRectSize(cropRect, rotation);
|
|
|
|
// calculate scalar required to fit image
|
|
return Math.max(
|
|
rotatedCropSize.width / imageWidth,
|
|
rotatedCropSize.height / imageHeight
|
|
);
|
|
};
|
|
|
|
var getCenteredCropRect = function getCenteredCropRect(
|
|
container,
|
|
aspectRatio
|
|
) {
|
|
var width = container.width;
|
|
var height = width * aspectRatio;
|
|
if (height > container.height) {
|
|
height = container.height;
|
|
width = height / aspectRatio;
|
|
}
|
|
var x = (container.width - width) * 0.5;
|
|
var y = (container.height - height) * 0.5;
|
|
|
|
return {
|
|
x: x,
|
|
y: y,
|
|
width: width,
|
|
height: height
|
|
};
|
|
};
|
|
|
|
var getCurrentCropSize = function getCurrentCropSize(imageSize) {
|
|
var crop =
|
|
arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
|
|
var zoom = crop.zoom,
|
|
rotation = crop.rotation,
|
|
center = crop.center,
|
|
aspectRatio = crop.aspectRatio;
|
|
|
|
if (!aspectRatio) aspectRatio = imageSize.height / imageSize.width;
|
|
|
|
var canvasSize = calculateCanvasSize(imageSize, aspectRatio, zoom);
|
|
|
|
var canvasCenter = {
|
|
x: canvasSize.width * 0.5,
|
|
y: canvasSize.height * 0.5
|
|
};
|
|
|
|
var stage = {
|
|
x: 0,
|
|
y: 0,
|
|
width: canvasSize.width,
|
|
height: canvasSize.height,
|
|
center: canvasCenter
|
|
};
|
|
|
|
var shouldLimit = typeof crop.scaleToFit === 'undefined' || crop.scaleToFit;
|
|
|
|
var stageZoomFactor = getImageRectZoomFactor(
|
|
imageSize,
|
|
getCenteredCropRect(stage, aspectRatio),
|
|
rotation,
|
|
shouldLimit ? center : { x: 0.5, y: 0.5 }
|
|
);
|
|
|
|
var scale = zoom * stageZoomFactor;
|
|
|
|
// start drawing
|
|
return {
|
|
widthFloat: canvasSize.width / scale,
|
|
heightFloat: canvasSize.height / scale,
|
|
width: Math.round(canvasSize.width / scale),
|
|
height: Math.round(canvasSize.height / scale)
|
|
};
|
|
};
|
|
|
|
var IMAGE_SCALE_SPRING_PROPS = {
|
|
type: 'spring',
|
|
stiffness: 0.5,
|
|
damping: 0.45,
|
|
mass: 10
|
|
};
|
|
|
|
// does horizontal and vertical flipping
|
|
var createBitmapView = function createBitmapView(_) {
|
|
return _.utils.createView({
|
|
name: 'image-bitmap',
|
|
ignoreRect: true,
|
|
mixins: { styles: ['scaleX', 'scaleY'] },
|
|
create: function create(_ref) {
|
|
var root = _ref.root,
|
|
props = _ref.props;
|
|
root.appendChild(props.image);
|
|
}
|
|
});
|
|
};
|
|
|
|
// shifts and rotates image
|
|
var createImageCanvasWrapper = function createImageCanvasWrapper(_) {
|
|
return _.utils.createView({
|
|
name: 'image-canvas-wrapper',
|
|
tag: 'div',
|
|
ignoreRect: true,
|
|
mixins: {
|
|
apis: ['crop', 'width', 'height'],
|
|
|
|
styles: [
|
|
'originX',
|
|
'originY',
|
|
'translateX',
|
|
'translateY',
|
|
'scaleX',
|
|
'scaleY',
|
|
'rotateZ'
|
|
],
|
|
|
|
animations: {
|
|
originX: IMAGE_SCALE_SPRING_PROPS,
|
|
originY: IMAGE_SCALE_SPRING_PROPS,
|
|
scaleX: IMAGE_SCALE_SPRING_PROPS,
|
|
scaleY: IMAGE_SCALE_SPRING_PROPS,
|
|
translateX: IMAGE_SCALE_SPRING_PROPS,
|
|
translateY: IMAGE_SCALE_SPRING_PROPS,
|
|
rotateZ: IMAGE_SCALE_SPRING_PROPS
|
|
}
|
|
},
|
|
|
|
create: function create(_ref2) {
|
|
var root = _ref2.root,
|
|
props = _ref2.props;
|
|
props.width = props.image.width;
|
|
props.height = props.image.height;
|
|
root.ref.bitmap = root.appendChildView(
|
|
root.createChildView(createBitmapView(_), { image: props.image })
|
|
);
|
|
},
|
|
write: function write(_ref3) {
|
|
var root = _ref3.root,
|
|
props = _ref3.props;
|
|
var flip = props.crop.flip;
|
|
var bitmap = root.ref.bitmap;
|
|
bitmap.scaleX = flip.horizontal ? -1 : 1;
|
|
bitmap.scaleY = flip.vertical ? -1 : 1;
|
|
}
|
|
});
|
|
};
|
|
|
|
// clips canvas to correct aspect ratio
|
|
var createClipView = function createClipView(_) {
|
|
return _.utils.createView({
|
|
name: 'image-clip',
|
|
tag: 'div',
|
|
ignoreRect: true,
|
|
mixins: {
|
|
apis: [
|
|
'crop',
|
|
'markup',
|
|
'resize',
|
|
'width',
|
|
'height',
|
|
'dirty',
|
|
'background'
|
|
],
|
|
|
|
styles: ['width', 'height', 'opacity'],
|
|
animations: {
|
|
opacity: { type: 'tween', duration: 250 }
|
|
}
|
|
},
|
|
|
|
didWriteView: function didWriteView(_ref4) {
|
|
var root = _ref4.root,
|
|
props = _ref4.props;
|
|
if (!props.background) return;
|
|
root.element.style.backgroundColor = props.background;
|
|
},
|
|
create: function create(_ref5) {
|
|
var root = _ref5.root,
|
|
props = _ref5.props;
|
|
|
|
root.ref.image = root.appendChildView(
|
|
root.createChildView(
|
|
createImageCanvasWrapper(_),
|
|
Object.assign({}, props)
|
|
)
|
|
);
|
|
|
|
root.ref.createMarkup = function() {
|
|
if (root.ref.markup) return;
|
|
root.ref.markup = root.appendChildView(
|
|
root.createChildView(createMarkupView(_), Object.assign({}, props))
|
|
);
|
|
};
|
|
|
|
root.ref.destroyMarkup = function() {
|
|
if (!root.ref.markup) return;
|
|
root.removeChildView(root.ref.markup);
|
|
root.ref.markup = null;
|
|
};
|
|
|
|
// set up transparency grid
|
|
var transparencyIndicator = root.query(
|
|
'GET_IMAGE_PREVIEW_TRANSPARENCY_INDICATOR'
|
|
);
|
|
if (transparencyIndicator === null) return;
|
|
|
|
// grid pattern
|
|
if (transparencyIndicator === 'grid') {
|
|
root.element.dataset.transparencyIndicator = transparencyIndicator;
|
|
}
|
|
// basic color
|
|
else {
|
|
root.element.dataset.transparencyIndicator = 'color';
|
|
}
|
|
},
|
|
write: function write(_ref6) {
|
|
var root = _ref6.root,
|
|
props = _ref6.props,
|
|
shouldOptimize = _ref6.shouldOptimize;
|
|
var crop = props.crop,
|
|
markup = props.markup,
|
|
resize = props.resize,
|
|
dirty = props.dirty,
|
|
width = props.width,
|
|
height = props.height;
|
|
|
|
root.ref.image.crop = crop;
|
|
|
|
var stage = {
|
|
x: 0,
|
|
y: 0,
|
|
width: width,
|
|
height: height,
|
|
center: {
|
|
x: width * 0.5,
|
|
y: height * 0.5
|
|
}
|
|
};
|
|
|
|
var image = {
|
|
width: root.ref.image.width,
|
|
height: root.ref.image.height
|
|
};
|
|
|
|
var origin = {
|
|
x: crop.center.x * image.width,
|
|
y: crop.center.y * image.height
|
|
};
|
|
|
|
var translation = {
|
|
x: stage.center.x - image.width * crop.center.x,
|
|
y: stage.center.y - image.height * crop.center.y
|
|
};
|
|
|
|
var rotation = Math.PI * 2 + (crop.rotation % (Math.PI * 2));
|
|
|
|
var cropAspectRatio = crop.aspectRatio || image.height / image.width;
|
|
|
|
var shouldLimit =
|
|
typeof crop.scaleToFit === 'undefined' || crop.scaleToFit;
|
|
|
|
var stageZoomFactor = getImageRectZoomFactor(
|
|
image,
|
|
getCenteredCropRect(stage, cropAspectRatio),
|
|
|
|
rotation,
|
|
shouldLimit ? crop.center : { x: 0.5, y: 0.5 }
|
|
);
|
|
|
|
var scale = crop.zoom * stageZoomFactor;
|
|
|
|
// update markup view
|
|
if (markup && markup.length) {
|
|
root.ref.createMarkup();
|
|
root.ref.markup.width = width;
|
|
root.ref.markup.height = height;
|
|
root.ref.markup.resize = resize;
|
|
root.ref.markup.dirty = dirty;
|
|
root.ref.markup.markup = markup;
|
|
root.ref.markup.crop = getCurrentCropSize(image, crop);
|
|
} else if (root.ref.markup) {
|
|
root.ref.destroyMarkup();
|
|
}
|
|
|
|
// update image view
|
|
var imageView = root.ref.image;
|
|
|
|
// don't update clip layout
|
|
if (shouldOptimize) {
|
|
imageView.originX = null;
|
|
imageView.originY = null;
|
|
imageView.translateX = null;
|
|
imageView.translateY = null;
|
|
imageView.rotateZ = null;
|
|
imageView.scaleX = null;
|
|
imageView.scaleY = null;
|
|
return;
|
|
}
|
|
|
|
imageView.originX = origin.x;
|
|
imageView.originY = origin.y;
|
|
imageView.translateX = translation.x;
|
|
imageView.translateY = translation.y;
|
|
imageView.rotateZ = rotation;
|
|
imageView.scaleX = scale;
|
|
imageView.scaleY = scale;
|
|
}
|
|
});
|
|
};
|
|
|
|
var createImageView = function createImageView(_) {
|
|
return _.utils.createView({
|
|
name: 'image-preview',
|
|
tag: 'div',
|
|
ignoreRect: true,
|
|
mixins: {
|
|
apis: ['image', 'crop', 'markup', 'resize', 'dirty', 'background'],
|
|
|
|
styles: ['translateY', 'scaleX', 'scaleY', 'opacity'],
|
|
|
|
animations: {
|
|
scaleX: IMAGE_SCALE_SPRING_PROPS,
|
|
scaleY: IMAGE_SCALE_SPRING_PROPS,
|
|
translateY: IMAGE_SCALE_SPRING_PROPS,
|
|
opacity: { type: 'tween', duration: 400 }
|
|
}
|
|
},
|
|
|
|
create: function create(_ref7) {
|
|
var root = _ref7.root,
|
|
props = _ref7.props;
|
|
root.ref.clip = root.appendChildView(
|
|
root.createChildView(createClipView(_), {
|
|
id: props.id,
|
|
image: props.image,
|
|
crop: props.crop,
|
|
markup: props.markup,
|
|
resize: props.resize,
|
|
dirty: props.dirty,
|
|
background: props.background
|
|
})
|
|
);
|
|
},
|
|
write: function write(_ref8) {
|
|
var root = _ref8.root,
|
|
props = _ref8.props,
|
|
shouldOptimize = _ref8.shouldOptimize;
|
|
var clip = root.ref.clip;
|
|
var image = props.image,
|
|
crop = props.crop,
|
|
markup = props.markup,
|
|
resize = props.resize,
|
|
dirty = props.dirty;
|
|
|
|
clip.crop = crop;
|
|
clip.markup = markup;
|
|
clip.resize = resize;
|
|
clip.dirty = dirty;
|
|
|
|
// don't update clip layout
|
|
clip.opacity = shouldOptimize ? 0 : 1;
|
|
|
|
// don't re-render if optimizing or hidden (width will be zero resulting in weird animations)
|
|
if (shouldOptimize || root.rect.element.hidden) return;
|
|
|
|
// calculate scaled preview image size
|
|
var imageAspectRatio = image.height / image.width;
|
|
var aspectRatio = crop.aspectRatio || imageAspectRatio;
|
|
|
|
// calculate container size
|
|
var containerWidth = root.rect.inner.width;
|
|
var containerHeight = root.rect.inner.height;
|
|
|
|
var fixedPreviewHeight = root.query('GET_IMAGE_PREVIEW_HEIGHT');
|
|
var minPreviewHeight = root.query('GET_IMAGE_PREVIEW_MIN_HEIGHT');
|
|
var maxPreviewHeight = root.query('GET_IMAGE_PREVIEW_MAX_HEIGHT');
|
|
|
|
var panelAspectRatio = root.query('GET_PANEL_ASPECT_RATIO');
|
|
var allowMultiple = root.query('GET_ALLOW_MULTIPLE');
|
|
|
|
if (panelAspectRatio && !allowMultiple) {
|
|
fixedPreviewHeight = containerWidth * panelAspectRatio;
|
|
aspectRatio = panelAspectRatio;
|
|
}
|
|
|
|
// determine clip width and height
|
|
var clipHeight =
|
|
fixedPreviewHeight !== null
|
|
? fixedPreviewHeight
|
|
: Math.max(
|
|
minPreviewHeight,
|
|
Math.min(containerWidth * aspectRatio, maxPreviewHeight)
|
|
);
|
|
|
|
var clipWidth = clipHeight / aspectRatio;
|
|
if (clipWidth > containerWidth) {
|
|
clipWidth = containerWidth;
|
|
clipHeight = clipWidth * aspectRatio;
|
|
}
|
|
|
|
if (clipHeight > containerHeight) {
|
|
clipHeight = containerHeight;
|
|
clipWidth = containerHeight / aspectRatio;
|
|
}
|
|
|
|
clip.width = clipWidth;
|
|
clip.height = clipHeight;
|
|
}
|
|
});
|
|
};
|
|
|
|
var SVG_MASK =
|
|
'<svg width="500" height="200" viewBox="0 0 500 200" preserveAspectRatio="none">\n <defs>\n <radialGradient id="gradient-__UID__" cx=".5" cy="1.25" r="1.15">\n <stop offset=\'50%\' stop-color=\'#000000\'/>\n <stop offset=\'56%\' stop-color=\'#0a0a0a\'/>\n <stop offset=\'63%\' stop-color=\'#262626\'/>\n <stop offset=\'69%\' stop-color=\'#4f4f4f\'/>\n <stop offset=\'75%\' stop-color=\'#808080\'/>\n <stop offset=\'81%\' stop-color=\'#b1b1b1\'/>\n <stop offset=\'88%\' stop-color=\'#dadada\'/>\n <stop offset=\'94%\' stop-color=\'#f6f6f6\'/>\n <stop offset=\'100%\' stop-color=\'#ffffff\'/>\n </radialGradient>\n <mask id="mask-__UID__">\n <rect x="0" y="0" width="500" height="200" fill="url(#gradient-__UID__)"></rect>\n </mask>\n </defs>\n <rect x="0" width="500" height="200" fill="currentColor" mask="url(#mask-__UID__)"></rect>\n</svg>';
|
|
|
|
var SVGMaskUniqueId = 0;
|
|
|
|
var createImageOverlayView = function createImageOverlayView(fpAPI) {
|
|
return fpAPI.utils.createView({
|
|
name: 'image-preview-overlay',
|
|
tag: 'div',
|
|
ignoreRect: true,
|
|
create: function create(_ref) {
|
|
var root = _ref.root,
|
|
props = _ref.props;
|
|
var mask = SVG_MASK;
|
|
if (document.querySelector('base')) {
|
|
var url = new URL(
|
|
window.location.href.replace(window.location.hash, '')
|
|
).href;
|
|
mask = mask.replace(/url\(\#/g, 'url(' + url + '#');
|
|
}
|
|
|
|
SVGMaskUniqueId++;
|
|
root.element.classList.add(
|
|
'filepond--image-preview-overlay-'.concat(props.status)
|
|
);
|
|
|
|
root.element.innerHTML = mask.replace(/__UID__/g, SVGMaskUniqueId);
|
|
},
|
|
mixins: {
|
|
styles: ['opacity'],
|
|
animations: {
|
|
opacity: { type: 'spring', mass: 25 }
|
|
}
|
|
}
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Bitmap Worker
|
|
*/
|
|
var BitmapWorker = function BitmapWorker() {
|
|
self.onmessage = function(e) {
|
|
createImageBitmap(e.data.message.file).then(function(bitmap) {
|
|
self.postMessage({ id: e.data.id, message: bitmap }, [bitmap]);
|
|
});
|
|
};
|
|
};
|
|
|
|
/**
|
|
* ColorMatrix Worker
|
|
*/
|
|
var ColorMatrixWorker = function ColorMatrixWorker() {
|
|
self.onmessage = function(e) {
|
|
var imageData = e.data.message.imageData;
|
|
var matrix = e.data.message.colorMatrix;
|
|
|
|
var data = imageData.data;
|
|
var l = data.length;
|
|
|
|
var m11 = matrix[0];
|
|
var m12 = matrix[1];
|
|
var m13 = matrix[2];
|
|
var m14 = matrix[3];
|
|
var m15 = matrix[4];
|
|
|
|
var m21 = matrix[5];
|
|
var m22 = matrix[6];
|
|
var m23 = matrix[7];
|
|
var m24 = matrix[8];
|
|
var m25 = matrix[9];
|
|
|
|
var m31 = matrix[10];
|
|
var m32 = matrix[11];
|
|
var m33 = matrix[12];
|
|
var m34 = matrix[13];
|
|
var m35 = matrix[14];
|
|
|
|
var m41 = matrix[15];
|
|
var m42 = matrix[16];
|
|
var m43 = matrix[17];
|
|
var m44 = matrix[18];
|
|
var m45 = matrix[19];
|
|
|
|
var index = 0,
|
|
r = 0.0,
|
|
g = 0.0,
|
|
b = 0.0,
|
|
a = 0.0;
|
|
|
|
for (; index < l; index += 4) {
|
|
r = data[index] / 255;
|
|
g = data[index + 1] / 255;
|
|
b = data[index + 2] / 255;
|
|
a = data[index + 3] / 255;
|
|
data[index] = Math.max(
|
|
0,
|
|
Math.min((r * m11 + g * m12 + b * m13 + a * m14 + m15) * 255, 255)
|
|
);
|
|
data[index + 1] = Math.max(
|
|
0,
|
|
Math.min((r * m21 + g * m22 + b * m23 + a * m24 + m25) * 255, 255)
|
|
);
|
|
data[index + 2] = Math.max(
|
|
0,
|
|
Math.min((r * m31 + g * m32 + b * m33 + a * m34 + m35) * 255, 255)
|
|
);
|
|
data[index + 3] = Math.max(
|
|
0,
|
|
Math.min((r * m41 + g * m42 + b * m43 + a * m44 + m45) * 255, 255)
|
|
);
|
|
}
|
|
|
|
self.postMessage({ id: e.data.id, message: imageData }, [
|
|
imageData.data.buffer
|
|
]);
|
|
};
|
|
};
|
|
|
|
var getImageSize = function getImageSize(url, cb) {
|
|
var image = new Image();
|
|
image.onload = function() {
|
|
var width = image.naturalWidth;
|
|
var height = image.naturalHeight;
|
|
image = null;
|
|
cb(width, height);
|
|
};
|
|
image.src = url;
|
|
};
|
|
|
|
var transforms = {
|
|
1: function _() {
|
|
return [1, 0, 0, 1, 0, 0];
|
|
},
|
|
2: function _(width) {
|
|
return [-1, 0, 0, 1, width, 0];
|
|
},
|
|
3: function _(width, height) {
|
|
return [-1, 0, 0, -1, width, height];
|
|
},
|
|
4: function _(width, height) {
|
|
return [1, 0, 0, -1, 0, height];
|
|
},
|
|
5: function _() {
|
|
return [0, 1, 1, 0, 0, 0];
|
|
},
|
|
6: function _(width, height) {
|
|
return [0, 1, -1, 0, height, 0];
|
|
},
|
|
7: function _(width, height) {
|
|
return [0, -1, -1, 0, height, width];
|
|
},
|
|
8: function _(width) {
|
|
return [0, -1, 1, 0, 0, width];
|
|
}
|
|
};
|
|
|
|
var fixImageOrientation = function fixImageOrientation(
|
|
ctx,
|
|
width,
|
|
height,
|
|
orientation
|
|
) {
|
|
// no orientation supplied
|
|
if (orientation === -1) {
|
|
return;
|
|
}
|
|
|
|
ctx.transform.apply(ctx, transforms[orientation](width, height));
|
|
};
|
|
|
|
// draws the preview image to canvas
|
|
var createPreviewImage = function createPreviewImage(
|
|
data,
|
|
width,
|
|
height,
|
|
orientation
|
|
) {
|
|
// can't draw on half pixels
|
|
width = Math.round(width);
|
|
height = Math.round(height);
|
|
|
|
// draw image
|
|
var canvas = document.createElement('canvas');
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
var ctx = canvas.getContext('2d');
|
|
|
|
// if is rotated incorrectly swap width and height
|
|
if (orientation >= 5 && orientation <= 8) {
|
|
var _ref = [height, width];
|
|
width = _ref[0];
|
|
height = _ref[1];
|
|
}
|
|
|
|
// correct image orientation
|
|
fixImageOrientation(ctx, width, height, orientation);
|
|
|
|
// draw the image
|
|
ctx.drawImage(data, 0, 0, width, height);
|
|
|
|
return canvas;
|
|
};
|
|
|
|
var isBitmap = function isBitmap(file) {
|
|
return /^image/.test(file.type) && !/svg/.test(file.type);
|
|
};
|
|
|
|
var MAX_WIDTH = 10;
|
|
var MAX_HEIGHT = 10;
|
|
|
|
var calculateAverageColor = function calculateAverageColor(image) {
|
|
var scalar = Math.min(MAX_WIDTH / image.width, MAX_HEIGHT / image.height);
|
|
|
|
var canvas = document.createElement('canvas');
|
|
var ctx = canvas.getContext('2d');
|
|
var width = (canvas.width = Math.ceil(image.width * scalar));
|
|
var height = (canvas.height = Math.ceil(image.height * scalar));
|
|
ctx.drawImage(image, 0, 0, width, height);
|
|
var data = null;
|
|
try {
|
|
data = ctx.getImageData(0, 0, width, height).data;
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
var l = data.length;
|
|
|
|
var r = 0;
|
|
var g = 0;
|
|
var b = 0;
|
|
var i = 0;
|
|
|
|
for (; i < l; i += 4) {
|
|
r += data[i] * data[i];
|
|
g += data[i + 1] * data[i + 1];
|
|
b += data[i + 2] * data[i + 2];
|
|
}
|
|
|
|
r = averageColor(r, l);
|
|
g = averageColor(g, l);
|
|
b = averageColor(b, l);
|
|
|
|
return { r: r, g: g, b: b };
|
|
};
|
|
|
|
var averageColor = function averageColor(c, l) {
|
|
return Math.floor(Math.sqrt(c / (l / 4)));
|
|
};
|
|
|
|
var cloneCanvas = function cloneCanvas(origin, target) {
|
|
target = target || document.createElement('canvas');
|
|
target.width = origin.width;
|
|
target.height = origin.height;
|
|
var ctx = target.getContext('2d');
|
|
ctx.drawImage(origin, 0, 0);
|
|
return target;
|
|
};
|
|
|
|
var cloneImageData = function cloneImageData(imageData) {
|
|
var id;
|
|
try {
|
|
id = new ImageData(imageData.width, imageData.height);
|
|
} catch (e) {
|
|
var canvas = document.createElement('canvas');
|
|
var ctx = canvas.getContext('2d');
|
|
id = ctx.createImageData(imageData.width, imageData.height);
|
|
}
|
|
id.data.set(new Uint8ClampedArray(imageData.data));
|
|
return id;
|
|
};
|
|
|
|
var loadImage = function loadImage(url) {
|
|
return new Promise(function(resolve, reject) {
|
|
var img = new Image();
|
|
img.crossOrigin = 'Anonymous';
|
|
img.onload = function() {
|
|
resolve(img);
|
|
};
|
|
img.onerror = function(e) {
|
|
reject(e);
|
|
};
|
|
img.src = url;
|
|
});
|
|
};
|
|
|
|
var createImageWrapperView = function createImageWrapperView(_) {
|
|
// create overlay view
|
|
var OverlayView = createImageOverlayView(_);
|
|
|
|
var ImageView = createImageView(_);
|
|
var createWorker = _.utils.createWorker;
|
|
|
|
var applyFilter = function applyFilter(root, filter, target) {
|
|
return new Promise(function(resolve) {
|
|
// will store image data for future filter updates
|
|
if (!root.ref.imageData) {
|
|
root.ref.imageData = target
|
|
.getContext('2d')
|
|
.getImageData(0, 0, target.width, target.height);
|
|
}
|
|
|
|
// get image data reference
|
|
var imageData = cloneImageData(root.ref.imageData);
|
|
|
|
if (!filter || filter.length !== 20) {
|
|
target.getContext('2d').putImageData(imageData, 0, 0);
|
|
return resolve();
|
|
}
|
|
|
|
var worker = createWorker(ColorMatrixWorker);
|
|
worker.post(
|
|
{
|
|
imageData: imageData,
|
|
colorMatrix: filter
|
|
},
|
|
|
|
function(response) {
|
|
// apply filtered colors
|
|
target.getContext('2d').putImageData(response, 0, 0);
|
|
|
|
// stop worker
|
|
worker.terminate();
|
|
|
|
// done!
|
|
resolve();
|
|
},
|
|
[imageData.data.buffer]
|
|
);
|
|
});
|
|
};
|
|
|
|
var removeImageView = function removeImageView(root, imageView) {
|
|
root.removeChildView(imageView);
|
|
imageView.image.width = 1;
|
|
imageView.image.height = 1;
|
|
imageView._destroy();
|
|
};
|
|
|
|
// remove an image
|
|
var shiftImage = function shiftImage(_ref) {
|
|
var root = _ref.root;
|
|
var imageView = root.ref.images.shift();
|
|
imageView.opacity = 0;
|
|
imageView.translateY = -15;
|
|
root.ref.imageViewBin.push(imageView);
|
|
return imageView;
|
|
};
|
|
|
|
// add new image
|
|
var pushImage = function pushImage(_ref2) {
|
|
var root = _ref2.root,
|
|
props = _ref2.props,
|
|
image = _ref2.image;
|
|
var id = props.id;
|
|
var item = root.query('GET_ITEM', { id: id });
|
|
if (!item) return;
|
|
|
|
var crop = item.getMetadata('crop') || {
|
|
center: {
|
|
x: 0.5,
|
|
y: 0.5
|
|
},
|
|
|
|
flip: {
|
|
horizontal: false,
|
|
vertical: false
|
|
},
|
|
|
|
zoom: 1,
|
|
rotation: 0,
|
|
aspectRatio: null
|
|
};
|
|
|
|
var background = root.query(
|
|
'GET_IMAGE_TRANSFORM_CANVAS_BACKGROUND_COLOR'
|
|
);
|
|
|
|
var markup;
|
|
var resize;
|
|
var dirty = false;
|
|
if (root.query('GET_IMAGE_PREVIEW_MARKUP_SHOW')) {
|
|
markup = item.getMetadata('markup') || [];
|
|
resize = item.getMetadata('resize');
|
|
dirty = true;
|
|
}
|
|
|
|
// append image presenter
|
|
var imageView = root.appendChildView(
|
|
root.createChildView(ImageView, {
|
|
id: id,
|
|
image: image,
|
|
crop: crop,
|
|
resize: resize,
|
|
markup: markup,
|
|
dirty: dirty,
|
|
background: background,
|
|
opacity: 0,
|
|
scaleX: 1.15,
|
|
scaleY: 1.15,
|
|
translateY: 15
|
|
}),
|
|
|
|
root.childViews.length
|
|
);
|
|
|
|
root.ref.images.push(imageView);
|
|
|
|
// reveal the preview image
|
|
imageView.opacity = 1;
|
|
imageView.scaleX = 1;
|
|
imageView.scaleY = 1;
|
|
imageView.translateY = 0;
|
|
|
|
// the preview is now ready to be drawn
|
|
setTimeout(function() {
|
|
root.dispatch('DID_IMAGE_PREVIEW_SHOW', { id: id });
|
|
}, 250);
|
|
};
|
|
|
|
var updateImage = function updateImage(_ref3) {
|
|
var root = _ref3.root,
|
|
props = _ref3.props;
|
|
var item = root.query('GET_ITEM', { id: props.id });
|
|
if (!item) return;
|
|
var imageView = root.ref.images[root.ref.images.length - 1];
|
|
imageView.crop = item.getMetadata('crop');
|
|
imageView.background = root.query(
|
|
'GET_IMAGE_TRANSFORM_CANVAS_BACKGROUND_COLOR'
|
|
);
|
|
|
|
if (root.query('GET_IMAGE_PREVIEW_MARKUP_SHOW')) {
|
|
imageView.dirty = true;
|
|
imageView.resize = item.getMetadata('resize');
|
|
imageView.markup = item.getMetadata('markup');
|
|
}
|
|
};
|
|
|
|
// replace image preview
|
|
var didUpdateItemMetadata = function didUpdateItemMetadata(_ref4) {
|
|
var root = _ref4.root,
|
|
props = _ref4.props,
|
|
action = _ref4.action;
|
|
// only filter and crop trigger redraw
|
|
if (!/crop|filter|markup|resize/.test(action.change.key)) return;
|
|
|
|
// no images to update, exit
|
|
if (!root.ref.images.length) return;
|
|
|
|
// no item found, exit
|
|
var item = root.query('GET_ITEM', { id: props.id });
|
|
if (!item) return;
|
|
|
|
// for now, update existing image when filtering
|
|
if (/filter/.test(action.change.key)) {
|
|
var imageView = root.ref.images[root.ref.images.length - 1];
|
|
applyFilter(root, action.change.value, imageView.image);
|
|
return;
|
|
}
|
|
|
|
if (/crop|markup|resize/.test(action.change.key)) {
|
|
var crop = item.getMetadata('crop');
|
|
var image = root.ref.images[root.ref.images.length - 1];
|
|
|
|
// if aspect ratio has changed, we need to create a new image
|
|
if (
|
|
crop &&
|
|
crop.aspectRatio &&
|
|
image.crop &&
|
|
image.crop.aspectRatio &&
|
|
Math.abs(crop.aspectRatio - image.crop.aspectRatio) > 0.00001
|
|
) {
|
|
var _imageView = shiftImage({ root: root });
|
|
pushImage({
|
|
root: root,
|
|
props: props,
|
|
image: cloneCanvas(_imageView.image)
|
|
});
|
|
}
|
|
// if not, we can update the current image
|
|
else {
|
|
updateImage({ root: root, props: props });
|
|
}
|
|
}
|
|
};
|
|
|
|
var canCreateImageBitmap = function canCreateImageBitmap(file) {
|
|
// Firefox versions before 58 will freeze when running createImageBitmap
|
|
// in a Web Worker so we detect those versions and return false for support
|
|
var userAgent = window.navigator.userAgent;
|
|
var isFirefox = userAgent.match(/Firefox\/([0-9]+)\./);
|
|
var firefoxVersion = isFirefox ? parseInt(isFirefox[1]) : null;
|
|
if (firefoxVersion !== null && firefoxVersion <= 58) return false;
|
|
|
|
return 'createImageBitmap' in window && isBitmap(file);
|
|
};
|
|
|
|
/**
|
|
* Write handler for when preview container has been created
|
|
*/
|
|
var didCreatePreviewContainer = function didCreatePreviewContainer(_ref5) {
|
|
var root = _ref5.root,
|
|
props = _ref5.props;
|
|
var id = props.id;
|
|
|
|
// we need to get the file data to determine the eventual image size
|
|
var item = root.query('GET_ITEM', id);
|
|
if (!item) return;
|
|
|
|
// get url to file (we'll revoke it later on when done)
|
|
var fileURL = URL.createObjectURL(item.file);
|
|
|
|
// determine image size of this item
|
|
getImageSize(fileURL, function(width, height) {
|
|
// we can now scale the panel to the final size
|
|
root.dispatch('DID_IMAGE_PREVIEW_CALCULATE_SIZE', {
|
|
id: id,
|
|
width: width,
|
|
height: height
|
|
});
|
|
});
|
|
};
|
|
|
|
var drawPreview = function drawPreview(_ref6) {
|
|
var root = _ref6.root,
|
|
props = _ref6.props;
|
|
var id = props.id;
|
|
|
|
// we need to get the file data to determine the eventual image size
|
|
var item = root.query('GET_ITEM', id);
|
|
if (!item) return;
|
|
|
|
// get url to file (we'll revoke it later on when done)
|
|
var fileURL = URL.createObjectURL(item.file);
|
|
|
|
// fallback
|
|
var loadPreviewFallback = function loadPreviewFallback() {
|
|
// let's scale the image in the main thread :(
|
|
loadImage(fileURL).then(previewImageLoaded);
|
|
};
|
|
|
|
// image is now ready
|
|
var previewImageLoaded = function previewImageLoaded(imageData) {
|
|
// the file url is no longer needed
|
|
URL.revokeObjectURL(fileURL);
|
|
|
|
// draw the scaled down version here and use that as source so bitmapdata can be closed
|
|
// orientation info
|
|
var exif = item.getMetadata('exif') || {};
|
|
var orientation = exif.orientation || -1;
|
|
|
|
// get width and height from action, and swap if orientation is incorrect
|
|
var width = imageData.width,
|
|
height = imageData.height;
|
|
|
|
// if no width or height, just return early.
|
|
if (!width || !height) return;
|
|
|
|
if (orientation >= 5 && orientation <= 8) {
|
|
var _ref7 = [height, width];
|
|
width = _ref7[0];
|
|
height = _ref7[1];
|
|
}
|
|
|
|
// scale canvas based on pixel density
|
|
// we multiply by .75 as that creates smaller but still clear images on screens with high res displays
|
|
var pixelDensityFactor = Math.max(1, window.devicePixelRatio * 0.75);
|
|
|
|
// we want as much pixels to work with as possible,
|
|
// this multiplies the minimum image resolution,
|
|
// so when zooming in it doesn't get too blurry
|
|
var zoomFactor = root.query('GET_IMAGE_PREVIEW_ZOOM_FACTOR');
|
|
|
|
// imaeg scale factor
|
|
var scaleFactor = zoomFactor * pixelDensityFactor;
|
|
|
|
// calculate scaled preview image size
|
|
var previewImageRatio = height / width;
|
|
|
|
// calculate image preview height and width
|
|
var previewContainerWidth = root.rect.element.width;
|
|
var previewContainerHeight = root.rect.element.height;
|
|
|
|
var imageWidth = previewContainerWidth;
|
|
var imageHeight = imageWidth * previewImageRatio;
|
|
|
|
if (previewImageRatio > 1) {
|
|
imageWidth = Math.min(width, previewContainerWidth * scaleFactor);
|
|
imageHeight = imageWidth * previewImageRatio;
|
|
} else {
|
|
imageHeight = Math.min(height, previewContainerHeight * scaleFactor);
|
|
imageWidth = imageHeight / previewImageRatio;
|
|
}
|
|
|
|
// transfer to image tag so no canvas memory wasted on iOS
|
|
var previewImage = createPreviewImage(
|
|
imageData,
|
|
imageWidth,
|
|
imageHeight,
|
|
orientation
|
|
);
|
|
|
|
// done
|
|
var done = function done() {
|
|
// calculate average image color, disabled for now
|
|
var averageColor = root.query(
|
|
'GET_IMAGE_PREVIEW_CALCULATE_AVERAGE_IMAGE_COLOR'
|
|
)
|
|
? calculateAverageColor(data)
|
|
: null;
|
|
item.setMetadata('color', averageColor, true);
|
|
|
|
// data has been transferred to canvas ( if was ImageBitmap )
|
|
if ('close' in imageData) {
|
|
imageData.close();
|
|
}
|
|
|
|
// show the overlay
|
|
root.ref.overlayShadow.opacity = 1;
|
|
|
|
// create the first image
|
|
pushImage({ root: root, props: props, image: previewImage });
|
|
};
|
|
|
|
// apply filter
|
|
var filter = item.getMetadata('filter');
|
|
if (filter) {
|
|
applyFilter(root, filter, previewImage).then(done);
|
|
} else {
|
|
done();
|
|
}
|
|
};
|
|
|
|
// if we support scaling using createImageBitmap we use a worker
|
|
if (canCreateImageBitmap(item.file)) {
|
|
// let's scale the image in a worker
|
|
var worker = createWorker(BitmapWorker);
|
|
|
|
worker.post(
|
|
{
|
|
file: item.file
|
|
},
|
|
|
|
function(imageBitmap) {
|
|
// destroy worker
|
|
worker.terminate();
|
|
|
|
// no bitmap returned, must be something wrong,
|
|
// try the oldschool way
|
|
if (!imageBitmap) {
|
|
loadPreviewFallback();
|
|
return;
|
|
}
|
|
|
|
// yay we got our bitmap, let's continue showing the preview
|
|
previewImageLoaded(imageBitmap);
|
|
}
|
|
);
|
|
} else {
|
|
// create fallback preview
|
|
loadPreviewFallback();
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Write handler for when the preview image is ready to be animated
|
|
*/
|
|
var didDrawPreview = function didDrawPreview(_ref8) {
|
|
var root = _ref8.root;
|
|
// get last added image
|
|
var image = root.ref.images[root.ref.images.length - 1];
|
|
image.translateY = 0;
|
|
image.scaleX = 1.0;
|
|
image.scaleY = 1.0;
|
|
image.opacity = 1;
|
|
};
|
|
|
|
/**
|
|
* Write handler for when the preview has been loaded
|
|
*/
|
|
var restoreOverlay = function restoreOverlay(_ref9) {
|
|
var root = _ref9.root;
|
|
root.ref.overlayShadow.opacity = 1;
|
|
root.ref.overlayError.opacity = 0;
|
|
root.ref.overlaySuccess.opacity = 0;
|
|
};
|
|
|
|
var didThrowError = function didThrowError(_ref10) {
|
|
var root = _ref10.root;
|
|
root.ref.overlayShadow.opacity = 0.25;
|
|
root.ref.overlayError.opacity = 1;
|
|
};
|
|
|
|
var didCompleteProcessing = function didCompleteProcessing(_ref11) {
|
|
var root = _ref11.root;
|
|
root.ref.overlayShadow.opacity = 0.25;
|
|
root.ref.overlaySuccess.opacity = 1;
|
|
};
|
|
|
|
/**
|
|
* Constructor
|
|
*/
|
|
var create = function create(_ref12) {
|
|
var root = _ref12.root;
|
|
// image view
|
|
root.ref.images = [];
|
|
|
|
// the preview image data (we need this to filter the image)
|
|
root.ref.imageData = null;
|
|
|
|
// image bin
|
|
root.ref.imageViewBin = [];
|
|
|
|
// image overlays
|
|
root.ref.overlayShadow = root.appendChildView(
|
|
root.createChildView(OverlayView, {
|
|
opacity: 0,
|
|
status: 'idle'
|
|
})
|
|
);
|
|
|
|
root.ref.overlaySuccess = root.appendChildView(
|
|
root.createChildView(OverlayView, {
|
|
opacity: 0,
|
|
status: 'success'
|
|
})
|
|
);
|
|
|
|
root.ref.overlayError = root.appendChildView(
|
|
root.createChildView(OverlayView, {
|
|
opacity: 0,
|
|
status: 'failure'
|
|
})
|
|
);
|
|
};
|
|
|
|
return _.utils.createView({
|
|
name: 'image-preview-wrapper',
|
|
create: create,
|
|
styles: ['height'],
|
|
apis: ['height'],
|
|
destroy: function destroy(_ref13) {
|
|
var root = _ref13.root;
|
|
// we resize the image so memory on iOS 12 is released more quickly (it seems)
|
|
root.ref.images.forEach(function(imageView) {
|
|
imageView.image.width = 1;
|
|
imageView.image.height = 1;
|
|
});
|
|
},
|
|
didWriteView: function didWriteView(_ref14) {
|
|
var root = _ref14.root;
|
|
root.ref.images.forEach(function(imageView) {
|
|
imageView.dirty = false;
|
|
});
|
|
},
|
|
write: _.utils.createRoute(
|
|
{
|
|
// image preview stated
|
|
DID_IMAGE_PREVIEW_DRAW: didDrawPreview,
|
|
DID_IMAGE_PREVIEW_CONTAINER_CREATE: didCreatePreviewContainer,
|
|
DID_FINISH_CALCULATE_PREVIEWSIZE: drawPreview,
|
|
DID_UPDATE_ITEM_METADATA: didUpdateItemMetadata,
|
|
|
|
// file states
|
|
DID_THROW_ITEM_LOAD_ERROR: didThrowError,
|
|
DID_THROW_ITEM_PROCESSING_ERROR: didThrowError,
|
|
DID_THROW_ITEM_INVALID: didThrowError,
|
|
DID_COMPLETE_ITEM_PROCESSING: didCompleteProcessing,
|
|
DID_START_ITEM_PROCESSING: restoreOverlay,
|
|
DID_REVERT_ITEM_PROCESSING: restoreOverlay
|
|
},
|
|
|
|
function(_ref15) {
|
|
var root = _ref15.root;
|
|
// views on death row
|
|
var viewsToRemove = root.ref.imageViewBin.filter(function(imageView) {
|
|
return imageView.opacity === 0;
|
|
});
|
|
|
|
// views to retain
|
|
root.ref.imageViewBin = root.ref.imageViewBin.filter(function(
|
|
imageView
|
|
) {
|
|
return imageView.opacity > 0;
|
|
});
|
|
|
|
// remove these views
|
|
viewsToRemove.forEach(function(imageView) {
|
|
return removeImageView(root, imageView);
|
|
});
|
|
viewsToRemove.length = 0;
|
|
}
|
|
)
|
|
});
|
|
};
|
|
|
|
/**
|
|
* Image Preview Plugin
|
|
*/
|
|
var plugin = function plugin(fpAPI) {
|
|
var addFilter = fpAPI.addFilter,
|
|
utils = fpAPI.utils;
|
|
var Type = utils.Type,
|
|
createRoute = utils.createRoute,
|
|
isFile = utils.isFile;
|
|
|
|
// imagePreviewView
|
|
var imagePreviewView = createImageWrapperView(fpAPI);
|
|
|
|
// called for each view that is created right after the 'create' method
|
|
addFilter('CREATE_VIEW', function(viewAPI) {
|
|
// get reference to created view
|
|
var is = viewAPI.is,
|
|
view = viewAPI.view,
|
|
query = viewAPI.query;
|
|
|
|
// only hook up to item view and only if is enabled for this cropper
|
|
if (!is('file') || !query('GET_ALLOW_IMAGE_PREVIEW')) return;
|
|
|
|
// create the image preview plugin, but only do so if the item is an image
|
|
var didLoadItem = function didLoadItem(_ref) {
|
|
var root = _ref.root,
|
|
props = _ref.props;
|
|
var id = props.id;
|
|
var item = query('GET_ITEM', id);
|
|
|
|
// item could theoretically have been removed in the mean time
|
|
if (!item || !isFile(item.file) || item.archived) return;
|
|
|
|
// get the file object
|
|
var file = item.file;
|
|
|
|
// exit if this is not an image
|
|
if (!isPreviewableImage(file)) return;
|
|
|
|
// test if is filtered
|
|
if (!query('GET_IMAGE_PREVIEW_FILTER_ITEM')(item)) return;
|
|
|
|
// exit if image size is too high and no createImageBitmap support
|
|
// this would simply bring the browser to its knees and that is not what we want
|
|
var supportsCreateImageBitmap = 'createImageBitmap' in (window || {});
|
|
var maxPreviewFileSize = query('GET_IMAGE_PREVIEW_MAX_FILE_SIZE');
|
|
if (
|
|
!supportsCreateImageBitmap &&
|
|
maxPreviewFileSize &&
|
|
file.size > maxPreviewFileSize
|
|
)
|
|
return;
|
|
|
|
// set preview view
|
|
root.ref.imagePreview = view.appendChildView(
|
|
view.createChildView(imagePreviewView, { id: id })
|
|
);
|
|
|
|
// update height if is fixed
|
|
var fixedPreviewHeight = root.query('GET_IMAGE_PREVIEW_HEIGHT');
|
|
if (fixedPreviewHeight) {
|
|
root.dispatch('DID_UPDATE_PANEL_HEIGHT', {
|
|
id: item.id,
|
|
height: fixedPreviewHeight
|
|
});
|
|
}
|
|
|
|
// now ready
|
|
var queue =
|
|
!supportsCreateImageBitmap &&
|
|
file.size > query('GET_IMAGE_PREVIEW_MAX_INSTANT_PREVIEW_FILE_SIZE');
|
|
root.dispatch('DID_IMAGE_PREVIEW_CONTAINER_CREATE', { id: id }, queue);
|
|
};
|
|
|
|
var rescaleItem = function rescaleItem(root, props) {
|
|
if (!root.ref.imagePreview) return;
|
|
var id = props.id;
|
|
|
|
// get item
|
|
var item = root.query('GET_ITEM', { id: id });
|
|
if (!item) return;
|
|
|
|
// if is fixed height or panel has aspect ratio, exit here, height has already been defined
|
|
var panelAspectRatio = root.query('GET_PANEL_ASPECT_RATIO');
|
|
var itemPanelAspectRatio = root.query('GET_ITEM_PANEL_ASPECT_RATIO');
|
|
var fixedHeight = root.query('GET_IMAGE_PREVIEW_HEIGHT');
|
|
if (panelAspectRatio || itemPanelAspectRatio || fixedHeight) return;
|
|
|
|
// no data!
|
|
var _root$ref = root.ref,
|
|
imageWidth = _root$ref.imageWidth,
|
|
imageHeight = _root$ref.imageHeight;
|
|
if (!imageWidth || !imageHeight) return;
|
|
|
|
// get height min and max
|
|
var minPreviewHeight = root.query('GET_IMAGE_PREVIEW_MIN_HEIGHT');
|
|
var maxPreviewHeight = root.query('GET_IMAGE_PREVIEW_MAX_HEIGHT');
|
|
|
|
// orientation info
|
|
var exif = item.getMetadata('exif') || {};
|
|
var orientation = exif.orientation || -1;
|
|
|
|
// get width and height from action, and swap of orientation is incorrect
|
|
if (orientation >= 5 && orientation <= 8) {
|
|
var _ref2 = [imageHeight, imageWidth];
|
|
imageWidth = _ref2[0];
|
|
imageHeight = _ref2[1];
|
|
}
|
|
|
|
// scale up width and height when we're dealing with an SVG
|
|
if (!isBitmap(item.file) || root.query('GET_IMAGE_PREVIEW_UPSCALE')) {
|
|
var scalar = 2048 / imageWidth;
|
|
imageWidth *= scalar;
|
|
imageHeight *= scalar;
|
|
}
|
|
|
|
// image aspect ratio
|
|
var imageAspectRatio = imageHeight / imageWidth;
|
|
|
|
// we need the item to get to the crop size
|
|
var previewAspectRatio =
|
|
(item.getMetadata('crop') || {}).aspectRatio || imageAspectRatio;
|
|
|
|
// preview height range
|
|
var previewHeightMax = Math.max(
|
|
minPreviewHeight,
|
|
Math.min(imageHeight, maxPreviewHeight)
|
|
);
|
|
|
|
var itemWidth = root.rect.element.width;
|
|
var previewHeight = Math.min(
|
|
itemWidth * previewAspectRatio,
|
|
previewHeightMax
|
|
);
|
|
|
|
// request update to panel height
|
|
root.dispatch('DID_UPDATE_PANEL_HEIGHT', {
|
|
id: item.id,
|
|
height: previewHeight
|
|
});
|
|
};
|
|
|
|
var didResizeView = function didResizeView(_ref3) {
|
|
var root = _ref3.root;
|
|
// actions in next write operation
|
|
root.ref.shouldRescale = true;
|
|
};
|
|
|
|
var didUpdateItemMetadata = function didUpdateItemMetadata(_ref4) {
|
|
var root = _ref4.root,
|
|
action = _ref4.action;
|
|
if (action.change.key !== 'crop') return;
|
|
|
|
// actions in next write operation
|
|
root.ref.shouldRescale = true;
|
|
};
|
|
|
|
var didCalculatePreviewSize = function didCalculatePreviewSize(_ref5) {
|
|
var root = _ref5.root,
|
|
action = _ref5.action;
|
|
// remember dimensions
|
|
root.ref.imageWidth = action.width;
|
|
root.ref.imageHeight = action.height;
|
|
|
|
// actions in next write operation
|
|
root.ref.shouldRescale = true;
|
|
root.ref.shouldDrawPreview = true;
|
|
|
|
// as image load could take a while and fire when draw loop is resting we need to give it a kick
|
|
root.dispatch('KICK');
|
|
};
|
|
|
|
// start writing
|
|
view.registerWriter(
|
|
createRoute(
|
|
{
|
|
DID_RESIZE_ROOT: didResizeView,
|
|
DID_STOP_RESIZE: didResizeView,
|
|
DID_LOAD_ITEM: didLoadItem,
|
|
DID_IMAGE_PREVIEW_CALCULATE_SIZE: didCalculatePreviewSize,
|
|
DID_UPDATE_ITEM_METADATA: didUpdateItemMetadata
|
|
},
|
|
|
|
function(_ref6) {
|
|
var root = _ref6.root,
|
|
props = _ref6.props;
|
|
// no preview view attached
|
|
if (!root.ref.imagePreview) return;
|
|
|
|
// don't do anything while hidden
|
|
if (root.rect.element.hidden) return;
|
|
|
|
// resize the item panel
|
|
if (root.ref.shouldRescale) {
|
|
rescaleItem(root, props);
|
|
root.ref.shouldRescale = false;
|
|
}
|
|
|
|
if (root.ref.shouldDrawPreview) {
|
|
// queue till next frame so we're sure the height has been applied this forces the draw image call inside the wrapper view to use the correct height
|
|
requestAnimationFrame(function() {
|
|
// this requestAnimationFrame nesting is horrible but it fixes an issue with 100hz displays on Chrome
|
|
// https://github.com/pqina/filepond-plugin-image-preview/issues/57
|
|
requestAnimationFrame(function() {
|
|
root.dispatch('DID_FINISH_CALCULATE_PREVIEWSIZE', {
|
|
id: props.id
|
|
});
|
|
});
|
|
});
|
|
|
|
root.ref.shouldDrawPreview = false;
|
|
}
|
|
}
|
|
)
|
|
);
|
|
});
|
|
|
|
// expose plugin
|
|
return {
|
|
options: {
|
|
// Enable or disable image preview
|
|
allowImagePreview: [true, Type.BOOLEAN],
|
|
|
|
// filters file items to determine which are shown as preview
|
|
imagePreviewFilterItem: [
|
|
function() {
|
|
return true;
|
|
},
|
|
Type.FUNCTION
|
|
],
|
|
|
|
// Fixed preview height
|
|
imagePreviewHeight: [null, Type.INT],
|
|
|
|
// Min image height
|
|
imagePreviewMinHeight: [44, Type.INT],
|
|
|
|
// Max image height
|
|
imagePreviewMaxHeight: [256, Type.INT],
|
|
|
|
// Max size of preview file for when createImageBitmap is not supported
|
|
imagePreviewMaxFileSize: [null, Type.INT],
|
|
|
|
// The amount of extra pixels added to the image preview to allow comfortable zooming
|
|
imagePreviewZoomFactor: [2, Type.INT],
|
|
|
|
// Should we upscale small images to fit the max bounding box of the preview area
|
|
imagePreviewUpscale: [false, Type.BOOLEAN],
|
|
|
|
// Max size of preview file that we allow to try to instant preview if createImageBitmap is not supported, else image is queued for loading
|
|
imagePreviewMaxInstantPreviewFileSize: [1000000, Type.INT],
|
|
|
|
// Style of the transparancy indicator used behind images
|
|
imagePreviewTransparencyIndicator: [null, Type.STRING],
|
|
|
|
// Enables or disables reading average image color
|
|
imagePreviewCalculateAverageImageColor: [false, Type.BOOLEAN],
|
|
|
|
// Enables or disables the previewing of markup
|
|
imagePreviewMarkupShow: [true, Type.BOOLEAN],
|
|
|
|
// Allows filtering of markup to only show certain shapes
|
|
imagePreviewMarkupFilter: [
|
|
function() {
|
|
return true;
|
|
},
|
|
Type.FUNCTION
|
|
]
|
|
}
|
|
};
|
|
};
|
|
|
|
// fire pluginloaded event if running in browser, this allows registering the plugin when using async script tags
|
|
var isBrowser =
|
|
typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
if (isBrowser) {
|
|
document.dispatchEvent(
|
|
new CustomEvent('FilePond:pluginloaded', { detail: plugin })
|
|
);
|
|
}
|
|
|
|
return plugin;
|
|
});
|