UNPKG

@atlaskit/editor-plugin-layout

Version:

Layout plugin for @atlaskit/editor-core

168 lines (166 loc) 6.59 kB
import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray"; var roundLayoutColumnWidth = function roundLayoutColumnWidth(width) { return Number(width.toFixed(2)); }; var sumWidths = function sumWidths(widths) { return widths.reduce(function (sum, width) { return sum + width; }, 0); }; var normaliseWidthsTotal = function normaliseWidthsTotal(widths, totalWidth, minWidth) { var roundedWidths = widths.map(roundLayoutColumnWidth); var remainder = roundLayoutColumnWidth(totalWidth - sumWidths(roundedWidths)); if (remainder === 0 || roundedWidths.length === 0) { return roundedWidths; } var adjustmentIndex = 0; roundedWidths.forEach(function (width, index) { if (width > roundedWidths[adjustmentIndex]) { adjustmentIndex = index; } }); var adjustedWidth = roundLayoutColumnWidth(roundedWidths[adjustmentIndex] + remainder); if (adjustedWidth < minWidth) { return roundedWidths; } return roundedWidths.map(function (width, index) { return index === adjustmentIndex ? adjustedWidth : width; }); }; var isValidWidth = function isValidWidth(width) { return Number.isFinite(width) && width > 0; }; var redistributeWithMinimumWidth = function redistributeWithMinimumWidth(_ref) { var minWidth = _ref.minWidth, totalWidth = _ref.totalWidth, weights = _ref.weights; if (weights.length * minWidth > totalWidth) { return; } var widths = Array(weights.length).fill(0); var clampedIndexes = new Set(); var remainingWidth = totalWidth; var remainingWeight = sumWidths(weights); var _loop = function _loop() { var remainingWidthForPass = remainingWidth; var remainingWeightForPass = remainingWeight; var indexesToClamp = []; weights.forEach(function (weight, index) { if (clampedIndexes.has(index)) { return; } var proportionalWidth = remainingWeightForPass > 0 ? weight / remainingWeightForPass * remainingWidthForPass : 0; if (proportionalWidth < minWidth) { indexesToClamp.push(index); } }); if (indexesToClamp.length === 0) { return 1; // break } indexesToClamp.forEach(function (index) { widths[index] = minWidth; clampedIndexes.add(index); remainingWidth -= minWidth; remainingWeight -= weights[index]; }); }; while (clampedIndexes.size < weights.length) { if (_loop()) break; } weights.forEach(function (weight, index) { if (!clampedIndexes.has(index)) { widths[index] = remainingWeight > 0 ? weight / remainingWeight * remainingWidth : minWidth; } }); return widths; }; /** * Returns true when the given selected columns already reflect the distribution that * `distributeLayoutColumns` would produce — i.e. the first N-1 cols each hold * `equalWidth` (rounded to 2 dp) and the last col absorbs the rounding remainder. * * This mirrors the action's "last col absorbs remainder" logic so that the UI can * disable the option when it would be a no-op, avoiding spurious undo entries. */ export var calculateDistribution = function calculateDistribution(selectedWidths) { var count = selectedWidths.length; if (count < 2) { return undefined; } var selectedTotal = sumWidths(selectedWidths); var equalWidth = roundLayoutColumnWidth(selectedTotal / count); return { selectedTotal: selectedTotal, equalWidth: equalWidth }; }; export function isDistributedUniformly(selectedWidths) { var distribution = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : calculateDistribution(selectedWidths); if (!distribution || selectedWidths.length < 2) { return false; } var selectedTotal = distribution.selectedTotal, equalWidth = distribution.equalWidth; var lastColWidth = roundLayoutColumnWidth(selectedTotal - equalWidth * (selectedWidths.length - 1)); return selectedWidths.slice(0, -1).every(function (width) { return width === equalWidth; }) && selectedWidths[selectedWidths.length - 1] === lastColWidth; } export var redistributeAfterDeletion = function redistributeAfterDeletion(currentWidths, removeIndex, minWidth) { if (currentWidths.length === 0 || removeIndex < 0 || removeIndex >= currentWidths.length || !isValidWidth(minWidth)) { return currentWidths; } if (currentWidths.some(function (width) { return !isValidWidth(width); })) { return currentWidths.filter(function (_, i) { return i !== removeIndex; }); } var remainingWidths = currentWidths.filter(function (_, i) { return i !== removeIndex; }); if (remainingWidths.length === 0) { return remainingWidths; } var currentTotalWidth = sumWidths(currentWidths); var targetTotalWidth = Math.round(currentTotalWidth) === 100 ? 100 : currentTotalWidth; var redistributed = redistributeWithMinimumWidth({ weights: remainingWidths, totalWidth: targetTotalWidth, minWidth: minWidth }); if (!redistributed) { var equalWidth = roundLayoutColumnWidth(targetTotalWidth / remainingWidths.length); return normaliseWidthsTotal(Array(remainingWidths.length).fill(equalWidth), targetTotalWidth, minWidth); } return normaliseWidthsTotal(redistributed, targetTotalWidth, minWidth); }; export var redistributeProportionally = function redistributeProportionally(currentWidths, insertIndex, maxColumns, minWidth) { if (currentWidths.length === 0 || !Number.isInteger(maxColumns) || maxColumns <= 0 || currentWidths.length >= maxColumns || insertIndex < 0 || insertIndex > currentWidths.length || !isValidWidth(minWidth) || currentWidths.some(function (width) { return !isValidWidth(width); })) { return currentWidths; } var currentTotalWidth = sumWidths(currentWidths); if (!isValidWidth(currentTotalWidth)) { return currentWidths; } var targetTotalWidth = Math.round(currentTotalWidth) === 100 ? 100 : currentTotalWidth; var newColumnWidth = Math.max(minWidth, roundLayoutColumnWidth(targetTotalWidth / (currentWidths.length + 1))); var existingColumnsTotalWidth = targetTotalWidth - newColumnWidth; if (existingColumnsTotalWidth < currentWidths.length * minWidth) { return currentWidths; } var redistributedExistingWidths = redistributeWithMinimumWidth({ weights: currentWidths, totalWidth: existingColumnsTotalWidth, minWidth: minWidth }); if (!redistributedExistingWidths) { return currentWidths; } var nextWidths = _toConsumableArray(redistributedExistingWidths); nextWidths.splice(insertIndex, 0, newColumnWidth); return normaliseWidthsTotal(nextWidths, targetTotalWidth, minWidth); };