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 shape #1478

Merged
merged 21 commits into from
Oct 18, 2023
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 .changeset/gold-buttons-notice.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
---
"@siteimprove/alfa-style": minor
"@siteimprove/alfa-css": minor
---

**Added:** CSS `Shape` now accept calculated values

Shapes that accept length-percentage are only partially resolved at compute time.
6 changes: 2 additions & 4 deletions .changeset/shy-schools-flash.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
"@siteimprove/alfa-css": minor
---

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

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.
Instead of just accepting the horizontal and vertical components, the type now also requires the horizontal and vertical keywords list (as first and second parameter). The components parameter default to `Position.Component<H>` (reps. `V`) for keywords `H` (resp. `V`).
5 changes: 0 additions & 5 deletions .changeset/thick-ways-clap.md

This file was deleted.

171 changes: 128 additions & 43 deletions docs/review/api/alfa-css.api.md

Large diffs are not rendered by default.

8 changes: 4 additions & 4 deletions docs/review/api/alfa-style.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,9 +161,9 @@ export namespace Longhands {
readonly bottom: Longhand<LengthPercentage | Keyword<"auto">, LengthPercentage | Keyword<"auto">>;
readonly "box-shadow": Longhand<Keyword<"none"> | List<Shadow<Length, Length, Length, Length, Color, boolean>, boolean>, Keyword<"none"> | List<Shadow.Canonical, boolean>>;
readonly "clip-path": Longhand<URL | Keyword<"none"> | Shape<Shape.Basic, Box.Geometry>, URL | Keyword<"none"> | Shape<Shape.Basic, Box.Geometry>>;
readonly clip: Longhand<Keyword<"auto"> | Shape<Rectangle<Length<Unit.Length> | Rectangle.Auto>, Keyword<"border-box">>, Keyword<"auto"> | Shape<Rectangle<Length<Unit.Length> | Rectangle.Auto>, Keyword<"border-box">>>;
readonly clip: Longhand<Keyword<"auto"> | Shape<Rectangle<Length | Rectangle.Auto>, Keyword<"border-box">>, Keyword<"auto"> | Shape<Rectangle<Length | Rectangle.Auto>, Keyword<"border-box">>>;
readonly color: Longhand<Color, Color.Canonical>;
readonly cursor: Longhand<Tuple<[List<URL | Tuple<[URL, Number_2, Number_2], boolean>, boolean>, Keyword<"none"> | Keyword<"auto"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">], boolean>, Tuple<[List<URL | Tuple<[URL, Number_2, Number_2], boolean>, boolean>, Keyword<"none"> | Keyword<"auto"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">], boolean>>;
readonly cursor: Longhand<Tuple<[List<URL | Tuple<[URL, Number_2, Number_2], boolean>, boolean>, Keyword<"auto"> | Keyword<"none"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">], boolean>, Tuple<[List<URL | Tuple<[URL, Number_2, Number_2], boolean>, boolean>, Keyword<"auto"> | Keyword<"none"> | Keyword<"default"> | Keyword<"context-menu"> | Keyword<"help"> | Keyword<"pointer"> | Keyword<"progress"> | Keyword<"wait"> | Keyword<"cell"> | Keyword<"crosshair"> | Keyword<"text"> | Keyword<"vertical-text"> | Keyword<"alias"> | Keyword<"copy"> | Keyword<"move"> | Keyword<"no-drop"> | Keyword<"not-allowed"> | Keyword<"grab"> | Keyword<"grabbing"> | Keyword<"e-resize"> | Keyword<"n-resize"> | Keyword<"ne-resize"> | Keyword<"nw-resize"> | Keyword<"s-resize"> | Keyword<"se-resize"> | Keyword<"sw-resize"> | Keyword<"w-resize"> | Keyword<"ew-resize"> | Keyword<"ns-resize"> | Keyword<"nesw-resize"> | Keyword<"nwse-resize"> | Keyword<"col-resize"> | Keyword<"row-resize"> | Keyword<"all-scroll"> | Keyword<"zoom-in"> | Keyword<"zoom-out">], boolean>>;
readonly display: Longhand<Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">], boolean> | Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">, listitem: Keyword<"list-item">], boolean> | Tuple<[outside: Keyword<"table-row-group"> | Keyword<"table-header-group"> | Keyword<"table-footer-group"> | Keyword<"table-row"> | Keyword<"table-cell"> | Keyword<"table-column-group"> | Keyword<"table-column"> | Keyword<"table-caption"> | Keyword<"ruby-base"> | Keyword<"ruby-text"> | Keyword<"ruby-base-container"> | Keyword<"ruby-text-container">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">], boolean> | Tuple<[Keyword<"none"> | Keyword<"contents">], boolean>, Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">], boolean> | Tuple<[outside: Keyword<"block"> | Keyword<"inline"> | Keyword<"run-in">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">, listitem: Keyword<"list-item">], boolean> | Tuple<[outside: Keyword<"table-row-group"> | Keyword<"table-header-group"> | Keyword<"table-footer-group"> | Keyword<"table-row"> | Keyword<"table-cell"> | Keyword<"table-column-group"> | Keyword<"table-column"> | Keyword<"table-caption"> | Keyword<"ruby-base"> | Keyword<"ruby-text"> | Keyword<"ruby-base-container"> | Keyword<"ruby-text-container">, inside: Keyword<"flow"> | Keyword<"flow-root"> | Keyword<"table"> | Keyword<"flex"> | Keyword<"grid"> | Keyword<"ruby">], boolean> | Tuple<[Keyword<"none"> | Keyword<"contents">], boolean>>;
readonly "flex-direction": Longhand<Keyword.ToKeywords<"row" | "row-reverse" | "column" | "column-reverse">, Keyword.ToKeywords<"row" | "row-reverse" | "column" | "column-reverse">>;
readonly "flex-wrap": Longhand<Keyword.ToKeywords<"nowrap" | "wrap" | "wrap-reverse">, Keyword.ToKeywords<"nowrap" | "wrap" | "wrap-reverse">>;
Expand Down Expand Up @@ -197,8 +197,8 @@ export namespace Longhands {
readonly "outline-offset": Longhand<Length | Length<Unit.Length>, Length>;
readonly "outline-style": Longhand<Keyword.ToKeywords<"none" | "inset" | "auto" | "dotted" | "dashed" | "solid" | "double" | "groove" | "ridge" | "outset">, Keyword.ToKeywords<"none" | "inset" | "auto" | "dotted" | "dashed" | "solid" | "double" | "groove" | "ridge" | "outset">>;
readonly "outline-width": Longhand<Length | Keyword<"thin"> | Keyword<"medium"> | Keyword<"thick">, Length>;
readonly "overflow-x": Longhand<Keyword.ToKeywords<"hidden" | "auto" | "scroll" | "visible" | "clip">, Keyword<"scroll"> | Keyword<"auto"> | Keyword<"hidden"> | Keyword<"visible"> | Keyword<"clip">>;
readonly "overflow-y": Longhand<Keyword.ToKeywords<"hidden" | "auto" | "scroll" | "visible" | "clip">, Keyword<"scroll"> | Keyword<"auto"> | Keyword<"hidden"> | Keyword<"visible"> | Keyword<"clip">>;
readonly "overflow-x": Longhand<Keyword.ToKeywords<"hidden" | "auto" | "scroll" | "visible" | "clip">, Keyword<"auto"> | Keyword<"scroll"> | Keyword<"hidden"> | Keyword<"visible"> | Keyword<"clip">>;
readonly "overflow-y": Longhand<Keyword.ToKeywords<"hidden" | "auto" | "scroll" | "visible" | "clip">, Keyword<"auto"> | Keyword<"scroll"> | Keyword<"hidden"> | Keyword<"visible"> | Keyword<"clip">>;
readonly position: Longhand<Keyword.ToKeywords<"fixed" | "relative" | "static" | "absolute" | "sticky">, Keyword.ToKeywords<"fixed" | "relative" | "static" | "absolute" | "sticky">>;
readonly right: Longhand<LengthPercentage | Keyword<"auto">, LengthPercentage | Keyword<"auto">>;
readonly rotate: Longhand<Rotate | Keyword<"none">, Rotate | Keyword<"none">>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { Value } from "../../../value";

import { Position } from "./position";

const { map, either, option, right } = Parser;
const { map, option, right } = Parser;

/**
* @internal
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ export namespace Radial {
export type Canonical = Radial<
Item.Canonical,
Shape.Canonical,
Position.Fixed
Position.Canonical
>;

export interface JSON extends Value.JSON<"gradient"> {
Expand Down
25 changes: 6 additions & 19 deletions packages/alfa-css/src/value/numeric/length-percentage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,12 @@ const { either, map } = Parser;
/**
* @public
*/
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;
export type LengthPercentage<U extends Unit.Length = Unit.Length> =
| LengthPercentage.Calculated
| Length.Calculated
| Percentage.Calculated
| Length.Fixed<U>
| Percentage.Fixed;

/**
* @public
Expand Down Expand Up @@ -257,10 +250,4 @@ export namespace LengthPercentage {
of
)
);

/**
* @internal
*/
export const parseBase: CSSParser<LengthPercentage<Unit.Length, false>> =
either(Length.parseBase, Percentage.parseBase);
}
46 changes: 13 additions & 33 deletions packages/alfa-css/src/value/position/component.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { Parser } from "@siteimprove/alfa-parser";

import { Parser as CSSParser } from "../../syntax";
import { Unit } from "../../unit";

import { Keyword } from "../keyword";
import { LengthPercentage } from "../numeric";
Expand All @@ -18,9 +17,8 @@ export type Component<
S extends Keywords.Horizontal | Keywords.Vertical =
| Keywords.Horizontal
| Keywords.Vertical,
U extends Unit.Length = Unit.Length,
CALC extends boolean = boolean
> = Keywords.Center | Side<S, U, CALC>;
O extends LengthPercentage = LengthPercentage
> = Keywords.Center | Side<S, O>;

/**
* @public
Expand All @@ -34,12 +32,6 @@ export namespace Component {
S extends Keywords.Horizontal | Keywords.Vertical
> = Keywords.Center | Side.PartiallyResolved<S>;

/**
* @internal
*/
export type Fixed<S extends Keywords.Horizontal | Keywords.Vertical> =
Component<S, Unit.Length, false>;

export type JSON = Keyword.JSON | Side.JSON;

export type Resolver = Side.Resolver;
Expand All @@ -66,37 +58,25 @@ export namespace Component {
* @internal
*/
export function parseOffset<
T extends Keywords.Horizontal | Keywords.Vertical,
CALC extends boolean
>(
side: T,
withCalculation: CALC
): CSSParser<Component<T, Unit.Length, CALC>> {
const parser = (
withCalculation ? LengthPercentage.parse : LengthPercentage.parseBase
) as CSSParser<LengthPercentage<Unit.Length, CALC>>;

return map(parser, (value) => Side.of(side, value));
T extends Keywords.Horizontal | Keywords.Vertical
>(side: T): CSSParser<Component<T>> {
return map(LengthPercentage.parse, (value) => Side.of(side, value));
}

// "center" is included in Side.parse[Horizontal, Vertical]
/**
* @internal
*/
export const parseHorizontal = <CALC extends boolean>(
withCalculation: CALC
) =>
either(
parseOffset(Keyword.of("left"), withCalculation),
Side.parseHorizontal(withCalculation)
);
export const parseHorizontal = either(
parseOffset(Keyword.of("left")),
Side.parseHorizontal
);

/**
* @internal
*/
export const parseVertical = <CALC extends boolean>(withCalculation: CALC) =>
either(
parseOffset(Keyword.of("top"), withCalculation),
Side.parseVertical(withCalculation)
);
export const parseVertical = either(
parseOffset(Keyword.of("top")),
Side.parseVertical
);
}
Loading