@toolbox-web/grid 1.22.0 → 1.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/README.md +20 -10
  2. package/all.js +2 -2
  3. package/all.js.map +1 -1
  4. package/index.js +1 -1
  5. package/index.js.map +1 -1
  6. package/lib/core/grid.d.ts +88 -1
  7. package/lib/core/grid.d.ts.map +1 -1
  8. package/lib/core/types.d.ts +61 -0
  9. package/lib/core/types.d.ts.map +1 -1
  10. package/lib/plugins/clipboard/index.js.map +1 -1
  11. package/lib/plugins/column-virtualization/index.js.map +1 -1
  12. package/lib/plugins/context-menu/index.js.map +1 -1
  13. package/lib/plugins/editing/EditingPlugin.d.ts +132 -1
  14. package/lib/plugins/editing/EditingPlugin.d.ts.map +1 -1
  15. package/lib/plugins/editing/editors.d.ts.map +1 -1
  16. package/lib/plugins/editing/index.d.ts +1 -0
  17. package/lib/plugins/editing/index.d.ts.map +1 -1
  18. package/lib/plugins/editing/index.js +1 -1
  19. package/lib/plugins/editing/index.js.map +1 -1
  20. package/lib/plugins/editing/internal/dirty-tracking.d.ts +90 -0
  21. package/lib/plugins/editing/internal/dirty-tracking.d.ts.map +1 -0
  22. package/lib/plugins/editing/types.d.ts +82 -0
  23. package/lib/plugins/editing/types.d.ts.map +1 -1
  24. package/lib/plugins/export/index.js.map +1 -1
  25. package/lib/plugins/filtering/FilteringPlugin.d.ts +17 -4
  26. package/lib/plugins/filtering/FilteringPlugin.d.ts.map +1 -1
  27. package/lib/plugins/filtering/index.js +1 -1
  28. package/lib/plugins/filtering/index.js.map +1 -1
  29. package/lib/plugins/grouping-columns/index.js.map +1 -1
  30. package/lib/plugins/grouping-rows/index.js.map +1 -1
  31. package/lib/plugins/master-detail/index.js.map +1 -1
  32. package/lib/plugins/multi-sort/index.js.map +1 -1
  33. package/lib/plugins/pinned-columns/index.js.map +1 -1
  34. package/lib/plugins/pinned-rows/index.js.map +1 -1
  35. package/lib/plugins/pivot/index.js.map +1 -1
  36. package/lib/plugins/print/index.js.map +1 -1
  37. package/lib/plugins/reorder/index.js.map +1 -1
  38. package/lib/plugins/responsive/index.js.map +1 -1
  39. package/lib/plugins/row-reorder/index.js.map +1 -1
  40. package/lib/plugins/selection/index.js.map +1 -1
  41. package/lib/plugins/server-side/index.js.map +1 -1
  42. package/lib/plugins/tree/index.js.map +1 -1
  43. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts +52 -7
  44. package/lib/plugins/undo-redo/UndoRedoPlugin.d.ts.map +1 -1
  45. package/lib/plugins/undo-redo/history.d.ts +11 -4
  46. package/lib/plugins/undo-redo/history.d.ts.map +1 -1
  47. package/lib/plugins/undo-redo/index.d.ts +1 -1
  48. package/lib/plugins/undo-redo/index.d.ts.map +1 -1
  49. package/lib/plugins/undo-redo/index.js +1 -1
  50. package/lib/plugins/undo-redo/index.js.map +1 -1
  51. package/lib/plugins/undo-redo/types.d.ts +20 -3
  52. package/lib/plugins/undo-redo/types.d.ts.map +1 -1
  53. package/lib/plugins/visibility/index.js.map +1 -1
  54. package/package.json +1 -1
  55. package/public.d.ts +1 -1
  56. package/public.d.ts.map +1 -1
  57. package/umd/grid.all.umd.js +1 -1
  58. package/umd/grid.all.umd.js.map +1 -1
  59. package/umd/grid.umd.js +1 -1
  60. package/umd/grid.umd.js.map +1 -1
  61. package/umd/plugins/editing.umd.js +1 -1
  62. package/umd/plugins/editing.umd.js.map +1 -1
  63. package/umd/plugins/filtering.umd.js +1 -1
  64. package/umd/plugins/filtering.umd.js.map +1 -1
  65. package/umd/plugins/undo-redo.umd.js +1 -1
  66. package/umd/plugins/undo-redo.umd.js.map +1 -1
@@ -1 +1 @@
1
- {"version":3,"file":"undo-redo.umd.js","sources":["../../../../../libs/grid/src/lib/plugins/undo-redo/history.ts","../../../../../libs/grid/src/lib/plugins/undo-redo/UndoRedoPlugin.ts"],"sourcesContent":["/**\n * Undo/Redo History Management\n *\n * Pure functions for managing the undo/redo stacks.\n * These functions are stateless and return new state objects.\n */\n\nimport type { EditAction, UndoRedoState } from './types';\n\n/**\n * Push a new action onto the undo stack.\n * Clears the redo stack since new actions invalidate redo history.\n *\n * @param state - Current undo/redo state\n * @param action - The action to add\n * @param maxSize - Maximum history size\n * @returns New state with the action added\n */\nexport function pushAction(state: UndoRedoState, action: EditAction, maxSize: number): UndoRedoState {\n const undoStack = [...state.undoStack, action];\n\n // Trim oldest actions if over max size\n while (undoStack.length > maxSize) {\n undoStack.shift();\n }\n\n return {\n undoStack,\n redoStack: [], // Clear redo on new action\n };\n}\n\n/**\n * Undo the most recent action.\n * Moves the action from undo stack to redo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was undone (or null if nothing to undo)\n */\nexport function undo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: EditAction | null;\n} {\n if (state.undoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const undoStack = [...state.undoStack];\n const action = undoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack,\n redoStack: [...state.redoStack, action],\n },\n action,\n };\n}\n\n/**\n * Redo the most recently undone action.\n * Moves the action from redo stack back to undo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was redone (or null if nothing to redo)\n */\nexport function redo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: EditAction | null;\n} {\n if (state.redoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const redoStack = [...state.redoStack];\n const action = redoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack: [...state.undoStack, action],\n redoStack,\n },\n action,\n };\n}\n\n/**\n * Check if there are any actions that can be undone.\n *\n * @param state - Current undo/redo state\n * @returns True if undo is available\n */\nexport function canUndo(state: UndoRedoState): boolean {\n return state.undoStack.length > 0;\n}\n\n/**\n * Check if there are any actions that can be redone.\n *\n * @param state - Current undo/redo state\n * @returns True if redo is available\n */\nexport function canRedo(state: UndoRedoState): boolean {\n return state.redoStack.length > 0;\n}\n\n/**\n * Clear all history, returning an empty state.\n *\n * @returns Fresh empty state\n */\nexport function clearHistory(): UndoRedoState {\n return { undoStack: [], redoStack: [] };\n}\n\n/**\n * Create a new edit action with the current timestamp.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n * @returns A new EditAction object\n */\nexport function createEditAction(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): EditAction {\n return {\n type: 'cell-edit',\n rowIndex,\n field,\n oldValue,\n newValue,\n timestamp: Date.now(),\n };\n}\n","/**\n * Undo/Redo Plugin (Class-based)\n *\n * Provides undo/redo functionality for cell edits in tbw-grid.\n * Supports Ctrl+Z/Cmd+Z for undo and Ctrl+Y/Cmd+Y (or Ctrl+Shift+Z) for redo.\n */\n\nimport { BaseGridPlugin, type GridElement, type PluginDependency } from '../../core/plugin/base-plugin';\nimport { canRedo, canUndo, clearHistory, createEditAction, pushAction, redo, undo } from './history';\nimport type { EditAction, UndoRedoConfig, UndoRedoDetail } from './types';\n\n/**\n * Undo/Redo Plugin for tbw-grid\n *\n * Tracks all cell edits and lets users revert or replay changes with familiar keyboard\n * shortcuts (Ctrl+Z / Ctrl+Y). Maintains an in-memory history stack with configurable\n * depth—perfect for data entry workflows where mistakes happen.\n *\n * > **Required Dependency:** This plugin requires EditingPlugin to be loaded first.\n * > UndoRedo tracks the edit history that EditingPlugin creates.\n *\n * ## Installation\n *\n * ```ts\n * import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';\n * import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';\n * ```\n *\n * ## Configuration Options\n *\n * | Option | Type | Default | Description |\n * |--------|------|---------|-------------|\n * | `maxHistorySize` | `number` | `100` | Maximum actions in history stack |\n *\n * ## Keyboard Shortcuts\n *\n * | Shortcut | Action |\n * |----------|--------|\n * | `Ctrl+Z` / `Cmd+Z` | Undo last edit |\n * | `Ctrl+Y` / `Cmd+Shift+Z` | Redo last undone edit |\n *\n * ## Programmatic API\n *\n * | Method | Signature | Description |\n * |--------|-----------|-------------|\n * | `undo` | `() => void` | Undo the last edit |\n * | `redo` | `() => void` | Redo the last undone edit |\n * | `canUndo` | `() => boolean` | Check if undo is available |\n * | `canRedo` | `() => boolean` | Check if redo is available |\n * | `clearHistory` | `() => void` | Clear the entire history stack |\n *\n * @example Basic Usage with EditingPlugin\n * ```ts\n * import '@toolbox-web/grid';\n * import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';\n * import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';\n *\n * const grid = document.querySelector('tbw-grid');\n * grid.gridConfig = {\n * columns: [\n * { field: 'name', header: 'Name', editable: true },\n * { field: 'price', header: 'Price', type: 'number', editable: true },\n * ],\n * plugins: [\n * new EditingPlugin({ editOn: 'dblclick' }), // Required - must be first\n * new UndoRedoPlugin({ maxHistorySize: 50 }),\n * ],\n * };\n * ```\n *\n * @see {@link UndoRedoConfig} for configuration options\n * @see {@link EditingPlugin} for the required dependency\n *\n * @internal Extends BaseGridPlugin\n */\nexport class UndoRedoPlugin extends BaseGridPlugin<UndoRedoConfig> {\n /**\n * Plugin dependencies - UndoRedoPlugin requires EditingPlugin to track edits.\n *\n * The EditingPlugin must be loaded BEFORE this plugin in the plugins array.\n * @internal\n */\n static override readonly dependencies: PluginDependency[] = [\n { name: 'editing', required: true, reason: 'UndoRedoPlugin tracks cell edit history' },\n ];\n\n /** @internal */\n readonly name = 'undoRedo';\n\n /** @internal */\n protected override get defaultConfig(): Partial<UndoRedoConfig> {\n return {\n maxHistorySize: 100,\n };\n }\n\n // State as class properties\n private undoStack: EditAction[] = [];\n private redoStack: EditAction[] = [];\n\n /**\n * Subscribe to cell-edit-committed events from EditingPlugin.\n * @internal\n */\n override attach(grid: GridElement): void {\n super.attach(grid);\n // Auto-record edits via Event Bus\n this.on(\n 'cell-edit-committed',\n (detail: { rowIndex: number; field: string; oldValue: unknown; newValue: unknown }) => {\n this.recordEdit(detail.rowIndex, detail.field, detail.oldValue, detail.newValue);\n },\n );\n }\n\n /**\n * Clean up state when plugin is detached.\n * @internal\n */\n override detach(): void {\n this.undoStack = [];\n this.redoStack = [];\n }\n\n /**\n * Handle keyboard shortcuts for undo/redo.\n * - Ctrl+Z / Cmd+Z: Undo\n * - Ctrl+Y / Cmd+Y / Ctrl+Shift+Z / Cmd+Shift+Z: Redo\n * @internal\n */\n override onKeyDown(event: KeyboardEvent): boolean {\n const isUndo = (event.ctrlKey || event.metaKey) && event.key === 'z' && !event.shiftKey;\n const isRedo = (event.ctrlKey || event.metaKey) && (event.key === 'y' || (event.key === 'z' && event.shiftKey));\n\n if (isUndo) {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n // Apply undo - restore old value\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.oldValue;\n }\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('undo', {\n action: result.action,\n type: 'undo',\n });\n\n this.requestRender();\n }\n return true;\n }\n\n if (isRedo) {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n // Apply redo - restore new value\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.newValue;\n }\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('redo', {\n action: result.action,\n type: 'redo',\n });\n\n this.requestRender();\n }\n return true;\n }\n\n return false;\n }\n\n // #region Public API Methods\n\n /**\n * Record a cell edit for undo/redo tracking.\n * Call this when a cell value changes.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n */\n recordEdit(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): void {\n const action = createEditAction(rowIndex, field, oldValue, newValue);\n const newState = pushAction(\n { undoStack: this.undoStack, redoStack: this.redoStack },\n action,\n this.config.maxHistorySize ?? 100,\n );\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Programmatically undo the last action.\n *\n * @returns The undone action, or null if nothing to undo\n */\n undo(): EditAction | null {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.oldValue;\n }\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.requestRender();\n }\n return result.action;\n }\n\n /**\n * Programmatically redo the last undone action.\n *\n * @returns The redone action, or null if nothing to redo\n */\n redo(): EditAction | null {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n const rows = this.rows as Record<string, unknown>[];\n if (rows[result.action.rowIndex]) {\n rows[result.action.rowIndex][result.action.field] = result.action.newValue;\n }\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.requestRender();\n }\n return result.action;\n }\n\n /**\n * Check if there are any actions that can be undone.\n */\n canUndo(): boolean {\n return canUndo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Check if there are any actions that can be redone.\n */\n canRedo(): boolean {\n return canRedo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Clear all undo/redo history.\n */\n clearHistory(): void {\n const newState = clearHistory();\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Get a copy of the current undo stack.\n */\n getUndoStack(): EditAction[] {\n return [...this.undoStack];\n }\n\n /**\n * Get a copy of the current redo stack.\n */\n getRedoStack(): EditAction[] {\n return [...this.redoStack];\n }\n // #endregion\n}\n"],"names":["undo","state","undoStack","length","newState","action","pop","redoStack","redo","UndoRedoPlugin","BaseGridPlugin","static","name","required","reason","defaultConfig","maxHistorySize","attach","grid","super","this","on","detail","recordEdit","rowIndex","field","oldValue","newValue","detach","onKeyDown","event","isUndo","ctrlKey","metaKey","key","shiftKey","isRedo","result","rows","emit","type","requestRender","timestamp","Date","now","createEditAction","maxSize","shift","pushAction","config","canUndo","canRedo","clearHistory","getUndoStack","getRedoStack"],"mappings":"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"}
1
+ {"version":3,"file":"undo-redo.umd.js","sources":["../../../../../libs/grid/src/lib/plugins/undo-redo/history.ts","../../../../../libs/grid/src/lib/plugins/undo-redo/UndoRedoPlugin.ts"],"sourcesContent":["/**\n * Undo/Redo History Management\n *\n * Pure functions for managing the undo/redo stacks.\n * These functions are stateless and return new state objects.\n */\n\nimport type { CompoundEditAction, EditAction, UndoRedoAction, UndoRedoState } from './types';\n\n/**\n * Push a new action onto the undo stack.\n * Clears the redo stack since new actions invalidate redo history.\n *\n * @param state - Current undo/redo state\n * @param action - The action to add\n * @param maxSize - Maximum history size\n * @returns New state with the action added\n */\nexport function pushAction(state: UndoRedoState, action: UndoRedoAction, maxSize: number): UndoRedoState {\n const undoStack = [...state.undoStack, action];\n\n // Trim oldest actions if over max size\n while (undoStack.length > maxSize) {\n undoStack.shift();\n }\n\n return {\n undoStack,\n redoStack: [], // Clear redo on new action\n };\n}\n\n/**\n * Undo the most recent action.\n * Moves the action from undo stack to redo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was undone (or null if nothing to undo)\n */\nexport function undo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: UndoRedoAction | null;\n} {\n if (state.undoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const undoStack = [...state.undoStack];\n const action = undoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack,\n redoStack: [...state.redoStack, action],\n },\n action,\n };\n}\n\n/**\n * Redo the most recently undone action.\n * Moves the action from redo stack back to undo stack.\n *\n * @param state - Current undo/redo state\n * @returns New state and the action that was redone (or null if nothing to redo)\n */\nexport function redo(state: UndoRedoState): {\n newState: UndoRedoState;\n action: UndoRedoAction | null;\n} {\n if (state.redoStack.length === 0) {\n return { newState: state, action: null };\n }\n\n const redoStack = [...state.redoStack];\n const action = redoStack.pop();\n\n // This should never happen due to the length check above,\n // but TypeScript needs the explicit check\n if (!action) {\n return { newState: state, action: null };\n }\n\n return {\n newState: {\n undoStack: [...state.undoStack, action],\n redoStack,\n },\n action,\n };\n}\n\n/**\n * Check if there are any actions that can be undone.\n *\n * @param state - Current undo/redo state\n * @returns True if undo is available\n */\nexport function canUndo(state: UndoRedoState): boolean {\n return state.undoStack.length > 0;\n}\n\n/**\n * Check if there are any actions that can be redone.\n *\n * @param state - Current undo/redo state\n * @returns True if redo is available\n */\nexport function canRedo(state: UndoRedoState): boolean {\n return state.redoStack.length > 0;\n}\n\n/**\n * Clear all history, returning an empty state.\n *\n * @returns Fresh empty state\n */\nexport function clearHistory(): UndoRedoState {\n return { undoStack: [], redoStack: [] };\n}\n\n/**\n * Create a new edit action with the current timestamp.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n * @returns A new EditAction object\n */\nexport function createEditAction(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): EditAction {\n return {\n type: 'cell-edit',\n rowIndex,\n field,\n oldValue,\n newValue,\n timestamp: Date.now(),\n };\n}\n\n/**\n * Create a compound action grouping multiple edits into a single undo/redo unit.\n *\n * @param actions - The individual edit actions to group (in chronological order)\n * @returns A CompoundEditAction wrapping all provided edits\n */\nexport function createCompoundAction(actions: EditAction[]): CompoundEditAction {\n return {\n type: 'compound',\n actions,\n timestamp: Date.now(),\n };\n}\n","/**\n * Undo/Redo Plugin (Class-based)\n *\n * Provides undo/redo functionality for cell edits in tbw-grid.\n * Supports Ctrl+Z/Cmd+Z for undo and Ctrl+Y/Cmd+Y (or Ctrl+Shift+Z) for redo.\n */\n\nimport { FOCUSABLE_EDITOR_SELECTOR } from '../../core/internal/rows';\nimport { BaseGridPlugin, type GridElement, type PluginDependency } from '../../core/plugin/base-plugin';\nimport type { InternalGrid } from '../../core/types';\nimport {\n canRedo,\n canUndo,\n clearHistory,\n createCompoundAction,\n createEditAction,\n pushAction,\n redo,\n undo,\n} from './history';\nimport type { EditAction, UndoRedoAction, UndoRedoConfig, UndoRedoDetail } from './types';\n\n/**\n * Undo/Redo Plugin for tbw-grid\n *\n * Tracks all cell edits and lets users revert or replay changes with familiar keyboard\n * shortcuts (Ctrl+Z / Ctrl+Y). Maintains an in-memory history stack with configurable\n * depth—perfect for data entry workflows where mistakes happen.\n *\n * > **Required Dependency:** This plugin requires EditingPlugin to be loaded first.\n * > UndoRedo tracks the edit history that EditingPlugin creates.\n *\n * ## Installation\n *\n * ```ts\n * import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';\n * import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';\n * ```\n *\n * ## Configuration Options\n *\n * | Option | Type | Default | Description |\n * |--------|------|---------|-------------|\n * | `maxHistorySize` | `number` | `100` | Maximum actions in history stack |\n *\n * ## Keyboard Shortcuts\n *\n * | Shortcut | Action |\n * |----------|--------|\n * | `Ctrl+Z` / `Cmd+Z` | Undo last edit |\n * | `Ctrl+Y` / `Cmd+Shift+Z` | Redo last undone edit |\n *\n * ## Programmatic API\n *\n * | Method | Signature | Description |\n * |--------|-----------|-------------|\n * | `undo` | `() => UndoRedoAction \\| null` | Undo the last edit (or compound) |\n * | `redo` | `() => UndoRedoAction \\| null` | Redo the last undone edit (or compound) |\n * | `canUndo` | `() => boolean` | Check if undo is available |\n * | `canRedo` | `() => boolean` | Check if redo is available |\n * | `clearHistory` | `() => void` | Clear the entire history stack |\n * | `recordEdit` | `(rowIndex, field, old, new) => void` | Manually record a cell edit |\n * | `beginTransaction` | `() => void` | Start grouping edits into a compound |\n * | `endTransaction` | `() => void` | Finalize and push the compound action |\n *\n * @example Basic Usage with EditingPlugin\n * ```ts\n * import '@toolbox-web/grid';\n * import { EditingPlugin } from '@toolbox-web/grid/plugins/editing';\n * import { UndoRedoPlugin } from '@toolbox-web/grid/plugins/undo-redo';\n *\n * const grid = document.querySelector('tbw-grid');\n * grid.gridConfig = {\n * columns: [\n * { field: 'name', header: 'Name', editable: true },\n * { field: 'price', header: 'Price', type: 'number', editable: true },\n * ],\n * plugins: [\n * new EditingPlugin({ editOn: 'dblclick' }), // Required - must be first\n * new UndoRedoPlugin({ maxHistorySize: 50 }),\n * ],\n * };\n * ```\n *\n * @see {@link UndoRedoConfig} for configuration options\n * @see {@link EditingPlugin} for the required dependency\n *\n * @internal Extends BaseGridPlugin\n */\nexport class UndoRedoPlugin extends BaseGridPlugin<UndoRedoConfig> {\n /**\n * Plugin dependencies - UndoRedoPlugin requires EditingPlugin to track edits.\n *\n * The EditingPlugin must be loaded BEFORE this plugin in the plugins array.\n * @internal\n */\n static override readonly dependencies: PluginDependency[] = [\n { name: 'editing', required: true, reason: 'UndoRedoPlugin tracks cell edit history' },\n ];\n\n /** @internal */\n readonly name = 'undoRedo';\n\n /** @internal */\n protected override get defaultConfig(): Partial<UndoRedoConfig> {\n return {\n maxHistorySize: 100,\n };\n }\n\n // State as class properties\n private undoStack: UndoRedoAction[] = [];\n private redoStack: UndoRedoAction[] = [];\n\n /** Suppresses recording during undo/redo to prevent feedback loops. */\n #suppressRecording = false;\n\n /** Accumulates edits during a transaction; `null` when no transaction is active. */\n #transactionBuffer: EditAction[] | null = null;\n\n /**\n * Apply a value to a row cell, using `updateRow()` when possible so that\n * active editors (during row-edit mode) are notified via the `cell-change`\n * → `onValueChange` pipeline. Falls back to direct mutation when the row\n * has no ID.\n */\n #applyValue(action: EditAction, value: unknown): void {\n const rows = this.rows as Record<string, unknown>[];\n const row = rows[action.rowIndex];\n if (!row) return;\n\n // Prefer updateRow() — it emits `cell-change` events which notify active\n // editors via their `onValueChange` callbacks. Without this, undo/redo\n // during row-edit mode is invisible because the render pipeline skips\n // cells that have active editors.\n try {\n const rowId = this.grid.getRowId(row);\n if (rowId) {\n this.grid.updateRow(rowId, { [action.field]: value });\n return;\n }\n } catch {\n // No row ID configured — fall back to direct mutation\n }\n\n // Fallback: direct mutation (editors won't see the change during editing)\n row[action.field] = value;\n }\n\n /**\n * Move keyboard focus to the cell targeted by an undo/redo action.\n * If the grid is in row-edit mode and the cell has an active editor,\n * the editor input is focused so the user can continue editing.\n */\n #focusActionCell(action: EditAction): void {\n const internalGrid = this.grid as unknown as InternalGrid;\n\n // Map field name → visible column index\n const colIdx = internalGrid._visibleColumns?.findIndex((c) => c.field === action.field) ?? -1;\n if (colIdx < 0) return;\n\n internalGrid._focusRow = action.rowIndex;\n internalGrid._focusCol = colIdx;\n\n // If we're in row-edit mode, focus the editor input in the target cell\n const rowEl = internalGrid.findRenderedRowElement?.(action.rowIndex);\n if (!rowEl) return;\n\n const cellEl = rowEl.querySelector(`.cell[data-col=\"${colIdx}\"]`) as HTMLElement | null;\n if (cellEl?.classList.contains('editing')) {\n const editor = cellEl.querySelector(FOCUSABLE_EDITOR_SELECTOR) as HTMLElement | null;\n editor?.focus({ preventScroll: true });\n }\n }\n\n /**\n * Apply value changes for a single or compound action.\n * Wraps `#applyValue` calls with `#suppressRecording` to prevent feedback loops.\n */\n #applyUndoRedoAction(action: UndoRedoAction, direction: 'undo' | 'redo'): void {\n this.#suppressRecording = true;\n if (action.type === 'compound') {\n const subActions = direction === 'undo' ? [...action.actions].reverse() : action.actions;\n for (const sub of subActions) {\n this.#applyValue(sub, direction === 'undo' ? sub.oldValue : sub.newValue);\n }\n } else {\n this.#applyValue(action, direction === 'undo' ? action.oldValue : action.newValue);\n }\n this.#suppressRecording = false;\n }\n\n /**\n * Focus the cell associated with an undo/redo action.\n * For compound actions, focuses the **last** action's cell. When consumers\n * use `beginTransaction()` + `recordEdit()` (cascaded fields) followed by\n * `queueMicrotask(() => endTransaction())`, the grid's auto-recorded\n * primary field edit is appended last. Focusing it ensures the cursor\n * lands on the field the user originally edited, not on a cascaded field\n * whose column may not even be visible.\n */\n #focusUndoRedoAction(action: UndoRedoAction): void {\n const target = action.type === 'compound' ? action.actions[action.actions.length - 1] : action;\n if (target) this.#focusActionCell(target);\n }\n\n /**\n * Subscribe to cell-edit-committed events from EditingPlugin.\n * @internal\n */\n override attach(grid: GridElement): void {\n super.attach(grid);\n // Auto-record edits via Event Bus\n this.on(\n 'cell-edit-committed',\n (detail: { rowIndex: number; field: string; oldValue: unknown; newValue: unknown }) => {\n // Skip recording during undo/redo operations. When undo/redo applies a\n // value via updateRow, two things can cause re-entry:\n // 1. updateRow → cell-change → onValueChange → editor triggers commit\n // 2. Browser native undo (if not fully suppressed) fires input event → commit\n // The suppress flag prevents these from corrupting the history stacks.\n if (this.#suppressRecording) return;\n this.recordEdit(detail.rowIndex, detail.field, detail.oldValue, detail.newValue);\n },\n );\n }\n\n /**\n * Clean up state when plugin is detached.\n * @internal\n */\n override detach(): void {\n this.undoStack = [];\n this.redoStack = [];\n this.#transactionBuffer = null;\n }\n\n /**\n * Handle keyboard shortcuts for undo/redo.\n * - Ctrl+Z / Cmd+Z: Undo\n * - Ctrl+Y / Cmd+Y / Ctrl+Shift+Z / Cmd+Shift+Z: Redo\n * @internal\n */\n override onKeyDown(event: KeyboardEvent): boolean {\n const isUndo = (event.ctrlKey || event.metaKey) && event.key === 'z' && !event.shiftKey;\n const isRedo = (event.ctrlKey || event.metaKey) && (event.key === 'y' || (event.key === 'z' && event.shiftKey));\n\n if (isUndo) {\n // Prevent browser native undo on text inputs — it would conflict\n // with the grid's undo by mutating the input text independently,\n // triggering re-commits that cancel the grid undo.\n event.preventDefault();\n\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n this.#applyUndoRedoAction(result.action, 'undo');\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('undo', {\n action: result.action,\n type: 'undo',\n });\n\n this.#focusUndoRedoAction(result.action);\n this.requestRenderWithFocus();\n }\n return true;\n }\n\n if (isRedo) {\n // Prevent browser native redo — same reason as undo above\n event.preventDefault();\n\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n this.#applyUndoRedoAction(result.action, 'redo');\n\n // Update state from result\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n\n this.emit<UndoRedoDetail>('redo', {\n action: result.action,\n type: 'redo',\n });\n\n this.#focusUndoRedoAction(result.action);\n this.requestRenderWithFocus();\n }\n return true;\n }\n\n return false;\n }\n\n // #region Public API Methods\n\n /**\n * Record a cell edit for undo/redo tracking.\n * Call this when a cell value changes.\n *\n * @param rowIndex - The row index where the edit occurred\n * @param field - The field (column key) that was edited\n * @param oldValue - The value before the edit\n * @param newValue - The value after the edit\n */\n recordEdit(rowIndex: number, field: string, oldValue: unknown, newValue: unknown): void {\n const action = createEditAction(rowIndex, field, oldValue, newValue);\n\n // Buffer during transactions instead of pushing to undo stack\n if (this.#transactionBuffer) {\n this.#transactionBuffer.push(action);\n return;\n }\n\n const newState = pushAction(\n { undoStack: this.undoStack, redoStack: this.redoStack },\n action,\n this.config.maxHistorySize ?? 100,\n );\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Begin grouping subsequent edits into a single compound action.\n *\n * While a transaction is active, all `recordEdit()` calls (both manual\n * and auto-recorded from `cell-edit-committed`) are buffered instead of\n * pushed to the undo stack. Call `endTransaction()` to finalize the group.\n *\n * **Typical usage** — group a user edit with its cascaded side-effects:\n *\n * ```ts\n * grid.addEventListener('cell-commit', (e) => {\n * const undoRedo = grid.getPluginByName('undoRedo');\n * undoRedo.beginTransaction();\n *\n * // Record cascaded updates (these won't auto-record)\n * const oldB = row.fieldB;\n * undoRedo.recordEdit(rowIndex, 'fieldB', oldB, computedB);\n * grid.updateRow(rowId, { fieldB: computedB });\n *\n * // End after the auto-recorded original edit is captured\n * queueMicrotask(() => undoRedo.endTransaction());\n * });\n * ```\n *\n * @throws Error if a transaction is already in progress\n */\n beginTransaction(): void {\n if (this.#transactionBuffer) {\n throw new Error('UndoRedoPlugin: Transaction already in progress. Call endTransaction() first.');\n }\n this.#transactionBuffer = [];\n }\n\n /**\n * Finalize the current transaction, wrapping all buffered edits into a\n * single compound action on the undo stack.\n *\n * - If the buffer contains multiple edits, they are wrapped in a `CompoundEditAction`.\n * - If the buffer contains a single edit, it is pushed as a regular `EditAction`.\n * - If the buffer is empty, this is a no-op.\n *\n * Undoing a compound action reverts all edits in reverse order; redoing\n * replays them in forward order.\n *\n * @throws Error if no transaction is in progress\n */\n endTransaction(): void {\n const buffer = this.#transactionBuffer;\n if (!buffer) {\n throw new Error('UndoRedoPlugin: No transaction in progress. Call beginTransaction() first.');\n }\n this.#transactionBuffer = null;\n\n if (buffer.length === 0) return;\n\n const action: UndoRedoAction = buffer.length === 1 ? buffer[0] : createCompoundAction(buffer);\n const newState = pushAction(\n { undoStack: this.undoStack, redoStack: this.redoStack },\n action,\n this.config.maxHistorySize ?? 100,\n );\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n }\n\n /**\n * Programmatically undo the last action.\n *\n * @returns The undone action, or null if nothing to undo\n */\n undo(): UndoRedoAction | null {\n const result = undo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n this.#applyUndoRedoAction(result.action, 'undo');\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.#focusUndoRedoAction(result.action);\n this.requestRenderWithFocus();\n }\n return result.action;\n }\n\n /**\n * Programmatically redo the last undone action.\n *\n * @returns The redone action, or null if nothing to redo\n */\n redo(): UndoRedoAction | null {\n const result = redo({ undoStack: this.undoStack, redoStack: this.redoStack });\n if (result.action) {\n this.#applyUndoRedoAction(result.action, 'redo');\n this.undoStack = result.newState.undoStack;\n this.redoStack = result.newState.redoStack;\n this.#focusUndoRedoAction(result.action);\n this.requestRenderWithFocus();\n }\n return result.action;\n }\n\n /**\n * Check if there are any actions that can be undone.\n */\n canUndo(): boolean {\n return canUndo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Check if there are any actions that can be redone.\n */\n canRedo(): boolean {\n return canRedo({ undoStack: this.undoStack, redoStack: this.redoStack });\n }\n\n /**\n * Clear all undo/redo history.\n */\n clearHistory(): void {\n const newState = clearHistory();\n this.undoStack = newState.undoStack;\n this.redoStack = newState.redoStack;\n this.#transactionBuffer = null;\n }\n\n /**\n * Get a copy of the current undo stack.\n */\n getUndoStack(): UndoRedoAction[] {\n return [...this.undoStack];\n }\n\n /**\n * Get a copy of the current redo stack.\n */\n getRedoStack(): UndoRedoAction[] {\n return [...this.redoStack];\n }\n // #endregion\n}\n"],"names":["pushAction","state","action","maxSize","undoStack","length","shift","redoStack","undo","newState","pop","redo","UndoRedoPlugin","BaseGridPlugin","static","name","required","reason","defaultConfig","maxHistorySize","suppressRecording","transactionBuffer","applyValue","value","row","this","rows","rowIndex","rowId","grid","getRowId","updateRow","field","focusActionCell","internalGrid","colIdx","_visibleColumns","findIndex","c","_focusRow","_focusCol","rowEl","findRenderedRowElement","cellEl","querySelector","classList","contains","editor","FOCUSABLE_EDITOR_SELECTOR","focus","preventScroll","applyUndoRedoAction","direction","type","subActions","actions","reverse","sub","oldValue","newValue","focusUndoRedoAction","target","attach","super","on","detail","recordEdit","detach","onKeyDown","event","isUndo","ctrlKey","metaKey","key","shiftKey","isRedo","preventDefault","result","emit","requestRenderWithFocus","timestamp","Date","now","createEditAction","push","config","beginTransaction","Error","endTransaction","buffer","canUndo","canRedo","clearHistory","getUndoStack","getRedoStack"],"mappings":"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"}