@atlaskit/editor-plugin-table
Version:
Table plugin for the @atlaskit/editor
249 lines (243 loc) • 9.99 kB
JavaScript
;
var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.growColumn = void 0;
exports.reduceSpace = reduceSpace;
exports.shrinkColumn = void 0;
exports.updateAffectedColumn = updateAffectedColumn;
var _toConsumableArray2 = _interopRequireDefault(require("@babel/runtime/helpers/toConsumableArray"));
var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));
var _columnState = require("./column-state");
var _resizeState = require("./resize-state");
function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { (0, _defineProperty2.default)(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
var growColumn = exports.growColumn = function growColumn(state, colIndex, amount, selectedColumns) {
// can't grow if columns don't exist or it's the last column
if (!state.cols[colIndex] || !state.cols[colIndex + 1]) {
return state;
}
var res = moveSpaceFrom(state, colIndex + 1, colIndex, amount);
var remaining = amount - res.amount;
var newState = res.state;
if (remaining > 0) {
newState = stackSpace(newState, colIndex, remaining).state;
}
if (selectedColumns && selectedColumns.length > 1) {
return (0, _resizeState.bulkColumnsResize)(newState, selectedColumns, colIndex);
}
return newState;
};
var shrinkColumn = exports.shrinkColumn = function shrinkColumn(state, colIndex, amount, selectedColumns) {
// can't shrink if columns don't exist
if (!state.cols[colIndex]) {
return state;
}
// try to shrink dragging column by giving from the column to the right first
var res = moveSpaceFrom(state, colIndex, colIndex + 1, -amount);
var newState = res.state;
var isOverflownTable = (0, _resizeState.getTotalWidth)(newState) > newState.maxSize;
var isLastColumn = !newState.cols[colIndex + 1];
// stop resizing the last column once table is not overflown
if (isLastColumn && !isOverflownTable) {
return newState;
}
var remaining = amount + res.amount;
if (remaining < 0) {
newState = stackSpace(newState, colIndex + 1, remaining).state;
}
if (selectedColumns && selectedColumns.length > 1) {
return (0, _resizeState.bulkColumnsResize)(newState, selectedColumns, colIndex);
}
return newState;
};
function reduceSpace(state, amount) {
var ignoreCols = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
var remaining = amount;
// keep trying to resolve resize request until we run out of free space,
// or nothing to resize
var _loop = function _loop() {
// filter candidates only with free space
var candidates = state.cols.filter(function (column) {
return (0, _columnState.getFreeSpace)(column) && ignoreCols.indexOf(column.index) === -1;
});
if (candidates.length === 0) {
return 0; // break
}
var requestedResize = Math.floor(remaining / candidates.length);
if (requestedResize === 0) {
return 0; // break
}
candidates.forEach(function (candidate) {
var newWidth = candidate.width - requestedResize;
if (newWidth < candidate.minWidth) {
// If the new requested width is less than our min
// Calc what width we didn't use, we'll try extract that
// from other cols.
var remainder = candidate.minWidth - newWidth;
newWidth = candidate.minWidth;
remaining = remaining - requestedResize + remainder;
} else {
remaining -= requestedResize;
}
state = _objectSpread(_objectSpread({}, state), {}, {
cols: [].concat((0, _toConsumableArray2.default)(state.cols.slice(0, candidate.index)), [_objectSpread(_objectSpread({}, candidate), {}, {
width: newWidth
})], (0, _toConsumableArray2.default)(state.cols.slice(candidate.index + 1)))
});
});
},
_ret;
while (remaining > 0) {
_ret = _loop();
if (_ret === 0) break;
}
return state;
}
var ColType = /*#__PURE__*/function (ColType) {
ColType["SOURCE"] = "src";
ColType["DEST"] = "dest";
return ColType;
}(ColType || {}); // TODO: ED-26961 - should handle when destIdx:
// - is beyond the range, and then not give it back
function moveSpaceFrom(state, srcIdx, destIdx, amount) {
var useFreeSpace = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : true;
var srcCol = state.cols[srcIdx];
var destCol = state.cols[destIdx];
if (useFreeSpace) {
var freeSpace = (0, _columnState.getFreeSpace)(srcCol);
// if taking more than source column's free space, only take that much
if (amountFor(ColType.DEST)(amount) > freeSpace) {
amount = amount > 0 ? freeSpace : -freeSpace;
}
}
// if the source column shrinks past its min size, don't give the space away
if (amountFor(ColType.SOURCE)(amount) < 0 && widthFor(ColType.SOURCE)(amount, srcCol, destCol) < srcCol.minWidth) {
amount = srcCol.width - srcCol.minWidth;
}
var newDest = destCol ? _objectSpread(_objectSpread({}, destCol), {}, {
width: widthFor(ColType.DEST)(amount, srcCol, destCol)
}) : undefined;
if (!newDest && amountFor(ColType.SOURCE)(amount) < 0) {
// non-zero-sum game, ensure that we're not removing more than the total table width either
var totalWidth = (0, _resizeState.getTotalWidth)(state);
if (totalWidth - srcCol.width + widthFor(ColType.SOURCE)(amount, srcCol, destCol) < state.maxSize) {
// would shrink table below max width, stop it
amount = state.maxSize - (totalWidth - srcCol.width) - srcCol.width - 1;
}
}
var newSrc = _objectSpread(_objectSpread({}, srcCol), {}, {
width: widthFor(ColType.SOURCE)(amount, srcCol, destCol)
});
var newCols = state.cols.map(function (existingCol, idx) {
return idx === srcIdx ? newSrc : idx === destIdx ? newDest : existingCol;
}).filter(Boolean);
return {
state: _objectSpread(_objectSpread({}, state), {}, {
cols: newCols
}),
amount: amount
};
}
function stackSpace(state, destIdx, amount) {
var candidates = getCandidates(state, destIdx, amount);
var _loop2 = function _loop2() {
// search for most (or least) free space in candidates
var candidateIdx = findNextFreeColumn(candidates, amount);
if (candidateIdx === -1) {
// stack to the right -> growing the dragging column and go overflow
if (amount > 0) {
return {
v: {
state: _objectSpread(_objectSpread({}, state), {}, {
cols: [].concat((0, _toConsumableArray2.default)(state.cols.slice(0, destIdx)), [_objectSpread(_objectSpread({}, state.cols[destIdx]), {}, {
width: state.cols[destIdx].width + amount
})], (0, _toConsumableArray2.default)(state.cols.slice(destIdx + 1)))
}),
remaining: amount
}
};
}
// stacking to the left, if no free space remains
return 0; // break
}
var column = candidates.find(function (col) {
return col.index === candidateIdx;
});
if (!column || (0, _columnState.getFreeSpace)(column) <= 0) {
// no more columns with free space remain
return 0; // break
}
var res = moveSpaceFrom(state, column.index, destIdx, amount);
state = res.state;
amount -= res.amount;
candidates = candidates.filter(function (col) {
return col.index !== candidateIdx;
});
},
_ret2;
while (candidates.length && amount) {
_ret2 = _loop2();
if (_ret2 === 0) break;
if (_ret2) return _ret2.v;
}
return {
state: state,
remaining: amount
};
}
function findNextFreeColumn(columns, amount) {
if (columns.length === 0) {
return -1;
}
var direction = amount < 0 ? 'left' : 'right';
if (direction === 'left') {
columns = columns.slice().reverse();
}
var freeIndex = -1;
columns.forEach(function (column) {
if ((0, _columnState.getFreeSpace)(column) && freeIndex === -1) {
freeIndex = column.index;
}
});
if (freeIndex === -1) {
return -1;
}
return freeIndex;
}
function amountFor(colType) {
return function (amount) {
return colType === ColType.SOURCE ? amount > 0 ? -amount : amount : amount < 0 ? -amount : amount;
};
}
function widthFor(colType) {
return function (amount, srcCol, destCol) {
return (colType === ColType.SOURCE ? srcCol : destCol).width + amountFor(colType)(amount);
};
}
function getCandidates(state, destIdx, amount) {
var candidates = state.cols;
// only consider rows after the selected column in the direction of resize
return amount < 0 ? candidates.slice(0, destIdx) : candidates.slice(destIdx + 1);
}
/**
* Update the given column based on resizeAmount, maintaining all other columns
*/
function updateAffectedColumn(resizeState, colIndex, resizeAmount) {
var updatedCols = resizeState.cols.map(function (col, index) {
if (index === colIndex) {
var newWidth = Math.max(col.width + resizeAmount, col.minWidth);
return _objectSpread(_objectSpread({}, col), {}, {
width: newWidth
});
}
return col;
});
return _objectSpread(_objectSpread({}, resizeState), {}, {
tableWidth: updatedCols.reduce(function (acc, col) {
return acc + col.width;
}, 0),
cols: updatedCols
});
}