# EditingConfig

> _Since v0.4.0_

Configuration options for EditingPlugin.

## Properties

| Property | Type | Description |
| -------- | ---- | ----------- |
| `mode?` | <code>row &#124; grid</code> | Editing mode that determines how many rows are editable at once. |
| `dirtyTracking?` | <code>boolean</code> | Enable per-row dirty tracking against deep-cloned baselines. |
| `editOn?` | <code>false &#124; manual &#124; click &#124; dblclick</code> | Controls when editing is triggered (only applies to `mode: 'row'`). - 'click': Edit on single click (default) - 'dblclick': Edit on double click - 'manual': Only via programmatic API (beginEdit) - false: Disable editing entirely |
| `onBeforeEditClose?` | <code>(event: MouseEvent &#124; KeyboardEvent) =&gt; boolean</code> | Callback invoked before a row edit session closes. |
| `focusTrap?` | <code>boolean</code> | When `true`, prevents focus from leaving the grid (or its registered external focus containers) while a row is in edit mode. |

### Property Details

#### mode

Editing mode that determines how many rows are editable at once.

- `'row'` (default): Click/double-click to edit one row at a time.
  Editors appear when the row enters edit mode and disappear on commit/cancel.

- `'grid'`: The entire grid is always in edit mode. All editable cells
  display their editors immediately. Commit/cancel affects individual cells
  but does not exit edit mode. Useful for spreadsheet-like data entry.

**Default:** `'row'`

---

#### dirtyTracking

Enable per-row dirty tracking against deep-cloned baselines.

When `true`, the plugin captures a `structuredClone` snapshot of each
row the first time it appears in `processRows` (first-write-wins).
Subsequent edits are compared against this baseline to determine dirty
state.

**Requires** `getRowId` to be resolvable (via config or `row.id` /
`row._id` fallback). The plugin throws a clear error at activation time
if row identity cannot be determined.

**Default:** `false`

```typescript
import { queryGrid } from '@toolbox-web/grid';

const grid = queryGrid('tbw-grid');
grid.gridConfig = {
  getRowId: (r) => r.id,
  columns: [...],
  plugins: [new EditingPlugin({ editOn: 'dblclick', dirtyTracking: true })],
};

// After editing:
const editing = grid.getPluginByName('editing')!;
editing.isDirty('row-1');          // true if row differs from baseline
editing.getDirtyRows();            // [{ id, original, current }]
editing.markAsPristine('row-1');   // re-snapshot after save
```

---

#### onBeforeEditClose

Callback invoked before a row edit session closes.

Return `false` to prevent the row from exiting edit mode.
This is useful when editors have open overlays (datepickers, dropdowns)
that render outside the grid DOM.

The callback receives the triggering event:
- `MouseEvent` - when clicking outside the editing row
- `KeyboardEvent` - when pressing Enter or Escape

Use this to check if the event target is inside your component library's
overlay container, allowing keyboard navigation and selection within
open dropdowns before the edit commits.

```typescript
// Angular Material / CDK - prevent close when overlay is open
new EditingPlugin({
  editOn: 'dblclick',
  onBeforeEditClose: (event) => {
    const target = event.target as Element;
    // Return false to PREVENT closing (interaction is inside overlay)
    // Return true to ALLOW closing (no overlay is open)
    return !target?.closest('.cdk-overlay-container');
  }
})

// MUI (React)
new EditingPlugin({
  onBeforeEditClose: (event) => {
    const target = event.target as Element;
    return !target?.closest('.MuiPopover-root, .MuiPopper-root');
  }
})
```

---

#### focusTrap

When `true`, prevents focus from leaving the grid (or its registered
external focus containers) while a row is in edit mode.

If the user tabs or clicks outside the grid during an active edit,
focus is returned to the editing cell. This prevents accidental
data loss from focus leaving the grid unexpectedly.

Elements registered via `grid.registerExternalFocusContainer()` are
considered "inside" the grid for focus trap purposes, so overlays
(datepickers, dropdowns) continue to work normally.

**Default:** `false`

Independently of this option, the grid ships an always-on
focus trap that restores the last user-focused element whenever focus
is bounced to `<body>` (e.g. an overlay child of `<body>` closes). That
built-in behavior covers most accidental focus loss without locking the
user inside the editor. Set `focusTrap: true` only when you also want
to actively reclaim focus into the editing cell on intentional outside
navigation (Tab/click) during a row edit.

```typescript
new EditingPlugin({
  focusTrap: true,
  editOn: 'dblclick',
})
```

---
