diff --git a/Gruntfile.js b/Gruntfile.js index 40d66eda..ba9eab71 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -26,9 +26,7 @@ module.exports = function(grunt) { prefix: '// @@', }, main: { - // Files to perform replacements and includes with src: '<%= paths.srcFolder %>/css-layout.js', - // Destination directory to copy files to dest: '<%= paths.distFolder %>/css-layout.js' } }, diff --git a/README.md b/README.md index 1510eeaa..965aa6ff 100644 --- a/README.md +++ b/README.md @@ -29,8 +29,6 @@ computeLayout( ]} ``` -NOTE: You need to run the JavaScript build, as detailed below, before running this code. - Supported Attributes -------------------- diff --git a/dist/css-layout.js b/dist/css-layout.js new file mode 100644 index 00000000..af198231 --- /dev/null +++ b/dist/css-layout.js @@ -0,0 +1,1018 @@ +// UMD (Universal Module Definition) +// See https://github.com/umdjs/umd for reference +// +// This file uses the following specific UMD implementation: +// https://github.com/umdjs/umd/blob/master/returnExports.js +(function (root, factory) { + if (typeof define === 'function' && define.amd) { + // AMD. Register as an anonymous module. + define([], factory); + } else if (typeof exports === 'object') { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(); + } else { + // Browser globals (root is window) + root.computeLayout = factory(); + } +}(this, function () { + /** + * Copyright (c) 2014, Facebook, Inc. + * All rights reserved. + * + * This source code is licensed under the BSD-style license found in the + * LICENSE file in the root directory of this source tree. An additional grant + * of patent rights can be found in the PATENTS file in the same directory. + */ + +var computeLayout = (function() { + + var CSS_UNDEFINED; + + var CSS_DIRECTION_INHERIT = 'inherit'; + var CSS_DIRECTION_LTR = 'ltr'; + var CSS_DIRECTION_RTL = 'rtl'; + + var CSS_FLEX_DIRECTION_ROW = 'row'; + var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse'; + var CSS_FLEX_DIRECTION_COLUMN = 'column'; + var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse'; + + // var CSS_JUSTIFY_FLEX_START = 'flex-start'; + var CSS_JUSTIFY_CENTER = 'center'; + var CSS_JUSTIFY_FLEX_END = 'flex-end'; + var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between'; + var CSS_JUSTIFY_SPACE_AROUND = 'space-around'; + + var CSS_ALIGN_FLEX_START = 'flex-start'; + var CSS_ALIGN_CENTER = 'center'; + var CSS_ALIGN_FLEX_END = 'flex-end'; + var CSS_ALIGN_STRETCH = 'stretch'; + + var CSS_POSITION_RELATIVE = 'relative'; + var CSS_POSITION_ABSOLUTE = 'absolute'; + + var leading = { + 'row': 'left', + 'row-reverse': 'right', + 'column': 'top', + 'column-reverse': 'bottom' + }; + var trailing = { + 'row': 'right', + 'row-reverse': 'left', + 'column': 'bottom', + 'column-reverse': 'top' + }; + var pos = { + 'row': 'left', + 'row-reverse': 'right', + 'column': 'top', + 'column-reverse': 'bottom' + }; + var dim = { + 'row': 'width', + 'row-reverse': 'width', + 'column': 'height', + 'column-reverse': 'height' + }; + + function capitalizeFirst(str) { + return str.charAt(0).toUpperCase() + str.slice(1); + } + + function getSpacing(node, type, suffix, locations) { + for (var i = 0; i < locations.length; ++i) { + var location = locations[i]; + + var key = type + capitalizeFirst(location) + suffix; + if (key in node.style) { + return node.style[key]; + } + + key = type + suffix; + if (key in node.style) { + return node.style[key]; + } + } + + return 0; + } + function fillNodes(node) { + node.layout = { + width: undefined, + height: undefined, + top: 0, + left: 0, + right: 0, + bottom: 0 + }; + if (!node.style) { + node.style = {}; + } + + if (!node.children || node.style.measure) { + node.children = []; + } + node.children.forEach(fillNodes); + return node; + } + + function extractNodes(node) { + var layout = node.layout; + delete node.layout; + if (node.children && node.children.length > 0) { + layout.children = node.children.map(extractNodes); + } else { + delete node.children; + } + + delete layout.right; + delete layout.bottom; + delete layout.direction; + + return layout; + } + + function getPositiveSpacing(node, type, suffix, locations) { + for (var i = 0; i < locations.length; ++i) { + var location = locations[i]; + + var key = type + capitalizeFirst(location) + suffix; + if (key in node.style && node.style[key] >= 0) { + return node.style[key]; + } + + key = type + suffix; + if (key in node.style && node.style[key] >= 0) { + return node.style[key]; + } + } + + return 0; + } + + function isUndefined(value) { + return value === undefined; + } + + function isRowDirection(flexDirection) { + return flexDirection === CSS_FLEX_DIRECTION_ROW || + flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE; + } + + function isColumnDirection(flexDirection) { + return flexDirection === CSS_FLEX_DIRECTION_COLUMN || + flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE; + } + + function getLeadingLocations(axis) { + var locations = [leading[axis]]; + if (isRowDirection(axis)) { + locations.unshift('start'); + } + + return locations; + } + + function getTrailingLocations(axis) { + var locations = [trailing[axis]]; + if (isRowDirection(axis)) { + locations.unshift('end'); + } + + return locations; + } + + function getMargin(node, locations) { + return getSpacing(node, 'margin', '', locations); + } + + function getLeadingMargin(node, axis) { + return getMargin(node, getLeadingLocations(axis)); + } + + function getTrailingMargin(node, axis) { + return getMargin(node, getTrailingLocations(axis)); + } + + function getPadding(node, locations) { + return getPositiveSpacing(node, 'padding', '', locations); + } + + function getLeadingPadding(node, axis) { + return getPadding(node, getLeadingLocations(axis)); + } + + function getTrailingPadding(node, axis) { + return getPadding(node, getTrailingLocations(axis)); + } + + function getBorder(node, locations) { + return getPositiveSpacing(node, 'border', 'Width', locations); + } + + function getLeadingBorder(node, axis) { + return getBorder(node, getLeadingLocations(axis)); + } + + function getTrailingBorder(node, axis) { + return getBorder(node, getTrailingLocations(axis)); + } + + function getLeadingPaddingAndBorder(node, axis) { + return getLeadingPadding(node, axis) + getLeadingBorder(node, axis); + } + + function getTrailingPaddingAndBorder(node, axis) { + return getTrailingPadding(node, axis) + getTrailingBorder(node, axis); + } + + function getBorderAxis(node, axis) { + return getLeadingBorder(node, axis) + getTrailingBorder(node, axis); + } + + function getMarginAxis(node, axis) { + return getLeadingMargin(node, axis) + getTrailingMargin(node, axis); + } + + function getPaddingAndBorderAxis(node, axis) { + return getLeadingPaddingAndBorder(node, axis) + + getTrailingPaddingAndBorder(node, axis); + } + + function getJustifyContent(node) { + if ('justifyContent' in node.style) { + return node.style.justifyContent; + } + return 'flex-start'; + } + + function getAlignContent(node) { + if ('alignContent' in node.style) { + return node.style.alignContent; + } + return 'flex-start'; + } + + function getAlignItem(node, child) { + if ('alignSelf' in child.style) { + return child.style.alignSelf; + } + if ('alignItems' in node.style) { + return node.style.alignItems; + } + return 'stretch'; + } + + function resolveAxis(axis, direction) { + if (direction === CSS_DIRECTION_RTL) { + if (axis === CSS_FLEX_DIRECTION_ROW) { + return CSS_FLEX_DIRECTION_ROW_REVERSE; + } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) { + return CSS_FLEX_DIRECTION_ROW; + } + } + + return axis; + } + + function resolveDirection(node, parentDirection) { + var direction; + if ('direction' in node.style) { + direction = node.style.direction; + } else { + direction = CSS_DIRECTION_INHERIT; + } + + if (direction === CSS_DIRECTION_INHERIT) { + direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection); + } + + return direction; + } + + function getFlexDirection(node) { + if ('flexDirection' in node.style) { + return node.style.flexDirection; + } + return CSS_FLEX_DIRECTION_COLUMN; + } + + function getCrossFlexDirection(flexDirection, direction) { + if (isColumnDirection(flexDirection)) { + return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction); + } else { + return CSS_FLEX_DIRECTION_COLUMN; + } + } + + function getPositionType(node) { + if ('position' in node.style) { + return node.style.position; + } + return 'relative'; + } + + function getFlex(node) { + return node.style.flex; + } + + function isFlex(node) { + return ( + getPositionType(node) === CSS_POSITION_RELATIVE && + getFlex(node) > 0 + ); + } + + function isFlexWrap(node) { + return node.style.flexWrap === 'wrap'; + } + + function getDimWithMargin(node, axis) { + return node.layout[dim[axis]] + getMarginAxis(node, axis); + } + + function isDimDefined(node, axis) { + return !isUndefined(node.style[dim[axis]]) && node.style[dim[axis]] >= 0; + } + + function isPosDefined(node, pos) { + return !isUndefined(node.style[pos]); + } + + function isMeasureDefined(node) { + return 'measure' in node.style; + } + + function getPosition(node, pos) { + if (pos in node.style) { + return node.style[pos]; + } + return 0; + } + + function boundAxis(node, axis, value) { + var min = { + 'row': node.style.minWidth, + 'row-reverse': node.style.minWidth, + 'column': node.style.minHeight, + 'column-reverse': node.style.minHeight + }[axis]; + + var max = { + 'row': node.style.maxWidth, + 'row-reverse': node.style.maxWidth, + 'column': node.style.maxHeight, + 'column-reverse': node.style.maxHeight + }[axis]; + + var boundValue = value; + if (!isUndefined(max) && max >= 0 && boundValue > max) { + boundValue = max; + } + if (!isUndefined(min) && min >= 0 && boundValue < min) { + boundValue = min; + } + return boundValue; + } + + function fmaxf(a, b) { + if (a > b) { + return a; + } + return b; + } + + // When the user specifically sets a value for width or height + function setDimensionFromStyle(node, axis) { + // The parent already computed us a width or height. We just skip it + if (!isUndefined(node.layout[dim[axis]])) { + return; + } + // We only run if there's a width or height defined + if (!isDimDefined(node, axis)) { + return; + } + + // The dimensions can never be smaller than the padding and border + node.layout[dim[axis]] = fmaxf( + boundAxis(node, axis, node.style[dim[axis]]), + getPaddingAndBorderAxis(node, axis) + ); + } + + function setTrailingPosition(node, child, axis) { + child.layout[trailing[axis]] = node.layout[dim[axis]] - + child.layout[dim[axis]] - child.layout[pos[axis]]; + } + + // If both left and right are defined, then use left. Otherwise return + // +left or -right depending on which is defined. + function getRelativePosition(node, axis) { + if (leading[axis] in node.style) { + return getPosition(node, leading[axis]); + } + return -getPosition(node, trailing[axis]); + } + + function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) { + var/*css_direction_t*/ direction = resolveDirection(node, parentDirection); + var/*css_flex_direction_t*/ mainAxis = resolveAxis(getFlexDirection(node), direction); + var/*css_flex_direction_t*/ crossAxis = getCrossFlexDirection(mainAxis, direction); + var/*css_flex_direction_t*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction); + + // Handle width and height style attributes + setDimensionFromStyle(node, mainAxis); + setDimensionFromStyle(node, crossAxis); + + // Set the resolved resolution in the node's layout + node.layout.direction = direction; + + // The position is set by the parent, but we need to complete it with a + // delta composed of the margin and left/top/right/bottom + node.layout[leading[mainAxis]] += getLeadingMargin(node, mainAxis) + + getRelativePosition(node, mainAxis); + node.layout[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) + + getRelativePosition(node, mainAxis); + node.layout[leading[crossAxis]] += getLeadingMargin(node, crossAxis) + + getRelativePosition(node, crossAxis); + node.layout[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) + + getRelativePosition(node, crossAxis); + + if (isMeasureDefined(node)) { + var/*float*/ width = CSS_UNDEFINED; + if (isDimDefined(node, resolvedRowAxis)) { + width = node.style.width; + } else if (!isUndefined(node.layout[dim[resolvedRowAxis]])) { + width = node.layout[dim[resolvedRowAxis]]; + } else { + width = parentMaxWidth - + getMarginAxis(node, resolvedRowAxis); + } + width -= getPaddingAndBorderAxis(node, resolvedRowAxis); + + // We only need to give a dimension for the text if we haven't got any + // for it computed yet. It can either be from the style attribute or because + // the element is flexible. + var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) && + isUndefined(node.layout[dim[resolvedRowAxis]]); + var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && + isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]); + + // Let's not measure the text if we already know both dimensions + if (isRowUndefined || isColumnUndefined) { + var/*css_dim_t*/ measureDim = node.style.measure( + /*(c)!node->context,*/ + /*(java)!layoutContext.measureOutput,*/ + width + ); + if (isRowUndefined) { + node.layout.width = measureDim.width + + getPaddingAndBorderAxis(node, resolvedRowAxis); + } + if (isColumnUndefined) { + node.layout.height = measureDim.height + + getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); + } + } + if (node.children.length === 0) { + return; + } + } + + var/*int*/ i; + var/*int*/ ii; + var/*css_node_t**/ child; + var/*css_flex_direction_t*/ axis; + + // Pre-fill some dimensions straight from the parent + for (i = 0; i < node.children.length; ++i) { + child = node.children[i]; + // Pre-fill cross axis dimensions when the child is using stretch before + // we call the recursive layout pass + if (getAlignItem(node, child) === CSS_ALIGN_STRETCH && + getPositionType(child) === CSS_POSITION_RELATIVE && + !isUndefined(node.layout[dim[crossAxis]]) && + !isDimDefined(child, crossAxis)) { + child.layout[dim[crossAxis]] = fmaxf( + boundAxis(child, crossAxis, node.layout[dim[crossAxis]] - + getPaddingAndBorderAxis(node, crossAxis) - + getMarginAxis(child, crossAxis)), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, crossAxis) + ); + } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) { + // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both + // left and right or top and bottom). + for (ii = 0; ii < 2; ii++) { + axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (!isUndefined(node.layout[dim[axis]]) && + !isDimDefined(child, axis) && + isPosDefined(child, leading[axis]) && + isPosDefined(child, trailing[axis])) { + child.layout[dim[axis]] = fmaxf( + boundAxis(child, axis, node.layout[dim[axis]] - + getPaddingAndBorderAxis(node, axis) - + getMarginAxis(child, axis) - + getPosition(child, leading[axis]) - + getPosition(child, trailing[axis])), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, axis) + ); + } + } + } + } + + var/*float*/ definedMainDim = CSS_UNDEFINED; + if (!isUndefined(node.layout[dim[mainAxis]])) { + definedMainDim = node.layout[dim[mainAxis]] - + getPaddingAndBorderAxis(node, mainAxis); + } + + // We want to execute the next two loops one per line with flex-wrap + var/*int*/ startLine = 0; + var/*int*/ endLine = 0; + // var/*int*/ nextOffset = 0; + var/*int*/ alreadyComputedNextLayout = 0; + // We aggregate the total dimensions of the container in those two variables + var/*float*/ linesCrossDim = 0; + var/*float*/ linesMainDim = 0; + var/*int*/ linesCount = 0; + while (endLine < node.children.length) { + // Layout non flexible children and count children by type + + // mainContentDim is accumulation of the dimensions and margin of all the + // non flexible children. This will be used in order to either set the + // dimensions of the node if none already exist, or to compute the + // remaining space left for the flexible children. + var/*float*/ mainContentDim = 0; + + // There are three kind of children, non flexible, flexible and absolute. + // We need to know how many there are in order to distribute the space. + var/*int*/ flexibleChildrenCount = 0; + var/*float*/ totalFlexible = 0; + var/*int*/ nonFlexibleChildrenCount = 0; + + var/*float*/ maxWidth; + for (i = startLine; i < node.children.length; ++i) { + child = node.children[i]; + var/*float*/ nextContentDim = 0; + + // It only makes sense to consider a child flexible if we have a computed + // dimension for the node. + if (!isUndefined(node.layout[dim[mainAxis]]) && isFlex(child)) { + flexibleChildrenCount++; + totalFlexible += getFlex(child); + + // Even if we don't know its exact size yet, we already know the padding, + // border and margin. We'll use this partial information, which represents + // the smallest possible size for the child, to compute the remaining + // available space. + nextContentDim = getPaddingAndBorderAxis(child, mainAxis) + + getMarginAxis(child, mainAxis); + + } else { + maxWidth = CSS_UNDEFINED; + if (!isRowDirection(mainAxis)) { + maxWidth = parentMaxWidth - + getMarginAxis(node, resolvedRowAxis) - + getPaddingAndBorderAxis(node, resolvedRowAxis); + + if (isDimDefined(node, resolvedRowAxis)) { + maxWidth = node.layout[dim[resolvedRowAxis]] - + getPaddingAndBorderAxis(node, resolvedRowAxis); + } + } + + // This is the main recursive call. We layout non flexible children. + if (alreadyComputedNextLayout === 0) { + layoutNode(/*(java)!layoutContext, */child, maxWidth, direction); + } + + // Absolute positioned elements do not take part of the layout, so we + // don't use them to compute mainContentDim + if (getPositionType(child) === CSS_POSITION_RELATIVE) { + nonFlexibleChildrenCount++; + // At this point we know the final size and margin of the element. + nextContentDim = getDimWithMargin(child, mainAxis); + } + } + + // The element we are about to add would make us go to the next line + if (isFlexWrap(node) && + !isUndefined(node.layout[dim[mainAxis]]) && + mainContentDim + nextContentDim > definedMainDim && + // If there's only one element, then it's bigger than the content + // and needs its own line + i !== startLine) { + nonFlexibleChildrenCount--; + alreadyComputedNextLayout = 1; + break; + } + alreadyComputedNextLayout = 0; + mainContentDim += nextContentDim; + endLine = i + 1; + } + + // Layout flexible children and allocate empty space + + // In order to position the elements in the main axis, we have two + // controls. The space between the beginning and the first element + // and the space between each two elements. + var/*float*/ leadingMainDim = 0; + var/*float*/ betweenMainDim = 0; + + // The remaining available space that needs to be allocated + var/*float*/ remainingMainDim = 0; + if (!isUndefined(node.layout[dim[mainAxis]])) { + remainingMainDim = definedMainDim - mainContentDim; + } else { + remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim; + } + + // If there are flexible children in the mix, they are going to fill the + // remaining space + if (flexibleChildrenCount !== 0) { + var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible; + var/*float*/ baseMainDim; + var/*float*/ boundMainDim; + + // Iterate over every child in the axis. If the flex share of remaining + // space doesn't meet min/max bounds, remove this child from flex + // calculations. + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + if (isFlex(child)) { + baseMainDim = flexibleMainDim * getFlex(child) + + getPaddingAndBorderAxis(child, mainAxis); + boundMainDim = boundAxis(child, mainAxis, baseMainDim); + + if (baseMainDim !== boundMainDim) { + remainingMainDim -= boundMainDim; + totalFlexible -= getFlex(child); + } + } + } + flexibleMainDim = remainingMainDim / totalFlexible; + + // The non flexible children can overflow the container, in this case + // we should just assume that there is no space available. + if (flexibleMainDim < 0) { + flexibleMainDim = 0; + } + // We iterate over the full array and only apply the action on flexible + // children. This is faster than actually allocating a new array that + // contains only flexible children. + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + if (isFlex(child)) { + // At this point we know the final size of the element in the main + // dimension + child.layout[dim[mainAxis]] = boundAxis(child, mainAxis, + flexibleMainDim * getFlex(child) + getPaddingAndBorderAxis(child, mainAxis) + ); + + maxWidth = CSS_UNDEFINED; + if (isDimDefined(node, resolvedRowAxis)) { + maxWidth = node.layout[dim[resolvedRowAxis]] - + getPaddingAndBorderAxis(node, resolvedRowAxis); + } else if (!isRowDirection(mainAxis)) { + maxWidth = parentMaxWidth - + getMarginAxis(node, resolvedRowAxis) - + getPaddingAndBorderAxis(node, resolvedRowAxis); + } + + // And we recursively call the layout algorithm for this child + layoutNode(/*(java)!layoutContext, */child, maxWidth, direction); + } + } + + // We use justifyContent to figure out how to allocate the remaining + // space available + } else { + var/*css_justify_t*/ justifyContent = getJustifyContent(node); + if (justifyContent === CSS_JUSTIFY_CENTER) { + leadingMainDim = remainingMainDim / 2; + } else if (justifyContent === CSS_JUSTIFY_FLEX_END) { + leadingMainDim = remainingMainDim; + } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) { + remainingMainDim = fmaxf(remainingMainDim, 0); + if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) { + betweenMainDim = remainingMainDim / + (flexibleChildrenCount + nonFlexibleChildrenCount - 1); + } else { + betweenMainDim = 0; + } + } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) { + // Space on the edges is half of the space between elements + betweenMainDim = remainingMainDim / + (flexibleChildrenCount + nonFlexibleChildrenCount); + leadingMainDim = betweenMainDim / 2; + } + } + + // Position elements in the main axis and compute dimensions + + // At this point, all the children have their dimensions set. We need to + // find their position. In order to do that, we accumulate data in + // variables that are also useful to compute the total dimensions of the + // container! + var/*float*/ crossDim = 0; + var/*float*/ mainDim = leadingMainDim + + getLeadingPaddingAndBorder(node, mainAxis); + + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + child.lineIndex = linesCount; + + if (getPositionType(child) === CSS_POSITION_ABSOLUTE && + isPosDefined(child, leading[mainAxis])) { + // In case the child is position absolute and has left/top being + // defined, we override the position to whatever the user said + // (and margin/border). + child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) + + getLeadingBorder(node, mainAxis) + + getLeadingMargin(child, mainAxis); + } else { + // If the child is position absolute (without top/left) or relative, + // we put it at the current accumulated offset. + child.layout[pos[mainAxis]] += mainDim; + + // Define the trailing position accordingly. + if (!isUndefined(node.layout[dim[mainAxis]])) { + setTrailingPosition(node, child, mainAxis); + } + } + + // Now that we placed the element, we need to update the variables + // We only need to do that for relative elements. Absolute elements + // do not take part in that phase. + if (getPositionType(child) === CSS_POSITION_RELATIVE) { + // The main dimension is the sum of all the elements dimension plus + // the spacing. + mainDim += betweenMainDim + getDimWithMargin(child, mainAxis); + // The cross dimension is the max of the elements dimension since there + // can only be one element in that cross dimension. + crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis))); + } + } + + var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]]; + if (isUndefined(node.layout[dim[crossAxis]])) { + containerCrossAxis = fmaxf( + // For the cross dim, we add both sides at the end because the value + // is aggregate via a max function. Intermediate negative values + // can mess this computation otherwise + boundAxis(node, crossAxis, crossDim + getPaddingAndBorderAxis(node, crossAxis)), + getPaddingAndBorderAxis(node, crossAxis) + ); + } + + // Position elements in the cross axis + for (i = startLine; i < endLine; ++i) { + child = node.children[i]; + + if (getPositionType(child) === CSS_POSITION_ABSOLUTE && + isPosDefined(child, leading[crossAxis])) { + // In case the child is absolutely positionned and has a + // top/left/bottom/right being set, we override all the previously + // computed positions to set it correctly. + child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) + + getLeadingBorder(node, crossAxis) + + getLeadingMargin(child, crossAxis); + + } else { + var/*float*/ leadingCrossDim = getLeadingPaddingAndBorder(node, crossAxis); + + // For a relative children, we're either using alignItems (parent) or + // alignSelf (child) in order to determine the position in the cross axis + if (getPositionType(child) === CSS_POSITION_RELATIVE) { + var/*css_align_t*/ alignItem = getAlignItem(node, child); + if (alignItem === CSS_ALIGN_STRETCH) { + // You can only stretch if the dimension has not already been set + // previously. + if (!isDimDefined(child, crossAxis)) { + child.layout[dim[crossAxis]] = fmaxf( + boundAxis(child, crossAxis, containerCrossAxis - + getPaddingAndBorderAxis(node, crossAxis) - + getMarginAxis(child, crossAxis)), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, crossAxis) + ); + } + } else if (alignItem !== CSS_ALIGN_FLEX_START) { + // The remaining space between the parent dimensions+padding and child + // dimensions+margin. + var/*float*/ remainingCrossDim = containerCrossAxis - + getPaddingAndBorderAxis(node, crossAxis) - + getDimWithMargin(child, crossAxis); + + if (alignItem === CSS_ALIGN_CENTER) { + leadingCrossDim += remainingCrossDim / 2; + } else { // CSS_ALIGN_FLEX_END + leadingCrossDim += remainingCrossDim; + } + } + } + + // And we apply the position + child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim; + + // Define the trailing position accordingly. + if (!isUndefined(node.layout[dim[crossAxis]])) { + setTrailingPosition(node, child, crossAxis); + } + } + } + + linesCrossDim += crossDim; + linesMainDim = fmaxf(linesMainDim, mainDim); + linesCount += 1; + startLine = endLine; + } + + // + // + // Note(prenaux): More than one line, we need to layout the crossAxis + // according to alignContent. + // + // Note that we could probably remove and handle the one line case + // here too, but for the moment this is safer since it won't interfere with + // previously working code. + // + // See specs: + // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm + // section 9.4 + // + if (linesCount > 1 && + !isUndefined(node.layout[dim[crossAxis]])) { + var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] - + getPaddingAndBorderAxis(node, crossAxis); + var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim; + + var/*float*/ crossDimLead = 0; + var/*float*/ currentLead = getLeadingPaddingAndBorder(node, crossAxis); + + var/*css_align_t*/ alignContent = getAlignContent(node); + if (alignContent === CSS_ALIGN_FLEX_END) { + currentLead += remainingAlignContentDim; + } else if (alignContent === CSS_ALIGN_CENTER) { + currentLead += remainingAlignContentDim / 2; + } else if (alignContent === CSS_ALIGN_STRETCH) { + if (nodeCrossAxisInnerSize > linesCrossDim) { + crossDimLead = (remainingAlignContentDim / linesCount); + } + } + + var/*int*/ endIndex = 0; + for (i = 0; i < linesCount; ++i) { + var/*int*/ startIndex = endIndex; + + // compute the line's height and find the endIndex + var/*float*/ lineHeight = 0; + for (ii = startIndex; ii < node.children.length; ++ii) { + child = node.children[ii]; + if (getPositionType(child) !== CSS_POSITION_RELATIVE) { + continue; + } + if (child.lineIndex !== i) { + break; + } + if (!isUndefined(child.layout[dim[crossAxis]])) { + lineHeight = fmaxf( + lineHeight, + child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis) + ); + } + } + endIndex = ii; + lineHeight += crossDimLead; + + for (ii = startIndex; ii < endIndex; ++ii) { + child = node.children[ii]; + if (getPositionType(child) !== CSS_POSITION_RELATIVE) { + continue; + } + + var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child); + if (alignContentAlignItem === CSS_ALIGN_FLEX_START) { + child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis); + } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) { + child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[dim[crossAxis]]; + } else if (alignContentAlignItem === CSS_ALIGN_CENTER) { + var/*float*/ childHeight = child.layout[dim[crossAxis]]; + child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2; + } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) { + child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis); + // TODO(prenaux): Correctly set the height of items with undefined + // (auto) crossAxis dimension. + } + } + + currentLead += lineHeight; + } + } + + var/*bool*/ needsMainTrailingPos = false; + var/*bool*/ needsCrossTrailingPos = false; + + // If the user didn't specify a width or height, and it has not been set + // by the container, then we set it via the children. + if (isUndefined(node.layout[dim[mainAxis]])) { + node.layout[dim[mainAxis]] = fmaxf( + // We're missing the last padding at this point to get the final + // dimension + boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)), + // We can never assign a width smaller than the padding and borders + getPaddingAndBorderAxis(node, mainAxis) + ); + + needsMainTrailingPos = true; + } + + if (isUndefined(node.layout[dim[crossAxis]])) { + node.layout[dim[crossAxis]] = fmaxf( + // For the cross dim, we add both sides at the end because the value + // is aggregate via a max function. Intermediate negative values + // can mess this computation otherwise + boundAxis(node, crossAxis, linesCrossDim + getPaddingAndBorderAxis(node, crossAxis)), + getPaddingAndBorderAxis(node, crossAxis) + ); + + needsCrossTrailingPos = true; + } + + // Set trailing position if necessary + if (needsMainTrailingPos || needsCrossTrailingPos) { + for (i = 0; i < node.children.length; ++i) { + child = node.children[i]; + + if (needsMainTrailingPos) { + setTrailingPosition(node, child, mainAxis); + } + + if (needsCrossTrailingPos) { + setTrailingPosition(node, child, crossAxis); + } + } + } + + // Calculate dimensions for absolutely positioned elements + for (i = 0; i < node.children.length; ++i) { + child = node.children[i]; + if (getPositionType(child) === CSS_POSITION_ABSOLUTE) { + // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both + // left and right or top and bottom). + for (ii = 0; ii < 2; ii++) { + axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (!isUndefined(node.layout[dim[axis]]) && + !isDimDefined(child, axis) && + isPosDefined(child, leading[axis]) && + isPosDefined(child, trailing[axis])) { + child.layout[dim[axis]] = fmaxf( + boundAxis(child, axis, node.layout[dim[axis]] - + getBorderAxis(node, axis) - + getMarginAxis(child, axis) - + getPosition(child, leading[axis]) - + getPosition(child, trailing[axis]) + ), + // You never want to go smaller than padding + getPaddingAndBorderAxis(child, axis) + ); + } + } + for (ii = 0; ii < 2; ii++) { + axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; + if (isPosDefined(child, trailing[axis]) && + !isPosDefined(child, leading[axis])) { + child.layout[leading[axis]] = + node.layout[dim[axis]] - + child.layout[dim[axis]] - + getPosition(child, trailing[axis]); + } + } + } + } + } + + return { + computeLayout: layoutNode, + fillNodes: fillNodes, + extractNodes: extractNodes + }; +})(); + +if (typeof exports === 'object') { + module.exports = computeLayout; +} + + return function(node) { + node = computeLayout.fillNodes(node); + computeLayout.computeLayout(node); + node = computeLayout.extractNodes(node); + return node; + }; +})); diff --git a/dist/css-layout.min.js b/dist/css-layout.min.js new file mode 100644 index 00000000..efe7fd66 --- /dev/null +++ b/dist/css-layout.min.js @@ -0,0 +1,2 @@ +!function(a,b){"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.computeLayout=b()}(this,function(){var a=function(){function a(a){return a.charAt(0).toUpperCase()+a.slice(1)}function b(b,c,d,e){for(var f=0;f0?b.children=a.children.map(d):delete a.children,delete b.right,delete b.bottom,delete b.direction,b}function e(b,c,d,e){for(var f=0;f=0)return b.style[h];if(h=c+d,h in b.style&&b.style[h]>=0)return b.style[h]}return 0}function f(a){return void 0===a}function g(a){return a===Y||a===Z}function h(a){return a===$||a===_}function i(a){var b=[ka[a]];return g(a)&&b.unshift("start"),b}function j(a){var b=[la[a]];return g(a)&&b.unshift("end"),b}function k(a,c){return b(a,"margin","",c)}function l(a,b){return k(a,i(b))}function m(a,b){return k(a,j(b))}function n(a,b){return e(a,"padding","",b)}function o(a,b){return n(a,i(b))}function p(a,b){return n(a,j(b))}function q(a,b){return e(a,"border","Width",b)}function r(a,b){return q(a,i(b))}function s(a,b){return q(a,j(b))}function t(a,b){return o(a,b)+r(a,b)}function u(a,b){return p(a,b)+s(a,b)}function v(a,b){return r(a,b)+s(a,b)}function w(a,b){return l(a,b)+m(a,b)}function x(a,b){return t(a,b)+u(a,b)}function y(a){return"justifyContent"in a.style?a.style.justifyContent:"flex-start"}function z(a){return"alignContent"in a.style?a.style.alignContent:"flex-start"}function A(a,b){return"alignSelf"in b.style?b.style.alignSelf:"alignItems"in a.style?a.style.alignItems:"stretch"}function B(a,b){if(b===X){if(a===Y)return Z;if(a===Z)return Y}return a}function C(a,b){var c;return c="direction"in a.style?a.style.direction:V,c===V&&(c=void 0===b?W:b),c}function D(a){return"flexDirection"in a.style?a.style.flexDirection:$}function E(a,b){return h(a)?B(Y,b):$}function F(a){return"position"in a.style?a.style.position:"relative"}function G(a){return a.style.flex}function H(a){return F(a)===ia&&G(a)>0}function I(a){return"wrap"===a.style.flexWrap}function J(a,b){return a.layout[na[b]]+w(a,b)}function K(a,b){return!f(a.style[na[b]])&&a.style[na[b]]>=0}function L(a,b){return!f(a.style[b])}function M(a){return"measure"in a.style}function N(a,b){return b in a.style?a.style[b]:0}function O(a,b,c){var d={row:a.style.minWidth,"row-reverse":a.style.minWidth,column:a.style.minHeight,"column-reverse":a.style.minHeight}[b],e={row:a.style.maxWidth,"row-reverse":a.style.maxWidth,column:a.style.maxHeight,"column-reverse":a.style.maxHeight}[b],g=c;return!f(e)&&e>=0&&g>e&&(g=e),!f(d)&&d>=0&&d>g&&(g=d),g}function P(a,b){return a>b?a:b}function Q(a,b){f(a.layout[na[b]])&&K(a,b)&&(a.layout[na[b]]=P(O(a,b,a.style[na[b]]),x(a,b)))}function R(a,b,c){b.layout[la[c]]=a.layout[na[c]]-b.layout[na[c]]-b.layout[ma[c]]}function S(a,b){return ka[b]in a.style?N(a,ka[b]):-N(a,la[b])}function T(a,b,c){var d=C(a,c),e=B(D(a),d),h=E(e,d),i=B(Y,d);if(Q(a,e),Q(a,h),a.layout.direction=d,a.layout[ka[e]]+=l(a,e)+S(a,e),a.layout[la[e]]+=m(a,e)+S(a,e),a.layout[ka[h]]+=l(a,h)+S(a,h),a.layout[la[h]]+=m(a,h)+S(a,h),M(a)){var j=U;j=K(a,i)?a.style.width:f(a.layout[na[i]])?b-w(a,i):a.layout[na[i]],j-=x(a,i);var k=!K(a,i)&&f(a.layout[na[i]]),n=!K(a,$)&&f(a.layout[na[$]]);if(k||n){var o=a.style.measure(j);k&&(a.layout.width=o.width+x(a,i)),n&&(a.layout.height=o.height+x(a,$))}if(0===a.children.length)return}var p,q,s,V;for(p=0;pq;q++)V=0!==q?Y:$,!f(a.layout[na[V]])&&!K(s,V)&&L(s,ka[V])&&L(s,la[V])&&(s.layout[na[V]]=P(O(s,V,a.layout[na[V]]-x(a,V)-w(s,V)-N(s,ka[V])-N(s,la[V])),x(s,V)))}else s.layout[na[h]]=P(O(s,h,a.layout[na[h]]-x(a,h)-w(s,h)),x(s,h));var W=U;f(a.layout[na[e]])||(W=a.layout[na[e]]-x(a,e));for(var X=0,Z=0,_=0,oa=0,pa=0,qa=0;ZW&&p!==X){va--,_=1;break}_=0,sa+=wa,Z=p+1}var xa=0,ya=0,za=0;if(za=f(a.layout[na[e]])?P(sa,0)-sa:W-sa,0!==ta){var Aa,Ba,Ca=za/ua;for(p=X;Z>p;++p)s=a.children[p],H(s)&&(Aa=Ca*G(s)+x(s,e),Ba=O(s,e,Aa),Aa!==Ba&&(za-=Ba,ua-=G(s)));for(Ca=za/ua,0>Ca&&(Ca=0),p=X;Z>p;++p)s=a.children[p],H(s)&&(s.layout[na[e]]=O(s,e,Ca*G(s)+x(s,e)),ra=U,K(a,i)?ra=a.layout[na[i]]-x(a,i):g(e)||(ra=b-w(a,i)-x(a,i)),T(s,ra,d))}else{var Da=y(a);Da===aa?xa=za/2:Da===ba?xa=za:Da===ca?(za=P(za,0),ya=ta+va-1!==0?za/(ta+va-1):0):Da===da&&(ya=za/(ta+va),xa=ya/2)}var Ea=0,Fa=xa+t(a,e);for(p=X;Z>p;++p)s=a.children[p],s.lineIndex=qa,F(s)===ja&&L(s,ka[e])?s.layout[ma[e]]=N(s,ka[e])+r(a,e)+l(s,e):(s.layout[ma[e]]+=Fa,f(a.layout[na[e]])||R(a,s,e)),F(s)===ia&&(Fa+=ya+J(s,e),Ea=P(Ea,O(s,h,J(s,h))));var Ga=a.layout[na[h]];for(f(a.layout[na[h]])&&(Ga=P(O(a,h,Ea+x(a,h)),x(a,h))),p=X;Z>p;++p)if(s=a.children[p],F(s)===ja&&L(s,ka[h]))s.layout[ma[h]]=N(s,ka[h])+r(a,h)+l(s,h);else{var Ha=t(a,h);if(F(s)===ia){var Ia=A(a,s);if(Ia===ha)K(s,h)||(s.layout[na[h]]=P(O(s,h,Ga-x(a,h)-w(s,h)),x(s,h)));else if(Ia!==ea){var Ja=Ga-x(a,h)-J(s,h);Ha+=Ia===fa?Ja/2:Ja}}s.layout[ma[h]]+=oa+Ha,f(a.layout[na[h]])||R(a,s,h)}oa+=Ea,pa=P(pa,Fa),qa+=1,X=Z}if(qa>1&&!f(a.layout[na[h]])){var Ka=a.layout[na[h]]-x(a,h),La=Ka-oa,Ma=0,Na=t(a,h),Oa=z(a);Oa===ga?Na+=La:Oa===fa?Na+=La/2:Oa===ha&&Ka>oa&&(Ma=La/qa);var Pa=0;for(p=0;qa>p;++p){var Qa=Pa,Ra=0;for(q=Qa;qq;++q)if(s=a.children[q],F(s)===ia){var Sa=A(a,s);if(Sa===ea)s.layout[ma[h]]=Na+l(s,h);else if(Sa===ga)s.layout[ma[h]]=Na+Ra-m(s,h)-s.layout[na[h]];else if(Sa===fa){var Ta=s.layout[na[h]];s.layout[ma[h]]=Na+(Ra-Ta)/2}else Sa===ha&&(s.layout[ma[h]]=Na+l(s,h))}Na+=Ra}}var Ua=!1,Va=!1;if(f(a.layout[na[e]])&&(a.layout[na[e]]=P(O(a,e,pa+u(a,e)),x(a,e)),Ua=!0),f(a.layout[na[h]])&&(a.layout[na[h]]=P(O(a,h,oa+x(a,h)),x(a,h)),Va=!0),Ua||Va)for(p=0;pq;q++)V=0!==q?Y:$,!f(a.layout[na[V]])&&!K(s,V)&&L(s,ka[V])&&L(s,la[V])&&(s.layout[na[V]]=P(O(s,V,a.layout[na[V]]-v(a,V)-w(s,V)-N(s,ka[V])-N(s,la[V])),x(s,V)));for(q=0;2>q;q++)V=0!==q?Y:$,L(s,la[V])&&!L(s,ka[V])&&(s.layout[ka[V]]=a.layout[na[V]]-s.layout[na[V]]-N(s,la[V]))}}var U,V="inherit",W="ltr",X="rtl",Y="row",Z="row-reverse",$="column",_="column-reverse",aa="center",ba="flex-end",ca="space-between",da="space-around",ea="flex-start",fa="center",ga="flex-end",ha="stretch",ia="relative",ja="absolute",ka={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},la={row:"right","row-reverse":"left",column:"bottom","column-reverse":"top"},ma={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},na={row:"width","row-reverse":"width",column:"height","column-reverse":"height"};return{computeLayout:T,fillNodes:c,extractNodes:d}}();return"object"==typeof exports&&(module.exports=a),function(b){return b=a.fillNodes(b),a.computeLayout(b),b=a.extractNodes(b)}}); +//# sourceMappingURL=css-layout.min.js.map \ No newline at end of file diff --git a/dist/css-layout.min.js.map b/dist/css-layout.min.js.map new file mode 100644 index 00000000..b4cdec24 --- /dev/null +++ b/dist/css-layout.min.js.map @@ -0,0 +1 @@ +{"version":3,"file":"css-layout.min.js","sources":["css-layout.js"],"names":["root","factory","define","amd","exports","module","computeLayout","this","capitalizeFirst","str","charAt","toUpperCase","slice","getSpacing","node","type","suffix","locations","i","length","location","key","style","fillNodes","layout","width","undefined","height","top","left","right","bottom","children","measure","forEach","extractNodes","map","direction","getPositiveSpacing","isUndefined","value","isRowDirection","flexDirection","CSS_FLEX_DIRECTION_ROW","CSS_FLEX_DIRECTION_ROW_REVERSE","isColumnDirection","CSS_FLEX_DIRECTION_COLUMN","CSS_FLEX_DIRECTION_COLUMN_REVERSE","getLeadingLocations","axis","leading","unshift","getTrailingLocations","trailing","getMargin","getLeadingMargin","getTrailingMargin","getPadding","getLeadingPadding","getTrailingPadding","getBorder","getLeadingBorder","getTrailingBorder","getLeadingPaddingAndBorder","getTrailingPaddingAndBorder","getBorderAxis","getMarginAxis","getPaddingAndBorderAxis","getJustifyContent","justifyContent","getAlignContent","alignContent","getAlignItem","child","alignSelf","alignItems","resolveAxis","CSS_DIRECTION_RTL","resolveDirection","parentDirection","CSS_DIRECTION_INHERIT","CSS_DIRECTION_LTR","getFlexDirection","getCrossFlexDirection","getPositionType","position","getFlex","flex","isFlex","CSS_POSITION_RELATIVE","isFlexWrap","flexWrap","getDimWithMargin","dim","isDimDefined","isPosDefined","pos","isMeasureDefined","getPosition","boundAxis","min","row","minWidth","row-reverse","column","minHeight","column-reverse","max","maxWidth","maxHeight","boundValue","fmaxf","a","b","setDimensionFromStyle","setTrailingPosition","getRelativePosition","layoutNode","parentMaxWidth","mainAxis","crossAxis","resolvedRowAxis","CSS_UNDEFINED","isRowUndefined","isColumnUndefined","measureDim","ii","CSS_ALIGN_STRETCH","CSS_POSITION_ABSOLUTE","definedMainDim","startLine","endLine","alreadyComputedNextLayout","linesCrossDim","linesMainDim","linesCount","mainContentDim","flexibleChildrenCount","totalFlexible","nonFlexibleChildrenCount","nextContentDim","leadingMainDim","betweenMainDim","remainingMainDim","baseMainDim","boundMainDim","flexibleMainDim","CSS_JUSTIFY_CENTER","CSS_JUSTIFY_FLEX_END","CSS_JUSTIFY_SPACE_BETWEEN","CSS_JUSTIFY_SPACE_AROUND","crossDim","mainDim","lineIndex","containerCrossAxis","leadingCrossDim","alignItem","CSS_ALIGN_FLEX_START","remainingCrossDim","CSS_ALIGN_CENTER","nodeCrossAxisInnerSize","remainingAlignContentDim","crossDimLead","currentLead","CSS_ALIGN_FLEX_END","endIndex","startIndex","lineHeight","alignContentAlignItem","childHeight","needsMainTrailingPos","needsCrossTrailingPos"],"mappings":"CAKC,SAAUA,EAAMC,GACO,kBAAXC,SAAyBA,OAAOC,IAEzCD,UAAWD,GACiB,gBAAZG,SAIhBC,OAAOD,QAAUH,IAGjBD,EAAKM,cAAgBL,KAEvBM,KAAM,WAUR,GAAID,GAAgB,WAoDlB,QAASE,GAAgBC,GACvB,MAAOA,GAAIC,OAAO,GAAGC,cAAgBF,EAAIG,MAAM,GAGjD,QAASC,GAAWC,EAAMC,EAAMC,EAAQC,GACtC,IAAK,GAAIC,GAAI,EAAGA,EAAID,EAAUE,SAAUD,EAAG,CACzC,GAAIE,GAAWH,EAAUC,GAErBG,EAAMN,EAAOP,EAAgBY,GAAYJ,CAC7C,IAAIK,IAAOP,GAAKQ,MACd,MAAOR,GAAKQ,MAAMD,EAIpB,IADAA,EAAMN,EAAOC,EACTK,IAAOP,GAAKQ,MACd,MAAOR,GAAKQ,MAAMD,GAItB,MAAO,GAET,QAASE,GAAUT,GAiBjB,MAhBAA,GAAKU,QACHC,MAAOC,OACPC,OAAQD,OACRE,IAAK,EACLC,KAAM,EACNC,MAAO,EACPC,OAAQ,GAELjB,EAAKQ,QACRR,EAAKQ,YAGFR,EAAKkB,UAAYlB,EAAKQ,MAAMW,WAC/BnB,EAAKkB,aAEPlB,EAAKkB,SAASE,QAAQX,GACfT,EAGT,QAASqB,GAAarB,GACpB,GAAIU,GAASV,EAAKU,MAYlB,cAXOV,GAAKU,OACRV,EAAKkB,UAAYlB,EAAKkB,SAASb,OAAS,EAC1CK,EAAOQ,SAAWlB,EAAKkB,SAASI,IAAID,SAE7BrB,GAAKkB,eAGPR,GAAOM,YACPN,GAAOO,aACPP,GAAOa,UAEPb,EAGT,QAASc,GAAmBxB,EAAMC,EAAMC,EAAQC,GAC9C,IAAK,GAAIC,GAAI,EAAGA,EAAID,EAAUE,SAAUD,EAAG,CACzC,GAAIE,GAAWH,EAAUC,GAErBG,EAAMN,EAAOP,EAAgBY,GAAYJ,CAC7C,IAAIK,IAAOP,GAAKQ,OAASR,EAAKQ,MAAMD,IAAQ,EAC1C,MAAOP,GAAKQ,MAAMD,EAIpB,IADAA,EAAMN,EAAOC,EACTK,IAAOP,GAAKQ,OAASR,EAAKQ,MAAMD,IAAQ,EAC1C,MAAOP,GAAKQ,MAAMD,GAItB,MAAO,GAGT,QAASkB,GAAYC,GACnB,MAAiBd,UAAVc,EAGT,QAASC,GAAeC,GACtB,MAAOA,KAAkBC,GAClBD,IAAkBE,EAG3B,QAASC,GAAkBH,GACzB,MAAOA,KAAkBI,GAClBJ,IAAkBK,EAG3B,QAASC,GAAoBC,GAC3B,GAAIhC,IAAaiC,GAAQD,GAKzB,OAJIR,GAAeQ,IACjBhC,EAAUkC,QAAQ,SAGblC,EAGT,QAASmC,GAAqBH,GAC5B,GAAIhC,IAAaoC,GAASJ,GAK1B,OAJIR,GAAeQ,IACjBhC,EAAUkC,QAAQ,OAGblC,EAGT,QAASqC,GAAUxC,EAAMG,GACvB,MAAOJ,GAAWC,EAAM,SAAU,GAAIG,GAGxC,QAASsC,GAAiBzC,EAAMmC,GAC9B,MAAOK,GAAUxC,EAAMkC,EAAoBC,IAG7C,QAASO,GAAkB1C,EAAMmC,GAC/B,MAAOK,GAAUxC,EAAMsC,EAAqBH,IAG9C,QAASQ,GAAW3C,EAAMG,GACxB,MAAOqB,GAAmBxB,EAAM,UAAW,GAAIG,GAGjD,QAASyC,GAAkB5C,EAAMmC,GAC/B,MAAOQ,GAAW3C,EAAMkC,EAAoBC,IAG9C,QAASU,GAAmB7C,EAAMmC,GAChC,MAAOQ,GAAW3C,EAAMsC,EAAqBH,IAG/C,QAASW,GAAU9C,EAAMG,GACvB,MAAOqB,GAAmBxB,EAAM,SAAU,QAASG,GAGrD,QAAS4C,GAAiB/C,EAAMmC,GAC9B,MAAOW,GAAU9C,EAAMkC,EAAoBC,IAG7C,QAASa,GAAkBhD,EAAMmC,GAC/B,MAAOW,GAAU9C,EAAMsC,EAAqBH,IAG9C,QAASc,GAA2BjD,EAAMmC,GACxC,MAAOS,GAAkB5C,EAAMmC,GAAQY,EAAiB/C,EAAMmC,GAGhE,QAASe,GAA4BlD,EAAMmC,GACzC,MAAOU,GAAmB7C,EAAMmC,GAAQa,EAAkBhD,EAAMmC,GAGlE,QAASgB,GAAcnD,EAAMmC,GAC3B,MAAOY,GAAiB/C,EAAMmC,GAAQa,EAAkBhD,EAAMmC,GAGhE,QAASiB,GAAcpD,EAAMmC,GAC3B,MAAOM,GAAiBzC,EAAMmC,GAAQO,EAAkB1C,EAAMmC,GAGhE,QAASkB,GAAwBrD,EAAMmC,GACrC,MAAOc,GAA2BjD,EAAMmC,GACpCe,EAA4BlD,EAAMmC,GAGxC,QAASmB,GAAkBtD,GACzB,MAAI,kBAAoBA,GAAKQ,MACpBR,EAAKQ,MAAM+C,eAEb,aAGT,QAASC,GAAgBxD,GACvB,MAAI,gBAAkBA,GAAKQ,MAClBR,EAAKQ,MAAMiD,aAEb,aAGT,QAASC,GAAa1D,EAAM2D,GAC1B,MAAI,aAAeA,GAAMnD,MAChBmD,EAAMnD,MAAMoD,UAEjB,cAAgB5D,GAAKQ,MAChBR,EAAKQ,MAAMqD,WAEb,UAGT,QAASC,GAAY3B,EAAMZ,GACzB,GAAIA,IAAcwC,EAAmB,CACnC,GAAI5B,IAASN,EACX,MAAOC,EACF,IAAIK,IAASL,EAClB,MAAOD,GAIX,MAAOM,GAGT,QAAS6B,GAAiBhE,EAAMiE,GAC9B,GAAI1C,EAWJ,OATEA,GADE,aAAevB,GAAKQ,MACVR,EAAKQ,MAAMe,UAEX2C,EAGV3C,IAAc2C,IAChB3C,EAAiCX,SAApBqD,EAAgCE,EAAoBF,GAG5D1C,EAGT,QAAS6C,GAAiBpE,GACxB,MAAI,iBAAmBA,GAAKQ,MACnBR,EAAKQ,MAAMoB,cAEbI,EAGT,QAASqC,GAAsBzC,EAAeL,GAC5C,MAAIQ,GAAkBH,GACbkC,EAAYjC,EAAwBN,GAEpCS,EAIX,QAASsC,GAAgBtE,GACvB,MAAI,YAAcA,GAAKQ,MACdR,EAAKQ,MAAM+D,SAEb,WAGT,QAASC,GAAQxE,GACf,MAAOA,GAAKQ,MAAMiE,KAGpB,QAASC,GAAO1E,GACd,MACEsE,GAAgBtE,KAAU2E,IAC1BH,EAAQxE,GAAQ,EAIpB,QAAS4E,GAAW5E,GAClB,MAA+B,SAAxBA,EAAKQ,MAAMqE,SAGpB,QAASC,GAAiB9E,EAAMmC,GAC9B,MAAOnC,GAAKU,OAAOqE,GAAI5C,IAASiB,EAAcpD,EAAMmC,GAGtD,QAAS6C,GAAahF,EAAMmC,GAC1B,OAAQV,EAAYzB,EAAKQ,MAAMuE,GAAI5C,MAAWnC,EAAKQ,MAAMuE,GAAI5C,KAAU,EAGzE,QAAS8C,GAAajF,EAAMkF,GAC1B,OAAQzD,EAAYzB,EAAKQ,MAAM0E,IAGjC,QAASC,GAAiBnF,GACxB,MAAO,WAAaA,GAAKQ,MAG3B,QAAS4E,GAAYpF,EAAMkF,GACzB,MAAIA,KAAOlF,GAAKQ,MACPR,EAAKQ,MAAM0E,GAEb,EAGT,QAASG,GAAUrF,EAAMmC,EAAMT,GAC7B,GAAI4D,IACFC,IAAOvF,EAAKQ,MAAMgF,SAClBC,cAAezF,EAAKQ,MAAMgF,SAC1BE,OAAU1F,EAAKQ,MAAMmF,UACrBC,iBAAkB5F,EAAKQ,MAAMmF,WAC7BxD,GAEE0D,GACFN,IAAOvF,EAAKQ,MAAMsF,SAClBL,cAAezF,EAAKQ,MAAMsF,SAC1BJ,OAAU1F,EAAKQ,MAAMuF,UACrBH,iBAAkB5F,EAAKQ,MAAMuF,WAC7B5D,GAEE6D,EAAatE,CAOjB,QANKD,EAAYoE,IAAQA,GAAO,GAAKG,EAAaH,IAChDG,EAAaH,IAEVpE,EAAY6D,IAAQA,GAAO,GAAkBA,EAAbU,IACnCA,EAAaV,GAERU,EAGT,QAASC,GAAMC,EAAGC,GAChB,MAAID,GAAIC,EACCD,EAEFC,EAIT,QAASC,GAAsBpG,EAAMmC,GAE9BV,EAAYzB,EAAKU,OAAOqE,GAAI5C,MAI5B6C,EAAahF,EAAMmC,KAKxBnC,EAAKU,OAAOqE,GAAI5C,IAAS8D,EACvBZ,EAAUrF,EAAMmC,EAAMnC,EAAKQ,MAAMuE,GAAI5C,KACrCkB,EAAwBrD,EAAMmC,KAIlC,QAASkE,GAAoBrG,EAAM2D,EAAOxB,GACxCwB,EAAMjD,OAAO6B,GAASJ,IAASnC,EAAKU,OAAOqE,GAAI5C,IAC3CwB,EAAMjD,OAAOqE,GAAI5C,IAASwB,EAAMjD,OAAOwE,GAAI/C,IAKjD,QAASmE,GAAoBtG,EAAMmC,GACjC,MAAIC,IAAQD,IAASnC,GAAKQ,MACjB4E,EAAYpF,EAAMoC,GAAQD,KAE3BiD,EAAYpF,EAAMuC,GAASJ,IAGrC,QAASoE,GAAWvG,EAAMwG,EAAmCvC,GAC3D,GAAuB1C,GAAYyC,EAAiBhE,EAAMiE,GAC9BwC,EAAW3C,EAAYM,EAAiBpE,GAAOuB,GAC/CmF,EAAYrC,EAAsBoC,EAAUlF,GAC5CoF,EAAkB7C,EAAYjC,EAAwBN,EAoBlF,IAjBA6E,EAAsBpG,EAAMyG,GAC5BL,EAAsBpG,EAAM0G,GAG5B1G,EAAKU,OAAOa,UAAYA,EAIxBvB,EAAKU,OAAO0B,GAAQqE,KAAchE,EAAiBzC,EAAMyG,GACvDH,EAAoBtG,EAAMyG,GAC5BzG,EAAKU,OAAO6B,GAASkE,KAAc/D,EAAkB1C,EAAMyG,GACzDH,EAAoBtG,EAAMyG,GAC5BzG,EAAKU,OAAO0B,GAAQsE,KAAejE,EAAiBzC,EAAM0G,GACxDJ,EAAoBtG,EAAM0G,GAC5B1G,EAAKU,OAAO6B,GAASmE,KAAehE,EAAkB1C,EAAM0G,GAC1DJ,EAAoBtG,EAAM0G,GAExBvB,EAAiBnF,GAAO,CAC1B,GAAaW,GAAQiG,CAEnBjG,GADEqE,EAAahF,EAAM2G,GACb3G,EAAKQ,MAAMG,MACTc,EAAYzB,EAAKU,OAAOqE,GAAI4B,KAG9BH,EACNpD,EAAcpD,EAAM2G,GAHd3G,EAAKU,OAAOqE,GAAI4B,IAK1BhG,GAAS0C,EAAwBrD,EAAM2G,EAKvC,IAAYE,IAAkB7B,EAAahF,EAAM2G,IAC/ClF,EAAYzB,EAAKU,OAAOqE,GAAI4B,KAClBG,GAAqB9B,EAAahF,EAAMgC,IAClDP,EAAYzB,EAAKU,OAAOqE,GAAI/C,IAG9B,IAAI6E,GAAkBC,EAAmB,CACvC,GAAiBC,GAAa/G,EAAKQ,MAAMW,QAGvCR,EAEEkG,KACF7G,EAAKU,OAAOC,MAAQoG,EAAWpG,MAC7B0C,EAAwBrD,EAAM2G,IAE9BG,IACF9G,EAAKU,OAAOG,OAASkG,EAAWlG,OAC9BwC,EAAwBrD,EAAMgC,IAGpC,GAA6B,IAAzBhC,EAAKkB,SAASb,OAChB,OAIJ,GAAWD,GACA4G,EACQrD,EACSxB,CAG5B,KAAK/B,EAAI,EAAGA,EAAIJ,EAAKkB,SAASb,SAAUD,EAItC,GAHAuD,EAAQ3D,EAAKkB,SAASd,GAGlBsD,EAAa1D,EAAM2D,KAAWsD,IAC9B3C,EAAgBX,KAAWgB,IAC1BlD,EAAYzB,EAAKU,OAAOqE,GAAI2B,MAC5B1B,EAAarB,EAAO+C,IAQlB,GAAIpC,EAAgBX,KAAWuD,GAGpC,IAAKF,EAAK,EAAQ,EAALA,EAAQA,IACnB7E,EAAe,IAAP6E,EAAYnF,EAAyBG,GACxCP,EAAYzB,EAAKU,OAAOqE,GAAI5C,OAC5B6C,EAAarB,EAAOxB,IACrB8C,EAAatB,EAAOvB,GAAQD,KAC5B8C,EAAatB,EAAOpB,GAASJ,MAC/BwB,EAAMjD,OAAOqE,GAAI5C,IAAS8D,EACxBZ,EAAU1B,EAAOxB,EAAMnC,EAAKU,OAAOqE,GAAI5C,IACrCkB,EAAwBrD,EAAMmC,GAC9BiB,EAAcO,EAAOxB,GACrBiD,EAAYzB,EAAOvB,GAAQD,IAC3BiD,EAAYzB,EAAOpB,GAASJ,KAE9BkB,EAAwBM,EAAOxB,SAvBrCwB,GAAMjD,OAAOqE,GAAI2B,IAAcT,EAC7BZ,EAAU1B,EAAO+C,EAAW1G,EAAKU,OAAOqE,GAAI2B,IAC1CrD,EAAwBrD,EAAM0G,GAC9BtD,EAAcO,EAAO+C,IAEvBrD,EAAwBM,EAAO+C,GAyBrC,IAAaS,GAAiBP,CACzBnF,GAAYzB,EAAKU,OAAOqE,GAAI0B,OAC/BU,EAAiBnH,EAAKU,OAAOqE,GAAI0B,IAC7BpD,EAAwBrD,EAAMyG,GAYpC,KARA,GAAWW,GAAY,EACZC,EAAU,EAEVC,EAA4B,EAE1BC,GAAgB,EAChBC,GAAe,EACjBC,GAAa,EACjBJ,EAAUrH,EAAKkB,SAASb,QAAQ,CAOrC,GAQayF,IARA4B,GAAiB,EAInBC,GAAwB,EACtBC,GAAgB,EAClBC,GAA2B,CAGtC,KAAKzH,EAAIgH,EAAWhH,EAAIJ,EAAKkB,SAASb,SAAUD,EAAG,CACjDuD,EAAQ3D,EAAKkB,SAASd,EACtB,IAAa0H,IAAiB,CA2C9B,KAvCKrG,EAAYzB,EAAKU,OAAOqE,GAAI0B,MAAe/B,EAAOf,IACrDgE,KACAC,IAAiBpD,EAAQb,GAMzBmE,GAAiBzE,EAAwBM,EAAO8C,GAC9CrD,EAAcO,EAAO8C,KAGvBX,GAAWc,EACNjF,EAAe8E,KAClBX,GAAWU,EACTpD,EAAcpD,EAAM2G,GACpBtD,EAAwBrD,EAAM2G,GAE5B3B,EAAahF,EAAM2G,KACrBb,GAAW9F,EAAKU,OAAOqE,GAAI4B,IACzBtD,EAAwBrD,EAAM2G,KAKF,IAA9BW,GACFf,EAAqC5C,EAAOmC,GAAUvE,GAKpD+C,EAAgBX,KAAWgB,KAC7BkD,KAEAC,GAAiBhD,EAAiBnB,EAAO8C,KAKzC7B,EAAW5E,KACVyB,EAAYzB,EAAKU,OAAOqE,GAAI0B,MAC7BiB,GAAiBI,GAAiBX,GAGlC/G,IAAMgH,EAAW,CACnBS,KACAP,EAA4B,CAC5B,OAEFA,EAA4B,EAC5BI,IAAkBI,GAClBT,EAAUjH,EAAI,EAQhB,GAAa2H,IAAiB,EACjBC,GAAiB,EAGjBC,GAAmB,CAShC,IALEA,GAHGxG,EAAYzB,EAAKU,OAAOqE,GAAI0B,KAGZR,EAAMyB,GAAgB,GAAKA,GAF3BP,EAAiBO,GAOR,IAA1BC,GAA6B,CAC/B,GACaO,IACAC,GAFAC,GAAkBH,GAAmBL,EAOlD,KAAKxH,EAAIgH,EAAeC,EAAJjH,IAAeA,EACjCuD,EAAQ3D,EAAKkB,SAASd,GAClBsE,EAAOf,KACTuE,GAAcE,GAAkB5D,EAAQb,GACpCN,EAAwBM,EAAO8C,GACnC0B,GAAe9C,EAAU1B,EAAO8C,EAAUyB,IAEtCA,KAAgBC,KAClBF,IAAoBE,GACpBP,IAAiBpD,EAAQb,IAc/B,KAVAyE,GAAkBH,GAAmBL,GAIf,EAAlBQ,KACFA,GAAkB,GAKfhI,EAAIgH,EAAeC,EAAJjH,IAAeA,EACjCuD,EAAQ3D,EAAKkB,SAASd,GAClBsE,EAAOf,KAGTA,EAAMjD,OAAOqE,GAAI0B,IAAapB,EAAU1B,EAAO8C,EAC7C2B,GAAkB5D,EAAQb,GAASN,EAAwBM,EAAO8C,IAGpEX,GAAWc,EACP5B,EAAahF,EAAM2G,GACrBb,GAAW9F,EAAKU,OAAOqE,GAAI4B,IACzBtD,EAAwBrD,EAAM2G,GACtBhF,EAAe8E,KACzBX,GAAWU,EACTpD,EAAcpD,EAAM2G,GACpBtD,EAAwBrD,EAAM2G,IAIlCJ,EAAqC5C,EAAOmC,GAAUvE,QAMrD,CACL,GAAqBgC,IAAiBD,EAAkBtD,EACpDuD,MAAmB8E,GACrBN,GAAiBE,GAAmB,EAC3B1E,KAAmB+E,GAC5BP,GAAiBE,GACR1E,KAAmBgF,IAC5BN,GAAmBhC,EAAMgC,GAAkB,GAEzCD,GADEL,GAAwBE,GAA2B,IAAM,EAC1CI,IACdN,GAAwBE,GAA2B,GAErC,GAEVtE,KAAmBiF,KAE5BR,GAAiBC,IACdN,GAAwBE,IAC3BE,GAAiBC,GAAiB,GAUtC,GAAaS,IAAW,EACXC,GAAUX,GACrB9E,EAA2BjD,EAAMyG,EAEnC,KAAKrG,EAAIgH,EAAeC,EAAJjH,IAAeA,EACjCuD,EAAQ3D,EAAKkB,SAASd,GACtBuD,EAAMgF,UAAYlB,GAEdnD,EAAgBX,KAAWuD,IAC3BjC,EAAatB,EAAOvB,GAAQqE,IAI9B9C,EAAMjD,OAAOwE,GAAIuB,IAAarB,EAAYzB,EAAOvB,GAAQqE,IACvD1D,EAAiB/C,EAAMyG,GACvBhE,EAAiBkB,EAAO8C,IAI1B9C,EAAMjD,OAAOwE,GAAIuB,KAAciC,GAG1BjH,EAAYzB,EAAKU,OAAOqE,GAAI0B,MAC/BJ,EAAoBrG,EAAM2D,EAAO8C,IAOjCnC,EAAgBX,KAAWgB,KAG7B+D,IAAWV,GAAiBlD,EAAiBnB,EAAO8C,GAGpDgC,GAAWxC,EAAMwC,GAAUpD,EAAU1B,EAAO+C,EAAW5B,EAAiBnB,EAAO+C,KAInF,IAAakC,IAAqB5I,EAAKU,OAAOqE,GAAI2B,GAYlD,KAXIjF,EAAYzB,EAAKU,OAAOqE,GAAI2B,OAC9BkC,GAAqB3C,EAInBZ,EAAUrF,EAAM0G,EAAW+B,GAAWpF,EAAwBrD,EAAM0G,IACpErD,EAAwBrD,EAAM0G,KAK7BtG,EAAIgH,EAAeC,EAAJjH,IAAeA,EAGjC,GAFAuD,EAAQ3D,EAAKkB,SAASd,GAElBkE,EAAgBX,KAAWuD,IAC3BjC,EAAatB,EAAOvB,GAAQsE,IAI9B/C,EAAMjD,OAAOwE,GAAIwB,IAActB,EAAYzB,EAAOvB,GAAQsE,IACxD3D,EAAiB/C,EAAM0G,GACvBjE,EAAiBkB,EAAO+C,OAErB,CACL,GAAamC,IAAkB5F,EAA2BjD,EAAM0G,EAIhE,IAAIpC,EAAgBX,KAAWgB,GAAuB,CACpD,GAAmBmE,IAAYpF,EAAa1D,EAAM2D,EAClD,IAAImF,KAAc7B,GAGXjC,EAAarB,EAAO+C,KACvB/C,EAAMjD,OAAOqE,GAAI2B,IAAcT,EAC7BZ,EAAU1B,EAAO+C,EAAWkC,GAC1BvF,EAAwBrD,EAAM0G,GAC9BtD,EAAcO,EAAO+C,IAEvBrD,EAAwBM,EAAO+C,SAG9B,IAAIoC,KAAcC,GAAsB,CAG7C,GAAaC,IAAoBJ,GAC/BvF,EAAwBrD,EAAM0G,GAC9B5B,EAAiBnB,EAAO+C,EAGxBmC,KADEC,KAAcG,GACGD,GAAoB,EAEpBA,IAMzBrF,EAAMjD,OAAOwE,GAAIwB,KAAea,GAAgBsB,GAG3CpH,EAAYzB,EAAKU,OAAOqE,GAAI2B,MAC/BL,EAAoBrG,EAAM2D,EAAO+C,GAKvCa,IAAiBkB,GACjBjB,GAAevB,EAAMuB,GAAckB,IACnCjB,IAAc,EACdL,EAAYC,EAgBd,GAAII,GAAa,IACZhG,EAAYzB,EAAKU,OAAOqE,GAAI2B,KAAc,CAC7C,GAAawC,IAAyBlJ,EAAKU,OAAOqE,GAAI2B,IAClDrD,EAAwBrD,EAAM0G,GACrByC,GAA2BD,GAAyB3B,GAEpD6B,GAAe,EACfC,GAAcpG,EAA2BjD,EAAM0G,GAEzCjD,GAAeD,EAAgBxD,EAC9CyD,MAAiB6F,GACnBD,IAAeF,GACN1F,KAAiBwF,GAC1BI,IAAeF,GAA2B,EACjC1F,KAAiBwD,IACtBiC,GAAyB3B,KAC3B6B,GAAgBD,GAA2B1B,GAI/C,IAAW8B,IAAW,CACtB,KAAKnJ,EAAI,EAAOqH,GAAJrH,IAAkBA,EAAG,CAC/B,GAAWoJ,IAAaD,GAGXE,GAAa,CAC1B,KAAKzC,EAAKwC,GAAYxC,EAAKhH,EAAKkB,SAASb,SAAU2G,EAEjD,GADArD,EAAQ3D,EAAKkB,SAAS8F,GAClB1C,EAAgBX,KAAWgB,GAA/B,CAGA,GAAIhB,EAAMgF,YAAcvI,EACtB,KAEGqB,GAAYkC,EAAMjD,OAAOqE,GAAI2B,OAChC+C,GAAaxD,EACXwD,GACA9F,EAAMjD,OAAOqE,GAAI2B,IAActD,EAAcO,EAAO+C,KAO1D,IAHA6C,GAAWvC,EACXyC,IAAcL,GAETpC,EAAKwC,GAAiBD,GAALvC,IAAiBA,EAErC,GADArD,EAAQ3D,EAAKkB,SAAS8F,GAClB1C,EAAgBX,KAAWgB,GAA/B,CAIA,GAAmB+E,IAAwBhG,EAAa1D,EAAM2D,EAC9D,IAAI+F,KAA0BX,GAC5BpF,EAAMjD,OAAOwE,GAAIwB,IAAc2C,GAAc5G,EAAiBkB,EAAO+C,OAChE,IAAIgD,KAA0BJ,GACnC3F,EAAMjD,OAAOwE,GAAIwB,IAAc2C,GAAcI,GAAa/G,EAAkBiB,EAAO+C,GAAa/C,EAAMjD,OAAOqE,GAAI2B,QAC5G,IAAIgD,KAA0BT,GAAkB,CACrD,GAAaU,IAAchG,EAAMjD,OAAOqE,GAAI2B,GAC5C/C,GAAMjD,OAAOwE,GAAIwB,IAAc2C,IAAeI,GAAaE,IAAe,MACjED,MAA0BzC,KACnCtD,EAAMjD,OAAOwE,GAAIwB,IAAc2C,GAAc5G,EAAiBkB,EAAO+C,IAMzE2C,IAAeI,IAInB,GAAYG,KAAuB,EACvBC,IAAwB,CA6BpC,IAzBIpI,EAAYzB,EAAKU,OAAOqE,GAAI0B,OAC9BzG,EAAKU,OAAOqE,GAAI0B,IAAaR,EAG3BZ,EAAUrF,EAAMyG,EAAUe,GAAetE,EAA4BlD,EAAMyG,IAE3EpD,EAAwBrD,EAAMyG,IAGhCmD,IAAuB,GAGrBnI,EAAYzB,EAAKU,OAAOqE,GAAI2B,OAC9B1G,EAAKU,OAAOqE,GAAI2B,IAAcT,EAI5BZ,EAAUrF,EAAM0G,EAAWa,GAAgBlE,EAAwBrD,EAAM0G,IACzErD,EAAwBrD,EAAM0G,IAGhCmD,IAAwB,GAItBD,IAAwBC,GAC1B,IAAKzJ,EAAI,EAAGA,EAAIJ,EAAKkB,SAASb,SAAUD,EACtCuD,EAAQ3D,EAAKkB,SAASd,GAElBwJ,IACFvD,EAAoBrG,EAAM2D,EAAO8C,GAG/BoD,IACFxD,EAAoBrG,EAAM2D,EAAO+C,EAMvC,KAAKtG,EAAI,EAAGA,EAAIJ,EAAKkB,SAASb,SAAUD,EAEtC,GADAuD,EAAQ3D,EAAKkB,SAASd,GAClBkE,EAAgBX,KAAWuD,GAAuB,CAGpD,IAAKF,EAAK,EAAQ,EAALA,EAAQA,IACnB7E,EAAe,IAAP6E,EAAYnF,EAAyBG,GACxCP,EAAYzB,EAAKU,OAAOqE,GAAI5C,OAC5B6C,EAAarB,EAAOxB,IACrB8C,EAAatB,EAAOvB,GAAQD,KAC5B8C,EAAatB,EAAOpB,GAASJ,MAC/BwB,EAAMjD,OAAOqE,GAAI5C,IAAS8D,EACxBZ,EAAU1B,EAAOxB,EAAMnC,EAAKU,OAAOqE,GAAI5C,IACrCgB,EAAcnD,EAAMmC,GACpBiB,EAAcO,EAAOxB,GACrBiD,EAAYzB,EAAOvB,GAAQD,IAC3BiD,EAAYzB,EAAOpB,GAASJ,KAG9BkB,EAAwBM,EAAOxB,IAIrC,KAAK6E,EAAK,EAAQ,EAALA,EAAQA,IACnB7E,EAAe,IAAP6E,EAAYnF,EAAyBG,EACzCiD,EAAatB,EAAOpB,GAASJ,MAC5B8C,EAAatB,EAAOvB,GAAQD,MAC/BwB,EAAMjD,OAAO0B,GAAQD,IACnBnC,EAAKU,OAAOqE,GAAI5C,IAChBwB,EAAMjD,OAAOqE,GAAI5C,IACjBiD,EAAYzB,EAAOpB,GAASJ,MAn8BxC,GAAIyE,GAEA1C,EAAwB,UACxBC,EAAoB,MACpBJ,EAAoB,MAEpBlC,EAAyB,MACzBC,EAAiC,cACjCE,EAA4B,SAC5BC,EAAoC,iBAGpCoG,GAAqB,SACrBC,GAAuB,WACvBC,GAA4B,gBAC5BC,GAA2B,eAE3BO,GAAuB,aACvBE,GAAmB,SACnBK,GAAqB,WACrBrC,GAAoB,UAEpBtC,GAAwB,WACxBuC,GAAwB,WAExB9E,IACFmD,IAAO,OACPE,cAAe,QACfC,OAAU,MACVE,iBAAkB,UAEhBrD,IACFgD,IAAO,QACPE,cAAe,OACfC,OAAU,SACVE,iBAAkB,OAEhBV,IACFK,IAAO,OACPE,cAAe,QACfC,OAAU,MACVE,iBAAkB,UAEhBb,IACFQ,IAAO,QACPE,cAAe,QACfC,OAAU,SACVE,iBAAkB,SA25BpB,QACEpG,cAAe+G,EACf9F,UAAWA,EACXY,aAAcA,KAQd,OAJmB,gBAAZ/B,WACTC,OAAOD,QAAUE,GAGR,SAASQ,GAId,MAHAA,GAAOR,EAAciB,UAAUT,GAC/BR,EAAcA,cAAcQ,GAC5BA,EAAOR,EAAc6B,aAAarB","sourcesContent":["// UMD (Universal Module Definition)\n// See https://github.com/umdjs/umd for reference\n//\n// This file uses the following specific UMD implementation:\n// https://github.com/umdjs/umd/blob/master/returnExports.js\n(function (root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define([], factory);\n } else if (typeof exports === 'object') {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory();\n } else {\n // Browser globals (root is window)\n root.computeLayout = factory();\n }\n}(this, function () {\n /**\n * Copyright (c) 2014, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nvar computeLayout = (function() {\n\n var CSS_UNDEFINED;\n\n var CSS_DIRECTION_INHERIT = 'inherit';\n var CSS_DIRECTION_LTR = 'ltr';\n var CSS_DIRECTION_RTL = 'rtl';\n\n var CSS_FLEX_DIRECTION_ROW = 'row';\n var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';\n var CSS_FLEX_DIRECTION_COLUMN = 'column';\n var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';\n\n // var CSS_JUSTIFY_FLEX_START = 'flex-start';\n var CSS_JUSTIFY_CENTER = 'center';\n var CSS_JUSTIFY_FLEX_END = 'flex-end';\n var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between';\n var CSS_JUSTIFY_SPACE_AROUND = 'space-around';\n\n var CSS_ALIGN_FLEX_START = 'flex-start';\n var CSS_ALIGN_CENTER = 'center';\n var CSS_ALIGN_FLEX_END = 'flex-end';\n var CSS_ALIGN_STRETCH = 'stretch';\n\n var CSS_POSITION_RELATIVE = 'relative';\n var CSS_POSITION_ABSOLUTE = 'absolute';\n\n var leading = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var trailing = {\n 'row': 'right',\n 'row-reverse': 'left',\n 'column': 'bottom',\n 'column-reverse': 'top'\n };\n var pos = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var dim = {\n 'row': 'width',\n 'row-reverse': 'width',\n 'column': 'height',\n 'column-reverse': 'height'\n };\n\n function capitalizeFirst(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n }\n\n function getSpacing(node, type, suffix, locations) {\n for (var i = 0; i < locations.length; ++i) {\n var location = locations[i];\n\n var key = type + capitalizeFirst(location) + suffix;\n if (key in node.style) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style) {\n return node.style[key];\n }\n }\n\n return 0;\n }\n function fillNodes(node) {\n node.layout = {\n width: undefined,\n height: undefined,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n };\n if (!node.style) {\n node.style = {};\n }\n\n if (!node.children || node.style.measure) {\n node.children = [];\n }\n node.children.forEach(fillNodes);\n return node;\n }\n\n function extractNodes(node) {\n var layout = node.layout;\n delete node.layout;\n if (node.children && node.children.length > 0) {\n layout.children = node.children.map(extractNodes);\n } else {\n delete node.children;\n }\n\n delete layout.right;\n delete layout.bottom;\n delete layout.direction;\n\n return layout;\n }\n\n function getPositiveSpacing(node, type, suffix, locations) {\n for (var i = 0; i < locations.length; ++i) {\n var location = locations[i];\n\n var key = type + capitalizeFirst(location) + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n }\n\n return 0;\n }\n\n function isUndefined(value) {\n return value === undefined;\n }\n\n function isRowDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_ROW ||\n flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;\n }\n\n function isColumnDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||\n flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;\n }\n\n function getLeadingLocations(axis) {\n var locations = [leading[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('start');\n }\n\n return locations;\n }\n\n function getTrailingLocations(axis) {\n var locations = [trailing[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('end');\n }\n\n return locations;\n }\n\n function getMargin(node, locations) {\n return getSpacing(node, 'margin', '', locations);\n }\n\n function getLeadingMargin(node, axis) {\n return getMargin(node, getLeadingLocations(axis));\n }\n\n function getTrailingMargin(node, axis) {\n return getMargin(node, getTrailingLocations(axis));\n }\n\n function getPadding(node, locations) {\n return getPositiveSpacing(node, 'padding', '', locations);\n }\n\n function getLeadingPadding(node, axis) {\n return getPadding(node, getLeadingLocations(axis));\n }\n\n function getTrailingPadding(node, axis) {\n return getPadding(node, getTrailingLocations(axis));\n }\n\n function getBorder(node, locations) {\n return getPositiveSpacing(node, 'border', 'Width', locations);\n }\n\n function getLeadingBorder(node, axis) {\n return getBorder(node, getLeadingLocations(axis));\n }\n\n function getTrailingBorder(node, axis) {\n return getBorder(node, getTrailingLocations(axis));\n }\n\n function getLeadingPaddingAndBorder(node, axis) {\n return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);\n }\n\n function getTrailingPaddingAndBorder(node, axis) {\n return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);\n }\n\n function getBorderAxis(node, axis) {\n return getLeadingBorder(node, axis) + getTrailingBorder(node, axis);\n }\n\n function getMarginAxis(node, axis) {\n return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);\n }\n\n function getPaddingAndBorderAxis(node, axis) {\n return getLeadingPaddingAndBorder(node, axis) +\n getTrailingPaddingAndBorder(node, axis);\n }\n\n function getJustifyContent(node) {\n if ('justifyContent' in node.style) {\n return node.style.justifyContent;\n }\n return 'flex-start';\n }\n\n function getAlignContent(node) {\n if ('alignContent' in node.style) {\n return node.style.alignContent;\n }\n return 'flex-start';\n }\n\n function getAlignItem(node, child) {\n if ('alignSelf' in child.style) {\n return child.style.alignSelf;\n }\n if ('alignItems' in node.style) {\n return node.style.alignItems;\n }\n return 'stretch';\n }\n\n function resolveAxis(axis, direction) {\n if (direction === CSS_DIRECTION_RTL) {\n if (axis === CSS_FLEX_DIRECTION_ROW) {\n return CSS_FLEX_DIRECTION_ROW_REVERSE;\n } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {\n return CSS_FLEX_DIRECTION_ROW;\n }\n }\n\n return axis;\n }\n\n function resolveDirection(node, parentDirection) {\n var direction;\n if ('direction' in node.style) {\n direction = node.style.direction;\n } else {\n direction = CSS_DIRECTION_INHERIT;\n }\n\n if (direction === CSS_DIRECTION_INHERIT) {\n direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection);\n }\n\n return direction;\n }\n\n function getFlexDirection(node) {\n if ('flexDirection' in node.style) {\n return node.style.flexDirection;\n }\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n\n function getCrossFlexDirection(flexDirection, direction) {\n if (isColumnDirection(flexDirection)) {\n return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n } else {\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n }\n\n function getPositionType(node) {\n if ('position' in node.style) {\n return node.style.position;\n }\n return 'relative';\n }\n\n function getFlex(node) {\n return node.style.flex;\n }\n\n function isFlex(node) {\n return (\n getPositionType(node) === CSS_POSITION_RELATIVE &&\n getFlex(node) > 0\n );\n }\n\n function isFlexWrap(node) {\n return node.style.flexWrap === 'wrap';\n }\n\n function getDimWithMargin(node, axis) {\n return node.layout[dim[axis]] + getMarginAxis(node, axis);\n }\n\n function isDimDefined(node, axis) {\n return !isUndefined(node.style[dim[axis]]) && node.style[dim[axis]] >= 0;\n }\n\n function isPosDefined(node, pos) {\n return !isUndefined(node.style[pos]);\n }\n\n function isMeasureDefined(node) {\n return 'measure' in node.style;\n }\n\n function getPosition(node, pos) {\n if (pos in node.style) {\n return node.style[pos];\n }\n return 0;\n }\n\n function boundAxis(node, axis, value) {\n var min = {\n 'row': node.style.minWidth,\n 'row-reverse': node.style.minWidth,\n 'column': node.style.minHeight,\n 'column-reverse': node.style.minHeight\n }[axis];\n\n var max = {\n 'row': node.style.maxWidth,\n 'row-reverse': node.style.maxWidth,\n 'column': node.style.maxHeight,\n 'column-reverse': node.style.maxHeight\n }[axis];\n\n var boundValue = value;\n if (!isUndefined(max) && max >= 0 && boundValue > max) {\n boundValue = max;\n }\n if (!isUndefined(min) && min >= 0 && boundValue < min) {\n boundValue = min;\n }\n return boundValue;\n }\n\n function fmaxf(a, b) {\n if (a > b) {\n return a;\n }\n return b;\n }\n\n // When the user specifically sets a value for width or height\n function setDimensionFromStyle(node, axis) {\n // The parent already computed us a width or height. We just skip it\n if (!isUndefined(node.layout[dim[axis]])) {\n return;\n }\n // We only run if there's a width or height defined\n if (!isDimDefined(node, axis)) {\n return;\n }\n\n // The dimensions can never be smaller than the padding and border\n node.layout[dim[axis]] = fmaxf(\n boundAxis(node, axis, node.style[dim[axis]]),\n getPaddingAndBorderAxis(node, axis)\n );\n }\n\n function setTrailingPosition(node, child, axis) {\n child.layout[trailing[axis]] = node.layout[dim[axis]] -\n child.layout[dim[axis]] - child.layout[pos[axis]];\n }\n\n // If both left and right are defined, then use left. Otherwise return\n // +left or -right depending on which is defined.\n function getRelativePosition(node, axis) {\n if (leading[axis] in node.style) {\n return getPosition(node, leading[axis]);\n }\n return -getPosition(node, trailing[axis]);\n }\n\n function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) {\n var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);\n var/*css_flex_direction_t*/ mainAxis = resolveAxis(getFlexDirection(node), direction);\n var/*css_flex_direction_t*/ crossAxis = getCrossFlexDirection(mainAxis, direction);\n var/*css_flex_direction_t*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n\n // Handle width and height style attributes\n setDimensionFromStyle(node, mainAxis);\n setDimensionFromStyle(node, crossAxis);\n\n // Set the resolved resolution in the node's layout\n node.layout.direction = direction;\n\n // The position is set by the parent, but we need to complete it with a\n // delta composed of the margin and left/top/right/bottom\n node.layout[leading[mainAxis]] += getLeadingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[trailing[mainAxis]] += getTrailingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[leading[crossAxis]] += getLeadingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n node.layout[trailing[crossAxis]] += getTrailingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n\n if (isMeasureDefined(node)) {\n var/*float*/ width = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n width = node.style.width;\n } else if (!isUndefined(node.layout[dim[resolvedRowAxis]])) {\n width = node.layout[dim[resolvedRowAxis]];\n } else {\n width = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis);\n }\n width -= getPaddingAndBorderAxis(node, resolvedRowAxis);\n\n // We only need to give a dimension for the text if we haven't got any\n // for it computed yet. It can either be from the style attribute or because\n // the element is flexible.\n var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) &&\n isUndefined(node.layout[dim[resolvedRowAxis]]);\n var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&\n isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);\n\n // Let's not measure the text if we already know both dimensions\n if (isRowUndefined || isColumnUndefined) {\n var/*css_dim_t*/ measureDim = node.style.measure(\n /*(c)!node->context,*/\n /*(java)!layoutContext.measureOutput,*/\n width\n );\n if (isRowUndefined) {\n node.layout.width = measureDim.width +\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n }\n if (isColumnUndefined) {\n node.layout.height = measureDim.height +\n getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n }\n }\n if (node.children.length === 0) {\n return;\n }\n }\n\n var/*int*/ i;\n var/*int*/ ii;\n var/*css_node_t**/ child;\n var/*css_flex_direction_t*/ axis;\n\n // Pre-fill some dimensions straight from the parent\n for (i = 0; i < node.children.length; ++i) {\n child = node.children[i];\n // Pre-fill cross axis dimensions when the child is using stretch before\n // we call the recursive layout pass\n if (getAlignItem(node, child) === CSS_ALIGN_STRETCH &&\n getPositionType(child) === CSS_POSITION_RELATIVE &&\n !isUndefined(node.layout[dim[crossAxis]]) &&\n !isDimDefined(child, crossAxis)) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, node.layout[dim[crossAxis]] -\n getPaddingAndBorderAxis(node, crossAxis) -\n getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both\n // left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(child, axis) &&\n isPosDefined(child, leading[axis]) &&\n isPosDefined(child, trailing[axis])) {\n child.layout[dim[axis]] = fmaxf(\n boundAxis(child, axis, node.layout[dim[axis]] -\n getPaddingAndBorderAxis(node, axis) -\n getMarginAxis(child, axis) -\n getPosition(child, leading[axis]) -\n getPosition(child, trailing[axis])),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, axis)\n );\n }\n }\n }\n }\n\n var/*float*/ definedMainDim = CSS_UNDEFINED;\n if (!isUndefined(node.layout[dim[mainAxis]])) {\n definedMainDim = node.layout[dim[mainAxis]] -\n getPaddingAndBorderAxis(node, mainAxis);\n }\n\n // We want to execute the next two loops one per line with flex-wrap\n var/*int*/ startLine = 0;\n var/*int*/ endLine = 0;\n // var/*int*/ nextOffset = 0;\n var/*int*/ alreadyComputedNextLayout = 0;\n // We aggregate the total dimensions of the container in those two variables\n var/*float*/ linesCrossDim = 0;\n var/*float*/ linesMainDim = 0;\n var/*int*/ linesCount = 0;\n while (endLine < node.children.length) {\n // Layout non flexible children and count children by type\n\n // mainContentDim is accumulation of the dimensions and margin of all the\n // non flexible children. This will be used in order to either set the\n // dimensions of the node if none already exist, or to compute the\n // remaining space left for the flexible children.\n var/*float*/ mainContentDim = 0;\n\n // There are three kind of children, non flexible, flexible and absolute.\n // We need to know how many there are in order to distribute the space.\n var/*int*/ flexibleChildrenCount = 0;\n var/*float*/ totalFlexible = 0;\n var/*int*/ nonFlexibleChildrenCount = 0;\n\n var/*float*/ maxWidth;\n for (i = startLine; i < node.children.length; ++i) {\n child = node.children[i];\n var/*float*/ nextContentDim = 0;\n\n // It only makes sense to consider a child flexible if we have a computed\n // dimension for the node.\n if (!isUndefined(node.layout[dim[mainAxis]]) && isFlex(child)) {\n flexibleChildrenCount++;\n totalFlexible += getFlex(child);\n\n // Even if we don't know its exact size yet, we already know the padding,\n // border and margin. We'll use this partial information, which represents\n // the smallest possible size for the child, to compute the remaining\n // available space.\n nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +\n getMarginAxis(child, mainAxis);\n\n } else {\n maxWidth = CSS_UNDEFINED;\n if (!isRowDirection(mainAxis)) {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n }\n }\n\n // This is the main recursive call. We layout non flexible children.\n if (alreadyComputedNextLayout === 0) {\n layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);\n }\n\n // Absolute positioned elements do not take part of the layout, so we\n // don't use them to compute mainContentDim\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n nonFlexibleChildrenCount++;\n // At this point we know the final size and margin of the element.\n nextContentDim = getDimWithMargin(child, mainAxis);\n }\n }\n\n // The element we are about to add would make us go to the next line\n if (isFlexWrap(node) &&\n !isUndefined(node.layout[dim[mainAxis]]) &&\n mainContentDim + nextContentDim > definedMainDim &&\n // If there's only one element, then it's bigger than the content\n // and needs its own line\n i !== startLine) {\n nonFlexibleChildrenCount--;\n alreadyComputedNextLayout = 1;\n break;\n }\n alreadyComputedNextLayout = 0;\n mainContentDim += nextContentDim;\n endLine = i + 1;\n }\n\n // Layout flexible children and allocate empty space\n\n // In order to position the elements in the main axis, we have two\n // controls. The space between the beginning and the first element\n // and the space between each two elements.\n var/*float*/ leadingMainDim = 0;\n var/*float*/ betweenMainDim = 0;\n\n // The remaining available space that needs to be allocated\n var/*float*/ remainingMainDim = 0;\n if (!isUndefined(node.layout[dim[mainAxis]])) {\n remainingMainDim = definedMainDim - mainContentDim;\n } else {\n remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;\n }\n\n // If there are flexible children in the mix, they are going to fill the\n // remaining space\n if (flexibleChildrenCount !== 0) {\n var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible;\n var/*float*/ baseMainDim;\n var/*float*/ boundMainDim;\n\n // Iterate over every child in the axis. If the flex share of remaining\n // space doesn't meet min/max bounds, remove this child from flex\n // calculations.\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n if (isFlex(child)) {\n baseMainDim = flexibleMainDim * getFlex(child) +\n getPaddingAndBorderAxis(child, mainAxis);\n boundMainDim = boundAxis(child, mainAxis, baseMainDim);\n\n if (baseMainDim !== boundMainDim) {\n remainingMainDim -= boundMainDim;\n totalFlexible -= getFlex(child);\n }\n }\n }\n flexibleMainDim = remainingMainDim / totalFlexible;\n\n // The non flexible children can overflow the container, in this case\n // we should just assume that there is no space available.\n if (flexibleMainDim < 0) {\n flexibleMainDim = 0;\n }\n // We iterate over the full array and only apply the action on flexible\n // children. This is faster than actually allocating a new array that\n // contains only flexible children.\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n if (isFlex(child)) {\n // At this point we know the final size of the element in the main\n // dimension\n child.layout[dim[mainAxis]] = boundAxis(child, mainAxis,\n flexibleMainDim * getFlex(child) + getPaddingAndBorderAxis(child, mainAxis)\n );\n\n maxWidth = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n } else if (!isRowDirection(mainAxis)) {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n getPaddingAndBorderAxis(node, resolvedRowAxis);\n }\n\n // And we recursively call the layout algorithm for this child\n layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);\n }\n }\n\n // We use justifyContent to figure out how to allocate the remaining\n // space available\n } else {\n var/*css_justify_t*/ justifyContent = getJustifyContent(node);\n if (justifyContent === CSS_JUSTIFY_CENTER) {\n leadingMainDim = remainingMainDim / 2;\n } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {\n leadingMainDim = remainingMainDim;\n } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {\n remainingMainDim = fmaxf(remainingMainDim, 0);\n if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) {\n betweenMainDim = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount - 1);\n } else {\n betweenMainDim = 0;\n }\n } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) {\n // Space on the edges is half of the space between elements\n betweenMainDim = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount);\n leadingMainDim = betweenMainDim / 2;\n }\n }\n\n // Position elements in the main axis and compute dimensions\n\n // At this point, all the children have their dimensions set. We need to\n // find their position. In order to do that, we accumulate data in\n // variables that are also useful to compute the total dimensions of the\n // container!\n var/*float*/ crossDim = 0;\n var/*float*/ mainDim = leadingMainDim +\n getLeadingPaddingAndBorder(node, mainAxis);\n\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n child.lineIndex = linesCount;\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[mainAxis])) {\n // In case the child is position absolute and has left/top being\n // defined, we override the position to whatever the user said\n // (and margin/border).\n child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +\n getLeadingBorder(node, mainAxis) +\n getLeadingMargin(child, mainAxis);\n } else {\n // If the child is position absolute (without top/left) or relative,\n // we put it at the current accumulated offset.\n child.layout[pos[mainAxis]] += mainDim;\n\n // Define the trailing position accordingly.\n if (!isUndefined(node.layout[dim[mainAxis]])) {\n setTrailingPosition(node, child, mainAxis);\n }\n }\n\n // Now that we placed the element, we need to update the variables\n // We only need to do that for relative elements. Absolute elements\n // do not take part in that phase.\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n // The main dimension is the sum of all the elements dimension plus\n // the spacing.\n mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);\n // The cross dimension is the max of the elements dimension since there\n // can only be one element in that cross dimension.\n crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));\n }\n }\n\n var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]];\n if (isUndefined(node.layout[dim[crossAxis]])) {\n containerCrossAxis = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, crossDim + getPaddingAndBorderAxis(node, crossAxis)),\n getPaddingAndBorderAxis(node, crossAxis)\n );\n }\n\n // Position elements in the cross axis\n for (i = startLine; i < endLine; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[crossAxis])) {\n // In case the child is absolutely positionned and has a\n // top/left/bottom/right being set, we override all the previously\n // computed positions to set it correctly.\n child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +\n getLeadingBorder(node, crossAxis) +\n getLeadingMargin(child, crossAxis);\n\n } else {\n var/*float*/ leadingCrossDim = getLeadingPaddingAndBorder(node, crossAxis);\n\n // For a relative children, we're either using alignItems (parent) or\n // alignSelf (child) in order to determine the position in the cross axis\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n if (alignItem === CSS_ALIGN_STRETCH) {\n // You can only stretch if the dimension has not already been set\n // previously.\n if (!isDimDefined(child, crossAxis)) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, containerCrossAxis -\n getPaddingAndBorderAxis(node, crossAxis) -\n getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n }\n } else if (alignItem !== CSS_ALIGN_FLEX_START) {\n // The remaining space between the parent dimensions+padding and child\n // dimensions+margin.\n var/*float*/ remainingCrossDim = containerCrossAxis -\n getPaddingAndBorderAxis(node, crossAxis) -\n getDimWithMargin(child, crossAxis);\n\n if (alignItem === CSS_ALIGN_CENTER) {\n leadingCrossDim += remainingCrossDim / 2;\n } else { // CSS_ALIGN_FLEX_END\n leadingCrossDim += remainingCrossDim;\n }\n }\n }\n\n // And we apply the position\n child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim;\n\n // Define the trailing position accordingly.\n if (!isUndefined(node.layout[dim[crossAxis]])) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n\n linesCrossDim += crossDim;\n linesMainDim = fmaxf(linesMainDim, mainDim);\n linesCount += 1;\n startLine = endLine;\n }\n\n // \n //\n // Note(prenaux): More than one line, we need to layout the crossAxis\n // according to alignContent.\n //\n // Note that we could probably remove and handle the one line case\n // here too, but for the moment this is safer since it won't interfere with\n // previously working code.\n //\n // See specs:\n // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm\n // section 9.4\n //\n if (linesCount > 1 &&\n !isUndefined(node.layout[dim[crossAxis]])) {\n var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] -\n getPaddingAndBorderAxis(node, crossAxis);\n var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;\n\n var/*float*/ crossDimLead = 0;\n var/*float*/ currentLead = getLeadingPaddingAndBorder(node, crossAxis);\n\n var/*css_align_t*/ alignContent = getAlignContent(node);\n if (alignContent === CSS_ALIGN_FLEX_END) {\n currentLead += remainingAlignContentDim;\n } else if (alignContent === CSS_ALIGN_CENTER) {\n currentLead += remainingAlignContentDim / 2;\n } else if (alignContent === CSS_ALIGN_STRETCH) {\n if (nodeCrossAxisInnerSize > linesCrossDim) {\n crossDimLead = (remainingAlignContentDim / linesCount);\n }\n }\n\n var/*int*/ endIndex = 0;\n for (i = 0; i < linesCount; ++i) {\n var/*int*/ startIndex = endIndex;\n\n // compute the line's height and find the endIndex\n var/*float*/ lineHeight = 0;\n for (ii = startIndex; ii < node.children.length; ++ii) {\n child = node.children[ii];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n if (child.lineIndex !== i) {\n break;\n }\n if (!isUndefined(child.layout[dim[crossAxis]])) {\n lineHeight = fmaxf(\n lineHeight,\n child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis)\n );\n }\n }\n endIndex = ii;\n lineHeight += crossDimLead;\n\n for (ii = startIndex; ii < endIndex; ++ii) {\n child = node.children[ii];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n\n var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child);\n if (alignContentAlignItem === CSS_ALIGN_FLEX_START) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) {\n child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[dim[crossAxis]];\n } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {\n var/*float*/ childHeight = child.layout[dim[crossAxis]];\n child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;\n } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n // TODO(prenaux): Correctly set the height of items with undefined\n // (auto) crossAxis dimension.\n }\n }\n\n currentLead += lineHeight;\n }\n }\n\n var/*bool*/ needsMainTrailingPos = false;\n var/*bool*/ needsCrossTrailingPos = false;\n\n // If the user didn't specify a width or height, and it has not been set\n // by the container, then we set it via the children.\n if (isUndefined(node.layout[dim[mainAxis]])) {\n node.layout[dim[mainAxis]] = fmaxf(\n // We're missing the last padding at this point to get the final\n // dimension\n boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),\n // We can never assign a width smaller than the padding and borders\n getPaddingAndBorderAxis(node, mainAxis)\n );\n\n needsMainTrailingPos = true;\n }\n\n if (isUndefined(node.layout[dim[crossAxis]])) {\n node.layout[dim[crossAxis]] = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, linesCrossDim + getPaddingAndBorderAxis(node, crossAxis)),\n getPaddingAndBorderAxis(node, crossAxis)\n );\n\n needsCrossTrailingPos = true;\n }\n\n // Set trailing position if necessary\n if (needsMainTrailingPos || needsCrossTrailingPos) {\n for (i = 0; i < node.children.length; ++i) {\n child = node.children[i];\n\n if (needsMainTrailingPos) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n if (needsCrossTrailingPos) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n\n // Calculate dimensions for absolutely positioned elements\n for (i = 0; i < node.children.length; ++i) {\n child = node.children[i];\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both\n // left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(child, axis) &&\n isPosDefined(child, leading[axis]) &&\n isPosDefined(child, trailing[axis])) {\n child.layout[dim[axis]] = fmaxf(\n boundAxis(child, axis, node.layout[dim[axis]] -\n getBorderAxis(node, axis) -\n getMarginAxis(child, axis) -\n getPosition(child, leading[axis]) -\n getPosition(child, trailing[axis])\n ),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, axis)\n );\n }\n }\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (isPosDefined(child, trailing[axis]) &&\n !isPosDefined(child, leading[axis])) {\n child.layout[leading[axis]] =\n node.layout[dim[axis]] -\n child.layout[dim[axis]] -\n getPosition(child, trailing[axis]);\n }\n }\n }\n }\n }\n\n return {\n computeLayout: layoutNode,\n fillNodes: fillNodes,\n extractNodes: extractNodes\n };\n})();\n\nif (typeof exports === 'object') {\n module.exports = computeLayout;\n}\n\n return function(node) {\n node = computeLayout.fillNodes(node);\n computeLayout.computeLayout(node);\n node = computeLayout.extractNodes(node);\n return node;\n };\n}));\n"]} \ No newline at end of file diff --git a/src/Layout.js b/src/Layout.js index 4c1ca6f6..f5ee1953 100755 --- a/src/Layout.js +++ b/src/Layout.js @@ -985,3 +985,7 @@ var computeLayout = (function() { extractNodes: extractNodes }; })(); + +if (typeof exports === 'object') { + module.exports = computeLayout; +} \ No newline at end of file