<?php
/**
 * Dynamic Chart element.
 *
 * @package BricksExtras
 */

if ( ! defined( 'ABSPATH' ) ) {
	exit; // Exit if accessed directly.
}

/**
 * Dynamic Chart element class.
 */
class X_Dynamic_Chart extends \Bricks\Element {

	/**
	 * Element category.
	 *
	 * @var string
	 */
	public $category = 'extras';

	/**
	 * Element name.
	 *
	 * @var string
	 */
	public $name = 'xdynamicchart';

	/**
	 * Element icon.
	 *
	 * @var string
	 */
	public $icon = 'ti-bar-chart';

	/**
	 * CSS selector.
	 *
	 * @var string
	 */
	public $css_selector = '';

	/**
	 * Required scripts.
	 *
	 * @var array
	 */
	public $scripts = array( 'xDynamicChart' );

	/**
	 * Loop index.
	 *
	 * @var int
	 */
	public $loop_index = 0;

	/**
	 * Flat datapoints.
	 *
	 * @var array
	 */
	public $flat_datapoints = array();

	/**
	 * Script localized flag.
	 *
	 * @var bool
	 */
	private static $script_localized = false;

	/**
	 * Get element label.
	 */
	public function get_label() {
		return esc_html__( 'Dynamic Chart', 'bricksextras' );
	}

	/**
	 * Get element keywords.
	 */
	public function get_keywords() {
		return array( 'dynamic chart', 'chart' );
	}

	/**
	 * Set control groups.
	 */
	public function set_control_groups() {

		$this->control_groups['table_content_group'] = array(
			'title' => esc_html__( 'Data', 'bricks' ),
			'tab'   => 'content',
		);

		$this->control_groups['chart_type_group'] = array(
			'title' => esc_html__( 'Chart style', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['axis_group'] = array(
			'title'    => esc_html__( 'Axes', 'bricksextras' ),
			'tab'      => 'content',
			'required' => array( 'chart_type', '!=', 'doughnut' ),
		);

		$this->control_groups['tooltip_group'] = array(
			'title' => esc_html__( 'Tooltips', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['legend_group'] = array(
			'title' => esc_html__( 'Legends', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['data_labels_group'] = array(
			'title' => esc_html__( 'Data labels', 'bricksextras' ),
			'tab'   => 'content',
		);

		$this->control_groups['spacing_group'] = array(
			'title' => esc_html__( 'Spacing', 'bricks' ),
			'tab'   => 'content',
		);

		$this->control_groups['dataset_colors_group'] = array(
			'title' => esc_html__( 'Dataset colors', 'bricksextras' ),
			'tab'   => 'content',
		);
	}


	/**
	 * Set element controls.
	 */
	public function set_controls() {

		$this->controls['chartWidth'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Width', 'bricks' ),
			'inline'      => true,
			'type'        => 'number',
			'units'       => true,
			'css'         => array(
				array(
					'selector' => '',
					'property' => 'width',
				),
			),
			'placeholder' => '800px',
		);

		$this->controls['chartAspectRatio'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Aspect ratio', 'bricks' ),
			'inline'         => true,
			'type'           => 'text',
			'hasDynamicData' => false,
			'units'          => false,
			'breakpoints'    => true,
		);

		$this->controls['ariaLabel'] = array(
			'tab'         => 'content',
			'label'       => 'aria-label',
			'type'        => 'text',
			'placeholder' => esc_html__( 'Chart', 'bricksextras' ),
			'inline'      => true,
		);

		$this->controls['loop_sep'] = array(
			'tab'  => 'content',
			'type' => 'separator',
		);

		$this->controls = array_replace_recursive( $this->controls, $this->get_loop_builder_controls() );

		$this->controls['queryLoopDatapoints'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Use query loop for..', 'bricksextras' ),
			'type'        => 'select',
			'inline'      => true,
			'options'     => array(
				'dataSets'   => esc_html__( 'Datasets', 'bricksextras' ),
				'dataPoints' => esc_html__( 'Data points', 'bricksextras' ),
				'array'      => 'JSON (' . esc_html__( 'Query Array', 'bricks' ) . ')',
			),
			'placeholder' => esc_html__( 'Datasets', 'bricksextras' ),
			'required'    => array( 'hasLoop', '!=', false ),

		);

		$this->controls['queryLoopDatapoints_Label'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Label', 'bricks' ),
			'group'    => 'table_content_group',
			'type'     => 'text',
			'required' => array( 'queryLoopDatapoints', '=', 'dataPoints' ),
		);

		$this->controls['queryLoopDatapoints_Value'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Value', 'bricks' ),
			'group'    => 'table_content_group',
			'type'     => 'text',
			'required' => array( 'queryLoopDatapoints', '=', 'dataPoints' ),
		);

		$this->controls['flatArray_DatasetIdentifier'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Dataset', 'bricksextras' ),
			'group'       => 'table_content_group',
			'info'        => 'Use {query_array} to identify which dataset (leave blank for single dataset)',
			'type'        => 'text',
			'inline'      => true,
			'placeholder' => '{query_array @key:\'dataset\'}',
			'required'    => array( 'queryLoopDatapoints', '=', 'array' ),
		);

		$this->controls['flatArray_XAxisLabel'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Data point', 'bricksextras' ),
			'group'       => 'table_content_group',
			'type'        => 'text',
			'placeholder' => '{query_array @key:\'datapoint\'}',
			'info'        => 'Use {query_array} to identify the datapoint',
			'inline'      => true,
			'required'    => array( 'queryLoopDatapoints', '=', 'array' ),
		);

		$this->controls['flatArray_Value'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Value', 'bricks' ),
			'group'       => 'table_content_group',
			'type'        => 'text',
			'placeholder' => '{query_array @key:\'value\'}',
			'info'        => 'Use {query_array} for the numeric value',
			'inline'      => true,
			'required'    => array( 'queryLoopDatapoints', '=', 'array' ),
		);

		$this->controls['content_items'] = array(
			'tab'           => 'content',
			'type'          => 'repeater',
			'group'         => 'table_content_group',
			'required'      => array( array( 'queryLoopDatapoints', '!=', 'dataPoints' ), array( 'queryLoopDatapoints', '!=', 'array' ) ),
			'label'         => esc_html__( 'Data points', 'bricksextras' ),
			'placeholder'   => esc_html__( 'Data point', 'bricksextras' ),
			'titleProperty' => 'title',
			'fields'        => array(
				'title' => array(
					'type'  => 'text',
					'label' => esc_html__( 'Label', 'bricks' ),
				),
				'data'  => array(
					'type'  => 'text',
					'label' => esc_html__( 'Value', 'bricks' ),
				),
				'color' => array(
					'type'        => 'color',
					'label'       => esc_html__( 'Data point color', 'bricksextras' ),
					'description' => '(' . esc_html__( 'If using only one dataset', 'bricksextras' ) . ')',
				),
			),
			'default'       => array(
				array(
					'title' => esc_html__( 'January', 'bricks' ),
					'data'  => '20',
					'color' => array(
						'hex' => '#1da69a',
					),
				),
				array(
					'title' => esc_html__( 'February', 'bricks' ),
					'data'  => '70',
					'color' => array(
						'hex' => '#072027',
					),
				),
			),
		);

		$this->controls['xAxisUnits'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Units for values', 'bricksextras' ),
			'type'     => 'text',
			'info'     => 'Units to show next to numbers. eg % or years',
			'group'    => 'table_content_group',
			'required' => array( 'xAxisDisplay', '!=', 'false' ),
			'inline'   => true,
		);

		$this->controls['xAxisUnitPosition'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Position', 'bricks' ),
			'type'        => 'select',
			'options'     => array(
				'after'  => esc_html__( 'After', 'bricks' ),
				'before' => esc_html__( 'Before', 'bricks' ),
			),
			'group'       => 'table_content_group',
			'placeholder' => esc_html__( 'After', 'bricks' ),
			'required'    => array(
				array( 'xAxisDisplay', '!=', 'false' ),
				array( 'xAxisUnits', '!=', '' ),
			),
			'inline'      => true,
		);

			$this->controls['dataSetColorsStart'] = array(
				'tab'         => 'content',
				'type'        => 'separator',
				'group'       => 'dataset_colors_group',
				'description' => esc_html__( 'Use only if using multiple datasets. Set a colour for each set (either manually or using dynamic data).', 'bricksextras' ),
			);

			$this->controls['maybeDynamicColors'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Set dataset colors', 'bricksextras' ),
				'type'        => 'select',
				'group'       => 'dataset_colors_group',
				'options'     => array(
					'manually' => esc_html__( 'Manually', 'bricksextras' ),
					'dynamic'  => esc_html__( 'Use dynamic data', 'bricksextras' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Manually', 'bricksextras' ),
			);

			$this->controls['datasetColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Dataset color', 'bricksextras' ),
				'group'    => 'dataset_colors_group',
				'type'     => 'text',
				'inline'   => true,
				'required' => array( 'maybeDynamicColors', '=', 'dynamic' ),
			);

			$this->controls['datasetItems'] = array(
				'tab'           => 'content',
				'type'          => 'repeater',
				'group'         => 'dataset_colors_group',
				'label'         => esc_html__( 'Dataset colors', 'bricksextras' ),
				'titleProperty' => 'type',
				'fields'        => array(
					'color' => array(
						'type'  => 'color',
						'label' => esc_html__( 'Color', 'bricks' ),
					),
				),
				'required'      => array( 'maybeDynamicColors', '!=', 'dynamic' ),
			);

			$this->controls['chartTypography'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'chart_type_group',
				'rerender'    => true,
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-wrap',
					'text-decoration',
					'white-space',
					'font-variation-settings',
					'text-shadow',
					'text-transform',
					'letter-spacing',
				),
			);

			$this->controls['chartDirection'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Direction', 'bricks' ),
				'type'        => 'select',
				'group'       => 'chart_type_group',
				'options'     => array(
					'horizontal' => esc_html__( 'Horizontal', 'bricks' ),
					'vertical'   => esc_html__( 'Vertical', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Vertical', 'bricks' ),
				'required'    => array( 'chart_type', '!=', 'doughnut' ),
			);

			$this->controls['chart_type'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Type', 'bricks' ),
				'type'        => 'select',
				'group'       => 'chart_type_group',
				'options'     => array(
					'bar'      => esc_html__( 'Bar', 'bricks' ),
					'line'     => esc_html__( 'Line', 'bricksextras' ),
					'doughnut' => esc_html__( 'Pie', 'bricksextras' ) . ' / ' . esc_html__( 'Doughnut', 'bricksextras' ),

				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Bar', 'bricks' ),
			);

			$this->controls['stacked'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Chart stacking', 'bricksextras' ),
				'type'        => 'select',
				'group'       => 'chart_type_group',
				'options'     => array(
					'disable' => esc_html__( 'Disable', 'bricks' ),
					'stack'   => esc_html__( 'Stack on top', 'bricksextras' ),
					'overlap' => esc_html__( 'Overlap', 'bricksextras' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
				'required'    => array( 'chart_type', '!=', 'doughnut' ),
			);

			$this->controls['reverseDatasets'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Reverse dataset order', 'bricksextras' ),
				'type'     => 'checkbox',
				'group'    => 'chart_type_group',
				'inline'   => true,
				'required' => array(
					array( 'chart_type', '!=', 'doughnut' ),
				),
			);

			$this->controls['lineSep'] = array(
				'tab'      => 'content',
				'type'     => 'separator',
				'label'    => esc_html__( 'Line', 'bricksextras' ),
				'group'    => 'chart_type_group',
				'required' => array( 'chart_type', '=', 'line' ),
			);

			$this->controls['lineColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'group'    => 'chart_type_group',
				'required' => array( 'chart_type', '=', array( 'line', 'doughnut' ) ),
			);

			$this->controls['tension'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Tension', 'bricksextras' ),
				'type'        => 'slider',
				'group'       => 'chart_type_group',
				'units'       => false,
				'min'         => 0,
				'max'         => 1,
				'step'        => .01,
				'placeholder' => '0',
				'required'    => array( 'chart_type', '=', 'line' ),
			);

			$this->controls['pieBorderWidth'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Line width', 'bricksextras' ),
				'type'        => 'number',
				'group'       => 'chart_type_group',
				'units'       => false,
				'min'         => 0,
				'max'         => 10,
				'step'        => 1,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'chart_type', '=', array( 'doughnut' ) ),
			);

			$this->controls['pieCutOut'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Center cutout', 'bricksextras' ) . ' (%)',
				'type'        => 'number',
				'group'       => 'chart_type_group',
				'units'       => false,
				'min'         => 0,
				'max'         => 100,
				'step'        => 1,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'chart_type', '=', array( 'doughnut' ) ),
			);

			$this->controls['lineWidth'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Line width', 'bricksextras' ),
				'type'        => 'number',
				'group'       => 'chart_type_group',
				'units'       => false,
				'min'         => 0,
				'max'         => 10,
				'step'        => 1,
				'small'       => true,
				'placeholder' => esc_html__( '2', 'bricks' ),
				'required'    => array( 'chart_type', '=', array( 'line' ) ),
			);

			$this->controls['pointSep'] = array(
				'tab'      => 'content',
				'type'     => 'separator',
				'label'    => esc_html__( 'Point', 'bricksextras' ),
				'group'    => 'chart_type_group',
				'required' => array( 'chart_type', '=', 'line' ),
			);

			$this->controls['linePointRadius'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Size', 'bricks' ),
				'group'       => 'chart_type_group',
				'type'        => 'number',
				'unit'        => 'px',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '3', 'bricks' ),
				'required'    => array( 'chart_type', '=', 'line' ),
			);

			$this->controls['linePointBorderWidth'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Border width', 'bricks' ),
				'group'       => 'chart_type_group',
				'type'        => 'number',
				'unit'        => 'px',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '1', 'bricks' ),
				'required'    => array( 'chart_type', '=', 'line' ),
			);

			$this->controls['barBorderRadius'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Border radius', 'bricksextras' ),
				'group'       => 'chart_type_group',
				'type'        => 'number',
				'unit'        => 'px',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '5', 'bricks' ),
				'required'    => array( 'chart_type', '!=', array( 'line', 'doughnut' ) ),
			);

			$this->controls['barBorderColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Border color', 'bricks' ),
				'group'    => 'chart_type_group',
				'type'     => 'color',
				'inline'   => true,
				'required' => array( 'chart_type', '!=', array( 'line', 'doughnut' ) ),
			);

			$this->controls['barBorderWidth'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Border width', 'bricks' ),
				'group'       => 'chart_type_group',
				'type'        => 'number',
				'unit'        => 'px',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'chart_type', '!=', array( 'line', 'doughnut' ) ),
			);

			$this->controls['rotation'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Rotation', 'bricksextras' ),
				'group'       => 'chart_type_group',
				'type'        => 'number',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'chart_type', '=', array( 'doughnut' ) ),
			);

			$this->controls['circumference'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Circumference', 'bricksextras' ),
				'group'       => 'chart_type_group',
				'type'        => 'number',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '360', 'bricks' ),
				'required'    => array( 'chart_type', '=', array( 'doughnut' ) ),
			);

			/* x axis */

			$this->controls['xAxisStart'] = array(
				'tab'   => 'content',
				'group' => 'axis_group',
				'type'  => 'separator',
				'label' => esc_html__( 'x-axis', 'bricks' ),
			);

			$this->controls['xAxisDisplay'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Enable', 'bricks' ),
				'type'        => 'select',
				'group'       => 'axis_group',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
			);

			$this->controls['xAxisTitleSep'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'type'     => 'separator',
				'label'    => esc_html__( 'Title', 'bricks' ),
				'required' => array( 'xAxisDisplay', '!=', 'false' ),
			);

			$this->controls['xAxisTitle'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Title', 'bricks' ),
				'group'       => 'axis_group',
				'type'        => 'text',
				'inline'      => true,
				'placeholder' => '',
				'required'    => array( 'xAxisDisplay', '!=', 'false' ),
			);

			$this->controls['xAxisTitleColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'group'    => 'axis_group',
				'required' => array( 'xAxisDisplay', '!=', 'false' ),
			);

			$this->controls['xAxisFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'axis_group',
				'required'    => array( 'xAxisDisplay', '!=', 'false' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			$this->controls['xAxisLabelsSep'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'type'     => 'separator',
				'label'    => esc_html__( 'Labels', 'bricks' ),
				'required' => array( 'xAxisDisplay', '!=', 'false' ),
			);

			$this->controls['xAxisTicksColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'group'    => 'axis_group',
				'required' => array( 'xAxisDisplay', '!=', 'false' ),
			);

			$this->controls['xAxisTicksFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'axis_group',
				'required'    => array( 'xAxisDisplay', '!=', 'false' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			$this->controls['xAxisLabelRotation'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Label rotation', 'bricksextras' ),
				'type'        => 'number',
				'group'       => 'axis_group',
				'inline'      => true,
				'required'    => array( 'xAxisDisplay', '!=', 'false' ),
				'breakpoints' => true,
			);

			$this->controls['xGridColor'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'label'    => esc_html__( 'Color', 'bricks' ) . ' (' . esc_html__( 'Grid', 'bricks' ) . ')',
				'type'     => 'color',
				'required' => array( 'xAxisDisplay', '!=', 'false' ),
			);

			$this->controls['xBorderColor'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'label'    => esc_html__( 'Border color', 'bricks' ),
				'type'     => 'color',
				'required' => array( 'xAxisDisplay', '!=', 'false' ),
			);

			/* y axis */

			$this->controls['yAxisStart'] = array(
				'tab'   => 'content',
				'group' => 'axis_group',
				'type'  => 'separator',
				'label' => esc_html__( 'y-axis', 'bricks' ),
			);

			$this->controls['yAxisDisplay'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Enable', 'bricks' ),
				'type'        => 'select',
				'group'       => 'axis_group',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
			);

			$this->controls['yAxisTitleSep'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'type'     => 'separator',
				'label'    => esc_html__( 'Title', 'bricks' ),
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['yAxisTitle'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Title', 'bricks' ),
				'group'       => 'axis_group',
				'type'        => 'text',
				'inline'      => true,
				'placeholder' => '',
				'required'    => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['yAxisTitleColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'group'    => 'axis_group',
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['yAxisFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'axis_group',
				'required'    => array( 'yAxisDisplay', '!=', 'false' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			$this->controls['yAxisTicksSep'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'type'     => 'separator',
				'label'    => esc_html__( 'Values', 'bricksextras' ),
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['yAxisTicksColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'group'    => 'axis_group',
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['yAxisTicksFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'axis_group',
				'required'    => array( 'yAxisDisplay', '!=', 'false' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			$this->controls['yAxisLabelRotation'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Label rotation', 'bricksextras' ),
				'type'        => 'number',
				'group'       => 'axis_group',
				'inline'      => true,
				'placeholder' => '0',
				'required'    => array( 'yAxisDisplay', '!=', 'false' ),
				'breakpoints' => true,
			);

			$this->controls['yAxisType'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Type', 'bricks' ),
				'type'        => 'select',
				'group'       => 'axis_group',
				'options'     => array(
					'linear'      => esc_html__( 'Linear', 'bricks' ),
					'logarithmic' => esc_html__( 'Logarithmic', 'bricksextras' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'Linear', 'bricks' ),
				'required'    => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['beginAtZero'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Begin At Zero', 'bricksextras' ),
				'type'        => 'select',
				'group'       => 'axis_group',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'inline'      => true,
				'required'    => array( 'yAxisDisplay', '!=', 'false' ),
				'placeholder' => esc_html__( 'Enable', 'bricks' ),
			);

			$this->controls['yGridColor'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'label'    => esc_html__( 'Color', 'bricks' ) . ' (' . esc_html__( 'Grid', 'bricks' ) . ')',
				'type'     => 'color',
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['yBorderColor'] = array(
				'tab'      => 'content',
				'group'    => 'axis_group',
				'label'    => esc_html__( 'Border color', 'bricks' ),
				'type'     => 'color',
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['suggestedMin'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Suggested Min', 'bricksextras' ),
				'group'    => 'axis_group',
				'type'     => 'number',
				'units'    => false,
				'inline'   => true,
				'small'    => true,
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			$this->controls['suggestedMax'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Suggested Max', 'bricksextras' ),
				'group'    => 'axis_group',
				'type'     => 'number',
				'units'    => false,
				'inline'   => true,
				'small'    => true,
				'required' => array( 'yAxisDisplay', '!=', 'false' ),
			);

			/*   tooltips */

			$this->controls['tooltipDisplay'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Enable', 'bricks' ),
				'type'        => 'select',
				'group'       => 'tooltip_group',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
			);

			$this->controls['events'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Events', 'bricks' ),
				'type'        => 'select',
				'group'       => 'tooltip_group',
				'options'     => array(
					'click' => esc_html__( 'Click', 'bricks' ),
					'hover' => esc_html__( 'Hover', 'bricks' ) . ' / ' . esc_html__( 'Click', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Click', 'bricks' ),
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipIntersect'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Accuracy', 'bricksextras' ),
				'type'        => 'select',
				'group'       => 'tooltip_group',
				'options'     => array(
					'default' => esc_html__( 'Default', 'bricks' ),
					'true'    => esc_html__( 'Open on direct hover only', 'bricksextras' ),
					'false'   => esc_html__( 'Open on hover nearby', 'bricksextras' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'Default', 'bricks' ),
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipInteractionMode'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Content', 'bricks' ),
				'type'        => 'select',
				'group'       => 'tooltip_group',
				'options'     => array(
					'default' => esc_html__( 'Default', 'bricks' ),
					'index'   => esc_html__( 'Values from all datasets in single tooltip', 'bricksextras' ),
					'nearest' => esc_html__( 'Values from nearest dataset in separate tooltips', 'bricksextras' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'Default', 'bricks' ),
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipColor'] = array(
				'tab'      => 'content',
				'group'    => 'tooltip_group',
				'label'    => esc_html__( 'Text color', 'bricks' ),
				'type'     => 'color',
				'required' => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipBorderColor'] = array(
				'tab'      => 'content',
				'group'    => 'tooltip_group',
				'label'    => esc_html__( 'Border color', 'bricks' ),
				'type'     => 'color',
				'required' => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipBorderWidth'] = array(
				'tab'         => 'content',
				'group'       => 'tooltip_group',
				'label'       => esc_html__( 'Border width', 'bricks' ),
				'type'        => 'number',
				'placeholder' => esc_html__( '1', 'bricks' ),
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipCaretSize'] = array(
				'tab'         => 'content',
				'group'       => 'tooltip_group',
				'label'       => esc_html__( 'Size', 'bricks' ) . ' (' . esc_html__( 'Caret', 'bricks' ) . ')',
				'type'        => 'number',
				'placeholder' => esc_html__( '5', 'bricks' ),
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipBackground'] = array(
				'tab'      => 'content',
				'group'    => 'tooltip_group',
				'label'    => esc_html__( 'Background color', 'bricks' ),
				'type'     => 'color',
				'required' => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipTitleSep'] = array(
				'tab'      => 'content',
				'group'    => 'tooltip_group',
				'type'     => 'separator',
				'label'    => esc_html__( 'Title', 'bricks' ),
				'required' => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipTitleFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'tooltip_group',
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			$this->controls['tooltipBodySep'] = array(
				'tab'      => 'content',
				'group'    => 'tooltip_group',
				'type'     => 'separator',
				'label'    => esc_html__( 'Body', 'bricks' ),
				'required' => array( 'tooltipDisplay', '=', 'true' ),
			);

			$this->controls['tooltipBodyFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'tooltip_group',
				'required'    => array( 'tooltipDisplay', '=', 'true' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			/*   legend */

			$this->controls['legendDisplay'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Enable', 'bricks' ),
				'type'        => 'select',
				'group'       => 'legend_group',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
			);

			$this->controls['datasetLabel'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Legend', 'bricksextras' ),
				'group'       => 'legend_group',
				'type'        => 'text',
				'inline'      => true,
				'placeholder' => '',
				'required'    => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendPosition'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Position', 'bricks' ),
				'type'        => 'select',
				'group'       => 'legend_group',
				'options'     => array(
					'top'    => esc_html__( 'Top', 'bricks' ),
					'left'   => esc_html__( 'Left', 'bricks' ),
					'bottom' => esc_html__( 'Bottom', 'bricks' ),
					'right'  => esc_html__( 'Right', 'bricks' ),

				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Top', 'bricks' ),
				'required'    => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendAlign'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Align', 'bricks' ),
				'type'        => 'select',
				'group'       => 'legend_group',
				'options'     => array(
					'start'  => esc_html__( 'Start', 'bricks' ),
					'center' => esc_html__( 'Center', 'bricks' ),
					'end'    => esc_html__( 'End', 'bricks' ),

				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Center', 'bricks' ),
				'required'    => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Color', 'bricks' ),
				'type'     => 'color',
				'group'    => 'legend_group',
				'required' => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendFont'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Typography', 'bricks' ),
				'type'        => 'typography',
				'group'       => 'legend_group',
				'required'    => array( 'legendDisplay', '=', 'true' ),
				'breakpoints' => true,
				'exclude'     => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
				),
			);

			$this->controls['legendPadding'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Padding', 'bricks' ),
				'group'       => 'legend_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '10', 'bricks' ),
				'required'    => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendMargin'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Margin', 'bricks' ),
				'group'    => 'legend_group',
				'type'     => 'number',
				'units'    => false,
				'inline'   => true,
				'small'    => true,
				'required' => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendBoxWidth'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Width', 'bricks' ),
				'group'       => 'legend_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '15', 'bricks' ),
				'required'    => array( 'legendDisplay', '=', 'true' ),
			);

			$this->controls['legendBoxHeight'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Height', 'bricks' ),
				'group'       => 'legend_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '12', 'bricks' ),
				'required'    => array( 'legendDisplay', '=', 'true' ),
			);

			/*   data labels */

			$this->controls['dataLabelsDisplay'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Enable', 'bricks' ),
				'type'        => 'select',
				'group'       => 'data_labels_group',
				'options'     => array(
					'true'  => esc_html__( 'Enable', 'bricks' ),
					'false' => esc_html__( 'Disable', 'bricks' ),
				),
				'inline'      => true,
				'clearable'   => false,
				'placeholder' => esc_html__( 'Disable', 'bricks' ),
			);

			$this->controls['dataLabelsAnchor'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Anchor', 'bricksextras' ),
				'type'        => 'select',
				'group'       => 'data_labels_group',
				'options'     => array(
					'start'  => esc_html__( 'Start', 'bricks' ),
					'center' => esc_html__( 'Center', 'bricks' ),
					'end'    => esc_html__( 'End', 'bricks' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'Center', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsAlign'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Align', 'bricks' ),
				'type'        => 'select',
				'group'       => 'data_labels_group',
				'options'     => array(
					'start'  => esc_html__( 'Start', 'bricks' ),
					'center' => esc_html__( 'Center', 'bricks' ),
					'end'    => esc_html__( 'End', 'bricks' ),
				),
				'inline'      => true,
				'placeholder' => esc_html__( 'Center', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsOffset'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Offset', 'bricks' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '4', 'bricks' ),
				'required'    => array(
					array( 'dataLabelsDisplay', '=', 'true' ),
					array( 'dataLabelsAlign', '!=', 'center' ),
				),
			);

			$this->controls['dataLabelsPadding'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Padding', 'bricks' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '6', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsColorSeperator'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Styles', 'bricks' ),
				'group'    => 'data_labels_group',
				'type'     => 'separator',
				'required' => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Text color', 'bricks' ),
				'group'    => 'data_labels_group',
				'type'     => 'color',
				'inline'   => true,
				'required' => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsBackgroundColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Background color', 'bricks' ),
				'info'     => esc_html__( 'Leave empty to inherit color', 'bricksextras' ),
				'group'    => 'data_labels_group',
				'type'     => 'color',
				'inline'   => true,
				'required' => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsBorderColor'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Border color', 'bricks' ),
				'info'     => esc_html__( 'Leave empty to inherit color', 'bricksextras' ),
				'group'    => 'data_labels_group',
				'type'     => 'color',
				'inline'   => true,
				'required' => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsBorderWidth'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Border width', 'bricks' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsRotation'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Rotation', 'bricksextras' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
				'breakpoints' => true,
			);

			$this->controls['dataLabelsBorderRadius'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Border radius', 'bricksextras' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'inline'      => true,
				'small'       => true,
				'placeholder' => esc_html__( '0', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsFontSize'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Font size', 'bricks' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'inline'      => true,
				'small'       => true,
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
				'breakpoints' => true,
			);

			$this->controls['dataLabelsFontWeight'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Font weight', 'bricks' ),
				'group'       => 'data_labels_group',
				'type'        => 'number',
				'small'       => true,
				'inline'      => true,
				'placeholder' => esc_html__( 'Normal', 'bricks' ),
				'required'    => array( 'dataLabelsDisplay', '=', 'true' ),
			);

			$this->controls['dataLabelsFontFamily'] = array(
				'tab'      => 'content',
				'label'    => esc_html__( 'Font family', 'bricks' ),
				'group'    => 'data_labels_group',
				'type'     => 'typography',
				'required' => array( 'dataLabelsDisplay', '=', 'true' ),
				'exclude'  => array(
					'color',
					'text-align',
					'text-decoration',
					'text-transform',
					'letter-spacing',
					'white-space',
					'text-shadow',
					'text-wrap',
					'font-variation-settings',
					'font-size',
					'font-weight',
				),
			);

			/*   spacing */

			$this->controls['spacingSeperator'] = array(
				'tab'   => 'content',
				'label' => esc_html__( 'Padding', 'bricks' ),
				'group' => 'spacing_group',
				'type'  => 'separator',
			);

			$this->controls['spacingTop'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Top', 'bricks' ),
				'group'       => 'spacing_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => '0',
				'breakpoints' => true,
			);

			$this->controls['spacingRight'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Right', 'bricks' ),
				'group'       => 'spacing_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => '0',
				'breakpoints' => true,
			);

			$this->controls['spacingBottom'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Bottom', 'bricks' ),
				'group'       => 'spacing_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => '0',
				'breakpoints' => true,
			);

			$this->controls['spacingLeft'] = array(
				'tab'         => 'content',
				'label'       => esc_html__( 'Left', 'bricks' ),
				'group'       => 'spacing_group',
				'type'        => 'number',
				'units'       => false,
				'inline'      => true,
				'small'       => true,
				'placeholder' => '0',
				'breakpoints' => true,
			);
	}


	/**
	 * Enqueue scripts.
	 */
	public function enqueue_scripts() {

		if ( bricks_is_builder_main() ) {
			return;
		}

		wp_enqueue_script( 'chartjs', BRICKSEXTRAS_URL . 'components/assets/js/chart.js', array( 'bricks-scripts' ), '4.5.1', true );
		wp_enqueue_script( 'chartjs-plugin-datalabels', BRICKSEXTRAS_URL . 'components/assets/js/chart-plugin-datalabels.min.js', array( 'chartjs' ), '2.2.0', true );
		wp_enqueue_script( 'x-chart', BRICKSEXTRAS_URL . 'components/assets/js/' . \BricksExtras\Helpers::maybe_minify_scripts( 'dynamicchart' ) . '.js', array( 'chartjs', 'chartjs-plugin-datalabels' ), \BricksExtras\Plugin::VERSION, true );

		if ( ! self::$script_localized ) {

			wp_localize_script(
				'x-chart',
				'xChart',
				array(
					'Instances' => array(),
					'Config'    => array(),
					'RTL'       => is_rtl() ? 'true' : 'false',
				)
			);

			self::$script_localized = true;

		}

		if ( ! \BricksExtras\Helpers::element_css_added( $this->name ) ) {
			wp_enqueue_style( 'x-chart', BRICKSEXTRAS_URL . 'components/assets/css/dynamicchart.css', array(), \BricksExtras\Plugin::VERSION );
		}
	}

	/**
	 * Render element output.
	 */
	public function render() {

		$settings = $this->settings;

		$content_items      = ! empty( $settings['content_items'] ) ? $settings['content_items'] : false;
		$dataset_items      = ! empty( $settings['datasetItems'] ) ? $settings['datasetItems'] : false;
		$chart_type         = isset( $settings['chart_type'] ) ? $settings['chart_type'] : 'bar';
		$loop_data_points   = isset( $settings['queryLoopDatapoints'] ) ? 'dataPoints' === $settings['queryLoopDatapoints'] : false;
		$loop_nested_arrays = isset( $settings['queryLoopDatapoints'] ) ? 'array' === $settings['queryLoopDatapoints'] : false;

		$config = array(
			'legendDisplay'          => isset( $settings['legendDisplay'] ) ? $settings['legendDisplay'] : 'false',
			'chartType'              => $chart_type,
			'suggestedMin'           => isset( $settings['suggestedMin'] ) ? $settings['suggestedMin'] : null,
			'suggestedMax'           => isset( $settings['suggestedMax'] ) ? $settings['suggestedMax'] : null,
			'xGridColor'             => isset( $settings['xGridColor'] ) ? $settings['xGridColor'] : '#ccc',
			'yGridColor'             => isset( $settings['yGridColor'] ) ? $settings['yGridColor'] : '#ccc',
			'xBorderColor'           => isset( $settings['xBorderColor'] ) ? $settings['xBorderColor'] : '#222',
			'yBorderColor'           => isset( $settings['yBorderColor'] ) ? $settings['yBorderColor'] : '#222',
			'yAxisType'              => isset( $settings['yAxisType'] ) ? $settings['yAxisType'] : 'linear',
			'xAxisTitle'             => ! empty( $settings['xAxisTitle'] ) ? bricks_render_dynamic_data( $settings['xAxisTitle'] ) : '',
			'yAxisTitle'             => ! empty( $settings['yAxisTitle'] ) ? bricks_render_dynamic_data( $settings['yAxisTitle'] ) : '',
			'beginAtZero'            => isset( $settings['beginAtZero'] ) ? $settings['beginAtZero'] : 'true',
			'tension'                => isset( $settings['tension'] ) ? floatval( $settings['tension'] ) : 0.1,
			'barBorderRadius'        => isset( $settings['barBorderRadius'] ) ? floatval( $settings['barBorderRadius'] ) : 5,
			'barBorderWidth'         => isset( $settings['barBorderWidth'] ) ? floatval( $settings['barBorderWidth'] ) : 0,
			'barBorderColor'         => isset( $settings['barBorderColor'] ) ? $settings['barBorderColor'] : '',
			'lineColor'              => isset( $settings['lineColor'] ) ? $settings['lineColor'] : '#222',
			'lineWidth'              => isset( $settings['lineWidth'] ) ? floatval( $settings['lineWidth'] ) : 2,
			'linePointRadius'        => isset( $settings['linePointRadius'] ) ? floatval( $settings['linePointRadius'] ) : 3,
			'linePointBorderWidth'   => isset( $settings['linePointBorderWidth'] ) ? floatval( $settings['linePointBorderWidth'] ) : 1,
			'xAxisTitleColor'        => isset( $settings['xAxisTitleColor'] ) ? $settings['xAxisTitleColor'] : '',
			'yAxisTitleColor'        => isset( $settings['yAxisTitleColor'] ) ? $settings['yAxisTitleColor'] : '',
			'xAxisTicksColor'        => isset( $settings['xAxisTicksColor'] ) ? $settings['xAxisTicksColor'] : '',
			'yAxisTicksColor'        => isset( $settings['yAxisTicksColor'] ) ? $settings['yAxisTicksColor'] : '',
			'xAxisUnits'             => isset( $settings['xAxisUnits'] ) ? bricks_render_dynamic_data( $settings['xAxisUnits'] ) : '',
			'xAxisUnitPosition'      => isset( $settings['xAxisUnitPosition'] ) ? $settings['xAxisUnitPosition'] : 'after',
			'ariaLabel'              => isset( $settings['ariaLabel'] ) ? bricks_render_dynamic_data( $settings['ariaLabel'] ) : __( 'Chart', 'bricksextras' ),
			'rotation'               => isset( $settings['rotation'] ) ? floatval( $settings['rotation'] ) : 0,
			'circumference'          => isset( $settings['circumference'] ) ? floatval( $settings['circumference'] ) : 360,
			'pieBorderColor'         => isset( $settings['pieBorderColor'] ) ? $settings['pieBorderColor'] : '#222',
			'pieBorderWidth'         => isset( $settings['pieBorderWidth'] ) ? floatval( $settings['pieBorderWidth'] ) : 0,
			'pieCutOut'              => isset( $settings['pieCutOut'] ) ? floatval( $settings['pieCutOut'] ) : 0,
			'legendPadding'          => isset( $settings['legendPadding'] ) ? floatval( $settings['legendPadding'] ) : 0,
			'legendMargin'           => isset( $settings['legendMargin'] ) ? floatval( $settings['legendMargin'] ) : 0,
			'chartDirection'         => isset( $settings['chartDirection'] ) ? $settings['chartDirection'] : 'vertical',
			'stacked'                => isset( $settings['stacked'] ) ? $settings['stacked'] : 'disable',
			'reverseDatasets'        => isset( $settings['reverseDatasets'] ),
			'tooltipDisplay'         => isset( $settings['tooltipDisplay'] ) ? $settings['tooltipDisplay'] : 'false',
			'events'                 => isset( $settings['events'] ) ? $settings['events'] : 'click',
			'tooltipInteractionMode' => isset( $settings['tooltipInteractionMode'] ) ? $settings['tooltipInteractionMode'] : 'default',
			'tooltipIntersect'       => isset( $settings['tooltipIntersect'] ) ? $settings['tooltipIntersect'] : 'default',
			'tooltipColor'           => isset( $settings['tooltipColor'] ) ? $settings['tooltipColor'] : '#222',
			'tooltipBackground'      => isset( $settings['tooltipBackground'] ) ? $settings['tooltipBackground'] : '#fff',
			'tooltipBorderColor'     => isset( $settings['tooltipBorderColor'] ) ? $settings['tooltipBorderColor'] : '#222',
			'tooltipBorderWidth'     => isset( $settings['tooltipBorderWidth'] ) ? floatval( $settings['tooltipBorderWidth'] ) : 1,
			'tooltipCaretSize'       => isset( $settings['tooltipCaretSize'] ) ? floatval( $settings['tooltipCaretSize'] ) : 5,
			'loopDataPoints'         => $loop_data_points,
			'spacingTop'             => isset( $settings['spacingTop'] ) ? floatval( $settings['spacingTop'] ) : 0,
			'spacingRight'           => isset( $settings['spacingRight'] ) ? floatval( $settings['spacingRight'] ) : 0,
			'spacingBottom'          => isset( $settings['spacingBottom'] ) ? floatval( $settings['spacingBottom'] ) : 0,
			'spacingLeft'            => isset( $settings['spacingLeft'] ) ? floatval( $settings['spacingLeft'] ) : 0,

			'chartTypography'        => isset( $settings['chartTypography'] ) ? $settings['chartTypography'] : array(),
			'xAxisFont'              => ! empty( $settings['xAxisFont'] ) ? $settings['xAxisFont'] : array(),
			'xAxisTicksFont'         => ! empty( $settings['xAxisTicksFont'] ) ? $settings['xAxisTicksFont'] : array(),
			'yAxisFont'              => ! empty( $settings['yAxisFont'] ) ? $settings['yAxisFont'] : array(),
			'yAxisTicksFont'         => ! empty( $settings['yAxisTicksFont'] ) ? $settings['yAxisTicksFont'] : array(),
			'legendFont'             => ! empty( $settings['legendFont'] ) ? $settings['legendFont'] : array(),
			'legendColor'            => ! empty( $settings['legendColor'] ) ? $settings['legendColor'] : '#222',
			'tooltipTitleFont'       => ! empty( $settings['tooltipTitleFont'] ) ? $settings['tooltipTitleFont'] : array(),
			'tooltipBodyFont'        => ! empty( $settings['tooltipBodyFont'] ) ? $settings['tooltipBodyFont'] : array(),
			'xAxisLabelRotation'     => isset( $settings['xAxisLabelRotation'] ) ? floatval( $settings['xAxisLabelRotation'] ) : false,
			'yAxisLabelRotation'     => isset( $settings['yAxisLabelRotation'] ) ? floatval( $settings['yAxisLabelRotation'] ) : false,
		);

		// Add chartAspectRatio only if set (preserves Chart.js default per chart type).
		if ( isset( $settings['chartAspectRatio'] ) ) {
			$config['chartAspectRatio'] = $settings['chartAspectRatio'];
		}

		// Build breakpoints object.
		$breakpoints         = array();
		$responsive_settings = array(
			'chartAspectRatio',
			'xAxisLabelRotation',
			'yAxisLabelRotation',
			'chartTypography',
			'xAxisTicksFont',
			'yAxisTicksFont',
			'xAxisFont',
			'yAxisFont',
			'legendFont',
			'tooltipTitleFont',
			'tooltipBodyFont',
			'spacingTop',
			'spacingRight',
			'spacingBottom',
			'spacingLeft',
			'dataLabelsRotation',
			'dataLabelsFontSize',
		);

		if ( class_exists( '\Bricks\Breakpoints' ) && isset( \Bricks\Breakpoints::$breakpoints ) ) {
			foreach ( \Bricks\Breakpoints::$breakpoints as $breakpoint ) {
				if ( 'desktop' === $breakpoint['key'] ) {
					continue; // Desktop values are in the main config.
				}

				$breakpoint_width = $breakpoint['width'] ?? false;
				if ( ! $breakpoint_width ) {
					continue;
				}

				foreach ( $responsive_settings as $setting ) {
					$setting_key   = "{$setting}:{$breakpoint['key']}";
					$setting_value = $settings[ $setting_key ] ?? false;

					if ( false !== $setting_value ) {
						$breakpoints[ $breakpoint_width ][ $setting ] = $setting_value;
					}
				}
			}
		}

		if ( count( $breakpoints ) ) {
			$config['breakpoints'] = $breakpoints;
		}

		// Add mobile-first flag for JavaScript.
		$config['isMobileFirst'] = class_exists( '\Bricks\Breakpoints' ) && isset( \Bricks\Breakpoints::$is_mobile_first ) ? \Bricks\Breakpoints::$is_mobile_first : false;

		if ( isset( $settings['legendPosition'] ) ) {
			$config += array(
				'legendPosition' => $settings['legendPosition'],
			);
		}

		if ( isset( $settings['legendAlign'] ) ) {
			$config += array(
				'legendAlign' => $settings['legendAlign'],
			);
		}

		if ( isset( $settings['legendBoxWidth'] ) ) {
			$config += array(
				'legendBoxWidth' => floatval( $settings['legendBoxWidth'] ),
			);
		}

		if ( isset( $settings['legendBoxHeight'] ) ) {
			$config += array(
				'legendBoxHeight' => floatval( $settings['legendBoxHeight'] ),
			);
		}

		if ( isset( $settings['dataLabelsDisplay'] ) && 'true' === $settings['dataLabelsDisplay'] ) {
			$config += array(
				'dataLabelsDisplay'         => true,
				'dataLabelsAlign'           => isset( $settings['dataLabelsAlign'] ) ? $settings['dataLabelsAlign'] : 'center',
				'dataLabelsAnchor'          => isset( $settings['dataLabelsAnchor'] ) ? $settings['dataLabelsAnchor'] : 'center',
				'dataLabelsOffset'          => isset( $settings['dataLabelsOffset'] ) ? floatval( $settings['dataLabelsOffset'] ) : 4,
				'dataLabelsPadding'         => isset( $settings['dataLabelsPadding'] ) ? floatval( $settings['dataLabelsPadding'] ) : 6,
				'dataLabelsColor'           => isset( $settings['dataLabelsColor'] ) ? $settings['dataLabelsColor'] : '#ffffff',
				'dataLabelsBackgroundColor' => isset( $settings['dataLabelsBackgroundColor'] ) ? $settings['dataLabelsBackgroundColor'] : false,
				'dataLabelsBorderColor'     => isset( $settings['dataLabelsBorderColor'] ) ? $settings['dataLabelsBorderColor'] : false,
				'dataLabelsBorderWidth'     => isset( $settings['dataLabelsBorderWidth'] ) ? floatval( $settings['dataLabelsBorderWidth'] ) : 0,
				'dataLabelsBorderRadius'    => isset( $settings['dataLabelsBorderRadius'] ) ? floatval( $settings['dataLabelsBorderRadius'] ) : 0,
				'dataLabelsFontSize'        => isset( $settings['dataLabelsFontSize'] ) ? floatval( $settings['dataLabelsFontSize'] ) : false,
				'dataLabelsFontWeight'      => isset( $settings['dataLabelsFontWeight'] ) ? floatval( $settings['dataLabelsFontWeight'] ) : false,
				'dataLabelsFontFamily'      => isset( $settings['dataLabelsFontFamily'] ) ? $settings['dataLabelsFontFamily'] : false,
				'dataLabelsRotation'        => isset( $settings['dataLabelsRotation'] ) ? floatval( $settings['dataLabelsRotation'] ) : 0,
			);
		}

		if ( 'doughnut' === $chart_type ) {
			$x_axis_display = 'false';
			$y_axis_display = 'false';
		} else {
			$x_axis_display = ! isset( $settings['xAxisDisplay'] ) ? 'true' : $settings['xAxisDisplay'];
			$y_axis_display = ! isset( $settings['yAxisDisplay'] ) ? 'true' : $settings['yAxisDisplay'];
		}

		$config += array(
			'xAxisDisplay' => $x_axis_display,
			'yAxisDisplay' => $y_axis_display,
		);

		$this->set_attribute( 'x-dynamic-chart_table', 'class', 'x-dynamic-chart_table' );
		$this->set_attribute( 'x-dynamic-chart_table', 'style', 'display: none' );
		$this->set_attribute( 'x-dynamic-chart_table', 'data-x-chart', wp_json_encode( $config ) );

		// Generate and set a unique identifier for this instance.
		$indentifier = \BricksExtras\Helpers::set_identifier_attribute( $this );

		$this->set_attribute( '_root', 'data-x-dynamic-chart', $chart_type );

		$output = '';

		$output .= "<div {$this->render_attributes( '_root' )}>";

		$output .= "<table {$this->render_attributes( 'x-dynamic-chart_table' )}>";

		if ( $loop_nested_arrays ) {

			// Query Loop for nested arrays - collect all data first.
			if ( isset( $settings['hasLoop'] ) ) {
				$query = new \Bricks\Query(
					array(
						'id'       => $this->id,
						'settings' => $settings,
					)
				);

				if ( 1 === $query->count ) {
					// No results.
					$no_results_content = $query->get_no_results_content();
					if ( empty( $no_results_content ) ) {
						$output .= $this->render_element_placeholder( array( 'title' => esc_html__( 'No results', 'bricks' ) ) );
					}
				} else {

					// Initialize collection array.
					$this->flat_datapoints = array();

					$query->render( array( $this, 'collect_flat_array_data' ), array() );

					// Collect all unique X-axis labels from all datasets.
					$all_labels = array();
					foreach ( $this->flat_datapoints as $dataset_data ) {
						foreach ( $dataset_data['labels'] as $label ) {
							if ( ! in_array( $label, $all_labels, true ) ) {
								$all_labels[] = $label;
							}
						}
					}

					// Build datasets array with proper alignment.
					$datasets = array();
					foreach ( $this->flat_datapoints as $dataset_name => $dataset_data ) {
						// For single dataset charts (empty dataset name), use datasetLabel if available.
						if ( empty( $dataset_name ) && ! empty( $settings['datasetLabel'] ) ) {
							$legend_text = bricks_render_dynamic_data( $settings['datasetLabel'] );
						} else {
							$legend_text = $dataset_name;
						}

							// Remap data to align with all labels.
						$remapped_data = array();
						foreach ( $all_labels as $label ) {
							$index = array_search( $label, $dataset_data['labels'], true );
							if ( false !== $index && isset( $dataset_data['values'][ $index ] ) ) {
								$remapped_data[] = $dataset_data['values'][ $index ];
							} else {
								$remapped_data[] = null;
							}
						}

						$datasets[] = array(
							'label'  => $dataset_name,
							'legend' => $legend_text,
							'data'   => $remapped_data,
							'color'  => ! empty( $dataset_data['color'] ) ? $dataset_data['color'] : '',
						);
					}

					// Render table with collected data.
					$output .= $this->render_flat_array_table( $all_labels, $datasets, $settings );
				}

				$query->destroy();
				unset( $query );
			}
		} elseif ( ! $loop_data_points ) {

					/* table header */
			if ( $content_items ) {

				$output .= '<thead><tr>';

				foreach ( $content_items as $index => $content_item ) {

					$header_title = ! empty( $content_item['title'] ) ? bricks_render_dynamic_data( $content_item['title'] ) : '';

					$output .= '<th class="label">' . esc_html( $header_title ) . '</th>';

				}

				$output .= '</tr></thead>';

			}

			/* table content */

			$output .= '<tbody>';

			// Query Loop.
			if ( isset( $settings['hasLoop'] ) ) {
				$query = new \Bricks\Query(
					array(
						'id'       => $this->id,
						'settings' => $settings,
					)
				);

				if ( 1 === $query->count ) {
					// No results.
					$no_results_content = $query->get_no_results_content();

					if ( empty( $no_results_content ) ) {
						$output .= $this->render_element_placeholder( array( 'title' => esc_html__( 'No results', 'bricks' ) ) );
					}
				}

				if ( (bool) $content_items ) {
					$content_item = $content_items[0];
					$output      .= wp_kses_post( $query->render( array( $this, 'render_repeater_item' ), compact( 'content_items' ) ) );
				}
				$query->destroy();
				unset( $query );
			} else {

				// just output one row if not using query loop, so user can build single static chart.
				?> <tr> 
				<?php

				$dataset_labels = ! empty( $settings['datasetLabel'] ) ? $settings['datasetLabel'] : '';

				if ( ! empty( $dataset_labels ) ) {
						$output .= '<td class="legend">';
						$output .= esc_attr( $dataset_labels );
						$output .= '</td>';
				}

				if ( $content_items ) {

					foreach ( $content_items as $index => $content_item ) {

						$style_config = array();

						if ( isset( $content_item['color'] ) ) {

							$style_config += array(
								'color' => isset( $content_item['color'] ) ? $content_item['color'] : '',
							);

						}

						$this->set_attribute( "td-$index", 'data-x-chart-style', wp_json_encode( $style_config ) );

						$output .= "<td {$this->render_attributes( "td-$index" )}>";

						$content_datas = ! empty( $content_item['data'] ) ? bricks_render_dynamic_data( $content_item['data'] ) : '';

						if ( is_numeric( $content_datas ) ) {
							if ( ! is_float( $content_datas ) ) {
								$content_datas = number_format( $content_datas, 2, '.', '' );
							}
						}

						$output .= esc_attr( $content_datas );

						$output .= '</td>';

					}
				}

				?>
			</tr> 
				<?php
			}

			$output .= '</tbody>';

		} else {

			$output .= '<thead><tr>';

			// Query Loop..
			if ( isset( $settings['hasLoop'] ) ) {
				$query = new \Bricks\Query(
					array(
						'id'       => $this->id,
						'settings' => $settings,
					)
				);

				if ( 1 === $query->count ) {
					// No results.
					$no_results_content = $query->get_no_results_content();

					if ( empty( $no_results_content ) ) {
						$output .= $this->render_element_placeholder( array( 'title' => esc_html__( 'No results', 'bricks' ) ) );
					}
				} else {

					$output .= wp_kses_post( $query->render( array( $this, 'render_repeater_head' ), compact( 'content_items' ) ) );

					$query->destroy();
					unset( $query );

				}
			}

			$output .= '</tr></thead>';

			$output .= '<tbody><tr>';

			$output .= '<td class=legend ';

			$output .= '>';

			$dataset_label = ! empty( $settings['datasetLabel'] ) ? $settings['datasetLabel'] : '';

			$output .= wp_kses_post( $dataset_label );

			$output .= '</td>';

			// Query Loop..
			if ( isset( $settings['hasLoop'] ) ) {
					$query = new \Bricks\Query(
						array(
							'id'       => $this->id,
							'settings' => $settings,
						)
					);

				if ( 1 === $query->count ) {
					// No results.
					$no_results_content = $query->get_no_results_content();

					if ( empty( $no_results_content ) ) {
						$output .= $this->render_element_placeholder( array( 'title' => esc_html__( 'No results', 'bricks' ) ) );
					}
				} else {

					$output .= wp_kses_post( $query->render( array( $this, 'render_repeater_body' ), compact( 'content_items' ) ) );

					$query->destroy();
					unset( $query );

				}
			}

				$output .= '</tr></tbody>';

		}

		/* datasetSettings */
		if ( $dataset_items && isset( $settings['hasLoop'] ) ) {

			$output .= "<ul class='x-dynamic-chart_list' style='display: none;'>";

			foreach ( $dataset_items as $index => $dataset_item ) {

				$color = ! empty( $dataset_item['color'] ) ? $dataset_item['color'] : '';

				$dataset_config = array();

				if ( isset( $dataset_item['color'] ) ) {

					$dataset_config += array(
						'color' => isset( $dataset_item['color'] ) ? $dataset_item['color'] : '',
					);

				}

				$this->set_attribute( "li-$index", 'data-x-chart-style', wp_json_encode( $dataset_config ) );

				$output .= "<li {$this->render_attributes( "li-$index" )} ></li>";

			}

			$output .= '</ul>';

		}

		$output .= '</table>';
		$output .= '</div>';

		echo $output;
	}

	/**
	 * Render repeater item.
	 *
	 * @param array $content_items Content items array.
	 */
	public function render_repeater_item( $content_items ) {

		$settings = $this->settings;
		$index    = $this->loop_index;

		$html = '';

		$html .= '<tr>';

		$dataset_labels = ! empty( $settings['datasetLabel'] ) ? $settings['datasetLabel'] : '';
		$dataset_color  = ! empty( $settings['datasetColor'] ) ? $settings['datasetColor'] : '';

		$html .= '<td class=legend ';

		if ( isset( $settings['maybeDynamicColors'] ) ) {
			$html .= 'dynamic' === $settings['maybeDynamicColors'] ? 'data-set-color=' . esc_attr( $dataset_color ) . ' ' : '';
		}

		$html .= '>';
		$html .= esc_html( bricks_render_dynamic_data( $dataset_labels ) );
		$html .= '</td>';

		if ( $content_items ) {

			foreach ( $content_items as $index => $content_item ) {

				$html .= '<td>';

				$content_datas = ! empty( $content_item['data'] ) ? bricks_render_dynamic_data( $content_item['data'] ) : '';

				$html .= esc_html( $content_datas );

				$html .= '</td>';

			}
		}

		$html .= '</tr>';

		++$this->loop_index;

		return $html;
	}

	/**
	 * Render repeater head.
	 *
	 * @param array $content_items Content items array.
	 */
	public function render_repeater_head( $content_items ) {

		$settings = $this->settings;
		$index    = $this->loop_index;

		$html = '';

		$query_loop_datapoints_label = ! empty( $settings['queryLoopDatapoints_Label'] ) ? bricks_render_dynamic_data( $settings['queryLoopDatapoints_Label'] ) : '';

		$html .= '<th class="label" ';

		$dataset_color = ! empty( $settings['datasetColor'] ) ? $settings['datasetColor'] : '';

		if ( isset( $settings['maybeDynamicColors'] ) ) {
			$html .= 'dynamic' === $settings['maybeDynamicColors'] ? 'data-set-color=' . esc_attr( $dataset_color ) . ' ' : '';
		}

		$html .= '>';

		$html .= esc_html( $query_loop_datapoints_label );

		$html .= '</th>';

		++$this->loop_index;

		return $html;
	}

	/**
	 * Render repeater body.
	 *
	 * @param array $content_items Content items array.
	 */
	public function render_repeater_body( $content_items ) {

		$settings = $this->settings;
		$index    = $this->loop_index;

		$html = '';

		$query_loop_datapoints_value = ! empty( $settings['queryLoopDatapoints_Value'] ) ? bricks_render_dynamic_data( $settings['queryLoopDatapoints_Value'] ) : '';

		$html .= '<td ';

		$data_point_color = isset( $settings['datasetColor'] ) ? $settings['datasetColor'] : '';

		if ( isset( $settings['maybeDynamicColors'] ) ) {
			if ( 'dynamic' === $settings['maybeDynamicColors'] ) {
				$html .= "data-point-color='" . esc_attr( $data_point_color ) . "' ";
			}
		}

		$html .= '>' . esc_html( $query_loop_datapoints_value ) . '</td>';

		++$this->loop_index;

		return $html;
	}

	/**
	 * Collect flat array data.
	 *
	 * @param array $args Arguments array.
	 */
	public function collect_flat_array_data( $args = array() ) {

		$settings = $this->settings;

		// Set defaults for flatArray settings if not set.
		if ( ! isset( $settings['flatArray_XAxisLabel'] ) || empty( $settings['flatArray_XAxisLabel'] ) ) {
			$settings['flatArray_XAxisLabel'] = '{query_array @key:\'datapoint\'}';
		}
		if ( ! isset( $settings['flatArray_Value'] ) || empty( $settings['flatArray_Value'] ) ) {
			$settings['flatArray_Value'] = '{query_array @key:\'value\'}';
		}
		if ( ! isset( $settings['flatArray_DatasetIdentifier'] ) || empty( $settings['flatArray_DatasetIdentifier'] ) ) {
			$settings['flatArray_DatasetIdentifier'] = '{query_array @key:\'dataset\'}';
		}

		// Render dynamic tags for this datapoint.
		$dataset_identifier = bricks_render_dynamic_data( $settings['flatArray_DatasetIdentifier'] );
		$xaxis_label        = bricks_render_dynamic_data( $settings['flatArray_XAxisLabel'] );
		$value              = bricks_render_dynamic_data( $settings['flatArray_Value'] );

		if ( empty( $xaxis_label ) || '' === $value ) {
			return '';
		}

		// If dataset identifier is empty, use empty string for single dataset charts.
		if ( empty( $dataset_identifier ) ) {
			$dataset_identifier = '';
		}

		// Store this datapoint grouped by dataset identifier.
		if ( ! isset( $this->flat_datapoints[ $dataset_identifier ] ) ) {
			// Get color using existing datasetColor control (if dynamic colors enabled).
			$color = '';
			if ( isset( $settings['maybeDynamicColors'] ) && 'dynamic' === $settings['maybeDynamicColors'] && ! empty( $settings['datasetColor'] ) ) {
				$color = bricks_render_dynamic_data( $settings['datasetColor'] );
			}

			$this->flat_datapoints[ $dataset_identifier ] = array(
				'labels' => array(),
				'values' => array(),
				'color'  => $color,
			);
		}

		$this->flat_datapoints[ $dataset_identifier ]['labels'][] = esc_html( $xaxis_label );
		$this->flat_datapoints[ $dataset_identifier ]['values'][] = floatval( $value );

		return '';
	}

	/**
	 * Render flat array table.
	 *
	 * @param array $labels Chart labels array.
	 * @param array $datasets Chart datasets array.
	 * @param array $settings Element settings.
	 */
	public function render_flat_array_table( $labels, $datasets, $settings ) {

		$html = '';

		// Build thead with X-axis labels as columns.
		$html .= '<thead><tr>';

		foreach ( $labels as $label ) {
			$html .= '<th class="label">' . esc_html( $label ) . '</th>';
		}

		$html .= '</tr></thead>';

		// Build tbody with datasets as rows.
		$html .= '<tbody>';

		foreach ( $datasets as $dataset ) {
			$html .= '<tr>';

			// First cell is the legend (use legend setting or dataset label as fallback).
			$html .= '<td class="legend"';

			// Add color data attribute if dynamic colors enabled.
			if ( isset( $settings['maybeDynamicColors'] ) && 'dynamic' === $settings['maybeDynamicColors'] && ! empty( $dataset['color'] ) ) {
				$html .= ' data-set-color="' . esc_attr( $dataset['color'] ) . '"';
			}

			$html .= '>';
			$html .= esc_html( isset( $dataset['legend'] ) ? $dataset['legend'] : $dataset['label'] );
			$html .= '</td>';

			// Output data values for each X-axis point.
			foreach ( $dataset['data'] as $value ) {
				$html .= '<td>';
				$html .= esc_html( $value );
				$html .= '</td>';
			}

			$html .= '</tr>';
		}

		$html .= '</tbody>';

		return $html;
	}
}