@fluid-app/portal-sdk 0.1.228 → 0.1.229

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.
@@ -9,7 +9,7 @@ require("./es-nxOxb57F.cjs");
9
9
  require("./SearchSort-Hwga1dIi.cjs");
10
10
  require("./dist-5XPflEEG.cjs");
11
11
  require("./dist-FHf4OHgt.cjs");
12
- const require_ShareablesScreen = require("./ShareablesScreen-D6zYE_qj.cjs");
12
+ const require_ShareablesScreen = require("./ShareablesScreen-o6frhZUM.cjs");
13
13
  require("./PortalProductsApiProvider-Bb5B1Hv5.cjs");
14
14
  exports.ShareablesScreen = require_ShareablesScreen.ShareablesScreen;
15
15
  exports.shareablesScreenPropertySchema = require_ShareablesScreen.shareablesScreenPropertySchema;
@@ -44,12 +44,13 @@ function useRepContext() {
44
44
  const shareablesKeys = {
45
45
  media: {
46
46
  all: ["media"],
47
- list: (search, sortDesc, repContext) => [
47
+ list: (search, sortDesc, repContext, ownership) => [
48
48
  "media",
49
49
  "list",
50
50
  search,
51
51
  sortDesc,
52
- repContext
52
+ repContext,
53
+ ownership
53
54
  ],
54
55
  detail: (id, repContext) => [
55
56
  "media",
@@ -689,6 +690,37 @@ function ToggleButton({ active, label, onClick, children }) {
689
690
  });
690
691
  }
691
692
  //#endregion
693
+ //#region ../../shareables/ui/src/hooks/use-infinite-list-sentinel.ts
694
+ /**
695
+ * Wires a sentinel `<div>` to TanStack Query infinite-pagination state.
696
+ *
697
+ * Returns a ref the caller attaches to a 1px sentinel element rendered below
698
+ * the list. When the sentinel scrolls into view (with a 200px root margin)
699
+ * and the query has a next page, isn't already fetching, and hasn't errored,
700
+ * `fetchNextPage()` is invoked.
701
+ */
702
+ function useInfiniteListSentinel({ hasNextPage, isFetchingNextPage, fetchNextPage, error }) {
703
+ const sentinelRef = useRef(null);
704
+ useEffect(() => {
705
+ const target = sentinelRef.current;
706
+ if (!target) return;
707
+ const observer = new IntersectionObserver((entries) => {
708
+ if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage && !error) fetchNextPage();
709
+ }, {
710
+ threshold: 0,
711
+ rootMargin: "200px"
712
+ });
713
+ observer.observe(target);
714
+ return () => observer.disconnect();
715
+ }, [
716
+ fetchNextPage,
717
+ hasNextPage,
718
+ isFetchingNextPage,
719
+ error
720
+ ]);
721
+ return sentinelRef;
722
+ }
723
+ //#endregion
692
724
  //#region ../../shareables/ui/src/components/screens/ProductsScreen.tsx
693
725
  const PAGE_SIZE$5 = 24;
694
726
  const SORT_OPTIONS$1 = [
@@ -731,7 +763,6 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
731
763
  const [debouncedSearch, setDebouncedSearch] = useState("");
732
764
  const [sortValue, setSortValue] = useState("created_at_desc");
733
765
  const [viewMode, setViewMode] = useState("grid");
734
- const observerTarget = useRef(null);
735
766
  useEffect(() => {
736
767
  const timer = setTimeout(() => {
737
768
  setDebouncedSearch(searchTerm);
@@ -780,23 +811,12 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
780
811
  });
781
812
  const usePortal = !!fetchPortalProducts;
782
813
  const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage, error } = usePortal ? portalQuery : legacyQuery;
783
- const handleIntersect = useCallback((entries) => {
784
- if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) fetchNextPage();
785
- }, [
814
+ const sentinelRef = useInfiniteListSentinel({
786
815
  hasNextPage,
787
816
  isFetchingNextPage,
788
- fetchNextPage
789
- ]);
790
- useEffect(() => {
791
- const target = observerTarget.current;
792
- if (!target) return;
793
- const observer = new IntersectionObserver(handleIntersect, {
794
- threshold: .1,
795
- rootMargin: "200px"
796
- });
797
- observer.observe(target);
798
- return () => observer.disconnect();
799
- }, [handleIntersect]);
817
+ fetchNextPage,
818
+ error
819
+ });
800
820
  const products = useMemo(() => {
801
821
  if (!data) return [];
802
822
  if (usePortal) return data?.pages.flatMap((page) => (page.products ?? []).map((p) => ({
@@ -812,11 +832,16 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
812
832
  media_count: void 0
813
833
  })) ?? [];
814
834
  }, [data, usePortal]);
835
+ const footer = /* @__PURE__ */ jsxs(Fragment$1, { children: [isFetchingNextPage && /* @__PURE__ */ jsx("div", {
836
+ className: "flex justify-center py-4",
837
+ children: /* @__PURE__ */ jsx("div", { className: "border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" })
838
+ }), error && /* @__PURE__ */ jsx("p", {
839
+ className: "bg-destructive/10 text-destructive rounded-lg px-3 py-2",
840
+ children: "Failed to load products. Please try again."
841
+ })] });
815
842
  return /* @__PURE__ */ jsx(ShareableListLayout, {
816
843
  isLoading,
817
- error,
818
- errorMessage: "Failed to load products. Please try again.",
819
- isEmpty: products.length === 0,
844
+ isEmpty: !error && products.length === 0 && !isFetchingNextPage && !hasNextPage,
820
845
  emptyMessage: debouncedSearch ? "No products match your search." : "No products available.",
821
846
  filters: /* @__PURE__ */ jsxs("div", {
822
847
  className: "flex items-center justify-end gap-2",
@@ -836,11 +861,8 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
836
861
  })]
837
862
  }),
838
863
  loadingFilterShape: "search-view",
839
- footer: isFetchingNextPage && /* @__PURE__ */ jsx("div", {
840
- className: "flex justify-center py-4",
841
- children: /* @__PURE__ */ jsx("div", { className: "border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" })
842
- }),
843
- sentinelRef: observerTarget,
864
+ footer,
865
+ sentinelRef,
844
866
  children: viewMode === "grid" ? /* @__PURE__ */ jsx("div", {
845
867
  className: SHAREABLE_GRID_CLASS,
846
868
  children: products.map((product) => /* @__PURE__ */ jsx(ShareProductCard, {
@@ -1615,37 +1637,6 @@ function ProductDetailScreen({ productId, countryCode, fetchProduct: fetchPortal
1615
1637
  });
1616
1638
  }
1617
1639
  //#endregion
1618
- //#region ../../shareables/ui/src/hooks/use-infinite-list-sentinel.ts
1619
- /**
1620
- * Wires a sentinel `<div>` to TanStack Query infinite-pagination state.
1621
- *
1622
- * Returns a ref the caller attaches to a 1px sentinel element rendered below
1623
- * the list. When the sentinel scrolls into view (with a 200px root margin)
1624
- * and the query has a next page, isn't already fetching, and hasn't errored,
1625
- * `fetchNextPage()` is invoked.
1626
- */
1627
- function useInfiniteListSentinel({ hasNextPage, isFetchingNextPage, fetchNextPage, error }) {
1628
- const sentinelRef = useRef(null);
1629
- useEffect(() => {
1630
- const target = sentinelRef.current;
1631
- if (!target) return;
1632
- const observer = new IntersectionObserver((entries) => {
1633
- if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage && !error) fetchNextPage();
1634
- }, {
1635
- threshold: 0,
1636
- rootMargin: "200px"
1637
- });
1638
- observer.observe(target);
1639
- return () => observer.disconnect();
1640
- }, [
1641
- fetchNextPage,
1642
- hasNextPage,
1643
- isFetchingNextPage,
1644
- error
1645
- ]);
1646
- return sentinelRef;
1647
- }
1648
- //#endregion
1649
1640
  //#region ../../shareables/ui/src/components/OwnerFilterTabs.tsx
1650
1641
  function getFilteredEmptyMessage({ searchTerm, ownerFilter, hasOtherFilters = false, entityName = "items", defaultMessage = "Nothing available at the moment." }) {
1651
1642
  const isFiltered = ownerFilter !== "all" || hasOtherFilters;
@@ -1664,7 +1655,7 @@ function OwnerFilterTabs({ value, onValueChange, myLabel = "Mine" }) {
1664
1655
  children: "All"
1665
1656
  }),
1666
1657
  /* @__PURE__ */ jsx(TabsTrigger, {
1667
- value: "my",
1658
+ value: "mine",
1668
1659
  children: myLabel
1669
1660
  }),
1670
1661
  /* @__PURE__ */ jsx(TabsTrigger, {
@@ -1747,7 +1738,7 @@ function MediaListingScreen(_props) {
1747
1738
  title: "Media deleted",
1748
1739
  type: "success"
1749
1740
  });
1750
- queryClient.invalidateQueries({ queryKey: shareablesKeys.media.list(debouncedSearch, sortValue === "title_desc", repContext) });
1741
+ queryClient.invalidateQueries({ queryKey: shareablesKeys.media.all });
1751
1742
  setPendingDeleteId(null);
1752
1743
  },
1753
1744
  onError: (error) => {
@@ -1766,13 +1757,14 @@ function MediaListingScreen(_props) {
1766
1757
  const bffKind = kindFilter === "all" ? void 0 : kindFilter;
1767
1758
  const { data, isLoading, isFetchingNextPage, hasNextPage, fetchNextPage, error } = useInfiniteQuery({
1768
1759
  queryKey: [
1769
- ...shareablesKeys.media.list(debouncedSearch, sortValue === "title_desc", repContext),
1760
+ ...shareablesKeys.media.list(debouncedSearch, sortValue === "title_desc", repContext, ownerFilter),
1770
1761
  sortValue,
1771
1762
  kindFilter
1772
1763
  ],
1773
1764
  queryFn: async ({ pageParam }) => {
1774
1765
  return await api.media.list({
1775
1766
  "filter[title]": debouncedSearch || void 0,
1767
+ "filter[ownership]": ownerFilter,
1776
1768
  "filter[content_format]": bffKind,
1777
1769
  "page[cursor]": pageParam,
1778
1770
  "page[limit]": PAGE_SIZE$4,
@@ -1783,8 +1775,7 @@ function MediaListingScreen(_props) {
1783
1775
  initialPageParam: void 0,
1784
1776
  placeholderData: keepPreviousData
1785
1777
  });
1786
- const allItems = useMemo(() => data?.pages.flatMap((p) => p.media) ?? [], [data?.pages]);
1787
- const filteredItems = ownerFilter === "all" ? allItems : ownerFilter === "my" ? allItems.filter((item) => item.owner_type === "user") : allItems.filter((item) => item.owner_type === "company");
1778
+ const filteredItems = useMemo(() => data?.pages.flatMap((p) => p.media) ?? [], [data?.pages]);
1788
1779
  const sentinelRef = useInfiniteListSentinel({
1789
1780
  hasNextPage,
1790
1781
  isFetchingNextPage,
@@ -9089,7 +9080,7 @@ function PlaylistsListingScreen(_props) {
9089
9080
  const allPlaylists = useMemo(() => data?.pages.flatMap((page) => page.playlists) ?? [], [data?.pages]);
9090
9081
  const filteredPlaylists = useMemo(() => {
9091
9082
  if (ownerFilter === "all" || !user?.id) return allPlaylists;
9092
- if (ownerFilter === "my") return allPlaylists.filter((p) => p.user_id === user.id);
9083
+ if (ownerFilter === "mine") return allPlaylists.filter((p) => p.user_id === user.id);
9093
9084
  return allPlaylists.filter((p) => p.user_id !== user.id);
9094
9085
  }, [
9095
9086
  allPlaylists,
@@ -10841,7 +10832,6 @@ function FilesListingScreen({ onNavigate }) {
10841
10832
  }) }), []));
10842
10833
  const [searchTerm, setSearchTerm] = useState("");
10843
10834
  const [debouncedSearch, setDebouncedSearch] = useState("");
10844
- const observerTarget = useRef(null);
10845
10835
  useEffect(() => {
10846
10836
  const timer = setTimeout(() => {
10847
10837
  setDebouncedSearch(searchTerm);
@@ -10864,28 +10854,22 @@ function FilesListingScreen({ onNavigate }) {
10864
10854
  initialPageParam: 1
10865
10855
  });
10866
10856
  const files = useMemo(() => data?.pages.flatMap((page) => page.file_resources) ?? [], [data?.pages]);
10867
- const handleIntersect = useCallback((entries) => {
10868
- if (entries[0]?.isIntersecting && hasNextPage && !isFetchingNextPage) fetchNextPage();
10869
- }, [
10857
+ const sentinelRef = useInfiniteListSentinel({
10870
10858
  hasNextPage,
10871
10859
  isFetchingNextPage,
10872
- fetchNextPage
10873
- ]);
10874
- useEffect(() => {
10875
- const target = observerTarget.current;
10876
- if (!target) return;
10877
- const observer = new IntersectionObserver(handleIntersect, {
10878
- threshold: .1,
10879
- rootMargin: "200px"
10880
- });
10881
- observer.observe(target);
10882
- return () => observer.disconnect();
10883
- }, [handleIntersect]);
10860
+ fetchNextPage,
10861
+ error
10862
+ });
10863
+ const footer = /* @__PURE__ */ jsxs(Fragment$1, { children: [isFetchingNextPage && /* @__PURE__ */ jsx("div", {
10864
+ className: "flex justify-center py-4",
10865
+ children: /* @__PURE__ */ jsx("div", { className: "border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" })
10866
+ }), error && /* @__PURE__ */ jsx("p", {
10867
+ className: "bg-destructive/10 text-destructive rounded-lg px-3 py-2",
10868
+ children: "Failed to load files. Please try again."
10869
+ })] });
10884
10870
  return /* @__PURE__ */ jsx(ShareableListLayout, {
10885
10871
  isLoading,
10886
- error,
10887
- errorMessage: "Failed to load files. Please try again.",
10888
- isEmpty: files.length === 0,
10872
+ isEmpty: !error && files.length === 0 && !isFetchingNextPage && !hasNextPage,
10889
10873
  emptyMessage: debouncedSearch ? `No files match "${debouncedSearch}". Try a different search term.` : "No files available.",
10890
10874
  filters: /* @__PURE__ */ jsx("div", {
10891
10875
  className: "flex justify-end",
@@ -10898,11 +10882,8 @@ function FilesListingScreen({ onNavigate }) {
10898
10882
  })
10899
10883
  })
10900
10884
  }),
10901
- footer: isFetchingNextPage && /* @__PURE__ */ jsx("div", {
10902
- className: "flex justify-center py-4",
10903
- children: /* @__PURE__ */ jsx("div", { className: "border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" })
10904
- }),
10905
- sentinelRef: observerTarget,
10885
+ footer,
10886
+ sentinelRef,
10906
10887
  children: /* @__PURE__ */ jsx("div", {
10907
10888
  className: SHAREABLE_GRID_CLASS,
10908
10889
  children: files.map((file) => {
@@ -11398,6 +11379,7 @@ function createRawMediaAdapter(client) {
11398
11379
  "page[cursor]": params?.cursor,
11399
11380
  "page[limit]": params?.limit,
11400
11381
  "filter[title]": params?.["filter[title]"],
11382
+ "filter[ownership]": params?.["filter[ownership]"],
11401
11383
  "filter[content_format]": params?.["filter[content_format]"],
11402
11384
  sort: params?.sort
11403
11385
  });
@@ -11570,6 +11552,7 @@ function createMediaAdapter(client) {
11570
11552
  cursor: options?.["page[cursor]"],
11571
11553
  limit: options?.["page[limit]"],
11572
11554
  "filter[title]": options?.["filter[title]"],
11555
+ "filter[ownership]": options?.["filter[ownership]"],
11573
11556
  "filter[content_format]": options?.["filter[content_format]"],
11574
11557
  sort: options?.sort
11575
11558
  });
@@ -11580,7 +11563,7 @@ function createMediaAdapter(client) {
11580
11563
  },
11581
11564
  getMedia: async (options) => {
11582
11565
  const pageNumber = options?.page ?? 1;
11583
- const filterKey = `${options?.search_query ?? ""}|${options?.sorted_by ?? ""}`;
11566
+ const filterKey = `${options?.search_query ?? ""}|${options?.sorted_by ?? ""}|${options?.ownership ?? ""}`;
11584
11567
  if (filterKey !== lastFilterKey) {
11585
11568
  cursorByPage.clear();
11586
11569
  lastFilterKey = filterKey;
@@ -11590,10 +11573,13 @@ function createMediaAdapter(client) {
11590
11573
  let bffSort;
11591
11574
  if (rawSort === "title_asc") bffSort = "title_asc";
11592
11575
  else if (rawSort === "title_desc") bffSort = "title_desc";
11576
+ const ownership = options?.ownership;
11577
+ const bffOwnership = ownership === "all" || ownership === "mine" || ownership === "company" ? ownership : void 0;
11593
11578
  const response = await portAdapter.listMedia({
11594
11579
  cursor,
11595
11580
  limit: options?.per_page,
11596
11581
  "filter[title]": options?.search_query,
11582
+ "filter[ownership]": bffOwnership,
11597
11583
  sort: bffSort
11598
11584
  });
11599
11585
  const nextCursor = response.meta.pagination?.next_cursor;
@@ -12519,4 +12505,4 @@ const shareablesScreenPropertySchema = {
12519
12505
  //#endregion
12520
12506
  export { ShareablesScreen_exports as n, shareablesScreenPropertySchema as r, ShareablesScreen as t };
12521
12507
 
12522
- //# sourceMappingURL=ShareablesScreen-DaOvfu8L.mjs.map
12508
+ //# sourceMappingURL=ShareablesScreen-DjRtywMv.mjs.map