Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculatable Position #1454

Merged
merged 36 commits into from
Oct 3, 2023
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
9c93d3c
Extract position to its own folder
Jym77 Jul 14, 2023
ec55f21
Move Offset to its own file
Jym77 Jul 14, 2023
d0e0b12
Move Keywords and Side to their own files
Jym77 Jul 14, 2023
aa14b79
Move Component to its own file
Jym77 Jul 14, 2023
202d603
Remove Offset and use LengthPercentage directly
Jym77 Jul 14, 2023
cd60ce1
Make Side somewhat calculatable
Jym77 Jul 14, 2023
72c5bd2
Merge branch 'main' into calculatable-position
Jym77 Jul 14, 2023
9280f88
Switch parameter order
Jym77 Jul 14, 2023
65af409
Prepare partial resolving
Jym77 Jul 14, 2023
3d77177
Make Component always take a Side
Jym77 Jul 14, 2023
59f26ed
Add missing changeset
Jym77 Jul 17, 2023
0fa3e6d
Make offest optional in Side.of
Jym77 Jul 17, 2023
0648e81
Make offset optional or Option in Side.of
Jym77 Jul 17, 2023
ba8a064
Add partial resolver, rework type parameters
Jym77 Jul 17, 2023
a5f6d14
Make Position calculatable
Jym77 Jul 17, 2023
a87c4b3
Add some parsing examples with calculations
Jym77 Jul 17, 2023
83ec64d
Add some resolving examples with calculations
Jym77 Jul 17, 2023
826f1d9
Resolve percentages separatly in each dimension
Jym77 Jul 17, 2023
be8a129
Add changeset
Jym77 Jul 17, 2023
aee029c
Clean up
Jym77 Jul 17, 2023
6fd0187
Extract API
github-actions[bot] Jul 17, 2023
ac25073
Clean up
Jym77 Jul 18, 2023
b65262c
Typo
Jym77 Jul 18, 2023
5908a7f
Extract API
github-actions[bot] Jul 18, 2023
ad6827c
Add Resolvable implementation
Jym77 Jul 18, 2023
eb25c35
Extract API
github-actions[bot] Jul 18, 2023
e5ced93
Merge branch 'main' into calculatable-position
Jym77 Jul 20, 2023
f3de492
Calculatable `Shadow` (#1455)
Jym77 Jul 20, 2023
c7a3b8f
Calculatable `transform` functions (#1457)
Jym77 Aug 7, 2023
03429f3
SIA-R19: fix regression (#1459)
Jym77 Aug 9, 2023
7065b08
v0.66.0
siteimprove-builduser Aug 9, 2023
3ef9889
Remove duplicate variable
Jym77 Aug 9, 2023
6efed28
Merge branch 'main' into calculatable-position
Jym77 Aug 10, 2023
ac6689a
Merge branch 'main' into calculatable-position
Jym77 Sep 5, 2023
ac5cb2b
Merge branch 'main' into calculatable-position
Jym77 Sep 6, 2023
94ceeb0
Merge branch 'main' into calculatable-position
Jym77 Sep 26, 2023
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 .changeset/clever-falcons-press.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@siteimprove/alfa-css": minor
---

**Added:** `Position` now accept calculations in any of their components.

To fully resolve a `Position`, the resolver needs both a length resolver, and two percentage bases, one for each dimension.
To partially resolve a `Position`, only a length resolver is needed.
7 changes: 7 additions & 0 deletions .changeset/cuddly-items-repeat.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@siteimprove/alfa-css": minor
---

**Breaking:** `Position.Component` cannot be raw `LengthPercentage` anymore.

Instead, they must always be a full `Position.Side` (or the "center" keyword) i.e. include an explicit side to count from. This side is automatically added when parsing raw `LengthPercentage`.
9 changes: 9 additions & 0 deletions .changeset/shy-schools-flash.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
---
"@siteimprove/alfa-css": minor
---

**Changed:** The `Position` type requires more type paramters.

Instead of just accepting the horizontal and vertical components, the type now also requires the horizontal and vertical keywords list (as first and second paramter). The components parameter default to `Position.Component<H>` (reps. `V`) for keywords `H` (resp. `V`).

The type also accepts a `CALC` paramter indicating whether it may have calculations.
5 changes: 5 additions & 0 deletions .changeset/silver-papayas-develop.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-css": minor
---

**Removed:** The unused `Side.isCenter()` predicate is no longer available.
5 changes: 5 additions & 0 deletions .changeset/smart-mayflies-jog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-css": patch
---

**Added:** `Position.Side.of` now also accepts an optional offset, as well as an `Option<offset>`.
5 changes: 5 additions & 0 deletions .changeset/thick-ways-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@siteimprove/alfa-css": patch
---

**Added:** The `LengthPercentage` type now accepts an optional `CALC` boolean parameter to indicate whether it contains calculations.
140 changes: 40 additions & 100 deletions docs/review/api/alfa-css.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -259,7 +259,7 @@ export namespace Box {
// Warning: (ae-forgotten-export) The symbol "BasicShape" needs to be exported by the entry point index.d.ts
//
// @public (undocumented)
export class Circle<R extends Radius = Radius, P extends Position = Position> extends BasicShape<"circle"> {
export class Circle<R extends Radius = Radius, P extends Position.Fixed = Position.Fixed> extends BasicShape<"circle"> {
// (undocumented)
get center(): P;
// (undocumented)
Expand All @@ -269,7 +269,7 @@ export class Circle<R extends Radius = Radius, P extends Position = Position> ex
// (undocumented)
hash(hash: Hash): void;
// (undocumented)
static of<R extends Radius, P extends Position>(radius: R, center: P): Circle<R, P>;
static of<R extends Radius, P extends Position.Fixed>(radius: R, center: P): Circle<R, P>;
// (undocumented)
get radius(): R;
// (undocumented)
Expand Down Expand Up @@ -526,7 +526,7 @@ namespace Dimension_2 {
}

// @public (undocumented)
export class Ellipse<R extends Radius = Radius, P extends Position = Position> extends BasicShape<"ellipse"> {
export class Ellipse<R extends Radius = Radius, P extends Position.Fixed = Position.Fixed> extends BasicShape<"ellipse"> {
// (undocumented)
get center(): P;
// (undocumented)
Expand All @@ -536,7 +536,7 @@ export class Ellipse<R extends Radius = Radius, P extends Position = Position> e
// (undocumented)
hash(hash: Hash): void;
// (undocumented)
static of<R extends Radius = Radius, P extends Position = Position>(rx: R, ry: R, center: P): Ellipse<R, P>;
static of<R extends Radius = Radius, P extends Position.Fixed = Position.Fixed>(rx: R, ry: R, center: P): Ellipse<R, P>;
// (undocumented)
resolve(): Ellipse<R, P>;
// (undocumented)
Expand Down Expand Up @@ -1128,7 +1128,7 @@ namespace Length_2 {
}

// @public (undocumented)
export type LengthPercentage<U extends Unit.Length = Unit.Length> = LengthPercentage.Calculated | Length.Calculated | Length.Fixed<U> | Percentage.Calculated | Percentage.Fixed;
export type LengthPercentage<U extends Unit.Length = Unit.Length, CALC extends boolean = boolean> = CALC extends true ? LengthPercentage.Calculated | Length.Calculated | Percentage.Calculated : CALC extends false ? Length.Fixed<U> | Percentage.Fixed : LengthPercentage.Calculated | Length.Calculated | Percentage.Calculated | Length.Fixed<U> | Percentage.Fixed;

// @public (undocumented)
export namespace LengthPercentage {
Expand Down Expand Up @@ -1181,13 +1181,17 @@ export namespace LengthPercentage {
export function of(value: Math_2<"length-percentage">): Calculated;
// (undocumented)
export function of(value: Math_2<"percentage">): Percentage.Calculated;
export function partiallyResolve(resolver: Length.Resolver): (value: LengthPercentage) => PartiallyResolved;
export function partiallyResolve(resolver: PartialResolver): (value: LengthPercentage) => PartiallyResolved;
export type PartiallyResolved = Canonical | Percentage.Canonical | LengthPercentage.Calculated;
// (undocumented)
export type PartialResolver = Length.Resolver;
export function resolve(resolver: Resolver): (value: LengthPercentage) => Canonical;
// (undocumented)
export type Resolver = Length.Resolver & Percentage.Resolver<"length", Canonical>;
const // (undocumented)
parse: Parser_2<Slice<Token>, LengthPercentage<Unit.Length>, string, []>;
parse: Parser_2<Slice<Token>, Length.Calculated | Length.Fixed<Unit.Length> | Calculated | Percentage.Calculated<Base.Numeric.Type> | Percentage.Fixed<Base.Numeric.Type>, string, []>;
const // @internal (undocumented)
parseBase: Parser<LengthPercentage<Unit.Length, false>>;
{};
}

Expand Down Expand Up @@ -2008,129 +2012,65 @@ export namespace Polygon {
}

// @public (undocumented)
export class Position<H extends Position.Component<Position.Keywords.Horizontal> = Position.Component<Position.Keywords.Horizontal>, V extends Position.Component<Position.Keywords.Vertical> = Position.Component<Position.Keywords.Vertical>> extends Value<"position", false> {
export class Position<H extends Position.Keywords.Horizontal = Position.Keywords.Horizontal, V extends Position.Keywords.Vertical = Position.Keywords.Vertical, HC extends Position.Component<H> = Position.Component<H>, VC extends Position.Component<V> = Position.Component<V>, CALC extends boolean = boolean> extends Value<"position", CALC> {
// (undocumented)
equals(value: unknown): value is this;
// (undocumented)
hash(hash: Hash): void;
// (undocumented)
get horizontal(): H;
get horizontal(): HC;
// (undocumented)
static of<H extends Position.Component<Position.Keywords.Horizontal>, V extends Position.Component<Position.Keywords.Vertical>>(horizontal: H, vertical: V): Position<H, V>;
static of<H extends Position.Keywords.Horizontal = Position.Keywords.Horizontal, V extends Position.Keywords.Vertical = Position.Keywords.Vertical, HC extends Position.Component<H> = Position.Component<H>, VC extends Position.Component<V> = Position.Component<V>>(horizontal: HC, vertical: VC): Position<H, V, HC, VC, Value.HasCalculation<[HC, VC]>>;
// (undocumented)
resolve(): Position<H, V>;
resolve(resolver: Position.Resolver): Position.Canonical<H, V>;
// (undocumented)
toJSON(): Position.JSON;
// (undocumented)
toString(): string;
// (undocumented)
get vertical(): V;
get vertical(): VC;
}

// @public (undocumented)
export namespace Position {
// Warning: (ae-forgotten-export) The symbol "Keywords" needs to be exported by the entry point index.d.ts
// Warning: (ae-forgotten-export) The symbol "Component" needs to be exported by the entry point index.d.ts
//
// (undocumented)
export type Canonical = Position<Component.Canonical<Keywords.Horizontal>, Component.Canonical<Keywords.Vertical>>;
// (undocumented)
export type Component<S extends Keywords.Horizontal | Keywords.Vertical = Keywords.Horizontal | Keywords.Vertical, U extends Unit.Length = Unit.Length> = Keywords.Center | Offset<U> | Side<S, Offset<U>>;
// (undocumented)
export namespace Component {
// (undocumented)
export type Canonical<S extends Keywords.Horizontal | Keywords.Vertical> = Percentage.Canonical | Keywords.Center | Length.Canonical | Side.Canonical<S>;
// (undocumented)
export type JSON = Keyword.JSON | Length.Fixed.JSON | Percentage.Fixed.JSON | Side.JSON;
const // Warning: (ae-incompatible-release-tags) The symbol "parseHorizontal" is marked as @public, but its signature references "Type" which is marked as @internal
//
// (undocumented)
parseHorizontal: Parser_2<Slice<Token>, Percentage.Fixed<import("../calculation/numeric").Numeric.Type> | Length.Fixed<Unit.Length> | Keyword<"center"> | Side<Keyword.ToKeywords<"right" | "left">, Offset<Unit.Length>>, string, []>;
const // Warning: (ae-incompatible-release-tags) The symbol "parseVertical" is marked as @public, but its signature references "Type" which is marked as @internal
//
// (undocumented)
parseVertical: Parser_2<Slice<Token>, Percentage.Fixed<import("../calculation/numeric").Numeric.Type> | Length.Fixed<Unit.Length> | Keyword<"center"> | Side<Keyword.ToKeywords<"top" | "bottom">, Offset<Unit.Length>>, string, []>;
}
export type Canonical<H extends Keywords.Horizontal = Keywords.Horizontal, V extends Keywords.Vertical = Keywords.Vertical> = Position<H, V, Component_2.Canonical<H>, Component_2.Canonical<V>, false>;
// @internal (undocumented)
export type Fixed<H extends Keywords.Horizontal = Keywords.Horizontal, V extends Keywords.Vertical = Keywords.Vertical> = Position<H, V, Component_2.Fixed<H>, Component_2.Fixed<V>, false>;
// (undocumented)
export interface JSON extends Value.JSON<"position"> {
// (undocumented)
horizontal: Component.JSON;
// (undocumented)
vertical: Component.JSON;
}
// (undocumented)
export namespace Keywords {
// (undocumented)
export type Center = Keyword<"center">;
const // @internal (undocumented)
parseCenter: Parser<Keyword<"center">>;
// (undocumented)
export type Horizontal = Keyword<"left"> | Keyword<"right">;
const // @internal (undocumented)
parseVertical: Parser<Keyword.ToKeywords<"top" | "bottom">>;
horizontal: Component_2.JSON;
// (undocumented)
export type Vertical = Keyword<"top"> | Keyword<"bottom">;
const // @internal (undocumented)
parseHorizontal: Parser<Keyword.ToKeywords<"right" | "left">>;
vertical: Component_2.JSON;
}
export function parse(legacySyntax?: boolean): Parser<Position>;
import Keywords = keywords.Keywords;
import Side = side.Side;
import Component = component.Component;
// Warning: (ae-incompatible-release-tags) The symbol "parseBase" is marked as @public, but its signature references "Fixed" which is marked as @internal
//
// (undocumented)
export type Offset<U extends Unit.Length = Unit.Length> = Length.Fixed<U> | Percentage.Fixed;
// (undocumented)
export namespace Offset {
const // Warning: (ae-incompatible-release-tags) The symbol "parse" is marked as @public, but its signature references "Type" which is marked as @internal
//
// (undocumented)
parse: Parser_2<Slice<Token>, Percentage.Fixed<import("../calculation/numeric").Numeric.Type> | Length.Fixed<Unit.Length>, string, []>;
}
export function parseBase(legacySyntax?: boolean): Parser<Fixed>;
// (undocumented)
export function parse(legacySyntax?: boolean): Parser<Position>;
export function partiallyResolve<H extends Keywords.Horizontal, V extends Keywords.Vertical>(resolver: PartialResolver): (value: Position<H, V>) => PartiallyResolved<H, V>;
// (undocumented)
export class Side<S extends Keywords.Vertical | Keywords.Horizontal = Keywords.Vertical | Keywords.Horizontal, O extends Offset = Offset> extends Value<"side", false> {
// (undocumented)
equals(value: unknown): value is this;
// (undocumented)
hash(hash: Hash): void;
// (undocumented)
isCenter(): boolean;
// (undocumented)
static of<S extends Keywords.Vertical | Keywords.Horizontal, O extends Offset>(side: S, offset?: Option<O>): Side<S, O>;
// (undocumented)
get offset(): Option<O>;
// (undocumented)
resolve(): Side<S, O>;
// (undocumented)
get side(): S;
// (undocumented)
toJSON(): Side.JSON;
// (undocumented)
toString(): string;
}
export type PartiallyResolved<H extends Keywords.Horizontal = Keywords.Horizontal, V extends Keywords.Vertical = Keywords.Vertical> = Position<H, V, Component_2.PartiallyResolved<H>, Component_2.PartiallyResolved<V>>;
// (undocumented)
export namespace Side {
export type PartialResolver = Component_2.PartialResolver;
export interface Resolver extends Length.Resolver {
// (undocumented)
export type Canonical<S extends Keywords.Vertical | Keywords.Horizontal> = Side<S, Percentage.Canonical | Length.Canonical>;
percentageHBase: Length.Canonical;
// (undocumented)
export interface JSON extends Value.JSON<"side"> {
// (undocumented)
offset: Length.Fixed.JSON | Percentage.Fixed.JSON | null;
// (undocumented)
side: Keyword.JSON;
}
const // (undocumented)
parseHorizontalKeywordValue: Parser<Side<Keyword.ToKeywords<"right" | "left">, Offset<Unit.Length>>>;
const // (undocumented)
parseHorizontalKeyword: Parser<Keyword<"center"> | Side<Keyword.ToKeywords<"right" | "left">, Offset<Unit.Length>>>;
const // (undocumented)
parseVerticalKeywordValue: Parser<Side<Keyword.ToKeywords<"top" | "bottom">, Offset<Unit.Length>>>;
const // (undocumented)
parseVerticalKeyword: Parser<Keyword<"center"> | Side<Keyword.ToKeywords<"top" | "bottom">, Offset<Unit.Length>>>;
const // (undocumented)
parseHorizontal: Parser_2<Slice<Token>, Keyword<"center"> | Side<Keyword.ToKeywords<"right" | "left">, Offset<Unit.Length>>, string, []>;
const // (undocumented)
parseVertical: Parser_2<Slice<Token>, Keyword<"center"> | Side<Keyword.ToKeywords<"top" | "bottom">, Offset<Unit.Length>>, string, []>;
percentageVBase: Length.Canonical;
}
{};
}

// @public (undocumented)
export class Radial<I extends Gradient.Item = Gradient.Item, S extends Radial.Shape = Radial.Shape, P extends Position = Position> extends Value<"gradient", false> {
export class Radial<I extends Gradient.Item = Gradient.Item, S extends Radial.Shape = Radial.Shape, P extends Position.Fixed = Position.Fixed> extends Value<"gradient", false> {
// (undocumented)
equals(value: Radial): boolean;
// (undocumented)
Expand All @@ -2142,7 +2082,7 @@ export class Radial<I extends Gradient.Item = Gradient.Item, S extends Radial.Sh
// (undocumented)
get kind(): "radial";
// (undocumented)
static of<I extends Gradient.Item = Gradient.Item, S extends Radial.Shape = Radial.Shape, P extends Position = Position>(shape: S, position: P, items: Iterable<I>, repeats: boolean): Radial<I, S, P>;
static of<I extends Gradient.Item = Gradient.Item, S extends Radial.Shape = Radial.Shape, P extends Position.Fixed = Position.Fixed>(shape: S, position: P, items: Iterable<I>, repeats: boolean): Radial<I, S, P>;
// (undocumented)
get position(): P;
// (undocumented)
Expand All @@ -2160,7 +2100,7 @@ export class Radial<I extends Gradient.Item = Gradient.Item, S extends Radial.Sh
// @public (undocumented)
export namespace Radial {
// (undocumented)
export type Canonical = Radial<Gradient.Hint.Canonical | Gradient.Stop.Canonical, Radial.Circle.Canonical | Radial.Ellipse.Canonical | Radial.Extent, Position.Canonical>;
export type Canonical = Radial<Gradient.Hint.Canonical | Gradient.Stop.Canonical, Radial.Circle.Canonical | Radial.Ellipse.Canonical | Radial.Extent, Position.Fixed>;
// (undocumented)
export class Circle<R extends Length.Fixed = Length.Fixed> implements Equatable, Hashable, Serializable<Circle.JSON> {
// (undocumented)
Expand Down
10 changes: 6 additions & 4 deletions docs/review/api/alfa-style.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import { Image } from '@siteimprove/alfa-css';
import { Iterable as Iterable_2 } from '@siteimprove/alfa-iterable';
import * as json from '@siteimprove/alfa-json';
import { Keyword } from '@siteimprove/alfa-css';
import { Keywords } from '@siteimprove/alfa-css/src/value/position/keywords';
import { Length } from '@siteimprove/alfa-css';
import { LengthPercentage } from '@siteimprove/alfa-css';
import { List } from '@siteimprove/alfa-css';
Expand All @@ -40,6 +41,7 @@ import { Rotate } from '@siteimprove/alfa-css';
import { Serializable } from '@siteimprove/alfa-json';
import { Shadow } from '@siteimprove/alfa-css';
import { Shape } from '@siteimprove/alfa-css';
import { Side } from '@siteimprove/alfa-css/src/value/position/side';
import { Slice } from '@siteimprove/alfa-slice';
import { String as String_2 } from '@siteimprove/alfa-css';
import { Text } from '@siteimprove/alfa-dom';
Expand Down Expand Up @@ -177,8 +179,8 @@ export namespace Longhands {
readonly "background-color": Longhand<Color, Color.Canonical>;
readonly "background-image": Longhand<List<import("./property/background-image").Specified.Item, boolean>, List<Image | Keyword<"none">, boolean>>;
readonly "background-origin": Longhand<List<Box, boolean>, List<Box, boolean>>;
readonly "background-position-x": Longhand<List<import("./property/background-position-x").Specified.Item, boolean>, List<Position | (Length<"px"> | Percentage.Fixed<Numeric.Type>) | Position<Position, Length<"px"> | Percentage.Fixed<Numeric.Type>>, boolean>>;
readonly "background-position-y": Longhand<List<import("./property/background-position-y").Specified.Item, boolean>, List<Position | (Length<"px"> | Percentage.Fixed<Numeric.Type>) | Position<Position, Length<"px"> | Percentage.Fixed<Numeric.Type>>, boolean>>;
readonly "background-position-x": Longhand<List<import("./property/background-position-x").Specified.Item, boolean>, List<Keywords.Center | Side.PartiallyResolved<Keywords.Horizontal>, boolean>>;
readonly "background-position-y": Longhand<List<import("./property/background-position-y").Specified.Item, boolean>, List<Keywords.Center | Side.PartiallyResolved<Keywords.Vertical>, boolean>>;
readonly "background-repeat-x": Longhand<List<import("./property/background-repeat-x").Specified.Item, boolean>, List<import("./property/background-repeat-x").Specified.Item, boolean>>;
readonly "background-repeat-y": Longhand<List<import("./property/background-repeat-x").Specified.Item, boolean>, List<import("./property/background-repeat-x").Specified.Item, boolean>>;
readonly "background-size": Longhand<List<import("./property/background-size").Specified.Item, boolean>, List<Tuple<[LengthPercentage | Keyword<"auto">, LengthPercentage | Keyword<"auto">], boolean> | Keyword<"cover"> | Keyword<"contain">, boolean>>;
Expand Down Expand Up @@ -298,9 +300,9 @@ export namespace Resolver {
// (undocumented)
export function lengthPercentage(base: Length.Canonical, style: Style): LengthPercentage.Resolver;
// (undocumented)
export function position(position: Position, style: Style): Position.Canonical;
export function position(position: Position.Fixed, style: Style): Position.Fixed;
// (undocumented)
export function positionComponent<S extends Position.Keywords.Horizontal | Position.Keywords.Vertical>(position: Position.Component<S>, style: Style): Position.Component.Canonical<S>;
export function positionComponent<S extends Position.Keywords.Horizontal | Position.Keywords.Vertical>(position: Position.Component.Fixed<S>, style: Style): Position.Component.Fixed<S>;
}

// Warning: (ae-forgotten-export) The symbol "Name" needs to be exported by the entry point index.d.ts
Expand Down
Loading