@rickcedwhat/playwright-smart-table 6.3.0 → 6.3.1

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.
package/dist/index.d.ts CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './useTable';
2
2
  export * from './types';
3
+ export * from './plugins';
package/dist/index.js CHANGED
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./useTable"), exports);
18
18
  __exportStar(require("./types"), exports);
19
+ __exportStar(require("./plugins"), exports);
package/dist/plugins.d.ts CHANGED
@@ -16,11 +16,13 @@ export declare const Plugins: {
16
16
  selector?: string;
17
17
  scrollAmount?: number;
18
18
  }) => Promise<string[]>;
19
- cellNavigation: (context: import("./types").StrategyContext & {
20
- column: string;
21
- index: number;
22
- rowIndex?: number;
23
- }) => Promise<void>;
19
+ navigation: {
20
+ goUp: (context: import("./types").StrategyContext) => Promise<void>;
21
+ goDown: (context: import("./types").StrategyContext) => Promise<void>;
22
+ goLeft: (context: import("./types").StrategyContext) => Promise<void>;
23
+ goRight: (context: import("./types").StrategyContext) => Promise<void>;
24
+ goHome: (context: import("./types").StrategyContext) => Promise<void>;
25
+ };
24
26
  getCellLocator: ({ row, columnIndex }: any) => any;
25
27
  getActiveCell: ({ page }: any) => Promise<{
26
28
  rowIndex: number;
package/dist/smartRow.js CHANGED
@@ -13,6 +13,99 @@ exports.createSmartRow = void 0;
13
13
  const fill_1 = require("./strategies/fill");
14
14
  const stringUtils_1 = require("./utils/stringUtils");
15
15
  const debugUtils_1 = require("./utils/debugUtils");
16
+ /**
17
+ * Internal helper to navigate to a cell with active cell optimization.
18
+ * Uses navigation primitives (goUp, goDown, goLeft, goRight, goHome) for orchestration.
19
+ * Falls back to cellNavigation for backward compatibility.
20
+ * Returns the target cell locator after navigation.
21
+ */
22
+ const _navigateToCell = (params) => __awaiter(void 0, void 0, void 0, function* () {
23
+ const { config, rootLocator, page, resolve, column, index, rowLocator, rowIndex } = params;
24
+ // Get active cell if strategy is available
25
+ let activeCell = null;
26
+ if (config.strategies.getActiveCell) {
27
+ activeCell = yield config.strategies.getActiveCell({
28
+ config,
29
+ root: rootLocator,
30
+ page,
31
+ resolve
32
+ });
33
+ // Optimization: Check if we are ALREADY at the target cell
34
+ if (activeCell && activeCell.rowIndex === rowIndex && activeCell.columnIndex === index) {
35
+ // Skip navigation - we're already there!
36
+ return activeCell.locator;
37
+ }
38
+ }
39
+ const context = { config, root: rootLocator, page, resolve };
40
+ // Use navigation primitives if available
41
+ if (config.strategies.navigation) {
42
+ const nav = config.strategies.navigation;
43
+ if (typeof rowIndex !== 'number') {
44
+ throw new Error('Row index is required for navigation');
45
+ }
46
+ // Determine starting position
47
+ let startRow = 0;
48
+ let startCol = 0;
49
+ if (activeCell && activeCell.rowIndex >= 0 && activeCell.columnIndex >= 0) {
50
+ // Use current position
51
+ startRow = activeCell.rowIndex;
52
+ startCol = activeCell.columnIndex;
53
+ }
54
+ else if (nav.goHome) {
55
+ // Reset to top-left
56
+ yield nav.goHome(context);
57
+ }
58
+ // Calculate movement needed
59
+ const rowDiff = rowIndex - startRow;
60
+ const colDiff = index - startCol;
61
+ // Navigate vertically
62
+ for (let i = 0; i < Math.abs(rowDiff); i++) {
63
+ if (rowDiff > 0 && nav.goDown) {
64
+ yield nav.goDown(context);
65
+ }
66
+ else if (rowDiff < 0 && nav.goUp) {
67
+ yield nav.goUp(context);
68
+ }
69
+ }
70
+ // Navigate horizontally
71
+ for (let i = 0; i < Math.abs(colDiff); i++) {
72
+ if (colDiff > 0 && nav.goRight) {
73
+ yield nav.goRight(context);
74
+ }
75
+ else if (colDiff < 0 && nav.goLeft) {
76
+ yield nav.goLeft(context);
77
+ }
78
+ }
79
+ yield page.waitForTimeout(50);
80
+ }
81
+ else if (config.strategies.cellNavigation) {
82
+ // Fallback to legacy cellNavigation strategy
83
+ yield config.strategies.cellNavigation({
84
+ config,
85
+ root: rootLocator,
86
+ page,
87
+ resolve,
88
+ column,
89
+ index,
90
+ rowLocator,
91
+ rowIndex,
92
+ activeCell
93
+ });
94
+ }
95
+ // Get the active cell locator after navigation (for virtualized tables)
96
+ if (config.strategies.getActiveCell) {
97
+ const updatedActiveCell = yield config.strategies.getActiveCell({
98
+ config,
99
+ root: rootLocator,
100
+ page,
101
+ resolve
102
+ });
103
+ if (updatedActiveCell) {
104
+ return updatedActiveCell.locator;
105
+ }
106
+ }
107
+ return null;
108
+ });
16
109
  /**
17
110
  * Factory to create a SmartRow by extending a Playwright Locator.
18
111
  * We avoid Class/Proxy to ensure full compatibility with Playwright's expect(locator) matchers.
@@ -68,55 +161,19 @@ const createSmartRow = (rowLocator, map, rowIndex, config, rootLocator, resolve,
68
161
  let targetCell = cell;
69
162
  const count = yield cell.count();
70
163
  if (count === 0) {
71
- // Optimization: Check if we are ALREADY at the target cell
72
- if (config.strategies.getActiveCell) {
73
- const active = yield config.strategies.getActiveCell({
74
- config,
75
- root: rootLocator,
76
- page,
77
- resolve
78
- });
79
- if (active && active.rowIndex === rowIndex && active.columnIndex === idx) {
80
- targetCell = active.locator;
81
- // Skip navigation
82
- }
83
- else {
84
- // Cell doesn't exist - navigate to it
85
- yield config.strategies.cellNavigation({
86
- config: config,
87
- root: rootLocator,
88
- page: page,
89
- resolve: resolve,
90
- column: col,
91
- index: idx,
92
- rowLocator: rowLocator,
93
- rowIndex: rowIndex
94
- });
95
- // Update targetCell after navigation if needed (e.g. active cell changed)
96
- if (config.strategies.getActiveCell) {
97
- const activeCell = yield config.strategies.getActiveCell({
98
- config,
99
- root: rootLocator,
100
- page,
101
- resolve
102
- });
103
- if (activeCell)
104
- targetCell = activeCell.locator;
105
- }
106
- }
107
- }
108
- else {
109
- // Fallback navigation without active cell check
110
- yield config.strategies.cellNavigation({
111
- config: config,
112
- root: rootLocator,
113
- page: page,
114
- resolve: resolve,
115
- column: col,
116
- index: idx,
117
- rowLocator: rowLocator,
118
- rowIndex: rowIndex
119
- });
164
+ // Cell not in DOM (virtualized) - navigate to it
165
+ const navigatedCell = yield _navigateToCell({
166
+ config,
167
+ rootLocator,
168
+ page,
169
+ resolve,
170
+ column: col,
171
+ index: idx,
172
+ rowLocator,
173
+ rowIndex
174
+ });
175
+ if (navigatedCell) {
176
+ targetCell = navigatedCell;
120
177
  }
121
178
  }
122
179
  // --- Navigation Logic End ---
@@ -142,15 +199,15 @@ const createSmartRow = (rowLocator, map, rowIndex, config, rootLocator, resolve,
142
199
  if (colIdx === undefined) {
143
200
  throw new Error((0, stringUtils_1.buildColumnNotFoundError)(colName, Array.from(map.keys())));
144
201
  }
145
- yield config.strategies.cellNavigation({
146
- config: config,
147
- root: rootLocator,
202
+ yield _navigateToCell({
203
+ config,
204
+ rootLocator,
148
205
  page: rootLocator.page(),
149
- resolve: resolve,
206
+ resolve,
150
207
  column: colName,
151
208
  index: colIdx,
152
- rowLocator: rowLocator,
153
- rowIndex: rowIndex
209
+ rowLocator,
210
+ rowIndex
154
211
  });
155
212
  const strategy = config.strategies.fill || fill_1.FillStrategies.default;
156
213
  (0, debugUtils_1.logDebug)(config, 'verbose', `Filling cell "${colName}" with value`, value);
@@ -1,13 +1,29 @@
1
+ import type { Locator } from '@playwright/test';
1
2
  import { StrategyContext } from '../types';
2
3
  /**
4
+ * Primitive navigation functions that define HOW to move within a table.
5
+ * The orchestration logic (WHEN to move) lives in _navigateToCell.
6
+ */
7
+ export interface NavigationPrimitives {
8
+ goUp?: (context: StrategyContext) => Promise<void>;
9
+ goDown?: (context: StrategyContext) => Promise<void>;
10
+ goLeft?: (context: StrategyContext) => Promise<void>;
11
+ goRight?: (context: StrategyContext) => Promise<void>;
12
+ goHome?: (context: StrategyContext) => Promise<void>;
13
+ }
14
+ /**
15
+ * @deprecated Use NavigationPrimitives instead. This will be removed in a future version.
3
16
  * Defines the contract for a cell navigation strategy.
4
- * It is responsible for ensuring a specific CELL is visible/focused (navigates to row + column),
5
- * typically by scrolling or using keyboard navigation.
6
17
  */
7
18
  export type CellNavigationStrategy = (context: StrategyContext & {
8
19
  column: string;
9
20
  index: number;
10
21
  rowIndex?: number;
22
+ activeCell?: {
23
+ rowIndex: number;
24
+ columnIndex: number;
25
+ locator: Locator;
26
+ } | null;
11
27
  }) => Promise<void>;
12
28
  export declare const CellNavigationStrategies: {
13
29
  /**
@@ -1,13 +1,11 @@
1
1
  import { StrategyContext } from '../../types';
2
2
  /**
3
- * Strategy that clicks into the table to establish focus and then uses the Right Arrow key
4
- * to navigate to the target CELL (navigates down to the row, then right to the column).
5
- *
6
- * Useful for canvas-based grids like Glide where DOM scrolling might not be enough for interaction
7
- * or where keyboard navigation is the primary way to move focus.
3
+ * Primitive navigation functions for Glide Data Grid.
4
+ * These define HOW to move, not WHEN to move.
5
+ * The orchestration logic lives in _navigateToCell.
8
6
  */
9
- export declare const keyboardCellNavigation: (context: StrategyContext & {
10
- column: string;
11
- index: number;
12
- rowIndex?: number;
13
- }) => Promise<void>;
7
+ export declare const glideGoUp: (context: StrategyContext) => Promise<void>;
8
+ export declare const glideGoDown: (context: StrategyContext) => Promise<void>;
9
+ export declare const glideGoLeft: (context: StrategyContext) => Promise<void>;
10
+ export declare const glideGoRight: (context: StrategyContext) => Promise<void>;
11
+ export declare const glideGoHome: (context: StrategyContext) => Promise<void>;
@@ -9,35 +9,36 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.keyboardCellNavigation = void 0;
12
+ exports.glideGoHome = exports.glideGoRight = exports.glideGoLeft = exports.glideGoDown = exports.glideGoUp = void 0;
13
13
  /**
14
- * Strategy that clicks into the table to establish focus and then uses the Right Arrow key
15
- * to navigate to the target CELL (navigates down to the row, then right to the column).
16
- *
17
- * Useful for canvas-based grids like Glide where DOM scrolling might not be enough for interaction
18
- * or where keyboard navigation is the primary way to move focus.
14
+ * Primitive navigation functions for Glide Data Grid.
15
+ * These define HOW to move, not WHEN to move.
16
+ * The orchestration logic lives in _navigateToCell.
19
17
  */
20
- const keyboardCellNavigation = (context) => __awaiter(void 0, void 0, void 0, function* () {
21
- const { root, page, index, rowIndex } = context;
22
- if (typeof rowIndex !== 'number') {
23
- throw new Error('Row index is required for keyboard navigation');
24
- }
18
+ const glideGoUp = (context) => __awaiter(void 0, void 0, void 0, function* () {
19
+ yield context.page.keyboard.press('ArrowUp');
20
+ });
21
+ exports.glideGoUp = glideGoUp;
22
+ const glideGoDown = (context) => __awaiter(void 0, void 0, void 0, function* () {
23
+ yield context.page.keyboard.press('ArrowDown');
24
+ });
25
+ exports.glideGoDown = glideGoDown;
26
+ const glideGoLeft = (context) => __awaiter(void 0, void 0, void 0, function* () {
27
+ yield context.page.keyboard.press('ArrowLeft');
28
+ });
29
+ exports.glideGoLeft = glideGoLeft;
30
+ const glideGoRight = (context) => __awaiter(void 0, void 0, void 0, function* () {
31
+ yield context.page.keyboard.press('ArrowRight');
32
+ });
33
+ exports.glideGoRight = glideGoRight;
34
+ const glideGoHome = (context) => __awaiter(void 0, void 0, void 0, function* () {
35
+ const { root, page } = context;
25
36
  yield root.focus();
26
37
  yield page.waitForTimeout(100);
27
- // Robust Navigation:
28
- // 1. Jump to Top-Left (Reset) - Sequence for Cross-OS (Mac/Windows)
38
+ // Reset to top-left - Cross-OS sequence (Mac/Windows)
29
39
  yield page.keyboard.press('Control+Home');
30
40
  yield page.keyboard.press('Meta+ArrowUp'); // Mac Go-To-Top
31
41
  yield page.keyboard.press('Home'); // Ensure start of row
32
42
  yield page.waitForTimeout(150);
33
- // 2. Move Down to Target Row
34
- for (let i = 0; i < rowIndex; i++) {
35
- yield page.keyboard.press('ArrowDown');
36
- }
37
- // 3. Move Right to Target Column
38
- for (let i = 0; i < index; i++) {
39
- yield page.keyboard.press('ArrowRight');
40
- }
41
- yield page.waitForTimeout(50);
42
43
  });
43
- exports.keyboardCellNavigation = keyboardCellNavigation;
44
+ exports.glideGoHome = glideGoHome;
@@ -15,11 +15,13 @@ export declare const GlideStrategies: {
15
15
  selector?: string;
16
16
  scrollAmount?: number;
17
17
  }) => Promise<string[]>;
18
- cellNavigation: (context: import("../types").StrategyContext & {
19
- column: string;
20
- index: number;
21
- rowIndex?: number;
22
- }) => Promise<void>;
18
+ navigation: {
19
+ goUp: (context: import("../types").StrategyContext) => Promise<void>;
20
+ goDown: (context: import("../types").StrategyContext) => Promise<void>;
21
+ goLeft: (context: import("../types").StrategyContext) => Promise<void>;
22
+ goRight: (context: import("../types").StrategyContext) => Promise<void>;
23
+ goHome: (context: import("../types").StrategyContext) => Promise<void>;
24
+ };
23
25
  getCellLocator: ({ row, columnIndex }: any) => any;
24
26
  getActiveCell: ({ page }: any) => Promise<{
25
27
  rowIndex: number;
@@ -92,7 +92,13 @@ exports.GlideStrategies = {
92
92
  fill: exports.glideFillStrategy,
93
93
  pagination: exports.glidePaginationStrategy,
94
94
  header: headers_1.scrollRightHeader,
95
- cellNavigation: columns_1.keyboardCellNavigation,
95
+ navigation: {
96
+ goUp: columns_1.glideGoUp,
97
+ goDown: columns_1.glideGoDown,
98
+ goLeft: columns_1.glideGoLeft,
99
+ goRight: columns_1.glideGoRight,
100
+ goHome: columns_1.glideGoHome
101
+ },
96
102
  getCellLocator: exports.glideGetCellLocator,
97
103
  getActiveCell: exports.glideGetActiveCell
98
104
  };
@@ -3,4 +3,4 @@
3
3
  * This file is generated by scripts/embed-types.js
4
4
  * It contains the raw text of types.ts to provide context for LLM prompts.
5
5
  */
6
- export declare const TYPE_CONTEXT = "\n/**\n * Flexible selector type - can be a CSS string, function returning a Locator, or Locator itself.\n * @example\n * // String selector\n * rowSelector: 'tbody tr'\n * \n * // Function selector\n * rowSelector: (root) => root.locator('[role=\"row\"]')\n */\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\n/**\n * Value used to filter rows.\n * - string/number/RegExp: filter by text content of the cell.\n * - function: filter by custom locator logic within the cell.\n * @example\n * // Text filter\n * { Name: 'John' }\n * \n * // Custom locator filter (e.g. checkbox is checked)\n * { Status: (cell) => cell.locator('input:checked') }\n */\nexport type FilterValue = string | RegExp | number | ((cell: Locator) => Locator);\n\n/**\n * Function to get a cell locator given row, column info.\n * Replaces the old cellResolver.\n */\nexport type GetCellLocatorFn = (args: {\n row: Locator;\n columnName: string;\n columnIndex: number;\n rowIndex?: number;\n page: Page;\n}) => Locator;\n\n/**\n * Function to get the currently active/focused cell.\n * Returns null if no cell is active.\n */\nexport type GetActiveCellFn = (args: TableContext) => Promise<{\n rowIndex: number;\n columnIndex: number;\n columnName?: string;\n locator: Locator;\n} | null>;\n\n\n/**\n * SmartRow - A Playwright Locator with table-aware methods.\n * \n * Extends all standard Locator methods (click, isVisible, etc.) with table-specific functionality.\n * \n * @example\n * const row = table.getRow({ Name: 'John Doe' });\n * await row.click(); // Standard Locator method\n * const email = row.getCell('Email'); // Table-aware method\n * const data = await row.toJSON(); // Extract all row data\n * await row.smartFill({ Name: 'Jane', Status: 'Active' }); // Fill form fields\n */\nexport type SmartRow<T = any> = Locator & {\n /** Optional row index (0-based) if known */\n rowIndex?: number;\n\n /**\n * Get a cell locator by column name.\n * @param column - Column name (case-sensitive)\n * @returns Locator for the cell\n * @example\n * const emailCell = row.getCell('Email');\n * await expect(emailCell).toHaveText('john@example.com');\n */\n getCell(column: string): Locator;\n\n /**\n * Extract all cell data as a key-value object.\n * @param options - Optional configuration\n * @param options.columns - Specific columns to extract (extracts all if not specified)\n * @returns Promise resolving to row data\n * @example\n * const data = await row.toJSON();\n * // { Name: 'John', Email: 'john@example.com', ... }\n * \n * const partial = await row.toJSON({ columns: ['Name', 'Email'] });\n * // { Name: 'John', Email: 'john@example.com' }\n */\n toJSON(options?: { columns?: string[] }): Promise<T>;\n\n /**\n * Scrolls/paginates to bring this row into view.\n * Only works if rowIndex is known (e.g., from getRowByIndex).\n * @throws Error if rowIndex is unknown\n */\n bringIntoView(): Promise<void>;\n\n /**\n * Intelligently fills form fields in the row.\n * Automatically detects input types (text, select, checkbox, contenteditable).\n * \n * @param data - Column-value pairs to fill\n * @param options - Optional configuration\n * @param options.inputMappers - Custom input selectors per column\n * @example\n * // Auto-detection\n * await row.smartFill({ Name: 'John', Status: 'Active', Subscribe: true });\n * \n * // Custom input mappers\n * await row.smartFill(\n * { Name: 'John' },\n * { inputMappers: { Name: (cell) => cell.locator('.custom-input') } }\n * );\n */\n smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext & { rowLocator?: Locator; rowIndex?: number };\n\n/**\n * Defines the contract for a sorting strategy.\n */\nexport interface SortingStrategy {\n /**\n * Performs the sort action on a column.\n */\n doSort(options: {\n columnName: string;\n direction: 'asc' | 'desc';\n context: StrategyContext;\n }): Promise<void>;\n\n /**\n * Retrieves the current sort state of a column.\n */\n getSortState(options: {\n columnName: string;\n context: StrategyContext;\n }): Promise<'asc' | 'desc' | 'none'>;\n}\n\n/**\n * Debug configuration for development and troubleshooting\n */\nexport type DebugConfig = {\n /**\n * Slow down operations for debugging\n * - number: Apply same delay to all operations (ms)\n * - object: Granular delays per operation type\n */\n slow?: number | {\n pagination?: number;\n getCell?: number;\n findRow?: number;\n default?: number;\n };\n /**\n * Log level for debug output\n * - 'verbose': All logs (verbose, info, error)\n * - 'info': Info and error logs only\n * - 'error': Error logs only\n * - 'none': No logs\n */\n logLevel?: 'verbose' | 'info' | 'error' | 'none';\n};\n\nexport interface TableContext<T = any> {\n root: Locator;\n config: FinalTableConfig<T>;\n page: Page;\n resolve: (selector: Selector, parent: Locator | Page) => Locator;\n}\n\nexport type PaginationStrategy = (context: TableContext) => Promise<boolean>;\n\nexport type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;\n\nexport interface PromptOptions {\n /**\n * Output Strategy:\n * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).\n * - 'console': Standard console logs (Default).\n */\n output?: 'console' | 'error';\n includeTypes?: boolean;\n}\n\nexport type FillStrategy = (options: {\n row: SmartRow;\n columnName: string;\n value: any;\n index: number;\n page: Page;\n rootLocator: Locator;\n table: TableResult; // The parent table instance\n fillOptions?: FillOptions;\n}) => Promise<void>;\n\nexport type { HeaderStrategy } from './strategies/headers';\nexport type { CellNavigationStrategy } from './strategies/columns';\n\n/**\n * Strategy to resolve column names (string or regex) to their index.\n */\nexport type { ColumnResolutionStrategy } from './strategies/resolution';\n\n/**\n * Strategy to filter rows based on criteria.\n */\nexport interface FilterStrategy {\n apply(options: {\n rows: Locator;\n filter: { column: string, value: FilterValue };\n colIndex: number;\n tableContext: TableContext;\n }): Locator;\n}\n\n/**\n * Strategy to check if the table or rows are loading.\n */\nexport interface LoadingStrategy {\n isTableLoading?: (context: TableContext) => Promise<boolean>;\n isRowLoading?: (row: SmartRow) => Promise<boolean>;\n isHeaderLoading?: (context: TableContext) => Promise<boolean>;\n}\n\n/**\n * Organized container for all table interaction strategies.\n */\nexport interface TableStrategies {\n /** Strategy for discovering/scanning headers */\n header?: HeaderStrategy;\n /** Strategy for navigating to specific cells (row + column) */\n cellNavigation?: CellNavigationStrategy;\n /** Strategy for filling form inputs */\n fill?: FillStrategy;\n /** Strategy for paginating through data */\n pagination?: PaginationStrategy;\n /** Strategy for sorting columns */\n sorting?: SortingStrategy;\n /** Strategy for deduplicating rows during iteration/scrolling */\n dedupe?: DedupeStrategy;\n /** Function to get a cell locator */\n getCellLocator?: GetCellLocatorFn;\n /** Function to get the currently active/focused cell */\n getActiveCell?: GetActiveCellFn;\n /** Custom helper to check if a table is fully loaded/ready */\n isTableLoaded?: (args: TableContext) => Promise<boolean>;\n /** Custom helper to check if a row is fully loaded/ready */\n isRowLoaded?: (args: { row: Locator, index: number }) => Promise<boolean>;\n /** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */\n isCellLoaded?: (args: { cell: Locator, column: string, row: Locator }) => Promise<boolean>;\n /** Strategy for detecting loading states */\n loading?: LoadingStrategy;\n}\n\n/**\n * Configuration options for useTable.\n */\n/**\n * Configuration options for useTable.\n */\nexport interface TableConfig<T = any> {\n /** Selector for the table headers */\n headerSelector?: string;\n /** Selector for the table rows */\n rowSelector?: string;\n /** Selector for the cells within a row */\n cellSelector?: string;\n /** Number of pages to scan for verification */\n maxPages?: number;\n /** Hook to rename columns dynamically */\n headerTransformer?: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;\n /** Automatically scroll to table on init */\n autoScroll?: boolean;\n /** Debug options for development and troubleshooting */\n debug?: DebugConfig;\n /** Reset hook */\n onReset?: (context: TableContext) => Promise<void>;\n /** All interaction strategies */\n strategies?: TableStrategies;\n /**\n * Custom data mappers for specific columns.\n * Allows extracting complex data types (boolean, number) instead of just string.\n */\n dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;\n}\n\nexport interface FinalTableConfigLike<T = any> extends TableConfig<T> {\n headerSelector: string;\n rowSelector: string;\n cellSelector: string;\n maxPages: number;\n autoScroll: boolean;\n debug?: TableConfig['debug'];\n headerTransformer: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;\n onReset: (context: TableContext) => Promise<void>;\n strategies: TableStrategies;\n}\n// Alias for backward compatibility if needed, or update usages\nexport type FinalTableConfig<T = any> = FinalTableConfigLike<T>;\n\n\nexport interface FillOptions {\n /**\n * Custom input mappers for specific columns.\n * Maps column names to functions that return the input locator for that cell.\n */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\n/**\n * Options for generateConfigPrompt\n */\nexport interface PromptOptions {\n /**\n * Output Strategy:\n * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).\n * - 'console': Standard console logs (Default).\n */\n output?: 'console' | 'error';\n /**\n * Include TypeScript type definitions in the prompt\n * @default true\n */\n includeTypes?: boolean;\n}\n\nexport interface TableResult<T = any> {\n /**\n * Initializes the table by resolving headers. Must be called before using sync methods.\n * @param options Optional timeout for header resolution (default: 3000ms)\n */\n init(options?: { timeout?: number }): Promise<TableResult>;\n\n /**\n * SYNC: Checks if the table has been initialized.\n * @returns true if init() has been called and completed, false otherwise\n */\n isInitialized(): boolean;\n\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n /**\n * Finds a row by filters on the current page only. Returns immediately (sync).\n * Throws error if table is not initialized.\n */\n getRow: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean }\n ) => SmartRow;\n\n /**\n * Gets a row by 1-based index on the current page.\n * Throws error if table is not initialized.\n * @param index 1-based row index\n * @param options Optional settings including bringIntoView\n */\n getRowByIndex: (\n index: number,\n options?: { bringIntoView?: boolean }\n ) => SmartRow;\n\n /**\n * ASYNC: Searches for a single row across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match and max pages\n */\n findRow: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRow>;\n\n /**\n * ASYNC: Searches for all matching rows across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match and max pages\n */\n findRows: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRowArray<T>>;\n\n /**\n * Navigates to a specific column using the configured CellNavigationStrategy.\n */\n scrollToColumn: (columnName: string) => Promise<void>;\n\n /**\n * Gets all rows on the current page only (does not paginate).\n * Auto-initializes the table if not already initialized.\n * Returns a SmartRowArray which extends Array with a toJSON() helper method.\n * @param options - Filter options\n */\n getRows: (options?: { filter?: Record<string, any>, exact?: boolean }) => Promise<SmartRowArray>;\n\n /**\n * Resets the table state (clears cache, flags) and invokes the onReset strategy.\n */\n reset: () => Promise<void>;\n\n /**\n * Revalidates the table's structure (headers, columns) without resetting pagination or state.\n * Useful when columns change visibility or order dynamically.\n */\n revalidate: () => Promise<void>;\n\n /**\n * Scans a specific column across all pages and returns the values.\n */\n getColumnValues: <V = string>(column: string, options?: { mapper?: (cell: Locator) => Promise<V> | V, maxPages?: number }) => Promise<V[]>;\n\n /**\n * Provides access to sorting actions and assertions.\n */\n sorting: {\n /**\n * Applies the configured sorting strategy to the specified column.\n * @param columnName The name of the column to sort.\n * @param direction The direction to sort ('asc' or 'desc').\n */\n apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;\n /**\n * Gets the current sort state of a column using the configured sorting strategy.\n * @param columnName The name of the column to check.\n * @returns A promise that resolves to 'asc', 'desc', or 'none'.\n */\n getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;\n };\n\n /**\n * Iterates through paginated table data, calling the callback for each iteration.\n * Callback return values are automatically appended to allData, which is returned.\n */\n iterateThroughTable: <T = any>(\n callback: (context: {\n index: number;\n isFirst: boolean;\n isLast: boolean;\n rows: SmartRowArray;\n allData: T[];\n table: RestrictedTableResult;\n batchInfo?: {\n startIndex: number;\n endIndex: number;\n size: number;\n };\n\n }) => T | T[] | Promise<T | T[]>,\n options?: {\n pagination?: PaginationStrategy;\n dedupeStrategy?: DedupeStrategy;\n maxIterations?: number;\n batchSize?: number;\n getIsFirst?: (context: { index: number }) => boolean;\n getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;\n beforeFirst?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;\n afterLast?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;\n /**\n * If true, flattens array results from callback into the main data array.\n * If false (default), pushes the return value as-is (preserves batching/arrays).\n */\n autoFlatten?: boolean;\n }\n ) => Promise<T[]>;\n\n /**\n * Generate an AI-friendly configuration prompt for debugging.\n * Outputs table HTML and TypeScript definitions to help AI assistants generate config.\n */\n generateConfigPrompt: (options?: PromptOptions) => Promise<void>;\n}\n\n/**\n * Restricted table result that excludes methods that shouldn't be called during iteration.\n */\nexport type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;\n";
6
+ export declare const TYPE_CONTEXT = "\n/**\n * Flexible selector type - can be a CSS string, function returning a Locator, or Locator itself.\n * @example\n * // String selector\n * rowSelector: 'tbody tr'\n * \n * // Function selector\n * rowSelector: (root) => root.locator('[role=\"row\"]')\n */\nexport type Selector = string | ((root: Locator | Page) => Locator);\n\n/**\n * Value used to filter rows.\n * - string/number/RegExp: filter by text content of the cell.\n * - function: filter by custom locator logic within the cell.\n * @example\n * // Text filter\n * { Name: 'John' }\n * \n * // Custom locator filter (e.g. checkbox is checked)\n * { Status: (cell) => cell.locator('input:checked') }\n */\nexport type FilterValue = string | RegExp | number | ((cell: Locator) => Locator);\n\n/**\n * Function to get a cell locator given row, column info.\n * Replaces the old cellResolver.\n */\nexport type GetCellLocatorFn = (args: {\n row: Locator;\n columnName: string;\n columnIndex: number;\n rowIndex?: number;\n page: Page;\n}) => Locator;\n\n/**\n * Function to get the currently active/focused cell.\n * Returns null if no cell is active.\n */\nexport type GetActiveCellFn = (args: TableContext) => Promise<{\n rowIndex: number;\n columnIndex: number;\n columnName?: string;\n locator: Locator;\n} | null>;\n\n\n/**\n * SmartRow - A Playwright Locator with table-aware methods.\n * \n * Extends all standard Locator methods (click, isVisible, etc.) with table-specific functionality.\n * \n * @example\n * const row = table.getRow({ Name: 'John Doe' });\n * await row.click(); // Standard Locator method\n * const email = row.getCell('Email'); // Table-aware method\n * const data = await row.toJSON(); // Extract all row data\n * await row.smartFill({ Name: 'Jane', Status: 'Active' }); // Fill form fields\n */\nexport type SmartRow<T = any> = Locator & {\n /** Optional row index (0-based) if known */\n rowIndex?: number;\n\n /**\n * Get a cell locator by column name.\n * @param column - Column name (case-sensitive)\n * @returns Locator for the cell\n * @example\n * const emailCell = row.getCell('Email');\n * await expect(emailCell).toHaveText('john@example.com');\n */\n getCell(column: string): Locator;\n\n /**\n * Extract all cell data as a key-value object.\n * @param options - Optional configuration\n * @param options.columns - Specific columns to extract (extracts all if not specified)\n * @returns Promise resolving to row data\n * @example\n * const data = await row.toJSON();\n * // { Name: 'John', Email: 'john@example.com', ... }\n * \n * const partial = await row.toJSON({ columns: ['Name', 'Email'] });\n * // { Name: 'John', Email: 'john@example.com' }\n */\n toJSON(options?: { columns?: string[] }): Promise<T>;\n\n /**\n * Scrolls/paginates to bring this row into view.\n * Only works if rowIndex is known (e.g., from getRowByIndex).\n * @throws Error if rowIndex is unknown\n */\n bringIntoView(): Promise<void>;\n\n /**\n * Intelligently fills form fields in the row.\n * Automatically detects input types (text, select, checkbox, contenteditable).\n * \n * @param data - Column-value pairs to fill\n * @param options - Optional configuration\n * @param options.inputMappers - Custom input selectors per column\n * @example\n * // Auto-detection\n * await row.smartFill({ Name: 'John', Status: 'Active', Subscribe: true });\n * \n * // Custom input mappers\n * await row.smartFill(\n * { Name: 'John' },\n * { inputMappers: { Name: (cell) => cell.locator('.custom-input') } }\n * );\n */\n smartFill: (data: Partial<T> | Record<string, any>, options?: FillOptions) => Promise<void>;\n};\n\nexport type StrategyContext = TableContext & { rowLocator?: Locator; rowIndex?: number };\n\n/**\n * Defines the contract for a sorting strategy.\n */\nexport interface SortingStrategy {\n /**\n * Performs the sort action on a column.\n */\n doSort(options: {\n columnName: string;\n direction: 'asc' | 'desc';\n context: StrategyContext;\n }): Promise<void>;\n\n /**\n * Retrieves the current sort state of a column.\n */\n getSortState(options: {\n columnName: string;\n context: StrategyContext;\n }): Promise<'asc' | 'desc' | 'none'>;\n}\n\n/**\n * Debug configuration for development and troubleshooting\n */\nexport type DebugConfig = {\n /**\n * Slow down operations for debugging\n * - number: Apply same delay to all operations (ms)\n * - object: Granular delays per operation type\n */\n slow?: number | {\n pagination?: number;\n getCell?: number;\n findRow?: number;\n default?: number;\n };\n /**\n * Log level for debug output\n * - 'verbose': All logs (verbose, info, error)\n * - 'info': Info and error logs only\n * - 'error': Error logs only\n * - 'none': No logs\n */\n logLevel?: 'verbose' | 'info' | 'error' | 'none';\n};\n\nexport interface TableContext<T = any> {\n root: Locator;\n config: FinalTableConfig<T>;\n page: Page;\n resolve: (selector: Selector, parent: Locator | Page) => Locator;\n}\n\nexport type PaginationStrategy = (context: TableContext) => Promise<boolean>;\n\nexport type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;\n\nexport interface PromptOptions {\n /**\n * Output Strategy:\n * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).\n * - 'console': Standard console logs (Default).\n */\n output?: 'console' | 'error';\n includeTypes?: boolean;\n}\n\nexport type FillStrategy = (options: {\n row: SmartRow;\n columnName: string;\n value: any;\n index: number;\n page: Page;\n rootLocator: Locator;\n table: TableResult; // The parent table instance\n fillOptions?: FillOptions;\n}) => Promise<void>;\n\nexport type { HeaderStrategy } from './strategies/headers';\nexport type { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';\n\n/**\n * Strategy to resolve column names (string or regex) to their index.\n */\nexport type { ColumnResolutionStrategy } from './strategies/resolution';\n\n/**\n * Strategy to filter rows based on criteria.\n */\nexport interface FilterStrategy {\n apply(options: {\n rows: Locator;\n filter: { column: string, value: FilterValue };\n colIndex: number;\n tableContext: TableContext;\n }): Locator;\n}\n\n/**\n * Strategy to check if the table or rows are loading.\n */\nexport interface LoadingStrategy {\n isTableLoading?: (context: TableContext) => Promise<boolean>;\n isRowLoading?: (row: SmartRow) => Promise<boolean>;\n isHeaderLoading?: (context: TableContext) => Promise<boolean>;\n}\n\n/**\n * Organized container for all table interaction strategies.\n */\nexport interface TableStrategies {\n /** Strategy for discovering/scanning headers */\n header?: HeaderStrategy;\n /** Primitive navigation functions (goUp, goDown, goLeft, goRight, goHome) */\n navigation?: NavigationPrimitives;\n /** @deprecated Use navigation primitives instead. Strategy for navigating to specific cells (row + column) */\n cellNavigation?: CellNavigationStrategy;\n /** Strategy for filling form inputs */\n fill?: FillStrategy;\n /** Strategy for paginating through data */\n pagination?: PaginationStrategy;\n /** Strategy for sorting columns */\n sorting?: SortingStrategy;\n /** Strategy for deduplicating rows during iteration/scrolling */\n dedupe?: DedupeStrategy;\n /** Function to get a cell locator */\n getCellLocator?: GetCellLocatorFn;\n /** Function to get the currently active/focused cell */\n getActiveCell?: GetActiveCellFn;\n /** Custom helper to check if a table is fully loaded/ready */\n isTableLoaded?: (args: TableContext) => Promise<boolean>;\n /** Custom helper to check if a row is fully loaded/ready */\n isRowLoaded?: (args: { row: Locator, index: number }) => Promise<boolean>;\n /** Custom helper to check if a cell is fully loaded/ready (e.g. for editing) */\n isCellLoaded?: (args: { cell: Locator, column: string, row: Locator }) => Promise<boolean>;\n /** Strategy for detecting loading states */\n loading?: LoadingStrategy;\n}\n\n/**\n * Configuration options for useTable.\n */\n/**\n * Configuration options for useTable.\n */\nexport interface TableConfig<T = any> {\n /** Selector for the table headers */\n headerSelector?: string;\n /** Selector for the table rows */\n rowSelector?: string;\n /** Selector for the cells within a row */\n cellSelector?: string;\n /** Number of pages to scan for verification */\n maxPages?: number;\n /** Hook to rename columns dynamically */\n headerTransformer?: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;\n /** Automatically scroll to table on init */\n autoScroll?: boolean;\n /** Debug options for development and troubleshooting */\n debug?: DebugConfig;\n /** Reset hook */\n onReset?: (context: TableContext) => Promise<void>;\n /** All interaction strategies */\n strategies?: TableStrategies;\n /**\n * Custom data mappers for specific columns.\n * Allows extracting complex data types (boolean, number) instead of just string.\n */\n dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;\n}\n\nexport interface FinalTableConfigLike<T = any> extends TableConfig<T> {\n headerSelector: string;\n rowSelector: string;\n cellSelector: string;\n maxPages: number;\n autoScroll: boolean;\n debug?: TableConfig['debug'];\n headerTransformer: (args: { text: string, index: number, locator: Locator, seenHeaders: Set<string> }) => string | Promise<string>;\n onReset: (context: TableContext) => Promise<void>;\n strategies: TableStrategies;\n}\n// Alias for backward compatibility if needed, or update usages\nexport type FinalTableConfig<T = any> = FinalTableConfigLike<T>;\n\n\nexport interface FillOptions {\n /**\n * Custom input mappers for specific columns.\n * Maps column names to functions that return the input locator for that cell.\n */\n inputMappers?: Record<string, (cell: Locator) => Locator>;\n}\n\n/**\n * Options for generateConfigPrompt\n */\nexport interface PromptOptions {\n /**\n * Output Strategy:\n * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).\n * - 'console': Standard console logs (Default).\n */\n output?: 'console' | 'error';\n /**\n * Include TypeScript type definitions in the prompt\n * @default true\n */\n includeTypes?: boolean;\n}\n\nexport interface TableResult<T = any> {\n /**\n * Initializes the table by resolving headers. Must be called before using sync methods.\n * @param options Optional timeout for header resolution (default: 3000ms)\n */\n init(options?: { timeout?: number }): Promise<TableResult>;\n\n /**\n * SYNC: Checks if the table has been initialized.\n * @returns true if init() has been called and completed, false otherwise\n */\n isInitialized(): boolean;\n\n getHeaders: () => Promise<string[]>;\n getHeaderCell: (columnName: string) => Promise<Locator>;\n\n /**\n * Finds a row by filters on the current page only. Returns immediately (sync).\n * Throws error if table is not initialized.\n */\n getRow: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean }\n ) => SmartRow;\n\n /**\n * Gets a row by 1-based index on the current page.\n * Throws error if table is not initialized.\n * @param index 1-based row index\n * @param options Optional settings including bringIntoView\n */\n getRowByIndex: (\n index: number,\n options?: { bringIntoView?: boolean }\n ) => SmartRow;\n\n /**\n * ASYNC: Searches for a single row across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match and max pages\n */\n findRow: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRow>;\n\n /**\n * ASYNC: Searches for all matching rows across pages using pagination.\n * Auto-initializes the table if not already initialized.\n * @param filters - The filter criteria to match\n * @param options - Search options including exact match and max pages\n */\n findRows: (\n filters: Record<string, FilterValue>,\n options?: { exact?: boolean, maxPages?: number }\n ) => Promise<SmartRowArray<T>>;\n\n /**\n * Navigates to a specific column using the configured CellNavigationStrategy.\n */\n scrollToColumn: (columnName: string) => Promise<void>;\n\n /**\n * Gets all rows on the current page only (does not paginate).\n * Auto-initializes the table if not already initialized.\n * Returns a SmartRowArray which extends Array with a toJSON() helper method.\n * @param options - Filter options\n */\n getRows: (options?: { filter?: Record<string, any>, exact?: boolean }) => Promise<SmartRowArray>;\n\n /**\n * Resets the table state (clears cache, flags) and invokes the onReset strategy.\n */\n reset: () => Promise<void>;\n\n /**\n * Revalidates the table's structure (headers, columns) without resetting pagination or state.\n * Useful when columns change visibility or order dynamically.\n */\n revalidate: () => Promise<void>;\n\n /**\n * Scans a specific column across all pages and returns the values.\n */\n getColumnValues: <V = string>(column: string, options?: { mapper?: (cell: Locator) => Promise<V> | V, maxPages?: number }) => Promise<V[]>;\n\n /**\n * Provides access to sorting actions and assertions.\n */\n sorting: {\n /**\n * Applies the configured sorting strategy to the specified column.\n * @param columnName The name of the column to sort.\n * @param direction The direction to sort ('asc' or 'desc').\n */\n apply(columnName: string, direction: 'asc' | 'desc'): Promise<void>;\n /**\n * Gets the current sort state of a column using the configured sorting strategy.\n * @param columnName The name of the column to check.\n * @returns A promise that resolves to 'asc', 'desc', or 'none'.\n */\n getState(columnName: string): Promise<'asc' | 'desc' | 'none'>;\n };\n\n /**\n * Iterates through paginated table data, calling the callback for each iteration.\n * Callback return values are automatically appended to allData, which is returned.\n */\n iterateThroughTable: <T = any>(\n callback: (context: {\n index: number;\n isFirst: boolean;\n isLast: boolean;\n rows: SmartRowArray;\n allData: T[];\n table: RestrictedTableResult;\n batchInfo?: {\n startIndex: number;\n endIndex: number;\n size: number;\n };\n\n }) => T | T[] | Promise<T | T[]>,\n options?: {\n pagination?: PaginationStrategy;\n dedupeStrategy?: DedupeStrategy;\n maxIterations?: number;\n batchSize?: number;\n getIsFirst?: (context: { index: number }) => boolean;\n getIsLast?: (context: { index: number, paginationResult: boolean }) => boolean;\n beforeFirst?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;\n afterLast?: (context: { index: number, rows: SmartRowArray, allData: any[] }) => void | Promise<void>;\n /**\n * If true, flattens array results from callback into the main data array.\n * If false (default), pushes the return value as-is (preserves batching/arrays).\n */\n autoFlatten?: boolean;\n }\n ) => Promise<T[]>;\n\n /**\n * Generate an AI-friendly configuration prompt for debugging.\n * Outputs table HTML and TypeScript definitions to help AI assistants generate config.\n */\n generateConfigPrompt: (options?: PromptOptions) => Promise<void>;\n}\n\n/**\n * Restricted table result that excludes methods that shouldn't be called during iteration.\n */\nexport type RestrictedTableResult<T = any> = Omit<TableResult<T>, 'searchForRow' | 'iterateThroughTable' | 'reset'>;\n";
@@ -204,7 +204,7 @@ export type FillStrategy = (options: {
204
204
  }) => Promise<void>;
205
205
 
206
206
  export type { HeaderStrategy } from './strategies/headers';
207
- export type { CellNavigationStrategy } from './strategies/columns';
207
+ export type { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';
208
208
 
209
209
  /**
210
210
  * Strategy to resolve column names (string or regex) to their index.
@@ -238,7 +238,9 @@ export interface LoadingStrategy {
238
238
  export interface TableStrategies {
239
239
  /** Strategy for discovering/scanning headers */
240
240
  header?: HeaderStrategy;
241
- /** Strategy for navigating to specific cells (row + column) */
241
+ /** Primitive navigation functions (goUp, goDown, goLeft, goRight, goHome) */
242
+ navigation?: NavigationPrimitives;
243
+ /** @deprecated Use navigation primitives instead. Strategy for navigating to specific cells (row + column) */
242
244
  cellNavigation?: CellNavigationStrategy;
243
245
  /** Strategy for filling form inputs */
244
246
  fill?: FillStrategy;
package/dist/types.d.ts CHANGED
@@ -183,9 +183,9 @@ export type FillStrategy = (options: {
183
183
  fillOptions?: FillOptions;
184
184
  }) => Promise<void>;
185
185
  export type { HeaderStrategy } from './strategies/headers';
186
- export type { CellNavigationStrategy } from './strategies/columns';
186
+ export type { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';
187
187
  import { HeaderStrategy } from './strategies/headers';
188
- import { CellNavigationStrategy } from './strategies/columns';
188
+ import { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';
189
189
  /**
190
190
  * Strategy to resolve column names (string or regex) to their index.
191
191
  */
@@ -218,7 +218,9 @@ export interface LoadingStrategy {
218
218
  export interface TableStrategies {
219
219
  /** Strategy for discovering/scanning headers */
220
220
  header?: HeaderStrategy;
221
- /** Strategy for navigating to specific cells (row + column) */
221
+ /** Primitive navigation functions (goUp, goDown, goLeft, goRight, goHome) */
222
+ navigation?: NavigationPrimitives;
223
+ /** @deprecated Use navigation primitives instead. Strategy for navigating to specific cells (row + column) */
222
224
  cellNavigation?: CellNavigationStrategy;
223
225
  /** Strategy for filling form inputs */
224
226
  fill?: FillStrategy;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rickcedwhat/playwright-smart-table",
3
- "version": "6.3.0",
3
+ "version": "6.3.1",
4
4
  "description": "Smart, column-aware table interactions for Playwright",
5
5
  "author": "Cedrick Catalan",
6
6
  "license": "MIT",