@fluid-app/portal-sdk 0.1.218 → 0.1.220

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.
Files changed (80) hide show
  1. package/dist/{AppDownloadScreen-CZ0EOIZ5.mjs → AppDownloadScreen-Bhix461K.mjs} +1 -1
  2. package/dist/{AppDownloadScreen-CZ0EOIZ5.mjs.map → AppDownloadScreen-Bhix461K.mjs.map} +1 -1
  3. package/dist/{AppDownloadScreen-CBoC31wL.cjs → AppDownloadScreen-DwBzuPcF.cjs} +1 -1
  4. package/dist/{AppDownloadScreen-CBoC31wL.cjs.map → AppDownloadScreen-DwBzuPcF.cjs.map} +1 -1
  5. package/dist/{FluidProvider-22PONJDa.mjs → FluidProvider-DTttgSXi.mjs} +2 -2
  6. package/dist/{FluidProvider-22PONJDa.mjs.map → FluidProvider-DTttgSXi.mjs.map} +1 -1
  7. package/dist/{FluidProvider-DTdi38VO.cjs → FluidProvider-Dm4BhF_t.cjs} +2 -2
  8. package/dist/{FluidProvider-DTdi38VO.cjs.map → FluidProvider-Dm4BhF_t.cjs.map} +1 -1
  9. package/dist/{MessagingScreen-BM21ZxGL.mjs → MessagingScreen-CwEXQJlW.mjs} +2 -2
  10. package/dist/{MessagingScreen-BM21ZxGL.mjs.map → MessagingScreen-CwEXQJlW.mjs.map} +1 -1
  11. package/dist/{MessagingScreen-ehHW4LwI.cjs → MessagingScreen-DLQ5V0m4.cjs} +2 -2
  12. package/dist/{MessagingScreen-ehHW4LwI.cjs.map → MessagingScreen-DLQ5V0m4.cjs.map} +1 -1
  13. package/dist/{MessagingScreen-BDlC9VWJ.cjs → MessagingScreen-YBXJL7a9.cjs} +2 -2
  14. package/dist/{MySiteScreen-DUN5TTvU.mjs → MySiteScreen-BAPWqDfm.mjs} +11 -31
  15. package/dist/{MySiteScreen-DUN5TTvU.mjs.map → MySiteScreen-BAPWqDfm.mjs.map} +1 -1
  16. package/dist/{MySiteScreen-B0aOIzU4.cjs → MySiteScreen-CEX1qxdj.cjs} +2 -3
  17. package/dist/{MySiteScreen-B1L8coGs.cjs → MySiteScreen-DaNlmVSi.cjs} +24 -44
  18. package/dist/MySiteScreen-DaNlmVSi.cjs.map +1 -0
  19. package/dist/{PortalProductsApiProvider-CE71zDj9.mjs → PortalProductsApiProvider-BwIRudl_.mjs} +1 -1
  20. package/dist/{PortalProductsApiProvider-CE71zDj9.mjs.map → PortalProductsApiProvider-BwIRudl_.mjs.map} +1 -1
  21. package/dist/{PortalProductsApiProvider-Ca1oeTtJ.cjs → PortalProductsApiProvider-CRaocswH.cjs} +1 -1
  22. package/dist/{PortalProductsApiProvider-Ca1oeTtJ.cjs.map → PortalProductsApiProvider-CRaocswH.cjs.map} +1 -1
  23. package/dist/{ProfileScreen-DNRpWpex.cjs → ProfileScreen-B0WRifk_.cjs} +2 -2
  24. package/dist/{ProfileScreen-DNRpWpex.cjs.map → ProfileScreen-B0WRifk_.cjs.map} +1 -1
  25. package/dist/{ProfileScreen-VonnJyFa.mjs → ProfileScreen-BuejQU_V.mjs} +2 -2
  26. package/dist/{ProfileScreen-VonnJyFa.mjs.map → ProfileScreen-BuejQU_V.mjs.map} +1 -1
  27. package/dist/{ProfileScreen-CN1DDd-Q.cjs → ProfileScreen-g3se9Jw-.cjs} +2 -2
  28. package/dist/{ShareablesScreen-smU5pGyH.cjs → ShareablesScreen-CqvPzH1v.cjs} +3 -5
  29. package/dist/{PortalContentApiProvider-C9FeVwRb.mjs → ShareablesScreen-DV2nikzp.mjs} +460 -119
  30. package/dist/ShareablesScreen-DV2nikzp.mjs.map +1 -0
  31. package/dist/{PortalContentApiProvider-RXBp8FNj.cjs → ShareablesScreen-DwnMBftJ.cjs} +457 -156
  32. package/dist/ShareablesScreen-DwnMBftJ.cjs.map +1 -0
  33. package/dist/{ShopScreen-BAbAc2ah.cjs → ShopScreen-C-Ki6fuh.cjs} +3 -3
  34. package/dist/{ShopScreen-DQ1-68kV.mjs → ShopScreen-C2K1C2tt.mjs} +3 -3
  35. package/dist/{ShopScreen-DQ1-68kV.mjs.map → ShopScreen-C2K1C2tt.mjs.map} +1 -1
  36. package/dist/{ShopScreen-DcJ0DLvB.cjs → ShopScreen-smzNn37E.cjs} +3 -3
  37. package/dist/{ShopScreen-DcJ0DLvB.cjs.map → ShopScreen-smzNn37E.cjs.map} +1 -1
  38. package/dist/{UpgradeScreen-BdY0rCoF.cjs → UpgradeScreen-CNXQ1hcP.cjs} +1 -1
  39. package/dist/{UpgradeScreen-Dau5Elx4.mjs → UpgradeScreen-ChLiVSf7.mjs} +1 -1
  40. package/dist/{UpgradeScreen-Dau5Elx4.mjs.map → UpgradeScreen-ChLiVSf7.mjs.map} +1 -1
  41. package/dist/{UpgradeScreen-DrBa2uzD.cjs → UpgradeScreen-DMJUK4dl.cjs} +1 -1
  42. package/dist/{UpgradeScreen-DrBa2uzD.cjs.map → UpgradeScreen-DMJUK4dl.cjs.map} +1 -1
  43. package/dist/{dist-DWs3-WOI.cjs → dist-Bxa9x0H9.cjs} +218 -1
  44. package/dist/{dist-DWs3-WOI.cjs.map → dist-Bxa9x0H9.cjs.map} +1 -1
  45. package/dist/index.cjs +24 -53
  46. package/dist/index.cjs.map +1 -1
  47. package/dist/index.d.cts +1 -20
  48. package/dist/index.d.cts.map +1 -1
  49. package/dist/index.d.mts +1 -20
  50. package/dist/index.d.mts.map +1 -1
  51. package/dist/index.mjs +25 -52
  52. package/dist/index.mjs.map +1 -1
  53. package/dist/{portal_tenant_content-0zpnjBot.cjs → portal_tenant_content-BvYxmADB.cjs} +18 -1
  54. package/dist/portal_tenant_content-BvYxmADB.cjs.map +1 -0
  55. package/dist/{portal_tenant_content-DzIQtSLE.mjs → portal_tenant_content-nHEI2qEY.mjs} +13 -2
  56. package/dist/portal_tenant_content-nHEI2qEY.mjs.map +1 -0
  57. package/dist/{sortable.esm-CJLSD-Ce.mjs → sortable.esm-fSGrAZU2.mjs} +141 -2
  58. package/dist/sortable.esm-fSGrAZU2.mjs.map +1 -0
  59. package/package.json +14 -14
  60. package/dist/MySiteScreen-B1L8coGs.cjs.map +0 -1
  61. package/dist/PortalContentApiProvider-C9FeVwRb.mjs.map +0 -1
  62. package/dist/PortalContentApiProvider-RXBp8FNj.cjs.map +0 -1
  63. package/dist/ProductsScreen-BD53vh6Y.cjs +0 -103
  64. package/dist/ProductsScreen-BD53vh6Y.cjs.map +0 -1
  65. package/dist/ProductsScreen-BtUZxJCt.mjs +0 -91
  66. package/dist/ProductsScreen-BtUZxJCt.mjs.map +0 -1
  67. package/dist/ProductsScreen-DNpzJ6lh.cjs +0 -15
  68. package/dist/ProductsScreen-pkOeOW8M.mjs +0 -13
  69. package/dist/ShareablesScreen-CW1e9x4K.mjs +0 -188
  70. package/dist/ShareablesScreen-CW1e9x4K.mjs.map +0 -1
  71. package/dist/ShareablesScreen-D1J2Kljk.mjs +0 -15
  72. package/dist/ShareablesScreen-DC8xXUo4.cjs +0 -200
  73. package/dist/ShareablesScreen-DC8xXUo4.cjs.map +0 -1
  74. package/dist/portal_tenant_content-0zpnjBot.cjs.map +0 -1
  75. package/dist/portal_tenant_content-DzIQtSLE.mjs.map +0 -1
  76. package/dist/sortable.esm-CJLSD-Ce.mjs.map +0 -1
  77. package/dist/use-mysite-portal-BV-BP3CE.mjs +0 -141
  78. package/dist/use-mysite-portal-BV-BP3CE.mjs.map +0 -1
  79. package/dist/use-mysite-portal-DzDYRU0u.cjs +0 -219
  80. package/dist/use-mysite-portal-DzDYRU0u.cjs.map +0 -1
@@ -1,13 +1,16 @@
1
- import { t as useDropzone } from "./es-Cw_Kikmu.mjs";
2
- import { A as playlists_update, C as playlists_create, D as playlists_items_remove, E as playlists_items_list, M as shares_list, O as playlists_list, T as playlists_items_add, _ as media_products_add, a as content_playlists_metrics_share_visits, b as media_show, c as dam_asset_paths_list, d as dam_assets_discard, f as dam_assets_list, g as media_list, h as media_destroy, i as content_pages_metrics_visits, j as shares_create, k as playlists_show, l as dam_assets_create, m as media_create, n as content_media_metrics_visits, o as content_playlists_metrics_visits, p as dam_query, r as content_pages_metrics_share_visits, s as dam_asset_paths_create, t as content_media_metrics_share_visits, u as dam_assets_destroy, v as media_products_list, w as playlists_destroy, x as media_update, y as media_products_remove } from "./portal_tenant_content-DzIQtSLE.mjs";
1
+ import { r as __exportAll, t as useDropzone } from "./es-Cw_Kikmu.mjs";
2
+ import { A as playlists_show, C as playlists_create, D as playlists_items_remove, E as playlists_items_list, M as shares_create, N as shares_list, O as playlists_items_reorder, T as playlists_items_add, _ as media_products_add, a as content_playlists_metrics_share_visits, b as media_show, c as dam_asset_paths_list, d as dam_assets_discard, f as dam_assets_list, g as media_list, h as media_destroy, i as content_pages_metrics_visits, j as playlists_update, k as playlists_list, l as dam_assets_create, m as media_create, n as content_media_metrics_visits, o as content_playlists_metrics_visits, p as dam_query, r as content_pages_metrics_share_visits, s as dam_asset_paths_create, t as content_media_metrics_share_visits, u as dam_assets_destroy, v as media_products_list, w as playlists_destroy, x as media_update, y as media_products_remove } from "./portal_tenant_content-nHEI2qEY.mjs";
3
3
  import { n as usePortalTenantClient } from "./PortalTenantClientProvider-4ZmY6hac.mjs";
4
- import { $ as DropdownMenuSeparator, A as Select, At as Checkbox, B as Form, C as Skeleton, Cn as AlertDialogFooter, Dn as Content, En as Button, Et as CardContent, G as FormMessage, H as FormField, J as DropdownMenuContent, K as Label, L as Input, M as SelectItem, N as SelectTrigger, Nn as useZodForm, P as SelectValue, Pn as cn, S as Slider, Sn as AlertDialogDescription, Tn as AlertDialogTitle, U as FormItem, V as FormControl, W as FormLabel, Y as DropdownMenuItem, _ as Switch, bn as AlertDialogCancel, c as Tabs, cn as Breadcrumb, dn as BreadcrumbList, dt as DialogPortal, et as DropdownMenuSub, fn as BreadcrumbPage, ft as DialogTitle, ht as PopoverTrigger, i as TooltipTrigger, it as Dialog, j as SelectContent, k as Separator, l as TabsList, ln as BreadcrumbItem, lt as DialogHeader, mn as Badge, mt as PopoverContent, n as TooltipContent, nt as DropdownMenuSubTrigger, ot as DialogContent, pn as BreadcrumbSeparator, pt as Popover, q as DropdownMenu, r as TooltipProvider, rt as DropdownMenuTrigger, s as Textarea, st as DialogDescription, t as Tooltip, tt as DropdownMenuSubContent, u as TabsTrigger, un as BreadcrumbLink, ut as DialogOverlay, vn as AlertDialog, wn as AlertDialogHeader, wt as Card, xn as AlertDialogContent, y as Spinner, yn as AlertDialogAction } from "./src-BEKH1DXO.mjs";
4
+ import { $ as DropdownMenuSeparator, A as Select, At as Checkbox, B as Form, C as Skeleton, Cn as AlertDialogFooter, Dn as Content, En as Button, Et as CardContent, G as FormMessage, H as FormField, J as DropdownMenuContent, K as Label, L as Input, M as SelectItem, N as SelectTrigger, Nn as useZodForm, P as SelectValue, Pn as cn, S as Slider, Sn as AlertDialogDescription, Tn as AlertDialogTitle, U as FormItem, V as FormControl, W as FormLabel, Y as DropdownMenuItem, _ as Switch, b as fluidToast, bn as AlertDialogCancel, c as Tabs, cn as Breadcrumb, dn as BreadcrumbList, dt as DialogPortal, et as DropdownMenuSub, fn as BreadcrumbPage, ft as DialogTitle, ht as PopoverTrigger, i as TooltipTrigger, it as Dialog, j as SelectContent, k as Separator, l as TabsList, ln as BreadcrumbItem, lt as DialogHeader, mn as Badge, mt as PopoverContent, n as TooltipContent, nt as DropdownMenuSubTrigger, ot as DialogContent, pn as BreadcrumbSeparator, pt as Popover, q as DropdownMenu, r as TooltipProvider, rt as DropdownMenuTrigger, s as Textarea, st as DialogDescription, t as Tooltip, tt as DropdownMenuSubContent, u as TabsTrigger, un as BreadcrumbLink, ut as DialogOverlay, vn as AlertDialog, wn as AlertDialogHeader, wt as Card, xn as AlertDialogContent, y as Spinner, yn as AlertDialogAction } from "./src-BEKH1DXO.mjs";
5
5
  import { n as useScreenHeaderActions, r as useScreenHeaderBreadcrumbs } from "./ScreenHeaderContext-BDjNSUfr.mjs";
6
+ import { t as useAccount } from "./use-account-Cvig0exB.mjs";
7
+ import { t as useStore } from "./use-store-efmQhKpB.mjs";
8
+ import { n as useAppNavigation } from "./AppNavigationContext-Cq3BDKSf.mjs";
6
9
  import { a as useEditor, o as Placeholder, r as EditorContent, t as StarterKit } from "./dist-D39Yezrv.mjs";
7
10
  import { t as SearchSort } from "./SearchSort-DXBt-uj0.mjs";
8
11
  import { n as TextAlign, t as Underline } from "./dist-Cis8L6HV.mjs";
9
- import { a as verticalListSortingStrategy, c as PointerSensor, d as useSensors, f as CSS, i as useSortable, l as closestCenter, n as arrayMove, o as DndContext, r as sortableKeyboardCoordinates, s as KeyboardSensor, t as SortableContext, u as useSensor } from "./sortable.esm-CJLSD-Ce.mjs";
10
- import { o as usePortalProductsApi } from "./PortalProductsApiProvider-CE71zDj9.mjs";
12
+ import { a as verticalListSortingStrategy, c as PointerSensor, d as useSensors, f as CSS, i as useSortable, l as closestCenter, n as arrayMove, o as DndContext, p as PORTAL_MYSITE_KEYS, r as sortableKeyboardCoordinates, s as KeyboardSensor, t as SortableContext, u as useSensor } from "./sortable.esm-fSGrAZU2.mjs";
13
+ import { o as usePortalProductsApi, t as PortalProductsApiProvider } from "./PortalProductsApiProvider-BwIRudl_.mjs";
11
14
  import React, { PureComponent, createContext, createRef, forwardRef, useCallback, useContext, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react";
12
15
  import { keepPreviousData, useInfiniteQuery, useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
13
16
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
@@ -286,6 +289,25 @@ const useUpdatePlaylistMutation = (options) => {
286
289
  }
287
290
  });
288
291
  };
292
+ const useReorderPlaylistItemsMutation = (options) => {
293
+ const api = useShareablesApi();
294
+ const queryClient = useQueryClient();
295
+ return useMutation({
296
+ mutationFn: ({ playlistId, data }) => {
297
+ if (!api.playlists.reorderPlaylistItems) return Promise.resolve();
298
+ return api.playlists.reorderPlaylistItems(playlistId, data);
299
+ },
300
+ onSuccess: (_, { playlistId }) => {
301
+ if (api.playlists.reorderPlaylistItems) queryClient.invalidateQueries({ queryKey: shareablesKeys.playlists.detail(playlistId) });
302
+ options?.onSuccess?.(playlistId);
303
+ },
304
+ onError: (error, { playlistId }) => {
305
+ if (isCancellationError(error)) return;
306
+ console.error("Error reordering playlist items:", error);
307
+ options?.onError?.(error, playlistId);
308
+ }
309
+ });
310
+ };
289
311
  //#endregion
290
312
  //#region ../../shareables/ui/src/context.tsx
291
313
  const MISSING_PROVIDER = Symbol("missing-shareables-provider");
@@ -576,6 +598,83 @@ function ShareableListLayout({ filters, children, isLoading, error, errorMessage
576
598
  });
577
599
  }
578
600
  //#endregion
601
+ //#region ../../shareables/ui/src/components/shared/ShareableListRow.tsx
602
+ /**
603
+ * Container className for a list-view rendering of shareables. Pairs with
604
+ * `ShareableListRow` and mirrors `SHAREABLE_GRID_CLASS` for symmetry.
605
+ */
606
+ const SHAREABLE_LIST_CLASS = "divide-border divide-y rounded-lg border";
607
+ /**
608
+ * Single row in a shareables list view. The row body (thumbnail + title) is
609
+ * a `<button>` for keyboard/click navigation; `leading` and `trailing` slots
610
+ * are siblings so their interactive elements don't nest inside the body
611
+ * button. Hover styling applies to the entire row container.
612
+ */
613
+ function ShareableListRow({ imageUrl, imageAlt, title, subtitle, onClick, leading, trailing }) {
614
+ return /* @__PURE__ */ jsxs("div", {
615
+ className: "hover:bg-muted flex items-center gap-3 px-4 py-3 transition-colors",
616
+ children: [
617
+ leading,
618
+ /* @__PURE__ */ jsxs("button", {
619
+ type: "button",
620
+ onClick,
621
+ className: "flex min-w-0 flex-1 items-center gap-4 text-left",
622
+ children: [/* @__PURE__ */ jsx("div", {
623
+ className: "bg-muted h-12 w-12 shrink-0 overflow-hidden rounded-md",
624
+ children: imageUrl ? /* @__PURE__ */ jsx("img", {
625
+ src: imageUrl,
626
+ alt: imageAlt ?? title,
627
+ className: "h-full w-full object-cover"
628
+ }) : /* @__PURE__ */ jsx("div", { className: "bg-muted h-full w-full" })
629
+ }), /* @__PURE__ */ jsxs("div", {
630
+ className: "min-w-0 flex-1",
631
+ children: [/* @__PURE__ */ jsx("p", {
632
+ className: "text-foreground truncate text-sm font-medium",
633
+ children: title || "Untitled"
634
+ }), subtitle != null && subtitle !== false && /* @__PURE__ */ jsx("p", {
635
+ className: "text-muted-foreground flex items-center gap-1.5 text-xs",
636
+ children: subtitle
637
+ })]
638
+ })]
639
+ }),
640
+ trailing
641
+ ]
642
+ });
643
+ }
644
+ //#endregion
645
+ //#region ../../shareables/ui/src/components/shared/ViewModeToggle.tsx
646
+ /**
647
+ * Segmented list/grid toggle used in the filter bar of every shareable
648
+ * listing screen. Stateless — callers own the `viewMode` state.
649
+ */
650
+ function ViewModeToggle({ value, onChange }) {
651
+ return /* @__PURE__ */ jsxs("div", {
652
+ className: "border-input bg-muted flex items-center rounded-lg border p-0.5",
653
+ children: [/* @__PURE__ */ jsx(ToggleButton, {
654
+ active: value === "list",
655
+ label: "List view",
656
+ onClick: () => onChange("list"),
657
+ children: /* @__PURE__ */ jsx(List, { className: "h-4 w-4" })
658
+ }), /* @__PURE__ */ jsx(ToggleButton, {
659
+ active: value === "grid",
660
+ label: "Grid view",
661
+ onClick: () => onChange("grid"),
662
+ children: /* @__PURE__ */ jsx(LayoutGrid, { className: "h-4 w-4" })
663
+ })]
664
+ });
665
+ }
666
+ function ToggleButton({ active, label, onClick, children }) {
667
+ return /* @__PURE__ */ jsx("button", {
668
+ type: "button",
669
+ onClick,
670
+ title: label,
671
+ "aria-label": label,
672
+ "aria-pressed": active,
673
+ className: cn("flex h-8 w-8 items-center justify-center rounded-md transition-all", active ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"),
674
+ children
675
+ });
676
+ }
677
+ //#endregion
579
678
  //#region ../../shareables/ui/src/components/screens/ProductsScreen.tsx
580
679
  const PAGE_SIZE$4 = 24;
581
680
  const SORT_OPTIONS$1 = [
@@ -606,6 +705,7 @@ const SORT_OPTIONS$1 = [
606
705
  ];
607
706
  function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNavigate }) {
608
707
  const client = useShareablesClient();
708
+ const { navigate } = useShareablesUI();
609
709
  useScreenHeaderBreadcrumbs(useMemo(() => /* @__PURE__ */ jsx(Breadcrumb, { children: /* @__PURE__ */ jsx(BreadcrumbList, {
610
710
  className: "text-lg",
611
711
  children: /* @__PURE__ */ jsx(BreadcrumbItem, { children: /* @__PURE__ */ jsx(BreadcrumbPage, {
@@ -616,6 +716,7 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
616
716
  const [searchTerm, setSearchTerm] = useState("");
617
717
  const [debouncedSearch, setDebouncedSearch] = useState("");
618
718
  const [sortValue, setSortValue] = useState("created_at_desc");
719
+ const [viewMode, setViewMode] = useState("grid");
619
720
  const observerTarget = useRef(null);
620
721
  useEffect(() => {
621
722
  const timer = setTimeout(() => {
@@ -703,9 +804,9 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
703
804
  errorMessage: "Failed to load products. Please try again.",
704
805
  isEmpty: products.length === 0,
705
806
  emptyMessage: debouncedSearch ? "No products match your search." : "No products available.",
706
- filters: /* @__PURE__ */ jsx("div", {
707
- className: "flex justify-end",
708
- children: /* @__PURE__ */ jsx("div", {
807
+ filters: /* @__PURE__ */ jsxs("div", {
808
+ className: "flex items-center justify-end gap-2",
809
+ children: [/* @__PURE__ */ jsx("div", {
709
810
  className: "w-full max-w-sm",
710
811
  children: /* @__PURE__ */ jsx(SearchSort, {
711
812
  searchValue: searchTerm,
@@ -715,14 +816,18 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
715
816
  sortValue,
716
817
  onSortChange: setSortValue
717
818
  })
718
- })
819
+ }), /* @__PURE__ */ jsx(ViewModeToggle, {
820
+ value: viewMode,
821
+ onChange: setViewMode
822
+ })]
719
823
  }),
824
+ loadingFilterShape: "search-view",
720
825
  footer: isFetchingNextPage && /* @__PURE__ */ jsx("div", {
721
826
  className: "flex justify-center py-4",
722
827
  children: /* @__PURE__ */ jsx("div", { className: "border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" })
723
828
  }),
724
829
  sentinelRef: observerTarget,
725
- children: /* @__PURE__ */ jsx("div", {
830
+ children: viewMode === "grid" ? /* @__PURE__ */ jsx("div", {
726
831
  className: SHAREABLE_GRID_CLASS,
727
832
  children: products.map((product) => /* @__PURE__ */ jsx(ShareProductCard, {
728
833
  product: {
@@ -732,6 +837,14 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
732
837
  },
733
838
  mediaCount: product.media_count
734
839
  }, product.id))
840
+ }) : /* @__PURE__ */ jsx("div", {
841
+ className: SHAREABLE_LIST_CLASS,
842
+ children: products.map((product) => /* @__PURE__ */ jsx(ShareableListRow, {
843
+ imageUrl: product.image_url,
844
+ title: product.title,
845
+ subtitle: product.media_count != null ? `${product.media_count} assets` : void 0,
846
+ onClick: () => navigate(`product/${product.id}`)
847
+ }, product.id))
735
848
  })
736
849
  });
737
850
  }
@@ -1701,21 +1814,9 @@ function MediaListingScreen({ onNavigate }) {
1701
1814
  }), kindFilter === opt.value && /* @__PURE__ */ jsx(Check, { className: "text-muted-foreground size-4" })]
1702
1815
  }, opt.value))
1703
1816
  })] }),
1704
- /* @__PURE__ */ jsxs("div", {
1705
- className: "border-input bg-muted flex items-center rounded-lg border p-0.5",
1706
- children: [/* @__PURE__ */ jsx("button", {
1707
- type: "button",
1708
- onClick: () => setViewMode("list"),
1709
- className: `flex h-8 w-8 items-center justify-center rounded-md transition-all ${viewMode === "list" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
1710
- title: "List view",
1711
- children: /* @__PURE__ */ jsx(List, { className: "h-4 w-4" })
1712
- }), /* @__PURE__ */ jsx("button", {
1713
- type: "button",
1714
- onClick: () => setViewMode("grid"),
1715
- className: `flex h-8 w-8 items-center justify-center rounded-md transition-all ${viewMode === "grid" ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"}`,
1716
- title: "Grid view",
1717
- children: /* @__PURE__ */ jsx(LayoutGrid, { className: "h-4 w-4" })
1718
- })]
1817
+ /* @__PURE__ */ jsx(ViewModeToggle, {
1818
+ value: viewMode,
1819
+ onChange: setViewMode
1719
1820
  })
1720
1821
  ]
1721
1822
  })]
@@ -1785,37 +1886,20 @@ function MediaListingScreen({ onNavigate }) {
1785
1886
  }, item.id);
1786
1887
  })
1787
1888
  }) : /* @__PURE__ */ jsx("div", {
1788
- className: "divide-border divide-y rounded-lg border",
1889
+ className: SHAREABLE_LIST_CLASS,
1789
1890
  children: filteredItems.map((item) => {
1790
1891
  const canEdit = !readOnly && item.owner_type === "user";
1791
- return /* @__PURE__ */ jsxs("div", {
1792
- className: "hover:bg-muted flex items-center gap-4 px-4 py-3 transition-colors",
1793
- children: [/* @__PURE__ */ jsxs("button", {
1794
- type: "button",
1795
- onClick: () => navigate(`media/${item.id}`),
1796
- className: "flex min-w-0 flex-1 items-center gap-4 text-left",
1797
- children: [/* @__PURE__ */ jsx("div", {
1798
- className: "bg-muted h-12 w-12 shrink-0 overflow-hidden rounded-md",
1799
- children: item.image_url ? /* @__PURE__ */ jsx("img", {
1800
- src: item.image_url,
1801
- alt: item.title ?? "",
1802
- className: "h-full w-full object-cover"
1803
- }) : /* @__PURE__ */ jsx("div", { className: "bg-muted h-full w-full" })
1804
- }), /* @__PURE__ */ jsxs("div", {
1805
- className: "min-w-0 flex-1",
1806
- children: [/* @__PURE__ */ jsx("p", {
1807
- className: "text-foreground truncate text-sm font-medium",
1808
- children: item.title ?? "Untitled"
1809
- }), /* @__PURE__ */ jsxs("p", {
1810
- className: "text-muted-foreground flex items-center gap-1.5 text-xs",
1811
- children: [getMediaKindLabel(item.kind), item.owner_type === "user" && /* @__PURE__ */ jsx(Badge, {
1812
- variant: "secondary",
1813
- className: "px-1.5 py-0 text-[10px] leading-4",
1814
- children: "My Media"
1815
- })]
1816
- })]
1817
- })]
1818
- }), canEdit && /* @__PURE__ */ jsx(MediaRowActionsMenu, { onDelete: () => setPendingDeleteId(item.id) })]
1892
+ return /* @__PURE__ */ jsx(ShareableListRow, {
1893
+ imageUrl: item.image_url,
1894
+ imageAlt: item.title ?? "",
1895
+ title: item.title ?? "Untitled",
1896
+ subtitle: /* @__PURE__ */ jsxs(Fragment$1, { children: [getMediaKindLabel(item.kind), item.owner_type === "user" && /* @__PURE__ */ jsx(Badge, {
1897
+ variant: "secondary",
1898
+ className: "px-1.5 py-0 text-[10px] leading-4",
1899
+ children: "My Media"
1900
+ })] }),
1901
+ onClick: () => navigate(`media/${item.id}`),
1902
+ trailing: canEdit && /* @__PURE__ */ jsx(MediaRowActionsMenu, { onDelete: () => setPendingDeleteId(item.id) })
1819
1903
  }, item.id);
1820
1904
  })
1821
1905
  })
@@ -8934,6 +9018,7 @@ function PlaylistsListingScreen(_props) {
8934
9018
  const [debouncedSearch, setDebouncedSearch] = useState("");
8935
9019
  const [sortValue, setSortValue] = useState("title");
8936
9020
  const [ownerFilter, setOwnerFilter] = useState("all");
9021
+ const [viewMode, setViewMode] = useState("grid");
8937
9022
  const [selectedIds, setSelectedIds] = useState(/* @__PURE__ */ new Set());
8938
9023
  const [pendingDeleteId, setPendingDeleteId] = useState(null);
8939
9024
  useEffect(() => {
@@ -9104,33 +9189,39 @@ function PlaylistsListingScreen(_props) {
9104
9189
  value: ownerFilter,
9105
9190
  onValueChange: setOwnerFilter,
9106
9191
  myLabel: "My Playlists"
9107
- }), /* @__PURE__ */ jsx("div", {
9108
- className: "ml-auto w-full max-w-sm",
9109
- children: /* @__PURE__ */ jsx(SearchSort, {
9110
- searchValue: searchTerm,
9111
- onSearchChange: setSearchTerm,
9112
- placeholder: "Search playlists...",
9113
- sortOptions: [
9114
- {
9115
- label: "Name (A-Z)",
9116
- value: "title"
9117
- },
9118
- {
9119
- label: "Name (Z-A)",
9120
- value: "-title"
9121
- },
9122
- {
9123
- label: "Date Created (Newest)",
9124
- value: "-created_at"
9125
- },
9126
- {
9127
- label: "Date Created (Oldest)",
9128
- value: "created_at"
9129
- }
9130
- ],
9131
- sortValue,
9132
- onSortChange: setSortValue
9133
- })
9192
+ }), /* @__PURE__ */ jsxs("div", {
9193
+ className: "ml-auto flex items-center gap-2",
9194
+ children: [/* @__PURE__ */ jsx("div", {
9195
+ className: "w-full max-w-sm",
9196
+ children: /* @__PURE__ */ jsx(SearchSort, {
9197
+ searchValue: searchTerm,
9198
+ onSearchChange: setSearchTerm,
9199
+ placeholder: "Search playlists...",
9200
+ sortOptions: [
9201
+ {
9202
+ label: "Name (A-Z)",
9203
+ value: "title"
9204
+ },
9205
+ {
9206
+ label: "Name (Z-A)",
9207
+ value: "-title"
9208
+ },
9209
+ {
9210
+ label: "Date Created (Newest)",
9211
+ value: "-created_at"
9212
+ },
9213
+ {
9214
+ label: "Date Created (Oldest)",
9215
+ value: "created_at"
9216
+ }
9217
+ ],
9218
+ sortValue,
9219
+ onSortChange: setSortValue
9220
+ })
9221
+ }), /* @__PURE__ */ jsx(ViewModeToggle, {
9222
+ value: viewMode,
9223
+ onChange: setViewMode
9224
+ })]
9134
9225
  })]
9135
9226
  });
9136
9227
  const footer = /* @__PURE__ */ jsxs(Fragment$1, { children: [isFetchingNextPage && /* @__PURE__ */ jsx("div", {
@@ -9152,8 +9243,8 @@ function PlaylistsListingScreen(_props) {
9152
9243
  }),
9153
9244
  footer,
9154
9245
  sentinelRef: observerTarget,
9155
- loadingFilterShape: "search-action",
9156
- children: /* @__PURE__ */ jsx("div", {
9246
+ loadingFilterShape: "search-view",
9247
+ children: viewMode === "grid" ? /* @__PURE__ */ jsx("div", {
9157
9248
  className: GRID_CLASS,
9158
9249
  children: filteredPlaylists.map((playlist) => {
9159
9250
  const firstItem = playlist.items?.[0];
@@ -9175,6 +9266,61 @@ function PlaylistsListingScreen(_props) {
9175
9266
  onDelete: onDeletePlaylist ? () => setPendingDeleteId(playlist.id) : void 0
9176
9267
  }, playlist.id);
9177
9268
  })
9269
+ }) : /* @__PURE__ */ jsx("div", {
9270
+ className: SHAREABLE_LIST_CLASS,
9271
+ children: filteredPlaylists.map((playlist) => {
9272
+ const firstItem = playlist.items?.[0];
9273
+ const imageUrl = playlist.image_url ?? firstItem?.image_url ?? firstItem?.relateable?.image_url ?? firstItem?.relateable?.compressed_image_url;
9274
+ const itemCount = playlist.items_count ?? playlist.items?.length ?? 0;
9275
+ const canEdit = !readOnly && playlist.user_id === user?.id;
9276
+ const isSelected = selectedIds.has(playlist.id);
9277
+ const title = playlist.title || "Untitled Playlist";
9278
+ return /* @__PURE__ */ jsx(ShareableListRow, {
9279
+ imageUrl,
9280
+ title,
9281
+ subtitle: /* @__PURE__ */ jsxs(Badge, {
9282
+ variant: "secondary",
9283
+ className: "px-1.5 py-0 text-[10px] leading-4",
9284
+ children: [
9285
+ itemCount,
9286
+ " ",
9287
+ itemCount === 1 ? "item" : "items"
9288
+ ]
9289
+ }),
9290
+ onClick: () => navigate(`playlists/${playlist.id}`),
9291
+ leading: /* @__PURE__ */ jsx(Checkbox, {
9292
+ checked: isSelected,
9293
+ onCheckedChange: (checked) => handleToggleSelection(playlist.id, checked === true),
9294
+ "aria-label": `Select ${title}`
9295
+ }),
9296
+ trailing: /* @__PURE__ */ jsxs(Fragment$1, { children: [onToggleFavorite && /* @__PURE__ */ jsx("button", {
9297
+ type: "button",
9298
+ onClick: () => handleFavorite(playlist.id),
9299
+ "aria-label": playlist.is_favorited ? "Unfavorite" : "Favorite",
9300
+ className: "hover:bg-muted-foreground/10 flex h-8 w-8 items-center justify-center rounded-md transition-colors",
9301
+ children: /* @__PURE__ */ jsx(Heart, { className: cn("h-4 w-4 transition-colors", playlist.is_favorited ? "fill-destructive text-destructive" : "text-muted-foreground") })
9302
+ }), canEdit && /* @__PURE__ */ jsxs(DropdownMenu, { children: [/* @__PURE__ */ jsx(DropdownMenuTrigger, {
9303
+ asChild: true,
9304
+ children: /* @__PURE__ */ jsx(Button, {
9305
+ variant: "ghost",
9306
+ size: "sm",
9307
+ className: "h-8 w-8 p-0",
9308
+ "aria-label": "Playlist actions",
9309
+ children: /* @__PURE__ */ jsx(MoreVertical, { className: "h-4 w-4" })
9310
+ })
9311
+ }), /* @__PURE__ */ jsxs(DropdownMenuContent, {
9312
+ align: "end",
9313
+ children: [/* @__PURE__ */ jsxs(DropdownMenuItem, {
9314
+ onClick: () => handleEdit(playlist.id),
9315
+ children: [/* @__PURE__ */ jsx(Pencil, { className: "mr-2 h-4 w-4" }), "Edit"]
9316
+ }), onDeletePlaylist && /* @__PURE__ */ jsxs(Fragment$1, { children: [/* @__PURE__ */ jsx(DropdownMenuSeparator, {}), /* @__PURE__ */ jsxs(DropdownMenuItem, {
9317
+ variant: "destructive",
9318
+ onClick: () => setPendingDeleteId(playlist.id),
9319
+ children: [/* @__PURE__ */ jsx(Trash2, { className: "mr-2 h-4 w-4" }), "Delete"]
9320
+ })] })]
9321
+ })] })] })
9322
+ }, playlist.id);
9323
+ })
9178
9324
  })
9179
9325
  }), /* @__PURE__ */ jsx(AlertDialog, {
9180
9326
  open: pendingDeleteId !== null,
@@ -10060,6 +10206,7 @@ function SortableTable({ items, setItems, onDeleteItem, isDeletePending, enableR
10060
10206
  }
10061
10207
  //#endregion
10062
10208
  //#region ../../shareables/ui/src/components/playlists/form/PlaylistItemsSection.tsx
10209
+ const REORDER_DEBOUNCE_MS = 500;
10063
10210
  const PLAYLIST_CONTENT_TYPES = new Set([
10064
10211
  "Medium",
10065
10212
  "Page",
@@ -10129,9 +10276,53 @@ function PlaylistItemsSection({ playlistId }) {
10129
10276
  });
10130
10277
  }
10131
10278
  });
10279
+ const reorderItemsMutation = useReorderPlaylistItemsMutation();
10280
+ const reorderTimerRef = useRef(null);
10281
+ const reorderRollbackRef = useRef(null);
10282
+ useEffect(() => () => {
10283
+ if (reorderTimerRef.current) clearTimeout(reorderTimerRef.current);
10284
+ }, []);
10285
+ const canPersistReorder = !!api.playlists.reorderPlaylistItems;
10132
10286
  const mergeAndOrder = useCallback((reorderedContent) => {
10133
- updateItems(computeOrderedItems([...reorderedContent, ...tailItems]));
10134
- }, [tailItems, updateItems]);
10287
+ const ordered = computeOrderedItems([...reorderedContent, ...tailItems]);
10288
+ if (playlistId && canPersistReorder && reorderTimerRef.current === null && reorderRollbackRef.current === null) reorderRollbackRef.current = tableItems;
10289
+ updateItems(ordered);
10290
+ if (!playlistId || !canPersistReorder) return;
10291
+ if (reorderTimerRef.current) clearTimeout(reorderTimerRef.current);
10292
+ reorderTimerRef.current = setTimeout(() => {
10293
+ reorderTimerRef.current = null;
10294
+ const rollback = reorderRollbackRef.current;
10295
+ reorderItemsMutation.mutate({
10296
+ playlistId,
10297
+ data: { items: ordered.filter((item) => Number.isInteger(item.id) && typeof item.order === "number").map((item) => ({
10298
+ id: item.id,
10299
+ order: item.order
10300
+ })) }
10301
+ }, {
10302
+ onSuccess: () => {
10303
+ if (reorderTimerRef.current === null) reorderRollbackRef.current = null;
10304
+ else reorderRollbackRef.current = ordered;
10305
+ },
10306
+ onError: (error) => {
10307
+ if (rollback) updateItems(rollback);
10308
+ reorderRollbackRef.current = null;
10309
+ showToast({
10310
+ title: "Failed to save new item order",
10311
+ type: "error",
10312
+ error
10313
+ });
10314
+ }
10315
+ });
10316
+ }, REORDER_DEBOUNCE_MS);
10317
+ }, [
10318
+ tailItems,
10319
+ tableItems,
10320
+ updateItems,
10321
+ playlistId,
10322
+ canPersistReorder,
10323
+ reorderItemsMutation.mutate,
10324
+ showToast
10325
+ ]);
10135
10326
  const handleDeleteItem = (itemId) => {
10136
10327
  removeItem(itemId);
10137
10328
  if (playlistId) removeItemMutation.mutate({
@@ -10187,13 +10378,7 @@ function PlaylistItemsSection({ playlistId }) {
10187
10378
  type: "success"
10188
10379
  });
10189
10380
  } catch {}
10190
- else {
10191
- addItem(newItem);
10192
- showToast({
10193
- title: "Item added. Save the playlist to persist these items.",
10194
- type: "warning"
10195
- });
10196
- }
10381
+ else addItem(newItem);
10197
10382
  }
10198
10383
  };
10199
10384
  const filePickerContextValue = useMemo(() => {
@@ -10795,31 +10980,6 @@ function ShareablesApp({ screen, detailId, action, onNavigate, onBack, countryCo
10795
10980
  return content;
10796
10981
  }
10797
10982
  //#endregion
10798
- //#region ../../shareables/ui/src/components/ProductsApp.tsx
10799
- function ProductsApp({ countryCode, companyLogoUrl, fetchProducts, fetchProduct, productId: controlledProductId, onSelectProduct: onSelectProductProp, onBack: onBackProp }) {
10800
- const [internalProductId, setInternalProductId] = useState(null);
10801
- const activeProductId = controlledProductId !== void 0 ? controlledProductId : internalProductId;
10802
- const handleSelectProduct = onSelectProductProp ?? setInternalProductId;
10803
- const handleBack = onBackProp ?? (() => setInternalProductId(null));
10804
- const handleNavigate = (screen, detailId) => {
10805
- if (screen === "products" && detailId) handleSelectProduct(detailId);
10806
- };
10807
- if (activeProductId) return /* @__PURE__ */ jsx(ProductDetailScreen, {
10808
- productId: activeProductId,
10809
- countryCode,
10810
- fetchProduct,
10811
- onNavigate: handleNavigate,
10812
- onBack: handleBack
10813
- });
10814
- return /* @__PURE__ */ jsx(ProductsScreen, {
10815
- countryCode,
10816
- fetchProducts,
10817
- onNavigate: (screen, detailId) => {
10818
- if (detailId) handleSelectProduct(detailId);
10819
- }
10820
- });
10821
- }
10822
- //#endregion
10823
10983
  //#region ../../file-picker/api-client/src/api/url-proxy.ts
10824
10984
  const urlProxyResponseSchema = z.object({
10825
10985
  data: z.string(),
@@ -11485,6 +11645,9 @@ function createPlaylistsAdapter(client) {
11485
11645
  items: [],
11486
11646
  items_count: 0
11487
11647
  };
11648
+ },
11649
+ reorderPlaylistItems: async (playlistId, data) => {
11650
+ await playlists_items_reorder(client, playlistId, { items: data.items });
11488
11651
  }
11489
11652
  };
11490
11653
  }
@@ -11851,6 +12014,184 @@ function PortalContentApiProvider({ children }) {
11851
12014
  });
11852
12015
  }
11853
12016
  //#endregion
11854
- export { ShareablesApp as a, ShareablesCoreProvider as c, ProductsApp as i, usePortalContentContext as n, useFilePickerApi as o, toggleFavorite as r, ShareablesUIProvider as s, PortalContentApiProvider as t };
12017
+ //#region src/screens/ShareablesScreen.tsx
12018
+ var ShareablesScreen_exports = /* @__PURE__ */ __exportAll({
12019
+ ShareablesScreen: () => ShareablesScreen,
12020
+ shareablesScreenPropertySchema: () => shareablesScreenPropertySchema
12021
+ });
12022
+ /**
12023
+ * Parse the current shareables sub-route from the full slug.
12024
+ *
12025
+ * System nav slugs are "share/products", "share/media", "share/playlists".
12026
+ * Detail pages append an ID: "share/products/123", "share/media/456".
12027
+ *
12028
+ * "share/products" → screen="products", detailId=null
12029
+ * "share/products/123" → screen="products", detailId="123"
12030
+ * "share/media/456" → screen="media", detailId="456"
12031
+ * "share/playlists" → screen="playlists", detailId=null
12032
+ * "share/playlists/789" → screen="playlists", detailId="789"
12033
+ * "share/files" → screen="files", detailId=null
12034
+ * "share" → screen=null (default to products)
12035
+ */
12036
+ function parseShareablesRoute(currentSlug) {
12037
+ const slugWithoutPrefix = currentSlug.replace(/^share\/?/, "");
12038
+ if (!slugWithoutPrefix) return {
12039
+ screen: null,
12040
+ detailId: null,
12041
+ action: null
12042
+ };
12043
+ const parts = slugWithoutPrefix.split("/");
12044
+ return {
12045
+ screen: parts[0] || null,
12046
+ detailId: parts[1] || null,
12047
+ action: parts[2] || null
12048
+ };
12049
+ }
12050
+ function ShareablesScreen({ background, textColor, accentColor, padding, borderRadius, ...divProps }) {
12051
+ return /* @__PURE__ */ jsx("div", {
12052
+ ...divProps,
12053
+ className: `h-full ${divProps.className ?? ""}`,
12054
+ children: /* @__PURE__ */ jsx(PortalProductsApiProvider, { children: /* @__PURE__ */ jsx(PortalContentApiProvider, { children: /* @__PURE__ */ jsx(ShareablesScreenContent, {}) }) })
12055
+ });
12056
+ }
12057
+ /** Inner component rendered inside providers so hooks can access context. */
12058
+ function ShareablesScreenContent() {
12059
+ const shareablesCtx = usePortalContentContext();
12060
+ const { productsApi: portalProductsApi } = shareablesCtx;
12061
+ const filePickerApi = useFilePickerApi();
12062
+ const { data: account } = useAccount();
12063
+ const { data: store } = useStore();
12064
+ const { currentSlug, navigate } = useAppNavigation();
12065
+ const isCustomer = account?.member_type === "customer";
12066
+ const client = usePortalTenantClient();
12067
+ const queryClient = useQueryClient();
12068
+ const fetchProducts = useCallback(async (search, cursor, limit, sort) => {
12069
+ if (search) return portalProductsApi.searchProducts(search, {
12070
+ cursor,
12071
+ limit
12072
+ });
12073
+ return portalProductsApi.listProducts({
12074
+ cursor,
12075
+ limit,
12076
+ sort
12077
+ });
12078
+ }, [portalProductsApi]);
12079
+ const fetchProduct = useCallback(async (id) => portalProductsApi.getProduct(id), [portalProductsApi]);
12080
+ const { screen, detailId, action } = parseShareablesRoute(currentSlug);
12081
+ const handleNavigate = useCallback((subScreen, id) => {
12082
+ navigate(id ? `share/${subScreen}/${id}` : `share/${subScreen}`);
12083
+ }, [navigate]);
12084
+ const handleBack = useCallback(() => {
12085
+ if (detailId && screen) navigate(`share/${screen}`);
12086
+ else navigate("share/products");
12087
+ }, [
12088
+ navigate,
12089
+ detailId,
12090
+ screen
12091
+ ]);
12092
+ return /* @__PURE__ */ jsx(ShareablesCoreProvider, {
12093
+ config: useMemo(() => ({
12094
+ user: account ? { id: account.id } : null,
12095
+ repContext: true
12096
+ }), [account]),
12097
+ children: /* @__PURE__ */ jsx(ShareablesUIProvider, {
12098
+ config: useMemo(() => ({
12099
+ user: account ? {
12100
+ id: account.id,
12101
+ company: { logo_url: store?.logo_url ?? null }
12102
+ } : void 0,
12103
+ affiliateId: null,
12104
+ basePath: "",
12105
+ navigate: (path) => {
12106
+ const cleanPath = path.replace(/^\//, "");
12107
+ navigate(cleanPath.startsWith("share/") ? cleanPath : `share/${cleanPath}`);
12108
+ },
12109
+ showToast: (opts) => {
12110
+ fluidToast({
12111
+ title: opts.title,
12112
+ type: opts.type
12113
+ });
12114
+ if (opts.error) console.error("[Shareables]", opts.error);
12115
+ },
12116
+ filePickerApi,
12117
+ onToggleFavorite: async (params) => {
12118
+ const result = await toggleFavorite(client, params.favoriteableId, params.favoriteableType);
12119
+ queryClient.invalidateQueries({ queryKey: PORTAL_MYSITE_KEYS.favorites() });
12120
+ return result;
12121
+ },
12122
+ onMySiteShare: async (params) => {
12123
+ await toggleFavorite(client, params.relateable_id, params.relateable_type);
12124
+ queryClient.invalidateQueries({ queryKey: PORTAL_MYSITE_KEYS.favorites() });
12125
+ },
12126
+ onDeletePlaylist: isCustomer ? void 0 : async (playlistId) => {
12127
+ await shareablesCtx.playlistsAdapter.deletePlaylist(playlistId);
12128
+ },
12129
+ mediaProductsApi: isCustomer ? void 0 : shareablesCtx.mediaProductsAdapter,
12130
+ searchProducts: isCustomer ? void 0 : async (query, options) => {
12131
+ const limit = options?.limit ?? 25;
12132
+ const cursor = options?.cursor ?? void 0;
12133
+ const result = query.trim().length > 0 ? await portalProductsApi.searchProducts(query, {
12134
+ cursor,
12135
+ limit
12136
+ }) : await portalProductsApi.listProducts({
12137
+ cursor,
12138
+ limit
12139
+ });
12140
+ return {
12141
+ products: (result.products ?? []).map((p) => p.id != null ? {
12142
+ id: p.id,
12143
+ name: p.name ?? p.title ?? "Untitled",
12144
+ image_url: p.image_url ?? null,
12145
+ price: p.price ?? null
12146
+ } : null).filter((p) => p !== null),
12147
+ nextCursor: result.meta?.pagination?.next_cursor ?? null
12148
+ };
12149
+ },
12150
+ readOnly: isCustomer,
12151
+ uploadThumbnail: isCustomer ? void 0 : async (blob, filename) => {
12152
+ const formData = new FormData();
12153
+ formData.append("asset[name]", filename);
12154
+ formData.append("asset[file]", blob, filename);
12155
+ const url = (await client.requestWithFormData("/api/content/dam/assets", formData)).asset?.default_variant_url;
12156
+ if (!url) throw new Error("Thumbnail upload succeeded but no URL returned");
12157
+ return url;
12158
+ }
12159
+ }), [
12160
+ account,
12161
+ store,
12162
+ navigate,
12163
+ filePickerApi,
12164
+ isCustomer,
12165
+ shareablesCtx.playlistsAdapter,
12166
+ shareablesCtx.mediaProductsAdapter,
12167
+ portalProductsApi,
12168
+ client,
12169
+ queryClient
12170
+ ]),
12171
+ children: /* @__PURE__ */ jsx(ShareablesApp, {
12172
+ screen,
12173
+ detailId,
12174
+ action,
12175
+ companyLogoUrl: void 0,
12176
+ countryCode: void 0,
12177
+ fetchProducts,
12178
+ fetchProduct,
12179
+ onNavigate: handleNavigate,
12180
+ onBack: handleBack
12181
+ })
12182
+ })
12183
+ });
12184
+ }
12185
+ const shareablesScreenPropertySchema = {
12186
+ widgetType: "ShareablesScreen",
12187
+ displayName: "Shareables Screen",
12188
+ tabsConfig: [{
12189
+ id: "styling",
12190
+ label: "Styling"
12191
+ }],
12192
+ fields: []
12193
+ };
12194
+ //#endregion
12195
+ export { ShareablesScreen_exports as n, shareablesScreenPropertySchema as r, ShareablesScreen as t };
11855
12196
 
11856
- //# sourceMappingURL=PortalContentApiProvider-C9FeVwRb.mjs.map
12197
+ //# sourceMappingURL=ShareablesScreen-DV2nikzp.mjs.map