mirror of
https://github.com/NativeScript/NativeScript.git
synced 2025-08-15 02:54:11 +08:00
Introduce background shorthand property (#5053)
* Introduce background shorthand style property * Add text property in parser for BackgroundPosition value reason: prevent parsing of background position (pass it as sample string) * Introduce background-shorthand test page * Modify parser unit tests to respect the new BackgroundPosition 'text' property
This commit is contained in:

committed by
Svetoslav

parent
ac3c895c89
commit
fc9a0b7ad8
48
apps/app/ui-tests-app/css/background-shorthand.ts
Normal file
48
apps/app/ui-tests-app/css/background-shorthand.ts
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
import * as pages from "tns-core-modules/ui/page";
|
||||||
|
import { EventData } from "tns-core-modules/data/observable";
|
||||||
|
import * as button from "tns-core-modules/ui/button";
|
||||||
|
|
||||||
|
import { GridLayout } from "tns-core-modules/ui/layouts/grid-layout";
|
||||||
|
|
||||||
|
let testIndex = 0;
|
||||||
|
const tests = [
|
||||||
|
{ name: "black hex color only", background: "#000000" },
|
||||||
|
{ name: "yellow hex color only", background: "#ffff00" },
|
||||||
|
{ name: "blue color only", background: "blue" },
|
||||||
|
{ name: "repeat image only", background: 'url("~/ui-tests-app/resources/images/icon.png")' },
|
||||||
|
|
||||||
|
{ name: "[straight] image only, no-repeat ", background: 'url("~/ui-tests-app/resources/images/icon.png") no-repeat' },
|
||||||
|
{ name: "[straight] green color, image, no-repeat", background: 'green url("~/ui-tests-app/resources/images/icon.png") no-repeat' },
|
||||||
|
{ name: "[straight] yellow hex color, image, no-repeat, position pixels", background: '#ffff00 url("~/ui-tests-app/resources/images/icon.png") no-repeat 200px 200px' },
|
||||||
|
{ name: "[straight] yellow hex color, image, repeat-y, position pixels", background: '#ffff00 url("~/ui-tests-app/resources/images/icon.png") repeat-y 100px 500px' },
|
||||||
|
{ name: "[straight] orange hex color, image, no-repeat, position percents", background: '#F9791F url("~/ui-tests-app/resources/images/icon.png") no-repeat 100% 100%' },
|
||||||
|
{ name: "[straight] green color, image, repeat-x, position percents", background: 'green url("~/ui-tests-app/resources/images/icon.png") repeat-x 100% 100%' },
|
||||||
|
{ name: "[straight] blue color, image, repeat-x, position", background: 'blue url("~/ui-tests-app/resources/images/icon.png") repeat-x 150 150' },
|
||||||
|
|
||||||
|
{ name: "[shuffle] no-repeat, image only", background: 'no-repeat url("~/ui-tests-app/resources/images/icon.png")' },
|
||||||
|
{ name: "[shuffle] no-repeat, green color, image, ", background: 'no-repeat green url("~/ui-tests-app/resources/images/icon.png")' },
|
||||||
|
{ name: "[shuffle] yellow hex color, position pixels, image, no-repeat", background: '#ffff00 200px 200px url("~/ui-tests-app/resources/images/icon.png") no-repeat' },
|
||||||
|
{ name: "[shuffle] image, repeat-y, yellow hex color, position pixels", background: 'url("~/ui-tests-app/resources/images/icon.png") repeat-y #ffff00 100px 500px' },
|
||||||
|
{ name: "[shuffle] position percents, image, no-repeat, orange hex color", background: '100% 100% url("~/ui-tests-app/resources/images/icon.png") no-repeat #F9791F' },
|
||||||
|
{ name: "[shuffle] position percents, image, repeat-x, green color", background: '100% 100% url("~/ui-tests-app/resources/images/icon.png") repeat-x green' },
|
||||||
|
{ name: "[shuffle] image, repeat-x, position, blue color,", background: 'url("~/ui-tests-app/resources/images/icon.png") repeat-x 150 150 blue' },
|
||||||
|
]
|
||||||
|
|
||||||
|
export function onLoaded(args) {
|
||||||
|
applyNextStyle(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function onButtonTap(args) {
|
||||||
|
applyNextStyle(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
function applyNextStyle(args) {
|
||||||
|
let page = <pages.Page>args.object.page;
|
||||||
|
let btn = <button.Button>args.object;
|
||||||
|
let gridElement = <GridLayout>page.getViewById("Container");
|
||||||
|
|
||||||
|
btn.text = tests[testIndex].name;
|
||||||
|
gridElement.background = tests[testIndex].background;
|
||||||
|
|
||||||
|
testIndex = testIndex < tests.length - 1 ? ++testIndex : 0;
|
||||||
|
}
|
7
apps/app/ui-tests-app/css/background-shorthand.xml
Normal file
7
apps/app/ui-tests-app/css/background-shorthand.xml
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<Page xmlns="http://schemas.nativescript.org/tns.xsd" loaded="onLoaded">
|
||||||
|
<GridLayout rows="*, 7*">
|
||||||
|
<Button row="0" text="a1" tap="onButtonTap"/>
|
||||||
|
|
||||||
|
<GridLayout id="Container" fontSize="12" borderColor="black" margin="5" borderWidth="1" row="1"/>
|
||||||
|
</GridLayout>
|
||||||
|
</Page>
|
@ -40,5 +40,6 @@ export function loadExamples() {
|
|||||||
examples.set("styled-formatted-text", "css/styled-formatted-text");
|
examples.set("styled-formatted-text", "css/styled-formatted-text");
|
||||||
examples.set("non-uniform-radius", "css/non-uniform-radius");
|
examples.set("non-uniform-radius", "css/non-uniform-radius");
|
||||||
examples.set("missing-background-image", "css/missing-background-image");
|
examples.set("missing-background-image", "css/missing-background-image");
|
||||||
|
examples.set("background-shorthand", "css/background-shorthand");
|
||||||
return examples;
|
return examples;
|
||||||
}
|
}
|
@ -47,6 +47,7 @@ export interface VerticalAlignWithOffset {
|
|||||||
export interface BackgroundPosition {
|
export interface BackgroundPosition {
|
||||||
readonly x: HorizontalAlign | HorizontalAlignWithOffset;
|
readonly x: HorizontalAlign | HorizontalAlignWithOffset;
|
||||||
readonly y: VerticalAlign | VerticalAlignWithOffset;
|
readonly y: VerticalAlign | VerticalAlignWithOffset;
|
||||||
|
text?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const urlRegEx = /\s*url\((?:('|")([^\1]*)\1|([^\)]*))\)\s*/gy;
|
const urlRegEx = /\s*url\((?:('|")([^\1]*)\1|([^\)]*))\)\s*/gy;
|
||||||
@ -623,6 +624,7 @@ export function parseBackground(text: string, start: number = 0): Parsed<Backgro
|
|||||||
}
|
}
|
||||||
const position = parseBackgroundPosition(text, end, keyword);
|
const position = parseBackgroundPosition(text, end, keyword);
|
||||||
if (position) {
|
if (position) {
|
||||||
|
position.value.text = text.substring(position.start, position.end);
|
||||||
value.position = position.value;
|
value.position = position.value;
|
||||||
end = position.end;
|
end = position.end;
|
||||||
|
|
||||||
|
@ -254,6 +254,13 @@ export abstract class ViewCommon extends ViewBase implements ViewDefinition {
|
|||||||
this.style.color = value;
|
this.style.color = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
get background(): string {
|
||||||
|
return this.style.background;
|
||||||
|
}
|
||||||
|
set background(value: string) {
|
||||||
|
this.style.background = value;
|
||||||
|
}
|
||||||
|
|
||||||
get backgroundColor(): Color {
|
get backgroundColor(): Color {
|
||||||
return this.style.backgroundColor;
|
return this.style.backgroundColor;
|
||||||
}
|
}
|
||||||
|
5
tns-core-modules/ui/core/view/view.d.ts
vendored
5
tns-core-modules/ui/core/view/view.d.ts
vendored
@ -163,6 +163,11 @@ export abstract class View extends ViewBase {
|
|||||||
*/
|
*/
|
||||||
color: Color;
|
color: Color;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets or sets the background style property.
|
||||||
|
*/
|
||||||
|
background: string;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets or sets the background color of the view.
|
* Gets or sets the background color of the view.
|
||||||
*/
|
*/
|
||||||
|
@ -54,6 +54,7 @@ export function transformConverter(text: string): TransformFunctionsInfo;
|
|||||||
export const clipPathProperty: CssProperty<Style, string>;
|
export const clipPathProperty: CssProperty<Style, string>;
|
||||||
export const colorProperty: InheritedCssProperty<Style, Color>;
|
export const colorProperty: InheritedCssProperty<Style, Color>;
|
||||||
|
|
||||||
|
export const backgroundProperty: ShorthandProperty<Style, string>;
|
||||||
export const backgroundColorProperty: CssAnimationProperty<Style, Color>;
|
export const backgroundColorProperty: CssAnimationProperty<Style, Color>;
|
||||||
export const backgroundImageProperty: CssProperty<Style, string>;
|
export const backgroundImageProperty: CssProperty<Style, string>;
|
||||||
export const backgroundRepeatProperty: CssProperty<Style, BackgroundRepeat>;
|
export const backgroundRepeatProperty: CssProperty<Style, BackgroundRepeat>;
|
||||||
|
@ -26,6 +26,8 @@ import {
|
|||||||
multiplyAffine2d,
|
multiplyAffine2d,
|
||||||
} from "../../matrix";
|
} from "../../matrix";
|
||||||
|
|
||||||
|
import * as parser from "../../css/parser";
|
||||||
|
|
||||||
export type LengthDipUnit = { readonly unit: "dip", readonly value: dip };
|
export type LengthDipUnit = { readonly unit: "dip", readonly value: dip };
|
||||||
export type LengthPxUnit = { readonly unit: "px", readonly value: px };
|
export type LengthPxUnit = { readonly unit: "px", readonly value: px };
|
||||||
export type LengthPercentUnit = { readonly unit: "%", readonly value: percent };
|
export type LengthPercentUnit = { readonly unit: "%", readonly value: percent };
|
||||||
@ -544,6 +546,15 @@ function convertTransformValue(property: string, stringValue: string)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Background properties.
|
// Background properties.
|
||||||
|
const backgroundProperty = new ShorthandProperty<Style, string | Color>({
|
||||||
|
name: "background", cssName: "background",
|
||||||
|
getter: function (this: Style) {
|
||||||
|
return `${this.backgroundColor} ${this.backgroundImage} ${this.backgroundRepeat} ${this.backgroundPosition}`;
|
||||||
|
},
|
||||||
|
converter: convertToBackgrounds
|
||||||
|
});
|
||||||
|
backgroundProperty.register(Style);
|
||||||
|
|
||||||
export const backgroundInternalProperty = new CssProperty<Style, Background>({
|
export const backgroundInternalProperty = new CssProperty<Style, Background>({
|
||||||
name: "backgroundInternal",
|
name: "backgroundInternal",
|
||||||
cssName: "_backgroundInternal",
|
cssName: "_backgroundInternal",
|
||||||
@ -603,6 +614,30 @@ export const backgroundPositionProperty = new CssProperty<Style, string>({
|
|||||||
});
|
});
|
||||||
backgroundPositionProperty.register(Style);
|
backgroundPositionProperty.register(Style);
|
||||||
|
|
||||||
|
function convertToBackgrounds(this: void, value: string): [CssProperty<any, any>, any][] {
|
||||||
|
if (typeof value === "string") {
|
||||||
|
const backgrounds = parser.parseBackground(value).value;
|
||||||
|
const backgroundColor = backgrounds.color ? new Color(backgrounds.color) : unsetValue;
|
||||||
|
const backgroundImage = backgrounds.image || unsetValue;
|
||||||
|
const backgroundRepeat = backgrounds.repeat || unsetValue;
|
||||||
|
const backgroundPosition = backgrounds.position ? backgrounds.position.text : unsetValue;
|
||||||
|
|
||||||
|
return [
|
||||||
|
[backgroundColorProperty, backgroundColor],
|
||||||
|
[backgroundImageProperty, backgroundImage],
|
||||||
|
[backgroundRepeatProperty, backgroundRepeat],
|
||||||
|
[backgroundPositionProperty, backgroundPosition]
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
return [
|
||||||
|
[backgroundColorProperty, unsetValue],
|
||||||
|
[backgroundImageProperty, unsetValue],
|
||||||
|
[backgroundRepeatProperty, unsetValue],
|
||||||
|
[backgroundPositionProperty, unsetValue]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function parseBorderColor(value: string): { top: Color, right: Color, bottom: Color, left: Color } {
|
function parseBorderColor(value: string): { top: Color, right: Color, bottom: Color, left: Color } {
|
||||||
let result: { top: Color, right: Color, bottom: Color, left: Color } = { top: undefined, right: undefined, bottom: undefined, left: undefined };
|
let result: { top: Color, right: Color, bottom: Color, left: Color } = { top: undefined, right: undefined, bottom: undefined, left: undefined };
|
||||||
if (value.indexOf("rgb") === 0) {
|
if (value.indexOf("rgb") === 0) {
|
||||||
|
2
tns-core-modules/ui/styling/style/style.d.ts
vendored
2
tns-core-modules/ui/styling/style/style.d.ts
vendored
@ -62,7 +62,7 @@ export class Style extends Observable {
|
|||||||
public tintColor: Color;
|
public tintColor: Color;
|
||||||
public placeholderColor: Color;
|
public placeholderColor: Color;
|
||||||
|
|
||||||
public background: string | Color;
|
public background: string;
|
||||||
public backgroundColor: Color;
|
public backgroundColor: Color;
|
||||||
public backgroundImage: string;
|
public backgroundImage: string;
|
||||||
public backgroundRepeat: BackgroundRepeat;
|
public backgroundRepeat: BackgroundRepeat;
|
||||||
|
@ -35,7 +35,7 @@ export class Style extends Observable implements StyleDefinition {
|
|||||||
public tintColor: Color;
|
public tintColor: Color;
|
||||||
public placeholderColor: Color;
|
public placeholderColor: Color;
|
||||||
|
|
||||||
public background: string | Color;
|
public background: string;
|
||||||
public backgroundColor: Color;
|
public backgroundColor: Color;
|
||||||
public backgroundImage: string;
|
public backgroundImage: string;
|
||||||
public backgroundRepeat: BackgroundRepeat;
|
public backgroundRepeat: BackgroundRepeat;
|
||||||
|
@ -96,6 +96,7 @@ describe("css", () => {
|
|||||||
image: "smiley.gif",
|
image: "smiley.gif",
|
||||||
repeat: "no-repeat",
|
repeat: "no-repeat",
|
||||||
position: {
|
position: {
|
||||||
|
text: "top 50% left 100% ",
|
||||||
x: { align: "left", offset: { value: 1, unit: "%" }},
|
x: { align: "left", offset: { value: 1, unit: "%" }},
|
||||||
y: { align: "top", offset: { value: 0.5, unit: "%" }}
|
y: { align: "top", offset: { value: 0.5, unit: "%" }}
|
||||||
}
|
}
|
||||||
@ -105,6 +106,7 @@ describe("css", () => {
|
|||||||
image: "smiley.gif",
|
image: "smiley.gif",
|
||||||
repeat: "no-repeat",
|
repeat: "no-repeat",
|
||||||
position: {
|
position: {
|
||||||
|
text: "top 50% left 100% ",
|
||||||
x: { align: "left", offset: { value: 1, unit: "%" }},
|
x: { align: "left", offset: { value: 1, unit: "%" }},
|
||||||
y: { align: "top", offset: { value: 0.5, unit: "%" }}
|
y: { align: "top", offset: { value: 0.5, unit: "%" }}
|
||||||
},
|
},
|
||||||
|
Reference in New Issue
Block a user