@powerportalspro/react-fluent 6.0.0 → 6.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -4635,7 +4635,11 @@ interface MainGridProps {
4635
4635
  * Set to `'virtualize'` for infinite-scroll — the pager footer is
4636
4636
  * hidden, rows accumulate across page boundaries, and the next page
4637
4637
  * fetches automatically when the user scrolls past the rendered
4638
- * bottom.
4638
+ * bottom. Pages are requested sequentially with the previous page's
4639
+ * Dataverse paging cookie (cursor paging), and loading stops when the
4640
+ * server reports no more records — not when the accumulated rows reach
4641
+ * the total count, which can never happen if per-row permission
4642
+ * handlers drop rows after Dataverse has counted them.
4639
4643
  */
4640
4644
  pagingMode?: PagingMode;
4641
4645
  /**
package/dist/index.d.ts CHANGED
@@ -4635,7 +4635,11 @@ interface MainGridProps {
4635
4635
  * Set to `'virtualize'` for infinite-scroll — the pager footer is
4636
4636
  * hidden, rows accumulate across page boundaries, and the next page
4637
4637
  * fetches automatically when the user scrolls past the rendered
4638
- * bottom.
4638
+ * bottom. Pages are requested sequentially with the previous page's
4639
+ * Dataverse paging cookie (cursor paging), and loading stops when the
4640
+ * server reports no more records — not when the accumulated rows reach
4641
+ * the total count, which can never happen if per-row permission
4642
+ * handlers drop rows after Dataverse has counted them.
4639
4643
  */
4640
4644
  pagingMode?: PagingMode;
4641
4645
  /**
package/dist/index.js CHANGED
@@ -8304,6 +8304,36 @@ function MainGridVirtualizeFooter({
8304
8304
  ] });
8305
8305
  }
8306
8306
 
8307
+ // src/grids/virtualize-paging.ts
8308
+ function hasMoreRowsToLoad(state) {
8309
+ if (state.moreRecords === false) return false;
8310
+ if (state.moreRecords === true) return true;
8311
+ if (state.lastPageEmpty) return false;
8312
+ if (state.totalCount === void 0) return true;
8313
+ return state.accumulatedCount < state.totalCount;
8314
+ }
8315
+ var VirtualizePagingCookies = class {
8316
+ key;
8317
+ byPage = /* @__PURE__ */ new Map();
8318
+ /** Store the cookie the response for `page` came back with (no-op for a null / empty cookie). */
8319
+ record(key, page, cookie) {
8320
+ if (this.key !== key) {
8321
+ this.key = key;
8322
+ this.byPage = /* @__PURE__ */ new Map();
8323
+ }
8324
+ if (cookie) this.byPage.set(page, cookie);
8325
+ }
8326
+ /**
8327
+ * The cookie to send when requesting `page` under `key`: the one page
8328
+ * `page - 1` returned, or `undefined` when it isn't known (page 1, a
8329
+ * non-sequential jump, or a key the store has no cookies for).
8330
+ */
8331
+ cookieFor(key, page) {
8332
+ if (this.key !== key || page <= 1) return void 0;
8333
+ return this.byPage.get(page - 1);
8334
+ }
8335
+ };
8336
+
8307
8337
  // src/grids/persisted-grid-state.ts
8308
8338
  function readPersistedGridStateFromUrl(queryParameterName) {
8309
8339
  if (!queryParameterName) return null;
@@ -8835,8 +8865,22 @@ function MainGridImpl({
8835
8865
  `[MainGrid] Declared <GridColumn> children override the column projection of the supplied fetchXml (columns: ${columnsKey.split(",").join(", ")}). Drop the children \u2014 or remove the conflicting <attribute> elements from the fetchXml \u2014 to silence this message.`
8836
8866
  );
8837
8867
  }, [columnsKey, useInlineFetchXml]);
8868
+ const accumulatorResetKey = useMemo(
8869
+ () => [
8870
+ resolvedViewId ?? "",
8871
+ useInlineFetchXml ? inlineFetchXml ?? "" : "",
8872
+ debouncedSearchText,
8873
+ sort.map((s) => `${s.columnName}:${s.descending ? "d" : "a"}`).join("|"),
8874
+ filtersKey,
8875
+ pageSize,
8876
+ tableName ?? ""
8877
+ ].join("|"),
8878
+ [resolvedViewId, useInlineFetchXml, inlineFetchXml, debouncedSearchText, sort, filtersKey, pageSize, tableName]
8879
+ );
8880
+ const [virtualizeCookies] = useState(() => new VirtualizePagingCookies());
8838
8881
  const searchRequest = useMemo(() => {
8839
8882
  const trimmed = debouncedSearchText.trim();
8883
+ const pagingCookie = isVirtualize ? virtualizeCookies.cookieFor(accumulatorResetKey, page) : void 0;
8840
8884
  return {
8841
8885
  ...useInlineFetchXml && inlineFetchXml ? { fetchXml: inlineFetchXml } : resolvedViewId !== void 0 && { viewId: resolvedViewId },
8842
8886
  ...trimmed && { searchText: trimmed },
@@ -8856,7 +8900,8 @@ function MainGridImpl({
8856
8900
  },
8857
8901
  ...columnsOverride && { columns: [...columnsOverride] },
8858
8902
  pageNumber: page,
8859
- pageSize
8903
+ pageSize,
8904
+ ...pagingCookie && { pagingCookie }
8860
8905
  };
8861
8906
  }, [
8862
8907
  resolvedViewId,
@@ -8867,7 +8912,9 @@ function MainGridImpl({
8867
8912
  page,
8868
8913
  pageSize,
8869
8914
  filtersKey,
8870
- columnsKey
8915
+ columnsKey,
8916
+ isVirtualize,
8917
+ accumulatorResetKey
8871
8918
  ]);
8872
8919
  const transformPending = !!transformViewAsync || isCustomActiveView;
8873
8920
  const recordsResult = useGridData(searchRequest, {
@@ -9164,18 +9211,6 @@ function MainGridImpl({
9164
9211
  ]);
9165
9212
  const pageRecords = dataSource ? dataSource.rows : recordsResult.data?.tableRecords ?? EMPTY_RECORDS;
9166
9213
  const [accumulatedRows, setAccumulatedRows] = useState(null);
9167
- const accumulatorResetKey = useMemo(
9168
- () => [
9169
- resolvedViewId ?? "",
9170
- useInlineFetchXml ? inlineFetchXml ?? "" : "",
9171
- debouncedSearchText,
9172
- sort.map((s) => `${s.columnName}:${s.descending ? "d" : "a"}`).join("|"),
9173
- filtersKey,
9174
- pageSize,
9175
- tableName ?? ""
9176
- ].join("|"),
9177
- [resolvedViewId, useInlineFetchXml, inlineFetchXml, debouncedSearchText, sort, filtersKey, pageSize, tableName]
9178
- );
9179
9214
  const resetVirtualizedView = useCallback(() => {
9180
9215
  setAccumulatedRows([]);
9181
9216
  setPage(1);
@@ -9201,6 +9236,12 @@ function MainGridImpl({
9201
9236
  return [...base, ...additions];
9202
9237
  });
9203
9238
  }, [isVirtualize, recordsResult.status, pageRecords]);
9239
+ useEffect(() => {
9240
+ if (!isVirtualize) return;
9241
+ const landed = recordsResult.data;
9242
+ if (!landed) return;
9243
+ virtualizeCookies.record(accumulatorResetKey, page, landed.pagingInfo?.pagingCookie);
9244
+ }, [isVirtualize, recordsResult.data]);
9204
9245
  const data = isVirtualize ? accumulatedRows ?? EMPTY_RECORDS : pageRecords;
9205
9246
  const [pendingRowUpdates, setPendingRowUpdates] = useState(() => /* @__PURE__ */ new Map());
9206
9247
  const [pendingRowCreates, setPendingRowCreates] = useState(() => []);
@@ -9681,7 +9722,15 @@ function MainGridImpl({
9681
9722
  if (raw == null) return void 0;
9682
9723
  return typeof raw === "number" ? raw : Number(raw);
9683
9724
  })();
9684
- const hasMoreRowsToLoad = isVirtualize && (totalCount === void 0 || (accumulatedRows?.length ?? 0) < totalCount);
9725
+ const hasMoreRowsToLoad2 = isVirtualize && hasMoreRowsToLoad({
9726
+ accumulatedCount: accumulatedRows?.length ?? 0,
9727
+ totalCount,
9728
+ moreRecords: dataSource ? dataSource.moreRecords : recordsResult.data?.pagingInfo?.moreRecords,
9729
+ // "A page has landed and it carried no rows." In standalone mode
9730
+ // `data` is only ever defined for a landed response (errors wipe it);
9731
+ // the datasource has no data handle, so idle-after-success stands in.
9732
+ lastPageEmpty: dataSource ? dataSource.status === QueryStatus.Success && !dataSource.isFetching && dataSource.rows.length === 0 : recordsResult.data !== void 0 && pageRecords.length === 0
9733
+ });
9685
9734
  useEffect(() => {
9686
9735
  if (!isVirtualize) return;
9687
9736
  const sentinel = loadMoreSentinelRef.current;
@@ -9692,7 +9741,7 @@ function MainGridImpl({
9692
9741
  const entry = entries[0];
9693
9742
  if (!entry?.isIntersecting) return;
9694
9743
  if (recordsResult.isFetching) return;
9695
- if (!hasMoreRowsToLoad) return;
9744
+ if (!hasMoreRowsToLoad2) return;
9696
9745
  setPage(page + 1);
9697
9746
  },
9698
9747
  {
@@ -9705,7 +9754,7 @@ function MainGridImpl({
9705
9754
  );
9706
9755
  observer.observe(sentinel);
9707
9756
  return () => observer.disconnect();
9708
- }, [isVirtualize, hasMoreRowsToLoad, recordsResult.isFetching, page, setPage]);
9757
+ }, [isVirtualize, hasMoreRowsToLoad2, recordsResult.isFetching, page, setPage]);
9709
9758
  const handlePageChange = (nextPage) => {
9710
9759
  if (nextPage === page) return;
9711
9760
  setPage(nextPage);
@@ -10325,7 +10374,7 @@ function MainGridImpl({
10325
10374
  }
10326
10375
  ),
10327
10376
  displayedData.length === 0 && /* @__PURE__ */ jsx("div", { className: styles.emptyStateRow, children: t("app.components.grid.empty-content") }),
10328
- isVirtualize && hasMoreRowsToLoad && // No spinner here: the full-body `refetchScrim` overlay below is the
10377
+ isVirtualize && hasMoreRowsToLoad2 && // No spinner here: the full-body `refetchScrim` overlay below is the
10329
10378
  // single load indicator. Rendering a `size="tiny"` spinner in the
10330
10379
  // sentinel as well meant a deps-change refetch (refresh / sort /
10331
10380
  // search / view switch) — which resets the accumulator to empty and
@@ -14445,6 +14494,18 @@ var useStyles12 = makeStyles({
14445
14494
  },
14446
14495
  // Scroll viewport for the merged grid so a tall result set scrolls inside the dialog.
14447
14496
  dialogGrid: { maxHeight: "60vh", overflowY: "auto", overflowX: "auto" },
14497
+ // Merged-snapshot cells. Keys and sources are long single tokens (dotted keys,
14498
+ // backslash-only absolute paths) with no natural break opportunity, so without
14499
+ // this the text paints straight over the neighbouring column. `overflow-wrap:
14500
+ // anywhere` (not just `break-word`) is what makes the flex cell honour its
14501
+ // column width — it counts the soft breaks toward min-content — so the token
14502
+ // wraps inside the column instead of stretching it. Same recipe as
14503
+ // `sourceCell` in the per-source loads table above.
14504
+ mergedCell: {
14505
+ whiteSpace: "normal",
14506
+ overflowWrap: "anywhere",
14507
+ wordBreak: "break-word"
14508
+ },
14448
14509
  filterInput: { minWidth: "260px" },
14449
14510
  pager: { display: "flex", alignItems: "center", gap: tokens.spacingHorizontalS },
14450
14511
  grow: { flex: 1 },
@@ -14926,7 +14987,7 @@ function MergedSourcesDialog({
14926
14987
  size: "small",
14927
14988
  children: [
14928
14989
  /* @__PURE__ */ jsx(DataGridHeader, { children: /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderHeaderCell }) => /* @__PURE__ */ jsx(DataGridHeaderCell, { children: renderHeaderCell() }) }) }),
14929
- /* @__PURE__ */ jsx(DataGridBody, { children: ({ item, rowId }) => /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderCell }) => /* @__PURE__ */ jsx(DataGridCell, { children: renderCell(item) }) }, rowId) })
14990
+ /* @__PURE__ */ jsx(DataGridBody, { children: ({ item, rowId }) => /* @__PURE__ */ jsx(DataGridRow, { children: ({ renderCell }) => /* @__PURE__ */ jsx(DataGridCell, { className: styles.mergedCell, children: renderCell(item) }) }, rowId) })
14930
14991
  ]
14931
14992
  }
14932
14993
  ) })