Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/display/components/Background.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const ComposedBackground = mixins(
);

export class Background extends ComposedBackground {
static respectsPadding = false;

constructor(context) {
super({ type: 'background', context, texture: Texture.WHITE });
}
Expand Down
9 changes: 7 additions & 2 deletions src/display/data-schema/element-schema.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { z } from 'zod';
import { componentArraySchema } from './component-schema';
import { Base, Gap, RelationsStyle, Size } from './primitive-schema';
import { Base, Gap, Margin, RelationsStyle, Size } from './primitive-schema';

/**
* Groups multiple elements to apply common properties..
Expand All @@ -22,7 +22,11 @@ export const gridSchema = Base.extend({
type: z.literal('grid'),
cells: z.array(z.array(z.union([z.literal(0), z.literal(1)]))),
gap: Gap,
item: z.object({ components: componentArraySchema, size: Size }),
item: z.object({
components: componentArraySchema,
size: Size,
padding: Margin.default(0),
}),
}).strict();

/**
Expand All @@ -35,6 +39,7 @@ export const itemSchema = Base.extend({
type: z.literal('item'),
components: componentArraySchema,
size: Size,
padding: Margin.default(0),
}).strict();

/**
Expand Down
1 change: 1 addition & 0 deletions src/display/data-schema/element-schema.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,7 @@ describe('Element Schemas', () => {
expect(parsed.gap).toEqual({ x: 0, y: 0 });
expect(parsed.item).toEqual({
size: { width: 50, height: 50 },
padding: { bottom: 0, left: 0, right: 0, top: 0 },
components: [],
});
});
Expand Down
3 changes: 2 additions & 1 deletion src/display/data-schema/primitive-schema.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { z } from 'zod';
import { uid } from '../../utils/uuid';
import { ZERO_MARGIN } from '../mixins/constants';
import {
Color,
HslColor,
Expand Down Expand Up @@ -168,7 +169,7 @@ export const Margin = z.preprocess(
bottom: z.number().default(0),
left: z.number().default(0),
})
.default({}),
.default(ZERO_MARGIN),
);

export const TextureStyle = z
Expand Down
2 changes: 1 addition & 1 deletion src/display/mixins/Itemsizeable.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { UPDATE_STAGES } from './constants';

const KEYS = ['size'];
const KEYS = ['size', 'padding'];

export const ItemSizeable = (superClass) => {
const MixedClass = class extends superClass {
Expand Down
26 changes: 16 additions & 10 deletions src/display/mixins/Placementable.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { UPDATE_STAGES } from './constants';
import { getLayoutContext } from './utils';

const KEYS = ['placement', 'margin'];

Expand Down Expand Up @@ -34,31 +35,36 @@ export const Placementable = (superClass) => {
};

const getHorizontalPosition = (component, align, margin) => {
const parentWidth = component.parent.props.size.width;
const { parentWidth, contentWidth, parentPadding } =
getLayoutContext(component);

let result = null;
if (align === 'left') {
result = margin.left;
result = parentPadding.left + margin.left;
} else if (align === 'right') {
result = parentWidth - component.width - margin.right;
result = parentWidth - component.width - margin.right - parentPadding.right;
} else if (align === 'center') {
const marginWidth = component.width + margin.left + margin.right;
const blockStartPosition = (parentWidth - marginWidth) / 2;
result = blockStartPosition + margin.left;
const blockStartPosition = (contentWidth - marginWidth) / 2;
result = parentPadding.left + blockStartPosition + margin.left;
}
return result;
};

const getVerticalPosition = (component, align, margin) => {
const parentHeight = component.parent.props.size.height;
const { parentHeight, contentHeight, parentPadding } =
getLayoutContext(component);

let result = null;
if (align === 'top') {
result = margin.top;
result = parentPadding.top + margin.top;
} else if (align === 'bottom') {
result = parentHeight - component.height - margin.bottom;
result =
parentHeight - component.height - margin.bottom - parentPadding.bottom;
} else if (align === 'center') {
const marginHeight = component.height + margin.top + margin.bottom;
const blockStartPosition = (parentHeight - marginHeight) / 2;
result = blockStartPosition + margin.top;
const blockStartPosition = (contentHeight - marginHeight) / 2;
result = parentPadding.top + blockStartPosition + margin.top;
}
return result;
};
7 changes: 7 additions & 0 deletions src/display/mixins/constants.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,10 @@ export const FONT_WEIGHT = {
extrabold: 'extrabold',
black: 'black',
};

export const ZERO_MARGIN = Object.freeze({
top: 0,
right: 0,
bottom: 0,
left: 0,
});
55 changes: 49 additions & 6 deletions src/display/mixins/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import gsap from 'gsap';
import { isValidationError } from 'zod-validation-error';
import { findIndexByPriority } from '../../utils/findIndexByPriority';
import { validate } from '../../utils/validator';
import { ZERO_MARGIN } from './constants';

export const tweensOf = (object) => gsap.getTweensOf(object);

Expand All @@ -27,29 +28,29 @@ const parseCalcExpression = (expression, parentDimension) => {
};

export const calcSize = (component, { source, size }) => {
const { width: parentWidth, height: parentHeight } =
component.parent.props.size;
const { contentWidth, contentHeight } = getLayoutContext(component);

const borderWidth =
typeof source === 'object' ? (source?.borderWidth ?? 0) : 0;

let finalWidth = null;
let finalHeight = null;

if (typeof size.width === 'string' && size.width.startsWith('calc')) {
finalWidth = parseCalcExpression(size.width, parentWidth);
finalWidth = parseCalcExpression(size.width, contentWidth);
} else {
finalWidth =
size.width.unit === '%'
? parentWidth * (size.width.value / 100)
? contentWidth * (size.width.value / 100)
: size.width.value;
}

if (typeof size.height === 'string' && size.height.startsWith('calc')) {
finalHeight = parseCalcExpression(size.height, parentHeight);
finalHeight = parseCalcExpression(size.height, contentHeight);
} else {
finalHeight =
size.height.unit === '%'
? parentHeight * (size.height.value / 100)
? contentHeight * (size.height.value / 100)
: size.height.value;
}

Expand Down Expand Up @@ -106,3 +107,45 @@ export const validateAndPrepareChanges = (currentElements, changes, schema) => {

return preparedChanges;
};

/**
* Calculates the layout context of a component (content area size, padding, etc).
* @param {PIXI.DisplayObject} component - The component for which to calculate the layout context
* @returns {{parentWidth: number, parentHeight: number, contentWidth: number, contentHeight: number, parentPadding: object}}
*/
export const getLayoutContext = (component) => {
const parent = component?.parent;
if (!parent) {
return {
parentWidth: 0,
parentHeight: 0,
contentWidth: 0,
contentHeight: 0,
parentPadding: ZERO_MARGIN,
};
}

const usePadding = component.constructor.respectsPadding !== false;
const parentPadding =
usePadding && parent.props.padding ? parent.props.padding : ZERO_MARGIN;

const parentWidth = parent.props.size.width;
const parentHeight = parent.props.size.height;

const contentWidth = Math.max(
0,
parentWidth - parentPadding.left - parentPadding.right,
);
const contentHeight = Math.max(
0,
parentHeight - parentPadding.top - parentPadding.bottom,
);

return {
parentWidth,
parentHeight,
contentWidth,
contentHeight,
parentPadding,
};
};
Loading