@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.
- package/dist/{AppDownloadScreen-CZ0EOIZ5.mjs → AppDownloadScreen-Bhix461K.mjs} +1 -1
- package/dist/{AppDownloadScreen-CZ0EOIZ5.mjs.map → AppDownloadScreen-Bhix461K.mjs.map} +1 -1
- package/dist/{AppDownloadScreen-CBoC31wL.cjs → AppDownloadScreen-DwBzuPcF.cjs} +1 -1
- package/dist/{AppDownloadScreen-CBoC31wL.cjs.map → AppDownloadScreen-DwBzuPcF.cjs.map} +1 -1
- package/dist/{FluidProvider-22PONJDa.mjs → FluidProvider-DTttgSXi.mjs} +2 -2
- package/dist/{FluidProvider-22PONJDa.mjs.map → FluidProvider-DTttgSXi.mjs.map} +1 -1
- package/dist/{FluidProvider-DTdi38VO.cjs → FluidProvider-Dm4BhF_t.cjs} +2 -2
- package/dist/{FluidProvider-DTdi38VO.cjs.map → FluidProvider-Dm4BhF_t.cjs.map} +1 -1
- package/dist/{MessagingScreen-BM21ZxGL.mjs → MessagingScreen-CwEXQJlW.mjs} +2 -2
- package/dist/{MessagingScreen-BM21ZxGL.mjs.map → MessagingScreen-CwEXQJlW.mjs.map} +1 -1
- package/dist/{MessagingScreen-ehHW4LwI.cjs → MessagingScreen-DLQ5V0m4.cjs} +2 -2
- package/dist/{MessagingScreen-ehHW4LwI.cjs.map → MessagingScreen-DLQ5V0m4.cjs.map} +1 -1
- package/dist/{MessagingScreen-BDlC9VWJ.cjs → MessagingScreen-YBXJL7a9.cjs} +2 -2
- package/dist/{MySiteScreen-DUN5TTvU.mjs → MySiteScreen-BAPWqDfm.mjs} +11 -31
- package/dist/{MySiteScreen-DUN5TTvU.mjs.map → MySiteScreen-BAPWqDfm.mjs.map} +1 -1
- package/dist/{MySiteScreen-B0aOIzU4.cjs → MySiteScreen-CEX1qxdj.cjs} +2 -3
- package/dist/{MySiteScreen-B1L8coGs.cjs → MySiteScreen-DaNlmVSi.cjs} +24 -44
- package/dist/MySiteScreen-DaNlmVSi.cjs.map +1 -0
- package/dist/{PortalProductsApiProvider-CE71zDj9.mjs → PortalProductsApiProvider-BwIRudl_.mjs} +1 -1
- package/dist/{PortalProductsApiProvider-CE71zDj9.mjs.map → PortalProductsApiProvider-BwIRudl_.mjs.map} +1 -1
- package/dist/{PortalProductsApiProvider-Ca1oeTtJ.cjs → PortalProductsApiProvider-CRaocswH.cjs} +1 -1
- package/dist/{PortalProductsApiProvider-Ca1oeTtJ.cjs.map → PortalProductsApiProvider-CRaocswH.cjs.map} +1 -1
- package/dist/{ProfileScreen-DNRpWpex.cjs → ProfileScreen-B0WRifk_.cjs} +2 -2
- package/dist/{ProfileScreen-DNRpWpex.cjs.map → ProfileScreen-B0WRifk_.cjs.map} +1 -1
- package/dist/{ProfileScreen-VonnJyFa.mjs → ProfileScreen-BuejQU_V.mjs} +2 -2
- package/dist/{ProfileScreen-VonnJyFa.mjs.map → ProfileScreen-BuejQU_V.mjs.map} +1 -1
- package/dist/{ProfileScreen-CN1DDd-Q.cjs → ProfileScreen-g3se9Jw-.cjs} +2 -2
- package/dist/{ShareablesScreen-smU5pGyH.cjs → ShareablesScreen-CqvPzH1v.cjs} +3 -5
- package/dist/{PortalContentApiProvider-C9FeVwRb.mjs → ShareablesScreen-DV2nikzp.mjs} +460 -119
- package/dist/ShareablesScreen-DV2nikzp.mjs.map +1 -0
- package/dist/{PortalContentApiProvider-RXBp8FNj.cjs → ShareablesScreen-DwnMBftJ.cjs} +457 -156
- package/dist/ShareablesScreen-DwnMBftJ.cjs.map +1 -0
- package/dist/{ShopScreen-BAbAc2ah.cjs → ShopScreen-C-Ki6fuh.cjs} +3 -3
- package/dist/{ShopScreen-DQ1-68kV.mjs → ShopScreen-C2K1C2tt.mjs} +3 -3
- package/dist/{ShopScreen-DQ1-68kV.mjs.map → ShopScreen-C2K1C2tt.mjs.map} +1 -1
- package/dist/{ShopScreen-DcJ0DLvB.cjs → ShopScreen-smzNn37E.cjs} +3 -3
- package/dist/{ShopScreen-DcJ0DLvB.cjs.map → ShopScreen-smzNn37E.cjs.map} +1 -1
- package/dist/{UpgradeScreen-BdY0rCoF.cjs → UpgradeScreen-CNXQ1hcP.cjs} +1 -1
- package/dist/{UpgradeScreen-Dau5Elx4.mjs → UpgradeScreen-ChLiVSf7.mjs} +1 -1
- package/dist/{UpgradeScreen-Dau5Elx4.mjs.map → UpgradeScreen-ChLiVSf7.mjs.map} +1 -1
- package/dist/{UpgradeScreen-DrBa2uzD.cjs → UpgradeScreen-DMJUK4dl.cjs} +1 -1
- package/dist/{UpgradeScreen-DrBa2uzD.cjs.map → UpgradeScreen-DMJUK4dl.cjs.map} +1 -1
- package/dist/{dist-DWs3-WOI.cjs → dist-Bxa9x0H9.cjs} +218 -1
- package/dist/{dist-DWs3-WOI.cjs.map → dist-Bxa9x0H9.cjs.map} +1 -1
- package/dist/index.cjs +24 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -20
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -20
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +25 -52
- package/dist/index.mjs.map +1 -1
- package/dist/{portal_tenant_content-0zpnjBot.cjs → portal_tenant_content-BvYxmADB.cjs} +18 -1
- package/dist/portal_tenant_content-BvYxmADB.cjs.map +1 -0
- package/dist/{portal_tenant_content-DzIQtSLE.mjs → portal_tenant_content-nHEI2qEY.mjs} +13 -2
- package/dist/portal_tenant_content-nHEI2qEY.mjs.map +1 -0
- package/dist/{sortable.esm-CJLSD-Ce.mjs → sortable.esm-fSGrAZU2.mjs} +141 -2
- package/dist/sortable.esm-fSGrAZU2.mjs.map +1 -0
- package/package.json +14 -14
- package/dist/MySiteScreen-B1L8coGs.cjs.map +0 -1
- package/dist/PortalContentApiProvider-C9FeVwRb.mjs.map +0 -1
- package/dist/PortalContentApiProvider-RXBp8FNj.cjs.map +0 -1
- package/dist/ProductsScreen-BD53vh6Y.cjs +0 -103
- package/dist/ProductsScreen-BD53vh6Y.cjs.map +0 -1
- package/dist/ProductsScreen-BtUZxJCt.mjs +0 -91
- package/dist/ProductsScreen-BtUZxJCt.mjs.map +0 -1
- package/dist/ProductsScreen-DNpzJ6lh.cjs +0 -15
- package/dist/ProductsScreen-pkOeOW8M.mjs +0 -13
- package/dist/ShareablesScreen-CW1e9x4K.mjs +0 -188
- package/dist/ShareablesScreen-CW1e9x4K.mjs.map +0 -1
- package/dist/ShareablesScreen-D1J2Kljk.mjs +0 -15
- package/dist/ShareablesScreen-DC8xXUo4.cjs +0 -200
- package/dist/ShareablesScreen-DC8xXUo4.cjs.map +0 -1
- package/dist/portal_tenant_content-0zpnjBot.cjs.map +0 -1
- package/dist/portal_tenant_content-DzIQtSLE.mjs.map +0 -1
- package/dist/sortable.esm-CJLSD-Ce.mjs.map +0 -1
- package/dist/use-mysite-portal-BV-BP3CE.mjs +0 -141
- package/dist/use-mysite-portal-BV-BP3CE.mjs.map +0 -1
- package/dist/use-mysite-portal-DzDYRU0u.cjs +0 -219
- package/dist/use-mysite-portal-DzDYRU0u.cjs.map +0 -1
|
@@ -1,14 +1,17 @@
|
|
|
1
1
|
const require_chunk = require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_portal_tenant_content = require("./portal_tenant_content-
|
|
2
|
+
const require_portal_tenant_content = require("./portal_tenant_content-BvYxmADB.cjs");
|
|
3
3
|
const require_PortalTenantClientProvider = require("./PortalTenantClientProvider-CVv-4rQ9.cjs");
|
|
4
4
|
const require_src = require("./src-aItPhUAR.cjs");
|
|
5
5
|
const require_ScreenHeaderContext = require("./ScreenHeaderContext-BXgWydjB.cjs");
|
|
6
|
+
const require_use_account = require("./use-account-C5QI6NSe.cjs");
|
|
7
|
+
const require_use_store = require("./use-store-BLcehk1A.cjs");
|
|
8
|
+
const require_AppNavigationContext = require("./AppNavigationContext-CbK8uCjS.cjs");
|
|
6
9
|
const require_dist$3 = require("./dist-CGuUUVNt.cjs");
|
|
7
10
|
const require_es = require("./es-DHLLltoR.cjs");
|
|
8
11
|
const require_SearchSort = require("./SearchSort-DHDDqero.cjs");
|
|
9
12
|
const require_dist$4 = require("./dist-DDZMFlal.cjs");
|
|
10
|
-
const require_dist$5 = require("./dist-
|
|
11
|
-
const require_PortalProductsApiProvider = require("./PortalProductsApiProvider-
|
|
13
|
+
const require_dist$5 = require("./dist-Bxa9x0H9.cjs");
|
|
14
|
+
const require_PortalProductsApiProvider = require("./PortalProductsApiProvider-CRaocswH.cjs");
|
|
12
15
|
let react = require("react");
|
|
13
16
|
react = require_chunk.__toESM(react);
|
|
14
17
|
let _tanstack_react_query = require("@tanstack/react-query");
|
|
@@ -288,6 +291,25 @@ const useUpdatePlaylistMutation = (options) => {
|
|
|
288
291
|
}
|
|
289
292
|
});
|
|
290
293
|
};
|
|
294
|
+
const useReorderPlaylistItemsMutation = (options) => {
|
|
295
|
+
const api = useShareablesApi();
|
|
296
|
+
const queryClient = (0, _tanstack_react_query.useQueryClient)();
|
|
297
|
+
return (0, _tanstack_react_query.useMutation)({
|
|
298
|
+
mutationFn: ({ playlistId, data }) => {
|
|
299
|
+
if (!api.playlists.reorderPlaylistItems) return Promise.resolve();
|
|
300
|
+
return api.playlists.reorderPlaylistItems(playlistId, data);
|
|
301
|
+
},
|
|
302
|
+
onSuccess: (_, { playlistId }) => {
|
|
303
|
+
if (api.playlists.reorderPlaylistItems) queryClient.invalidateQueries({ queryKey: shareablesKeys.playlists.detail(playlistId) });
|
|
304
|
+
options?.onSuccess?.(playlistId);
|
|
305
|
+
},
|
|
306
|
+
onError: (error, { playlistId }) => {
|
|
307
|
+
if (isCancellationError(error)) return;
|
|
308
|
+
console.error("Error reordering playlist items:", error);
|
|
309
|
+
options?.onError?.(error, playlistId);
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
};
|
|
291
313
|
//#endregion
|
|
292
314
|
//#region ../../shareables/ui/src/context.tsx
|
|
293
315
|
const MISSING_PROVIDER = Symbol("missing-shareables-provider");
|
|
@@ -578,6 +600,83 @@ function ShareableListLayout({ filters, children, isLoading, error, errorMessage
|
|
|
578
600
|
});
|
|
579
601
|
}
|
|
580
602
|
//#endregion
|
|
603
|
+
//#region ../../shareables/ui/src/components/shared/ShareableListRow.tsx
|
|
604
|
+
/**
|
|
605
|
+
* Container className for a list-view rendering of shareables. Pairs with
|
|
606
|
+
* `ShareableListRow` and mirrors `SHAREABLE_GRID_CLASS` for symmetry.
|
|
607
|
+
*/
|
|
608
|
+
const SHAREABLE_LIST_CLASS = "divide-border divide-y rounded-lg border";
|
|
609
|
+
/**
|
|
610
|
+
* Single row in a shareables list view. The row body (thumbnail + title) is
|
|
611
|
+
* a `<button>` for keyboard/click navigation; `leading` and `trailing` slots
|
|
612
|
+
* are siblings so their interactive elements don't nest inside the body
|
|
613
|
+
* button. Hover styling applies to the entire row container.
|
|
614
|
+
*/
|
|
615
|
+
function ShareableListRow({ imageUrl, imageAlt, title, subtitle, onClick, leading, trailing }) {
|
|
616
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
617
|
+
className: "hover:bg-muted flex items-center gap-3 px-4 py-3 transition-colors",
|
|
618
|
+
children: [
|
|
619
|
+
leading,
|
|
620
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
621
|
+
type: "button",
|
|
622
|
+
onClick,
|
|
623
|
+
className: "flex min-w-0 flex-1 items-center gap-4 text-left",
|
|
624
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
625
|
+
className: "bg-muted h-12 w-12 shrink-0 overflow-hidden rounded-md",
|
|
626
|
+
children: imageUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
627
|
+
src: imageUrl,
|
|
628
|
+
alt: imageAlt ?? title,
|
|
629
|
+
className: "h-full w-full object-cover"
|
|
630
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-full w-full" })
|
|
631
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
632
|
+
className: "min-w-0 flex-1",
|
|
633
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
634
|
+
className: "text-foreground truncate text-sm font-medium",
|
|
635
|
+
children: title || "Untitled"
|
|
636
|
+
}), subtitle != null && subtitle !== false && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
637
|
+
className: "text-muted-foreground flex items-center gap-1.5 text-xs",
|
|
638
|
+
children: subtitle
|
|
639
|
+
})]
|
|
640
|
+
})]
|
|
641
|
+
}),
|
|
642
|
+
trailing
|
|
643
|
+
]
|
|
644
|
+
});
|
|
645
|
+
}
|
|
646
|
+
//#endregion
|
|
647
|
+
//#region ../../shareables/ui/src/components/shared/ViewModeToggle.tsx
|
|
648
|
+
/**
|
|
649
|
+
* Segmented list/grid toggle used in the filter bar of every shareable
|
|
650
|
+
* listing screen. Stateless — callers own the `viewMode` state.
|
|
651
|
+
*/
|
|
652
|
+
function ViewModeToggle({ value, onChange }) {
|
|
653
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
654
|
+
className: "border-input bg-muted flex items-center rounded-lg border p-0.5",
|
|
655
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleButton, {
|
|
656
|
+
active: value === "list",
|
|
657
|
+
label: "List view",
|
|
658
|
+
onClick: () => onChange("list"),
|
|
659
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.List, { className: "h-4 w-4" })
|
|
660
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToggleButton, {
|
|
661
|
+
active: value === "grid",
|
|
662
|
+
label: "Grid view",
|
|
663
|
+
onClick: () => onChange("grid"),
|
|
664
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.LayoutGrid, { className: "h-4 w-4" })
|
|
665
|
+
})]
|
|
666
|
+
});
|
|
667
|
+
}
|
|
668
|
+
function ToggleButton({ active, label, onClick, children }) {
|
|
669
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
670
|
+
type: "button",
|
|
671
|
+
onClick,
|
|
672
|
+
title: label,
|
|
673
|
+
"aria-label": label,
|
|
674
|
+
"aria-pressed": active,
|
|
675
|
+
className: require_src.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"),
|
|
676
|
+
children
|
|
677
|
+
});
|
|
678
|
+
}
|
|
679
|
+
//#endregion
|
|
581
680
|
//#region ../../shareables/ui/src/components/screens/ProductsScreen.tsx
|
|
582
681
|
const PAGE_SIZE$4 = 24;
|
|
583
682
|
const SORT_OPTIONS$1 = [
|
|
@@ -608,6 +707,7 @@ const SORT_OPTIONS$1 = [
|
|
|
608
707
|
];
|
|
609
708
|
function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNavigate }) {
|
|
610
709
|
const client = useShareablesClient();
|
|
710
|
+
const { navigate } = useShareablesUI();
|
|
611
711
|
require_ScreenHeaderContext.useScreenHeaderBreadcrumbs((0, react.useMemo)(() => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Breadcrumb, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbList, {
|
|
612
712
|
className: "text-lg",
|
|
613
713
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbItem, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.BreadcrumbPage, {
|
|
@@ -618,6 +718,7 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
|
|
|
618
718
|
const [searchTerm, setSearchTerm] = (0, react.useState)("");
|
|
619
719
|
const [debouncedSearch, setDebouncedSearch] = (0, react.useState)("");
|
|
620
720
|
const [sortValue, setSortValue] = (0, react.useState)("created_at_desc");
|
|
721
|
+
const [viewMode, setViewMode] = (0, react.useState)("grid");
|
|
621
722
|
const observerTarget = (0, react.useRef)(null);
|
|
622
723
|
(0, react.useEffect)(() => {
|
|
623
724
|
const timer = setTimeout(() => {
|
|
@@ -705,9 +806,9 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
|
|
|
705
806
|
errorMessage: "Failed to load products. Please try again.",
|
|
706
807
|
isEmpty: products.length === 0,
|
|
707
808
|
emptyMessage: debouncedSearch ? "No products match your search." : "No products available.",
|
|
708
|
-
filters: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
709
|
-
className: "flex justify-end",
|
|
710
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
809
|
+
filters: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
810
|
+
className: "flex items-center justify-end gap-2",
|
|
811
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
711
812
|
className: "w-full max-w-sm",
|
|
712
813
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SearchSort.SearchSort, {
|
|
713
814
|
searchValue: searchTerm,
|
|
@@ -717,14 +818,18 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
|
|
|
717
818
|
sortValue,
|
|
718
819
|
onSortChange: setSortValue
|
|
719
820
|
})
|
|
720
|
-
})
|
|
821
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModeToggle, {
|
|
822
|
+
value: viewMode,
|
|
823
|
+
onChange: setViewMode
|
|
824
|
+
})]
|
|
721
825
|
}),
|
|
826
|
+
loadingFilterShape: "search-view",
|
|
722
827
|
footer: isFetchingNextPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
723
828
|
className: "flex justify-center py-4",
|
|
724
829
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-primary h-6 w-6 animate-spin rounded-full border-2 border-t-transparent" })
|
|
725
830
|
}),
|
|
726
831
|
sentinelRef: observerTarget,
|
|
727
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
832
|
+
children: viewMode === "grid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
728
833
|
className: SHAREABLE_GRID_CLASS,
|
|
729
834
|
children: products.map((product) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareProductCard, {
|
|
730
835
|
product: {
|
|
@@ -734,6 +839,14 @@ function ProductsScreen({ countryCode, fetchProducts: fetchPortalProducts, onNav
|
|
|
734
839
|
},
|
|
735
840
|
mediaCount: product.media_count
|
|
736
841
|
}, product.id))
|
|
842
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
843
|
+
className: SHAREABLE_LIST_CLASS,
|
|
844
|
+
children: products.map((product) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareableListRow, {
|
|
845
|
+
imageUrl: product.image_url,
|
|
846
|
+
title: product.title,
|
|
847
|
+
subtitle: product.media_count != null ? `${product.media_count} assets` : void 0,
|
|
848
|
+
onClick: () => navigate(`product/${product.id}`)
|
|
849
|
+
}, product.id))
|
|
737
850
|
})
|
|
738
851
|
});
|
|
739
852
|
}
|
|
@@ -1703,21 +1816,9 @@ function MediaListingScreen({ onNavigate }) {
|
|
|
1703
1816
|
}), kindFilter === opt.value && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Check, { className: "text-muted-foreground size-4" })]
|
|
1704
1817
|
}, opt.value))
|
|
1705
1818
|
})] }),
|
|
1706
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
type: "button",
|
|
1710
|
-
onClick: () => setViewMode("list"),
|
|
1711
|
-
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"}`,
|
|
1712
|
-
title: "List view",
|
|
1713
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.List, { className: "h-4 w-4" })
|
|
1714
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
1715
|
-
type: "button",
|
|
1716
|
-
onClick: () => setViewMode("grid"),
|
|
1717
|
-
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"}`,
|
|
1718
|
-
title: "Grid view",
|
|
1719
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.LayoutGrid, { className: "h-4 w-4" })
|
|
1720
|
-
})]
|
|
1819
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModeToggle, {
|
|
1820
|
+
value: viewMode,
|
|
1821
|
+
onChange: setViewMode
|
|
1721
1822
|
})
|
|
1722
1823
|
]
|
|
1723
1824
|
})]
|
|
@@ -1787,37 +1888,20 @@ function MediaListingScreen({ onNavigate }) {
|
|
|
1787
1888
|
}, item.id);
|
|
1788
1889
|
})
|
|
1789
1890
|
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1790
|
-
className:
|
|
1891
|
+
className: SHAREABLE_LIST_CLASS,
|
|
1791
1892
|
children: filteredItems.map((item) => {
|
|
1792
1893
|
const canEdit = !readOnly && item.owner_type === "user";
|
|
1793
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
1794
|
-
|
|
1795
|
-
|
|
1796
|
-
|
|
1797
|
-
|
|
1798
|
-
|
|
1799
|
-
|
|
1800
|
-
|
|
1801
|
-
|
|
1802
|
-
|
|
1803
|
-
|
|
1804
|
-
className: "h-full w-full object-cover"
|
|
1805
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "bg-muted h-full w-full" })
|
|
1806
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1807
|
-
className: "min-w-0 flex-1",
|
|
1808
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
1809
|
-
className: "text-foreground truncate text-sm font-medium",
|
|
1810
|
-
children: item.title ?? "Untitled"
|
|
1811
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1812
|
-
className: "text-muted-foreground flex items-center gap-1.5 text-xs",
|
|
1813
|
-
children: [getMediaKindLabel(item.kind), item.owner_type === "user" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Badge, {
|
|
1814
|
-
variant: "secondary",
|
|
1815
|
-
className: "px-1.5 py-0 text-[10px] leading-4",
|
|
1816
|
-
children: "My Media"
|
|
1817
|
-
})]
|
|
1818
|
-
})]
|
|
1819
|
-
})]
|
|
1820
|
-
}), canEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaRowActionsMenu, { onDelete: () => setPendingDeleteId(item.id) })]
|
|
1894
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareableListRow, {
|
|
1895
|
+
imageUrl: item.image_url,
|
|
1896
|
+
imageAlt: item.title ?? "",
|
|
1897
|
+
title: item.title ?? "Untitled",
|
|
1898
|
+
subtitle: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [getMediaKindLabel(item.kind), item.owner_type === "user" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Badge, {
|
|
1899
|
+
variant: "secondary",
|
|
1900
|
+
className: "px-1.5 py-0 text-[10px] leading-4",
|
|
1901
|
+
children: "My Media"
|
|
1902
|
+
})] }),
|
|
1903
|
+
onClick: () => navigate(`media/${item.id}`),
|
|
1904
|
+
trailing: canEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(MediaRowActionsMenu, { onDelete: () => setPendingDeleteId(item.id) })
|
|
1821
1905
|
}, item.id);
|
|
1822
1906
|
})
|
|
1823
1907
|
})
|
|
@@ -8936,6 +9020,7 @@ function PlaylistsListingScreen(_props) {
|
|
|
8936
9020
|
const [debouncedSearch, setDebouncedSearch] = (0, react.useState)("");
|
|
8937
9021
|
const [sortValue, setSortValue] = (0, react.useState)("title");
|
|
8938
9022
|
const [ownerFilter, setOwnerFilter] = (0, react.useState)("all");
|
|
9023
|
+
const [viewMode, setViewMode] = (0, react.useState)("grid");
|
|
8939
9024
|
const [selectedIds, setSelectedIds] = (0, react.useState)(/* @__PURE__ */ new Set());
|
|
8940
9025
|
const [pendingDeleteId, setPendingDeleteId] = (0, react.useState)(null);
|
|
8941
9026
|
(0, react.useEffect)(() => {
|
|
@@ -9106,33 +9191,39 @@ function PlaylistsListingScreen(_props) {
|
|
|
9106
9191
|
value: ownerFilter,
|
|
9107
9192
|
onValueChange: setOwnerFilter,
|
|
9108
9193
|
myLabel: "My Playlists"
|
|
9109
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.
|
|
9110
|
-
className: "ml-auto
|
|
9111
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9112
|
-
|
|
9113
|
-
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9128
|
-
|
|
9129
|
-
|
|
9130
|
-
|
|
9131
|
-
|
|
9132
|
-
|
|
9133
|
-
|
|
9134
|
-
|
|
9135
|
-
|
|
9194
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
9195
|
+
className: "ml-auto flex items-center gap-2",
|
|
9196
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9197
|
+
className: "w-full max-w-sm",
|
|
9198
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_SearchSort.SearchSort, {
|
|
9199
|
+
searchValue: searchTerm,
|
|
9200
|
+
onSearchChange: setSearchTerm,
|
|
9201
|
+
placeholder: "Search playlists...",
|
|
9202
|
+
sortOptions: [
|
|
9203
|
+
{
|
|
9204
|
+
label: "Name (A-Z)",
|
|
9205
|
+
value: "title"
|
|
9206
|
+
},
|
|
9207
|
+
{
|
|
9208
|
+
label: "Name (Z-A)",
|
|
9209
|
+
value: "-title"
|
|
9210
|
+
},
|
|
9211
|
+
{
|
|
9212
|
+
label: "Date Created (Newest)",
|
|
9213
|
+
value: "-created_at"
|
|
9214
|
+
},
|
|
9215
|
+
{
|
|
9216
|
+
label: "Date Created (Oldest)",
|
|
9217
|
+
value: "created_at"
|
|
9218
|
+
}
|
|
9219
|
+
],
|
|
9220
|
+
sortValue,
|
|
9221
|
+
onSortChange: setSortValue
|
|
9222
|
+
})
|
|
9223
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ViewModeToggle, {
|
|
9224
|
+
value: viewMode,
|
|
9225
|
+
onChange: setViewMode
|
|
9226
|
+
})]
|
|
9136
9227
|
})]
|
|
9137
9228
|
});
|
|
9138
9229
|
const footer = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [isFetchingNextPage && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -9154,8 +9245,8 @@ function PlaylistsListingScreen(_props) {
|
|
|
9154
9245
|
}),
|
|
9155
9246
|
footer,
|
|
9156
9247
|
sentinelRef: observerTarget,
|
|
9157
|
-
loadingFilterShape: "search-
|
|
9158
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9248
|
+
loadingFilterShape: "search-view",
|
|
9249
|
+
children: viewMode === "grid" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9159
9250
|
className: GRID_CLASS,
|
|
9160
9251
|
children: filteredPlaylists.map((playlist) => {
|
|
9161
9252
|
const firstItem = playlist.items?.[0];
|
|
@@ -9177,6 +9268,61 @@ function PlaylistsListingScreen(_props) {
|
|
|
9177
9268
|
onDelete: onDeletePlaylist ? () => setPendingDeleteId(playlist.id) : void 0
|
|
9178
9269
|
}, playlist.id);
|
|
9179
9270
|
})
|
|
9271
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9272
|
+
className: SHAREABLE_LIST_CLASS,
|
|
9273
|
+
children: filteredPlaylists.map((playlist) => {
|
|
9274
|
+
const firstItem = playlist.items?.[0];
|
|
9275
|
+
const imageUrl = playlist.image_url ?? firstItem?.image_url ?? firstItem?.relateable?.image_url ?? firstItem?.relateable?.compressed_image_url;
|
|
9276
|
+
const itemCount = playlist.items_count ?? playlist.items?.length ?? 0;
|
|
9277
|
+
const canEdit = !readOnly && playlist.user_id === user?.id;
|
|
9278
|
+
const isSelected = selectedIds.has(playlist.id);
|
|
9279
|
+
const title = playlist.title || "Untitled Playlist";
|
|
9280
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareableListRow, {
|
|
9281
|
+
imageUrl,
|
|
9282
|
+
title,
|
|
9283
|
+
subtitle: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.Badge, {
|
|
9284
|
+
variant: "secondary",
|
|
9285
|
+
className: "px-1.5 py-0 text-[10px] leading-4",
|
|
9286
|
+
children: [
|
|
9287
|
+
itemCount,
|
|
9288
|
+
" ",
|
|
9289
|
+
itemCount === 1 ? "item" : "items"
|
|
9290
|
+
]
|
|
9291
|
+
}),
|
|
9292
|
+
onClick: () => navigate(`playlists/${playlist.id}`),
|
|
9293
|
+
leading: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Checkbox, {
|
|
9294
|
+
checked: isSelected,
|
|
9295
|
+
onCheckedChange: (checked) => handleToggleSelection(playlist.id, checked === true),
|
|
9296
|
+
"aria-label": `Select ${title}`
|
|
9297
|
+
}),
|
|
9298
|
+
trailing: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [onToggleFavorite && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9299
|
+
type: "button",
|
|
9300
|
+
onClick: () => handleFavorite(playlist.id),
|
|
9301
|
+
"aria-label": playlist.is_favorited ? "Unfavorite" : "Favorite",
|
|
9302
|
+
className: "hover:bg-muted-foreground/10 flex h-8 w-8 items-center justify-center rounded-md transition-colors",
|
|
9303
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Heart, { className: require_src.cn("h-4 w-4 transition-colors", playlist.is_favorited ? "fill-destructive text-destructive" : "text-muted-foreground") })
|
|
9304
|
+
}), canEdit && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuTrigger, {
|
|
9305
|
+
asChild: true,
|
|
9306
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.Button, {
|
|
9307
|
+
variant: "ghost",
|
|
9308
|
+
size: "sm",
|
|
9309
|
+
className: "h-8 w-8 p-0",
|
|
9310
|
+
"aria-label": "Playlist actions",
|
|
9311
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.MoreVertical, { className: "h-4 w-4" })
|
|
9312
|
+
})
|
|
9313
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenuContent, {
|
|
9314
|
+
align: "end",
|
|
9315
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenuItem, {
|
|
9316
|
+
onClick: () => handleEdit(playlist.id),
|
|
9317
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Pencil, { className: "mr-2 h-4 w-4" }), "Edit"]
|
|
9318
|
+
}), onDeletePlaylist && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.DropdownMenuSeparator, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(require_src.DropdownMenuItem, {
|
|
9319
|
+
variant: "destructive",
|
|
9320
|
+
onClick: () => setPendingDeleteId(playlist.id),
|
|
9321
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Trash2, { className: "mr-2 h-4 w-4" }), "Delete"]
|
|
9322
|
+
})] })]
|
|
9323
|
+
})] })] })
|
|
9324
|
+
}, playlist.id);
|
|
9325
|
+
})
|
|
9180
9326
|
})
|
|
9181
9327
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_src.AlertDialog, {
|
|
9182
9328
|
open: pendingDeleteId !== null,
|
|
@@ -10065,6 +10211,7 @@ function SortableTable({ items, setItems, onDeleteItem, isDeletePending, enableR
|
|
|
10065
10211
|
}
|
|
10066
10212
|
//#endregion
|
|
10067
10213
|
//#region ../../shareables/ui/src/components/playlists/form/PlaylistItemsSection.tsx
|
|
10214
|
+
const REORDER_DEBOUNCE_MS = 500;
|
|
10068
10215
|
const PLAYLIST_CONTENT_TYPES = new Set([
|
|
10069
10216
|
"Medium",
|
|
10070
10217
|
"Page",
|
|
@@ -10134,9 +10281,53 @@ function PlaylistItemsSection({ playlistId }) {
|
|
|
10134
10281
|
});
|
|
10135
10282
|
}
|
|
10136
10283
|
});
|
|
10284
|
+
const reorderItemsMutation = useReorderPlaylistItemsMutation();
|
|
10285
|
+
const reorderTimerRef = (0, react.useRef)(null);
|
|
10286
|
+
const reorderRollbackRef = (0, react.useRef)(null);
|
|
10287
|
+
(0, react.useEffect)(() => () => {
|
|
10288
|
+
if (reorderTimerRef.current) clearTimeout(reorderTimerRef.current);
|
|
10289
|
+
}, []);
|
|
10290
|
+
const canPersistReorder = !!api.playlists.reorderPlaylistItems;
|
|
10137
10291
|
const mergeAndOrder = (0, react.useCallback)((reorderedContent) => {
|
|
10138
|
-
|
|
10139
|
-
|
|
10292
|
+
const ordered = computeOrderedItems([...reorderedContent, ...tailItems]);
|
|
10293
|
+
if (playlistId && canPersistReorder && reorderTimerRef.current === null && reorderRollbackRef.current === null) reorderRollbackRef.current = tableItems;
|
|
10294
|
+
updateItems(ordered);
|
|
10295
|
+
if (!playlistId || !canPersistReorder) return;
|
|
10296
|
+
if (reorderTimerRef.current) clearTimeout(reorderTimerRef.current);
|
|
10297
|
+
reorderTimerRef.current = setTimeout(() => {
|
|
10298
|
+
reorderTimerRef.current = null;
|
|
10299
|
+
const rollback = reorderRollbackRef.current;
|
|
10300
|
+
reorderItemsMutation.mutate({
|
|
10301
|
+
playlistId,
|
|
10302
|
+
data: { items: ordered.filter((item) => Number.isInteger(item.id) && typeof item.order === "number").map((item) => ({
|
|
10303
|
+
id: item.id,
|
|
10304
|
+
order: item.order
|
|
10305
|
+
})) }
|
|
10306
|
+
}, {
|
|
10307
|
+
onSuccess: () => {
|
|
10308
|
+
if (reorderTimerRef.current === null) reorderRollbackRef.current = null;
|
|
10309
|
+
else reorderRollbackRef.current = ordered;
|
|
10310
|
+
},
|
|
10311
|
+
onError: (error) => {
|
|
10312
|
+
if (rollback) updateItems(rollback);
|
|
10313
|
+
reorderRollbackRef.current = null;
|
|
10314
|
+
showToast({
|
|
10315
|
+
title: "Failed to save new item order",
|
|
10316
|
+
type: "error",
|
|
10317
|
+
error
|
|
10318
|
+
});
|
|
10319
|
+
}
|
|
10320
|
+
});
|
|
10321
|
+
}, REORDER_DEBOUNCE_MS);
|
|
10322
|
+
}, [
|
|
10323
|
+
tailItems,
|
|
10324
|
+
tableItems,
|
|
10325
|
+
updateItems,
|
|
10326
|
+
playlistId,
|
|
10327
|
+
canPersistReorder,
|
|
10328
|
+
reorderItemsMutation.mutate,
|
|
10329
|
+
showToast
|
|
10330
|
+
]);
|
|
10140
10331
|
const handleDeleteItem = (itemId) => {
|
|
10141
10332
|
removeItem(itemId);
|
|
10142
10333
|
if (playlistId) removeItemMutation.mutate({
|
|
@@ -10192,13 +10383,7 @@ function PlaylistItemsSection({ playlistId }) {
|
|
|
10192
10383
|
type: "success"
|
|
10193
10384
|
});
|
|
10194
10385
|
} catch {}
|
|
10195
|
-
else
|
|
10196
|
-
addItem(newItem);
|
|
10197
|
-
showToast({
|
|
10198
|
-
title: "Item added. Save the playlist to persist these items.",
|
|
10199
|
-
type: "warning"
|
|
10200
|
-
});
|
|
10201
|
-
}
|
|
10386
|
+
else addItem(newItem);
|
|
10202
10387
|
}
|
|
10203
10388
|
};
|
|
10204
10389
|
const filePickerContextValue = (0, react.useMemo)(() => {
|
|
@@ -10800,31 +10985,6 @@ function ShareablesApp({ screen, detailId, action, onNavigate, onBack, countryCo
|
|
|
10800
10985
|
return content;
|
|
10801
10986
|
}
|
|
10802
10987
|
//#endregion
|
|
10803
|
-
//#region ../../shareables/ui/src/components/ProductsApp.tsx
|
|
10804
|
-
function ProductsApp({ countryCode, companyLogoUrl, fetchProducts, fetchProduct, productId: controlledProductId, onSelectProduct: onSelectProductProp, onBack: onBackProp }) {
|
|
10805
|
-
const [internalProductId, setInternalProductId] = (0, react.useState)(null);
|
|
10806
|
-
const activeProductId = controlledProductId !== void 0 ? controlledProductId : internalProductId;
|
|
10807
|
-
const handleSelectProduct = onSelectProductProp ?? setInternalProductId;
|
|
10808
|
-
const handleBack = onBackProp ?? (() => setInternalProductId(null));
|
|
10809
|
-
const handleNavigate = (screen, detailId) => {
|
|
10810
|
-
if (screen === "products" && detailId) handleSelectProduct(detailId);
|
|
10811
|
-
};
|
|
10812
|
-
if (activeProductId) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductDetailScreen, {
|
|
10813
|
-
productId: activeProductId,
|
|
10814
|
-
countryCode,
|
|
10815
|
-
fetchProduct,
|
|
10816
|
-
onNavigate: handleNavigate,
|
|
10817
|
-
onBack: handleBack
|
|
10818
|
-
});
|
|
10819
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ProductsScreen, {
|
|
10820
|
-
countryCode,
|
|
10821
|
-
fetchProducts,
|
|
10822
|
-
onNavigate: (screen, detailId) => {
|
|
10823
|
-
if (detailId) handleSelectProduct(detailId);
|
|
10824
|
-
}
|
|
10825
|
-
});
|
|
10826
|
-
}
|
|
10827
|
-
//#endregion
|
|
10828
10988
|
//#region ../../file-picker/api-client/src/api/url-proxy.ts
|
|
10829
10989
|
const urlProxyResponseSchema = zod.z.object({
|
|
10830
10990
|
data: zod.z.string(),
|
|
@@ -11490,6 +11650,9 @@ function createPlaylistsAdapter(client) {
|
|
|
11490
11650
|
items: [],
|
|
11491
11651
|
items_count: 0
|
|
11492
11652
|
};
|
|
11653
|
+
},
|
|
11654
|
+
reorderPlaylistItems: async (playlistId, data) => {
|
|
11655
|
+
await require_portal_tenant_content.playlists_items_reorder(client, playlistId, { items: data.items });
|
|
11493
11656
|
}
|
|
11494
11657
|
};
|
|
11495
11658
|
}
|
|
@@ -11856,53 +12019,191 @@ function PortalContentApiProvider({ children }) {
|
|
|
11856
12019
|
});
|
|
11857
12020
|
}
|
|
11858
12021
|
//#endregion
|
|
11859
|
-
|
|
11860
|
-
|
|
11861
|
-
|
|
11862
|
-
|
|
11863
|
-
|
|
11864
|
-
|
|
11865
|
-
|
|
11866
|
-
|
|
11867
|
-
|
|
11868
|
-
|
|
11869
|
-
|
|
11870
|
-
|
|
11871
|
-
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
|
|
11875
|
-
|
|
11876
|
-
|
|
11877
|
-
|
|
11878
|
-
|
|
11879
|
-
|
|
11880
|
-
|
|
11881
|
-
|
|
11882
|
-
|
|
11883
|
-
|
|
11884
|
-
|
|
11885
|
-
|
|
11886
|
-
|
|
11887
|
-
|
|
11888
|
-
})
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
11892
|
-
|
|
11893
|
-
}
|
|
11894
|
-
}
|
|
11895
|
-
|
|
12022
|
+
//#region src/screens/ShareablesScreen.tsx
|
|
12023
|
+
/**
|
|
12024
|
+
* Parse the current shareables sub-route from the full slug.
|
|
12025
|
+
*
|
|
12026
|
+
* System nav slugs are "share/products", "share/media", "share/playlists".
|
|
12027
|
+
* Detail pages append an ID: "share/products/123", "share/media/456".
|
|
12028
|
+
*
|
|
12029
|
+
* "share/products" → screen="products", detailId=null
|
|
12030
|
+
* "share/products/123" → screen="products", detailId="123"
|
|
12031
|
+
* "share/media/456" → screen="media", detailId="456"
|
|
12032
|
+
* "share/playlists" → screen="playlists", detailId=null
|
|
12033
|
+
* "share/playlists/789" → screen="playlists", detailId="789"
|
|
12034
|
+
* "share/files" → screen="files", detailId=null
|
|
12035
|
+
* "share" → screen=null (default to products)
|
|
12036
|
+
*/
|
|
12037
|
+
function parseShareablesRoute(currentSlug) {
|
|
12038
|
+
const slugWithoutPrefix = currentSlug.replace(/^share\/?/, "");
|
|
12039
|
+
if (!slugWithoutPrefix) return {
|
|
12040
|
+
screen: null,
|
|
12041
|
+
detailId: null,
|
|
12042
|
+
action: null
|
|
12043
|
+
};
|
|
12044
|
+
const parts = slugWithoutPrefix.split("/");
|
|
12045
|
+
return {
|
|
12046
|
+
screen: parts[0] || null,
|
|
12047
|
+
detailId: parts[1] || null,
|
|
12048
|
+
action: parts[2] || null
|
|
12049
|
+
};
|
|
12050
|
+
}
|
|
12051
|
+
function ShareablesScreen({ background, textColor, accentColor, padding, borderRadius, ...divProps }) {
|
|
12052
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
12053
|
+
...divProps,
|
|
12054
|
+
className: `h-full ${divProps.className ?? ""}`,
|
|
12055
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_PortalProductsApiProvider.PortalProductsApiProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PortalContentApiProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareablesScreenContent, {}) }) })
|
|
12056
|
+
});
|
|
12057
|
+
}
|
|
12058
|
+
/** Inner component rendered inside providers so hooks can access context. */
|
|
12059
|
+
function ShareablesScreenContent() {
|
|
12060
|
+
const shareablesCtx = usePortalContentContext();
|
|
12061
|
+
const { productsApi: portalProductsApi } = shareablesCtx;
|
|
12062
|
+
const filePickerApi = useFilePickerApi();
|
|
12063
|
+
const { data: account } = require_use_account.useAccount();
|
|
12064
|
+
const { data: store } = require_use_store.useStore();
|
|
12065
|
+
const { currentSlug, navigate } = require_AppNavigationContext.useAppNavigation();
|
|
12066
|
+
const isCustomer = account?.member_type === "customer";
|
|
12067
|
+
const client = require_PortalTenantClientProvider.usePortalTenantClient();
|
|
12068
|
+
const queryClient = (0, _tanstack_react_query.useQueryClient)();
|
|
12069
|
+
const fetchProducts = (0, react.useCallback)(async (search, cursor, limit, sort) => {
|
|
12070
|
+
if (search) return portalProductsApi.searchProducts(search, {
|
|
12071
|
+
cursor,
|
|
12072
|
+
limit
|
|
12073
|
+
});
|
|
12074
|
+
return portalProductsApi.listProducts({
|
|
12075
|
+
cursor,
|
|
12076
|
+
limit,
|
|
12077
|
+
sort
|
|
12078
|
+
});
|
|
12079
|
+
}, [portalProductsApi]);
|
|
12080
|
+
const fetchProduct = (0, react.useCallback)(async (id) => portalProductsApi.getProduct(id), [portalProductsApi]);
|
|
12081
|
+
const { screen, detailId, action } = parseShareablesRoute(currentSlug);
|
|
12082
|
+
const handleNavigate = (0, react.useCallback)((subScreen, id) => {
|
|
12083
|
+
navigate(id ? `share/${subScreen}/${id}` : `share/${subScreen}`);
|
|
12084
|
+
}, [navigate]);
|
|
12085
|
+
const handleBack = (0, react.useCallback)(() => {
|
|
12086
|
+
if (detailId && screen) navigate(`share/${screen}`);
|
|
12087
|
+
else navigate("share/products");
|
|
12088
|
+
}, [
|
|
12089
|
+
navigate,
|
|
12090
|
+
detailId,
|
|
12091
|
+
screen
|
|
12092
|
+
]);
|
|
12093
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareablesCoreProvider, {
|
|
12094
|
+
config: (0, react.useMemo)(() => ({
|
|
12095
|
+
user: account ? { id: account.id } : null,
|
|
12096
|
+
repContext: true
|
|
12097
|
+
}), [account]),
|
|
12098
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareablesUIProvider, {
|
|
12099
|
+
config: (0, react.useMemo)(() => ({
|
|
12100
|
+
user: account ? {
|
|
12101
|
+
id: account.id,
|
|
12102
|
+
company: { logo_url: store?.logo_url ?? null }
|
|
12103
|
+
} : void 0,
|
|
12104
|
+
affiliateId: null,
|
|
12105
|
+
basePath: "",
|
|
12106
|
+
navigate: (path) => {
|
|
12107
|
+
const cleanPath = path.replace(/^\//, "");
|
|
12108
|
+
navigate(cleanPath.startsWith("share/") ? cleanPath : `share/${cleanPath}`);
|
|
12109
|
+
},
|
|
12110
|
+
showToast: (opts) => {
|
|
12111
|
+
require_src.fluidToast({
|
|
12112
|
+
title: opts.title,
|
|
12113
|
+
type: opts.type
|
|
12114
|
+
});
|
|
12115
|
+
if (opts.error) console.error("[Shareables]", opts.error);
|
|
12116
|
+
},
|
|
12117
|
+
filePickerApi,
|
|
12118
|
+
onToggleFavorite: async (params) => {
|
|
12119
|
+
const result = await toggleFavorite(client, params.favoriteableId, params.favoriteableType);
|
|
12120
|
+
queryClient.invalidateQueries({ queryKey: require_dist$5.PORTAL_MYSITE_KEYS.favorites() });
|
|
12121
|
+
return result;
|
|
12122
|
+
},
|
|
12123
|
+
onMySiteShare: async (params) => {
|
|
12124
|
+
await toggleFavorite(client, params.relateable_id, params.relateable_type);
|
|
12125
|
+
queryClient.invalidateQueries({ queryKey: require_dist$5.PORTAL_MYSITE_KEYS.favorites() });
|
|
12126
|
+
},
|
|
12127
|
+
onDeletePlaylist: isCustomer ? void 0 : async (playlistId) => {
|
|
12128
|
+
await shareablesCtx.playlistsAdapter.deletePlaylist(playlistId);
|
|
12129
|
+
},
|
|
12130
|
+
mediaProductsApi: isCustomer ? void 0 : shareablesCtx.mediaProductsAdapter,
|
|
12131
|
+
searchProducts: isCustomer ? void 0 : async (query, options) => {
|
|
12132
|
+
const limit = options?.limit ?? 25;
|
|
12133
|
+
const cursor = options?.cursor ?? void 0;
|
|
12134
|
+
const result = query.trim().length > 0 ? await portalProductsApi.searchProducts(query, {
|
|
12135
|
+
cursor,
|
|
12136
|
+
limit
|
|
12137
|
+
}) : await portalProductsApi.listProducts({
|
|
12138
|
+
cursor,
|
|
12139
|
+
limit
|
|
12140
|
+
});
|
|
12141
|
+
return {
|
|
12142
|
+
products: (result.products ?? []).map((p) => p.id != null ? {
|
|
12143
|
+
id: p.id,
|
|
12144
|
+
name: p.name ?? p.title ?? "Untitled",
|
|
12145
|
+
image_url: p.image_url ?? null,
|
|
12146
|
+
price: p.price ?? null
|
|
12147
|
+
} : null).filter((p) => p !== null),
|
|
12148
|
+
nextCursor: result.meta?.pagination?.next_cursor ?? null
|
|
12149
|
+
};
|
|
12150
|
+
},
|
|
12151
|
+
readOnly: isCustomer,
|
|
12152
|
+
uploadThumbnail: isCustomer ? void 0 : async (blob, filename) => {
|
|
12153
|
+
const formData = new FormData();
|
|
12154
|
+
formData.append("asset[name]", filename);
|
|
12155
|
+
formData.append("asset[file]", blob, filename);
|
|
12156
|
+
const url = (await client.requestWithFormData("/api/content/dam/assets", formData)).asset?.default_variant_url;
|
|
12157
|
+
if (!url) throw new Error("Thumbnail upload succeeded but no URL returned");
|
|
12158
|
+
return url;
|
|
12159
|
+
}
|
|
12160
|
+
}), [
|
|
12161
|
+
account,
|
|
12162
|
+
store,
|
|
12163
|
+
navigate,
|
|
12164
|
+
filePickerApi,
|
|
12165
|
+
isCustomer,
|
|
12166
|
+
shareablesCtx.playlistsAdapter,
|
|
12167
|
+
shareablesCtx.mediaProductsAdapter,
|
|
12168
|
+
portalProductsApi,
|
|
12169
|
+
client,
|
|
12170
|
+
queryClient
|
|
12171
|
+
]),
|
|
12172
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ShareablesApp, {
|
|
12173
|
+
screen,
|
|
12174
|
+
detailId,
|
|
12175
|
+
action,
|
|
12176
|
+
companyLogoUrl: void 0,
|
|
12177
|
+
countryCode: void 0,
|
|
12178
|
+
fetchProducts,
|
|
12179
|
+
fetchProduct,
|
|
12180
|
+
onNavigate: handleNavigate,
|
|
12181
|
+
onBack: handleBack
|
|
12182
|
+
})
|
|
12183
|
+
})
|
|
12184
|
+
});
|
|
12185
|
+
}
|
|
12186
|
+
const shareablesScreenPropertySchema = {
|
|
12187
|
+
widgetType: "ShareablesScreen",
|
|
12188
|
+
displayName: "Shareables Screen",
|
|
12189
|
+
tabsConfig: [{
|
|
12190
|
+
id: "styling",
|
|
12191
|
+
label: "Styling"
|
|
12192
|
+
}],
|
|
12193
|
+
fields: []
|
|
12194
|
+
};
|
|
12195
|
+
//#endregion
|
|
12196
|
+
Object.defineProperty(exports, "ShareablesScreen", {
|
|
11896
12197
|
enumerable: true,
|
|
11897
12198
|
get: function() {
|
|
11898
|
-
return
|
|
12199
|
+
return ShareablesScreen;
|
|
11899
12200
|
}
|
|
11900
12201
|
});
|
|
11901
|
-
Object.defineProperty(exports, "
|
|
12202
|
+
Object.defineProperty(exports, "shareablesScreenPropertySchema", {
|
|
11902
12203
|
enumerable: true,
|
|
11903
12204
|
get: function() {
|
|
11904
|
-
return
|
|
12205
|
+
return shareablesScreenPropertySchema;
|
|
11905
12206
|
}
|
|
11906
12207
|
});
|
|
11907
12208
|
|
|
11908
|
-
//# sourceMappingURL=
|
|
12209
|
+
//# sourceMappingURL=ShareablesScreen-DwnMBftJ.cjs.map
|