diff --git a/tns-core-modules/ui/core/view-common.ts b/tns-core-modules/ui/core/view-common.ts index 77455f39d..77ef770bc 100644 --- a/tns-core-modules/ui/core/view-common.ts +++ b/tns-core-modules/ui/core/view-common.ts @@ -9,7 +9,7 @@ import { gestureFromString, isIOS, traceEnabled, traceWrite, traceCategories, traceNotifyEvent, printUnregisteredProperties } from "./view-base"; import { observe as gestureObserve, GesturesObserver, GestureTypes, GestureEventData } from "ui/gestures"; -import { Font, parseFont } from "ui/styling/font"; +import { Font, parseFont, FontStyle, FontWeight } from "ui/styling/font"; import { fontSizeConverter } from "../styling/converters"; // TODO: Remove this and start using string as source (for android). @@ -1815,12 +1815,8 @@ export const fontSizeProperty = new InheritedCssProperty({ }); fontSizeProperty.register(Style); -export const fontStyleProperty = new InheritedCssProperty({ - name: "fontStyle", cssName: "font-style", defaultValue: "normal", valueChanged: (target, newValue) => { - if (!(newValue === "normal" || newValue === "italic")) { - throw new Error(`font-style should be 'normal' or 'italic'. value: ${newValue}`) - } - +export const fontStyleProperty = new InheritedCssProperty({ + name: "fontStyle", cssName: "font-style", defaultValue: FontStyle.NORMAL, valueConverter: FontStyle.parse, valueChanged: (target, newValue) => { let currentFont = target.fontInternal; if (currentFont.fontStyle !== newValue) { target.fontInternal = currentFont.withFontStyle(newValue); @@ -1829,20 +1825,8 @@ export const fontStyleProperty = new InheritedCssProperty({ - name: "fontWeight", cssName: "font-weight", defaultValue: "normal", valueChanged: (target, newValue) => { - if (!newValue) { - console.trace(); - } - - // TODO: Console.log errors or throw error? - if (!(newValue === "normal" || newValue === "bold" - || newValue === "100" || newValue === "200" || newValue === "300" - || newValue === "400" || newValue === "500" || newValue === "600" - || newValue === "700" || newValue === "800" || newValue === "900")) { - throw new Error(`Invalid font-weight value: ${newValue}`); - } - +export const fontWeightProperty = new InheritedCssProperty({ + name: "fontWeight", cssName: "font-weight", defaultValue: FontWeight.NORMAL, valueConverter: FontWeight.parse, valueChanged: (target, newValue) => { let currentFont = target.fontInternal; if (currentFont.fontWeight !== newValue) { target.fontInternal = currentFont.withFontWeight(newValue); diff --git a/tns-core-modules/ui/styling/font-common.ts b/tns-core-modules/ui/styling/font-common.ts index b1d859640..e56191a8c 100644 --- a/tns-core-modules/ui/styling/font-common.ts +++ b/tns-core-modules/ui/styling/font-common.ts @@ -1,22 +1,23 @@ import { Font as FontDefinition, ParsedFont } from "ui/styling/font"; +import { makeValidator, makeParser} from "ui/core/view"; export abstract class FontBase implements FontDefinition { public static default = undefined; private _fontFamily: string; - private _fontStyle: "normal" | "italic"; - private _fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; + private _fontStyle: FontStyle; + private _fontWeight: FontWeight; private _fontSize: number; get fontFamily(): string { return this._fontFamily; } - get fontStyle(): "normal" | "italic" { + get fontStyle(): FontStyle { return this._fontStyle; } - get fontWeight(): "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900" { + get fontWeight(): FontWeight { return this._fontWeight; } @@ -24,16 +25,16 @@ export abstract class FontBase implements FontDefinition { return this._fontSize; } - get isBold(): boolean { - return this._fontWeight.toLowerCase() === "bold" - || this._fontWeight.toLowerCase() === "700"; - } - get isItalic(): boolean { - return this._fontStyle.toLowerCase() === "italic"; + return this._fontStyle === FontStyle.ITALIC; } - protected constructor(family: string, size: number, style: "normal" | "italic", weight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900") { + get isBold(): boolean { + return this._fontWeight === FontWeight.BOLD + || this._fontWeight === "700"; + } + + protected constructor(family: string, size: number, style: FontStyle, weight: FontWeight) { this._fontFamily = family; this._fontSize = size; this._fontStyle = style; @@ -65,6 +66,29 @@ export abstract class FontBase implements FontDefinition { } } +export type FontStyle = "normal" | "italic"; +export namespace FontStyle { + export const NORMAL: "normal" = "normal"; + export const ITALIC: "italic" = "italic"; + export const isValid = makeValidator(NORMAL, ITALIC); + export const parse = makeParser(isValid, NORMAL); +} + +export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; +export namespace FontWeight { + export const THIN: "100" = "100"; + export const EXTRA_LIGHT: "200" = "200"; + export const LIGHT: "300" = "300"; + export const NORMAL: "normal" = "normal"; + export const MEDIUM: "500" = "500"; + export const SEMI_BOLD: "600" = "600"; + export const BOLD: "bold" = "bold"; + export const EXTRA_BOLD: "800" = "800"; + export const BLACK: "900" = "900"; + export const isValid = makeValidator(THIN, EXTRA_LIGHT, LIGHT, NORMAL, "400", MEDIUM, SEMI_BOLD, BOLD, "700", EXTRA_BOLD, BLACK); + export const parse = makeParser(isValid, NORMAL); +} + export function parseFontFamily(value: string): Array { const result = new Array(); if (!value) { @@ -89,7 +113,10 @@ export module genericFontFamilies { } const styles = new Set(); -["italic", "oblique"].forEach((val, i, a) => styles.add(val)); +[ + FontStyle.NORMAL, + FontStyle.ITALIC +].forEach((val, i, a) => styles.add(val)); // http://www.w3schools.com/cssref/pr_font_weight.asp //- normal(same as 400) @@ -104,7 +131,19 @@ const styles = new Set(); //- 800(Extra Bold / Ultra Bold) (API16 -bold) //- 900(Black / Heavy) (API21 -black) const weights = new Set(); -["normal", "bold", "100", "200", "300", "400", "500", "600", "700", "800", "900"].forEach((val, i, a) => weights.add(val)); +[ + FontWeight.THIN, + FontWeight.EXTRA_LIGHT, + FontWeight.LIGHT, + FontWeight.NORMAL, + "400", + FontWeight.MEDIUM, + FontWeight.SEMI_BOLD, + FontWeight.BOLD, + "700", + FontWeight.EXTRA_BOLD, + FontWeight.BLACK +].forEach((val, i, a) => weights.add(val)); export function parseFont(fontValue: string): ParsedFont { let result: ParsedFont = { diff --git a/tns-core-modules/ui/styling/font.android.ts b/tns-core-modules/ui/styling/font.android.ts index 2510861e3..d90713587 100644 --- a/tns-core-modules/ui/styling/font.android.ts +++ b/tns-core-modules/ui/styling/font.android.ts @@ -1,4 +1,4 @@ -import { FontBase, parseFontFamily, genericFontFamilies, parseFont } from "./font-common"; +import { FontBase, parseFontFamily, genericFontFamilies, parseFont, FontWeight } from "./font-common"; import { enabled as traceEnabled, write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace"; import * as application from "application"; import * as fs from "file-system"; @@ -9,14 +9,12 @@ const FONTS_BASE_PATH = "/fonts/"; const typefaceCache = new Map(); let appAssets: android.content.res.AssetManager; -type fontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; - export class Font extends FontBase { public static default = new Font(undefined, undefined, "normal", "normal"); private _typeface: android.graphics.Typeface; - constructor(family: string, size: number, style: "normal" | "italic", weight: fontWeight) { + constructor(family: string, size: number, style: "normal" | "italic", weight: FontWeight) { super(family, size, style, weight); } @@ -28,7 +26,7 @@ export class Font extends FontBase { return new Font(this.fontFamily, this.fontSize, style, this.fontWeight); } - public withFontWeight(weight: fontWeight): Font { + public withFontWeight(weight: FontWeight): Font { return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight); } @@ -134,26 +132,26 @@ function createTypeface(font: Font): android.graphics.Typeface { return null; } -function getFontWeightSuffix(fontWeight: string): string { +function getFontWeightSuffix(fontWeight: FontWeight): string { switch (fontWeight) { - case "100": + case FontWeight.THIN: return android.os.Build.VERSION.SDK_INT >= 16 ? "-thin" : ""; - case "200": - case "300": + case FontWeight.EXTRA_LIGHT: + case FontWeight.LIGHT: return android.os.Build.VERSION.SDK_INT >= 16 ? "-light" : ""; - case "normal": + case FontWeight.NORMAL: case "400": case undefined: case null: return ""; - case "500": - case "600": + case FontWeight.MEDIUM: + case FontWeight.SEMI_BOLD: return android.os.Build.VERSION.SDK_INT >= 21 ? "-medium" : ""; - case "bold": + case FontWeight.BOLD: case "700": - case "800": + case FontWeight.EXTRA_BOLD: return ""; - case "900": + case FontWeight.BLACK: return android.os.Build.VERSION.SDK_INT >= 21 ? "-black" : ""; default: throw new Error(`Invalid font weight: "${fontWeight}"`); diff --git a/tns-core-modules/ui/styling/font.d.ts b/tns-core-modules/ui/styling/font.d.ts index d29a9f838..cde0e80df 100644 --- a/tns-core-modules/ui/styling/font.d.ts +++ b/tns-core-modules/ui/styling/font.d.ts @@ -3,8 +3,8 @@ public static default: Font; public fontFamily: string; - public fontStyle: "normal" | "italic"; - public fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; + public fontStyle: FontStyle; + public fontWeight: FontWeight; public fontSize: number; public isBold: boolean; @@ -23,10 +23,33 @@ public static equals(value1: Font, value2: Font): boolean; } + export type FontStyle = "normal" | "italic"; + export namespace FontStyle { + export const NORMAL: "normal"; + export const ITALIC: "italic"; + export function isValid(value: any): boolean; + export function parse(value: string): FontStyle; + } + + export type FontWeight = "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; + export namespace FontWeight { + export const THIN: "100"; + export const EXTRA_LIGHT: "200"; + export const LIGHT: "300"; + export const NORMAL: "normal"; + export const MEDIUM: "500"; + export const SEMI_BOLD: "600"; + export const BOLD: "bold"; + export const EXTRA_BOLD: "800"; + export const BLACK: "900"; + export function isValid(value: any): boolean; + export function parse(value: string): FontWeight; + } + interface ParsedFont { - fontStyle?: "normal" | "italic"; + fontStyle?: FontStyle; fontVariant?: string; - fontWeight?: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900", + fontWeight?: FontWeight, lineHeight?: string, fontSize?: string, fontFamily?: string diff --git a/tns-core-modules/ui/styling/font.ios.ts b/tns-core-modules/ui/styling/font.ios.ts index d8c311b51..590eb782d 100644 --- a/tns-core-modules/ui/styling/font.ios.ts +++ b/tns-core-modules/ui/styling/font.ios.ts @@ -1,14 +1,14 @@ -import { FontBase, parseFontFamily, genericFontFamilies, parseFont } from "./font-common"; +import { FontBase, parseFontFamily, genericFontFamilies, parseFont, FontStyle, FontWeight } from "./font-common"; import { enabled as traceEnabled, write as traceWrite, categories as traceCategories, messageType as traceMessageType } from "trace"; import fs = require("file-system"); import * as utils from "utils/utils"; export class Font extends FontBase { - public static default = new Font(undefined, undefined, "normal", "normal"); + public static default = new Font(undefined, undefined, FontStyle.NORMAL, FontWeight.NORMAL); private _uiFont: UIFont; - constructor(family: string, size: number, style: "normal" | "italic", weight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900") { + constructor(family: string, size: number, style: FontStyle, weight: FontWeight) { super(family, size, style, weight); } @@ -16,11 +16,11 @@ export class Font extends FontBase { return new Font(family, this.fontSize, this.fontStyle, this.fontWeight); } - public withFontStyle(style: "normal" | "italic"): Font { + public withFontStyle(style: FontStyle): Font { return new Font(this.fontFamily, this.fontSize, style, this.fontWeight); } - public withFontWeight(weight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"): Font { + public withFontWeight(weight: FontWeight): Font { return new Font(this.fontFamily, this.fontSize, this.fontStyle, weight); } @@ -187,33 +187,33 @@ declare const UIFontWeightBold: number; //0.4 declare const UIFontWeightHeavy: number; //0.56 declare const UIFontWeightBlack: number; //0.62 -function getiOSFontWeight(fontWeight: string): number { +function getiOSFontWeight(fontWeight: FontWeight): number { if (!(UIFont).systemFontOfSizeWeight) { throw new Error("Font weight is available in iOS 8.2 and later."); } switch (fontWeight) { - case "100": + case FontWeight.THIN: return UIFontWeightThin; - case "200": + case FontWeight.EXTRA_LIGHT: return UIFontWeightUltraLight; - case "300": + case FontWeight.LIGHT: return UIFontWeightLight; - case "normal": + case FontWeight.NORMAL: case "400": case undefined: case null: return UIFontWeightRegular; - case "500": + case FontWeight.MEDIUM: return UIFontWeightMedium; - case "600": + case FontWeight.SEMI_BOLD: return UIFontWeightSemibold; - case "bold": + case FontWeight.BOLD: case "700": return UIFontWeightBold; - case "800": + case FontWeight.EXTRA_BOLD: return UIFontWeightHeavy; - case "900": + case FontWeight.BLACK: return UIFontWeightBlack; default: throw new Error(`Invalid font weight: "${fontWeight}"`); @@ -248,39 +248,39 @@ function findCorrectWeightString(fontFamily: string, weightStringAlternatives: A return weightStringAlternatives[0]; } -function getiOSFontFace(fontFamily: string, fontWeight: string, isItalic: boolean): string { +function getiOSFontFace(fontFamily: string, fontWeight: FontWeight, isItalic: boolean): string { // ... with a lot of fuzzy logic and artificial intelligence thanks to the lack of font naming standards. let weight: string; switch (fontWeight) { - case "100": + case FontWeight.THIN: weight = "Thin"; break; - case "200": + case FontWeight.EXTRA_LIGHT: weight = findCorrectWeightString(fontFamily, ["Ultra Light", "UltraLight", "Extra Light", "ExtraLight", "Ultra light", "Ultralight", "Extra light", "Extralight"], isItalic); break; - case "300": + case FontWeight.LIGHT: weight = "Light"; break; - case "normal": + case FontWeight.NORMAL: case "400": case undefined: case null: weight = ""; // We dont' need to write Regular break; - case "500": + case FontWeight.MEDIUM: weight = "Medium"; break; - case "600": + case FontWeight.SEMI_BOLD: weight = findCorrectWeightString(fontFamily, ["Demi Bold", "DemiBold", "Semi Bold", "SemiBold", "Demi bold", "Demibold", "Semi bold", "Semibold"], isItalic); break; - case "bold": + case FontWeight.BOLD: case "700": weight = "Bold"; break; - case "800": + case FontWeight.EXTRA_BOLD: weight = findCorrectWeightString(fontFamily, ["Heavy", "Extra Bold", "ExtraBold", "Extra bold", "Extrabold"], isItalic); break; - case "900": + case FontWeight.BLACK: weight = "Black"; break; default: diff --git a/tns-core-modules/ui/styling/style.d.ts b/tns-core-modules/ui/styling/style.d.ts index 47b37bb6a..989658e09 100644 --- a/tns-core-modules/ui/styling/style.d.ts +++ b/tns-core-modules/ui/styling/style.d.ts @@ -1,6 +1,7 @@ declare module "ui/styling/style" { import { Length, PercentLength, Color, Background, Font, ViewBase, Observable } from "ui/core/view"; import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base"; + import { FontStyle, FontWeight } from "ui/styling/font"; export interface Thickness { left: number; @@ -77,8 +78,8 @@ declare module "ui/styling/style" { public fontSize: number; public fontFamily: string; - public fontStyle: "normal" | "italic"; - public fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; + public fontStyle: FontStyle; + public fontWeight: FontWeight; public font: string; public zIndex: number; diff --git a/tns-core-modules/ui/styling/style.ts b/tns-core-modules/ui/styling/style.ts index 68e2d9450..c0c4a1731 100644 --- a/tns-core-modules/ui/styling/style.ts +++ b/tns-core-modules/ui/styling/style.ts @@ -9,6 +9,7 @@ import { } from "ui/layouts/flexbox-layout"; import { TextAlignment, TextDecoration, TextTransform, WhiteSpace } from "ui/text-base"; +import { FontStyle, FontWeight } from "ui/styling/font"; export class Style extends Observable implements StyleDefinition { constructor(public view: ViewBase) { @@ -56,8 +57,8 @@ export class Style extends Observable implements StyleDefinition { public fontSize: number; public fontFamily: string; - public fontStyle: "normal" | "italic"; - public fontWeight: "100" | "200" | "300" | "normal" | "400" | "500" | "600" | "bold" | "700" | "800" | "900"; + public fontStyle: FontStyle; + public fontWeight: FontWeight; public font: string; public zIndex: number; diff --git a/tsconfig.json b/tsconfig.json index 735d74ff0..ac19b1df6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -17,6 +17,8 @@ ] }, "exclude": [ + "apps", + "tests", "tns-platform-declarations/node_modules/", "tns-platform-declarations/package/", "tns-core-modules/node_modules/",