@fluid-app/portal-sdk 0.1.208 → 0.1.209
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/{FluidProvider-0Mba_MWW.mjs → FluidProvider-BhXU4mXn.mjs} +3 -3
- package/dist/{FluidProvider-0Mba_MWW.mjs.map → FluidProvider-BhXU4mXn.mjs.map} +1 -1
- package/dist/{FluidProvider-Df88VSWk.cjs → FluidProvider-CVYSJW9G.cjs} +3 -3
- package/dist/{FluidProvider-Df88VSWk.cjs.map → FluidProvider-CVYSJW9G.cjs.map} +1 -1
- package/dist/{MessagingScreen-BrHK0nrA.cjs → MessagingScreen-CneT3yWA.cjs} +3 -3
- package/dist/{MessagingScreen-BKgNsHdQ.mjs → MessagingScreen-DZPzRM2a.mjs} +2 -2
- package/dist/{MessagingScreen-BKgNsHdQ.mjs.map → MessagingScreen-DZPzRM2a.mjs.map} +1 -1
- package/dist/{MessagingScreen-BE9FZr7f.cjs → MessagingScreen-lOhqghg5.cjs} +2 -2
- package/dist/{MessagingScreen-BE9FZr7f.cjs.map → MessagingScreen-lOhqghg5.cjs.map} +1 -1
- package/dist/{ProfileScreen-WC3LIwDh.mjs → ProfileScreen-BVlyq4I8.mjs} +2 -2
- package/dist/{ProfileScreen-WC3LIwDh.mjs.map → ProfileScreen-BVlyq4I8.mjs.map} +1 -1
- package/dist/{ProfileScreen-DYHRKKVI.cjs → ProfileScreen-CJlMCpIM.cjs} +3 -3
- package/dist/{ProfileScreen-DtNJ1sdF.cjs → ProfileScreen-DToaxnsZ.cjs} +2 -2
- package/dist/{ProfileScreen-DtNJ1sdF.cjs.map → ProfileScreen-DToaxnsZ.cjs.map} +1 -1
- package/dist/RecentActivityWidget-C6qm5x9b.mjs +560 -0
- package/dist/RecentActivityWidget-C6qm5x9b.mjs.map +1 -0
- package/dist/RecentActivityWidget-Cw5Qxx_x.cjs +577 -0
- package/dist/RecentActivityWidget-Cw5Qxx_x.cjs.map +1 -0
- package/dist/{ShopScreen-MZm20clN.cjs → ShopScreen-7s5O5oFR.cjs} +3 -3
- package/dist/{ShopScreen-BfexFHUc.mjs → ShopScreen-DAZC9E9E.mjs} +2 -2
- package/dist/{ShopScreen-BfexFHUc.mjs.map → ShopScreen-DAZC9E9E.mjs.map} +1 -1
- package/dist/{ShopScreen-Bo9YZ_EO.cjs → ShopScreen-dkt4YuUO.cjs} +2 -2
- package/dist/{ShopScreen-Bo9YZ_EO.cjs.map → ShopScreen-dkt4YuUO.cjs.map} +1 -1
- package/dist/index.cjs +11 -11
- package/dist/index.d.cts +8 -0
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +8 -0
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +11 -11
- package/package.json +9 -9
- package/dist/RecentActivityWidget-CWr6bFgP.cjs +0 -394
- package/dist/RecentActivityWidget-CWr6bFgP.cjs.map +0 -1
- package/dist/RecentActivityWidget-D-uJcFkE.mjs +0 -377
- package/dist/RecentActivityWidget-D-uJcFkE.mjs.map +0 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import "./es-DmEK0Umf.mjs";
|
|
2
|
-
import { a as createScreen, c as FluidThemeProvider, h as deleteDatabase, i as widgetPropertySchemas, l as useThemeContext, m as createPersister, n as useFluidContext, o as createWidgetFromShareable, p as useAppDefinitionApi, r as DEFAULT_SDK_WIDGET_REGISTRY, s as createWidgetRegistry, t as FluidProvider } from "./FluidProvider-
|
|
2
|
+
import { a as createScreen, c as FluidThemeProvider, h as deleteDatabase, i as widgetPropertySchemas, l as useThemeContext, m as createPersister, n as useFluidContext, o as createWidgetFromShareable, p as useAppDefinitionApi, r as DEFAULT_SDK_WIDGET_REGISTRY, s as createWidgetRegistry, t as FluidProvider } from "./FluidProvider-BhXU4mXn.mjs";
|
|
3
3
|
import { a as assertNever, i as assertDefined, n as DataAwareWidget, o as isWidgetType, r as WIDGET_TYPE_NAMES, s as isWidgetTypeName, u as useRegistry } from "./ScreenRenderer-Cv2rxvtF.mjs";
|
|
4
4
|
import "./account-api-context-BIZ_aibJ.mjs";
|
|
5
5
|
import "./store-api-context-C1lXT_3d.mjs";
|
|
@@ -20,7 +20,7 @@ import { r as calendarWidgetPropertySchema, t as CalendarWidget } from "./Calend
|
|
|
20
20
|
import { r as cardWidgetPropertySchema, t as CardWidget } from "./CardWidget-gcPNwuZk.mjs";
|
|
21
21
|
import "./purify.es-Bl6SBkmi.mjs";
|
|
22
22
|
import { C as Skeleton$1, En as Button, Pn as cn$1, _t as CollapsibleContent, gt as Collapsible, ht as PopoverTrigger, mt as PopoverContent, pt as Popover, vt as CollapsibleTrigger, x as Toaster } from "./src-BEx23d86.mjs";
|
|
23
|
-
import { a as useMessagingConfig, i as createFluidFileUploader, o as useMessagingAuth, r as messagingScreenPropertySchema, t as MessagingScreen } from "./MessagingScreen-
|
|
23
|
+
import { a as useMessagingConfig, i as createFluidFileUploader, o as useMessagingAuth, r as messagingScreenPropertySchema, t as MessagingScreen } from "./MessagingScreen-DZPzRM2a.mjs";
|
|
24
24
|
import { r as subscriptionsScreenPropertySchema, t as SubscriptionsScreen } from "./SubscriptionsScreen-CuP9OfBI.mjs";
|
|
25
25
|
import "./scroll-arrows-CYshgsiB.mjs";
|
|
26
26
|
import "./MediaRenderer-CEtrOi5O.mjs";
|
|
@@ -35,7 +35,7 @@ import { r as mySiteWidgetPropertySchema, t as MySiteWidget } from "./MySiteWidg
|
|
|
35
35
|
import { r as nestedWidgetPropertySchema, t as NestedWidget } from "./NestedWidget-J9sJbt9s.mjs";
|
|
36
36
|
import { r as pointsWidgetPropertySchema, t as PointsWidget } from "./PointsWidget-CoDqvWC5.mjs";
|
|
37
37
|
import { r as quickShareWidgetPropertySchema, t as QuickShareWidget } from "./QuickShareWidget-Dbjueevf.mjs";
|
|
38
|
-
import { r as recentActivityWidgetPropertySchema, t as RecentActivityWidget } from "./RecentActivityWidget-
|
|
38
|
+
import { r as recentActivityWidgetPropertySchema, t as RecentActivityWidget } from "./RecentActivityWidget-C6qm5x9b.mjs";
|
|
39
39
|
import { r as separatorWidgetPropertySchema, t as SeparatorWidget } from "./SeparatorWidget-Clm35u4g.mjs";
|
|
40
40
|
import { r as spacerWidgetPropertySchema, t as SpacerWidget } from "./SpacerWidget-JyChGNdx.mjs";
|
|
41
41
|
import { r as tableWidgetPropertySchema, t as TableWidget } from "./TableWidget-DVfzScu1.mjs";
|
|
@@ -46,7 +46,7 @@ import { t as useAccount } from "./use-account-B16Tor2Q.mjs";
|
|
|
46
46
|
import { t as useStore } from "./use-store-BnHhQDYo.mjs";
|
|
47
47
|
import { i as CoreScreenPlaceholder, r as customersScreenPropertySchema, t as CustomersScreen } from "./CustomersScreen-CeLL33Gu.mjs";
|
|
48
48
|
import { n as useAppNavigation, t as AppNavigationProvider } from "./AppNavigationContext-BW3lSpfT.mjs";
|
|
49
|
-
import { r as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen-
|
|
49
|
+
import { r as profileScreenPropertySchema, t as ProfileScreen } from "./ProfileScreen-BVlyq4I8.mjs";
|
|
50
50
|
import "./dist-BETEuYfn.mjs";
|
|
51
51
|
import { r as contactsScreenPropertySchema, t as ContactsScreen } from "./ContactsScreen-CCsst8bb.mjs";
|
|
52
52
|
import "./SearchSort-TmuNOCwA.mjs";
|
|
@@ -61,7 +61,7 @@ import { n as productsScreenPropertySchema, t as ProductsScreen } from "./Produc
|
|
|
61
61
|
import "./use-mysite-portal-axe_PFzR.mjs";
|
|
62
62
|
import { r as mySiteScreenPropertySchema, t as MySiteScreen } from "./MySiteScreen-Dz5htti5.mjs";
|
|
63
63
|
import { n as shareablesScreenPropertySchema, t as ShareablesScreen } from "./ShareablesScreen-BZK_lSdi.mjs";
|
|
64
|
-
import { r as shopScreenPropertySchema, t as ShopScreen } from "./ShopScreen-
|
|
64
|
+
import { r as shopScreenPropertySchema, t as ShopScreen } from "./ShopScreen-DAZC9E9E.mjs";
|
|
65
65
|
import "./UpgradeScreen-K1atEcyx.mjs";
|
|
66
66
|
import "./AppDownloadScreen-CLSjQhHn.mjs";
|
|
67
67
|
import * as React$1 from "react";
|
|
@@ -2132,12 +2132,12 @@ function AccountManageLayout({ children }) {
|
|
|
2132
2132
|
}
|
|
2133
2133
|
//#endregion
|
|
2134
2134
|
//#region src/shell/system-screen-map.ts
|
|
2135
|
-
const ProfileScreen$1 = lazy(() => import("./ProfileScreen-
|
|
2135
|
+
const ProfileScreen$1 = lazy(() => import("./ProfileScreen-BVlyq4I8.mjs").then((n) => n.n).then((m) => ({ default: m.ProfileScreen })));
|
|
2136
2136
|
const OrdersScreen$1 = lazy(() => import("./OrdersScreen-D4pe5mLs.mjs").then((n) => n.n).then((m) => ({ default: m.OrdersScreen })));
|
|
2137
2137
|
const SubscriptionsScreen$1 = lazy(() => import("./SubscriptionsScreen-CuP9OfBI.mjs").then((n) => n.n).then((m) => ({ default: m.SubscriptionsScreen })));
|
|
2138
|
-
const MessagingScreen$1 = lazy(() => import("./MessagingScreen-
|
|
2138
|
+
const MessagingScreen$1 = lazy(() => import("./MessagingScreen-DZPzRM2a.mjs").then((n) => n.n).then((m) => ({ default: m.MessagingScreen })));
|
|
2139
2139
|
const ContactsScreen$1 = lazy(() => import("./ContactsScreen-CCsst8bb.mjs").then((n) => n.n).then((m) => ({ default: m.ContactsScreen })));
|
|
2140
|
-
const ShopScreen$1 = lazy(() => import("./ShopScreen-
|
|
2140
|
+
const ShopScreen$1 = lazy(() => import("./ShopScreen-DAZC9E9E.mjs").then((n) => n.n).then((m) => ({ default: m.ShopScreen })));
|
|
2141
2141
|
const CustomersScreen$1 = lazy(() => import("./CustomersScreen-CeLL33Gu.mjs").then((n) => n.n).then((m) => ({ default: m.CustomersScreen })));
|
|
2142
2142
|
const ProductsScreen$1 = lazy(() => import("./ProductsScreen-CRV1_NVf.mjs").then((m) => ({ default: m.ProductsScreen })));
|
|
2143
2143
|
const ShareablesScreen$1 = lazy(() => import("./ShareablesScreen-Ce7kJAPw.mjs").then((m) => ({ default: m.ShareablesScreen })));
|
|
@@ -3627,8 +3627,8 @@ z.object({
|
|
|
3627
3627
|
//#endregion
|
|
3628
3628
|
//#region src/screens/index.ts
|
|
3629
3629
|
const screenPropertySchemas = {
|
|
3630
|
-
ProfileScreen: () => import("./ProfileScreen-
|
|
3631
|
-
MessagingScreen: () => import("./MessagingScreen-
|
|
3630
|
+
ProfileScreen: () => import("./ProfileScreen-BVlyq4I8.mjs").then((n) => n.n).then((m) => m.profileScreenPropertySchema),
|
|
3631
|
+
MessagingScreen: () => import("./MessagingScreen-DZPzRM2a.mjs").then((n) => n.n).then((m) => m.messagingScreenPropertySchema),
|
|
3632
3632
|
ContactsScreen: () => import("./ContactsScreen-CCsst8bb.mjs").then((n) => n.n).then((m) => m.contactsScreenPropertySchema),
|
|
3633
3633
|
OrdersScreen: () => import("./OrdersScreen-D4pe5mLs.mjs").then((n) => n.n).then((m) => m.ordersScreenPropertySchema),
|
|
3634
3634
|
SubscriptionsScreen: () => import("./SubscriptionsScreen-CuP9OfBI.mjs").then((n) => n.n).then((m) => m.subscriptionsScreenPropertySchema),
|
|
@@ -3636,7 +3636,7 @@ const screenPropertySchemas = {
|
|
|
3636
3636
|
ProductsScreen: () => import("./ProductsScreen-CRV1_NVf.mjs").then((m) => m.productsScreenPropertySchema),
|
|
3637
3637
|
MySiteScreen: () => import("./MySiteScreen-Dz5htti5.mjs").then((n) => n.n).then((m) => m.mySiteScreenPropertySchema),
|
|
3638
3638
|
ShareablesScreen: () => import("./ShareablesScreen-Ce7kJAPw.mjs").then((m) => m.shareablesScreenPropertySchema),
|
|
3639
|
-
ShopScreen: () => import("./ShopScreen-
|
|
3639
|
+
ShopScreen: () => import("./ShopScreen-DAZC9E9E.mjs").then((n) => n.n).then((m) => m.shopScreenPropertySchema),
|
|
3640
3640
|
UpgradeScreen: () => import("./UpgradeScreen-K1atEcyx.mjs").then((n) => n.t).then((m) => m.upgradeScreenPropertySchema),
|
|
3641
3641
|
AppDownloadScreen: () => import("./AppDownloadScreen-CLSjQhHn.mjs").then((n) => n.t).then((m) => m.appDownloadScreenPropertySchema)
|
|
3642
3642
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluid-app/portal-sdk",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.209",
|
|
4
4
|
"description": "SDK for building custom Fluid portals",
|
|
5
5
|
"files": [
|
|
6
6
|
"dist",
|
|
@@ -74,18 +74,18 @@
|
|
|
74
74
|
"@fluid-app/api-client-core": "0.1.0",
|
|
75
75
|
"@fluid-app/auth": "0.1.0",
|
|
76
76
|
"@fluid-app/cart-ui": "0.1.17",
|
|
77
|
-
"@fluid-app/company-switcher-core": "0.1.0",
|
|
78
77
|
"@fluid-app/company-switcher-ui": "0.1.0",
|
|
79
|
-
"@fluid-app/
|
|
80
|
-
"@fluid-app/contacts-core": "0.1.0",
|
|
78
|
+
"@fluid-app/company-switcher-core": "0.1.0",
|
|
81
79
|
"@fluid-app/file-picker-api-client": "0.1.0",
|
|
82
80
|
"@fluid-app/file-picker-core": "0.1.0",
|
|
83
|
-
"@fluid-app/
|
|
81
|
+
"@fluid-app/contacts-ui": "0.1.0",
|
|
84
82
|
"@fluid-app/fluid-pay-core": "0.1.0",
|
|
83
|
+
"@fluid-app/fluidos-api-client": "0.1.0",
|
|
85
84
|
"@fluid-app/messaging-api-client": "0.1.0",
|
|
85
|
+
"@fluid-app/contacts-core": "0.1.0",
|
|
86
|
+
"@fluid-app/mysite-core": "0.1.0",
|
|
86
87
|
"@fluid-app/messaging-core": "0.1.0",
|
|
87
88
|
"@fluid-app/messaging-ui": "0.1.0",
|
|
88
|
-
"@fluid-app/mysite-core": "0.1.0",
|
|
89
89
|
"@fluid-app/mysite-ui": "0.1.0",
|
|
90
90
|
"@fluid-app/orders-core": "0.1.0",
|
|
91
91
|
"@fluid-app/orders-ui": "0.1.0",
|
|
@@ -95,23 +95,23 @@
|
|
|
95
95
|
"@fluid-app/portal-preview": "0.1.0",
|
|
96
96
|
"@fluid-app/portal-pro-upgrade-ui": "0.1.0",
|
|
97
97
|
"@fluid-app/portal-react": "0.1.0",
|
|
98
|
-
"@fluid-app/portal-tenant-api-client": "0.1.0",
|
|
99
98
|
"@fluid-app/portal-tenant-contacts-api-client": "0.1.0",
|
|
100
99
|
"@fluid-app/portal-tenant-content-api-client": "0.1.0",
|
|
100
|
+
"@fluid-app/portal-tenant-api-client": "0.1.0",
|
|
101
101
|
"@fluid-app/portal-tenant-mysite-api-client": "0.1.0",
|
|
102
102
|
"@fluid-app/portal-tenant-pay-api-client": "0.1.0",
|
|
103
103
|
"@fluid-app/portal-tenant-store-api-client": "0.1.0",
|
|
104
|
+
"@fluid-app/products-core": "0.1.0",
|
|
104
105
|
"@fluid-app/portal-widgets": "0.1.22",
|
|
105
106
|
"@fluid-app/products-api-client": "0.1.0",
|
|
106
|
-
"@fluid-app/products-core": "0.1.0",
|
|
107
107
|
"@fluid-app/profile-core": "0.1.0",
|
|
108
108
|
"@fluid-app/profile-ui": "0.1.0",
|
|
109
109
|
"@fluid-app/query-persister": "0.1.0",
|
|
110
110
|
"@fluid-app/shareables-core": "0.1.0",
|
|
111
111
|
"@fluid-app/shareables-ui": "0.1.0",
|
|
112
112
|
"@fluid-app/shop-ui": "0.1.0",
|
|
113
|
-
"@fluid-app/store-api-client": "0.1.0",
|
|
114
113
|
"@fluid-app/store-core": "0.1.0",
|
|
114
|
+
"@fluid-app/store-api-client": "0.1.0",
|
|
115
115
|
"@fluid-app/subscriptions-core": "0.1.0",
|
|
116
116
|
"@fluid-app/subscriptions-ui": "0.1.0",
|
|
117
117
|
"@fluid-app/typescript-config": "0.0.0",
|
|
@@ -1,394 +0,0 @@
|
|
|
1
|
-
const require_chunk = require("./chunk-9hOWP6kD.cjs");
|
|
2
|
-
const require_registry_context = require("./registry-context-RWj2xJlC.cjs");
|
|
3
|
-
const require_error_state = require("./error-state-C-AalLnz.cjs");
|
|
4
|
-
const require_registries = require("./registries-CpUM406S.cjs");
|
|
5
|
-
const require_purify_es = require("./purify.es-BQcWWtgQ.cjs");
|
|
6
|
-
let react = require("react");
|
|
7
|
-
let _tanstack_react_query = require("@tanstack/react-query");
|
|
8
|
-
let react_jsx_runtime = require("react/jsx-runtime");
|
|
9
|
-
let lucide_react = require("lucide-react");
|
|
10
|
-
//#region ../widgets/src/hooks/use-activities.preview.ts
|
|
11
|
-
const now = /* @__PURE__ */ new Date();
|
|
12
|
-
function minutesAgo(minutes) {
|
|
13
|
-
return (/* @__PURE__ */ new Date(now.getTime() - minutes * 6e4)).toISOString();
|
|
14
|
-
}
|
|
15
|
-
const PREVIEW_DATA = [
|
|
16
|
-
{
|
|
17
|
-
id: 1,
|
|
18
|
-
userName: "Sarah Johnson",
|
|
19
|
-
avatarUrl: null,
|
|
20
|
-
activityType: "Order Placed",
|
|
21
|
-
targetName: "Wellness Starter Kit",
|
|
22
|
-
timestamp: minutesAgo(12),
|
|
23
|
-
slug: "order_placed"
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
id: 2,
|
|
27
|
-
userName: "Mike Chen",
|
|
28
|
-
avatarUrl: null,
|
|
29
|
-
activityType: "New Lead",
|
|
30
|
-
targetName: "Signed up from Instagram link",
|
|
31
|
-
timestamp: minutesAgo(45),
|
|
32
|
-
slug: "new_lead"
|
|
33
|
-
},
|
|
34
|
-
{
|
|
35
|
-
id: 3,
|
|
36
|
-
userName: "Visitor from Austin, TX",
|
|
37
|
-
avatarUrl: null,
|
|
38
|
-
activityType: "Page Views",
|
|
39
|
-
targetName: "Viewed product catalog (3 pages)",
|
|
40
|
-
timestamp: minutesAgo(90),
|
|
41
|
-
slug: "page_views"
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
id: 4,
|
|
45
|
-
userName: "Lisa Park",
|
|
46
|
-
avatarUrl: null,
|
|
47
|
-
activityType: "Video Complete",
|
|
48
|
-
targetName: "Watched: Getting Started Guide",
|
|
49
|
-
timestamp: minutesAgo(180),
|
|
50
|
-
slug: "video_complete"
|
|
51
|
-
}
|
|
52
|
-
];
|
|
53
|
-
//#endregion
|
|
54
|
-
//#region ../widgets/src/hooks/use-activities.ts
|
|
55
|
-
function useActivities() {
|
|
56
|
-
const widgetsApi = require_error_state.useWidgetsApi();
|
|
57
|
-
const { isPreview } = require_error_state.useWidgetPreviewContext();
|
|
58
|
-
const { baseUrl } = require_registry_context.useDataSourceRegistryConfig();
|
|
59
|
-
return (0, _tanstack_react_query.useQuery)({
|
|
60
|
-
queryKey: [
|
|
61
|
-
"portal-widget-use",
|
|
62
|
-
"activities",
|
|
63
|
-
isPreview ? "preview" : baseUrl
|
|
64
|
-
],
|
|
65
|
-
queryFn: ({ signal }) => widgetsApi.fetchActivities(signal),
|
|
66
|
-
enabled: !isPreview,
|
|
67
|
-
...isPreview && { placeholderData: PREVIEW_DATA }
|
|
68
|
-
});
|
|
69
|
-
}
|
|
70
|
-
//#endregion
|
|
71
|
-
//#region ../widgets/src/widgets/RecentActivityWidget.tsx
|
|
72
|
-
var RecentActivityWidget_exports = /* @__PURE__ */ require_chunk.__exportAll({
|
|
73
|
-
RecentActivityWidget: () => RecentActivityWidget,
|
|
74
|
-
recentActivityWidgetPropertySchema: () => recentActivityWidgetPropertySchema
|
|
75
|
-
});
|
|
76
|
-
const formatTimestamp = (timestamp) => {
|
|
77
|
-
return new Date(timestamp).toLocaleTimeString("en-US", {
|
|
78
|
-
hour: "numeric",
|
|
79
|
-
minute: "2-digit",
|
|
80
|
-
hour12: true
|
|
81
|
-
});
|
|
82
|
-
};
|
|
83
|
-
const formatDateHeader = (timestamp) => {
|
|
84
|
-
return new Date(timestamp).toLocaleDateString("en-US", {
|
|
85
|
-
month: "long",
|
|
86
|
-
day: "numeric"
|
|
87
|
-
});
|
|
88
|
-
};
|
|
89
|
-
const getDateKey = (timestamp) => {
|
|
90
|
-
return new Date(timestamp).toISOString().split("T")[0] ?? timestamp;
|
|
91
|
-
};
|
|
92
|
-
const groupActivitiesByDate = (activities) => {
|
|
93
|
-
const grouped = /* @__PURE__ */ new Map();
|
|
94
|
-
for (const activity of activities) {
|
|
95
|
-
const dateKey = getDateKey(activity.timestamp);
|
|
96
|
-
const existing = grouped.get(dateKey);
|
|
97
|
-
if (existing) existing.push(activity);
|
|
98
|
-
else grouped.set(dateKey, [activity]);
|
|
99
|
-
}
|
|
100
|
-
return grouped;
|
|
101
|
-
};
|
|
102
|
-
const ACTIVITY_ICON_MAP = {
|
|
103
|
-
order_placed: lucide_react.ShoppingCart,
|
|
104
|
-
abandoned_cart: lucide_react.ShoppingCart,
|
|
105
|
-
cart_items_added: lucide_react.ShoppingCart,
|
|
106
|
-
new_cart_items_added: lucide_react.ShoppingCart,
|
|
107
|
-
direct_message: lucide_react.MessageSquare,
|
|
108
|
-
comment_reply: lucide_react.MessageSquare,
|
|
109
|
-
message_received: lucide_react.MessageSquare,
|
|
110
|
-
message_sent: lucide_react.MessageSquare,
|
|
111
|
-
video: lucide_react.Play,
|
|
112
|
-
video_complete: lucide_react.Play,
|
|
113
|
-
video_contact: lucide_react.Play,
|
|
114
|
-
video_complete_contact: lucide_react.Play,
|
|
115
|
-
new_lead: lucide_react.UserPlus,
|
|
116
|
-
page_views_contact: lucide_react.UserPlus,
|
|
117
|
-
smart_link_clicked: lucide_react.UserPlus,
|
|
118
|
-
page_views: lucide_react.Eye,
|
|
119
|
-
upcoming_event: lucide_react.Calendar,
|
|
120
|
-
review_left: lucide_react.Star,
|
|
121
|
-
tasks: lucide_react.SquareCheck,
|
|
122
|
-
announcements: lucide_react.Bell,
|
|
123
|
-
fantasy_point: lucide_react.Trophy
|
|
124
|
-
};
|
|
125
|
-
const getActivityIcon = (slug) => ACTIVITY_ICON_MAP[slug] ?? lucide_react.User;
|
|
126
|
-
function ActivityFeedItem({ activity, accentColor, textColor }) {
|
|
127
|
-
const Icon = getActivityIcon(activity.slug);
|
|
128
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
129
|
-
className: "flex w-full items-start gap-1.5",
|
|
130
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
131
|
-
className: "shrink-0",
|
|
132
|
-
children: activity.avatarUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
133
|
-
className: "relative size-8 overflow-hidden rounded-full",
|
|
134
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
135
|
-
src: activity.avatarUrl,
|
|
136
|
-
alt: activity.userName,
|
|
137
|
-
className: "size-full object-cover"
|
|
138
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "border-foreground/[0.08] absolute inset-0 rounded-full border" })]
|
|
139
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
140
|
-
className: `bg-muted flex size-8 items-center justify-center rounded-full`,
|
|
141
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Icon, { className: `size-3.5 text-${textColor} opacity-60` })
|
|
142
|
-
})
|
|
143
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
144
|
-
className: "min-w-0 flex-1",
|
|
145
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
146
|
-
className: "flex w-full items-center gap-1.5",
|
|
147
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
148
|
-
className: `flex-1 text-base font-semibold text-${textColor} truncate`,
|
|
149
|
-
children: activity.activityType
|
|
150
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
151
|
-
className: `text-xs text-${textColor} shrink-0 opacity-50`,
|
|
152
|
-
children: formatTimestamp(activity.timestamp)
|
|
153
|
-
})]
|
|
154
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
155
|
-
className: `text-sm text-${textColor} opacity-80`,
|
|
156
|
-
children: [
|
|
157
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
158
|
-
className: `font-medium text-${accentColor}`,
|
|
159
|
-
children: activity.userName
|
|
160
|
-
}),
|
|
161
|
-
" ",
|
|
162
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { dangerouslySetInnerHTML: { __html: require_purify_es.purify.sanitize(activity.targetName, {
|
|
163
|
-
ALLOWED_TAGS: [
|
|
164
|
-
"br",
|
|
165
|
-
"strong",
|
|
166
|
-
"em",
|
|
167
|
-
"b",
|
|
168
|
-
"i"
|
|
169
|
-
],
|
|
170
|
-
ALLOWED_ATTR: []
|
|
171
|
-
}) } })
|
|
172
|
-
]
|
|
173
|
-
})]
|
|
174
|
-
})]
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
function RecentActivityWidget({ titleEnabled = true, titleText = "Recent Activity", titleFontSize = "lg", titleColor = "foreground", background = {
|
|
178
|
-
type: "solid",
|
|
179
|
-
color: "background"
|
|
180
|
-
}, textColor = "foreground", accentColor = "primary", padding = 4, borderRadius = "md", borderWidth = "thin", borderColor = "muted", maxItemsToShow = 5, className, ...props }) {
|
|
181
|
-
const backgroundColor = background.color || "background";
|
|
182
|
-
const backgroundImage = (background.resource?.image_url || background.resource?.imageUrl) && background.type === "image" ? `url(${background.resource.image_url || background.resource.imageUrl})` : "none";
|
|
183
|
-
const { data: activities = [], isLoading, isError } = useActivities();
|
|
184
|
-
const groupedActivities = (0, react.useMemo)(() => groupActivitiesByDate(activities), [activities]);
|
|
185
|
-
const totalCount = Math.min(activities.length, maxItemsToShow);
|
|
186
|
-
const activitiesToShow = (0, react.useMemo)(() => {
|
|
187
|
-
const result = [];
|
|
188
|
-
let count = 0;
|
|
189
|
-
for (const [dateKey, items] of groupedActivities) {
|
|
190
|
-
if (count >= maxItemsToShow) break;
|
|
191
|
-
const remainingSlots = maxItemsToShow - count;
|
|
192
|
-
const itemsToAdd = items.slice(0, remainingSlots);
|
|
193
|
-
if (itemsToAdd.length > 0) {
|
|
194
|
-
result.push({
|
|
195
|
-
date: formatDateHeader(items[0]?.timestamp ?? dateKey),
|
|
196
|
-
items: itemsToAdd
|
|
197
|
-
});
|
|
198
|
-
count += itemsToAdd.length;
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return result;
|
|
202
|
-
}, [groupedActivities, maxItemsToShow]);
|
|
203
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
204
|
-
className: `@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${require_registries.borderWidthClasses[borderWidth]} ${borderWidth !== "none" ? require_registries.borderColorClasses[borderColor] : ""} ${className}`,
|
|
205
|
-
style: { backgroundImage },
|
|
206
|
-
...props,
|
|
207
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
208
|
-
className: `p-${padding} flex flex-col gap-2`,
|
|
209
|
-
children: [titleEnabled && titleText && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
210
|
-
className: "flex w-full items-start gap-2",
|
|
211
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("h2", {
|
|
212
|
-
className: `flex-1 text-${titleFontSize} font-header font-bold text-${titleColor}`,
|
|
213
|
-
children: titleText
|
|
214
|
-
}), !isLoading && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
215
|
-
className: `text-4xl font-bold text-${textColor} leading-none`,
|
|
216
|
-
children: totalCount.toString().padStart(2, "0")
|
|
217
|
-
})]
|
|
218
|
-
}), isLoading ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
219
|
-
className: "flex min-h-[200px] items-center justify-center",
|
|
220
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent" })
|
|
221
|
-
}) : isError ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_error_state.ErrorState, {}) : activities.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
222
|
-
className: "flex min-h-[200px] flex-col items-center justify-center gap-2",
|
|
223
|
-
children: [
|
|
224
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.User, { className: `size-12 text-${textColor} opacity-30` }),
|
|
225
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
226
|
-
className: `text-base font-semibold text-${textColor} opacity-50`,
|
|
227
|
-
children: "No Activity To Report"
|
|
228
|
-
}),
|
|
229
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
230
|
-
className: `text-sm text-${textColor} opacity-40`,
|
|
231
|
-
children: "You'll Do Great!"
|
|
232
|
-
})
|
|
233
|
-
]
|
|
234
|
-
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
235
|
-
className: "flex flex-col gap-4",
|
|
236
|
-
children: activitiesToShow.map((group, groupIndex) => /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
237
|
-
className: "flex flex-col gap-4",
|
|
238
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("p", {
|
|
239
|
-
className: `text-base font-semibold text-${textColor}`,
|
|
240
|
-
children: group.date
|
|
241
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
242
|
-
className: "flex flex-col gap-4",
|
|
243
|
-
children: group.items.map((activity) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ActivityFeedItem, {
|
|
244
|
-
activity,
|
|
245
|
-
accentColor,
|
|
246
|
-
textColor
|
|
247
|
-
}, activity.id))
|
|
248
|
-
})]
|
|
249
|
-
}, groupIndex))
|
|
250
|
-
})]
|
|
251
|
-
})
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
const recentActivityWidgetPropertySchema = {
|
|
255
|
-
widgetType: "RecentActivityWidget",
|
|
256
|
-
displayName: "Recent Activity Widget",
|
|
257
|
-
tabsConfig: [{
|
|
258
|
-
id: "styling",
|
|
259
|
-
label: "Styling"
|
|
260
|
-
}],
|
|
261
|
-
fields: [
|
|
262
|
-
{
|
|
263
|
-
key: "titleEnabled",
|
|
264
|
-
label: "Widget Title",
|
|
265
|
-
type: "boolean",
|
|
266
|
-
description: "Enable the title displayed above the activity feed",
|
|
267
|
-
defaultValue: true,
|
|
268
|
-
tab: "styling",
|
|
269
|
-
group: "Title"
|
|
270
|
-
},
|
|
271
|
-
{
|
|
272
|
-
key: "titleText",
|
|
273
|
-
label: "Title",
|
|
274
|
-
type: "text",
|
|
275
|
-
description: "Title text displayed above the activity feed",
|
|
276
|
-
defaultValue: "Recent Activity",
|
|
277
|
-
tab: "styling",
|
|
278
|
-
group: "Title",
|
|
279
|
-
requiresKeyToBeTrue: "titleEnabled"
|
|
280
|
-
},
|
|
281
|
-
require_registries.getFontSizeField({
|
|
282
|
-
key: "titleFontSize",
|
|
283
|
-
label: "Title Font Size",
|
|
284
|
-
description: "Font size for the widget title",
|
|
285
|
-
defaultValue: "xl",
|
|
286
|
-
tab: "styling",
|
|
287
|
-
group: "Title",
|
|
288
|
-
requiresKeyToBeTrue: "titleEnabled"
|
|
289
|
-
}),
|
|
290
|
-
require_registries.getColorField({
|
|
291
|
-
key: "titleColor",
|
|
292
|
-
label: "Title Color",
|
|
293
|
-
description: "Color for the widget title",
|
|
294
|
-
defaultValue: "foreground",
|
|
295
|
-
tab: "styling",
|
|
296
|
-
group: "Title",
|
|
297
|
-
requiresKeyToBeTrue: "titleEnabled"
|
|
298
|
-
}),
|
|
299
|
-
{
|
|
300
|
-
type: "background",
|
|
301
|
-
key: "background",
|
|
302
|
-
label: "Background",
|
|
303
|
-
description: "Background for the widget container",
|
|
304
|
-
defaultValue: "background",
|
|
305
|
-
tab: "styling",
|
|
306
|
-
group: "Design"
|
|
307
|
-
},
|
|
308
|
-
require_registries.getColorField({
|
|
309
|
-
key: "textColor",
|
|
310
|
-
label: "Text Color",
|
|
311
|
-
description: "Default text color for activity content",
|
|
312
|
-
defaultValue: "foreground",
|
|
313
|
-
tab: "styling",
|
|
314
|
-
group: "Design"
|
|
315
|
-
}),
|
|
316
|
-
require_registries.getColorField({
|
|
317
|
-
key: "accentColor",
|
|
318
|
-
label: "Accent Color",
|
|
319
|
-
description: "Color used for links and highlights",
|
|
320
|
-
defaultValue: "primary",
|
|
321
|
-
tab: "styling",
|
|
322
|
-
group: "Design"
|
|
323
|
-
}),
|
|
324
|
-
{
|
|
325
|
-
key: "separator",
|
|
326
|
-
type: "separator",
|
|
327
|
-
label: "Separator",
|
|
328
|
-
tab: "styling",
|
|
329
|
-
group: "Design"
|
|
330
|
-
},
|
|
331
|
-
require_registries.getPaddingField({
|
|
332
|
-
key: "padding",
|
|
333
|
-
label: "Padding",
|
|
334
|
-
description: "Padding around the widget container",
|
|
335
|
-
defaultValue: 4,
|
|
336
|
-
tab: "styling",
|
|
337
|
-
group: "Design"
|
|
338
|
-
}),
|
|
339
|
-
require_registries.getBorderRadiusField({
|
|
340
|
-
key: "borderRadius",
|
|
341
|
-
label: "Border Radius",
|
|
342
|
-
description: "Border radius for the widget container",
|
|
343
|
-
defaultValue: "md",
|
|
344
|
-
tab: "styling",
|
|
345
|
-
group: "Design"
|
|
346
|
-
}),
|
|
347
|
-
require_registries.getBorderWidthField({
|
|
348
|
-
key: "borderWidth",
|
|
349
|
-
label: "Border Width",
|
|
350
|
-
description: "Border width for the widget container",
|
|
351
|
-
defaultValue: "thin",
|
|
352
|
-
tab: "styling",
|
|
353
|
-
group: "Design"
|
|
354
|
-
}),
|
|
355
|
-
require_registries.getBorderColorField({
|
|
356
|
-
key: "borderColor",
|
|
357
|
-
label: "Border Color",
|
|
358
|
-
description: "Border color for the widget container",
|
|
359
|
-
defaultValue: "muted",
|
|
360
|
-
tab: "styling",
|
|
361
|
-
group: "Design"
|
|
362
|
-
}),
|
|
363
|
-
{
|
|
364
|
-
key: "maxItemsToShow",
|
|
365
|
-
label: "Max Items",
|
|
366
|
-
type: "number",
|
|
367
|
-
description: "Maximum number of activity items to display",
|
|
368
|
-
defaultValue: 5,
|
|
369
|
-
tab: "styling",
|
|
370
|
-
group: "Display"
|
|
371
|
-
}
|
|
372
|
-
]
|
|
373
|
-
};
|
|
374
|
-
//#endregion
|
|
375
|
-
Object.defineProperty(exports, "RecentActivityWidget", {
|
|
376
|
-
enumerable: true,
|
|
377
|
-
get: function() {
|
|
378
|
-
return RecentActivityWidget;
|
|
379
|
-
}
|
|
380
|
-
});
|
|
381
|
-
Object.defineProperty(exports, "RecentActivityWidget_exports", {
|
|
382
|
-
enumerable: true,
|
|
383
|
-
get: function() {
|
|
384
|
-
return RecentActivityWidget_exports;
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
Object.defineProperty(exports, "recentActivityWidgetPropertySchema", {
|
|
388
|
-
enumerable: true,
|
|
389
|
-
get: function() {
|
|
390
|
-
return recentActivityWidgetPropertySchema;
|
|
391
|
-
}
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
//# sourceMappingURL=RecentActivityWidget-CWr6bFgP.cjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"RecentActivityWidget-CWr6bFgP.cjs","names":["useWidgetsApi","useWidgetPreviewContext","useDataSourceRegistryConfig","ShoppingCart","MessageSquare","Play","UserPlus","Eye","Calendar","Star","SquareCheck","Bell","Trophy","User","DOMPurify","borderWidthClasses","borderColorClasses","ErrorState","getFontSizeField","getColorField","getPaddingField","getBorderRadiusField","getBorderWidthField","getBorderColorField"],"sources":["../../widgets/src/hooks/use-activities.preview.ts","../../widgets/src/hooks/use-activities.ts","../../widgets/src/widgets/RecentActivityWidget.tsx"],"sourcesContent":["import type { Activity } from \"@fluid-app/portal-core/widgets-api-types\";\n\nconst now = new Date();\n\nfunction minutesAgo(minutes: number): string {\n return new Date(now.getTime() - minutes * 60_000).toISOString();\n}\n\nexport const PREVIEW_DATA: Activity[] = [\n {\n id: 1,\n userName: \"Sarah Johnson\",\n avatarUrl: null,\n activityType: \"Order Placed\",\n targetName: \"Wellness Starter Kit\",\n timestamp: minutesAgo(12),\n slug: \"order_placed\",\n },\n {\n id: 2,\n userName: \"Mike Chen\",\n avatarUrl: null,\n activityType: \"New Lead\",\n targetName: \"Signed up from Instagram link\",\n timestamp: minutesAgo(45),\n slug: \"new_lead\",\n },\n {\n id: 3,\n userName: \"Visitor from Austin, TX\",\n avatarUrl: null,\n activityType: \"Page Views\",\n targetName: \"Viewed product catalog (3 pages)\",\n timestamp: minutesAgo(90),\n slug: \"page_views\",\n },\n {\n id: 4,\n userName: \"Lisa Park\",\n avatarUrl: null,\n activityType: \"Video Complete\",\n targetName: \"Watched: Getting Started Guide\",\n timestamp: minutesAgo(180),\n slug: \"video_complete\",\n },\n];\n","import { useQuery, type UseQueryResult } from \"@tanstack/react-query\";\nimport { useWidgetsApi } from \"@fluid-app/portal-core/widgets-api-context\";\nimport { useWidgetPreviewContext } from \"@fluid-app/portal-react/data-sources/preview-context\";\nimport { useDataSourceRegistryConfig } from \"@fluid-app/portal-react/data-sources/registry-context\";\nimport { PREVIEW_DATA } from \"./use-activities.preview\";\nimport type { Activity } from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport type {\n Activity,\n ActivitySlug,\n} from \"@fluid-app/portal-core/widgets-api-types\";\n\nexport function useActivities(): UseQueryResult<Activity[], Error> {\n const widgetsApi = useWidgetsApi();\n const { isPreview } = useWidgetPreviewContext();\n const { baseUrl } = useDataSourceRegistryConfig();\n\n return useQuery({\n queryKey: [\n \"portal-widget-use\",\n \"activities\",\n isPreview ? \"preview\" : baseUrl,\n ] as const,\n queryFn: ({ signal }) => widgetsApi.fetchActivities(signal),\n enabled: !isPreview,\n ...(isPreview && { placeholderData: PREVIEW_DATA }),\n });\n}\n","import DOMPurify from \"dompurify\";\nimport { useMemo, type ComponentProps } from \"react\";\nimport type React from \"react\";\nimport type {\n BackgroundValue,\n BorderRadiusOptions,\n BorderWidthOptions,\n ColorOptions,\n FontSizeOptions,\n PaddingOptions,\n} from \"@fluid-app/portal-core/types\";\nimport type { WidgetPropertySchema } from \"@fluid-app/portal-core/registries\";\nimport {\n getBorderRadiusField,\n getBorderWidthField,\n getBorderColorField,\n getColorField,\n getFontSizeField,\n getPaddingField,\n borderWidthClasses,\n borderColorClasses,\n} from \"../core/fields\";\nimport {\n useActivities,\n type Activity,\n type ActivitySlug,\n} from \"../hooks/use-activities\";\nimport { ErrorState } from \"../components/error-state\";\nimport {\n Bell,\n Calendar,\n SquareCheck,\n Eye,\n MessageSquare,\n Play,\n ShoppingCart,\n Star,\n Trophy,\n User,\n UserPlus,\n type LucideIcon,\n} from \"lucide-react\";\n\n// Format timestamp to time string\nconst formatTimestamp = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toLocaleTimeString(\"en-US\", {\n hour: \"numeric\",\n minute: \"2-digit\",\n hour12: true,\n });\n};\n\n// Format date for grouping header\nconst formatDateHeader = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toLocaleDateString(\"en-US\", {\n month: \"long\",\n day: \"numeric\",\n });\n};\n\n// Get date string for grouping (without time)\nconst getDateKey = (timestamp: string): string => {\n const date = new Date(timestamp);\n return date.toISOString().split(\"T\")[0] ?? timestamp;\n};\n\n// Group activities by date\nconst groupActivitiesByDate = (\n activities: Activity[],\n): Map<string, Activity[]> => {\n const grouped = new Map<string, Activity[]>();\n\n for (const activity of activities) {\n const dateKey = getDateKey(activity.timestamp);\n const existing = grouped.get(dateKey);\n if (existing) {\n existing.push(activity);\n } else {\n grouped.set(dateKey, [activity]);\n }\n }\n\n return grouped;\n};\n\n// Activity slug to icon mapping\nconst ACTIVITY_ICON_MAP: Record<ActivitySlug, LucideIcon> = {\n // Orders/Cart\n order_placed: ShoppingCart,\n abandoned_cart: ShoppingCart,\n cart_items_added: ShoppingCart,\n new_cart_items_added: ShoppingCart,\n // Messages\n direct_message: MessageSquare,\n comment_reply: MessageSquare,\n message_received: MessageSquare,\n message_sent: MessageSquare,\n // Video\n video: Play,\n video_complete: Play,\n video_contact: Play,\n video_complete_contact: Play,\n // Leads\n new_lead: UserPlus,\n page_views_contact: UserPlus,\n smart_link_clicked: UserPlus,\n // Page Views\n page_views: Eye,\n // Events\n upcoming_event: Calendar,\n // Reviews\n review_left: Star,\n // Tasks\n tasks: SquareCheck,\n // Announcements\n announcements: Bell,\n // Fantasy\n fantasy_point: Trophy,\n};\n\nconst getActivityIcon = (slug: ActivitySlug) => ACTIVITY_ICON_MAP[slug] ?? User;\n\n// Activity feed item component\ntype ActivityFeedItemProps = {\n activity: Activity;\n accentColor: ColorOptions;\n textColor: ColorOptions;\n};\n\nfunction ActivityFeedItem({\n activity,\n accentColor,\n textColor,\n}: ActivityFeedItemProps) {\n const Icon = getActivityIcon(activity.slug);\n\n return (\n <div className=\"flex w-full items-start gap-1.5\">\n {/* Avatar */}\n <div className=\"shrink-0\">\n {activity.avatarUrl ? (\n <div className=\"relative size-8 overflow-hidden rounded-full\">\n <img\n src={activity.avatarUrl}\n alt={activity.userName}\n className=\"size-full object-cover\"\n />\n <div className=\"border-foreground/[0.08] absolute inset-0 rounded-full border\" />\n </div>\n ) : (\n <div\n className={`bg-muted flex size-8 items-center justify-center rounded-full`}\n >\n <Icon className={`size-3.5 text-${textColor} opacity-60`} />\n </div>\n )}\n </div>\n\n {/* Content */}\n <div className=\"min-w-0 flex-1\">\n <div className=\"flex w-full items-center gap-1.5\">\n <p\n className={`flex-1 text-base font-semibold text-${textColor} truncate`}\n >\n {activity.activityType}\n </p>\n <p className={`text-xs text-${textColor} shrink-0 opacity-50`}>\n {formatTimestamp(activity.timestamp)}\n </p>\n </div>\n <p className={`text-sm text-${textColor} opacity-80`}>\n <span className={`font-medium text-${accentColor}`}>\n {activity.userName}\n </span>{\" \"}\n <span\n dangerouslySetInnerHTML={{\n __html: DOMPurify.sanitize(activity.targetName, {\n ALLOWED_TAGS: [\"br\", \"strong\", \"em\", \"b\", \"i\"],\n ALLOWED_ATTR: [],\n }),\n }}\n />\n </p>\n </div>\n </div>\n );\n}\n\ntype RecentActivityWidgetProps = ComponentProps<\"div\"> & {\n // Title\n titleEnabled?: boolean;\n titleText?: string;\n titleFontSize?: FontSizeOptions;\n titleColor?: ColorOptions;\n\n // Styling\n background?: BackgroundValue;\n textColor?: ColorOptions;\n accentColor?: ColorOptions;\n padding?: PaddingOptions;\n borderRadius?: BorderRadiusOptions;\n borderWidth?: BorderWidthOptions;\n borderColor?: ColorOptions;\n\n // Activity settings\n maxItemsToShow?: number;\n};\n\nexport function RecentActivityWidget({\n // Title defaults\n titleEnabled = true,\n titleText = \"Recent Activity\",\n titleFontSize = \"lg\",\n titleColor = \"foreground\",\n\n // Styling defaults\n background = {\n type: \"solid\",\n color: \"background\",\n },\n textColor = \"foreground\",\n accentColor = \"primary\",\n padding = 4,\n borderRadius = \"md\",\n borderWidth = \"thin\",\n borderColor = \"muted\",\n\n // Activity defaults\n maxItemsToShow = 5,\n\n className,\n ...props\n}: RecentActivityWidgetProps): React.JSX.Element {\n const backgroundColor = background.color || \"background\";\n const backgroundImage =\n (background.resource?.image_url || background.resource?.imageUrl) &&\n background.type === \"image\"\n ? `url(${background.resource.image_url || background.resource.imageUrl})`\n : \"none\";\n const { data: activities = [], isLoading, isError } = useActivities();\n\n const groupedActivities = useMemo(\n () => groupActivitiesByDate(activities),\n [activities],\n );\n\n const totalCount = Math.min(activities.length, maxItemsToShow);\n\n // Get activities to display (limited by maxItemsToShow)\n const activitiesToShow = useMemo(() => {\n const result: { date: string; items: Activity[] }[] = [];\n let count = 0;\n\n for (const [dateKey, items] of groupedActivities) {\n if (count >= maxItemsToShow) break;\n\n const remainingSlots = maxItemsToShow - count;\n const itemsToAdd = items.slice(0, remainingSlots);\n\n if (itemsToAdd.length > 0) {\n result.push({\n date: formatDateHeader(items[0]?.timestamp ?? dateKey),\n items: itemsToAdd,\n });\n count += itemsToAdd.length;\n }\n }\n\n return result;\n }, [groupedActivities, maxItemsToShow]);\n\n return (\n <div\n className={`@container overflow-hidden rounded-${borderRadius} bg-${backgroundColor} text-${textColor} ${borderWidthClasses[borderWidth]} ${borderWidth !== \"none\" ? borderColorClasses[borderColor] : \"\"} ${className}`}\n style={{ backgroundImage }}\n {...props}\n >\n <div className={`p-${padding} flex flex-col gap-2`}>\n {/* Header */}\n {titleEnabled && titleText && (\n <div className=\"flex w-full items-start gap-2\">\n <h2\n className={`flex-1 text-${titleFontSize} font-header font-bold text-${titleColor}`}\n >\n {titleText}\n </h2>\n {!isLoading && (\n <span\n className={`text-4xl font-bold text-${textColor} leading-none`}\n >\n {totalCount.toString().padStart(2, \"0\")}\n </span>\n )}\n </div>\n )}\n\n {/* Loading state */}\n {isLoading ? (\n <div className=\"flex min-h-[200px] items-center justify-center\">\n <div className=\"h-8 w-8 animate-spin rounded-full border-2 border-current border-t-transparent\" />\n </div>\n ) : isError ? (\n /* Error state */\n <ErrorState />\n ) : activities.length === 0 ? (\n /* Empty state */\n <div className=\"flex min-h-[200px] flex-col items-center justify-center gap-2\">\n <User className={`size-12 text-${textColor} opacity-30`} />\n <p\n className={`text-base font-semibold text-${textColor} opacity-50`}\n >\n No Activity To Report\n </p>\n <p className={`text-sm text-${textColor} opacity-40`}>\n You'll Do Great!\n </p>\n </div>\n ) : (\n /* Activity list */\n <div className=\"flex flex-col gap-4\">\n {activitiesToShow.map((group, groupIndex) => (\n <div key={groupIndex} className=\"flex flex-col gap-4\">\n {/* Date header */}\n <p className={`text-base font-semibold text-${textColor}`}>\n {group.date}\n </p>\n\n {/* Activity items */}\n <div className=\"flex flex-col gap-4\">\n {group.items.map((activity) => (\n <ActivityFeedItem\n key={activity.id}\n activity={activity}\n accentColor={accentColor}\n textColor={textColor}\n />\n ))}\n </div>\n </div>\n ))}\n </div>\n )}\n </div>\n </div>\n );\n}\n\nexport const recentActivityWidgetPropertySchema: WidgetPropertySchema = {\n widgetType: \"RecentActivityWidget\",\n displayName: \"Recent Activity Widget\",\n tabsConfig: [{ id: \"styling\", label: \"Styling\" }],\n fields: [\n // Styling Tab - Title Group\n {\n key: \"titleEnabled\",\n label: \"Widget Title\",\n type: \"boolean\",\n description: \"Enable the title displayed above the activity feed\",\n defaultValue: true,\n tab: \"styling\",\n group: \"Title\",\n },\n {\n key: \"titleText\",\n label: \"Title\",\n type: \"text\",\n description: \"Title text displayed above the activity feed\",\n defaultValue: \"Recent Activity\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n },\n getFontSizeField({\n key: \"titleFontSize\",\n label: \"Title Font Size\",\n description: \"Font size for the widget title\",\n defaultValue: \"xl\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n getColorField({\n key: \"titleColor\",\n label: \"Title Color\",\n description: \"Color for the widget title\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Title\",\n requiresKeyToBeTrue: \"titleEnabled\",\n }),\n\n // Styling Tab - Design Group\n {\n type: \"background\",\n key: \"background\",\n label: \"Background\",\n description: \"Background for the widget container\",\n defaultValue: \"background\",\n tab: \"styling\",\n group: \"Design\",\n },\n getColorField({\n key: \"textColor\",\n label: \"Text Color\",\n description: \"Default text color for activity content\",\n defaultValue: \"foreground\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getColorField({\n key: \"accentColor\",\n label: \"Accent Color\",\n description: \"Color used for links and highlights\",\n defaultValue: \"primary\",\n tab: \"styling\",\n group: \"Design\",\n }),\n {\n key: \"separator\",\n type: \"separator\",\n label: \"Separator\",\n tab: \"styling\",\n group: \"Design\",\n },\n getPaddingField({\n key: \"padding\",\n label: \"Padding\",\n description: \"Padding around the widget container\",\n defaultValue: 4,\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderRadiusField({\n key: \"borderRadius\",\n label: \"Border Radius\",\n description: \"Border radius for the widget container\",\n defaultValue: \"md\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderWidthField({\n key: \"borderWidth\",\n label: \"Border Width\",\n description: \"Border width for the widget container\",\n defaultValue: \"thin\",\n tab: \"styling\",\n group: \"Design\",\n }),\n getBorderColorField({\n key: \"borderColor\",\n label: \"Border Color\",\n description: \"Border color for the widget container\",\n defaultValue: \"muted\",\n tab: \"styling\",\n group: \"Design\",\n }),\n\n // Styling Tab - Display Group\n {\n key: \"maxItemsToShow\",\n label: \"Max Items\",\n type: \"number\",\n description: \"Maximum number of activity items to display\",\n defaultValue: 5,\n tab: \"styling\",\n group: \"Display\",\n },\n ],\n} as const satisfies WidgetPropertySchema;\n"],"mappings":"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"}
|