@katlux/providers 0.1.1-alpha.103 → 0.1.1-alpha.104

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.cjs CHANGED
@@ -274,6 +274,8 @@ class ADataProvider {
274
274
  this.setSortList(s);
275
275
  }
276
276
  _listeners = /* @__PURE__ */ new Set();
277
+ _stateListeners = /* @__PURE__ */ new Set();
278
+ _pendingChangedKeys = /* @__PURE__ */ new Set();
277
279
  _debouncedFilterLoad;
278
280
  _debouncedSortLoad;
279
281
  constructor(options) {
@@ -333,6 +335,10 @@ class ADataProvider {
333
335
  this.subscribe = this.subscribe.bind(this);
334
336
  this.batchUpdates = this.batchUpdates.bind(this);
335
337
  this.getState = this.getState.bind(this);
338
+ this.setState = this.setState.bind(this);
339
+ this.onStateChange = this.onStateChange.bind(this);
340
+ this.serializeState = this.serializeState.bind(this);
341
+ this.deserializeState = this.deserializeState.bind(this);
336
342
  this.cancelPending = this.cancelPending.bind(this);
337
343
  }
338
344
  _batchDepth = 0;
@@ -389,6 +395,20 @@ class ADataProvider {
389
395
  console.error("[Katlux Providers] Listener error:", e);
390
396
  }
391
397
  });
398
+ if (this._stateListeners.size > 0) {
399
+ const state = this.getState();
400
+ const changed = Array.from(this._pendingChangedKeys);
401
+ this._pendingChangedKeys.clear();
402
+ this._stateListeners.forEach((listener) => {
403
+ try {
404
+ listener(state, changed);
405
+ } catch (e) {
406
+ console.error("[Katlux Providers] State listener error:", e);
407
+ }
408
+ });
409
+ } else {
410
+ this._pendingChangedKeys.clear();
411
+ }
392
412
  } finally {
393
413
  this._isNotifying = false;
394
414
  if (this._pendingNotify && this._batchDepth === 0) {
@@ -397,6 +417,10 @@ class ADataProvider {
397
417
  }
398
418
  }
399
419
  }
420
+ onStateChange(listener) {
421
+ this._stateListeners.add(listener);
422
+ return () => this._stateListeners.delete(listener);
423
+ }
400
424
  getState() {
401
425
  return {
402
426
  pageData: this.pageData,
@@ -412,9 +436,84 @@ class ADataProvider {
412
436
  selectAll: this.selectAll
413
437
  };
414
438
  }
439
+ onFilterUpdated() {
440
+ }
441
+ onSortUpdated() {
442
+ }
443
+ setState(partial, options) {
444
+ this.batchUpdates(() => {
445
+ let needsLoad = false;
446
+ if (partial.pageSize !== void 0 && partial.pageSize !== this._pageSize) {
447
+ this._pageSize = partial.pageSize;
448
+ this._pendingChangedKeys.add("pageSize");
449
+ needsLoad = true;
450
+ }
451
+ if (partial.filter !== void 0 && JSON.stringify(partial.filter) !== JSON.stringify(this._filter)) {
452
+ this._filter = partial.filter;
453
+ this.onFilterUpdated();
454
+ this._pendingChangedKeys.add("filter");
455
+ needsLoad = true;
456
+ }
457
+ if (partial.sortList !== void 0 && JSON.stringify(partial.sortList) !== JSON.stringify(this._sortList)) {
458
+ this._sortList = partial.sortList;
459
+ this.onSortUpdated();
460
+ this._pendingChangedKeys.add("sortList");
461
+ needsLoad = true;
462
+ }
463
+ if (partial.currentPage !== void 0 && partial.currentPage !== this._currentPage) {
464
+ this._currentPage = partial.currentPage;
465
+ this._pendingChangedKeys.add("currentPage");
466
+ needsLoad = true;
467
+ }
468
+ if (partial.selectedRows !== void 0) {
469
+ this._selectedRows = Array.isArray(partial.selectedRows) ? partial.selectedRows : [];
470
+ this._pendingChangedKeys.add("selectedRows");
471
+ }
472
+ if (partial.selectAll !== void 0 && partial.selectAll !== this._selectAll) {
473
+ this._selectAll = partial.selectAll;
474
+ this._pendingChangedKeys.add("selectAll");
475
+ }
476
+ if (needsLoad) {
477
+ if (options?.immediate) {
478
+ this.cancelPending();
479
+ }
480
+ this.loadPageData();
481
+ } else if (!options?.silent) {
482
+ this.notify();
483
+ }
484
+ });
485
+ }
486
+ serializeState() {
487
+ const state = {
488
+ currentPage: this._currentPage,
489
+ pageSize: this._pageSize,
490
+ filter: this._filter,
491
+ sortList: this._sortList,
492
+ selectAll: this._selectAll
493
+ };
494
+ return JSON.stringify(state);
495
+ }
496
+ deserializeState(serialized, options) {
497
+ if (!serialized) return;
498
+ let parsed;
499
+ if (typeof serialized === "string") {
500
+ try {
501
+ parsed = JSON.parse(serialized);
502
+ } catch (e) {
503
+ console.error("[Katlux Providers] Failed to deserialize provider state:", e);
504
+ return;
505
+ }
506
+ } else {
507
+ parsed = serialized;
508
+ }
509
+ this.setState(parsed, options);
510
+ }
415
511
  setFilter(filter, immediate = false) {
416
512
  this._filter = filter;
513
+ this.onFilterUpdated();
417
514
  this._currentPage = 1;
515
+ this._pendingChangedKeys.add("filter");
516
+ this._pendingChangedKeys.add("currentPage");
418
517
  if (immediate) {
419
518
  this._debouncedFilterLoad?.cancel?.();
420
519
  this.loadPageData();
@@ -424,7 +523,10 @@ class ADataProvider {
424
523
  }
425
524
  setSortList(sortList, immediate = false) {
426
525
  this._sortList = sortList;
526
+ this.onSortUpdated();
427
527
  this._currentPage = 1;
528
+ this._pendingChangedKeys.add("sortList");
529
+ this._pendingChangedKeys.add("currentPage");
428
530
  if (immediate) {
429
531
  this._debouncedSortLoad?.cancel?.();
430
532
  this.loadPageData();
@@ -435,6 +537,8 @@ class ADataProvider {
435
537
  setCurrentPage(currentPage) {
436
538
  this._currentPage = currentPage;
437
539
  this._selectAll = false;
540
+ this._pendingChangedKeys.add("currentPage");
541
+ this._pendingChangedKeys.add("selectAll");
438
542
  this.loadPageData();
439
543
  if (typeof window !== "undefined" && this.urlPageParam) {
440
544
  try {
@@ -457,14 +561,18 @@ class ADataProvider {
457
561
  setPageSize(pageSize) {
458
562
  this._pageSize = pageSize;
459
563
  this._currentPage = 1;
564
+ this._pendingChangedKeys.add("pageSize");
565
+ this._pendingChangedKeys.add("currentPage");
460
566
  this.loadPageData();
461
567
  this.notify();
462
568
  }
463
569
  setSelectedRows(rows) {
464
570
  this.selectedRows = rows;
571
+ this._pendingChangedKeys.add("selectedRows");
465
572
  }
466
573
  setSelectAll(val) {
467
574
  this.selectAll = val;
575
+ this._pendingChangedKeys.add("selectAll");
468
576
  }
469
577
  async refresh(hardRefresh = false) {
470
578
  await this.loadPageData({ disableCache: hardRefresh });
@@ -755,6 +863,13 @@ class CFlatClientDataProvider extends ADataProvider {
755
863
  this.allData = Array.isArray(data) ? data : [];
756
864
  this.loadPageData();
757
865
  }
866
+ onFilterUpdated() {
867
+ this._filterDirty = true;
868
+ this._sortDirty = true;
869
+ }
870
+ onSortUpdated() {
871
+ this._sortDirty = true;
872
+ }
758
873
  setFilter(filter, immediate = false) {
759
874
  this._filterDirty = true;
760
875
  this._sortDirty = true;
package/dist/index.d.cts CHANGED
@@ -154,6 +154,31 @@ interface IDataProviderOptions {
154
154
  filterDebounce?: number;
155
155
  sortDebounce?: number;
156
156
  }
157
+ interface IDataProviderState<TRow = TDataRow> {
158
+ currentPage: number;
159
+ pageSize: number;
160
+ filter: IDataFilter | null;
161
+ sortList: IDataSort[];
162
+ selectedRows: TRow[];
163
+ selectAll: boolean;
164
+ rowCount?: number;
165
+ loading?: boolean;
166
+ initialLoad?: boolean;
167
+ error?: any;
168
+ pageData?: TRow[];
169
+ }
170
+ interface IDataProviderSetStateOptions {
171
+ immediate?: boolean;
172
+ silent?: boolean;
173
+ }
174
+ type TDataProviderStateChangeListener<TRow = TDataRow> = (state: IDataProviderState<TRow>, changedKeys: Array<keyof IDataProviderState<TRow>>) => void;
175
+ interface IVirtualScrollState {
176
+ startIndex: number;
177
+ endIndex: number;
178
+ scrollTop: number;
179
+ totalItems: number;
180
+ itemHeight: number;
181
+ }
157
182
 
158
183
  interface ITreeNode<TRow = TDataRow> {
159
184
  data: TRow;
@@ -271,6 +296,8 @@ declare abstract class ADataProvider<TRow = TDataRow> {
271
296
  get sortList(): IDataSort[];
272
297
  set sortList(s: IDataSort[]);
273
298
  private _listeners;
299
+ private _stateListeners;
300
+ private _pendingChangedKeys;
274
301
  private _debouncedFilterLoad;
275
302
  private _debouncedSortLoad;
276
303
  constructor(options?: IDataProviderOptions);
@@ -283,19 +310,13 @@ declare abstract class ADataProvider<TRow = TDataRow> {
283
310
  batchUpdates<R>(fn: () => R): R;
284
311
  subscribe(listener: TDataProviderListener<this>): TUnsubscribe;
285
312
  notify(): void;
286
- getState(): {
287
- pageData: TRow[];
288
- rowCount: number;
289
- currentPage: number;
290
- pageSize: number;
291
- loading: boolean;
292
- initialLoad: boolean;
293
- error: any;
294
- filter: IDataFilter | null;
295
- sortList: IDataSort[];
296
- selectedRows: TRow[];
297
- selectAll: boolean;
298
- };
313
+ onStateChange(listener: TDataProviderStateChangeListener<TRow>): TUnsubscribe;
314
+ getState(): IDataProviderState<TRow>;
315
+ protected onFilterUpdated(): void;
316
+ protected onSortUpdated(): void;
317
+ setState(partial: Partial<IDataProviderState<TRow>>, options?: IDataProviderSetStateOptions): void;
318
+ serializeState(): string;
319
+ deserializeState(serialized: string | Partial<IDataProviderState<TRow>>, options?: IDataProviderSetStateOptions): void;
299
320
  setFilter(filter: IDataFilter | null, immediate?: boolean): void;
300
321
  setSortList(sortList: IDataSort[], immediate?: boolean): void;
301
322
  setCurrentPage(currentPage: number): void;
@@ -321,6 +342,8 @@ declare class CFlatClientDataProvider<TRow = TDataRow> extends ADataProvider<TRo
321
342
  set allData(data: TRow[]);
322
343
  get rowMap(): readonly TRow[];
323
344
  setData(data: TRow[]): void;
345
+ protected onFilterUpdated(): void;
346
+ protected onSortUpdated(): void;
324
347
  setFilter(filter: IDataFilter | null, immediate?: boolean): void;
325
348
  setSortList(sortList: IDataSort[], immediate?: boolean): void;
326
349
  /**
@@ -1088,4 +1111,4 @@ declare function getAppRouter(): any;
1088
1111
  declare function onPlatformReady(cb: () => void): void;
1089
1112
 
1090
1113
  export { AAPIDataProvider, ADataProvider, CAPIFlatClientDataProvider, CAPIFlatServerDataProvider, CAPITreeClientDataProvider, CAPITreeServerDataProvider, CApplicationCache, CBrowserSessionCache, CCookieCache, CFlatClientDataProvider, CFlatServerDataProvider, CIndexedDBCache, CLocalStorageCache, CMemoryCache, CServerSessionCache, CTreeClientDataProvider, CTreeServerDataProvider, CacheProviderFactory, DefaultHydrationAdapter, ECacheStrategy, EDataFilterOperator, EQueueStorage, KatluxIndexedDB, QueueStorageFactory, RequestProvider, RequestProviderRegistry, RequestQueue, SENSITIVE_HEADER_KEYS, applyOperator, clearSSRData, compareAnd, compareEqual, compareIn, compareOr, compareValues, debounce, evaluateFilter, fetchWithSSR, filterData, filterTreeData, getAppRoute, getAppRouter, getHydrationAdapter, getPlatformApp, getSSRData, getSSRPayload, onPlatformReady, setHydrationAdapter, sortData, useDebounce, useFilterLogic, useSortLogic };
1091
- export type { CacheDriverLoader, ICacheEntry, IDataFilter, IDataProviderOptions, IDataResult, IDataSort, IDeadLetterItem, IDebouncedFunction, IFlushOptions, IKDatatableAction, IPlatformRouter, IQueueStorageAdapter, IQueuedOperation, IRequestOptions, ISSRHydrationAdapter, ITreeDataProvider, ITreeDataProviderOptions, ITreeNode, ITreeNodeStatic, KProductItemData, KProductRowAction, TDataProviderListener, TDataRow, TKatluxStore, TPageDataHandler, TQueueItemStatus, TTreePageDataHandler, TTreeRow, TUnsubscribe, TreePaginationMode };
1114
+ export type { CacheDriverLoader, ICacheEntry, IDataFilter, IDataProviderOptions, IDataProviderSetStateOptions, IDataProviderState, IDataResult, IDataSort, IDeadLetterItem, IDebouncedFunction, IFlushOptions, IKDatatableAction, IPlatformRouter, IQueueStorageAdapter, IQueuedOperation, IRequestOptions, ISSRHydrationAdapter, ITreeDataProvider, ITreeDataProviderOptions, ITreeNode, ITreeNodeStatic, IVirtualScrollState, KProductItemData, KProductRowAction, TDataProviderListener, TDataProviderStateChangeListener, TDataRow, TKatluxStore, TPageDataHandler, TQueueItemStatus, TTreePageDataHandler, TTreeRow, TUnsubscribe, TreePaginationMode };
package/dist/index.d.mts CHANGED
@@ -154,6 +154,31 @@ interface IDataProviderOptions {
154
154
  filterDebounce?: number;
155
155
  sortDebounce?: number;
156
156
  }
157
+ interface IDataProviderState<TRow = TDataRow> {
158
+ currentPage: number;
159
+ pageSize: number;
160
+ filter: IDataFilter | null;
161
+ sortList: IDataSort[];
162
+ selectedRows: TRow[];
163
+ selectAll: boolean;
164
+ rowCount?: number;
165
+ loading?: boolean;
166
+ initialLoad?: boolean;
167
+ error?: any;
168
+ pageData?: TRow[];
169
+ }
170
+ interface IDataProviderSetStateOptions {
171
+ immediate?: boolean;
172
+ silent?: boolean;
173
+ }
174
+ type TDataProviderStateChangeListener<TRow = TDataRow> = (state: IDataProviderState<TRow>, changedKeys: Array<keyof IDataProviderState<TRow>>) => void;
175
+ interface IVirtualScrollState {
176
+ startIndex: number;
177
+ endIndex: number;
178
+ scrollTop: number;
179
+ totalItems: number;
180
+ itemHeight: number;
181
+ }
157
182
 
158
183
  interface ITreeNode<TRow = TDataRow> {
159
184
  data: TRow;
@@ -271,6 +296,8 @@ declare abstract class ADataProvider<TRow = TDataRow> {
271
296
  get sortList(): IDataSort[];
272
297
  set sortList(s: IDataSort[]);
273
298
  private _listeners;
299
+ private _stateListeners;
300
+ private _pendingChangedKeys;
274
301
  private _debouncedFilterLoad;
275
302
  private _debouncedSortLoad;
276
303
  constructor(options?: IDataProviderOptions);
@@ -283,19 +310,13 @@ declare abstract class ADataProvider<TRow = TDataRow> {
283
310
  batchUpdates<R>(fn: () => R): R;
284
311
  subscribe(listener: TDataProviderListener<this>): TUnsubscribe;
285
312
  notify(): void;
286
- getState(): {
287
- pageData: TRow[];
288
- rowCount: number;
289
- currentPage: number;
290
- pageSize: number;
291
- loading: boolean;
292
- initialLoad: boolean;
293
- error: any;
294
- filter: IDataFilter | null;
295
- sortList: IDataSort[];
296
- selectedRows: TRow[];
297
- selectAll: boolean;
298
- };
313
+ onStateChange(listener: TDataProviderStateChangeListener<TRow>): TUnsubscribe;
314
+ getState(): IDataProviderState<TRow>;
315
+ protected onFilterUpdated(): void;
316
+ protected onSortUpdated(): void;
317
+ setState(partial: Partial<IDataProviderState<TRow>>, options?: IDataProviderSetStateOptions): void;
318
+ serializeState(): string;
319
+ deserializeState(serialized: string | Partial<IDataProviderState<TRow>>, options?: IDataProviderSetStateOptions): void;
299
320
  setFilter(filter: IDataFilter | null, immediate?: boolean): void;
300
321
  setSortList(sortList: IDataSort[], immediate?: boolean): void;
301
322
  setCurrentPage(currentPage: number): void;
@@ -321,6 +342,8 @@ declare class CFlatClientDataProvider<TRow = TDataRow> extends ADataProvider<TRo
321
342
  set allData(data: TRow[]);
322
343
  get rowMap(): readonly TRow[];
323
344
  setData(data: TRow[]): void;
345
+ protected onFilterUpdated(): void;
346
+ protected onSortUpdated(): void;
324
347
  setFilter(filter: IDataFilter | null, immediate?: boolean): void;
325
348
  setSortList(sortList: IDataSort[], immediate?: boolean): void;
326
349
  /**
@@ -1088,4 +1111,4 @@ declare function getAppRouter(): any;
1088
1111
  declare function onPlatformReady(cb: () => void): void;
1089
1112
 
1090
1113
  export { AAPIDataProvider, ADataProvider, CAPIFlatClientDataProvider, CAPIFlatServerDataProvider, CAPITreeClientDataProvider, CAPITreeServerDataProvider, CApplicationCache, CBrowserSessionCache, CCookieCache, CFlatClientDataProvider, CFlatServerDataProvider, CIndexedDBCache, CLocalStorageCache, CMemoryCache, CServerSessionCache, CTreeClientDataProvider, CTreeServerDataProvider, CacheProviderFactory, DefaultHydrationAdapter, ECacheStrategy, EDataFilterOperator, EQueueStorage, KatluxIndexedDB, QueueStorageFactory, RequestProvider, RequestProviderRegistry, RequestQueue, SENSITIVE_HEADER_KEYS, applyOperator, clearSSRData, compareAnd, compareEqual, compareIn, compareOr, compareValues, debounce, evaluateFilter, fetchWithSSR, filterData, filterTreeData, getAppRoute, getAppRouter, getHydrationAdapter, getPlatformApp, getSSRData, getSSRPayload, onPlatformReady, setHydrationAdapter, sortData, useDebounce, useFilterLogic, useSortLogic };
1091
- export type { CacheDriverLoader, ICacheEntry, IDataFilter, IDataProviderOptions, IDataResult, IDataSort, IDeadLetterItem, IDebouncedFunction, IFlushOptions, IKDatatableAction, IPlatformRouter, IQueueStorageAdapter, IQueuedOperation, IRequestOptions, ISSRHydrationAdapter, ITreeDataProvider, ITreeDataProviderOptions, ITreeNode, ITreeNodeStatic, KProductItemData, KProductRowAction, TDataProviderListener, TDataRow, TKatluxStore, TPageDataHandler, TQueueItemStatus, TTreePageDataHandler, TTreeRow, TUnsubscribe, TreePaginationMode };
1114
+ export type { CacheDriverLoader, ICacheEntry, IDataFilter, IDataProviderOptions, IDataProviderSetStateOptions, IDataProviderState, IDataResult, IDataSort, IDeadLetterItem, IDebouncedFunction, IFlushOptions, IKDatatableAction, IPlatformRouter, IQueueStorageAdapter, IQueuedOperation, IRequestOptions, ISSRHydrationAdapter, ITreeDataProvider, ITreeDataProviderOptions, ITreeNode, ITreeNodeStatic, IVirtualScrollState, KProductItemData, KProductRowAction, TDataProviderListener, TDataProviderStateChangeListener, TDataRow, TKatluxStore, TPageDataHandler, TQueueItemStatus, TTreePageDataHandler, TTreeRow, TUnsubscribe, TreePaginationMode };
package/dist/index.d.ts CHANGED
@@ -154,6 +154,31 @@ interface IDataProviderOptions {
154
154
  filterDebounce?: number;
155
155
  sortDebounce?: number;
156
156
  }
157
+ interface IDataProviderState<TRow = TDataRow> {
158
+ currentPage: number;
159
+ pageSize: number;
160
+ filter: IDataFilter | null;
161
+ sortList: IDataSort[];
162
+ selectedRows: TRow[];
163
+ selectAll: boolean;
164
+ rowCount?: number;
165
+ loading?: boolean;
166
+ initialLoad?: boolean;
167
+ error?: any;
168
+ pageData?: TRow[];
169
+ }
170
+ interface IDataProviderSetStateOptions {
171
+ immediate?: boolean;
172
+ silent?: boolean;
173
+ }
174
+ type TDataProviderStateChangeListener<TRow = TDataRow> = (state: IDataProviderState<TRow>, changedKeys: Array<keyof IDataProviderState<TRow>>) => void;
175
+ interface IVirtualScrollState {
176
+ startIndex: number;
177
+ endIndex: number;
178
+ scrollTop: number;
179
+ totalItems: number;
180
+ itemHeight: number;
181
+ }
157
182
 
158
183
  interface ITreeNode<TRow = TDataRow> {
159
184
  data: TRow;
@@ -271,6 +296,8 @@ declare abstract class ADataProvider<TRow = TDataRow> {
271
296
  get sortList(): IDataSort[];
272
297
  set sortList(s: IDataSort[]);
273
298
  private _listeners;
299
+ private _stateListeners;
300
+ private _pendingChangedKeys;
274
301
  private _debouncedFilterLoad;
275
302
  private _debouncedSortLoad;
276
303
  constructor(options?: IDataProviderOptions);
@@ -283,19 +310,13 @@ declare abstract class ADataProvider<TRow = TDataRow> {
283
310
  batchUpdates<R>(fn: () => R): R;
284
311
  subscribe(listener: TDataProviderListener<this>): TUnsubscribe;
285
312
  notify(): void;
286
- getState(): {
287
- pageData: TRow[];
288
- rowCount: number;
289
- currentPage: number;
290
- pageSize: number;
291
- loading: boolean;
292
- initialLoad: boolean;
293
- error: any;
294
- filter: IDataFilter | null;
295
- sortList: IDataSort[];
296
- selectedRows: TRow[];
297
- selectAll: boolean;
298
- };
313
+ onStateChange(listener: TDataProviderStateChangeListener<TRow>): TUnsubscribe;
314
+ getState(): IDataProviderState<TRow>;
315
+ protected onFilterUpdated(): void;
316
+ protected onSortUpdated(): void;
317
+ setState(partial: Partial<IDataProviderState<TRow>>, options?: IDataProviderSetStateOptions): void;
318
+ serializeState(): string;
319
+ deserializeState(serialized: string | Partial<IDataProviderState<TRow>>, options?: IDataProviderSetStateOptions): void;
299
320
  setFilter(filter: IDataFilter | null, immediate?: boolean): void;
300
321
  setSortList(sortList: IDataSort[], immediate?: boolean): void;
301
322
  setCurrentPage(currentPage: number): void;
@@ -321,6 +342,8 @@ declare class CFlatClientDataProvider<TRow = TDataRow> extends ADataProvider<TRo
321
342
  set allData(data: TRow[]);
322
343
  get rowMap(): readonly TRow[];
323
344
  setData(data: TRow[]): void;
345
+ protected onFilterUpdated(): void;
346
+ protected onSortUpdated(): void;
324
347
  setFilter(filter: IDataFilter | null, immediate?: boolean): void;
325
348
  setSortList(sortList: IDataSort[], immediate?: boolean): void;
326
349
  /**
@@ -1088,4 +1111,4 @@ declare function getAppRouter(): any;
1088
1111
  declare function onPlatformReady(cb: () => void): void;
1089
1112
 
1090
1113
  export { AAPIDataProvider, ADataProvider, CAPIFlatClientDataProvider, CAPIFlatServerDataProvider, CAPITreeClientDataProvider, CAPITreeServerDataProvider, CApplicationCache, CBrowserSessionCache, CCookieCache, CFlatClientDataProvider, CFlatServerDataProvider, CIndexedDBCache, CLocalStorageCache, CMemoryCache, CServerSessionCache, CTreeClientDataProvider, CTreeServerDataProvider, CacheProviderFactory, DefaultHydrationAdapter, ECacheStrategy, EDataFilterOperator, EQueueStorage, KatluxIndexedDB, QueueStorageFactory, RequestProvider, RequestProviderRegistry, RequestQueue, SENSITIVE_HEADER_KEYS, applyOperator, clearSSRData, compareAnd, compareEqual, compareIn, compareOr, compareValues, debounce, evaluateFilter, fetchWithSSR, filterData, filterTreeData, getAppRoute, getAppRouter, getHydrationAdapter, getPlatformApp, getSSRData, getSSRPayload, onPlatformReady, setHydrationAdapter, sortData, useDebounce, useFilterLogic, useSortLogic };
1091
- export type { CacheDriverLoader, ICacheEntry, IDataFilter, IDataProviderOptions, IDataResult, IDataSort, IDeadLetterItem, IDebouncedFunction, IFlushOptions, IKDatatableAction, IPlatformRouter, IQueueStorageAdapter, IQueuedOperation, IRequestOptions, ISSRHydrationAdapter, ITreeDataProvider, ITreeDataProviderOptions, ITreeNode, ITreeNodeStatic, KProductItemData, KProductRowAction, TDataProviderListener, TDataRow, TKatluxStore, TPageDataHandler, TQueueItemStatus, TTreePageDataHandler, TTreeRow, TUnsubscribe, TreePaginationMode };
1114
+ export type { CacheDriverLoader, ICacheEntry, IDataFilter, IDataProviderOptions, IDataProviderSetStateOptions, IDataProviderState, IDataResult, IDataSort, IDeadLetterItem, IDebouncedFunction, IFlushOptions, IKDatatableAction, IPlatformRouter, IQueueStorageAdapter, IQueuedOperation, IRequestOptions, ISSRHydrationAdapter, ITreeDataProvider, ITreeDataProviderOptions, ITreeNode, ITreeNodeStatic, IVirtualScrollState, KProductItemData, KProductRowAction, TDataProviderListener, TDataProviderStateChangeListener, TDataRow, TKatluxStore, TPageDataHandler, TQueueItemStatus, TTreePageDataHandler, TTreeRow, TUnsubscribe, TreePaginationMode };
package/dist/index.mjs CHANGED
@@ -271,6 +271,8 @@ class ADataProvider {
271
271
  this.setSortList(s);
272
272
  }
273
273
  _listeners = /* @__PURE__ */ new Set();
274
+ _stateListeners = /* @__PURE__ */ new Set();
275
+ _pendingChangedKeys = /* @__PURE__ */ new Set();
274
276
  _debouncedFilterLoad;
275
277
  _debouncedSortLoad;
276
278
  constructor(options) {
@@ -330,6 +332,10 @@ class ADataProvider {
330
332
  this.subscribe = this.subscribe.bind(this);
331
333
  this.batchUpdates = this.batchUpdates.bind(this);
332
334
  this.getState = this.getState.bind(this);
335
+ this.setState = this.setState.bind(this);
336
+ this.onStateChange = this.onStateChange.bind(this);
337
+ this.serializeState = this.serializeState.bind(this);
338
+ this.deserializeState = this.deserializeState.bind(this);
333
339
  this.cancelPending = this.cancelPending.bind(this);
334
340
  }
335
341
  _batchDepth = 0;
@@ -386,6 +392,20 @@ class ADataProvider {
386
392
  console.error("[Katlux Providers] Listener error:", e);
387
393
  }
388
394
  });
395
+ if (this._stateListeners.size > 0) {
396
+ const state = this.getState();
397
+ const changed = Array.from(this._pendingChangedKeys);
398
+ this._pendingChangedKeys.clear();
399
+ this._stateListeners.forEach((listener) => {
400
+ try {
401
+ listener(state, changed);
402
+ } catch (e) {
403
+ console.error("[Katlux Providers] State listener error:", e);
404
+ }
405
+ });
406
+ } else {
407
+ this._pendingChangedKeys.clear();
408
+ }
389
409
  } finally {
390
410
  this._isNotifying = false;
391
411
  if (this._pendingNotify && this._batchDepth === 0) {
@@ -394,6 +414,10 @@ class ADataProvider {
394
414
  }
395
415
  }
396
416
  }
417
+ onStateChange(listener) {
418
+ this._stateListeners.add(listener);
419
+ return () => this._stateListeners.delete(listener);
420
+ }
397
421
  getState() {
398
422
  return {
399
423
  pageData: this.pageData,
@@ -409,9 +433,84 @@ class ADataProvider {
409
433
  selectAll: this.selectAll
410
434
  };
411
435
  }
436
+ onFilterUpdated() {
437
+ }
438
+ onSortUpdated() {
439
+ }
440
+ setState(partial, options) {
441
+ this.batchUpdates(() => {
442
+ let needsLoad = false;
443
+ if (partial.pageSize !== void 0 && partial.pageSize !== this._pageSize) {
444
+ this._pageSize = partial.pageSize;
445
+ this._pendingChangedKeys.add("pageSize");
446
+ needsLoad = true;
447
+ }
448
+ if (partial.filter !== void 0 && JSON.stringify(partial.filter) !== JSON.stringify(this._filter)) {
449
+ this._filter = partial.filter;
450
+ this.onFilterUpdated();
451
+ this._pendingChangedKeys.add("filter");
452
+ needsLoad = true;
453
+ }
454
+ if (partial.sortList !== void 0 && JSON.stringify(partial.sortList) !== JSON.stringify(this._sortList)) {
455
+ this._sortList = partial.sortList;
456
+ this.onSortUpdated();
457
+ this._pendingChangedKeys.add("sortList");
458
+ needsLoad = true;
459
+ }
460
+ if (partial.currentPage !== void 0 && partial.currentPage !== this._currentPage) {
461
+ this._currentPage = partial.currentPage;
462
+ this._pendingChangedKeys.add("currentPage");
463
+ needsLoad = true;
464
+ }
465
+ if (partial.selectedRows !== void 0) {
466
+ this._selectedRows = Array.isArray(partial.selectedRows) ? partial.selectedRows : [];
467
+ this._pendingChangedKeys.add("selectedRows");
468
+ }
469
+ if (partial.selectAll !== void 0 && partial.selectAll !== this._selectAll) {
470
+ this._selectAll = partial.selectAll;
471
+ this._pendingChangedKeys.add("selectAll");
472
+ }
473
+ if (needsLoad) {
474
+ if (options?.immediate) {
475
+ this.cancelPending();
476
+ }
477
+ this.loadPageData();
478
+ } else if (!options?.silent) {
479
+ this.notify();
480
+ }
481
+ });
482
+ }
483
+ serializeState() {
484
+ const state = {
485
+ currentPage: this._currentPage,
486
+ pageSize: this._pageSize,
487
+ filter: this._filter,
488
+ sortList: this._sortList,
489
+ selectAll: this._selectAll
490
+ };
491
+ return JSON.stringify(state);
492
+ }
493
+ deserializeState(serialized, options) {
494
+ if (!serialized) return;
495
+ let parsed;
496
+ if (typeof serialized === "string") {
497
+ try {
498
+ parsed = JSON.parse(serialized);
499
+ } catch (e) {
500
+ console.error("[Katlux Providers] Failed to deserialize provider state:", e);
501
+ return;
502
+ }
503
+ } else {
504
+ parsed = serialized;
505
+ }
506
+ this.setState(parsed, options);
507
+ }
412
508
  setFilter(filter, immediate = false) {
413
509
  this._filter = filter;
510
+ this.onFilterUpdated();
414
511
  this._currentPage = 1;
512
+ this._pendingChangedKeys.add("filter");
513
+ this._pendingChangedKeys.add("currentPage");
415
514
  if (immediate) {
416
515
  this._debouncedFilterLoad?.cancel?.();
417
516
  this.loadPageData();
@@ -421,7 +520,10 @@ class ADataProvider {
421
520
  }
422
521
  setSortList(sortList, immediate = false) {
423
522
  this._sortList = sortList;
523
+ this.onSortUpdated();
424
524
  this._currentPage = 1;
525
+ this._pendingChangedKeys.add("sortList");
526
+ this._pendingChangedKeys.add("currentPage");
425
527
  if (immediate) {
426
528
  this._debouncedSortLoad?.cancel?.();
427
529
  this.loadPageData();
@@ -432,6 +534,8 @@ class ADataProvider {
432
534
  setCurrentPage(currentPage) {
433
535
  this._currentPage = currentPage;
434
536
  this._selectAll = false;
537
+ this._pendingChangedKeys.add("currentPage");
538
+ this._pendingChangedKeys.add("selectAll");
435
539
  this.loadPageData();
436
540
  if (typeof window !== "undefined" && this.urlPageParam) {
437
541
  try {
@@ -454,14 +558,18 @@ class ADataProvider {
454
558
  setPageSize(pageSize) {
455
559
  this._pageSize = pageSize;
456
560
  this._currentPage = 1;
561
+ this._pendingChangedKeys.add("pageSize");
562
+ this._pendingChangedKeys.add("currentPage");
457
563
  this.loadPageData();
458
564
  this.notify();
459
565
  }
460
566
  setSelectedRows(rows) {
461
567
  this.selectedRows = rows;
568
+ this._pendingChangedKeys.add("selectedRows");
462
569
  }
463
570
  setSelectAll(val) {
464
571
  this.selectAll = val;
572
+ this._pendingChangedKeys.add("selectAll");
465
573
  }
466
574
  async refresh(hardRefresh = false) {
467
575
  await this.loadPageData({ disableCache: hardRefresh });
@@ -752,6 +860,13 @@ class CFlatClientDataProvider extends ADataProvider {
752
860
  this.allData = Array.isArray(data) ? data : [];
753
861
  this.loadPageData();
754
862
  }
863
+ onFilterUpdated() {
864
+ this._filterDirty = true;
865
+ this._sortDirty = true;
866
+ }
867
+ onSortUpdated() {
868
+ this._sortDirty = true;
869
+ }
755
870
  setFilter(filter, immediate = false) {
756
871
  this._filterDirty = true;
757
872
  this._sortDirty = true;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@katlux/providers",
3
- "version": "0.1.1-alpha.103",
3
+ "version": "0.1.1-alpha.104",
4
4
  "description": "Core data calculation and caching providers for the Katlux ecosystem",
5
5
  "author": "Katlux",
6
6
  "license": "Apache-2.0",