@wix/editor-react-components 1.2546.0 → 1.2547.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.
@@ -2,6 +2,7 @@ import { default as React } from 'react';
2
2
  type Props = {
3
3
  onLoadMore: () => Promise<void>;
4
4
  isLoading: boolean;
5
+ disabled?: boolean;
5
6
  label?: string;
6
7
  };
7
8
  export declare const LoadMoreButton: React.FC<Props>;
@@ -4,65 +4,55 @@ import { f as convertA11yKeysToHtmlFormat } from "../chunks/a11y.js";
4
4
  import { d as directionStyles } from "../chunks/direction.module.js";
5
5
  import { p as presetWrapperStyles } from "../chunks/presetWrapper.module.js";
6
6
  import { D as DEFAULT_ITEMS_PER_ROW, C as COLUMN_COUNT_CSS_VAR, T as TestIds, s as semanticClassNames } from "../chunks/constants23.js";
7
- import React__default, { useState, useRef, useEffect, useCallback, forwardRef } from "react";
8
- const useAsyncLoadMore = (onLoadMore, itemsLength, isLoadingProp) => {
9
- const [isLoading, setIsLoading] = useState(false);
10
- const [hasMore, setHasMore] = useState(true);
11
- const itemsLengthAtLastLoad = useRef(null);
12
- useEffect(() => {
13
- setHasMore(true);
14
- itemsLengthAtLastLoad.current = null;
15
- }, [onLoadMore]);
16
- useEffect(() => {
17
- if (itemsLengthAtLastLoad.current === null) return;
18
- setHasMore(itemsLength > itemsLengthAtLastLoad.current);
19
- itemsLengthAtLastLoad.current = null;
20
- }, [itemsLength]);
21
- const handleLoadMore = useCallback(async () => {
22
- itemsLengthAtLastLoad.current = itemsLength;
23
- setIsLoading(true);
7
+ import React__default, { useState, useRef, useCallback, useEffect, forwardRef } from "react";
8
+ const useAsyncLoadMore = (onLoadMore, itemsLength, isIntersecting, isLoadingProp) => {
9
+ const [internalLoading, setInternalLoading] = useState(false);
10
+ const [requested, setRequested] = useState(false);
11
+ const inFlightRef = useRef(false);
12
+ const isLoading = isLoadingProp ?? internalLoading;
13
+ const load = useCallback(async () => {
14
+ if (inFlightRef.current) {
15
+ return;
16
+ }
17
+ inFlightRef.current = true;
18
+ setRequested(true);
19
+ setInternalLoading(true);
24
20
  try {
25
21
  await (onLoadMore == null ? void 0 : onLoadMore());
26
22
  } catch {
27
23
  } finally {
28
- setIsLoading(false);
29
- if (itemsLengthAtLastLoad.current !== null) {
30
- setHasMore(false);
31
- itemsLengthAtLastLoad.current = null;
32
- }
24
+ inFlightRef.current = false;
25
+ setInternalLoading(false);
33
26
  }
34
- }, [onLoadMore, itemsLength]);
35
- return { isLoading: isLoadingProp ?? isLoading, handleLoadMore, hasMore };
36
- };
37
- const useLoadMoreObserver = ({
38
- enabled,
39
- onLoadMore
40
- }) => {
41
- const sentinelRef = useRef(null);
42
- const onLoadMoreRef = useRef(onLoadMore);
43
- useEffect(() => {
44
- onLoadMoreRef.current = onLoadMore;
45
27
  }, [onLoadMore]);
46
28
  useEffect(() => {
47
- if (!enabled) {
29
+ setRequested(false);
30
+ }, [itemsLength]);
31
+ useEffect(() => {
32
+ if (!onLoadMore || !isIntersecting || isLoading || internalLoading || requested) {
48
33
  return;
49
34
  }
50
- if (!sentinelRef.current) {
35
+ load();
36
+ }, [onLoadMore, isIntersecting, isLoading, internalLoading, requested, load]);
37
+ const hasReachedEnd = requested && !isLoading && !internalLoading;
38
+ return { isLoading, load, hasReachedEnd };
39
+ };
40
+ const useLoadMoreObserver = (enabled) => {
41
+ const sentinelRef = useRef(null);
42
+ const [isIntersecting, setIsIntersecting] = useState(false);
43
+ useEffect(() => {
44
+ if (!enabled || !sentinelRef.current) {
45
+ setIsIntersecting(false);
51
46
  return;
52
47
  }
53
48
  const observer = new IntersectionObserver(
54
- ([entry]) => {
55
- var _a;
56
- if (entry.isIntersecting) {
57
- (_a = onLoadMoreRef.current) == null ? void 0 : _a.call(onLoadMoreRef);
58
- }
59
- },
49
+ ([entry]) => setIsIntersecting(entry.isIntersecting),
60
50
  { rootMargin: "200px" }
61
51
  );
62
52
  observer.observe(sentinelRef.current);
63
53
  return () => observer.disconnect();
64
54
  }, [enabled]);
65
- return sentinelRef;
55
+ return [sentinelRef, isIntersecting];
66
56
  };
67
57
  const useItemsPerRow = (shouldMeasure) => {
68
58
  const ref = useRef(null);
@@ -454,6 +444,7 @@ const LiveAnnouncer = ({
454
444
  const LoadMoreButton = ({
455
445
  onLoadMore,
456
446
  isLoading,
447
+ disabled,
457
448
  label = "Load more items"
458
449
  }) => /* @__PURE__ */ jsx(
459
450
  "button",
@@ -462,7 +453,7 @@ const LoadMoreButton = ({
462
453
  "data-testid": TestIds.loadMoreButton,
463
454
  className: styles.loadMoreTrigger,
464
455
  onClick: onLoadMore,
465
- disabled: isLoading,
456
+ disabled: disabled ?? isLoading,
466
457
  "aria-busy": isLoading || void 0,
467
458
  children: label
468
459
  }
@@ -488,16 +479,17 @@ const Repeater = (props) => {
488
479
  emptyState
489
480
  } = props;
490
481
  const presetsWrapperProps = ((_a = props.wix) == null ? void 0 : _a.presetsWrapperProps) || {};
491
- const { isLoading, handleLoadMore, hasMore } = useAsyncLoadMore(
482
+ const showsEmptyState = items.length === 0 && !!emptyState;
483
+ const [sentinelRef, isIntersecting] = useLoadMoreObserver(
484
+ !!onLoadMore && !showsEmptyState
485
+ );
486
+ const { isLoading, load, hasReachedEnd } = useAsyncLoadMore(
492
487
  onLoadMore,
493
488
  items.length,
489
+ isIntersecting,
494
490
  isLoadingProp
495
491
  );
496
492
  const [ulRef, itemsPerRow] = useItemsPerRow(!!onLoadMore);
497
- const sentinelRef = useLoadMoreObserver({
498
- enabled: !!onLoadMore && hasMore,
499
- onLoadMore: onLoadMore ? handleLoadMore : void 0
500
- });
501
493
  if (!items.length && emptyState) {
502
494
  return null;
503
495
  }
@@ -551,8 +543,15 @@ const Repeater = (props) => {
551
543
  ]
552
544
  }
553
545
  ),
554
- !!onLoadMore && hasMore && /* @__PURE__ */ jsxs(Fragment, { children: [
555
- /* @__PURE__ */ jsx(LoadMoreButton, { onLoadMore: handleLoadMore, isLoading }),
546
+ !!onLoadMore && /* @__PURE__ */ jsxs(Fragment, { children: [
547
+ /* @__PURE__ */ jsx(
548
+ LoadMoreButton,
549
+ {
550
+ onLoadMore: load,
551
+ isLoading,
552
+ disabled: isLoading || hasReachedEnd
553
+ }
554
+ ),
556
555
  /* @__PURE__ */ jsx(
557
556
  "div",
558
557
  {
@@ -567,7 +566,7 @@ const Repeater = (props) => {
567
566
  LiveAnnouncer,
568
567
  {
569
568
  itemCount: items.length,
570
- hasMore,
569
+ hasMore: !hasReachedEnd,
571
570
  onLoadMore
572
571
  }
573
572
  )
@@ -1,5 +1,5 @@
1
- export declare const useAsyncLoadMore: (onLoadMore: (() => Promise<void>) | undefined, itemsLength: number, isLoadingProp?: boolean) => {
1
+ export declare const useAsyncLoadMore: (onLoadMore: (() => Promise<void>) | undefined, itemsLength: number, isIntersecting: boolean, isLoadingProp?: boolean) => {
2
2
  isLoading: boolean;
3
- handleLoadMore: () => Promise<void>;
4
- hasMore: boolean;
3
+ load: () => Promise<void>;
4
+ hasReachedEnd: boolean;
5
5
  };
@@ -1,6 +1 @@
1
- type UseLoadMoreObserverArgs = {
2
- enabled: boolean;
3
- onLoadMore: (() => void) | undefined;
4
- };
5
- export declare const useLoadMoreObserver: ({ enabled, onLoadMore, }: UseLoadMoreObserverArgs) => import('react').RefObject<HTMLDivElement>;
6
- export {};
1
+ export declare const useLoadMoreObserver: (enabled: boolean) => readonly [import('react').RefObject<HTMLDivElement>, boolean];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@wix/editor-react-components",
3
- "version": "1.2546.0",
3
+ "version": "1.2547.0",
4
4
  "description": "React components for the Wix Editor",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -199,5 +199,5 @@
199
199
  "registry": "https://registry.npmjs.org/",
200
200
  "access": "public"
201
201
  },
202
- "falconPackageHash": "6832479dbb355187b2c0df1c8c54e23813710645d19f71fbc0dd9b98"
202
+ "falconPackageHash": "c7ba27661995f7a2dd1bc00316e63d251c0775294e71c8fd98523b71"
203
203
  }