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
8 changes: 8 additions & 0 deletions packages/core/core-types/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -272,6 +272,14 @@ export namespace CoreTypes {
export const parse = makeParser<BackgroundRepeatType>(isValid);
}

export type CornerShapeType = 'round' | 'squircle';
export namespace CornerShape {
export const round: CornerShapeType = 'round';
export const squircle: CornerShapeType = 'squircle';
export const isValid = makeValidator<CornerShapeType>(round, squircle);
export const parse = makeParser<CornerShapeType>(isValid);
}

export namespace AnimationCurve {
export const ease = 'ease';
export const easeIn = 'easeIn';
Expand Down
10 changes: 10 additions & 0 deletions packages/core/ui/styling/background-common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ export class Background {
public borderTopRightRadius = 0;
public borderBottomLeftRadius = 0;
public borderBottomRightRadius = 0;
public cornerShape: CoreTypes.CornerShapeType = CoreTypes.CornerShape.round;
public clipPath: string | ClipPathFunction;
public boxShadows: BoxShadow[];
public clearFlags: number = BackgroundClearFlags.NONE;
Expand All @@ -63,6 +64,7 @@ export class Background {
clone.borderTopRightRadius = this.borderTopRightRadius;
clone.borderBottomRightRadius = this.borderBottomRightRadius;
clone.borderBottomLeftRadius = this.borderBottomLeftRadius;
clone.cornerShape = this.cornerShape;
clone.clipPath = this.clipPath;
clone.boxShadows = this.boxShadows;
clone.clearFlags = this.clearFlags;
Expand Down Expand Up @@ -192,6 +194,13 @@ export class Background {
return clone;
}

public withCornerShape(value: CoreTypes.CornerShapeType): Background {
const clone = this.clone();
clone.cornerShape = value;

return clone;
}

public withClipPath(value: string | ClipPathFunction): Background {
const clone = this.clone();
clone.clipPath = value;
Expand Down Expand Up @@ -256,6 +265,7 @@ export class Background {
value1.borderTopRightRadius === value2.borderTopRightRadius &&
value1.borderBottomRightRadius === value2.borderBottomRightRadius &&
value1.borderBottomLeftRadius === value2.borderBottomLeftRadius &&
value1.cornerShape === value2.cornerShape &&
isClipPathEqual
// && value1.clearFlags === value2.clearFlags
);
Expand Down
2 changes: 2 additions & 0 deletions packages/core/ui/styling/background.ios.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import { parse as cssParse } from '../../css-value/reworkcss-value';
import { BoxShadow } from './box-shadow';
import { BackgroundClearFlags } from './background-common';
import { ClipPathFunction } from './clip-path-function';
import { CoreTypes } from '../../core-types';

export * from './background-common';

Expand Down Expand Up @@ -93,6 +94,7 @@ export namespace ios {
layer.borderColor = borderColor?.ios?.CGColor;
layer.borderWidth = layout.toDeviceIndependentPixels(background.getUniformBorderWidth());
layer.cornerRadius = getUniformBorderRadius(view, layer.bounds);
layer.cornerCurve = background.cornerShape === CoreTypes.CornerShape.squircle ? kCACornerCurveContinuous : kCACornerCurveCircular;
} else {
drawNonUniformBorders(nativeView, background);
needsLayerAdjustmentOnScroll = true;
Expand Down
26 changes: 26 additions & 0 deletions packages/core/ui/styling/style-properties.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,3 +35,29 @@ describe('border-color shorthand', () => {
expect(label.style.borderLeftColor).toEqual(new Color('blue'));
});
});

describe('corner-shape', () => {
it('defaults to round', () => {
const label = new Label();

expect(label.style.cornerShape).toBe('round');
expect(label.style.backgroundInternal.cornerShape).toBe('round');
});

it('accepts squircle and reaches the background', () => {
const label = new Label();
label.style.cornerShape = 'squircle';

expect(label.style.backgroundInternal.cornerShape).toBe('squircle');

label.style.cornerShape = 'round';

expect(label.style.backgroundInternal.cornerShape).toBe('round');
});

it('rejects unknown keywords', () => {
const label = new Label();

expect(() => (label.style.cornerShape = 'bevel' as any)).toThrow();
});
});
11 changes: 11 additions & 0 deletions packages/core/ui/styling/style-properties.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,17 @@ export const borderBottomLeftRadiusProperty = new CssProperty<Style, CoreTypes.L
});
borderBottomLeftRadiusProperty.register(Style);

export const cornerShapeProperty = new CssProperty<Style, CoreTypes.CornerShapeType>({
name: 'cornerShape',
cssName: 'corner-shape',
defaultValue: CoreTypes.CornerShape.round,
valueConverter: CoreTypes.CornerShape.parse,
valueChanged: (target, oldValue, newValue) => {
target.backgroundInternal = target.backgroundInternal.withCornerShape(newValue);
},
});
cornerShapeProperty.register(Style);

const boxShadowProperty = new CssProperty<Style, ShadowCSSValues[]>({
name: 'boxShadow',
cssName: 'box-shadow',
Expand Down
7 changes: 7 additions & 0 deletions packages/core/ui/styling/style/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,13 @@ export class Style extends Observable {
public borderBottomRightRadius: CoreTypes.LengthType;
public borderBottomLeftRadius: CoreTypes.LengthType;

/**
* The curve used to round the corners: 'round' (circular arcs, the default)
* or 'squircle' (Apple's continuous corner curve). iOS only; Android always
* renders circular corners.
*/
public cornerShape: CoreTypes.CornerShapeType;

public boxShadow: string | ShadowCSSValues[];

public direction: CoreTypes.LayoutDirectionType;
Expand Down
Loading