@rolster/react-components 19.8.22 → 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.
@@ -486,6 +486,17 @@ const RlsAmount = require$$0.memo(RlsAmountComponent);
486
486
 
487
487
  const AREA_TEXT_MAX_ROWS = 8;
488
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
+ }
489
500
  function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier, maxLength, maxRows, minRows, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, resize = 'vertical', value }) {
490
501
  const valueInitial = String(formControl?.value ?? value ?? '');
491
502
  const rowsMin = minRows ?? AREA_TEXT_MIN_ROWS;
@@ -494,7 +505,9 @@ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier,
494
505
  const [focused, setFocused] = require$$0.useState(false);
495
506
  const elementRef = require$$0.useRef(null);
496
507
  const areaRef = formControl?.elementRef ?? elementRef;
497
- 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);
498
511
  const heightIsManual = require$$0.useRef(false);
499
512
  const heightApplied = require$$0.useRef(0);
500
513
  const refreshHeight = require$$0.useCallback(() => {
@@ -520,13 +533,16 @@ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier,
520
533
  heightApplied.current = height;
521
534
  }, [areaRef, rowsMax, rowsMin]);
522
535
  require$$0.useEffect(() => {
523
- if (!changeIsInternal.current) {
524
- 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 ?? '');
525
542
  if (valueArea !== nextValue) {
526
543
  setValueArea(nextValue);
527
544
  }
528
545
  }
529
- changeIsInternal.current = false;
530
546
  }, [formControl?.value, value, valueArea]);
531
547
  require$$0.useEffect(() => {
532
548
  refreshHeight();
@@ -550,13 +566,28 @@ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier,
550
566
  observer.observe(element);
551
567
  return () => observer.disconnect();
552
568
  }, [areaRef, resize]);
553
- const onChangeArea = require$$0.useCallback((event) => {
554
- const nextValue = event.target.value;
555
- changeIsInternal.current = true;
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;
556
577
  onValue?.(nextValue);
557
578
  setValueArea(nextValue);
558
579
  formControl?.setValue(nextValue);
559
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]);
560
591
  const onKeyDownArea = require$$0.useCallback((event) => {
561
592
  onKeyDown?.(event);
562
593
  if (event.key === 'Enter') {
@@ -583,7 +614,7 @@ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier,
583
614
  readonly: readOnly,
584
615
  resizable: resize !== 'none' && !disabledArea && !readOnly
585
616
  });
586
- 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, onKeyDown: onKeyDownArea, onKeyUp: onKeyUpArea, value: valueArea }), jsxRuntimeExports.jsx("span", { className: "rls-area-text__value", "aria-hidden": "true", 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 })] }));
587
618
  }
588
619
  const RlsAreaText = require$$0.memo(RlsAreaTextComponent);
589
620
 
@@ -712,30 +743,82 @@ function RlsImageComponent({ src, rlsTheme }) {
712
743
  }
713
744
  const RlsImage = require$$0.memo(RlsImageComponent);
714
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
+ }
715
777
  function RlsInputComponent({ children, decimals, disabled, formControl, identifier, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, type, value }) {
716
- const valueInitial = (formControl?.value ?? value) ? String(value) : '';
717
- const [valueInput, setValueInput] = require$$0.useState(valueInitial);
778
+ const [valueInput, setValueInput] = require$$0.useState(() => valueToInput(formControl?.value ?? value));
718
779
  const [focused, setFocused] = require$$0.useState(false);
719
- const changeIsInternal = require$$0.useRef(false);
780
+ const composing = require$$0.useRef(false);
781
+ const valueSent = require$$0.useRef(formControl?.value);
720
782
  require$$0.useEffect(() => {
721
- if (!changeIsInternal.current && formControl) {
722
- const valueControl = formControl.value ? String(formControl.value) : '';
783
+ if (formControl && !Object.is(formControl.value, valueSent.current)) {
784
+ const valueControl = valueToInput(formControl.value);
723
785
  if (valueInput !== valueControl) {
724
786
  setValueInput(valueControl);
725
787
  }
726
788
  }
727
- changeIsInternal.current = false;
728
789
  }, [formControl?.value]);
729
- const onChangeInput = require$$0.useCallback((event) => {
730
- const valueInput = event.target.value;
731
- const value = type === 'number'
732
- ? parseFloat((+valueInput).toFixed(decimals))
733
- : valueInput;
734
- 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;
735
808
  onValue?.(value);
736
- setValueInput(valueInput);
809
+ setValueInput(textInput);
737
810
  formControl?.setValue(value);
738
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]);
739
822
  const onKeyDownInput = require$$0.useCallback((event) => {
740
823
  onKeyDown?.(event);
741
824
  if (event.key === 'Enter') {
@@ -759,7 +842,7 @@ function RlsInputComponent({ children, decimals, disabled, formControl, identifi
759
842
  disabled: formControl?.disabled || disabled,
760
843
  focused: formControl?.focused ?? focused
761
844
  });
762
- 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 })] }));
763
846
  }
764
847
  const RlsInput = require$$0.memo(RlsInputComponent);
765
848