import uuid from "uuid/v4" ; import * as T from "./types" ; import { firstKey , getKeyByIndex } from "./helpers/immutable-map" ; import { layerTypeToName , layerTreeToArray } from "./layerUtils" ; import { assertUnreachable } from "./utils" ; export function makeRef ( id ) { return { type : "ref" , id } ; } export function entry < TValue > ( value ) { return [ uuid ( ) , value ] ; } export function px ( value ) { return { type : "px" , value } ; } export function generateUniqueLayerName ( type , root ) { const existingNames = new Set ( layerTreeToArray ( root ) . map ( ( layer ) => layer . name ) ) ; const prefix = layerTypeToName ( type ) ; if ( ! existingNames . has ( prefix ) ) { return prefix ; } let i = 1 ; while ( existingNames . has ( `${ prefix }${ i }` ) ) { i ++ ; } return `${ prefix }${ i }` ; } export function makeLayer ( id , type , root , refs , componentId ? ) { const name = generateUniqueLayerName ( type , root ) ; switch ( type ) { case "text" : return makeTextLayer ( refs , { name , id } ) ; case "link" : return makeLinkLayer ( refs , { name , id } ) ; case "container" : return makeContainerLayer ( refs , { name , id } ) ; case "image" : return makeImageLayer ( refs , { name , id } ) ; case "component" : if ( componentId == null ) { throw new Error ( "ComponentId is required to create a component layer" ) ; } return makeComponentLayer ( refs , name , componentId , { id } ) ; } assertUnreachable ( type ) ; } export function makeComponentLayer ( refs , name , componentId , props = { } ) { return { type : "component" , id : uuid ( ) , name : name , componentId , mediaQueries : [ ] , bindings : { } , style : { } , props : { } , ... props , } ; } export function makeImageLayer ( refs , props = { } ) { return { type : "image" , id : uuid ( ) , name : "Image" , tag : "img" , props : { src : "" , alt : "" , } , mediaQueries : [ ] , style : { } , bindings : { } , ... props , } ; } export function makeLinkLayer ( refs , props = { } ) { return { type : "link" , id : uuid ( ) , name : "Text" , tag : "a" , children : [ ] , mediaQueries : [ ] , bindings : { } , props : { content : "link" , href : "" , } , style : { display : "inline" , textDecoration : { isStrikedThrough : false , isUnderlined : true , } , color : makeRef ( firstKey ( refs . colors ) ) , fontFamily : makeRef ( firstKey ( refs . fontFamilies ) ) , fontSize : makeRef ( firstKey ( refs . fontSizes ) ) , textAlign : "left" , lineHeight : 1.2 , overrides : [ ] , } , ... props , } ; } export function makeTextLayer ( refs , props = { } ) { return { type : "text" , id : uuid ( ) , name : "Text" , tag : "span" , mediaQueries : [ ] , bindings : { } , props : { content : "Text" , } , style : { display : "block" , textDecoration : { isStrikedThrough : false , isUnderlined : false , } , color : makeRef ( firstKey ( refs . colors ) ) , fontFamily : makeRef ( firstKey ( refs . fontFamilies ) ) , fontSize : makeRef ( firstKey ( refs . fontSizes ) ) , textAlign : "left" , lineHeight : 1.2 , overrides : [ ] , } , ... props , } ; } export function makeContainerLayer ( refs , props = { } ) { return { type : "container" , id : uuid ( ) , name : "container" , tag : "div" , mediaQueries : [ ] , children : [ ] , bindings : { } , props : { } , style : { display : "flex" , flexDirection : "column" , flexWrap : "nowrap" , justifyContent : "flex-start" , alignItems : "stretch" , alignContent : "stretch" , overrides : [ ] , minHeight : "50px" , minWidth : "50px" , backgroundColor : makeRef ( firstKey ( refs . colors ) ) , } , ... props , } ; } export function makeDefaultFontFamilies ( ) { const defaultFontFamily = entry ( { name : "default" , value : '-apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", sans-serif' , } ) ; return new Map ( [ defaultFontFamily ] ) ; } export function makeDefaultColors ( ) { const white = entry ( { name : "white" , value : "#FFFFFF" } ) ; const black = entry ( { name : "black" , value : "#000000" } ) ; const primary = entry ( { name : "primary" , value : "#0076FF" } ) ; return new Map ( [ white , black , primary ] ) ; } export function makeDefaultBreakpoints ( ) { return new Map ( [ entry ( { name : "small" , value : px ( 544 ) } ) , entry ( { name : "medium" , value : px ( 768 ) } ) , entry ( { name : "large" , value : px ( 1012 ) } ) , entry ( { name : "xlarge" , value : px ( 1280 ) } ) , ] ) ; } export function makeDefaultFontSizes ( ) { const fontSizes = new Map ( [ 14 , 16 , 18 , 24 , 26 , 32 ] . map ( ( x , index ) => entry ( { name : `fs-${ index + 1 }` , value : `${ x }px` } ) ) ) ; return fontSizes ; } const iPhoneX = "3c6c1f84-c6b2-46d7-97f9-750cfe25df73" ; const iPad = "3c6c1f84-c6b2-46d7-97f9-750cfe25df74" ; const iPadPro = "3c6c1f84-c6b2-46d7-97f9-750cfe25df75" ; export function makeDefaultArtboards ( ) { return new Map ( [ [ iPhoneX , { name : "iPhone X" , width : "375px" , height : "auto" , backgroundColor : "white" , } , ] , [ iPad , { name : "iPad" , width : "768px" , height : "auto" , backgroundColor : "white" , } , ] , [ iPadPro , { name : "iPad Pro" , width : "1024px" , height : "auto" , backgroundColor : "white" , } , ] , ] ) ; } export function makeComponent ( overrides = { } ) { return { name : "componentName" , props : [ ] , examples : [ ] , ... overrides , } ; } export function makeComponentProp ( overrides = { } ) { return { name : "component-prop-name" , type : "text" , ... overrides , } ; } export function makeDefaultProject ( ) { const fontFamilies = makeDefaultFontFamilies ( ) ; const colors = makeDefaultColors ( ) ; const breakpoints = makeDefaultBreakpoints ( ) ; const fontSizes = makeDefaultFontSizes ( ) ; const artboards = makeDefaultArtboards ( ) ; const refs = { fileName : undefined , isSaved : false , uiState : { type : "typography" , } , artboards , colors , fontFamilies , fontSizes : new Map ( fontSizes ) , breakpoints , components : new Map ( ) , } ; const components = new Map ( [ [ uuid ( ) , { name : "hello-world" , props : [ ] , examples : [ ] , layout : makeContainerLayer ( refs , { style : { display : "flex" , flexDirection : "column" , flexWrap : "nowrap" , justifyContent : "flex-start" , alignItems : "flex-start" , alignContent : "stretch" , overrides : [ ] , } , children : [ makeTextLayer ( refs , { props : { content : "Hello World" , } , style : { backgroundColor : makeRef ( getKeyByIndex ( colors , 2 ) ) , color : makeRef ( firstKey ( colors ) ) , paddingBottom : "16px" , paddingLeft : "16px" , paddingRight : "16px" , paddingTop : "16px" , borderBottomLeftRadius : "3px" , borderBottomRightRadius : "3px" , borderTopLeftRadius : "3px" , borderTopRightRadius : "3px" , } , } ) , ] , } ) , } , ] , ] ) ; refs . components = components ; refs . uiState = { type : "component" , componentId : firstKey ( components ) , isEditing : false , layerEditorMode : "html" , isCodeVisible : false , } ; return refs ; }