# Client API

The Elements client is the main interface for interacting with the SDK. It provides methods for injecting components, managing UI elements, and performing actions.

## Initialization

### Elements()

Initialize the full SDK client.

```typescript
function Elements(
  apiKey: string,
  config: ILiquidCommerceElementsConfig
): Promise<ILiquidCommerceElementsClient | null>
```

**Parameters:**

| Parameter | Type                          | Required | Description                 |
|-----------|-------------------------------|----------|-----------------------------|
| `apiKey`  | string                        | Yes      | Your LiquidCommerce API key |
| `config`  | ILiquidCommerceElementsConfig | Yes      | Configuration object        |

**Returns:** Promise that resolves to the client instance, or `null` if initialization fails.

**Example:**

```javascript
import { Elements } from '@liquidcommerce/elements-sdk';

const client = await Elements('YOUR_API_KEY', {
  env: 'production',
  debugMode: 'console',
  customTheme: { /* theme config */ }
});
```

### ElementsCheckout()

Initialize the checkout-only client (tree-shaken build).

```typescript
function ElementsCheckout(
  apiKey: string,
  config: ILiquidCommerceElementsCheckoutClientConfig
): Promise<IElementsCheckoutClient | null>
```

**Parameters:**

| Parameter | Type                                        | Required | Description                 |
|-----------|---------------------------------------------|----------|-----------------------------|
| `apiKey`  | string                                      | Yes      | Your LiquidCommerce API key |
| `config`  | ILiquidCommerceElementsCheckoutClientConfig | Yes      | Checkout configuration      |

**Example:**

```javascript
import { ElementsCheckout } from '@liquidcommerce/elements-sdk/checkout';

const client = await ElementsCheckout('YOUR_API_KEY', {
  env: 'production'
});
```

## Configuration

### ILiquidCommerceElementsConfig

Complete configuration interface for the full SDK.

```typescript
interface ILiquidCommerceElementsConfig {
  // Required
  env: ElementsEnv;  // 'development' | 'staging' | 'production'

  // Optional
  debugMode?: DebugMode;  // 'none' | 'console' | 'panel'
  customTheme?: IClientCustomThemeConfig;
  promoTicker?: IPromoTicker[];
  proxy?: IElementsProxyConfig;
  checkout?: ILiquidCommerceElementsCheckoutConfig;
  development?: ILiquidCommerceElementsDevelopmentConfig;
}
```

#### Environment

```typescript
type ElementsEnv = 'development' | 'staging' | 'production';
```

Determines which API environment to use.

#### Debug Mode

```typescript
type DebugMode = 'none' | 'console' | 'panel';
```

- `'none'`: No debug output (production default)
- `'console'`: Log debug info to browser console
- `'panel'`: Show debug panel on page

#### Custom Theme

```typescript
interface IClientCustomThemeConfig {
  global?: UpdateComponentGlobalConfigs;
  product?: UpdateProductComponent;
  address?: UpdateAddressComponent;
  cart?: UpdateCartComponent;
  checkout?: UpdateCheckoutComponent;
  productList?: UpdateProductListComponent;
}
```

See [Configuration Reference](./configuration.md) for detailed theme options.

#### Promo Ticker

```typescript
interface IPromoTicker {
  promoCode: string;
  text: string[];
  separator: string;
  activeFrom: string;  // ISO 8601 UTC format
  activeUntil: string;  // ISO 8601 UTC format
}
```

**Example:**

```javascript
promoTicker: [{
  promoCode: 'SUMMER20',
  text: ['20% Off Summer Sale', 'Free Shipping on $50+'],
  separator: '•',
  activeFrom: '2026-06-01T00:00:00Z',
  activeUntil: '2026-08-31T23:59:59Z'
}]
```

#### Proxy Configuration

```typescript
interface IElementsProxyConfig {
  baseUrl: string;
  headers?: Record<string, string>;
}
```

**Example:**

```javascript
proxy: {
  baseUrl: 'https://yoursite.com/api/elements-proxy',
  headers: {
    'X-Custom-Header': 'value'
  }
}
```

See [Proxy Setup Guide](../integration/proxy-setup.md) for implementation.

#### Checkout Configuration

```typescript
interface ILiquidCommerceElementsCheckoutConfig {
  pageUrl: string;  // URL pattern with {token} placeholder
}
```

**Example:**

```javascript
checkout: {
  pageUrl: 'https://yoursite.com/checkout?lce_checkout={token}'
}
```

#### Development Configuration

```typescript
interface ILiquidCommerceElementsDevelopmentConfig {
  customApiUrl?: string;
  openShadowDom?: boolean;
}
```

**Example:**

```javascript
development: {
  customApiUrl: 'http://localhost:3000/api',
  openShadowDom: true  // Disable Shadow DOM for debugging
}
```

## Global Access

After initialization, the client is available globally under the `window.LiquidCommerce` namespace:

```javascript
window.LiquidCommerce.elements
```

This allows access from anywhere in your application:

```javascript
// From any script
window.LiquidCommerce.elements.actions.cart.openCart();
```

## Client Ready Event

Listen for client initialization:

```javascript
window.addEventListener('lce:actions.client_ready', ( event ) => {
  const { isReady, version, timestamp } = event.detail.data;

  console.log(`Elements SDK v${version} ready`);

  // Safe to use client
  window.LiquidCommerce.elements.injectProductElement([...]);
});
```

## Client Interface

### ILiquidCommerceElementsClient

The main client interface:

```typescript
interface ILiquidCommerceElementsClient {
  // Injection methods
  injectProductElement(params: IInjectProductElement[]): Promise<IInjectedComponent[]>;

  injectAddressElement(containerId: string, options?: IAddressOptions): Promise<IInjectedComponent | null>;

  injectCartElement(containerId: string): Promise<IInjectedComponent | null>;

  injectCheckoutElement(params: IInjectCheckoutParams): Promise<IInjectedComponent | null>;

  injectProductList(params: IInjectProductListParams): Promise<void>;

  injectProductListSearch(params: IInjectProductListSearchParams): Promise<void>;

  injectProductListFilters(params: IInjectProductListFiltersParams): Promise<void>;

  // UI methods
  ui: ILiquidCommerceElementsUIMethod;

  // Actions
  actions: ILiquidCommerceElementsActions;

  // Component management
  getInjectedComponents(): Map<string, IInjectedComponent>;

  // Cleanup
  destroy(): void;
}
```

## Methods Overview

### Injection Methods

- `injectProductElement()` - Inject product displays
- `injectAddressElement()` - Inject address input
- `injectCartElement()` - Inject cart (rarely needed)
- `injectCheckoutElement()` - Inject checkout
- `injectProductList()` - Inject product catalog
- `injectProductListSearch()` - Inject search box
- `injectProductListFilters()` - Inject filter panel

See [Injection Methods](./injection-methods.md) for details.

### UI Methods

- `ui.cartButton()` - Add cart button
- `ui.floatingCartButton()` - Add floating cart button
- `ui.cartSubtotal()` - Display cart subtotal
- `ui.cartItemsCount()` - Display item count

See [UI Helpers](./ui-helpers.md) for details.

### Actions

- `actions.product.*` - Product actions
- `actions.address.*` - Address actions
- `actions.cart.*` - Cart actions
- `actions.checkout.*` - Checkout actions

See [Actions](./actions/) for details.

### Component Management

```javascript
// Get all injected components
const components = client.getInjectedComponents();

// Get specific component
const productComponent = components.get('product-1');

// Component methods
productComponent.getType();      // 'product'
productComponent.getElement();   // <div id="product-1">...</div>
productComponent.rerender();     // Force rerender
productComponent.destroy();      // Remove from DOM and clean up
```

### destroy()

Remove the client and all injected components, cleaning up event listeners and internal state.

```javascript
client.destroy();
```

## Error Handling

### SDKError

All SDK errors use the custom `SDKError` class:

```typescript
class SDKError extends Error {
  constructor(message: string, reThrow?: boolean);

  name: 'SDKError';
  isSdk: boolean;
  reThrow: boolean;
}
```
### Catching Errors

```javascript
try {
  await client.injectProductElement([
    { containerId: 'product', identifier: 'invalid_id' }
  ]);
} catch (error) {
  if (error.name === 'SDKError') {
    console.error('SDK Error:', error);
  }
}
```

### Error Isolation

The SDK catches and contains its own errors:

```javascript
// Even if SDK throws, your app continues
window.LiquidCommerce.elements.actions.cart.addProduct([/* invalid */]);

// Your code still runs
console.log('App still working');
```

## TypeScript Support

### Importing Types

```typescript
import { Elements } from '@liquidcommerce/elements-sdk';
import type {
  ILiquidCommerceElementsClient,
  ILiquidCommerceElementsConfig,
  IInjectProductElement,
  IInjectedComponent
} from '@liquidcommerce/elements-sdk';

const config: ILiquidCommerceElementsConfig = {
  env: 'production'
};

const client: ILiquidCommerceElementsClient = await Elements('KEY', config);
```

### Type Exports

All public interfaces are exported from the main package:

```typescript
import type {
  // Client types
  ILiquidCommerceElementsClient,
  ILiquidCommerceElementsConfig,

  // Injection types
  IInjectProductElement,
  IInjectCheckoutParams,
  IInjectedComponent,

  // Action types
  IProductActions,
  ICartActions,
  ICheckoutActions,
  IAddressActions,
  IAddProductParams,

  // Configuration types
  IClientCustomThemeConfig,
  IComponentGlobalConfigs,
  IProductComponent,
  ICartComponent,
  ICheckoutComponent,
  IAddressComponent,

  // Enum types
  ElementsEnv,
  DebugMode,
  FulfillmentType,
  ComponentType
} from '@liquidcommerce/elements-sdk';
```

See [TypeScript Types](./typescript-types.md) for complete type reference.

## Best Practices

### Single Client Instance

Create one client instance and reuse it:

```javascript
// Good
const client = await Elements('KEY', { env: 'production' });
await client.injectProductElement([...]);
await client.injectCartElement('cart');

// Bad - creates multiple instances
await Elements('KEY', { env: 'production' });
await Elements('KEY', { env: 'production' });
```

### Use Global Access

After initialization, use `window.LiquidCommerce.elements`:

```javascript
// Initialize once
await Elements('KEY', { env: 'production' });

// Use globally
window.LiquidCommerce.elements.actions.cart.openCart();
window.LiquidCommerce.elements.ui.cartButton('cart-btn');
```

### Check Client Ready

Wait for client ready before using:

```javascript
if (window.LiquidCommerce?.elements) {
  // Client is ready
  window.LiquidCommerce.elements.actions.cart.openCart();
} else {
  // Wait for client ready
  window.addEventListener('lce:actions.client_ready', () => {
    window.LiquidCommerce.elements.actions.cart.openCart();
  });
}
```

### Handle Initialization Failures

```javascript
const client = await Elements('KEY', { env: 'production' });

if (!client) {
  console.error('Failed to initialize Elements SDK');
  // Show fallback UI or error message
  showErrorPage();
  return;
}

// Client initialized successfully
await client.injectProductElement([...]);
```

## See Also

- [Injection Methods](./injection-methods.md) - Component injection API
- [UI Helpers](./ui-helpers.md) - UI helper methods
- [Actions](./actions/) - Action APIs
- [Configuration](./configuration.md) - Configuration options
- [TypeScript Types](./typescript-types.md) - Type definitions
