components.ts

  1import {
  2    font_families,
  3    font_sizes,
  4    FontWeight,
  5} from "../common"
  6import { Layer, Styles, StyleSets, Style } from "../theme/color_scheme"
  7
  8function is_style_set(key: any): key is StyleSets {
  9    return [
 10        "base",
 11        "variant",
 12        "on",
 13        "accent",
 14        "positive",
 15        "warning",
 16        "negative",
 17    ].includes(key)
 18}
 19
 20function is_style(key: any): key is Styles {
 21    return [
 22        "default",
 23        "active",
 24        "disabled",
 25        "hovered",
 26        "pressed",
 27        "inverted",
 28    ].includes(key)
 29}
 30function get_style(
 31    layer: Layer,
 32    possible_style_set_or_style?: any,
 33    possible_style?: any
 34): Style {
 35    let style_set: StyleSets = "base"
 36    let style: Styles = "default"
 37    if (is_style_set(possible_style_set_or_style)) {
 38        style_set = possible_style_set_or_style
 39    } else if (is_style(possible_style_set_or_style)) {
 40        style = possible_style_set_or_style
 41    }
 42
 43    if (is_style(possible_style)) {
 44        style = possible_style
 45    }
 46
 47    return layer[style_set][style]
 48}
 49
 50export function background(layer: Layer, style?: Styles): string
 51export function background(
 52    layer: Layer,
 53    style_set?: StyleSets,
 54    style?: Styles
 55): string
 56export function background(
 57    layer: Layer,
 58    style_set_or_styles?: StyleSets | Styles,
 59    style?: Styles
 60): string {
 61    return get_style(layer, style_set_or_styles, style).background
 62}
 63
 64export function border_color(layer: Layer, style?: Styles): string
 65export function border_color(
 66    layer: Layer,
 67    style_set?: StyleSets,
 68    style?: Styles
 69): string
 70export function border_color(
 71    layer: Layer,
 72    style_set_or_styles?: StyleSets | Styles,
 73    style?: Styles
 74): string {
 75    return get_style(layer, style_set_or_styles, style).border
 76}
 77
 78export function foreground(layer: Layer, style?: Styles): string
 79export function foreground(
 80    layer: Layer,
 81    style_set?: StyleSets,
 82    style?: Styles
 83): string
 84export function foreground(
 85    layer: Layer,
 86    style_set_or_styles?: StyleSets | Styles,
 87    style?: Styles
 88): string {
 89    return get_style(layer, style_set_or_styles, style).foreground
 90}
 91
 92export interface TextStyle extends Object {
 93    family: keyof typeof font_families
 94    color: string
 95    size: number
 96    weight?: FontWeight
 97    underline?: boolean
 98}
 99
100export interface TextProperties {
101    size?: keyof typeof font_sizes
102    weight?: FontWeight
103    underline?: boolean
104    color?: string
105    features?: FontFeatures
106}
107
108interface FontFeatures {
109    /** Contextual Alternates: Applies a second substitution feature based on a match of a character pattern within a context of surrounding patterns */
110    calt?: boolean
111    /** Case-Sensitive Forms: Shifts various punctuation marks up to a position that works better with all-capital sequences */
112    case?: boolean
113    /** Capital Spacing: Adjusts inter-glyph spacing for all-capital text */
114    cpsp?: boolean
115    /** Fractions: Replaces figures separated by a slash with diagonal fractions */
116    frac?: boolean
117    /** Standard Ligatures: Replaces a sequence of glyphs with a single glyph which is preferred for typographic purposes */
118    liga?: boolean
119    /** Oldstyle Figures: Changes selected figures from the default or lining style to oldstyle form. */
120    onum?: boolean
121    /** Ordinals: Replaces default alphabetic glyphs with the corresponding ordinal forms for use after figures */
122    ordn?: boolean
123    /** Proportional Figures: Replaces figure glyphs set on uniform (tabular) widths with corresponding glyphs set on proportional widths */
124    pnum?: boolean
125    /** Stylistic set 01 */
126    ss01?: boolean
127    /** Stylistic set 02 */
128    ss02?: boolean
129    /** Stylistic set 03 */
130    ss03?: boolean
131    /** Stylistic set 04 */
132    ss04?: boolean
133    /** Stylistic set 05 */
134    ss05?: boolean
135    /** Stylistic set 06 */
136    ss06?: boolean
137    /** Stylistic set 07 */
138    ss07?: boolean
139    /** Stylistic set 08 */
140    ss08?: boolean
141    /** Stylistic set 09 */
142    ss09?: boolean
143    /** Stylistic set 10 */
144    ss10?: boolean
145    /** Stylistic set 11 */
146    ss11?: boolean
147    /** Stylistic set 12 */
148    ss12?: boolean
149    /** Stylistic set 13 */
150    ss13?: boolean
151    /** Stylistic set 14 */
152    ss14?: boolean
153    /** Stylistic set 15 */
154    ss15?: boolean
155    /** Stylistic set 16 */
156    ss16?: boolean
157    /** Stylistic set 17 */
158    ss17?: boolean
159    /** Stylistic set 18 */
160    ss18?: boolean
161    /** Stylistic set 19 */
162    ss19?: boolean
163    /** Stylistic set 20 */
164    ss20?: boolean
165    /** Subscript: Replaces default glyphs with subscript glyphs */
166    subs?: boolean
167    /** Superscript: Replaces default glyphs with superscript glyphs */
168    sups?: boolean
169    /** Swash: Replaces default glyphs with swash glyphs for stylistic purposes */
170    swsh?: boolean
171    /** Titling: Replaces default glyphs with titling glyphs for use in large-size settings */
172    titl?: boolean
173    /** Tabular Figures: Replaces figure glyphs set on proportional widths with corresponding glyphs set on uniform (tabular) widths */
174    tnum?: boolean
175    /** Slashed Zero: Replaces default zero with a slashed zero for better distinction between "0" and "O" */
176    zero?: boolean
177}
178
179export function text(
180    layer: Layer,
181    font_family: keyof typeof font_families,
182    style_set: StyleSets,
183    style: Styles,
184    properties?: TextProperties
185): TextStyle
186export function text(
187    layer: Layer,
188    font_family: keyof typeof font_families,
189    style_set: StyleSets,
190    properties?: TextProperties
191): TextStyle
192export function text(
193    layer: Layer,
194    font_family: keyof typeof font_families,
195    style: Styles,
196    properties?: TextProperties
197): TextStyle
198export function text(
199    layer: Layer,
200    font_family: keyof typeof font_families,
201    properties?: TextProperties
202): TextStyle
203export function text(
204    layer: Layer,
205    font_family: keyof typeof font_families,
206    style_set_style_or_properties?: StyleSets | Styles | TextProperties,
207    style_or_properties?: Styles | TextProperties,
208    properties?: TextProperties
209) {
210    const style = get_style(
211        layer,
212        style_set_style_or_properties,
213        style_or_properties
214    )
215
216    if (typeof style_set_style_or_properties === "object") {
217        properties = style_set_style_or_properties
218    }
219    if (typeof style_or_properties === "object") {
220        properties = style_or_properties
221    }
222
223    const size = font_sizes[properties?.size || "sm"]
224    const color = properties?.color || style.foreground
225
226    return {
227        family: font_families[font_family],
228        ...properties,
229        color,
230        size,
231    }
232}
233
234export interface Border {
235    color: string
236    width: number
237    top?: boolean
238    bottom?: boolean
239    left?: boolean
240    right?: boolean
241    overlay?: boolean
242}
243
244export interface BorderProperties {
245    width?: number
246    top?: boolean
247    bottom?: boolean
248    left?: boolean
249    right?: boolean
250    overlay?: boolean
251}
252
253export function border(
254    layer: Layer,
255    style_set: StyleSets,
256    style: Styles,
257    properties?: BorderProperties
258): Border
259export function border(
260    layer: Layer,
261    style_set: StyleSets,
262    properties?: BorderProperties
263): Border
264export function border(
265    layer: Layer,
266    style: Styles,
267    properties?: BorderProperties
268): Border
269export function border(layer: Layer, properties?: BorderProperties): Border
270export function border(
271    layer: Layer,
272    style_set_or_properties?: StyleSets | Styles | BorderProperties,
273    style_or_properties?: Styles | BorderProperties,
274    properties?: BorderProperties
275): Border {
276    const style = get_style(layer, style_set_or_properties, style_or_properties)
277
278    if (typeof style_set_or_properties === "object") {
279        properties = style_set_or_properties
280    }
281    if (typeof style_or_properties === "object") {
282        properties = style_or_properties
283    }
284
285    return {
286        color: style.border,
287        width: 1,
288        ...properties,
289    }
290}
291
292export function svg(
293    color: string,
294    asset: string,
295    width: number,
296    height: number
297) {
298    return {
299        color,
300        asset,
301        dimensions: {
302            width,
303            height,
304        },
305    }
306}