# @nitrogenbuilder/client-react

This package provides the core Nitrogen client-side functionality to be used in all react projects.

## Installation

```bash
npm install @nitrogenbuilder/client-react
```

## Dynamic Data Templates

Use `{{ }}` syntax in string props to render dynamic data.

### Path Resolution

Access nested values with dot notation:

```
{{ post.title }}
{{ post.author.name }}
{{ post.meta.og_image }}
```

### Fallbacks with `||`

Chain multiple values — the first non-empty result is used:

```
{{ post.subtitle || post.title }}
{{ post.custom_excerpt || post.excerpt || 'No excerpt available' }}
{{ author.display_name || author.username || 'Anonymous' }}
```

### String Literals

Wrap literal strings in single quotes:

```
{{ 'Hello World' }}
{{ post.title || 'Untitled' }}
```

### Filters

Apply transformations with `:filter` after a path. Filters chain left to right.

| Filter | Args | Description | Example |
|---|---|---|---|
| `uppercase` | — | Converts to UPPERCASE | `{{ post.title:uppercase }}` |
| `lowercase` | — | Converts to lowercase | `{{ post.title:lowercase }}` |
| `capitalize` | — | Capitalizes first character | `{{ post.status:capitalize }}` |
| `trim` | — | Removes leading/trailing whitespace | `{{ post.title:trim }}` |
| `substring` | `(start)` or `(start, end)` | Extracts a portion of the string | `{{ post.title:substring(0,17) }}` |
| `truncate` | `(length)` | Truncates and appends `...` if over length | `{{ post.excerpt:truncate(55) }}` |
| `striphtml` | — | Removes all HTML tags | `{{ post.content:striphtml }}` |

### Chaining Filters

Apply multiple filters in sequence:

```
{{ post.content:striphtml:truncate(100) }}
{{ post.title:trim:uppercase }}
{{ post.body:striphtml:trim:truncate(50) }}
```

### String Concatenation with `+`

Join values and literals together:

```
{{ post.title:substring(0,17)+'...' }}
{{ post.first_name+' '+post.last_name }}
{{ 'By '+post.author.name }}
```

### Combining Everything

Filters, concatenation, and fallbacks work together:

```
{{ post.title:substring(0,17)+'...' || 'Untitled' }}
{{ post.content:striphtml:truncate(100) || post.excerpt:striphtml || 'No content' }}
{{ post.author.name:uppercase || 'ANONYMOUS' }}
```

### Custom Filters

Register custom filters from your project:

```typescript
import { registerFilter } from '@nitrogenbuilder/client-core';

registerFilter('blogdate', (value) => {
  return new Date(value).toLocaleDateString('en-US', {
    month: 'short', day: 'numeric', year: 'numeric',
  });
});

// Usage: {{ post.date:blogdate }}
```

### Dynamic Value Props (`___dynamic`)

For structured dynamic bindings (set via the builder UI), props ending in `___dynamic` resolve a `DynamicValue` object:

```typescript
interface DynamicValue {
  key: string;       // dot-notation path into dynamic data
  before?: string;   // prepended to the resolved value
  fallback?: string | boolean; // used if key resolves to empty
  after?: string;    // appended to the resolved value
}
```

These are processed separately from `{{ }}` templates and do not support filters.
