@atlaskit/editor-common
Version:
A package that contains common classes and components for editor and renderer
146 lines (141 loc) • 5.68 kB
JavaScript
import { akEditorBreakoutPadding, akEditorDefaultLayoutWidth, akEditorFullWidthLayoutWidth, akEditorSwoopCubicBezier, akEditorWideLayoutWidth, breakoutWideScaleRatio } from '@atlaskit/editor-shared-styles';
import commonMessages from '../messages';
import { mapBreakpointToLayoutMaxWidth } from '../ui/BaseTheme';
import { getBreakpoint } from '../ui/WidthProvider';
import { parsePx } from './dom';
/**
* Variables required to construct a context for breakout ssr inline script.
*
* TODO: Clean this up after: https://product-fabric.atlassian.net/browse/ED-8942
*
*/
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const breakoutConsts = {
padding: akEditorBreakoutPadding,
defaultLayoutWidth: akEditorDefaultLayoutWidth,
wideScaleRatio: breakoutWideScaleRatio,
fullWidthLayoutWidth: akEditorFullWidthLayoutWidth,
wideLayoutWidth: akEditorWideLayoutWidth,
mapBreakpointToLayoutMaxWidth,
getBreakpoint,
/**
* This function can return percentage value or px value depending upon the inputs
*/
calcBreakoutWidth: (layout, containerWidth, padding) => {
const effectiveFullWidth = containerWidth - (padding !== null && padding !== void 0 ? padding : breakoutConsts.padding);
switch (layout) {
case 'full-width':
return `${Math.min(effectiveFullWidth, breakoutConsts.fullWidthLayoutWidth)}px`;
case 'wide':
if (effectiveFullWidth <= 0) {
return '100%';
}
const wideWidth = breakoutConsts.calcWideWidth(containerWidth, undefined, undefined, padding);
if (wideWidth.endsWith('%')) {
return `${Math.min(effectiveFullWidth, breakoutConsts.fullWidthLayoutWidth)}px`;
}
return wideWidth;
default:
return '100%';
}
},
calcBreakoutWithCustomWidth: (mode, width, editorContainerWidth) => {
if (width !== null && width > 0) {
const effectiveFullWidth = editorContainerWidth - breakoutConsts.padding;
// if below 0 then expect we're rendering in SSR
return `${Math.min(width, effectiveFullWidth)}px`;
}
return breakoutConsts.calcBreakoutWidth(mode, editorContainerWidth);
},
calcLineLength: () => breakoutConsts.defaultLayoutWidth,
// Ignored via go/ees005
// eslint-disable-next-line @typescript-eslint/max-params
calcWideWidth: (containerWidth = breakoutConsts.defaultLayoutWidth, maxWidth = Infinity, fallback = '100%', padding) => {
const effectiveFullWidth = containerWidth - (padding !== null && padding !== void 0 ? padding : breakoutConsts.padding);
const layoutMaxWidth = breakoutConsts.mapBreakpointToLayoutMaxWidth(breakoutConsts.getBreakpoint(containerWidth));
const wideWidth = Math.min(Math.ceil(layoutMaxWidth * breakoutConsts.wideScaleRatio), effectiveFullWidth);
return layoutMaxWidth > wideWidth ? fallback : `${Math.min(maxWidth, wideWidth)}px`;
}
};
export const absoluteBreakoutWidth = (layout, containerWidth) => {
const breakoutWidth = breakoutConsts.calcBreakoutWidth(layout, containerWidth);
// If it's percent, map to max layout size
if (breakoutWidth.endsWith('%')) {
switch (layout) {
case 'full-width':
return akEditorFullWidthLayoutWidth;
case 'wide':
return akEditorWideLayoutWidth;
default:
return breakoutConsts.mapBreakpointToLayoutMaxWidth(breakoutConsts.getBreakpoint(containerWidth));
}
}
return parseInt(breakoutWidth, 10);
};
export { breakoutConsts };
export const calcWideWidth = breakoutConsts.calcWideWidth;
export const calcBreakoutWidth = breakoutConsts.calcBreakoutWidth;
export const calcBreakoutWithCustomWidth = breakoutConsts.calcBreakoutWithCustomWidth;
export function calculateBreakoutStyles({
mode,
widthStateLineLength,
widthStateWidth
}) {
const breakoutWidth = calcBreakoutWidth(mode, widthStateWidth);
const breakoutWidthPx = parsePx(breakoutWidth);
if (!widthStateLineLength) {
// lineLength is not normally undefined when this is run for,
// consumers but can be in SSR, initial render or test (jsdom)
// environments.
//
// this approach doesn't work well with position: fixed, so
// it breaks things like sticky headers.
//
// It can also cause bluriness for some child content (such as iframes)
return {
type: 'line-length-unknown',
width: breakoutWidth,
minWidth: breakoutWidthPx,
display: 'flex',
justifyContent: 'center',
transform: 'none',
transition: `min-width 0.5s ${akEditorSwoopCubicBezier}`
};
}
// NOTE
// At time of writing -- when toggling between full-width and
// full-page appearance modes. There is a slight delay before
// the widthState is updated.
// During this period -- the marginLeftPx will be incorrect.
// const marginLeftPx = -(breakoutWidthPx - widthStateLineLength) / 2;
return {
type: 'line-length-known',
width: breakoutWidth,
minWidth: breakoutWidthPx,
transition: `min-width 0.5s ${akEditorSwoopCubicBezier}`,
transform: `translateX(-50%)`,
marginLeft: `50%`
};
}
export function calcBreakoutWidthPx(mode, widthStateWidth, padding) {
return parsePx(calcBreakoutWidth(mode, widthStateWidth, padding));
}
export const getNextBreakoutMode = currentMode => {
if (currentMode === 'full-width') {
return 'center';
} else if (currentMode === 'wide') {
return 'full-width';
}
return 'wide';
};
export const getTitle = layout => {
switch (layout) {
case 'full-width':
return commonMessages.layoutFixedWidth;
case 'wide':
return commonMessages.layoutFullWidth;
default:
return commonMessages.layoutWide;
}
};