From 033f76bd4954c77ecad8cc3232151b42e0e31ba0 Mon Sep 17 00:00:00 2001 From: Viktoria Dragun Date: Thu, 13 Jun 2024 17:28:32 +0300 Subject: [PATCH] feat: add function to get input states --- .../src/FigmaThemeColorsGenerator.ts | 164 ++++-------------- .../src/getters/get-button-states.ts | 120 +++++++++++++ .../src/getters/get-input-states.ts | 140 +++++++++++++++ .../src/getters/index.ts | 2 + 4 files changed, 298 insertions(+), 128 deletions(-) create mode 100644 theme/theme-colors-generator/src/getters/get-button-states.ts create mode 100644 theme/theme-colors-generator/src/getters/get-input-states.ts create mode 100644 theme/theme-colors-generator/src/getters/index.ts diff --git a/theme/theme-colors-generator/src/FigmaThemeColorsGenerator.ts b/theme/theme-colors-generator/src/FigmaThemeColorsGenerator.ts index 1361e98..cbb2fdd 100644 --- a/theme/theme-colors-generator/src/FigmaThemeColorsGenerator.ts +++ b/theme/theme-colors-generator/src/FigmaThemeColorsGenerator.ts @@ -5,19 +5,21 @@ import { FigmaThemeGenerator } from '@atls/figma-theme-generator-common' import { FigmaThemeGeneratorResult } from '@atls/figma-theme-generator-common' import { clearStringOfSpecialChars } from '@atls/figma-utils' import { isColor } from '@atls/figma-utils' -import { toColorOpacityString } from '@atls/figma-utils' import { toAverage } from '@atls/figma-utils' import { toColorName } from '@atls/figma-utils' import { toColorString } from '@atls/figma-utils' import { walk } from '@atls/figma-utils' -import { ButtonState } from './Interfaces' +import { getButtonStates } from './getters' +import { getInputStates } from './getters' export class FigmaThemeColorsGenerator extends FigmaThemeGenerator { readonly name = 'colors' readonly buttonFrameId = 'Desktop / Buttons' + readonly inputFrameId = 'Desktop / Inputs' + formatString(str: string): string { return camelCase(clearStringOfSpecialChars(str), { pascalCase: false }) } @@ -34,128 +36,17 @@ export class FigmaThemeColorsGenerator extends FigmaThemeGenerator { getColors(nodes) { const colors = {} - const buttonNames: string[] = [] - const buttonStates: ButtonState[] = [] walk(nodes, (node) => { - const { name } = node - - if (name?.match(this.buttonFrameId)) { - const names = node.children.map((buttonName) => buttonName.name) - - const buttons = node.children - .map((item) => { - const obj = { - name: item.name, - default: item.children[0], - hover: item.children[1], - pressed: item.children[2] !== undefined ? item.children[2] : item.children[0], - disabled: item.children[3] !== undefined ? item.children[3] : item.children[0], - } - - const fontDefault = obj.default.children.find((child) => child.type === 'TEXT') - const fontColorDefault = fontDefault - ? this.getColor(fontDefault) - : 'rgba(0, 0, 0, 0.00)' - - const backgroundColorDefault = toColorString(obj.default.backgroundColor) - const borderColorDefault = - obj.default.strokes[0]?.color !== undefined - ? toColorOpacityString( - obj.default.strokes[0].color, - obj.default.strokes[0]?.opacity - ) - : 'rgba(0, 0, 0, 0.00)' - - const fontHover = obj.hover?.children?.find((child) => child.type === 'TEXT') - const fontColorHover = fontHover ? this.getColor(fontHover) : 'rgba(0, 0, 0, 0.00)' - - const backgroundColorHover = obj.hover?.backgroundColor - ? toColorString(obj.hover.backgroundColor) - : 'rgba(0, 0, 0, 0.00)' - const borderColorHover = - obj.hover.strokes[0]?.color !== undefined - ? toColorOpacityString(obj.hover.strokes[0].color, obj.hover.strokes[0]?.opacity) - : 'rgba(0, 0, 0, 0.00)' - - const fontPressed = obj.pressed?.children?.find((child) => child.type === 'TEXT') - const fontColorPressed = fontPressed - ? this.getColor(fontPressed) - : 'rgba(0, 0, 0, 0.00)' - - const backgroundColorPressed = toColorString(obj.pressed.backgroundColor) - const borderColorPressed = - obj.pressed.strokes[0]?.color !== undefined - ? toColorOpacityString( - obj.pressed.strokes[0].color, - obj.pressed.strokes[0]?.opacity - ) - : 'rgba(0, 0, 0, 0.00)' - - const fontDisabled = obj.disabled?.children?.find((child) => child.type === 'TEXT') - const fontColorDisabled = fontDisabled - ? this.getColor(fontDisabled) - : 'rgba(0, 0, 0, 0.00)' - - const backgroundColorDisabled = toColorString(obj.disabled.backgroundColor) - const borderColorDisabled = - obj.disabled.strokes[0]?.color !== undefined - ? toColorOpacityString( - obj.disabled.strokes[0].color, - obj.disabled.strokes[0]?.opacity - ) - : 'rgba(0, 0, 0, 0.00)' - - return { - default: { - background: backgroundColorDefault, - font: fontColorDefault, - border: borderColorDefault, - }, - hover: { - background: backgroundColorHover, - font: fontColorHover, - border: borderColorHover, - }, - pressed: { - background: backgroundColorPressed, - font: fontColorPressed, - border: borderColorPressed, - }, - disabled: { - background: backgroundColorDisabled, - font: fontColorDisabled, - border: borderColorDisabled, - }, - } - }) - .flat() - .filter((item) => item !== undefined) - - buttonStates.push(...buttons) - - names.map((buttonName: string) => { - if (buttonName !== undefined) { - const trimItem = this.formatString(buttonName) - - buttonNames.push(trimItem) - } - - return [] - }) - } - if (node.color && isColor(node.color)) { - // node fills const color = toColorString(node.color) - if (!colors[color]) { colors[color] = node.color } } }) - const colorsResult = Object.keys(colors) + return Object.keys(colors) .sort((a, b) => toAverage(colors[b]) - toAverage(colors[a])) .reduce( (result, color) => ({ @@ -164,6 +55,24 @@ export class FigmaThemeColorsGenerator extends FigmaThemeGenerator { }), {} ) + } + + generate(file: FileResponse): FigmaThemeGeneratorResult { + const colorsResult = this.getColors(file.document.children) + + const { buttonNames, buttonStates } = getButtonStates( + file.document.children, + this.buttonFrameId, + this.getColor.bind(this), + this.formatString.bind(this) + ) + + const { inputNames, inputStates } = getInputStates( + file.document.children, + this.inputFrameId, + this.getColor.bind(this), + this.formatString.bind(this) + ) const buttonColorsResult = buttonNames.reduce( (result, name, index) => ({ @@ -173,24 +82,23 @@ export class FigmaThemeColorsGenerator extends FigmaThemeGenerator { {} ) - return Object.keys(buttonColorsResult).length - ? { - ...colorsResult, - button: { - ...buttonColorsResult, - }, - } - : { - ...colorsResult, - } - } + const inputColorsResult = inputNames.reduce( + (result, name, index) => ({ + ...result, + [name]: inputStates[index], + }), + {} + ) - generate(file: FileResponse): FigmaThemeGeneratorResult { - const values = this.getColors(file.document.children) + const result = { + ...colorsResult, + ...(Object.keys(buttonColorsResult).length ? { button: buttonColorsResult } : {}), + ...(Object.keys(inputColorsResult).length ? { input: inputColorsResult } : {}), + } return { name: this.name, - content: this.exportValuesTemplate('colors', values), + content: this.exportValuesTemplate('colors', result), } } } diff --git a/theme/theme-colors-generator/src/getters/get-button-states.ts b/theme/theme-colors-generator/src/getters/get-button-states.ts new file mode 100644 index 0000000..e33ed2e --- /dev/null +++ b/theme/theme-colors-generator/src/getters/get-button-states.ts @@ -0,0 +1,120 @@ +import { toColorOpacityString } from '@atls/figma-utils' +import { toColorString } from '@atls/figma-utils' + +interface ButtonState { + default: StateColors + hover: StateColors + pressed: StateColors + disabled: StateColors +} + +interface StateColors { + background: string + font: string + border: string +} + +export function getButtonStates( + nodes, + frameId: string, + getColor: (obj: any) => string, + formatString: (str: string) => string +) { + const buttonStates: ButtonState[] = [] + const buttonNames: string[] = [] + + nodes.forEach((node) => { + const { name } = node + if (name?.match(frameId)) { + const names = node.children.map((buttonName) => buttonName.name) + + const buttons = node.children + .map((item) => { + const obj = { + name: item.name, + default: item.children[0], + hover: item.children[1], + pressed: item.children[2] !== undefined ? item.children[2] : item.children[0], + disabled: item.children[3] !== undefined ? item.children[3] : item.children[0], + } + + const fontDefault = obj.default.children.find((child) => child.type === 'TEXT') + const fontColorDefault = fontDefault ? getColor(fontDefault) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorDefault = toColorString(obj.default.backgroundColor) + const borderColorDefault = + obj.default.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.default.strokes[0].color, obj.default.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontHover = obj.hover?.children?.find((child) => child.type === 'TEXT') + const fontColorHover = fontHover ? getColor(fontHover) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorHover = obj.hover?.backgroundColor + ? toColorString(obj.hover.backgroundColor) + : 'rgba(0, 0, 0, 0.00)' + const borderColorHover = + obj.hover.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.hover.strokes[0].color, obj.hover.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontPressed = obj.pressed?.children?.find((child) => child.type === 'TEXT') + const fontColorPressed = fontPressed ? getColor(fontPressed) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorPressed = toColorString(obj.pressed.backgroundColor) + const borderColorPressed = + obj.pressed.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.pressed.strokes[0].color, obj.pressed.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontDisabled = obj.disabled?.children?.find((child) => child.type === 'TEXT') + const fontColorDisabled = fontDisabled ? getColor(fontDisabled) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorDisabled = toColorString(obj.disabled.backgroundColor) + const borderColorDisabled = + obj.disabled.strokes[0]?.color !== undefined + ? toColorOpacityString( + obj.disabled.strokes[0].color, + obj.disabled.strokes[0]?.opacity + ) + : 'rgba(0, 0, 0, 0.00)' + + return { + default: { + background: backgroundColorDefault, + font: fontColorDefault, + border: borderColorDefault, + }, + hover: { + background: backgroundColorHover, + font: fontColorHover, + border: borderColorHover, + }, + pressed: { + background: backgroundColorPressed, + font: fontColorPressed, + border: borderColorPressed, + }, + disabled: { + background: backgroundColorDisabled, + font: fontColorDisabled, + border: borderColorDisabled, + }, + } + }) + .flat() + .filter((item) => item !== undefined) + + buttonStates.push(...buttons) + + names.forEach((buttonName: string) => { + if (buttonName !== undefined) { + const trimItem = formatString(buttonName) + buttonNames.push(trimItem) + } + }) + } + }) + + return { buttonNames, buttonStates } +} diff --git a/theme/theme-colors-generator/src/getters/get-input-states.ts b/theme/theme-colors-generator/src/getters/get-input-states.ts new file mode 100644 index 0000000..f250777 --- /dev/null +++ b/theme/theme-colors-generator/src/getters/get-input-states.ts @@ -0,0 +1,140 @@ +import { toColorOpacityString } from '@atls/figma-utils' +import { toColorString } from '@atls/figma-utils' + +interface InputState { + default: StateColors + active: StateColors + error: StateColors + focus: StateColors + disabled: StateColors +} + +interface StateColors { + background: string + font: string + border: string +} + +export function getInputStates( + nodes, + frameId: string, + getColor: (obj: any) => string, + formatString: (str: string) => string +) { + const inputStates: InputState[] = [] + const inputNames: string[] = [] + + nodes.forEach((node) => { + const { name } = node + if (name?.match(frameId)) { + const names = node.children.map((inputName) => inputName.name) + + const inputs = node.children + .map((item) => { + const obj = { + name: item.name, + default: item.children[0], + active: item.children[1], + error: item.children[2], + focus: item.children[3], + disabled: item.children[4] !== undefined ? item.children[4] : item.children[0], + } + + const fontDefault = obj.default.children.find((child) => child.type === 'TEXT') + const fontColorDefault = fontDefault ? getColor(fontDefault) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorDefault = toColorString(obj.default.backgroundColor) + const borderColorDefault = + obj.default.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.default.strokes[0].color, obj.default.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontActive = obj.active?.children?.find((child) => child.type === 'TEXT') + const fontColorActive = fontActive ? getColor(fontActive) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorActive = obj.active?.backgroundColor + ? toColorString(obj.active.backgroundColor) + : 'rgba(0, 0, 0, 0.00)' + const borderColorActive = + obj.active.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.active.strokes[0].color, obj.active.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontError = obj.error?.children?.find((child) => child.type === 'TEXT') + const fontColorError = fontError ? getColor(fontError) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorError = obj.error?.backgroundColor + ? toColorString(obj.error.backgroundColor) + : 'rgba(0, 0, 0, 0.00)' + const borderColorError = + obj.error?.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.error.strokes[0].color, obj.error.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontFocus = obj.focus?.children?.find((child) => child.type === 'TEXT') + const fontColorFocus = fontFocus ? getColor(fontFocus) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorFocus = obj.focus?.backgroundColor + ? toColorString(obj.focus.backgroundColor) + : 'rgba(0, 0, 0, 0.00)' + const borderColorFocus = + obj.focus?.strokes[0]?.color !== undefined + ? toColorOpacityString(obj.focus.strokes[0].color, obj.focus.strokes[0]?.opacity) + : 'rgba(0, 0, 0, 0.00)' + + const fontDisabled = obj.disabled?.children?.find((child) => child.type === 'TEXT') + const fontColorDisabled = fontDisabled ? getColor(fontDisabled) : 'rgba(0, 0, 0, 0.00)' + + const backgroundColorDisabled = toColorString(obj.disabled.backgroundColor) + const borderColorDisabled = + obj.disabled.strokes[0]?.color !== undefined + ? toColorOpacityString( + obj.disabled.strokes[0].color, + obj.disabled.strokes[0]?.opacity + ) + : 'rgba(0, 0, 0, 0.00)' + + return { + default: { + background: backgroundColorDefault, + font: fontColorDefault, + border: borderColorDefault, + }, + active: { + background: backgroundColorActive, + font: fontColorActive, + border: borderColorActive, + }, + error: { + background: backgroundColorError, + font: fontColorError, + border: borderColorError, + }, + focus: { + background: backgroundColorFocus, + font: fontColorFocus, + border: borderColorFocus, + }, + disabled: { + background: backgroundColorDisabled, + font: fontColorDisabled, + border: borderColorDisabled, + }, + } + }) + .flat() + .filter((item) => item !== undefined) + + inputStates.push(...inputs) + + names.forEach((inputName: string) => { + if (inputName !== undefined) { + const trimItem = formatString(inputName) + inputNames.push(trimItem) + } + }) + } + }) + + return { inputNames, inputStates } +} diff --git a/theme/theme-colors-generator/src/getters/index.ts b/theme/theme-colors-generator/src/getters/index.ts new file mode 100644 index 0000000..700e18a --- /dev/null +++ b/theme/theme-colors-generator/src/getters/index.ts @@ -0,0 +1,2 @@ +export * from './get-input-states' +export * from './get-button-states'