UNPKG

@salla.sa/twilight-components

Version:
1,696 lines (1,448 loc) 68.9 kB
/*! * Crafted with ❤ by Salla */ import { g as getDefaultExportFromCjs } from './_commonjsHelpers.js'; function _mergeNamespaces(n, m) { m.forEach(function (e) { e && typeof e !== 'string' && !Array.isArray(e) && Object.keys(e).forEach(function (k) { if (k !== 'default' && !(k in n)) { var d = Object.getOwnPropertyDescriptor(e, k); Object.defineProperty(n, k, d.get ? d : { enumerable: true, get: function () { return e[k]; } }); } }); }); return Object.freeze(n); } var filepondPluginImagePreview$3 = {exports: {}}; /*! * FilePondPluginImagePreview 4.6.12 * Licensed under MIT, https://opensource.org/licenses/MIT/ * Please visit https://pqina.nl/filepond/ for details. */ var filepondPluginImagePreview$2 = filepondPluginImagePreview$3.exports; var hasRequiredFilepondPluginImagePreview; function requireFilepondPluginImagePreview () { if (hasRequiredFilepondPluginImagePreview) return filepondPluginImagePreview$3.exports; hasRequiredFilepondPluginImagePreview = 1; (function (module, exports) { /* eslint-disable */ (function(global, factory) { (module.exports = factory()) ; })(filepondPluginImagePreview$2, function() { // test if file is of type image and can be viewed in canvas var isPreviewableImage = function isPreviewableImage(file) { return /^image/.test(file.type); }; function _slicedToArray(arr, i) { return ( _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest() ); } function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } 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 (_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 _nonIterableRest() { throw new TypeError('Invalid attempt to destructure non-iterable instance'); } 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 stage = { width: canvasSize.width, height: canvasSize.height}; 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 = { 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