@codebit-programando-solucoes/codebit-web-antd 1.1.32 → 1.1.34

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.
@@ -0,0 +1,10 @@
1
+ import { JSX } from 'react';
2
+
3
+ /** Props for the AudioPlayer component */
4
+ export interface AudioPlayerProps {
5
+ /** The URL of the audio file to play */
6
+ audioUrl: string;
7
+ }
8
+
9
+ /** AudioPlayer component - A customizable audio player with play/pause, mute/unmute, and seek functionality. */
10
+ export function AudioPlayer(props: AudioPlayerProps): JSX.Element;
@@ -139,4 +139,10 @@ import { FC } from 'react';
139
139
  * }
140
140
  * ```;
141
141
  */
142
- export const CssTokenBridge: FC;
142
+ export interface CssTokenBridgeProps {
143
+ /** Optional ID of the container element to receive the CSS variables. */
144
+ containerId?: string;
145
+ }
146
+
147
+ /** CssTokenBridge component definition. */
148
+ export const CssTokenBridge: FC<CssTokenBridgeProps>;
@@ -5,3 +5,4 @@ export * from './ListCard';
5
5
  export * from './CssTokenBridge';
6
6
  export * from './TableContainer';
7
7
  export * from './FilterContainer';
8
+ export * from './AudioPlayer';
@@ -23,4 +23,8 @@ type CodebitThemeProviderProps = {
23
23
  children: React.ReactNode;
24
24
  /** Whether to persist theme preference in localStorage (default: `true`) */
25
25
  storeThemeInLocalStorage?: boolean;
26
+ /** ID of the root container element where theme classes are applied (default: `'root'`) */
27
+ containerId?: string;
28
+ /** Optional explicit theme override. When set, the provider uses this value instead of internal detection. */
29
+ forcedTheme?: 'dark' | 'light' | null;
26
30
  } & ConfigProviderProps;
package/dist/index.cjs CHANGED
@@ -304,17 +304,18 @@ var __webpack_exports__ = {};
304
304
  LocalLoginChangePasswordResult: ()=>LocalLoginChangePasswordResult,
305
305
  ChangePassword: ()=>ChangePassword,
306
306
  ListCard: ()=>ListCard,
307
- CodebitConfigContext: ()=>CodebitConfigContext,
308
307
  ForgotPassword: ()=>ForgotPassword,
308
+ CodebitConfigContext: ()=>CodebitConfigContext,
309
309
  LoginContainer: ()=>LoginContainer,
310
310
  useErrorMessage: ()=>useErrorMessage,
311
311
  LocalLoginRecoveryPasswordResult: ()=>LocalLoginRecoveryPasswordResult,
312
312
  FilterContainer: ()=>FilterContainer,
313
313
  HandleError: ()=>HandleError,
314
- OllamaOutlinedIcon: ()=>OllamaOutlinedIcon,
314
+ AudioPlayer: ()=>AudioPlayer,
315
315
  AdminUserOutlinedIcon: ()=>AdminUserOutlinedIcon,
316
316
  CodebitConfigProvider: ()=>CodebitConfigProvider,
317
317
  ElectronicBrainOutlinedIcon: ()=>ElectronicBrainOutlinedIcon,
318
+ OllamaOutlinedIcon: ()=>OllamaOutlinedIcon,
318
319
  ThemeToggle: ()=>ThemeToggle
319
320
  });
320
321
  var jsx_runtime = __webpack_require__("../../node_modules/.pnpm/react@19.2.3/node_modules/react/jsx-runtime.js");
@@ -514,6 +515,16 @@ var __webpack_exports__ = {};
514
515
  ListCard: {
515
516
  clearFilters: 'Limpar filtros'
516
517
  },
518
+ AudioPlayer: {
519
+ play: 'Reproduzir',
520
+ pause: 'Pausar',
521
+ mute: 'Desativar som',
522
+ unmute: 'Ativar som',
523
+ playAudio: 'Reproduzir áudio',
524
+ pauseAudio: 'Pausar áudio',
525
+ muteAudio: 'Ativar som',
526
+ unmuteAudio: 'Desativar som'
527
+ },
517
528
  Common: {
518
529
  ok: 'Ok',
519
530
  close: 'Fechar',
@@ -616,6 +627,16 @@ var __webpack_exports__ = {};
616
627
  ListCard: {
617
628
  clearFilters: 'Clear filters'
618
629
  },
630
+ AudioPlayer: {
631
+ play: 'Play',
632
+ pause: 'Pause',
633
+ mute: 'Mute',
634
+ unmute: 'Unmute',
635
+ playAudio: 'Play audio',
636
+ pauseAudio: 'Pause audio',
637
+ muteAudio: 'Mute audio',
638
+ unmuteAudio: 'Unmute audio'
639
+ },
619
640
  Common: {
620
641
  ok: 'Ok',
621
642
  close: 'Close',
@@ -797,10 +818,10 @@ var __webpack_exports__ = {};
797
818
  tableContainer: null,
798
819
  actions: null
799
820
  };
800
- const CssTokenBridge = ()=>{
821
+ const CssTokenBridge = ({ containerId })=>{
801
822
  const { token } = external_antd_namespaceObject.theme.useToken();
802
823
  (0, external_react_.useLayoutEffect)(()=>{
803
- const root = document.documentElement;
824
+ const root = containerId ? document.getElementById(containerId) ?? document.documentElement : document.documentElement;
804
825
  root.style.setProperty('--antd-color-bg-base', token['colorBgBase']);
805
826
  root.style.setProperty('--antd-color-bg-container', token['colorBgContainer']);
806
827
  root.style.setProperty('--antd-color-bg-elevated', token['colorBgElevated']);
@@ -888,10 +909,14 @@ var __webpack_exports__ = {};
888
909
  root.style.setProperty('--antd-border-radius', `${token['borderRadius']}px`);
889
910
  root.style.setProperty('--antd-border-radius-lg', `${token['borderRadiusLG']}px`);
890
911
  }, [
912
+ containerId,
891
913
  token
892
914
  ]);
893
915
  return null;
894
916
  };
917
+ CssTokenBridge.propTypes = {
918
+ containerId: external_prop_types_default().string
919
+ };
895
920
  const TableContainer_module = {
896
921
  tableContainer: "tableContainer-EhNwOm"
897
922
  };
@@ -979,10 +1004,155 @@ var __webpack_exports__ = {};
979
1004
  children: external_prop_types_default().node.isRequired,
980
1005
  ...external_antd_namespaceObject.Card.propTypes
981
1006
  };
1007
+ const external_date_fns_namespaceObject = require("date-fns");
1008
+ const AudioPlayer_module = {
1009
+ audioPlayer: "audioPlayer-a4xARM",
1010
+ durationTimeContainer: "durationTimeContainer-kmkK6M",
1011
+ slider: "slider-bdta4v"
1012
+ };
1013
+ const AudioPlayer = ({ audioUrl })=>{
1014
+ const [isMuted, setIsMuted] = (0, external_react_.useState)(false);
1015
+ const [duration, setDuration] = (0, external_react_.useState)(0);
1016
+ const [currentTime, setCurrentTime] = (0, external_react_.useState)(0);
1017
+ const [isPlaying, setIsPlaying] = (0, external_react_.useState)(false);
1018
+ const { t } = useCodebitWebAntdTranslation();
1019
+ const audioRef = (0, external_react_.useRef)(null);
1020
+ const hasSource = !!audioUrl;
1021
+ const formatTime = (seconds)=>{
1022
+ const sec = Math.max(0, Math.floor(seconds));
1023
+ const date = (0, external_date_fns_namespaceObject.addSeconds)(new Date(0), sec);
1024
+ const h = Math.floor(sec / 3600);
1025
+ const timeFormat = h > 0 ? 'H:mm:ss' : 'm:ss';
1026
+ return (0, external_date_fns_namespaceObject.format)(date, timeFormat);
1027
+ };
1028
+ const togglePlay = async ()=>{
1029
+ if (!audioRef.current || !hasSource) return;
1030
+ if (audioRef.current.paused) {
1031
+ await audioRef.current.play();
1032
+ setIsPlaying(true);
1033
+ } else {
1034
+ audioRef.current.pause();
1035
+ setIsPlaying(false);
1036
+ }
1037
+ };
1038
+ const toggleMute = ()=>{
1039
+ if (!audioRef.current) return;
1040
+ audioRef.current.muted = !audioRef.current.muted;
1041
+ setIsMuted(audioRef.current.muted);
1042
+ };
1043
+ const handleSliderChange = (value)=>{
1044
+ if (!audioRef.current) return;
1045
+ const safeValue = Math.min(Math.round(value), Math.round(duration));
1046
+ audioRef.current.currentTime = safeValue;
1047
+ setCurrentTime(safeValue);
1048
+ };
1049
+ (0, external_react_.useEffect)(()=>{
1050
+ if (audioRef.current && audioUrl) {
1051
+ audioRef.current.pause();
1052
+ audioRef.current.currentTime = 0;
1053
+ audioRef.current.src = audioUrl;
1054
+ audioRef.current.load();
1055
+ }
1056
+ setIsPlaying(false);
1057
+ setCurrentTime(0);
1058
+ setDuration(0);
1059
+ }, [
1060
+ audioUrl
1061
+ ]);
1062
+ const handleLoadedMetadata = ()=>{
1063
+ if (!audioRef.current) return;
1064
+ const audio = audioRef.current;
1065
+ if (audio.duration !== 1 / 0 && Number.isFinite(audio.duration)) {
1066
+ if (audio.duration > 0) setDuration(audio.duration);
1067
+ } else {
1068
+ audio.currentTime = 1e101;
1069
+ const timeUpdateHandler = ()=>{
1070
+ audio.removeEventListener('timeupdate', timeUpdateHandler);
1071
+ audio.currentTime = 0;
1072
+ setDuration(audio.duration || 0);
1073
+ };
1074
+ audio.addEventListener('timeupdate', timeUpdateHandler);
1075
+ }
1076
+ };
1077
+ return /*#__PURE__*/ (0, jsx_runtime.jsxs)("div", {
1078
+ className: AudioPlayer_module.audioPlayer,
1079
+ children: [
1080
+ /*#__PURE__*/ (0, jsx_runtime.jsxs)(external_antd_namespaceObject.Space, {
1081
+ orientation: 'vertical',
1082
+ size: 'middle',
1083
+ children: [
1084
+ /*#__PURE__*/ (0, jsx_runtime.jsxs)(external_antd_namespaceObject.Space, {
1085
+ align: 'center',
1086
+ children: [
1087
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1088
+ type: 'primary',
1089
+ shape: 'circle',
1090
+ icon: isPlaying ? /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.PauseCircleOutlined, {}) : /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.PlayCircleOutlined, {}),
1091
+ onClick: togglePlay,
1092
+ disabled: !hasSource,
1093
+ title: isPlaying ? t('AudioPlayer.pause') : t('AudioPlayer.play'),
1094
+ "aria-label": isPlaying ? t('AudioPlayer.pauseAudio') : t('AudioPlayer.playAudio')
1095
+ }),
1096
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Slider, {
1097
+ min: 0,
1098
+ max: duration,
1099
+ value: currentTime,
1100
+ onChange: handleSliderChange,
1101
+ tooltip: {
1102
+ open: false
1103
+ },
1104
+ disabled: 0 === duration,
1105
+ className: AudioPlayer_module.slider
1106
+ }),
1107
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Button, {
1108
+ shape: 'circle',
1109
+ icon: isMuted ? /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.MutedOutlined, {}) : /*#__PURE__*/ (0, jsx_runtime.jsx)(icons_namespaceObject.SoundOutlined, {}),
1110
+ onClick: toggleMute,
1111
+ disabled: !hasSource,
1112
+ title: isMuted ? t('AudioPlayer.unmute') : t('AudioPlayer.mute'),
1113
+ "aria-label": isMuted ? t('AudioPlayer.unmuteAudio') : t('AudioPlayer.muteAudio')
1114
+ })
1115
+ ]
1116
+ }),
1117
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Space, {
1118
+ className: AudioPlayer_module.durationTimeContainer,
1119
+ children: /*#__PURE__*/ (0, jsx_runtime.jsx)(external_antd_namespaceObject.Typography.Text, {
1120
+ strong: true,
1121
+ children: `${formatTime(currentTime)} / ${formatTime(duration)}`
1122
+ })
1123
+ })
1124
+ ]
1125
+ }),
1126
+ /*#__PURE__*/ (0, jsx_runtime.jsx)("audio", {
1127
+ ref: audioRef,
1128
+ onTimeUpdate: (e)=>{
1129
+ if (!isPlaying) return;
1130
+ const audioElement = e.target;
1131
+ setCurrentTime(audioElement.currentTime);
1132
+ },
1133
+ onLoadedMetadata: handleLoadedMetadata,
1134
+ onEnded: ()=>{
1135
+ setIsPlaying(false);
1136
+ setCurrentTime(0);
1137
+ },
1138
+ onPlay: ()=>setIsPlaying(true),
1139
+ onPause: ()=>setIsPlaying(false),
1140
+ muted: isMuted,
1141
+ children: /*#__PURE__*/ (0, jsx_runtime.jsx)("track", {
1142
+ kind: 'captions'
1143
+ })
1144
+ })
1145
+ ]
1146
+ });
1147
+ };
1148
+ AudioPlayer.propTypes = {
1149
+ audioUrl: external_prop_types_default().string.isRequired
1150
+ };
982
1151
  const CodebitThemeContext = /*#__PURE__*/ (0, external_react_.createContext)(null);
983
- const CodebitThemeProvider = ({ children, storeThemeInLocalStorage = true, ...props })=>{
1152
+ const CodebitThemeProvider = ({ children, storeThemeInLocalStorage = true, containerId = 'root', forcedTheme = null, ...props })=>{
984
1153
  const hasLoaded = (0, external_react_.useRef)(false);
985
1154
  const [isDarkMode, setIsDarkMode] = (0, external_react_.useState)(()=>{
1155
+ if (forcedTheme) return 'dark' === forcedTheme;
986
1156
  try {
987
1157
  if (storeThemeInLocalStorage) {
988
1158
  const savedTheme = localStorage?.getItem('theme');
@@ -993,27 +1163,39 @@ var __webpack_exports__ = {};
993
1163
  hasLoaded.current = true;
994
1164
  }
995
1165
  });
1166
+ (0, external_react_.useEffect)(()=>{
1167
+ if (forcedTheme) {
1168
+ const mode = 'dark' === forcedTheme;
1169
+ setIsDarkMode(mode);
1170
+ }
1171
+ }, [
1172
+ forcedTheme
1173
+ ]);
996
1174
  const toggleTheme = ()=>{
997
1175
  setIsDarkMode((prev)=>!prev);
998
1176
  };
999
1177
  (0, external_react_.useEffect)(()=>{
1000
- const rootElement = document.getElementById('root');
1178
+ const target = document.getElementById(containerId);
1179
+ if (!target) return;
1001
1180
  if (isDarkMode) {
1002
1181
  document.documentElement.classList.add('dark-theme');
1003
- rootElement.classList.add('dark-theme');
1182
+ target.classList.add('dark-theme');
1004
1183
  } else {
1005
1184
  document.documentElement.classList.remove('dark-theme');
1006
- rootElement.classList.remove('dark-theme');
1185
+ target.classList.remove('dark-theme');
1007
1186
  }
1008
1187
  document.documentElement.style.setProperty('--color-primary', isDarkMode ? '#589C75' : '#29D266');
1009
1188
  }, [
1010
- isDarkMode
1189
+ isDarkMode,
1190
+ containerId
1011
1191
  ]);
1012
1192
  (0, external_react_.useEffect)(()=>{
1013
1193
  if (hasLoaded.current && storeThemeInLocalStorage) localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
1194
+ if (hasLoaded.current && storeThemeInLocalStorage && !forcedTheme) localStorage.setItem('theme', isDarkMode ? 'dark' : 'light');
1014
1195
  }, [
1015
1196
  isDarkMode,
1016
- storeThemeInLocalStorage
1197
+ storeThemeInLocalStorage,
1198
+ forcedTheme
1017
1199
  ]);
1018
1200
  const themeContextValue = (0, external_react_.useMemo)(()=>({
1019
1201
  isDarkMode,
@@ -1056,7 +1238,9 @@ var __webpack_exports__ = {};
1056
1238
  },
1057
1239
  ...props,
1058
1240
  children: [
1059
- /*#__PURE__*/ (0, jsx_runtime.jsx)(CssTokenBridge, {}),
1241
+ /*#__PURE__*/ (0, jsx_runtime.jsx)(CssTokenBridge, {
1242
+ containerId: containerId
1243
+ }),
1060
1244
  children
1061
1245
  ]
1062
1246
  })
@@ -1064,7 +1248,13 @@ var __webpack_exports__ = {};
1064
1248
  };
1065
1249
  CodebitThemeProvider.propTypes = {
1066
1250
  children: external_prop_types_default().node.isRequired,
1067
- storeThemeInLocalStorage: external_prop_types_default().bool
1251
+ storeThemeInLocalStorage: external_prop_types_default().bool,
1252
+ containerId: external_prop_types_default().string,
1253
+ forcedTheme: external_prop_types_default().oneOf([
1254
+ 'dark',
1255
+ 'light',
1256
+ null
1257
+ ])
1068
1258
  };
1069
1259
  const LoggedMainContainer_module = {
1070
1260
  layout: "layout-mL5o6I",
@@ -2110,6 +2300,7 @@ var __webpack_exports__ = {};
2110
2300
  OllamaOutlinedIcon.propTypes = external_prop_types_default().object;
2111
2301
  })();
2112
2302
  exports.AdminUserOutlinedIcon = __webpack_exports__.AdminUserOutlinedIcon;
2303
+ exports.AudioPlayer = __webpack_exports__.AudioPlayer;
2113
2304
  exports.ChangePassword = __webpack_exports__.ChangePassword;
2114
2305
  exports.CodebitConfigContext = __webpack_exports__.CodebitConfigContext;
2115
2306
  exports.CodebitConfigProvider = __webpack_exports__.CodebitConfigProvider;
@@ -2135,6 +2326,7 @@ exports.useErrorMessage = __webpack_exports__.useErrorMessage;
2135
2326
  exports.useErrorModal = __webpack_exports__.useErrorModal;
2136
2327
  for(var __rspack_i in __webpack_exports__)if (-1 === [
2137
2328
  "AdminUserOutlinedIcon",
2329
+ "AudioPlayer",
2138
2330
  "ChangePassword",
2139
2331
  "CodebitConfigContext",
2140
2332
  "CodebitConfigProvider",
package/dist/index.css CHANGED
@@ -73,6 +73,24 @@ html.dark-theme {
73
73
  height: 100vh;
74
74
  }
75
75
 
76
+ .audioPlayer-a4xARM {
77
+ padding: var(--antd-padding);
78
+ gap: var(--antd-padding-sm);
79
+ border-radius: 8px;
80
+ flex-direction: column;
81
+ display: flex;
82
+ }
83
+
84
+ .audioPlayer-a4xARM .durationTimeContainer-kmkK6M {
85
+ justify-content: center;
86
+ width: 100%;
87
+ }
88
+
89
+ .audioPlayer-a4xARM .slider-bdta4v {
90
+ flex: 1;
91
+ min-width: 100px;
92
+ }
93
+
76
94
  .layout-mL5o6I {
77
95
  height: 100vh;
78
96
  position: fixed;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebit-programando-solucoes/codebit-web-antd",
3
- "version": "1.1.32",
3
+ "version": "1.1.34",
4
4
  "main": "./dist/index.cjs",
5
5
  "type": "module",
6
6
  "types": "./src/index.d.ts",
@@ -20,18 +20,19 @@
20
20
  "./dist/*.css": "./dist/*.css"
21
21
  },
22
22
  "dependencies": {
23
+ "date-fns": "^4.1.0",
23
24
  "i18next": "^25.6.2",
24
25
  "react-i18next": "^16.3.5"
25
26
  },
26
27
  "peerDependencies": {
28
+ "@ant-design/icons": ">=6.1.0",
27
29
  "@codebit-programando-solucoes/codebit-web": ">=1.1.6",
30
+ "@sentry/react": ">=10.26.0",
31
+ "antd": ">=5.29.3",
32
+ "prop-types": ">=15.8.1",
28
33
  "react": ">=19.2.0",
29
34
  "react-dom": ">=19.2.0",
30
35
  "react-router": ">=7.12.0",
31
- "prop-types": ">=15.8.1",
32
- "antd": ">=5.29.3",
33
- "@ant-design/icons": ">=6.1.0",
34
- "@sentry/react": ">=10.26.0",
35
36
  "sass": ">=1.94.0"
36
37
  },
37
38
  "devDependencies": {