# @targetprocess/layout-schema

Shared library for Targetprocess layout schema operations — traversal, incremental updates, component ID generation, and solution management for Detailed View layouts.

## Overview

This package provides the core algorithms used by `layout-management` to manipulate layout schemas:

- **Incremental updates** — add/update individual components in a layout without replacing the entire schema
- **Component traversal** — walk the layout tree using type-specific traversal strategies
- **Component ID generation** — assign stable IDs to layout components
- **Solution removal** — remove components installed by a specific solution
- **Placeholder filling** — populate layout placeholders with default content

## Key Modules

| Module | Purpose |
|--------|---------|
| `traverseAndApplyIncrementalUpdates` | Apply incremental updates to a layout schema, with optional `canonicalId`-based global matching |
| `componentTraversalRegistry` | Registry of type-specific traversal strategies (`stack`, `tabs`, `collapsible`, etc.) |
| `traverseSchemaTree` | Generic tree traversal using the component registry |
| `traverseAndGenerateComponentId` | Assign unique `componentId` to each node |
| `traverseAndRemoveSolutions` | Remove components by their `from` source |
| `types` | Shared type definitions (`ISchema`, `IncrementalUpdate`, `ISchemaComponentConfig`, etc.) |

## Incremental Updates

### Standard Mode

Components are matched in the layout by comparing their full `jsonConfig` structure using `isMatch`. If not found, the component is inserted as new.

### Canonical Mode (`useCanonicalElements=true`)

When enabled, adds a global search fallback for components with `canonicalId`:

1. Try local match via `findChild` (same as standard)
2. If not found and component has `canonicalId` → search the entire layout tree by `canonicalId`
3. If found globally → update in-place via `Object.assign`
4. If not found anywhere → insert as new

This prevents duplicates when components have been moved or their properties changed since installation.

### Component Children Storage

Different component types store children in different properties:

| Component Type | Children Property | Traversal Strategy |
|---------------|-------------------|-------------------|
| `stack`, `grid`, `wrap` | `components[]` | `componentsArrayTraversal` |
| `sections` (tabs) | `sections[]` (each with `.component` and `.titleExtra`) | `tabsTraversal` |
| `collapsible` | `component` + `titleExtra` | `collapsibleTraversal` |
| `tab`, `loadingCover` | `component` | `singleComponentTraversal` |

The `IncrementalUpdate` tree always uses `children[]` regardless of the underlying component type.

## Building

```bash
npm run build     # clean + rollup bundle → dist/
npm test          # run jest tests
npm run lint      # tslint + prettier check
npm run lint:fix  # auto-fix lint issues
```

Output files in `dist/`:
- `layout-schema.js` — CommonJS bundle (main)
- `layout-schema.esm.js` — ES module bundle
- `layout-schema.browser.js` — browser bundle
- `index.d.ts` — TypeScript declarations

## Local Development

### Option 1: Link via path (recommended)

In layout-schema:
```bash
npm run build
```

In the target project (e.g. `layout-management`):
```bash
npm i --link <path-to-layout-schema>
```

### Option 2: Global link

In layout-schema:
```bash
npm run build
npm link
```

In the target project:
```bash
npm link @targetprocess/layout-schema
```

### Note on TypeScript

The project uses TypeScript 3.9. Newer `@types/node` versions may cause compilation errors. Use `npx tsc --skipLibCheck` or build via `npm run build` (rollup) which handles this.
