HEX
Server: Apache
System: Linux webd003.cluster128.gra.hosting.ovh.net 6.18.42-ovh-vps-grsec-zfs+ #1 SMP PREEMPT_DYNAMIC Wed Aug 5 15:59:48 CEST 2026 x86_64
User: slyfwmm (169339)
PHP: 8.1.34
Disabled: _dyuweyrj4,_dyuweyrj4r,dl
Upload Files
File: /home/slyfwmm/adspray/wp-content/plugins/lazy-blocks/controls/repeater/script.js
/* eslint-disable no-param-reassign */
/**
 * External dependencies.
 */
import { arrayMoveImmutable } from 'array-move';
import classnames from 'classnames/dedupe';

/**
 * WordPress dependencies.
 */
import { __, _n, sprintf } from '@wordpress/i18n';
import { addFilter } from '@wordpress/hooks';
import { useState } from '@wordpress/element';
import { PanelBody, TextControl, ToggleControl } from '@wordpress/components';

/**
 * Internal dependencies.
 */
import BaseControl from '../../assets/components/base-control';
import useBlockControlProps from '../../assets/hooks/use-block-control-props';

import RepeaterControl from './repeater-control';

/**
 * Control render in editor.
 */
addFilter(
	'lzb.editor.control.repeater.render',
	'lzb.editor',
	(render, props) => {
		const val = props.getValue() || [];

		return (
			<BaseControl {...useBlockControlProps(props)}>
				<RepeaterControl
					controlData={props.data}
					count={val.length}
					getInnerControls={(index) => {
						const innerControls = props.getControls(props.uniqueId);
						const innerResult = {};

						Object.keys(innerControls).forEach((i) => {
							const innerData = innerControls[i];

							innerResult[i] = {
								data: innerData,
								val: props.getValue(innerData, index),
							};
						});

						return innerResult;
					}}
					renderRow={(index) => (
						<>
							{props.renderControls(
								props.placement,
								props.uniqueId,
								index
							)}
						</>
					)}
					removeRow={(i) => {
						if (i > -1) {
							val.splice(i, 1);
							props.onChange(val);
						}
					}}
					addRow={() => {
						const innerControls = props.getControls(props.uniqueId);
						const newRow = {};

						// Add defaults to the new row.
						Object.keys(innerControls).forEach((i) => {
							const innerControl = innerControls[i];

							// Add default values of controls.
							newRow[innerControl.name] =
								innerControl.default ||
								innerControl.checked ||
								'';
						});

						val.push(newRow);
						props.onChange(val);
					}}
					resortRow={(oldIndex, newIndex) => {
						const newVal = arrayMoveImmutable(
							val,
							oldIndex,
							newIndex
						);
						props.onChange(newVal);
					}}
				/>
			</BaseControl>
		);
	}
);

/**
 * getValue filter in editor.
 */
addFilter('lzb.editor.control.repeater.getValue', 'lzb.editor', (value) => {
	// change string value to array.
	if (typeof value === 'string') {
		try {
			// WPML decodes string in a different way, so we have to use decodeURIComponent
			// when string does not contains ':'.
			if (value.includes(':')) {
				value = JSON.parse(decodeURI(value));
			} else {
				value = JSON.parse(decodeURIComponent(value));
			}
		} catch (e) {
			value = [];
		}
	}

	return value;
});

/**
 * updateValue filter in editor.
 */
addFilter('lzb.editor.control.repeater.updateValue', 'lzb.editor', (value) => {
	// change array value to string.
	if (typeof value === 'object' || Array.isArray(value)) {
		value = encodeURI(JSON.stringify(value));
	}

	return value;
});

/**
 * Repeater item with childs render
 *
 * @param {Object} props - component props.
 *
 * @return {JSX} - component return.
 */
function ControlsRepeaterItem(props) {
	const { printControls, id, controls } = props;
	const [collapsedChilds, setCollapsedChilds] = useState(false);

	function toggleCollapseChilds() {
		setCollapsedChilds(!collapsedChilds);
	}

	// repeater child items count.
	let childItemsNum = 0;
	Object.keys(controls).forEach((thisId) => {
		const controlData = controls[thisId];

		if (controlData.child_of === id) {
			childItemsNum += 1;
		}
	});

	let toggleText = __('Show Child Controls', 'lazy-blocks');
	if (collapsedChilds) {
		toggleText = __('Hide Child Controls', 'lazy-blocks');
	} else if (childItemsNum) {
		toggleText = sprintf(
			// translators: %d: number of child controls.
			_n(
				'Show %d Child Control',
				'Show %d Child Controls',
				childItemsNum
			),
			childItemsNum
		);
	}

	return (
		<>
			{/* eslint-disable-next-line react/button-has-type */}
			<button
				className={classnames(
					'lzb-constructor-controls-item-repeater-toggle',
					collapsedChilds
						? 'lzb-constructor-controls-item-repeater-toggle-collapsed'
						: ''
				)}
				onClick={(e) => {
					e.stopPropagation();
					e.preventDefault();
					toggleCollapseChilds();
				}}
			>
				{toggleText}
				<svg
					aria-hidden="true"
					focusable="false"
					role="img"
					xmlns="http://www.w3.org/2000/svg"
					viewBox="0 0 320 512"
				>
					<path
						fill="currentColor"
						d="M285.476 272.971L91.132 467.314c-9.373 9.373-24.569 9.373-33.941 0l-22.667-22.667c-9.357-9.357-9.375-24.522-.04-33.901L188.505 256 34.484 101.255c-9.335-9.379-9.317-24.544.04-33.901l22.667-22.667c9.373-9.373 24.569-9.373 33.941 0L285.475 239.03c9.373 9.372 9.373 24.568.001 33.941z"
					/>
				</svg>
			</button>
			{collapsedChilds ? (
				<div className="lzb-constructor-controls-item-childs">
					{printControls(id)}
				</div>
			) : (
				''
			)}
		</>
	);
}

/**
 * Control lists item render in constructor.
 */
addFilter(
	'lzb.constructor.controls.repeater.item',
	'lzb.constructor',
	(render, props) => (
		<>
			{render}
			<ControlsRepeaterItem {...props} />
		</>
	)
);

/**
 * Control settings render in constructor.
 */
addFilter(
	'lzb.constructor.control.repeater.settings',
	'lzb.constructor',
	(render, props) => {
		const { updateData, data } = props;

		return (
			<>
				<PanelBody>
					<TextControl
						label={__('Row Label', 'lazy-blocks')}
						placeholder={__('Row {{#}}', 'lazy-blocks')}
						help={__(
							'Example: "My row number {{#}} with inner control {{control_name}}"',
							'lazy-blocks'
						)}
						value={data.rows_label}
						onChange={(value) => updateData({ rows_label: value })}
					/>
				</PanelBody>
				<PanelBody>
					<TextControl
						label={__('Add Button Label', 'lazy-blocks')}
						placeholder={__('+ Add Row', 'lazy-blocks')}
						value={data.rows_add_button_label}
						onChange={(value) =>
							updateData({ rows_add_button_label: value })
						}
					/>
				</PanelBody>
				<PanelBody>
					<TextControl
						type="number"
						label={__('Minimum Rows', 'lazy-blocks')}
						placeholder={0}
						min={0}
						value={data.rows_min}
						onChange={(value) => updateData({ rows_min: value })}
					/>
				</PanelBody>
				<PanelBody>
					<TextControl
						type="number"
						label={__('Maximum Rows', 'lazy-blocks')}
						placeholder={0}
						min={0}
						value={data.rows_max}
						onChange={(value) => updateData({ rows_max: value })}
					/>
				</PanelBody>
				<PanelBody>
					<BaseControl
						id="lazyblocks-control-repeater-collapsible"
						label={__('Collapsible Rows', 'lazy-blocks')}
					>
						<ToggleControl
							id="lazyblocks-control-repeater-collapsible"
							label={__('Yes', 'lazy-blocks')}
							checked={data.rows_collapsible === 'true'}
							onChange={(value) =>
								updateData({
									rows_collapsible: value ? 'true' : 'false',
								})
							}
						/>
						{data.rows_collapsible === 'true' ? (
							<ToggleControl
								label={__(
									'Collapsed by Default',
									'lazy-blocks'
								)}
								checked={data.rows_collapsed === 'true'}
								onChange={(value) =>
									updateData({
										rows_collapsed: value
											? 'true'
											: 'false',
									})
								}
							/>
						) : (
							''
						)}
					</BaseControl>
				</PanelBody>
			</>
		);
	}
);