<!--
 This file is generated by o-spreadsheet build tools. Do not edit it.
 @see https://github.com/odoo/o-spreadsheet
 @version 19.1.4
 @date 2026-01-21T11:08:11.909Z
 @hash ceae12a
-->
<odoo>
  <t t-name="o-spreadsheet-ValidationMessages">
    <t t-foreach="alertBoxes" t-as="box" t-key="'box' + box_index">
      <div t-att-class="divClasses" class="d-flex flex-column p-3 m-1 o-validation">
        <div class="d-flex align-items-center">
          <t t-if="props.msgType === 'info'" t-call="o-spreadsheet-Icon.CIRCLE_INFO"/>
          <t t-else="" t-call="o-spreadsheet-Icon.TRIANGLE_EXCLAMATION"/>
          <div class="d-flex flex-column overflow-hidden">
            <span
              t-foreach="box"
              t-as="msg"
              t-key="msg_index"
              class="ps-2"
              t-att-class="{'text-truncate': props.singleBox }"
              t-esc="msg"
            />
          </div>
        </div>
      </div>
    </t>
  </t>

  <t t-name="o-spreadsheet-TopBar">
    <div
      class="o-spreadsheet-topbar d-flex flex-column user-select-none bg-white"
      t-on-click="props.onClick">
      <div t-if="!env.isSmall" class="o-topbar-top d-flex justify-content-between border-bottom">
        <!-- Menus -->
        <div class="o-topbar-topleft d-flex">
          <t t-foreach="menus" t-as="menu" t-key="menu_index">
            <div
              t-if="menu.children.length !== 0"
              class="o-topbar-menu o-hoverable-button text-nowrap rounded"
              t-att-class="{'active': state.menuState.parentMenu and state.menuState.parentMenu.id === menu.id}"
              t-on-click="(ev) => this.toggleContextMenu(menu, ev)"
              t-on-mouseover="(ev) => this.onMenuMouseOver(menu, ev)"
              t-att-data-id="menu.id">
              <t t-esc="getMenuName(menu)"/>
            </div>
          </t>
        </div>
        <div class="o-topbar-topright d-flex justify-content-end align-items-center">
          <div t-foreach="topbarComponents" t-as="comp" t-key="comp.id" class="px-1">
            <t t-component="comp.component"/>
          </div>
        </div>
      </div>
      <!-- Toolbar and Cell Content -->
      <div
        class="d-flex o-topbar-responsive"
        t-att-class="{'o-topbar-responsive': !env.model.getters.isReadonly()}"
        t-ref="toolBarContainer">
        <div
          class="o-topbar-toolbar d-flex"
          t-att-class="{'flex-shrink-0': env.model.getters.isReadonly()}">
          <!-- Toolbar -->
          <div
            t-if="env.model.getters.isReadonly()"
            class="o-readonly-toolbar d-flex align-items-center text-muted">
            <span>
              <i class="fa fa-eye"/>
              Readonly Access
            </span>
          </div>
          <div t-else="" class="o-toolbar-tools d-flex ms-4 flex-grow-1" t-ref="toolBar">
            <div
              class="d-flex tool-container"
              t-foreach="toolsCategories"
              t-as="category"
              t-key="category"
              t-att-id="category">
              <t
                t-foreach="toolbarMenuRegistry.getEntries(category)"
                t-as="toolbarAction"
                t-key="toolbarAction_index">
                <t t-component="toolbarAction.component" t-props="toolbarAction.props"/>
              </t>
              <div t-if="showDivider(category_index)" class="o-topbar-divider border-end"/>
            </div>
            <div
              t-ref="moreToolsContainer"
              class="d-flex align-items-center flex-grow-1 me-auto more-tools-container">
              <span
                class="o-toolbar-button o-menu-item-button o-hoverable-button  me-2 px-1 py-2 more-tools"
                t-ref="moreToolsButton"
                t-on-click.stop="toggleMoreTools">
                <t t-call="o-spreadsheet-Icon.SHORT_THIN_DRAG_HANDLE"/>
              </span>
            </div>
          </div>
        </div>
        <TopBarComposer t-if="!env.isSmall"/>
      </div>
      <div
        t-if="this.fingerprints.isEnabled"
        class="topbar-banner irregularity-map d-flex align-items-center justify-content-between border-top">
        <div
          t-on-click="() => this.fingerprints.disable()"
          role="button"
          title="This tool analyzes spreadsheet formulas for patterns and highlights inconsistencies. Irregularities may indicate potential errors in formula structures, references, or arguments. (Click to turn off)"
          class="h-100 d-flex align-items-center text-info px-3">
          <t t-call="o-spreadsheet-Icon.IRREGULARITY_MAP"/>
          Irregularity map
        </div>
        <div
          class="ps-3 h-100 flex-fill d-flex justify-content-between rounded-0 alert alert-info ps-0 py-0 my-0">
          <span class="d-flex align-items-center">
            This tool analyzes formulas for patterns and highlights inconsistencies. Irregularities
            may indicate potential errors in formula structures, references or arguments.
          </span>
          <div
            class="ps-3 btn btn-link flex-shrink-0"
            t-on-click="() => this.fingerprints.disable()">
            Turn off
          </div>
        </div>
      </div>
    </div>
    <MenuPopover
      t-if="state.menuState.isOpen"
      anchorRect="state.menuState.anchorRect"
      menuItems="state.menuState.menuItems"
      onClose="() => this.closeMenus()"
      onMenuClicked="() => this.props.onClick()"
      popoverPositioning="'bottom-left'"
    />
    <Popover t-if="state.toolsPopoverState.isOpen" t-props="toolsPopoverProps">
      <div class="d-flex px-2 py-1 flex-wrap align-items-center bg-white">
        <t
          t-foreach="state.invisibleToolsCategories"
          t-as="category"
          t-key="category"
          t-att-id="category">
          <t
            t-foreach="toolbarMenuRegistry.getEntries(category)"
            t-as="toolbarAction"
            t-key="toolbarAction_index">
            <t t-component="toolbarAction.component" t-props="toolbarAction.props"/>
          </t>
          <div
            t-if="category_index &lt; state.invisibleToolsCategories.length-1"
            class="o-topbar-divider border-end"
          />
        </t>
      </div>
    </Popover>
  </t>

  <div t-name="o-spreadsheet-TopBarZoom" t-ref="buttonRef" t-on-click.stop="">
    <NumberEditor
      currentValue="currentFontSize"
      onValueChange.bind="this.setZoom"
      class="props.class"
      onToggle.bind="this.toggle"
      onFocusInput.bind="this.onFocusInput"
      valueIcon="'%'"
      min="25"
      max="300"
      valueList="valueList"
      title.translate="Zoom"
    />
  </div>

  <div t-name="o-spreadsheet-NumberFormatsTool" t-ref="buttonRef" t-on-click.stop="">
    <ActionButton
      action="formatNumberMenuItemSpec"
      hasTriangleDownIcon="true"
      onClick.bind="toggleMenu"
      class="props.class"
    />
    <MenuPopover
      t-if="isActive"
      anchorRect="state.anchorRect"
      menuItems="state.menuItems"
      onClose="() => {}"
      popoverPositioning="'bottom-left'"
    />
  </div>

  <t t-name="o-spreadsheet-TopBarFontSizeEditor">
    <FontSizeEditor
      currentFontSize="currentFontSize"
      onFontSizeChanged.bind="this.setFontSize"
      class="props.class"
      onToggle.bind="this.onToggle"
      onFocusInput.bind="this.onFocusInput"
    />
  </t>

  <div
    t-name="o-spreadsheet-DropdownAction"
    class="o-dropdown"
    t-ref="actionRef"
    t-on-click.stop="">
    <ActionButton
      action="props.parentAction"
      hasTriangleDownIcon="true"
      onClick.bind="toggleDropdown"
      class="props.class"
    />
    <Popover t-if="isActive" t-props="popoverProps">
      <div class="o-dropdown-content p-1 bg-white" t-if="isActive" t-on-click.stop="">
        <div class="o-dropdown-line">
          <t t-foreach="props.childActions" t-as="action" t-key="action_index">
            <ActionButton action="action" class="props.childClass"/>
          </t>
        </div>
      </div>
    </Popover>
  </div>

  <t t-name="o-spreadsheet-ColorEditor">
    <div class="d-flex align-items-center">
      <ColorPickerWidget
        currentColor="currentColor"
        toggleColorPicker.bind="onClick"
        showColorPicker="isMenuOpen"
        onColorPicked="(color) => this.setColor(color)"
        title="props.title"
        icon="props.icon"
        class="props.class"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-TextInput">
    <div class="position-relative">
      <input
        type="text"
        t-ref="{{refName}}"
        t-att-class="inputClass"
        t-att-id="props.id"
        t-att-placeholder="props.placeholder"
        t-on-change="save"
        t-on-blur="save"
        t-on-pointerdown="onMouseDown"
        t-on-pointerup="onMouseUp"
        t-on-keydown="onKeyDown"
      />
      <span
        t-if="props.errorMessage"
        class="os-input-error-icon text-danger position-absolute d-flex align-items-center"
        t-att-title="props.errorMessage">
        <t t-call="o-spreadsheet-Icon.ERROR"/>
      </span>
    </div>
  </t>

  <t t-name="o-spreadsheet-TableStylesPopover">
    <Popover t-if="props.popoverProps" t-props="props.popoverProps">
      <div
        class="o-table-style-popover d-flex flex-column py-3 bg-white"
        t-ref="tableStyleList"
        t-on-contextmenu.prevent="">
        <div class="d-flex o-notebook ps-4 mb-3">
          <div
            t-foreach="Object.keys(categories)"
            t-as="category"
            t-key="category"
            class="o-notebook-tab d-flex align-items-center border"
            t-att-class="{ 'selected': state.selectedCategory === category }"
            t-on-click="() => state.selectedCategory = category"
            t-att-data-id="category"
            t-esc="categories[category_value]"
          />
        </div>
        <div class="d-flex flex-wrap px-4">
          <t t-foreach="displayedStyles" t-as="styleId" t-key="styleId">
            <TableStylePreview
              class="'o-table-style-popover-preview'"
              styleId="styleId"
              selected="styleId === props.selectedStyleId"
              tableConfig="props.tableConfig"
              tableStyle="env.model.getters.getTableStyle(styleId)"
              onClick="() => this.props.onStylePicked(styleId)"
            />
          </t>
          <div
            t-if="state.selectedCategory === 'custom'"
            class="o-new-table-style o-table-style-list-item o-table-style-popover-preview d-flex justify-content-center align-items-center"
            t-on-click="newTableStyle">
            +
          </div>
        </div>
      </div>
    </Popover>
  </t>

  <t t-name="o-spreadsheet-TableStylePreview">
    <div
      class="o-table-style-list-item position-relative"
      t-att-class="{ 'selected': props.selected }"
      t-att-data-id="props.styleId"
      t-att-title="styleName"
      t-on-click="props.onClick"
      t-on-contextmenu.prevent="(ev) => this.onContextMenu(ev)">
      <div t-att-class="props.class">
        <canvas t-ref="canvas" class="w-100 h-100"/>
      </div>
      <div
        class="o-table-style-edit-button position-absolute d-none bg-white border"
        t-if="isStyleEditable"
        t-on-click="this.editTableStyle"
        title="Edit custom table style">
        <t t-call="o-spreadsheet-Icon.EDIT"/>
      </div>
    </div>
    <MenuPopover
      t-if="menu.isOpen"
      menuItems="menu.menuItems"
      anchorRect="menu.anchorRect"
      onClose.bind="this.closeMenu"
    />
  </t>

  <t t-name="o-spreadsheet-TableStylePicker">
    <div class="o-table-style-picker d-flex flew-row justify-content-between ps-1 border rounded">
      <div class="d-flex flex-row overflow-hidden ps-2">
        <t t-foreach="getDisplayedTableStyles()" t-as="styleId" t-key="styleId">
          <TableStylePreview
            class="'o-table-style-picker-preview'"
            selected="styleId === props.table.config.styleId"
            tableConfig="props.table.config"
            tableStyle="env.model.getters.getTableStyle(styleId)"
            styleId="styleId"
            onClick="() => this.onStylePicked(styleId)"
          />
        </t>
      </div>
      <div
        class="o-table-style-picker-arrow d-flex align-items-center px-1 border-start"
        t-on-click.stop="onArrowButtonClick">
        <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
      </div>
    </div>
    <TableStylesPopover
      tableConfig="props.table.config"
      selectedStyleId="props.table.config.styleId"
      onStylePicked.bind="onStylePicked"
      popoverProps="state.popoverProps"
      closePopover.bind="closePopover"
    />
  </t>

  <t t-name="o-spreadsheet-TableResizer">
    <div
      class="o-table-resizer position-absolute"
      t-att-style="containerStyle"
      t-on-pointerdown="onMouseDown"
    />
  </t>

  <t t-name="o-spreadsheet-TableDropdownButton">
    <div class="o-table-widget d-flex align-item-center" t-att-class="props.class">
      <ActionButton
        action="action"
        hasTriangleDownIcon="true"
        t-on-click="onClick"
        class="'o-hoverable-button'"
      />
    </div>
    <TableStylesPopover
      tableConfig="tableConfig"
      onStylePicked.bind="onStylePicked"
      popoverProps="state.popoverProps"
      closePopover.bind="closePopover"
    />
  </t>

  <t t-name="o-spreadsheet-Spreadsheet">
    <div
      class="o-spreadsheet h-100 w-100"
      t-att-class="getSpreadSheetClasses()"
      t-ref="spreadsheet"
      t-att-style="getStyle()">
      <t t-if="env.isDashboard()">
        <SpreadsheetDashboard getGridSize.bind="getGridSize"/>
        <FullScreenFigure/>
      </t>
      <t t-else="">
        <div class="o-spreadsheet-topbar-wrapper o-two-columns">
          <TopBar onClick="() => this.focusGrid()" dropdownMaxHeight="gridHeight"/>
        </div>
        <div
          class="o-grid-container"
          t-att-class="{'o-two-columns': !sidePanel.isMainPanelOpen}"
          t-att-style="gridContainerStyle"
          t-on-click="this.focusGrid">
          <div class="o-top-left"/>
          <div class="o-column-groups o-zoomable">
            <HeaderGroupContainer layers="colLayers" dimension="'COL'"/>
          </div>
          <div class="o-row-groups o-zoomable">
            <HeaderGroupContainer layers="rowLayers" dimension="'ROW'"/>
          </div>
          <div class="o-group-grid overflow-hidden">
            <Grid exposeFocus="(focus) => this._focusGrid = focus" getGridSize.bind="getGridSize"/>
          </div>
        </div>
        <SidePanels/>
        <div class="o-spreadsheet-bottombar-wrapper o-two-columns overflow-hidden">
          <SmallBottomBar t-if="env.isSmall" onClick="() => this.focusGrid()"/>
          <BottomBar t-else="" onClick="() => this.focusGrid()"/>
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-SmallBottomBar">
    <div class="o-spreadsheet-small-bottom-bar o-two-columns d-flex flex-column overflow-hidden">
      <t t-if="menuState.isOpen">
        <RibbonMenu onClose="() => this.menuState.isOpen=false"/>
      </t>
      <t t-else="">
        <div class="o-small-composer px-2 py-2 position-relative bg-white border">
          <div class="w-100" t-ref="bottombarComposer">
            <Composer t-props="composerProps"/>
            <span
              t-if="showFxIcon"
              class="position-absolute top-50 translate-middle-y ps-2 pe-none">
              <t t-call="o-spreadsheet-Icon.FX_SVG"/>
            </span>
          </div>
          <span
            class="align-items-center d-flex justify-content-center o-selection-button"
            title="confirm edition"
            t-if="this.focus !== 'inactive'"
            t-on-click="() => this.composerStore.stopEdition()">
            <span class="d-flex">
              <t t-call="o-spreadsheet-Icon.CHECK"/>
            </span>
          </span>
        </div>
        <div class="d-flex flex-row mb-1" t-if="this.focus !== 'inactive'">
          <div
            t-foreach="symbols"
            t-as="symbol"
            t-key="symbol_index"
            class="o-spreadsheet-editor-symbol w-100 d-flex justify-content-center align-items-center mx-1"
            t-esc="symbol"
            tabindex="-1"
            t-att-title="symbol"
            t-on-click="() => this.insertSymbol(symbol)"
            composerFocusableElement="true"
          />
        </div>
        <div class="d-flex flex-fill align-items-center bottom-bar-menu border-top border-bottom">
          <Ripple>
            <div class="py-1 px-1 mx-2 ribbon-toggler" t-on-click="toggleRibbon">
              <i class="o-icon fa fa-cog"/>
            </div>
          </Ripple>
          <BottomBar onClick="props.onClick"/>
        </div>
      </t>
    </div>
  </t>

  <div t-name="o-spreadsheet-RibbonMenu">
    <div class="o-ribbon-menu d-flex flex-column" t-ref="menu">
      <div class="o-ribbon-title d-flex py-2 fw-bold">
        <div
          class="o-previous-button px-3 py-1 mx-2 rounded"
          t-on-click="onClickBack"
          t-att-title="backTitle">
          <i class="fa fa-angle-left"/>
        </div>
        <span class="d-flex align-items-center" t-esc="state.title"/>
      </div>
      <div
        class="o-ribbon-menu-wrapper overflow-auto"
        t-ref="container"
        t-on-scroll="updateShadows">
        <Menu t-props="menuProps"/>
      </div>
    </div>
  </div>

  <t t-name="o-spreadsheet-TableStyleEditorPanel">
    <div class="o-table-style-editor-panel">
      <Section title.translate="Style name">
        <input type="text" class="o-input" t-model="state.styleName"/>
      </Section>
      <Section class="'pt-1'" title.translate="Style color">
        <RoundColorPicker
          currentColor="state.primaryColor"
          onColorPicked.bind="onColorPicked"
          disableNoColor="true"
        />
      </Section>
      <Section class="'pt-1'" title.translate="Style template">
        <div class="d-flex flex-wrap">
          <t t-foreach="tableTemplates" t-as="templateName" t-key="templateName">
            <TableStylePreview
              class="'o-table-style-edit-template-preview'"
              selected="templateName === state.selectedTemplateName"
              tableConfig="previewTableConfig"
              tableStyle="computeTableStyle(templateName)"
              onClick="() => this.onTemplatePicked(templateName)"
            />
          </t>
        </div>
      </Section>
      <Section>
        <div class="o-sidePanelButtons">
          <button
            t-if="props.styleId"
            t-on-click="onDelete"
            class="o-delete o-button-danger o-button">
            Delete
          </button>
          <button t-on-click="onCancel" class="o-cancel o-button">Cancel</button>
          <button t-on-click="onConfirm" class="o-confirm o-button primary">Confirm</button>
        </div>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-TablePanel">
    <div class="o-table-panel">
      <Section title.translate="Style options">
        <div class="d-flex flex-row">
          <div class="w-50">
            <div class="d-flex align-items-center">
              <Checkbox
                label="getCheckboxLabel('headerRow')"
                name="'headerRow'"
                value="tableConfig.numberOfHeaders > 0"
                onChange.bind="this.updateHasHeaders"
              />
              <NumberInput
                t-if="tableConfig.numberOfHeaders > 0"
                value="tableConfig.numberOfHeaders"
                class="'o-table-n-of-headers ms-2'"
                min="0"
                onChange.bind="onChangeNumberOfHeaders"
              />
            </div>
            <Checkbox
              label="getCheckboxLabel('totalRow')"
              name="'totalRow'"
              value="tableConfig.totalRow"
              onChange="(val) => this.updateTableConfig('totalRow', val)"
            />
            <Checkbox
              label="getCheckboxLabel('bandedRows')"
              name="'bandedRows'"
              value="tableConfig.bandedRows"
              onChange="(val) => this.updateTableConfig('bandedRows', val)"
            />
            <Checkbox
              label="getCheckboxLabel('hasFilters')"
              name="'hasFilters'"
              value="tableConfig.hasFilters"
              title="hasFilterCheckboxTooltip"
              disabled="!this.canHaveFilters"
              onChange.bind="this.updateHasFilters"
            />
          </div>
          <div>
            <Checkbox
              label="getCheckboxLabel('firstColumn')"
              name="'firstColumn'"
              value="tableConfig.firstColumn"
              onChange="(val) => this.updateTableConfig('firstColumn', val)"
            />
            <Checkbox
              label="getCheckboxLabel('lastColumn')"
              name="'lastColumn'"
              value="tableConfig.lastColumn"
              onChange="(val) => this.updateTableConfig('lastColumn', val)"
            />
            <Checkbox
              label="getCheckboxLabel('bandedColumns')"
              name="'bandedColumns'"
              value="tableConfig.bandedColumns"
              onChange="(val) => this.updateTableConfig('bandedColumns', val)"
            />
          </div>
        </div>
      </Section>
      <Section>
        <TableStylePicker table="props.table"/>
      </Section>
      <Section title.translate="Data range">
        <SelectionInput
          t-key="props.table.type"
          ranges="[this.state.tableXc]"
          hasSingleRange="true"
          isInvalid="this.state.tableZoneErrors.length !== 0"
          onSelectionChanged="(ranges) => this.onRangeChanged(ranges)"
          onSelectionConfirmed.bind="this.onRangeConfirmed"
        />
      </Section>
      <Section class="'pt-0'">
        <Checkbox
          label="getCheckboxLabel('automaticAutofill')"
          name="'automaticAutofill'"
          value="tableConfig.automaticAutofill"
          onChange="(val) => this.updateTableConfig('automaticAutofill', val)"
          className="'mb-1'"
        />
        <div class="d-flex flex-row align-items-center">
          <Checkbox
            label="getCheckboxLabel('isDynamic')"
            name="'isDynamic'"
            value="props.table.type === 'dynamic'"
            onChange.bind="this.updateTableIsDynamic"
            disabled="!this.canBeDynamic"
          />
          <div
            class="o-info-icon d-flex flex-row align-items-center text-muted ms-1"
            t-att-title="dynamicTableTooltip">
            <t t-call="o-spreadsheet-Icon.CIRCLE_INFO"/>
          </div>
        </div>
      </Section>
      <Section>
        <div class="o-sidePanelButtons">
          <button t-on-click="deleteTable" class="o-table-delete o-button o-button-danger">
            Delete table
          </button>
        </div>
      </Section>
      <Section t-if="errorMessages.length">
        <ValidationMessages messages="errorMessages" msgType="'error'"/>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-SplitIntoColumnsPanel">
    <div class="o-split-to-cols-panel">
      <Section title.translate="Separator">
        <select class="o-input mb-3" t-on-change="(ev) => this.onSeparatorChange(ev.target.value)">
          <option
            t-foreach="separators"
            t-as="separator"
            t-key="separator.value"
            t-att-value="separator.value"
            t-esc="separator.name"
            t-att-selected="state.separatorValue === separator.value"
          />
        </select>

        <input
          class="o-input mb-3"
          type="text"
          t-if="state.separatorValue === 'custom'"
          t-att-value="state.customSeparator"
          t-on-input="updateCustomSeparator"
          placeholder="Add any characters or symbol"
        />

        <t t-set="addColumnsLabel">Add new columns to avoid overwriting cells</t>
        <Checkbox
          value="state.addNewColumns"
          label="addColumnsLabel"
          onChange.bind="updateAddNewColumnsCheckbox"
        />
      </Section>
      <Section>
        <div class="o-sidePanelButtons">
          <button
            class="o-button primary"
            t-att-class="{'o-disabled': isConfirmDisabled}"
            t-on-click="confirm">
            Confirm
          </button>
        </div>
      </Section>
      <Section t-if="errorMessages.length || warningMessages.length" class="'pb-0 pt-2'">
        <ValidationMessages messages="errorMessages" msgType="'error'"/>
        <ValidationMessages messages="warningMessages" msgType="'warning'"/>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-SidePanels" t-if="sidePanelStore.isMainPanelOpen">
    <div class="o-sidePanels d-flex overflow-hidden">
      <t t-foreach="panelList" t-as="panel" t-key="panel.key">
        <div t-att-style="panel.style">
          <SidePanel t-key="panel.key" t-props="panel.props"/>
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-SidePanel">
    <t t-if="props.isCollapsed" t-call="o-spreadsheet-SidePanelCollapsed"/>
    <t t-else="" t-call="o-spreadsheet-SidePanelExtended"/>
  </t>

  <t t-name="o-spreadsheet-SidePanelExtended">
    <div class="o-sidePanel h-100 bg-white border-top border-start">
      <div
        class="o-sidePanelHeader d-flex align-items-center justify-content-between border-bottom">
        <div
          t-if="props.onToggleCollapsePanel"
          class="o-collapse-panel o-sidePanelAction rounded"
          t-on-click="props.onToggleCollapsePanel">
          <i class="fa fa-angle-double-right"/>
        </div>
        <div class="o-sidePanelTitle o-fw-bold ms-2" t-esc="getTitle()"/>
        <div
          t-if="props.onTogglePinPanel"
          class="o-pin-panel o-sidePanelAction ms-auto rounded"
          t-att-class="{'active': props.isPinned}"
          t-on-click="props.onTogglePinPanel"
          t-att-title="pinInfoMessage">
          <i class="fa fa-thumb-tack"/>
        </div>
        <div class="o-sidePanelClose o-sidePanelAction rounded" t-on-click="props.onCloseSidePanel">
          ✕
        </div>
      </div>
      <div class="o-sidePanelBody-container d-flex flex-grow-1 ">
        <div class="o-sidePanel-handle-container">
          <div
            class="o-sidePanel-handle"
            t-on-pointerdown="props.onStartHandleDrag"
            t-on-dblclick="props.onResetPanelSize">
            <t t-call="o-spreadsheet-Icon.THIN_DRAG_HANDLE"/>
          </div>
        </div>
        <div class="o-sidePanelBody">
          <t
            t-component="props.panelContent.Body"
            t-props="props.panelProps"
            onCloseSidePanel="props.onCloseSidePanel"
          />
        </div>
        <div class="o-sidePanelFooter" t-if="props.panelContent?.Footer">
          <t t-component="props.panelContent.Footer" t-props="props.panelProps"/>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-SidePanelCollapsed">
    <div
      class="o-sidePanel collapsed w-100 h-100 bg-white"
      t-on-click="props.onToggleCollapsePanel">
      <div class="d-flex flex-column align-items-center">
        <div
          t-if="props.onToggleCollapsePanel"
          class="o-collapse-panel o-sidePanelAction rounded mb-1">
          <i class="fa fa-angle-double-left"/>
        </div>
        <div
          t-if="props.onTogglePinPanel"
          class="o-pin-panel o-sidePanelAction rounded mb-1"
          t-att-class="{'active': props.isPinned}"
          t-on-click.stop="props.onTogglePinPanel"
          t-att-title="pinInfoMessage">
          <i class="fa fa-thumb-tack"/>
        </div>
        <div
          class="o-sidePanelClose o-sidePanelAction rounded mb-1"
          t-on-click.stop="props.onCloseSidePanel">
          ✕
        </div>

        <div class="o-sidePanelTitle o-fw-bold" t-esc="getTitle()"/>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-SettingsPanel">
    <div class="o-settings-panel">
      <Section title.translate="Locale">
        <select class="o-input" t-on-change="(ev) => this.onLocaleChange(ev.target.value)">
          <option
            t-foreach="supportedLocales"
            t-as="locale"
            t-key="locale.code"
            t-att-value="locale.code"
            t-esc="locale.name"
            t-att-selected="currentLocale.code === locale.code"
          />
        </select>
        <div class="o-locale-preview mt-4 p-3 rounded border">
          <div>
            <span class="o-fw-bold me-1">Number:</span>
            <span t-esc="numberFormatPreview"/>
          </div>
          <div>
            <span class="o-fw-bold me-1">Date:</span>
            <span t-esc="dateFormatPreview"/>
          </div>
          <div>
            <span class="o-fw-bold me-1">Date time:</span>
            <span t-esc="dateTimeFormatPreview"/>
          </div>
          <div>
            <span class="o-fw-bold me-1">First day of week:</span>
            <span t-esc="firstDayOfWeek"/>
          </div>
        </div>
      </Section>

      <Section class="'pt-0'">
        <t t-set="message">Those settings affect all users.</t>
        <ValidationMessages messages="[message]" msgType="'info'"/>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-SelectMenu">
    <select
      t-att-class="props.class"
      t-ref="select"
      t-on-pointerdown.stop.prevent=""
      t-on-click="onClick">
      <option selected="true" t-esc="props.selectedValue"/>
    </select>
    <MenuPopover
      t-if="state.isMenuOpen"
      menuItems="props.menuItems"
      anchorRect="menuAnchorRect"
      onClose.bind="onMenuClosed"
      menuId="menuId"
      popoverPositioning="'bottom-left'"
    />
  </t>

  <t t-name="o-spreadsheet-RemoveDuplicatesPanel">
    <div class="o-remove-duplicates">
      <Section>
        <ValidationMessages messages="[selectionStatisticalInformation]" msgType="'info'"/>
      </Section>
      <Section class="'pt-0'">
        <t t-set="dataHasHeaderLabel">Data has header row</t>
        <Checkbox
          name="'dataHasHeader'"
          value="state.hasHeader"
          label="dataHasHeaderLabel"
          onChange.bind="toggleHasHeader"
        />
      </Section>

      <Section class="'pt-0'" title.translate="Columns to analyze">
        <div class="o-checkbox-selection overflow-auto">
          <t t-set="selectAllLabel">Select all</t>
          <Checkbox
            value="isEveryColumnSelected"
            label="selectAllLabel"
            onChange.bind="toggleAllColumns"
          />

          <t t-foreach="Object.keys(state.columns)" t-as="colIndex" t-key="colIndex">
            <Checkbox
              value="state.columns[colIndex]"
              label="getColLabel(colIndex)"
              onChange="() => this.toggleColumn(colIndex)"
            />
          </t>
        </div>
      </Section>

      <Section>
        <div class="o-sidePanelButtons">
          <button
            class="o-button primary"
            t-att-class="{'o-disabled': !canConfirm}"
            t-on-click="onRemoveDuplicates">
            Remove duplicates
          </button>
        </div>
      </Section>
      <Section t-if="errorMessages.length">
        <ValidationMessages messages="errorMessages" msgType="'error'"/>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-PivotTitleSection">
    <Section>
      <t t-set-slot="title">
        <div class="d-flex flex-row justify-content-between align-items-center">
          Name
          <CogWheelMenu items="cogWheelMenuItems"/>
        </div>
      </t>
      <TextInput
        class="'os-pivot-title'"
        value="name"
        onChange.bind="onNameChanged"
        selectContentOnFocus="true"
      />
    </Section>
  </t>

  <t t-name="o-spreadsheet-PivotSidePanel">
    <div class="d-flex flex-column h-100">
      <div class="o-panel d-flex">
        <div
          class="o-sidePanel-tab o-panel-configuration d-flew flex-grow-1 text-center"
          t-att-class="state.panel !== 'configuration' ? 'inactive' : ''"
          t-on-click="switchPanel.bind(this, 'configuration')">
          <i class="fa fa-sliders me-1"/>
          Configuration
        </div>
        <div
          class="o-sidePanel-tab o-panel-design d-flew flex-grow-1 text-center"
          t-att-class="state.panel !== 'design' ? 'inactive' : ''"
          t-on-click="switchPanel.bind(this, 'design')">
          <i class="fa fa-paint-brush me-1"/>
          Design
        </div>
      </div>

      <div class="o-panel-content overflow-y-auto h-100" t-ref="panelContent">
        <div class="h-100" t-att-class="{ 'd-none': state.panel !== 'configuration' }">
          <t t-component="sidePanelEditor" t-props="props"/>
        </div>
        <div t-att-class="state.panel !== 'design' ? 'd-none' : ''">
          <PivotDesignPanel pivotId="props.pivotId"/>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-PivotSpreadsheetSidePanel">
    <t t-set="isReadonly" t-value="env.model.getters.isReadonly()"/>
    <div class="d-flex flex-column h-100 justify-content-between overflow-hidden">
      <div class="h-100 position-relative overflow-x-hidden overflow-y-auto" t-ref="pivotSidePanel">
        <div
          t-att="isReadonly ? ['inert', 1] : []"
          t-att-class="{ 'pe-none opacity-50': isReadonly }">
          <PivotTitleSection pivotId="props.pivotId" flipAxis.bind="flipAxis"/>
          <Section title.translate="Range">
            <SelectionInput
              ranges="ranges"
              required="true"
              isInvalid="shouldDisplayInvalidRangeError"
              hasSingleRange="true"
              onSelectionChanged="(ranges) => this.onSelectionChanged(ranges)"
              onSelectionConfirmed="() => this.onSelectionConfirmed()"
            />
            <span
              class="text-danger sp_range_error_message"
              t-if="shouldDisplayInvalidRangeError"
              t-esc="pivot.invalidRangeMessage"
            />
          </Section>

          <PivotLayoutConfigurator
            t-if="!pivot.isInvalidRange"
            unusedGroupableFields="store.unusedGroupableFields"
            measureFields="store.measureFields"
            unusedGranularities="store.unusedGranularities"
            dateGranularities="store.dateGranularities"
            datetimeGranularities="store.datetimeGranularities"
            definition="definition"
            onDimensionsUpdated.bind="onDimensionsUpdated"
            getScrollableContainerEl.bind="getScrollableContainerEl"
            pivotId="props.pivotId"
          />
        </div>
      </div>
      <PivotDeferUpdate
        t-if="!isReadonly"
        deferUpdate="store.updatesAreDeferred"
        toggleDeferUpdate="(value) => store.deferUpdates(value)"
        isDirty="store.isDirty"
        discard="store.discardPendingUpdate"
        apply="store.applyUpdate"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-PivotDesignPanel">
    <Section class="'o-pivot-design'" title.translate="Display options">
      <div>
        <div class="container-fluid p-0 pt-2">
          <div class="row mb-2 align-items-center">
            <div class="col-6">Max rows:</div>
            <div class="col-6 d-flex align-items-center">
              <NumberInput
                value="pivotStyle.numberOfRows ?? ''"
                class="'o-pivot-n-of-rows'"
                placeholder.translate="e.g. 10"
                onChange="(value) => this.updatePivotStyleNumberProperty(value, 'numberOfRows')"
              />
            </div>
          </div>
          <div class="row mb-2 align-items-center">
            <div class="col-6">Max columns:</div>
            <div class="col-6 d-flex align-items-center">
              <NumberInput
                value="pivotStyle.numberOfColumns ?? ''"
                class="'o-pivot-n-of-columns'"
                placeholder.translate="e.g. 5"
                onChange="(value) => this.updatePivotStyleNumberProperty(value, 'numberOfColumns')"
              />
            </div>
          </div>
          <div class="row mb-2 align-items-center">
            <div class="col-6">Show totals:</div>
            <div class="col-6 d-flex align-items-center">
              <Checkbox
                name="'displayTotals'"
                value="pivotStyle.displayTotals ?? defaultStyle.displayTotals"
                onChange="(val) => this.updatePivotStyleProperty('displayTotals', val)"
              />
            </div>
          </div>
          <div class="row mb-2 align-items-center">
            <div class="col-6">Show column titles:</div>
            <div class="col-6 d-flex align-items-center">
              <Checkbox
                name="'displayColumnHeaders'"
                value="pivotStyle.displayColumnHeaders ?? defaultStyle.displayColumnHeaders"
                onChange="(val) => this.updatePivotStyleProperty('displayColumnHeaders', val)"
              />
            </div>
          </div>
          <div class="row mb-2 align-items-center">
            <div class="col-6">Show measure titles:</div>
            <div class="col-6 d-flex align-items-center">
              <Checkbox
                name="'displayMeasuresRow'"
                value="pivotStyle.displayMeasuresRow ?? defaultStyle.displayMeasuresRow"
                onChange="(val) => this.updatePivotStyleProperty('displayMeasuresRow', val)"
              />
            </div>
          </div>
        </div>
      </div>
    </Section>
  </t>

  <t t-name="o-spreadsheet-PivotMeasureDisplayPanel">
    <Section title.translate="Show measure as:">
      <select
        class="o-pivot-measure-display-type o-input"
        t-on-change="(ev) => this.store.updateMeasureDisplayType(ev.target.value)">
        <t t-foreach="measureDisplayTypeLabels" t-as="measureType" t-key="measureType">
          <option
            t-att-value="measureType"
            t-att-selected="measureType === store.measureDisplay.type"
            t-esc="measureType_value"
          />
        </t>
      </select>
      <div
        class="o-pivot-measure-display-description mt-3 ps-3 border-start"
        t-esc="measureDisplayDescription[store.measureDisplay.type]"
      />
    </Section>

    <Section t-if="store.doesDisplayNeedsField" title.translate="Base field:">
      <div class="o-pivot-measure-display-field w-100 py-1 px-3 border">
        <t t-if="store.fields.length">
          <RadioSelection
            choices="fieldChoices"
            selectedValue="store.measureDisplay.fieldNameWithGranularity"
            name="'baseField'"
            onChange.bind="(val) => store.updateMeasureDisplayField(val)"
            direction="'vertical'"
          />
        </t>
        <t t-else="">
          <div class="text-muted text-center my-3">No active dimension in the pivot</div>
        </t>
      </div>
    </Section>

    <t t-set="values" t-value="store.values"/>
    <Section t-if="store.doesDisplayNeedsValue and values.length" title.translate="Base item:">
      <div class="o-pivot-measure-display-value w-100 py-1 px-3 border">
        <RadioSelection
          choices="values"
          selectedValue="store.measureDisplay.value"
          name="'baseValue'"
          onChange.bind="(val) => store.updateMeasureDisplayValue(val)"
          direction="'vertical'"
        />
      </div>
    </Section>

    <Section>
      <div class="o-sidePanelButtons">
        <button t-on-click="onCancel" class="o-pivot-measure-cancel o-button">Cancel</button>
        <button t-on-click="onSave" class="o-pivot-measure-save o-button primary">Save</button>
      </div>
    </Section>
  </t>

  <t t-name="o-spreadsheet-PivotLayoutConfigurator">
    <div class="pivot-dimensions o-section" t-ref="pivot-dimensions">
      <div
        class="o-fw-bold py-1 d-flex flex-row justify-content-between align-items-center o-section-title">
        Columns
        <AddDimensionButton
          onFieldPicked.bind="addColumnDimension"
          fields="props.unusedGroupableFields"
        />
      </div>
      <t t-foreach="props.definition.columns" t-as="col" t-key="col_index">
        <div
          t-on-pointerdown="(ev) => this.startDragAndDrop(col, ev)"
          t-att-style="dragAndDrop.itemsStyle[col.nameWithGranularity]"
          class="pt-1">
          <PivotDimension dimension="col" onRemoved.bind="removeDimension">
            <t t-set-slot="upper-right-icons">
              <t t-set="errorMessage" t-value="getHugeDimensionErrorMessage(col)"/>
              <i
                t-if="errorMessage"
                class="text-warning fa fa-exclamation-triangle"
                t-att-title="errorMessage"
              />
            </t>

            <PivotDimensionGranularity
              t-if="isDateOrDatetimeField(col)"
              dimension="col"
              onUpdated.bind="this.updateGranularity"
              availableGranularities="props.unusedGranularities[col.fieldName]"
              allGranularities="getGranularitiesFor(col)"
            />
            <PivotDimensionOrder dimension="col" onUpdated.bind="this.updateOrder"/>
            <PivotCustomGroupsCollapsible
              t-if="col.isCustomField"
              pivotId="props.pivotId"
              customField="getCustomField(col)"
              onCustomFieldUpdated="props.onDimensionsUpdated"
            />
          </PivotDimension>
        </div>
      </t>
      <div
        class="o-fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center o-section-title"
        t-att-style="dragAndDrop.itemsStyle['__rows_title__']">
        Rows
        <AddDimensionButton
          onFieldPicked.bind="addRowDimension"
          fields="props.unusedGroupableFields"
        />
      </div>
      <t t-foreach="props.definition.rows" t-as="row" t-key="row_index">
        <div
          t-on-pointerdown="(ev) => this.startDragAndDrop(row, ev)"
          t-att-style="dragAndDrop.itemsStyle[row.nameWithGranularity]"
          class="pt-1">
          <PivotDimension dimension="row" onRemoved.bind="removeDimension">
            <t t-set-slot="upper-right-icons">
              <t t-set="errorMessage" t-value="getHugeDimensionErrorMessage(row)"/>
              <i
                t-if="errorMessage"
                class="text-warning fa fa-exclamation-triangle"
                t-att-title="errorMessage"
              />
            </t>

            <PivotDimensionGranularity
              t-if="isDateOrDatetimeField(row)"
              dimension="row"
              onUpdated.bind="this.updateGranularity"
              availableGranularities="props.unusedGranularities[row.fieldName]"
              allGranularities="getGranularitiesFor(row)"
            />
            <PivotDimensionOrder dimension="row" onUpdated.bind="this.updateOrder"/>
            <PivotCustomGroupsCollapsible
              t-if="row.isCustomField"
              pivotId="props.pivotId"
              customField="getCustomField(row)"
              onCustomFieldUpdated="props.onDimensionsUpdated"
            />
          </PivotDimension>
        </div>
      </t>
      <div
        class="o-fw-bold pt-4 pb-1 d-flex flex-row justify-content-between align-items-center o-section-title o-pivot-measure">
        Measures
        <AddDimensionButton onFieldPicked.bind="addMeasureDimension" fields="props.measureFields">
          <div
            t-on-click="addCalculatedMeasure"
            class="p-2 bg-white border-top d-flex align-items-center sticky-bottom add-calculated-measure">
            <i class="pe-1">
              <t t-call="o-spreadsheet-Icon.FORMULA"/>
            </i>
            Add calculated measure
          </div>
        </AddDimensionButton>
      </div>
      <t t-foreach="props.definition.measures" t-as="measure" t-key="measure.id">
        <div
          t-on-pointerdown="(ev) => this.startDragAndDropMeasures(measure, ev)"
          t-att-style="dragAndDrop.itemsStyle[measure.id]"
          t-att-class="measure.isHidden ? 'opacity-50' : ''"
          class="pt-1 pivot-measure">
          <PivotMeasureEditor
            pivotId="props.pivotId"
            definition="props.definition"
            measure="measure"
            aggregators="AGGREGATORS"
            onRemoved="() => this.removeMeasureDimension(measure)"
            onMeasureUpdated="(newMeasure) => this.updateMeasure(measure, newMeasure)"
            generateMeasureId.bind="getMeasureId"
          />
        </div>
      </t>
    </div>
    <PivotSortSection definition="props.definition" pivotId="props.pivotId"/>
  </t>

  <t t-name="o-spreadsheet-PivotSortSection">
    <Section t-if="hasValidSort" class="'o-pivot-sort'">
      <t t-set-slot="title">Sorting</t>
      <div t-esc="sortDescription" class="pb-2"/>
      <div class="d-flex flex-column gap-2">
        <t t-foreach="sortValuesAndFields" t-as="valueAndField" t-key="valueAndField_index">
          <div class="o-sort-card d-flex gap-1 px-2 border">
            <t t-if="valueAndField.field">
              <span class="fw-bolder" t-esc="valueAndField.field"/>
              =
            </t>
            <span class="fw-bolder o-sort-value" t-esc="valueAndField.value"/>
          </div>
        </t>
      </div>
    </Section>
  </t>

  <t t-name="o-spreadsheet-PivotMeasureEditor">
    <t t-set="measure" t-value="props.measure"/>
    <PivotDimension dimension="measure" onRemoved="props.onRemoved" onNameUpdated.bind="updateName">
      <t t-set-slot="upper-right-icons">
        <t t-if="measure.isHidden" t-set="hideTitle">Show</t>
        <t t-else="" t-set="hideTitle">Hide</t>
        <i
          t-att-class="measure.isHidden ? 'fa fa-eye-slash': 'fa fa-eye'"
          t-att-title="hideTitle"
          class="o-button-icon pe-1 ps-2"
          t-on-click="toggleMeasureVisibility"
        />
        <i
          class="o-button-icon pe-1 ps-2 fa fa-cog"
          title="Show values as"
          t-on-click="openShowValuesAs"
        />
      </t>
      <div t-if="measure.computedBy" class="d-flex flex-row small">
        <div class="d-flex flex-column py-2 px-2 w-100" t-on-pointerdown.stop="">
          <StandaloneComposer
            onConfirm.bind="updateMeasureFormula"
            composerContent="measure.computedBy.formula"
            defaultRangeSheetId="measure.computedBy.sheetId"
            contextualAutocomplete="getMeasureAutocomplete()"
            getContextualColoredSymbolToken.bind="getColoredSymbolToken"
            invalid="isCalculatedMeasureInvalid"
          />
        </div>
      </div>
      <div class="d-flex flex-row">
        <div class="d-flex py-1 px-2 w-100 small">
          <div class="pivot-dim-operator-label">Aggregated by</div>
          <select
            class="o-input flex-grow-1"
            t-on-change="(ev) => this.updateAggregator(ev.target.value)">
            <option
              t-foreach="Object.keys(props.aggregators[measure.type])"
              t-as="agg"
              t-key="agg"
              t-att-value="agg"
              t-att-selected="agg === measure.aggregator"
              t-esc="props.aggregators[measure.type][agg]"
            />
            <option
              t-if="measure.computedBy"
              t-att-value="''"
              t-att-selected="'' === measure.aggregator">
              Compute from totals
            </option>
          </select>
        </div>
      </div>
    </PivotDimension>
  </t>

  <t t-name="o-spreadsheet-PivotDimensionOrder">
    <div class="d-flex">
      <div class="d-flex py-1 px-2 w-100 small">
        <div class="pivot-dim-operator-label">Order by</div>
        <select
          class="o-input flex-grow-1"
          t-on-change="(ev) => props.onUpdated(props.dimension, ev.target.value)">
          <option value="asc" t-att-selected="props.dimension.order === 'asc'">Ascending</option>
          <option value="desc" t-att-selected="props.dimension.order === 'desc'">Descending</option>
          <option
            t-if="props.dimension.type !== 'date'"
            value=""
            t-att-selected="props.dimension.order === undefined">
            Unsorted
          </option>
        </select>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-PivotDimensionGranularity">
    <div class="d-flex flex-row">
      <div class="d-flex flex-row py-1 px-2 w-100 small">
        <t t-set="granularityProps" t-value="props.dimension.granularity || 'month'"/>
        <div class="pivot-dim-operator-label">Granularity</div>
        <select
          class="o-input flex-grow-1"
          t-on-change="(ev) => props.onUpdated(props.dimension, ev.target.value)">
          <option
            t-foreach="props.allGranularities"
            t-as="granularity"
            t-key="granularity"
            t-if="props.availableGranularities.has(granularity) || granularity === granularityProps"
            t-att-value="granularity"
            t-esc="periods[granularity]"
            t-att-selected="granularity === granularityProps or (granularity === 'month' and !granularityProps)"
          />
        </select>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-PivotDimension">
    <div
      class="py-1 px-2 d-flex flex-column shadow-sm pivot-dimension border rounded"
      t-att-class="{'pivot-dimension-invalid': !props.dimension.isValid}">
      <div class="d-flex flex-row justify-content-between align-items-center">
        <div class="d-flex align-items-center overflow-hidden text-nowrap">
          <span class="text-danger me-1" t-if="!props.dimension.isValid">
            <t t-call="o-spreadsheet-Icon.TRIANGLE_EXCLAMATION"/>
          </span>
          <TextInput
            t-if="props.onNameUpdated"
            value="props.dimension.displayName"
            onChange.bind="updateName"
            class="'o-fw-bold'"
            selectContentOnFocus="true"
          />
          <span t-else="1" class="o-fw-bold" t-esc="props.dimension.displayName"/>
        </div>
        <div class="d-flex flex-rows" t-on-pointerdown.stop="">
          <t t-slot="upper-right-icons"/>
          <i
            class="o-button-icon fa fa-trash pe-1 ps-2"
            t-if="props.onRemoved"
            t-on-click="() => props.onRemoved(props.dimension)"
          />
        </div>
      </div>
      <t t-slot="default"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-AddDimensionButton">
    <button class="add-dimension o-button" t-on-click="togglePopover" t-ref="button">Add</button>
    <Popover t-if="popover.isOpen" t-props="popoverProps">
      <div
        class="p-2 bg-white border-bottom d-flex sticky-top align-items-baseline pivot-dimension-search bg-white">
        <i class="pe-1 pivot-dimension-search-field-icon text-muted">
          <t t-call="o-spreadsheet-Icon.SEARCH"/>
        </i>
        <input
          t-on-input="(ev) => this.updateSearch(ev.target.value)"
          t-on-keydown="onKeyDown"
          class="border-0 w-100 pivot-dimension-search-field"
          t-ref="autofocus"
        />
      </div>
      <TextValueProvider
        proposals="autoComplete.provider.proposals"
        selectedIndex="autoComplete.selectedIndex"
        onValueSelected="autoComplete.provider.selectProposal"
        onValueHovered="() => {}"
      />
      <t t-slot="default" t-on-click="togglePopover"/>
    </Popover>
  </t>

  <t t-name="o-spreadsheet-PivotDeferUpdate">
    <Section
      class="'align-items-center border-top d-flex flex-row justify-content-between py-1 pivot-defer-update'">
      <Checkbox
        label="deferUpdatesLabel"
        title="deferUpdatesTooltip"
        value="props.deferUpdate"
        onChange="(value) => props.toggleDeferUpdate(value)"
      />
      <div t-if="props.isDirty" class="d-flex align-items-center">
        <i
          class="o-button-icon pe-0 fa fa-undo"
          title="Discard all changes"
          t-on-click="() => props.discard()"
        />
        <span
          class="o-button-link sp_apply_update small ps-2"
          title="Apply all changes"
          t-on-click="() => props.apply()">
          Update
        </span>
      </div>
    </Section>
  </t>

  <t t-name="o-spreadsheet-PivotCustomGroupsCollapsible">
    <SidePanelCollapsible
      class="'o-pivot-custom-groups'"
      isInitiallyCollapsed="true"
      title.translate="Groups">
      <t t-set-slot="content">
        <div class="ps-4">
          <div
            t-foreach="groups"
            t-as="group"
            t-key="group_index"
            class="o-pivot-custom-group pb-1">
            <div
              class="d-flex align-items-center justify-content-between small"
              t-on-pointerdown.stop="">
              <TextInput
                value="group.name"
                onChange="(newName) => this.onRenameGroup(group_index, newName)"
                selectContentOnFocus="true"
              />
              <i
                class="o-button-icon ps-3 fa fa-trash"
                t-on-click="() => this.onDeleteGroup(group_index)"
              />
            </div>
          </div>
          <div
            t-if="!hasOthersGroup"
            class="o-button-link o-add-others-group small pb-1"
            t-on-click="() => this.addOthersGroup()">
            <span>+ &quot;Others&quot; group</span>
          </div>
        </div>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-MoreFormatsPanel">
    <div class="o-more-formats-panel">
      <Section title.translate="Format type">
        <BadgeSelection
          choices="store.categories"
          onChange.bind="(category) => store.changeCategory(category)"
          selectedValue="store.category"
        />
      </Section>
      <t t-if="store.category === 'currency'" t-call="o-spreadsheet-CustomCurrencySection"/>
      <t t-set="proposals" t-value="store.formatProposals"/>
      <Section title.translate="Type" t-if="proposals.length">
        <div class="o-format-proposals overflow-auto border">
          <div
            t-foreach="proposals"
            t-as="proposal"
            t-key="proposal.format"
            t-att-data-name="proposal.format"
            t-on-click="() => this.store.updateFormat(proposal.format)"
            class="w-100 d-flex align-items-center format-preview px-2 py-1"
            t-att-class="{'active': (proposal.format || '') === (store.currentFormat || '')}">
            <span t-out="proposal.label"/>
          </div>
        </div>
      </Section>

      <Section title.translate="Format" class="'o-custom-format-section'">
        <TextInput
          value="store.currentFormat || ''"
          onChange="(format) => this.store.updateFormat(format)"
          placeholder.translate="Format code"
          alwaysShowBorder="true"
          errorMessage="store.invalidFormatMessage"
        />
        <t t-set="examples" t-value="store.formatExamples"/>
        <div class="o-format-examples mt-4 p-2 rounded border" t-if="examples.length">
          <table class="w-100">
            <t t-foreach="examples" t-as="example" t-key="example_index">
              <tr>
                <td class="w-25 pe-3 o-fw-bold" t-esc="example.label"/>
                <td class="w-75 text-truncate" t-esc="example.value"/>
              </tr>
            </t>
          </table>
        </div>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-CustomCurrencySection">
    <t t-set="availableCurrencies" t-value="store.availableCurrencies"/>
    <Section t-if="availableCurrencies.length > 1" title.translate="Currency">
      <select
        class="o-input o-available-currencies"
        t-on-change="(ev) => this.updateSelectCurrency(ev)">
        <t t-foreach="availableCurrencies" t-as="currency" t-key="currency_index">
          <option
            t-att-value="currency_index"
            t-esc="currencyDisplayName(currency)"
            t-att-selected="currency_index === store.selectedCurrencyIndex"
          />
        </t>
      </select>
    </Section>
    <Section>
      <div class="o-subsection-left">
        <div class="o-section-title">Code</div>
        <TextInput
          value="store.currencyCode"
          placeholder.translate="code"
          onChange="(code) => this.store.changeCurrencyCode(code)"
          alwaysShowBorder="true"
        />
      </div>
      <div class="o-subsection-right">
        <div class="o-section-title">Symbol</div>
        <TextInput
          value="store.currencySymbol"
          placeholder.translate="symbol"
          onChange="(symbol) => this.store.changeCurrencySymbol(symbol)"
          alwaysShowBorder="true"
        />
      </div>
      <Checkbox
        name="'accountingFormat'"
        className="'pt-2'"
        label.translate="Accounting format"
        value="store.isAccountingFormat"
        onChange="() => store.toggleAccountingFormat()"
      />
    </Section>
  </t>

  <t t-name="o-spreadsheet-FindAndReplacePanel">
    <div class="o-find-and-replace">
      <Section title.translate="Search">
        <div class="o-input-search-container">
          <input
            type="text"
            t-ref="searchInput"
            class="o-input o-input-with-count o-search"
            t-on-input="onSearchInput"
            t-on-focus="onFocusSearch"
            t-on-keydown="onKeydownSearch"
            placeholder="e.g. 'search me'"
          />
          <div class="o-input-count" t-if="hasSearchResult">
            <t t-esc="store.selectedMatchIndex+1"/>
            /
            <t t-esc="store.searchMatches.length"/>
          </div>
          <div t-elif="!this.pendingSearch and store.toSearch !== ''" class="o-input-count">
            0 / 0
          </div>
          <div class="d-flex flex-row o-result-buttons align-items-center" t-if="hasSearchResult">
            <button
              t-on-click="() => store.selectPreviousMatch()"
              class="o-button ms-2 d-flex justify-content-center align-items-center">
              <t t-call="o-spreadsheet-Icon.ARROW_UP"/>
            </button>
            <button
              t-on-click="() => store.selectNextMatch()"
              class="o-button ms-1 d-flex justify-content-center align-items-center">
              <t t-call="o-spreadsheet-Icon.ARROW_DOWN"/>
            </button>
          </div>
        </div>
        <select
          class="o-input o-type-range-selector mt-3 mb-3"
          t-on-change="changeSearchScope"
          t-att-value="searchOptions.searchScope">
          <option value="allSheets">All sheets</option>
          <option value="activeSheet">Current sheet</option>
          <option value="specificRange">Specific range</option>
        </select>
        <div t-if="searchOptions.searchScope === 'specificRange'">
          <SelectionInput
            t-key="selectionInputKey"
            ranges="[specificRange]"
            onSelectionChanged="(ranges) => this.onSearchRangeChanged(ranges)"
            onSelectionConfirmed.bind="updateDataRange"
            hasSingleRange="true"
            required="true"
          />
        </div>
        <div>
          <t t-set="matchCaseLabel">Match case</t>
          <Checkbox
            value="searchOptions.matchCase"
            label="matchCaseLabel"
            onChange.bind="searchMatchCase"
            className="'mb-1'"
          />
          <t t-set="exactMatchLabel">Match entire cell content</t>
          <Checkbox
            value="searchOptions.exactMatch"
            label="exactMatchLabel"
            onChange.bind="searchExactMatch"
            className="'mb-1'"
          />
          <t t-set="searchFormulasLabel">Search in formulas</t>
          <Checkbox
            value="searchOptions.searchFormulas"
            label="searchFormulasLabel"
            onChange.bind="searchFormulas"
          />
        </div>
        <div class="o-matches-count mt-4" t-if="searchInfo.length">
          <ValidationMessages msgType="'info'" messages="searchInfo" singleBox="true"/>
        </div>
      </Section>
      <Section class="'pt-0'" t-if="!env.model.getters.isReadonly()" title.translate="Replace">
        <div class="o-input-search-container">
          <input
            type="text"
            class="o-input o-input-without-count o-replace"
            t-on-keydown="onKeydownReplace"
            t-model="store.toReplace"
            placeholder="e.g. 'replace me'"
          />
        </div>
      </Section>
      <Section>
        <div class="o-sidePanelButtons" t-if="!env.model.getters.isReadonly()">
          <button
            t-att-disabled="store.selectedMatchIndex === null"
            t-on-click="() => store.replace()"
            class="o-button o-replace">
            Replace
          </button>
          <button
            t-att-disabled="store.selectedMatchIndex === null"
            t-on-click="() => store.replaceAll()"
            class="o-button o-replace-all">
            Replace all
          </button>
        </div>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-DataValidationPanel">
    <div class="o-data-validation">
      <t t-if="state.mode === 'list'">
        <div class="o-dv-preview-list">
          <t t-foreach="validationRules" t-as="rule" t-key="rule.id">
            <DataValidationPreview
              rule="localizeDVRule(rule)"
              onClick="() => this.onPreviewClick(rule.id)"
            />
          </t>
        </div>
        <div class="o-dv-add o-button-link p-4 float-end" t-on-click="addDataValidationRule">
          + Add another rule
        </div>
      </t>
      <t t-else="">
        <DataValidationEditor rule="localizeDVRule(state.activeRule)" onExit.bind="onExitEditMode"/>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-DataValidationPreview">
    <div class="o-dv-preview p-3 border-bottom" t-on-click="props.onClick" t-ref="dvPreview">
      <div class="d-flex justify-content-between">
        <div class="o-dv-container d-flex flex-column">
          <div class="o-dv-preview-description o-fw-bold text-truncate" t-esc="descriptionString"/>
          <div class="o-dv-preview-ranges text-truncate" t-esc="rangesString"/>
        </div>
        <div
          class="o-dv-preview-delete d-flex align-items-center o-button-icon px-3"
          t-on-click.stop="deleteDataValidation">
          <t t-call="o-spreadsheet-Icon.TRASH_FILLED"/>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-DataValidationEditor">
    <div class="o-dv-form w-100 h-100">
      <Section class="'o-dv-range'" title.translate="Apply to range">
        <SelectionInput
          ranges="state.rule.ranges"
          onSelectionChanged="(ranges) => this.onRangesChanged(ranges)"
          required="true"
        />
      </Section>
      <Section class="'pt-0'">
        <div class="o-subsection o-dv-settings">
          <div class="o-section-title">Criteria</div>
          <SelectMenu
            class="'o-dv-type o-input mb-2'"
            menuItems="dvCriterionMenuItems"
            selectedValue="selectedCriterionName"
          />

          <t
            t-if="criterionComponent"
            t-component="criterionComponent"
            t-key="state.rule.criterion.type"
            criterion="state.rule.criterion"
            onCriterionChanged.bind="onCriterionChanged"
            autofocus="state.isTypeUpdated"
          />
        </div>
      </Section>

      <Section class="'o-dv-invalid-option pt-0'" title.translate="If the data is invalid">
        <select class="o-dv-reject-input o-input" t-on-change="changeRuleIsBlocking">
          <option t-att-selected="!state.rule.isBlocking" value="false">Show a warning</option>
          <option t-att-selected="state.rule.isBlocking" value="true">Reject the input</option>
        </select>
      </Section>

      <Section>
        <div class="o-sidePanelButtons">
          <button t-on-click="props.onExit" class="o-dv-cancel o-button">Cancel</button>
          <button t-on-click="onSave" class="o-dv-save o-button primary">Save</button>
        </div>
      </Section>
      <Section>
        <ValidationMessages messages="errorMessages" msgType="'error'"/>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-ValueInRangeCriterionForm">
    <SelectionInput
      ranges="[props.criterion.values[0] || '']"
      onSelectionChanged="(ranges) => this.onRangeChanged(ranges[0])"
      required="true"
      hasSingleRange="true"
      autofocus="props.autofocus"
    />
    <t t-foreach="values" t-as="value" t-key="value_index">
      <div class="o-dv-list-values p-1 d-flex align-items-center">
        <div class="me-2">
          <RoundColorPicker
            currentColor="props.criterion.colors?.[value.value] || '#E7E9ED'"
            onColorPicked="(c) => this.onColorChanged(c, value.value)"
          />
        </div>
        <input type="text" class="o-input" t-att-value="value.label" disabled="1"/>
      </div>
    </t>

    <div class="o-section-subtitle mt-4">Display style</div>
    <select class="o-dv-display-style o-input" t-on-change="onChangedDisplayStyle">
      <option t-att-selected="props.criterion.displayStyle === 'chip'" value="chip">Chip</option>
      <option t-att-selected="props.criterion.displayStyle === 'arrow'" value="arrow">Arrow</option>
      <option t-att-selected="props.criterion.displayStyle === 'plainText'" value="plainText">
        Plain text
      </option>
    </select>
  </t>

  <t t-name="o-spreadsheet-ListCriterionForm">
    <t t-foreach="displayedValues" t-as="value" t-key="value_index">
      <div class="o-dv-list-values d-flex align-items-center">
        <div class="me-1">
          <RoundColorPicker
            currentColor="props.criterion.colors?.[value] || '#E7E9ED'"
            onColorPicked="(c) => this.onColorChanged(c, value)"
          />
        </div>
        <CriterionInput
          value="props.criterion.values[value_index]"
          onValueChanged="(v) => this.onValueChanged(v, value_index)"
          criterionType="props.criterion.type"
          onKeyDown="(ev) => this.onKeyDown(ev, value_index)"
          focused="value_index === state.focusedValueIndex"
          onBlur.bind="onBlurInput"
          disableFormulas="props.disableFormulas"
        />
        <div
          class="o-dv-list-item-delete ms-2 o-button-icon"
          t-on-click="() => this.removeItem(value_index)">
          <t t-call="o-spreadsheet-Icon.TRASH_FILLED"/>
        </div>
      </div>
      <div class="mb-2"/>
    </t>
    <button class="o-dv-list-add-value o-button mb-3" t-on-click="onAddAnotherValue">
      Add another item
    </button>

    <div class="o-section-subtitle">Display style</div>
    <select class="o-dv-display-style o-input" t-on-change="onChangedDisplayStyle">
      <option t-att-selected="props.criterion.displayStyle === 'chip'" value="chip">Chip</option>
      <option t-att-selected="props.criterion.displayStyle === 'arrow'" value="arrow">Arrow</option>
      <option t-att-selected="props.criterion.displayStyle === 'plainText'" value="plainText">
        Plain text
      </option>
    </select>
  </t>

  <t t-name="o-spreadsheet-SingleInputCriterionForm">
    <CriterionInput
      value="props.criterion.values[0]"
      onValueChanged.bind="onValueChanged"
      criterionType="props.criterion.type"
      disableFormulas="props.disableFormulas"
      focused="props.autofocus"
    />
  </t>

  <t t-name="o-spreadsheet-DoubleInputCriterionForm">
    <CriterionInput
      value="props.criterion.values[0]"
      onValueChanged.bind="onFirstValueChanged"
      criterionType="props.criterion.type"
      disableFormulas="props.disableFormulas"
      focused="props.autofocus"
    />
    <CriterionInput
      value="props.criterion.values[1]"
      onValueChanged.bind="onSecondValueChanged"
      criterionType="props.criterion.type"
      disableFormulas="props.disableFormulas"
    />
  </t>

  <t t-name="o-spreadsheet-DataValidationDateCriterion">
    <select class="o-dv-date-value o-input mb-4" t-on-change="onDateValueChanged">
      <option
        t-foreach="dateValues"
        t-as="dateValue"
        t-key="dateValue.value"
        t-att-value="dateValue.value"
        t-esc="dateValue.title"
        t-att-selected="dateValue.value === currentDateValue"
      />
    </select>

    <CriterionInput
      t-if="currentDateValue === 'exactDate'"
      value="props.criterion.values[0]"
      onValueChanged.bind="onValueChanged"
      criterionType="props.criterion.type"
      disableFormulas="props.disableFormulas"
      focused="props.autofocus"
    />
  </t>

  <t t-name="o-spreadsheet-CriterionInput">
    <div class="o-dv-input position-relative w-100 p-1">
      <t t-if="allowedValues === 'onlyLiterals'">
        <input
          type="text"
          t-ref="input"
          t-on-input="onInputValueChanged"
          t-att-value="props.value"
          class="o-input"
          t-att-class="{
              'o-invalid border-danger position-relative': errorMessage,
            }"
          t-att-title="errorMessage"
          t-att-placeholder="placeholder"
          t-on-keydown="props.onKeyDown"
          t-on-blur="props.onBlur"
        />
      </t>
      <t t-else="">
        <StandaloneComposer t-props="getDataValidationRuleInputComposerProps()"/>
      </t>
      <span
        t-if="errorMessage"
        class="error-icon text-danger position-absolute d-flex align-items-center"
        t-att-title="errorMessage">
        <t t-call="o-spreadsheet-Icon.ERROR"/>
      </span>
    </div>
  </t>

  <t t-name="o-spreadsheet-ConditionalFormattingPanel">
    <div class="o-cf h-100">
      <t t-if="state.mode === 'list'">
        <ConditionalFormatPreviewList
          conditionalFormats="conditionalFormats"
          onPreviewClick.bind="editConditionalFormat"
          onAddConditionalFormat.bind="addConditionalFormat"
        />
      </t>
      <t t-if="state.mode === 'edit'">
        <ConditionalFormattingEditor
          editedCf="editedCF"
          onExit.bind="switchToList"
          onCancel.bind="cancelEdition"
          isNewCf="originalEditedCf === undefined"
        />
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-ConditionalFormatPreviewList">
    <div class="o-cf-preview-list h-100 overflow-auto" t-ref="cfList">
      <t t-foreach="props.conditionalFormats" t-as="cf" t-key="cf.id">
        <div
          class="o-cf-preview-container d-flex position-relative"
          t-att-style="getPreviewDivStyle(cf)">
          <ConditionalFormatPreview
            conditionalFormat="cf"
            class="dragAndDrop.draggedItemId === cf.id ? 'o-cf-dragging' : ''"
            onMouseDown="(ev) => this.onPreviewMouseDown(cf, ev)"
            onPreviewClick="() => props.onPreviewClick(cf)"
          />
        </div>
      </t>
      <div
        class="o-button-link p-4 o-cf-add float-end"
        t-on-click.prevent.stop="props.onAddConditionalFormat">
        + Add another rule
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-ConditionalFormatPreview">
    <t t-set="cf" t-value="props.conditionalFormat"/>
    <div
      class="o-cf-preview w-100 d-flex align-items-center border-bottom"
      t-ref="cfPreview"
      t-att-class="props.class"
      t-att-data-id="cf.id"
      t-on-click="props.onPreviewClick"
      t-on-pointerdown="(ev) => this.onMouseDown(ev)">
      <div class="o-cf-drag-handle h-100 position-absolute d-flex align-items-center o-button-icon">
        <t t-call="o-spreadsheet-Icon.THIN_DRAG_HANDLE"/>
      </div>
      <t t-if="cf.rule.type==='IconSetRule'">
        <div
          class="o-cf-preview-icon d-flex justify-content-around align-items-center me-3 bg-white border">
          <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.upper].template}}"/>
          <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.middle].template}}"/>
          <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.lower].template}}"/>
        </div>
      </t>
      <t t-else="">
        <div
          t-att-style="getPreviewImageStyle(cf.rule)"
          class="o-cf-preview-icon d-flex justify-content-around align-items-center me-3 flex-shrink-0 border">
          123
        </div>
      </t>
      <div class="o-cf-preview-description me-3 overflow-auto">
        <div class="o-cf-preview-ruletype">
          <div class="o-cf-preview-description-rule o-fw-bold text-truncate">
            <t t-esc="getDescription(cf)"/>
          </div>
        </div>
        <div class="o-cf-preview-range text-truncate" t-esc="cf.ranges"/>
      </div>
      <div class="o-cf-delete ms-auto">
        <div
          class="o-cf-delete-button o-button-icon"
          t-on-click.stop="(ev) => this.deleteConditionalFormat(cf, ev)"
          title="Remove rule">
          <t t-call="o-spreadsheet-Icon.TRASH_FILLED"/>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-IconSets">
    <div class="pb-2">
      <div class="o-section-subtitle">Icons</div>
      <div class="o-cf-iconsets d-flex flex-row">
        <div
          class="o-cf-iconset o-cf-clickable-icon d-flex flex-row justify-content-between border rounded"
          t-foreach="['arrows', 'smiley', 'dots']"
          t-as="iconSet"
          t-key="iconSet"
          t-on-click="(ev) => this.setIconSet(iconSet, ev)">
          <div>
            <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].good].template}}"/>
          </div>
          <div>
            <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].neutral].template}}"/>
          </div>
          <div>
            <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].bad].template}}"/>
          </div>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-IconSetInflexionPointRow">
    <tr>
      <td>
        <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-'+icon+'Icon', ev)">
          <div class="o-cf-icon-button o-cf-clickable-icon me-3 border rounded">
            <t t-call="o-spreadsheet-Icon.{{icons[iconValue].template}}"/>
          </div>
        </div>
        <IconPicker
          t-if="state.openedMenu === 'iconSet-'+icon+'Icon'"
          onIconPicked="(i) => this.setIcon(icon, i)"
        />
      </td>
      <td>When value is</td>
      <td>
        <select
          class="o-input"
          name="valueType"
          t-on-change="(ev) => this.setInflectionOperator(inflectionPoint, ev.target.value)">
          <option value="gt" t-att-selected="inflectionPointValue.operator === 'gt'">
            <span>&#62;</span>
          </option>
          <option value="ge" t-att-selected="inflectionPointValue.operator === 'ge'">
            <span>&#8805;</span>
          </option>
        </select>
      </td>
      <td>
        <div class="ms-2 me-2">
          <input
            type="text"
            t-if="inflectionPointValue.type !== 'formula'"
            class="o-input"
            t-att-class="{ 'o-invalid': isInflectionPointInvalid(inflectionPoint) }"
            t-att-value="rule[inflectionPoint].value"
            t-on-change="(ev) => this.setInflectionValue(inflectionPoint, ev.target.value)"
          />
          <StandaloneComposer t-else="" t-props="getColorIconSetComposerProps(inflectionPoint)"/>
        </div>
      </td>
      <td>
        <select
          class="o-input"
          name="valueType"
          t-on-change="(ev) => this.setInflectionType(inflectionPoint, ev.target.value, ev)">
          <option value="number" t-att-selected="inflectionPointValue.type === 'number'">
            Number
          </option>
          <option value="percentage" t-att-selected="inflectionPointValue.type === 'percentage'">
            Percentage
          </option>
          <option value="percentile" t-att-selected="inflectionPointValue.type === 'percentile'">
            Percentile
          </option>
          <option value="formula" t-att-selected="inflectionPointValue.type === 'formula'">
            Formula
          </option>
        </select>
      </td>
    </tr>
  </t>

  <t t-name="o-spreadsheet-IconSetInflexionPoints">
    <div class="o-inflection mt-4">
      <table class="w-100">
        <tr>
          <th class="o-cf-iconset-icons"/>
          <th class="o-cf-iconset-text"/>
          <th class="o-cf-iconset-operator"/>
          <th/>
          <th class="o-cf-iconset-type"/>
        </tr>
        <t t-call="o-spreadsheet-IconSetInflexionPointRow">
          <t t-set="iconValue" t-value="rule.icons.upper"/>
          <t t-set="icon" t-value="'upper'"/>
          <t t-set="inflectionPointValue" t-value="rule.upperInflectionPoint"/>
          <t t-set="inflectionPoint" t-value="'upperInflectionPoint'"/>
        </t>
        <t t-call="o-spreadsheet-IconSetInflexionPointRow">
          <t t-set="iconValue" t-value="rule.icons.middle"/>
          <t t-set="icon" t-value="'middle'"/>
          <t t-set="inflectionPointValue" t-value="rule.lowerInflectionPoint"/>
          <t t-set="inflectionPoint" t-value="'lowerInflectionPoint'"/>
        </t>
        <tr>
          <td>
            <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-lowerIcon', ev)">
              <div class="o-cf-icon-button o-cf-clickable-icon me-3 border rounded">
                <t t-call="o-spreadsheet-Icon.{{icons[rule.icons.lower].template}}"/>
              </div>
            </div>
            <IconPicker
              t-if="state.openedMenu === 'iconSet-lowerIcon'"
              onIconPicked="(icon) => this.setIcon('lower', icon)"
            />
          </td>
          <td>Else</td>
          <td/>
          <td/>
          <td/>
        </tr>
      </table>
    </div>
  </t>
  <t t-name="o-spreadsheet-IconSetEditor">
    <div class="o-cf-iconset-rule">
      <t t-call="o-spreadsheet-IconSets"/>
      <t t-call="o-spreadsheet-IconSetInflexionPoints"/>
      <div class="d-flex flex-row">
        <div
          class="o-button-link py-1 ps-0 o-cf-iconset-reverse d-flex align-items-center"
          t-on-click="reverseIcons">
          <t t-call="o-spreadsheet-Icon.REFRESH"/>
          <div class="ms-1">Reverse icons</div>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-DataBarEditor">
    <div class="o-cf-data-bar-editor">
      <div class="o-section-subtitle">Color</div>
      <RoundColorPicker
        currentColor="colorNumberToHex(rule.color)"
        onColorPicked.bind="updateDataBarColor"
        disableNoColor="true"
      />
      <div class="o-section-subtitle">Range of values</div>
      <SelectionInput
        ranges="getRangeValues()"
        class="'o-range'"
        isInvalid="false"
        hasSingleRange="true"
        onSelectionChanged.bind="onDataBarRangeUpdate"
        onSelectionConfirmed.bind="onDataBarRangeChange"
        required="false"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-ColorScaleRuleEditorThreshold">
    <t t-set="fill_color">Fill Color</t>
    <div
      t-attf-class="o-threshold o-threshold-{{thresholdType}} d-flex align-items-center flex-row">
      <t t-if="thresholdType === 'midpoint'">
        <t t-set="type" t-value="threshold and threshold.type"/>
        <select
          class="o-input me-2"
          name="valueType"
          t-on-change="onMidpointChange"
          t-att-class="{ 'o-select-with-input': threshold and threshold.type !== 'value' }"
          t-on-click="closeMenus">
          <option value="none" t-att-selected="threshold === undefined">None</option>
          <option value="number" t-att-selected="type === 'number'">Fixed Number</option>
          <option value="percentage" t-att-selected="type === 'percentage'">Percentage</option>
          <option value="percentile" t-att-selected="type === 'percentile'">Percentile</option>
          <option value="formula" t-att-selected="type === 'formula'">Formula</option>
        </select>
      </t>
      <t t-else="">
        <select
          class="o-input me-2"
          name="valueType"
          t-on-change="(ev) => this.updateThresholdType(thresholdType, ev.target.value)"
          t-on-click="closeMenus"
          t-att-class="{ 'o-select-with-input': threshold?.type !== 'value' }">
          <option value="value" t-att-selected="threshold.type === 'value'">Cell values</option>
          <option value="number" t-att-selected="threshold.type === 'number'">Number</option>
          <option value="percentage" t-att-selected="threshold.type === 'percentage'">
            Percentage
          </option>
          <option value="percentile" t-att-selected="threshold.type === 'percentile'">
            Percentile
          </option>
          <option value="formula" t-att-selected="threshold.type === 'formula'">Formula</option>
        </select>
      </t>
      <div class="o-threshold-value me-2" t-if="threshold and threshold.type !== 'value'">
        <input
          t-if="threshold.type !== 'formula'"
          type="text"
          class="o-input"
          t-att-value="threshold.value"
          t-on-change="(ev) => this.updateThresholdValue(thresholdType, ev.target.value)"
          t-att-class="{ 'o-invalid': isValueInvalid(thresholdType), 'invisible': threshold === undefined }"
        />
        <StandaloneComposer t-else="" t-props="getColorScaleComposerProps(thresholdType)"/>
      </div>
      <div t-attf-class="flex-shrink-0 ms-1 {{ threshold === undefined ? 'invisible' : ''}}">
        <RoundColorPicker
          currentColor="getThresholdColor(threshold)"
          onColorPicked="(color) => this.setColorScaleColor(thresholdType, color)"
          title="fill_color"
          disableNoColor="true"
        />
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-ColorScaleRuleEditor">
    <div class="o-cf-color-scale-editor">
      <div class="o-section-subtitle">Preview</div>
      <div class="o-cf-preview-display mb-4" t-attf-style="{{getColorScalePreviewStyle()}}">
        Preview text
      </div>
      <div class="o-section-subtitle">Minpoint</div>
      <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
        <t t-set="threshold" t-value="rule.minimum"/>
        <t t-set="thresholdType" t-value="'minimum'"/>
      </t>
      <div class="o-section-subtitle">MidPoint</div>
      <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
        <t t-set="threshold" t-value="rule.midpoint"/>
        <t t-set="thresholdType" t-value="'midpoint'"/>
      </t>
      <div class="o-section-subtitle">MaxPoint</div>
      <t t-call="o-spreadsheet-ColorScaleRuleEditorThreshold">
        <t t-set="threshold" t-value="rule.maximum"/>
        <t t-set="thresholdType" t-value="'maximum'"/>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-ConditionalFormattingEditor">
    <div class="o-cf-ruleEditor">
      <Section class="'o-cf-range pb-0'" title.translate="Apply to range">
        <div class="o-selection-cf">
          <SelectionInput
            ranges="state.ranges"
            class="'o-range'"
            isInvalid="isRangeValid"
            onSelectionChanged.bind="onRangeUpdate"
            onSelectionConfirmed.bind="onRangeConfirmed"
            required="true"
          />
        </div>
      </Section>
      <Section class="'pb-0'" title.translate="Format rules">
        <div class="o-cf-type-selector">
          <BadgeSelection
            choices="cfTypesValues"
            onChange.bind="changeRuleType"
            selectedValue="state.currentCFType"
          />
        </div>
      </Section>
      <Section class="'o-cf-editor'">
        <t t-if="state.currentCFType === 'CellIsRule'" t-call="o-spreadsheet-CellIsRuleEditor">
          <t t-set="rule" t-value="state.rules.cellIs"/>
        </t>
        <t
          t-if="state.currentCFType === 'ColorScaleRule'"
          t-call="o-spreadsheet-ColorScaleRuleEditor">
          <t t-set="rule" t-value="state.rules.colorScale"/>
        </t>
        <t t-if="state.currentCFType === 'IconSetRule'" t-call="o-spreadsheet-IconSetEditor">
          <t t-set="rule" t-value="state.rules.iconSet"/>
        </t>
        <t t-if="state.currentCFType === 'DataBarRule'" t-call="o-spreadsheet-DataBarEditor">
          <t t-set="rule" t-value="state.rules.dataBar"/>
        </t>
      </Section>
      <Section class="'pt-1'">
        <div class="o-sidePanelButtons">
          <button t-on-click="onCancel" class="o-button o-cf-cancel">Cancel</button>
          <button
            t-on-click="onSave"
            class="o-button primary o-cf-save"
            t-att-disabled="state.errors.length !== 0">
            Save
          </button>
        </div>
      </Section>
      <Section>
        <ValidationMessages messages="errorMessages" msgType="'error'"/>
      </Section>
    </div>
  </t>

  <t t-name="o-spreadsheet-CellIsRuleEditorPreview">
    <div
      class="o-cf-preview-display border"
      t-attf-style="font-weight:{{currentStyle.bold ?'bold':'normal'}};
                       text-decoration:{{getTextDecoration(currentStyle)}};
                       font-style:{{currentStyle.italic?'italic':'normal'}};
                       color:{{currentStyle.textColor || '#000'}};
                       background-color:{{currentStyle.fillColor}};">
      <t t-if="previewText" t-esc="previewText"/>
      <t t-else="">Preview text</t>
    </div>
  </t>

  <t t-name="o-spreadsheet-CellIsRuleEditor">
    <t t-set="fill_color">Fill Color</t>
    <t t-set="text_color">Text Color</t>
    <div class="o-cf-cell-is-rule">
      <div class="o-section-subtitle">Format cells if...</div>
      <SelectMenu
        class="'o-cell-is-operator o-input mb-2'"
        menuItems="cfCriterionMenuItems"
        selectedValue="selectedCriterionName"
      />

      <t
        t-if="criterionComponent"
        t-component="criterionComponent"
        t-key="state.rules.cellIs.operator"
        criterion="genericCriterion"
        onCriterionChanged.bind="onRuleValuesChanged"
        autofocus="this.state.hasEditedCf"
      />

      <div class="o-section-subtitle pt-3">Formatting style</div>

      <t t-call="o-spreadsheet-CellIsRuleEditorPreview">
        <t t-set="currentStyle" t-value="rule.style"/>
      </t>
      <div class="o-sidePanel-tools d-flex">
        <div
          class="o-hoverable-button o-menu-item-button"
          title="Bold"
          t-att-class="{active:rule.style.bold}"
          t-on-click="() => this.toggleStyle('bold')">
          <t t-call="o-spreadsheet-Icon.BOLD"/>
        </div>
        <div
          class="o-hoverable-button o-menu-item-button"
          title="Italic"
          t-att-class="{active:rule.style.italic}"
          t-on-click="() => this.toggleStyle('italic')">
          <t t-call="o-spreadsheet-Icon.ITALIC"/>
        </div>
        <div
          class="o-hoverable-button o-menu-item-button"
          title="Underline"
          t-att-class="{active:rule.style.underline}"
          t-on-click="(ev) => this.toggleStyle('underline', ev)">
          <t t-call="o-spreadsheet-Icon.UNDERLINE"/>
        </div>
        <div
          class="o-hoverable-button o-menu-item-button"
          title="Strikethrough"
          t-att-class="{active:rule.style.strikethrough}"
          t-on-click="(ev) => this.toggleStyle('strikethrough', ev)">
          <t t-call="o-spreadsheet-Icon.STRIKE"/>
        </div>
        <ColorPickerWidget
          currentColor="rule.style.textColor || '#000000'"
          toggleColorPicker="(ev) => this.toggleMenu('cellIsRule-textColor', ev)"
          showColorPicker="state.openedMenu === 'cellIsRule-textColor'"
          onColorPicked="(color) => this.setColor('textColor', color)"
          title="text_color"
          icon="'o-spreadsheet-Icon.TEXT_COLOR'"
          class="'o-hoverable-button o-menu-item-button'"
        />
        <div class="o-divider border-end"/>
        <ColorPickerWidget
          currentColor="rule.style.fillColor"
          toggleColorPicker="(ev) => this.toggleMenu('cellIsRule-fillColor', ev)"
          showColorPicker="state.openedMenu === 'cellIsRule-fillColor'"
          onColorPicked="(color) => this.setColor('fillColor', color)"
          title="fill_color"
          icon="'o-spreadsheet-Icon.FILL_COLOR'"
          class="'o-hoverable-button o-menu-item-button'"
        />
      </div>
    </div>
  </t>

  <t t-name="o_spreadsheet.Section">
    <div class="o-section" t-att-class="props.class">
      <t t-if="props.slots.title or props.title">
        <div class="o-section-title">
          <t t-esc="props.title"/>
          <t t-slot="title"/>
        </div>
      </t>
      <t t-slot="default"/>
    </div>
  </t>

  <t t-name="o-spreadsheet.RoundColorPicker">
    <div
      class="o-round-color-picker-button rounded-circle border"
      t-ref="colorPickerButton"
      t-on-click.stop="togglePicker"
      t-att-title="props.title"
      t-att-style="buttonStyle"
    />
    <ColorPicker
      t-if="state.pickerOpened"
      anchorRect="colorPickerAnchorRect"
      onColorPicked.bind="onColorPicked"
      currentColor="props.currentColor"
      disableNoColor="props.disableNoColor"
    />
  </t>

  <t t-name="o-spreadsheet.RadioSelection">
    <div
      class="d-flex"
      t-att-class="{
            'flex-row': props.direction === 'horizontal',
            'flex-column': props.direction === 'vertical'}">
      <t t-foreach="props.choices" t-as="choice" t-key="choice.value">
        <label class="o-radio d-flex align-items-center me-4">
          <input
            class="border rounded-circle"
            t-att-class="{
              'me-1': props.direction === 'horizontal',
              'me-2': props.direction === 'vertical'}"
            type="radio"
            t-att-name="props.name"
            t-att-value="choice.value"
            t-att-checked="choice.value === props.selectedValue"
            t-on-change="() => props.onChange(choice.value)"
          />
          <t t-esc="choice.label"/>
        </label>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-SidePanelCollapsible">
    <div class="" t-att-class="props.class">
      <div
        class="o_side_panel_collapsible_title o-fw-bold d-flex align-items-center"
        t-on-click="() => this.toggle()">
        <div
          class="collapsor w-100 d-flex align-items-center ps-1"
          t-att-class="state.isCollapsed ? 'collapsed' : ''">
          <span class="collapsor-arrow">
            <t t-call="o-spreadsheet-Icon.ANGLE_DOWN"/>
          </span>
          <div class="ps-2" t-esc="props.title"/>
        </div>
      </div>
      <Collapse isCollapsed="state.isCollapsed">
        <div class="pt-2">
          <t t-slot="content"/>
        </div>
      </Collapse>
    </div>
  </t>

  <t t-name="o-spreadsheet-Collapse">
    <div t-ref="content" class="os-collapse">
      <t t-slot="default"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-CogWheelMenu">
    <span
      class="fa fa-cog os-cog-wheel-menu-icon o-button-icon"
      t-on-click="toggleMenu"
      t-ref="button"
    />
    <MenuPopover
      t-if="menuState.isOpen"
      menuId="menuId"
      anchorRect="menuState.anchorRect"
      menuItems="menuState.menuItems"
      onClose="() => this.menuState.isOpen=false"
      width="160"
    />
  </t>

  <t t-name="o-spreadsheet.Checkbox">
    <label
      class="o-checkbox d-flex align-items-center"
      role="button"
      t-att-title="props.title"
      t-att-class="{'text-muted': props.disabled }"
      t-attf-class="{{props.className}}">
      <input
        class="me-2 flex-shrink-0 border"
        type="checkbox"
        t-att-disabled="props.disabled"
        t-att-name="props.name"
        t-att-checked="props.value"
        t-on-change="onChange"
        t-on-click.stop=""
      />
      <span class="text-truncate" t-if="props.label" t-esc="props.label"/>
    </label>
  </t>

  <t t-name="o-spreadsheet.BadgeSelection">
    <div class="d-flex w-100 o-badge-selection">
      <t t-foreach="props.choices" t-as="choice" t-key="choice.value">
        <button
          class="flex-grow-1 o-button"
          t-esc="choice.label"
          t-att-class="{ 'selected': props.selectedValue === choice.value }"
          t-on-click="() => props.onChange(choice.value)"
          t-att-data-id="choice.value"
        />
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-GenericZoomableChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Zoom">
          <Checkbox
            name="'zoomable'"
            label.translate="Show slicer"
            value="props.definition.zoomable"
            onChange.bind="onToggleZoom"
            className="'mb-2'"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesWithAxisDesignEditor t-props="props"/>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-WaterfallChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <Section class="'o-vertical-axis-selection pt-0'" title.translate="Vertical axis position">
          <RadioSelection
            choices="axisChoices"
            selectedValue="props.definition.verticalAxisPosition"
            name="'axis'"
            onChange.bind="updateVerticalAxisPosition"
          />
        </Section>
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Zoom">
          <Checkbox
            name="'zoomable'"
            label.translate="Show slicer"
            value="props.definition.zoomable"
            onChange.bind="onToggleZoom"
            className="'mb-2'"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Waterfall design">
      <t t-set-slot="content">
        <Section class="'pt-0'" title.translate="Options">
          <t t-set="firstValueAsSubtotal">Use first value as subtotal</t>
          <Checkbox
            className="'mb-2'"
            name="'firstValueAsSubtotal'"
            label="firstValueAsSubtotal"
            value="props.definition.firstValueAsSubtotal"
            onChange.bind="onUpdateFirstValueAsSubtotal"
          />
          <t t-set="showSubTotalsLabel">Show subtotals at the end of series</t>
          <Checkbox
            className="'mb-2'"
            name="'showSubTotals'"
            label="showSubTotalsLabel"
            value="props.definition.showSubTotals"
            onChange.bind="onUpdateShowSubTotals"
          />
          <t t-set="showConnectorLinesLabel">Show connector lines</t>
          <Checkbox
            name="'showConnectorLines'"
            label="showConnectorLinesLabel"
            value="props.definition.showConnectorLines"
            onChange.bind="onUpdateShowConnectorLines"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Colors">
          <div class="o-waterfall-positive-color d-flex align-items-center mb-2">
            <RoundColorPicker
              currentColor="positiveValuesColor"
              onColorPicked="(color) => this.updateColor('positiveValuesColor', color)"
            />
            <span class="ps-2">Color of positive values</span>
          </div>
          <div class="o-waterfall-negative-color d-flex align-items-center mb-2">
            <RoundColorPicker
              currentColor="negativeValuesColor"
              onColorPicked="(color) => this.updateColor('negativeValuesColor', color)"
            />
            <span class="ps-2">Color of negative values</span>
          </div>
          <div class="o-waterfall-subtotal-color d-flex align-items-center">
            <RoundColorPicker
              currentColor="subTotalValuesColor"
              onColorPicked="(color) => this.updateColor('subTotalValuesColor', color)"
            />
            <span class="ps-2">Color of subtotals</span>
          </div>
        </Section>
      </t>
    </SidePanelCollapsible>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-TreeMapChartDesignPanel">
    <GeneralDesignEditor t-props="props"/>

    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Tree map colors">
      <t t-set-slot="content">
        <Section class="'pt-0'">
          <BadgeSelection
            choices="coloringOptionChoices"
            onChange.bind="changeColoringOption"
            selectedValue="coloringOptions.type"
          />

          <t t-if="coloringOptions.type === 'categoryColor'">
            <TreeMapCategoryColors
              chartId="props.chartId"
              definition="props.definition"
              onColorChanged.bind="onCategoryColorChange"
            />
          </t>
          <t t-else="">
            <TreeMapColorScale
              chartId="props.chartId"
              definition="props.definition"
              onColorChanged.bind="onColorScaleChange"
            />
          </t>
        </Section>
      </t>
    </SidePanelCollapsible>

    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Headers and labels">
      <t t-set-slot="content">
        <Section title.translate="Headers" class="'pt-0 pb-0'">
          <Checkbox
            name="'showHeaders'"
            label.translate="Show headers"
            value="showHeaders"
            onChange="(showHeaders) => props.updateChart(this.props.chartId, { showHeaders })"
          />
        </Section>
        <Section class="'pt-0'" t-if="showHeaders">
          <TextStyler
            class="'pt-0 o-header-style'"
            updateStyle="(headerDesign) => props.updateChart(this.props.chartId, { headerDesign })"
            style="props.definition.headerDesign || {}"
            defaultStyle="defaults.headerDesign"
            hasBackgroundColor="true"
          />
        </Section>

        <Section title.translate="Labels" class="'pt-0 pb-0'">
          <div class="d-flex flex-row gap-4">
            <Checkbox
              name="'showLabels'"
              label.translate="Show labels"
              value="showLabels"
              onChange="(showLabels) => props.updateChart(this.props.chartId, { showLabels })"
            />
            <ChartShowValues t-props="props" defaultValue="defaults.showValues"/>
          </div>
        </Section>
        <Section class="'pt-0'" t-if="showValues || showLabels">
          <TextStyler
            class="'pt-0 o-values-style'"
            updateStyle="(valuesDesign) => props.updateChart(this.props.chartId, { valuesDesign })"
            style="props.definition.valuesDesign || {}"
            defaultStyle="defaults.valuesDesign"
            hasVerticalAlign="true"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-TreeMapColorScale">
    <div class="o-min-color d-flex align-items-center mb-2 mt-4">
      <RoundColorPicker
        currentColor="coloringOptions.minColor"
        onColorPicked="(color) => this.setColorScaleColor('minColor', color)"
        disableNoColor="true"
      />
      <span class="ps-2">Color of minimum values</span>
    </div>
    <div class="o-mid-color d-flex align-items-center mb-2">
      <RoundColorPicker
        currentColor="coloringOptions.midColor"
        onColorPicked="(color) => this.setColorScaleColor('midColor', color)"
      />
      <span class="ps-2">Color of middle values</span>
    </div>
    <div class="o-max-color d-flex align-items-center">
      <RoundColorPicker
        currentColor="coloringOptions.maxColor"
        onColorPicked="(color) => this.setColorScaleColor('maxColor', color)"
        disableNoColor="true"
      />
      <span class="ps-2">Color of maximum values</span>
    </div>
  </t>

  <t t-name="o-spreadsheet-TreeMapCategoryColors">
    <div class="mt-3">
      <div class="o-fw-bold mb-2">Category</div>
      <t t-foreach="getTreeGroupAndColors()" t-as="group" t-key="group_index">
        <div class="d-flex align-items-center mb-2" t-att-data-id="group.label">
          <RoundColorPicker
            currentColor="group.color"
            onColorPicked="(color) => this.onGroupColorChanged(group_index, color)"
          />
          <span class="ps-2">
            <span t-esc="'(#' + (group_index +1 ) + ')'" class="o-text-bolder pe-1"/>
            <span class="text-muted" t-esc="group.label"/>
          </span>
        </div>
      </t>

      <Checkbox
        name="'useValueBasedGradient'"
        label.translate="Use value-based gradient"
        value="coloringOptions.useValueBasedGradient"
        onChange.bind="useValueBasedGradient"
        className="'mt-4'"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-SunburstChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>

    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Sunburst options">
      <t t-set-slot="content">
        <Section class="'pt-0 o-sunburst-colors'" title.translate="Colors">
          <t t-foreach="groupColors" t-as="item" t-key="item.label">
            <div class="d-flex align-items-center mb-2" t-att-data-id="item.label">
              <RoundColorPicker
                currentColor="item.color"
                onColorPicked="(color) => this.onGroupColorChanged(item_index, color)"
              />
              <span class="ps-2">
                <span t-esc="'(#' + (item_index +1 ) + ')'" class="o-text-bolder pe-1"/>
                <span class="text-muted" t-esc="item.label"/>
              </span>
            </div>
          </t>
        </Section>
        <Section title.translate="Labels" class="'pt-0 pb-0'">
          <div class="d-flex flex-row gap-4">
            <Checkbox
              name="'showLabels'"
              label.translate="Show labels"
              value="showLabels"
              onChange="(showLabels) => props.updateChart(this.props.chartId, { showLabels })"
            />
            <ChartShowValues t-props="props" defaultValue="defaults.showValues"/>
          </div>
        </Section>
        <Section class="'pt-0'" t-if="showValues || showLabels">
          <TextStyler
            class="'o-values-style'"
            updateStyle="(valuesDesign) => props.updateChart(this.props.chartId, { valuesDesign })"
            style="props.definition.valuesDesign || {}"
            defaultStyle="defaults.valuesDesign"
          />
        </Section>
        <PieHoleSize
          value="props.definition.pieHolePercentage ?? 25"
          onValueChange.bind="onPieHoleSizeChange"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-ScorecardChartDesignPanel">
    <t t-set="color_up">Color Up</t>
    <t t-set="color_down">Color Down</t>
    <GeneralDesignEditor t-props="props" defaultChartTitleFontSize="defaultScorecardTitleFontSize">
      <t t-set-slot="general-extension">
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <ChartTitle
      title="this.props.definition.keyDescr?.text ?? ''"
      updateTitle="(text) => this.setKeyText(text)"
      name.translate="Key Value Style"
      placeholder.translate="Add a key value description"
      updateStyle.bind="updateKeyStyle"
      style="keyStyle"
    />
    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Baseline">
      <t t-set-slot="content">
        <ChartTitle
          title="this.props.definition.baselineDescr?.text ?? ''"
          updateTitle="(text) => this.setBaselineText(text)"
          name.translate="Baseline Style"
          placeholder.translate="Add a baseline description"
          updateStyle.bind="updateBaselineStyle"
          style="baselineStyle"
        />
        <Section class="'o-chart-baseline-color pt-0'" title="colorsSectionTitle">
          <div class="d-flex align-items-center mb-2">
            <RoundColorPicker
              currentColor="props.definition.baselineColorUp"
              onColorPicked="(color) => this.setColor(color, 'baselineColorUp')"
              title="color_up"
            />
            <span class="ps-2">Color on value increase</span>
          </div>
          <div class="d-flex align-items-center">
            <RoundColorPicker
              currentColor="props.definition.baselineColorDown"
              onColorPicked="(color) => this.setColor(color, 'baselineColorDown')"
              title="color_down"
            />
            <span class="ps-2">Color on value decrease</span>
          </div>
        </Section>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-ScorecardChartConfigPanel">
    <div>
      <Section class="'o-data-series'" title.translate="Key value">
        <SelectionInput
          ranges="[this.getKeyValueRange()]"
          isInvalid="isKeyValueInvalid"
          hasSingleRange="true"
          required="true"
          onSelectionChanged="(ranges) => this.onKeyValueRangeChanged(ranges)"
          onSelectionConfirmed="() => this.updateKeyValueRange()"
        />
      </Section>
      <Section class="'o-data-labels'" title.translate="Baseline configuration">
        <div class="o-section-subtitle">Value</div>
        <SelectionInput
          ranges="[this.getBaselineRange()]"
          isInvalid="isBaselineInvalid"
          hasSingleRange="true"
          onSelectionChanged="(ranges) => this.onBaselineRangeChanged(ranges)"
          onSelectionConfirmed="() => this.updateBaselineRange()"
        />
        <div class="o-section-subtitle">Format</div>
        <select
          t-att-value="props.definition.baselineMode"
          class="o-input"
          t-on-change="(ev) => this.updateBaselineMode(ev)">
          <option value="text">Absolute value</option>
          <option value="difference">Value change from key value</option>
          <option value="percentage">Percentage change from key value</option>
          <option value="progress">Progress bar</option>
        </select>
      </Section>

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-ScatterConfigPanel">
    <div>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        canChangeDatasetOrientation="canChangeDatasetOrientation"
        datasetOrientation="datasetOrientation"
        onFlipAxis.bind="setDatasetOrientation"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged.bind="onLabelRangeChanged"
        onSelectionConfirmed.bind="onLabelRangeConfirmed"
        options="this.getLabelRangeOptions()"
      />

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-RadarChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
          <ChartShowDataMarkers t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesDesignEditor t-props="props"/>
  </t>

  <t t-name="o-spreadsheet-PieChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
        <PieHoleSize
          t-if="props.definition.isDoughnut"
          value="props.definition.pieHolePercentage ?? this.defaultHoleSize"
          onValueChange.bind="onPieHoleSizeChange"
        />
      </t>
    </GeneralDesignEditor>
  </t>

  <t t-name="o-spreadsheet-ChartPanel">
    <div class="o-chart d-flex flex-column h-100" t-if="chartId">
      <div class="o-panel d-flex">
        <div
          class="o-sidePanel-tab o-panel-configuration d-flew flex-grow-1 text-center"
          t-att-class="store.panel !== 'configuration' ? 'inactive' : ''"
          t-on-click="switchPanel.bind(this, 'configuration')">
          <i class="fa fa-sliders me-1"/>
          Configuration
        </div>
        <div
          class="o-sidePanel-tab o-panel-design d-flew flex-grow-1 text-center"
          t-att-class="store.panel !== 'design' ? 'inactive' : ''"
          t-on-click="switchPanel.bind(this, 'design')">
          <i class="fa fa-paint-brush me-1"/>
          Design
        </div>
      </div>

      <t t-set="definition" t-value="getChartDefinition(this.chartId)"/>
      <div class="o-panel-content" t-ref="panelContent">
        <div t-att-class="store.panel !== 'configuration' ? 'd-none' : ''">
          <ChartTypePicker chartId="chartId" chartPanelStore="store"/>
          <t
            t-component="chartPanel.configuration"
            definition="definition"
            chartId="chartId"
            updateChart.bind="updateChart"
            canUpdateChart.bind="canUpdateChart"
            t-key="chartId + definition.type"
          />
        </div>
        <div t-att-class="store.panel !== 'design' ? 'd-none' : ''">
          <t
            t-component="chartPanel.design"
            definition="definition"
            chartId="chartId"
            updateChart.bind="updateChart"
            canUpdateChart.bind="canUpdateChart"
            t-key="chartId + definition.type"
          />
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-LineChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
          <ChartShowDataMarkers t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Zoom">
          <Checkbox
            name="'zoomable'"
            label.translate="Show slicer"
            value="props.definition.zoomable"
            onChange.bind="onToggleZoom"
            className="'mb-2'"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesWithAxisDesignEditor t-props="props"/>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-LineConfigPanel">
    <div>
      <Section class="'pt-0'">
        <Checkbox
          name="'stacked'"
          label="stackedLabel"
          value="props.definition.stacked"
          onChange.bind="onUpdateStacked"
          className="'mb-2'"
        />
        <Checkbox
          name="'cumulative'"
          label="chartTerms.CumulativeData"
          value="props.definition.cumulative"
          onChange.bind="onUpdateCumulative"
        />
      </Section>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        canChangeDatasetOrientation="canChangeDatasetOrientation"
        datasetOrientation="datasetOrientation"
        onFlipAxis.bind="setDatasetOrientation"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged.bind="onLabelRangeChanged"
        onSelectionConfirmed.bind="onLabelRangeConfirmed"
        options="this.getLabelRangeOptions()"
      />

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-HierarchicalChartConfigPanel">
    <div>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        title.translate="Hierarchy"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged.bind="onLabelRangeChanged"
        onSelectionConfirmed.bind="onLabelRangeConfirmed"
        options="this.getLabelRangeOptions()"
        title.translate="Values"
      />

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-GeoChartRegionSelectSection">
    <Section class="'o-geo-region'" title.translate="Region">
      <select class="o-input" t-on-change="this.updateSelectedRegion">
        <t t-foreach="availableRegions" t-as="region" t-key="region.id">
          <option
            t-att-value="region.id"
            t-esc="region.label"
            t-att-selected="region.id === selectedRegion"
          />
        </t>
      </select>
    </Section>
  </t>

  <t t-name="o-spreadsheet-GeoChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <Section class="'pt-0'" title.translate="Legend position">
          <select
            t-att-value="props.definition.legendPosition ?? 'bottom-left'"
            class="o-input o-chart-legend-position"
            t-on-change="this.updateLegendPosition">
            <option value="none">None</option>
            <option value="top">Top left</option>
            <option value="right">Top right</option>
            <option value="bottom">Bottom right</option>
            <option value="left">Bottom left</option>
          </select>
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>

    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Geo chart options">
      <t t-set-slot="content">
        <ColorScalePicker
          definition="props.definition"
          onUpdateColorScale.bind="this.updateColorScale"
        />

        <Section class="'pt-0 o-missing-value'" title.translate="Countries without value">
          <RoundColorPicker
            currentColor="selectedMissingValueColor"
            onColorPicked.bind="updateMissingValueColor"
          />
        </Section>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-GeoChartConfigPanel">
    <div>
      <GeoChartRegionSelectSection
        chartId="props.chartId"
        definition="props.definition"
        updateChart="props.updateChart"
      />

      <ChartDataSeries
        ranges="dataRanges"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        maxNumberOfUsedRanges="maxNumberOfUsedRanges"
        canChangeDatasetOrientation="canChangeDatasetOrientation"
        datasetOrientation="datasetOrientation"
        onFlipAxis.bind="setDatasetOrientation"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged="(ranges) => this.onLabelRangeChanged(ranges)"
        onSelectionConfirmed="() => this.onLabelRangeConfirmed()"
        options="this.getLabelRangeOptions()"
        title.translate="Territories"
      />

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-GaugeChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Gauge Design">
      <t t-set-slot="content">
        <Section class="'pt-0'" title.translate="Range">
          <div class="o-subsection-left">
            <StandaloneComposer
              class="'o-data-range-min'"
              placeholder.translate="Value or formula"
              title.translate="Min value or formula"
              invalid="isRangeMinInvalid"
              composerContent="state.sectionRule.rangeMin"
              defaultRangeSheetId="sheetId"
              onConfirm="(str) => this.onConfirmGaugeRange('rangeMin', str)"
            />
          </div>
          <div class="o-subsection-right">
            <StandaloneComposer
              class="'o-data-range-max'"
              placeholder.translate="Value or formula"
              title.translate="Max value or formula"
              invalid="isRangeMaxInvalid"
              composerContent="state.sectionRule.rangeMax"
              defaultRangeSheetId="sheetId"
              onConfirm="(str) => this.onConfirmGaugeRange('rangeMax', str)"
            />
          </div>
        </Section>

        <Section title.translate="Thresholds">
          <t t-call="o-spreadsheet-GaugeChartColorSectionTemplate">
            <t t-set="sectionRule" t-value="state.sectionRule"/>
          </t>
        </Section>

        <ChartErrorSection t-if="designErrorMessages.length" messages="designErrorMessages"/>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-GaugeChartColorSectionTemplate">
    <div class="o-gauge-color-set">
      <table>
        <tr>
          <th class="o-gauge-color-set-colorPicker"/>
          <th class="o-gauge-color-set-text"/>
          <th class="o-gauge-color-set-operator"/>
          <th class="o-gauge-color-set-value">Value</th>
          <th class="o-gauge-color-set-type">Type</th>
        </tr>

        <t t-call="o-spreadsheet-GaugeChartColorSectionTemplateRow">
          <t t-set="sectionColor" t-value="sectionRule.colors.lowerColor"/>
          <t t-set="sectionType" t-value="'lowerColor'"/>
          <t t-set="inflectionPoint" t-value="sectionRule.lowerInflectionPoint"/>
          <t t-set="isInvalid" t-value="isLowerInflectionPointInvalid"/>
          <t t-set="inflectionPointName" t-value="'lowerInflectionPoint'"/>
        </t>

        <t t-call="o-spreadsheet-GaugeChartColorSectionTemplateRow">
          <t t-set="sectionColor" t-value="sectionRule.colors.middleColor"/>
          <t t-set="sectionType" t-value="'middleColor'"/>
          <t t-set="inflectionPoint" t-value="sectionRule.upperInflectionPoint"/>
          <t t-set="isInvalid" t-value="isUpperInflectionPointInvalid"/>
          <t t-set="inflectionPointName" t-value="'upperInflectionPoint'"/>
        </t>

        <tr>
          <td>
            <RoundColorPicker
              currentColor="sectionRule.colors.upperColor"
              onColorPicked="(color) => this.updateSectionColor('upperColor', color)"
            />
          </td>
          <td>Else</td>
          <td/>
          <td/>
          <td/>
        </tr>
      </table>
    </div>
  </t>

  <t t-name="o-spreadsheet-GaugeChartColorSectionTemplateRow">
    <tr>
      <td>
        <RoundColorPicker
          currentColor="sectionColor"
          onColorPicked="(color) => this.updateSectionColor(sectionType, color)"
        />
      </td>
      <td>When value is</td>
      <td class="pe-2">
        <t t-set="below">below</t>
        <t t-set="belowOrEqualTo">below or equal to</t>
        <select
          class="o-input"
          name="operatorType"
          t-att-title="inflectionPoint.operator === '&lt;' ? below : belowOrEqualTo"
          t-model="inflectionPoint.operator"
          t-on-change="() => this.updateSectionRule(state.sectionRule)">
          <option title="below" value="&lt;">&lt;</option>
          <option title="below or equal to" value="&lt;=">&lt;=</option>
        </select>
      </td>
      <td class="pe-2">
        <StandaloneComposer t-props="getGaugeInflectionComposerProps(sectionType)"/>
      </td>
      <td>
        <select
          class="o-input"
          name="valueType"
          t-model="inflectionPoint.type"
          t-on-change="(ev) => this.updateSectionRule(state.sectionRule)">
          <option value="number">Number</option>
          <option value="percentage">Percentage</option>
        </select>
      </td>
    </tr>
  </t>

  <t t-name="o-spreadsheet-GaugeChartConfigPanel">
    <div>
      <ChartDataSeries
        ranges="[this.getDataRange()]"
        onSelectionChanged="(ranges) => this.onDataRangeChanged(ranges)"
        onSelectionConfirmed="() => this.updateDataRange()"
        hasSingleRange="true"
      />

      <ChartErrorSection
        t-if="configurationErrorMessages.length"
        messages="configurationErrorMessages"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-FunnelChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>

    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Funnel options">
      <t t-set-slot="content">
        <Section class="'o-funnel-colors pt-0'" title.translate="Funnel colors">
          <t t-foreach="getFunnelColorItems()" t-as="item" t-key="item_index">
            <div class="d-flex align-items-center mb-2" t-att-data-id="item_index">
              <RoundColorPicker
                currentColor="item.color"
                onColorPicked="(color) => this.updateFunnelItemColor(item_index, color)"
              />
              <span class="ps-2" t-esc="item.label"/>
            </div>
          </t>
        </Section>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-ComboChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
          <ChartShowDataMarkers t-props="props"/>
        </Section>
        <Section class="'pt-0'" title.translate="Zoom">
          <Checkbox
            name="'zoomable'"
            label.translate="Show slicer"
            value="props.definition.zoomable"
            onChange.bind="onToggleZoom"
            className="'mb-2'"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesWithAxisDesignEditor t-props="props">
      <t t-set-slot="general-extension" t-slot-scope="scope">
        <t t-set="index" t-value="scope.index"/>
        <Section class="'pt-0 o-series-type-selection'" title.translate="Serie type">
          <RadioSelection
            choices="seriesTypeChoices"
            selectedValue="getDataSeriesType(index)"
            name="'seriesType'"
            onChange="(type) => this.updateDataSeriesType(index, type)"
          />
        </Section>
      </t>
    </SeriesWithAxisDesignEditor>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-ChartWithAxisDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
        <Section class="'pt-1'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesWithAxisDesignEditor t-props="props"/>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-ChartTypePicker">
    <t t-set="selectedChartProperties" t-value="getSelectedChartSubtypeProperties()"/>
    <Section title.translate="Chart type">
      <div class="position-relative">
        <select
          class="o-input o-type-selector"
          t-ref="selectRef"
          t-on-pointerdown.prevent="onPointerDown">
          <option
            t-esc="selectedChartProperties.displayName"
            t-att-value="selectedChartProperties.chartSubtype"
          />
        </select>
        <div class="o-type-selector-preview position-absolute">
          <t t-call="{{selectedChartProperties.preview}}"/>
        </div>
      </div>
    </Section>
    <Popover t-if="state.popoverProps" t-props="state.popoverProps">
      <div
        t-ref="popoverRef"
        class="o-chart-select-popover px-3 pb-4 bg-white"
        t-att-style="state.popoverStyle">
        <t t-foreach="categories" t-as="category" t-key="category">
          <t t-if="chartTypeByCategories[category]">
            <h5 class="my-3" t-esc="category_value"/>
            <div class="d-flex flex-wrap">
              <t
                t-foreach="chartTypeByCategories[category]"
                t-as="properties"
                t-key="properties.chartSubtype">
                <div
                  class="o-chart-type-item"
                  t-att-title="properties.displayName"
                  t-on-click="() => this.onTypeChange(properties.chartSubtype)"
                  t-att-data-id="properties.chartSubtype"
                  t-att-class="{'selected': properties === selectedChartProperties}">
                  <t t-call="{{properties.preview}}"/>
                </div>
              </t>
            </div>
          </t>
        </t>
      </div>
    </Popover>
  </t>

  <t t-name="o-spreadsheet-ChartPreview.LINE_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
      <path
        stroke="var(--os-chart-preview-orange-line)"
        style="fill:none"
        d="M6,40 l12,-12 l6,6 l18,-18"
      />
      <path
        stroke="var(--os-chart-preview-blue-line)"
        style="fill:none"
        d="M6,25 l12,-12 l18,18 l6,-6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.STACKED_LINE_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        stroke="var(--os-chart-preview-blue-line)"
        style="fill:none"
        d="M3,30 l12,-12 l6,6 l18,-18"
      />
      <path
        stroke="var(--os-chart-preview-orange-line)"
        style="fill:none"
        d="M3,40 l12,-12 l6,6 l18,-12"
      />
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.AREA_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-chart-preview-blue-fill)" d="M3,45 V25 l12,-12 l18,18 l6,-6 V45"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M3,45 V40 l12,-12 l6,6 l18,-18 V45"/>
      <path
        stroke="var(--os-chart-preview-orange-line)"
        style="fill:none"
        d="M3,40 l12,-12 l6,6 l18,-18"
      />
      <path
        stroke="var(--os-chart-preview-blue-line)"
        style="fill:none"
        d="M3,25 l12,-12 l18,18 l6,-6"
      />
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.STACKED_AREA_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-chart-preview-blue-fill)" d="M3,45 h36 v-39 l-18,18 l-6,-6 l-12,12"/>
      <path
        stroke="var(--os-chart-preview-blue-line)"
        style="fill:none"
        d="M3,30 l12,-12 l6,6 l18,-18"
      />
      <path fill="var(--os-chart-preview-orange-fill)" d="M3,45 h36 v-23 l-18,12 l-6,-6 l-12,12"/>
      <path
        stroke="var(--os-chart-preview-orange-line)"
        style="fill:none"
        d="M3,40 l12,-12 l6,6 l18,-12"
      />
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.COLUMN_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-chart-preview-blue-line)" d="M7,45 v-28 h6 v28"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M8,45 v-27 h4 v27"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M14,45 v-14 h6 v14"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M15,45 v-13 h4 v13"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M26,45 v-22 h6 v22"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M27,45 v-21 h4 v21"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M33,45 v-32 h6 v32"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M34,45 v-31 h4 v31"/>
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.STACKED_COLUMN_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-chart-preview-blue-line)" d="M7,45 v-12 h8 v12"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M8,45 v-11 h6 v11"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M7,33 v-14 h8 v14"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M8,33 v-13 h6 v13"/>

      <path fill="var(--os-chart-preview-blue-line)" d="M20,45 v-8 h8 v8"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M21,45 v-7 h6 v7"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M20,37 v-9 h8 v9"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M21,37 v-8 h6 v8"/>

      <path fill="var(--os-chart-preview-blue-line)" d="M33,45 v-18 h8 v18"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M34,45 v-17 h6 v17"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M33,27 v-16 h8 v16"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M34,27 v-15 h6 v15"/>

      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.BAR_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <g transform="matrix(0 1 -1 0 48 3)">
        <path fill="var(--os-chart-preview-blue-line)" d="M7,45 v-28 h6 v28"/>
        <path fill="var(--os-chart-preview-blue-fill)" d="M8,45 v-27 h4 v27"/>
        <path fill="var(--os-chart-preview-orange-line)" d="M14,45 v-14 h6 v14"/>
        <path fill="var(--os-chart-preview-orange-fill)" d="M15,45 v-13 h4 v13"/>
        <path fill="var(--os-chart-preview-blue-line)" d="M26,45 v-22 h6 v22"/>
        <path fill="var(--os-chart-preview-blue-fill)" d="M27,45 v-21 h4 v21"/>
        <path fill="var(--os-chart-preview-orange-line)" d="M33,45 v-32 h6 v32"/>
        <path fill="var(--os-chart-preview-orange-fill)" d="M34,45 v-31 h4 v31"/>
      </g>
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.STACKED_BAR_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <g transform="matrix(0 1 -1 0 48 1)">
        <path fill="var(--os-chart-preview-blue-line)" d="M7,45 v-12 h8 v12"/>
        <path fill="var(--os-chart-preview-blue-fill)" d="M8,45 v-11 h6 v11"/>
        <path fill="var(--os-chart-preview-orange-line)" d="M7,33 v-14 h8 v14"/>
        <path fill="var(--os-chart-preview-orange-fill)" d="M8,33 v-13 h6 v13"/>
        <path fill="var(--os-chart-preview-blue-line)" d="M20,45 v-8 h8 v8"/>
        <path fill="var(--os-chart-preview-blue-fill)" d="M21,45 v-7 h6 v7"/>
        <path fill="var(--os-chart-preview-orange-line)" d="M20,37 v-9 h8 v9"/>
        <path fill="var(--os-chart-preview-orange-fill)" d="M21,37 v-8 h6 v8"/>
        <path fill="var(--os-chart-preview-blue-line)" d="M33,45 v-18 h8 v18"/>
        <path fill="var(--os-chart-preview-blue-fill)" d="M34,45 v-17 h6 v17"/>
        <path fill="var(--os-chart-preview-orange-line)" d="M33,27 v-16 h8 v16"/>
        <path fill="var(--os-chart-preview-orange-fill)" d="M34,27 v-15 h6 v15"/>
      </g>
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.COMBO_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-chart-preview-blue-line)" d="M7,45 v-14 h6 v14"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M8,45 v-13 h4 v13"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M14,45 v-28 h6 v28"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M15,45 v-27 h4 v27"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M26,45 v-22 h6 v22"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M27,45 v-21 h4 v21"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M33,45 v-32 h6 v32"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M34,45 v-31 h4 v31"/>
      <path
        stroke="var(--os-gray-500)"
        style="fill:none;stroke-width:1.5;"
        d="M4,40 l14,-12 l6,6 l20,-18"
      />
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.PIE_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="var(--os-chart-preview-orange-fill)"
        stroke="var(--os-chart-preview-orange-line)"
        d="M41.32, 34 A20 20, 0, 1, 1, 24, 4 v20"
      />
      <path
        fill="var(--os-chart-preview-blue-fill)"
        stroke="var(--os-chart-preview-blue-line)"
        d="M24,24 v-20 A20 20, 0, 0, 1, 41.32, 34 L24,24"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.DOUGHNUT_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="var(--os-chart-preview-orange-fill)"
        stroke="var(--os-chart-preview-orange-line)"
        d="M41.32, 34 A20 20, 0, 1, 1, 24, 4 v8 A12,12,0,1,0,34.4,30"
      />
      <path
        fill="var(--os-chart-preview-blue-fill)"
        stroke="var(--os-chart-preview-blue-line)"
        d="M24,12 v-8 A20 20, 0, 0, 1, 41.32, 34 L34.4,30 A12,12,0,0,0,24,12"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.SCATTER_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <circle fill="var(--os-chart-preview-blue-line)" cx="10" cy="10" r="2"/>
      <circle fill="var(--os-chart-preview-blue-line)" cx="15" cy="30" r="2"/>
      <circle fill="var(--os-chart-preview-blue-line)" cx="25" cy="36" r="2"/>
      <circle fill="var(--os-chart-preview-blue-line)" cx="32" cy="15" r="2"/>
      <circle fill="var(--os-chart-preview-orange-line)" cx="10" cy="40" r="2"/>
      <circle fill="var(--os-chart-preview-orange-line)" cx="18" cy="20" r="2"/>
      <circle fill="var(--os-chart-preview-orange-line)" cx="30" cy="25" r="2"/>
      <circle fill="var(--os-chart-preview-orange-line)" cx="40" cy="33" r="2"/>
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.GAUGE_CHART">
    <svg
      viewBox="0 0 48 48"
      class="o-chart-preview user-select-none"
      xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-gray-400)" d="M2,32 A22,22,0,0,1,46,32 h-6 A16,16,0,0,0,8,32"/>
      <path fill="#6aa84f" d="M2,32 A22,22,0,0,1,35,13 L32,18.2 A16,16,0,0,0,8,32"/>
      <text fill="currentColor" x="17" y="32" style="font-size:12px;">62</text>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.SCORECARD_CHART">
    <svg
      viewBox="0 0 48 48"
      class="o-chart-preview user-select-none"
      xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-gray-300)" d="M1,8 h46 v32 h-46"/>
      <path fill="var(--os-gray-200)" d="M2,9 h44 v30 h-44"/>
      <text fill="currentColor" x="9" y="32" style="font-size:18px;">123</text>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.WATERFALL_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-gray-600)" d="M5,45 v-26 h6 v26"/>
      <path fill="var(--os-white-bg)" d="M6,45 v-25 h4 v25"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M13,19 v7 h6 v-7"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M14,20 v5 h4 v-5"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M21,25 v10 h6 v-10"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M22,26 v8 h4 v-8"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M29,35 v-24 h6 v24"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M30,34 v-22 h4 v22"/>
      <path fill="var(--os-gray-600)" d="M37,45 v-34 h6 v34"/>
      <path fill="var(--os-white-bg)" d="M38,45 v-33 h4 v33"/>
      <path
        fill="var(--os-gray-600)"
        d="M11,20 v-1 h2 v1 M19,26 v-1 h2 v1 M27,35 v-1 h2 v1 M35,12 v-1 h2 v1"
      />
      <path fill="var(--os-gray-600)" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.POPULATION_PYRAMID_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-chart-preview-orange-line)" d="M23,43 v-6 h22 v6"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M23,42 v-4 h21 v4"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M23,36 v-6 h18 v6"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M23,35 v-4 h17 v4"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M23,29 v-6 h12 v6"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M23,28 v-4 h11 v4"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M23,22 v-6 h8 v6"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M23,21 v-4 h7 v4"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M23,15 v-6 h4 v6"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M23,14 v-4 h3 v4"/>

      <path fill="var(--os-chart-preview-blue-line)" d="M24,43 v-6 h-20 v6"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M24,42 v-4 h-19 v4"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M24,36 v-6 h-18 v6"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M24,35 v-4 h-17 v4"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M24,29 v-6 h-12 v6"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M24,28 v-4 h-11 v4"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M24,22 v-6 h-6 v6"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M24,21 v-4 h-5 v4"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M24,15 v-6 h-4 v6"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M24,14 v-4 h-3 v4"/>

      <path fill="var(--os-gray-600)" d="M23,2 v43 h1 v-43 M2,45 h44 v1 h-44"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.RADAR_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="none"
        stroke="var(--os-chart-preview-blue-line)"
        d="m24 16 14.27 3.36-1.93 21.63-18.22-8.9-3.63-11.18Z"
      />
      <path
        fill="none"
        stroke="var(--os-chart-preview-orange-line)"
        d="m24 4 7.61 17.53-4.67 6.52-12.34 8.89-7.72-18.5Z"
      />
      <path
        fill="none"
        stroke="var(--os-gray-600)"
        d="M24 2v22l20.92-6.8L24 24l12.93 17.8L24 24 11.07 41.8 24 24 3.08 17.2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.FILLED_RADAR_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="var(--os-chart-preview-blue-line)"
        fill-opacity="0.25"
        stroke="var(--os-chart-preview-blue-line)"
        d="m24 16 14.27 3.36-1.93 21.63-18.22-8.9-3.63-11.18Z"
      />
      <path
        fill="var(--os-chart-preview-orange-line)"
        fill-opacity="0.25"
        stroke="var(--os-chart-preview-orange-line)"
        d="m24 4 7.61 17.53-4.67 6.52-12.34 8.89-7.72-18.5Z"
      />
      <path
        fill="none"
        stroke="var(--os-gray-600)"
        d="M24 2v22l20.92-6.8L24 24l12.93 17.8L24 24 11.07 41.8 24 24 3.08 17.2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.GEO_CHART">
    <svg
      viewBox="0 0 32 32"
      xmlns="http://www.w3.org/2000/svg"
      class="o-chart-preview"
      fill="none"
      stroke-width="0.5"
      stroke-linejoin="round">
      <circle cx="16" cy="16" r="13" fill="var(--os-chart-preview-blue-fill)"/>
      <path
        stroke="var(--os-chart-preview-orange-line)"
        fill="var(--os-chart-preview-orange-fill)"
        d="M12.225 16.293c0 6.8 4 9 5 9 3.5 0 2-5.293 3.5-6.793s5-.707 5-4.207-2-5-5-5c-5 0-8.5 1.5-8.5 7z"
      />
      <path
        fill="var(--os-chart-preview-orange-fill)"
        d="M21.5 4.4c0 1.167-1.735 1.5-3 1.5-5.217 0-10.705 3.48-11.421 8.004C6.992 14.549 6.552 15 6 15H3.07 A 13 13 0 0 1 21.5 4.2
                M3.8 20.5c.785.262 2.126 1.285 3.44 1.517.57.101 1.153.464 1.299 1.023.303 1.16.548 1.992-.239 3.58 A 13 13 0 0 1 3.8 20.5"
      />
      <path
        stroke="var(--os-chart-preview-orange-line)"
        d="M21.5 4.4c0 1.167-1.735 1.5-3 1.5-5.217 0-10.705 3.48-11.421 8.004C6.992 14.549 6.552 15 6 15H3.07
                M3.8 20.5c.785.262 2.126 1.285 3.44 1.517.57.101 1.153.464 1.299 1.023.303 1.16.548 1.992-.239 3.58"
      />
      <circle cx="16" cy="16" r="13" stroke="var(--os-gray-600)"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.FUNNEL_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        stroke="var(--os-chart-preview-blue-line)"
        fill="var(--os-chart-preview-blue-fill)"
        d="M2.5,6.5 h44 l-5,7 h-34 l-5,-7 h1"
      />
      <path
        stroke="var(--os-chart-preview-orange-line)"
        fill="var(--os-chart-preview-orange-fill)"
        d="M9.5,16.5 h30 l-3,7 h-25 l-3,-7 h1"
      />
      <path
        stroke="var(--os-chart-preview-blue-line)"
        fill="var(--os-chart-preview-blue-fill)"
        d="M12.5,26.5 h23 l-8,7 h-7 l-8,-7 h1"
      />
      <path
        stroke="var(--os-chart-preview-orange-line)"
        fill="var(--os-chart-preview-orange-fill)"
        d="M21.5,35.5 h5 l-2.5,7 l-2.5,-7 h1"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.SUNBURST_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="var(--os-chart-preview-orange-fill)"
        stroke="var(--os-chart-preview-orange-line)"
        d="M24,12 v8A4,4,0,1,0,27.46,26 L41.32, 34 A20,20,0,0,1,8.679,36.856 L14.807,31.713 A12,12,0,0,1,24,12 M34.4,30 A12,12,0,0,1,14.807,31.713"
      />
      <path
        fill="var(--os-chart-preview-blue-fill)"
        stroke="var(--os-chart-preview-blue-line)"
        d="M24,20 v-16 A20 20, 0, 0, 1, 41.32, 34 L27.46,26 A4,4,0,0,0,24,20 M24,12 A12,12,0,0,1,34.4,30 M33.193,16.287 L39.321,11.144 M36,24 L44,24"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.TREE_MAP_CHART">
    <svg viewBox="0 0 48 48" class="o-chart-preview" xmlns="http://www.w3.org/2000/svg">
      <path fill="var(--os-gray-600)" d="M2,4 h44 v5 h-44"/>
      <path fill="var(--os-gray-600)" d="M2,10 h28 v5 h-28"/>
      <path fill="var(--os-gray-600)" d="M31,10 h15 v5 h-15"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M2,16 h28 v14 h-28"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M3,17 h26 v12 h-26"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M2,31 h15 v12 h-15"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M3,32 h13 v10 h-13"/>
      <path fill="var(--os-chart-preview-blue-line)" d="M18,31 h12 v12 h-12"/>
      <path fill="var(--os-chart-preview-blue-fill)" d="M19,32 h10 v10 h-10"/>
      <path fill="var(--os-chart-preview-orange-line)" d="M31,16 h15 v27 h-15"/>
      <path fill="var(--os-chart-preview-orange-fill)" d="M32,17 h13 v25 h-13"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-ChartPreview.CALENDAR_CHART">
    <svg class="o-chart-preview" viewBox="0 0 48 48">
      <path fill="var(--os-gray-600)" d="M3 3h42v42H3zh1v41h40V4H4"/>
      <path
        fill="var(--os-chart-preview-orange-line)"
        d="M7 7h7v7H7m0 2h7v7H7m0 2h7v7H7m0 2h7v7H7m9-34h7v7h-7m0 2h7v7h-7m0 2h7v7h-7m0 2h7v7h-7m9-34h7v7h-7m0 11h7v7h-7m0 2h7v7h-7m9-34h7v7h-7m0 2h7v7h-7m0 2h7v7h-7m0 2h7v7h-7"
      />
      <path
        fill="var(--os-chart-preview-orange-fill)"
        d="M8 8h5v5H8m0 13h5v5H8m9 4h5v5h-5m18-5h5v5h-5"
      />
      <path
        fill="var(--os-chart-preview-orange-light)"
        d="M8 17h5v5H8m9-14h5v5h-5m0 13h5v5h-5m9 4h5v5h-5m9-32h5v5h-5m0 13h5v5h-5"
      />
      <path fill="var(--os-white-bg)" d="M8 35h5v5H8"/>
      <path fill="var(--os-chart-preview-orange-dark)" d="M25 16h7v7h-7"/>
    </svg>
  </t>

  <t t-name="o-spreadsheet-CalendarChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <Section class="'pt-0'" title.translate="Legend position">
          <select
            t-att-value="props.definition.legendPosition ?? 'bottom-left'"
            class="o-input o-chart-legend-position"
            t-on-change="this.updateLegendPosition">
            <option value="none">None</option>
            <option value="right">Right</option>
            <option value="left">Left</option>
          </select>
        </Section>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Calendar chart options">
      <t t-set-slot="content">
        <ColorScalePicker definition="props.definition" onUpdateColorScale.bind="onColormapChange"/>
        <Section class="'pt-0 o-missing-value'" title.translate="Missing value color">
          <RoundColorPicker
            currentColor="selectedMissingValueColor"
            onColorPicked.bind="updateMissingValueColor"
          />
        </Section>
      </t>
    </SidePanelCollapsible>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-CalendarChartConfigPanel">
    <div>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        maxNumberOfUsedRanges="1"
        canChangeDatasetOrientation="false"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged.bind="onLabelRangeChanged"
        onSelectionConfirmed.bind="onLabelRangeConfirmed"
        options="this.getLabelRangeOptions()"
        title.translate="Date range"
      />

      <Section title.translate="Fields to group by">
        <div class="d-flex">
          <span class="w-100">Horizontal axis</span>
          <select
            t-att-value="getGroupByType('horizontal')"
            class="o-input o-horizontal-group-by"
            t-on-change="ev => this.updateGroupBy('horizontal', ev.target.value)">
            <t t-foreach="getGroupByOptions()" t-as="groupBy" t-key="groupBy.value">
              <option
                t-att-selected="getGroupByType('horizontal') === groupBy.value"
                t-att-value="groupBy.value">
                <t t-esc="groupBy.label"/>
              </option>
            </t>
          </select>
        </div>
        <div class="d-flex">
          <span class="w-100">Vertical axis</span>
          <select
            t-att-value="getGroupByType('vertical')"
            class="o-input o-vertical-group-by"
            t-on-change="ev => this.updateGroupBy('vertical', ev.target.value)">
            <t t-foreach="getGroupByOptions()" t-as="groupBy" t-key="groupBy.value">
              <option
                t-att-selected="getGroupByType('vertical') === groupBy.value"
                t-att-value="groupBy.value">
                <t t-esc="groupBy.label"/>
              </option>
            </t>
          </select>
        </div>
      </Section>

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet.TextStyler">
    <div
      class="o-chart-title-designer position-relative d-flex align-items-center"
      t-att-class="props.class">
      <ActionButton action="boldButtonAction" class="'o-hoverable-button'"/>
      <ActionButton action="italicButtonAction" class="'o-hoverable-button'"/>
      <div
        class="o-divider border-start"
        t-if="props.hasHorizontalAlign || props.hasVerticalAlign"
      />
      <div class="o-dropdown position-relative" t-if="props.hasHorizontalAlign">
        <ActionButton
          action="horizontalAlignButtonAction"
          hasTriangleDownIcon="true"
          t-on-click="(ev) => this.toggleDropdownTool('horizontalAlignTool', ev)"
          class="'o-hoverable-button'"
        />
        <div
          class="o-dropdown-content position-absolute top-100 start-0 bg-white"
          t-if="state.activeTool === 'horizontalAlignTool'"
          t-att-style="dropdownStyle"
          t-on-click.stop="">
          <div class="o-dropdown-line d-flex">
            <t t-foreach="horizontalAlignActions" t-as="action" t-key="action_index">
              <ActionButton action="action" class="'o-hoverable-button'"/>
            </t>
          </div>
        </div>
      </div>
      <div class="o-dropdown position-relative" t-if="props.hasVerticalAlign">
        <ActionButton
          action="verticalAlignButtonAction"
          hasTriangleDownIcon="true"
          t-on-click="(ev) => this.toggleDropdownTool('verticalAlignTool', ev)"
          class="'o-hoverable-button'"
        />
        <div
          class="o-dropdown-content position-absolute top-100 start-0 bg-white"
          t-if="state.activeTool === 'verticalAlignTool'"
          t-att-style="dropdownStyle"
          t-on-click.stop="">
          <div class="o-dropdown-line d-flex">
            <t t-foreach="verticalAlignActions" t-as="action" t-key="action_index">
              <ActionButton action="action" class="'o-hoverable-button'"/>
            </t>
          </div>
        </div>
      </div>
      <div class="o-divider border-start"/>
      <FontSizeEditor
        currentFontSize="currentFontSize"
        onFontSizeChanged.bind="this.updateFontSize"
        class="'o-hoverable-button'"
      />
      <div class="o-divider border-start"/>
      <ColorPickerWidget
        currentColor="props.style.color ?? props.defaultStyle?.color"
        toggleColorPicker="(ev) => this.toggleDropdownTool('fillChartColorTool', ev)"
        showColorPicker="state.activeTool === 'fillChartColorTool'"
        onColorPicked.bind="onTextColorChange"
        title.translate="Text color"
        icon="'o-spreadsheet-Icon.TEXT_COLOR'"
        class="'o-hoverable-button o-menu-item-button'"
      />
      <ColorPickerWidget
        t-if="props.hasBackgroundColor"
        currentColor="props.style.fillColor || props.defaultStyle?.fillColor"
        toggleColorPicker="(ev) => this.toggleDropdownTool('fillcolorTool', ev)"
        showColorPicker="state.activeTool === 'fillcolorTool'"
        onColorPicked.bind="onFillColorChange"
        title.translate="Fill color"
        icon="'o-spreadsheet-Icon.FILL_COLOR'"
        class="'o-hoverable-button o-menu-item-button'"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-ChartShowValues">
    <Checkbox
      name="'showValues'"
      label.translate="Show values"
      value="props.definition.showValues ?? props.defaultValue"
      onChange="(showValues) => props.updateChart(this.props.chartId, { showValues })"
    />
  </t>

  <t t-name="o-spreadsheet-ChartShowDataMarkers">
    <Checkbox
      name="'showDataMarkers'"
      label.translate="Show data markers"
      value="!props.definition.hideDataMarkers"
      onChange="(showDataMarkers) => props.updateChart(this.props.chartId, { hideDataMarkers: !showDataMarkers })"
    />
  </t>

  <t t-name="o-spreadsheet-SeriesWithAxisDesignEditor">
    <SeriesDesignEditor t-props="props">
      <t t-set-slot="data-series-extension" t-slot-scope="scope">
        <t t-set="index" t-value="scope.index"/>
        <t t-slot="general-extension" index="index"/>
        <Section class="'pt-0 pb-0'">
          <Section
            class="'pt-0 px-0 o-vertical-axis-selection'"
            t-if="canHaveTwoVerticalAxis"
            title.translate="Vertical axis">
            <RadioSelection
              choices="axisChoices"
              selectedValue="getDataSerieAxis(index)"
              name="'axis'"
              onChange="(value) => this.updateDataSeriesAxis(index, value)"
            />
          </Section>
          <Section
            class="'pt-0 px-0 o-show-trend-line'"
            t-if="!props.definition.horizontal"
            title.translate="Trend line">
            <t t-set="showTrendLineLabel">Show trend line</t>
            <t t-set="trend" t-value="getTrendLineConfiguration(index)"/>
            <t t-set="trendType" t-value="getTrendType(trend)"/>
            <Checkbox
              name="'showTrendLine'"
              label="showTrendLineLabel"
              value="trend !== undefined and trend.display"
              onChange="(display) => this.toggleDataTrend(index, display)"
            />
            <div t-if="trend !== undefined and trend.display">
              <div class="d-flex py-2">
                <div class="w-100">
                  <span class="o-section-subtitle">Type</span>
                  <select
                    class="o-input trend-type-selector"
                    t-on-change="(ev) => this.onChangeTrendType(index, ev)">
                    <option value="linear" t-att-selected="trendType === 'linear'">Linear</option>
                    <option value="exponential" t-att-selected="trendType === 'exponential'">
                      Exponential
                    </option>
                    <option value="polynomial" t-att-selected="trendType === 'polynomial'">
                      Polynomial
                    </option>
                    <option value="logarithmic" t-att-selected="trendType === 'logarithmic'">
                      Logarithmic
                    </option>
                    <option
                      value="trailingMovingAverage"
                      t-att-selected="trendType === 'trailingMovingAverage'">
                      Trailing moving average
                    </option>
                  </select>
                </div>
                <div class="w-50 ms-3" t-if="trendType === 'trailingMovingAverage'">
                  <span class="o-section-subtitle">Window</span>
                  <NumberInput
                    value="trend.window || this.defaultWindowSize"
                    class="'w-100 trend-window-input'"
                    min="2"
                    onChange="(value) => this.onChangeMovingAverageWindow(index, value)"
                  />
                </div>
                <div class="w-50 ms-3" t-if="trendType === 'polynomial'">
                  <span class="o-section-subtitle">Degree</span>
                  <select
                    t-att-value="trend.order"
                    class="o-input trend-order-input"
                    t-on-change="(ev) => this.onChangePolynomialDegree(index, ev)">
                    <t t-foreach="getPolynomialDegrees(index)" t-as="degree" t-key="degree">
                      <option t-att-value="degree">
                        <t t-esc="degree"/>
                      </option>
                    </t>
                  </select>
                </div>
              </div>
              <div class="d-flex align-items-center">
                <span class="o-section-subtitle my-0 pe-2">Trend line color</span>
                <RoundColorPicker
                  currentColor="getTrendLineColor(index)"
                  onColorPicked="(ev) => this.updateTrendLineColor(index, ev)"
                />
              </div>
            </div>
          </Section>
        </Section>
      </t>
    </SeriesDesignEditor>
  </t>

  <t t-name="o-spreadsheet-SeriesDesignEditor">
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Data Series">
      <t t-set-slot="content">
        <Section class="'pt-0 pb-0'">
          <select
            class="o-input data-series-selector"
            t-model="state.label"
            t-on-change="(ev) => this.updateEditedSeries(ev)">
            <t t-foreach="getDataSeries()" t-as="serie" t-key="serie_index">
              <option
                t-att-value="serie"
                t-att-selected="state.index === serie_index"
                t-esc="serie"
              />
            </t>
          </select>
          <Section class="'px-0'">
            <div class="d-flex align-items-center">
              <span class="o-section-title mb-0 pe-2">Series color</span>
              <RoundColorPicker
                currentColor="getDataSeriesColor()"
                onColorPicked.bind="updateDataSeriesColor"
              />
            </div>
          </Section>
          <Section class="'pt-0 px-0'" title.translate="Series name">
            <input
              class="o-input o-serie-label-editor"
              type="text"
              t-att-value="getDataSeriesLabel()"
              t-on-change="(ev) => this.updateDataSeriesLabel(ev)"
            />
          </Section>
        </Section>
        <t t-slot="data-series-extension" index="state.index"/>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet.PieHoleSize">
    <Section class="'pt-0'" title.translate="Center radius">
      <div class="d-flex flex-row">
        <NumberInput
          value="props.value"
          class="'o-pie-hole-size-input'"
          min="0"
          max="95"
          onChange.bind="onChange"
        />
        %
      </div>
    </Section>
  </t>

  <t t-name="o-spreadsheet-ChartLegend">
    <Section class="'pt-0'" title.translate="Legend position">
      <select
        t-att-value="props.definition.legendPosition ?? 'top'"
        class="o-input o-chart-legend-position"
        t-on-change="this.updateLegendPosition">
        <option value="none">None</option>
        <option value="top">Top</option>
        <option value="bottom">Bottom</option>
        <option value="left">Left</option>
        <option value="right">Right</option>
      </select>
    </Section>
  </t>

  <t t-name="o-spreadsheet.ChartLabelRange">
    <Section class="'o-data-labels'" title="props.title">
      <SelectionInput
        ranges="[props.range]"
        isInvalid="props.isInvalid"
        hasSingleRange="true"
        onSelectionChanged="(ranges) => props.onSelectionChanged(ranges)"
        onSelectionConfirmed="() => props.onSelectionConfirmed()"
      />
      <t t-foreach="props.options" t-as="option" t-key="option.name">
        <Checkbox
          name="option.name"
          label="option.label"
          value="option.value"
          onChange="option.onChange"
          className="'mt-2'"
          disabled="option.disabled"
        />
      </t>
    </Section>
  </t>

  <t t-name="o-spreadsheet-ChartHumanizeNumbers">
    <Checkbox
      name="'humanizeNumbers'"
      label.translate="Use compact format"
      title="title"
      value="props.definition.humanize ?? true"
      onChange="(humanize) => props.updateChart(this.props.chartId, { humanize })"
    />
  </t>

  <t t-name="o-spreadsheet-GenericChartConfigPanel">
    <div>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        maxNumberOfUsedRanges="maxNumberOfUsedRanges"
        datasetOrientation="datasetOrientation"
        canChangeDatasetOrientation="canChangeDatasetOrientation"
        onFlipAxis.bind="setDatasetOrientation"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged.bind="onLabelRangeChanged"
        onSelectionConfirmed.bind="onLabelRangeConfirmed"
        options="this.getLabelRangeOptions()"
      />

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-GeneralDesignEditor">
    <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="General">
      <t t-set-slot="content">
        <Section class="'o-chart-background-color pt-0 pb-0'" title.translate="Background color">
          <RoundColorPicker
            currentColor="props.definition.background"
            onColorPicked.bind="updateBackgroundColor"
          />
        </Section>
        <ChartTitle
          title="title.text"
          updateTitle.bind="updateTitle"
          name.translate="Chart title"
          placeholder.translate="Add a Title"
          updateStyle.bind="updateChartTitleStyle"
          style="title"
          defaultStyle="{align: 'left', fontSize: this.props.defaultChartTitleFontSize}"
        />
        <t t-slot="general-extension"/>
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet.ChartErrorSection">
    <Section>
      <ValidationMessages messages="props.messages" msgType="'error'"/>
    </Section>
  </t>

  <t t-name="o-spreadsheet.ChartDataSeries">
    <Section class="'o-data-series'">
      <t t-set-slot="title">
        <div class="d-flex flex-row justify-content-between">
          <t t-esc="title"/>
          <div t-if="props.onFlipAxis and props.canChangeDatasetOrientation" class="d-flex">
            <span
              t-if="props.datasetOrientation !== 'rows'"
              title="Split dataset by rows"
              t-on-click="(ev) => props.onFlipAxis('rows')"
              class="p-1 o-hoverable-button o-split-by-rows">
              <t t-call="o-spreadsheet-Icon.INSERT_ROW_BEFORE"/>
            </span>
            <span
              t-else=""
              title="Split dataset by columns"
              t-on-click="(ev) => props.onFlipAxis('columns')"
              class="p-1 o-hoverable-button o-split-by-columns">
              <t t-call="o-spreadsheet-Icon.INSERT_COL_BEFORE"/>
            </span>
          </div>
        </div>
      </t>
      <SelectionInput
        ranges="ranges"
        required="true"
        hasSingleRange="props.hasSingleRange"
        onSelectionChanged="props.onSelectionChanged"
        onSelectionConfirmed="props.onSelectionConfirmed"
        onSelectionReordered="props.onSelectionReordered"
        onSelectionRemoved="props.onSelectionRemoved"
        colors="colors"
        disabledRanges="disabledRanges"
        disabledRangeTitle.translate="Excluded due to chart limits. Drag to swap with another range."
      />
    </Section>
  </t>

  <t t-name="o-spreadsheet-ColorScalePicker">
    <Section class="'pt-0 o-color-scale'" title.translate="Color Scale">
      <div class="w-100" style="position:relative">
        <div
          class="color-scale-container d-flex justify-content-end"
          t-on-click.stop="onPointerDown">
          <span class="color-scale-label">
            <t t-esc="currentColorScaleLabel"/>
          </span>
          <div
            class="color-scale-preview w-100"
            t-att-data-test-colorscale="selectedColorScale"
            t-att-style="currentColorScaleStyle"
          />
          <span class="ms-1">
            <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
          </span>
        </div>
        <Popover t-if="state.popoverProps" t-props="state.popoverProps">
          <table t-ref="popoverRef" class="bg-white" t-att-style="state.popoverStyle">
            <tr
              class="color-scale-container custom-color-scale-container"
              t-on-click="() => this.onColorScaleChange('custom')">
              <td class="p-1 text-end">Custom</td>
              <td class="w-100 p-1">
                <div
                  class="color-scale-preview o-checkers-background"
                  data-test-id="custom-color-scale"
                />
              </td>
            </tr>
            <t t-foreach="colorScales" t-as="colorScale" t-key="colorScale.value">
              <tr
                class="color-scale-container"
                t-on-click="() => this.onColorScaleChange(colorScale.value)"
                t-att-title="colorScale.label">
                <td class="p-1 text-end">
                  <t t-esc="colorScale.label"/>
                </td>
                <td class="w-100 p-1">
                  <div
                    class="color-scale-preview"
                    t-att-data-test-id="colorScale.className"
                    t-att-style="colorScalePreviewStyle(colorScale.value)"
                  />
                </td>
              </tr>
            </t>
          </table>
        </Popover>
      </div>
      <div class="ps-3 mt-2">
        <div class="o-min-color d-flex align-items-center mb-2">
          <RoundColorPicker
            currentColor="currentColorScale.minColor"
            onColorPicked="(color) => this.setCustomColorScaleColor('minColor', color)"
            disableNoColor="true"
          />
          <span class="ps-2">Color of minimum values</span>
        </div>
        <div class="o-mid-color d-flex align-items-center mb-2">
          <RoundColorPicker
            currentColor="currentColorScale.midColor"
            onColorPicked="(color) => this.setCustomColorScaleColor('midColor', color)"
          />
          <span class="ps-2">Color of middle values</span>
        </div>
        <div class="o-max-color d-flex align-items-center">
          <RoundColorPicker
            currentColor="currentColorScale.maxColor"
            onColorPicked="(color) => this.setCustomColorScaleColor('maxColor', color)"
            disableNoColor="true"
          />
          <span class="ps-2">Color of maximum values</span>
        </div>
      </div>
    </Section>
  </t>

  <t t-name="o-spreadsheet.ChartTitle">
    <Section class="'o-chart-title'" title="props.name">
      <TextInput
        value="props.title"
        onChange.bind="updateTitle"
        placeholder="props.placeholder"
        alwaysShowBorder="true"
      />
      <TextStyler
        style="props.style"
        updateStyle="props.updateStyle"
        defaultStyle="props.defaultStyle"
        hasHorizontalAlign="true"
      />
    </Section>
  </t>

  <t t-name="o-spreadsheet-AxisDesignEditor">
    <t t-set="editor_label">Axis title</t>
    <Section class="'py-0'">
      <BadgeSelection
        choices="badgeAxes"
        onChange.bind="(value) => state.currentAxis = value"
        selectedValue="state.currentAxis"
      />
    </Section>
    <ChartTitle
      title="this.getAxisTitle()"
      updateTitle.bind="updateAxisTitle"
      updateStyle.bind="updateAxisTitleStyle"
      name="editor_label"
      style="axisTitleStyle"
      placeholder.translate="Add a Title"
      defaultStyle="{align: 'center', color: '', fontSize: defaultFontSize}"
    />
  </t>

  <t t-name="o-spreadsheet-BarChartDesignPanel">
    <GeneralDesignEditor t-props="props">
      <t t-set-slot="general-extension">
        <ChartLegend t-props="props"/>
        <Section class="'pt-0'" title.translate="Values">
          <ChartShowValues t-props="props"/>
        </Section>
        <Section t-if="isZoomable" class="'pt-0'" title.translate="Zoom">
          <Checkbox
            name="'zoomable'"
            label.translate="Show slicer"
            value="props.definition.zoomable"
            onChange.bind="onToggleZoom"
            className="'mb-2'"
          />
        </Section>
        <Section class="'pt-0'" title.translate="Number formatting">
          <ChartHumanizeNumbers t-props="props"/>
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesWithAxisDesignEditor t-props="props"/>
    <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          chartId="props.chartId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-BarConfigPanel">
    <div>
      <Section class="'pt-0'">
        <Checkbox
          name="'stacked'"
          label="stackedLabel"
          value="props.definition.stacked"
          onChange.bind="onUpdateStacked"
        />
      </Section>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
        canChangeDatasetOrientation="canChangeDatasetOrientation"
        datasetOrientation="datasetOrientation"
        onFlipAxis.bind="setDatasetOrientation"
      />
      <ChartLabelRange
        range="this.getLabelRange()"
        isInvalid="isLabelInvalid"
        onSelectionChanged.bind="onLabelRangeChanged"
        onSelectionConfirmed.bind="onLabelRangeConfirmed"
        options="this.getLabelRangeOptions()"
      />

      <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-CarouselPanel">
    <div class="o-carousel-panel h-100 overflow-auto">
      <Section title.translate="Carousel Title" class="'o-carousel-title'">
        <TextInput
          value="title?.text ?? ''"
          onChange.bind="updateTitleText"
          placeholder.translate="Add a Title"
          alwaysShowBorder="true"
          selectContentOnFocus="true"
        />
        <TextStyler
          style="title ?? {}"
          updateStyle.bind="updateTitleStyle"
          defaultStyle="DEFAULT_CAROUSEL_TITLE_STYLE"
          hasHorizontalAlign="false"
        />
      </Section>
      <div class="o-section pb-1 pt-0">
        <div class="o-section-title">Carousel Sections</div>
      </div>
      <div class="o-carousel-preview-list overflow-auto bg-white" t-ref="previewList">
        <t t-foreach="carouselItems" t-as="item" t-key="getItemId(item)">
          <div
            class="o-carousel-preview border-bottom pe-2 position-relative w-100 d-flex align-items-center"
            t-att-class="{
              'o-dragging': dragAndDrop.draggedItemId === getItemId(item),
              'o-selected': isCarouselItemActive(item)
            }"
            t-att-style="getPreviewDivStyle(item)">
            <div
              class="o-drag-handle h-100 position-absolute d-flex align-items-center o-button-icon ps-1 flex-shrink-0"
              t-on-pointerdown.stop.prevent="(ev) => this.onDragHandleMouseDown(item, ev)">
              <t t-call="o-spreadsheet-Icon.THIN_DRAG_HANDLE"/>
            </div>
            <div
              class="o-carousel-preview-icon ms-3 flex-shrink-0 d-flex align-items-center justify-content-center">
              <t t-call="{{getItemPreview(item)}}"/>
            </div>
            <div class="o-carousel-preview-title text-truncate ms-2">
              <TextInput
                value="getItemTitle(item)"
                onChange="(newName) => this.renameCarouselItem(item, newName)"
                selectContentOnFocus="true"
              />
            </div>
            <div class="ms-auto"/>
            <div class="flex-shrink-0 d-flex me-1">
              <CogWheelMenu items="getCogWheelMenuItems(item)"/>
            </div>
          </div>
        </t>
      </div>
      <div
        class="o-button-link o-carousel-add-chart float-end d-flex align-items-center py-4 pe-4 gap-2"
        t-on-click="addNewChartToCarousel"
        t-att-title="carouselAddChartInfoMessage">
        + Add chart
      </div>
      <div
        t-if="!hasDataView"
        class="o-button-link o-carousel-add-data-view float-end py-4 pe-4"
        t-on-click="addDataViewToCarousel"
        t-att-title="carouselDataViewMessage">
        + Add data view
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-SelectionInput">
    <div class="o-selection" t-ref="o-selection">
      <div
        t-foreach="ranges"
        t-as="range"
        t-key="range.id"
        class="o-selection-input d-flex flex-row"
        t-att-style="dragAndDrop.itemsStyle[range.id]"
        t-att-class="props.class">
        <span
          t-if="ranges.length > 1 and props.onSelectionReordered"
          title="Reorder range"
          t-on-pointerdown="(ev) => this.startDragAndDrop(range.id, ev)"
          class="o-drag-handle d-flex align-items-center mb-2 o-button-icon">
          <t t-call="o-spreadsheet-Icon.SHORT_THIN_DRAG_HANDLE"/>
        </span>
        <div class="position-relative w-100">
          <input
            type="text"
            spellcheck="false"
            placeholder="e.g. A1:A2"
            t-on-input="(ev) => this.onInputChanged(range.id, ev)"
            t-on-focus="() => this.focus(range.id)"
            t-on-keydown="onKeydown"
            t-att-value="range.xc"
            t-att-style="getColor(range)"
            class="o-input mb-2"
            t-att-class="{
              'o-disabled-ranges' : range.disabled and !range.isFocused,
              'o-focused' : range.isFocused,
              'o-invalid border-danger position-relative': isInvalid || !range.isValidRange,
              'text-decoration-underline': range.xc and range.isFocused and state.mode === 'select-range'
            }"
            t-ref="{{range.isFocused ? 'focusedInput' : 'unfocusedInput' + range_index}}"
          />
          <span
            t-if="isInvalid || !range.isValidRange"
            class="input-icon text-danger position-absolute d-flex align-items-center"
            title="This range is invalid">
            <t t-call="o-spreadsheet-Icon.ERROR"/>
          </span>
          <span
            class="input-icon o-disabled-ranges position-absolute d-flex align-items-center"
            t-if="!range.isFocused and range.disabled"
            t-att-title="props.disabledRangeTitle">
            <t t-call="o-spreadsheet-Icon.CIRCLE_INFO"/>
          </span>
        </div>
        <button
          class="border-0 bg-transparent fw-bold o-remove-selection o-button-icon pe-0"
          t-if="ranges.length > 1"
          t-on-click="() => this.removeInput(range.id)">
          <t t-call="o-spreadsheet-Icon.TRASH_FILLED"/>
        </button>
      </div>
      <div class="d-flex flex-row w-100 o-selection-input">
        <button class="o-button o-add-selection" t-if="canAddRange" t-on-click="addEmptyInput">
          Add range
        </button>
        <div class="ms-auto" t-if="store.hasFocus">
          <button class="o-button o-selection-ko" t-if="isResettable" t-on-click="reset">
            Reset
          </button>
          <button
            class="o-button primary ms-2 o-selection-ok"
            t-if="store.hasFocus"
            t-att-disabled="!isConfirmable"
            t-on-click="confirm">
            Confirm
          </button>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-Selection">
    <Highlight t-props="highlightProps"/>
  </t>

  <t t-name="o-spreadsheet-ScrollBar">
    <div class="o-scrollbar" t-on-scroll="onScroll" t-ref="scrollbar" t-att-style="positionCss">
      <div t-att-style="sizeCss"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-Popover">
    <t t-portal="'.o-spreadsheet'">
      <div
        class="o-popover rounded"
        t-att-class="props.class"
        t-ref="popover"
        t-on-wheel="props.onMouseWheel"
        t-on-click.stop="">
        <div class="o-popover-content" t-ref="popoverContent">
          <t t-slot="default"/>
        </div>
      </div>
    </t>
  </t>

  <t t-name="o_spreadsheet.PivotHTMLRenderer">
    <div class="o_pivot_html_renderer">
      <Checkbox
        name="'missing_values'"
        label.translate="Display missing cells only"
        value="state.showMissingValuesOnly"
        onChange.bind="(value) => this.state.showMissingValuesOnly = value"
        className="'m-2'"
      />
      <t t-set="tableData" t-value="getTableData()"/>
      <table
        class="o_pivot_html_renderer"
        t-if="tableData.values.length > 0 or tableData.rows.length > 0">
        <tr t-foreach="tableData.columns" t-as="row" t-key="row_index">
          <t t-if="row_index === 0">
            <th t-att-rowspan="tableData.columns.length"/>
          </t>
          <t t-foreach="row" t-as="cell" t-key="cell_index">
            <th
              t-att-colspan="cell.span"
              t-att-style="cell.style"
              t-att-class="{ o_missing_value: cell.isMissing }"
              t-on-click="() => props.onCellClicked(cell.formula)">
              <t t-esc="cell.value"/>
            </th>
          </t>
        </tr>
        <t t-foreach="tableData.rows" t-as="row" t-key="row_index">
          <tr>
            <th
              t-att-style="row.style"
              t-att-class="{ o_missing_value: row.isMissing }"
              t-on-click="() => props.onCellClicked(row.formula)">
              <t t-esc="row.value"/>
            </th>
            <t t-foreach="tableData.values" t-as="col" t-key="col_index">
              <td
                t-att-class="{ o_missing_value: col[row_index].isMissing }"
                t-on-click="() => props.onCellClicked(col[row_index].formula)">
                <t t-esc="col[row_index].value"/>
              </td>
            </t>
          </tr>
        </t>
      </table>
      <div class="alert alert-info" t-else="1">This pivot has no cell missing on this sheet</div>
    </div>
  </t>

  <t t-name="o-spreadsheet-PaintFormatButton">
    <span
      class="o-menu-item-button"
      title="Paint Format"
      t-att-class="{active: isActive}"
      t-attf-class="{{props.class}}"
      t-on-click="togglePaintFormat"
      t-on-dblclick="onDblClick">
      <span>
        <t t-call="o-spreadsheet-Icon.PAINT_FORMAT"/>
      </span>
    </span>
  </t>

  <t t-name="o-spreadsheet-NumberInput">
    <input
      type="number"
      t-ref="{{refName}}"
      t-att-class="inputClass"
      t-att-id="props.id"
      t-att-placeholder="props.placeholder"
      t-on-change="save"
      t-on-blur="save"
      t-on-pointerdown="onMouseDown"
      t-on-pointerup="onMouseUp"
      t-on-keydown="onKeyDown"
      t-att-min="props.min"
      t-att-max="props.max"
    />
  </t>

  <t t-name="o-spreadsheet-NumberEditor">
    <div class="o-dropdown" t-ref="NumberEditor">
      <div
        class="o-number-editor d-flex align-items-center"
        t-att-class="props.class"
        t-att-title="props.title"
        t-on-click.stop="this.toggleList">
        <input
          type="number"
          t-att-min="props.min"
          t-att-max="props.max"
          class="o-font-size o-number-input bg-transparent border-0"
          t-on-keydown="onInputKeydown"
          t-on-wheel.prevent.stop=""
          t-on-click.stop="props.onFocusInput"
          t-on-focus.stop="onInputFocused"
          t-on-change="setValueFromInput"
          t-ref="inputNumber"
        />
        <t t-esc="props.valueIcon"/>
        <span>
          <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
        </span>
      </div>
      <Popover t-if="dropdown.isOpen" t-props="popoverProps">
        <div class="o-text-options bg-white" t-on-click.stop="" t-ref="numberList">
          <t t-foreach="props.valueList" t-as="value" t-key="value">
            <div t-att-data-size="value" t-on-click="() => this.setValueFromList(value)">
              <t t-esc="value"/>
              <t t-esc="props.valueIcon"/>
            </div>
          </t>
        </div>
      </Popover>
    </div>
  </t>

  <t t-name="o-spreadsheet-Menu-Popover">
    <Popover t-if="props.menuItems" t-props="popoverProps">
      <div
        t-ref="menu"
        class="o-menu-wrapper bg-white"
        t-on-mouseover="() => this.onMouseOverMainMenu()">
        <Menu t-props="menuProps"/>
      </div>
      <MenuPopover
        t-if="subMenu.isOpen"
        t-key="subMenu.parentMenu.id"
        anchorRect="subMenuAnchorRect"
        menuItems="subMenu.menuItems"
        depth="props.depth + 1"
        maxHeight="props.maxHeight"
        onMenuClicked="props.onMenuClicked"
        onClose.bind="close"
        menuId="props.menuId"
        onMouseOver.bind="onMouseOverChildMenu"
        width="props.width"
      />
    </Popover>
  </t>

  <t t-name="o-spreadsheet-Menu">
    <div
      t-ref="menu"
      class="o-menu bg-white"
      t-att-style="menuStyle"
      t-on-scroll="props.onScroll"
      t-on-wheel.stop=""
      t-on-pointerdown.prevent=""
      t-on-click.stop=""
      t-on-contextmenu.prevent="">
      <t t-foreach="menuItemsAndSeparators" t-as="menuItem" t-key="menuItem_index">
        <div t-if="menuItem === 'separator'" class="o-separator border-bottom"/>
        <t t-else="">
          <t t-set="isMenuRoot" t-value="isRoot(menuItem)"/>
          <t t-set="isMenuEnabled" t-value="isEnabled(menuItem)"/>
          <div
            t-att-title="getName(menuItem)"
            t-att-data-name="menuItem.id"
            t-on-click="(ev) => this.onClickMenu(menuItem, ev)"
            t-on-auxclick="(ev) => this.onClickMenu(menuItem, ev)"
            t-on-mouseover="(ev) => this.props.onMouseOver?.(menuItem, ev)"
            t-on-mouseenter="(ev) => this.onMouseEnter?.(menuItem, ev)"
            t-on-mouseleave="(ev) => this.onMouseLeave?.(menuItem)"
            class="o-menu-item d-flex justify-content-between align-items-center"
            t-att-class="{'disabled': !isMenuEnabled, 'o-menu-item-active': props.isActive?.(menuItem)}"
            t-att-style="getColor(menuItem)">
            <div class="d-flex w-100">
              <div
                t-if="childrenHaveIcon"
                class="o-menu-item-icon d-flex align-items-center flex-shrink-0"
                t-att-style="getIconColor(menuItem)">
                <t t-if="getIconName(menuItem)" t-call="{{getIconName(menuItem)}}"/>
              </div>
              <div class="o-menu-item-name align-middle text-truncate" t-esc="getName(menuItem)"/>
              <t t-set="description" t-value="menuItem.description(env)"/>
              <div
                t-if="description"
                class="o-menu-item-description ms-auto text-truncate"
                t-esc="description"
              />
              <t t-set="secondaryIcon" t-value="menuItem.secondaryIcon(env)"/>
              <div
                t-if="isMenuRoot"
                class="o-menu-item-root ms-auto align-items-center d-flex"
                t-call="o-spreadsheet-Icon.CARET_RIGHT"
              />
              <div
                t-elif="secondaryIcon"
                class="o-menu-item-root ms-auto align-items-center d-flex"
                t-call="{{secondaryIcon}}"
              />
            </div>
          </div>
        </t>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-LinkEditor">
    <div
      class="o-link-editor bg-white rounded"
      t-on-click.stop="() => this.menu.isOpen=false"
      t-on-keydown="onKeyDown">
      <div class="o-section">
        <div class="o-section-title">Text</div>
        <div class="d-flex">
          <input
            type="text"
            title="Link label"
            placeholder="e.g. 'Link label'"
            class="o-input"
            t-model="link.label"
          />
        </div>

        <div class="o-section-title mt-3">Link</div>
        <div class="o-link-url">
          <t t-if="link.isUrlEditable">
            <input
              class="o-input"
              type="text"
              placeholder="e.g. 'http://www.odoo.com'"
              title="Link URL"
              t-ref="urlInput"
              t-model="link.url"
            />
          </t>
          <t t-else="">
            <input
              type="text"
              class="o-input"
              title="Link URL"
              t-att-value="getUrlRepresentation(link)"
              disabled="1"
            />
          </t>
          <button t-if="link.url" t-on-click="removeLink" class="o-remove-url o-button-icon">
            ✖
          </button>
          <button
            t-if="!link.url"
            t-on-click.stop="openMenu"
            class="o-special-link o-button-icon bg-white"
            t-ref="linkEditorMenuButton">
            <t t-call="o-spreadsheet-Icon.LIST"/>
          </button>
        </div>
      </div>
      <MenuPopover
        t-if="menu.isOpen"
        anchorRect="menuButtonRect"
        menuItems="menuItems"
        onMenuClicked="(ev) => this.onSpecialLink(ev)"
        onClose="() => this.menu.isOpen=false"
      />
      <div class="o-buttons">
        <button t-on-click="cancel" class="o-button o-cancel me-2">Cancel</button>
        <button t-on-click="save" class="o-button primary o-save" t-att-disabled="!link.url">
          Confirm
        </button>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-LinkDisplay">
    <div class="o-link-tool d-flex align-items-center bg-white rounded">
      <!-- t-key to prevent owl from re-using the previous img element when the link changes.
    The wrong/previous image would be displayed while the new one loads -->
      <img
        t-if="link.isExternal"
        t-key="link.url"
        t-attf-src="https://www.google.com/s2/favicons?sz=16&amp;domain={{link.url}}"
      />
      <a
        t-if="link.isExternal"
        class="o-link"
        t-att-href="link.url"
        target="_blank"
        t-on-click.prevent="openLink"
        t-att-title="link.url">
        <t t-esc="getUrlRepresentation(link)"/>
      </a>
      <a
        t-else=""
        class="o-link"
        t-on-click.prevent="openLink"
        t-on-auxclick.prevent="openLink"
        t-att-title="getUrlRepresentation(link)">
        <t t-esc="getUrlRepresentation(link)"/>
      </a>
      <span
        t-if="!env.model.getters.isReadonly()"
        class="o-link-icon o-unlink"
        t-on-click="unlink"
        title="Remove link">
        <t t-call="o-spreadsheet-Icon.UNLINK"/>
      </span>
      <span
        t-if="!env.model.getters.isReadonly()"
        class="o-link-icon o-edit-link"
        t-on-click="edit"
        title="Edit link">
        <t t-call="o-spreadsheet-Icon.EDIT"/>
      </span>
    </div>
  </t>

  <t t-name="o-spreadsheet-Icon.CLEAR_AND_RELOAD">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M14 15H4V3h6v3h4M4 1.5A1.5 1.5 0 0 0 2.5 3v12a1.5 1.5 0 0 0 1.4 1.5h10a1.5 1.5 0 0 0 1.5-1.5V5l-3.5-3.5
        "
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.EXPORT_XLSX">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M0 1a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1m4-4V1H1v3m7 0V1H5v3M4 8V5H1v3m7 0V5H5v3m-3.5 2h2v4h3v-1.5l3 2.5-3 2.5V16h-5m9.5-6h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1h-6a1 1 0 0 1-1-1v-6a1 1 0 0 1 1-1m1.7 7 1.3-2 1.3 2h2l-2-3 2-3h-2L14 13l-1.3-2h-2l2 3-2 3"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.OPEN_READ_ONLY">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M13 7V5c0-2.5-2-4-4-4S5 2.5 5 5v2h-.5C3.5 7 3 7.5 3 8.5v7c0 1 .5 1.5 1.5 1.5h9c1 0 1.5-.5 1.5-1.5v-7c0-1-.5-1.5-1.5-1.5m-7-2c0-1.5 1-2.5 2.5-2.5s2.5 1 2.5 2.5v2h-5V5m1 7a1.5 1.5 0 0 1 3 0 1.5 1.5 0 0 1-3 0"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.OPEN_DASHBOARD">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M13 2.07A8 8 0 1 0 15.93 5L14.2 6A6 6 0 1 1 12 3.8m-2 3.47a2 2 0 1 0 .73.73l5.5-5.5-.6-.6M9.3 3.8a.6.6 0 1 1-.01-.01m1.81.51a.6.6 0 1 1-.01-.01M7.5 4.3a.6.6 0 1 1-.01-.01M5.9 5.4a.6.6 0 1 1-.01-.01M4.8 6.9a.6.6 0 1 1-.01-.01m8.71.61a.6.6 0 1 0-.01 0"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.OPEN_READ_WRITE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M13 7V5a4 4 0 0 0-8 0v2h-.5C3.5 7 3 7.5 3 8.5v7c0 1 .5 1.5 1.5 1.5h9c1 0 1.5-.5 1.5-1.5v-7c0-1-.5-1.5-1.5-1.5m-7-2a2 2 0 0 1 5 0v2h-5m1 5a1.5 1.5 0 0 1 3 0 1.5 1.5 0 0 1-3 0m6 3.5h-9v-7h9"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.IMPORT_XLSX">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M9 10a1 1 0 0 1 1-1h7a1 1 0 0 1 1 1v7a1 1 0 0 1-1 1h-7a1 1 0 0 1-1-1m4-4v-3h-3v3m7 0v-3h-3v3m-1 4v-3h-3v3m7 0v-3h-3v3M.5 9h2v4h3v-1.5l3 2.5-3 2.5V15h-5M1 0h6a1 1 0 0 1 1 1v6a1 1 0 0 1-1 1H1a1 1 0 0 1-1-1V1a1 1 0 0 1 1-1m1.7 7L4 5l1.3 2h2l-2-3 2-3h-2L4 3 2.7 1h-2l2 3-2 3"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNDO">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M5.43 9.43 8 12H1V5l2.96 2.958A8.29 8.29 0 0 1 9.32 6c3.46 0 6.42 2.11 7.68 5l-2 1c-.94-2.39-3.13-3.92-5.68-4a6.57 6.57 0 0 0-3.89 1.43"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.REDO">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M12.57 9.43 10 12h7V5l-2.96 2.96A8.29 8.29 0 0 0 8.68 6C5.22 6 2.26 8.11 1 11l2 1c.94-2.39 3.13-3.92 5.68-4a6.58 6.58 0 0 1 3.89 1.43"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.CLIPBOARD">
    <div class="o-icon">
      <i class="fa fa-clipboard"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.COPY">
    <div class="o-icon">
      <i class="fa fa-clone"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CUT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M3 2v2l4.5 5-1.2 1.3c-.4-.2-.8-.3-1.3-.3-1.7 0-3 1.3-3 3s1.3 3 3 3 3-1.3 3-3c0-.5-.1-.9-.3-1.3L9 10.4l1.3 1.3c-.2.4-.3.8-.3 1.3 0 1.7 1.3 3 3 3s3-1.3 3-3-1.3-3-3-3c-.5 0-.9.1-1.3.3L10.4 9 15 4.4V2h-.4L9 7.6 3.4 2H3Zm2 12.5c-.8 0-1.5-.7-1.5-1.5s.7-1.5 1.5-1.5 1.5.7 1.5 1.5-.7 1.5-1.5 1.5Zm9.5-1.5c0 .8-.7 1.5-1.5 1.5s-1.5-.7-1.5-1.5.7-1.5 1.5-1.5 1.5.7 1.5 1.5ZM9 8.5c.3 0 .5.2.5.5s-.2.5-.5.5-.5-.2-.5-.5.2-.5.5-.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.COPY_AS_IMAGE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="m 14,15 v 1.5 H 2.5147386 c -0.5522847,0 -1,-0.447715 -1,-1 V 3 H 3 V 14 c 0,0.552285 0.4477153,1 1,1 h 10"
      />
      <path
        fill="currentColor"
        d="M 3.8194506,2.0480809 A 1.1084934,1.1763958 0 0 1 4.927944,0.87168505 H 15.273882 A 1.1084934,1.1763958 0 0 1 16.382375,2.0480809 V 13.027775 a 1.1084934,1.1763958 0 0 1 -1.108493,1.176396 H 4.927944 A 1.1084934,1.1763958 0 0 1 3.8194506,13.027775 V 2.0480809 H 4.927944 V 13.027775 H 15.273882 V 2.0480809 H 4.927944 M 12.3179,5.5772683 10.839908,9.1064553 9.7314149,7.93006 8.2534245,9.8907193 7.1449309,8.7143233 5.6669395,11.067114 H 14.534886 M 6.0364374,4.4008725 a 1.1084936,1.176396 0 0 1 2.2169871,0 1.1084936,1.176396 0 0 1 -2.2169871,0"
        id="path1-5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.PASTE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M14.5 2.5H11C10.7 1.6 10 1 9 1s-1.5.5-2 1.5H3.5C2.5 2.5 2 3 2 4v11c0 1 .5 1.5 1.5 1.5h11c1 0 1.5-.5 1.5-1.5V4c0-1-.5-1.5-1.5-1.5Zm-4.75.75c0 .5-.34.75-.75.75s-.75-.34-.75-.75.34-.75.75-.75.75.34.75.75ZM14.5 15h-11V4H5v2.5h8V4h1.5v11"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.CLEAR">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M1.5 15a.75.75 0 0 0 0 1.5h15a.75.75 0 0 0 0-1.5M5.3 12.75c.1.1.3.2.5.2h4c.2 0 .4-.1.5-.2l5.5-5.5c.2-.3.2-.6 0-.8l-4.4-4.4c-.3-.2-.6-.2-.8 0l-4.8 4.8c-2.7 2.9-3.1 2.8-2.4 4M7 7.25l3.6 3.6-1 1-3.6.1-1.8-1.9"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.FREEZE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 17.5h16a1 1 0 0 0 1-1v-15a1 1 0 0 0-1-1h-15a1 1 0 0 0-1 1v15a1 1 0 0 0 1 1m9-10.5v4.5H6V7m0 9v-3.5h4.5V16M5 16H3.5L5 14.5M5 13l-3 3v-1.5l3-3M2 13v-2l3-3v2m-3-.5v-2l3-3v2M2 6V4l2-2h1v1m11 13h-4.5v-3.5H16m0-1h-4.5V7H16m0-5v4h-4.5V2m-1 4H6V2h4.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNFREEZE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 17.5h16a1 1 0 0 0 1-1v-15a1 1 0 0 0-1-1h-15a1 1 0 0 0-1 1v15a1 1 0 0 0 1 1M5 6H2V2h3m0 9.5H2V7h3m0 9H2v-3.5h3M10.5 7v4.5H6V7m0 9v-3.5h4.5V16m5.5 0h-4.5v-3.5H16m0-1h-4.5V7H16m0-5v4h-4.5V2m-1 4H6V2h4.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.SHOW">
    <div class="o-icon">
      <i class="fa fa-eye"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.FORMULA">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M7 14.25q-.25.75-.75 1.25T5 16q-.75 0-1.5-.5Q3 15 3 14.25q0-.5.25-.75t.75-.25q.25 0 .25.75v.5H5q.5 0 .5-.5l1.25-6.5H5V6h2l.5-2.25q.25-.75.75-1.25T9.5 2q1 0 1.5.5t.5 1q0 .5-.25.75t-.5.25q-.5 0-.75-.25t-.25-.5V3H9.5q-.25 0-.5.5L8.5 6H10v1.5H8.25m1.25 1H15v1h-4l2 2-2 2h4v1H9V14l2.5-2.5L9 9"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.HIDE_ROW">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v3.5h14V2H2v9h14V7H2v9h14v-3.5H2M1 12l4-5h2l-4 5m2 0 4-5h2l-4 5m2 0 4-5h2l-4 5m2 0 4-5v4"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNHIDE_ROW">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M17.5 16a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2zH16v-3.5H2V16h14V2H2v3.5h14"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.HIDE_COL">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M16 .5A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2A1.5 1.5 0 0 1 2 .5h14V2h-3.5v14H16V2H7v14h4V2H2v14h3.5V2M6 1l5 4v2L6 3m0 2 5 4v2L6 7m0 2 5 4v2l-5-4"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNHIDE_COL">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M16 .5A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2A1.5 1.5 0 0 1 2 .5h14V2h-3.5v14H16V2H2V16h3.5V2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_ROW">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v3.5h14V2H2v9h14V7H2v9h14v-3.5H2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_ROW_BEFORE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M3.5 14.5A1.5 1.5 0 0 0 5 16h10a1.5 1.5 0 0 0 1.5-1.5v-7h-3V5h3V1.5A1.5 1.5 0 0 0 15 0H5a1.5 1.5 0 0 0-1.5 1.5v2h-3V9h3M15 12.5v2H5v-2M15 9v2H5V9m10-7.5v2H5v-2M12 5v2.5H2V5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_ROW_AFTER">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M3.5 1.5A1.5 1.5 0 0 1 5 0h10a1.5 1.5 0 0 1 1.5 1.5v7h-3V11h3v3.5A1.5 1.5 0 0 1 15 16H5a1.5 1.5 0 0 1-1.5-1.5v-2h-3V7h3M15 3.5v-2H5v2M15 7V5H5v2m10 7.5v-2H5v2m7-3.5V8.5H2V11"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_COL">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h3.5V2H2h5v14h4V2H2h10.5v14H16V2H2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_COL_AFTER">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M2.5 3A1.5 1.5 0 0 0 1 4.5v10A1.5 1.5 0 0 0 2.5 16h7v-3H12v3h3.5a1.5 1.5 0 0 0 1.5-1.5v-10A1.5 1.5 0 0 0 15.5 3h-2V0H8v3M4.5 14.5h-2v-10h2m3.5 10H6v-10h2m7.5 10h-2v-10h2m-3.5 7H9.5v-10H12"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_COL_BEFORE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M15.5 3A1.5 1.5 0 0 1 17 4.5v10a1.5 1.5 0 0 1-1.5 1.5h-7v-3H6v3H2.5A1.5 1.5 0 0 1 1 14.5v-10A1.5 1.5 0 0 1 2.5 3h2V0H10v3m3.5 11.5h2v-10h-2m-3.5 10h2v-10h-2m-7.5 10h2v-10h-2m3.5 7h2.5v-10H6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_CELL">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_CELL_SHIFT_DOWN">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M5 2.5A1.5 1.5 0 0 1 6.5 1h10A1.5 1.5 0 0 1 18 2.5v13a1.5 1.5 0 0 1-1.5 1.5h-10A1.5 1.5 0 0 1 5 15.5v-5h5.25v-3H5m11.5-2v-3h-4.75v3m-1.5 0v-3H6.5v3m10 5v-3h-4.75v3m-1.5 5v-3H6.5v3m10 0v-3h-4.75v3M0 12.5l2.5 4 2.5-4H3.25v-6h-1.5v6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_CELL_SHIFT_RIGHT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M2.5 5A1.5 1.5 0 0 0 1 6.5v10A1.5 1.5 0 0 0 2.5 18h13a1.5 1.5 0 0 0 1.5-1.5v-10A1.5 1.5 0 0 0 15.5 5h-5v5.25h-3V5m-2 11.5h-3v-4.75h3m0-1.5h-3V6.5h3m5 10h-3v-4.75h3m5-1.5h-3V6.5h3m0 10h-3v-4.75h3M12.5 0l4 2.5-4 2.5V3.25h-6v-1.5h6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.DELETE_CELL_SHIFT_UP">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M5 2.5A1.5 1.5 0 0 1 6.5 1h10A1.5 1.5 0 0 1 18 2.5v13a1.5 1.5 0 0 1-1.5 1.5h-10A1.5 1.5 0 0 1 5 15.5v-5h5.25v-3H5m11.5-2v-3h-4.75v3m-1.5 0v-3H6.5v3m10 5v-3h-4.75v3m-1.5 5v-3H6.5v3m10 0v-3h-4.75v3M0 10l2.5-4L5 10H3.25v6h-1.5v-6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.DELETE_CELL_SHIFT_LEFT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M2.5 5A1.5 1.5 0 0 0 1 6.5v10A1.5 1.5 0 0 0 2.5 18h13a1.5 1.5 0 0 0 1.5-1.5v-10A1.5 1.5 0 0 0 15.5 5h-5v5.25h-3V5m-2 11.5h-3v-4.75h3m0-1.5h-3V6.5h3m5 10h-3v-4.75h3m5-1.5h-3V6.5h3m0 10h-3v-4.75h3M10 0 6 2.5 10 5V3.25h6v-1.5h-6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_CHART">
    <div class="o-icon">
      <i class="fa fa-bar-chart"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_IMAGE">
    <div class="o-icon">
      <i class="fa fa-file-image-o"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_LINK">
    <div class="o-icon">
      <i class="fa fa-link"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_CHECKBOX">
    <div class="o-icon">
      <i class="fa fa-check-square-o"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_DROPDOWN">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M6 3.5a5 5.5 0 0 0 0 11h6a5 5.5 0 0 0 0-11H6V5h6a3.5 4 0 0 1 0 8H6a3.5 4 0 0 1 0-8m5 6 3-3H8"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_SHEET">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M17.5 5.5V16a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2A1.5 1.5 0 0 1 2 .5h10.5M2 5.5h3.5V2H2m5.25 3.5h3.5V2h-3.5M2 10.75h3.5v-3.5H2m5.25 3.5h3.5v-3.5h-3.5m5.25 3.5H16v-3.5h-3.5M2 16h3.5v-3.5H2M7.25 16h3.5v-3.5h-3.5M12.5 16H16v-3.5h-3.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.PAINT_FORMAT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M9,0 L1,0 C0.45,0 0,0.45 0,1 L0,4 C0,4.55 0.45,5 1,5 L9,5 C9.55,5 10,4.55 10,4 L10,3 L11,3 L11,6 L4,6 L4,14 L6,14 L6,8 L13,8 L13,2 L10,2 L10,1 C10,0.45 9.55,0 9,0 Z"
        transform="translate(3 2)"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.CONDITIONAL_FORMAT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M12.25.5c2 0 3.5 1.5 3.5 3.5v6.5c0 .5 0 2-2 2h-2.5v4c0 .5-.5 1-1 1h-2.5c-.5 0-1-.5-1-1v-4h-2.5c-1 0-2-1-2-2V.5m12 3a1.5 1.5 0 0 0-1.5-1.5h-3v2h-1.5V2h-1v4h-2V2h-1.5v8.5h10.5m-12-3h12.5V9H2.25"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.CLEAR_FORMAT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M2.12 4.05 7.28 9.2l-2.43 5.3h2.5l1.64-3.58 4.59 4.58 1.27-1.27L3.4 2.77 2.12 4.05ZM5.67 2.5l2 2h1.76l-.55 1.21 1.71 1.71 1.34-2.92h3.92v-2H5.67"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BOLD">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M13.5 6.5C13.5 4.57 11.93 3 10 3H4.5v12h6.25c1.79 0 3.25-1.46 3.25-3.25 0-1.3-.77-2.41-1.87-2.93.83-.58 1.37-1.44 1.37-2.32M9.5 5c.83 0 1.5.67 1.5 1.5S10.33 8 9.5 8h-2V5h2m-2 8v-3H10c.83 0 1.5.67 1.5 1.5S10.83 13 10 13H7.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ITALIC">
    <svg class="o-icon">
      <path fill="currentColor" d="M7 3v2h2.58l-3.66 8H3v2h8v-2H8.42l3.66-8H15V3"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNDERLINE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M9 15c2.76 0 5-2.24 5-5V3h-2v7c0 1.75-1.5 3-3 3s-3-1.242-3-3V3H4v7c0 2.76 2.24 5 5 5Zm-6 1v2h12v-2H3"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.STRIKE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M4.89 6.06c0-.46.1-.87.3-1.25.2-.38.46-.7.84-.97s.78-.47 1.28-.62A5.71 5.71 0 0 1 8.93 3c.61 0 1.16.08 1.65.25.5.17.92.4 1.27.7.35.3.62.66.81 1.07.19.41.28.87.28 1.36h-2.26a1.85 1.85 0 0 0-.11-.64 1.26 1.26 0 0 0-.33-.51 1.53 1.53 0 0 0-.56-.33A2.42 2.42 0 0 0 8.89 4.8c-.3 0-.55.03-.77.1a1.52 1.52 0 0 0-.54.27 1.14 1.14 0 0 0-.43.9c0 .36.18.66.55.91l.06.04C8.02 7.19 8.5 7.5 9 8H6s-.79-.62-.82-.69c-.19-.36-.29-.77-.29-1.25M16 9H2v2h7.22c.14.05.3.1.41.15.28.12.5.26.65.38.16.13.26.27.32.42.06.15.08.33.08.51 0 .18-.03.34-.1.49a1.02 1.02 0 0 1-.31.39 1.6 1.6 0 0 1-.53.26 2.71 2.71 0 0 1-.76.09c-.33 0-.62-.03-.89-.1a1.8 1.8 0 0 1-.68-.31 1.45 1.45 0 0 1-.44-.56c-.11-.23-.19-.57-.19-.74H4.55c0 .25.06.69.18 1.02a3.15 3.15 0 0 0 1.22 1.6c.28.2.58.36.92.49.33.13.67.23 1.04.29.36.06.72.09 1.08.09.6 0 1.15-.07 1.64-.21a3.88 3.88 0 0 0 1.25-.59 2.69 2.69 0 0 0 .8-.95c.19-.38.28-.81.28-1.29 0-.45-.08-.86-.23-1.211a2.26 2.26 0 0 0-.13-.25L16 11V9"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.TEXT_COLOR">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M10 1H8L3.5 13h2l1.12-3h4.75l1.12 3h2L10 1ZM7.38 8 9 3.67 10.62 8H7.38"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.FILL_COLOR">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M14.5 8.87S13 10.49 13 11.49c0 .83.67 1.5 1.5 1.5s1.5-.67 1.5-1.5c0-.99-1.5-2.62-1.5-2.62m-1.79-2.08L5.91 0 4.85 1.06l1.59 1.59-4.15 4.14a.996.996 0 0 0 0 1.41l4.5 4.5c.2.2.45.3.71.3.26 0 .51-.1.71-.29l4.5-4.5c.39-.39.39-1.03 0-1.42M4.21 7 7.5 3.71 10.79 7H4.21"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.MERGE_CELL">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M3 6H1V2h7v2H3v2m7-2V2h7v4h-2V4h-5m0 10h5v-2h2v4h-7v-2m-9-2h2v2h5v2H1v-4m0-4h4V6l3 3-3 3v-2H1V8m9 1 3-3v2h4v2h-4v2l-3-3"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ALIGN_LEFT">
    <svg class="o-icon align-left">
      <path fill="currentColor" d="M2 16h10v-2H2v2M12 6H2v2h10V6M2 2v2h14V2H2m0 10h14v-2H2v2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ALIGN_CENTER">
    <svg class="o-icon align-center">
      <path fill="currentColor" d="M4 14v2h10v-2H4m0-8v2h10V6H4m-2 6h14v-2H2v2M2 2v2h14V2H2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.IRREGULARITY_MAP">
    <div class="o-icon">
      <i class="fa fa-align-center fa-rotate-270"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.ALIGN_RIGHT">
    <svg class="o-icon align-right">
      <path fill="currentColor" d="M6 16h10v-2H6v2m-4-4h14v-2H2v2M2 2v2h14V2H2m4 6h10V6H6v2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ALIGN_TOP">
    <svg class="o-icon align-top">
      <path d="M3 2h12v2H3m2.5 5H8v7h2V9h2.5L9 5.5" fill="currentColor"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ALIGN_MIDDLE">
    <svg class="o-icon align-middle">
      <path
        d="M12.5 3H10V0H8v3H5.5L9 6.5M5.5 15H8v3h2v-3h2.5L9 11.5M3 8v2h12V8"
        fill="currentColor"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ALIGN_BOTTOM">
    <svg class="o-icon align-bottom">
      <path d="M5.5 9H8V2h2v7h2.5L9 12.5M3 14v2h12v-2" fill="currentColor"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.WRAPPING_OVERFLOW">
    <svg class="o-icon wrapping-overflow">
      <path d="M13 8H6v2h7v2l3-3-3-3M2 2h2v14H2M9 2h2v4H9m0 6h2v4H9" fill="currentColor"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.WRAPPING_WRAP">
    <svg class="o-icon wrapping-wrap">
      <path
        fill="currentColor"
        d="M6 5v2h3.75c.75 0 1.5.67 1.5 1.5 0 .75-.75 1.5-1.5 1.5H8V8l-3 3 3 3v-2h1.5c2 0 3.5-1.5 3.5-3.5S11.5 5 9.5 5M2 2h2v14H2M14 2M14,2,h2v14h-2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.WRAPPING_CLIP">
    <svg class="o-icon wrapping-clip">
      <path fill="currentColor" d="M2 2h2v14H2M14 2h2v14h-2v-6H6V8h8"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDERS">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M2 2v14h14V2H2m6 12H4v-4h4v4m0-6H4V4h4v4m6 6h-4v-4h4v4m0-6h-4V4h4v4"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_HV">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M2 16h2v-2H2v2M4 5H2v2h2V5m1 11h2v-2H5v2m8-14h-2v2h2V2M4 2H2v2h2V2m3 0H5v2h2V2M2 13h2v-2H2v2m9 3h2v-2h-2v2m3-14v2h2V2h-2m0 5h2V5h-2v2m0 9h2v-2h-2v2m0-3h2v-2h-2v2"
        opacity=".54"
      />
      <path d="M10 2H8v6H2v2h6v6h2v-6h6V8h-6"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_H">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M8 16h2v-2H8v2M5 4h2V2H5v2m3 9h2v-2H8v2m-3 3h2v-2H5v2M2 7h2V5H2v2m0 9h2v-2H2v2M2 4h2V2H2v2m0 9h2v-2H2v2m12 0h2v-2h-2v2m0 3h2v-2h-2v2m0-9h2V5h-2v2m0-5v2h2V2h-2M8 4h2V2H8v2m3 0h2V2h-2v2M8 7h2V5H8v2m3 9h2v-2h-2v2"
        opacity=".54"
      />
      <path d="M2 10h14V8H2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_V">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M5 16h2v-2H5v2M2 7h2V5H2v2m0-3h2V2H2v2m3 6h2V8H5v2m0-6h2V2H5v2M2 16h2v-2H2v2m0-6h2V8H2v2m0 3h2v-2H2v2M14 2v2h2V2h-2m0 8h2V8h-2v2m0 6h2v-2h-2v2m0-9h2V5h-2v2m0 6h2v-2h-2v2m-3 3h2v-2h-2v2m0-6h2V8h-2v2m0-6h2V2h-2v2"
        opacity=".54"
      />
      <path d="M8 16h2V2H8"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_EXTERNAL">
    <svg class="o-icon" fill="currentColor">
      <path d="M10 5H8v2h2V5m3 3h-2v2h2V8m-3 0H8v2h2V8m0 3H8v2h2v-2M7 8H5v2h2V8" opacity=".54"/>
      <path d="M2 2h14v14H2V2m12 12V4H4v10h10"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_LEFT">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M8 10h2V8H8v2m0-3h2V5H8v2m0 6h2v-2H8v2m0 3h2v-2H8v2m-3 0h2v-2H5v2M5 4h2V2H5v2m0 6h2V8H5v2m9 6h2v-2h-2v2m0-6h2V8h-2v2m0 3h2v-2h-2v2m0-6h2V5h-2v2M8 4h2V2H8v2m6-2v2h2V2h-2m-3 14h2v-2h-2v2m0-6h2V8h-2v2m0-6h2V2h-2v2"
        opacity=".54"
      />
      <path d="M2 16h2V2H2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_TOP">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M5 10h2V8H5v2m-3 6h2v-2H2v2m6 0h2v-2H8v2m0-3h2v-2H8v2m-3 3h2v-2H5v2m-3-3h2v-2H2v2m6-3h2V8H8v2M2 7h2V5H2v2m0 3h2V8H2v2m12 0h2V8h-2v2m0 3h2v-2h-2v2m0-6h2V5h-2v2M8 7h2V5H8v2m3 9h2v-2h-2v2m0-6h2V8h-2v2m3 6h2v-2h-2v2"
        opacity=".54"
      />
      <path d="M2 2v2h14V2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_RIGHT">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M2 4h2V2H2v2m3 0h2V2H5v2m0 6h2V8H5v2m0 6h2v-2H5v2M2 7h2V5H2v2m0 3h2V8H2v2m0 6h2v-2H2v2m0-3h2v-2H2v2m9-3h2V8h-2v2m-3 6h2v-2H8v2m3 0h2v-2h-2v2M8 4h2V2H8v2m3 0h2V2h-2v2m-3 9h2v-2H8v2m0-6h2V5H8v2m0 3h2V8H8v2"
        opacity=".54"
      />
      <path d="M14 2v14h2V2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_BOTTOM">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M7 2H5v2h2V2m3 6H8v2h2V8m0 3H8v2h2v-2m3-3h-2v2h2V8M7 8H5v2h2V8m6-6h-2v2h2V2m-3 3H8v2h2V5m0-3H8v2h2V2m-6 9H2v2h2v-2m10 2h2v-2h-2v2m0-6h2V5h-2v2m0 3h2V8h-2v2m0-8v2h2V2h-2M4 2H2v2h2V2m0 3H2v2h2V5m0 3H2v2h2V8"
        opacity=".54"
      />
      <path d="M2 16h14v-2H2"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_CLEAR">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M8 16h2v-2H8v2m-3-6h2V8H5v2m0-6h2V2H5v2m3 9h2v-2H8v2m-3 3h2v-2H5v2M2 7h2V5H2v2m0 9h2v-2H2v2M2 4h2V2H2v2m0 6h2V8H2v2m6 0h2V8H8v2m-6 3h2v-2H2v2m12 0h2v-2h-2v2m0 3h2v-2h-2v2m0-6h2V8h-2v2m0-3h2V5h-2v2m0-5v2h2V2h-2M8 4h2V2H8v2m3 0h2V2h-2v2M8 7h2V5H8v2m3 9h2v-2h-2v2m0-6h2V8h-2v2"
        opacity=".54"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_TYPE">
    <svg class="o-icon">
      <g fill="currentColor" transform="translate(2 2)">
        <polygon points="0 0 0 2 14 2 14 0"/>
        <polygon points="0 6 0 8 5 8 5 6"/>
        <polygon points="9 6 9 8 14 8 14 6"/>
        <polygon points="0 12 0 14 2 14 2 12"/>
        <polygon points="4 12 4 14 6 14 6 12"/>
        <polygon points="8 12 8 14 10 14 10 12"/>
        <polygon points="12 12 12 14 14 14 14 12"/>
      </g>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_COLOR">
    <svg class="o-icon">
      <g fill="currentColor" transform="translate(4 2)">
        <polygon points="0 12 0 9 7 2 10 5 3 12"/>
        <polygon points="8 1 9 0 12 3 11 4"/>
      </g>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.BORDER_NO_COLOR">
    <svg class="o-icon">
      <g fill="currentColor">
        <polygon points="4 12 4 9 11 2 14 5 7 12"/>
        <polygon points="12 1 13 0 16 3 15 4"/>
      </g>
      <g>
        <rect x="0" y="14" width="18" height="4" stroke="black" fill="none"/>
      </g>
    </svg>
  </t>

  <t t-name="o-spreadsheet-Icon.PLUS">
    <svg class="o-icon plus" viewBox="0 0 18 18">
      <path fill="currentColor" d="M8 0h2v8h8v2h-8v8H8v-8H0V8h8"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.MINUS">
    <svg class="o-icon minus" viewBox="0 0 18 18">
      <path fill="currentColor" d="M0 8h18v2H0z"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.LIST">
    <svg class="o-icon" viewBox="0 0 384 384">
      <rect x="0" y="277.333" width="384" height="42.667" fill="currentColor"/>
      <rect x="0" y="170.667" width="384" height="42.667" fill="currentColor"/>
      <rect x="0" y="64" width="384" height="42.667" fill="currentColor"/>
    </svg>
  </t>

  <t t-name="o-spreadsheet-Icon.EDIT">
    <div class="o-icon">
      <i class="fa fa-pencil-square-o"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.EXTERNAL">
    <div class="o-icon">
      <i class="fa fa-external-link"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.UNLINK">
    <div class="o-icon">
      <i class="fa fa-chain-broken"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CARET_UP">
    <div class="o-icon fa-small">
      <i class="fa fa-caret-up"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CARET_DOWN">
    <div class="o-icon fa-small">
      <i class="fa fa-caret-down"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CARET_RIGHT">
    <div class="o-icon fa-small">
      <i class="fa fa-caret-right"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CARET_LEFT">
    <div class="o-icon fa-small">
      <i class="fa fa-caret-left"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.TRASH">
    <div class="o-icon">
      <i class="fa fa-trash-o"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.TRASH_FILLED">
    <div class="o-icon">
      <i class="fa fa-trash"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.REFRESH">
    <div class="o-icon">
      <i class="fa fa-refresh"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.EXCHANGE">
    <div class="o-icon">
      <i class="fa fa-exchange"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.ARROW_DOWN">
    <svg class="o-icon arrow-down" viewBox="0 0 448 512">
      <path
        fill="currentColor"
        d="M413.1 222.5l22.2 22.2c9.4 9.4 9.4 24.6 0 33.9L241 473c-9.4 9.4-24.6 9.4-33.9 0L12.7 278.6c-9.4-9.4-9.4-24.6 0-33.9l22.2-22.2c9.5-9.5 25-9.3 34.3.4L184 343.4V56c0-13.3 10.7-24 24-24h32c13.3 0 24 10.7 24 24v287.4l114.8-120.5c9.3-9.8 24.8-10 34.3-.4z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ARROW_UP">
    <svg class="o-icon arrow-up" width="10" height="10" focusable="false" viewBox="0 0 448 512">
      <path
        fill="currentColor"
        d="M34.9 289.5l-22.2-22.2c-9.4-9.4-9.4-24.6 0-33.9L207 39c9.4-9.4 24.6-9.4 33.9 0l194.3 194.3c9.4 9.4 9.4 24.6 0 33.9L413 289.4c-9.5 9.5-25 9.3-34.3-.4L264 168.6V456c0 13.3-10.7 24-24 24h-32c-13.3 0-24-10.7-24-24V168.6L69.2 289.1c-9.3 9.8-24.8 10-34.3.4z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ARROW_RIGHT">
    <svg class="o-icon arrow-right" width="10" height="10" focusable="false" viewBox="0 0 448 512">
      <path
        fill="#F0AD4E"
        d="M190.5 66.9l22.2-22.2c9.4-9.4 24.6-9.4 33.9 0L441 239c9.4 9.4 9.4 24.6 0 33.9L246.6 467.3c-9.4 9.4-24.6 9.4-33.9 0l-22.2-22.2c-9.5-9.5-9.3-25 .4-34.3L311.4 296H24c-13.3 0-24-10.7-24-24v-32c0-13.3 10.7-24 24-24h287.4L190.9 101.2c-9.8-9.3-10-24.8-.4-34.3z"
      />
    </svg>
  </t>

  <t t-name="o-spreadsheet-Icon.SMILE">
    <svg class="o-icon smile" width="10" height="10" focusable="false" viewBox="0 0 496 512">
      <path
        fill="#6AA84F"
        d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160 0c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm4 72.6c-20.8 25-51.5 39.4-84 39.4s-63.2-14.3-84-39.4c-8.5-10.2-23.7-11.5-33.8-3.1-10.2 8.5-11.5 23.6-3.1 33.8 30 36 74.1 56.6 120.9 56.6s90.9-20.6 120.9-56.6c8.5-10.2 7.1-25.3-3.1-33.8-10.1-8.4-25.3-7.1-33.8 3.1z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.MEH">
    <svg class="o-icon meh" width="10" height="10" focusable="false" viewBox="0 0 496 512">
      <path
        fill="#F0AD4E"
        d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm8 144H160c-13.2 0-24 10.8-24 24s10.8 24 24 24h176c13.2 0 24-10.8 24-24s-10.8-24-24-24z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.FROWN">
    <svg class="o-icon frown" width="10" height="10" focusable="false" viewBox="0 0 496 512">
      <path
        fill="#E06666"
        d="M248 8C111 8 0 119 0 256s111 248 248 248 248-111 248-248S385 8 248 8zm0 448c-110.3 0-200-89.7-200-200S137.7 56 248 56s200 89.7 200 200-89.7 200-200 200zm-80-216c17.7 0 32-14.3 32-32s-14.3-32-32-32-32 14.3-32 32 14.3 32 32 32zm160-64c-17.7 0-32 14.3-32 32s14.3 32 32 32 32-14.3 32-32-14.3-32-32-32zm-80 128c-40.2 0-78 17.7-103.8 48.6-8.5 10.2-7.1 25.3 3.1 33.8 10.2 8.4 25.3 7.1 33.8-3.1 16.6-19.9 41-31.4 66.9-31.4s50.3 11.4 66.9 31.4c8.1 9.7 23.1 11.9 33.8 3.1 10.2-8.5 11.5-23.6 3.1-33.8C326 321.7 288.2 304 248 304z"
      />
    </svg>
  </t>

  <t t-name="o-spreadsheet-Icon.GREEN_DOT">
    <svg class="o-icon green-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
      <path
        fill="#6AA84F"
        d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.YELLOW_DOT">
    <svg class="o-icon yellow-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
      <path
        fill="#F0AD4E"
        d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.RED_DOT">
    <svg class="o-icon red-dot" width="10" height="10" focusable="false" viewBox="0 0 512 512">
      <path
        fill="#E06666"
        d="M256 8C119 8 8 119 8 256s111 248 248 248 248-111 248-248S393 8 256 8z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.SMALL_DOT_RIGHT_ALIGN">
    <svg
      class="o-icon"
      style="color: currentcolor;"
      width="10"
      height="10"
      xmlns="http://www.w3.org/2000/svg"
      viewBox="0 0 18 18">
      <circle fill="currentColor" cx="14" cy="9" r="4"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.SORT_RANGE">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M9 3.5h8v2H9M9 8h6v2H9m0 2.5h3v2H9M6 6l1-1-3-3-3 3 1 1 1-1v8l-1-1-1 1 3 3 3-3-1-1-1 1V5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.SORT_ASCENDING">
    <div class="o-icon">
      <i class="fa fa-sort-alpha-asc"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.SORT_DESCENDING">
    <div class="o-icon">
      <i class="fa fa-sort-alpha-desc"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.DATA_CLEANUP">
    <div class="o-icon">
      <i class="fa fa-magic"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.FILTER_ICON">
    <svg class="o-icon filter-icon" viewBox="0 0 850 850">
      <path
        fill="currentColor"
        d="M 339.667 681 L 510.333 681 L 510.333 595.667 L 339.667 595.667 L 339.667 681 Z M 41 169 L 41 254.333 L 809 254.333 L 809 169 L 41 169 Z M 169 467.667 L 681 467.667 L 681 382.333 L 169 382.333 L 169 467.667 Z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.FILTER_ICON_ACTIVE">
    <div class="o-icon filter-icon-active">
      <i class="fa fa-filter"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.SEARCH">
    <div class="o-icon">
      <i class="fa fa-search"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.ZOOM">
    <div class="o-icon">
      <i class="fa fa-search-plus"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CHECK">
    <svg class="o-icon" viewBox="0 0 24 24">
      <path
        fill="currentColor"
        d="M18.707 7.293a1 1 0 0 1 0 1.414L11.414 16a1.8 2 0 0 1-2.828 0l-3.293-3.293a1 1 0 1 1 1.414-1.414L10 14.586l7.293-7.293a1 1 0 0 1 1.414 0z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.PERCENT">
    <span class="o-text-icon">%</span>
  </t>
  <t t-name="o-spreadsheet-Icon.DECRASE_DECIMAL">
    <span class="o-text-icon">.0</span>
  </t>
  <t t-name="o-spreadsheet-Icon.INCREASE_DECIMAL">
    <span class="o-text-icon">.00</span>
  </t>
  <t t-name="o-spreadsheet-Icon.NUMBER_FORMATS">
    <svg class="o-icon" fill="currentColor">
      <path
        d="M0 6h2v8h2V4H0m9 0H5v2h4v2H6.5A1.5 1.5 0 0 0 5 9.5V14h6v-2H7v-2h2.5A1.5 1.5 0 0 0 11 8.5v-3A1.5 1.5 0 0 0 9.5 4M12 4v2h4v2h-2v2h2v2h-4v2h4.5a1.5 1.5 0 0 0 1.5-1.5v-2A1.5 1.5 0 0 0 16.5 9 1.5 1.5 0 0 0 18 7.5v-2A1.5 1.5 0 0 0 16.5 4"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.FONT_SIZE">
    <svg class="o-icon" fill="currentColor">
      <text x="2" y="15" class="small-text">A</text>
      <text x="6" y="15" class="heavy-text">A</text>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.TRIANGLE_EXCLAMATION">
    <div class="o-icon fa-small">
      <i class="fa fa-exclamation-triangle"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.SPLIT_TEXT">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M14 6v2h-4v2h4v2l3-3m-9 1V8H4V6L1 9l3 3v-2m3.5-6.5h3V7H12V3.5h3V2H3v1.5h3V7h1.5m3 7.5h-3V11H6v3.5H3V16h12v-1.5h-3V11h-1.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ERROR">
    <div class="o-icon">
      <i class="fa fa-exclamation-circle"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.DISPLAY_HEADER">
    <svg class="o-icon" width="18" height="18">
      <path
        fill="currentColor"
        d="M.75.5h16.5v17H.75m1.5-12H.75V7h1.5v1.5H.75V10h1.5v1.5H.75V13h1.5v1.5H.75V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v1.5h1.5V16h1.5v-1.5h-1.5V13h1.5v-1.5h-1.5V10h1.5V8.5h-1.5V7h1.5V5.5M2.75 2.25v1.5h2v-1.5m2.5 0v1.5h7v-1.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.COG">
    <svg class="o-icon" fill="currentColor" viewBox="0 0 16 16">
      <path
        d="M8 4.754a3.246 3.246 0 1 0 0 6.492 3.246 3.246 0 0 0 0-6.492zM5.754 8a2.246 2.246 0 1 1 4.492 0 2.246 2.246 0 0 1-4.492 0z"
      />
      <path
        d="M9.796 1.343c-.527-1.79-3.065-1.79-3.592 0l-.094.319a.873.873 0 0 1-1.255.52l-.292-.16c-1.64-.892-3.433.902-2.54 2.541l.159.292a.873.873 0 0 1-.52 1.255l-.319.094c-1.79.527-1.79 3.065 0 3.592l.319.094a.873.873 0 0 1 .52 1.255l-.16.292c-.892 1.64.901 3.434 2.541 2.54l.292-.159a.873.873 0 0 1 1.255.52l.094.319c.527 1.79 3.065 1.79 3.592 0l.094-.319a.873.873 0 0 1 1.255-.52l.292.16c1.64.893 3.434-.902 2.54-2.541l-.159-.292a.873.873 0 0 1 .52-1.255l.319-.094c1.79-.527 1.79-3.065 0-3.592l-.319-.094a.873.873 0 0 1-.52-1.255l.16-.292c.893-1.64-.902-3.433-2.541-2.54l-.292.159a.873.873 0 0 1-1.255-.52l-.094-.319zm-2.633.283c.246-.835 1.428-.835 1.674 0l.094.319a1.873 1.873 0 0 0 2.693 1.115l.291-.16c.764-.415 1.6.42 1.184 1.185l-.159.292a1.873 1.873 0 0 0 1.116 2.692l.318.094c.835.246.835 1.428 0 1.674l-.319.094a1.873 1.873 0 0 0-1.115 2.693l.16.291c.415.764-.42 1.6-1.185 1.184l-.291-.159a1.873 1.873 0 0 0-2.693 1.116l-.094.318c-.246.835-1.428.835-1.674 0l-.094-.319a1.873 1.873 0 0 0-2.692-1.115l-.292.16c-.764.415-1.6-.42-1.184-1.185l.159-.291A1.873 1.873 0 0 0 1.945 8.93l-.319-.094c-.835-.246-.835-1.428 0-1.674l.319-.094A1.873 1.873 0 0 0 3.06 4.377l-.16-.292c-.415-.764.42-1.6 1.185-1.184l.292.159a1.873 1.873 0 0 0 2.692-1.115l.094-.319z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.PLUS_IN_BOX">
    <svg class="o-icon" width="18" height="18" style="">
      <path
        fill="currentColor"
        d="
        M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2
        M4,9.5 h10 v-1.5 h-10
        M8.25,3.75 v10 h1.5 v-10
        "
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.MINUS_IN_BOX">
    <svg class="o-icon" width="18" height="18" style="">
      <path
        fill="currentColor"
        d="
        M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v14a1.5 1.5 0 0 1-1.5 1.5H2A1.5 1.5 0 0 1 .5 16V2H2v14h14V2H2
        M4,9.5 h10 v-1.5 h-10
        "
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.GROUP_ROWS">
    <svg class="o-icon" width="18" height="18">
      <path
        fill="currentColor"
        d="M6 2.5A1.5 1.5 0 0 1 7.5 1H16a1.5 1.5 0 0 1 1.5 1.5V15a1.5 1.5 0 0 1-1.5 1.5H7.5A1.5 1.5 0 0 1 6 15M7.5 2.5v2H16v-2M7.5 6v2H16V6M7.5 9.5v2H16v-2M7.5 13v2H16v-2M2 5.75V13h3v-1.5H3.5V5.75h1.25V3l-1 1v.75H3M.25 1.25v4.5h4.5v-4.5m-3.5 1h2.5v2.5h-2.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNGROUP_ROWS">
    <svg class="o-icon" width="18" height="18">
      <path
        fill="currentColor"
        d="M6 2.5A1.5 1.5 0 0 1 7.5 1H16a1.5 1.5 0 0 1 1.5 1.5V15a1.5 1.5 0 0 1-1.5 1.5H7.5A1.5 1.5 0 0 1 6 15M7.5 2.5v2H16v-2M7.5 6v2H16V6M7.5 9.5v2H16v-2M7.5 13v2H16v-2M2 5.75V13h3v-1.5H3.5V5.75M0 5.25.75 6l2-2 2 2 .75-.75-2-2 2-2L4.75.5l-2 2-2-2-.75.75 2 2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.GROUP_COLUMNS">
    <svg class="o-icon" width="18" height="18">
      <path
        fill="currentColor"
        d="M2.75 6a1.5 1.5 0 0 0-1.5 1.5V16a1.5 1.5 0 0 0 1.5 1.5h12.5a1.5 1.5 0 0 0 1.5-1.5V7.5a1.5 1.5 0 0 0-1.5-1.5M2.75 7.5h2V16h-2m3.5-8.5h2V16h-2m3.5-8.5h2V16h-2m3.5-8.5h2V16h-2M6 2h7.25v3h-1.5V3.5H6v1.25H3.25l1-1H5V3M1.5.25H6v4.5H1.5m1-3.5v2.5H5v-2.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNGROUP_COLUMNS">
    <svg class="o-icon" width="18" height="18">
      <path
        fill="currentColor"
        d="M2.75 6a1.5 1.5 0 0 0-1.5 1.5V16a1.5 1.5 0 0 0 1.5 1.5h12.5a1.5 1.5 0 0 0 1.5-1.5V7.5a1.5 1.5 0 0 0-1.5-1.5M2.75 7.5h2V16h-2m3.5-8.5h2V16h-2m3.5-8.5h2V16h-2m3.5-8.5h2V16h-2M6 2h7.25v3h-1.5V3.5H6M5.5 0l.75.75-2 2 2 2-.75.75-2-2-2 2-.75-.75 2-2-2-2L1.5 0l2 2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.DATA_VALIDATION">
    <svg class="o-icon">
      <path
        fill="currentColor"
        d="M.5 2A1.5 1.5 0 0 1 2 .5h14A1.5 1.5 0 0 1 17.5 2v7H11V7H7v4s-.5 0-1.5 1h-1v5h-3a1.5 1.5 0 0 1-1-1M6 6V2H2v4m9 0V2H7v4m9 0V2h-4v4m-6 5V7H2v4m14-2V7h-4v2m-7.5 6.5V12H2v3.5"
      />
      <path
        stroke="currentColor"
        style="fill:none; stroke-linecap:round; stroke-width:1.5"
        d="M8,13 l3 3 l6 -5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.THIN_DRAG_HANDLE">
    <svg class="o-icon" viewBox="0 0 4 16" fill="currentColor">
      <circle cx="2" cy="3.5" r="1"/>
      <circle cx="2" cy="6.5" r="1"/>
      <circle cx="2" cy="9.5" r="1"/>
      <circle cx="2" cy="12.5" r="1"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.SHORT_THIN_DRAG_HANDLE">
    <svg class="o-icon" viewBox="0 0 4 12" fill="currentColor">
      <circle cx="2" cy="3.5" r="1"/>
      <circle cx="2" cy="6.5" r="1"/>
      <circle cx="2" cy="9.5" r="1"/>
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.EDIT_TABLE">
    <svg class="o-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
      <path
        fill="currentColor"
        d="M2.5 1A1.5 1.5 0 0 0 1 2.5v11A1.5 1.5 0 0 0 2.5 15H7l1.5-1.5H7v-2.75h3.5v.75l2.25-2.25H12v-2.5h3.5v.75c.1-.2.45-.05.5.02l1 1V2.5A1.5 1.5 0 0 0 15.5 1m-13 1.5h13v2.75h-13m0 1.5h3v2.5h-3M7 6.75h3.5v2.5H7m-4.5 1.5h3v2.75h-3 M8.2 15.7v1.8h1.8l5.4-5.4-1.8-1.8-5.4 5.4Zm8.8-5.2a.5.5 0 0 0 0-.7l-1.1-1.1a.5.5 0 0 0-.7 0l-.9.9 1.8 1.8.9-.9Z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.DELETE_TABLE">
    <svg class="o-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
      <path
        fill="currentColor"
        d="M2.5 1A1.5 1.5 0 0 0 1 2.5v11A1.5 1.5 0 0 0 2.5 15H7l1.5-1.5H7V6.75h3.5v.75L12 9V6.75h3.5l1.5 1.5V2.5A1.5 1.5 0 0 0 15.5 1m-13 1.5h13v2.75h-13m0 1.5h3v2.5h-3m0 1.5h3v2.75h-3m10-2.25 3-3 1.5 1.5-3 3 3 3-1.5 1.5-3-3-3 3-1.5-1.5 3-3-3-3 1.5-1.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.PAINT_TABLE">
    <svg class="o-icon" xmlns="http://www.w3.org/2000/svg" width="18" height="18">
      <path
        fill="currentColor"
        d="M2.5 1A1.5 1.5 0 0 0 1 2.5v11A1.5 1.5 0 0 0 2.5 15h5c0-.5 0-1 .5-1.5H7v-2.75h3.5v.75l2.25-2.25H12v-2.5h3.5v.75c1-.7 1.5-.4 1.5-.4V2.5A1.5 1.5 0 0 0 15.5 1m-13 1.5h13v2.75h-13m0 1.5h3v2.5h-3M7 6.75h3.5v2.5H7m-4.5 1.5h3v2.75h-3m7.5-.3c.7-.3 1.5-.1 2.1.6.6.7.8 1.4.5 1.9-.6 1.4-3.7 1.6-4 1.7l-.6.1.3-.5s.5-.8.5-2.1c0-.7.5-1.4 1.1-1.7Zm6.7-5.1a.9.9 0 0 1 1 1c-.1 1.3-2.5 3.7-4.3 5.3a3.9 3.9 0 0 0-.6-1.1c-.4-.4-.8-.7-1.3-.8 1.5-1.7 4-4.3 5.4-4.4"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.CIRCLE_INFO">
    <svg class="o-icon" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="currentColor"
        d="M9 .55a8.4 8.4 0 1 0 8.4 8.4A8.4 8.4 0 0 0 9 .55M7.6 4.155a1.4 1.4 0 1 1 1.4 1.4 1.4 1.4 0 0 1-1.4-1.4m4.9 8.995a.7.7 0 0 1-.7.7H6.9a.7.7 0 1 1 0-1.4h1.4v-4.2h-.7a.7.7 0 0 1 0-1.4h2.8v5.6h1.4a.7.7 0 0 1 .7.7"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.PIVOT">
    <svg class="o-icon" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="currentColor"
        d="M17 2v14H1V6h4V2h12m-1 1H6v3h10M2 7v2h3V7m-3 3v2h3v-2m-3 3v2h3v-2m1-6v2h6V7m-6 3v2h6v-2m-6 3v2h6v-2m1-6v2h3V7m-3 3v2h3v-2m-3 3v2h3v-2"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.UNUSED_PIVOT_WARNING">
    <div class="o-unused-pivot-icon text-warning" title="This pivot is not used">
      <t t-call="o-spreadsheet-Icon.TRIANGLE_EXCLAMATION"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.ANGLE_DOWN">
    <div class="o-icon">
      <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 224 256">
        <path
          fill="currentColor"
          d="M201.4 342.6c12.5 12.5 32.8 12.5 45.3 0l160-160c12.5-12.5 12.5-32.8 0-45.3s-32.8-12.5-45.3 0L224 274.7 86.6 137.4c-12.5-12.5-32.8-12.5-45.3 0s-12.5 32.8 0 45.3l160 160z"
          transform="translate(0, 9) scale(0.5,0.5)"
        />
      </svg>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.INSERT_PIVOT">
    <svg class="o-icon">
      <defs>
        <mask id="a">
          <path fill="#fff" d="M0 0h18v18H0z"/>
          <path d="M18 26a3.5 3 0 0 1 0-18"/>
        </mask>
      </defs>
      <path
        fill="currentColor"
        d="M17 2v14H1V6h4V2h12m-1 1H6v3h10M2 7v2h3V7m-3 3v2h3v-2m-3 3v2h3v-2m1-6v2h6V7m-6 3v2h6v-2m-6 3v2h6v-2m1-6v2h3V7m-3 3v2h3v-2m-3 3v2h3v-2"
        mask="url(#a)"
      />
      <path
        fill="currentColor"
        d="M13 13v-3a.75.5 0 0 1 1.5 0v3h3a.5.75 0 0 1 0 1.5h-3v3a.75.5 0 0 1-1.5 0v-3h-3a.5.75 0 0 1 0-1.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.MOVE_SHEET_LEFT">
    <svg class="o-icon" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="currentColor"
        d="M16 2.5 V15.5 a1.5,1.5 0 1 1 -3 0 V2.5 a1.5 1.5 0 1 1 3 0 M12 10 H5 v2 l-3 -3 3 -3 v2 H12"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.MOVE_SHEET_RIGHT">
    <svg class="o-icon" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="currentColor"
        d="M5 2.5 V15.5 a1.5,1.5 0 1 1 -3 0 V2.5 a1.5 1.5 0 1 1 3 0 M6 10 H13 v2 l3 -3 -3 -3 v2 H6"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.RENAME_SHEET">
    <svg class="o-icon" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        fill="currentColor"
        d="
        M 9 5 H3 a 1.5 1.5 0 0 0 -1.5 1.5 v5 a1.5 1.5 0 0 0 1.5 1.5 H9 v-1.5 H3.5 a.5 .5 0 0 1 -.5 -.5 v-4 a.5 .5 0 0 1 .5 -.5 H9
        M 13 5 H15 a1.5 1.5 0 0 1 1.5 1.5 v5 a1.5 1.5 0 0 1 -1.5 1.5 H13 v-1.5 h1.5 a.5 .5 0 0 0 .5 -.5 v-4 a.5 .5 0 0 0 -.5 -.5 h-1.5
        M 10.25 3 h-2 v-1.5 h5.5 v1.5 h-2 v12 h2 v1.5 h-5.5 v-1.5 h2
      "
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.HIDE_SHEET">
    <div class="o-icon">
      <i class="fa fa-eye-slash"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.DOWNLOAD">
    <div class="o-icon">
      <i class="fa fa-download"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.CAROUSEL">
    <svg class="o-icon" viewBox="0 0 122.88 99.75">
      <path
        fill="currentColor"
        d="M29.09,0h64.7A5.21,5.21,0,0,1,99,5.18v89.4a5.19,5.19,0,0,1-5.18,5.17H29.09a5.19,5.19,0,0,1-5.17-5.18V5.18A5.21,5.21,0,0,1,29.09,0Zm78.52,12.46,10.59-1.52a4.71,4.71,0,0,1,4.68,4.69v68.5a4.71,4.71,0,0,1-4.68,4.68L107.77,88a1.35,1.35,0,0,1-1.31-1.34V83.14a1.34,1.34,0,0,1,1.44-1.23l8.91.73V17.22l-9,1.34a1.34,1.34,0,0,1-1.34-1.34V13.78a1.34,1.34,0,0,1,1.15-1.32ZM5,11l10.31,1.49a1.33,1.33,0,0,1,1.14,1.32v3.44a1.34,1.34,0,0,1-1.34,1.34l-9-1.34V82.64L15,81.91a1.33,1.33,0,0,1,1.43,1.23v3.49A1.35,1.35,0,0,1,15.11,88l-10.43.84A4.71,4.71,0,0,1,0,84.13V15.63a4.73,4.73,0,0,1,4.68-4.69L5,11Zm87.93-4.9H30v87.6h62.9V6.07Z"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.DATA">
    <svg class="o-icon" viewBox="0 0 18 18">
      <path
        fill="currentColor"
        d="M.5 1.5a1 1 0 0 1 1-1h15a1 1 0 0 1 1 1v15a1 1 0 0 1-1 1h-15a1 1 0 0 1-1-1zM6 6V1.5H1.5V6m10 0V1.5h-5V6m10 0V1.5H12V6m-6 5.5v-5H1.5v5m10 0v-5h-5v5m10 0v-5H12v5m-6 5V12H1.5v4.5m10 0V12h-5v4.5m10 0V12H12v4.5"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.FX_SVG">
    <svg class="o-icon fx-icon" viewBox="0 0 121.8 122.9">
      <path
        fill="currentColor"
        d='m28 34-4 5v2h10l-6 40c-4 22-6 28-7 30-2 2-3 3-5 3-3 0-7-2-9-4H4c-2 2-4 4-4 7s4 6 8 6 9-2 15-8c8-7 13-17 18-39l7-35 13-1 3-6H49c4-23 7-27 11-27 2 0 5 2 8 6h4c1-1 4-4 4-7 0-2-3-6-9-6-5 0-13 4-20 10-6 7-9 14-11 24h-8zm41 16c4-5 7-7 8-7s2 1 5 9l3 12c-7 11-12 17-16 17l-3-1-2-1c-3 0-6 3-6 7s3 7 7 7c6 0 12-6 22-23l3 10c3 9 6 13 10 13 5 0 11-4 18-15l-3-4c-4 6-7 8-8 8-2 0-4-3-6-10l-5-15 8-10 6-4 3 1 3 2c2 0 6-3 6-7s-2-7-6-7c-6 0-11 5-21 20l-2-6c-3-9-5-14-9-14-5 0-12 6-18 15l3 3z'
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.COLLAPSE">
    <svg class="o-icon" viewBox="0 0 18 18">
      <path
        d="M12.124 2.576a.6.6 0 0 1 0 .848l-2.7 2.7a.6.6 0 0 1-.848 0l-2.7-2.7a.6.6 0 0 1 .848-.848L8.4 4.2V.9a.6.6 0 0 1 1.2 0v3.3l1.676-1.624a.6.6 0 0 1 .848 0M5.876 15.424a.6.6 0 0 1 0-.848l2.7-2.7a.6.6 0 0 1 .848 0l2.7 2.7a.6.6 0 0 1-.848.848L9.6 13.8v3.3a.6.6 0 0 1-1.2 0v-3.3l-1.676 1.624a.6.6 0 0 1-.848 0M2 7a.5.5 0 0 0 0 1h14a.5.5 0 0 0 0-1M2 10a.5.5 0 0 0 0 1h14a.5.5 0 0 0 0-1"
        fill="currentColor"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.EXPAND">
    <svg class="o-icon" viewBox="0 0 18 18">
      <path
        d="M5.876 14.076a.6.6 0 0 0 0 .848l2.7 2.7a.6.6 0 0 0 .848 0l2.7-2.7a.6.6 0 0 0-.848-.848L9.6 15.7v-3.3a.6.6 0 0 0-1.2 0v3.3l-1.676-1.624a.6.6 0 0 0-.848 0m6.248-10.152a.6.6 0 0 0 0-.848l-2.7-2.7a.6.6 0 0 0-.848 0l-2.7 2.7a.6.6 0 0 0 .848.848L8.4 2.3v3.3a.6.6 0 0 0 1.2 0V2.3l1.676 1.624a.6.6 0 0 0 .848 0M2 10a.5.5 0 0 0 0 1h14a.5.5 0 0 0 0-1M2 7a.5.5 0 0 0 0 1h14a.5.5 0 0 0 0-1"
        fill="currentColor"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.DARK_MODE">
    <div class="o-icon">
      <i class="fa fa-moon-o"/>
    </div>
  </t>
  <t t-name="o-spreadsheet-Icon.ROTATION-0">
    <svg
      width="18"
      height="18"
      viewBox="0 0 18 18"
      transform="rotate(270)"
      xmlns="http://www.w3.org/2000/svg">
      <path
        d="M5 2h1v12h1.5l-2 2-2-2H5m6-5h1v5h1.5l-2 2-2-2H11M8 2l7 2.8V6L8 8.8l-.43-1.12 1.9-.7V3.8l-1.9-.7L8 1.98m2.7 2.25v2.3l2.8-1.1z"
        fill="currentColor"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ROTATION-45">
    <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        d="m1.95 6.879.707-.707 8.485 8.485 1.06-1.06v2.828H9.375l1.061-1.061m.706-7.778.707-.707 3.536 3.535 1.06-1.06v2.828h-2.828l1.06-1.06M4.071 4.757l6.93-2.97.848.849-2.97 6.93-1.096-.488.849-1.839-2.249-2.248-1.838.848-.488-1.096m3.5-.318 1.626 1.626 1.203-2.757z"
        fill="currentColor"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ROTATION-90">
    <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        d="M5 2h1v12h1.5l-2 2-2-2H5m6-5h1v5h1.5l-2 2-2-2H11M8 2l7 2.8V6L8 8.8l-.43-1.12 1.9-.7V3.8l-1.9-.7L8 1.98m2.7 2.25v2.3l2.8-1.1z"
        fill="currentColor"
      />
    </svg>
  </t>

  <t t-name="o-spreadsheet-Icon.ROTATION-270">
    <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        d="M13 16h-1V4h-1.5l2-2 2 2H13M7 9H6V4H4.5l2-2 2 2H7m3 12-7-2.8V12l7-2.8.43 1.12-1.9.7v3.18l1.9.7-.43 1.12m-2.7-2.25v-2.3l-2.8 1.1z"
        fill="currentColor"
      />
    </svg>
  </t>
  <t t-name="o-spreadsheet-Icon.ROTATION-315">
    <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
      <path
        d="m6.879 16.55-.707-.707 8.485-8.485-1.06-1.06h2.828v2.828l-1.061-1.061m-7.778-.707-.707-.707 3.535-3.536-1.06-1.06h2.828v2.828l-1.06-1.06M4.757 14.429l-2.97-6.93.849-.848 6.93 2.97-.488 1.096-1.839-.849-2.248 2.249.848 1.838-1.096.488m-.318-3.5 1.626-1.626-2.757-1.203z"
        fill="currentColor"
      />
    </svg>
  </t>

  <t t-name="o-spreadsheet-IconPicker">
    <div class="o-icon-picker bg-white">
      <t t-foreach="iconSets" t-as="iconSet" t-key="iconSet">
        <div class="o-cf-icon-line">
          <div
            class="o-icon-picker-item p-1"
            t-on-click="() => this.onIconClick(iconSets[iconSet].good)">
            <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].good].template}}"/>
          </div>
          <div
            class="o-icon-picker-item p-1"
            t-on-click="() => this.onIconClick(iconSets[iconSet].neutral)">
            <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].neutral].template}}"/>
          </div>
          <div
            class="o-icon-picker-item p-1"
            t-on-click="() => this.onIconClick(iconSets[iconSet].bad)">
            <t t-call="o-spreadsheet-Icon.{{icons[iconSets[iconSet].bad].template}}"/>
          </div>
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-Highlight">
    <div class="o-highlight" t-ref="highlight">
      <t
        t-if="!env.isMobile()"
        t-foreach="['n', 's', 'w', 'e']"
        t-as="orientation"
        t-key="orientation">
        <Border
          onMoveHighlight.bind="this.onMoveHighlight"
          isMoving='highlightState.shiftingMode === "isMoving"'
          orientation="orientation"
          zone="props.range.zone"
        />
      </t>
      <t t-foreach="cornerOrientations" t-as="orientation" t-key="orientation">
        <Corner
          onResizeHighlight.bind="onResizeHighlight"
          isResizing='highlightState.shiftingMode === "isResizing"'
          orientation="orientation"
          zone="props.range.zone"
          color="props.color"
        />
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-Corner">
    <div
      class="o-corner d-flex justify-content-center align-items-center"
      t-on-pointerdown.prevent="onMouseDown"
      t-on-touchstart.prevent.stop=""
      t-att-style="handlerStyle">
      <div
        t-att-style="buttonLook"
        class="o-corner-button"
        t-att-class="{
          'o-resizing': props.isResizing,
          'o-corner-nw': props.orientation === 'nw',
          'o-corner-ne': props.orientation === 'ne',
          'o-corner-sw': props.orientation === 'sw',
          'o-corner-se': props.orientation === 'se',
        }"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-Border">
    <div
      class="o-border"
      t-on-pointerdown.prevent="onMouseDown"
      t-att-style="style"
      t-att-class="{
          'o-moving': props.isMoving,
          'o-border-n': props.orientation === 'n',
          'o-border-s': props.orientation === 's',
          'o-border-w': props.orientation === 'w',
          'o-border-e': props.orientation === 'e',
        }"
    />
  </t>

  <t t-name="o-spreadsheet-UnhideRowHeaders">
    <t t-foreach="props.headersGroups" t-as="hiddenItem" t-key="hiddenItem_index">
      <t t-if="isVisible(hiddenItem[0]-1)">
        <div
          class="position-absolute w-100 pe-none"
          t-att-style="getUnhidePreviousButtonStyle(hiddenItem[0]-1)">
          <div
            class="o-unhide rounded end-0 position-absolute pe-auto"
            t-att-data-index="hiddenItem_index"
            t-attf-style="bottom: 2px;"
            t-att-data-direction="'up'"
            t-on-click="() => this.unhide(hiddenItem)">
            <t t-call="o-spreadsheet-Icon.CARET_UP"/>
          </div>
        </div>
      </t>
      <t t-if="isVisible(hiddenItem.at(-1)+1)">
        <div
          class="position-absolute w-100 pe-none"
          t-att-style="getUnhideNextButtonStyle(hiddenItem.at(-1)+1)">
          <div
            class="o-unhide rounded end-0 position-absolute pe-auto"
            t-att-data-index="hiddenItem_index"
            t-att-data-direction="'down'"
            t-attf-style="top: 1px;"
            t-on-click="() => this.unhide(hiddenItem)">
            <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
          </div>
        </div>
      </t>
    </t>
  </t>

  <t t-name="o-spreadsheet-UnhideColumnHeaders">
    <t t-foreach="props.headersGroups" t-as="hiddenItem" t-key="hiddenItem_index">
      <t t-if="isVisible(hiddenItem[0]-1)">
        <div
          class="position-absolute d-flex align-items-center pe-none h-100"
          t-att-style="getUnhidePreviousButtonStyle(hiddenItem[0]-1)">
          <div
            class="o-unhide position-absolute rounded pe-auto"
            t-att-data-index="hiddenItem_index"
            t-att-data-direction="'left'"
            t-attf-style="right: 1px;"
            t-on-click="() => this.unhide(hiddenItem)">
            <t t-call="o-spreadsheet-Icon.CARET_LEFT"/>
          </div>
        </div>
      </t>
      <t t-if="isVisible(hiddenItem.at(-1)+1)">
        <div
          class="position-absolute d-flex align-items-center pe-none h-100"
          t-att-style="getUnhideNextButtonStyle(hiddenItem.at(-1)+1)">
          <div
            class="o-unhide position-absolute rounded pe-auto"
            t-att-data-index="hiddenItem_index"
            t-att-data-direction="'right'"
            t-attf-style="left: 1px;"
            t-on-click="() => this.unhide(hiddenItem)">
            <t t-call="o-spreadsheet-Icon.CARET_RIGHT"/>
          </div>
        </div>
      </t>
    </t>
  </t>

  <t t-name="o-spreadsheet-HeadersOverlay">
    <div class="o-overlay">
      <ColResizer onOpenContextMenu="props.onOpenContextMenu"/>
      <RowResizer onOpenContextMenu="props.onOpenContextMenu"/>
      <div class="all" t-on-pointerdown.self="selectAll"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-RowResizer">
    <div
      class="o-row-resizer o-zoomable"
      t-ref="rowResizer"
      t-on-pointermove.self="onMouseMove"
      t-on-mouseleave="onMouseLeave"
      t-on-pointerdown.self.prevent="select"
      t-on-click="onClick"
      t-on-contextmenu.self="onContextMenu"
      t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving}">
      <div
        t-if="state.isMoving"
        class="dragging-row-line"
        t-attf-style="top:{{state.draggerLinePosition}}px;"
      />
      <div
        t-if="state.isMoving"
        class="dragging-row-shadow"
        t-attf-style="top:{{state.draggerShadowPosition}}px; height:{{state.draggerShadowThickness}}px;"
      />
      <t t-if="state.resizerIsActive">
        <div
          class="o-handle"
          t-on-pointerdown="onMouseDown"
          t-on-dblclick="onDblClick"
          t-on-contextmenu.prevent=""
          t-attf-style="top:{{state.draggerLinePosition - 2}}px;">
          <div class="dragging-resizer" t-if="state.isResizing"/>
        </div>
      </t>
      <t t-if="env.model.getters.getHiddenRowsGroups(sheetId).length">
        <t t-if="hasFrozenPane">
          <div class="position-relative pe-none overflow-hidden" t-att-style="frozenContainerStyle">
            <UnhideRowHeaders t-props="frozenUnhideHeadersProps"/>
          </div>
        </t>
        <div class="pe-none overflow-hidden flex-shrink-0 position-relative h-100">
          <UnhideRowHeaders t-props="mainUnhideHeadersProps"/>
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-ColResizer">
    <div
      class="o-col-resizer d-flex o-zoomable"
      t-ref="colResizer"
      t-on-pointermove.self="onMouseMove"
      t-on-mouseleave="onMouseLeave"
      t-on-pointerdown.self.prevent="select"
      t-on-click="onClick"
      t-on-contextmenu.self="onContextMenu"
      t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving, }">
      <div
        t-if="state.isMoving"
        class="dragging-col-line"
        t-attf-style="left:{{state.draggerLinePosition}}px;"
      />
      <div
        t-if="state.isMoving"
        class="dragging-col-shadow"
        t-attf-style="left:{{state.draggerShadowPosition}}px; width:{{state.draggerShadowThickness}}px"
      />
      <t t-if="state.resizerIsActive">
        <div
          class="o-handle"
          t-on-pointerdown="onMouseDown"
          t-on-dblclick="onDblClick"
          t-on-contextmenu.prevent=""
          t-attf-style="left:{{state.draggerLinePosition - 2}}px;">
          <div class="dragging-resizer" t-if="state.isResizing"/>
        </div>
      </t>
      <t t-if="env.model.getters.getHiddenColsGroups(sheetId).length">
        <t t-if="hasFrozenPane">
          <div
            class="position-relative pe-none h-100 flex-shrink-0"
            t-att-style="frozenContainerStyle">
            <UnhideColumnHeaders t-props="frozenUnhideHeadersProps"/>
          </div>
        </t>
        <div class="pe-none overflow-hidden flex-shrink-0 position-relative w-100">
          <UnhideColumnHeaders t-props="mainUnhideHeadersProps"/>
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-HeaderGroupContainer">
    <div
      class="o-header-group-container d-flex w-100 h-100 overflow-hidden"
      t-att-class="{
        'flex-column': props.dimension === 'ROW',
        'flex-row': props.dimension === 'COL',
      }"
      t-if="props.layers.length"
      t-on-contextmenu.prevent="onContextMenu">
      <div
        class="o-header-group-frozen-pane flex-shrink-0 overflow-hidden position-relative"
        t-att-class="{
          'o-group-rows': props.dimension === 'ROW',
          'o-group-columns': props.dimension === 'COL',
        }"
        t-if="hasFrozenPane"
        t-att-style="frozenPaneContainerStyle">
        <t t-foreach="props.layers" t-as="layer" t-key="layer_index">
          <t t-foreach="layer" t-as="group" t-key="group.start + '-' + group.end">
            <t
              t-component="groupComponent"
              group=" group"
              layerOffset="getLayerOffset(layer_index)"
              openContextMenu.bind="openContextMenu"
            />
          </t>
        </t>
      </div>
      <div
        class="o-header-group-frozen-pane-border"
        t-att-class="{
          'o-group-rows': props.dimension === 'ROW',
          'o-group-columns': props.dimension === 'COL',
        }"
        t-if="hasFrozenPane"
      />

      <div
        class="o-header-group-main-pane flex-shrink-0 position-relative h-100 w-100 overflow-hidden"
        t-att-class="{
          'o-group-rows': hasFrozenPane and props.dimension === 'ROW',
          'o-group-columns': hasFrozenPane and props.dimension === 'COL',
        }">
        <div
          class="o-header-group-scroll-container position-relative"
          t-att-style="scrollContainerStyle">
          <t t-foreach="props.layers" t-as="layer" t-key="layer_index">
            <t t-foreach="layer" t-as="group" t-key="group.start + '-' + group.end">
              <t
                t-component="groupComponent"
                group="group"
                layerOffset="getLayerOffset(layer_index)"
                openContextMenu.bind="openContextMenu"
              />
            </t>
          </t>
        </div>
      </div>

      <MenuPopover
        t-if="menu.isOpen"
        menuItems="menu.menuItems"
        anchorRect="menu.anchorRect"
        onClose.bind="this.closeMenu"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-HeaderGroup">
    <div
      class="o-header-group position-absolute"
      t-att-style="groupBoxStyle"
      t-att-data-id="props.group.start + '-' + props.group.end"
      t-on-click="toggleGroup"
      t-on-contextmenu.stop.prevent="onContextMenu">
      <div
        class="o-header-group-header position-absolute d-flex align-items-center justify-content-center overflow-hidden"
        t-att-style="groupHeaderStyle">
        <div
          class="o-group-fold-button user-select-none rounded d-flex align-items-center justify-content-center"
          t-att-style="groupButtonStyle">
          <t t-call="{{groupButtonIcon}}"/>
        </div>
      </div>
      <div
        class="o-group-border position-absolute"
        t-if="!isGroupFolded"
        t-att-style="groupBorderStyle"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-GridPopover">
    <Popover
      t-if="cellPopover.isOpen"
      positioning="cellPopover.cellCorner"
      maxHeight="cellPopover.Component.size and cellPopover.Component.size.maxHeight"
      maxWidth="cellPopover.Component.size and cellPopover.Component.size.maxHidth"
      anchorRect="cellPopover.anchorRect"
      containerRect="env.getPopoverContainerRect()"
      onMouseWheel="props.onMouseWheel"
      class="'o-popover-grid-index'">
      <t
        t-component="cellPopover.Component"
        t-props="{...cellPopover.props, onClosed : () => props.onClosePopover()}"
      />
    </Popover>
  </t>

  <t t-name="o-spreadsheet-GridOverlay">
    <div class="position-absolute" t-att-style="style">
      <FiguresContainer/>
    </div>
    <div
      t-ref="gridOverlay"
      class="o-grid-overlay overflow-hidden o-zoomable"
      t-att-class="{'o-paint-format-cursor': isPaintingFormat}"
      t-att-style="style"
      t-on-pointerdown="onPointerDown"
      t-on-pointermove="onPointerMove"
      t-on-click="onClick"
      t-on-dblclick.self="onDoubleClick"
      t-on-contextmenu.stop.prevent="onContextMenu">
      <GridAddRowsFooter
        t-if="!env.model.getters.isReadonly()"
        t-key="env.model.getters.getActiveSheetId()"
      />
      <t t-slot="default"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-GridAddRowsFooter">
    <div
      class="o-grid-add-rows mt-2 ms-2 w-100 d-flex position-relative align-items-center"
      t-att-style="addRowsPosition"
      t-on-pointerdown.stop.prevent="">
      <button
        t-on-click="onConfirm"
        t-att-disabled="state.errorFlag"
        class="o-button flex-grow-0 me-2"
        tabindex="-1">
        Add
      </button>
      <input
        type="text"
        class="o-grid-add-rows-input o-input mt-0 me-2"
        t-ref="inputRef"
        value="100"
        t-on-click.stop=""
        t-on-keydown.stop="onKeydown"
        t-on-pointerdown.stop=""
        t-on-input.stop="onInput"
        tabindex="-1"
      />
      <span>more rows at the bottom</span>
      <ValidationMessages t-if="state.errorFlag" messages="errorMessages" msgType="'error'"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-Grid">
    <div
      class="o-grid w-100 h-100 o-zoomable"
      tabindex="-1"
      composerFocusableElement="true"
      t-on-click="focusDefaultElement"
      t-on-keydown="onKeydown"
      t-on-wheel.prevent="onMouseWheel"
      t-ref="grid">
      <GridOverlay
        onCellClicked.bind="onCellClicked"
        onCellDoubleClicked.bind="onCellDoubleClicked"
        onCellRightClicked.bind="onCellRightClicked"
        onGridResized.bind="onGridResized"
        onGridMoved.bind="moveCanvas"
        gridOverlayDimensions="gridOverlayDimensions"
      />
      <HeadersOverlay onOpenContextMenu="(type, x, y) => this.toggleContextMenu(type, x, y)"/>
      <GridComposer
        gridDims="env.model.getters.getSheetViewDimensionWithHeaders()"
        onInputContextMenu.bind="onInputContextMenu"
      />
      <canvas t-ref="canvas"/>
      <t t-set="focused" t-value="focusedClients"/>
      <t
        t-foreach="env.model.getters.getClientsToDisplay()"
        t-as="client"
        t-key="getClientPositionKey(client)">
        <ClientTag
          name="client.name"
          color="client.color"
          col="client.position.col"
          row="client.position.row"
          active="isCellHovered(client.position.col, client.position.row) || focused.has(client.id)"
        />
      </t>
      <GridPopover
        t-if="!menuState.isOpen"
        gridRect="getGridRect()"
        onMouseWheel.bind="onMouseWheel"
        onClosePopover.bind="onClosePopover"
      />
      <t t-if="env.model.getters.isGridSelectionActive() and !env.isMobile()">
        <Autofill position="getAutofillPosition()" isVisible="isAutofillVisible"/>
      </t>
      <t t-foreach="highlights" t-as="highlight" t-key="highlight_index">
        <t
          t-if="highlight.interactive and highlight.range.sheetId === env.model.getters.getActiveSheetId()">
          <Highlight range="highlight.range" color="highlight.color"/>
        </t>
      </t>
      <Selection t-if="displaySelectionHandler"/>
      <MenuPopover
        t-if="menuState.isOpen"
        menuItems="menuState.menuItems"
        anchorRect="menuState.anchorRect"
        onClose="() => this.closeMenu()"
      />
      <t t-foreach="staticTables" t-as="table" t-key="table.id">
        <TableResizer table="table"/>
      </t>
      <VerticalScrollBar topOffset="HEADER_HEIGHT"/>
      <HorizontalScrollBar leftOffset="HEADER_WIDTH"/>
      <div class="o-scrollbar corner border-top border-start"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-FullScreenFigure">
    <div class="position-absolute o-fullscreen-figure-overlay w-100 h-100 d-flex" t-if="figureUI">
      <div
        class="position-absolute top-0 start-0 end-0 bottom-0"
        t-on-click="exitFullScreen"
        aria-hidden="true"
      />
      <button
        class="o-exit top-0 end-0 position-absolute o-button primary m-1 shadow"
        t-on-click="exitFullScreen">
        Exit fullscreen
      </button>
      <div class="flex-fill">
        <div
          class="o-fullscreen-figure o-figure position-relative border rounded shadow"
          tabindex="1"
          t-ref="fullScreenFigure"
          t-on-click.stop=""
          t-on-keydown="(ev) => this.onKeyDown(ev)">
          <t>
            <t
              t-component="figureComponent"
              figureUI="figureUI"
              isFullScreen="true"
              t-key="figureUI.id"
            />
          </t>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-FontSizeEditor">
    <NumberEditor
      currentValue="props.currentFontSize"
      onValueChange="props.onFontSizeChanged"
      class="props.class"
      onToggle="props.onToggle"
      onFocusInput="props.onFocusInput"
      min="1"
      max="400"
      valueList="fontSizes"
      title.translate="Font Size"
    />
  </t>

  <t t-name="o-spreadsheet-FilterMenuValueList">
    <div class="o-filter-menu-actions d-flex">
      <div class="o-button-link me-4" t-on-click="selectAll">Select all</div>
      <div class="o-button-link me-4" t-on-click="clearAll">Clear</div>
    </div>
    <div class="position-relative">
      <input
        class="w-100 o-input my-2"
        t-ref="filterMenuSearchBar"
        type="text"
        t-on-input="updateSearch"
        placeholder="Search..."
        t-on-keydown="onKeyDown"
      />
      <i class="o-search-icon position-absolute">
        <t t-call="o-spreadsheet-Icon.SEARCH"/>
      </i>
    </div>
    <div
      class="o-filter-menu-list d-flex flex-column border"
      t-ref="filterValueList"
      t-on-click="this.clearScrolledToValue"
      t-on-scroll="this.clearScrolledToValue">
      <t t-foreach="state.displayedValues" t-as="value" t-key="value.string">
        <FilterMenuValueItem
          onClick="() => this.checkValue(value)"
          onMouseMove="() => this.onMouseMove(value)"
          value="value.string"
          isChecked="value.checked"
          isSelected="value.string === state.selectedValue"
          scrolledTo="value.scrolledTo"
        />
      </t>
      <div
        t-if="state.hasMoreValues"
        class="o-filter-load-more o-button-link d-flex justify-content-center py-1"
        t-on-click="this.loadMoreValues">
        Load more...
      </div>
      <div
        t-if="state.displayedValues.length === 0"
        class="o-filter-menu-no-values d-flex align-items-center justify-content-center w-100 h-100 text-muted fst-italic">
        No results
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-FilterMenuValueItem">
    <div
      t-on-pointermove="this.props.onMouseMove"
      class="o-filter-menu-item o-filter-menu-value"
      t-ref="menuValueItem"
      t-att-class="{'selected': this.props.isSelected}">
      <t t-set="value">
        <t t-if="this.props.value === ''">(Blanks)</t>
        <t t-else="" t-esc="this.props.value"/>
      </t>
      <!-- toString because t-set with a body creates a LazyValue instead of a string -->
      <Checkbox
        name="value.toString()"
        value="this.props.isChecked"
        onChange="this.props.onClick"
        className="'p-2 w-100 pe-auto'"
        label="value.toString()"
        title="value.toString()"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-FilterMenuCriterion">
    <SelectMenu
      class="'o-filter-criterion-type o-input m-1 mb-2'"
      menuItems="criterionMenuItems"
      selectedValue="selectedCriterionName"
    />

    <t
      t-if="criterionComponent"
      t-component="criterionComponent"
      t-key="selectedCriterionName"
      criterion="state.criterion"
      onCriterionChanged.bind="onCriterionChanged"
      disableFormulas="true"
      autofocus="true"
    />
  </t>

  <t t-name="o-spreadsheet-FilterMenu">
    <div class="o-filter-menu d-flex flex-column bg-white" t-on-wheel.stop="">
      <t t-if="isSortable">
        <div>
          <div
            class="o-filter-menu-item o-sort-item py-2 mb-1"
            t-on-click="() => this.sortFilterZone('asc')">
            Sort ascending (A ⟶ Z)
          </div>
          <div
            class="o-filter-menu-item o-sort-item py-2"
            t-on-click="() => this.sortFilterZone('desc')">
            Sort descending (Z ⟶ A)
          </div>
        </div>
      </t>
      <div class="o-filter-menu-content">
        <div class="o-separator border-bottom"/>
        <SidePanelCollapsible
          isInitiallyCollapsed="filterValueType !== 'criterion'"
          title.translate="Filter by criterion">
          <t t-set-slot="content">
            <FilterMenuCriterion
              filterPosition="props.filterPosition"
              onCriterionChanged.bind="onCriterionChanged"
              criterionOperators="criterionOperators"
            />
            <div class="mb-3"/>
          </t>
        </SidePanelCollapsible>

        <SidePanelCollapsible
          isInitiallyCollapsed="filterValueType === 'criterion'"
          title.translate="Filter by values">
          <t t-set-slot="content">
            <FilterMenuValueList
              filterPosition="props.filterPosition"
              onUpdateHiddenValues.bind="onUpdateHiddenValues"
            />
          </t>
        </SidePanelCollapsible>

        <div class="o-filter-menu-buttons d-flex justify-content-end">
          <button class="o-button o-filter-menu-cancel me-2" t-on-click="cancel">Cancel</button>
          <button class="o-button primary o-filter-menu-confirm" t-on-click="confirm">
            Confirm
          </button>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-ImageFigure">
    <img t-att-src="getImagePath" class="w-100 h-100"/>
  </t>

  <t t-name="o-spreadsheet-FiguresContainer">
    <div class="position-absolute">
      <t t-foreach="containers" t-as="container" t-key="container.type">
        <div
          class="o-figure-container position-absolute pe-none overflow-hidden"
          t-att-style="container.style"
          t-att-data-id="container.type + 'Container'">
          <div
            class="o-figure-viewport-inverse w-0 h-0 overflow-visible position-absolute"
            t-att-style="container.inverseViewportStyle">
            <t t-foreach="container.figures" t-as="figureUI" t-key="figureUI.id">
              <FigureComponent
                figureUI="figureUI"
                style="getFigureStyle(figureUI)"
                class="getFigureClass(figureUI)"
                onMouseDown="(ev) => this.startDraggingFigure(figureUI, ev)"
                onClickAnchor="(dirX, dirY, ev) => this.startResize(figureUI, dirX, dirY, ev)"
              />
            </t>
          </div>
        </div>
      </t>
    </div>
    <div
      class="o-figure-container position-absolute pe-none overflow-hidden"
      t-if="dnd.horizontalSnap"
      t-att-style="dnd.horizontalSnap.containerStyle"
      t-att-data-id="'HorizontalSnapContainer'">
      <div class="o-figure-snap-line horizontal" t-att-style="dnd.horizontalSnap.lineStyle"/>
    </div>
    <div
      class="o-figure-container position-absolute pe-none overflow-hidden"
      t-if="dnd.verticalSnap"
      t-att-style="dnd.verticalSnap.containerStyle"
      t-att-data-id="'VerticalSnapContainer'">
      <div class="o-figure-snap-line vertical" t-att-style="dnd.verticalSnap.lineStyle"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-ChartFigure">
    <div class="o-chart-container w-100 h-100" t-on-dblclick="onDoubleClick">
      <t
        t-component="chartComponent"
        chartId="chartId"
        t-key="chartId"
        isFullScreen="props.isFullScreen"
      />
    </div>
    <div t-if="env.isDashboard()" class="position-absolute top-0 end-0">
      <ChartDashboardMenu chartId="chartId"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-CarouselFigure">
    <div class="o-carousel w-100 h-100 d-flex flex-column" t-on-dblclick="onCarouselDoubleClick">
      <t t-set="selectedItem" t-value="selectedCarouselItem"/>
      <div
        class="o-carousel-header d-flex align-items-baseline flex-shrink-0 pe-1 pe-auto"
        t-att-class="{
          'border-bottom': env.isDashboard(),
          'o-carousel-header-floating': !env.isDashboard() and selectedItem?.type === 'carouselDataView',
         }"
        t-att-style="headerStyle">
        <div
          class="o-carousel-title text-truncate flex-shrink-0 pe-2"
          t-esc="title"
          t-att-title="title"
          t-att-style="titleStyle"
        />
        <div class="o-carousel-tabs d-flex flex-fill justify-content-end" t-ref="carouselTabs">
          <t t-foreach="visibleCarouselItems" t-as="item" t-key="item_index">
            <div
              class="o-carousel-tab text-truncate px-2 mt-1 flex-shrink-0"
              t-att-class="{ 'selected': isItemSelected(item) }"
              t-att-data-type="item.type"
              t-esc="getItemTitle(item)"
              t-on-click.stop="() => this.onCarouselTabClick(item)"
            />
          </t>
        </div>
        <div
          class="o-carousel-tabs-dropdown o-carousel-button flex-shrink-0 rounded p-1"
          t-att-class="{'active': menuState.isOpen}"
          t-ref="carouselTabsDropdown"
          t-on-click="toggleMenu">
          <div class="fa fa-angle-down"/>
          <MenuPopover
            t-if="menuState.isOpen"
            menuId="menuId"
            anchorRect="menuState.anchorRect"
            menuItems="menuState.menuItems"
            onClose="() => this.menuState.isOpen=false"
            popoverPositioning="'bottom-left'"
          />
        </div>
        <div
          t-if="env.isDashboard()"
          t-att-title="fullScreenButtonTitle"
          class="o-carousel-full-screen-button fa o-carousel-button rounded p-1 ms-1"
          t-att-class="{
            'fa-compress': props.isFullScreen,
            'fa-expand': !props.isFullScreen,
            'invisible': selectedCarouselItem?.type !== 'chart',
          }"
          t-on-click="toggleFullScreen"
        />
        <div
          t-if="!env.isDashboard()"
          class="o-carousel-menu-button o-carousel-button fa fa-ellipsis-v rounded ms-1"
          t-on-click="openContextMenu"
        />
      </div>
      <div
        t-if="!selectedItem"
        class="o-carousel-empty w-100 flex-fill d-flex align-items-center justify-content-center">
        <t t-call="o-spreadsheet-Icon.CAROUSEL"/>
      </div>
      <div
        t-elif="selectedItem.type === 'chart'"
        class="o-carousel-content w-100 flex-fill position-relative">
        <div class="o-chart-container w-100 h-100">
          <t
            t-component="chartComponent"
            chartId="selectedItem.chartId"
            isFullScreen="props.isFullScreen"
            t-key="selectedItem.chartId"
          />
        </div>
        <ChartDashboardMenu
          t-if="env.isDashboard()"
          chartId="selectedItem.chartId"
          hasFullScreenButton="false"
          t-key="selectedItem.chartId"
        />
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-FigureComponent">
    <div
      class="o-figure-wrapper"
      t-att-class="{'o-figure-selected': isSelected}"
      t-att-style="wrapperStyle"
      t-ref="figureWrapper">
      <div
        class="o-figure w-100 h-100"
        t-att-class="props.class"
        t-on-pointerdown.stop="(ev) => this.onMouseDown(ev)"
        t-on-click="onClick"
        t-on-contextmenu.prevent.stop="(ev) => !env.model.getters.isReadonly() and this.onContextMenu(ev)"
        t-ref="figure"
        t-att-style="props.style"
        t-att-data-id="props.figureUI.id"
        tabindex="0"
        t-on-keydown="(ev) => this.onKeyDown(ev)"
        t-on-keyup.stop="">
        <t
          t-component="figureRegistry.get(props.figureUI.tag).Component"
          t-key="props.figureUI.id"
          figureUI="props.figureUI"
          editFigureStyle.bind="editWrapperStyle"
          openContextMenu.bind="openContextMenu"
        />
        <div class="o-figure-menu position-absolute m-2" t-if="!env.isDashboard()">
          <div
            class="o-figure-menu-item d-flex-align-items-center"
            t-if="!env.model.getters.isReadonly() and props.figureUI.tag !== 'carousel'"
            t-on-click="showMenu"
            t-ref="menuButton"
            t-on-contextmenu.prevent.stop="showMenu">
            <t t-call="o-spreadsheet-Icon.LIST"/>
          </div>
          <MenuPopover
            t-if="menuState.isOpen"
            anchorRect="menuState.anchorRect"
            menuItems="menuState.menuItems"
            onClose="() => this.menuState.isOpen=false"
          />
        </div>
        <div t-if="!env.isDashboard()" class="position-absolute top-0 start-0 pe-none w-100 h-100">
          <div
            class="o-figure-border pe-auto w-100 h-0 position-absolute pb-2"
            t-att-class="{'o-selected': isSelected}"
            t-att-style="getBorderStyle('top')"
          />
          <div
            class="o-figure-border pe-auto h-100 position-absolute start-0 ps-2"
            t-att-class="{'o-selected': isSelected}"
            t-att-style="getBorderStyle('left')"
          />
          <div
            class="o-figure-border pe-auto w-100 position-absolute bottom-0 pt-2"
            t-att-class="{'o-selected': isSelected}"
            t-att-style="getBorderStyle('bottom')"
          />
          <div
            class="o-figure-border pe-auto h-100 position-absolute end-0 pe-2"
            t-att-class="{'o-selected': isSelected}"
            t-att-style="getBorderStyle('right')"
          />
        </div>
      </div>
      <t t-if="isSelected and !env.isMobile()">
        <div
          class="o-fig-anchor o-top pe-auto"
          t-att-style="this.getResizerPosition('top')"
          t-on-pointerdown="(ev) => this.clickAnchor(0,-1, ev)"
        />
        <div
          class="o-fig-anchor o-topRight pe-auto"
          t-att-style="this.getResizerPosition('top right')"
          t-on-pointerdown="(ev) => this.clickAnchor(1,-1, ev)"
        />
        <div
          class="o-fig-anchor o-right pe-auto"
          t-att-style="this.getResizerPosition('right')"
          t-on-pointerdown="(ev) => this.clickAnchor(1,0, ev)"
        />
        <div
          class="o-fig-anchor o-bottomRight pe-auto"
          t-att-style="this.getResizerPosition('bottom right')"
          t-on-pointerdown="(ev) => this.clickAnchor(1,1, ev)"
        />
        <div
          class="o-fig-anchor o-bottom pe-auto"
          t-att-style="this.getResizerPosition('bottom')"
          t-on-pointerdown="(ev) => this.clickAnchor(0,1, ev)"
        />
        <div
          class="o-fig-anchor o-bottomLeft pe-auto"
          t-att-style="this.getResizerPosition('bottom left')"
          t-on-pointerdown="(ev) => this.clickAnchor(-1,1, ev)"
        />
        <div
          class="o-fig-anchor o-left pe-auto"
          t-att-style="this.getResizerPosition('left')"
          t-on-pointerdown="(ev) => this.clickAnchor(-1,0, ev)"
        />
        <div
          class="o-fig-anchor o-topLeft pe-auto"
          t-att-style="this.getResizerPosition('top left')"
          t-on-pointerdown="(ev) => this.clickAnchor(-1,-1, ev)"
        />
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-ScorecardChart">
    <canvas
      class="o-figure-canvas o-scorecard w-100 h-100 d-block"
      t-ref="chartContainer"
      t-att-title="title"
    />
  </t>

  <t t-name="o-spreadsheet-GaugeChartComponent">
    <canvas class="o-figure-canvas o-gauge-chart w-100 h-100 d-block" t-ref="chartContainer"/>
  </t>

  <t t-name="o-spreadsheet-ChartDashboardMenu">
    <div class="o-dashboard-chart-select position-absolute top-0 end-0" t-on-click.stop="">
      <div class="d-flex align-items-center gap-1 p-1 rounded" t-att-style="backgroundColor">
        <t t-foreach="getMenuItems()" t-as="item" t-key="item.id">
          <div
            t-attf-class=" {{item.class}}"
            class="o-chart-dashboard-item btn border-0 lh-1 p-1 d-flex align-items-center justify-content-center"
            t-att-title="item.label"
            t-on-click="item.onClick"
            t-att-data-id="item.id">
            <t t-if="item.preview" t-call="{{item.preview}}"/>
          </div>
        </t>
        <button
          class="o-chart-dashboard-item btn text-muted lh-1 p-1 fa fa-ellipsis-v"
          t-on-click="openContextMenu"
        />
      </div>
      <MenuPopover
        t-if="menuState.isOpen"
        anchorRect="menuState.anchorRect"
        menuItems="menuState.menuItems"
        onClose="() => this.menuState.isOpen=false"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-ChartJsComponent">
    <canvas class="o-figure-canvas w-100 h-100" t-att-style="canvasStyle" t-ref="graphContainer"/>
  </t>

  <t t-name="o-spreadsheet-ZoomableChartJsComponent">
    <div class="w-100 h-100" t-att-style="canvasStyle">
      <div t-att-style="containerStyle">
        <canvas class="o-figure-canvas w-100 h-100" t-ref="graphContainer"/>
      </div>
      <div
        t-if="sliceable"
        class="o-master-chart-container m-0"
        t-att-style="masterChartContainerStyle">
        <canvas
          class="o-figure-canvas o-master-chart-canvas w-100 h-100"
          t-ref="masterChartCanvas"
          t-on-dblclick="onMasterChartDoubleClick"
          t-on-pointerdown="onMasterChartPointerDown"
          t-on-pointermove="onMasterChartPointerMove"
          t-on-mouseleave="onMasterChartMouseLeave"
        />
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-ErrorToolTip">
    <div class="o-error-tooltip bg-white">
      <t t-if="evaluationError">
        <div class="o-error-tooltip-title fw-bold text-danger">Error</div>
        <div class="o-error-tooltip-message">
          <t t-esc="evaluationError.message"/>
          <div class="fst-italic" t-if="errorOriginPositionString">
            Caused by
            <span
              t-esc="errorOriginPositionString"
              class="o-button-link"
              t-on-click="selectCell"
              title="Click to select the cell"
            />
          </div>
        </div>
      </t>
      <t t-if="dataValidationErrorMessage">
        <div class="o-error-tooltip-title fw-bold text-danger">Invalid</div>
        <div class="o-error-tooltip-message">
          <t t-esc="dataValidationErrorMessage"/>
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-SpreadsheetDashboard">
    <div class="o-grid o-two-columns" t-ref="dashboard" tabindex="-1" t-on-wheel="onMouseWheel">
      <div class="mx-auto h-100 position-relative" t-ref="grid" t-att-style="gridContainer">
        <GridOverlay
          onGridResized.bind="onGridResized"
          onGridMoved.bind="moveCanvas"
          gridOverlayDimensions="gridOverlayDimensions">
          <div
            t-foreach="getClickableCells()"
            t-as="clickableCell"
            t-key="clickableCell_index"
            class="o-dashboard-clickable-cell"
            t-att-title="clickableCell.title"
            t-on-click="(ev) => this.selectClickableCell(ev, clickableCell)"
            t-on-auxclick="(ev) => this.selectClickableCell(ev, clickableCell)"
            t-on-contextmenu.prevent=""
            t-att-style="getCellClickableStyle(clickableCell.coordinates)">
            <t
              t-if="clickableCell.component"
              t-component="clickableCell.component"
              t-props="clickableCell.componentProps"
            />
          </div>
        </GridOverlay>
        <canvas t-ref="canvas"/>
        <GridPopover
          gridRect="getGridRect()"
          onMouseWheel.bind="onMouseWheel"
          onClosePopover.bind="onClosePopover"
        />
      </div>
      <VerticalScrollBar/>
      <HorizontalScrollBar/>
      <div class="o-scrollbar corner"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-ClickableCellSortIcon">
    <div class="w-100 h-100 d-flex flex-column align-items-end" t-att-class="verticalJustifyClass">
      <span
        t-if="props.sortDirection === 'none'"
        class="o-icon sorting-icon pb-1"
        t-att-style="style">
        <i class="fa fa-small fa-sort"/>
      </span>
    </div>
  </t>

  <t t-name="o-spreadsheet-TopBarComposer">
    <div class="o-topbar-composer-container w-100">
      <div
        class="o-topbar-composer position-relative bg-white user-select-text d-flex border"
        t-att-class="{
          'o-topbar-composer-readonly': env.model.getters.isReadonly(),
          'o-topbar-composer-active': focus !== 'inactive',
          'o-topbar-composer-inactive': focus === 'inactive',
        }"
        t-on-click.stop="">
        <Composer
          focus="focus"
          inputStyle="composerStyle"
          onComposerContentFocused.bind="onFocus"
          composerStore="composerStore"
          placeholder="composerStore.placeholder"
        />
        <span t-if="showFxIcon" class="position-absolute top-50 translate-middle-y ps-2 pe-none">
          <t t-call="o-spreadsheet-Icon.FX_SVG"/>
        </span>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-StandaloneComposer">
    <div
      class="o-standalone-composer border-bottom"
      t-on-click.stop=""
      t-att-class="containerClass"
      t-att-title="props.title">
      <Composer
        focus="focus"
        inputStyle="composerStyle"
        onComposerContentFocused.bind="onFocus"
        composerStore="standaloneComposerStore"
        placeholder="props.placeholder"
        delimitation="spreadsheetRect"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-SpeechBubble">
    <t t-portal="'.o-spreadsheet'">
      <div class="o-speech-bubble position-absolute px-3 border" t-ref="bubble">
        <div class="o-speech-content text-truncate pb-1" t-esc="props.content"/>
      </div>
    </t>
  </t>

  <t t-name="o-spreadsheet-GridComposer">
    <div
      class="o-cell-reference rounded"
      t-if="shouldDisplayCellReference"
      t-att-style="cellReferenceStyle"
      t-esc="cellReference"
    />
    <div class="o-grid-composer" t-att-style="containerStyle" t-ref="gridComposer">
      <Composer t-props="composerProps"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-FunctionDescriptionProvider">
    <div
      class="o-formula-assistant-container shadow"
      tabindex="-1"
      t-on-pointerdown=""
      t-on-pointerup.stop=""
      t-on-keydown.stop=""
      t-on-click.stop="">
      <t t-set="context" t-value="getContext()"/>
      <div class="o-formula-assistant bg-white" t-if="context.functionDescription.name">
        <div class="o-formula-assistant-head d-flex flex-row justify-content-between">
          <div>
            <t t-foreach="formulaHeaderContent" t-as="part" t-key="part_index">
              <span
                t-esc="part.content"
                t-att-class="part.focused ? 'o-formula-assistant-focus' : ''"
              />
            </t>
          </div>
          <div
            class="collapsor px-2 d-flex align-items-center rounded"
            t-att-class="state.isCollapsed ? 'collapsed' : ''"
            t-on-pointerdown.prevent=""
            t-on-click="() => this.toggle()">
            <span class="collapsor-arrow d-inline-block">
              <t t-call="o-spreadsheet-Icon.ANGLE_DOWN"/>
            </span>
          </div>
        </div>

        <Collapse isCollapsed="state.isCollapsed">
          <div class="o-formula-assistant-core pb-3 m-3 border-bottom">
            <div class="o-formula-assistant-gray">ABOUT</div>
            <div t-esc="context.functionDescription.description"/>
          </div>

          <t
            t-set="firstRepeatableGroupOptional"
            t-value="context.functionDescription.args.some(arg => arg.repeating and arg.optional)"
          />

          <t t-foreach="context.functionDescription.args" t-as="arg" t-key="arg.name">
            <div
              class="o-formula-assistant-arg p-3 pt-0 display-flex flex-column"
              t-att-class="{'o-formula-assistant-gray': context.argsToFocus.length > 0}">
              <div
                t-att-class="{'o-formula-assistant-focus': context.argsToFocus.includes(arg_index)}">
                <span t-if="arg.repeating">
                  <span t-esc="arg.name + (context.repeatingArgGroupIndex + 1)"/>
                </span>
                <span t-else="">
                  <span t-esc="arg.name"/>
                </span>
                <span
                  t-if="arg.optional || arg.default || (arg.repeating and (firstRepeatableGroupOptional or context.repeatingArgGroupIndex > 0))">&#xA0;- [optional]&#xA0;</span>
                <span t-if="arg.default">
                  <span>default:&#xA0;</span>
                  <t t-esc="arg.defaultValue"/>
                </span>
              </div>
              <div class="o-formula-assistant-arg-description" t-esc="arg.description"/>
            </div>
          </t>
        </Collapse>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-Composer">
    <div class="o-composer-container w-100 h-100" t-ref="composerContainer">
      <t t-set="autoCompleteProposals" t-value="props.composerStore.autoCompleteProposals"/>
      <t t-set="canBeToggled" t-value="props.composerStore.canBeToggled"/>
      <t
        t-set="assistantIsAvailable"
        t-value="props.showAssistant and (autoCompleteProposals.length or functionDescriptionState.showDescription)"
      />
      <div class="d-flex flex-row position-relative">
        <span
          t-if="props.focus !== 'inactive' and assistantIsAvailable and canBeToggled and assistant.forcedClosed"
          role="button"
          title="Show formula help"
          t-on-click.stop="openAssistant"
          t-on-pointerdown.prevent.stop=""
          t-on-pointerup.stop=""
          class="fa-stack position-absolute translate-middle force-open-assistant fs-4">
          <i class="fa fa-circle fa-stack-1x fa-inverse"/>
          <i class="fa fa-question-circle fa-stack-1x"/>
        </span>
        <div
          class="o-composer w-100 text-start"
          t-att-class="{ 'text-muted': env.model.getters.isReadonly(), 'active': props.focus !== 'inactive' }"
          t-att-style="props.inputStyle"
          t-ref="o_composer"
          tabindex="1"
          t-att-contenteditable="env.model.getters.isReadonly() ? 'false' : 'plaintext-only'"
          t-att-placeHolder="props.placeholder"
          t-att-inputmode="props.inputMode"
          spellcheck="false"
          t-on-keydown="onKeydown"
          t-on-mousewheel.stop=""
          t-on-input="onInput"
          t-on-pointerdown="onMousedown"
          t-on-pointerup="onMouseup"
          t-on-click="onClick"
          t-on-keyup="onKeyup"
          t-on-paste="onPaste"
          t-on-compositionstart="onCompositionStart"
          t-on-compositionend="onCompositionEnd"
          t-on-dblclick="onDblClick"
          t-on-contextmenu="onContextMenu"
          t-on-blur="onBlur"
          t-on-wheel="onWheel"
        />
      </div>
      <div
        class="o-composer-assistant-container shadow position-absolute z-1"
        t-att-style="assistantContainerStyle"
        t-if="props.focus !== 'inactive' and assistantIsAvailable and !(canBeToggled and assistant.forcedClosed)"
        t-on-wheel.stop=""
        t-on-pointerdown.stop=""
        t-on-pointerup.stop=""
        t-on-click.stop="">
        <span
          t-if="canBeToggled and !assistant.forcedClosed"
          role="button"
          t-on-click="closeAssistant"
          t-on-pointerdown.prevent.stop=""
          class="fa-stack position-absolute top-0 start-100 translate-middle fs-4">
          <i class="fa fa-circle fa-stack-1x fa-inverse"/>
          <i class="fa fa-times-circle fa-stack-1x"/>
        </span>
        <div class="o-composer-assistant overflow-auto" t-att-style="assistantStyle">
          <FunctionDescriptionProvider
            t-if="functionDescriptionState.showDescription"
            functionDescription="functionDescriptionState.functionDescription"
            argsToFocus="functionDescriptionState.argsToFocus"
            repeatingArgGroupIndex="functionDescriptionState.repeatingArgGroupIndex"
          />
          <div
            t-if="functionDescriptionState.showDescription and autoCompleteProposals.length"
            class="border-top"
          />
          <TextValueProvider
            t-if="autoCompleteProposals.length"
            proposals="autoCompleteProposals"
            selectedIndex="props.composerStore.autoCompleteSelectedIndex"
            onValueSelected.bind="this.autoComplete"
            onValueHovered.bind="props.composerStore.selectAutoCompleteIndex"
          />
        </div>
      </div>
      <SpeechBubble
        t-if="displaySpeechBubble"
        content="props.composerStore.hoveredContentEvaluation"
        anchorRect="composerState.hoveredRect"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-TextValueProvider">
    <div
      t-ref="autoCompleteList"
      t-on-pointerdown.prevent=""
      t-att-class="{
          'o-autocomplete-dropdown bg-white': props.proposals.length}">
      <t t-foreach="props.proposals" t-as="proposal" t-key="proposal.text + proposal_index">
        <div
          class="d-flex flex-column text-start"
          t-att-class="{'o-autocomplete-value-focus': props.selectedIndex === proposal_index}"
          t-on-click="() => this.props.onValueSelected(proposal.text)"
          t-on-pointermove="() => this.props.onValueHovered(proposal_index)">
          <div class="o-autocomplete-value text-truncate">
            <t t-set="htmlContent" t-value="proposal.htmlContent || [{ value: proposal.text}]"/>
            <span
              t-foreach="htmlContent"
              t-as="content"
              t-key="content_index"
              t-att-class="content.classes?.join(' ')"
              t-att-style="getCss(content)"
              t-esc="content.value"
            />
          </div>
          <div
            class="o-autocomplete-description text-truncate"
            t-esc="proposal.description"
            t-if="props.selectedIndex === proposal_index || proposal.alwaysExpanded"
          />
        </div>
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-ColorPickerWidget">
    <div class="o-color-picker-widget">
      <span
        class="o-color-picker-button"
        t-ref="colorPickerButton"
        t-on-click.stop="props.toggleColorPicker"
        t-att-title="props.title"
        t-att-class="props.class ? props.class : 'o-color-picker-button-style'"
        t-att-disabled="props.disabled">
        <span t-att-style="iconStyle">
          <t t-call="{{props.icon}}"/>
        </span>
      </span>
      <ColorPicker
        t-if="props.showColorPicker"
        anchorRect="colorPickerAnchorRect"
        onColorPicked="props.onColorPicked"
        currentColor="props.currentColor"
        maxHeight="props.dropdownMaxHeight"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-ColorPicker">
    <Popover t-props="popoverProps">
      <div class="o-color-picker bg-white" t-on-click.stop="" t-att-style="colorPickerStyle">
        <div class="o-color-picker-section-name">Standard</div>
        <div class="colors-grid">
          <div
            t-foreach="COLORS"
            t-as="color"
            t-key="color"
            class="o-color-picker-line-item"
            t-att-data-color="color"
            t-on-click="() => this.onColorClick(color)"
            t-attf-style="background-color:{{color}};">
            <div
              t-if="isSameColor(props.currentColor, color)"
              align="center"
              t-attf-style="color:{{checkmarkColor}}">
              ✓
            </div>
          </div>
        </div>
        <div class="o-separator border-bottom"/>
        <div
          class="o-color-picker-section-name o-color-picker-toggler"
          t-on-click="toggleColorPicker">
          <span>Custom</span>
        </div>
        <div class="colors-grid o-color-picker-toggler" t-on-click.stop="toggleColorPicker">
          <div class="o-color-picker-line-item bg-white o-color-picker-toggler-button">
            <div class="o-color-picker-toggler-sign">
              <t t-call="o-spreadsheet-Icon.PLUS"/>
            </div>
          </div>
          <div
            t-foreach="env.model.getters.getCustomColors()"
            t-as="color"
            t-key="color"
            class="o-color-picker-line-item"
            t-att-data-color="color"
            t-attf-style="background-color:{{color}};"
            t-on-click="() => this.onColorClick(color)">
            <div
              t-if="isSameColor(props.currentColor, color)"
              align="center"
              t-attf-style="color:{{checkmarkColor}}">
              ✓
            </div>
          </div>
        </div>
        <div t-if="state.showGradient" class="o-custom-selector">
          <div
            class="o-gradient"
            t-on-click.stop=""
            t-on-pointerdown="dragGradientPointer"
            t-att-style="gradientHueStyle">
            <div class="saturation w-100 h-100 position-absolute pe-none"/>
            <div class="lightness w-100 h-100 position-absolute pe-none"/>
            <div class="magnifier pe-none" t-att-style="pointerStyle"/>
          </div>
          <div class="o-hue-container" t-on-pointerdown="dragHuePointer">
            <div class="o-hue-picker border rounded" t-on-click.stop=""/>
            <div class="o-hue-slider pe-none" t-att-style="sliderStyle">
              <t t-call="o-spreadsheet-Icon.CARET_UP"/>
            </div>
          </div>
          <div class="o-custom-input-preview">
            <input
              type="text"
              class="border rounded"
              t-att-class="{'o-wrong-color': !isHexColorInputValid }"
              t-on-click.stop=""
              t-att-value="state.customHexColor"
              t-on-input="setHexColor"
            />
            <div class="o-color-preview border rounded" t-att-style="colorPreviewStyle"/>
          </div>
          <div class="o-custom-input-buttons">
            <button
              class="o-add-button border rounded"
              t-att-class="{'o-disabled': !state.customHexColor or !isHexColorInputValid}"
              t-on-click.stop="addCustomColor">
              Add
            </button>
          </div>
        </div>
        <t t-if="!props.disableNoColor">
          <div class="o-separator border-bottom"/>
          <div class="o-buttons">
            <button t-on-click="resetColor" class="o-cancel border rounded">No Color</button>
          </div>
        </t>
      </div>
    </Popover>
  </t>

  <t t-name="o-spreadsheet-ClientTag">
    <div t-if="props.active" class="o-client-tag" t-att-style="tagStyle" t-esc="props.name"/>
  </t>

  <t t-name="o-spreadsheet-BottomBar">
    <div
      class="o-spreadsheet-bottom-bar o-two-columns d-flex flex-fill align-items-center overflow-hidden border-top"
      t-on-click="props.onClick"
      t-ref="bottomBar"
      t-on-contextmenu.prevent="">
      <Ripple class="'add-sheet-container'">
        <div
          class="o-sheet-item o-add-sheet me-2 p-1"
          t-if="!env.model.getters.isReadonly()"
          t-on-click="clickAddSheet">
          <t t-call="o-spreadsheet-Icon.PLUS"/>
        </div>
      </Ripple>
      <Ripple>
        <div
          class="o-sheet-item o-list-sheets me-2 p-1"
          composerFocusableElement="true"
          tabindex="-1"
          t-on-click="clickListSheets">
          <t t-call="o-spreadsheet-Icon.LIST"/>
        </div>
      </Ripple>
      <div class="o-all-sheets position-relative d-flex h-100 flex-fill overflow-hidden">
        <div
          class="o-bottom-bar-fade-in position-absolute h-100 w-100 pe-none"
          t-if="state.isSheetListScrollableLeft"
        />
        <div
          class="o-sheet-list d-flex w-100 px-1"
          t-ref="sheetList"
          t-on-wheel="onWheel"
          t-on-scroll="onScroll">
          <t t-foreach="getVisibleSheets()" t-as="sheet" t-key="sheet.id">
            <BottomBarSheet
              style="getSheetStyle(sheet.id)"
              sheetId="sheet.id"
              openContextMenu="(registry, ev) => this.onSheetContextMenu(sheet.id, registry, ev)"
              onMouseDown="(ev) => this.onSheetMouseDown(sheet.id, ev)"
            />
          </t>
        </div>
        <div
          class="o-bottom-bar-fade-out position-absolute h-100 w-100 pe-none"
          t-if="state.isSheetListScrollableRight"
        />
      </div>
      <t t-if="!env.isSmall">
        <div
          class="o-bottom-bar-arrows d-flex h-100 me-4 align-items-center ms-3"
          t-if="state.isSheetListScrollableLeft || state.isSheetListScrollableRight">
          <Ripple
            ignoreClickPosition="true"
            width="20"
            height="20"
            offsetX="1"
            allowOverflow="true"
            enabled="state.isSheetListScrollableLeft">
            <div
              class="o-bottom-bar-arrow o-bottom-bar-arrow-left d-flex align-items-center"
              t-att-class="{'o-disabled': !state.isSheetListScrollableLeft}"
              t-on-click="onArrowLeft">
              <t t-call="o-spreadsheet-Icon.CARET_LEFT"/>
            </div>
          </Ripple>
          <Ripple
            ignoreClickPosition="true"
            width="20"
            height="20"
            offsetX="-1"
            allowOverflow="true"
            enabled="state.isSheetListScrollableRight">
            <div
              class="o-bottom-bar-arrow o-bottom-bar-arrow-right d-flex align-items-center"
              t-att-class="{'o-disabled': !state.isSheetListScrollableRight}"
              t-on-click="onArrowRight">
              <t t-call="o-spreadsheet-Icon.CARET_RIGHT"/>
            </div>
          </Ripple>
        </div>
        <BottomBarStatistic
          openContextMenu="(x, y, registry) => this.openContextMenu(x, y, 'listSelectionStatistics', registry)"
          closeContextMenu="() => this.closeContextMenuWithId('listSelectionStatistics')"
        />
      </t>

      <MenuPopover
        t-if="menuState.isOpen"
        anchorRect="menuState.anchorRect"
        menuItems="menuState.menuItems"
        maxHeight="menuMaxHeight"
        onClose="() => this.closeMenu()"
        menuId="menuState.menuId"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-BottomBarStatistic">
    <t t-set="selectedStatistic" t-value="getSelectedStatistic()"/>
    <Ripple class="'ms-auto bottom-statistics'" t-if="selectedStatistic !== undefined">
      <div
        class="o-selection-statistic text-truncate user-select-none me-4 bg-white rounded shadow d-flex align-items-center"
        t-on-click="listSelectionStatistics">
        <t t-esc="selectedStatistic"/>
        <span class="ms-2">
          <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
        </span>
      </div>
    </Ripple>
  </t>

  <t t-name="o-spreadsheet-BottomBarSheet">
    <Ripple>
      <div
        class="o-sheet d-flex align-items-center user-select-none text-nowrap border-start border-end"
        tabindex="-1"
        composerFocusableElement="true"
        t-on-pointerdown="(ev) => this.onMouseDown(ev)"
        t-on-click="onClick"
        t-on-contextmenu.prevent="(ev) => this.onContextMenu(ev)"
        t-ref="sheetDiv"
        t-key="sheetName"
        t-att-style="props.style"
        t-att-title="sheetName"
        t-att-data-id="props.sheetId"
        t-att-class="{active: isSheetActive}">
        <span
          class="o-sheet-name"
          t-att-class="{'o-sheet-name-editable': state.isEditing }"
          t-ref="sheetNameSpan"
          t-esc="sheetName"
          t-on-pointerdown="(ev) => this.onMouseEventSheetName(ev)"
          t-on-click="(ev) => this.onMouseEventSheetName(ev)"
          t-on-dblclick="() => this.onDblClick()"
          t-on-focusout="() => this.onFocusOut()"
          t-on-keydown="(ev) => this.onKeyDown(ev)"
          t-att-contenteditable="state.isEditing ? 'plaintext-only': 'false'"
        />
        <span
          class="o-sheet-icon ms-1"
          tabindex="-1"
          t-on-click.stop="(ev) => this.onIconClick(ev)">
          <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
        </span>
        <div
          t-if="sheetColorStyle"
          class="o-sheet-color position-absolute"
          t-att-style="sheetColorStyle"
        />
      </div>
    </Ripple>
    <ColorPicker
      t-if="state.pickerOpened"
      anchorRect="colorPickerAnchorRect"
      onColorPicked.bind="onColorPicked"
      currentColor="props.currentColor"
    />
  </t>

  <t t-name="o-spreadsheet-BorderEditorWidget">
    <div class="d-flex position-relative" title="Borders">
      <span
        t-ref="borderEditorButton"
        t-on-click.stop="toggleBorderEditor"
        t-att-class="props.class ? props.class : ''"
        t-att-disabled="props.disabled">
        <span t-att-style="iconStyle">
          <t t-call="o-spreadsheet-Icon.BORDERS"/>
        </span>
      </span>
      <BorderEditor
        t-if="isActive"
        onBorderColorPicked.bind="onBorderColorPicked"
        onBorderStylePicked.bind="onBorderStylePicked"
        onBorderPositionPicked.bind="onBorderPositionPicked"
        currentBorderColor="state.currentColor"
        currentBorderStyle="state.currentStyle"
        currentBorderPosition="state.currentPosition"
        maxHeight="dropdownMaxHeight"
        anchorRect="borderEditorAnchorRect"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-BorderEditor">
    <t t-set="border_color">Border Color</t>
    <Popover t-props="popoverProps">
      <div
        class="d-flex o-border-selector bg-white"
        t-on-click.stop=""
        t-att-class="props.class ? props.class : ''">
        <div class="o-border-selector-section">
          <div
            t-foreach="BORDER_POSITIONS"
            t-as="borderPositionsRow"
            t-key="borderPositionsRow"
            class="d-flex o-dropdown-button o-dropdown-line">
            <span
              t-foreach="borderPositionsRow"
              t-as="borderPosition"
              t-key="borderPosition"
              class="o-line-item o-hoverable-button"
              t-att-class="{active:props.currentBorderPosition === borderPosition[0]}"
              t-att-name="borderPosition[0]"
              t-on-click.stop="() => this.setBorderPosition(borderPosition[0])">
              <t t-call="{{borderPosition[1]}}"/>
            </span>
          </div>
        </div>
        <div class="o-divider border-end"/>
        <div class="o-border-selector-section">
          <div
            class="m-0 p-0 d-flex align-items-center justify-content-center o-with-color o-hoverable-button"
            title="Border color"
            t-on-click.stop="(ev) => this.toggleDropdownTool('borderColorTool')">
            <ColorPickerWidget
              currentColor="props.currentBorderColor"
              toggleColorPicker="(ev) => this.toggleDropdownTool('borderColorTool')"
              showColorPicker="state.activeTool === 'borderColorTool'"
              onColorPicked="(color) => this.setBorderColor(color)"
              title="border_color"
              icon="props.currentBorderColor === '' ? 'o-spreadsheet-Icon.BORDER_NO_COLOR' : 'o-spreadsheet-Icon.BORDER_COLOR'"
              dropdownMaxHeight="this.props.dropdownMaxHeight"
              class="'o-dropdown-button o-border-picker-button'"
            />
            <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
          </div>
          <div
            class="o-border-style-tool d-flex align-items-center justify-content-center o-hoverable-button"
            title="Line style"
            t-ref="lineStyleButton"
            t-on-click.stop="(ev) => this.toggleDropdownTool('borderTypeTool')">
            <t t-call="o-spreadsheet-Icon.BORDER_TYPE"/>
            <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
            <Popover
              t-props="lineStylePickerPopoverProps"
              t-if="state.activeTool === 'borderTypeTool'">
              <div class="o-border-style-dropdown bg-white">
                <t t-foreach="borderStyles" t-as="borderStyle" t-key="borderStyle">
                  <div
                    t-att-title="borderStyle"
                    t-on-click.stop="() => this.setBorderStyle(borderStyle)">
                    <div class="d-flex o-dropdown-border-type">
                      <div class="o-dropdown-border-check">
                        <t
                          t-if="props.currentBorderStyle === borderStyle"
                          t-call="o-spreadsheet-Icon.CHECK"
                        />
                      </div>
                      <div t-attf-class="o-style-preview o-style-{{borderStyle}}"/>
                    </div>
                  </div>
                </t>
              </div>
            </Popover>
          </div>
        </div>
      </div>
    </Popover>
  </t>

  <t t-name="o-spreadsheet-Autofill">
    <div class="o-autofill" t-att-style="style"/>
    <div
      class="o-autofill-handler"
      t-att-style="handlerStyle"
      t-on-pointerdown="onMouseDown"
      t-on-dblclick="onDblClick"
    />
    <t t-set="tooltip" t-value="getTooltip()"/>
    <div t-if="tooltip" class="o-autofill-nextvalue" t-att-style="styleNextValue">
      <t t-component="tooltip.component" t-props="tooltip.props"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-Ripple">
    <div
      class="o-ripple-container position-relative"
      t-att-class="props.class"
      t-on-click="onClick">
      <div class="position-absolute w-100 h-100">
        <t t-foreach="state.ripples" t-as="ripple" t-key="ripple.id">
          <RippleEffect t-props="getRippleEffectProps(ripple.id)"/>
        </t>
      </div>
      <div class="position-relative" t-ref="childContainer">
        <t t-slot="default"/>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-RippleEffect">
    <div
      class="position-absolute"
      t-att-class="{ 'overflow-hidden': !props.allowOverflow }"
      t-att-style="props.style">
      <div class="o-ripple position-relative pe-none" t-ref="ripple" t-att-style="rippleStyle"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-ActionButton">
    <span
      t-if="isVisible"
      class="o-menu-item-button"
      t-att-title="title"
      t-att-class="{'o-disabled': !isEnabled, active: isActive}"
      t-attf-class="{{props.class}}"
      t-on-click="onClick">
      <span t-if="iconTitle" t-att-style="buttonStyle">
        <t t-call="{{iconTitle}}"/>
      </span>
      <t t-if="props.hasTriangleDownIcon">
        <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
      </t>
    </span>
  </t>
</odoo>
