analytica-frontend-lib 1.1.56 → 1.1.58

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/index.js CHANGED
@@ -5261,6 +5261,8 @@ var CardAudio = (0, import_react16.forwardRef)(
5261
5261
  const [showSpeedMenu, setShowSpeedMenu] = (0, import_react16.useState)(false);
5262
5262
  const [playbackRate, setPlaybackRate] = (0, import_react16.useState)(1);
5263
5263
  const audioRef = (0, import_react16.useRef)(null);
5264
+ const volumeControlRef = (0, import_react16.useRef)(null);
5265
+ const speedMenuRef = (0, import_react16.useRef)(null);
5264
5266
  const formatTime2 = (time) => {
5265
5267
  const minutes = Math.floor(time / 60);
5266
5268
  const seconds = Math.floor(time % 60);
@@ -5312,9 +5314,11 @@ var CardAudio = (0, import_react16.forwardRef)(
5312
5314
  };
5313
5315
  const toggleVolumeControl = () => {
5314
5316
  setShowVolumeControl(!showVolumeControl);
5317
+ setShowSpeedMenu(false);
5315
5318
  };
5316
5319
  const toggleSpeedMenu = () => {
5317
5320
  setShowSpeedMenu(!showSpeedMenu);
5321
+ setShowVolumeControl(false);
5318
5322
  };
5319
5323
  const handleSpeedChange = (speed) => {
5320
5324
  setPlaybackRate(speed);
@@ -5332,6 +5336,20 @@ var CardAudio = (0, import_react16.forwardRef)(
5332
5336
  }
5333
5337
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_phosphor_react13.SpeakerHigh, { size: 24 });
5334
5338
  };
5339
+ (0, import_react16.useEffect)(() => {
5340
+ const handleClickOutside = (event) => {
5341
+ if (volumeControlRef.current && !volumeControlRef.current.contains(event.target)) {
5342
+ setShowVolumeControl(false);
5343
+ }
5344
+ if (speedMenuRef.current && !speedMenuRef.current.contains(event.target)) {
5345
+ setShowSpeedMenu(false);
5346
+ }
5347
+ };
5348
+ document.addEventListener("mousedown", handleClickOutside);
5349
+ return () => {
5350
+ document.removeEventListener("mousedown", handleClickOutside);
5351
+ };
5352
+ }, []);
5335
5353
  return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(
5336
5354
  CardBase,
5337
5355
  {
@@ -5420,7 +5438,7 @@ var CardAudio = (0, import_react16.forwardRef)(
5420
5438
  }
5421
5439
  ) }),
5422
5440
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)("p", { className: "text-text-800 text-md font-medium min-w-[2.5rem]", children: formatTime2(duration) }),
5423
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-6", children: [
5441
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-6", ref: volumeControlRef, children: [
5424
5442
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5425
5443
  "button",
5426
5444
  {
@@ -5482,7 +5500,7 @@ var CardAudio = (0, import_react16.forwardRef)(
5482
5500
  }
5483
5501
  )
5484
5502
  ] }),
5485
- /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-6", children: [
5503
+ /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)("div", { className: "relative h-6", ref: speedMenuRef, children: [
5486
5504
  /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
5487
5505
  "button",
5488
5506
  {
@@ -7423,6 +7441,8 @@ var SpeedMenu = ({
7423
7441
  isFullscreen
7424
7442
  }) => {
7425
7443
  const buttonRef = (0, import_react25.useRef)(null);
7444
+ const speedMenuContainerRef = (0, import_react25.useRef)(null);
7445
+ const speedMenuRef = (0, import_react25.useRef)(null);
7426
7446
  const getMenuPosition = () => {
7427
7447
  if (!buttonRef.current) return { top: 0, left: 0 };
7428
7448
  const rect = buttonRef.current.getBoundingClientRect();
@@ -7433,9 +7453,26 @@ var SpeedMenu = ({
7433
7453
  };
7434
7454
  };
7435
7455
  const position = getMenuPosition();
7456
+ (0, import_react25.useEffect)(() => {
7457
+ const handleClickOutside = (event) => {
7458
+ const target = event.target;
7459
+ const isOutsideContainer = speedMenuContainerRef.current && !speedMenuContainerRef.current.contains(target);
7460
+ const isOutsideMenu = speedMenuRef.current && !speedMenuRef.current.contains(target);
7461
+ if (isOutsideContainer && isOutsideMenu) {
7462
+ onToggleMenu();
7463
+ }
7464
+ };
7465
+ if (showSpeedMenu) {
7466
+ document.addEventListener("mousedown", handleClickOutside);
7467
+ }
7468
+ return () => {
7469
+ document.removeEventListener("mousedown", handleClickOutside);
7470
+ };
7471
+ }, [showSpeedMenu, onToggleMenu]);
7436
7472
  const menuContent = /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7437
7473
  "div",
7438
7474
  {
7475
+ ref: speedMenuRef,
7439
7476
  role: "menu",
7440
7477
  "aria-label": "Playback speed",
7441
7478
  className: isFullscreen ? "absolute bottom-12 right-0 bg-black/90 rounded-lg p-2 min-w-20 z-[9999]" : "fixed bg-black/90 rounded-lg p-2 min-w-20 z-[9999]",
@@ -7460,7 +7497,7 @@ var SpeedMenu = ({
7460
7497
  }
7461
7498
  );
7462
7499
  const portalContent = typeof window !== "undefined" && typeof document !== "undefined" ? (0, import_react_dom.createPortal)(menuContent, document.body) : null;
7463
- return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "relative", children: [
7500
+ return /* @__PURE__ */ (0, import_jsx_runtime37.jsxs)("div", { className: "relative", ref: speedMenuContainerRef, children: [
7464
7501
  /* @__PURE__ */ (0, import_jsx_runtime37.jsx)(
7465
7502
  IconButton_default,
7466
7503
  {
@@ -10726,7 +10763,8 @@ var mapBackendNotification = (backendNotification) => {
10726
10763
  entityId: backendNotification.entityId,
10727
10764
  sender: backendNotification.sender,
10728
10765
  activity: backendNotification.activity,
10729
- goal: backendNotification.goal
10766
+ goal: backendNotification.goal,
10767
+ actionLink: backendNotification.actionLink ?? null
10730
10768
  };
10731
10769
  };
10732
10770
  var groupNotificationsByTime = (notifications) => {
@@ -10920,6 +10958,9 @@ var createNotificationStore = (apiClient) => {
10920
10958
  );
10921
10959
  };
10922
10960
 
10961
+ // src/assets/img/mock-content.png
10962
+ var mock_content_default = "./mock-content-K2CDVG6P.png";
10963
+
10923
10964
  // src/components/NotificationCard/NotificationCard.tsx
10924
10965
  var import_jsx_runtime42 = require("react/jsx-runtime");
10925
10966
  var NotificationEmpty = ({
@@ -11049,10 +11090,23 @@ var NotificationList = ({
11049
11090
  onMarkAsReadById,
11050
11091
  onDeleteById,
11051
11092
  onNavigateById,
11093
+ onGlobalNotificationClick,
11052
11094
  getActionLabel,
11053
11095
  renderEmpty,
11054
- className
11096
+ className,
11097
+ emptyStateImage
11055
11098
  }) => {
11099
+ const [globalNotificationModal, setGlobalNotificationModal] = (0, import_react32.useState)({ isOpen: false, notification: null });
11100
+ const handleGlobalNotificationClick = (notification) => {
11101
+ if (onGlobalNotificationClick) {
11102
+ onGlobalNotificationClick(notification);
11103
+ } else {
11104
+ setGlobalNotificationModal({
11105
+ isOpen: true,
11106
+ notification
11107
+ });
11108
+ }
11109
+ };
11056
11110
  if (error) {
11057
11111
  return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col items-center gap-4 p-6 w-full", children: [
11058
11112
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("p", { className: "text-sm text-error-600", children: error }),
@@ -11081,28 +11135,59 @@ var NotificationList = ({
11081
11135
  if (!groupedNotifications || groupedNotifications.length === 0) {
11082
11136
  return renderEmpty ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "w-full", children: renderEmpty() }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(NotificationEmpty, {});
11083
11137
  }
11084
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: cn("flex flex-col gap-0 w-full", className), children: groupedNotifications.map((group, idx) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col", children: [
11085
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex items-end px-4 py-6 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-lg font-bold text-text-500 flex-grow", children: group.label }) }),
11086
- group.notifications.map((notification) => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11087
- SingleNotificationCard,
11138
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: cn("flex flex-col gap-0 w-full", className), children: [
11139
+ groupedNotifications.map((group, idx) => /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col", children: [
11140
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex items-end px-4 py-6 pb-4", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h4", { className: "text-lg font-bold text-text-500 flex-grow", children: group.label }) }),
11141
+ group.notifications.map((notification) => {
11142
+ const isGlobalNotification = !notification.entityType && !notification.entityId && !notification.activity && !notification.goal;
11143
+ let navigationHandler;
11144
+ if (isGlobalNotification) {
11145
+ navigationHandler = () => handleGlobalNotificationClick(notification);
11146
+ } else if (notification.entityType && notification.entityId && onNavigateById) {
11147
+ navigationHandler = () => onNavigateById(
11148
+ notification.entityType ?? void 0,
11149
+ notification.entityId ?? void 0
11150
+ );
11151
+ }
11152
+ let actionLabel;
11153
+ if (isGlobalNotification) {
11154
+ actionLabel = getActionLabel?.(void 0);
11155
+ } else {
11156
+ actionLabel = getActionLabel?.(
11157
+ notification.entityType ?? void 0
11158
+ );
11159
+ }
11160
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11161
+ SingleNotificationCard,
11162
+ {
11163
+ title: notification.title,
11164
+ message: notification.message,
11165
+ time: notification.time ?? formatTimeAgo(new Date(notification.createdAt)),
11166
+ isRead: notification.isRead,
11167
+ onMarkAsRead: () => onMarkAsReadById?.(notification.id),
11168
+ onDelete: () => onDeleteById?.(notification.id),
11169
+ onNavigate: navigationHandler,
11170
+ actionLabel
11171
+ },
11172
+ notification.id
11173
+ );
11174
+ })
11175
+ ] }, `${group.label}-${idx}`)),
11176
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11177
+ Modal_default,
11088
11178
  {
11089
- title: notification.title,
11090
- message: notification.message,
11091
- time: notification.time ?? formatTimeAgo(new Date(notification.createdAt)),
11092
- isRead: notification.isRead,
11093
- onMarkAsRead: () => onMarkAsReadById?.(notification.id),
11094
- onDelete: () => onDeleteById?.(notification.id),
11095
- onNavigate: notification.entityType && notification.entityId && onNavigateById ? () => onNavigateById(
11096
- notification.entityType ?? void 0,
11097
- notification.entityId ?? void 0
11098
- ) : void 0,
11099
- actionLabel: getActionLabel?.(
11100
- notification.entityType ?? void 0
11101
- )
11102
- },
11103
- notification.id
11104
- ))
11105
- ] }, `${group.label}-${idx}`)) });
11179
+ isOpen: globalNotificationModal.isOpen,
11180
+ onClose: () => setGlobalNotificationModal({ isOpen: false, notification: null }),
11181
+ title: globalNotificationModal.notification?.title || "",
11182
+ description: globalNotificationModal.notification?.message || "",
11183
+ variant: "activity",
11184
+ image: emptyStateImage || mock_content_default,
11185
+ actionLink: globalNotificationModal.notification?.actionLink || void 0,
11186
+ actionLabel: "Ver mais",
11187
+ size: "lg"
11188
+ }
11189
+ )
11190
+ ] });
11106
11191
  };
11107
11192
  var NotificationCenter = ({
11108
11193
  isActive,
@@ -11125,6 +11210,7 @@ var NotificationCenter = ({
11125
11210
  }) => {
11126
11211
  const { isMobile } = useMobile();
11127
11212
  const [isModalOpen, setIsModalOpen] = (0, import_react32.useState)(false);
11213
+ const [globalNotificationModal, setGlobalNotificationModal] = (0, import_react32.useState)({ isOpen: false, notification: null });
11128
11214
  const handleMobileClick = () => {
11129
11215
  setIsModalOpen(true);
11130
11216
  onFetchNotifications?.();
@@ -11137,10 +11223,6 @@ var NotificationCenter = ({
11137
11223
  onFetchNotifications?.();
11138
11224
  }
11139
11225
  }, [isActive, onFetchNotifications]);
11140
- const handleNavigate = (entityType, entityId, onCleanup) => {
11141
- onCleanup?.();
11142
- onNavigateById?.(entityType, entityId);
11143
- };
11144
11226
  const renderEmptyState = () => /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11145
11227
  NotificationEmpty,
11146
11228
  {
@@ -11191,13 +11273,20 @@ var NotificationCenter = ({
11191
11273
  onRetry,
11192
11274
  onMarkAsReadById,
11193
11275
  onDeleteById,
11194
- onNavigateById: (entityType, entityId) => handleNavigate(
11195
- entityType,
11196
- entityId,
11197
- () => setIsModalOpen(false)
11198
- ),
11276
+ onNavigateById: (entityType, entityId) => {
11277
+ setIsModalOpen(false);
11278
+ onNavigateById?.(entityType, entityId);
11279
+ },
11280
+ onGlobalNotificationClick: (notification) => {
11281
+ setIsModalOpen(false);
11282
+ setGlobalNotificationModal({
11283
+ isOpen: true,
11284
+ notification
11285
+ });
11286
+ },
11199
11287
  getActionLabel,
11200
- renderEmpty: renderEmptyState
11288
+ renderEmpty: renderEmptyState,
11289
+ emptyStateImage
11201
11290
  }
11202
11291
  ) })
11203
11292
  ] })
@@ -11205,56 +11294,85 @@ var NotificationCenter = ({
11205
11294
  )
11206
11295
  ] });
11207
11296
  }
11208
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(DropdownMenu_default, { children: [
11209
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(DropdownMenuTrigger, { className: "text-primary cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11210
- IconButton_default,
11211
- {
11212
- active: isActive,
11213
- onClick: handleDesktopClick,
11214
- icon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11215
- import_phosphor_react22.Bell,
11216
- {
11217
- size: 24,
11218
- className: isActive ? "text-primary-950" : "text-primary"
11219
- }
11220
- ),
11221
- className
11222
- }
11223
- ) }),
11224
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11225
- DropdownMenuContent,
11226
- {
11227
- className: "min-w-[320px] max-w-[400px] max-h-[500px] overflow-hidden",
11228
- side: "bottom",
11229
- align: "end",
11230
- children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col", children: [
11231
- /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "px-4 py-3 border-b border-border-200", children: [
11232
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(NotificationHeader, { unreadCount, variant: "dropdown" }),
11233
- unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11234
- "button",
11235
- {
11236
- type: "button",
11237
- onClick: onMarkAllAsRead,
11238
- className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2",
11239
- children: "Marcar todas como lidas"
11240
- }
11241
- )
11242
- ] }),
11243
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "max-h-[350px] overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11244
- NotificationList,
11297
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(import_jsx_runtime42.Fragment, { children: [
11298
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)(DropdownMenu_default, { children: [
11299
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(DropdownMenuTrigger, { className: "text-primary cursor-pointer", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11300
+ IconButton_default,
11301
+ {
11302
+ active: isActive,
11303
+ onClick: handleDesktopClick,
11304
+ icon: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11305
+ import_phosphor_react22.Bell,
11245
11306
  {
11246
- groupedNotifications,
11247
- loading,
11248
- error,
11249
- onRetry,
11250
- onMarkAsReadById,
11251
- onDeleteById,
11252
- onNavigateById: (entityType, entityId) => handleNavigate(entityType, entityId),
11253
- getActionLabel,
11254
- renderEmpty: renderEmptyState
11307
+ size: 24,
11308
+ className: isActive ? "text-primary-950" : "text-primary"
11255
11309
  }
11256
- ) })
11257
- ] })
11310
+ ),
11311
+ className
11312
+ }
11313
+ ) }),
11314
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11315
+ DropdownMenuContent,
11316
+ {
11317
+ className: "min-w-[320px] max-w-[400px] max-h-[500px] overflow-hidden",
11318
+ side: "bottom",
11319
+ align: "end",
11320
+ children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col", children: [
11321
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "px-4 py-3 border-b border-border-200", children: [
11322
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11323
+ NotificationHeader,
11324
+ {
11325
+ unreadCount,
11326
+ variant: "dropdown"
11327
+ }
11328
+ ),
11329
+ unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11330
+ "button",
11331
+ {
11332
+ type: "button",
11333
+ onClick: onMarkAllAsRead,
11334
+ className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2",
11335
+ children: "Marcar todas como lidas"
11336
+ }
11337
+ )
11338
+ ] }),
11339
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "max-h-[350px] overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11340
+ NotificationList,
11341
+ {
11342
+ groupedNotifications,
11343
+ loading,
11344
+ error,
11345
+ onRetry,
11346
+ onMarkAsReadById,
11347
+ onDeleteById,
11348
+ onNavigateById,
11349
+ onGlobalNotificationClick: (notification) => {
11350
+ setGlobalNotificationModal({
11351
+ isOpen: true,
11352
+ notification
11353
+ });
11354
+ },
11355
+ getActionLabel,
11356
+ renderEmpty: renderEmptyState,
11357
+ emptyStateImage
11358
+ }
11359
+ ) })
11360
+ ] })
11361
+ }
11362
+ )
11363
+ ] }),
11364
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11365
+ Modal_default,
11366
+ {
11367
+ isOpen: globalNotificationModal.isOpen,
11368
+ onClose: () => setGlobalNotificationModal({ isOpen: false, notification: null }),
11369
+ title: globalNotificationModal.notification?.title || "",
11370
+ variant: "activity",
11371
+ description: globalNotificationModal.notification?.message,
11372
+ image: emptyStateImage || mock_content_default,
11373
+ actionLink: globalNotificationModal.notification?.actionLink || void 0,
11374
+ actionLabel: "Ver mais",
11375
+ size: "lg"
11258
11376
  }
11259
11377
  )
11260
11378
  ] });
@@ -11292,9 +11410,11 @@ var NotificationCard = (props) => {
11292
11410
  onMarkAsReadById: props.onMarkAsReadById,
11293
11411
  onDeleteById: props.onDeleteById,
11294
11412
  onNavigateById: props.onNavigateById,
11413
+ onGlobalNotificationClick: props.onGlobalNotificationClick,
11295
11414
  getActionLabel: props.getActionLabel,
11296
11415
  renderEmpty: props.renderEmpty,
11297
- className: props.className
11416
+ className: props.className,
11417
+ emptyStateImage: props.emptyStateImage
11298
11418
  }
11299
11419
  );
11300
11420
  case "center":