<!--
 This file is generated by o-spreadsheet build tools. Do not edit it.
 @see https://github.com/odoo/o-spreadsheet
 @version 18.2.6
 @date 2025-04-04T08:42:06.055Z
 @hash faa00e2
-->
<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">
    <t t-set="text_color">Text Color</t>
    <t t-set="fill_color">Fill Color</t>
    <div
      class="o-spreadsheet-topbar o-two-columns d-flex flex-column user-select-none"
      t-on-click="props.onClick">
      <div class="o-topbar-top d-flex justify-content-between">
        <!-- 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 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">
        <div class="o-topbar-toolbar d-flex flex-shrink-0">
          <!-- 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 flex-shrink-0 ms-4">
            <ActionButton action="EDIT.undo" class="'o-hoverable-button'"/>
            <ActionButton action="EDIT.redo" class="'o-hoverable-button'"/>
            <PaintFormatButton class="'o-hoverable-button'"/>
            <ActionButton action="FORMAT.clearFormat" class="'o-hoverable-button'"/>

            <div class="o-divider"/>

            <ActionButton action="FORMAT.formatPercent" class="'o-hoverable-button'"/>
            <ActionButton action="FORMAT.decraseDecimalPlaces" class="'o-hoverable-button'"/>
            <ActionButton action="FORMAT.incraseDecimalPlaces" class="'o-hoverable-button'"/>
            <ActionButton
              action="formatNumberMenuItemSpec"
              onClick="(ev) => this.toggleToolbarContextMenu(formatNumberMenuItemSpec, ev)"
              hasTriangleDownIcon="true"
              class="'o-hoverable-button'"
            />

            <div class="o-divider"/>
            <FontSizeEditor
              currentFontSize="currentFontSize"
              onFontSizeChanged.bind="this.setFontSize"
              class="'o-hoverable-button'"
              onToggle.bind="this.onClick"
            />
            <div class="o-divider"/>

            <ActionButton action="FORMAT.formatBold" class="'o-hoverable-button'"/>
            <ActionButton action="FORMAT.formatItalic" class="'o-hoverable-button'"/>
            <ActionButton action="FORMAT.formatStrikethrough" class="'o-hoverable-button'"/>

            <ColorPickerWidget
              currentColor="state.textColor"
              toggleColorPicker="(ev) => this.toggleDropdownTool('textColorTool', ev)"
              showColorPicker="state.activeTool === 'textColorTool'"
              onColorPicked="(color) => this.setColor('textColor', color)"
              title="text_color"
              icon="'o-spreadsheet-Icon.TEXT_COLOR'"
              dropdownMaxHeight="this.props.dropdownMaxHeight"
              class="'o-hoverable-button o-menu-item-button'"
            />

            <div class="o-divider"/>

            <ColorPickerWidget
              currentColor="state.fillColor"
              toggleColorPicker="(ev) => this.toggleDropdownTool('fillColorTool', ev)"
              showColorPicker="state.activeTool === 'fillColorTool'"
              onColorPicked="(color) => this.setColor('fillColor', color)"
              title="fill_color"
              icon="'o-spreadsheet-Icon.FILL_COLOR'"
              dropdownMaxHeight="this.props.dropdownMaxHeight"
              class="'o-hoverable-button o-menu-item-button'"
            />

            <BorderEditorWidget
              class="'o-hoverable-button o-menu-item-button'"
              toggleBorderEditor="(ev) => this.toggleDropdownTool('borderTool', ev)"
              showBorderEditor="state.activeTool === 'borderTool'"
              dropdownMaxHeight="this.props.dropdownMaxHeight"
            />
            <ActionButton action="EDIT.mergeCells" class="'o-hoverable-button'"/>
            <div class="o-divider"/>

            <div class="o-dropdown">
              <ActionButton
                action="FORMAT.formatAlignmentHorizontal"
                hasTriangleDownIcon="true"
                t-on-click="(ev) => this.toggleDropdownTool('horizontalAlignTool', ev)"
                class="'o-hoverable-button'"
              />
              <div
                class="o-dropdown-content"
                t-if="state.activeTool === 'horizontalAlignTool'"
                t-att-style="dropdownStyle"
                t-on-click.stop="">
                <div class="o-dropdown-line">
                  <ActionButton action="FORMAT.formatAlignmentLeft" class="'o-hoverable-button'"/>
                  <ActionButton action="FORMAT.formatAlignmentCenter" class="'o-hoverable-button'"/>
                  <ActionButton action="FORMAT.formatAlignmentRight" class="'o-hoverable-button'"/>
                </div>
              </div>
            </div>
            <div class="o-dropdown">
              <ActionButton
                action="FORMAT.formatAlignmentVertical"
                hasTriangleDownIcon="true"
                t-on-click="(ev) => this.toggleDropdownTool('verticalAlignTool', ev)"
                class="'o-hoverable-button'"
              />
              <div
                class="o-dropdown-content"
                t-att-style="dropdownStyle"
                t-if="state.activeTool === 'verticalAlignTool'"
                t-on-click.stop="">
                <div class="o-dropdown-line">
                  <ActionButton action="FORMAT.formatAlignmentTop" class="'o-hoverable-button'"/>
                  <ActionButton action="FORMAT.formatAlignmentMiddle" class="'o-hoverable-button'"/>
                  <ActionButton action="FORMAT.formatAlignmentBottom" class="'o-hoverable-button'"/>
                </div>
              </div>
            </div>
            <div class="o-dropdown">
              <ActionButton
                action="FORMAT.formatWrapping"
                hasTriangleDownIcon="true"
                t-on-click="(ev) => this.toggleDropdownTool('textWrappingTool', ev)"
                class="'o-hoverable-button'"
              />
              <div
                class="o-dropdown-content"
                t-att-style="dropdownStyle"
                t-if="state.activeTool === 'textWrappingTool'"
                t-on-click.stop="">
                <div class="o-dropdown-line">
                  <ActionButton
                    action="FORMAT.formatWrappingOverflow"
                    class="'o-hoverable-button'"
                  />
                  <ActionButton action="FORMAT.formatWrappingWrap" class="'o-hoverable-button'"/>
                  <ActionButton action="FORMAT.formatWrappingClip" class="'o-hoverable-button'"/>
                </div>
              </div>
            </div>

            <div class="o-divider"/>

            <TableDropdownButton/>
            <ActionButton action="DATA.createRemoveFilterTool" class="'o-hoverable-button'"/>
          </div>
        </div>
        <TopBarComposer/>
      </div>
      <div
        t-if="this.fingerprints.isEnabled"
        class="irregularity-map d-flex align-items-center justify-content-between">
        <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 align-items-center rounded-0 alert alert-info ps-0 py-0 my-0">
          This tool analyzes formulas for patterns and highlights
          inconsistencies. Irregularities may indicate potential errors in formula
          structures, references or arguments.
          <div class="btn btn-link align-self-end" t-on-click="() => this.fingerprints.disable()">
            Turn off
          </div>
        </div>
      </div>
    </div>
    <Menu
      t-if="state.menuState.isOpen"
      position="state.menuState.position"
      menuItems="state.menuState.menuItems"
      onClose="() => this.closeMenus()"
      onMenuClicked="() => this.props.onClick()"
    />
  </t>

  <div t-name="o-spreadsheet-TextInput" class="w-100">
    <input
      t-ref="input"
      class="os-input w-100"
      type="text"
      t-att-class="props.class"
      t-att-id="props.id"
      t-att-placeholder="props.placeholder"
      t-att-value="props.value"
      t-on-change="save"
      t-on-blur="save"
      t-on-pointerdown="onMouseDown"
      t-on-pointerup="onMouseUp"
      t-on-keydown="onKeyDown"
    />
  </div>

  <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"
        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"
            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"
        t-if="isStyleEditable"
        t-on-click="this.editTableStyle"
        title="Edit custom table style">
        <t t-call="o-spreadsheet-Icon.EDIT"/>
      </div>
    </div>
    <Menu
      t-if="menu.isOpen"
      menuItems="menu.menuItems"
      position="menu.position"
      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">
      <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"
        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">
      <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-ref="spreadsheet" t-att-style="getStyle()">
      <t t-if="env.isDashboard()">
        <SpreadsheetDashboard/>
      </t>
      <t t-else="">
        <TopBar onClick="() => this.focusGrid()" dropdownMaxHeight="gridHeight"/>
        <div
          class="o-grid-container"
          t-att-class="{'o-two-columns': !sidePanel.isOpen}"
          t-att-style="gridContainerStyle"
          t-on-click="this.focusGrid">
          <div class="o-top-left"/>
          <div class="o-column-groups">
            <HeaderGroupContainer layers="colLayers" dimension="'COL'"/>
          </div>
          <div class="o-row-groups">
            <HeaderGroupContainer layers="rowLayers" dimension="'ROW'"/>
          </div>
          <div class="o-group-grid overflow-hidden">
            <Grid exposeFocus="(focus) => this._focusGrid = focus"/>
          </div>
        </div>
        <SidePanel/>
        <BottomBar onClick="() => this.focusGrid()"/>
      </t>
    </div>
  </t>

  <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"
              />
              <input
                t-if="tableConfig.numberOfHeaders > 0"
                t-att-value="tableConfig.numberOfHeaders"
                type="number"
                class="o-table-n-of-headers ms-2 o-input"
                t-on-change="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-SidePanel">
    <div class="o-sidePanel" t-if="sidePanelStore.isOpen">
      <div class="o-sidePanelHeader">
        <div class="o-sidePanelTitle o-fw-bold" t-esc="getTitle()"/>
        <div class="o-sidePanelClose" t-on-click="close">✕</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="startHandleDrag"
            t-on-dblclick="sidePanelStore.resetPanelSize">
            <t t-call="o-spreadsheet-Icon.THIN_DRAG_HANDLE"/>
          </div>
        </div>
        <div class="o-sidePanelBody">
          <t
            t-component="panel.Body"
            t-props="sidePanelStore.panelProps"
            onCloseSidePanel.bind="close"
            t-key="'Body_' + sidePanelStore.componentTag + sidePanelStore.panelKey"
          />
        </div>
        <div class="o-sidePanelFooter" t-if="panel?.Footer">
          <t
            t-component="panel.Footer"
            t-props="sidePanelStore.panelProps"
            t-key="'Footer_' + sidePanelStore.componentTag"
          />
        </div>
      </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">
          <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">This setting affects 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>
    <Menu
      t-if="state.isMenuOpen"
      menuItems="props.menuItems"
      position="menuPosition"
      onClose.bind="onMenuClosed"
      menuId="menuId"
    />
  </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"/>
    </Section>
  </t>

  <t t-name="o-spreadsheet-PivotSidePanel">
    <t t-component="sidePanelEditor" t-props="props"/>
  </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"
      t-att="isReadonly ? ['inert', 1] : []"
      t-att-class="{ 'pe-none': isReadonly, 'opacity-50': isReadonly }">
      <div class="h-100 position-relative overflow-x-hidden overflow-y-auto" t-ref="pivotSidePanel">
        <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>
      <PivotDeferUpdate
        deferUpdate="store.updatesAreDeferred"
        toggleDeferUpdate="(value) => store.deferUpdates(value)"
        isDirty="store.isDirty"
        discard="store.discardPendingUpdate"
        apply="store.applyUpdate"
      />
    </div>
  </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"
        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">
        <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">
        <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.nameWithGranularity">
        <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">
            <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"/>
          </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.nameWithGranularity">
        <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">
            <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"/>
          </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">
            <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"
          />
        </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]"
            />
          </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="granularity" t-value="props.dimension.granularity"/>
        <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 === props.dimension.granularity"
            t-att-value="granularity"
            t-esc="periods[granularity]"
            t-att-selected="granularity === props.dimension.granularity or (granularity === 'month' and !props.dimension.granularity)"
          />
        </select>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-PivotDimension">
    <div
      class="py-1 px-2 d-flex flex-column shadow-sm pivot-dimension"
      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'"
          />
          <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">
        <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-MoreFormatsPanel">
    <div class="o-more-formats-panel">
      <div
        t-foreach="dateFormatsActions"
        t-as="action"
        t-key="action.name(env)"
        t-att-data-name="action.name(env)"
        t-on-click="() => action.execute(env)"
        class="w-100 d-flex align-items-center border-bottom format-preview">
        <span class="ms-3 check-icon">
          <t t-if="action.isActive(env)" t-call="o-spreadsheet-Icon.CHECK"/>
        </span>
        <span t-out="action.description(env)"/>
      </div>
    </div>
  </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
            ranges="[this.state.dataRange]"
            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" 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"
          />
        </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-DataValidationValueInRangeCriterionForm">
    <SelectionInput
      ranges="[props.criterion.values[0] || '']"
      onSelectionChanged="(ranges) => this.onRangeChanged(ranges[0])"
      required="true"
      hasSingleRange="true"
    />

    <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 === '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-DataValidationListCriterionForm">
    <t t-foreach="displayedValues" t-as="value" t-key="value_index">
      <div class="o-dv-list-values d-flex align-items-center">
        <DataValidationInput
          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"
        />
        <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 === '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-DataValidationSingleInput">
    <DataValidationInput
      value="props.criterion.values[0]"
      onValueChanged.bind="onValueChanged"
      criterionType="props.criterion.type"
    />
  </t>

  <t t-name="o-spreadsheet-DataValidationInput">
    <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-DataValidationDoubleInput">
    <DataValidationInput
      value="props.criterion.values[0]"
      onValueChanged.bind="onFirstValueChanged"
      criterionType="props.criterion.type"
    />

    <div class="o-section-subtitle ms-1 my-2">and</div>
    <DataValidationInput
      value="props.criterion.values[1]"
      onValueChanged.bind="onSecondValueChanged"
      criterionType="props.criterion.type"
    />
  </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 === props.criterion.dateValue"
      />
    </select>

    <DataValidationInput
      t-if="props.criterion.dateValue === 'exactDate'"
      value="props.criterion.values[0]"
      onValueChanged.bind="onValueChanged"
      criterionType="props.criterion.type"
    />
  </t>

  <t t-name="o-spreadsheet-CustomCurrencyPanel">
    <div class="o-custom-currency">
      <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 === state.selectedCurrencyIndex"
            />
          </t>
        </select>
      </Section>
      <Section>
        <div class="o-subsection-left">
          <div class="o-section-title">Code</div>
          <input
            type="text"
            class="o-input"
            t-model="state.currencyCode"
            placeholder="code"
            t-on-input="(ev) => this.updateCode(ev)"
          />
        </div>
        <div class="o-subsection-right">
          <div class="o-section-title">Symbol</div>
          <input
            type="text"
            class="o-input"
            placeholder="symbol"
            t-model="state.currencySymbol"
            t-on-input="(ev) => this.updateSymbol(ev)"
          />
        </div>
      </Section>
      <Section title.translate="Format">
        <select
          class="o-input o-format-proposals mb-1"
          t-on-change="(ev) => this.updateSelectFormat(ev)"
          t-att-disabled="!formatProposals.length">
          <t t-foreach="formatProposals" t-as="proposal" t-key="proposal_index">
            <option
              t-att-value="proposal_index"
              t-esc="proposal.example"
              t-att-selected="proposal_index === state.selectedFormatIndex"
            />
          </t>
        </select>
        <t t-set="accounting_format_label">Accounting format</t>
        <Checkbox
          name="'accountingFormat'"
          label="accounting_format_label"
          value="state.isAccountingFormat"
          onChange.bind="toggleAccountingFormat"
        />
        <div class="o-format-examples mt-4" t-if="selectedFormat">
          <table class="w-100">
            <t t-foreach="getFormatExamples()" 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>
      <Section>
        <div class="o-sidePanelButtons">
          <button
            class="o-button primary"
            t-on-click="() => this.apply()"
            t-att-disabled="!formatProposals.length || isSameFormat">
            Apply
          </button>
        </div>
      </Section>
    </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"
          onSave.bind="switchToList"
          onCancel.bind="cancelEdition"
        />
      </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"
      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="position-relative h-100 w-100 d-flex align-items-center">
        <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-2">
            <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-2">
            123
          </div>
        </t>
        <div class="o-cf-preview-description">
          <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">
          <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>
    </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"
          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">
            <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">
                <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="colorNumberString(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="{{getPreviewGradient()}}">
        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="props.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"
      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>
      <select
        class="o-input o-cell-is-operator mb-3"
        t-on-change="(ev) => this.editOperator(ev.target.value)">
        <t t-foreach="cellIsOperators" t-as="op" t-key="op_index">
          <option
            t-att-value="op"
            t-esc="cellIsOperators[op]"
            t-att-selected="rule.operator === op"
          />
        </t>
      </select>
      <t t-if="rule.operator !== 'IsEmpty' and rule.operator !== 'IsNotEmpty'">
        <div class="o-cell-is-value mb-3">
          <StandaloneComposer t-props="getCellIsRuleComposerProps(0)"/>
        </div>
        <t t-if="rule.operator === 'Between' || rule.operator === 'NotBetween'">
          <div class="o-cell-is-value o-secondary-value mb-3">
            <StandaloneComposer t-props="getCellIsRuleComposerProps(1)"/>
          </div>
        </t>
      </t>
      <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"/>
        <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"
      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
            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">
        <div
          t-att-id="'btn-collapse-'+currentId"
          t-att-class="{ 'collapsed': props.collapsedAtInit }"
          class="collapsor w-100 d-flex align-items-center ps-1"
          data-bs-toggle="collapse"
          t-att-data-bs-target="'#box-collapse-'+currentId">
          <span class="collapsor-arrow">
            <t t-call="o-spreadsheet-Icon.ANGLE_DOWN"/>
          </span>
          <div class="ps-2" t-esc="props.title"/>
        </div>
      </div>
      <div
        t-att-id="'box-collapse-'+currentId"
        t-att-class="{'show': !props.collapsedAtInit}"
        class="collapsible_section collapse">
        <div class="pt-2">
          <t t-slot="content"/>
        </div>
      </div>
    </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"
    />
    <Menu
      t-if="menuState.isOpen"
      menuId="menuId"
      position="menuState.position"
      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"
        type="checkbox"
        t-att-disabled="props.disabled"
        t-att-name="props.name"
        t-att-checked="props.value"
        t-on-change="onChange"
      />
      <t 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-WaterfallChartDesignPanel">
    <GeneralDesignEditor
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart">
      <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
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
        <Section class="'pt-0'" title.translate="Values">
          <Checkbox
            name="'showValues'"
            label.translate="Show values"
            value="props.definition.showValues"
            onChange="(showValues) => props.updateChart(this.props.figureId, { showValues })"
          />
        </Section>
      </t>
    </GeneralDesignEditor>
    <SidePanelCollapsible collapsedAtInit="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 collapsedAtInit="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </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
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart"
      defaultChartTitleFontSize="defaultScorecardTitleFontSize">
      <t t-set-slot="general-extension">
        <Section class="'pt-1'" title.translate="Number formatting">
          <Checkbox
            name="'humanizeNumbers'"
            label="humanizeNumbersLabel"
            value="props.definition.humanize"
            onChange.bind="updateHumanizeNumbers"
          />
        </Section>
      </t>
    </GeneralDesignEditor>
    <SidePanelCollapsible collapsedAtInit="false" title.translate="Baseline">
      <t t-set-slot="content">
        <Section class="'pt-0'" title.translate="Baseline description">
          <input
            type="text"
            t-att-value="translate(props.definition.baselineDescr)"
            t-on-change="updateBaselineDescr"
            class="o-input"
            placeholder="Baseline description"
          />
        </Section>
        <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"
      />
      <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
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart">
      <t t-set-slot="general-extension">
        <ChartLegend
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
        <Section class="'pt-0'" title.translate="Values">
          <Checkbox
            name="'showValues'"
            label.translate="Show values"
            value="props.definition.showValues"
            onChange="(showValues) => props.updateChart(this.props.figureId, { showValues })"
          />
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesDesignEditor t-props="props"/>
  </t>

  <t t-name="o-spreadsheet-PieChartDesignPanel">
    <GeneralDesignEditor
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart">
      <t t-set-slot="general-extension">
        <ChartLegend
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
        <Section class="'pt-0'" title.translate="Values">
          <Checkbox
            name="'showValues'"
            label.translate="Show values"
            value="props.definition.showValues"
            onChange="(showValues) => props.updateChart(this.props.figureId, { showValues })"
          />
        </Section>
      </t>
    </GeneralDesignEditor>
  </t>

  <t t-name="o-spreadsheet-ChartPanel">
    <div class="o-chart" t-if="figureId">
      <div class="o-panel">
        <div
          class="o-panel-element o-panel-configuration"
          t-att-class="store.panel !== 'configuration' ? 'inactive' : ''"
          t-on-click="() => this.store.activatePanel('configuration')">
          <i class="fa fa-sliders"/>
          Configuration
        </div>
        <div
          class="o-panel-element o-panel-design"
          t-att-class="store.panel !== 'design' ? 'inactive' : ''"
          t-on-click="() => this.store.activatePanel('design')">
          <i class="fa fa-paint-brush"/>
          Design
        </div>
      </div>

      <t t-set="definition" t-value="getChartDefinition(this.figureId)"/>
      <t t-if="store.panel === 'configuration'">
        <ChartTypePicker figureId="props.figureId" chartPanelStore="store"/>
        <t
          t-component="chartPanel.configuration"
          definition="definition"
          figureId="figureId"
          updateChart.bind="updateChart"
          canUpdateChart.bind="canUpdateChart"
          t-key="figureId + definition.type"
        />
      </t>
      <t t-else="">
        <t
          t-component="chartPanel.design"
          definition="definition"
          figureId="figureId"
          updateChart.bind="updateChart"
          canUpdateChart.bind="canUpdateChart"
          t-key="figureId + definition.type"
        />
      </t>
    </div>
  </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"
      />
      <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-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
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart">
      <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>
      </t>
    </GeneralDesignEditor>

    <SidePanelCollapsible collapsedAtInit="false" title.translate="Geo chart options">
      <t t-set-slot="content">
        <Section class="'pt-0 o-color-scale'" title.translate="Color Scale">
          <select class="o-input" t-on-change="this.updateColorScaleType">
            <option value="custom">Custom</option>
            <hr/>
            <t t-foreach="colorScalesChoices" t-as="colorScale" t-key="colorScale">
              <option
                t-att-value="colorScale"
                t-esc="colorScale_value"
                t-att-selected="colorScale === selectedColorScale"
              />
            </t>
          </select>

          <t t-if="customColorScale">
            <div class="o-min-color d-flex align-items-center mb-2 mt-4">
              <RoundColorPicker
                currentColor="getCustomColorScaleColor('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="getCustomColorScaleColor('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="getCustomColorScaleColor('maxColor')"
                onColorPicked="(color) => this.setCustomColorScaleColor('maxColor', color)"
                disableNoColor="true"
              />
              <span class="ps-2">Color of maximum values</span>
            </div>
          </t>
        </Section>

        <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
        figureId="props.figureId"
        definition="props.definition"
        updateChart="props.updateChart"
      />

      <ChartDataSeries
        ranges="dataRanges"
        onSelectionChanged="(ranges) => this.onDataSeriesRangesChanged(ranges)"
        onSelectionConfirmed="() => this.onDataSeriesConfirmed()"
        hasSingleRange="true"
      />
      <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
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart"
    />
    <SidePanelCollapsible collapsedAtInit="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-ComboChartDesignPanel">
    <GeneralDesignEditor
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart">
      <t t-set-slot="general-extension">
        <ChartLegend
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
        <Section class="'pt-0'" title.translate="Values">
          <Checkbox
            name="'showValues'"
            label.translate="Show values"
            value="props.definition.showValues"
            onChange="showValues => props.updateChart(this.props.figureId, {showValues})"
          />
        </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 collapsedAtInit="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
      </t>
    </SidePanelCollapsible>
  </t>

  <t t-name="o-spreadsheet-ChartWithAxisDesignPanel">
    <GeneralDesignEditor
      figureId="props.figureId"
      definition="props.definition"
      updateChart="props.updateChart">
      <t t-set-slot="general-extension">
        <ChartLegend
          figureId="props.figureId"
          definition="props.definition"
          updateChart="props.updateChart"
        />
        <Section class="'pt-0'" title.translate="Values">
          <Checkbox
            name="'showValues'"
            label.translate="Show values"
            value="props.definition.showValues"
            onChange="(showValues) => props.updateChart(this.props.figureId, { showValues })"
          />
        </Section>
      </t>
    </GeneralDesignEditor>
    <SeriesWithAxisDesignEditor t-props="props"/>
    <SidePanelCollapsible collapsedAtInit="true" title.translate="Axes">
      <t t-set-slot="content">
        <AxisDesignEditor
          axesList="axesList"
          figureId="props.figureId"
          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"
        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="#444" d="M2,2 v44 h1 v-44 M3,45 h42 v1 h-42"/>
      <path stroke="#eb6d00" style="fill:none" d="M6,40 l12,-12 l6,6 l18,-18"/>
      <path stroke="#0074d9" 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="#0074d9" style="fill:none" d="M3,30 l12,-12 l6,6 l18,-18"/>
      <path stroke="#eb6d00" style="fill:none" d="M3,40 l12,-12 l6,6 l18,-12"/>
      <path fill="#444" 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="#c4e4ff" d="M3,45 V25 l12,-12 l18,18 l6,-6 V45"/>
      <path fill="#ffe1c8" d="M3,45 V40 l12,-12 l6,6 l18,-18 V45"/>
      <path stroke="#eb6d00" style="fill:none" d="M3,40 l12,-12 l6,6 l18,-18"/>
      <path stroke="#0074d9" style="fill:none" d="M3,25 l12,-12 l18,18 l6,-6"/>
      <path fill="#444" 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="#c4e4ff" d="M3,45 h36 v-39 l-18,18 l-6,-6 l-12,12"/>
      <path stroke="#0074d9" style="fill:none" d="M3,30 l12,-12 l6,6 l18,-18"/>
      <path fill="#ffe1c8" d="M3,45 h36 v-23 l-18,12 l-6,-6 l-12,12"/>
      <path stroke="#eb6d00" style="fill:none" d="M3,40 l12,-12 l6,6 l18,-12"/>
      <path fill="#444" 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="#0074d9" d="M7,45 v-28 h6 v28"/>
      <path fill="#c4e4ff" d="M8,45 v-27 h4 v27"/>
      <path fill="#eb6d00" d="M14,45 v-14 h6 v14"/>
      <path fill="#ffe1c8" d="M15,45 v-13 h4 v13"/>
      <path fill="#0074d9" d="M26,45 v-22 h6 v22"/>
      <path fill="#c4e4ff" d="M27,45 v-21 h4 v21"/>
      <path fill="#eb6d00" d="M33,45 v-32 h6 v32"/>
      <path fill="#ffe1c8" d="M34,45 v-31 h4 v31"/>
      <path fill="#444" 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="#0074d9" d="M7,45 v-12 h8 v12"/>
      <path fill="#c4e4ff" d="M8,45 v-11 h6 v11"/>
      <path fill="#eb6d00" d="M7,33 v-14 h8 v14"/>
      <path fill="#ffe1c8" d="M8,33 v-13 h6 v13"/>

      <path fill="#0074d9" d="M20,45 v-8 h8 v8"/>
      <path fill="#c4e4ff" d="M21,45 v-7 h6 v7"/>
      <path fill="#eb6d00" d="M20,37 v-9 h8 v9"/>
      <path fill="#ffe1c8" d="M21,37 v-8 h6 v8"/>

      <path fill="#0074d9" d="M33,45 v-18 h8 v18"/>
      <path fill="#c4e4ff" d="M34,45 v-17 h6 v17"/>
      <path fill="#eb6d00" d="M33,27 v-16 h8 v16"/>
      <path fill="#ffe1c8" d="M34,27 v-15 h6 v15"/>

      <path fill="#444" 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="#0074d9" d="M7,45 v-28 h6 v28"/>
        <path fill="#c4e4ff" d="M8,45 v-27 h4 v27"/>
        <path fill="#eb6d00" d="M14,45 v-14 h6 v14"/>
        <path fill="#ffe1c8" d="M15,45 v-13 h4 v13"/>
        <path fill="#0074d9" d="M26,45 v-22 h6 v22"/>
        <path fill="#c4e4ff" d="M27,45 v-21 h4 v21"/>
        <path fill="#eb6d00" d="M33,45 v-32 h6 v32"/>
        <path fill="#ffe1c8" d="M34,45 v-31 h4 v31"/>
      </g>
      <path fill="#444" 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="#0074d9" d="M7,45 v-12 h8 v12"/>
        <path fill="#c4e4ff" d="M8,45 v-11 h6 v11"/>
        <path fill="#eb6d00" d="M7,33 v-14 h8 v14"/>
        <path fill="#ffe1c8" d="M8,33 v-13 h6 v13"/>
        <path fill="#0074d9" d="M20,45 v-8 h8 v8"/>
        <path fill="#c4e4ff" d="M21,45 v-7 h6 v7"/>
        <path fill="#eb6d00" d="M20,37 v-9 h8 v9"/>
        <path fill="#ffe1c8" d="M21,37 v-8 h6 v8"/>
        <path fill="#0074d9" d="M33,45 v-18 h8 v18"/>
        <path fill="#c4e4ff" d="M34,45 v-17 h6 v17"/>
        <path fill="#eb6d00" d="M33,27 v-16 h8 v16"/>
        <path fill="#ffe1c8" d="M34,27 v-15 h6 v15"/>
      </g>
      <path fill="#444" 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="#0074d9" d="M7,45 v-14 h6 v14"/>
      <path fill="#c4e4ff" d="M8,45 v-13 h4 v13"/>
      <path fill="#eb6d00" d="M14,45 v-28 h6 v28"/>
      <path fill="#ffe1c8" d="M15,45 v-27 h4 v27"/>
      <path fill="#0074d9" d="M26,45 v-22 h6 v22"/>
      <path fill="#c4e4ff" d="M27,45 v-21 h4 v21"/>
      <path fill="#eb6d00" d="M33,45 v-32 h6 v32"/>
      <path fill="#ffe1c8" d="M34,45 v-31 h4 v31"/>
      <path stroke="#888" style="fill:none;stroke-width:1.5;" d="M4,40 l14,-12 l6,6 l20,-18"/>
      <path fill="#444" 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="#ffe1c8" stroke="#eb6d00" d="M41.32, 34 A20 20, 0, 1, 1, 24, 4 v20"/>
      <path fill="#c4e4ff" stroke="#0074d9" 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="#ffe1c8"
        stroke="#eb6d00"
        d="M41.32, 34 A20 20, 0, 1, 1, 24, 4 v8 A12,12,0,1,0,34.4,30"
      />
      <path
        fill="#c4e4ff"
        stroke="#0074d9"
        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="#0074d9" cx="10" cy="10" r="2"/>
      <circle fill="#0074d9" cx="15" cy="30" r="2"/>
      <circle fill="#0074d9" cx="25" cy="36" r="2"/>
      <circle fill="#0074d9" cx="32" cy="15" r="2"/>
      <circle fill="#eb6d00" cx="10" cy="40" r="2"/>
      <circle fill="#eb6d00" cx="18" cy="20" r="2"/>
      <circle fill="#eb6d00" cx="30" cy="25" r="2"/>
      <circle fill="#eb6d00" cx="40" cy="33" r="2"/>
      <path fill="#444" 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="#ccc" 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 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="#ddd" d="M1,8 h46 v32 h-46"/>
      <path fill="#eee" d="M2,9 h44 v30 h-44"/>
      <text 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="#444" d="M5,45 v-26 h6 v26"/>
      <path fill="#fff" d="M6,45 v-25 h4 v25"/>
      <path fill="#eb6d00" d="M13,19 v7 h6 v-7"/>
      <path fill="#ffe1c8" d="M14,20 v5 h4 v-5"/>
      <path fill="#eb6d00" d="M21,25 v10 h6 v-10"/>
      <path fill="#ffe1c8" d="M22,26 v8 h4 v-8"/>
      <path fill="#0074d9" d="M29,35 v-24 h6 v24"/>
      <path fill="#c4e4ff" d="M30,34 v-22 h4 v22"/>
      <path fill="#444" d="M37,45 v-34 h6 v34"/>
      <path fill="#fff" d="M38,45 v-33 h4 v33"/>
      <path fill="#444" 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="#444" 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="#eb6d00" d="M23,43 v-6 h22 v6"/>
      <path fill="#ffe1c8" d="M23,42 v-4 h21 v4"/>
      <path fill="#eb6d00" d="M23,36 v-6 h18 v6"/>
      <path fill="#ffe1c8" d="M23,35 v-4 h17 v4"/>
      <path fill="#eb6d00" d="M23,29 v-6 h12 v6"/>
      <path fill="#ffe1c8" d="M23,28 v-4 h11 v4"/>
      <path fill="#eb6d00" d="M23,22 v-6 h8 v6"/>
      <path fill="#ffe1c8" d="M23,21 v-4 h7 v4"/>
      <path fill="#eb6d00" d="M23,15 v-6 h4 v6"/>
      <path fill="#ffe1c8" d="M23,14 v-4 h3 v4"/>

      <path fill="#0074d9" d="M24,43 v-6 h-20 v6"/>
      <path fill="#c4e4ff" d="M24,42 v-4 h-19 v4"/>
      <path fill="#0074d9" d="M24,36 v-6 h-18 v6"/>
      <path fill="#c4e4ff" d="M24,35 v-4 h-17 v4"/>
      <path fill="#0074d9" d="M24,29 v-6 h-12 v6"/>
      <path fill="#c4e4ff" d="M24,28 v-4 h-11 v4"/>
      <path fill="#0074d9" d="M24,22 v-6 h-6 v6"/>
      <path fill="#c4e4ff" d="M24,21 v-4 h-5 v4"/>
      <path fill="#0074d9" d="M24,15 v-6 h-4 v6"/>
      <path fill="#c4e4ff" d="M24,14 v-4 h-3 v4"/>

      <path fill="#444" 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="#0074d9" d="m24 16 14.27 3.36-1.93 21.63-18.22-8.9-3.63-11.18Z"/>
      <path fill="none" stroke="#eb6d00" d="m24 4 7.61 17.53-4.67 6.52-12.34 8.89-7.72-18.5Z"/>
      <path
        fill="none"
        stroke="#444"
        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="#0074d944"
        stroke="#0074d9"
        d="m24 16 14.27 3.36-1.93 21.63-18.22-8.9-3.63-11.18Z"
      />
      <path fill="#eb6d0044" stroke="#eb6d00" d="m24 4 7.61 17.53-4.67 6.52-12.34 8.89-7.72-18.5Z"/>
      <path
        fill="none"
        stroke="#444"
        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="#c4e4ff"/>
      <path
        stroke="#eb6d00"
        fill="#ffe1c8"
        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="#ffe1c8"
        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="#eb6d00"
        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="#444"/>
    </svg>
  </t>

  <t t-name="o-spreadsheet.ChartTitle">
    <t t-set="placeholder">Add a title</t>
    <t t-set="title">
      <t t-if="props.name" t-esc="props.name"/>
      <t t-else="">Title</t>
    </t>
    <Section class="'o-chart-title'" title="title.toString()">
      <input
        type="text"
        class="o-input"
        t-att-value="props.title"
        t-on-change="updateTitle"
        t-att-placeholder="placeholder"
      />
      <div class="o-chart-title-designer position-relative d-flex align-items-center">
        <span
          class="o-menu-item-button o-hoverable-button"
          title="Bold"
          t-att-class="{active: props.style.bold}"
          t-on-click="(ev) => this.props.toggleBold()">
          <span>
            <t t-call="o-spreadsheet-Icon.BOLD"/>
          </span>
        </span>
        <span
          class="o-menu-item-button o-hoverable-button"
          title="Italic"
          t-att-class="{active: props.style.italic}"
          t-on-click="(ev) => this.props.toggleItalic()">
          <span>
            <t t-call="o-spreadsheet-Icon.ITALIC"/>
          </span>
        </span>
        <div class="o-divider"/>
        <span
          class="o-menu-item-button o-hoverable-button"
          title="Horizontal alignment"
          t-on-click="(ev) => this.toggleDropdownTool('horizontalChartAlignTool', ev)">
          <span>
            <t t-if="props.style.align === 'center'" t-call="o-spreadsheet-Icon.ALIGN_CENTER"/>
            <t t-elif="props.style.align === 'right'" t-call="o-spreadsheet-Icon.ALIGN_RIGHT"/>
            <t t-else="" t-call="o-spreadsheet-Icon.ALIGN_LEFT"/>
          </span>
          <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
        </span>
        <div
          class="o-dropdown-content position-absolute top-100 start-0 bg-white"
          t-if="state.activeTool === 'horizontalChartAlignTool'"
          t-on-click.stop="">
          <div class="o-dropdown-line d-flex">
            <span
              class="o-menu-item-button o-hoverable-button"
              t-att-class="{active: props.style.align === 'left'}"
              title="Left"
              t-on-click="(ev) => this.updateAlignment('left')">
              <span>
                <t t-call="o-spreadsheet-Icon.ALIGN_LEFT"/>
              </span>
            </span>
            <span
              class="o-menu-item-button o-hoverable-button"
              t-att-class="{active: props.style.align === 'center'}"
              title="Center"
              t-on-click="(ev) => this.updateAlignment('center')">
              <span>
                <t t-call="o-spreadsheet-Icon.ALIGN_CENTER"/>
              </span>
            </span>
            <span
              class="o-menu-item-button o-hoverable-button"
              t-att-class="{active: props.style.align === 'right'}"
              title="Right"
              t-on-click="(ev) => this.updateAlignment('right')">
              <span>
                <t t-call="o-spreadsheet-Icon.ALIGN_RIGHT"/>
              </span>
            </span>
          </div>
        </div>
        <div class="o-divider"/>
        <FontSizeEditor
          currentFontSize="props.style.fontSize"
          onFontSizeChanged.bind="this.updateFontSize"
          class="'o-hoverable-button'"
        />
        <div class="o-divider"/>
        <ColorPickerWidget
          currentColor="props.style.color"
          toggleColorPicker="(ev) => this.toggleDropdownTool('fillChartColorTool', ev)"
          showColorPicker="state.activeTool === 'fillChartColorTool'"
          onColorPicked.bind="onColorPicked"
          title="fill_color"
          icon="'o-spreadsheet-Icon.TEXT_COLOR'"
          class="'o-hoverable-button o-menu-item-button'"
        />
      </div>
    </Section>
  </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>
                  <input
                    t-att-value="trend.window || this.defaultWindowSize"
                    type="number"
                    class="w-100 o-input trend-window-input"
                    t-on-change="(ev) => this.onChangeMovingAverageWindow(index, ev)"
                  />
                </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 collapsedAtInit="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-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'"
        />
      </t>
    </Section>
  </t>

  <t t-name="o-spreadsheet-GenericChartConfigPanel">
    <div>
      <ChartDataSeries
        ranges="this.getDataSeriesRanges()"
        onSelectionChanged.bind="onDataSeriesRangesChanged"
        onSelectionConfirmed.bind="onDataSeriesConfirmed"
        onSelectionReordered.bind="onDataSeriesReordered"
        onSelectionRemoved.bind="onDataSeriesRemoved"
      />
      <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">
    <t t-set="chart_title">Chart title</t>
    <SidePanelCollapsible collapsedAtInit="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="chart_title"
          toggleItalic.bind="toggleItalicChartTitle"
          toggleBold.bind="toggleBoldChartTitle"
          updateAlignment.bind="updateChartTitleAlignment"
          updateColor.bind="updateChartTitleColor"
          style="titleStyle"
          onFontSizeChanged.bind="updateChartTitleFontSize"
        />
        <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'" title="title">
      <SelectionInput
        ranges="ranges"
        required="true"
        hasSingleRange="props.hasSingleRange"
        onSelectionChanged="props.onSelectionChanged"
        onSelectionConfirmed="props.onSelectionConfirmed"
        onSelectionReordered="props.onSelectionReordered"
        onSelectionRemoved="props.onSelectionRemoved"
        colors="colors"
      />
    </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"
      name="editor_label"
      toggleItalic.bind="toggleItalicAxisTitle"
      toggleBold.bind="toggleBoldAxisTitle"
      updateAlignment.bind="updateAxisTitleAlignment"
      updateColor.bind="updateAxisTitleColor"
      style="axisTitleStyle"
      onFontSizeChanged.bind="updateAxisTitleFontSize"
    />
  </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"
      />
      <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-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-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="error-icon text-danger position-absolute d-flex align-items-center"
            title="This range is invalid">
            <t t-call="o-spreadsheet-Icon.ERROR"/>
          </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-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"
        t-ref="popover"
        t-on-wheel="props.onMouseWheel"
        t-att-style="popoverStyle"
        t-on-click.stop="">
        <t t-slot="default"/>
      </div>
    </t>
  </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-Menu">
    <Popover t-if="menuItemsAndSeparators.length" t-props="popoverProps">
      <div
        t-ref="menu"
        class="o-menu"
        t-att-style="menuStyle"
        t-on-scroll="onScroll"
        t-on-wheel.stop=""
        t-on-pointerdown.prevent=""
        t-on-click.stop=""
        t-on-mouseover="onMouseOverMainMenu"
        t-on-contextmenu.prevent="">
        <t t-foreach="menuItemsAndSeparators" t-as="menuItem" t-key="menuItem_index">
          <div t-if="menuItem === 'separator'" class="o-separator"/>
          <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-mouseenter="(ev) => this.onMouseEnter(menuItem, ev)"
              t-on-mouseover="(ev) => this.onMouseOver(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': 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 align-middle ms-auto"
                  t-call="o-spreadsheet-Icon.CARET_RIGHT"
                />
                <div
                  t-elif="secondaryIcon"
                  class="o-menu-item-root align-middle ms-auto"
                  t-call="{{secondaryIcon}}"
                />
              </div>
            </div>
          </t>
        </t>
      </div>
      <Menu
        t-if="subMenu.isOpen"
        t-key="subMenu.parentMenu.id"
        position="subMenuPosition"
        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-LinkEditor">
    <div
      class="o-link-editor"
      t-on-click.stop="() => this.menu.isOpen=false"
      t-on-keydown="onKeyDown"
      t-ref="linkEditor">
      <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">
            <t t-call="o-spreadsheet-Icon.LIST"/>
          </button>
        </div>
      </div>
      <Menu
        t-if="menu.isOpen"
        position="menuPosition"
        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">
      <!-- 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-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.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.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.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 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="fill:none;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5">
      <path stroke="currentColor" d="M1.5,1.5h15v15h-15v-15M9,5v8M5,9h8"/>
    </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 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 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 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
          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-IconPicker">
    <div class="o-icon-picker">
      <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-foreach="['n', 's', 'w', 'e']" t-as="orientation" t-key="orientation">
        <Border
          onMoveHighlight="(x, y) => this.onMoveHighlight(x,y)"
          isMoving='highlightState.shiftingMode === "isMoving"'
          orientation="orientation"
          zone="props.zone"
        />
      </t>
      <t t-foreach="['nw', 'ne', 'sw', 'se']" t-as="orientation" t-key="orientation">
        <Corner
          onResizeHighlight="(isLeft, isTop) => this.onResizeHighlight(isLeft, isTop)"
          isResizing='highlightState.shiftingMode === "isResizing"'
          orientation="orientation"
          zone="props.zone"
          color="props.color"
        />
      </t>
    </div>
  </t>

  <t t-name="o-spreadsheet-Corner">
    <div
      class="o-corner"
      t-on-pointerdown.prevent="onMouseDown"
      t-att-style="style"
      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',
        }"
    />
  </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 overflow-hidden"
      t-on-pointermove.self="onMouseMove"
      t-on-mouseleave="onMouseLeave"
      t-on-pointerdown.self.prevent="select"
      t-ref="rowResizer"
      t-on-pointerup.self="onMouseUp"
      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 overflow-hidden"
      t-on-pointermove.self="onMouseMove"
      t-on-mouseleave="onMouseLeave"
      t-on-pointerdown.self.prevent="select"
      t-ref="colResizer"
      t-on-pointerup.self="onMouseUp"
      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>

      <Menu
        t-if="menu.isOpen"
        menuItems="menu.menuItems"
        position="menu.position"
        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"
      zIndex="zIndex">
      <t
        t-component="cellPopover.Component"
        t-props="{...cellPopover.props, onClosed : () => props.onClosePopover()}"
      />
    </Popover>
  </t>

  <t t-name="o-spreadsheet-GridOverlay">
    <div
      t-ref="gridOverlay"
      class="o-grid-overlay overflow-hidden"
      t-att-class="{'o-paint-format-cursor': isPaintingFormat}"
      t-att-style="style"
      t-on-pointerdown="onMouseDown"
      t-on-dblclick.self="onDoubleClick"
      t-on-contextmenu.stop.prevent="onContextMenu">
      <FiguresContainer onFigureDeleted="props.onFigureDeleted"/>
      <DataValidationOverlay/>
      <FilterIconsOverlay/>
      <GridAddRowsFooter
        t-if="!env.model.getters.isReadonly()"
        t-key="env.model.getters.getActiveSheetId()"
        focusGrid="props.onFigureDeleted"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-GridCellIcon">
    <div
      class="o-grid-cell-icon position-absolute overflow-hidden"
      t-if="isPositionVisible(this.props.cellPosition)"
      t-att-style="iconStyle">
      <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">
        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"
      />
      <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"
      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"
        onCellHovered.bind="onCellHovered"
        onGridResized.bind="onGridResized"
        onGridMoved.bind="moveCanvas"
        gridOverlayDimensions="gridOverlayDimensions"
        onFigureDeleted.bind="focusDefaultElement"
      />
      <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-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)"
        />
      </t>
      <GridPopover
        t-if="!menuState.isOpen"
        gridRect="getGridRect()"
        onMouseWheel.bind="onMouseWheel"
        onClosePopover.bind="onClosePopover"
      />
      <t t-if="env.model.getters.isGridSelectionActive()">
        <Autofill position="getAutofillPosition()" isVisible="isAutofillVisible"/>
      </t>
      <t t-foreach="highlights" t-as="highlight" t-key="highlight_index">
        <t
          t-if="highlight.interactive and highlight.sheetId === env.model.getters.getActiveSheetId()">
          <Highlight zone="highlight.zone" color="highlight.color"/>
        </t>
      </t>
      <Menu
        t-if="menuState.isOpen"
        menuItems="menuState.menuItems"
        position="menuState.position"
        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"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-FontSizeEditor">
    <div class="o-dropdown" t-ref="FontSizeEditor">
      <div
        class=" o-font-size-editor d-flex align-items-center"
        t-att-class="props.class"
        title="Font Size"
        t-on-click="this.toggleFontList">
        <input
          type="number"
          min="1"
          max="400"
          class="o-font-size o-number-input bg-transparent border-0"
          t-on-keydown="onInputKeydown"
          t-on-wheel.prevent.stop=""
          t-on-click.stop=""
          t-on-focus.stop="onInputFocused"
          t-att-value="props.currentFontSize"
          t-on-change="setSizeFromInput"
          t-ref="inputFontSize"
        />
        <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="fontSizeList">
          <t t-foreach="fontSizes" t-as="fontSize" t-key="fontSize">
            <div
              t-esc="fontSize"
              t-att-data-size="fontSize"
              t-on-click="() => this.setSizeFromList(fontSize)"
            />
          </t>
        </div>
      </Popover>
    </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 text-truncate'"
        label="value.toString()"
      />
    </div>
  </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 my-2 mb-3" t-on-click="() => this.sortFilterZone('asc')">
            Sort ascending (A ⟶ Z)
          </div>
          <div class="o-filter-menu-item my-2" t-on-click="() => this.sortFilterZone('desc')">
            Sort descending (Z ⟶ A)
          </div>
        </div>
        <div class="o-separator"/>
      </t>
      <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-model="state.textFilter"
          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"
        t-ref="filterValueList"
        t-on-click="this.clearScrolledToValue"
        t-on-scroll="this.clearScrolledToValue">
        <t t-foreach="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="displayedValues.length === 0"
          class="o-filter-menu-no-values d-flex align-items-center justify-content-center w-100 h-100 ">
          No results
        </div>
      </div>
      <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>
  </t>

  <t t-name="o-spreadsheet-FilterIconsOverlay">
    <t
      t-foreach="getFilterHeadersPositions()"
      t-as="position"
      t-key="'filter'+position.col + '_' + position.row">
      <GridCellIcon cellPosition="position" horizontalAlign="'right'">
        <FilterIcon cellPosition="position"/>
      </GridCellIcon>
    </t>
  </t>

  <t t-name="o-spreadsheet-FilterIcon">
    <div class="o-filter-icon" t-att-class="iconClass" t-on-click="onClick">
      <t t-if="isFilterActive" t-call="o-spreadsheet-Icon.FILTER_ICON_ACTIVE"/>
      <t t-else="" t-call="o-spreadsheet-Icon.FILTER_ICON"/>
    </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="figure" t-key="figure.id">
              <FigureComponent
                onFigureDeleted="this.props.onFigureDeleted"
                figure="figure"
                style="getFigureStyle(figure)"
                onMouseDown="(ev) => this.startDraggingFigure(figure, ev)"
                onClickAnchor="(dirX, dirY, ev) => this.startResize(figure, 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"
        figure="this.props.figure"
        t-key="this.props.figure.id + '-' + chartType"
      />
    </div>
  </t>

  <t t-name="o-spreadsheet-FigureComponent">
    <div class="o-figure-wrapper pe-auto" t-att-style="wrapperStyle">
      <div
        class="o-figure w-100 h-100"
        t-on-pointerdown.stop="(ev) => this.onMouseDown(ev)"
        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.figure.id"
        tabindex="0"
        t-on-keydown="(ev) => this.onKeyDown(ev)"
        t-on-keyup.stop="">
        <t
          t-component="figureRegistry.get(props.figure.tag).Component"
          t-key="props.figure.id"
          onFigureDeleted="props.onFigureDeleted"
          figure="props.figure"
        />
        <div class="o-figure-menu position-absolute m-2" t-if="!env.isDashboard()">
          <div
            class="o-figure-menu-item"
            t-if="!env.model.getters.isReadonly()"
            t-on-click="showMenu"
            t-ref="menuButton"
            t-on-contextmenu.prevent.stop="showMenu">
            <t t-call="o-spreadsheet-Icon.LIST"/>
          </div>
          <Menu
            t-if="menuState.isOpen"
            position="menuState.position"
            menuItems="menuState.menuItems"
            onClose="() => this.menuState.isOpen=false"
          />
        </div>
      </div>
      <div class="o-figure-border w-100 h-100 position-absolute pe-none" t-att-style="borderStyle"/>
      <t t-if="isSelected">
        <div
          class="o-fig-anchor o-top"
          t-att-style="this.getResizerPosition('top')"
          t-on-pointerdown="(ev) => this.clickAnchor(0,-1, ev)"
        />
        <div
          class="o-fig-anchor o-topRight"
          t-att-style="this.getResizerPosition('top right')"
          t-on-pointerdown="(ev) => this.clickAnchor(1,-1, ev)"
        />
        <div
          class="o-fig-anchor o-right"
          t-att-style="this.getResizerPosition('right')"
          t-on-pointerdown="(ev) => this.clickAnchor(1,0, ev)"
        />
        <div
          class="o-fig-anchor o-bottomRight"
          t-att-style="this.getResizerPosition('bottom right')"
          t-on-pointerdown="(ev) => this.clickAnchor(1,1, ev)"
        />
        <div
          class="o-fig-anchor o-bottom"
          t-att-style="this.getResizerPosition('bottom')"
          t-on-pointerdown="(ev) => this.clickAnchor(0,1, ev)"
        />
        <div
          class="o-fig-anchor o-bottomLeft"
          t-att-style="this.getResizerPosition('bottom left')"
          t-on-pointerdown="(ev) => this.clickAnchor(-1,1, ev)"
        />
        <div
          class="o-fig-anchor o-left"
          t-att-style="this.getResizerPosition('left')"
          t-on-pointerdown="(ev) => this.clickAnchor(-1,0, ev)"
        />
        <div
          class="o-fig-anchor o-topLeft"
          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"
      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" t-ref="chartContainer"/>
  </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-ErrorToolTip">
    <div class="o-error-tooltip">
      <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-DataValidationOverlay">
    <t t-foreach="checkBoxCellPositions" t-as="position" t-key="'checkbox'+position_index">
      <GridCellIcon cellPosition="position">
        <DataValidationCheckbox cellPosition="position"/>
      </GridCellIcon>
    </t>

    <t t-foreach="listIconsCellPositions" t-as="position" t-key="'list'+position_index">
      <GridCellIcon cellPosition="position" horizontalAlign="'right'">
        <DataValidationListIcon cellPosition="position"/>
      </GridCellIcon>
    </t>
  </t>

  <t t-name="o-spreadsheet-DataValidationListIcon">
    <div
      class="o-dv-list-icon d-flex align-items-center justify-content-center"
      t-on-click="onClick">
      <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
    </div>
  </t>

  <t t-name="o-spreadsheet-DataValidationCheckbox">
    <Checkbox
      name="'data-validation-checkbox'"
      value="checkBoxValue"
      onChange.bind="onCheckboxChange"
      className="isDisabled ? 'pe-none o-dv-checkbox' : 'o-dv-checkbox'"
    />
  </t>

  <t t-name="o-spreadsheet-SpreadsheetDashboard">
    <div class="o-grid o-two-columns" tabindex="-1" t-on-wheel="onMouseWheel">
      <div class="mx-auto h-100 position-relative" t-ref="grid" t-att-style="gridContainer">
        <GridOverlay
          onCellHovered.bind="onCellHovered"
          onGridResized.bind="onGridResized"
          onGridMoved.bind="moveCanvas"
          gridOverlayDimensions="gridOverlayDimensions"
        />
        <canvas t-ref="canvas"/>
        <GridPopover
          gridRect="getGridRect()"
          onMouseWheel.bind="onMouseWheel"
          onClosePopover.bind="onClosePopover"
        />
        <div
          t-foreach="getClickableCells()"
          t-as="clickableCell"
          t-key="clickableCell_index"
          class="o-dashboard-clickable-cell"
          t-att-title="clickableCell.title"
          t-on-click="() => this.selectClickableCell(clickableCell)"
          t-on-contextmenu.prevent=""
          t-att-style="getCellClickableStyle(clickableCell.coordinates)"
        />
      </div>
      <VerticalScrollBar/>
      <HorizontalScrollBar/>
      <div class="o-scrollbar corner"/>
    </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"
        t-att-class="{
          'o-topbar-composer-readonly': env.model.getters.isReadonly(),
        }"
        t-on-click.stop=""
        t-att-style="containerStyle">
        <Composer
          focus="focus"
          inputStyle="composerStyle"
          onComposerContentFocused.bind="onFocus"
          composerStore="composerStore"
          placeholder="composerStore.placeholder"
        />
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-StandaloneComposer">
    <div
      class="o-standalone-composer"
      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-GridComposer">
    <div
      class="o-cell-reference"
      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 user-select-none shadow">
      <t t-set="context" t-value="getContext()"/>
      <div class="o-formula-assistant" t-if="context.functionName">
        <div class="o-formula-assistant-head d-flex flex-row justify-content-between">
          <div>
            <span t-esc="context.functionName"/>
            (
            <t t-foreach="context.functionDescription.args" t-as="arg" t-key="arg.name">
              <span t-if="arg_index > '0'" t-esc="formulaArgSeparator"/>
              <span t-att-class="{ 'o-formula-assistant-focus': context.argToFocus === arg_index }">
                <span>
                  <span t-if="arg.optional || arg.repeating || arg.default">[</span>
                  <span t-esc="arg.name"/>
                  <span t-if="arg.repeating">, ...</span>
                  <span t-if="arg.optional || arg.repeating || arg.default">]</span>
                </span>
              </span>
            </t>
            )
          </div>
          <i
            class="fa fa-caret-up px-2 align-self-start collapsed"
            data-bs-toggle="collapse"
            data-bs-target="#formula-assistant-details"
          />
        </div>

        <div id="formula-assistant-details" class="collapse">
          <div class="o-formula-assistant-core pb-3 m-3">
            <div class="o-formula-assistant-gray">ABOUT</div>
            <div t-esc="context.functionDescription.description"/>
          </div>

          <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.argToFocus >= '0',
                  'o-formula-assistant-focus': context.argToFocus === arg_index,
                }">
              <div>
                <span t-esc="arg.name"/>
                <span
                  t-if="arg.optional || arg.repeating || arg.default ">&#xA0;- [optional]&#xA0;</span>
                <span t-if="arg.default">
                  <span>default:&#xA0;</span>
                  <t t-esc="arg.defaultValue"/>
                </span>
                <span t-if="arg.repeating">repeatable</span>
              </div>
              <div class="o-formula-assistant-arg-description" t-esc="arg.description"/>
            </div>
          </t>
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-Composer">
    <div class="o-composer-container w-100 h-100">
      <t
        t-set="assistantIsAvailable"
        t-value="autoCompleteState.provider or functionDescriptionState.showDescription"
      />
      <div class="d-flex flex-row position-relative">
        <span
          t-if="props.focus !== 'inactive' and assistantIsAvailable and assistant.forcedClosed"
          role="button"
          title="Show formula help"
          t-on-click="openAssistant"
          t-on-pointerdown.prevent.stop=""
          t-on-click.prevent.stop=""
          t-on-pointerup.prevent.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' : 'true'"
          t-att-placeHolder="props.placeholder"
          spellcheck="false"
          t-on-keydown="onKeydown"
          t-on-mousewheel.stop=""
          t-on-input="onInput"
          t-on-pointerdown="onMousedown"
          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"
        />
      </div>
      <div
        class="o-composer-assistant-container shadow position-absolute"
        t-att-style="assistantContainerStyle"
        t-if="props.focus !== 'inactive' and !assistant.forcedClosed and assistantIsAvailable">
        <span
          role="button"
          t-on-click="closeAssistant"
          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 text-muted"/>
        </span>
        <div
          class="o-composer-assistant overflow-auto"
          t-att-style="assistantStyle"
          t-on-wheel.stop=""
          t-on-pointerdown.prevent.stop=""
          t-on-click.prevent.stop=""
          t-on-pointerup.prevent.stop="">
          <FunctionDescriptionProvider
            t-if="functionDescriptionState.showDescription"
            functionName="functionDescriptionState.functionName"
            functionDescription="functionDescriptionState.functionDescription"
            argToFocus="functionDescriptionState.argToFocus"
          />
          <div
            t-if="functionDescriptionState.showDescription and autoCompleteState.provider"
            class="border-top"
          />
          <TextValueProvider
            t-if="autoCompleteState.provider"
            proposals="autoCompleteState.provider.proposals"
            selectedIndex="autoCompleteState.selectedIndex"
            onValueSelected.bind="this.autoComplete"
            onValueHovered.bind="this.updateAutoCompleteIndex"
          />
        </div>
      </div>
    </div>
  </t>

  <t t-name="o-spreadsheet-TextValueProvider">
    <div
      t-ref="autoCompleteList"
      t-att-class="{
          'o-autocomplete-dropdown': 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.class"
              t-attf-style="color: {{content.color || 'inherit'}};"
              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" 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"/>
        <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 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" 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"
              t-att-class="{'o-wrong-color': !isHexColorInputValid }"
              t-on-click.stop=""
              t-att-value="state.customHexColor"
              t-on-input="setHexColor"
              maxlength="7"
            />
            <div class="o-color-preview" t-att-style="colorPreviewStyle"/>
          </div>
          <div class="o-custom-input-buttons">
            <button
              class="o-add-button"
              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"/>
          <div class="o-buttons">
            <button t-on-click="resetColor" class="o-cancel">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 align-items-center overflow-hidden"
      t-on-click="props.onClick"
      t-ref="bottomBar"
      t-on-contextmenu.prevent="">
      <Ripple>
        <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 flex-shrink-0 d-flex h-100 me-3">
        <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>
      <div
        class="o-bottom-bar-arrows d-flex h-100 me-5 align-items-center"
        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 me-2"
            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 me-4"
            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')"
      />

      <Menu
        t-if="menuState.isOpen"
        position="menuState.position"
        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'" 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 "
        tabindex="-1"
        composerFocusableElement="true"
        t-on-pointerdown="(ev) => this.onMouseDown(ev)"
        t-on-contextmenu.prevent="(ev) => this.onContextMenu(ev)"
        t-ref="sheetDiv"
        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-dblclick="() => this.onDblClick()"
          t-on-focusout="() => this.onFocusOut()"
          t-on-keydown="(ev) => this.onKeyDown(ev)"
          t-att-contenteditable="state.isEditing ? 'true': '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="props.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="props.showBorderEditor"
        onBorderColorPicked.bind="onBorderColorPicked"
        onBorderStylePicked.bind="onBorderStylePicked"
        onBorderPositionPicked.bind="onBorderPositionPicked"
        currentBorderColor="state.currentColor"
        currentBorderStyle="state.currentStyle"
        currentBorderPosition="state.currentPosition"
        maxHeight="props.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"
        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"/>
        <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">
                <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>
