wakuconnect-chat-sdk/packages/colors/scripts/sync.ts

143 lines
3.4 KiB
TypeScript
Raw Normal View History

import { intro, isCancel, outro, spinner, text } from '@clack/prompts'
import * as Figma from 'figma-api'
import fs from 'fs-extra'
import type { GetFileNodesResult } from 'figma-api/lib/api-types'
const FILE_KEY = 'v98g9ZiaSHYUdKWrbFg9eM'
intro('🟥🟧🟨🟩🟦🟪🟫⬛⬜')
const personalAccessToken = await text({
message: 'Your personal Figma access token:',
validate(value) {
if (value.length === 0) return `required`
},
})
if (isCancel(personalAccessToken)) {
outro('Bye!')
process.exit(0)
}
function sortObjectByKey<T extends Record<string, any>>(obj: T): T {
const sortedObj: Record<string, any> = {}
Object.keys(obj)
.sort()
.forEach(key => {
sortedObj[key] = obj[key]
})
return sortedObj as T
}
const figma = new Figma.Api({
personalAccessToken,
})
/**
* Get file styles from Figma
*/
const s = spinner()
s.start('Fetching styles from Figma')
const styles = await figma.getFileStyles(FILE_KEY)
if (styles.error) {
console.log('error:', styles.error)
outro('Error!')
process.exit(1)
}
s.stop('Done!')
/**
* Get colors tokens from Figma
*/
const s2 = spinner()
s2.start('Fetching tokens from Figma')
const nodeIds = styles
.meta!.styles.filter(style => style.style_type === 'FILL')
.map(style => style.node_id)
const { nodes } = (await figma.getFileNodes(
FILE_KEY,
2.0 (#523) * set up tailwind * add typography tokens * add shadows tokens * add border radius tokens * add react-aria * update tailwind config * update tokens * fix deps * add blur variant * update tw config * upgrade storybook * update storybook config * add inter * wip button * wip input * wip tabs * update typography tokens * u storybook * add types to src root * update storybook config * add sb type * u storybook * add icon button * add input * add checkbox * add counter * update checkbox * add dropdown * update button * f storybook types * u deps * update base config * update icon imports * add text * update colors build output * fix import * update colors format * add .vsode setting * update components buidl * mv * u button * add popover * u * add types * u shortcut * fix icons attributes * f * mv * u * add toast * update tw formatting * rm apps * rm examples * rm tamagui * dist tailwind config * rm more * stricter tsconfig * add source field * remove tokens * rm tamagui files * add prettier config to components * u text props * add tooltip * u toast * do not pass props * u icon buton * u dropdown button * add icon only to button * u type * checkbox * wip * fix build * fix components build * u tooltip * add theme * add input * u checkbox * update dropdown-button * add dropdown menu * move input to be reviewew * u dropdown button * u * u popover * u tabs * mv IconComponent -> IconElement * u tag * u context tag * u * fix context tag story * add provider * u button * u avatar * f avatar * a opacity to avatar * f prettier * f avatar * f * f * rm old setting * fix button props * skeleton wip * rm config * a dropdown submenu * add blur variant * add step * add step to tabs * add blur to context tag * u * add 80 to community * u tw config * add type * u checkbox * fix dropdown menu checkbox item * u button * unify content * customize color globally * add icons stories * add colors story * rm * u * rm dep * cleanup * u tsconfig * f opacity for emoji * remove "web#build" task from turbo.json * f dropdown menu * u tw export * add license * add changeset * update readme * f steps * f tag * f button * udpate colors format * update customisation color tailwind config * fix opacity * add shadow dark mode * u readme * u --------- Co-authored-by: Jakub Kotula <520927+jkbktl@users.noreply.github.com> Co-authored-by: Felicio Mununga <felicio@users.noreply.github.com>
2024-09-25 15:17:58 +00:00
nodeIds,
)) as GetFileNodesResult<'FRAME'>
s2.stop('Done!')
/**
* Generate files
*/
const s3 = spinner()
s3.start('Generating colors')
const colors: Record<string, Record<string, string>> = {}
// eslint-disable-next-line @typescript-eslint/no-unused-vars
for (const [_nodeId, value] of Object.entries(nodes)) {
const { document } = value!
const { r, g, b } = document.fills[0].color!
const a = document.fills[0].opacity ?? 1
const red = Math.round(r * 255)
const green = Math.round(g * 255)
const blue = Math.round(b * 255)
const alpha = Math.round(a * 100)
const name = toKebabCase(document.name).replace('-/-', '/')
const [namespace, ...rest] = name.split('/')
const tokenName = normalizeName(namespace, rest.join('-'))
colors[namespace] ??= {}
colors[namespace][tokenName] = `rgba(${red} ${green} ${blue} / ${alpha}%)`
}
/**
* Write tokens to src folder
*/
fs.ensureDirSync('./src')
for (const [namespace, value] of Object.entries(colors)) {
const fileName = `./src/${namespace}.ts`
const tokens = JSON.stringify(sortObjectByKey(value), null, 2)
fs.writeFileSync(fileName, `export const ${namespace} = ${tokens}`, {
encoding: 'utf-8',
})
}
// re-export from index
fs.writeFileSync(
'./src/index.ts',
Object.keys(colors)
.map(key => `export { ${key} } from './${key}'`)
.join('\n'),
2.0 (#523) * set up tailwind * add typography tokens * add shadows tokens * add border radius tokens * add react-aria * update tailwind config * update tokens * fix deps * add blur variant * update tw config * upgrade storybook * update storybook config * add inter * wip button * wip input * wip tabs * update typography tokens * u storybook * add types to src root * update storybook config * add sb type * u storybook * add icon button * add input * add checkbox * add counter * update checkbox * add dropdown * update button * f storybook types * u deps * update base config * update icon imports * add text * update colors build output * fix import * update colors format * add .vsode setting * update components buidl * mv * u button * add popover * u * add types * u shortcut * fix icons attributes * f * mv * u * add toast * update tw formatting * rm apps * rm examples * rm tamagui * dist tailwind config * rm more * stricter tsconfig * add source field * remove tokens * rm tamagui files * add prettier config to components * u text props * add tooltip * u toast * do not pass props * u icon buton * u dropdown button * add icon only to button * u type * checkbox * wip * fix build * fix components build * u tooltip * add theme * add input * u checkbox * update dropdown-button * add dropdown menu * move input to be reviewew * u dropdown button * u * u popover * u tabs * mv IconComponent -> IconElement * u tag * u context tag * u * fix context tag story * add provider * u button * u avatar * f avatar * a opacity to avatar * f prettier * f avatar * f * f * rm old setting * fix button props * skeleton wip * rm config * a dropdown submenu * add blur variant * add step * add step to tabs * add blur to context tag * u * add 80 to community * u tw config * add type * u checkbox * fix dropdown menu checkbox item * u button * unify content * customize color globally * add icons stories * add colors story * rm * u * rm dep * cleanup * u tsconfig * f opacity for emoji * remove "web#build" task from turbo.json * f dropdown menu * u tw export * add license * add changeset * update readme * f steps * f tag * f button * udpate colors format * update customisation color tailwind config * fix opacity * add shadow dark mode * u readme * u --------- Co-authored-by: Jakub Kotula <520927+jkbktl@users.noreply.github.com> Co-authored-by: Felicio Mununga <felicio@users.noreply.github.com>
2024-09-25 15:17:58 +00:00
{ encoding: 'utf-8' },
)
s3.stop('Done!')
function normalizeName(_tokenName: string, value: string): string {
let normalizedValue = value
normalizedValue = value.replace('solid-', '')
normalizedValue = normalizedValue.replace('%', '')
normalizedValue = normalizedValue.replace('-transparent-opa', '/')
normalizedValue = normalizedValue.replace('-transparent-', '/')
normalizedValue = normalizedValue.replace('transparent-', '/')
normalizedValue = normalizedValue.replace('-opa-', '/')
return normalizedValue
}
function toKebabCase(str: string): string {
return str
.replace(/([a-z])([A-Z])/g, '$1-$2') // convert camel case to kebab case
.replace(/[\s_]+/g, '-') // replace spaces and underscores with hyphens
.toLowerCase()
}