> ## Documentation Index
> Fetch the complete documentation index at: https://developers.smarterservices.com/llms.txt
> Use this file to discover all available pages before exploring further.

# API Reference

> Complete API documentation for SmarterElements

# API Reference

Complete reference for SmarterElements JavaScript API with component isolation, modal system, and automatic resizing.

## CDN Version Management

### unpkg.com Integration

SmarterElements is available via unpkg.com CDN with flexible versioning options:

#### Version Formats

| Format    | Example                                    | Description                    | Use Case                 |
| --------- | ------------------------------------------ | ------------------------------ | ------------------------ |
| `@latest` | `@smarterservices/smarter-elements@latest` | Always gets the newest version | Development, testing     |
| `@x.y.z`  | `@smarterservices/smarter-elements@1.2.3`  | Specific version lock          | Production (recommended) |
| `@^x.y.z` | `@smarterservices/smarter-elements@^1.2.0` | Compatible minor/patch updates | Flexible production      |
| `@~x.y.z` | `@smarterservices/smarter-elements@~1.2.0` | Patch updates only             | Conservative updates     |

#### Version Selection Strategy

```html theme={null}
<!-- Development: Always get latest features -->
<script src="https://unpkg.com/@smarterservices/smarter-elements@latest/dist/browser.js"></script>

<!-- Production: Lock to tested version -->
<script src="https://unpkg.com/@smarterservices/smarter-elements@1.0.24/dist/browser.js"></script>

<!-- Auto-updates: Patch fixes only -->
<script src="https://unpkg.com/@smarterservices/smarter-elements@~1.0.0/dist/browser.js"></script>
```

## SmarterElements Class

### Constructor

```javascript theme={null}
import { SmarterElements } from '@smarterservices/smarter-elements';
const elements = new SmarterElements(options);
```

#### Options

| Parameter            | Type     | Default        | Description                                                |
| -------------------- | -------- | -------------- | ---------------------------------------------------------- |
| `baseUrl`            | `string` | `'/elements'`  | Base URL for element endpoints                             |
| `environment`        | `string` | `'production'` | Environment: 'development', 'production', 'stage', 'local' |
| `defaultConstraints` | `object` | `{}`           | Default size constraints for all elements                  |

#### Example

```javascript theme={null}
const elements = new SmarterElements({
  baseUrl: '/elements',
  environment: 'development',
  defaultConstraints: {
    maxWidth: 1200,
    maxHeight: 800
  }
});
```

## Element Creation

### `elements.create(type, options)`

Creates a new element instance.

#### Parameters

| Parameter | Type     | Description                              |
| --------- | -------- | ---------------------------------------- |
| `type`    | `string` | Element type (e.g., 'blockkit/renderer') |
| `options` | `object` | Element configuration options            |

#### Options Object

| Property                 | Type       | Description                                                                                                |
| ------------------------ | ---------- | ---------------------------------------------------------------------------------------------------------- |
| `config`                 | `object`   | Configuration data passed to element                                                                       |
| `constraints`            | `object`   | Size constraints (minWidth, maxWidth, minHeight, maxHeight)                                                |
| `autoResize`             | `boolean`  | Enable automatic resizing (default: true)                                                                  |
| `stsToken`               | `string`   | Opaque runtime credential used for API calls; returned on issuance and refresh                             |
| `elementToken`           | `string`   | RS256-signed identity assertion for the element; element issuance only                                     |
| `tokenExpiresIn`         | `number`   | Seconds until the current token expires (drives silent-refresh timing)                                     |
| `tokenAbsoluteExpiresAt` | `number`   | Hard cap (epoch ms) across refreshes; refresh stops at/after this                                          |
| `onTokenRefresh`         | `function` | `async () => StsTokenSet` — called before expiry to fetch the next token set from your backend (see below) |
| `refreshSkew`            | `number`   | Fraction of the TTL after which to refresh (default `0.8`)                                                 |
| `onReady`                | `function` | Callback when element is ready                                                                             |
| `onResize`               | `function` | Callback when element resizes                                                                              |
| `onError`                | `function` | Callback for errors                                                                                        |
| `onEvent`                | `function` | Callback for custom events                                                                                 |

#### `onTokenRefresh`

Long-lived embeds are backed by short-lived STS tokens; the SDK silently refreshes them before expiry. You opt in by supplying `onTokenRefresh` — the SDK owns the scheduling, forwards the rotated token to the element, and fires `tokenRefreshed` / `tokenExpired`, but the callback itself must fetch a fresh token set from **your backend** (the STS refresh endpoint requires your API credential, which never reaches the browser). If omitted, the token simply expires when its TTL runs out.

```javascript theme={null}
const element = elements.create('proctoring/sessionviewer', {
  config: { sessionSid: 'ES123456' },
  elementToken: initial.elementToken,
  stsToken: initial.stsToken,
  tokenExpiresIn: initial.expiresIn,
  tokenAbsoluteExpiresAt: new Date(initial.absoluteExpiresAt).getTime(),

  // Called by the SDK shortly before expiry — return the NEXT token set.
  onTokenRefresh: async () => {
    const next = await fetch('/api/embeds/proctoring-token/refresh', {
      method: 'POST',
    }).then((r) => r.json());
    return {
      stsToken: next.stsToken, // required
      elementToken: next.elementToken, // optional on element issuance
      expiresIn: next.expiresIn, // required
      absoluteExpiresAt: new Date(next.absoluteExpiresAt).getTime(), // optional
    };
  },
});
```

##### `onTokenRefresh` return shape

The callback must resolve with an `StsTokenSet` containing:

| Field               | Type                | Required | Description                                                                                                                                                                   |
| ------------------- | ------------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `stsToken`          | `string`            | Yes      | Opaque runtime credential from your backend's STS refresh response.                                                                                                           |
| `expiresIn`         | `number` (seconds)  | Yes      | TTL of the new token; the SDK uses it to schedule the next refresh.                                                                                                           |
| `elementToken`      | `string`            | No       | Signed identity assertion; only present on element issuance, not refresh, so it is typically omitted here.                                                                    |
| `absoluteExpiresAt` | `number` (epoch ms) | No       | Hard cap across refreshes; when reached, the SDK stops and fires `tokenExpired`. The API returns an ISO string; convert it with `new Date(next.absoluteExpiresAt).getTime()`. |

Resolving with a valid set applies the new tokens and fires `tokenRefreshed`. Throwing or returning a rejected promise fires `tokenExpired` and ends the session. For the full flow, see [Authentication & Tokens](/smarter-elements/authentication#silent-refresh).

#### Example

```javascript theme={null}
const element = elements.create('blockkit/renderer', {
  config: {
    blocksJson: JSON.stringify([
      { type: "heading", level: 1, text: "Hello World" }
    ])
  },
  constraints: {
    minWidth: 300,
    maxWidth: 800,
    minHeight: 200
  },
  onReady: () => console.log('Element ready'),
  onResize: ({ height, width, elementId }) => {
    console.log(`Resized: ${width}x${height}`);
  },
  onError: (error) => console.error('Error:', error)
});
```

## Element Instance Methods

### `element.mount(selector)`

Mounts element to DOM container.

**Parameters:**

* `selector` (string | HTMLElement) - Target container

```javascript theme={null}
// Mount to element with ID
element.mount('#container');

// Mount to first element with class  
element.mount('.element-container');

// Mount to DOM element reference
const container = document.getElementById('container');
element.mount(container);
```

### `element.openModal(options)`

Opens element in modal overlay with automatic resizing and focus management.

**Parameters:**

* `options` (object) - Modal configuration options

**Returns:** `Promise<void>`

#### Modal Options

| Property                 | Type               | Default   | Description                            |
| ------------------------ | ------------------ | --------- | -------------------------------------- |
| `width`                  | `string \| number` | `'90%'`   | Modal width (supports px, %, vw, etc.) |
| `height`                 | `string \| number` | `auto`    | Modal height (auto-sizes by default)   |
| `maxWidth`               | `string \| number` | `'800px'` | Maximum width constraint               |
| `maxHeight`              | `string \| number` | `'90vh'`  | Maximum height constraint              |
| `dismissOnDocumentClick` | `boolean`          | `false`   | Close modal on backdrop click          |
| `escapeClose`            | `boolean`          | `true`    | Close modal on ESC key press           |
| `zIndex`                 | `number`           | `9999`    | Modal z-index value                    |
| `padding`                | `string`           | `'10px'`  | Internal modal padding                 |

#### Modal Examples

```javascript theme={null}
// Basic modal
await element.openModal();

// Responsive modal with constraints
await element.openModal({
  width: '80%',
  maxWidth: '1000px',
  maxHeight: '90vh'
});

// Dismissible modal
await element.openModal({
  width: '600px',
  dismissOnDocumentClick: true,
  escapeClose: true
});

// Fixed size modal
await element.openModal({
  width: '800px',
  height: '600px'
});
```

### `element.closeModal()`

Closes the modal if element is displayed as modal.

```javascript theme={null}
element.closeModal();
```

### `element.updateConfig(newConfig)`

Updates element configuration.

**Parameters:**

* `newConfig` (object) - New configuration data

```javascript theme={null}
element.updateConfig({
  blocksJson: JSON.stringify([
    { type: "heading", level: 2, text: "Updated Content" }
  ])
});
```

### `element.updateConstraints(newConstraints)`

Updates size constraints for mounted elements.

**Parameters:**

* `newConstraints` (object) - New constraint values

```javascript theme={null}
element.updateConstraints({
  maxWidth: 1000,
  maxHeight: 600
});
```

### `element.sendMessage(type, data)`

Sends custom message to element.

**Parameters:**

* `type` (string) - Message type
* `data` (any) - Message data

```javascript theme={null}
element.sendMessage('custom-event', {
  action: 'update',
  value: 'new-data'
});
```

### `element.destroy()`

Destroys element and cleans up resources.

```javascript theme={null}
element.destroy();
```

## React Integration

### `useSmarterElements(options)`

React hook for managing SmarterElements.

**Parameters:**

* `options` (object) - Same as SmarterElements constructor options

**Returns:** SmarterElements instance

```javascript theme={null}
import { useSmarterElements } from '@smarterservices/smarter-elements';

function MyComponent() {
  const elements = useSmarterElements({
    baseUrl: '/elements',
    environment: 'development'
  });
  
  const openModal = async () => {
    const element = elements.create('blockkit/renderer', {
      config: { /* ... */ }
    });
    
    await element.openModal({
      width: '80%',
      maxWidth: '900px'
    });
  };
  
  return <button onClick={openModal}>Open Element</button>;
}
```

### `<SmarterElement>` Component

React component for declarative element usage.

```javascript theme={null}
import { SmarterElement } from '@smarterservices/smarter-elements';

function MyComponent() {
  return (
    <SmarterElement
      type="blockkit/renderer"
      config={{
        blocksJson: JSON.stringify([
          { type: "text", text: "Hello from React!" }
        ])
      }}
      constraints={{
        maxWidth: 800,
        maxHeight: 600
      }}
      onReady={() => console.log('Element ready')}
      onResize={({ height, width }) => console.log('Resized:', { height, width })}
      style={{ border: '1px solid #ccc' }}
    />
  );
}
```

## Size Constraints

Elements support flexible size constraints with CSS units:

```javascript theme={null}
const element = elements.create('blockkit/renderer', {
  constraints: {
    minWidth: 300,        // Pixels
    maxWidth: '80%',      // Percentage  
    minHeight: '20vh',    // Viewport height
    maxHeight: '600px'    // Pixels
  }
});
```

### Supported Units

* **Pixels**: `300` or `'300px'`
* **Percentages**: `'80%'` (of parent container)
* **Viewport units**: `'50vw'`, `'30vh'`
* **Relative units**: `'20rem'`, `'15em'`

## Event System

### Element Events

```javascript theme={null}
const element = elements.create('blockkit/renderer', {
  onReady: () => console.log('Element ready'),
  onResize: ({ height, width, elementId }) => {
    console.log(`Element ${elementId} resized: ${width}x${height}`);
  },
  onError: (error) => console.error('Element error:', error),
  onEvent: (eventType, data) => {
    console.log('Custom event:', eventType, data);
  }
});
```

### Standard Events

| Event            | Data                           | Description                                                     |
| ---------------- | ------------------------------ | --------------------------------------------------------------- |
| `ready`          | `{ elementId }`                | Element loaded and ready                                        |
| `resize`         | `{ width, height, elementId }` | Element dimensions changed                                      |
| `error`          | `{ error, elementId }`         | Element encountered error                                       |
| `destroyed`      | `{ elementId }`                | Element was destroyed                                           |
| `tokenRefreshed` | `{ elementId }`                | STS token silently rotated (see `onTokenRefresh`)               |
| `tokenExpired`   | `{ elementId, error }`         | STS session ended — absolute lifetime reached or refresh failed |

## Utility Functions

### `debounce(func, wait, immediate?)`

Delays function execution until after wait milliseconds have elapsed since the last time it was invoked.

**Parameters:**

* `func` (function) - The function to debounce
* `wait` (number) - The number of milliseconds to delay
* `immediate` (boolean, optional) - If true, trigger on leading edge

**Returns:** Debounced function with `cancel()` and `flush()` methods

```javascript theme={null}
import { debounce } from '@smarterservices/smarter-elements';

// Debounce resize handler
const debouncedResize = debounce(() => {
  element.recalculateSize();
}, 300);

window.addEventListener('resize', debouncedResize);

// Cancel pending execution
debouncedResize.cancel();

// Execute immediately
debouncedResize.flush();
```

### `throttle(func, wait, options?)`

Limits function execution to at most once per wait milliseconds.

**Parameters:**

* `func` (function) - The function to throttle
* `wait` (number) - The number of milliseconds to throttle to
* `options` (object, optional) - `{ leading?: boolean, trailing?: boolean }`

**Returns:** Throttled function with `cancel()` and `flush()` methods

```javascript theme={null}
import { throttle } from '@smarterservices/smarter-elements';

// Throttle scroll handler
const throttledScroll = throttle(() => {
  console.log('Scroll event');
}, 100);

window.addEventListener('scroll', throttledScroll);
```

### CDN Usage

```html theme={null}
<script src="https://unpkg.com/@smarterservices/smarter-elements@latest/dist/browser.js"></script>
<script>
  const { debounce, throttle } = SmarterElements;
  
  const debouncedResize = debounce(() => {
    element.recalculateSize();
  }, 300);
  
  window.addEventListener('resize', debouncedResize);
</script>
```

## TypeScript Support

Full TypeScript definitions included:

```typescript theme={null}
import { 
  SmarterElements, 
  SmarterElementInstance,
  ModalOptions,
  SmarterElementConstraints,
  debounce,
  throttle,
  DebouncedFunction
} from '@smarterservices/smarter-elements';

const elements = new SmarterElements({ baseUrl: '/elements' });

const element: SmarterElementInstance = elements.create('blockkit/renderer', {
  config: {
    blocksJson: string
  },
  constraints: {
    maxWidth: 800,
    maxHeight: 600
  } as SmarterElementConstraints
});

// Debounced function with type safety
const debouncedResize: DebouncedFunction<() => void> = debounce(() => {
  element.recalculateSize();
}, 300);

const modalOptions: ModalOptions = {
  width: '80%',
  maxWidth: '1000px',
  dismissOnDocumentClick: true
};

await element.openModal(modalOptions);
```

***

*For more examples and use cases, see the [Examples](/smarter-elements/examples) section.*
