figma-local 1.6.0 → 1.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "figma-local",
3
- "version": "1.6.0",
3
+ "version": "1.7.0",
4
4
  "description": "Control Figma Desktop with Claude Code. Smart read, write, and AI-prompt export. No API key required.",
5
5
  "author": "elvke",
6
6
  "license": "MIT",
@@ -5,6 +5,7 @@
5
5
  "main": "code.js",
6
6
  "ui": "ui.html",
7
7
  "capabilities": [],
8
+ "permissions": ["teamlibrary"],
8
9
  "enableProposedApi": false,
9
10
  "editorType": ["figma", "figjam"],
10
11
  "networkAccess": {
package/src/index.js CHANGED
@@ -10573,4 +10573,228 @@ program
10573
10573
  }
10574
10574
  });
10575
10575
 
10576
+ // ============ LIBRARY — access team library components & variables ============
10577
+
10578
+ program
10579
+ .command('library <action>')
10580
+ .description('Access team library components and variables from other Figma files')
10581
+ .option('--key <key>', 'Component key for importing')
10582
+ .option('--name <name>', 'Filter by name (partial match)')
10583
+ .option('--json', 'Output raw JSON')
10584
+ .addHelpText('after', `
10585
+ Actions:
10586
+ collections List all available library variable collections
10587
+ variables List variables from a library collection (use --name to filter)
10588
+ components List available library components (use --name to filter)
10589
+ import Import a component by key (use --key)
10590
+
10591
+ Examples:
10592
+ fig library collections List all library variable collections
10593
+ fig library variables List all library variables
10594
+ fig library variables --name "color" List variables matching "color"
10595
+ fig library components List available library components
10596
+ fig library components --name "button" Find button components
10597
+ fig library import --key "abc123..." Import a component by its key
10598
+ fig library import --key "abc123..." --name "MyButton" Import and rename
10599
+ `)
10600
+ .action(async (action, options) => {
10601
+ checkConnection();
10602
+ const spinner = ora('Accessing library...').start();
10603
+
10604
+ try {
10605
+ if (action === 'collections') {
10606
+ spinner.text = 'Fetching library variable collections...';
10607
+ const code = `(async function() {
10608
+ try {
10609
+ var cols = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
10610
+ return cols.map(function(c) {
10611
+ return { name: c.name, key: c.key, libraryName: c.libraryName };
10612
+ });
10613
+ } catch(e) {
10614
+ return { error: e.message || 'Failed to fetch library collections. Make sure teamlibrary permission is enabled.' };
10615
+ }
10616
+ })()`;
10617
+ const result = await daemonExec('eval', { code });
10618
+ if (result.error) {
10619
+ spinner.fail(result.error);
10620
+ process.exit(1);
10621
+ }
10622
+ spinner.succeed(`Found ${result.length} library variable collection${result.length !== 1 ? 's' : ''}`);
10623
+ if (options.json) {
10624
+ console.log(JSON.stringify(result, null, 2));
10625
+ } else {
10626
+ if (result.length === 0) {
10627
+ console.log(chalk.yellow('No library variable collections found. Make sure you have libraries enabled in this file.'));
10628
+ }
10629
+ for (const col of result) {
10630
+ console.log(` ${chalk.cyan(col.name)} ${chalk.gray('from')} ${chalk.white(col.libraryName)}`);
10631
+ console.log(` ${chalk.gray('key:')} ${col.key}`);
10632
+ }
10633
+ }
10634
+ } else if (action === 'variables') {
10635
+ spinner.text = 'Fetching library variables...';
10636
+ const nameFilter = options.name ? options.name.toLowerCase() : '';
10637
+ const code = `(async function() {
10638
+ try {
10639
+ var cols = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
10640
+ var allVars = [];
10641
+ for (var i = 0; i < cols.length; i++) {
10642
+ try {
10643
+ var vars = await figma.teamLibrary.getVariablesInLibraryCollectionAsync(cols[i].key);
10644
+ for (var j = 0; j < vars.length; j++) {
10645
+ allVars.push({
10646
+ name: vars[j].name,
10647
+ key: vars[j].key,
10648
+ resolvedType: vars[j].resolvedType,
10649
+ collection: cols[i].name,
10650
+ library: cols[i].libraryName
10651
+ });
10652
+ }
10653
+ } catch(e2) {}
10654
+ }
10655
+ ${nameFilter ? `allVars = allVars.filter(function(v) { return v.name.toLowerCase().indexOf('${nameFilter}') !== -1; });` : ''}
10656
+ return allVars;
10657
+ } catch(e) {
10658
+ return { error: e.message || 'Failed to fetch library variables.' };
10659
+ }
10660
+ })()`;
10661
+ const result = await daemonExec('eval', { code });
10662
+ if (result.error) {
10663
+ spinner.fail(result.error);
10664
+ process.exit(1);
10665
+ }
10666
+ spinner.succeed(`Found ${result.length} library variable${result.length !== 1 ? 's' : ''}`);
10667
+ if (options.json) {
10668
+ console.log(JSON.stringify(result, null, 2));
10669
+ } else {
10670
+ if (result.length === 0) {
10671
+ console.log(chalk.yellow('No variables found.' + (nameFilter ? ` Try a different search term.` : '')));
10672
+ }
10673
+ let currentCollection = '';
10674
+ for (const v of result) {
10675
+ const collLabel = `${v.collection} (${v.library})`;
10676
+ if (collLabel !== currentCollection) {
10677
+ currentCollection = collLabel;
10678
+ console.log(chalk.cyan(`\n ${collLabel}`));
10679
+ }
10680
+ console.log(` ${chalk.white(v.name)} ${chalk.gray(`[${v.resolvedType}]`)} ${chalk.gray('key:')} ${v.key}`);
10681
+ }
10682
+ }
10683
+ } else if (action === 'components') {
10684
+ spinner.text = 'Fetching library components...';
10685
+ const nameFilter = options.name ? options.name.toLowerCase() : '';
10686
+ const code = `(async function() {
10687
+ try {
10688
+ var collections = await figma.teamLibrary.getAvailableLibraryVariableCollectionsAsync();
10689
+ var libraryNames = collections.map(function(c) { return c.libraryName; });
10690
+ } catch(e) { var libraryNames = []; }
10691
+ try {
10692
+ // Get components from the assets panel search
10693
+ var components = [];
10694
+ // Try to find components by listing component sets and instances on the current page
10695
+ function findComponents(node) {
10696
+ if (node.type === 'INSTANCE' && node.mainComponent) {
10697
+ try {
10698
+ var mc = node.mainComponent;
10699
+ var parent = mc.parent;
10700
+ components.push({
10701
+ name: mc.name,
10702
+ key: mc.key,
10703
+ componentSetName: parent && parent.type === 'COMPONENT_SET' ? parent.name : null,
10704
+ description: mc.description || '',
10705
+ remote: mc.remote
10706
+ });
10707
+ } catch(e) {}
10708
+ }
10709
+ if ('children' in node) {
10710
+ for (var i = 0; i < node.children.length; i++) {
10711
+ findComponents(node.children[i]);
10712
+ }
10713
+ }
10714
+ }
10715
+ findComponents(figma.currentPage);
10716
+ // Deduplicate by key
10717
+ var seen = {};
10718
+ var unique = [];
10719
+ for (var i = 0; i < components.length; i++) {
10720
+ if (!seen[components[i].key]) {
10721
+ seen[components[i].key] = true;
10722
+ unique.push(components[i]);
10723
+ }
10724
+ }
10725
+ ${nameFilter ? `unique = unique.filter(function(c) { return c.name.toLowerCase().indexOf('${nameFilter}') !== -1 || (c.componentSetName && c.componentSetName.toLowerCase().indexOf('${nameFilter}') !== -1); });` : ''}
10726
+ return { components: unique, note: unique.length === 0 ? 'No library components found on this page. Drag some components from the Assets panel first, or use fig library import --key <key> if you have the component key.' : null };
10727
+ } catch(e) {
10728
+ return { error: e.message || 'Failed to fetch library components.' };
10729
+ }
10730
+ })()`;
10731
+ const result = await daemonExec('eval', { code });
10732
+ if (result.error) {
10733
+ spinner.fail(result.error);
10734
+ process.exit(1);
10735
+ }
10736
+ const comps = result.components || [];
10737
+ spinner.succeed(`Found ${comps.length} component${comps.length !== 1 ? 's' : ''} on this page`);
10738
+ if (options.json) {
10739
+ console.log(JSON.stringify(result, null, 2));
10740
+ } else {
10741
+ if (result.note) {
10742
+ console.log(chalk.yellow(` ${result.note}`));
10743
+ }
10744
+ for (const c of comps) {
10745
+ const setLabel = c.componentSetName ? chalk.gray(` (set: ${c.componentSetName})`) : '';
10746
+ const remoteLabel = c.remote ? chalk.blue(' [library]') : chalk.gray(' [local]');
10747
+ console.log(` ${chalk.white(c.name)}${setLabel}${remoteLabel}`);
10748
+ console.log(` ${chalk.gray('key:')} ${c.key}`);
10749
+ if (c.description) console.log(` ${chalk.gray('desc:')} ${c.description}`);
10750
+ }
10751
+ }
10752
+ } else if (action === 'import') {
10753
+ if (!options.key) {
10754
+ spinner.fail('--key is required. Get the key from: fig library components, or fig library variables');
10755
+ process.exit(1);
10756
+ }
10757
+ spinner.text = `Importing component ${options.key}...`;
10758
+ const importName = options.name || '';
10759
+ const code = `(async function() {
10760
+ try {
10761
+ var component = await figma.importComponentByKeyAsync('${options.key}');
10762
+ if (!component) return { error: 'Component not found for key: ${options.key}' };
10763
+ // Create an instance
10764
+ var instance = component.createInstance();
10765
+ // Place it in the center of the viewport
10766
+ var vp = figma.viewport.center;
10767
+ instance.x = Math.round(vp.x);
10768
+ instance.y = Math.round(vp.y);
10769
+ ${importName ? `instance.name = '${importName}';` : ''}
10770
+ figma.currentPage.selection = [instance];
10771
+ return {
10772
+ name: instance.name,
10773
+ id: instance.id,
10774
+ componentName: component.name,
10775
+ w: Math.round(instance.width),
10776
+ h: Math.round(instance.height)
10777
+ };
10778
+ } catch(e) {
10779
+ return { error: e.message || 'Failed to import component. Check the key is valid.' };
10780
+ }
10781
+ })()`;
10782
+ const result = await daemonExec('eval', { code });
10783
+ if (result.error) {
10784
+ spinner.fail(result.error);
10785
+ process.exit(1);
10786
+ }
10787
+ spinner.succeed(`Imported "${result.componentName}" as ${result.name} (${result.w}x${result.h})`);
10788
+ console.log(` ${chalk.gray('id:')} ${result.id}`);
10789
+ console.log(chalk.gray(' Component is now selected on the canvas.'));
10790
+ } else {
10791
+ spinner.fail(`Unknown action: ${action}. Use: collections, variables, components, import`);
10792
+ process.exit(1);
10793
+ }
10794
+ } catch (e) {
10795
+ spinner.fail(`Library access failed: ${e.message}`);
10796
+ process.exit(1);
10797
+ }
10798
+ });
10799
+
10576
10800
  program.parse();