@irontec/ivoz-ui 1.7.18 → 1.8.0

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.
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { jsx as _jsx } from "react/jsx-runtime";
11
11
  import { useStoreActions } from 'store';
12
12
  import { saveAs } from 'file-saver';
13
+ import { parseContentDispositionFilename } from '../../helpers';
13
14
  import { Tooltip } from '@mui/material';
14
15
  import DownloadIcon from '@mui/icons-material/Download';
15
16
  import { StyledPdfButton } from './DownloadFile.styles';
@@ -23,9 +24,8 @@ export default function DownloadFile(props) {
23
24
  path: `${path}/${row.id}/${fileType}`,
24
25
  params: {},
25
26
  successCallback: (data, headers) => __awaiter(this, void 0, void 0, function* () {
26
- var _a, _b;
27
- const fileName = (_b = (_a = headers['content-disposition']) === null || _a === void 0 ? void 0 : _a.split('filename=')) === null || _b === void 0 ? void 0 : _b.pop();
28
- saveAs(data, fileName || 'download');
27
+ const fileName = parseContentDispositionFilename(headers['content-disposition'] || '');
28
+ saveAs(data, fileName);
29
29
  }),
30
30
  });
31
31
  };
@@ -10,8 +10,8 @@ export declare const StyledDialogContentText: import("@emotion/styled").StyledCo
10
10
  noWrap?: boolean | undefined;
11
11
  paragraph?: boolean | undefined;
12
12
  sx?: import("@mui/material").SxProps<import("@mui/material").Theme> | undefined;
13
- variant?: "button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "overline" | "subtitle1" | "subtitle2" | "body1" | "body2" | undefined;
14
- variantMapping?: Partial<Record<"button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "overline" | "subtitle1" | "subtitle2" | "body1" | "body2", string>> | undefined;
13
+ variant?: "button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "subtitle1" | "subtitle2" | "body1" | "body2" | "overline" | undefined;
14
+ variantMapping?: Partial<Record<"button" | "caption" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "inherit" | "subtitle1" | "subtitle2" | "body1" | "body2" | "overline", string>> | undefined;
15
15
  }, "classes"> & import("@mui/material/OverridableComponent").CommonProps & Omit<Pick<import("react").DetailedHTMLProps<import("react").HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, "key" | keyof import("react").HTMLAttributes<HTMLSpanElement>> & {
16
16
  ref?: ((instance: HTMLSpanElement | null) => void) | import("react").RefObject<HTMLSpanElement> | null | undefined;
17
- }, "children" | keyof import("@mui/material/OverridableComponent").CommonProps | "sx" | "variant" | "align" | ("color" | "p" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxShadow" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "fontWeight" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "zIndex" | "border" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "noWrap" | "gutterBottom" | "paragraph" | "variantMapping"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
17
+ }, "children" | keyof import("@mui/material/OverridableComponent").CommonProps | "sx" | "variant" | "align" | ("color" | "p" | "alignContent" | "alignItems" | "alignSelf" | "bottom" | "boxShadow" | "boxSizing" | "columnGap" | "display" | "flexBasis" | "flexDirection" | "flexGrow" | "flexShrink" | "flexWrap" | "fontFamily" | "fontSize" | "fontStyle" | "fontWeight" | "gridAutoColumns" | "gridAutoFlow" | "gridAutoRows" | "gridTemplateAreas" | "gridTemplateColumns" | "gridTemplateRows" | "height" | "justifyContent" | "justifyItems" | "justifySelf" | "left" | "letterSpacing" | "lineHeight" | "marginBottom" | "marginLeft" | "marginRight" | "marginTop" | "maxHeight" | "maxWidth" | "minHeight" | "minWidth" | "order" | "paddingBottom" | "paddingLeft" | "paddingRight" | "paddingTop" | "position" | "right" | "rowGap" | "textAlign" | "textOverflow" | "textTransform" | "top" | "visibility" | "whiteSpace" | "width" | "zIndex" | "border" | "borderBottom" | "borderColor" | "borderLeft" | "borderRadius" | "borderRight" | "borderTop" | "flex" | "gap" | "gridArea" | "gridColumn" | "gridRow" | "margin" | "overflow" | "padding" | "bgcolor" | "m" | "mt" | "mr" | "mb" | "ml" | "mx" | "marginX" | "my" | "marginY" | "pt" | "pr" | "pb" | "pl" | "px" | "paddingX" | "py" | "paddingY" | "typography" | "displayPrint") | "gutterBottom" | "noWrap" | "paragraph" | "variantMapping"> & import("@mui/system").MUIStyledCommonProps<import("@mui/material").Theme>, {}, {}>;
@@ -1,2 +1,3 @@
1
1
  export * from './fetchAllPages';
2
2
  export * from './fetchFilteredPage';
3
+ export * from './parseContentDispositionFilename';
package/helpers/index.js CHANGED
@@ -1,2 +1,3 @@
1
1
  export * from './fetchAllPages';
2
2
  export * from './fetchFilteredPage';
3
+ export * from './parseContentDispositionFilename';
@@ -0,0 +1 @@
1
+ export declare function parseContentDispositionFilename(contentDisposition: string): string;
@@ -0,0 +1,12 @@
1
+ export function parseContentDispositionFilename(contentDisposition) {
2
+ var _a;
3
+ const filenameStar = contentDisposition.match(/filename\*\s*=\s*([^']*)'([^']*)'((?:%[0-9A-Fa-f]{2}|[!#$&+\-.^_`|~\w])+)/i);
4
+ if (filenameStar) {
5
+ return decodeURIComponent(filenameStar[3]);
6
+ }
7
+ const filename = contentDisposition.match(/filename\s*=\s*(?:"([^"]*)"|([^;\s]+))/i);
8
+ if (filename) {
9
+ return (_a = filename[1]) !== null && _a !== void 0 ? _a : filename[2];
10
+ }
11
+ return 'download';
12
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@irontec/ivoz-ui",
3
- "version": "1.7.18",
3
+ "version": "1.8.0",
4
4
  "description": "UI library used in ivozprovider",
5
5
  "license": "GPL-3.0",
6
6
  "main": "index.js",
@@ -57,7 +57,6 @@
57
57
  "i18next-browser-languagedetector": "^7.2.0",
58
58
  "i18next-sprintf-postprocessor": "^0.2.2",
59
59
  "query-string": "^7.0.0",
60
- "react-audio-player": "^0.17.0",
61
60
  "react-color": "^2.19.3",
62
61
  "react-i18next": "^13.0.0",
63
62
  "sync-request": "^6.1.0",
@@ -9,6 +9,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
9
9
  };
10
10
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
11
  import { saveAs } from 'file-saver';
12
+ import { parseContentDispositionFilename } from '../../../../helpers';
12
13
  import { useCallback, useState, } from 'react';
13
14
  import { useStoreActions } from '../../../../store';
14
15
  import { StyledFieldsetRoot } from '../CustomComponentWrapper.styles';
@@ -52,9 +53,8 @@ const FileUploader = (props) => {
52
53
  path: downloadPath,
53
54
  params: {},
54
55
  successCallback: (data, headers) => __awaiter(void 0, void 0, void 0, function* () {
55
- var _a, _b;
56
- const fileName = (_b = (_a = headers['content-disposition']) === null || _a === void 0 ? void 0 : _a.split('filename=')) === null || _b === void 0 ? void 0 : _b.pop();
57
- saveAs(data, fileName || 'download');
56
+ const fileName = parseContentDispositionFilename(headers['content-disposition'] || '');
57
+ saveAs(data, fileName);
58
58
  }),
59
59
  });
60
60
  }
@@ -11,14 +11,10 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
11
11
  import DownloadRoundedIcon from '@mui/icons-material/DownloadRounded';
12
12
  import UploadFileRoundedIcon from '@mui/icons-material/UploadFileRounded';
13
13
  import { useEffect, useState } from 'react';
14
- import ReactAudioPlayerSrc from 'react-audio-player';
15
14
  import { useStoreActions } from 'store';
16
15
  import { StyledFileNameContainer, StyledFileUploaderContainer, StyledUploadButtonLabel, } from '../FileUploader.styles';
17
16
  import { Box } from '@mui/material';
18
- // see https://github.com/justinmc/react-audio-player/issues/164
19
- const ReactAudioPlayer = process.env.NODE_ENV === 'production'
20
- ? ReactAudioPlayerSrc.default
21
- : ReactAudioPlayerSrc;
17
+ import AudioPlayer from './AudioPlayer';
22
18
  export const AudioFileUploader = (props) => {
23
19
  var _a, _b;
24
20
  const { _columnName, accept, values, disabled, downloadPath, handleDownload, changeHandler, onBlur, } = props;
@@ -63,5 +59,5 @@ export const AudioFileUploader = (props) => {
63
59
  display: 'flex',
64
60
  justifyContent: 'space-between',
65
61
  marginBottom: 'var(--spacing-sm)',
66
- } }, { children: [fileName && (_jsxs(StyledFileNameContainer, Object.assign({ className: disabled ? 'disabled' : '' }, { children: [values.id && _jsx(DownloadRoundedIcon, { onClick: handleDownload }), fileName, " (", fileSizeMb, "MB)"] }))), !disabled && (_jsx(StyledUploadButtonLabel, Object.assign({ htmlFor: id, className: 'upload-icon' }, { children: _jsx(UploadFileRoundedIcon, {}) })))] })), _jsx(ReactAudioPlayer, { src: audioSrc, controls: true })] }), _jsx("div", Object.assign({ className: 'uploader-backdrop' }, { children: "Audio" }))] }));
62
+ } }, { children: [fileName && (_jsxs(StyledFileNameContainer, Object.assign({ className: disabled ? 'disabled' : '' }, { children: [values.id && _jsx(DownloadRoundedIcon, { onClick: handleDownload }), fileName, " (", fileSizeMb, "MB)"] }))), !disabled && (_jsx(StyledUploadButtonLabel, Object.assign({ htmlFor: id, className: 'upload-icon' }, { children: _jsx(UploadFileRoundedIcon, {}) })))] })), _jsx(AudioPlayer, { src: audioSrc })] }), _jsx("div", Object.assign({ className: 'uploader-backdrop' }, { children: "Audio" }))] }));
67
63
  };
@@ -0,0 +1,6 @@
1
+ /// <reference types="react" />
2
+ interface AudioPlayerProps {
3
+ src: string;
4
+ }
5
+ export default function AudioPlayer({ src }: AudioPlayerProps): JSX.Element;
6
+ export {};
@@ -0,0 +1,89 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import PauseRoundedIcon from '@mui/icons-material/PauseRounded';
3
+ import PlayArrowRoundedIcon from '@mui/icons-material/PlayArrowRounded';
4
+ import VolumeUpRoundedIcon from '@mui/icons-material/VolumeUpRounded';
5
+ import VolumeOffRoundedIcon from '@mui/icons-material/VolumeOffRounded';
6
+ import { Box, IconButton, Slider, Typography } from '@mui/material';
7
+ import { useRef, useState, useEffect, useCallback } from 'react';
8
+ function formatTime(seconds) {
9
+ const m = Math.floor(seconds / 60);
10
+ const s = Math.floor(seconds % 60);
11
+ return `${m}:${s.toString().padStart(2, '0')}`;
12
+ }
13
+ export default function AudioPlayer({ src }) {
14
+ const audioRef = useRef(null);
15
+ const [playing, setPlaying] = useState(false);
16
+ const [currentTime, setCurrentTime] = useState(0);
17
+ const [duration, setDuration] = useState(0);
18
+ const [volume, setVolume] = useState(1);
19
+ const [muted, setMuted] = useState(false);
20
+ const [showVolume, setShowVolume] = useState(false);
21
+ const toggle = useCallback(() => {
22
+ const audio = audioRef.current;
23
+ if (!audio)
24
+ return;
25
+ if (playing) {
26
+ audio.pause();
27
+ }
28
+ else {
29
+ audio.play();
30
+ }
31
+ setPlaying(!playing);
32
+ }, [playing]);
33
+ useEffect(() => {
34
+ const audio = audioRef.current;
35
+ if (!audio)
36
+ return;
37
+ const onTime = () => setCurrentTime(audio.currentTime);
38
+ const onMeta = () => setDuration(audio.duration);
39
+ const onEnded = () => setPlaying(false);
40
+ audio.addEventListener('timeupdate', onTime);
41
+ audio.addEventListener('loadedmetadata', onMeta);
42
+ audio.addEventListener('ended', onEnded);
43
+ return () => {
44
+ audio.removeEventListener('timeupdate', onTime);
45
+ audio.removeEventListener('loadedmetadata', onMeta);
46
+ audio.removeEventListener('ended', onEnded);
47
+ };
48
+ }, []);
49
+ const seek = (_, value) => {
50
+ const audio = audioRef.current;
51
+ if (!audio)
52
+ return;
53
+ const t = value;
54
+ audio.currentTime = t;
55
+ setCurrentTime(t);
56
+ };
57
+ return (_jsxs(Box, Object.assign({ sx: {
58
+ display: 'flex',
59
+ alignItems: 'center',
60
+ gap: 1,
61
+ bgcolor: 'grey.100',
62
+ borderRadius: '24px',
63
+ px: 1,
64
+ py: 0.5,
65
+ } }, { children: [_jsx("audio", { ref: audioRef, src: src, preload: 'metadata' }), _jsx(IconButton, Object.assign({ size: 'small', onClick: toggle }, { children: playing ? (_jsx(PauseRoundedIcon, { fontSize: 'small' })) : (_jsx(PlayArrowRoundedIcon, { fontSize: 'small' })) })), _jsxs(Typography, Object.assign({ variant: 'caption', sx: { whiteSpace: 'nowrap', minWidth: 70 } }, { children: [formatTime(currentTime), " / ", formatTime(duration || 0)] })), _jsx(Slider, { size: 'small', min: 0, max: duration || 1, value: currentTime, onChange: seek, sx: { mx: 1, flex: 1, minWidth: 60 } }), _jsxs(Box, Object.assign({ sx: { position: 'relative', display: 'flex', alignItems: 'center' }, onMouseEnter: () => setShowVolume(true), onMouseLeave: () => setShowVolume(false) }, { children: [_jsx(IconButton, Object.assign({ size: 'small', onClick: () => {
66
+ const next = !muted;
67
+ if (audioRef.current) {
68
+ audioRef.current.muted = next;
69
+ }
70
+ setMuted(next);
71
+ } }, { children: muted || volume === 0 ? (_jsx(VolumeOffRoundedIcon, { fontSize: 'small' })) : (_jsx(VolumeUpRoundedIcon, { fontSize: 'small' })) })), showVolume && (_jsx(Box, Object.assign({ sx: {
72
+ position: 'absolute',
73
+ left: '100%',
74
+ display: 'flex',
75
+ alignItems: 'center',
76
+ bgcolor: 'grey.100',
77
+ borderRadius: '12px',
78
+ px: 1,
79
+ width: 80,
80
+ } }, { children: _jsx(Slider, { size: 'small', min: 0, max: 1, step: 0.01, value: muted ? 0 : volume, onChange: (_, v) => {
81
+ const val = v;
82
+ setVolume(val);
83
+ setMuted(val === 0);
84
+ if (audioRef.current) {
85
+ audioRef.current.volume = val;
86
+ audioRef.current.muted = val === 0;
87
+ }
88
+ } }) })))] }))] })));
89
+ }