Skip to content

Commit

Permalink
Code Connect v1.2.0
Browse files Browse the repository at this point in the history
  • Loading branch information
figma-bot committed Oct 16, 2024
1 parent 233ec33 commit 659795a
Show file tree
Hide file tree
Showing 56 changed files with 2,017 additions and 805 deletions.
21 changes: 21 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,24 @@
# Code Connect v1.2.0

## Features

### General
- The interactive setup now offers AI support for accurate prop mapping between Figma and code components. Users will now be given the option to use AI during the setup process, which if chosen will assist in creating Code Connect files and attempting to accurately map your code to Figma properties.

Data is used only for mapping and is not stored or used for training. To learn more, visit https://help.figma.com/hc/en-us/articles/23920389749655-Code-Connect

### React
- Added support for returning strings or React components from the `example` function, in addition to JSX
- Added `getProps` on `figma.instance()` which can be used to access props of a nested connected component
- Added `render` on `figma.instance()` which can be used to render a nested connected component dynamically
- Added support for including any custom props in the `props` object, that can be accessed with `getProps` in a parent component

## Fixed

### HTML
- Case of attribute names is now preserved to support Angular (fixes https://github.com/figma/code-connect/issues/172)
- Fixed a bug with `nestedProps` (fixes https://github.com/figma/code-connect/issues/176)

# Code Connect v1.1.4 (26th September 2024)

## Fixed
Expand Down
17 changes: 9 additions & 8 deletions cli/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@figma/code-connect",
"version": "1.1.4",
"version": "1.2.0",
"description": "A tool for connecting your design system components in code with your design system in Figma",
"keywords": [],
"author": "Figma",
Expand Down Expand Up @@ -38,7 +38,7 @@
"dev": "tsx src/cli.ts",
"build": "rm -rf dist && npm run typecheck && tsc",
"build:web": "pnpm build",
"build:webpack": "webpack --mode production",
"build:webpack": "cross-env NODE_OPTIONS=\"--max-old-space-size=4096\" webpack --mode production",
"test": "npm run test:no-coverage -- --coverage",
"test:no-coverage": "cross-env NODE_OPTIONS=--experimental-vm-modules npx jest",
"test:fast": "npm run test -- --testPathIgnorePatterns=template_rendering.test.ts --testPathIgnorePatterns=e2e_parse_command_swift.test.ts --testPathIgnorePatterns=e2e_wizard_swift.test.ts",
Expand All @@ -62,7 +62,7 @@
},
"devDependencies": {
"@types/cross-spawn": "^6.0.6",
"@types/jest": "^29.5.5",
"@types/jest": "^29.5.13",
"@types/jsdom": "^21.1.7",
"@types/lodash": "^4.17.0",
"@types/node": "^20.14.0",
Expand All @@ -73,17 +73,17 @@
"jest": "^29.7.0",
"pkg": "^5.8.1",
"react": "18.2.0",
"ts-jest": "^29.1.1",
"ts-jest": "^29.2.5",
"ts-loader": "^9.5.1",
"tsx": "^4.11.0",
"webpack": "^5.91.0",
"webpack-cli": "^5.1.4"
},
"dependencies": {
"@babel/core": "^7.24.7",
"@babel/generator": "^7.24.7",
"@babel/parser": "^7.24.7",
"@babel/types": "^7.24.7",
"@babel/core": "^7.25.2",
"@babel/generator": "^7.25.2",
"@babel/parser": "^7.25.2",
"@babel/types": "^7.25.2",

"@storybook/csf-tools": "^7.6.7",
"axios": "^1.7.4",
Expand All @@ -104,6 +104,7 @@
"prettier": "^2.8.8",
"prompts": "^2.4.2",
"strip-ansi": "^6.0.0",
"ts-morph": "^23.0.0",
"typescript": "5.4.2",
"zod": "^3.23.6",
"zod-validation-error": "^3.2.0"
Expand Down
2 changes: 1 addition & 1 deletion cli/scripts/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Code Connect for icons

This folder includes example scripts for generating Code Connect files for your components. This is useful for icons, where you might have tons of icons that you don't want to manually connect one by one.
This folder includes example scripts for generating Code Connect files for your components. This is the recommended way of connecting icons, where you might have tons of icons that you don't want to manually connect one by one.

## Usage

Expand Down
38 changes: 38 additions & 0 deletions cli/scripts/import-icons-as-strings.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// change to: "import { client } from '@figma/code-connect'"
import { client } from '../src/react/index_react'
import fs from 'fs'

async function generateIcons() {
// fetch components from a figma file. If the `node-id` query parameter is used,
// only components within those frames will be included. This is useful if your
// file is very large, as this will speed up the query by a lot
let components = await client.getComponents(
'https://figma.com/file/ABc123IjkLmnOPq?node-id=41-41',
)

// Finds all components starting with 'icon' (this assumes icons are named e.g: 'icon-list')
components = components.filter(({ name }) => {
return name.includes('icon')
})

// map each icon to a figma.connect call that looks like this:
// figma.connect('https://figma.com/file/ABc123IjkLmnOPq?node-id=41-41', {
// example: () => "icon-list"
// })
fs.writeFileSync(
'icons.figma.tsx',
`\
import figma from '@figma/code-connect'
${components
.map(
(c) => `figma.connect('${c.figmaUrl}', {
example: () => "${c.name}"
})`,
)
.join('\n')}
`,
)
}

generateIcons()
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"originHash" : "6a346fc32d6af41ee9cbc74e95852610a9fad9416dbc94728135f4316e9fe8ca",
"originHash" : "9937304cb61aff6361579860c5a1d18afa62d808d7e1e39ca036ac6e6e6f72b7",
"pins" : [
{
"identity" : "swift-argument-parser",
Expand All @@ -15,8 +15,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "515f79b522918f83483068d99c68daeb5116342d",
"version" : "600.0.0-prerelease-2024-08-20"
"revision" : "cb53fa1bd3219b0b23ded7dfdd3b2baff266fd25",
"version" : "600.0.0"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "515f79b522918f83483068d99c68daeb5116342d",
"version" : "600.0.0-prerelease-2024-08-20"
"revision" : "cb53fa1bd3219b0b23ded7dfdd3b2baff266fd25",
"version" : "600.0.0"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/apple/swift-syntax",
"state" : {
"revision" : "515f79b522918f83483068d99c68daeb5116342d",
"version" : "600.0.0-prerelease-2024-08-20"
"revision" : "cb53fa1bd3219b0b23ded7dfdd3b2baff266fd25",
"version" : "600.0.0"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ ${path.join(testPath, 'test-component.figma.ts')}${maybeLabelMessage}`,
},
])

expect(json[0].template.startsWith('function _fcc_renderHtmlValue')).toBe(true)
expect(json[0].template.startsWith('function _fcc_templateString')).toBe(true)
// We don't care about checking the contents of the function as this can change
expect(
json[0].template.endsWith('export default figma.html`<my-component></my-component>`\n'),
Expand Down
50 changes: 44 additions & 6 deletions cli/src/connect/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,47 @@ export type EnumValue =
| Function
| Object

/**
* These types are intended to be returned by figma helper functions for exposing the
* supported output modifiers for that type. There's no implementation for these types,
* they are resolved to primitive types when the `props` object is passed to `example`.
*/
export interface ConnectedComponent {
/**
* Returns the resolved props of the connected component. This is useful for accessing
* the `props` object of a child in a parent context. For example:
* ```ts
* figma.connect("parent", {
* props: {
* iconProps: figma.instance("Icon").getProps(),
* },
* example: (iconProps) => <IconButton iconId={iconProps.iconId} />,
* }
*/
getProps<T = any>(): T
/**
* Renders the instance with the provided render function. The function is passed the resolved
* `props` of the nested connected component. This is useful for dynamically rendering a child
* component depending on parent context. For example:
* ```ts
* figma.connect("parent", {
* props: {
* icon: figma.instance("Icon").render(({ iconId }) => <Button.Icon iconId={iconId} />),
* },
* example: ({ icon }) => <Button icon={icon}/>,
* }
*/
render<T = unknown>(renderFunction: (props: T) => JSX.Element): JSX.Element
}

// This contains the base API interface for figma.connect calls across React and
// HTML. Any parts which are platform-specific (either the function signature or
// its docblock) are specified in the individual index_<platform> and added to
// this using union typing.
//
// To override a docblock, all signatures of that function must be moved into
// the platform-specific index file.
export interface FigmaConnectAPI<InstanceChildrenT> {
export interface FigmaConnectAPI<InstanceChildrenT, ChildrenT> {
/**
* Maps a Figma Variant property to a set if values for the connected component. This prop is replaced
* with values from the Figma instance when viewed in Dev Mode. For example:
Expand Down Expand Up @@ -60,7 +93,7 @@ export interface FigmaConnectAPI<InstanceChildrenT> {
*
* @param figmaPropName The name of the property on the Figma component
*/
instance(figmaPropName: string): InstanceChildrenT
instance<T = InstanceChildrenT>(figmaPropName: string): T

/**
* Maps a Figma instance layer to a nested code example. For example:
Expand All @@ -82,7 +115,7 @@ export interface FigmaConnectAPI<InstanceChildrenT> {
*
* @param figmaPropName The name of the property on the Figma component
*/
children(layerNames: string | string[]): InstanceChildrenT
children(layerNames: string | string[]): ChildrenT

/**
* Creates a className string by joining an array of strings. The argument supports both
Expand Down Expand Up @@ -130,7 +163,12 @@ export interface FigmaConnectLink {
// ExampleFnReturnT is the return type of an example function.
// ExtraExampleT allows us to pass in an extra type to the `example` property,
// so that in Storybook, we can use strings to refer to non-hoisted functions
export interface FigmaConnectMeta<T = {}, ExampleFnReturnT = unknown, ExtraExampleT = never> {
export interface FigmaConnectMeta<
PropsT = {},
ResolvedPropsT = {},
ExampleFnReturnT = unknown,
ExtraExampleT = never,
> {
/**
* Restricts this figma connect to any variants that fullfill the given filter.
* The filter is a map of Figma variant names to values. Example:
Expand All @@ -155,15 +193,15 @@ export interface FigmaConnectMeta<T = {}, ExampleFnReturnT = unknown, ExtraExamp
* }),
* }
*/
props?: T
props?: PropsT

/**
* The code example to display in Figma. Any mapped `props` are passed to the component,
* where those values will be replaced with the mapped value when inspecting that instance in Figma.
* @param props
* @returns
*/
example?: ((props: T) => ExampleFnReturnT) | ExtraExampleT
example?: ((props: ResolvedPropsT) => ExampleFnReturnT) | ExtraExampleT

/**
* A list of links that will display in Figma along with the examples
Expand Down
6 changes: 5 additions & 1 deletion cli/src/connect/external_types.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { PropMapping, ValueOf, EnumValue } from './api'
import { PropMapping, ValueOf, EnumValue, ConnectedComponent } from './api'

export function booleanType(_figmaPropName: string): boolean
export function booleanType<V extends EnumValue>(
Expand Down Expand Up @@ -33,3 +33,7 @@ export function classNameType(_className: (string | undefined)[]) {
export function textContentType(_layer: string) {
return ''
}

export function instanceType<T = ConnectedComponent>(_figmaPropName: string): T {
return undefined as T
}
Loading

0 comments on commit 659795a

Please sign in to comment.