import { get } from '@ngard/tiny-get' ; import set from 'dset' ; import { System , SystemOptions , SystemBreakpoints , SystemZIndex , SystemFontSizes , SystemSpacing , SystemScale , SystemColorPalette , SystemBrandPalette , SystemType , SystemOptionalKey , } from './types' ; export { System , SystemOptions , SystemBreakpoints , SystemZIndex , SystemFontSizes , SystemSpacing , SystemScale , SystemColorPalette , SystemBrandPalette , SystemType , SystemOptionalKey , } ; /** pxTo(): converts a `rem` or `em` value to `px` */ export const pxTo = ( value , base = 16 , unit = 'rem' ) : string => `${ parseFloat ( value ) / base }${ unit }` ; /** toPx(): converts `px` to `rem` or `em` */ export const toPx = ( value , base = 16 ) : string => `${ parseFloat ( value ) * base }px` ; /** parseUnit(): parses a number and unit string, and returns the unit used */ export const parseUnit = ( str ) : string => str . trim ( ) . match ( /[\d.\-+]*\s*(.*)/ ) [ 1 ] || '' ; const errorIntro = 'design-system-utils:' ; const MissingParent = ( msg ) : string => `${ errorIntro } Values missing at: ${ msg } within your design tokens config` ; const MissingKey = ( location , val , val2 ? ) : string => { const value = val2 === undefined ? val : `${ val }.${ val2 }` ; return `${ errorIntro } There is a missing value at this key: ${ location }.${ value }` ; } ; export default class DesignSystem < T extends System , K extends SystemOptions > { private opts : K ; private ds : T ; constructor ( system , options ? ) { this . opts = Object . assign ( { } , { fontSizeUnit : undefined , } , options ) ; this . ds = system ; } /**
     * get()
     * get any value from the design system object
     */ public get ( value , obj = this . ds ) { return get ( obj , value , undefined ) ; } /**
     * set()
     * set any value in the design system object
     */ public set ( location , value ) { return set ( this . ds , location , value ) ; } /**
     * fontSize()
     * get a font-size value from the design system object
     */ public fontSize ( size ) { const location = 'type.sizes' ; this . parentCheck ( location ) ; let baseFontSize ; if ( typeof this . ds . type . baseFontSize === 'string' ) { baseFontSize = parseFloat ( this . ds . type . baseFontSize ) ; } const value = this . get ( size , this . ds . type . sizes ) ; if ( value === undefined ) { throw new Error ( MissingKey ( location , size ) ) ; } if ( parseUnit ( value ) === this . opts . fontSizeUnit ) { return value ; } switch ( this . opts . fontSizeUnit ) { case 'rem' : return pxTo ( value , baseFontSize , 'rem' ) ; case 'em' : return pxTo ( value , baseFontSize , 'em' ) ; case 'px' : return toPx ( value , baseFontSize ) ; default : return value ; } } /**
     * fs()
     * get a font-size value from the design system object
     * same as fontSize()
     */ public fs ( size ) { return this . fontSize ( size ) ; } /**
     * spacing()
     * get a spacing value from the design system object
     */ public spacing ( val ) { const location = 'spacing.scale' ; this . parentCheck ( location ) ; const value = this . get ( `${ val }` , this . ds . spacing . scale ) ; if ( value === undefined ) { throw new Error ( MissingKey ( location , val ) ) ; } if ( typeof value === 'string' ) { return value ; } return `${ value }px` ; } /**
     * space()
     * get a spacing value from the design system object
     * same as spacing()
     */ public space ( val ) { return this . spacing ( val ) ; } /**
     * color()
     * get a color from your color palette
     * `hue`: can contain a path to be traversed (eg: 'base.background.light'),
     * in that case the `variant` argument is ignored
     */ public color ( hue , variant = 'base' ) { const location = 'colors.colorPalette' ; if ( this . get ( 'colors' , this . ds ) === undefined && this . get ( location , this . ds ) === undefined ) { throw new Error ( MissingParent ( location ) ) ; } const isMultiPathHue = hue . split ( '.' ) . length > 1 ; const value = isMultiPathHue ? this . get ( hue , this . ds . colors . colorPalette ) : this . ds . colors . colorPalette [ hue ] [ variant ] ; if ( value === undefined ) { throw new Error ( MissingKey ( location , hue , variant ) ) ; } return value ; } /**
     * brand()
     * get a color from your brand color palette
     */ public brand ( color ) { const location = 'colors.brand' ; this . parentCheck ( location ) ; const value = this . get ( color , this . ds . colors . brand ) ; if ( value === undefined ) { throw new Error ( MissingKey ( location , color ) ) ; } return value ; } /**
     * bp()
     * get a breakpoint value from the design system object
     */ public bp ( breakpoint ) { const location = 'breakpoints' ; if ( this . get ( location , this . ds ) === undefined ) { throw new Error ( MissingParent ( location ) ) ; } const value = this . get ( breakpoint , this . ds . breakpoints ) ; if ( value === undefined ) { throw new Error ( MissingKey ( location , breakpoint ) ) ; } return value ; } /**
     * z()
     * get a z-index value from the design system object
     */ public z ( z ) { const location = 'zIndex' ; if ( this . get ( location , this . ds ) === undefined ) { throw new Error ( MissingParent ( location ) ) ; } const value = this . get ( z , this . ds . zIndex ) ; if ( value === undefined ) { throw new Error ( MissingKey ( location , z ) ) ; } return value ; } /**
     * multiply()
     * multiply a given value
     */ public multiply ( initial , multiplier ) { const initialVal = typeof initial === 'string' ? parseFloat ( this . get ( initial ) ) : initial ; return initialVal * multiplier ; } private parentCheck ( loc ) { const locPt1 = loc . split ( '.' ) ; if ( this . get ( locPt1 [ 0 ] , this . ds ) === undefined && this . get ( loc , this . ds ) === undefined ) { throw new Error ( MissingParent ( loc ) ) ; } } }