2024-12-26 14:41:51 +00:00
< template >
< section class = "mb-6" >
< span class = "block text-lg font-semibold mb-2" > Theme Name < / span >
2024-12-27 20:17:25 +00:00
< input v -model = " themeName " type = "text" autocomplete = "off" class = "px-3 py-2 rounded-md border border-surface-300 dark:border-surface-700 flex-1" maxlength = "25" / >
2024-12-26 14:41:51 +00:00
< / section >
< section class = "mb-6" >
< div class = "text-lg font-semibold mb-2" > Foundation < / div >
< span class = "block text-muted-color leading-6 mb-4" > Start by choosing a built - in theme as a foundation , or import your own design by uploading a tokens . json file created with the Prime UI Kit and Tokens Studio . < / span >
< div class = "flex flex-col" >
< div class = "flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4" >
< span class = "font-semibold" > Base Theme < / span >
< span class = "text-muted-color" > Variety of built - in themes with distinct characteristics . < / span >
< div class = "flex justify-between" >
< SelectButton v -model = " basePreset " :options ="presetOptions" optionLabel = "label" optionValue = "value" :allowEmpty ="false" / >
< button
type = "button"
@ click = "createThemeFromPreset"
icon = "pi pi-download"
class = "px-3 py-2 bg-zinc-950 hover:bg-zinc-800 text-white dark:bg-white dark:hover:bg-gray-100 dark:text-black rounded-md font-medium cursor-pointer transition-colors duration-200 focus:outline focus:outline-offset-2 focus:outline-zinc-950 focus:dark:outline-white"
>
Create
< / button >
< / div >
< / div >
< Divider > OR < / Divider >
< div class = "flex flex-col gap-4 border border-surface-200 dark:border-surface-700 rounded-md p-4" >
< span class = "font-semibold" > Import Figma Tokens < / span >
< span class = "text-muted-color leading-6" > Export the token . json file from Figma Token Studio and import to the Visual Editor . < / span >
< div class = "flex justify-between" >
< FileUpload mode = "basic" pt :root:class ="!justify-start" @select ="onFileSelect($event)" / >
< button
type = "button"
@ click = "createThemeFromFigma"
icon = "pi pi-download"
class = "px-3 py-2 bg-zinc-950 hover:bg-zinc-800 text-white dark:bg-white dark:hover:bg-gray-100 dark:text-black rounded-md font-medium cursor-pointer transition-colors duration-200 focus:outline focus:outline-offset-2 focus:outline-zinc-950 focus:dark:outline-white"
>
Create
< / button >
< / div >
< / div >
< / div >
< / section >
< / template >
< script >
import { usePreset } from '@primevue/themes' ;
import Aura from '@primevue/themes/aura' ;
import Lara from '@primevue/themes/lara' ;
import Material from '@primevue/themes/material' ;
import Nora from '@primevue/themes/nora' ;
const presets = {
Aura ,
Material ,
Lara ,
Nora
} ;
export default {
setup ( ) {
const runtimeConfig = useRuntimeConfig ( ) ;
return {
designerApiBase : runtimeConfig . public . designerApiBase
} ;
} ,
2024-12-28 19:21:13 +00:00
inject : [ 'designerService' ] ,
2024-12-26 14:41:51 +00:00
data ( ) {
return {
themeName : null ,
basePreset : 'Aura' ,
figmaData : null ,
presetOptions : [
{ label : 'Aura' , value : 'Aura' } ,
{ label : 'Material' , value : 'Material' } ,
{ label : 'Lara' , value : 'Lara' } ,
{ label : 'Nora' , value : 'Nora' }
]
} ;
} ,
methods : {
replaceColorPalette ( ) {
this . $appState . designer . theme . preset . semantic . primary = this . $appState . designer . theme . preset . primitive . emerald ;
this . $appState . designer . theme . preset . semantic . colorScheme . light . surface = { ... { 0 : '#ffffff' } , ... this . $appState . designer . theme . preset . primitive . slate } ;
this . $appState . designer . theme . preset . semantic . colorScheme . dark . surface = { ... { 0 : '#ffffff' } , ... this . $appState . designer . theme . preset . primitive . zinc } ;
} ,
async createThemeFromPreset ( ) {
const newPreset = presets [ this . basePreset ] ;
if ( this . basePreset === 'Material' ) {
document . body . classList . add ( 'material' ) ;
this . $primevue . config . ripple = true ;
} else {
document . body . classList . remove ( 'material' ) ;
}
2024-12-28 09:43:15 +00:00
if ( this . $appState . designer . licenseKey ) {
const { data , error } = await $fetch ( this . designerApiBase + '/theme/create' , {
method : 'POST' ,
2025-01-01 11:27:54 +00:00
headers : {
Authorization : ` Bearer ${ this . $appState . designer . ticket } ` ,
'X-License-Key' : this . $appState . designer . licenseKey
} ,
2024-12-28 09:43:15 +00:00
body : {
name : this . themeName ,
preset : newPreset ,
config : {
2025-01-01 11:44:27 +00:00
fontSize : '14px' ,
fontFamily : 'Inter var'
2024-12-28 09:43:15 +00:00
}
2024-12-27 20:17:25 +00:00
}
2024-12-28 09:43:15 +00:00
} ) ;
2024-12-26 14:41:51 +00:00
2024-12-28 09:43:15 +00:00
if ( error ) {
this . $toast . add ( { severity : 'error' , summary : 'An error occured' , detail : error . message , life : 3000 } ) ;
} else {
this . loadThemeEditor ( data . t _key , newPreset ) ;
}
2024-12-26 14:41:51 +00:00
} else {
2024-12-28 09:43:15 +00:00
this . loadThemeEditor ( 'trial' , newPreset ) ;
2024-12-27 20:17:25 +00:00
}
} ,
async createThemeFromFigma ( ) {
2024-12-28 09:43:15 +00:00
if ( this . figmaData ) {
if ( this . $appState . designer . licenseKey ) {
const { data , error } = await $fetch ( this . designerApiBase + '/theme/figma' , {
method : 'POST' ,
2025-01-01 11:27:54 +00:00
headers : {
Authorization : ` Bearer ${ this . $appState . designer . ticket } ` ,
'X-License-Key' : this . $appState . designer . licenseKey
} ,
2024-12-28 09:43:15 +00:00
body : {
name : this . themeName ,
figma _tokens : this . figmaData ,
config : {
2025-01-01 11:44:27 +00:00
fontSize : '14px' ,
fontFamily : 'Inter var'
2024-12-28 09:43:15 +00:00
}
}
} ) ;
if ( error ) {
this . $toast . add ( { severity : 'error' , summary : 'An error occured' , detail : error . message , life : 3000 } ) ;
} else {
2024-12-30 20:13:05 +00:00
this . loadThemeEditor ( data . t _key , data . t _preset ) ;
2025-01-02 08:26:32 +00:00
if ( data . lostAndFound ? . length ) {
this . $toast . add ( { severity : 'warn' , summary : 'Warning' , detail : 'There are missing tokens. An update is recommended using the "Migration Assistant" in the settings section.' } ) ;
}
2024-12-27 20:17:25 +00:00
}
2024-12-28 09:43:15 +00:00
} else {
this . $toast . add ( { severity : 'error' , summary : 'An error occured' , detail : 'A valid license required' , life : 3000 } ) ;
2024-12-27 20:17:25 +00:00
}
} else {
2024-12-28 09:43:15 +00:00
this . $toast . add ( { severity : 'error' , summary : 'An error occured' , detail : 'File is required' , life : 3000 } ) ;
2024-12-26 14:41:51 +00:00
}
} ,
onFileSelect ( event ) {
const file = event . files [ 0 ] ;
if ( ! file ) {
return ;
}
const reader = new FileReader ( ) ;
reader . onload = ( e ) => {
this . figmaData = e . target . result ;
} ;
reader . onerror = ( e ) => {
this . $toast . add ( { severity : 'error' , summary : 'An error occured' , detail : 'Unable to read file' , life : 3000 } ) ;
} ;
reader . readAsText ( file ) ;
} ,
2024-12-27 20:17:25 +00:00
loadThemeEditor ( t _key , preset ) {
this . $appState . designer . theme = {
name : this . themeName ,
key : t _key ,
preset : preset ,
config : {
2025-01-01 11:44:27 +00:00
fontSize : '14px' ,
fontFamily : 'Inter var'
2024-12-26 14:41:51 +00:00
}
2024-12-27 20:17:25 +00:00
} ;
this . replaceColorPalette ( ) ;
usePreset ( preset ) ;
2024-12-28 19:21:13 +00:00
this . designerService . refreshACTokens ( ) ;
2024-12-26 14:41:51 +00:00
2024-12-27 20:17:25 +00:00
this . $appState . designer . activeView = 'editor' ;
2024-12-26 14:41:51 +00:00
}
}
} ;
< / script >