analytica-frontend-lib 1.1.52 → 1.1.54

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
@@ -3960,6 +3960,52 @@ var Calendar_default = Calendar;
3960
3960
  // src/components/Modal/Modal.tsx
3961
3961
  var import_react13 = require("react");
3962
3962
  var import_phosphor_react11 = require("phosphor-react");
3963
+
3964
+ // src/components/Modal/utils/videoUtils.ts
3965
+ var isYouTubeUrl = (url) => {
3966
+ const youtubeRegex = /^(https?:\/\/)?((www|m|music)\.)?(youtube\.com|youtu\.be|youtube-nocookie\.com)\/.+/i;
3967
+ return youtubeRegex.test(url);
3968
+ };
3969
+ var isValidYouTubeHost = (host) => {
3970
+ if (host === "youtu.be") return "youtu.be";
3971
+ const isValidYouTubeCom = host === "youtube.com" || host.endsWith(".youtube.com") && /^(www|m|music)\.youtube\.com$/.test(host);
3972
+ if (isValidYouTubeCom) return "youtube";
3973
+ const isValidNoCookie = host === "youtube-nocookie.com" || host.endsWith(".youtube-nocookie.com") && /^(www|m|music)\.youtube-nocookie\.com$/.test(host);
3974
+ if (isValidNoCookie) return "nocookie";
3975
+ return null;
3976
+ };
3977
+ var extractYoutuBeId = (pathname) => {
3978
+ const firstSeg = pathname.split("/").filter(Boolean)[0];
3979
+ return firstSeg || null;
3980
+ };
3981
+ var extractYouTubeId = (pathname, searchParams) => {
3982
+ const parts = pathname.split("/").filter(Boolean);
3983
+ const [first, second] = parts;
3984
+ if (first === "embed" && second) return second;
3985
+ if (first === "shorts" && second) return second;
3986
+ if (first === "live" && second) return second;
3987
+ const v = searchParams.get("v");
3988
+ if (v) return v;
3989
+ return null;
3990
+ };
3991
+ var getYouTubeVideoId = (url) => {
3992
+ try {
3993
+ const u = new URL(url);
3994
+ const hostType = isValidYouTubeHost(u.hostname.toLowerCase());
3995
+ if (!hostType) return null;
3996
+ if (hostType === "youtu.be") {
3997
+ return extractYoutuBeId(u.pathname);
3998
+ }
3999
+ return extractYouTubeId(u.pathname, u.searchParams);
4000
+ } catch {
4001
+ return null;
4002
+ }
4003
+ };
4004
+ var getYouTubeEmbedUrl = (videoId) => {
4005
+ return `https://www.youtube-nocookie.com/embed/${videoId}?autoplay=0&rel=0&modestbranding=1`;
4006
+ };
4007
+
4008
+ // src/components/Modal/Modal.tsx
3963
4009
  var import_jsx_runtime25 = require("react/jsx-runtime");
3964
4010
  var SIZE_CLASSES10 = {
3965
4011
  xs: "max-w-[360px]",
@@ -3975,11 +4021,17 @@ var Modal = ({
3975
4021
  children,
3976
4022
  size = "md",
3977
4023
  className = "",
3978
- closeOnBackdropClick = true,
3979
4024
  closeOnEscape = true,
3980
4025
  footer,
3981
- hideCloseButton = false
4026
+ hideCloseButton = false,
4027
+ variant = "default",
4028
+ description,
4029
+ image,
4030
+ imageAlt,
4031
+ actionLink,
4032
+ actionLabel
3982
4033
  }) => {
4034
+ const titleId = (0, import_react13.useId)();
3983
4035
  (0, import_react13.useEffect)(() => {
3984
4036
  if (!isOpen || !closeOnEscape) return;
3985
4037
  const handleEscape = (event) => {
@@ -4001,16 +4053,6 @@ var Modal = ({
4001
4053
  document.body.style.overflow = originalOverflow;
4002
4054
  };
4003
4055
  }, [isOpen]);
4004
- const handleBackdropClick = (event) => {
4005
- if (closeOnBackdropClick && event.target === event.currentTarget) {
4006
- onClose();
4007
- }
4008
- };
4009
- const handleBackdropKeyDown = (event) => {
4010
- if (closeOnBackdropClick && (event.key === "Enter" || event.key === " ")) {
4011
- onClose();
4012
- }
4013
- };
4014
4056
  if (!isOpen) return null;
4015
4057
  const sizeClasses = SIZE_CLASSES10[size];
4016
4058
  const baseClasses = "bg-secondary-50 rounded-3xl shadow-hard-shadow-2 border border-border-100 w-full mx-4";
@@ -4021,18 +4063,105 @@ var Modal = ({
4021
4063
  dialogResetClasses,
4022
4064
  className
4023
4065
  );
4024
- return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4025
- "div",
4066
+ const normalizeUrl = (href) => /^https?:\/\//i.test(href) ? href : `https://${href}`;
4067
+ const handleActionClick = () => {
4068
+ if (actionLink) {
4069
+ window.open(normalizeUrl(actionLink), "_blank", "noopener,noreferrer");
4070
+ }
4071
+ };
4072
+ if (variant === "activity") {
4073
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs border-none p-0 m-0 w-full cursor-default", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
4074
+ "dialog",
4075
+ {
4076
+ className: modalClasses,
4077
+ "aria-labelledby": titleId,
4078
+ "aria-modal": "true",
4079
+ open: true,
4080
+ children: [
4081
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex justify-end p-6 pb-0", children: !hideCloseButton && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4082
+ "button",
4083
+ {
4084
+ onClick: onClose,
4085
+ className: "p-1 text-text-500 hover:text-text-700 hover:bg-background-50 rounded-md transition-colors focus:outline-none focus:ring-2 focus:ring-indicator-info focus:ring-offset-2",
4086
+ "aria-label": "Fechar modal",
4087
+ children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(import_phosphor_react11.X, { size: 18 })
4088
+ }
4089
+ ) }),
4090
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex flex-col items-center px-6 pb-6 gap-5", children: [
4091
+ image && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4092
+ "img",
4093
+ {
4094
+ src: image,
4095
+ alt: imageAlt ?? "",
4096
+ className: "w-[122px] h-[122px] object-contain"
4097
+ }
4098
+ ) }),
4099
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4100
+ "h2",
4101
+ {
4102
+ id: titleId,
4103
+ className: "text-lg font-semibold text-text-950 text-center",
4104
+ children: title
4105
+ }
4106
+ ),
4107
+ description && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("p", { className: "text-sm font-normal text-text-400 text-center max-w-md leading-[21px]", children: description }),
4108
+ actionLink && /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "w-full", children: [
4109
+ (() => {
4110
+ const normalized = normalizeUrl(actionLink);
4111
+ const isYT = isYouTubeUrl(normalized);
4112
+ if (!isYT) return null;
4113
+ const id = getYouTubeVideoId(normalized);
4114
+ if (!id) {
4115
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4116
+ Button_default,
4117
+ {
4118
+ variant: "solid",
4119
+ action: "primary",
4120
+ size: "large",
4121
+ className: "w-full",
4122
+ onClick: handleActionClick,
4123
+ children: actionLabel || "Iniciar Atividade"
4124
+ }
4125
+ );
4126
+ }
4127
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4128
+ "iframe",
4129
+ {
4130
+ src: getYouTubeEmbedUrl(id),
4131
+ className: "w-full aspect-video rounded-lg",
4132
+ allowFullScreen: true,
4133
+ allow: "accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture",
4134
+ title: "V\xEDdeo YouTube"
4135
+ }
4136
+ );
4137
+ })(),
4138
+ !isYouTubeUrl(normalizeUrl(actionLink)) && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4139
+ Button_default,
4140
+ {
4141
+ variant: "solid",
4142
+ action: "primary",
4143
+ size: "large",
4144
+ className: "w-full",
4145
+ onClick: handleActionClick,
4146
+ children: actionLabel || "Iniciar Atividade"
4147
+ }
4148
+ )
4149
+ ] })
4150
+ ] })
4151
+ ]
4152
+ }
4153
+ ) });
4154
+ }
4155
+ return /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs border-none p-0 m-0 w-full cursor-default", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)(
4156
+ "dialog",
4026
4157
  {
4027
- className: "fixed inset-0 z-50 flex items-center justify-center bg-black/60 backdrop-blur-xs",
4028
- onClick: handleBackdropClick,
4029
- onKeyDown: handleBackdropKeyDown,
4030
- role: "button",
4031
- tabIndex: closeOnBackdropClick ? 0 : -1,
4032
- "aria-label": "Fechar modal clicando no fundo",
4033
- children: /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("dialog", { className: modalClasses, "aria-labelledby": "modal-title", open: true, children: [
4158
+ className: modalClasses,
4159
+ "aria-labelledby": titleId,
4160
+ "aria-modal": "true",
4161
+ open: true,
4162
+ children: [
4034
4163
  /* @__PURE__ */ (0, import_jsx_runtime25.jsxs)("div", { className: "flex items-center justify-between px-6 py-6", children: [
4035
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { id: "modal-title", className: "text-lg font-semibold text-text-950", children: title }),
4164
+ /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("h2", { id: titleId, className: "text-lg font-semibold text-text-950", children: title }),
4036
4165
  !hideCloseButton && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)(
4037
4166
  "button",
4038
4167
  {
@@ -4043,11 +4172,11 @@ var Modal = ({
4043
4172
  }
4044
4173
  )
4045
4174
  ] }),
4046
- /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "px-6 pb-6", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-text-500 font-normal text-sm leading-6", children }) }),
4175
+ children && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "px-6 pb-6", children: /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "text-text-500 font-normal text-sm leading-6", children }) }),
4047
4176
  footer && /* @__PURE__ */ (0, import_jsx_runtime25.jsx)("div", { className: "flex justify-end gap-3 px-6 pb-6", children: footer })
4048
- ] })
4177
+ ]
4049
4178
  }
4050
- );
4179
+ ) });
4051
4180
  };
4052
4181
  var Modal_default = Modal;
4053
4182
 
@@ -10113,7 +10242,6 @@ var QuizFooter = (0, import_react30.forwardRef)(
10113
10242
  isOpen: modalResultOpen,
10114
10243
  onClose: () => setModalResultOpen(false),
10115
10244
  title: "",
10116
- closeOnBackdropClick: false,
10117
10245
  closeOnEscape: false,
10118
10246
  hideCloseButton: true,
10119
10247
  size: "md",
@@ -10776,12 +10904,19 @@ var NotificationHeader = ({
10776
10904
  unreadCount,
10777
10905
  variant = "modal"
10778
10906
  }) => {
10779
- return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
10907
+ return /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between gap-2", children: [
10780
10908
  variant === "modal" ? /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(Text_default, { size: "sm", weight: "bold", className: "text-text-950", children: "Notifica\xE7\xF5es" }) : /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("h3", { className: "text-sm font-semibold text-text-950", children: "Notifica\xE7\xF5es" }),
10781
- unreadCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("span", { className: "px-2 py-1 bg-info-100 text-info-700 text-xs rounded-full", children: [
10782
- unreadCount,
10783
- " n\xE3o lidas"
10784
- ] })
10909
+ unreadCount > 0 && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
10910
+ Badge_default,
10911
+ {
10912
+ variant: "solid",
10913
+ action: "info",
10914
+ size: "small",
10915
+ iconLeft: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(import_phosphor_react21.Bell, { size: 12, "aria-hidden": "true", focusable: "false" }),
10916
+ className: "border-0",
10917
+ children: unreadCount === 1 ? "1 n\xE3o lida" : `${unreadCount} n\xE3o lidas`
10918
+ }
10919
+ )
10785
10920
  ] });
10786
10921
  };
10787
10922
  var SingleNotificationCard = ({
@@ -10991,21 +11126,20 @@ var NotificationCenter = ({
10991
11126
  title: "Notifica\xE7\xF5es",
10992
11127
  size: "md",
10993
11128
  hideCloseButton: false,
10994
- closeOnBackdropClick: true,
10995
11129
  closeOnEscape: true,
10996
11130
  children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col h-full max-h-[80vh]", children: [
10997
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "px-0 pb-3 border-b border-border-200", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
11131
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "px-0 pb-3 border-b border-border-200", children: [
10998
11132
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(NotificationHeader, { unreadCount, variant: "modal" }),
10999
11133
  unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11000
11134
  "button",
11001
11135
  {
11002
11136
  type: "button",
11003
11137
  onClick: onMarkAllAsRead,
11004
- className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer",
11138
+ className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2",
11005
11139
  children: "Marcar todas como lidas"
11006
11140
  }
11007
11141
  )
11008
- ] }) }),
11142
+ ] }),
11009
11143
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "flex-1 overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11010
11144
  NotificationList,
11011
11145
  {
@@ -11052,24 +11186,18 @@ var NotificationCenter = ({
11052
11186
  side: "bottom",
11053
11187
  align: "end",
11054
11188
  children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex flex-col", children: [
11055
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "px-4 py-3 border-b border-border-200", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "flex items-center justify-between", children: [
11056
- /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11057
- NotificationHeader,
11058
- {
11059
- unreadCount,
11060
- variant: "dropdown"
11061
- }
11062
- ),
11189
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsxs)("div", { className: "px-4 py-3 border-b border-border-200", children: [
11190
+ /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(NotificationHeader, { unreadCount, variant: "dropdown" }),
11063
11191
  unreadCount > 0 && onMarkAllAsRead && /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11064
11192
  "button",
11065
11193
  {
11066
11194
  type: "button",
11067
11195
  onClick: onMarkAllAsRead,
11068
- className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer",
11196
+ className: "text-sm font-medium text-info-600 hover:text-info-700 cursor-pointer mt-2",
11069
11197
  children: "Marcar todas como lidas"
11070
11198
  }
11071
11199
  )
11072
- ] }) }),
11200
+ ] }),
11073
11201
  /* @__PURE__ */ (0, import_jsx_runtime42.jsx)("div", { className: "max-h-[350px] overflow-y-auto", children: /* @__PURE__ */ (0, import_jsx_runtime42.jsx)(
11074
11202
  NotificationList,
11075
11203
  {