@rickcedwhat/playwright-smart-table 6.3.1 → 6.4.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.
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
1
  export * from './useTable';
2
2
  export * from './types';
3
3
  export * from './plugins';
4
+ export * from './strategies';
package/dist/index.js CHANGED
@@ -17,3 +17,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
17
17
  __exportStar(require("./useTable"), exports);
18
18
  __exportStar(require("./types"), exports);
19
19
  __exportStar(require("./plugins"), exports);
20
+ __exportStar(require("./strategies"), exports);
@@ -0,0 +1,6 @@
1
+ /**
2
+ * šŸ¤– AUTO-GENERATED FILE. DO NOT EDIT.
3
+ * This file is generated by scripts/embed-config-types.mjs
4
+ * It contains minimal type definitions for config generation prompts.
5
+ */
6
+ export declare const MINIMAL_CONFIG_CONTEXT = "\n/**\n * Flexible selector type - can be a CSS string or function returning a Locator.\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 * Debug configuration for development and troubleshooting\n */\nexport type DebugConfig = {\n slow?: number | {\n pagination?: number;\n getCell?: number;\n findRow?: number;\n default?: number;\n };\n logLevel?: 'verbose' | 'info' | 'error' | 'none';\n};\n\n/**\n * Configuration options for useTable - focus on selectors and basic setup\n */\nexport interface TableConfig<T = any> {\n /** CSS selector or function for table headers */\n headerSelector?: string | ((root: Locator) => Locator);\n \n /** CSS selector or function for table rows */\n rowSelector?: string | ((root: Locator) => Locator);\n \n /** CSS selector or function for cells within a row */\n cellSelector?: string | ((row: Locator) => Locator);\n \n /** Transform header text (e.g., normalize, deduplicate) */\n headerTransformer?: (args: { \n text: string; \n index: number; \n locator: Locator;\n seenHeaders: Set<string>;\n }) => string | Promise<string>;\n \n /** Automatically scroll to table on init (default: true) */\n autoScroll?: boolean;\n \n /** Debug options for development and troubleshooting */\n debug?: DebugConfig;\n \n /** Advanced: Custom strategies for pagination, sorting, navigation, etc. */\n strategies?: TableStrategies;\n \n /** Custom data mappers for extracting complex types (boolean, number) */\n dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;\n}\n\n/**\n * Example usage:\n */\n// const table = useTable(page.locator('table'), {\n// headerSelector: 'thead th',\n// rowSelector: 'tbody tr',\n// cellSelector: 'td',\n// headerTransformer: ({ text }) => text.trim()\n// });\n\n";
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MINIMAL_CONFIG_CONTEXT = void 0;
4
+ /**
5
+ * šŸ¤– AUTO-GENERATED FILE. DO NOT EDIT.
6
+ * This file is generated by scripts/embed-config-types.mjs
7
+ * It contains minimal type definitions for config generation prompts.
8
+ */
9
+ exports.MINIMAL_CONFIG_CONTEXT = `
10
+ /**
11
+ * Flexible selector type - can be a CSS string or function returning a Locator.
12
+ * @example
13
+ * // String selector
14
+ * rowSelector: 'tbody tr'
15
+ *
16
+ * // Function selector
17
+ * rowSelector: (root) => root.locator('[role="row"]')
18
+ */
19
+ export type Selector = string | ((root: Locator | Page) => Locator);
20
+
21
+ /**
22
+ * Debug configuration for development and troubleshooting
23
+ */
24
+ export type DebugConfig = {
25
+ slow?: number | {
26
+ pagination?: number;
27
+ getCell?: number;
28
+ findRow?: number;
29
+ default?: number;
30
+ };
31
+ logLevel?: 'verbose' | 'info' | 'error' | 'none';
32
+ };
33
+
34
+ /**
35
+ * Configuration options for useTable - focus on selectors and basic setup
36
+ */
37
+ export interface TableConfig<T = any> {
38
+ /** CSS selector or function for table headers */
39
+ headerSelector?: string | ((root: Locator) => Locator);
40
+
41
+ /** CSS selector or function for table rows */
42
+ rowSelector?: string | ((root: Locator) => Locator);
43
+
44
+ /** CSS selector or function for cells within a row */
45
+ cellSelector?: string | ((row: Locator) => Locator);
46
+
47
+ /** Transform header text (e.g., normalize, deduplicate) */
48
+ headerTransformer?: (args: {
49
+ text: string;
50
+ index: number;
51
+ locator: Locator;
52
+ seenHeaders: Set<string>;
53
+ }) => string | Promise<string>;
54
+
55
+ /** Automatically scroll to table on init (default: true) */
56
+ autoScroll?: boolean;
57
+
58
+ /** Debug options for development and troubleshooting */
59
+ debug?: DebugConfig;
60
+
61
+ /** Advanced: Custom strategies for pagination, sorting, navigation, etc. */
62
+ strategies?: TableStrategies;
63
+
64
+ /** Custom data mappers for extracting complex types (boolean, number) */
65
+ dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
66
+ }
67
+
68
+ /**
69
+ * Example usage:
70
+ */
71
+ // const table = useTable(page.locator('table'), {
72
+ // headerSelector: 'thead th',
73
+ // rowSelector: 'tbody tr',
74
+ // cellSelector: 'td',
75
+ // headerTransformer: ({ text }) => text.trim()
76
+ // });
77
+
78
+ `;
package/dist/plugins.d.ts CHANGED
@@ -4,12 +4,20 @@ export declare const Plugins: {
4
4
  header: (context: import("./types").TableContext) => Promise<string[]>;
5
5
  getCellLocator: ({ row, columnIndex }: any) => any;
6
6
  cellNavigation: ({ root, page, index }: any) => Promise<void>;
7
+ navigation: {
8
+ goRight: ({ root, page }: any) => Promise<void>;
9
+ goLeft: ({ root, page }: any) => Promise<void>;
10
+ goDown: ({ root, page }: any) => Promise<void>;
11
+ goUp: ({ root, page }: any) => Promise<void>;
12
+ goHome: ({ root, page }: any) => Promise<void>;
13
+ };
7
14
  pagination: import("./types").PaginationStrategy;
8
15
  };
9
16
  };
10
17
  Glide: {
11
18
  Strategies: {
12
19
  fill: import("./types").FillStrategy;
20
+ fillSimple: import("./types").FillStrategy;
13
21
  pagination: import("./types").PaginationStrategy;
14
22
  header: (context: import("./types").StrategyContext, options?: {
15
23
  limit?: number;
package/dist/smartRow.js CHANGED
@@ -77,33 +77,21 @@ const _navigateToCell = (params) => __awaiter(void 0, void 0, void 0, function*
77
77
  }
78
78
  }
79
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;
80
+ // Get the active cell locator after navigation (for virtualized tables)
81
+ if (config.strategies.getActiveCell) {
82
+ const updatedActiveCell = yield config.strategies.getActiveCell({
83
+ config,
84
+ root: rootLocator,
85
+ page,
86
+ resolve
87
+ });
88
+ if (updatedActiveCell) {
89
+ return updatedActiveCell.locator;
90
+ }
105
91
  }
92
+ return null;
106
93
  }
94
+ ;
107
95
  return null;
108
96
  });
109
97
  /**
@@ -33,7 +33,17 @@ const glideGoRight = (context) => __awaiter(void 0, void 0, void 0, function* ()
33
33
  exports.glideGoRight = glideGoRight;
34
34
  const glideGoHome = (context) => __awaiter(void 0, void 0, void 0, function* () {
35
35
  const { root, page } = context;
36
- yield root.focus();
36
+ // Glide renders to canvas - the accessibility table (root) is inside the canvas
37
+ // We need to find and focus the canvas element that contains our root
38
+ yield root.evaluate((el) => {
39
+ var _a;
40
+ // Find the closest canvas ancestor
41
+ const canvas = el.closest('canvas') || ((_a = el.parentElement) === null || _a === void 0 ? void 0 : _a.querySelector('canvas'));
42
+ if (canvas instanceof HTMLCanvasElement) {
43
+ canvas.tabIndex = 0;
44
+ canvas.focus();
45
+ }
46
+ });
37
47
  yield page.waitForTimeout(100);
38
48
  // Reset to top-left - Cross-OS sequence (Mac/Windows)
39
49
  yield page.keyboard.press('Control+Home');
@@ -1,5 +1,15 @@
1
1
  import { FillStrategy } from '../types';
2
+ /**
3
+ * Fill strategy for Glide Data Grid with textarea validation.
4
+ * This is the default strategy that works with the standard Glide Data Grid editor.
5
+ */
2
6
  export declare const glideFillStrategy: FillStrategy;
7
+ /**
8
+ * Simple fill strategy for Glide Data Grid.
9
+ * Use this if your Glide implementation doesn't use the standard textarea editor.
10
+ * This is faster but may not work for all Glide configurations.
11
+ */
12
+ export declare const glideFillSimple: FillStrategy;
3
13
  export declare const glidePaginationStrategy: import("../types").PaginationStrategy;
4
14
  export declare const glideGetCellLocator: ({ row, columnIndex }: any) => any;
5
15
  export declare const glideGetActiveCell: ({ page }: any) => Promise<{
@@ -9,6 +19,7 @@ export declare const glideGetActiveCell: ({ page }: any) => Promise<{
9
19
  } | null>;
10
20
  export declare const GlideStrategies: {
11
21
  fill: FillStrategy;
22
+ fillSimple: FillStrategy;
12
23
  pagination: import("../types").PaginationStrategy;
13
24
  header: (context: import("../types").StrategyContext, options?: {
14
25
  limit?: number;
@@ -9,11 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.GlideStrategies = exports.glideGetActiveCell = exports.glideGetCellLocator = exports.glidePaginationStrategy = exports.glideFillStrategy = void 0;
12
+ exports.GlideStrategies = exports.glideGetActiveCell = exports.glideGetCellLocator = exports.glidePaginationStrategy = exports.glideFillSimple = exports.glideFillStrategy = void 0;
13
13
  const columns_1 = require("./glide/columns");
14
14
  const headers_1 = require("./glide/headers");
15
15
  const pagination_1 = require("./pagination");
16
16
  const stabilization_1 = require("./stabilization");
17
+ /**
18
+ * Fill strategy for Glide Data Grid with textarea validation.
19
+ * This is the default strategy that works with the standard Glide Data Grid editor.
20
+ */
17
21
  const glideFillStrategy = (_a) => __awaiter(void 0, [_a], void 0, function* ({ value, page }) {
18
22
  // Edit Cell
19
23
  yield page.keyboard.press('Enter');
@@ -44,6 +48,17 @@ const glideFillStrategy = (_a) => __awaiter(void 0, [_a], void 0, function* ({ v
44
48
  yield page.waitForTimeout(300);
45
49
  });
46
50
  exports.glideFillStrategy = glideFillStrategy;
51
+ /**
52
+ * Simple fill strategy for Glide Data Grid.
53
+ * Use this if your Glide implementation doesn't use the standard textarea editor.
54
+ * This is faster but may not work for all Glide configurations.
55
+ */
56
+ const glideFillSimple = (_a) => __awaiter(void 0, [_a], void 0, function* ({ value, page }) {
57
+ yield page.keyboard.press('Enter');
58
+ yield page.keyboard.type(String(value));
59
+ yield page.keyboard.press('Enter');
60
+ });
61
+ exports.glideFillSimple = glideFillSimple;
47
62
  exports.glidePaginationStrategy = pagination_1.PaginationStrategies.infiniteScroll({
48
63
  scrollTarget: 'xpath=//ancestor::body//div[contains(@class, "dvn-scroller")]',
49
64
  scrollAmount: 500,
@@ -90,6 +105,7 @@ const glideGetActiveCell = (_a) => __awaiter(void 0, [_a], void 0, function* ({
90
105
  exports.glideGetActiveCell = glideGetActiveCell;
91
106
  exports.GlideStrategies = {
92
107
  fill: exports.glideFillStrategy,
108
+ fillSimple: exports.glideFillSimple,
93
109
  pagination: exports.glidePaginationStrategy,
94
110
  header: headers_1.scrollRightHeader,
95
111
  navigation: {
@@ -17,9 +17,23 @@ export declare const rdgCellNavigation: ({ root, page, index }: any) => Promise<
17
17
  * Scrolls the grid vertically to load more virtualized rows.
18
18
  */
19
19
  export declare const rdgPaginationStrategy: import("../types").PaginationStrategy;
20
+ export declare const rdgNavigation: {
21
+ goRight: ({ root, page }: any) => Promise<void>;
22
+ goLeft: ({ root, page }: any) => Promise<void>;
23
+ goDown: ({ root, page }: any) => Promise<void>;
24
+ goUp: ({ root, page }: any) => Promise<void>;
25
+ goHome: ({ root, page }: any) => Promise<void>;
26
+ };
20
27
  export declare const RDGStrategies: {
21
28
  header: (context: TableContext) => Promise<string[]>;
22
29
  getCellLocator: ({ row, columnIndex }: any) => any;
23
30
  cellNavigation: ({ root, page, index }: any) => Promise<void>;
31
+ navigation: {
32
+ goRight: ({ root, page }: any) => Promise<void>;
33
+ goLeft: ({ root, page }: any) => Promise<void>;
34
+ goDown: ({ root, page }: any) => Promise<void>;
35
+ goUp: ({ root, page }: any) => Promise<void>;
36
+ goHome: ({ root, page }: any) => Promise<void>;
37
+ };
24
38
  pagination: import("../types").PaginationStrategy;
25
39
  };
@@ -9,7 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.RDGStrategies = exports.rdgPaginationStrategy = exports.rdgCellNavigation = exports.rdgGetCellLocator = exports.scrollRightHeaderRDG = void 0;
12
+ exports.RDGStrategies = exports.rdgNavigation = exports.rdgPaginationStrategy = exports.rdgCellNavigation = exports.rdgGetCellLocator = exports.scrollRightHeaderRDG = void 0;
13
13
  /**
14
14
  * Scrolls the grid horizontally to collect all column headers.
15
15
  * Handles empty headers by labeling them (e.g. "Checkbox").
@@ -20,6 +20,7 @@ const scrollRightHeaderRDG = (context) => __awaiter(void 0, void 0, void 0, func
20
20
  const gridHandle = yield root.evaluateHandle((el) => {
21
21
  return el.querySelector('[role="grid"]') || el.closest('[role="grid"]');
22
22
  });
23
+ const scrollContainer = gridHandle; // RDG usually scrolls the grid container itself
23
24
  const expectedColumns = yield gridHandle.evaluate(el => el ? parseInt(el.getAttribute('aria-colcount') || '0', 10) : 0);
24
25
  const getVisible = () => __awaiter(void 0, void 0, void 0, function* () {
25
26
  const headerLoc = resolve(config.headerSelector, root);
@@ -92,9 +93,50 @@ exports.rdgPaginationStrategy = pagination_1.PaginationStrategies.infiniteScroll
92
93
  scrollAmount: 500,
93
94
  stabilization: stabilization_1.StabilizationStrategies.contentChanged({ timeout: 5000 })
94
95
  });
96
+ exports.rdgNavigation = {
97
+ goRight: (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, page }) {
98
+ yield root.evaluate((el) => {
99
+ // Find grid container
100
+ const grid = el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el;
101
+ if (grid)
102
+ grid.scrollLeft += 150;
103
+ });
104
+ }),
105
+ goLeft: (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, page }) {
106
+ yield root.evaluate((el) => {
107
+ const grid = el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el;
108
+ if (grid)
109
+ grid.scrollLeft -= 150;
110
+ });
111
+ }),
112
+ goDown: (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, page }) {
113
+ yield root.evaluate((el) => {
114
+ const grid = el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el;
115
+ if (grid)
116
+ grid.scrollTop += 35;
117
+ });
118
+ }),
119
+ goUp: (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, page }) {
120
+ yield root.evaluate((el) => {
121
+ const grid = el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el;
122
+ if (grid)
123
+ grid.scrollTop -= 35;
124
+ });
125
+ }),
126
+ goHome: (_a) => __awaiter(void 0, [_a], void 0, function* ({ root, page }) {
127
+ yield root.evaluate((el) => {
128
+ const grid = el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el;
129
+ if (grid) {
130
+ grid.scrollLeft = 0;
131
+ grid.scrollTop = 0;
132
+ }
133
+ });
134
+ })
135
+ };
95
136
  exports.RDGStrategies = {
96
137
  header: exports.scrollRightHeaderRDG,
97
138
  getCellLocator: exports.rdgGetCellLocator,
98
139
  cellNavigation: exports.rdgCellNavigation,
140
+ navigation: exports.rdgNavigation,
99
141
  pagination: exports.rdgPaginationStrategy
100
142
  };
@@ -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, 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";
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\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';\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\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\nexport interface TableConfig<T = any> {\n /** Selector for the table headers */\n headerSelector?: string | ((root: Locator) => Locator);\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 FinalTableConfig<T = any> extends TableConfig<T> {\n headerSelector: string | ((root: Locator) => Locator);\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\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\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";
@@ -182,15 +182,7 @@ export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
182
182
 
183
183
  export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
184
184
 
185
- export interface PromptOptions {
186
- /**
187
- * Output Strategy:
188
- * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
189
- * - 'console': Standard console logs (Default).
190
- */
191
- output?: 'console' | 'error';
192
- includeTypes?: boolean;
193
- }
185
+
194
186
 
195
187
  export type FillStrategy = (options: {
196
188
  row: SmartRow;
@@ -204,7 +196,6 @@ export type FillStrategy = (options: {
204
196
  }) => Promise<void>;
205
197
 
206
198
  export type { HeaderStrategy } from './strategies/headers';
207
- export type { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';
208
199
 
209
200
  /**
210
201
  * Strategy to resolve column names (string or regex) to their index.
@@ -240,8 +231,7 @@ export interface TableStrategies {
240
231
  header?: HeaderStrategy;
241
232
  /** Primitive navigation functions (goUp, goDown, goLeft, goRight, goHome) */
242
233
  navigation?: NavigationPrimitives;
243
- /** @deprecated Use navigation primitives instead. Strategy for navigating to specific cells (row + column) */
244
- cellNavigation?: CellNavigationStrategy;
234
+
245
235
  /** Strategy for filling form inputs */
246
236
  fill?: FillStrategy;
247
237
  /** Strategy for paginating through data */
@@ -264,15 +254,10 @@ export interface TableStrategies {
264
254
  loading?: LoadingStrategy;
265
255
  }
266
256
 
267
- /**
268
- * Configuration options for useTable.
269
- */
270
- /**
271
- * Configuration options for useTable.
272
- */
257
+
273
258
  export interface TableConfig<T = any> {
274
259
  /** Selector for the table headers */
275
- headerSelector?: string;
260
+ headerSelector?: string | ((root: Locator) => Locator);
276
261
  /** Selector for the table rows */
277
262
  rowSelector?: string;
278
263
  /** Selector for the cells within a row */
@@ -296,8 +281,8 @@ export interface TableConfig<T = any> {
296
281
  dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
297
282
  }
298
283
 
299
- export interface FinalTableConfigLike<T = any> extends TableConfig<T> {
300
- headerSelector: string;
284
+ export interface FinalTableConfig<T = any> extends TableConfig<T> {
285
+ headerSelector: string | ((root: Locator) => Locator);
301
286
  rowSelector: string;
302
287
  cellSelector: string;
303
288
  maxPages: number;
@@ -307,8 +292,6 @@ export interface FinalTableConfigLike<T = any> extends TableConfig<T> {
307
292
  onReset: (context: TableContext) => Promise<void>;
308
293
  strategies: TableStrategies;
309
294
  }
310
- // Alias for backward compatibility if needed, or update usages
311
- export type FinalTableConfig<T = any> = FinalTableConfigLike<T>;
312
295
 
313
296
 
314
297
  export interface FillOptions {
@@ -399,13 +382,7 @@ export interface TableResult<T = any> {
399
382
  */
400
383
  scrollToColumn: (columnName: string) => Promise<void>;
401
384
 
402
- /**
403
- * Gets all rows on the current page only (does not paginate).
404
- * Auto-initializes the table if not already initialized.
405
- * Returns a SmartRowArray which extends Array with a toJSON() helper method.
406
- * @param options - Filter options
407
- */
408
- getRows: (options?: { filter?: Record<string, any>, exact?: boolean }) => Promise<SmartRowArray>;
385
+
409
386
 
410
387
  /**
411
388
  * Resets the table state (clears cache, flags) and invokes the onReset strategy.
package/dist/types.d.ts CHANGED
@@ -163,15 +163,6 @@ export interface TableContext<T = any> {
163
163
  }
164
164
  export type PaginationStrategy = (context: TableContext) => Promise<boolean>;
165
165
  export type DedupeStrategy = (row: SmartRow) => string | number | Promise<string | number>;
166
- export interface PromptOptions {
167
- /**
168
- * Output Strategy:
169
- * - 'error': Throws an error with the prompt (useful for platforms that capture error output cleanly).
170
- * - 'console': Standard console logs (Default).
171
- */
172
- output?: 'console' | 'error';
173
- includeTypes?: boolean;
174
- }
175
166
  export type FillStrategy = (options: {
176
167
  row: SmartRow;
177
168
  columnName: string;
@@ -182,10 +173,9 @@ export type FillStrategy = (options: {
182
173
  table: TableResult;
183
174
  fillOptions?: FillOptions;
184
175
  }) => Promise<void>;
185
- export type { HeaderStrategy } from './strategies/headers';
186
- export type { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';
187
176
  import { HeaderStrategy } from './strategies/headers';
188
- import { CellNavigationStrategy, NavigationPrimitives } from './strategies/columns';
177
+ export type { HeaderStrategy } from './strategies/headers';
178
+ import { NavigationPrimitives } from './strategies/columns';
189
179
  /**
190
180
  * Strategy to resolve column names (string or regex) to their index.
191
181
  */
@@ -220,8 +210,6 @@ export interface TableStrategies {
220
210
  header?: HeaderStrategy;
221
211
  /** Primitive navigation functions (goUp, goDown, goLeft, goRight, goHome) */
222
212
  navigation?: NavigationPrimitives;
223
- /** @deprecated Use navigation primitives instead. Strategy for navigating to specific cells (row + column) */
224
- cellNavigation?: CellNavigationStrategy;
225
213
  /** Strategy for filling form inputs */
226
214
  fill?: FillStrategy;
227
215
  /** Strategy for paginating through data */
@@ -250,15 +238,9 @@ export interface TableStrategies {
250
238
  /** Strategy for detecting loading states */
251
239
  loading?: LoadingStrategy;
252
240
  }
253
- /**
254
- * Configuration options for useTable.
255
- */
256
- /**
257
- * Configuration options for useTable.
258
- */
259
241
  export interface TableConfig<T = any> {
260
242
  /** Selector for the table headers */
261
- headerSelector?: string;
243
+ headerSelector?: string | ((root: Locator) => Locator);
262
244
  /** Selector for the table rows */
263
245
  rowSelector?: string;
264
246
  /** Selector for the cells within a row */
@@ -286,8 +268,8 @@ export interface TableConfig<T = any> {
286
268
  */
287
269
  dataMapper?: Partial<Record<keyof T, (cell: Locator) => Promise<T[keyof T]> | T[keyof T]>>;
288
270
  }
289
- export interface FinalTableConfigLike<T = any> extends TableConfig<T> {
290
- headerSelector: string;
271
+ export interface FinalTableConfig<T = any> extends TableConfig<T> {
272
+ headerSelector: string | ((root: Locator) => Locator);
291
273
  rowSelector: string;
292
274
  cellSelector: string;
293
275
  maxPages: number;
@@ -302,7 +284,6 @@ export interface FinalTableConfigLike<T = any> extends TableConfig<T> {
302
284
  onReset: (context: TableContext) => Promise<void>;
303
285
  strategies: TableStrategies;
304
286
  }
305
- export type FinalTableConfig<T = any> = FinalTableConfigLike<T>;
306
287
  export interface FillOptions {
307
288
  /**
308
289
  * Custom input mappers for specific columns.
@@ -381,16 +362,6 @@ export interface TableResult<T = any> {
381
362
  * Navigates to a specific column using the configured CellNavigationStrategy.
382
363
  */
383
364
  scrollToColumn: (columnName: string) => Promise<void>;
384
- /**
385
- * Gets all rows on the current page only (does not paginate).
386
- * Auto-initializes the table if not already initialized.
387
- * Returns a SmartRowArray which extends Array with a toJSON() helper method.
388
- * @param options - Filter options
389
- */
390
- getRows: (options?: {
391
- filter?: Record<string, any>;
392
- exact?: boolean;
393
- }) => Promise<SmartRowArray>;
394
365
  /**
395
366
  * Resets the table state (clears cache, flags) and invokes the onReset strategy.
396
367
  */
@@ -1,48 +1,6 @@
1
1
  import type { Locator } from '@playwright/test';
2
- import { TableConfig, TableContext, Selector, TableResult, SmartRow as SmartRowType, DedupeStrategy, PaginationStrategy } from './types';
3
- import { FillStrategies } from './strategies/fill';
4
- import { HeaderStrategies } from './strategies/headers';
5
- import { CellNavigationStrategies } from './strategies/columns';
6
- import { ResolutionStrategies } from './strategies/resolution';
7
- import { Strategies } from './strategies';
2
+ import { TableConfig, TableResult } from './types';
8
3
  /**
9
4
  * Main hook to interact with a table.
10
5
  */
11
6
  export declare const useTable: <T = any>(rootLocator: Locator, configOptions?: TableConfig<T>) => TableResult<T>;
12
- export declare const PaginationStrategies: {
13
- clickNext: (nextButtonSelector: Selector, options?: {
14
- stabilization?: import("./strategies/stabilization").StabilizationStrategy;
15
- timeout?: number;
16
- }) => PaginationStrategy;
17
- infiniteScroll: (options?: {
18
- action?: "scroll" | "js-scroll";
19
- scrollTarget?: Selector;
20
- scrollAmount?: number;
21
- stabilization?: import("./strategies/stabilization").StabilizationStrategy;
22
- timeout?: number;
23
- }) => PaginationStrategy;
24
- };
25
- export declare const LoadingStrategies: {
26
- Table: {
27
- hasSpinner: (selector?: string) => ({ root }: TableContext) => Promise<boolean>;
28
- custom: (fn: (context: TableContext) => Promise<boolean>) => (context: TableContext) => Promise<boolean>;
29
- never: () => Promise<boolean>;
30
- };
31
- Row: {
32
- hasClass: (className?: string) => (row: SmartRowType) => Promise<boolean>;
33
- hasText: (text?: string | RegExp) => (row: SmartRowType) => Promise<boolean>;
34
- hasEmptyCells: () => (row: SmartRowType) => Promise<boolean>;
35
- never: () => Promise<boolean>;
36
- };
37
- Headers: {
38
- stable: (duration?: number) => (context: TableContext) => Promise<boolean>;
39
- never: () => Promise<boolean>;
40
- };
41
- };
42
- export declare const SortingStrategies: {
43
- AriaSort: () => import("./types").SortingStrategy;
44
- };
45
- export declare const DedupeStrategies: {
46
- byTopPosition: (tolerance?: number) => DedupeStrategy;
47
- };
48
- export { FillStrategies, HeaderStrategies, CellNavigationStrategies, ResolutionStrategies, Strategies };
package/dist/useTable.js CHANGED
@@ -9,26 +9,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  });
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
- exports.Strategies = exports.ResolutionStrategies = exports.CellNavigationStrategies = exports.HeaderStrategies = exports.FillStrategies = exports.DedupeStrategies = exports.SortingStrategies = exports.LoadingStrategies = exports.PaginationStrategies = exports.useTable = void 0;
13
- const typeContext_1 = require("./typeContext");
14
- const sorting_1 = require("./strategies/sorting");
15
- const pagination_1 = require("./strategies/pagination");
16
- const dedupe_1 = require("./strategies/dedupe");
12
+ exports.useTable = void 0;
13
+ const minimalConfigContext_1 = require("./minimalConfigContext");
17
14
  const loading_1 = require("./strategies/loading");
18
15
  const fill_1 = require("./strategies/fill");
19
- Object.defineProperty(exports, "FillStrategies", { enumerable: true, get: function () { return fill_1.FillStrategies; } });
20
16
  const headers_1 = require("./strategies/headers");
21
- Object.defineProperty(exports, "HeaderStrategies", { enumerable: true, get: function () { return headers_1.HeaderStrategies; } });
22
- const columns_1 = require("./strategies/columns");
23
- Object.defineProperty(exports, "CellNavigationStrategies", { enumerable: true, get: function () { return columns_1.CellNavigationStrategies; } });
24
17
  const smartRow_1 = require("./smartRow");
25
18
  const filterEngine_1 = require("./filterEngine");
26
19
  const tableMapper_1 = require("./engine/tableMapper");
27
20
  const rowFinder_1 = require("./engine/rowFinder");
28
- const resolution_1 = require("./strategies/resolution");
29
- Object.defineProperty(exports, "ResolutionStrategies", { enumerable: true, get: function () { return resolution_1.ResolutionStrategies; } });
30
- const strategies_1 = require("./strategies");
31
- Object.defineProperty(exports, "Strategies", { enumerable: true, get: function () { return strategies_1.Strategies; } });
32
21
  const debugUtils_1 = require("./utils/debugUtils");
33
22
  const smartRowArray_1 = require("./utils/smartRowArray");
34
23
  /**
@@ -42,7 +31,6 @@ const useTable = (rootLocator, configOptions = {}) => {
42
31
  const defaultStrategies = {
43
32
  fill: fill_1.FillStrategies.default,
44
33
  header: headers_1.HeaderStrategies.visible,
45
- cellNavigation: columns_1.CellNavigationStrategies.default,
46
34
  pagination: () => __awaiter(void 0, void 0, void 0, function* () { return false; }),
47
35
  loading: {
48
36
  isHeaderLoading: loading_1.LoadingStrategies.Headers.stable(200)
@@ -117,7 +105,7 @@ const useTable = (rootLocator, configOptions = {}) => {
117
105
  const { output = 'console', includeTypes = true } = options;
118
106
  let finalPrompt = content;
119
107
  if (includeTypes) {
120
- finalPrompt += `\n\nšŸ‘‡ Useful TypeScript Definitions šŸ‘‡\n\`\`\`typescript\n${typeContext_1.TYPE_CONTEXT}\n\`\`\`\n`;
108
+ finalPrompt += `\n\nšŸ‘‡ Useful TypeScript Definitions šŸ‘‡\n\`\`\`typescript\n${minimalConfigContext_1.MINIMAL_CONFIG_CONTEXT}\n\`\`\`\n`;
121
109
  }
122
110
  if (output === 'error') {
123
111
  console.log(`āš ļø Throwing error to display [${promptName}] cleanly...`);
@@ -144,14 +132,9 @@ const useTable = (rootLocator, configOptions = {}) => {
144
132
  const idx = map.get(columnName);
145
133
  if (idx === undefined)
146
134
  throw _createColumnError(columnName, map);
147
- yield config.strategies.cellNavigation({
148
- config: config,
149
- root: rootLocator,
150
- page: rootLocator.page(),
151
- resolve,
152
- column: columnName,
153
- index: idx
154
- });
135
+ // Use header cell for scrolling
136
+ const headerCell = resolve(config.headerSelector, rootLocator).nth(idx);
137
+ yield headerCell.scrollIntoViewIfNeeded();
155
138
  }),
156
139
  getHeaders: () => __awaiter(void 0, void 0, void 0, function* () {
157
140
  const map = yield tableMapper.getMap();
@@ -228,11 +211,6 @@ const useTable = (rootLocator, configOptions = {}) => {
228
211
  // @ts-ignore
229
212
  return rowFinder.findRow(filters, options);
230
213
  }),
231
- getRows: (options) => __awaiter(void 0, void 0, void 0, function* () {
232
- console.warn('DEPRECATED: table.getRows() is deprecated and will be removed in a future version. Use table.findRows() instead.');
233
- // @ts-ignore
234
- return rowFinder.findRows((options === null || options === void 0 ? void 0 : options.filter) || {}, Object.assign(Object.assign({}, options), { maxPages: 1 }));
235
- }),
236
214
  findRows: (filters, options) => __awaiter(void 0, void 0, void 0, function* () {
237
215
  return rowFinder.findRows(filters, options);
238
216
  }),
@@ -273,7 +251,6 @@ const useTable = (rootLocator, configOptions = {}) => {
273
251
  getRow: result.getRow,
274
252
  getRowByIndex: result.getRowByIndex,
275
253
  findRow: result.findRow,
276
- getRows: result.getRows,
277
254
  findRows: result.findRows,
278
255
  getColumnValues: result.getColumnValues,
279
256
  isInitialized: result.isInitialized,
@@ -438,7 +415,3 @@ const useTable = (rootLocator, configOptions = {}) => {
438
415
  return result;
439
416
  };
440
417
  exports.useTable = useTable;
441
- exports.PaginationStrategies = Object.assign({}, pagination_1.PaginationStrategies);
442
- exports.LoadingStrategies = loading_1.LoadingStrategies;
443
- exports.SortingStrategies = sorting_1.SortingStrategies;
444
- exports.DedupeStrategies = dedupe_1.DedupeStrategies;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rickcedwhat/playwright-smart-table",
3
- "version": "6.3.1",
3
+ "version": "6.4.0",
4
4
  "description": "Smart, column-aware table interactions for Playwright",
5
5
  "author": "Cedrick Catalan",
6
6
  "license": "MIT",
@@ -15,12 +15,13 @@
15
15
  ],
16
16
  "scripts": {
17
17
  "generate-types": "node scripts/embed-types.mjs",
18
+ "generate-config-types": "node scripts/embed-config-types.mjs",
18
19
  "generate-docs": "node scripts/generate-readme.mjs",
19
20
  "generate-all-api-docs": "node scripts/generate-all-api-docs.mjs",
20
21
  "update-all-api-signatures": "node scripts/update-all-api-signatures.mjs",
21
22
  "docs:dev": "vitepress dev docs",
22
23
  "docs:build": "vitepress build docs",
23
- "build": "npm run generate-types && npm run generate-docs && npm run generate-all-api-docs && npm run update-all-api-signatures && tsc",
24
+ "build": "npm run generate-types && npm run generate-config-types && npm run generate-docs && npm run generate-all-api-docs && npm run update-all-api-signatures && tsc",
24
25
  "prepublishOnly": "npm run build",
25
26
  "test": "npm run test:unit && npx playwright test",
26
27
  "test:unit": "vitest run --reporter=verbose --reporter=html",