analytica-frontend-lib 1.0.57 → 1.0.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.
@@ -81,5 +81,23 @@ interface CardForumProps<T = unknown> extends HTMLAttributes<HTMLDivElement> {
81
81
  valueProfile?: T;
82
82
  }
83
83
  declare const CardForum: react.ForwardRefExoticComponent<CardForumProps<unknown> & react.RefAttributes<HTMLDivElement>>;
84
+ interface CardAudioProps extends HTMLAttributes<HTMLDivElement> {
85
+ src?: string;
86
+ title?: string;
87
+ onPlay?: () => void;
88
+ onPause?: () => void;
89
+ onEnded?: () => void;
90
+ onAudioTimeUpdate?: (currentTime: number, duration: number) => void;
91
+ loop?: boolean;
92
+ preload?: 'none' | 'metadata' | 'auto';
93
+ tracks?: Array<{
94
+ kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';
95
+ src: string;
96
+ srcLang: string;
97
+ label: string;
98
+ default?: boolean;
99
+ }>;
100
+ }
101
+ declare const CardAudio: react.ForwardRefExoticComponent<CardAudioProps & react.RefAttributes<HTMLDivElement>>;
84
102
 
85
- export { CardActivesResults, CardForum, CardPerformance, CardProgress, CardQuestions, CardResults, CardSettings, CardStatus, CardSupport, CardTopic };
103
+ export { CardActivesResults, CardAudio, CardForum, CardPerformance, CardProgress, CardQuestions, CardResults, CardSettings, CardStatus, CardSupport, CardTopic };
@@ -81,5 +81,23 @@ interface CardForumProps<T = unknown> extends HTMLAttributes<HTMLDivElement> {
81
81
  valueProfile?: T;
82
82
  }
83
83
  declare const CardForum: react.ForwardRefExoticComponent<CardForumProps<unknown> & react.RefAttributes<HTMLDivElement>>;
84
+ interface CardAudioProps extends HTMLAttributes<HTMLDivElement> {
85
+ src?: string;
86
+ title?: string;
87
+ onPlay?: () => void;
88
+ onPause?: () => void;
89
+ onEnded?: () => void;
90
+ onAudioTimeUpdate?: (currentTime: number, duration: number) => void;
91
+ loop?: boolean;
92
+ preload?: 'none' | 'metadata' | 'auto';
93
+ tracks?: Array<{
94
+ kind: 'subtitles' | 'captions' | 'descriptions' | 'chapters' | 'metadata';
95
+ src: string;
96
+ srcLang: string;
97
+ label: string;
98
+ default?: boolean;
99
+ }>;
100
+ }
101
+ declare const CardAudio: react.ForwardRefExoticComponent<CardAudioProps & react.RefAttributes<HTMLDivElement>>;
84
102
 
85
- export { CardActivesResults, CardForum, CardPerformance, CardProgress, CardQuestions, CardResults, CardSettings, CardStatus, CardSupport, CardTopic };
103
+ export { CardActivesResults, CardAudio, CardForum, CardPerformance, CardProgress, CardQuestions, CardResults, CardSettings, CardStatus, CardSupport, CardTopic };
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
21
21
  var Card_exports = {};
22
22
  __export(Card_exports, {
23
23
  CardActivesResults: () => CardActivesResults,
24
+ CardAudio: () => CardAudio,
24
25
  CardForum: () => CardForum,
25
26
  CardPerformance: () => CardPerformance,
26
27
  CardProgress: () => CardProgress,
@@ -850,7 +851,7 @@ var CardProgress = (0, import_react.forwardRef)(
850
851
  {
851
852
  ref,
852
853
  className: `
853
- w-full flex border border-border-50 bg-background rounded-xl
854
+ w-full flex border border-border-50 bg-background rounded-xl cursor-pointer
854
855
  ${isHorizontal ? "flex-row h-20" : "flex-col"}
855
856
  ${className}
856
857
  `,
@@ -900,7 +901,7 @@ var CardTopic = (0, import_react.forwardRef)(
900
901
  "div",
901
902
  {
902
903
  ref,
903
- className: `w-full py-2 px-4 flex flex-col justify-center gap-2 bg-background border border-border-50 rounded-xl min-h-20 ${className}`,
904
+ className: `cursor-pointer w-full py-2 px-4 flex flex-col justify-center gap-2 bg-background border border-border-50 rounded-xl min-h-20 ${className}`,
904
905
  ...props,
905
906
  children: [
906
907
  subHead && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "text-text-600 text-2xs flex flex-row gap-1", children: subHead.map((text, index) => /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_react.Fragment, { children: [
@@ -950,7 +951,7 @@ var CardPerformance = (0, import_react.forwardRef)(
950
951
  !hasProgress && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
951
952
  import_phosphor_react2.CaretRight,
952
953
  {
953
- className: "size-4.5 text-text-800",
954
+ className: "size-4.5 text-text-800 cursor-pointer",
954
955
  "data-testid": "caret-icon",
955
956
  onClick: () => onClickButton?.(valueButton)
956
957
  }
@@ -1034,7 +1035,7 @@ var CardResults = (0, import_react.forwardRef)(
1034
1035
  ]
1035
1036
  }
1036
1037
  ),
1037
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { className: "min-w-6 min-h-6 text-text-800" })
1038
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { className: "min-w-6 min-h-6 text-text-800 cursor-pointer" })
1038
1039
  ]
1039
1040
  }
1040
1041
  );
@@ -1076,7 +1077,7 @@ var CardStatus = (0, import_react.forwardRef)(
1076
1077
  ]
1077
1078
  }
1078
1079
  ),
1079
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { className: "min-w-6 min-h-6 text-text-800" })
1080
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { className: "min-w-6 min-h-6 text-text-800 cursor-pointer" })
1080
1081
  ]
1081
1082
  }
1082
1083
  );
@@ -1093,7 +1094,7 @@ var CardSettings = (0, import_react.forwardRef)(
1093
1094
  children: [
1094
1095
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "[&>svg]:size-6", children: icon }),
1095
1096
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "w-full text-md", children: header }),
1096
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { size: 24 })
1097
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { size: 24, className: "cursor-pointer" })
1097
1098
  ]
1098
1099
  }
1099
1100
  );
@@ -1120,7 +1121,7 @@ var CardSupport = (0, import_react.forwardRef)(
1120
1121
  ]
1121
1122
  }
1122
1123
  ),
1123
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { className: "text-text-800", size: 24 })
1124
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.CaretRight, { className: "text-text-800 cursor-pointer", size: 24 })
1124
1125
  ]
1125
1126
  }
1126
1127
  );
@@ -1189,9 +1190,247 @@ var CardForum = (0, import_react.forwardRef)(
1189
1190
  );
1190
1191
  }
1191
1192
  );
1193
+ var CardAudio = (0, import_react.forwardRef)(
1194
+ ({
1195
+ src,
1196
+ title,
1197
+ onPlay,
1198
+ onPause,
1199
+ onEnded,
1200
+ onAudioTimeUpdate,
1201
+ loop = false,
1202
+ preload = "metadata",
1203
+ tracks,
1204
+ className,
1205
+ ...props
1206
+ }, ref) => {
1207
+ const [isPlaying, setIsPlaying] = (0, import_react.useState)(false);
1208
+ const [currentTime, setCurrentTime] = (0, import_react.useState)(0);
1209
+ const [duration, setDuration] = (0, import_react.useState)(0);
1210
+ const [volume, setVolume] = (0, import_react.useState)(1);
1211
+ const [showVolumeControl, setShowVolumeControl] = (0, import_react.useState)(false);
1212
+ const audioRef = (0, import_react.useRef)(null);
1213
+ const formatTime = (time) => {
1214
+ const minutes = Math.floor(time / 60);
1215
+ const seconds = Math.floor(time % 60);
1216
+ return `${minutes}:${seconds.toString().padStart(2, "0")}`;
1217
+ };
1218
+ const handlePlayPause = () => {
1219
+ if (isPlaying) {
1220
+ audioRef.current?.pause();
1221
+ setIsPlaying(false);
1222
+ onPause?.();
1223
+ } else {
1224
+ audioRef.current?.play();
1225
+ setIsPlaying(true);
1226
+ onPlay?.();
1227
+ }
1228
+ };
1229
+ const handleTimeUpdate = () => {
1230
+ const current = audioRef.current?.currentTime ?? 0;
1231
+ const total = audioRef.current?.duration ?? 0;
1232
+ setCurrentTime(current);
1233
+ setDuration(total);
1234
+ onAudioTimeUpdate?.(current, total);
1235
+ };
1236
+ const handleLoadedMetadata = () => {
1237
+ setDuration(audioRef.current?.duration ?? 0);
1238
+ };
1239
+ const handleEnded = () => {
1240
+ setIsPlaying(false);
1241
+ setCurrentTime(0);
1242
+ onEnded?.();
1243
+ };
1244
+ const handleProgressClick = (e) => {
1245
+ const rect = e.currentTarget.getBoundingClientRect();
1246
+ const clickX = e.clientX - rect.left;
1247
+ const width = rect.width;
1248
+ const percentage = clickX / width;
1249
+ const newTime = percentage * duration;
1250
+ if (audioRef.current) {
1251
+ audioRef.current.currentTime = newTime;
1252
+ }
1253
+ setCurrentTime(newTime);
1254
+ };
1255
+ const handleVolumeChange = (e) => {
1256
+ const newVolume = parseFloat(e.target.value);
1257
+ setVolume(newVolume);
1258
+ if (audioRef.current) {
1259
+ audioRef.current.volume = newVolume;
1260
+ }
1261
+ };
1262
+ const toggleVolumeControl = () => {
1263
+ setShowVolumeControl(!showVolumeControl);
1264
+ };
1265
+ const getVolumeIcon = () => {
1266
+ if (volume === 0) {
1267
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.SpeakerSimpleX, {});
1268
+ }
1269
+ if (volume < 0.5) {
1270
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.SpeakerLow, {});
1271
+ }
1272
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.SpeakerHigh, {});
1273
+ };
1274
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1275
+ "div",
1276
+ {
1277
+ ref,
1278
+ className: `w-auto h-14 p-4 flex flex-row bg-background items-center gap-2 ${className}`,
1279
+ ...props,
1280
+ children: [
1281
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1282
+ "audio",
1283
+ {
1284
+ ref: audioRef,
1285
+ src,
1286
+ loop,
1287
+ preload,
1288
+ onTimeUpdate: handleTimeUpdate,
1289
+ onLoadedMetadata: handleLoadedMetadata,
1290
+ onEnded: handleEnded,
1291
+ "data-testid": "audio-element",
1292
+ "aria-label": title,
1293
+ children: tracks ? tracks.map((track) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1294
+ "track",
1295
+ {
1296
+ kind: track.kind,
1297
+ src: track.src,
1298
+ srcLang: track.srcLang,
1299
+ label: track.label,
1300
+ default: track.default
1301
+ },
1302
+ track.src
1303
+ )) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1304
+ "track",
1305
+ {
1306
+ kind: "captions",
1307
+ src: "data:text/vtt;base64,",
1308
+ srcLang: "pt",
1309
+ label: "Sem legendas dispon\xEDveis"
1310
+ }
1311
+ )
1312
+ }
1313
+ ),
1314
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1315
+ "button",
1316
+ {
1317
+ type: "button",
1318
+ onClick: handlePlayPause,
1319
+ disabled: !src,
1320
+ className: "cursor-pointer text-text-950 hover:text-primary-600 disabled:text-text-400 disabled:cursor-not-allowed",
1321
+ "aria-label": isPlaying ? "Pausar" : "Reproduzir",
1322
+ children: isPlaying ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-6 h-6 flex items-center justify-center", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex gap-0.5", children: [
1323
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-1 h-4 bg-current rounded-sm" }),
1324
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-1 h-4 bg-current rounded-sm" })
1325
+ ] }) }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_phosphor_react2.Play, { size: 24 })
1326
+ }
1327
+ ),
1328
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-text-800 text-sm font-medium min-w-[2.5rem]", children: formatTime(currentTime) }),
1329
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex-1 relative", "data-testid": "progress-bar", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1330
+ "button",
1331
+ {
1332
+ type: "button",
1333
+ className: "w-full h-2 bg-border-100 rounded-full cursor-pointer",
1334
+ onClick: handleProgressClick,
1335
+ onKeyDown: (e) => {
1336
+ if (e.key === "Enter" || e.key === " ") {
1337
+ e.preventDefault();
1338
+ handleProgressClick(
1339
+ e
1340
+ );
1341
+ }
1342
+ },
1343
+ "aria-label": "Barra de progresso do \xE1udio",
1344
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1345
+ "div",
1346
+ {
1347
+ className: "h-full bg-primary-600 rounded-full transition-all duration-100",
1348
+ style: {
1349
+ width: duration > 0 ? `${currentTime / duration * 100}%` : "0%"
1350
+ }
1351
+ }
1352
+ )
1353
+ }
1354
+ ) }),
1355
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-text-800 text-sm font-medium min-w-[2.5rem]", children: formatTime(duration) }),
1356
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative", children: [
1357
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1358
+ "button",
1359
+ {
1360
+ type: "button",
1361
+ onClick: toggleVolumeControl,
1362
+ className: "cursor-pointer text-text-950 hover:text-primary-600",
1363
+ "aria-label": "Controle de volume",
1364
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "w-6 h-6 flex items-center justify-center", children: getVolumeIcon() })
1365
+ }
1366
+ ),
1367
+ showVolumeControl && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1368
+ "button",
1369
+ {
1370
+ type: "button",
1371
+ className: "absolute bottom-full right-0 mb-2 p-2 bg-background border border-border-100 rounded-lg shadow-lg focus:outline-none focus:ring-2 focus:ring-primary-500",
1372
+ onKeyDown: (e) => {
1373
+ if (e.key === "Escape") {
1374
+ setShowVolumeControl(false);
1375
+ }
1376
+ },
1377
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1378
+ "input",
1379
+ {
1380
+ type: "range",
1381
+ min: "0",
1382
+ max: "1",
1383
+ step: "0.1",
1384
+ value: volume,
1385
+ onChange: handleVolumeChange,
1386
+ onKeyDown: (e) => {
1387
+ if (e.key === "ArrowUp" || e.key === "ArrowRight") {
1388
+ e.preventDefault();
1389
+ const newVolume = Math.min(
1390
+ 1,
1391
+ Math.round((volume + 0.1) * 10) / 10
1392
+ );
1393
+ setVolume(newVolume);
1394
+ if (audioRef.current) audioRef.current.volume = newVolume;
1395
+ } else if (e.key === "ArrowDown" || e.key === "ArrowLeft") {
1396
+ e.preventDefault();
1397
+ const newVolume = Math.max(
1398
+ 0,
1399
+ Math.round((volume - 0.1) * 10) / 10
1400
+ );
1401
+ setVolume(newVolume);
1402
+ if (audioRef.current) audioRef.current.volume = newVolume;
1403
+ }
1404
+ },
1405
+ className: "w-20 h-2 bg-border-100 rounded-lg appearance-none cursor-pointer",
1406
+ style: {
1407
+ background: `linear-gradient(to right, #3b82f6 0%, #3b82f6 ${volume * 100}%, #e5e7eb ${volume * 100}%, #e5e7eb 100%)`
1408
+ },
1409
+ "aria-label": "Volume",
1410
+ "aria-valuenow": Math.round(volume * 100),
1411
+ "aria-valuemin": 0,
1412
+ "aria-valuemax": 100
1413
+ }
1414
+ )
1415
+ }
1416
+ )
1417
+ ] }),
1418
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1419
+ import_phosphor_react2.DotsThreeVertical,
1420
+ {
1421
+ size: 24,
1422
+ className: "text-text-950 cursor-pointer hover:text-primary-600"
1423
+ }
1424
+ )
1425
+ ]
1426
+ }
1427
+ );
1428
+ }
1429
+ );
1192
1430
  // Annotate the CommonJS export names for ESM import in node:
1193
1431
  0 && (module.exports = {
1194
1432
  CardActivesResults,
1433
+ CardAudio,
1195
1434
  CardForum,
1196
1435
  CardPerformance,
1197
1436
  CardProgress,