# Modus Web Components 2.0 - Framework Documentation

## Table of Contents
1. [Overview](#overview)
2. [General Setup](#general-setup)
3. [React Implementation](#react-implementation)
4. [Angular Implementation](#angular-implementation)
5. [Event Handling Guide](#event-handling-guide)
6. [Component Reference](#component-reference)

---

## Overview

### Metadata
- **Library Name**: @trimble-oss/moduswebcomponents
- **Version**: 2.0

### Introduction

Modus Web Components 2.0 is a library of reusable UI components built with Web Components technology. These components are framework-agnostic and can be used in any web application regardless of the technology stack. The library provides a consistent design system following Trimble's Modus Design guidelines.

**Key Features:**
- Framework-agnostic components
- TypeScript support
- Multiple theming options
- Accessibility compliance
- Responsive design
- Shadow DOM disabled by default for easier styling

---

## General Setup

### Base Installation

---

## React Implementation

### Complete Step-by-Step Installation Guide

Follow these steps **in order** to properly set up Modus Web Components 2.0 in your React application:

#### Step 1: Install Core Modus Web Components Package

```powershell
npm install @trimble-oss/moduswebcomponents --legacy-peer-deps;
```

#### Step 2: Install React-Specific Package

```powershell
npm install @trimble-oss/moduswebcomponents-react --legacy-peer-deps;
```

#### Step 3: Define Custom Elements

Register the custom elements in your React application entry point (usually `main.jsx` or `index.js`):

```javascript
// main.jsx or index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { defineCustomElements } from '@trimble-oss/moduswebcomponents/loader';
import App from './App.jsx';

// Define custom elements BEFORE rendering your app
defineCustomElements();

ReactDOM.createRoot(document.getElementById('root')).render(
  <React.StrictMode>
    <App />
  </React.StrictMode>
);
```

#### Step 4: Add CSS Imports

Add the Modus CSS to your global CSS file (usually `index.css` or `main.css`):

```css
/* index.css or main.css */
@import '@trimble-oss/moduswebcomponents/modus-wc-styles.css';
```

#### Step 5: Add Modus Icons

Add the Modus Icons to your application's HTML head section (usually `index.html`):

```html
<!-- index.html -->
<head>
  <!-- Preload for performance -->
  <link
    rel="preload"
    href="https://cdn.jsdelivr.net/npm/@trimble-oss/modus-icons@latest/dist/modus-outlined/fonts/modus-icons.css"
    as="style"
    crossorigin="anonymous"
  />
  <!-- Actual stylesheet -->
  <link
    rel="stylesheet"
    href="https://cdn.jsdelivr.net/npm/@trimble-oss/modus-icons@latest/dist/modus-outlined/fonts/modus-icons.css"
  />
</head>
```

#### Step 6: Verify Installation

Test your setup by using a simple component:

```jsx
// App.jsx
import { ModusWcButton } from '@trimble-oss/moduswebcomponents-react';

function App() {
  return (
    <div>
      <ModusWcButton variant="primary">Test Button</ModusWcButton>
    </div>
  );
}

export default App;
```

### Installation Summary

**Complete installation requires these 5 steps:**
1. `npm install @trimble-oss/moduswebcomponents`
2. `npm install @trimble-oss/moduswebcomponents-react`
3. Call `defineCustomElements()` in your main entry file
4. Import `@trimble-oss/moduswebcomponents/modus-wc-styles.css` in your global CSS
5. Add Modus Icons CDN links to your HTML head

**⚠️ Important Notes:**
- Follow the steps in this **exact order**
- Do not skip any steps
- `defineCustomElements()` must be called before React renders your app
- CSS import must be in your global CSS file
- Icons are required for many components to display properly

### Basic React Usage

```jsx
// React usage
<ModusWcButton variant="primary">Click me</ModusWcButton>
```

### React TypeScript Support

```typescript
// TypeScript example with React
import { ISelectOption, ModusWcSelectCustomEvent } from '@trimble-oss/moduswebcomponents';

// Typed component props
const options: ISelectOption[] = [
  {
    label: 'Option 1',
    value: '1',
  },
  {
    label: 'Option 2',
    value: '2',
  },
];

// Typed event handlers - Always use event.detail.target.value
const handleEvent = (e: CustomEvent) => {
  // Type-safe access to event details
  console.log(e.detail.target.value); // ✅ Correct for all components
}
```

### React Controlled Input Pattern

The controlled input pattern involves maintaining the state of the input's value within the React application or component.

**Key Benefits:**
- Single source of truth for input values
- Real-time validation and transformation of data
- Simplified form state management
- Improved testability and debugging

#### Basic React Controlled Input

```jsx
import React, { useState } from 'react';
import { ModusWcTextInput } from '@trimble-oss/moduswebcomponents-react';

interface Props extends React.ComponentProps<typeof ModusWcTextInput> {}

const MyComponent: React.FC<Props> = (props) => {
  const [value, setValue] = useState('');

  const handleInputChange = (
    e: CustomEvent<HTMLModusWcTextInputElementEventMap['inputChange']>
  ) => {
    const value = e.detail.target.value;
    setValue(value);
  };

  return (
    <ModusWcTextInput
      {...props}
      onInputChange={handleInputChange}
      value={value}
    />
  );
};

export default MyComponent;
```

#### Alternative React Controlled Input

```jsx
// React controlled input example
import { useState } from 'react';

function ControlledTextInput() {
  const [value, setValue] = useState('');

  // Handle input changes
  const handleChange = (event: CustomEvent) => {
    setValue(event.detail.target.value);
    
    // Additional logic can be added here
  };

  return <ModusWcTextInput onInputChange={handleChange} value={value} />;
}
```

### React Component Wrapping Patterns

When using Modus React Components directly, it is recommended to wrap it in corresponding React components within your application. This will abstract away from the library dependency, allowing more flexibility for you and your application in the future.

#### Simple React Wrapper

```tsx
import React from 'react';
import { ModusWcAvatar } from '@trimble-oss/moduswebcomponents-react';

interface Props extends React.ComponentProps<typeof ModusWcAvatar> {}

const Avatar: React.FC<Props> = (props) => {
  return <ModusWcAvatar {...props} />;
};

export default Avatar;
```

#### Complex React Wrapper

```tsx
import React from 'react';
import { ModusWcTextInput } from '@trimble-oss/moduswebcomponents-react';

interface Props
  extends Omit<React.ComponentProps<typeof ModusWcTextInput>, 'inputChange'> {
  onValueChange: (value: string) => void;
}

const TextInput: React.FC<Props> = (props) => {
  const handleInputChange = (
    e: CustomEvent<HTMLModusWcTextInputElementEventMap['inputChange']>
  ) => {
    const value = e.detail.target.value;
    props.onValueChange(value);
  };

  return <ModusWcTextInput {...props} onInputChange={handleInputChange} />;
};

export default TextInput;
```

### Using React Component Library

```tsx
import { ModusWcBadge } from '@trimble-oss/moduswebcomponents-react';

<ModusWcBadge aria-label="Badge" content="Words" />;
```

---

## Angular Implementation

### Angular-Specific Installation

```powershell
npm install @trimble-oss/moduswebcomponents @trimble-oss/moduswebcomponents-angular;
```

### Basic Angular Usage

```typescript
// Angular usage
<ModusWcButton variant="primary">Click me</ModusWcButton>
```

### Angular Controlled Input Pattern

Angular uses its two-way data binding to implement controlled inputs:

```typescript
// Angular controlled input example
import { Component } from '@angular/core';

@Component({
  selector: 'controlled-text-input',
  template: `
    <ModusWcTextInput
      (inputChange)="onInputChange($event)"
      [value]="inputValue"
    >
    </ModusWcTextInput>
  `,
})
export class ControlledTextInput {
  inputValue: string = '';

  onInputChange(event: CustomEvent) {
    this.inputValue = event.detail.target.value; // ✅ Correct event handling
    
    // Validation or transformation logic can be added here
  }
}
```

---

## Event Handling Guide

### Event Handling Pattern for All Modus Components

> **⚠️ UPDATED EVENT HANDLING GUIDE ⚠️**

**IMPORTANT:** All Modus Web Components use the same consistent event handling pattern. Always use `event.detail.target.value` for all components, including select components.

#### Universal Event Handling Pattern

```typescript
// ✅ CORRECT: Use event.detail.target.value for ALL components
const handleEvent = (event: CustomEvent) => {
  setValue(event.detail.target.value); // Works for ALL Modus components
}
```

#### Component-Specific Examples

```typescript
// ModusWcSelect - Use event.detail.target.value
const handleSelectEvent = (e: CustomEvent) => {
  console.log(e.detail.target.value); // ✅ Correct for select components
}

// ModusWcTextInput - Use event.detail.target.value  
const handleInputChange = (event: CustomEvent) => {
  setValue(event.detail.target.value); // ✅ Correct for input components
}

// ModusWcCheckbox - Use event.detail.target.checked
const handleCheckboxChange = (event: CustomEvent) => {
  setChecked(event.detail.target.checked); // ✅ Correct for checkbox
}
```
---

### HTML Usage (Framework Agnostic)

```html
<!-- HTML usage -->
<modus-wc-button variant="primary">Click me</modus-wc-button>
```

**Note:** In HTML, web component tags use kebab-case (modus-wc-button), but in React/Angular frameworks, use camelCase (ModusWcButton).

---

### Event Handling for All Components

All components follow the same event handling pattern:

```typescript
// Universal pattern for all Modus Web Components
const handleComponentEvent = (event: CustomEvent) => {
  // For value-based components (inputs, selects, etc.)
  const value = event.detail.target.value;
  
  // For boolean components (checkboxes, switches, etc.)
  const checked = event.detail.target.checked;
};
```

---
