@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 +21 -21
- package/dist/cjs/index.cjs +177 -37
- package/dist/cjs/index.cjs.map +1 -1
- package/dist/es/index.mjs +177 -37
- package/dist/es/index.mjs.map +1 -1
- package/dist/esm/components/atoms/AreaText/AreaText.d.ts +4 -2
- package/dist/esm/components/atoms/AreaText/AreaText.js +88 -17
- package/dist/esm/components/atoms/AreaText/AreaText.js.map +1 -1
- package/dist/esm/components/atoms/Input/Input.js +66 -14
- package/dist/esm/components/atoms/Input/Input.js.map +1 -1
- package/dist/esm/components/atoms/Skeleton/Skeleton.d.ts +5 -1
- package/dist/esm/components/atoms/Skeleton/Skeleton.js +6 -2
- package/dist/esm/components/atoms/Skeleton/Skeleton.js.map +1 -1
- package/dist/esm/components/atoms/SkeletonText/SkeletonText.d.ts +3 -1
- package/dist/esm/components/atoms/SkeletonText/SkeletonText.js +2 -2
- package/dist/esm/components/atoms/SkeletonText/SkeletonText.js.map +1 -1
- package/dist/esm/components/molecules/FieldArea/FieldArea.d.ts +1 -0
- package/dist/esm/components/molecules/FieldArea/FieldArea.js +17 -3
- package/dist/esm/components/molecules/FieldArea/FieldArea.js.map +1 -1
- package/package.json +3 -3
- package/readme.md +403 -2
package/dist/es/index.mjs
CHANGED
|
@@ -482,41 +482,110 @@ function RlsAmountComponent({ value, className, decimals, rlsTheme, symbol }) {
|
|
|
482
482
|
}
|
|
483
483
|
const RlsAmount = memo(RlsAmountComponent);
|
|
484
484
|
|
|
485
|
-
|
|
485
|
+
const AREA_TEXT_MAX_ROWS = 8;
|
|
486
|
+
const AREA_TEXT_MIN_ROWS = 3;
|
|
487
|
+
function writeAreaValue(element, valueArea) {
|
|
488
|
+
const rawArea = element.value;
|
|
489
|
+
if (rawArea === valueArea) {
|
|
490
|
+
return;
|
|
491
|
+
}
|
|
492
|
+
const selection = element.selectionStart;
|
|
493
|
+
const offset = valueArea.length - rawArea.length;
|
|
494
|
+
const caret = Math.max(0, Math.min(selection + offset, valueArea.length));
|
|
495
|
+
element.value = valueArea;
|
|
496
|
+
element.setSelectionRange(caret, caret);
|
|
497
|
+
}
|
|
498
|
+
function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier, maxLength, maxRows, minRows, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, resize = 'vertical', value }) {
|
|
486
499
|
const valueInitial = String(formControl?.value ?? value ?? '');
|
|
500
|
+
const rowsMin = minRows ?? AREA_TEXT_MIN_ROWS;
|
|
501
|
+
const rowsMax = Math.max(maxRows ?? AREA_TEXT_MAX_ROWS, rowsMin);
|
|
487
502
|
const [valueArea, setValueArea] = useState(valueInitial);
|
|
488
503
|
const [focused, setFocused] = useState(false);
|
|
489
504
|
const elementRef = useRef(null);
|
|
490
505
|
const areaRef = formControl?.elementRef ?? elementRef;
|
|
491
|
-
const
|
|
506
|
+
const composing = useRef(false);
|
|
507
|
+
const valueSent = useRef(formControl?.value);
|
|
508
|
+
const valueSource = useRef(formControl ? formControl.value : value);
|
|
509
|
+
const heightIsManual = useRef(false);
|
|
510
|
+
const heightApplied = useRef(0);
|
|
492
511
|
const refreshHeight = useCallback(() => {
|
|
493
512
|
const element = areaRef.current;
|
|
494
|
-
if (element) {
|
|
495
|
-
|
|
496
|
-
element.style.height = `${element.scrollHeight}px`;
|
|
513
|
+
if (!element || heightIsManual.current) {
|
|
514
|
+
return;
|
|
497
515
|
}
|
|
498
|
-
|
|
516
|
+
element.style.height = 'auto';
|
|
517
|
+
const { lineHeight, paddingBottom, paddingTop } = getComputedStyle(element);
|
|
518
|
+
const heightLine = parseFloat(lineHeight);
|
|
519
|
+
const heightContent = element.scrollHeight;
|
|
520
|
+
if (!heightLine) {
|
|
521
|
+
element.style.height = `${heightContent}px`;
|
|
522
|
+
heightApplied.current = heightContent;
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
const heightPadding = parseFloat(paddingTop) + parseFloat(paddingBottom);
|
|
526
|
+
const heightMin = heightLine * rowsMin + heightPadding;
|
|
527
|
+
const heightMax = heightLine * rowsMax + heightPadding;
|
|
528
|
+
const height = Math.min(Math.max(heightContent, heightMin), heightMax);
|
|
529
|
+
element.style.height = `${height}px`;
|
|
530
|
+
element.style.overflowY = heightContent > heightMax ? 'auto' : 'hidden';
|
|
531
|
+
heightApplied.current = height;
|
|
532
|
+
}, [areaRef, rowsMax, rowsMin]);
|
|
499
533
|
useEffect(() => {
|
|
500
|
-
|
|
501
|
-
|
|
534
|
+
const source = formControl ? formControl.value : value;
|
|
535
|
+
const isEcho = Object.is(source, valueSent.current);
|
|
536
|
+
const isSame = Object.is(source, valueSource.current);
|
|
537
|
+
valueSource.current = source;
|
|
538
|
+
if (!isEcho && !isSame) {
|
|
539
|
+
const nextValue = String(source ?? '');
|
|
502
540
|
if (valueArea !== nextValue) {
|
|
503
541
|
setValueArea(nextValue);
|
|
504
542
|
}
|
|
505
543
|
}
|
|
506
|
-
changeIsInternal.current = false;
|
|
507
544
|
}, [formControl?.value, value, valueArea]);
|
|
508
545
|
useEffect(() => {
|
|
509
546
|
refreshHeight();
|
|
510
547
|
}, [refreshHeight, valueArea]);
|
|
511
|
-
|
|
512
|
-
const
|
|
513
|
-
|
|
548
|
+
useEffect(() => {
|
|
549
|
+
const element = areaRef.current;
|
|
550
|
+
if (!element ||
|
|
551
|
+
resize === 'none' ||
|
|
552
|
+
typeof ResizeObserver === 'undefined') {
|
|
553
|
+
return;
|
|
554
|
+
}
|
|
555
|
+
const observer = new ResizeObserver(() => {
|
|
556
|
+
if (heightIsManual.current || !heightApplied.current) {
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
if (Math.abs(element.offsetHeight - heightApplied.current) > 1) {
|
|
560
|
+
heightIsManual.current = true;
|
|
561
|
+
element.style.overflowY = 'auto';
|
|
562
|
+
}
|
|
563
|
+
});
|
|
564
|
+
observer.observe(element);
|
|
565
|
+
return () => observer.disconnect();
|
|
566
|
+
}, [areaRef, resize]);
|
|
567
|
+
const applyArea = useCallback((element) => {
|
|
568
|
+
const rawArea = element.value;
|
|
569
|
+
const formatter = formControl?.formatter;
|
|
570
|
+
const nextValue = formatter && formControl?.formatOn !== 'blur' && !composing.current
|
|
571
|
+
? (formatter(rawArea) ?? '')
|
|
572
|
+
: rawArea;
|
|
573
|
+
writeAreaValue(element, nextValue);
|
|
574
|
+
valueSent.current = nextValue;
|
|
514
575
|
onValue?.(nextValue);
|
|
515
576
|
setValueArea(nextValue);
|
|
516
577
|
formControl?.setValue(nextValue);
|
|
517
|
-
event.target.style.height = 'auto';
|
|
518
|
-
event.target.style.height = `${event.target.scrollHeight}px`;
|
|
519
578
|
}, [formControl, onValue]);
|
|
579
|
+
const onChangeArea = useCallback((event) => {
|
|
580
|
+
applyArea(event.target);
|
|
581
|
+
}, [applyArea]);
|
|
582
|
+
const onCompositionStart = useCallback(() => {
|
|
583
|
+
composing.current = true;
|
|
584
|
+
}, []);
|
|
585
|
+
const onCompositionEnd = useCallback((event) => {
|
|
586
|
+
composing.current = false;
|
|
587
|
+
applyArea(event.currentTarget);
|
|
588
|
+
}, [applyArea]);
|
|
520
589
|
const onKeyDownArea = useCallback((event) => {
|
|
521
590
|
onKeyDown?.(event);
|
|
522
591
|
if (event.key === 'Enter') {
|
|
@@ -536,12 +605,14 @@ function RlsAreaTextComponent({ autoComplete, disabled, formControl, identifier,
|
|
|
536
605
|
setFocused(() => false);
|
|
537
606
|
onBlur?.();
|
|
538
607
|
}, [formControl, onBlur]);
|
|
608
|
+
const disabledArea = formControl?.disabled || disabled;
|
|
539
609
|
const className = renderClassStatus('rls-area-text', {
|
|
540
|
-
disabled:
|
|
610
|
+
disabled: disabledArea,
|
|
541
611
|
focused: formControl?.focused ?? focused,
|
|
542
|
-
readonly: readOnly
|
|
612
|
+
readonly: readOnly,
|
|
613
|
+
resizable: resize !== 'none' && !disabledArea && !readOnly
|
|
543
614
|
});
|
|
544
|
-
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:
|
|
615
|
+
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 })] }));
|
|
545
616
|
}
|
|
546
617
|
const RlsAreaText = memo(RlsAreaTextComponent);
|
|
547
618
|
|
|
@@ -648,8 +719,11 @@ function RlsCheckBoxControlComponent({ formControl, disabled, identifier, rlsThe
|
|
|
648
719
|
}
|
|
649
720
|
const RlsCheckBoxControl = memo(RlsCheckBoxControlComponent);
|
|
650
721
|
|
|
651
|
-
function RlsSkeletonComponent({ rlsTheme }) {
|
|
652
|
-
|
|
722
|
+
function RlsSkeletonComponent({ animation, rlsTheme }) {
|
|
723
|
+
const className = renderClassStatus('rls-skeleton', {
|
|
724
|
+
animation: animation !== 'shimmer' && animation
|
|
725
|
+
});
|
|
726
|
+
return jsxRuntimeExports.jsx("div", { className: className, "rls-theme": rlsTheme });
|
|
653
727
|
}
|
|
654
728
|
const RlsSkeleton = memo(RlsSkeletonComponent);
|
|
655
729
|
|
|
@@ -667,30 +741,82 @@ function RlsImageComponent({ src, rlsTheme }) {
|
|
|
667
741
|
}
|
|
668
742
|
const RlsImage = memo(RlsImageComponent);
|
|
669
743
|
|
|
744
|
+
function valueToInput(value) {
|
|
745
|
+
return value ? String(value) : '';
|
|
746
|
+
}
|
|
747
|
+
function selectionStartOf(element) {
|
|
748
|
+
try {
|
|
749
|
+
// Lanza o retorna null en inputs sin selección (number, email, etc.)
|
|
750
|
+
return element.selectionStart;
|
|
751
|
+
}
|
|
752
|
+
catch {
|
|
753
|
+
return null;
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
/**
|
|
757
|
+
* Escribe el valor formateado directamente en el DOM y conserva la posición
|
|
758
|
+
* del cursor, corrigiéndola por la diferencia de longitud. Es necesario
|
|
759
|
+
* porque, cuando el formateador rechaza un carácter, el estado del control
|
|
760
|
+
* no cambia y React no vuelve a escribir el input.
|
|
761
|
+
*/
|
|
762
|
+
function writeInputValue(element, valueInput) {
|
|
763
|
+
const rawInput = element.value;
|
|
764
|
+
if (rawInput === valueInput) {
|
|
765
|
+
return;
|
|
766
|
+
}
|
|
767
|
+
const selection = selectionStartOf(element);
|
|
768
|
+
element.value = valueInput;
|
|
769
|
+
if (selection !== null) {
|
|
770
|
+
const offset = valueInput.length - rawInput.length;
|
|
771
|
+
const caret = Math.max(0, Math.min(selection + offset, valueInput.length));
|
|
772
|
+
element.setSelectionRange(caret, caret);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
670
775
|
function RlsInputComponent({ children, decimals, disabled, formControl, identifier, onBlur, onEnter, onFocus, onKeyDown, onKeyUp, onValue, placeholder, readOnly, type, value }) {
|
|
671
|
-
const
|
|
672
|
-
const [valueInput, setValueInput] = useState(valueInitial);
|
|
776
|
+
const [valueInput, setValueInput] = useState(() => valueToInput(formControl?.value ?? value));
|
|
673
777
|
const [focused, setFocused] = useState(false);
|
|
674
|
-
const
|
|
778
|
+
const composing = useRef(false);
|
|
779
|
+
const valueSent = useRef(formControl?.value);
|
|
675
780
|
useEffect(() => {
|
|
676
|
-
if (
|
|
677
|
-
const valueControl =
|
|
781
|
+
if (formControl && !Object.is(formControl.value, valueSent.current)) {
|
|
782
|
+
const valueControl = valueToInput(formControl.value);
|
|
678
783
|
if (valueInput !== valueControl) {
|
|
679
784
|
setValueInput(valueControl);
|
|
680
785
|
}
|
|
681
786
|
}
|
|
682
|
-
changeIsInternal.current = false;
|
|
683
787
|
}, [formControl?.value]);
|
|
684
|
-
const
|
|
685
|
-
const
|
|
686
|
-
const
|
|
687
|
-
? parseFloat((+
|
|
688
|
-
:
|
|
689
|
-
|
|
788
|
+
const applyInput = useCallback((element) => {
|
|
789
|
+
const rawInput = element.value;
|
|
790
|
+
const parsed = type === 'number'
|
|
791
|
+
? parseFloat((+rawInput).toFixed(decimals))
|
|
792
|
+
: rawInput;
|
|
793
|
+
const formatter = formControl?.formatter;
|
|
794
|
+
const value = formatter && formControl?.formatOn !== 'blur' && !composing.current
|
|
795
|
+
? formatter(parsed)
|
|
796
|
+
: parsed;
|
|
797
|
+
const textInput = Object.is(value, parsed)
|
|
798
|
+
? rawInput
|
|
799
|
+
: type === 'number'
|
|
800
|
+
? Number.isNaN(value)
|
|
801
|
+
? ''
|
|
802
|
+
: String(value)
|
|
803
|
+
: valueToInput(value);
|
|
804
|
+
writeInputValue(element, textInput);
|
|
805
|
+
valueSent.current = value;
|
|
690
806
|
onValue?.(value);
|
|
691
|
-
setValueInput(
|
|
807
|
+
setValueInput(textInput);
|
|
692
808
|
formControl?.setValue(value);
|
|
693
809
|
}, [formControl, onValue, type, decimals]);
|
|
810
|
+
const onChangeInput = useCallback((event) => {
|
|
811
|
+
applyInput(event.target);
|
|
812
|
+
}, [applyInput]);
|
|
813
|
+
const onCompositionStart = useCallback(() => {
|
|
814
|
+
composing.current = true;
|
|
815
|
+
}, []);
|
|
816
|
+
const onCompositionEnd = useCallback((event) => {
|
|
817
|
+
composing.current = false;
|
|
818
|
+
applyInput(event.currentTarget);
|
|
819
|
+
}, [applyInput]);
|
|
694
820
|
const onKeyDownInput = useCallback((event) => {
|
|
695
821
|
onKeyDown?.(event);
|
|
696
822
|
if (event.key === 'Enter') {
|
|
@@ -714,7 +840,7 @@ function RlsInputComponent({ children, decimals, disabled, formControl, identifi
|
|
|
714
840
|
disabled: formControl?.disabled || disabled,
|
|
715
841
|
focused: formControl?.focused ?? focused
|
|
716
842
|
});
|
|
717
|
-
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 })] }));
|
|
843
|
+
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 })] }));
|
|
718
844
|
}
|
|
719
845
|
const RlsInput = memo(RlsInputComponent);
|
|
720
846
|
|
|
@@ -1258,8 +1384,8 @@ function RlsRadioButtonComponent({ checked, disabled, identifier, rlsTheme, onCl
|
|
|
1258
1384
|
}
|
|
1259
1385
|
const RlsRadioButton = memo(RlsRadioButtonComponent);
|
|
1260
1386
|
|
|
1261
|
-
function RlsSkeletonTextComponent({ active, children, rlsTheme }) {
|
|
1262
|
-
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 })) }));
|
|
1387
|
+
function RlsSkeletonTextComponent({ active, animation, children, rlsTheme }) {
|
|
1388
|
+
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 })) }));
|
|
1263
1389
|
}
|
|
1264
1390
|
const RlsSkeletonText = memo(RlsSkeletonTextComponent);
|
|
1265
1391
|
|
|
@@ -1548,17 +1674,31 @@ function RlsMessageFormErrorComponent({ className, formControl }) {
|
|
|
1548
1674
|
const RlsMessageFormError = memo(RlsMessageFormErrorComponent);
|
|
1549
1675
|
|
|
1550
1676
|
function RlsFieldAreaComponent(props) {
|
|
1551
|
-
const { children, formControl, identifier, rlsTheme } = props;
|
|
1677
|
+
const { children, formControl, identifier, maxLength, rlsTheme } = props;
|
|
1678
|
+
const { onValue } = props;
|
|
1552
1679
|
const disabled = useMemo(() => {
|
|
1553
1680
|
return formControl?.disabled || props.disabled;
|
|
1554
1681
|
}, [formControl?.disabled, props.disabled]);
|
|
1682
|
+
const valueSource = formControl?.value ?? props.value;
|
|
1683
|
+
const [valueLength, setValueLength] = useState(() => {
|
|
1684
|
+
return (valueSource ?? '').length;
|
|
1685
|
+
});
|
|
1686
|
+
useEffect(() => {
|
|
1687
|
+
if (valueSource !== undefined) {
|
|
1688
|
+
setValueLength(valueSource.length);
|
|
1689
|
+
}
|
|
1690
|
+
}, [valueSource]);
|
|
1691
|
+
const onValueArea = useCallback((value) => {
|
|
1692
|
+
setValueLength(value.length);
|
|
1693
|
+
onValue?.(value);
|
|
1694
|
+
}, [onValue]);
|
|
1555
1695
|
const className = renderClassStatus('rls-field-box', {
|
|
1556
1696
|
disabled,
|
|
1557
1697
|
error: formControl?.wrong,
|
|
1558
1698
|
focused: formControl?.focused && !disabled,
|
|
1559
1699
|
readonly: props.readOnly
|
|
1560
1700
|
}, 'rls-field-area');
|
|
1561
|
-
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 }))] }));
|
|
1701
|
+
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 }))] }));
|
|
1562
1702
|
}
|
|
1563
1703
|
const RlsFieldArea = memo(RlsFieldAreaComponent);
|
|
1564
1704
|
|