@rickcedwhat/playwright-smart-table 6.15.0 → 6.16.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.
@@ -3,6 +3,7 @@ import { FinalTableConfig, Selector, SmartRow, FilterValue } from '../types';
3
3
  import { FilterEngine } from '../filterEngine';
4
4
  import { TableMapper } from './tableMapper';
5
5
  import { SmartRowArray } from '../utils/smartRowArray';
6
+ import { NavigationBarrier } from '../utils/navigationBarrier';
6
7
  export declare class RowFinder<T = any> {
7
8
  private rootLocator;
8
9
  private config;
@@ -10,10 +11,11 @@ export declare class RowFinder<T = any> {
10
11
  private tableMapper;
11
12
  private makeSmartRow;
12
13
  private tableState;
14
+ private advancePage;
13
15
  private resolve;
14
- constructor(rootLocator: Locator, config: FinalTableConfig, resolve: (item: Selector, parent: Locator | Page) => Locator, filterEngine: FilterEngine, tableMapper: TableMapper, makeSmartRow: (loc: Locator, map: Map<string, number>, index: number | undefined, tablePageIndex?: number) => SmartRow<T>, tableState?: {
16
+ constructor(rootLocator: Locator, config: FinalTableConfig, resolve: (item: Selector, parent: Locator | Page) => Locator, filterEngine: FilterEngine, tableMapper: TableMapper, makeSmartRow: (loc: Locator, map: Map<string, number>, index: number | undefined, tablePageIndex?: number, barrier?: NavigationBarrier) => SmartRow<T>, tableState?: {
15
17
  currentPageIndex: number;
16
- });
18
+ }, advancePage?: (useBulk: boolean) => Promise<boolean>);
17
19
  findRow(filters: Record<string, FilterValue>, options?: {
18
20
  exact?: boolean;
19
21
  maxPages?: number;
@@ -3,17 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RowFinder = void 0;
4
4
  const debugUtils_1 = require("../utils/debugUtils");
5
5
  const smartRowArray_1 = require("../utils/smartRowArray");
6
- const validation_1 = require("../strategies/validation");
7
6
  const elementTracker_1 = require("../utils/elementTracker");
8
7
  const sentinel_1 = require("../utils/sentinel");
8
+ const navigationBarrier_1 = require("../utils/navigationBarrier");
9
9
  class RowFinder {
10
- constructor(rootLocator, config, resolve, filterEngine, tableMapper, makeSmartRow, tableState = { currentPageIndex: 0 }) {
10
+ constructor(rootLocator, config, resolve, filterEngine, tableMapper, makeSmartRow, tableState = { currentPageIndex: 0 }, advancePage = async () => false) {
11
11
  this.rootLocator = rootLocator;
12
12
  this.config = config;
13
13
  this.filterEngine = filterEngine;
14
14
  this.tableMapper = tableMapper;
15
15
  this.makeSmartRow = makeSmartRow;
16
16
  this.tableState = tableState;
17
+ this.advancePage = advancePage;
17
18
  this.resolve = resolve;
18
19
  }
19
20
  async findRow(filters, options = {}) {
@@ -31,12 +32,12 @@ class RowFinder {
31
32
  await (0, debugUtils_1.debugDelay)(this.config, 'findRow');
32
33
  const sentinel = this.resolve(this.config.rowSelector, this.rootLocator)
33
34
  .filter({ hasText: "___SENTINEL_ROW_NOT_FOUND___" + Date.now() });
34
- const smartRow = this.makeSmartRow(sentinel, await this.tableMapper.getMap(), 0);
35
+ const smartRow = this.makeSmartRow(sentinel, await this.tableMapper.getMap(), undefined);
35
36
  smartRow[sentinel_1.SENTINEL_ROW] = true;
36
37
  return smartRow;
37
38
  }
38
39
  async findRows(filters = {}, options) {
39
- var _a, _b, _c, _d;
40
+ var _a, _b, _c;
40
41
  const filtersRecord = filters;
41
42
  const map = await this.tableMapper.getMap();
42
43
  const allRows = [];
@@ -64,12 +65,16 @@ class RowFinder {
64
65
  : undefined;
65
66
  const onRowLoadingTimeout = (_e = (_d = this.config.strategies.loading) === null || _d === void 0 ? void 0 : _d.onRowLoadingTimeout) !== null && _e !== void 0 ? _e : 'read-as-is';
66
67
  let added = 0;
68
+ // One barrier per batch — synchronizes cell navigation across all rows in this page's results
69
+ const useBarrier = this.config.concurrency === 'synchronized' && newIndices.length > 1;
70
+ const barrier = useBarrier ? new navigationBarrier_1.NavigationBarrier(newIndices.length) : undefined;
67
71
  for (const idx of newIndices) {
68
- const smartRow = this.makeSmartRow(currentRows[idx], map, allRows.length, this.tableState.currentPageIndex);
72
+ const smartRow = this.makeSmartRow(currentRows[idx], map, allRows.length, this.tableState.currentPageIndex, barrier);
69
73
  if (isRowLoading && await isRowLoading(smartRow)) {
70
74
  if (rowLoadingTimeout === undefined) {
71
75
  // No timeout configured (or invalid value) — legacy skip behavior
72
76
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRows: page ${this.tableState.currentPageIndex} — row skipped (isRowLoading=true, no timeout)`);
77
+ barrier === null || barrier === void 0 ? void 0 : barrier.markFinished();
73
78
  continue;
74
79
  }
75
80
  // Wait up to rowLoadingTimeout ms (0 = one immediate re-check, no polling)
@@ -82,9 +87,12 @@ class RowFinder {
82
87
  }
83
88
  if (!resolved) {
84
89
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRows: row ${allRows.length} — still loading after ${rowLoadingTimeout}ms, action: ${onRowLoadingTimeout}`);
85
- if (onRowLoadingTimeout === 'skip')
90
+ if (onRowLoadingTimeout === 'skip') {
91
+ barrier === null || barrier === void 0 ? void 0 : barrier.markFinished();
86
92
  continue;
93
+ }
87
94
  if (onRowLoadingTimeout === 'throw') {
95
+ barrier === null || barrier === void 0 ? void 0 : barrier.markFinished();
88
96
  throw new Error(`[SmartTable] Row ${allRows.length} did not finish loading within ${rowLoadingTimeout}ms`);
89
97
  }
90
98
  // 'read-as-is': fall through and add the row
@@ -102,31 +110,14 @@ class RowFinder {
102
110
  await collectMatches();
103
111
  // Pagination Loop
104
112
  while (pagesScanned < effectiveMaxPages && this.config.strategies.pagination) {
105
- const context = {
106
- root: this.rootLocator,
107
- config: this.config,
108
- resolve: this.resolve,
109
- page: this.rootLocator.page()
110
- };
111
- let paginationResult;
112
113
  const useBulk = (options === null || options === void 0 ? void 0 : options.useBulkPagination) !== false && !!((_c = this.config.strategies.pagination) === null || _c === void 0 ? void 0 : _c.goNextBulk);
113
- if (useBulk) {
114
- paginationResult = await this.config.strategies.pagination.goNextBulk(context);
115
- }
116
- else if ((_d = this.config.strategies.pagination) === null || _d === void 0 ? void 0 : _d.goNext) {
117
- paginationResult = await this.config.strategies.pagination.goNext(context);
118
- }
119
- else {
120
- (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRows: no pagination primitive — stopping`);
121
- break;
122
- }
123
- const didPaginate = (0, validation_1.validatePaginationResult)(paginationResult, 'Pagination Strategy');
114
+ const prevPage = this.tableState.currentPageIndex;
115
+ const didPaginate = await this.advancePage(useBulk);
124
116
  if (!didPaginate) {
125
117
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRows: pagination returned false — end of data`);
126
118
  break;
127
119
  }
128
- const pagesJumped = typeof paginationResult === 'number' ? paginationResult : 1;
129
- this.tableState.currentPageIndex += pagesJumped;
120
+ const pagesJumped = this.tableState.currentPageIndex - prevPage;
130
121
  pagesScanned += pagesJumped;
131
122
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRows: advanced ${pagesJumped} page(s), now at page ${this.tableState.currentPageIndex}`);
132
123
  await (0, debugUtils_1.debugDelay)(this.config, 'pagination');
@@ -140,7 +131,7 @@ class RowFinder {
140
131
  return (0, smartRowArray_1.createSmartRowArray)(allRows);
141
132
  }
142
133
  async findRowLocator(filters, options = {}) {
143
- var _a, _b;
134
+ var _a, _b, _c;
144
135
  const map = await this.tableMapper.getMap();
145
136
  const effectiveMaxPages = (_a = options.maxPages) !== null && _a !== void 0 ? _a : this.config.maxPages;
146
137
  let pagesScanned = 1;
@@ -183,29 +174,11 @@ class RowFinder {
183
174
  return matchedRows.first();
184
175
  if (pagesScanned < effectiveMaxPages) {
185
176
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `Page ${this.tableState.currentPageIndex}: Not found. Attempting pagination...`);
186
- const context = {
187
- root: this.rootLocator,
188
- config: this.config,
189
- resolve: this.resolve,
190
- page: this.rootLocator.page()
191
- };
192
- let paginationResult;
193
- const pagination = this.config.strategies.pagination;
194
- const useBulk = options.useBulkPagination !== false && !!(pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk);
195
- if (useBulk && (pagination === null || pagination === void 0 ? void 0 : pagination.goNextBulk)) {
196
- paginationResult = await pagination.goNextBulk(context);
197
- }
198
- else if (pagination === null || pagination === void 0 ? void 0 : pagination.goNext) {
199
- paginationResult = await pagination.goNext(context);
200
- }
201
- else {
202
- (0, debugUtils_1.logDebug)(this.config, 'verbose', `Page ${this.tableState.currentPageIndex}: Pagination failed (no goNext or goNextBulk primitive).`);
203
- return null;
204
- }
205
- const didLoadMore = (0, validation_1.validatePaginationResult)(paginationResult, 'Pagination Strategy');
177
+ const useBulk = options.useBulkPagination !== false && !!((_c = this.config.strategies.pagination) === null || _c === void 0 ? void 0 : _c.goNextBulk);
178
+ const prevPage = this.tableState.currentPageIndex;
179
+ const didLoadMore = await this.advancePage(useBulk);
206
180
  if (didLoadMore) {
207
- const pagesJumped = typeof paginationResult === 'number' ? paginationResult : 1;
208
- this.tableState.currentPageIndex += pagesJumped;
181
+ const pagesJumped = this.tableState.currentPageIndex - prevPage;
209
182
  pagesScanned += pagesJumped;
210
183
  (0, debugUtils_1.logDebug)(this.config, 'verbose', `findRowLocator: advanced ${pagesJumped} page(s), now at page ${this.tableState.currentPageIndex}`);
211
184
  await (0, debugUtils_1.debugDelay)(this.config, 'pagination');
@@ -3,4 +3,4 @@
3
3
  * Generated by scripts/embed-version.mjs from package.json
4
4
  */
5
5
  /** Semver of this package. Use in logs or diagnostics to confirm the installed build. */
6
- export declare const PLAYWRIGHT_SMART_TABLE_VERSION: "6.15.0";
6
+ export declare const PLAYWRIGHT_SMART_TABLE_VERSION: "6.16.0";
@@ -6,4 +6,4 @@ exports.PLAYWRIGHT_SMART_TABLE_VERSION = void 0;
6
6
  * Generated by scripts/embed-version.mjs from package.json
7
7
  */
8
8
  /** Semver of this package. Use in logs or diagnostics to confirm the installed build. */
9
- exports.PLAYWRIGHT_SMART_TABLE_VERSION = "6.15.0";
9
+ exports.PLAYWRIGHT_SMART_TABLE_VERSION = "6.16.0";
@@ -36,3 +36,4 @@ export declare function createGlide(options?: GlideOptions): Partial<TableConfig
36
36
  export declare const Glide: Partial<TableConfig> & {
37
37
  Strategies: typeof GlideStrategies;
38
38
  };
39
+ export { Glide as glide };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Glide = exports.GlideStrategies = exports.createGlideViewport = void 0;
3
+ exports.glide = exports.Glide = exports.GlideStrategies = exports.createGlideViewport = void 0;
4
4
  exports.createGlide = createGlide;
5
5
  const headers_1 = require("./headers");
6
6
  const pagination_1 = require("../../strategies/pagination");
@@ -75,9 +75,15 @@ const glideGetActiveCell = async ({ page }) => {
75
75
  let rowIndex = -1;
76
76
  let columnIndex = -1;
77
77
  if (parts.length >= 4 && parts[0] === 'glide' && parts[1] === 'cell') {
78
- columnIndex = parseInt(parts[2]) - 1;
78
+ columnIndex = parseInt(parts[2]); // 0-based in Glide's id format: glide-cell-{col}-{row}
79
79
  rowIndex = parseInt(parts[3]);
80
80
  }
81
+ else if (id !== '') {
82
+ throw new Error(`Glide preset: focused element has id "${id}" which does not match the expected format "glide-cell-{colIndex}-{rowIndex}". ` +
83
+ `Glide may have changed its internal id format. Please open an issue at https://github.com/rickcedwhat/playwright-smart-table/issues.`);
84
+ }
85
+ if (rowIndex === -1 || columnIndex === -1)
86
+ return null;
81
87
  return {
82
88
  rowIndex,
83
89
  columnIndex,
@@ -129,3 +135,4 @@ const GlidePreset = {
129
135
  strategies: GlideDefaultStrategies
130
136
  };
131
137
  exports.Glide = Object.defineProperty(GlidePreset, 'Strategies', { get: () => exports.GlideStrategies, enumerable: false });
138
+ exports.glide = exports.Glide;
@@ -1,4 +1,4 @@
1
1
  export { muiTable, muiDataGrid } from './mui';
2
- export { RDG as rdg } from './rdg';
2
+ export { RDG as rdg, RDG2D as rdg2D } from './rdg';
3
3
  export { Glide as glide, createGlide, createGlideViewport } from './glide';
4
4
  export type { GlideOptions, GlideViewportOptions } from './glide';
@@ -1,11 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.createGlideViewport = exports.createGlide = exports.glide = exports.rdg = exports.muiDataGrid = exports.muiTable = void 0;
3
+ exports.createGlideViewport = exports.createGlide = exports.glide = exports.rdg2D = exports.rdg = exports.muiDataGrid = exports.muiTable = void 0;
4
4
  var mui_1 = require("./mui");
5
5
  Object.defineProperty(exports, "muiTable", { enumerable: true, get: function () { return mui_1.muiTable; } });
6
6
  Object.defineProperty(exports, "muiDataGrid", { enumerable: true, get: function () { return mui_1.muiDataGrid; } });
7
7
  var rdg_1 = require("./rdg");
8
8
  Object.defineProperty(exports, "rdg", { enumerable: true, get: function () { return rdg_1.RDG; } });
9
+ Object.defineProperty(exports, "rdg2D", { enumerable: true, get: function () { return rdg_1.RDG2D; } });
9
10
  var glide_1 = require("./glide");
10
11
  Object.defineProperty(exports, "glide", { enumerable: true, get: function () { return glide_1.Glide; } });
11
12
  Object.defineProperty(exports, "createGlide", { enumerable: true, get: function () { return glide_1.createGlide; } });
@@ -237,8 +237,6 @@ exports.muiDataGrid = {
237
237
  else {
238
238
  await header.click({ force: true });
239
239
  }
240
- // Sorting can trigger large re-renders/virtualization shifts
241
- await context.page.waitForTimeout(500);
242
240
  // Wait for stabilization (using DataGrid specific overlay check inside helper)
243
241
  const displayedRows = context.root.locator('.MuiTablePagination-displayedRows');
244
242
  const text = await displayedRows.innerText().catch(() => '');
@@ -1,4 +1,4 @@
1
- import { TableContext, TableConfig } from '../types';
1
+ import { TableContext, TableConfig, ViewportStrategy } from '../types';
2
2
  /** Full strategies for React Data Grid. Use when you want to supply your own selectors: strategies: Plugins.RDG.Strategies */
3
3
  export declare const RDGStrategies: {
4
4
  header: (context: TableContext) => Promise<string[]>;
@@ -15,3 +15,20 @@ export declare const RDGStrategies: {
15
15
  export declare const RDG: Partial<TableConfig> & {
16
16
  Strategies: typeof RDGStrategies;
17
17
  };
18
+ export declare const RDG2DStrategies: {
19
+ viewport: ViewportStrategy;
20
+ header: (context: TableContext) => Promise<string[]>;
21
+ getCellLocator: ({ row, columnIndex }: any) => any;
22
+ navigation: {
23
+ goRight: ({ root, page }: any) => Promise<void>;
24
+ goLeft: ({ root, page }: any) => Promise<void>;
25
+ goDown: ({ root, page }: any) => Promise<void>;
26
+ goUp: ({ root, page }: any) => Promise<void>;
27
+ goHome: ({ root, page }: any) => Promise<void>;
28
+ };
29
+ pagination: import("..").PaginationPrimitives;
30
+ };
31
+ export declare const RDG2D: Partial<TableConfig> & {
32
+ Strategies: typeof RDG2DStrategies;
33
+ };
34
+ export { RDG as rdg, RDG2D as rdg2D };
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.RDG = exports.RDGStrategies = void 0;
3
+ exports.rdg2D = exports.rdg = exports.RDG2D = exports.RDG2DStrategies = exports.RDG = exports.RDGStrategies = void 0;
4
4
  const pagination_1 = require("../strategies/pagination");
5
5
  const stabilization_1 = require("../strategies/stabilization");
6
6
  /**
@@ -114,3 +114,74 @@ const RDGPreset = {
114
114
  strategies: RDGDefaultStrategies
115
115
  };
116
116
  exports.RDG = Object.defineProperty(RDGPreset, 'Strategies', { get: () => exports.RDGStrategies, enumerable: false });
117
+ exports.rdg = exports.RDG;
118
+ // ---------------------------------------------------------------------------
119
+ // rdg2D — React Data Grid with both rows AND columns virtualized
120
+ // ---------------------------------------------------------------------------
121
+ const rdg2DViewportStrategy = {
122
+ getVisibleRowRange: async ({ root }) => {
123
+ return root.evaluate((el) => {
124
+ const rows = [...el.querySelectorAll('[role="row"][aria-rowindex]')];
125
+ const indices = rows.map(r => parseInt(r.getAttribute('aria-rowindex') || '0', 10) - 1);
126
+ if (!indices.length)
127
+ return { first: 0, last: 0 };
128
+ return { first: Math.min(...indices), last: Math.max(...indices) };
129
+ });
130
+ },
131
+ getVisibleColumnRange: async ({ root }) => {
132
+ return root.evaluate((el) => {
133
+ const cells = [...el.querySelectorAll('[role="gridcell"][aria-colindex]')];
134
+ const indices = cells.map(c => parseInt(c.getAttribute('aria-colindex') || '0', 10) - 1);
135
+ if (!indices.length)
136
+ return { first: 0, last: 0 };
137
+ return { first: Math.min(...indices), last: Math.max(...indices) };
138
+ });
139
+ },
140
+ scrollToRow: async ({ root }, rowIndex) => {
141
+ await root.evaluate((el, rowIndex) => {
142
+ const grid = (el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el);
143
+ // Try to locate the target row by aria-rowindex (1-based in RDG)
144
+ const ariaIndex = rowIndex + 1;
145
+ const targetRow = el.querySelector(`[role="row"][aria-rowindex="${ariaIndex}"]`);
146
+ if (targetRow) {
147
+ const top = parseInt(targetRow.style.top || '0', 10);
148
+ grid.scrollTop = Math.max(0, top - grid.clientHeight / 3);
149
+ return;
150
+ }
151
+ // Row not in DOM — estimate position from an actual visible row's height
152
+ const anyRow = el.querySelector('[role="row"][aria-rowindex]');
153
+ const rowHeight = anyRow ? anyRow.getBoundingClientRect().height || 35 : 35;
154
+ grid.scrollTop = Math.max(0, rowIndex * rowHeight - grid.clientHeight / 3);
155
+ }, rowIndex);
156
+ },
157
+ scrollToColumn: async ({ root }, columnIndex) => {
158
+ await root.evaluate((el, columnIndex) => {
159
+ const grid = (el.querySelector('[role="grid"]') || el.closest('[role="grid"]') || el);
160
+ // Try to locate the header cell by aria-colindex (1-based in RDG)
161
+ const ariaIndex = columnIndex + 1;
162
+ const header = el.querySelector(`[role="columnheader"][aria-colindex="${ariaIndex}"]`);
163
+ if (header) {
164
+ grid.scrollLeft = header.offsetLeft;
165
+ return;
166
+ }
167
+ // Column not visible — estimate from average width of visible headers
168
+ const headers = [...el.querySelectorAll('[role="columnheader"][aria-colindex]')];
169
+ if (headers.length > 0) {
170
+ const avgWidth = headers.reduce((sum, h) => sum + h.offsetWidth, 0) / headers.length;
171
+ grid.scrollLeft = Math.max(0, columnIndex * avgWidth);
172
+ }
173
+ }, columnIndex);
174
+ },
175
+ };
176
+ /** Default strategies for the RDG2D preset (extends RDG with viewport recovery). */
177
+ const RDG2DDefaultStrategies = Object.assign(Object.assign({}, RDGDefaultStrategies), { viewport: rdg2DViewportStrategy });
178
+ // fallow-ignore-next-line unused-export
179
+ exports.RDG2DStrategies = RDG2DDefaultStrategies;
180
+ /**
181
+ * Full preset for React Data Grid with 2D virtualization (rows + columns both virtualized).
182
+ * Use instead of `rdg` when horizontal scrolling causes "could not reach cell" errors.
183
+ * The viewport strategy detects when a row is evicted by a horizontal scroll and restores it.
184
+ */
185
+ const RDG2DPreset = Object.assign(Object.assign({}, RDGPreset), { strategies: RDG2DDefaultStrategies });
186
+ exports.RDG2D = Object.defineProperty(RDG2DPreset, 'Strategies', { get: () => exports.RDG2DStrategies, enumerable: false });
187
+ exports.rdg2D = exports.RDG2D;
package/dist/smartRow.js CHANGED
@@ -304,7 +304,8 @@ const _navigateToCell = async (params) => {
304
304
  else {
305
305
  navResult = await navigateUntilReached();
306
306
  }
307
- if (navResult instanceof Object && navResult._isLocator) {
307
+ // navigateUntilReached may return a Locator it found mid-navigation; duck-type check via .count() (public API) rather than the internal _isLocator flag
308
+ if (navResult && typeof navResult.count === 'function') {
308
309
  const loc = navResult;
309
310
  if (await loc.count() > 0)
310
311
  return loc;
package/dist/useTable.js CHANGED
@@ -100,8 +100,6 @@ const useTable = (rootLocator, configOptions = {}) => {
100
100
  return item(parent);
101
101
  return item;
102
102
  };
103
- // Internal State
104
- let _hasPaginated = false;
105
103
  // Helpers
106
104
  const log = (msg) => {
107
105
  (0, debugUtils_1.logDebug)(config, 'verbose', msg);
@@ -135,7 +133,7 @@ const useTable = (rootLocator, configOptions = {}) => {
135
133
  return (0, smartRow_1.default)(rowLocator, map, rowIndex, config, rootLocator, resolve, finalTable, tablePageIndex, barrier);
136
134
  };
137
135
  const tableState = { currentPageIndex: 0 };
138
- const rowFinder = new rowFinder_1.RowFinder(rootLocator, config, resolve, filterEngine, tableMapper, _makeSmart, tableState);
136
+ const rowFinder = new rowFinder_1.RowFinder(rootLocator, config, resolve, filterEngine, tableMapper, _makeSmart, tableState, (useBulk) => _advancePage(useBulk));
139
137
  /** Builds a full TableContext/StrategyContext with getHeaderCell, getHeaders, scrollToColumn. Set after result is created. */
140
138
  let createStrategyContext = () => ({ root: rootLocator, config, page: rootLocator.page(), resolve });
141
139
  const _getCleanHtml = async (loc) => {
@@ -326,7 +324,6 @@ const useTable = (rootLocator, configOptions = {}) => {
326
324
  else if (hasPaginationInConfig) {
327
325
  log("No goToFirst strategy configured. Table may not be on page 1.");
328
326
  }
329
- _hasPaginated = false;
330
327
  tableState.currentPageIndex = 0;
331
328
  tableMapper.clear();
332
329
  log("Table reset complete. Calling autoInit to restore state.");
@@ -490,7 +487,11 @@ const useTable = (rootLocator, configOptions = {}) => {
490
487
  log("Generating table config prompt...");
491
488
  const html = await _getCleanHtml(rootLocator);
492
489
  const separator = "=".repeat(50);
493
- const content = `\n${separator} \n🤖 COPY INTO GEMINI / ChatGPT 🤖\n${separator} \nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()} \nGenerate config for: \n\`\`\`html\n${html.substring(0, 10000)} ...\n\`\`\`\n${separator}\n`;
490
+ const maxLen = 10000;
491
+ const truncated = html.length > maxLen;
492
+ const htmlSnippet = truncated ? html.substring(0, maxLen) : html;
493
+ const truncationNote = truncated ? `\n[truncated — ${html.length} chars total, showing first ${maxLen}]` : '';
494
+ const content = `\n${separator} \n🤖 Paste into your AI assistant 🤖\n${separator} \nI am using 'playwright-smart-table'.\nTarget Table Locator: ${rootLocator.toString()} \nGenerate config for: \n\`\`\`html\n${htmlSnippet}${truncationNote}\n\`\`\`\n${separator}\n`;
494
495
  await _handlePrompt('Smart Table Config', content);
495
496
  },
496
497
  generateConfigPrompt: async () => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rickcedwhat/playwright-smart-table",
3
- "version": "6.15.0",
3
+ "version": "6.16.0",
4
4
  "description": "Smart, column-aware table interactions for Playwright",
5
5
  "author": "Cedrick Catalan",
6
6
  "license": "MIT",
@@ -64,6 +64,23 @@
64
64
  "./presets/mui": {
65
65
  "types": "./dist/presets/mui.d.ts",
66
66
  "default": "./dist/presets/mui.js"
67
+ },
68
+ "./presets/rdg": {
69
+ "types": "./dist/presets/rdg.d.ts",
70
+ "default": "./dist/presets/rdg.js"
71
+ },
72
+ "./presets/glide": {
73
+ "types": "./dist/presets/glide/index.d.ts",
74
+ "default": "./dist/presets/glide/index.js"
75
+ }
76
+ },
77
+ "typesVersions": {
78
+ "*": {
79
+ "types": ["./dist/types.d.ts"],
80
+ "presets": ["./dist/presets/index.d.ts"],
81
+ "presets/mui": ["./dist/presets/mui.d.ts"],
82
+ "presets/rdg": ["./dist/presets/rdg.d.ts"],
83
+ "presets/glide": ["./dist/presets/glide/index.d.ts"]
67
84
  }
68
85
  },
69
86
  "keywords": [