# AnySurface Bundle Guide

## Building the Bundle

```bash
yarn bundle
```

This produces three files in `build/`:

| File | Size | Description |
|------|------|-------------|
| `anysurface.js` | ~286 KB | Main ESM bundle with source map |
| `anysurface.min.js` | ~136 KB | Minified ESM bundle with source map |
| `anysurface.worker.js` | ~5 KB | Web worker for laser detection |

For development with auto-rebuild:

```bash
yarn bundle:watch
```

## Bundle Outputs

### Main Bundle (`anysurface.js`)

Single ES module file containing all AnySurface classes and functions. Imports `simple-statistics` as an external dependency.

### Minified Bundle (`anysurface.min.js`)

Same as main bundle, minified with Terser. Use for production.

### Worker Bundle (`anysurface.worker.js`)

Self-contained ES module for the brightest-point detection web worker. Has no external dependencies. Must be served as a separate file (not inlined) to avoid CSP issues.

## External Dependencies

`simple-statistics` is **not** bundled. It appears as an `import` statement in the output:

```js
import { ckmeans, max } from 'simple-statistics';
```

You must provide it via one of:

- **Bundler resolution** (Vite, Webpack, etc.) - resolves from `node_modules` automatically
- **Import map** - for direct browser usage (see below)

## Usage with a Bundler (Vite, Webpack, Rollup)

Install AnySurface and its dependency:

```bash
yarn add anysurface
```

Import in your code:

```js
import { Surface, CameraInterface, initWorker } from 'anysurface'

// Initialize the web worker with the correct path
initWorker(new URL('anysurface/build/anysurface.worker.js', import.meta.url).href)
```

Your bundler resolves `simple-statistics` from `node_modules` automatically.

## Usage in the Browser (Direct)

```html
<script type="importmap">
{
    "imports": {
        "simple-statistics": "./node_modules/simple-statistics/dist/simple-statistics.mjs",
        "anysurface": "./node_modules/anysurface/build/anysurface.js"
    }
}
</script>

<script type="module">
    import { Surface, initWorker } from 'anysurface'

    initWorker('./node_modules/anysurface/build/anysurface.worker.js')

    const surface = new Surface()
    // ...
</script>
```

Or reference the bundle file directly without an import map:

```html
<script type="importmap">
{
    "imports": {
        "simple-statistics": "./path/to/simple-statistics.mjs"
    }
}
</script>

<script type="module">
    import { Surface } from './path/to/build/anysurface.js'
</script>
```

The import map for `simple-statistics` is always required when loading directly in the browser, since the bundle contains a bare `import` for it.

## Using Without the Bundle

You can still use the raw ES6 modules directly, as before:

```html
<script type="importmap">
{
    "imports": {
        "@simple-statistics/": "./node_modules/simple-statistics/"
    }
}
</script>

<script type="module">
    import { Surface } from './lib/Surface.js'
</script>
```

## Web Worker Notes

The brightest-point web worker is used for laser detection performance. It runs `findBrightestPointInImageData` off the main thread.

- The worker auto-initializes at import time with a default path of `"lib/Laser/brightestPoint_webWorker.js"` (the unbundled source location)
- For bundled usage, call `initWorker()` with the path to `anysurface.worker.js`
- If worker initialization fails (e.g., path wrong or CSP blocks it), detection falls back to main-thread processing automatically

```js
import { initWorker } from 'anysurface'

// Override the default worker path for bundled usage
initWorker('./build/anysurface.worker.js')
```

## Side Effects

Importing from the bundle triggers these side effects:

1. **Web worker auto-init** - `initWorker()` is called at module evaluation time (can be overridden by calling it again with the correct path)
2. **Custom element registration** - The UI components register these custom elements via `customElements.define()`:
   - `<calibrator-wrapper>`
   - `<camera-selector>`
   - `<laser-calibrator>`
   - `<align-calibrator>`
   - `<grayscan-calibrator>`
   - `<scan-calibrator>`

## Rollup Configuration

The bundle is configured in `rollup.config.js` at the project root:

- **Entry**: `lib/index.js` (barrel file re-exporting the full API)
- **Format**: ES modules
- **External**: `simple-statistics`
- **Plugins**: `@rollup/plugin-alias` (remaps import map paths), `@rollup/plugin-node-resolve`, `@rollup/plugin-terser`
- **Worker**: Built as a separate self-contained entry
