diff --git a/packages/react-core/.gitignore b/packages/react-core/.gitignore index 77cfc55e590..c85b6f8bc3e 100644 --- a/packages/react-core/.gitignore +++ b/packages/react-core/.gitignore @@ -2,4 +2,5 @@ /deprecated /components /layouts -/helpers \ No newline at end of file +/helpers +yarn.lock diff --git a/packages/react-core/codeConnect/components/AboutModal.figma.tsx b/packages/react-core/codeConnect/components/AboutModal.figma.tsx new file mode 100644 index 00000000000..e0f960b8133 --- /dev/null +++ b/packages/react-core/codeConnect/components/AboutModal.figma.tsx @@ -0,0 +1,18 @@ +// import React from 'react'; +// import { AboutModal } from './AboutModal'; +// import figma from '@figma/code-connect'; + +// /** +// * -- This file was auto-generated by Code Connect -- +// * `props` includes a mapping from Figma properties and variants to +// * suggested values. You should update this to match the props of your +// * code component, and update the `example` function to return the +// * code example you'd like to see in Figma +// */ + +// figma.connect(AboutModal, '[object Object]2879-13973', { +// props: { +// productName: figma.string('Product name') +// }, +// example: (props) => +// }); diff --git a/packages/react-core/codeConnect/config.json b/packages/react-core/codeConnect/config.json new file mode 100644 index 00000000000..790714d2232 --- /dev/null +++ b/packages/react-core/codeConnect/config.json @@ -0,0 +1,4 @@ +{ + "figmaBaseUrl": "https://www.figma.com/design/VMEX8Xg2nzhBX8rfBx53jp/branch/H3LonYnwH26v9zNEa2SXFk/PatternFly-6%3A-Components", + "defaultNodeId": "1-196" +} diff --git a/packages/react-core/codeConnect/scripts/figma-url-fixer.mjs b/packages/react-core/codeConnect/scripts/figma-url-fixer.mjs new file mode 100644 index 00000000000..4e29b858157 --- /dev/null +++ b/packages/react-core/codeConnect/scripts/figma-url-fixer.mjs @@ -0,0 +1,116 @@ +/* eslint-disable no-console */ +import fs from 'fs/promises'; +import { glob } from 'glob'; +import figmaBaseUrl from '../config.json' assert { type: 'json' }; + +/** + * Process a single file to fix Figma URLs with detailed debugging + */ +export async function processFigmaFile(filePath) { + try { + console.log(`\nProcessing file: ${filePath}`); + const content = await fs.readFile(filePath, 'utf8'); + let modified = false; + + // Find all figma.connect calls with string literals as second parameter + // Updated regex to be more flexible with whitespace and formatting + const figmaConnectRegex = /figma\.connect\(\s*[^,]+,\s*(['"])([^'"]+)\1/g; + let match; + let matchCount = 0; + + // Test the content for any figma.connect calls + const hasConnect = content.includes('figma.connect'); + console.log(`Contains figma.connect calls: ${hasConnect}`); + + if (!hasConnect) { + return false; + } + + // Process all matches + while ((match = figmaConnectRegex.exec(content)) !== null) { + matchCount++; + const [fullMatch, quotes, url] = match; + console.log(`\nMatch #${matchCount} found: ${fullMatch}`); + console.log(`URL extracted: ${url}`); + + // Only process if the URL doesn't already have the correct root + const needsUpdate = !url.startsWith(figmaBaseUrl); + console.log(`URL needs update: ${needsUpdate}`); + + if (needsUpdate) { + // Extract node ID from current URL + let nodeId = null; + + // Try to extract from node-id parameter + const nodeIdMatch = url.match(/node-id=([^&]+)/); + if (nodeIdMatch) { + nodeId = nodeIdMatch[1]; + console.log(`Found node-id in URL parameter: ${nodeId}`); + } else { + // Try to extract from end of URL (format: digits-digits) + const pathParts = url.split('/'); + const lastPart = pathParts[pathParts.length - 1]; + if (/^\d+-\d+$/.test(lastPart)) { + nodeId = lastPart; + console.log(`Found node-id at end of URL: ${nodeId}`); + } + } + + // Only update if we successfully extracted a node ID + if (nodeId) { + const newUrl = `${figmaBaseUrl}${nodeId}`; + console.log(`New URL will be: ${newUrl}`); + + // Create new content by replacing the old URL with the new one + const updatedContent = content.replace(fullMatch, fullMatch.replace(url, newUrl)); + + // Check if replacement actually changed anything + if (updatedContent !== content) { + console.log(`Successfully updated URL in content`); + await fs.writeFile(filePath, updatedContent, 'utf8'); + console.log(`Updated file: ${filePath}`); + modified = true; + } else { + console.log(`Warning: Replacement had no effect on content`); + } + } else { + console.log(`Could not extract node ID from URL: ${url}`); + } + } + } + + console.log(`Total matches found: ${matchCount}`); + return modified; + } catch (error) { + console.error(`Error processing ${filePath}:`, error); + return false; + } +} + +// Simple test function that processes one file +export async function testProcessFile(filePath) { + console.log('Running test on file:', filePath); + const result = await processFigmaFile(filePath); + console.log('Processing result:', result); +} + +// If this file is run directly, execute the fix +if (import.meta.url === `file://${process.argv[1]}`) { + const testFile = process.argv[2]; + + if (testFile) { + // Test a specific file if provided + testProcessFile(testFile); + } else { + // Otherwise, find and process all files + console.log('Finding all .figma.tsx files...'); + glob('**/*.figma.tsx', { + ignore: ['**/node_modules/**', '**/dist/**'] + }).then((files) => { + console.log(`Found ${files.length} files to process`); + if (files.length > 0) { + testProcessFile(files[0]); // Test with the first file found + } + }); + } +} diff --git a/packages/react-core/codeConnect/scripts/figma-url-watcher.mjs b/packages/react-core/codeConnect/scripts/figma-url-watcher.mjs new file mode 100644 index 00000000000..e945474eb74 --- /dev/null +++ b/packages/react-core/codeConnect/scripts/figma-url-watcher.mjs @@ -0,0 +1,79 @@ +/* eslint-disable no-console */ +import { glob } from 'glob'; +import chokidar from 'chokidar'; +import { processFigmaFile } from './figma-url-fixer.mjs'; +import figmaBaseUrl from '../config.json' assert { type: 'json' }; + +// Figma file watcher function +async function figmaFileWather() { + console.log('Starting Figma URL watcher...'); + console.log('Current directory:', process.cwd()); + console.log('Using root URL:', figmaBaseUrl); + + // Find all .figma.tsx files directly using glob + const files = await glob('**/*.figma.tsx', { + ignore: ['**/node_modules/**', '**/dist/**', 'codeConnect/tests/**/*'], + absolute: true // Get absolute paths + }); + + console.log(`Found ${files.length} .figma.tsx files in the project:`); + + if (files.length === 0) { + console.log('No .figma.tsx files found. Please check your project structure.'); + return; + } + + // Log found files + files.forEach((file) => console.log(` - ${file}`)); + + // Process all files first + let fixedCount = 0; + for (const file of files) { + try { + const wasFixed = await processFigmaFile(file); + if (wasFixed) { + fixedCount++; + } + } catch (error) { + console.error(`Error processing ${file}:`, error.message); + } + } + + console.log(`Initial processing complete. Fixed ${fixedCount} files.`); + + // Now set up watcher for these specific files + const watcher = chokidar.watch(files, { + persistent: true, + ignoreInitial: true, // We already processed them + awaitWriteFinish: { + stabilityThreshold: 300, + pollInterval: 100 + } + }); + + // Simple file handler + const handleFile = async (filePath) => { + console.log(`File changed: ${filePath}`); + try { + await processFigmaFile(filePath); + } catch (error) { + console.error(`Error processing ${filePath}:`, error.message); + } + }; + + // Set up event handlers + watcher + .on('change', handleFile) + .on('ready', () => { + console.log('Watcher ready. Monitoring these files for changes:'); + files.forEach((file) => console.log(` - ${file}`)); + }) + .on('error', (error) => console.error(`Watcher error:`, error)); + + console.log('Watcher started. Press Ctrl+C to stop.'); +} + +// Run the figmaFileWather function +figmaFileWather().catch((error) => { + console.error('Fatal error:', error); +}); diff --git a/packages/react-core/figma.config.json b/packages/react-core/figma.config.json new file mode 100644 index 00000000000..a149dac5643 --- /dev/null +++ b/packages/react-core/figma.config.json @@ -0,0 +1,33 @@ +{ + "codeConnect": { + "parser": "react", + "label": "PF-React", + "include": [ + "components/*.tsx", + "icons/generated/*.tsx", + "icons/**/*.tsx", + "icons/*.tsx", + "icons/IconWrapper.figma.tsx", + "icons/icons.figma.tsx" + ], + "paths": { + "../generated": ["icons/generated"], + "../src/components/Icon": ["src/components/Icon"] + }, + "aliases": { + "@patternfly/react-core": "." + }, + "options": { + "instanceSwapper": { + "enabled": true + }, + "development": { + "enabled": true, + "verbose": true + }, + "production": { + "enabled": false + } + } + } +} diff --git a/packages/react-core/package.json b/packages/react-core/package.json index a970820a5a7..290b343b7e8 100644 --- a/packages/react-core/package.json +++ b/packages/react-core/package.json @@ -3,6 +3,7 @@ "version": "6.2.0-prerelease.34", "description": "This library provides a set of common React components for use with the PatternFly reference implementation.", "main": "dist/js/index.js", + "type": "module", "module": "dist/esm/index.js", "types": "dist/esm/index.d.ts", "typesVersions": { @@ -42,6 +43,8 @@ "build:umd": "rollup -c --environment IS_PRODUCTION", "build:single:packages": "node ../../scripts/build-single-packages.mjs --config single-packages.config.json", "clean": "rimraf dist components layouts helpers next deprecated", + "figma:watchUrls": "node codeConnect/scripts/figma-url-watcher.mjs", + "figma:fixUrls": "node codeConnect/scripts/figma-url-fixer.mjs", "generate": "node scripts/copyStyles.mjs", "subpaths": "node ../../scripts/exportSubpaths.mjs --config subpaths.config.json" }, @@ -49,12 +52,16 @@ "@patternfly/react-icons": "workspace:^", "@patternfly/react-styles": "workspace:^", "@patternfly/react-tokens": "workspace:^", + "@types/glob": "^8.1.0", + "@types/node": "^22.13.5", "focus-trap": "7.6.4", + "react": "^18.2.0", "react-dropzone": "^14.3.5", "tslib": "^2.8.1" }, "devDependencies": { "@patternfly/patternfly": "6.2.0-prerelease.25", + "@figma/code-connect": "^1.3.1", "case-anything": "^3.1.2", "css": "^3.0.0", "fs-extra": "^11.3.0"