npm package: @pga/pga-component-library
Description: React Component Library
Author: PGA
Latest version: 2.4.2

# PGA Component Library

A React component library for internal component sharing across PGA applications.

## 🚨 Version 2.0.0 - Breaking Changes

**This is a major version release with breaking changes.** Please review the [CHANGELOG.md](./CHANGELOG.md) for detailed migration instructions before upgrading.

**Key requirements for v2.0.0:**

- Node.js 20.19.4+
- React Router DOM 5.3.4+
- Updated import statements (no more `/lib/` or `/es/` paths)
- Migration from Enzyme to React Testing Library (if applicable)

## 🚀 Installation & Usage

### Install the Package

```bash
npm install --save @pga/pga-component-library
```

### Import Components

```javascript
import { Header, Footer, Button } from "@pga/pga-component-library";
```

### View Components

- **Production:** [PGA Component Library](http://components.pga.org/)
- **Sandbox:** [PGA Sandbox](http://components.sandboxpga.org/)

> 💡 **Tip:** Make sure to read the `Notes` tab in the bottom pane for specific component instructions.

## 🛠️ Development Setup

### Prerequisites

- **Node.js 20.19.4+** (use `nvm use` to automatically switch to the correct version)
- **React Router DOM 5.3.4+** in your client project (peer dependency)
- Modern browser support (IE11 no longer supported)

### Get Started

```bash
# Clone the repository
gh repo clone pgahq/pga-component-library
cd pga-component-library

# Install dependencies
nvm install
nvm use
npm install

# Start Storybook for development
npm run storybook
```

### Available Scripts

| Command                      | Description                         |
| ---------------------------- | ----------------------------------- |
| `npm start`                  | Start development server            |
| `npm run storybook`          | Start Storybook on port 6006        |
| `npm test`                   | Run tests                           |
| `npm run test:watch`         | Run tests in watch mode             |
| `npm run coverage`           | Generate test coverage report       |
| `npm run lint`               | Run ESLint and Prettier checks      |
| `npm run lint:fix`           | Auto-fix ESLint and Prettier issues |
| `npm run build`              | Build the component library         |
| `npm run bump-version`       | Bump patch version                  |
| `npm run bump-version:patch` | Bump patch version (1.0.0 → 1.0.1)  |
| `npm run bump-version:minor` | Bump minor version (1.0.0 → 1.1.0)  |
| `npm run bump-version:major` | Bump major version (1.0.0 → 2.0.0)  |
| `npm run sandbox-deploy`     | Deploy to sandbox environment       |

### Local Testing with Client Projects

Use `npm link` to test your component library changes in a client project before publishing:

#### 1. Build and Link the Component Library

```bash
# In the pga-component-library directory
npm run build
npm link
```

#### 2. Link in Your Client Project

```bash
# In your client project directory
npm link @pga/pga-component-library
```

#### 3. Link Shared Dependencies (Required)

To prevent React hook errors and styled-components conflicts:

```bash
# In the pga-component-library directory
npm link ../your-client-project/node_modules/react
npm link ../your-client-project/node_modules/react-dom
npm link ../your-client-project/node_modules/react-router-dom
npm link ../your-client-project/node_modules/styled-components
```

Or

```bash
# In the pga-component-library directory
npm link ../your-client-project/node_modules/react ../your-client-project/node_modules/react-dom ../your-client-project/node_modules/react-router-dom ../your-client-project/node_modules/styled-components
```

#### 4. Test Your Changes

Your client project will now use the local build instead of the published version. Make changes to components, rebuild, and test:

```bash
# After making changes to components
npm run build  # Rebuild the library
# No need to re-link - the client will use the updated build
```

#### 5. Unlink When Done

```bash
# In your client project directory
npm unlink @pga/pga-component-library
npm install  # Reinstall the published version

# In the pga-component-library directory (cleanup)
npm unlink @pga/pga-component-library  # Remove global symlink
npm unlink react react-dom react-router-dom styled-components  # Clean up shared deps
```

#### 💡 Tips for npm link Development

- **Always run `npm run build`** after making changes to see them in your client project
- **Restart your client's dev server** after rebuilding the component library
- **Use `npm ls @pga/pga-component-library`** in your client project to verify you're using the linked version
- **Watch for dependency conflicts** - ensure your client project uses compatible React versions
- **Consider using `npm run build -- --watch`** if your build system supports watch mode for faster iteration

#### ⚠️ Fixing React Hook Errors and styled-components Conflicts with npm link

When using `npm link`, you may encounter "Invalid hook call" errors and styled-components conflicts due to multiple instances of shared dependencies. This is a common issue with linked React libraries and **only affects local development** (not production).

**The Problem**: Even though React and styled-components are listed as `peerDependencies`, `npm link` can create duplicate instances, causing hook violations and styled-components conflicts.

**The Solution**: Link your client app's shared dependencies to the component library:

```bash
# After linking the component library, run this in the component library directory:
cd /path/to/pga-component-library
npm link /path/to/your-client-app/node_modules/react \
         /path/to/your-client-app/node_modules/react-dom \
         /path/to/your-client-app/node_modules/react-router-dom \
         /path/to/your-client-app/node_modules/styled-components
```

**Example for jobs-pga-org**:

```bash
cd /path/to/pga-component-library
npm link ../jobs-pga-org/node_modules/react \
         ../jobs-pga-org/node_modules/react-dom \
         ../jobs-pga-org/node_modules/react-router-dom \
         ../jobs-pga-org/node_modules/styled-components
```

This ensures the component library uses the exact same React and styled-components instances as your client app, eliminating hook errors and styled-components conflicts.

**Note**: This step is **only needed for local development with npm link**. Published packages work correctly without this setup.

## 🧪 Testing

```bash
# Run all tests
npm test

# Run tests in watch mode
npm run test:watch
```

> ⚠️ **Important:** `npm test` automatically runs the linter before executing tests. If there are any linting or formatting issues, the test command will fail. This same behavior applies in CircleCI, so make sure your code passes `npm run lint` before pushing changes.

### Testing Framework

This project uses **React Testing Library** (migrated from Enzyme in v2.0.0) for component testing:

- Focus on testing user behavior rather than implementation details
- Enhanced DOM assertions with `@testing-library/jest-dom`
- Better accessibility testing capabilities
- Modern React testing patterns

## 📦 Deployment

### Sandbox Deployment

To deploy your changes to the `sandbox` environment for testing:

```bash
npm run sandbox-deploy
```

This command pushes your current branch to the `sandbox` branch, which triggers an automatic deployment to the sandbox environment via CircleCI.

### Production Deployment

Production deployments happen automatically when changes are merged to the `main` branch. CircleCI will:

1. Run tests
2. Build the component library
3. Publish to NPM
4. Deploy Storybook to production

## 🤝 Contributing

### Repository Structure

This repository contains two parts:

- **Component Library:** Built with [Vite](https://vitejs.dev/) for fast builds and optimal asset handling
- **Storybook:** Documentation and component showcase

### Creating a New Component

1. **Create the component** in `src/components/YourComponent/`
2. **Export it** in `src/index.js`
3. **Add tests** in `src/components/YourComponent/__tests__/`
4. **Create a story** in `stories/components/YourComponent.stories.js`
   - Include propTypes and clear usage instructions
   - Reference [Storybook Documentation](https://storybook.js.org/basics/introduction/)

### Submitting Changes

1. **Bump the version:**

   ```bash
   npm run bump-version
   ```

2. **Create a Pull Request**
   - CircleCI will automatically run tests
   - On merge to `main`, changes deploy to NPM and production

### Code Quality

- All code must pass linting and formatting checks (`npm run lint`)
- Use `npm run lint:fix` to automatically fix ESLint and Prettier issues
- Tests are required for new components
- Follow existing component patterns and naming conventions

#### Linting and Formatting

This project uses ESLint for code quality and Prettier for consistent formatting:

```bash
# Check for linting and formatting issues
npm run lint

# Auto-fix issues
npm run lint:fix
```

## 🏗️ Architecture

### Tech Stack

- **React** 17.0+ with JSX support
- **Styled Components** 4.3+ for CSS-in-JS styling
- **Bootstrap** 5.0+ (included as dependency)
- **Vite** 5.4+ for fast building with native ESM
- **Storybook** 7.6+ for component documentation
- **Jest** 29+ with React Testing Library for testing
- **ESLint + Prettier** for code quality and formatting
- **TypeScript definitions** generated automatically
- **FontAwesome** 7.0+ for icons

### Browser Support

Supports modern browsers (Chrome, Firefox, Safari, Edge). Legacy IE support was removed with the Vite migration for better performance and smaller bundles.

### Dependencies Included

The component library includes several dependencies that your client projects can leverage:

- **Bootstrap 5.0+**: Modern CSS framework (clients can remove their own Bootstrap dependency)
- **FontAwesome 7.0+**: Comprehensive icon library
- **Reactstrap 9.2+**: Bootstrap components for React
- **React DatePicker**: Date selection components
- **React Select**: Advanced select components

## 📋 Migration Guide

For detailed migration instructions from v1.x to v2.0.0, see [CHANGELOG.md](./CHANGELOG.md#200---2024-12-19).