npm package: @pie-players/pie-tool-tts-inline
Description: Inline TTS (Text-to-Speech) tool component for PIE Players Assessment Toolkit.
Latest version: 0.3.29

# @pie-players/pie-tool-tts-inline

Inline TTS (Text-to-Speech) tool component for PIE Players Assessment Toolkit.

## Overview

`pie-tool-tts-inline` is a web component that renders an inline speaker trigger with an expanded floating control panel for reading controls. Unlike floating modal tools, this component renders at its natural position in the DOM (typically in passage/item headers).

## Features

- Speaker trigger that toggles an expanded panel
- Expanded controls: Play/Pause, Stop, Fast-forward, Rewind, configurable Speed options
- Play button switches to Pause while reading
- Panel remains open while reading and closes on Stop
- Arrow-key navigation within the controls toolbar
- Registers with `ToolCoordinator` for lifecycle management
- Integrates with `TTSService` for QTI 3.0 catalog-based TTS
- Size variants: `sm`, `md`, `lg`
- Full accessibility support (ARIA labels, `role="toolbar"`, live status updates)
- Coordinator-controlled visibility via CSS `display` property

## Installation

```bash
bun add @pie-players/pie-tool-tts-inline
```

## Usage

```javascript
import '@pie-players/pie-tool-tts-inline';
import { TTSService, BrowserTTSProvider, ToolCoordinator } from '@pie-players/pie-assessment-toolkit';

// Initialize services
const ttsService = new TTSService();
await ttsService.initialize(new BrowserTTSProvider());
const toolCoordinator = new ToolCoordinator();

// Create element
const ttsButton = document.createElement('pie-tool-tts-inline');
ttsButton.setAttribute('tool-id', 'tts-passage-1');
ttsButton.setAttribute('catalog-id', 'passage-1');
ttsButton.setAttribute('size', 'md');

// Bind services as JavaScript properties (not HTML attributes)
ttsButton.ttsService = ttsService;
ttsButton.coordinator = toolCoordinator;

// Coordinator controls visibility
toolCoordinator.showTool('tts-passage-1');
```

### With Svelte

```svelte
<script>
  import '@pie-players/pie-tool-tts-inline';
  import { ZIndexLayer } from '@pie-players/pie-assessment-toolkit';

  let ttsToolElement;

  $effect(() => {
    if (ttsToolElement && toolCoordinator) {
      ttsToolElement.ttsService = ttsService;
      ttsToolElement.coordinator = toolCoordinator;

      if (ttsService) {
        toolCoordinator.showTool('tts-passage-1');
      }
    }
  });
</script>

<div class="header">
  <h3>Passage Title</h3>
  <pie-tool-tts-inline
    bind:this={ttsToolElement}
    tool-id="tts-passage-1"
    catalog-id="passage-1"
    size="md"
  ></pie-tool-tts-inline>
</div>
```

## Props

### HTML Attributes

- `tool-id` - Unique identifier for tool registration (default: `'tts-inline'`)
- `catalog-id` - QTI 3.0 accessibility catalog ID for SSML lookup (default: `''`)
- `language` - Language code for TTS (default: `'en-US'`)
- `size` - Icon size: `'sm'` (1.5rem), `'md'` (2rem), or `'lg'` (2.5rem) (default: `'md'`)

### JavaScript Properties

- `ttsService` - ITTSService instance (required)
- `coordinator` - IToolCoordinator instance (optional, for visibility management)
- `speedOptions` - Optional number array controlling inline speed button rendering

### `speedOptions` Configuration

`speedOptions` is intended to be set as a JavaScript property (not as a
serialized HTML attribute), either directly on the element or via toolkit
provider settings.

```javascript
const ttsButton = document.createElement("pie-tool-tts-inline");
ttsButton.speedOptions = [2, 1.25, 1.5]; // rendered in this order
```

Semantics:

- Omitted or non-array: defaults to `[0.8, 1.25]`.
- Explicit `[]`: no speed buttons rendered.
- Invalid-only values: fall back to `[0.8, 1.25]`.
- Values are deduplicated while preserving first-seen order.
- `1` is excluded from rendered options.

## Behavior

1. **Tool Registration**: Registers with ToolCoordinator on mount using the provided `tool-id`
2. **Text Extraction**: Finds nearest `.pie-section-player__passage-content` or `.pie-section-player__item-content` container
3. **TTS Trigger**: Calls `ttsService.speak(text, { catalogId, language })`
4. **Catalog Resolution**: TTSService checks for SSML in accessibility catalogs (priority order):
   - **Extracted catalogs** (from embedded SSML) - auto-generated by section player
   - **Item-level catalogs** (manually authored)
   - **Assessment-level catalogs** (manually authored)
   - **Plain text fallback** (browser TTS)
5. **Expanded Controls**:
   - Trigger button opens/closes the panel
   - Play/Pause toggles based on playback state
   - Stop halts playback and closes the panel
   - Fast-forward/Rewind invoke sentence-jump seek on `ITTSService`
   - Speed buttons call `ttsService.updateSettings({ rate })`
   - Selecting another speed switches active state to that option
   - Clicking the currently active speed resets back to `1x`
   - If `speedOptions` is `[]`, speed controls are omitted while rewind/forward/stop still render
6. **Keyboard Interaction**: Arrow keys move between controls; Tab enters/leaves the toolbar
7. **Cleanup**: Unregisters from coordinator on unmount

## SSML Extraction Integration

When used with the section player, this tool automatically benefits from SSML extraction:

**Author embeds SSML in content:**
```html
<div>
  <speak>Solve <prosody rate="slow">x squared plus two</prosody>.</speak>
  <p>Solve x² + 2 = 0</p>
</div>
```

**Section player extracts SSML at runtime:**
- Generates catalog with ID like `auto-prompt-q1-0`
- Adds `data-catalog-id="auto-prompt-q1-0"` to visual content
- Registers catalog with AccessibilityCatalogResolver

**Tool uses extracted catalog:**
- User clicks TTS button in header
- Tool calls `ttsService.speak(text, { catalogId: 'auto-prompt-q1-0' })`
- TTSService finds SSML in extracted catalogs
- Speaks with proper math pronunciation and pacing

**Result:** Authors get high-quality TTS without maintaining separate catalog files.

## Styling

The component uses scoped styles and doesn't require external CSS. Styling uses `--pie-*` token variables:

- **Trigger**: Circular speaker button that indicates panel open state
- **Panel**: Floating card with vertically stacked controls
- **Speed state**: Active speed button receives distinct token-driven styling
- **Disabled**: Reduced opacity, no pointer

## Architecture

This tool follows the PIE Assessment Toolkit tool pattern:

- Always rendered in DOM at natural position
- ToolCoordinator controls visibility via `showTool()`/`hideTool()` (CSS `display` property)
- Registers with `ZIndexLayer.TOOL` for proper layering
- Services passed as JavaScript properties (objects can't be HTML attributes)

## Example

See active demos in `apps/section-demos`.

## License

MIT