···222222 requiredToggle: Required
223223 deleteBlock: Delete block
224224 saveBlock: Save block
225225+ unsavedBlockChangesTitle: Save changes before leaving this block?
226226+ unsavedBlockChangesDescription: You have unsaved edits in this block. Save them before switching blocks or opening form settings, or cancel the changes and continue.
227227+ saveBlockChanges: Save
228228+ cancelBlockChanges: Reset
229229+ backFromUnsavedBlockChanges: Back
225230 nothingSelected: Nothing selected
226231 nothingSelectedTitle: Select a block or open form settings.
227232 nothingSelectedDescription: Use the left panel to choose what you want to edit.
+5
locales/ru.yml
···222222 requiredToggle: Обязательный
223223 deleteBlock: Удалить блок
224224 saveBlock: Сохранить блок
225225+ unsavedBlockChangesTitle: Сохранить изменения перед выходом из блока?
226226+ unsavedBlockChangesDescription: В этом блоке есть несохранённые правки. Сохраните их перед переключением на другой блок или настройками формы либо отмените изменения и продолжайте.
227227+ saveBlockChanges: Сохранить
228228+ cancelBlockChanges: Сбросить
229229+ backFromUnsavedBlockChanges: Назад
225230 nothingSelected: Ничего не выбрано
226231 nothingSelectedTitle: Выберите блок или откройте настройки формы.
227232 nothingSelectedDescription: Используйте левую панель, чтобы выбрать, что вы хотите редактировать.
···11+## Context
22+33+The builder keeps form-level data and saved blocks in `components/form-builder.tsx`, but block edits live in local draft state (`blockDraft`, `choiceOptionsDraft`, and `branchRulesDraft`) until the creator presses **Save block**. The current selection model immediately swaps the editor when the creator selects another block or opens form settings, so unsaved edits are replaced by the newly selected data with no warning.
44+55+This change is limited to the creator builder. It does not require API, persistence, or schema changes because the existing block save endpoint already supports the data that must be preserved.
66+77+## Goals / Non-Goals
88+99+**Goals:**
1010+- Detect whether the active block editor has unsaved changes compared with the last saved block state.
1111+- Intercept builder actions that would replace the active block editor.
1212+- Offer clear resolution paths: save changes and continue, discard changes and continue, or cancel and stay on the current block.
1313+- Reuse the existing explicit save flow so saved data still comes from the same block PATCH request.
1414+1515+**Non-Goals:**
1616+- Introduce autosave for block edits.
1717+- Warn on every page navigation or browser tab close.
1818+- Add unsaved-change protection for form settings fields in this change.
1919+- Change block validation, publishing, or storage behavior.
2020+2121+## Decisions
2222+2323+### 1. Compute dirty state from saved block data versus serialized editor draft
2424+The builder will derive `hasUnsavedBlockChanges` from the currently selected saved block in `form.blocks` and the active editor draft state.
2525+2626+Rationale:
2727+- `selectedBlock` already reflects the last saved server state.
2828+- Comparing serialized values avoids false positives from ephemeral draft IDs used for choice options and branch rules.
2929+- Dirty detection stays local to the builder and does not require extra server reads.
3030+3131+Alternatives considered:
3232+- Maintain a manual dirty flag on every input change. Rejected because it is easier to desynchronize when selection resets or saved data is reloaded.
3333+- Deep-compare raw draft objects including generated IDs. Rejected because choice and branch draft IDs are intentionally unstable.
3434+3535+### 2. Gate editor-exit actions through a single pending-navigation workflow
3636+Actions that replace the active block editor will route through one helper that either executes immediately or opens an unsaved-changes dialog when `hasUnsavedBlockChanges` is true. The pending action will be stored as a callback or discriminated state object and executed only after the creator chooses save or discard.
3737+3838+Covered actions:
3939+- selecting a different block
4040+- switching from a block to form settings
4141+- creating a new block when the UI would switch focus to that new block
4242+4343+Rationale:
4444+- Centralizing the guard keeps selection behavior consistent.
4545+- The same workflow can support more editor-exit actions later without duplicating prompt logic.
4646+4747+Alternatives considered:
4848+- Add separate confirmation logic inside each click handler. Rejected because it spreads stateful behavior across the component and makes later maintenance harder.
4949+5050+### 3. Save-before-leave reuses the existing `saveBlock` request path
5151+The dialog's primary action will call the same save logic used by the existing **Save block** button, then continue the pending navigation only after the save succeeds. If the save fails, the builder will keep the current editor open and surface the existing error toast.
5252+5353+Rationale:
5454+- Preserves one server write path for block updates.
5555+- Avoids divergent payload shapes or duplicated mutation logic.
5656+- Matches creator expectations: “Save” in the dialog behaves exactly like “Save block”.
5757+5858+Alternatives considered:
5959+- Perform a lighter-weight temporary save or local stash before navigating. Rejected because it adds a second persistence model and changes the product behavior beyond the request.
6060+6161+### 4. Use a three-action modal built on the existing dialog primitive
6262+The existing `ConfirmDialog` already supports custom `actions`, so the builder can present **Cancel**, **Discard changes**, and **Save changes** without introducing a second modal framework. New i18n strings will be added for the dialog title, body copy, and action labels.
6363+6464+Rationale:
6565+- Keeps the UI consistent with the existing deletion confirmation pattern.
6666+- Minimizes implementation surface area.
6767+- Supports the required third action without changing the component contract significantly.
6868+6969+Alternatives considered:
7070+- Replace the dialog with inline warnings inside the editor panel. Rejected because the creator may already have initiated navigation, and the system needs an immediate blocking choice.
7171+7272+## Risks / Trade-offs
7373+7474+- Dirty detection misses a field or compares the wrong normalized value → Add a dedicated helper for block-draft serialization and cover it with unit tests.
7575+- Save-then-navigate can feel slow on poor connections → Reuse the existing pending state and disable repeated dialog actions while save is in flight.
7676+- Pending navigation could run against stale selection state after async save → Store navigation intent explicitly and clear it only after execution or cancellation.
7777+- Scope remains limited to block editors, so unsaved form settings can still be lost → Document that form settings protection is out of scope for this change.
7878+7979+## Migration Plan
8080+8181+- No data migration is required.
8282+- Ship as a client-side builder update.
8383+- Rollback is a normal code rollback because no persisted shape changes are involved.
8484+8585+## Open Questions
8686+8787+- None for proposal scope. The default behavior will be to guard only actions that leave the active block editor inside the builder experience.
···11+## Why
22+33+The form builder keeps block edits in a local draft until the creator explicitly saves them. Today, selecting another block or switching away from the editor silently drops those unsaved changes, which makes the builder feel unreliable and increases the risk of accidental data loss.
44+55+## What Changes
66+77+- Detect unsaved edits in the active block editor by comparing the local block draft against the last saved block state.
88+- Prompt the creator before actions that would leave the active block editor with unsaved changes.
99+- Let the creator save changes, discard changes, or cancel the navigation so they can stay on the current block.
1010+- Preserve the existing explicit save flow for block edits instead of introducing background autosave.
1111+1212+## Capabilities
1313+1414+### New Capabilities
1515+- None.
1616+1717+### Modified Capabilities
1818+- `conversational-form-builder`: require the builder to warn before switching away from a block that has unsaved edits and provide save/discard/cancel resolution paths.
1919+2020+## Impact
2121+2222+- Affected UI: `components/form-builder.tsx`, `components/form-builder-panels.tsx`, and shared confirmation dialog patterns.
2323+- Affected behavior: block selection changes, switching from a block to form settings, and other builder actions that replace the active block editor.
2424+- No API or database schema changes are expected.
···11+## MODIFIED Requirements
22+33+### Requirement: Builder exposes block editing through a master-detail layout
44+The system SHALL present a builder interface with an ordered block list for navigation and reordering and a separate editor panel for the selected block's settings. For long forms, the builder SHALL keep the navigation list usable without making the entire page grow unbounded from the block column alone. When an authenticated creator attempts to replace the active block editor with another block editor or the form settings panel while the current block has unsaved edits, the system SHALL prompt the creator to save changes, discard changes, or cancel the navigation.
55+66+#### Scenario: Creator selects a block with no unsaved edits
77+- **WHEN** an authenticated creator selects a block in the block list and the current block editor has no unsaved edits
88+- **THEN** the system displays that block's editable settings in the editor panel
99+1010+#### Scenario: Creator saves changes while switching blocks
1111+- **WHEN** an authenticated creator selects a different block while the current block editor has unsaved edits and chooses to save changes
1212+- **THEN** the system saves the current block changes and opens the newly selected block in the editor panel
1313+1414+#### Scenario: Creator discards changes while switching blocks
1515+- **WHEN** an authenticated creator selects a different block while the current block editor has unsaved edits and chooses to discard changes
1616+- **THEN** the system leaves the saved block unchanged and opens the newly selected block in the editor panel
1717+1818+#### Scenario: Creator cancels block switching
1919+- **WHEN** an authenticated creator selects a different block while the current block editor has unsaved edits and chooses to cancel
2020+- **THEN** the system keeps the current block editor open with the unsaved edits intact
2121+2222+#### Scenario: Creator opens form settings with unsaved block edits
2323+- **WHEN** an authenticated creator switches from a block editor to the form settings panel while the current block has unsaved edits
2424+- **THEN** the system requires the creator to save changes, discard changes, or cancel before replacing the block editor panel
2525+2626+#### Scenario: Creator works on a long form
2727+- **WHEN** an authenticated creator opens a form with many blocks
2828+- **THEN** the builder keeps the block list navigable without requiring the full page height to expand indefinitely with the left column
···11+## 1. Dirty-state detection
22+33+- [x] 1.1 Add a builder helper that normalizes the active block draft, choice option drafts, and branch rule drafts into the same shape as the saved block.
44+- [x] 1.2 Derive `hasUnsavedBlockChanges` in `components/form-builder.tsx` by comparing the normalized active draft against the currently selected saved block.
55+- [x] 1.3 Add unit coverage for the normalization and dirty-state comparison logic, including choice and branching edits.
66+77+## 2. Guard editor-exit actions
88+99+- [x] 2.1 Add pending-navigation state in `components/form-builder.tsx` so block-selection changes, form-settings selection, and new-block creation can be intercepted consistently.
1010+- [x] 2.2 Add an unsaved-changes dialog with cancel, discard, and save actions using the existing dialog primitive and builder-specific copy.
1111+- [x] 2.3 Update the save flow so the dialog's save action reuses the existing block save request and continues navigation only after a successful save.
1212+- [x] 2.4 Update discard and cancel handling so discard proceeds with navigation without saving and cancel keeps the current block draft intact.
1313+1414+## 3. UX polish and verification
1515+1616+- [x] 3.1 Add any required translation strings for the unsaved-changes dialog and button labels.
1717+- [x] 3.2 Add component or interaction coverage for switching blocks and opening form settings with and without unsaved edits.
1818+- [x] 3.3 Manually verify the builder flows for save, discard, cancel, and save-failure behavior before closing the change.
···3131- **THEN** the system removes that block from the current form structure
32323333### Requirement: Builder exposes block editing through a master-detail layout
3434-The system SHALL present a builder interface with an ordered block list for navigation and reordering and a separate editor panel for the selected block's settings. For long forms, the builder SHALL keep the navigation list usable without making the entire page grow unbounded from the block column alone.
3434+The system SHALL present a builder interface with an ordered block list for navigation and reordering and a separate editor panel for the selected block's settings. For long forms, the builder SHALL keep the navigation list usable without making the entire page grow unbounded from the block column alone. When an authenticated creator attempts to replace the active block editor with another block editor or the form settings panel while the current block has unsaved edits, the system SHALL prompt the creator to save changes, discard changes, or cancel the navigation.
35353636-#### Scenario: Creator selects a block
3737-- **WHEN** an authenticated creator selects a block in the block list
3636+#### Scenario: Creator selects a block with no unsaved edits
3737+- **WHEN** an authenticated creator selects a block in the block list and the current block editor has no unsaved edits
3838- **THEN** the system displays that block's editable settings in the editor panel
3939+4040+#### Scenario: Creator saves changes while switching blocks
4141+- **WHEN** an authenticated creator selects a different block while the current block editor has unsaved edits and chooses to save changes
4242+- **THEN** the system saves the current block changes and opens the newly selected block in the editor panel
4343+4444+#### Scenario: Creator discards changes while switching blocks
4545+- **WHEN** an authenticated creator selects a different block while the current block editor has unsaved edits and chooses to discard changes
4646+- **THEN** the system leaves the saved block unchanged and opens the newly selected block in the editor panel
4747+4848+#### Scenario: Creator cancels block switching
4949+- **WHEN** an authenticated creator selects a different block while the current block editor has unsaved edits and chooses to cancel
5050+- **THEN** the system keeps the current block editor open with the unsaved edits intact
5151+5252+#### Scenario: Creator opens form settings with unsaved block edits
5353+- **WHEN** an authenticated creator switches from a block editor to the form settings panel while the current block has unsaved edits
5454+- **THEN** the system requires the creator to save changes, discard changes, or cancel before replacing the block editor panel
39554056#### Scenario: Creator works on a long form
4157- **WHEN** an authenticated creator opens a form with many blocks