@teleporthq/teleport-plugin-next-data-source 0.43.59 → 0.43.61
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/__tests__/_helpers/pagination-widget-fixture.ts +230 -0
- package/__tests__/ecommerce-product-discounts.test.ts +196 -0
- package/__tests__/infinite-scroll.test.ts +143 -0
- package/__tests__/numbered-pagination.test.ts +113 -0
- package/__tests__/page-reset-on-filter-sort.test.ts +182 -0
- package/__tests__/page-url-sync.test.ts +208 -0
- package/__tests__/product-price-sort.ts +313 -0
- package/__tests__/search-url-sync.test.ts +7 -3
- package/dist/cjs/array-mapper-pagination.d.ts +9 -0
- package/dist/cjs/array-mapper-pagination.d.ts.map +1 -1
- package/dist/cjs/array-mapper-pagination.js.map +1 -1
- package/dist/cjs/cache/ast.d.ts.map +1 -1
- package/dist/cjs/cache/ast.js +2 -2
- package/dist/cjs/cache/ast.js.map +1 -1
- package/dist/cjs/count-effect.d.ts +42 -0
- package/dist/cjs/count-effect.d.ts.map +1 -0
- package/dist/cjs/count-effect.js +81 -0
- package/dist/cjs/count-effect.js.map +1 -0
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +2 -1
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
- package/dist/cjs/fetchers/teleport.js +3 -2
- package/dist/cjs/fetchers/teleport.js.map +1 -1
- package/dist/cjs/infinite-scroll.d.ts +65 -0
- package/dist/cjs/infinite-scroll.d.ts.map +1 -0
- package/dist/cjs/infinite-scroll.js +190 -0
- package/dist/cjs/infinite-scroll.js.map +1 -0
- package/dist/cjs/numbered-pagination.d.ts +42 -0
- package/dist/cjs/numbered-pagination.d.ts.map +1 -0
- package/dist/cjs/numbered-pagination.js +167 -0
- package/dist/cjs/numbered-pagination.js.map +1 -0
- package/dist/cjs/page-reset.d.ts +42 -0
- package/dist/cjs/page-reset.d.ts.map +1 -0
- package/dist/cjs/page-reset.js +116 -0
- package/dist/cjs/page-reset.js.map +1 -0
- package/dist/cjs/page-url-sync.d.ts +42 -0
- package/dist/cjs/page-url-sync.d.ts.map +1 -0
- package/dist/cjs/page-url-sync.js +180 -0
- package/dist/cjs/page-url-sync.js.map +1 -0
- package/dist/cjs/pagination-controls.d.ts +55 -0
- package/dist/cjs/pagination-controls.d.ts.map +1 -0
- package/dist/cjs/pagination-controls.js +159 -0
- package/dist/cjs/pagination-controls.js.map +1 -0
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +508 -164
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/product-price-sort.d.ts +116 -0
- package/dist/cjs/product-price-sort.d.ts.map +1 -0
- package/dist/cjs/product-price-sort.js +169 -0
- package/dist/cjs/product-price-sort.js.map +1 -0
- package/dist/cjs/transformations/ecommerce-product.d.ts.map +1 -1
- package/dist/cjs/transformations/ecommerce-product.js +1 -1
- package/dist/cjs/transformations/ecommerce-product.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +5 -7
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/array-mapper-pagination.d.ts +9 -0
- package/dist/esm/array-mapper-pagination.d.ts.map +1 -1
- package/dist/esm/array-mapper-pagination.js.map +1 -1
- package/dist/esm/cache/ast.d.ts.map +1 -1
- package/dist/esm/cache/ast.js +2 -2
- package/dist/esm/cache/ast.js.map +1 -1
- package/dist/esm/count-effect.d.ts +42 -0
- package/dist/esm/count-effect.d.ts.map +1 -0
- package/dist/esm/count-effect.js +53 -0
- package/dist/esm/count-effect.js.map +1 -0
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +2 -1
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/teleport.d.ts.map +1 -1
- package/dist/esm/fetchers/teleport.js +3 -2
- package/dist/esm/fetchers/teleport.js.map +1 -1
- package/dist/esm/infinite-scroll.d.ts +65 -0
- package/dist/esm/infinite-scroll.d.ts.map +1 -0
- package/dist/esm/infinite-scroll.js +159 -0
- package/dist/esm/infinite-scroll.js.map +1 -0
- package/dist/esm/numbered-pagination.d.ts +42 -0
- package/dist/esm/numbered-pagination.d.ts.map +1 -0
- package/dist/esm/numbered-pagination.js +138 -0
- package/dist/esm/numbered-pagination.js.map +1 -0
- package/dist/esm/page-reset.d.ts +42 -0
- package/dist/esm/page-reset.d.ts.map +1 -0
- package/dist/esm/page-reset.js +87 -0
- package/dist/esm/page-reset.js.map +1 -0
- package/dist/esm/page-url-sync.d.ts +42 -0
- package/dist/esm/page-url-sync.d.ts.map +1 -0
- package/dist/esm/page-url-sync.js +152 -0
- package/dist/esm/page-url-sync.js.map +1 -0
- package/dist/esm/pagination-controls.d.ts +55 -0
- package/dist/esm/pagination-controls.d.ts.map +1 -0
- package/dist/esm/pagination-controls.js +126 -0
- package/dist/esm/pagination-controls.js.map +1 -0
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +510 -166
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/product-price-sort.d.ts +116 -0
- package/dist/esm/product-price-sort.d.ts.map +1 -0
- package/dist/esm/product-price-sort.js +160 -0
- package/dist/esm/product-price-sort.js.map +1 -0
- package/dist/esm/transformations/ecommerce-product.d.ts.map +1 -1
- package/dist/esm/transformations/ecommerce-product.js +2 -2
- package/dist/esm/transformations/ecommerce-product.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +6 -8
- package/dist/esm/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/array-mapper-pagination.ts +10 -0
- package/src/cache/ast.ts +2 -2
- package/src/count-effect.ts +137 -0
- package/src/fetchers/postgresql.ts +52 -13
- package/src/fetchers/teleport.ts +53 -13
- package/src/infinite-scroll.ts +401 -0
- package/src/numbered-pagination.ts +292 -0
- package/src/page-reset.ts +162 -0
- package/src/page-url-sync.ts +241 -0
- package/src/pagination-controls.ts +176 -0
- package/src/pagination-plugin.ts +758 -351
- package/src/product-price-sort.ts +204 -0
- package/src/transformations/ecommerce-product.ts +33 -7
- package/src/utils.ts +6 -8
- package/dist/cjs/array-mapper-registry.d.ts +0 -85
- package/dist/cjs/array-mapper-registry.d.ts.map +0 -1
- package/dist/cjs/array-mapper-registry.js +0 -296
- package/dist/cjs/array-mapper-registry.js.map +0 -1
- package/dist/cjs/pagination-with-count.d.ts +0 -6
- package/dist/cjs/pagination-with-count.d.ts.map +0 -1
- package/dist/cjs/pagination-with-count.js +0 -63
- package/dist/cjs/pagination-with-count.js.map +0 -1
- package/dist/esm/array-mapper-registry.d.ts +0 -85
- package/dist/esm/array-mapper-registry.d.ts.map +0 -1
- package/dist/esm/array-mapper-registry.js +0 -292
- package/dist/esm/array-mapper-registry.js.map +0 -1
- package/dist/esm/pagination-with-count.d.ts +0 -6
- package/dist/esm/pagination-with-count.d.ts.map +0 -1
- package/dist/esm/pagination-with-count.js +0 -34
- package/dist/esm/pagination-with-count.js.map +0 -1
- package/src/array-mapper-registry.ts +0 -416
- package/src/pagination-with-count.ts +0 -89
|
@@ -34,11 +34,20 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
34
34
|
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
35
35
|
}
|
|
36
36
|
};
|
|
37
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
38
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
39
|
+
if (ar || !(i in from)) {
|
|
40
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
41
|
+
ar[i] = from[i];
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
45
|
+
};
|
|
37
46
|
import { ChunkType, FileType, } from '@teleporthq/teleport-types';
|
|
38
47
|
import * as types from '@babel/types';
|
|
39
48
|
import { parseExpression } from '@babel/parser';
|
|
40
|
-
import { ASTStatementOrder, StringUtils } from '@teleporthq/teleport-shared';
|
|
41
|
-
import { ASTUtils, URLSearchParamSync } from '@teleporthq/teleport-plugin-common';
|
|
49
|
+
import { ASTStatementOrder, GenericUtils, StringUtils } from '@teleporthq/teleport-shared';
|
|
50
|
+
import { ASTUtils, URLQueryWriter, URLSearchParamSync } from '@teleporthq/teleport-plugin-common';
|
|
42
51
|
import { generateSafeFileName } from './utils';
|
|
43
52
|
import { generateDataSourceFetcherWithCore } from './data-source-fetchers';
|
|
44
53
|
import { buildProductTransformOptions, } from './transformations';
|
|
@@ -47,6 +56,12 @@ import { appendFiltersParam, pushStateIdsAsDeps, pushPropIdsAsDeps } from './fil
|
|
|
47
56
|
import { applyLoadingStateToDataProvider, buildLoadingStateDeclarations, getLoadingStateVars, } from './loading-state';
|
|
48
57
|
import { mergeServerCacheOptions, resolveCacheFromRepeaterContent } from './cache/config';
|
|
49
58
|
import { buildCacheHydrationEffect, buildCacheStoreThen, buildCachedFetchBody, buildCachedParamsDeclarations, registerCacheClientImports, } from './cache/ast';
|
|
59
|
+
import { convertControlToButton, dropInactivePaginationControls, findPaginationControl, setJSXExpressionAttribute, } from './pagination-controls';
|
|
60
|
+
import { buildCountFetchEffect } from './count-effect';
|
|
61
|
+
import { buildPageTokensDeclaration, wireNumberedPagination, } from './numbered-pagination';
|
|
62
|
+
import { buildAccumulatingResponseHandler, buildInfiniteScrollDeclarations, buildSentinelElement, buildSentinelObserverEffect, getInfiniteScrollVars, } from './infinite-scroll';
|
|
63
|
+
import { buildFilterSortPageResetEffect, buildPageResetRefDeclaration, hasNoPageResetDeps, } from './page-reset';
|
|
64
|
+
import { buildPageUrlRefDeclaration, buildPageUrlSyncEffect } from './page-url-sync';
|
|
50
65
|
// tslint:disable-next-line:no-any
|
|
51
66
|
function parseSearchDefaultValue(raw) {
|
|
52
67
|
if (!raw || typeof raw !== 'object') {
|
|
@@ -400,6 +415,17 @@ function buildStateRegistry(uidlNode) {
|
|
|
400
415
|
content.searchUrlParamKey.trim().length > 0
|
|
401
416
|
? content.searchUrlParamKey.trim()
|
|
402
417
|
: undefined;
|
|
418
|
+
// An accumulating list has no discrete pages, so it can neither jump
|
|
419
|
+
// between them nor put one in the URL. Normalising here — rather than at
|
|
420
|
+
// each of the ~6 emit sites — keeps every downstream branch able to trust
|
|
421
|
+
// `paginationMode` / `pageUrlParamKey` on their own.
|
|
422
|
+
var infiniteScroll = !!content.infiniteScroll;
|
|
423
|
+
var pageUrlParamKey = !infiniteScroll &&
|
|
424
|
+
typeof content.pageUrlParamKey === 'string' &&
|
|
425
|
+
content.pageUrlParamKey.trim().length > 0
|
|
426
|
+
? content.pageUrlParamKey.trim()
|
|
427
|
+
: undefined;
|
|
428
|
+
var paginationMode = !infiniteScroll && content.paginationMode === 'numbered' ? 'numbered' : 'buttons';
|
|
403
429
|
var usage = {
|
|
404
430
|
index: index++,
|
|
405
431
|
dataSourceIdentifier: parentDataSource.identifier,
|
|
@@ -423,6 +449,10 @@ function buildStateRegistry(uidlNode) {
|
|
|
423
449
|
filterPropIds: filterPropIds,
|
|
424
450
|
filterUrlSearchParamKeys: filterUrlSearchParamKeys,
|
|
425
451
|
cache: resolveCacheFromRepeaterContent(content.cache, parentDataSource.resourceDef),
|
|
452
|
+
paginationMode: paginationMode,
|
|
453
|
+
infiniteScroll: infiniteScroll,
|
|
454
|
+
infiniteScrollLoadMore: infiniteScroll && !!content.infiniteScrollLoadMore,
|
|
455
|
+
pageUrlParamKey: pageUrlParamKey,
|
|
426
456
|
category: 'plain',
|
|
427
457
|
};
|
|
428
458
|
// Determine category
|
|
@@ -514,6 +544,16 @@ function usageHasSearchUrlSync(usage) {
|
|
|
514
544
|
return (!!usage.searchUrlParamKey &&
|
|
515
545
|
(usage.category === 'paginated+search' || usage.category === 'search-only'));
|
|
516
546
|
}
|
|
547
|
+
// The page ⇄ URL counterpart of `usageHasSearchUrlSync`: the usage must carry a
|
|
548
|
+
// `pageUrlParamKey` AND own a page state (only the paginated categories declare
|
|
549
|
+
// `ds_N_page` / `ds_N_state.page`). `infiniteScroll` usages are already excluded
|
|
550
|
+
// by the registry, which clears their key.
|
|
551
|
+
function usageHasPageUrlSync(usage) {
|
|
552
|
+
return (!!usage.pageUrlParamKey &&
|
|
553
|
+
usage.paginated &&
|
|
554
|
+
!usage.infiniteScroll &&
|
|
555
|
+
(usage.category === 'paginated+search' || usage.category === 'paginated-only'));
|
|
556
|
+
}
|
|
517
557
|
// Emits the two URL-sync effects for a search input bound to a URL param
|
|
518
558
|
// (`searchUrlParamKey`), reusing the shared `URLSearchParamSync` builders so the
|
|
519
559
|
// search input behaves exactly like the `selectedCategory` / `sortBy` dropdowns:
|
|
@@ -553,10 +593,157 @@ function pushSearchUrlSyncEffects(effectStatements, usage, vars) {
|
|
|
553
593
|
// debounce effect propagates the change into the debounced value + fetch.
|
|
554
594
|
effectStatements.push(URLSearchParamSync.buildUrlReadBackEffect(usage.searchUrlParamKey, vars.setSearchQueryVar));
|
|
555
595
|
}
|
|
596
|
+
// How one usage reads and writes its current page.
|
|
597
|
+
//
|
|
598
|
+
// A paginated+search list keeps the page inside a combined
|
|
599
|
+
// `{ page, debouncedQuery }` object so a search reset can replace both at once,
|
|
600
|
+
// while a paginated-only list has a plain `ds_N_page`. Every control that moves
|
|
601
|
+
// the page goes through this pair rather than re-deriving the distinction.
|
|
602
|
+
function getPageAccessors(usage, vars) {
|
|
603
|
+
var isCombinedState = usage.category === 'paginated+search';
|
|
604
|
+
return {
|
|
605
|
+
currentPageExpr: function () {
|
|
606
|
+
return isCombinedState
|
|
607
|
+
? types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page'))
|
|
608
|
+
: types.identifier(vars.pageStateVar);
|
|
609
|
+
},
|
|
610
|
+
// Functional updates that bail when the page is unchanged: clicking the
|
|
611
|
+
// page you are already on must not schedule a render, and with it a refetch.
|
|
612
|
+
buildSetPageStatement: function (pageExpr) {
|
|
613
|
+
return isCombinedState
|
|
614
|
+
? types.callExpression(types.identifier(vars.setCombinedStateVar), [
|
|
615
|
+
types.arrowFunctionExpression([types.identifier('state')], types.conditionalExpression(types.binaryExpression('===', types.memberExpression(types.identifier('state'), types.identifier('page')), types.cloneNode(pageExpr, true)), types.identifier('state'), types.objectExpression([
|
|
616
|
+
types.spreadElement(types.identifier('state')),
|
|
617
|
+
types.objectProperty(types.identifier('page'), types.cloneNode(pageExpr, true)),
|
|
618
|
+
]))),
|
|
619
|
+
])
|
|
620
|
+
: types.callExpression(types.identifier(vars.setPageStateVar), [
|
|
621
|
+
types.arrowFunctionExpression([types.identifier('page')], types.conditionalExpression(types.binaryExpression('===', types.identifier('page'), types.cloneNode(pageExpr, true)), types.identifier('page'), types.cloneNode(pageExpr, true))),
|
|
622
|
+
]);
|
|
623
|
+
},
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
/**
|
|
627
|
+
* Advance one page, unless the count already says this is the last one. Shared
|
|
628
|
+
* by the scroll sentinel and the Load More button.
|
|
629
|
+
*
|
|
630
|
+
* ⛔ The next page is derived from the updater's OWN argument, never from the
|
|
631
|
+
* page in scope. The sentinel's effect is re-armed on `hasMore` / `maxPages`,
|
|
632
|
+
* and neither changes on an append while the total is unknown — so a captured
|
|
633
|
+
* `ds_N_page` would still read 1 on the second intersection and the list would
|
|
634
|
+
* stop growing after one page, on exactly the sources that cannot be counted.
|
|
635
|
+
*/
|
|
636
|
+
function buildAdvancePageStatement(usage, vars) {
|
|
637
|
+
var isCombinedState = usage.category === 'paginated+search';
|
|
638
|
+
var paramName = isCombinedState ? 'state' : 'page';
|
|
639
|
+
var pageOfParam = function () {
|
|
640
|
+
return isCombinedState
|
|
641
|
+
? types.memberExpression(types.identifier(paramName), types.identifier('page'))
|
|
642
|
+
: types.identifier(paramName);
|
|
643
|
+
};
|
|
644
|
+
// maxPages > 0 && <param page> >= maxPages
|
|
645
|
+
var atLastPage = types.logicalExpression('&&', types.binaryExpression('>', types.identifier(vars.maxPagesStateVar), types.numericLiteral(0)), types.binaryExpression('>=', pageOfParam(), types.identifier(vars.maxPagesStateVar)));
|
|
646
|
+
var nextPage = types.binaryExpression('+', pageOfParam(), types.numericLiteral(1));
|
|
647
|
+
return types.expressionStatement(types.callExpression(types.identifier(isCombinedState ? vars.setCombinedStateVar : vars.setPageStateVar), [
|
|
648
|
+
types.arrowFunctionExpression([types.identifier(paramName)], types.conditionalExpression(atLastPage, types.identifier(paramName), isCombinedState
|
|
649
|
+
? types.objectExpression([
|
|
650
|
+
types.spreadElement(types.identifier(paramName)),
|
|
651
|
+
types.objectProperty(types.identifier('page'), nextPage),
|
|
652
|
+
])
|
|
653
|
+
: nextPage)),
|
|
654
|
+
]));
|
|
655
|
+
}
|
|
656
|
+
// The accumulator, the end-of-data flag and (in auto mode) the sentinel ref,
|
|
657
|
+
// declared only for a mapper that appends.
|
|
658
|
+
function pushInfiniteScrollDeclarations(stateDeclarations, effectStatements, usage, vars) {
|
|
659
|
+
if (!usage.infiniteScroll || !usage.paginated) {
|
|
660
|
+
return;
|
|
661
|
+
}
|
|
662
|
+
var infiniteVars = getInfiniteScrollVars(usage.index);
|
|
663
|
+
var currentPageExpr = getPageAccessors(usage, vars).currentPageExpr;
|
|
664
|
+
var usesSentinel = !usage.infiniteScrollLoadMore;
|
|
665
|
+
stateDeclarations.push.apply(stateDeclarations, buildInfiniteScrollDeclarations(infiniteVars, vars.maxPagesStateVar, currentPageExpr(), usesSentinel));
|
|
666
|
+
if (usesSentinel) {
|
|
667
|
+
effectStatements.push(buildSentinelObserverEffect(infiniteVars, vars.maxPagesStateVar, function () {
|
|
668
|
+
return buildAdvancePageStatement(usage, vars);
|
|
669
|
+
}));
|
|
670
|
+
}
|
|
671
|
+
}
|
|
672
|
+
// The `useMemo` holding the visible page numbers, declared only for a mapper in
|
|
673
|
+
// numbered mode.
|
|
674
|
+
function pushPageTokensDeclaration(stateDeclarations, usage, vars) {
|
|
675
|
+
if (usage.paginationMode !== 'numbered' || !usage.paginated) {
|
|
676
|
+
return;
|
|
677
|
+
}
|
|
678
|
+
var currentPageExpr = getPageAccessors(usage, vars).currentPageExpr;
|
|
679
|
+
stateDeclarations.push(buildPageTokensDeclaration(usage.index, vars.maxPagesStateVar, currentPageExpr()));
|
|
680
|
+
}
|
|
681
|
+
// Emits the page ⇄ `?<key>=` sync for a mapper bound to `pageUrlParamKey` — the
|
|
682
|
+
// pagination counterpart of `pushSearchUrlSyncEffects`, but a SINGLE effect
|
|
683
|
+
// that owns both directions. `page-url-sync.ts` explains at length why the
|
|
684
|
+
// usual read-back / write-back pair cannot be used here.
|
|
685
|
+
//
|
|
686
|
+
// ⛔ MUST be pushed AFTER the filter/sort reset effect. Both can fire in one
|
|
687
|
+
// flush on a navigation that changes filter and page together; effects run in
|
|
688
|
+
// emission order, so this one running LAST is what makes the URL win when it
|
|
689
|
+
// carries a page, while a plain user filter change (whose URL has not moved
|
|
690
|
+
// yet) is left with the reset's page 1 and writes that back.
|
|
691
|
+
function pushPageUrlSyncEffects(stateDeclarations, effectStatements, usage, vars) {
|
|
692
|
+
if (!usageHasPageUrlSync(usage)) {
|
|
693
|
+
return;
|
|
694
|
+
}
|
|
695
|
+
var refVar = "ds_".concat(usage.index, "_pageUrlRef");
|
|
696
|
+
var _a = getPageAccessors(usage, vars), currentPageExpr = _a.currentPageExpr, buildSetPageStatement = _a.buildSetPageStatement;
|
|
697
|
+
stateDeclarations.push(buildPageUrlRefDeclaration(refVar));
|
|
698
|
+
effectStatements.push(buildPageUrlSyncEffect({
|
|
699
|
+
paramKey: usage.pageUrlParamKey,
|
|
700
|
+
refVar: refVar,
|
|
701
|
+
currentPageExpr: currentPageExpr,
|
|
702
|
+
buildSetPageStatement: buildSetPageStatement,
|
|
703
|
+
}));
|
|
704
|
+
}
|
|
705
|
+
// The name of the ref holding this usage's last-seen filter/sort signature.
|
|
706
|
+
function getPageResetRefVar(usage) {
|
|
707
|
+
return "ds_".concat(usage.index, "_filterResetRef");
|
|
708
|
+
}
|
|
709
|
+
// Everything that can narrow this list: filter destinations (state-, prop- and
|
|
710
|
+
// URL-bound) plus the state a dynamic sort reads. Sort does not change WHICH
|
|
711
|
+
// rows match, but it does change which row is on which page, so holding the
|
|
712
|
+
// visitor on page 5 across a sort change shows them an arbitrary window of a
|
|
713
|
+
// list they just reordered.
|
|
714
|
+
function collectPageResetDeps(usage) {
|
|
715
|
+
var _a, _b;
|
|
716
|
+
return {
|
|
717
|
+
stateIds: __spreadArray(__spreadArray([], usage.filterStateIds, true), ((_b = (_a = usage.dynamicSort) === null || _a === void 0 ? void 0 : _a.depStateIds) !== null && _b !== void 0 ? _b : []), true),
|
|
718
|
+
propIds: usage.filterPropIds,
|
|
719
|
+
urlSearchParamKeys: usage.filterUrlSearchParamKeys,
|
|
720
|
+
};
|
|
721
|
+
}
|
|
722
|
+
// Emits the "a filter or sort changed ⇒ go back to page 1" effect for one
|
|
723
|
+
// paginated usage. No-op for a list nothing can filter or reorder, so a mapper
|
|
724
|
+
// without filters generates byte-for-byte what it always did.
|
|
725
|
+
function pushFilterSortPageResetEffect(stateDeclarations, effectStatements, usage, vars) {
|
|
726
|
+
if (!usage.paginated) {
|
|
727
|
+
return;
|
|
728
|
+
}
|
|
729
|
+
var deps = collectPageResetDeps(usage);
|
|
730
|
+
if (hasNoPageResetDeps(deps)) {
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
var refVar = getPageResetRefVar(usage);
|
|
734
|
+
stateDeclarations.push(buildPageResetRefDeclaration(refVar));
|
|
735
|
+
// The setter bails when the page is already 1 (see `getPageAccessors`), so a
|
|
736
|
+
// visitor who was on page 1 all along and merely ticked a category does not
|
|
737
|
+
// get an extra render — and with it an extra fetch.
|
|
738
|
+
var buildSetPageStatement = getPageAccessors(usage, vars).buildSetPageStatement;
|
|
739
|
+
effectStatements.push(buildFilterSortPageResetEffect(refVar, deps, function () {
|
|
740
|
+
return types.expressionStatement(buildSetPageStatement(types.numericLiteral(1)));
|
|
741
|
+
}));
|
|
742
|
+
}
|
|
556
743
|
// ==================== MAIN PLUGIN ====================
|
|
557
744
|
export var createNextArrayMapperPaginationPlugin = function () {
|
|
558
745
|
var paginationPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
|
|
559
|
-
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, needsUseRouter, hasRouterDecl, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, loadingStateDeclarations, cacheDeclarations, sharedOptions, cachedScopes, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages
|
|
746
|
+
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, needsUseRouter, hasRouterDecl, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, loadingStateDeclarations, usagesWithLoadingState, usageByProviderNode, cacheDeclarations, sharedOptions, cachedScopes, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages;
|
|
560
747
|
var _a, _b;
|
|
561
748
|
return __generator(this, function (_c) {
|
|
562
749
|
uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options;
|
|
@@ -688,11 +875,19 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
688
875
|
types.variableDeclaration('const', [
|
|
689
876
|
types.variableDeclarator(types.identifier('timer'), types.callExpression(types.identifier('setTimeout'), [
|
|
690
877
|
types.arrowFunctionExpression([], types.blockStatement([
|
|
878
|
+
// ⛔ Functional, and a no-op when the query has not
|
|
879
|
+
// actually moved. This effect fires on ANY change to
|
|
880
|
+
// the input state — including the URL read-back
|
|
881
|
+
// echoing back a value the visitor never typed (a
|
|
882
|
+
// browser Forward to `?searchKeyword=x&page=3`) — and
|
|
883
|
+
// replacing the whole object would silently drop the
|
|
884
|
+
// page it had just adopted, as well as remount the
|
|
885
|
+
// provider on a `key` that contains the query.
|
|
691
886
|
types.expressionStatement(types.callExpression(types.identifier(vars.setCombinedStateVar), [
|
|
692
|
-
types.objectExpression([
|
|
887
|
+
types.arrowFunctionExpression([types.identifier('state')], types.conditionalExpression(types.binaryExpression('===', types.memberExpression(types.identifier('state'), types.identifier('debouncedQuery')), types.identifier(vars.searchQueryVar)), types.identifier('state'), types.objectExpression([
|
|
693
888
|
types.objectProperty(types.identifier('page'), types.numericLiteral(1)),
|
|
694
889
|
types.objectProperty(types.identifier('debouncedQuery'), types.identifier(vars.searchQueryVar)),
|
|
695
|
-
]),
|
|
890
|
+
]))),
|
|
696
891
|
])),
|
|
697
892
|
])),
|
|
698
893
|
types.numericLiteral(usage.searchDebounce),
|
|
@@ -725,42 +920,6 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
725
920
|
}
|
|
726
921
|
// Add filters to count fetch params if present
|
|
727
922
|
appendFiltersParam(urlParams, usage.filters, buildFilterDestinationExpression);
|
|
728
|
-
// Build the count fetch effect body
|
|
729
|
-
var countFetchEffectBody = [];
|
|
730
|
-
// Refresh the count on mount (no skip-on-mount guard). Pages seed maxPages
|
|
731
|
-
// from the build-time `getStaticProps` count, but that snapshot goes stale:
|
|
732
|
-
// rows added AFTER the build (e.g. the normalized product_variants table,
|
|
733
|
-
// which is seeded/grows past one page during store generation) are not
|
|
734
|
-
// reflected, so a frozen maxPages of 0/1 leaves "Next" permanently disabled
|
|
735
|
-
// on data-heavy tables. Re-fetching the live count on mount corrects
|
|
736
|
-
// maxPages so pagination tracks the real row count. The effect still runs
|
|
737
|
-
// when the search query or a filter changes (see deps below).
|
|
738
|
-
// Add the fetch call
|
|
739
|
-
countFetchEffectBody.push(types.expressionStatement(types.callExpression(types.memberExpression(types.callExpression(types.memberExpression(types.callExpression(types.identifier('fetch'), [
|
|
740
|
-
types.templateLiteral([
|
|
741
|
-
types.templateElement({
|
|
742
|
-
raw: "/api/".concat(fileName, "-count?"),
|
|
743
|
-
cooked: "/api/".concat(fileName, "-count?"),
|
|
744
|
-
}),
|
|
745
|
-
types.templateElement({ raw: '', cooked: '' }),
|
|
746
|
-
], [
|
|
747
|
-
types.newExpression(types.identifier('URLSearchParams'), [
|
|
748
|
-
types.objectExpression(urlParams),
|
|
749
|
-
]),
|
|
750
|
-
]),
|
|
751
|
-
]), types.identifier('then')), [
|
|
752
|
-
types.arrowFunctionExpression([types.identifier('res')], types.callExpression(types.memberExpression(types.identifier('res'), types.identifier('json')), [])),
|
|
753
|
-
]), types.identifier('then')), [
|
|
754
|
-
types.arrowFunctionExpression([types.identifier('data')], types.blockStatement([
|
|
755
|
-
types.ifStatement(types.logicalExpression('&&', types.identifier('data'), types.binaryExpression('in', types.stringLiteral('count'), types.identifier('data'))), types.blockStatement([
|
|
756
|
-
types.expressionStatement(types.callExpression(types.identifier(vars.setMaxPagesStateVar), [
|
|
757
|
-
types.conditionalExpression(types.binaryExpression('===', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(0)), types.numericLiteral(0), types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('ceil')), [
|
|
758
|
-
types.binaryExpression('/', types.memberExpression(types.identifier('data'), types.identifier('count')), types.numericLiteral(usage.perPage)),
|
|
759
|
-
])),
|
|
760
|
-
])),
|
|
761
|
-
])),
|
|
762
|
-
])),
|
|
763
|
-
])));
|
|
764
923
|
var countEffectDeps = [
|
|
765
924
|
types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
|
|
766
925
|
];
|
|
@@ -775,12 +934,24 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
775
934
|
pushPropIdsAsDeps(countEffectDeps, countEffectSeen, usage.filterPropIds);
|
|
776
935
|
// Same goes for URL-driven filters (already documented above).
|
|
777
936
|
pushUrlSearchParamMemoDeps(countEffectDeps, usage);
|
|
778
|
-
effectStatements.push(
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
937
|
+
effectStatements.push(buildCountFetchEffect({
|
|
938
|
+
fileName: fileName,
|
|
939
|
+
perPage: usage.perPage,
|
|
940
|
+
setMaxPagesVar: vars.setMaxPagesStateVar,
|
|
941
|
+
urlParams: urlParams,
|
|
942
|
+
deps: countEffectDeps,
|
|
943
|
+
}));
|
|
782
944
|
// Two-way URL sync for the search input when bound to a URL param.
|
|
783
945
|
pushSearchUrlSyncEffects(effectStatements, usage, vars);
|
|
946
|
+
// Visible page numbers, when this mapper draws a numbered strip.
|
|
947
|
+
pushPageTokensDeclaration(stateDeclarations, usage, vars);
|
|
948
|
+
// Accumulation state, when it appends instead of paging.
|
|
949
|
+
pushInfiniteScrollDeclarations(stateDeclarations, effectStatements, usage, vars);
|
|
950
|
+
// A filter or sort change invalidates the page the visitor is on.
|
|
951
|
+
pushFilterSortPageResetEffect(stateDeclarations, effectStatements, usage, vars);
|
|
952
|
+
// Ordering matters — see `pushPageUrlSyncEffects`: the read-back runs
|
|
953
|
+
// after the reset so a URL that names a page wins over it.
|
|
954
|
+
pushPageUrlSyncEffects(stateDeclarations, effectStatements, usage, vars);
|
|
784
955
|
}
|
|
785
956
|
else if (usage.category === 'paginated-only') {
|
|
786
957
|
// Simple page state
|
|
@@ -799,42 +970,52 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
799
970
|
types.identifier(vars.setPageStateVar),
|
|
800
971
|
]), types.callExpression(types.identifier('useState'), [types.numericLiteral(1)])),
|
|
801
972
|
]));
|
|
802
|
-
//
|
|
803
|
-
//
|
|
804
|
-
|
|
973
|
+
// The live row count behind `ds_N_maxPages`.
|
|
974
|
+
//
|
|
975
|
+
// Components have never had a build-time count to fall back on, so they
|
|
976
|
+
// have always fetched one here. Pages seed theirs from `getStaticProps`,
|
|
977
|
+
// which only knows the STATIC filters — good enough to enable/disable a
|
|
978
|
+
// "Next" button, but not to label a numbered strip or to know when an
|
|
979
|
+
// infinite list has reached its end, so those two modes fetch a live
|
|
980
|
+
// count as well.
|
|
981
|
+
var needsLiveCount = !isPage || usage.paginationMode === 'numbered' || usage.infiniteScroll;
|
|
982
|
+
if (needsLiveCount) {
|
|
805
983
|
var fileName = generateSafeFileName(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
pushStateIdsAsDeps(deps, depsSeen, usage.filterStateIds);
|
|
832
|
-
pushPropIdsAsDeps(deps, depsSeen, usage.filterPropIds);
|
|
833
|
-
pushUrlSearchParamMemoDeps(deps, usage);
|
|
834
|
-
return deps;
|
|
835
|
-
})()),
|
|
836
|
-
])));
|
|
984
|
+
// ⛔ This list has no search input, so no `query` param — but it may
|
|
985
|
+
// well have filters, and omitting them (as this call site did until
|
|
986
|
+
// the shared builder replaced it) counts the WHOLE table: "Next"
|
|
987
|
+
// stayed enabled far past the end of a filtered result set.
|
|
988
|
+
var countUrlParams = [];
|
|
989
|
+
if (usage.queryColumns.length > 0) {
|
|
990
|
+
countUrlParams.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
|
|
991
|
+
}
|
|
992
|
+
appendFiltersParam(countUrlParams, usage.filters, buildFilterDestinationExpression);
|
|
993
|
+
// Default to mount-only; refresh when ANY filter destination
|
|
994
|
+
// changes — state-bound (e.g. `selectedCategory`) and URL-driven —
|
|
995
|
+
// so the pagination control reflects the current filtered count
|
|
996
|
+
// instead of the unfiltered mount-time total.
|
|
997
|
+
var countDeps = [];
|
|
998
|
+
var countDepsSeen = new Set();
|
|
999
|
+
pushStateIdsAsDeps(countDeps, countDepsSeen, usage.filterStateIds);
|
|
1000
|
+
pushPropIdsAsDeps(countDeps, countDepsSeen, usage.filterPropIds);
|
|
1001
|
+
pushUrlSearchParamMemoDeps(countDeps, usage);
|
|
1002
|
+
effectStatements.push(buildCountFetchEffect({
|
|
1003
|
+
fileName: fileName,
|
|
1004
|
+
perPage: usage.perPage,
|
|
1005
|
+
setMaxPagesVar: vars.setMaxPagesStateVar,
|
|
1006
|
+
urlParams: countUrlParams,
|
|
1007
|
+
deps: countDeps,
|
|
1008
|
+
}));
|
|
837
1009
|
}
|
|
1010
|
+
// Visible page numbers, when this mapper draws a numbered strip.
|
|
1011
|
+
pushPageTokensDeclaration(stateDeclarations, usage, vars);
|
|
1012
|
+
// Accumulation state, when it appends instead of paging.
|
|
1013
|
+
pushInfiniteScrollDeclarations(stateDeclarations, effectStatements, usage, vars);
|
|
1014
|
+
// A filter or sort change invalidates the page the visitor is on.
|
|
1015
|
+
pushFilterSortPageResetEffect(stateDeclarations, effectStatements, usage, vars);
|
|
1016
|
+
// Ordering matters — see `pushPageUrlSyncEffects`: the read-back runs
|
|
1017
|
+
// after the reset so a URL that names a page wins over it.
|
|
1018
|
+
pushPageUrlSyncEffects(stateDeclarations, effectStatements, usage, vars);
|
|
838
1019
|
}
|
|
839
1020
|
else if (usage.category === 'search-only') {
|
|
840
1021
|
// Search-only state
|
|
@@ -880,7 +1061,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
880
1061
|
});
|
|
881
1062
|
// Insert state declarations at the beginning
|
|
882
1063
|
stateDeclarations.reverse().forEach(function (s) { return blockStatement.body.unshift(s); });
|
|
883
|
-
needsUseRouter = registry.usages.some(function (u) { return hasUrlSearchParamFilters(u) || usageHasSearchUrlSync(u); });
|
|
1064
|
+
needsUseRouter = registry.usages.some(function (u) { return hasUrlSearchParamFilters(u) || usageHasSearchUrlSync(u) || usageHasPageUrlSync(u); });
|
|
884
1065
|
if (needsUseRouter) {
|
|
885
1066
|
if (!dependencies.useRouter) {
|
|
886
1067
|
// Match the shape the sibling Next.js plugins use (i18n locale mapper,
|
|
@@ -910,6 +1091,13 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
910
1091
|
]));
|
|
911
1092
|
}
|
|
912
1093
|
}
|
|
1094
|
+
// Both the search write-back and the page ⇄ URL effect write the URL through
|
|
1095
|
+
// the shared `URLQueryWriter`, so the ref + helper they close over must be in
|
|
1096
|
+
// the body. Idempotent with `createNextUrlSearchParamsPlugin`, which needs the
|
|
1097
|
+
// same pair for the category/sort dropdowns and may have run first.
|
|
1098
|
+
if (registry.usages.some(function (u) { return usageHasSearchUrlSync(u) || usageHasPageUrlSync(u); })) {
|
|
1099
|
+
URLQueryWriter.ensureQuerySyncDeclarations(blockStatement.body);
|
|
1100
|
+
}
|
|
913
1101
|
returnIndex = blockStatement.body.findIndex(function (s) { return s.type === 'ReturnStatement'; });
|
|
914
1102
|
insertIndex = returnIndex !== -1 ? returnIndex : blockStatement.body.length;
|
|
915
1103
|
effectStatements.reverse().forEach(function (e) { return blockStatement.body.splice(insertIndex, 0, e); });
|
|
@@ -920,6 +1108,8 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
920
1108
|
});
|
|
921
1109
|
usageIndexByDataSourceId = new Map();
|
|
922
1110
|
loadingStateDeclarations = [];
|
|
1111
|
+
usagesWithLoadingState = new Set();
|
|
1112
|
+
usageByProviderNode = new Map();
|
|
923
1113
|
cacheDeclarations = [];
|
|
924
1114
|
dataProvidersWithRepeaters.forEach(function (dp) {
|
|
925
1115
|
var _a, _b;
|
|
@@ -936,6 +1126,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
936
1126
|
}
|
|
937
1127
|
var usage = usages[currentIndex];
|
|
938
1128
|
usageIndexByDataSourceId.set(dataSourceIdentifier, currentIndex + 1);
|
|
1129
|
+
usageByProviderNode.set(dp, usage);
|
|
939
1130
|
var vars = getStateVarsForUsage(usage);
|
|
940
1131
|
var fileName = generateSafeFileName(usage.resourceDefinition.dataSourceType, usage.resourceDefinition.tableName, usage.resourceDefinition.dataSourceId);
|
|
941
1132
|
// Update DataProvider based on category
|
|
@@ -958,6 +1149,15 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
958
1149
|
var loadingVars = getLoadingStateVars(usage.index);
|
|
959
1150
|
if (applyLoadingStateToDataProvider(dp, loadingVars)) {
|
|
960
1151
|
loadingStateDeclarations.push.apply(loadingStateDeclarations, buildLoadingStateDeclarations(loadingVars));
|
|
1152
|
+
// Recorded because the loading state is only declared for a provider
|
|
1153
|
+
// that HAS a loading slot; a Load More button wired later may only
|
|
1154
|
+
// reference `ds_N_isFetching` if it actually exists.
|
|
1155
|
+
usagesWithLoadingState.add(usage.index);
|
|
1156
|
+
}
|
|
1157
|
+
// An auto-loading list needs something at the end of the rows for its
|
|
1158
|
+
// IntersectionObserver to watch.
|
|
1159
|
+
if (usage.infiniteScroll && usage.paginated && !usage.infiniteScrollLoadMore) {
|
|
1160
|
+
insertSentinelAfterProvider(blockStatement, dp, buildSentinelElement(getInfiniteScrollVars(usage.index)));
|
|
961
1161
|
}
|
|
962
1162
|
// Create API route for all categories (including 'plain' for components)
|
|
963
1163
|
ensureAPIRouteExists(options.extractedResources, usage, options.dataSources, buildProductTransformOptions(options));
|
|
@@ -1009,16 +1209,23 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1009
1209
|
var vars = getStateVarsForUsage(usage);
|
|
1010
1210
|
wireSearchInput(input.node, vars);
|
|
1011
1211
|
});
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
//
|
|
1015
|
-
|
|
1016
|
-
|
|
1212
|
+
// STEP 5: Wire pagination widgets
|
|
1213
|
+
//
|
|
1214
|
+
// Each widget belongs to the mapper whose `DataProvider` it follows in the
|
|
1215
|
+
// document — the builder emits it as a sibling of (or inside) that provider.
|
|
1216
|
+
//
|
|
1217
|
+
// ⛔ Not a positional zip of "widgets" against "paginated usages": the two
|
|
1218
|
+
// lists no longer have to be the same length, because an infinite-scroll
|
|
1219
|
+
// mapper renders no widget. Counting one for it would shift every later
|
|
1220
|
+
// mapper onto the wrong usage and wire one list's buttons to another list's
|
|
1221
|
+
// state. Anchoring on the provider cannot drift for the same reason the
|
|
1222
|
+
// provider loop above cannot.
|
|
1223
|
+
findPaginationNodesWithOwners(blockStatement, usageByProviderNode).forEach(function (_a) {
|
|
1224
|
+
var node = _a.node, usage = _a.usage;
|
|
1225
|
+
if (!usage) {
|
|
1017
1226
|
return;
|
|
1018
1227
|
}
|
|
1019
|
-
|
|
1020
|
-
var vars = getStateVarsForUsage(usage);
|
|
1021
|
-
wirePaginationButtons(paginationNode.node, usage, vars);
|
|
1228
|
+
wirePaginationWidget(node, usage, getStateVarsForUsage(usage), usagesWithLoadingState.has(usage.index));
|
|
1022
1229
|
});
|
|
1023
1230
|
// STEP 6: Update getStaticProps if this is a page
|
|
1024
1231
|
if (isPage) {
|
|
@@ -1030,6 +1237,57 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
1030
1237
|
return paginationPlugin;
|
|
1031
1238
|
};
|
|
1032
1239
|
// ==================== HELPER FUNCTIONS ====================
|
|
1240
|
+
/**
|
|
1241
|
+
* Inserts the scroll sentinel immediately after a `DataProvider`, as its next
|
|
1242
|
+
* sibling, so it sits below the rendered rows.
|
|
1243
|
+
*
|
|
1244
|
+
* It has to be a sibling: the provider's own child is a render-prop function,
|
|
1245
|
+
* and anything placed inside it would be re-created on every fetch — the
|
|
1246
|
+
* observer would then be watching an element that is no longer in the document.
|
|
1247
|
+
*
|
|
1248
|
+
* Returns false when the provider has no element parent to splice into (a
|
|
1249
|
+
* provider returned directly from the component), leaving the list on its
|
|
1250
|
+
* count-driven `hasMore` rather than injecting a stray node.
|
|
1251
|
+
*/
|
|
1252
|
+
function insertSentinelAfterProvider(blockStatement, provider, sentinel) {
|
|
1253
|
+
var inserted = false;
|
|
1254
|
+
var traverse = function (node) {
|
|
1255
|
+
if (!node || inserted) {
|
|
1256
|
+
return;
|
|
1257
|
+
}
|
|
1258
|
+
if (Array.isArray(node.children)) {
|
|
1259
|
+
var at = node.children.indexOf(provider);
|
|
1260
|
+
if (at !== -1) {
|
|
1261
|
+
node.children.splice(at + 1, 0, sentinel);
|
|
1262
|
+
inserted = true;
|
|
1263
|
+
return;
|
|
1264
|
+
}
|
|
1265
|
+
node.children.forEach(traverse);
|
|
1266
|
+
}
|
|
1267
|
+
if (node.body) {
|
|
1268
|
+
if (Array.isArray(node.body)) {
|
|
1269
|
+
node.body.forEach(traverse);
|
|
1270
|
+
}
|
|
1271
|
+
else {
|
|
1272
|
+
traverse(node.body);
|
|
1273
|
+
}
|
|
1274
|
+
}
|
|
1275
|
+
if (node.consequent) {
|
|
1276
|
+
traverse(node.consequent);
|
|
1277
|
+
}
|
|
1278
|
+
if (node.alternate) {
|
|
1279
|
+
traverse(node.alternate);
|
|
1280
|
+
}
|
|
1281
|
+
if (node.expression) {
|
|
1282
|
+
traverse(node.expression);
|
|
1283
|
+
}
|
|
1284
|
+
if (node.argument) {
|
|
1285
|
+
traverse(node.argument);
|
|
1286
|
+
}
|
|
1287
|
+
};
|
|
1288
|
+
traverse(blockStatement);
|
|
1289
|
+
return inserted;
|
|
1290
|
+
}
|
|
1033
1291
|
function findAllDataProvidersInJSX(blockStatement) {
|
|
1034
1292
|
var results = [];
|
|
1035
1293
|
var traverse = function (node) {
|
|
@@ -1149,18 +1407,32 @@ function findAllSearchInputsInJSX(blockStatement) {
|
|
|
1149
1407
|
traverse(blockStatement);
|
|
1150
1408
|
return results;
|
|
1151
1409
|
}
|
|
1152
|
-
|
|
1410
|
+
/**
|
|
1411
|
+
* Every pagination widget in the JSX, paired with the mapper it belongs to.
|
|
1412
|
+
*
|
|
1413
|
+
* Ownership follows document order: a widget belongs to the most recent
|
|
1414
|
+
* `DataProvider` seen before it, which is exactly how the builder emits it —
|
|
1415
|
+
* as a sibling that follows its provider, or nested inside that provider's
|
|
1416
|
+
* subtree. A widget that precedes every provider (nothing sensible to wire it
|
|
1417
|
+
* to) comes back with no owner and is left alone.
|
|
1418
|
+
*/
|
|
1419
|
+
function findPaginationNodesWithOwners(blockStatement, usageByProviderNode) {
|
|
1153
1420
|
var results = [];
|
|
1421
|
+
var currentUsage;
|
|
1154
1422
|
var traverse = function (node) {
|
|
1155
1423
|
var _a, _b, _c, _d, _e;
|
|
1156
1424
|
if (!node) {
|
|
1157
1425
|
return;
|
|
1158
1426
|
}
|
|
1159
1427
|
if (node.type === 'JSXElement') {
|
|
1428
|
+
var owner = usageByProviderNode.get(node);
|
|
1429
|
+
if (owner) {
|
|
1430
|
+
currentUsage = owner;
|
|
1431
|
+
}
|
|
1160
1432
|
var classAttr = (_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
|
|
1161
1433
|
var className = ((_c = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _c === void 0 ? void 0 : _c.value) || ((_e = (_d = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _d === void 0 ? void 0 : _d.expression) === null || _e === void 0 ? void 0 : _e.value) || '';
|
|
1162
1434
|
if (className.includes('cms-pagination-node')) {
|
|
1163
|
-
results.push({ node: node,
|
|
1435
|
+
results.push({ node: node, usage: currentUsage });
|
|
1164
1436
|
}
|
|
1165
1437
|
}
|
|
1166
1438
|
if (node.children && Array.isArray(node.children)) {
|
|
@@ -1223,7 +1495,6 @@ dp, usage, paramsProps, memoDeps, cacheDeclarations) {
|
|
|
1223
1495
|
return hoisted.cachedIdentifier;
|
|
1224
1496
|
}
|
|
1225
1497
|
function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDeclarations) {
|
|
1226
|
-
var _a;
|
|
1227
1498
|
var attrs = dp.openingElement.attributes;
|
|
1228
1499
|
// Remove existing params, key, initialData, fetchData, persistDataDuringLoading
|
|
1229
1500
|
dp.openingElement.attributes = attrs.filter(function (attr) {
|
|
@@ -1259,7 +1530,12 @@ function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDe
|
|
|
1259
1530
|
// the first client fetch (its internal guard only skips when initialData is
|
|
1260
1531
|
// defined on mount). Without that skip, toggling sort correctly triggers a
|
|
1261
1532
|
// refetch via the useMemo params dependency chain.
|
|
1262
|
-
|
|
1533
|
+
//
|
|
1534
|
+
// An appending list skips it for a second reason: `initialData` makes
|
|
1535
|
+
// DataProvider skip its first fetch, so page 1 would render from the prefetch
|
|
1536
|
+
// and never enter the accumulator — appending page 2 would then REPLACE the
|
|
1537
|
+
// visible rows with page 2 alone.
|
|
1538
|
+
if (!usage.dynamicSort && !usage.infiniteScroll) {
|
|
1263
1539
|
var initialDataCondition = wrapInitialDataWithUrlFilterGuard(types.logicalExpression('&&', types.binaryExpression('===', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')), types.numericLiteral(1)), types.unaryExpression('!', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')), true)), usage);
|
|
1264
1540
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(initialDataCondition, types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), cachedInitialData ? types.identifier(cachedInitialData) : types.identifier('undefined')))));
|
|
1265
1541
|
}
|
|
@@ -1268,24 +1544,37 @@ function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName, cacheDe
|
|
|
1268
1544
|
// "skip-first-fetch-when-we-have-initialData" guard, which would prevent the
|
|
1269
1545
|
// new sort params from reaching the fetcher. Leaving sort out of the key
|
|
1270
1546
|
// lets the useMemo params identity change alone drive refetch.
|
|
1271
|
-
|
|
1272
|
-
|
|
1273
|
-
|
|
1274
|
-
|
|
1275
|
-
|
|
1276
|
-
types.
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1280
|
-
|
|
1281
|
-
|
|
1547
|
+
//
|
|
1548
|
+
// ⛔ The page is left out too when the list APPENDS: remounting on every
|
|
1549
|
+
// appended page would unmount the accumulated rows and refetch from scratch.
|
|
1550
|
+
// The query stays in the key, so a new search still starts a clean list.
|
|
1551
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(usage.infiniteScroll
|
|
1552
|
+
? types.templateLiteral([
|
|
1553
|
+
types.templateElement({
|
|
1554
|
+
raw: "".concat(usage.dataSourceIdentifier, "-"),
|
|
1555
|
+
cooked: "".concat(usage.dataSourceIdentifier, "-"),
|
|
1556
|
+
}),
|
|
1557
|
+
types.templateElement({ raw: '', cooked: '' }),
|
|
1558
|
+
], [
|
|
1559
|
+
types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
|
|
1560
|
+
])
|
|
1561
|
+
: types.templateLiteral([
|
|
1562
|
+
types.templateElement({
|
|
1563
|
+
raw: "".concat(usage.dataSourceIdentifier, "-"),
|
|
1564
|
+
cooked: "".concat(usage.dataSourceIdentifier, "-"),
|
|
1565
|
+
}),
|
|
1566
|
+
types.templateElement({ raw: '-', cooked: '-' }),
|
|
1567
|
+
types.templateElement({ raw: '', cooked: '' }),
|
|
1568
|
+
], [
|
|
1569
|
+
types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')),
|
|
1570
|
+
types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
|
|
1571
|
+
]))));
|
|
1282
1572
|
// Add fetchData
|
|
1283
|
-
dp.openingElement.attributes.push(
|
|
1573
|
+
dp.openingElement.attributes.push(buildFetchDataForUsage(fileName, usage));
|
|
1284
1574
|
// Add persistDataDuringLoading
|
|
1285
1575
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
|
|
1286
1576
|
}
|
|
1287
1577
|
function updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDeclarations) {
|
|
1288
|
-
var _a;
|
|
1289
1578
|
var attrs = dp.openingElement.attributes;
|
|
1290
1579
|
dp.openingElement.attributes = attrs.filter(function (attr) {
|
|
1291
1580
|
var _a;
|
|
@@ -1312,20 +1601,26 @@ function updateDataProviderForPaginationOnly(dp, usage, vars, fileName, cacheDec
|
|
|
1312
1601
|
// Add params
|
|
1313
1602
|
var cachedInitialData = pushParamsAttribute(dp, usage, paramsProps, memoDeps, cacheDeclarations);
|
|
1314
1603
|
// Add initialData. See paginated+search updater for why we skip prefetch
|
|
1315
|
-
// reuse when a dynamic state-bound sort is active
|
|
1316
|
-
|
|
1604
|
+
// reuse when a dynamic state-bound sort is active, and why an appending list
|
|
1605
|
+
// skips it too.
|
|
1606
|
+
if (!usage.dynamicSort && !usage.infiniteScroll) {
|
|
1317
1607
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(wrapInitialDataWithUrlFilterGuard(types.binaryExpression('===', types.identifier(vars.pageStateVar), types.numericLiteral(1)), usage), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), cachedInitialData ? types.identifier(cachedInitialData) : types.identifier('undefined')))));
|
|
1318
1608
|
}
|
|
1319
|
-
// Add key — sort is intentionally NOT included; see paginated+search updater
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1609
|
+
// Add key — sort is intentionally NOT included; see paginated+search updater,
|
|
1610
|
+
// which also explains why an appending list keys on nothing at all (there is
|
|
1611
|
+
// no query here to vary it by; a filter change restarts the accumulator
|
|
1612
|
+
// through its signature instead).
|
|
1613
|
+
if (!usage.infiniteScroll) {
|
|
1614
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
|
|
1615
|
+
types.templateElement({
|
|
1616
|
+
raw: "".concat(usage.dataSourceIdentifier, "-page-"),
|
|
1617
|
+
cooked: "".concat(usage.dataSourceIdentifier, "-page-"),
|
|
1618
|
+
}),
|
|
1619
|
+
types.templateElement({ raw: '', cooked: '' }),
|
|
1620
|
+
], [types.identifier(vars.pageStateVar)]))));
|
|
1621
|
+
}
|
|
1327
1622
|
// Add fetchData
|
|
1328
|
-
dp.openingElement.attributes.push(
|
|
1623
|
+
dp.openingElement.attributes.push(buildFetchDataForUsage(fileName, usage));
|
|
1329
1624
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('persistDataDuringLoading'), types.jsxExpressionContainer(types.booleanLiteral(true))));
|
|
1330
1625
|
}
|
|
1331
1626
|
function updateDataProviderForSearchOnly(dp, usage, vars, fileName, cacheDeclarations) {
|
|
@@ -1458,7 +1753,10 @@ function stabilizeDataProviderWithoutRepeater(dp) {
|
|
|
1458
1753
|
// Replace the params attribute
|
|
1459
1754
|
attrs[paramsAttrIndex] = types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(memoizedParams));
|
|
1460
1755
|
}
|
|
1461
|
-
function createFetchDataAttribute(fileName, cache
|
|
1756
|
+
function createFetchDataAttribute(fileName, cache,
|
|
1757
|
+
// When set, the resolved value is every page fetched so far rather than just
|
|
1758
|
+
// the page that was requested — see `infinite-scroll.ts`.
|
|
1759
|
+
accumulate) {
|
|
1462
1760
|
var fetchCall = types.callExpression(types.identifier('fetch'), [
|
|
1463
1761
|
types.templateLiteral([
|
|
1464
1762
|
types.templateElement({
|
|
@@ -1479,7 +1777,16 @@ function createFetchDataAttribute(fileName, cache) {
|
|
|
1479
1777
|
// The uncached tail is left exactly as it has always been emitted, so a
|
|
1480
1778
|
// project that does not cache produces byte-identical output.
|
|
1481
1779
|
var uncachedTail = types.arrowFunctionExpression([types.identifier('response')], types.optionalMemberExpression(types.identifier('response'), types.identifier('data'), false, true));
|
|
1482
|
-
|
|
1780
|
+
// ⛔ Accumulation and the client cache are mutually exclusive: a cache hit
|
|
1781
|
+
// short-circuits the fetch and hands back one page's rows, which would drop
|
|
1782
|
+
// every page already accumulated. The caller suppresses the client cache for
|
|
1783
|
+
// an appending list, so this branch never sees both.
|
|
1784
|
+
var responseTail = accumulate
|
|
1785
|
+
? buildAccumulatingResponseHandler(getInfiniteScrollVars(accumulate.usage.index), accumulate.usage.perPage)
|
|
1786
|
+
: cache
|
|
1787
|
+
? buildCacheStoreThen(cache)
|
|
1788
|
+
: uncachedTail;
|
|
1789
|
+
var networkChain = types.callExpression(types.memberExpression(parsedJson, types.identifier('then')), [responseTail]);
|
|
1483
1790
|
var arrow = cache
|
|
1484
1791
|
? types.arrowFunctionExpression([types.identifier('params')], buildCachedFetchBody(networkChain, cache))
|
|
1485
1792
|
: types.arrowFunctionExpression([types.identifier('params')], networkChain);
|
|
@@ -1495,45 +1802,91 @@ function wireSearchInput(inputNode, vars) {
|
|
|
1495
1802
|
// Add value
|
|
1496
1803
|
inputNode.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(types.identifier(vars.searchQueryVar))));
|
|
1497
1804
|
}
|
|
1805
|
+
/**
|
|
1806
|
+
* The `fetchData` attribute for one paginated usage.
|
|
1807
|
+
*
|
|
1808
|
+
* ⛔ An appending list gets no CLIENT cache: a cache hit resolves with one
|
|
1809
|
+
* page's rows without going through the accumulator, which would silently
|
|
1810
|
+
* discard every page already loaded. The SERVER cache is untouched — it sits
|
|
1811
|
+
* behind the API route and returns the same page either way.
|
|
1812
|
+
*/
|
|
1813
|
+
function buildFetchDataForUsage(fileName, usage) {
|
|
1814
|
+
var _a;
|
|
1815
|
+
if (usage.infiniteScroll) {
|
|
1816
|
+
return createFetchDataAttribute(fileName, undefined, { usage: usage });
|
|
1817
|
+
}
|
|
1818
|
+
return createFetchDataAttribute(fileName, ((_a = usage.cache) === null || _a === void 0 ? void 0 : _a.client) ? usage.cache : undefined);
|
|
1819
|
+
}
|
|
1820
|
+
/**
|
|
1821
|
+
* Wires the authored Load More button of an appending list.
|
|
1822
|
+
*
|
|
1823
|
+
* Disabled — not hidden — when there is nothing left to load, so the author's
|
|
1824
|
+
* styling of the finished state is theirs to decide, and so the control does
|
|
1825
|
+
* not vanish from under the visitor's cursor mid-click.
|
|
1826
|
+
*/
|
|
1827
|
+
function wireLoadMoreButton(paginationNode, usage, vars, hasLoadingState) {
|
|
1828
|
+
if (!usage.infiniteScrollLoadMore) {
|
|
1829
|
+
return;
|
|
1830
|
+
}
|
|
1831
|
+
var button = findPaginationControl(paginationNode, 'load-more');
|
|
1832
|
+
if (!button) {
|
|
1833
|
+
return;
|
|
1834
|
+
}
|
|
1835
|
+
var infiniteVars = getInfiniteScrollVars(usage.index);
|
|
1836
|
+
convertControlToButton(button);
|
|
1837
|
+
setJSXExpressionAttribute(button, 'onClick', types.arrowFunctionExpression([],
|
|
1838
|
+
// The advance statement is an expression statement; the handler needs the
|
|
1839
|
+
// expression itself.
|
|
1840
|
+
buildAdvancePageStatement(usage, vars).expression));
|
|
1841
|
+
// The in-flight term is only referenced when the provider declared it —
|
|
1842
|
+
// a mapper with no loading branch never gets `ds_N_isFetching`.
|
|
1843
|
+
var notHasMore = types.unaryExpression('!', types.identifier(infiniteVars.hasMoreVar), true);
|
|
1844
|
+
setJSXExpressionAttribute(button, 'disabled', hasLoadingState
|
|
1845
|
+
? types.logicalExpression('||', notHasMore, types.identifier(getLoadingStateVars(usage.index).isFetchingVar))
|
|
1846
|
+
: notHasMore);
|
|
1847
|
+
}
|
|
1848
|
+
/**
|
|
1849
|
+
* Wires one mapper's pagination container according to the mode it is in, and
|
|
1850
|
+
* removes the controls belonging to the other modes.
|
|
1851
|
+
*
|
|
1852
|
+
* The builder never deletes a control when the author switches mode — doing so
|
|
1853
|
+
* would throw away their styling — so the container can hold a superset of what
|
|
1854
|
+
* any one mode needs. Pruning here is what keeps a Previous/Next list from
|
|
1855
|
+
* rendering a dead numbered strip, and an infinite list from rendering page
|
|
1856
|
+
* buttons beside its Load More.
|
|
1857
|
+
*/
|
|
1858
|
+
function wirePaginationWidget(paginationNode, usage, vars, hasLoadingState) {
|
|
1859
|
+
if (usage.infiniteScroll) {
|
|
1860
|
+
// Only the Load More button survives; page controls make no sense for a
|
|
1861
|
+
// list the visitor never leaves.
|
|
1862
|
+
dropInactivePaginationControls(paginationNode, ['load-more']);
|
|
1863
|
+
wireLoadMoreButton(paginationNode, usage, vars, hasLoadingState);
|
|
1864
|
+
return;
|
|
1865
|
+
}
|
|
1866
|
+
var activeKinds = usage.paginationMode === 'numbered'
|
|
1867
|
+
? ['first', 'previous', 'pages', 'page', 'ellipsis', 'next', 'last']
|
|
1868
|
+
: ['previous', 'next'];
|
|
1869
|
+
dropInactivePaginationControls(paginationNode, activeKinds);
|
|
1870
|
+
wirePaginationButtons(paginationNode, usage, vars);
|
|
1871
|
+
if (usage.paginationMode === 'numbered') {
|
|
1872
|
+
var _a = getPageAccessors(usage, vars), currentPageExpr = _a.currentPageExpr, buildSetPageStatement = _a.buildSetPageStatement;
|
|
1873
|
+
var numberedVars = {
|
|
1874
|
+
index: usage.index,
|
|
1875
|
+
maxPagesVar: vars.maxPagesStateVar,
|
|
1876
|
+
currentPageExpr: currentPageExpr,
|
|
1877
|
+
buildSetPageStatement: buildSetPageStatement,
|
|
1878
|
+
};
|
|
1879
|
+
wireNumberedPagination(paginationNode, numberedVars);
|
|
1880
|
+
}
|
|
1881
|
+
}
|
|
1498
1882
|
function wirePaginationButtons(paginationNode, usage, vars) {
|
|
1499
|
-
//
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
return null;
|
|
1504
|
-
}
|
|
1505
|
-
if (node.type === 'JSXElement') {
|
|
1506
|
-
var classAttr = (_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.attributes) === null || _b === void 0 ? void 0 : _b.find(function (attr) { return attr.type === 'JSXAttribute' && attr.name.name === 'className'; });
|
|
1507
|
-
var className = ((_c = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _c === void 0 ? void 0 : _c.value) || ((_e = (_d = classAttr === null || classAttr === void 0 ? void 0 : classAttr.value) === null || _d === void 0 ? void 0 : _d.expression) === null || _e === void 0 ? void 0 : _e.value) || '';
|
|
1508
|
-
if (className.includes(direction)) {
|
|
1509
|
-
return node;
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
if (node.children && Array.isArray(node.children)) {
|
|
1513
|
-
for (var _i = 0, _f = node.children; _i < _f.length; _i++) {
|
|
1514
|
-
var c = _f[_i];
|
|
1515
|
-
var found = findButton(c, direction);
|
|
1516
|
-
if (found) {
|
|
1517
|
-
return found;
|
|
1518
|
-
}
|
|
1519
|
-
}
|
|
1520
|
-
}
|
|
1521
|
-
return null;
|
|
1522
|
-
};
|
|
1523
|
-
var prevButton = findButton(paginationNode, 'previous');
|
|
1524
|
-
var nextButton = findButton(paginationNode, 'next');
|
|
1883
|
+
// Marker attribute first, class-name substring second — projects generated
|
|
1884
|
+
// before the marker existed carry only the class name.
|
|
1885
|
+
var prevButton = findPaginationControl(paginationNode, 'previous', 'previous');
|
|
1886
|
+
var nextButton = findPaginationControl(paginationNode, 'next', 'next');
|
|
1525
1887
|
var isCombinedState = usage.category === 'paginated+search';
|
|
1526
1888
|
if (prevButton) {
|
|
1527
|
-
|
|
1528
|
-
prevButton.openingElement.name.name = 'button';
|
|
1529
|
-
if (prevButton.closingElement) {
|
|
1530
|
-
prevButton.closingElement.name.name = 'button';
|
|
1531
|
-
}
|
|
1532
|
-
// Add type="button"
|
|
1533
|
-
var hasType = prevButton.openingElement.attributes.some(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) === 'type'; });
|
|
1534
|
-
if (!hasType) {
|
|
1535
|
-
prevButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('type'), types.stringLiteral('button')));
|
|
1536
|
-
}
|
|
1889
|
+
convertControlToButton(prevButton);
|
|
1537
1890
|
// Add onClick
|
|
1538
1891
|
prevButton.openingElement.attributes = prevButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'onClick'; });
|
|
1539
1892
|
if (isCombinedState) {
|
|
@@ -1562,14 +1915,7 @@ function wirePaginationButtons(paginationNode, usage, vars) {
|
|
|
1562
1915
|
}
|
|
1563
1916
|
}
|
|
1564
1917
|
if (nextButton) {
|
|
1565
|
-
nextButton
|
|
1566
|
-
if (nextButton.closingElement) {
|
|
1567
|
-
nextButton.closingElement.name.name = 'button';
|
|
1568
|
-
}
|
|
1569
|
-
var hasType = nextButton.openingElement.attributes.some(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) === 'type'; });
|
|
1570
|
-
if (!hasType) {
|
|
1571
|
-
nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('type'), types.stringLiteral('button')));
|
|
1572
|
-
}
|
|
1918
|
+
convertControlToButton(nextButton);
|
|
1573
1919
|
nextButton.openingElement.attributes = nextButton.openingElement.attributes.filter(function (a) { var _a; return ((_a = a.name) === null || _a === void 0 ? void 0 : _a.name) !== 'onClick'; });
|
|
1574
1920
|
if (isCombinedState) {
|
|
1575
1921
|
nextButton.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('onClick'), types.jsxExpressionContainer(types.arrowFunctionExpression([], types.callExpression(types.identifier(vars.setCombinedStateVar), [
|
|
@@ -1824,8 +2170,7 @@ function updateGetStaticProps(chunks, registry, dependencies, folderPath) {
|
|
|
1824
2170
|
]));
|
|
1825
2171
|
// Add import dependency for the fetcher
|
|
1826
2172
|
if (!dependencies[fetcherImportName]) {
|
|
1827
|
-
var
|
|
1828
|
-
var relativePrefix = '../'.repeat(depth);
|
|
2173
|
+
var relativePrefix = GenericUtils.generatePageToRootPrefix({ folderPath: folderPath });
|
|
1829
2174
|
dependencies[fetcherImportName] = {
|
|
1830
2175
|
type: 'local',
|
|
1831
2176
|
path: "".concat(relativePrefix, "utils/data-sources/").concat(fileName),
|
|
@@ -1939,8 +2284,7 @@ function updateGetStaticProps(chunks, registry, dependencies, folderPath) {
|
|
|
1939
2284
|
}
|
|
1940
2285
|
// Add import dependency for the fetcher
|
|
1941
2286
|
if (!dependencies[fetcherImportName]) {
|
|
1942
|
-
var
|
|
1943
|
-
var relativePrefix = '../'.repeat(depth);
|
|
2287
|
+
var relativePrefix = GenericUtils.generatePageToRootPrefix({ folderPath: folderPath });
|
|
1944
2288
|
dependencies[fetcherImportName] = {
|
|
1945
2289
|
type: 'local',
|
|
1946
2290
|
path: "".concat(relativePrefix, "utils/data-sources/").concat(fileName),
|