@rolster/react-components 19.8.21 → 19.9.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.
package/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2022 Rolster Technology
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2022 Rolster Technology
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -484,41 +484,110 @@ function RlsAmountComponent({ value, className, decimals, rlsTheme, symbol }) {
484
484
  }
485
485
  const RlsAmount = require$$0.memo(RlsAmountComponent);
486
486
 
487
- function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, resize, rows = 1, value }) {
487
+ const AREA_TEXT_MAX_ROWS = 8;
488
+ const AREA_TEXT_MIN_ROWS = 3;
489
+ function writeAreaValue(element, valueArea) {
490
+ const rawArea = element.value;
491
+ if (rawArea === valueArea) {
492
+ return;
493
+ }
494
+ const selection = element.selectionStart;
495
+ const offset = valueArea.length - rawArea.length;
496
+ const caret = Math.max(0, Math.min(selection + offset, valueArea.length));
497
+ element.value = valueArea;
498
+ element.setSelectionRange(caret, caret);
499
+ }
500
+ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier, maxLength, maxRows, minRows, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, resize = 'vertical', value }) {
488
501
  const valueInitial = String(formControl?.value ?? value ?? '');
502
+ const rowsMin = minRows ?? AREA_TEXT_MIN_ROWS;
503
+ const rowsMax = Math.max(maxRows ?? AREA_TEXT_MAX_ROWS, rowsMin);
489
504
  const [valueArea, setValueArea] = require$$0.useState(valueInitial);
490
505
  const [focused, setFocused] = require$$0.useState(false);
491
506
  const elementRef = require$$0.useRef(null);
492
507
  const areaRef = formControl?.elementRef ?? elementRef;
493
- const changeIsInternal = require$$0.useRef(false);
508
+ const composing = require$$0.useRef(false);
509
+ const valueSent = require$$0.useRef(formControl?.value);
510
+ const valueSource = require$$0.useRef(formControl ? formControl.value : value);
511
+ const heightIsManual = require$$0.useRef(false);
512
+ const heightApplied = require$$0.useRef(0);
494
513
  const refreshHeight = require$$0.useCallback(() => {
495
514
  const element = areaRef.current;
496
- if (element) {
497
- element.style.height = 'auto';
498
- element.style.height = `${element.scrollHeight}px`;
515
+ if (!element || heightIsManual.current) {
516
+ return;
499
517
  }
500
- }, [areaRef]);
518
+ element.style.height = 'auto';
519
+ const { lineHeight, paddingBottom, paddingTop } = getComputedStyle(element);
520
+ const heightLine = parseFloat(lineHeight);
521
+ const heightContent = element.scrollHeight;
522
+ if (!heightLine) {
523
+ element.style.height = `${heightContent}px`;
524
+ heightApplied.current = heightContent;
525
+ return;
526
+ }
527
+ const heightPadding = parseFloat(paddingTop) + parseFloat(paddingBottom);
528
+ const heightMin = heightLine * rowsMin + heightPadding;
529
+ const heightMax = heightLine * rowsMax + heightPadding;
530
+ const height = Math.min(Math.max(heightContent, heightMin), heightMax);
531
+ element.style.height = `${height}px`;
532
+ element.style.overflowY = heightContent > heightMax ? 'auto' : 'hidden';
533
+ heightApplied.current = height;
534
+ }, [areaRef, rowsMax, rowsMin]);
501
535
  require$$0.useEffect(() => {
502
- if (!changeIsInternal.current) {
503
- const nextValue = String(formControl?.value ?? value ?? '');
536
+ const source = formControl ? formControl.value : value;
537
+ const isEcho = Object.is(source, valueSent.current);
538
+ const isSame = Object.is(source, valueSource.current);
539
+ valueSource.current = source;
540
+ if (!isEcho && !isSame) {
541
+ const nextValue = String(source ?? '');
504
542
  if (valueArea !== nextValue) {
505
543
  setValueArea(nextValue);
506
544
  }
507
545
  }
508
- changeIsInternal.current = false;
509
546
  }, [formControl?.value, value, valueArea]);
510
547
  require$$0.useEffect(() => {
511
548
  refreshHeight();
512
549
  }, [refreshHeight, valueArea]);
513
- const onChangeArea = require$$0.useCallback((event) => {
514
- const nextValue = event.target.value;
515
- changeIsInternal.current = true;
550
+ require$$0.useEffect(() => {
551
+ const element = areaRef.current;
552
+ if (!element ||
553
+ resize === 'none' ||
554
+ typeof ResizeObserver === 'undefined') {
555
+ return;
556
+ }
557
+ const observer = new ResizeObserver(() => {
558
+ if (heightIsManual.current || !heightApplied.current) {
559
+ return;
560
+ }
561
+ if (Math.abs(element.offsetHeight - heightApplied.current) > 1) {
562
+ heightIsManual.current = true;
563
+ element.style.overflowY = 'auto';
564
+ }
565
+ });
566
+ observer.observe(element);
567
+ return () => observer.disconnect();
568
+ }, [areaRef, resize]);
569
+ const applyArea = require$$0.useCallback((element) => {
570
+ const rawArea = element.value;
571
+ const formatter = formControl?.formatter;
572
+ const nextValue = formatter && formControl?.formatOn !== 'blur' && !composing.current
573
+ ? (formatter(rawArea) ?? '')
574
+ : rawArea;
575
+ writeAreaValue(element, nextValue);
576
+ valueSent.current = nextValue;
516
577
  onValue?.(nextValue);
517
578
  setValueArea(nextValue);
518
579
  formControl?.setValue(nextValue);
519
- event.target.style.height = 'auto';
520
- event.target.style.height = `${event.target.scrollHeight}px`;
521
580
  }, [formControl, onValue]);
581
+ const onChangeArea = require$$0.useCallback((event) => {
582
+ applyArea(event.target);
583
+ }, [applyArea]);
584
+ const onCompositionStart = require$$0.useCallback(() => {
585
+ composing.current = true;
586
+ }, []);
587
+ const onCompositionEnd = require$$0.useCallback((event) => {
588
+ composing.current = false;
589
+ applyArea(event.currentTarget);
590
+ }, [applyArea]);
522
591
  const onKeyDownArea = require$$0.useCallback((event) => {
523
592
  onKeyDown?.(event);
524
593
  if (event.key === 'Enter') {
@@ -538,12 +607,14 @@ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier,
538
607
  setFocused(() => false);
539
608
  onBlur?.();
540
609
  }, [formControl, onBlur]);
610
+ const disabledArea = formControl?.disabled || disabled;
541
611
  const className = renderClassStatus('rls-area-text', {
542
- disabled: formControl?.disabled || disabled,
612
+ disabled: disabledArea,
543
613
  focused: formControl?.focused ?? focused,
544
- readonly: readOnly
614
+ readonly: readOnly,
615
+ resizable: resize !== 'none' && !disabledArea && !readOnly
545
616
  });
546
- return (jsxRuntimeExports.jsxs("div", { id: identifier, className: className, children: [jsxRuntimeExports.jsx("textarea", { ref: areaRef, className: "rls-area-text__component", autoComplete: autoComplete ?? 'off', placeholder: placeholder, disabled: formControl?.disabled || disabled, readOnly: readOnly, rows: rows, style: { resize }, onFocus: onFocusArea, onBlur: onBlurArea, onChange: onChangeArea, onKeyDown: onKeyDownArea, onKeyUp: onKeyUpArea, value: valueArea }), jsxRuntimeExports.jsx("span", { className: "rls-area-text__value", children: valueArea })] }));
617
+ return (jsxRuntimeExports.jsxs("div", { id: identifier, className: className, children: [jsxRuntimeExports.jsx("textarea", { ref: areaRef, className: "rls-area-text__component", autoComplete: autoComplete ?? 'off', placeholder: placeholder, disabled: disabledArea, readOnly: readOnly, maxLength: maxLength, rows: rowsMin, style: { resize }, onFocus: onFocusArea, onBlur: onBlurArea, onChange: onChangeArea, onCompositionStart: onCompositionStart, onCompositionEnd: onCompositionEnd, onKeyDown: onKeyDownArea, onKeyUp: onKeyUpArea, value: valueArea }), jsxRuntimeExports.jsx("span", { className: "rls-area-text__value", "aria-hidden": "true", children: valueArea })] }));
547
618
  }
548
619
  const RlsAreaText = require$$0.memo(RlsAreaTextComponent);
549
620
 
@@ -650,8 +721,11 @@ function RlsCheckBoxControlComponent({ formControl, disabled, identifier, rlsThe
650
721
  }
651
722
  const RlsCheckBoxControl = require$$0.memo(RlsCheckBoxControlComponent);
652
723
 
653
- function RlsSkeletonComponent({ rlsTheme }) {
654
- return jsxRuntimeExports.jsx("div", { className: "rls-skeleton", "rls-theme": rlsTheme });
724
+ function RlsSkeletonComponent({ animation, rlsTheme }) {
725
+ const className = renderClassStatus('rls-skeleton', {
726
+ animation: animation !== 'shimmer' && animation
727
+ });
728
+ return jsxRuntimeExports.jsx("div", { className: className, "rls-theme": rlsTheme });
655
729
  }
656
730
  const RlsSkeleton = require$$0.memo(RlsSkeletonComponent);
657
731
 
@@ -669,30 +743,82 @@ function RlsImageComponent({ src, rlsTheme }) {
669
743
  }
670
744
  const RlsImage = require$$0.memo(RlsImageComponent);
671
745
 
746
+ function valueToInput(value) {
747
+ return value ? String(value) : '';
748
+ }
749
+ function selectionStartOf(element) {
750
+ try {
751
+ // Lanza o retorna null en inputs sin selección (number, email, etc.)
752
+ return element.selectionStart;
753
+ }
754
+ catch {
755
+ return null;
756
+ }
757
+ }
758
+ /**
759
+ * Escribe el valor formateado directamente en el DOM y conserva la posición
760
+ * del cursor, corrigiéndola por la diferencia de longitud. Es necesario
761
+ * porque, cuando el formateador rechaza un carácter, el estado del control
762
+ * no cambia y React no vuelve a escribir el input.
763
+ */
764
+ function writeInputValue(element, valueInput) {
765
+ const rawInput = element.value;
766
+ if (rawInput === valueInput) {
767
+ return;
768
+ }
769
+ const selection = selectionStartOf(element);
770
+ element.value = valueInput;
771
+ if (selection !== null) {
772
+ const offset = valueInput.length - rawInput.length;
773
+ const caret = Math.max(0, Math.min(selection + offset, valueInput.length));
774
+ element.setSelectionRange(caret, caret);
775
+ }
776
+ }
672
777
  function RlsInputComponent({ children, decimals, disabled, formControl, identifier, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, type, value }) {
673
- const valueInitial = (formControl?.value ?? value) ? String(value) : '';
674
- const [valueInput, setValueInput] = require$$0.useState(valueInitial);
778
+ const [valueInput, setValueInput] = require$$0.useState(() => valueToInput(formControl?.value ?? value));
675
779
  const [focused, setFocused] = require$$0.useState(false);
676
- const changeIsInternal = require$$0.useRef(false);
780
+ const composing = require$$0.useRef(false);
781
+ const valueSent = require$$0.useRef(formControl?.value);
677
782
  require$$0.useEffect(() => {
678
- if (!changeIsInternal.current && formControl) {
679
- const valueControl = formControl.value ? String(formControl.value) : '';
783
+ if (formControl && !Object.is(formControl.value, valueSent.current)) {
784
+ const valueControl = valueToInput(formControl.value);
680
785
  if (valueInput !== valueControl) {
681
786
  setValueInput(valueControl);
682
787
  }
683
788
  }
684
- changeIsInternal.current = false;
685
789
  }, [formControl?.value]);
686
- const onChangeInput = require$$0.useCallback((event) => {
687
- const valueInput = event.target.value;
688
- const value = type === 'number'
689
- ? parseFloat((+valueInput).toFixed(decimals))
690
- : valueInput;
691
- changeIsInternal.current = true;
790
+ const applyInput = require$$0.useCallback((element) => {
791
+ const rawInput = element.value;
792
+ const parsed = type === 'number'
793
+ ? parseFloat((+rawInput).toFixed(decimals))
794
+ : rawInput;
795
+ const formatter = formControl?.formatter;
796
+ const value = formatter && formControl?.formatOn !== 'blur' && !composing.current
797
+ ? formatter(parsed)
798
+ : parsed;
799
+ const textInput = Object.is(value, parsed)
800
+ ? rawInput
801
+ : type === 'number'
802
+ ? Number.isNaN(value)
803
+ ? ''
804
+ : String(value)
805
+ : valueToInput(value);
806
+ writeInputValue(element, textInput);
807
+ valueSent.current = value;
692
808
  onValue?.(value);
693
- setValueInput(valueInput);
809
+ setValueInput(textInput);
694
810
  formControl?.setValue(value);
695
811
  }, [formControl, onValue, type, decimals]);
812
+ const onChangeInput = require$$0.useCallback((event) => {
813
+ applyInput(event.target);
814
+ }, [applyInput]);
815
+ const onCompositionStart = require$$0.useCallback(() => {
816
+ composing.current = true;
817
+ }, []);
818
+ const onCompositionEnd = require$$0.useCallback((event) => {
819
+ composing.current = false;
820
+ applyInput(event.currentTarget);
821
+ }, [applyInput]);
696
822
  const onKeyDownInput = require$$0.useCallback((event) => {
697
823
  onKeyDown?.(event);
698
824
  if (event.key === 'Enter') {
@@ -716,7 +842,7 @@ function RlsInputComponent({ children, decimals, disabled, formControl, identifi
716
842
  disabled: formControl?.disabled || disabled,
717
843
  focused: formControl?.focused ?? focused
718
844
  });
719
- return (jsxRuntimeExports.jsxs("div", { id: identifier, className: className, children: [jsxRuntimeExports.jsx("input", { ref: formControl?.elementRef, className: "rls-input__component", autoComplete: "off", type: type ?? 'text', placeholder: placeholder, disabled: formControl?.disabled || disabled, readOnly: readOnly, onFocus: onFocusInput, onBlur: onBlurInput, onChange: onChangeInput, onKeyDown: onKeyDownInput, onKeyUp: onKeyUpInput, value: valueInput }), jsxRuntimeExports.jsx("span", { className: "rls-input__value", children: children })] }));
845
+ return (jsxRuntimeExports.jsxs("div", { id: identifier, className: className, children: [jsxRuntimeExports.jsx("input", { ref: formControl?.elementRef, className: "rls-input__component", autoComplete: "off", type: type ?? 'text', placeholder: placeholder, disabled: formControl?.disabled || disabled, readOnly: readOnly, onFocus: onFocusInput, onBlur: onBlurInput, onChange: onChangeInput, onCompositionStart: onCompositionStart, onCompositionEnd: onCompositionEnd, onKeyDown: onKeyDownInput, onKeyUp: onKeyUpInput, value: valueInput }), jsxRuntimeExports.jsx("span", { className: "rls-input__value", children: children })] }));
720
846
  }
721
847
  const RlsInput = require$$0.memo(RlsInputComponent);
722
848
 
@@ -1260,8 +1386,8 @@ function RlsRadioButtonComponent({ checked, disabled, identifier, rlsTheme, onCl
1260
1386
  }
1261
1387
  const RlsRadioButton = require$$0.memo(RlsRadioButtonComponent);
1262
1388
 
1263
- function RlsSkeletonTextComponent({ active, children, rlsTheme }) {
1264
- return (jsxRuntimeExports.jsx("div", { className: "rls-skeleton-text", "rls-theme": rlsTheme, children: active ? (jsxRuntimeExports.jsx(RlsSkeleton, {})) : (jsxRuntimeExports.jsx("div", { className: "rls-skeleton-text__value", children: children })) }));
1389
+ function RlsSkeletonTextComponent({ active, animation, children, rlsTheme }) {
1390
+ return (jsxRuntimeExports.jsx("div", { className: "rls-skeleton-text", "rls-theme": rlsTheme, children: active ? (jsxRuntimeExports.jsx(RlsSkeleton, { animation: animation })) : (jsxRuntimeExports.jsx("div", { className: "rls-skeleton-text__value", children: children })) }));
1265
1391
  }
1266
1392
  const RlsSkeletonText = require$$0.memo(RlsSkeletonTextComponent);
1267
1393
 
@@ -1550,17 +1676,31 @@ function RlsMessageFormErrorComponent({ className, formControl }) {
1550
1676
  const RlsMessageFormError = require$$0.memo(RlsMessageFormErrorComponent);
1551
1677
 
1552
1678
  function RlsFieldAreaComponent(props) {
1553
- const { children, formControl, identifier, rlsTheme } = props;
1679
+ const { children, formControl, identifier, maxLength, rlsTheme } = props;
1680
+ const { onValue } = props;
1554
1681
  const disabled = require$$0.useMemo(() => {
1555
1682
  return formControl?.disabled || props.disabled;
1556
1683
  }, [formControl?.disabled, props.disabled]);
1684
+ const valueSource = formControl?.value ?? props.value;
1685
+ const [valueLength, setValueLength] = require$$0.useState(() => {
1686
+ return (valueSource ?? '').length;
1687
+ });
1688
+ require$$0.useEffect(() => {
1689
+ if (valueSource !== undefined) {
1690
+ setValueLength(valueSource.length);
1691
+ }
1692
+ }, [valueSource]);
1693
+ const onValueArea = require$$0.useCallback((value) => {
1694
+ setValueLength(value.length);
1695
+ onValue?.(value);
1696
+ }, [onValue]);
1557
1697
  const className = renderClassStatus('rls-field-box', {
1558
1698
  disabled,
1559
1699
  error: formControl?.wrong,
1560
1700
  focused: formControl?.focused && !disabled,
1561
1701
  readonly: props.readOnly
1562
1702
  }, 'rls-field-area');
1563
- return (jsxRuntimeExports.jsxs("div", { id: identifier, className: className, "rls-theme": rlsTheme, children: [children && jsxRuntimeExports.jsx("span", { className: "rls-field-box__label", children: children }), jsxRuntimeExports.jsx("div", { className: "rls-field-box__component", children: jsxRuntimeExports.jsx("div", { className: "rls-field-box__body", children: jsxRuntimeExports.jsx(RlsAreaText, { ...props }) }) }), !props.msgErrorDisabled && (jsxRuntimeExports.jsx(RlsMessageFormError, { className: "rls-field-box__error", formControl: formControl }))] }));
1703
+ return (jsxRuntimeExports.jsxs("div", { id: identifier, className: className, "rls-theme": rlsTheme, children: [children && jsxRuntimeExports.jsx("span", { className: "rls-field-box__label", children: children }), jsxRuntimeExports.jsx("div", { className: "rls-field-box__component", children: jsxRuntimeExports.jsx("div", { className: "rls-field-box__body", children: jsxRuntimeExports.jsx(RlsAreaText, { ...props, onValue: onValueArea }) }) }), props.counter && (jsxRuntimeExports.jsx("span", { className: "rls-field-box__helper rls-field-area__counter", children: maxLength ? `${valueLength} / ${maxLength}` : valueLength })), !props.msgErrorDisabled && (jsxRuntimeExports.jsx(RlsMessageFormError, { className: "rls-field-box__error", formControl: formControl }))] }));
1564
1704
  }
1565
1705
  const RlsFieldArea = require$$0.memo(RlsFieldAreaComponent);
1566
1706