siam-ui-utils 2.2.19 → 2.2.21

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/index.d.ts CHANGED
@@ -9,6 +9,9 @@ declare module 'siam-ui-utils' {
9
9
  //CUSTOMSELECTINPUT
10
10
  export function CustomSelectInput(props);
11
11
 
12
+ //CUSTOMSELECT
13
+ export function CustomSelect(props);
14
+
12
15
  //CUSTOMINPUTCHECKBOX
13
16
  export function CustomInputCheckbox(props);
14
17
 
@@ -88,4 +91,7 @@ declare module 'siam-ui-utils' {
88
91
 
89
92
  //VIEW LAYOUT
90
93
  export function ViewLayout(props);
94
+
95
+ //TIMER
96
+ export function Timer(props);
91
97
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siam-ui-utils",
3
- "version": "2.2.19",
3
+ "version": "2.2.21",
4
4
  "keywords": [
5
5
  "ampf-react",
6
6
  "ampf-utils",
@@ -35,6 +35,7 @@
35
35
  "react-router-dom": "^6.26.2",
36
36
  "react-select": "^5.8.0",
37
37
  "reactstrap": "^9.2.2",
38
+ "react-tagsinput": "^3.20.3",
38
39
  "siam-utils": "^1.1.4",
39
40
  "source-map-loader": "^5.0.0",
40
41
  "styled-components": "^6.1.12",
package/src/App.jsx CHANGED
@@ -5,30 +5,37 @@ import {
5
5
  AccordionHeader,
6
6
  AccordionItem,
7
7
  } from 'reactstrap';
8
- import { TomarFoto, DropzoneUploader, DropzoneUploaderDniDigital } from './';
9
- import { CustomInputRadio, CustomInputCheckbox } from './custom-input';
10
- import './index.css';
8
+ import {
9
+ CopyLinkView,
10
+ CustomInputsView,
11
+ CustomSelectView,
12
+ DropzoneUploaderDniDigitalView,
13
+ DropzoneUploaderFirmaDigitalView,
14
+ DropzoneUploaderView,
15
+ TimerView,
16
+ VideoCallView,
17
+ ViewLayoutView,
18
+ } from './test-resources';
11
19
  import './App.css';
12
20
  import './assets/css/vendor/bootstrap.min.css';
13
- import { WhereByRoom } from './where-by-room';
14
- import { ViewLayout } from './view-layout';
15
- import { CopyLink } from './copy-link';
21
+ import './index.css';
16
22
 
17
- const slots = [
23
+ const views = [
24
+ { title: 'CopyLink', component: <CopyLinkView /> },
25
+ { title: 'CustomInputs', component: <CustomInputsView /> },
26
+ { title: 'CustomSelect', component: <CustomSelectView /> },
27
+ {
28
+ title: 'DropzoneDniDigital',
29
+ component: <DropzoneUploaderDniDigitalView />,
30
+ },
18
31
  {
19
- slot: 1,
20
- x: 3,
21
- y: 3,
22
- w: 2,
23
- h: 2,
24
- legend: 'Prueba',
25
- direction: 'column',
26
- contentSize: 'medium',
27
- align: 'stretch',
28
- justify: 'flex-start',
29
- component: null,
30
- showBorder: true,
32
+ title: 'DropZoneFirmaDigital',
33
+ component: <DropzoneUploaderFirmaDigitalView />,
31
34
  },
35
+ { title: 'DropzoneUploader', component: <DropzoneUploaderView /> },
36
+ { title: 'Timer', component: <TimerView /> },
37
+ { title: 'VideoCall', component: <VideoCallView /> },
38
+ { title: 'ViewLayoutGenerico', component: <ViewLayoutView /> },
32
39
  ];
33
40
 
34
41
  const App = () => {
@@ -41,108 +48,18 @@ const App = () => {
41
48
  }
42
49
  };
43
50
 
44
- const handleChecked = (item, isSelected) => {
45
- console.log('Item checked:', item, 'Selected:', isSelected);
46
- };
47
-
48
- const handleChangeRadio = (ID) => {
49
- console.log('ID :', ID);
50
- };
51
-
52
51
  return (
53
- <div>
54
- <Accordion open={open} toggle={toggle}>
55
- <AccordionItem>
56
- <AccordionHeader targetId="1">Tomar Foto</AccordionHeader>
57
- <AccordionBody accordionId="1">
58
- <TomarFoto isMobile={true} />
59
- <DropzoneUploader
60
- totalFiles={4}
61
- onChangeFiles={() => alert('onChange')}
62
- maxFiles={3}
63
- nameFileLabel="file"
64
- />
65
- </AccordionBody>
66
- </AccordionItem>
67
- <AccordionItem>
68
- <AccordionHeader targetId="2">
69
- DropzoneUploader Firma Digital
70
- </AccordionHeader>
71
- <AccordionBody accordionId="2">
72
- <DropzoneUploader
73
- totalFiles={0}
74
- onChangeFiles={() => {
75
- console.log('onChange');
76
- }}
77
- maxFiles={7}
78
- nameFileLabel="Subir archivos"
79
- capture="environment"
80
- onFilesSelectedSelfie
81
- />
82
- </AccordionBody>
83
- </AccordionItem>
84
- <AccordionItem>
85
- <AccordionHeader targetId="3">
86
- DropzoneUploader DNI Digital
87
- </AccordionHeader>
88
- <AccordionBody accordionId="3">
89
- <DropzoneUploaderDniDigital
90
- totalFiles={0}
91
- maxFiles={2}
92
- onChangeFiles={() => {
93
- console.log('onChange');
94
- }}
95
- classNames="custom-dropzone-uploader-dni-digital"
96
- />
97
- </AccordionBody>
98
- </AccordionItem>
99
- <AccordionItem>
100
- <AccordionHeader targetId="4">Video Call Room</AccordionHeader>
101
- <AccordionBody accordionId="4">
102
- <WhereByRoom
103
- src="https://whereby.com/test-ampf-room"
104
- title="Videollamada de ejemplo"
105
- />
106
- </AccordionBody>
107
- </AccordionItem>
108
- <AccordionItem>
109
- <AccordionHeader targetId="5">Custom Inputs</AccordionHeader>
110
- <AccordionBody accordionId="5">
111
- <CustomInputCheckbox
112
- className="itemCheck m-0"
113
- id={1}
114
- onChange={(e) => handleChecked(1, e.target.checked)}
115
- label={<span className="custom-checkbox">Checkbox 1</span>}
116
- />
117
- <CustomInputRadio
118
- name="radioTest"
119
- label="1"
120
- id="1"
121
- defaultChecked={true}
122
- onChange={handleChangeRadio}
123
- />
124
- <CustomInputRadio
125
- name="radioTest"
126
- label="2"
127
- id="2"
128
- onChange={handleChangeRadio}
129
- />
130
- </AccordionBody>
131
- </AccordionItem>
132
- <AccordionItem>
133
- <AccordionHeader targetId="6">Copy-Link</AccordionHeader>
134
- <AccordionBody accordionId="6">
135
- <CopyLink link="https://linkdepruebaparaelcopylink.com" />
136
- </AccordionBody>
137
- </AccordionItem>
138
- <AccordionItem>
139
- <AccordionHeader targetId="7">Reusable ViewLayout</AccordionHeader>
140
- <AccordionBody accordionId="7">
141
- <ViewLayout slots={slots} />
142
- </AccordionBody>
143
- </AccordionItem>
144
- </Accordion>
145
- </div>
52
+ <Accordion open={open} toggle={toggle}>
53
+ {views.map((view, index) => {
54
+ const { title, component: vista } = view;
55
+ return (
56
+ <AccordionItem key={index}>
57
+ <AccordionHeader targetId={`${index + 1}`}>{title}</AccordionHeader>
58
+ <AccordionBody accordionId={`${index + 1}`}>{vista}</AccordionBody>
59
+ </AccordionItem>
60
+ );
61
+ })}
62
+ </Accordion>
146
63
  );
147
64
  };
148
65
 
@@ -1,6 +1,5 @@
1
1
  import { getDroppedOrSelectedFiles } from 'html5-file-selector';
2
2
  import { useEffect, useState } from 'react';
3
- import '../dropzone/styles.css';
4
3
  import Dropzone from '../dropzone/Dropzone';
5
4
  import '../dropzone/styles.css';
6
5
  import { IconButtonSvg, pdfImage } from '../iconos';
@@ -88,7 +87,7 @@ export const DropzoneUploader = ({
88
87
  <p>{(meta.size / 1024).toFixed(2)} .Kb</p>
89
88
  <button
90
89
  onClick={remove}
91
- className="dropzone-upload-delete-btn simple-icon-trash"
90
+ className="dropzone-upload-delete-btn icon-trash"
92
91
  ></button>
93
92
  </div>
94
93
  );
package/src/index.js CHANGED
@@ -1,11 +1,13 @@
1
- export * from './archivos-adjuntos';
2
- export * from './archivos-adjuntos/dropzone-uploader-dni-digital';
1
+ export * from './dropzone-uploader';
2
+ export * from './dropzone-uploader/dropzone-uploader-dni-digital';
3
3
  export * from './bridges';
4
4
  export * from './CustomBootstrap';
5
5
  export * from './custom-input';
6
+ export * from './select';
6
7
  export * from './CustomSelectInput';
7
8
  export * from './tomar-foto';
8
9
  export * as IntlMessages from './IntlMessages';
9
10
  export * from './where-by-room';
10
11
  export * from './copy-link';
11
12
  export * from './view-layout';
13
+ export * from './timer';
@@ -0,0 +1,4 @@
1
+ export const LABELS = {
2
+ SIN_DATOS: "SIN DATOS",
3
+ SELECCIONE: "SELECCIONE...",
4
+ };
@@ -0,0 +1,147 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import Select from 'react-select';
3
+ import { Label } from 'reactstrap';
4
+ import CustomSelectInput from '../CustomSelectInput';
5
+ import { LABELS } from './constants';
6
+ import 'react-tagsinput/react-tagsinput.css';
7
+
8
+ interface ICustomStylesOption {
9
+ fieldMatch: string;
10
+ valueMatch: any;
11
+ }
12
+ interface IOption {
13
+ label: string;
14
+ value: any;
15
+ fields?: any;
16
+ }
17
+ interface IOption {
18
+ label: string;
19
+ value: any;
20
+ fields?: any;
21
+ }
22
+ interface Props {
23
+ label: string;
24
+ tabIndex: number;
25
+ options: [IOption];
26
+ onChange: any;
27
+ selectedValue: any;
28
+ firstElement?: IOption; // no ingresar null como VALUE del elemento, setear '' ya que lo toma como que no se selecciono nada
29
+ newItem?: IOption;
30
+ placeholder?: string;
31
+ disabled?: boolean;
32
+ customStylesOption?: ICustomStylesOption;
33
+ }
34
+
35
+ const {SIN_DATOS, SELECCIONE}=LABELS
36
+
37
+ const CustomSelect: React.FC<Props> = (props: Props) => {
38
+ const [firstElement] = useState(props.firstElement);
39
+ const [newItem] = useState(props.newItem);
40
+ const [selectedIoption, setIoption] = useState({});
41
+ const [customStylesOption] = useState(props.customStylesOption);
42
+ const [customStyles, setCustomStyles] = useState({});
43
+
44
+ // agrega items
45
+ useEffect(() => {
46
+ if (newItem) {
47
+ props.options.push(newItem);
48
+ }
49
+ }, [newItem, props.options]);
50
+
51
+ // Seleccion del 1er item.
52
+ useEffect(() => {
53
+ const { options = [] } = props;
54
+ if (firstElement && Number(options?.length) > 1) {
55
+ const propIOption = options.filter((item) => item === firstElement);
56
+
57
+ if (propIOption?.length === 0) {
58
+ props.options.unshift(firstElement);
59
+ }
60
+ }
61
+ // eslint-disable-next-line react-hooks/exhaustive-deps
62
+ }, [firstElement, props.options]);
63
+
64
+ // selecciona un valor seteado dentro de la coleccion
65
+ useEffect(() => {
66
+ const { selectedValue } = props;
67
+ const errorProp = { value: null };
68
+
69
+ if (
70
+ selectedValue ||
71
+ (firstElement && firstElement.value === selectedValue)
72
+ ) {
73
+ const propIOption = props.options.filter(({ value }) => {
74
+ return JSON.stringify(value) === JSON.stringify(selectedValue);
75
+ });
76
+
77
+ if (propIOption[0]) {
78
+ setIoption(propIOption[0]);
79
+ if (!Object.getOwnPropertyDescriptor(selectedIoption, 'label')) {
80
+ props.onChange(propIOption[0]);
81
+ }
82
+ } else {
83
+ setIoption(errorProp);
84
+ props.onChange(errorProp);
85
+ }
86
+ } else if (props.options.length > 0) {
87
+ setIoption(errorProp);
88
+ props.onChange(errorProp);
89
+ }
90
+ // eslint-disable-next-line react-hooks/exhaustive-deps
91
+ }, [props.selectedValue, props.options, firstElement]);
92
+
93
+ useEffect(() => {
94
+ if (customStylesOption) {
95
+ const stylesOption = {
96
+ option: (base: any, { data }: any) => {
97
+ return {
98
+ ...base,
99
+ color:
100
+ data.fields &&
101
+ data.fields[customStylesOption.fieldMatch] ===
102
+ customStylesOption.valueMatch
103
+ ? 'blue !important'
104
+ : '',
105
+ fontWeight:
106
+ data.fields &&
107
+ data.fields[customStylesOption.fieldMatch] ===
108
+ customStylesOption.valueMatch
109
+ ? 'bold'
110
+ : '',
111
+ };
112
+ },
113
+ };
114
+ setCustomStyles(stylesOption);
115
+ }
116
+ }, [customStylesOption]);
117
+
118
+ return (
119
+ <>
120
+ {props.label && props.label !== '' && (
121
+ <Label className="mb-0">{props.label}:</Label>
122
+ )}
123
+ <Select
124
+ {...props}
125
+ components={{ Input: CustomSelectInput }}
126
+ className="react-select"
127
+ classNamePrefix="react-select"
128
+ name="form-field-name"
129
+ value={
130
+ Object.getOwnPropertyDescriptor(selectedIoption, 'label')
131
+ ? selectedIoption
132
+ : ''
133
+ }
134
+ onChange={props.onChange}
135
+ options={props.options}
136
+ placeholder={
137
+ Number(props.options.length) === 0
138
+ ? SIN_DATOS
139
+ : props.placeholder || SELECCIONE
140
+ }
141
+ isDisabled={props.disabled}
142
+ styles={customStyles}
143
+ />
144
+ </>
145
+ );
146
+ };
147
+ export default CustomSelect;
@@ -0,0 +1,145 @@
1
+ import { DropzoneUploader, DropzoneUploaderDniDigital, TomarFoto } from '.';
2
+ import { CopyLink } from './copy-link';
3
+ import { CustomInputCheckbox, CustomInputRadio } from './custom-input';
4
+ import CustomSelect from './select';
5
+ import { Timer } from './timer';
6
+ import { ViewLayout } from './view-layout';
7
+ import { WhereByRoom } from './where-by-room';
8
+ import './assets/css/vendor/bootstrap.min.css';
9
+ import './index.css';
10
+ import './App.css';
11
+ import { useState } from 'react';
12
+
13
+ const slots = [
14
+ {
15
+ slot: 1,
16
+ x: 3,
17
+ y: 3,
18
+ w: 2,
19
+ h: 2,
20
+ legend: 'Prueba',
21
+ direction: 'column',
22
+ contentSize: 'medium',
23
+ align: 'stretch',
24
+ justify: 'flex-start',
25
+ component: null,
26
+ showBorder: true,
27
+ },
28
+ ];
29
+
30
+ export const DropzoneUploaderView = () => (
31
+ <>
32
+ <TomarFoto isMobile={true} />
33
+ <DropzoneUploader
34
+ totalFiles={4}
35
+ onChangeFiles={() => alert('onChange')}
36
+ maxFiles={3}
37
+ nameFileLabel="file"
38
+ />
39
+ </>
40
+ );
41
+
42
+ export const DropzoneUploaderFirmaDigitalView = () => (
43
+ <DropzoneUploader
44
+ totalFiles={0}
45
+ onChangeFiles={() => {
46
+ console.log('onChange');
47
+ }}
48
+ maxFiles={7}
49
+ nameFileLabel="Subir archivos"
50
+ capture="environment"
51
+ onFilesSelectedSelfie
52
+ />
53
+ );
54
+
55
+ export const DropzoneUploaderDniDigitalView = () => (
56
+ <DropzoneUploaderDniDigital
57
+ totalFiles={0}
58
+ onChangeFiles={() => {
59
+ console.log('onChange');
60
+ }}
61
+ maxFiles={7}
62
+ nameFileLabel="Subir archivos"
63
+ capture="environment"
64
+ onFilesSelectedSelfie
65
+ />
66
+ );
67
+
68
+ export const VideoCallView = () => (
69
+ <WhereByRoom
70
+ src="https://whereby.com/test-ampf-room"
71
+ title="Videollamada de ejemplo"
72
+ />
73
+ );
74
+
75
+ export const CustomInputsView = () => {
76
+ const handleChecked = (item, isSelected) => {
77
+ console.log('Item checked:', item, 'Selected:', isSelected);
78
+ };
79
+
80
+ const handleChangeRadio = (ID) => {
81
+ console.log('ID :', ID);
82
+ };
83
+ return (
84
+ <>
85
+ <CustomInputCheckbox
86
+ className="itemCheck m-0"
87
+ id={1}
88
+ onChange={(e) => handleChecked(1, e.target.checked)}
89
+ label={<span className="custom-checkbox">Checkbox 1</span>}
90
+ />
91
+ <CustomInputRadio
92
+ name="radioTest"
93
+ label="1"
94
+ id="1"
95
+ defaultChecked={true}
96
+ onChange={handleChangeRadio}
97
+ />
98
+ <CustomInputRadio
99
+ name="radioTest"
100
+ label="2"
101
+ id="2"
102
+ onChange={handleChangeRadio}
103
+ />
104
+ </>
105
+ );
106
+ };
107
+
108
+ export const CopyLinkView = () => (
109
+ <CopyLink link="https://linkdepruebaparaelcopylink.com" />
110
+ );
111
+
112
+ export const ViewLayoutView = () => <ViewLayout slots={slots} />;
113
+
114
+ export const TimerView = () => (
115
+ <Timer initialMinutes={2} active={true} style={{ color: 'green' }} />
116
+ );
117
+
118
+ export const CustomSelectView = () => {
119
+ const motivosBaja = [
120
+ {
121
+ label: 'MAL SERVICIO',
122
+ value: 'MSR',
123
+ },
124
+ {
125
+ label: 'AUMENTO DE CUOTA',
126
+ value: 'ADC',
127
+ },
128
+ ];
129
+ const [motivoBajaSelected, setMotivoBajaSelected] = useState({});
130
+
131
+ const handleMotivoSelected = (e) => {
132
+ setMotivoBajaSelected(e.value);
133
+ };
134
+
135
+ return (
136
+ <CustomSelect
137
+ tabIndex={0}
138
+ options={motivosBaja}
139
+ label="Seleccione una opción"
140
+ onChange={handleMotivoSelected}
141
+ placeholder="Seleccione..."
142
+ selectedValue={motivoBajaSelected}
143
+ />
144
+ );
145
+ };
@@ -0,0 +1,62 @@
1
+ import { useEffect, useState, useRef } from 'react';
2
+ import './styles.scss';
3
+
4
+ export const formatTiempo = (ms) => {
5
+ if (ms == null) return '--:--';
6
+ const absMs = Math.abs(ms);
7
+ const totalSec = Math.floor(absMs / 1000);
8
+ const min = Math.floor(totalSec / 60);
9
+ const sec = totalSec % 60;
10
+ const formatted = `${min.toString().padStart(2, '0')}:${sec
11
+ .toString()
12
+ .padStart(2, '0')}`;
13
+ return ms < 0 ? `-${formatted}` : formatted;
14
+ };
15
+
16
+ const getTimerColorClass = (ms, maxTime) => {
17
+ if (!maxTime) return '';
18
+ const percent = ms / maxTime;
19
+ if (percent > 0.33) return 'timer-green';
20
+ if (percent > 0.15) return 'timer-yellow';
21
+ if (percent > 0) return 'timer-red';
22
+ if (ms === 0) return 'timer-out';
23
+ if (ms < 0) return 'timer-over';
24
+ return '';
25
+ };
26
+
27
+ const Timer = ({
28
+ initialMinutes = 0,
29
+ icon = true,
30
+ className = '',
31
+ active = true,
32
+ style = {},
33
+ }) => {
34
+ const initialMs = initialMinutes * 60 * 1000;
35
+ const [ms, setMs] = useState(initialMs);
36
+ const intervalRef = useRef();
37
+
38
+ useEffect(() => {
39
+ if (!active) return;
40
+ intervalRef.current = setInterval(() => {
41
+ setMs((prev) => prev - 1000);
42
+ }, 1000);
43
+ return () => clearInterval(intervalRef.current);
44
+ }, [active]);
45
+
46
+ useEffect(() => {
47
+ setMs(initialMs);
48
+ }, [initialMs]);
49
+
50
+ const timerColorClass = getTimerColorClass(ms, initialMs);
51
+
52
+ return (
53
+ <span
54
+ className={`av-video-timer timer ${timerColorClass} ${className}`}
55
+ style={style}
56
+ >
57
+ {icon && <i className="icon-clock timer" />}
58
+ {formatTiempo(ms)}
59
+ </span>
60
+ );
61
+ };
62
+ export { Timer };
@@ -0,0 +1,54 @@
1
+ .av-video-timer {
2
+ color: inherit;
3
+ margin: 0 12px;
4
+ flex: 1;
5
+ text-align: center;
6
+ display: flex;
7
+ justify-content: center;
8
+ font-weight: bold;
9
+ align-items: center;
10
+ font-size: 1.3em;
11
+ width: 100%;
12
+ margin: 8px 0;
13
+ }
14
+ .timer {
15
+ font-size: clamp(5px, 2vw, 20px);
16
+ margin-right: 4px;
17
+ }
18
+ .timer-green {
19
+ color: #28a745;
20
+ }
21
+ .timer-yellow {
22
+ color: #ffc107;
23
+ }
24
+ .timer-red {
25
+ color: #bd0300;
26
+ }
27
+
28
+ @keyframes vibrate {
29
+ 0% {
30
+ transform: translateX(0);
31
+ }
32
+ 20% {
33
+ transform: translateX(-3px);
34
+ }
35
+ 40% {
36
+ transform: translateX(3px);
37
+ }
38
+ 60% {
39
+ transform: translateX(-3px);
40
+ }
41
+ 80% {
42
+ transform: translateX(3px);
43
+ }
44
+ 100% {
45
+ transform: translateX(0);
46
+ }
47
+ }
48
+ .timer-out {
49
+ color: #000000;
50
+ animation: vibrate 0.3s linear infinite;
51
+ }
52
+ .timer-over {
53
+ color: #c00805;
54
+ }