<?php
/**
 * Table of Contents element.
 *
 * @package BricksExtras
 */

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

/**
 * Table of Contents element class.
 */
class X_Table_Of_Contents extends \Bricks\Element {

	/**
	 * Element category.
	 *
	 * @var string
	 */
	public $category = 'extras';
	/**
	 * Element name.
	 *
	 * @var string
	 */
	public $name = 'xtableofcontents';
	/**
	 * Element icon.
	 *
	 * @var string
	 */
	public $icon = 'ti-layout-list-post';
	/**
	 * CSS selector.
	 *
	 * @var string
	 */
	public $css_selector = '';

	/**
	 * Get element label.
	 */
	public function get_label() {
		return esc_html__( 'Table of contents', 'bricksextras' );
	}

	/**
	 * Get element keywords.
	 */
	public function get_keywords() {
		return array( 'toc', 'table of contents', 'contents' );
	}

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

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

		$this->control_groups['listItems'] = array(
			'title' => esc_html__( 'List items', 'bricks' ),
			'tab'   => 'content',
		);

		$this->control_groups['counterGroup'] = array(
			'title'    => esc_html__( 'Counter', 'bricks' ),
			'tab'      => 'content',
			'required' => array( 'listType', '=', 'counter' ),
		);

		$this->control_groups['borderGroup'] = array(
			'title'    => esc_html__( 'Border', 'bricks' ),
			'tab'      => 'content',
			'required' => array( 'listType', '=', 'border' ),
		);

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

		$this->control_groups['conditionalDisplay'] = array(
			'title' => esc_html__( 'Conditional display', 'bricksextras' ),
			'tab'   => 'content',
		);
	}


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

		$this->controls['contentSelector'] = array(
			'tab'            => 'content',
			'type'           => 'text',
			'label'          => esc_html__( 'Content selector', 'bricks' ),
			'placeholder'    => '.your-class-here',
			'hasDynamicData' => false,
			'inline'         => true,
		);

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

		$this->controls['headingSelectors'] = array(
			'tab'         => 'content',
			'type'        => 'select',
			'multiple'    => true,
			'inline'      => true,
			'options'     => array(
				'h1' => 'h1',
				'h2' => 'h2',
				'h3' => 'h3',
				'h4' => 'h4',
				'h5' => 'h5',
				'h6' => 'h6',
			),
			'placeholder' => array( 'h2', 'h3', 'h4', 'h5' ),
			'label'       => esc_html__( 'Heading selectors', 'bricks' ),
		);

		$this->controls['ignoreSelector'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Ignore selector', 'bricks' ),
			'type'           => 'text',
			'inline'         => true,
			'placeholder'    => '.ignore-class',
			'hasDynamicData' => false,
		);

		$this->controls['tag'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'HTML tag', 'bricks' ),
			'type'        => 'select',
			'options'     => array(
				'div'   => 'div',
				'nav'   => 'nav',
				'aside' => 'aside',
			),
			'inline'      => true,
			'clearable'   => false,
			'placeholder' => 'nav',
			'default'     => 'nav',
		);

		$this->controls['collapseDepth'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Collapse depth', 'bricksextras' ),
			'type'        => 'number',
			'min'         => 0,
			'max'         => 5,
			'step'        => 1,
			'units'       => false,
			'small'       => true,
			'inline'      => true,
			'placeholder' => '0',
			'default'     => 0,
		);

		$this->controls['listType'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Type', 'bricks' ),
			'type'        => 'select',
			'options'     => array(
				'counter' => esc_html__( 'Counter', 'bricks' ),
				'border'  => esc_html__( 'Border', 'bricks' ),
				'text'    => esc_html__( 'Text', 'bricks' ),
			),
			'inline'      => true,
			'clearable'   => false,
			'placeholder' => esc_html__( 'Text', 'bricks' ),
		);

		$this->controls['conditionalDisplay'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Conditional display', 'bricksextras' ),
			'type'        => 'select',
			'group'       => 'conditionalDisplay',
			'options'     => array(
				'enable'  => esc_html__( 'Enable', 'bricks' ),
				'disable' => esc_html__( 'Disable', 'bricks' ),
			),
			'inline'      => true,
			'clearable'   => false,
			'placeholder' => esc_html__( 'Disable', 'bricks' ),
		);

		$this->controls['conditionalDisplayValue'] = array(
			'tab'         => 'content',
			'group'       => 'conditionalDisplay',
			'label'       => esc_html__( 'Minimum headings found to display', 'bricksextras' ),
			'type'        => 'number',
			'units'       => false,
			'inline'      => true,
			'small'       => true,
			'required'    => array( 'conditionalDisplay', '=', 'enable' ),
			'placeholder' => '1',
		);

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

		$this->controls['closePageLoad'] = array(
			'tab'    => 'content',
			'inline' => true,
			'small'  => true,
			'label'  => esc_html__( 'Always closed on page load', 'bricksextras' ),
			'type'   => 'checkbox',
		);

		$this->controls['closeBreakpoint'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Close at this breakpoint', 'bricksextras' ),
			'type'        => 'select',
			'options'     => array(
				'true'  => esc_html__( 'True', 'bricks' ),
				'false' => esc_html__( 'False', 'bricks' ),
			),
			'breakpoints' => true,
			'inline'      => true,
			'small'       => true,
			'placeholder' => esc_html__( 'False', 'bricks' ),
			'required'    => array( 'closePageLoad', '!=', true ),
			'css'         => array(
				array(
					'selector' => '.x-toc_body',
					'property' => '--x-toc-close',
					'value'    => 'var(--x-toc-close-%s)',
				),
			),
		);

		/* list items */

		$this->controls['subitemsIdent'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Indent', 'bricks' ),
			'type'        => 'number',
			'small'       => true,
			'group'       => 'listItems',
			'css'         => array(
				array(
					'selector' => '.x-toc_list .x-toc_list',
					'property' => 'padding-inline-start',
				),
			),
			'units'       => true,
			'placeholder' => '10',
		);

		$this->controls['columnCount'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Column count', 'bricksextras' ),
			'type'        => 'number',
			'group'       => 'listItems',
			'step'        => '1',
			'inline'      => true,
			'placeholder' => '0',
			'css'         => array(
				array(
					'property' => 'column-count',
					'selector' => '&:not([data-x-toc*=border]) .x-toc_body > .x-toc_list',
				),
			),
			'required'    => array( 'listType', '!=', 'border' ),
		);

		$this->controls['columnGap'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Column gap', 'bricks' ),
			'type'        => 'number',
			'group'       => 'listItems',
			'units'       => array(
				'px' => array(
					'min'  => 1,
					'max'  => 30,
					'step' => 1,
				),
				'em' => array(
					'min'  => 1,
					'max'  => 20,
					'step' => 0.1,
				),
			),
			'inline'      => true,
			'placeholder' => '0',
			'css'         => array(
				array(
					'property' => 'column-gap',
					'selector' => '&:not([data-x-toc*=border]) .x-toc_body > .x-toc_list',
				),
			),
			'required'    => array( 'listType', '!=', 'border' ),
		);

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

		$this->controls['itemTypography'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ),
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link',
				),
			),
		);

		$this->controls['itemTypographyActive'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ) . ' (' . esc_html__( 'Active', 'bricks' ) . ')',
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link.x-toc_active-link',
				),
			),
		);

		$this->controls['itemTypographyH2'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ) . ' (h2)',
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link.node-name--H2',
				),
			),
		);
		$this->controls['itemTypographyH3'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ) . ' (h3)',
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link.node-name--H3',
				),
			),
		);
		$this->controls['itemTypographyH4'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ) . ' (h4)',
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link.node-name--H4',
				),
			),
		);
		$this->controls['itemTypographyH5'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ) . ' (h5)',
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link.node-name--H5',
				),
			),
		);
		$this->controls['itemTypographyH6'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ) . ' (h6)',
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '.x-toc_link.node-name--H6',
				),
			),
		);

		$this->controls['linkSep'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'separator',
			'label' => esc_html__( 'Links', 'bricks' ),
		);

		$this->controls['linkBackground'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'color',
			'label' => esc_html__( 'Background color', 'bricks' ),
			'css'   => array(
				array(
					'property' => 'background-color',
					'selector' => '.x-toc_link',
				),
			),
		);

		$this->controls['linkBackgroundActive'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'color',
			'label' => esc_html__( 'Background color', 'bricks' ) . ' (' . esc_html__( 'Active', 'bricks' ) . ')',
			'css'   => array(
				array(
					'property' => 'background-color',
					'selector' => '.x-toc_link.x-toc_active-link',
				),
			),
		);

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

		$this->controls['linkPadding'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'label' => esc_html__( 'Padding', 'bricks' ),
			'type'  => 'spacing',
			'css'   => array(
				array(
					'property' => 'padding',
					'selector' => '.x-toc_link',
				),
			),
		);

		$this->controls['linkMargin'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'label' => esc_html__( 'Margin', 'bricks' ),
			'type'  => 'spacing',
			'css'   => array(
				array(
					'property' => 'margin',
					'selector' => '.x-toc_link',
				),
			),
		);

		$this->controls['tableBodySep'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'type'  => 'separator',
			'label' => esc_html__( 'List', 'bricks' ),
		);

		$this->controls['tableBodyPadding'] = array(
			'tab'   => 'content',
			'group' => 'listItems',
			'label' => esc_html__( 'Padding', 'bricks' ),
			'type'  => 'spacing',
			'css'   => array(
				array(
					'property' => 'padding',
					'selector' => '.x-toc_body > .x-toc_list',
				),
			),
		);

		/* icon counter border */

		$this->controls['nestCounters'] = array(
			'tab'    => 'content',
			'inline' => true,
			'group'  => 'counterGroup',
			'small'  => true,
			'label'  => esc_html__( 'Prevent nested counters', 'bricksextras' ),
			'type'   => 'checkbox',
		);

		$list_style_type_options = array(
			'decimal'              => 'decimal (1, 2, 3)',
			'decimal-leading-zero' => 'decimal-leading-zero (01, 02, 03)',
			'lower-roman'          => 'lower-roman (i ii iii)',
			'upper-roman'          => 'upper-roman (I II III)',
			'lower-alpha'          => 'lower-alpha (a b c)',
			'upper-alpha'          => 'upper-alpha (A B C)',
			'disc'                 => 'disc',
			'circle'               => 'circle',
			'none',
		);

		$this->controls['listStyleType'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'List style type', 'bricksextras' ),
			'group'       => 'counterGroup',
			'type'        => 'select',
			'options'     => $list_style_type_options,
			'inline'      => true,
			'placeholder' => 'decimal',
			'css'         => array(
				array(
					'property' => '--x-toc-type',
					'selector' => '.x-toc_link',
				),
			),
		);

		$this->controls['listStyleTypeTwo']   = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'List style type', 'bricksextras' ),
			'group'       => 'counterGroup',
			'type'        => 'select',
			'options'     => $list_style_type_options,
			'inline'      => true,
			'placeholder' => 'decimal',
			'css'         => array(
				array(
					'property' => '--x-toc-typetwo',
					'selector' => '.x-toc_link',
				),
			),
		);
		$this->controls['listStyleTypeThree'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'List style type', 'bricksextras' ),
			'group'       => 'counterGroup',
			'type'        => 'select',
			'options'     => $list_style_type_options,
			'inline'      => true,
			'placeholder' => 'decimal',
			'css'         => array(
				array(
					'property' => '--x-toc-typethree',
					'selector' => '.x-toc_body',
				),
			),
		);

		$this->controls['listStyleTypeFour'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'List style type', 'bricksextras' ),
			'group'       => 'counterGroup',
			'type'        => 'select',
			'options'     => $list_style_type_options,
			'inline'      => true,
			'placeholder' => 'decimal',
			'css'         => array(
				array(
					'property' => '--x-toc-typefour',
					'selector' => '.x-toc_body',
				),
			),
		);

		$this->controls['counterSeperator'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Separator', 'bricks' ),
			'group'          => 'counterGroup',
			'type'           => 'text',
			'inline'         => true,
			'placeholder'    => '.',
			'css'            => array(
				array(
					'property' => '--x-toc-seperator',
					'selector' => '.x-toc_body',
				),
			),
			'hasDynamicData' => false,
		);

		$this->controls['counterSuffix'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Suffix', 'bricks' ),
			'group'          => 'counterGroup',
			'type'           => 'text',
			'inline'         => true,
			'placeholder'    => '',
			'css'            => array(
				array(
					'property' => '--x-toc-suffix',
					'selector' => '.x-toc_body',
				),
			),
			'hasDynamicData' => false,
		);

		$this->controls['counterTypograpphy'] = array(
			'tab'   => 'content',
			'group' => 'counterGroup',
			'type'  => 'typography',
			'label' => esc_html__( 'Typography', 'bricks' ),
			'css'   => array(
				array(
					'property' => 'font',
					'selector' => '&[data-x-toc*=counter] .x-toc_link::before',
				),
			),
		);

		$this->controls['listBorder'] = array(
			'tab'   => 'content',
			'group' => 'borderGroup',
			'type'  => 'color',
			'label' => esc_html__( 'Border', 'bricks' ),
			'css'   => array(
				array(
					'property' => 'background-color',
					'selector' => '&[data-x-toc*=border] .x-toc_link::before',
				),
			),
		);

		$this->controls['listBorderActive'] = array(
			'tab'   => 'content',
			'group' => 'borderGroup',
			'type'  => 'color',
			'label' => esc_html__( 'Active border', 'bricks' ),
			'css'   => array(
				array(
					'property' => 'background-color',
					'selector' => '&[data-x-toc*=border] .x-toc_link.x-toc_active-link::before',
				),
			),
		);

		$this->controls['borderWidth'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Border width', 'bricks' ),
			'type'        => 'number',
			'group'       => 'borderGroup',
			'units'       => array(
				'px' => array(
					'min'  => 1,
					'max'  => 30,
					'step' => 1,
				),
				'em' => array(
					'min'  => 1,
					'max'  => 20,
					'step' => 0.1,
				),
			),
			'inline'      => true,
			'placeholder' => '2px',
			'css'         => array(
				array(
					'property' => 'width',
					'selector' => '&[data-x-toc*=border] .x-toc_link::before',
				),
			),
		);

		/* table header */

		$header_selector = '.x-toc_header';

		$this->controls['maybe_remove_header'] = array(
			'tab'   => 'content',
			'label' => esc_html__( 'Disable', 'bricks' ),
			'type'  => 'checkbox',
			'group' => 'tableHeading',
		);

		$this->controls['headerText'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Text', 'bricks' ),
			'group'          => 'tableHeading',
			'type'           => 'text',
			'inline'         => true,
			'hasDynamicData' => false,
			'placeholder'    => esc_html__( 'Table of contents', 'bricks' ),
			'default'        => esc_html__( 'Table of contents', 'bricks' ),
			'required'       => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headerAriaLabel'] = array(
			'tab'            => 'content',
			'label'          => 'aria-label',
			'group'          => 'tableHeading',
			'type'           => 'text',
			'inline'         => true,
			'hasDynamicData' => false,
			'placeholder'    => esc_html__( 'Table of contents', 'bricks' ),
			'default'        => esc_html__( 'Table of contents', 'bricks' ),
			'required'       => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['header_icon'] = array(
			'tab'      => 'content',
			'group'    => 'tableHeading',
			'label'    => esc_html__( 'Icon', 'bricks' ),
			'type'     => 'icon',
			'css'      => array(
				array(
					'selector' => '&.icon-svg',
				),
			),
			'default'  => array(
				'library' => 'themify',
				'icon'    => 'ti-angle-down',
			),
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headerIconSize'] = array(
			'tab'      => 'content',
			'label'    => esc_html__( 'Icon size', 'bricks' ),
			'type'     => 'number',
			'group'    => 'tableHeading',
			'units'    => array(
				'px' => array(
					'min'  => 1,
					'max'  => 30,
					'step' => 1,
				),
				'em' => array(
					'min'  => 1,
					'max'  => 20,
					'step' => 0.1,
				),
			),
			'inline'   => true,
			'css'      => array(
				array(
					'property' => 'font-size',
					'selector' => '.x-toc_header-icon',
				),
			),
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['slideDuration'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Duration', 'bricks' ) . ' (ms)',
			'description' => esc_html__( 'Reveal animation', 'bricks' ),
			'group'       => 'tableHeading',
			'type'        => 'number',
			'min'         => 0,
			'max'         => 1000,
			'inline'      => true,
			'placeholder' => esc_html__( '300', 'bricks' ),
			'required'    => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headerBackground'] = array(
			'tab'      => 'content',
			'group'    => 'tableHeading',
			'type'     => 'background',
			'label'    => esc_html__( 'Background', 'bricks' ),
			'css'      => array(
				array(
					'property' => 'background',
					'selector' => $header_selector,
				),
			),
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headerTypography'] = array(
			'tab'      => 'content',
			'group'    => 'tableHeading',
			'type'     => 'typography',
			'label'    => esc_html__( 'Typography', 'bricks' ),
			'css'      => array(
				array(
					'property' => 'font',
					'selector' => $header_selector,
				),
			),
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headerBorder'] = array(
			'tab'      => 'content',
			'group'    => 'tableHeading',
			'type'     => 'border',
			'label'    => esc_html__( 'Border', 'bricks' ),
			'css'      => array(
				array(
					'property' => 'border',
					'selector' => $header_selector,
				),
			),
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headingsep'] = array(
			'tab'      => 'content',
			'group'    => 'tableHeading',
			'type'     => 'separator',
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['headingPadding'] = array(
			'tab'      => 'content',
			'group'    => 'tableHeading',
			'label'    => esc_html__( 'Padding', 'bricks' ),
			'type'     => 'spacing',
			'css'      => array(
				array(
					'property' => 'padding',
					'selector' => $header_selector,
				),
			),
			'required' => array( 'maybe_remove_header', '!=', true ),
		);

		$this->controls['smoothScroll'] = array(
			'tab'         => 'content',
			'group'       => 'behaviour',
			'label'       => esc_html__( 'Smooth scroll', 'bricks' ),
			'description' => esc_html__( 'Disable if prefer to rely on Bricks smooth scroll or another solution', 'bricksextras' ),
			'type'        => 'select',
			'options'     => array(
				'true'  => esc_html__( 'Enable', 'bricks' ),
				'false' => esc_html__( 'Disable', 'bricks' ),
			),

			'placeholder' => esc_html__( 'Enable', 'bricks' ),
			'clearable'   => false,
		);

		$this->controls['smoothScrollOffset'] = array(
			'tab'         => 'content',
			'label'       => esc_html__( 'Offset', 'bricks' ) . ' (px)',
			'type'        => 'number',
			'group'       => 'behaviour',
			'min'         => 0,
			'max'         => 1000,
			'step'        => '1',
			'inline'      => true,
			'placeholder' => '0',
		);

		$this->controls['autoID'] = array(
			'tab'   => 'content',
			'group' => 'behaviour',
			'label' => esc_html__( 'Automatically add unique IDs to headings', 'bricksextras' ),
			'type'  => 'checkbox',
		);

		$this->controls['autoIDText'] = array(
			'tab'         => 'content',
			'group'       => 'behaviour',
			'label'       => esc_html__( 'Heading IDs', 'bricksextras' ),
			'type'        => 'select',
			'options'     => array(
				'prefix' => esc_html__( 'Prefix', 'bricks' ),
				'text'   => esc_html__( 'Use heading text', 'bricksextras' ),
			),
			'inline'      => true,
			'placeholder' => esc_html__( 'Prefix', 'bricks' ),
			'clearable'   => false,
			'required'    => array( 'autoID', '=', true ),
		);

		$this->controls['idPrefix'] = array(
			'tab'            => 'content',
			'label'          => esc_html__( 'Prefix', 'bricks' ),
			'group'          => 'behaviour',
			'type'           => 'text',
			'inline'         => true,
			'hasDynamicData' => false,
			'placeholder'    => 'heading-',
			'required'       => array(
				array( 'autoID', '=', true ),
				array( 'autoIDText', '!=', 'text' ),
			),
		);
	}


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

		if ( bricks_is_builder_main() ) {
			return;
		}

		// Enqueue Bricks' tocbot library.
		wp_enqueue_script( 'bricks-tocbot' );

		// Conditionally enqueue slugify if using auto ID with heading text.
		$dependencies = array( 'x-frontend', 'bricks-tocbot' );
		if ( isset( $this->settings['autoID'] ) && isset( $this->settings['autoIDText'] ) && 'text' === $this->settings['autoIDText'] ) {
			wp_enqueue_script( 'slugify', BRICKSEXTRAS_URL . 'components/assets/js/slugify.min.js', array(), '1.6.6', true );
			$dependencies[] = 'slugify';
		}

		wp_enqueue_script( 'x-toc', BRICKSEXTRAS_URL . 'components/assets/js/' . \BricksExtras\Helpers::maybe_minify_scripts( 'tableofcontents' ) . '.js', $dependencies, \BricksExtras\Plugin::VERSION, true );

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

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

		$tag = isset( $this->settings['tag'] ) ? \Bricks\Helpers::sanitize_html_tag( $this->settings['tag'], 'nav' ) : 'nav';

		$aria_label = isset( $this->settings['headerAriaLabel'] ) ? esc_attr( $this->settings['headerAriaLabel'] ) : esc_attr__( 'Table of contents', 'bricksextras' );

		$header_icon     = empty( $this->settings['header_icon'] ) ? false : self::render_icon( $this->settings['header_icon'] );
		$close_page_load = isset( $this->settings['closePageLoad'] );

		$toc_config = array(
			'contentSelector'         => isset( $this->settings['contentSelector'] ) ? $this->settings['contentSelector'] : '',
			'headingSelectors'        => isset( $this->settings['headingSelectors'] ) ? $this->settings['headingSelectors'] : 'h2,h3,h4,h5',
			'autoID'                  => isset( $this->settings['autoID'] ) ? true : false,
			'idPrefix'                => isset( $this->settings['idPrefix'] ) ? $this->settings['idPrefix'] : 'heading',
			'autoIDText'              => isset( $this->settings['autoIDText'] ) ? $this->settings['autoIDText'] : 'prefix',
			'scrollSmoothOffset'      => isset( $this->settings['smoothScrollOffset'] ) ? 0 - intval( $this->settings['smoothScrollOffset'] ) : 0,
			'listType'                => isset( $this->settings['listType'] ) ? $this->settings['listType'] : 'counter',
			'slideDuration'           => isset( $this->settings['slideDuration'] ) ? $this->settings['slideDuration'] : 300,
			'ignoreSelector'          => isset( $this->settings['ignoreSelector'] ) ? $this->settings['ignoreSelector'] : '',
			'smoothScroll'            => isset( $this->settings['smoothScroll'] ) ? $this->settings['smoothScroll'] : 'true',
			'collapseDepth'           => isset( $this->settings['collapseDepth'] ) ? intval( $this->settings['collapseDepth'] ) : 0,
			'conditionalDisplay'      => isset( $this->settings['conditionalDisplay'] ) ? $this->settings['conditionalDisplay'] : 'disable',
			'conditionalDisplayValue' => isset( $this->settings['conditionalDisplayValue'] ) ? intval( $this->settings['conditionalDisplayValue'] ) : 1,
			'hidden'                  => array(
				'closeBreakpoint' => ! empty( $this->settings['closeBreakpoint'] ) ? $this->settings['closeBreakpoint'] : 'false',
			),
		);

		if ( isset( $this->settings['nestCounters'] ) ) {
			$toc_config += array( 'nestCounters' => 'true' );
		}

		$breakpoints = array();

		foreach ( \Bricks\Breakpoints::$breakpoints as $breakpoint ) {
			foreach ( array_keys( $toc_config['hidden'] ) as $option ) {
				$setting_key      = "$option:{$breakpoint['key']}";
				$breakpoint_width = ! empty( $breakpoint['width'] ) ? $breakpoint['width'] : false;
				$setting_value    = isset( $this->settings[ $setting_key ] ) ? $this->settings[ $setting_key ] : false;

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

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

		$identifier = \BricksExtras\Helpers::generate_unique_identifier( $this->element, $this->id );

		$this->set_attribute( 'x-toc_header', 'class', 'x-toc_header' );
		$this->set_attribute( 'x-toc_header', 'role', 'button' );
		$this->set_attribute( 'x-toc_header', 'tabindex', '0' );
		$this->set_attribute( 'x-toc_header', 'aria-label', $aria_label );
		$this->set_attribute( 'x-toc_header', 'aria-controls', 'x-toc_' . $identifier );

		if ( $close_page_load ) {
			$this->set_attribute( 'x-toc_header', 'aria-expanded', 'false' );
			$this->set_attribute( 'x-toc_body', 'style', 'display:none' );
		} else {
			$this->set_attribute( 'x-toc_header', 'aria-expanded', 'true' );
		}

		$this->set_attribute( 'x-toc_header-text', 'class', 'x-toc_header-text' );

		$this->set_attribute( 'x-toc_body', 'class', 'x-toc_body' );
		$this->set_attribute( 'x-toc_body', 'aria-hidden', 'false' );
		$this->set_attribute( 'x-toc_body', 'id', 'x-toc_' . $identifier );

		$this->set_attribute( 'x-toc_header-icon', 'class', 'x-toc_header-icon' );

		$this->set_attribute( '_root', 'data-x-toc', wp_json_encode( $toc_config ) );

		$output = '';

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

		if ( ! isset( $this->settings['maybe_remove_header'] ) ) {

			$output .= "<div {$this->render_attributes( 'x-toc_header' )}><div {$this->render_attributes( 'x-toc_header-text' )}>";
			$output .= isset( $this->settings['headerText'] ) ? esc_html( $this->settings['headerText'] ) : esc_html__( 'Table of contents', 'bricksextras' );
			$output .= '</div>';
			$output .= $header_icon ? "<div {$this->render_attributes( 'x-toc_header-icon' )}>" . $header_icon . '</div>' : '';
			$output .= '</div>';

		}

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

		$output .= '</' . $tag . '>';

		echo $output;
	}

	/**
	 * Render builder template.
	 */
	public static function render_builder() {
		?>

		<script type="text/x-template" id="tmpl-bricks-element-xtableofcontents">
			<component
				class=brxe-xtableofcontents
				:is="tag"
				:data-x-toc="(settings.nestCounters ? 'nestCounters' : '') + settings.listType"
			>

			<div 
				class="x-toc_header" 
				role=button 
				:aria-expanded="!settings.closePageLoad ? 'true' : 'false'"
				v-show="!settings.maybe_remove_header"
			>
				<contenteditable
					tag="div"
					class="x-toc_header-text"
					:name="name"
					controlKey="headerText"
					toolbar="style"
					:settings="settings"
					placeholder="Table of Contents"
				/>
				<div class="x-toc_header-icon">
				<icon-svg 
					:iconSettings="settings.header_icon"
				/>
					</div>
				</div>
			<div 
				class="x-toc_body x-toc_body_builder"
				v-show="!settings.closePageLoad"
			>
						<ol class="x-toc_list ">
							<li v-show="5 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
								<a href="#one" class="x-toc_link x-toc_active-link node-name--H2">Primary item (h2)</a>
								<ol class="x-toc_list ">
									<li v-show="4 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
										<a href="#two" class="x-toc_link node-name--H3 ">Sub item (h3)</a>
									</li>
								</ol>
							</li>
							<li v-show="5 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item"><a href="#four" class="x-toc_link node-name--H2 ">Primary item (h2)</a>
								<ol class="x-toc_list ">
									<li v-show="4 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item"><a href="#five" class="x-toc_link node-name--H3 ">Sub item (h3)</a></li>
									<li v-show="4 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item"><a href="#six" class="x-toc_link node-name--H3 ">Sub item (h3)</a>
										<ol class="x-toc_list ">
											<li v-show="3 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
												<a href="#two" class="x-toc_link node-name--H4 ">Sub item (h4)</a>
												<ol class="x-toc_list ">
													<li v-show="2 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
														<a href="#two" class="x-toc_link node-name--H5 ">Sub item (h5)</a>
														<ol class="x-toc_list ">
															<li v-show="1 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
																<a href="#two" class="x-toc_link node-name--H5 ">Sub item (h6)</a>
															</li>
														</ol>
													</li>
												</ol>
											</li>
											<li v-show="3 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
												<a href="#two" class="x-toc_link node-name--H4 ">Sub item (h4)</a>
												<ol class="x-toc_list ">
													<li v-show="2 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
														<a href="#two" class="x-toc_link node-name--H5 ">Sub item (h5)</a>
														<ol class="x-toc_list ">
															<li v-show="1 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
																<a href="#two" class="x-toc_link node-name--H5 ">Sub item (h6)</a>
															</li>
														</ol>
													</li>
												</ol>
											</li>
										</ol>
									</li>
								</ol>
							</li>
							<li v-show="5 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
								<a href="#one" class="x-toc_link node-name--H2">Primary item (h2)</a>
								<ol class="x-toc_list ">
									<li v-show="4 > settings.collapseDepth || !settings.collapseDepth" class="x-toc_list-item">
										<a href="#two" class="x-toc_link node-name--H3 ">Sub item (h3)</a>
									</li>
								</ol>
							</li>
						</ol>
				</div>
			</component>	
		</script>

		<?php
	}
}