import {startTransition, useCallback, useEffect, useMemo, useRef, useState} from 'react'; import renderHtmlAttributes from "../../utils/renderHtmlAttributes"; import useFormSubmitSuccess from "../../hooks/useFormSubmitSuccess"; import jQuery from "jquery"; import "ion-rangeslider"; import type {IonRangeSliderOptions} from "ion-rangeslider"; import type {FreemiusProps} from "../../types/freemius"; import UpgradeOverlay from "../../components/UpgradeOverlay"; type FieldProps = { itemId: string attrs: Record min: IonRangeSliderOptions['min'] max: IonRangeSliderOptions['max'] step: IonRangeSliderOptions['step'] type: IonRangeSliderOptions['type'] skin: IonRangeSliderOptions['skin'] from: IonRangeSliderOptions['from'] to: IonRangeSliderOptions['to'] grid: boolean grid_snap: boolean grid_num: number hide_min_max: boolean hide_from_to: boolean prefix: string postfix: string max_postfix: string show_input: boolean } & FreemiusProps const Field = (props: FieldProps) => { const inputRef = useRef(null); const instance = useRef(null); const attrs = useMemo(() => renderHtmlAttributes(props.attrs), [props.attrs]); const [fromValue, setFromValue] = useState(String(props.from)); const [toValue, setToValue] = useState(String(props.to)); // Reset after form submit useFormSubmitSuccess(inputRef, () => { setFromValue(String(props.from)); setToValue(String(props.to)); instance.current?.update({ from: props.from, to: props.to }); }, [props.from, props.to]); const updateInputs = useCallback((data: any) => { const from = data.from; const to = data.to; setFromValue(String(from)); setToValue(String(to)); }, []); useEffect(() => { const element = jQuery(inputRef.current as unknown as HTMLInputElement); if (!element) { return; } element.ionRangeSlider({ skin: props.skin, type: props.type, min: props.min, max: props.max, step: props.step, from: props.from, to: props.to, keyboard: true, grid: props.grid, grid_snap: props.grid_snap, grid_num: props.grid_num, hide_min_max: props.hide_min_max, hide_from_to: props.hide_from_to, prefix: props.prefix, postfix: props.postfix, max_postfix: props.max_postfix, onStart: updateInputs, onChange: updateInputs, onFinish: updateInputs, input_values_separator: ',', disable: !props.freemius.can_use_premium_code }); instance.current = element.data("ionRangeSlider"); return () => { instance.current?.destroy(); } }, [props.freemius.can_use_premium_code, props.from, props.grid, props.grid_num, props.grid_snap, props.hide_from_to, props.hide_min_max, props.max, props.max_postfix, props.min, props.postfix, props.prefix, props.skin, props.step, props.to, props.type, updateInputs]); const fromValidate = useCallback((val: string) => { let numVal = Number(val); const min = Number(props.min); const max = Number(props.max); if (props.type === 'double') { const to = Number(toValue); if (numVal < min) { numVal = min; } else if (numVal > to) { numVal = to; } } else if (numVal < min) { numVal = min; } else if (numVal > max) { numVal = max } return numVal; }, [props.max, props.min, props.type, toValue]); const toValidate = useCallback((val: string) => { let numVal = Number(val); const max = Number(props.max); const from = Number(fromValue); if (numVal < from) { numVal = from; } else if (numVal > max) { numVal = max; } return numVal; }, [fromValue, props.max]); const fromMax = useMemo(() => { return props.type === 'double' ? toValue : props.max; }, [props.max, props.type, toValue]); useEffect(() => { const element = inputRef.current; element?.dispatchEvent(new Event('change', {bubbles: true})); }, [fromValue, toValue]); return ( <> {!props.freemius.can_use_premium_code && }
{props.show_input && (
{ if (!props.freemius.can_use_premium_code) { return; } const val = event.target.value; setFromValue(val); startTransition(() => { instance.current?.update({ from: fromValidate(val) }); }); }} onBlur={event => { setFromValue(String(fromValidate(event.target.value))); }} min={props.min} max={fromMax} step={props.step} className={'elementor-field elementor-field-textual hulk-show-input'} />
{props.type === 'double' && ( <>
{ if (!props.freemius.can_use_premium_code) { return; } const val = event.target.value; setToValue(val); startTransition(() => { instance.current?.update({ to: toValidate(val) }); }); }} onBlur={event => { setToValue(String(toValidate(event.target.value))); }} min={fromValue} max={props.max} step={props.step} className={'elementor-field elementor-field-textual hulk-show-input'} />
)}
)}
); }; export default Field;