@odoo/o-spreadsheet 19.1.0-alpha.12 → 19.1.0-alpha.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,9 +1,9 @@
1
1
  <!--
2
2
  This file is generated by o-spreadsheet build tools. Do not edit it.
3
3
  @see https://github.com/odoo/o-spreadsheet
4
- @version 19.1.0-alpha.12
5
- @date 2025-11-12T14:18:00.954Z
6
- @hash 6fefc9c
4
+ @version 19.1.0-alpha.14
5
+ @date 2025-12-02T05:35:39.337Z
6
+ @hash 04cf666
7
7
  -->
8
8
  <odoo>
9
9
  <t t-name="o-spreadsheet-ValidationMessages">
@@ -31,7 +31,7 @@
31
31
  <div
32
32
  class="o-spreadsheet-topbar d-flex flex-column user-select-none bg-white"
33
33
  t-on-click="props.onClick">
34
- <div t-if="!env.isSmall" class="o-topbar-top d-flex justify-content-between">
34
+ <div t-if="!env.isSmall" class="o-topbar-top d-flex justify-content-between border-bottom">
35
35
  <!-- Menus -->
36
36
  <div class="o-topbar-topleft d-flex">
37
37
  <t t-foreach="menus" t-as="menu" t-key="menu_index">
@@ -82,7 +82,7 @@
82
82
  t-key="toolbarAction_index">
83
83
  <t t-component="toolbarAction.component" t-props="toolbarAction.props"/>
84
84
  </t>
85
- <div t-if="showDivider(category_index)" class="o-topbar-divider"/>
85
+ <div t-if="showDivider(category_index)" class="o-topbar-divider border-end"/>
86
86
  </div>
87
87
  <div
88
88
  t-ref="moreToolsContainer"
@@ -100,7 +100,7 @@
100
100
  </div>
101
101
  <div
102
102
  t-if="this.fingerprints.isEnabled"
103
- class="topbar-banner irregularity-map d-flex align-items-center justify-content-between">
103
+ class="topbar-banner irregularity-map d-flex align-items-center justify-content-between border-top">
104
104
  <div
105
105
  t-on-click="() => this.fingerprints.disable()"
106
106
  role="button"
@@ -146,7 +146,7 @@
146
146
  </t>
147
147
  <div
148
148
  t-if="category_index &lt; state.invisibleToolsCategories.length-1"
149
- class="o-topbar-divider"
149
+ class="o-topbar-divider border-end"
150
150
  />
151
151
  </t>
152
152
  </div>
@@ -231,18 +231,26 @@
231
231
  </t>
232
232
 
233
233
  <t t-name="o-spreadsheet-TextInput">
234
- <input
235
- type="text"
236
- t-ref="{{refName}}"
237
- t-att-class="inputClass"
238
- t-att-id="props.id"
239
- t-att-placeholder="props.placeholder"
240
- t-on-change="save"
241
- t-on-blur="save"
242
- t-on-pointerdown="onMouseDown"
243
- t-on-pointerup="onMouseUp"
244
- t-on-keydown="onKeyDown"
245
- />
234
+ <div class="position-relative">
235
+ <input
236
+ type="text"
237
+ t-ref="{{refName}}"
238
+ t-att-class="inputClass"
239
+ t-att-id="props.id"
240
+ t-att-placeholder="props.placeholder"
241
+ t-on-change="save"
242
+ t-on-blur="save"
243
+ t-on-pointerdown="onMouseDown"
244
+ t-on-pointerup="onMouseUp"
245
+ t-on-keydown="onKeyDown"
246
+ />
247
+ <span
248
+ t-if="props.errorMessage"
249
+ class="os-input-error-icon text-danger position-absolute d-flex align-items-center"
250
+ t-att-title="props.errorMessage">
251
+ <t t-call="o-spreadsheet-Icon.ERROR"/>
252
+ </span>
253
+ </div>
246
254
  </t>
247
255
 
248
256
  <t t-name="o-spreadsheet-TableStylesPopover">
@@ -256,7 +264,7 @@
256
264
  t-foreach="Object.keys(categories)"
257
265
  t-as="category"
258
266
  t-key="category"
259
- class="o-notebook-tab d-flex align-items-center"
267
+ class="o-notebook-tab d-flex align-items-center border"
260
268
  t-att-class="{ 'selected': state.selectedCategory === category }"
261
269
  t-on-click="() => state.selectedCategory = category"
262
270
  t-att-data-id="category"
@@ -297,7 +305,7 @@
297
305
  <canvas t-ref="canvas" class="w-100 h-100"/>
298
306
  </div>
299
307
  <div
300
- class="o-table-style-edit-button position-absolute d-none bg-white"
308
+ class="o-table-style-edit-button position-absolute d-none bg-white border"
301
309
  t-if="isStyleEditable"
302
310
  t-on-click="this.editTableStyle"
303
311
  title="Edit custom table style">
@@ -313,7 +321,7 @@
313
321
  </t>
314
322
 
315
323
  <t t-name="o-spreadsheet-TableStylePicker">
316
- <div class="o-table-style-picker d-flex flew-row justify-content-between ps-1">
324
+ <div class="o-table-style-picker d-flex flew-row justify-content-between ps-1 border rounded">
317
325
  <div class="d-flex flex-row overflow-hidden ps-2">
318
326
  <t t-foreach="getDisplayedTableStyles()" t-as="styleId" t-key="styleId">
319
327
  <TableStylePreview
@@ -327,7 +335,7 @@
327
335
  </t>
328
336
  </div>
329
337
  <div
330
- class="o-table-style-picker-arrow d-flex align-items-center px-1"
338
+ class="o-table-style-picker-arrow d-flex align-items-center px-1 border-start"
331
339
  t-on-click.stop="onArrowButtonClick">
332
340
  <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
333
341
  </div>
@@ -411,7 +419,7 @@
411
419
  <RibbonMenu onClose="() => this.menuState.isOpen=false"/>
412
420
  </t>
413
421
  <t t-else="">
414
- <div class="o-small-composer px-2 py-2 position-relative bg-white">
422
+ <div class="o-small-composer px-2 py-2 position-relative bg-white border">
415
423
  <div class="w-100" t-ref="bottombarComposer">
416
424
  <Composer t-props="composerProps"/>
417
425
  <span
@@ -443,7 +451,7 @@
443
451
  composerFocusableElement="true"
444
452
  />
445
453
  </div>
446
- <div class="d-flex flex-fill align-items-center bottom-bar-menu">
454
+ <div class="d-flex flex-fill align-items-center bottom-bar-menu border-top border-bottom">
447
455
  <Ripple>
448
456
  <div class="py-1 px-1 mx-2 ribbon-toggler" t-on-click="toggleRibbon">
449
457
  <i class="o-icon fa fa-cog"/>
@@ -690,8 +698,9 @@
690
698
  </t>
691
699
 
692
700
  <t t-name="o-spreadsheet-SidePanelExtended">
693
- <div class="o-sidePanel h-100 bg-white">
694
- <div class="o-sidePanelHeader d-flex align-items-center justify-content-between">
701
+ <div class="o-sidePanel h-100 bg-white border-top border-start">
702
+ <div
703
+ class="o-sidePanelHeader d-flex align-items-center justify-content-between border-bottom">
695
704
  <div
696
705
  t-if="props.onToggleCollapsePanel"
697
706
  class="o-collapse-panel o-sidePanelAction rounded"
@@ -776,7 +785,7 @@
776
785
  t-att-selected="currentLocale.code === locale.code"
777
786
  />
778
787
  </select>
779
- <div class="o-locale-preview mt-4 p-3 rounded">
788
+ <div class="o-locale-preview mt-4 p-3 rounded border">
780
789
  <div>
781
790
  <span class="o-fw-bold me-1">Number:</span>
782
791
  <span t-esc="numberFormatPreview"/>
@@ -1042,13 +1051,13 @@
1042
1051
  </t>
1043
1052
  </select>
1044
1053
  <div
1045
- class="o-pivot-measure-display-description mt-3 ps-3"
1054
+ class="o-pivot-measure-display-description mt-3 ps-3 border-start"
1046
1055
  t-esc="measureDisplayDescription[store.measureDisplay.type]"
1047
1056
  />
1048
1057
  </Section>
1049
1058
 
1050
1059
  <Section t-if="store.doesDisplayNeedsField" title.translate="Base field:">
1051
- <div class="o-pivot-measure-display-field w-100 py-1 px-3">
1060
+ <div class="o-pivot-measure-display-field w-100 py-1 px-3 border">
1052
1061
  <t t-if="store.fields.length">
1053
1062
  <RadioSelection
1054
1063
  choices="fieldChoices"
@@ -1066,7 +1075,7 @@
1066
1075
 
1067
1076
  <t t-set="values" t-value="store.values"/>
1068
1077
  <Section t-if="store.doesDisplayNeedsValue and values.length" title.translate="Base item:">
1069
- <div class="o-pivot-measure-display-value w-100 py-1 px-3">
1078
+ <div class="o-pivot-measure-display-value w-100 py-1 px-3 border">
1070
1079
  <RadioSelection
1071
1080
  choices="values"
1072
1081
  selectedValue="store.measureDisplay.value"
@@ -1209,7 +1218,7 @@
1209
1218
  <div t-esc="sortDescription" class="pb-2"/>
1210
1219
  <div class="d-flex flex-column gap-2">
1211
1220
  <t t-foreach="sortValuesAndFields" t-as="valueAndField" t-key="valueAndField_index">
1212
- <div class="o-sort-card d-flex gap-1 px-2">
1221
+ <div class="o-sort-card d-flex gap-1 px-2 border">
1213
1222
  <t t-if="valueAndField.field">
1214
1223
  <span class="fw-bolder" t-esc="valueAndField.field"/>
1215
1224
  =
@@ -1321,7 +1330,7 @@
1321
1330
 
1322
1331
  <t t-name="o-spreadsheet-PivotDimension">
1323
1332
  <div
1324
- class="py-1 px-2 d-flex flex-column shadow-sm pivot-dimension bg-white"
1333
+ class="py-1 px-2 d-flex flex-column shadow-sm pivot-dimension border rounded"
1325
1334
  t-att-class="{'pivot-dimension-invalid': !props.dimension.isValid}">
1326
1335
  <div class="d-flex flex-row justify-content-between align-items-center">
1327
1336
  <div class="d-flex align-items-center overflow-hidden text-nowrap">
@@ -1439,21 +1448,97 @@
1439
1448
 
1440
1449
  <t t-name="o-spreadsheet-MoreFormatsPanel">
1441
1450
  <div class="o-more-formats-panel">
1442
- <div
1443
- t-foreach="dateFormatsActions"
1444
- t-as="action"
1445
- t-key="action.name(env)"
1446
- t-att-data-name="action.name(env)"
1447
- t-on-click="() => action.execute(env)"
1448
- class="w-100 d-flex align-items-center border-bottom format-preview bg-white">
1449
- <span class="ms-3 check-icon">
1450
- <t t-if="action.isActive(env)" t-call="o-spreadsheet-Icon.CHECK"/>
1451
- </span>
1452
- <span t-out="action.description(env)"/>
1453
- </div>
1451
+ <Section title.translate="Format type">
1452
+ <BadgeSelection
1453
+ choices="store.categories"
1454
+ onChange.bind="(category) => store.changeCategory(category)"
1455
+ selectedValue="store.category"
1456
+ />
1457
+ </Section>
1458
+ <t t-if="store.category === 'currency'" t-call="o-spreadsheet-CustomCurrencySection"/>
1459
+ <t t-set="proposals" t-value="store.formatProposals"/>
1460
+ <Section title.translate="Type" t-if="proposals.length">
1461
+ <div class="o-format-proposals overflow-auto border">
1462
+ <div
1463
+ t-foreach="proposals"
1464
+ t-as="proposal"
1465
+ t-key="proposal.format"
1466
+ t-att-data-name="proposal.format"
1467
+ t-on-click="() => this.store.updateFormat(proposal.format)"
1468
+ class="w-100 d-flex align-items-center format-preview px-2 py-1"
1469
+ t-att-class="{'active': (proposal.format || '') === (store.currentFormat || '')}">
1470
+ <span t-out="proposal.label"/>
1471
+ </div>
1472
+ </div>
1473
+ </Section>
1474
+
1475
+ <Section title.translate="Format" class="'o-custom-format-section'">
1476
+ <TextInput
1477
+ value="store.currentFormat || ''"
1478
+ onChange="(format) => this.store.updateFormat(format)"
1479
+ placeholder.translate="Format code"
1480
+ alwaysShowBorder="true"
1481
+ errorMessage="store.invalidFormatMessage"
1482
+ />
1483
+ <t t-set="examples" t-value="store.formatExamples"/>
1484
+ <div class="o-format-examples mt-4 p-2 rounded border" t-if="examples.length">
1485
+ <table class="w-100">
1486
+ <t t-foreach="examples" t-as="example" t-key="example_index">
1487
+ <tr>
1488
+ <td class="w-25 pe-3 o-fw-bold" t-esc="example.label"/>
1489
+ <td class="w-75 text-truncate" t-esc="example.value"/>
1490
+ </tr>
1491
+ </t>
1492
+ </table>
1493
+ </div>
1494
+ </Section>
1454
1495
  </div>
1455
1496
  </t>
1456
1497
 
1498
+ <t t-name="o-spreadsheet-CustomCurrencySection">
1499
+ <t t-set="availableCurrencies" t-value="store.availableCurrencies"/>
1500
+ <Section t-if="availableCurrencies.length > 1" title.translate="Currency">
1501
+ <select
1502
+ class="o-input o-available-currencies"
1503
+ t-on-change="(ev) => this.updateSelectCurrency(ev)">
1504
+ <t t-foreach="availableCurrencies" t-as="currency" t-key="currency_index">
1505
+ <option
1506
+ t-att-value="currency_index"
1507
+ t-esc="currencyDisplayName(currency)"
1508
+ t-att-selected="currency_index === store.selectedCurrencyIndex"
1509
+ />
1510
+ </t>
1511
+ </select>
1512
+ </Section>
1513
+ <Section>
1514
+ <div class="o-subsection-left">
1515
+ <div class="o-section-title">Code</div>
1516
+ <TextInput
1517
+ value="store.currencyCode"
1518
+ placeholder.translate="code"
1519
+ onChange="(code) => this.store.changeCurrencyCode(code)"
1520
+ alwaysShowBorder="true"
1521
+ />
1522
+ </div>
1523
+ <div class="o-subsection-right">
1524
+ <div class="o-section-title">Symbol</div>
1525
+ <TextInput
1526
+ value="store.currencySymbol"
1527
+ placeholder.translate="symbol"
1528
+ onChange="(symbol) => this.store.changeCurrencySymbol(symbol)"
1529
+ alwaysShowBorder="true"
1530
+ />
1531
+ </div>
1532
+ <Checkbox
1533
+ name="'accountingFormat'"
1534
+ className="'pt-2'"
1535
+ label.translate="Accounting format"
1536
+ value="store.isAccountingFormat"
1537
+ onChange="() => store.toggleAccountingFormat()"
1538
+ />
1539
+ </Section>
1540
+ </t>
1541
+
1457
1542
  <t t-name="o-spreadsheet-FindAndReplacePanel">
1458
1543
  <div class="o-find-and-replace">
1459
1544
  <Section title.translate="Search">
@@ -1583,7 +1668,7 @@
1583
1668
  </t>
1584
1669
 
1585
1670
  <t t-name="o-spreadsheet-DataValidationPreview">
1586
- <div class="o-dv-preview p-3" t-on-click="props.onClick" t-ref="dvPreview">
1671
+ <div class="o-dv-preview p-3 border-bottom" t-on-click="props.onClick" t-ref="dvPreview">
1587
1672
  <div class="d-flex justify-content-between">
1588
1673
  <div class="o-dv-container d-flex flex-column">
1589
1674
  <div class="o-dv-preview-description o-fw-bold text-truncate" t-esc="descriptionString"/>
@@ -1646,87 +1731,6 @@
1646
1731
  </div>
1647
1732
  </t>
1648
1733
 
1649
- <t t-name="o-spreadsheet-CustomCurrencyPanel">
1650
- <div class="o-custom-currency">
1651
- <Section t-if="availableCurrencies.length > 1" title.translate="Currency">
1652
- <select
1653
- class="o-input o-available-currencies"
1654
- t-on-change="(ev) => this.updateSelectCurrency(ev)">
1655
- <t t-foreach="availableCurrencies" t-as="currency" t-key="currency_index">
1656
- <option
1657
- t-att-value="currency_index"
1658
- t-esc="currencyDisplayName(currency)"
1659
- t-att-selected="currency_index === state.selectedCurrencyIndex"
1660
- />
1661
- </t>
1662
- </select>
1663
- </Section>
1664
- <Section>
1665
- <div class="o-subsection-left">
1666
- <div class="o-section-title">Code</div>
1667
- <input
1668
- type="text"
1669
- class="o-input"
1670
- t-model="state.currencyCode"
1671
- placeholder="code"
1672
- t-on-input="(ev) => this.updateCode(ev)"
1673
- />
1674
- </div>
1675
- <div class="o-subsection-right">
1676
- <div class="o-section-title">Symbol</div>
1677
- <input
1678
- type="text"
1679
- class="o-input"
1680
- placeholder="symbol"
1681
- t-model="state.currencySymbol"
1682
- t-on-input="(ev) => this.updateSymbol(ev)"
1683
- />
1684
- </div>
1685
- </Section>
1686
- <Section title.translate="Format">
1687
- <select
1688
- class="o-input o-format-proposals mb-1"
1689
- t-on-change="(ev) => this.updateSelectFormat(ev)"
1690
- t-att-disabled="!formatProposals.length">
1691
- <t t-foreach="formatProposals" t-as="proposal" t-key="proposal_index">
1692
- <option
1693
- t-att-value="proposal_index"
1694
- t-esc="proposal.example"
1695
- t-att-selected="proposal_index === state.selectedFormatIndex"
1696
- />
1697
- </t>
1698
- </select>
1699
- <t t-set="accounting_format_label">Accounting format</t>
1700
- <Checkbox
1701
- name="'accountingFormat'"
1702
- label="accounting_format_label"
1703
- value="state.isAccountingFormat"
1704
- onChange.bind="toggleAccountingFormat"
1705
- />
1706
- <div class="o-format-examples mt-4" t-if="selectedFormat">
1707
- <table class="w-100">
1708
- <t t-foreach="getFormatExamples()" t-as="example" t-key="example_index">
1709
- <tr>
1710
- <td class="w-25 pe-3 o-fw-bold" t-esc="example.label"/>
1711
- <td class="w-75 text-truncate" t-esc="example.value"/>
1712
- </tr>
1713
- </t>
1714
- </table>
1715
- </div>
1716
- </Section>
1717
- <Section>
1718
- <div class="o-sidePanelButtons">
1719
- <button
1720
- class="o-button primary"
1721
- t-on-click="() => this.apply()"
1722
- t-att-disabled="!formatProposals.length || isSameFormat">
1723
- Apply
1724
- </button>
1725
- </div>
1726
- </Section>
1727
- </div>
1728
- </t>
1729
-
1730
1734
  <t t-name="o-spreadsheet-ValueInRangeCriterionForm">
1731
1735
  <SelectionInput
1732
1736
  ranges="[props.criterion.values[0] || '']"
@@ -1920,7 +1924,7 @@
1920
1924
  <t t-name="o-spreadsheet-ConditionalFormatPreview">
1921
1925
  <t t-set="cf" t-value="props.conditionalFormat"/>
1922
1926
  <div
1923
- class="o-cf-preview w-100"
1927
+ class="o-cf-preview w-100 border-bottom"
1924
1928
  t-ref="cfPreview"
1925
1929
  t-att-class="props.class"
1926
1930
  t-att-data-id="cf.id"
@@ -1933,7 +1937,7 @@
1933
1937
  </div>
1934
1938
  <t t-if="cf.rule.type==='IconSetRule'">
1935
1939
  <div
1936
- class="o-cf-preview-icon d-flex justify-content-around align-items-center me-2 bg-white">
1940
+ class="o-cf-preview-icon d-flex justify-content-around align-items-center me-2 bg-white border">
1937
1941
  <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.upper].template}}"/>
1938
1942
  <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.middle].template}}"/>
1939
1943
  <t t-call="o-spreadsheet-Icon.{{icons[cf.rule.icons.lower].template}}"/>
@@ -1942,7 +1946,7 @@
1942
1946
  <t t-else="">
1943
1947
  <div
1944
1948
  t-att-style="getPreviewImageStyle(cf.rule)"
1945
- class="o-cf-preview-icon d-flex justify-content-around align-items-center me-2 bg-white">
1949
+ class="o-cf-preview-icon d-flex justify-content-around align-items-center me-2 border">
1946
1950
  123
1947
1951
  </div>
1948
1952
  </t>
@@ -1971,7 +1975,7 @@
1971
1975
  <div class="o-section-subtitle">Icons</div>
1972
1976
  <div class="o-cf-iconsets d-flex flex-row">
1973
1977
  <div
1974
- class="o-cf-iconset o-cf-clickable-icon d-flex flex-row justify-content-between"
1978
+ class="o-cf-iconset o-cf-clickable-icon d-flex flex-row justify-content-between border rounded"
1975
1979
  t-foreach="['arrows', 'smiley', 'dots']"
1976
1980
  t-as="iconSet"
1977
1981
  t-key="iconSet"
@@ -1994,7 +1998,7 @@
1994
1998
  <tr>
1995
1999
  <td>
1996
2000
  <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-'+icon+'Icon', ev)">
1997
- <div class="o-cf-icon-button o-cf-clickable-icon me-3">
2001
+ <div class="o-cf-icon-button o-cf-clickable-icon me-3 border rounded">
1998
2002
  <t t-call="o-spreadsheet-Icon.{{icons[iconValue].template}}"/>
1999
2003
  </div>
2000
2004
  </div>
@@ -2077,7 +2081,7 @@
2077
2081
  <tr>
2078
2082
  <td>
2079
2083
  <div t-on-click.stop="(ev) => this.toggleMenu('iconSet-lowerIcon', ev)">
2080
- <div class="o-cf-icon-button o-cf-clickable-icon me-3">
2084
+ <div class="o-cf-icon-button o-cf-clickable-icon me-3 border rounded">
2081
2085
  <t t-call="o-spreadsheet-Icon.{{icons[rule.icons.lower].template}}"/>
2082
2086
  </div>
2083
2087
  </div>
@@ -2271,7 +2275,7 @@
2271
2275
 
2272
2276
  <t t-name="o-spreadsheet-CellIsRuleEditorPreview">
2273
2277
  <div
2274
- class="o-cf-preview-display"
2278
+ class="o-cf-preview-display border"
2275
2279
  t-attf-style="font-weight:{{currentStyle.bold ?'bold':'normal'}};
2276
2280
  text-decoration:{{getTextDecoration(currentStyle)}};
2277
2281
  font-style:{{currentStyle.italic?'italic':'normal'}};
@@ -2345,7 +2349,7 @@
2345
2349
  icon="'o-spreadsheet-Icon.TEXT_COLOR'"
2346
2350
  class="'o-hoverable-button o-menu-item-button'"
2347
2351
  />
2348
- <div class="o-divider"/>
2352
+ <div class="o-divider border-end"/>
2349
2353
  <ColorPickerWidget
2350
2354
  currentColor="rule.style.fillColor"
2351
2355
  toggleColorPicker="(ev) => this.toggleMenu('cellIsRule-fillColor', ev)"
@@ -2373,7 +2377,7 @@
2373
2377
 
2374
2378
  <t t-name="o-spreadsheet.RoundColorPicker">
2375
2379
  <div
2376
- class="o-round-color-picker-button rounded-circle"
2380
+ class="o-round-color-picker-button rounded-circle border"
2377
2381
  t-ref="colorPickerButton"
2378
2382
  t-on-click.stop="togglePicker"
2379
2383
  t-att-title="props.title"
@@ -2397,6 +2401,7 @@
2397
2401
  <t t-foreach="props.choices" t-as="choice" t-key="choice.value">
2398
2402
  <label class="o-radio d-flex align-items-center me-4">
2399
2403
  <input
2404
+ class="border rounded-circle"
2400
2405
  t-att-class="{
2401
2406
  'me-1': props.direction === 'horizontal',
2402
2407
  'me-2': props.direction === 'vertical'}"
@@ -2464,7 +2469,7 @@
2464
2469
  t-att-class="{'text-muted': props.disabled }"
2465
2470
  t-attf-class="{{props.className}}">
2466
2471
  <input
2467
- class="me-2 flex-shrink-0"
2472
+ class="me-2 flex-shrink-0 border"
2468
2473
  type="checkbox"
2469
2474
  t-att-disabled="props.disabled"
2470
2475
  t-att-name="props.name"
@@ -2965,7 +2970,7 @@
2965
2970
  </div>
2966
2971
 
2967
2972
  <t t-set="definition" t-value="getChartDefinition(this.chartId)"/>
2968
- <div class="o-panel-content overflow-y-auto" t-ref="panelContent">
2973
+ <div class="o-panel-content" t-ref="panelContent">
2969
2974
  <div t-att-class="store.panel !== 'configuration' ? 'd-none' : ''">
2970
2975
  <ChartTypePicker chartId="chartId" chartPanelStore="store"/>
2971
2976
  <t
@@ -3125,45 +3130,10 @@
3125
3130
 
3126
3131
  <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Geo chart options">
3127
3132
  <t t-set-slot="content">
3128
- <Section class="'pt-0 o-color-scale'" title.translate="Color Scale">
3129
- <select class="o-input" t-on-change="this.updateColorScaleType">
3130
- <option value="custom">Custom</option>
3131
- <hr/>
3132
- <t t-foreach="colorScalesChoices" t-as="colorScale" t-key="colorScale">
3133
- <option
3134
- t-att-value="colorScale"
3135
- t-esc="colorScale_value"
3136
- t-att-selected="colorScale === selectedColorScale"
3137
- />
3138
- </t>
3139
- </select>
3140
-
3141
- <t t-if="customColorScale">
3142
- <div class="o-min-color d-flex align-items-center mb-2 mt-4">
3143
- <RoundColorPicker
3144
- currentColor="getCustomColorScaleColor('minColor')"
3145
- onColorPicked="(color) => this.setCustomColorScaleColor('minColor', color)"
3146
- disableNoColor="true"
3147
- />
3148
- <span class="ps-2">Color of minimum values</span>
3149
- </div>
3150
- <div class="o-mid-color d-flex align-items-center mb-2">
3151
- <RoundColorPicker
3152
- currentColor="getCustomColorScaleColor('midColor')"
3153
- onColorPicked="(color) => this.setCustomColorScaleColor('midColor', color)"
3154
- />
3155
- <span class="ps-2">Color of middle values</span>
3156
- </div>
3157
- <div class="o-max-color d-flex align-items-center">
3158
- <RoundColorPicker
3159
- currentColor="getCustomColorScaleColor('maxColor')"
3160
- onColorPicked="(color) => this.setCustomColorScaleColor('maxColor', color)"
3161
- disableNoColor="true"
3162
- />
3163
- <span class="ps-2">Color of maximum values</span>
3164
- </div>
3165
- </t>
3166
- </Section>
3133
+ <ColorScalePicker
3134
+ definition="props.definition"
3135
+ onUpdateColorScale.bind="this.updateColorScale"
3136
+ />
3167
3137
 
3168
3138
  <Section class="'pt-0 o-missing-value'" title.translate="Countries without value">
3169
3139
  <RoundColorPicker
@@ -3874,6 +3844,120 @@
3874
3844
  <path fill="var(--os-chart-preview-orange-fill)" d="M32,17 h13 v25 h-13"/>
3875
3845
  </svg>
3876
3846
  </t>
3847
+ <t t-name="o-spreadsheet-ChartPreview.CALENDAR_CHART">
3848
+ <svg class="o-chart-preview" viewBox="0 0 48 48">
3849
+ <path fill="#444" d="M3 3h42v42H3zh1v41h40V4H4"/>
3850
+ <path
3851
+ fill="#eb6d00"
3852
+ d="M7 7h7v7H7m0 2h7v7H7m0 2h7v7H7m0 2h7v7H7m9-34h7v7h-7m0 2h7v7h-7m0 2h7v7h-7m0 2h7v7h-7m9-34h7v7h-7m0 11h7v7h-7m0 2h7v7h-7m9-34h7v7h-7m0 2h7v7h-7m0 2h7v7h-7m0 2h7v7h-7"
3853
+ />
3854
+ <path fill="#ffe1c8" d="M8 8h5v5H8m0 13h5v5H8m9 4h5v5h-5m18-5h5v5h-5"/>
3855
+ <path
3856
+ fill="#FFA85C"
3857
+ d="M8 17h5v5H8m9-14h5v5h-5m0 13h5v5h-5m9 4h5v5h-5m9-32h5v5h-5m0 13h5v5h-5"
3858
+ />
3859
+ <path fill="#fff" d="M8 35h5v5H8"/>
3860
+ <path fill="#A34C00" d="M25 16h7v7h-7"/>
3861
+ </svg>
3862
+ </t>
3863
+
3864
+ <t t-name="o-spreadsheet-CalendarChartDesignPanel">
3865
+ <GeneralDesignEditor t-props="props">
3866
+ <t t-set-slot="general-extension">
3867
+ <Section class="'pt-0'" title.translate="Legend position">
3868
+ <select
3869
+ t-att-value="props.definition.legendPosition ?? 'bottom-left'"
3870
+ class="o-input o-chart-legend-position"
3871
+ t-on-change="this.updateLegendPosition">
3872
+ <option value="none">None</option>
3873
+ <option value="right">Right</option>
3874
+ <option value="left">Left</option>
3875
+ </select>
3876
+ </Section>
3877
+ <Section class="'pt-0'" title.translate="Values">
3878
+ <ChartShowValues t-props="props"/>
3879
+ </Section>
3880
+ </t>
3881
+ </GeneralDesignEditor>
3882
+ <SidePanelCollapsible isInitiallyCollapsed="false" title.translate="Calendar chart options">
3883
+ <t t-set-slot="content">
3884
+ <ColorScalePicker definition="props.definition" onUpdateColorScale.bind="onColormapChange"/>
3885
+ <Section class="'pt-0 o-missing-value'" title.translate="Missing value color">
3886
+ <RoundColorPicker
3887
+ currentColor="selectedMissingValueColor"
3888
+ onColorPicked.bind="updateMissingValueColor"
3889
+ />
3890
+ </Section>
3891
+ </t>
3892
+ </SidePanelCollapsible>
3893
+ <SidePanelCollapsible isInitiallyCollapsed="true" title.translate="Axes">
3894
+ <t t-set-slot="content">
3895
+ <AxisDesignEditor
3896
+ axesList="axesList"
3897
+ chartId="props.chartId"
3898
+ definition="props.definition"
3899
+ updateChart="props.updateChart"
3900
+ />
3901
+ </t>
3902
+ </SidePanelCollapsible>
3903
+ </t>
3904
+
3905
+ <t t-name="o-spreadsheet-CalendarChartConfigPanel">
3906
+ <div>
3907
+ <ChartDataSeries
3908
+ ranges="this.getDataSeriesRanges()"
3909
+ onSelectionChanged.bind="onDataSeriesRangesChanged"
3910
+ onSelectionConfirmed.bind="onDataSeriesConfirmed"
3911
+ onSelectionReordered.bind="onDataSeriesReordered"
3912
+ onSelectionRemoved.bind="onDataSeriesRemoved"
3913
+ maxNumberOfUsedRanges="1"
3914
+ canChangeDatasetOrientation="false"
3915
+ />
3916
+ <ChartLabelRange
3917
+ range="this.getLabelRange()"
3918
+ isInvalid="isLabelInvalid"
3919
+ onSelectionChanged.bind="onLabelRangeChanged"
3920
+ onSelectionConfirmed.bind="onLabelRangeConfirmed"
3921
+ options="this.getLabelRangeOptions()"
3922
+ title.translate="Date range"
3923
+ />
3924
+
3925
+ <Section title.translate="Fields to group by">
3926
+ <div class="d-flex">
3927
+ <span class="w-100">Horizontal axis</span>
3928
+ <select
3929
+ t-att-value="getGroupByType('horizontal')"
3930
+ class="o-input o-horizontal-group-by"
3931
+ t-on-change="ev => this.updateGroupBy('horizontal', ev.target.value)">
3932
+ <t t-foreach="getGroupByOptions()" t-as="groupBy" t-key="groupBy.value">
3933
+ <option
3934
+ t-att-selected="getGroupByType('horizontal') === groupBy.value"
3935
+ t-att-value="groupBy.value">
3936
+ <t t-esc="groupBy.label"/>
3937
+ </option>
3938
+ </t>
3939
+ </select>
3940
+ </div>
3941
+ <div class="d-flex">
3942
+ <span class="w-100">Vertical axis</span>
3943
+ <select
3944
+ t-att-value="getGroupByType('vertical')"
3945
+ class="o-input o-vertical-group-by"
3946
+ t-on-change="ev => this.updateGroupBy('vertical', ev.target.value)">
3947
+ <t t-foreach="getGroupByOptions()" t-as="groupBy" t-key="groupBy.value">
3948
+ <option
3949
+ t-att-selected="getGroupByType('vertical') === groupBy.value"
3950
+ t-att-value="groupBy.value">
3951
+ <t t-esc="groupBy.label"/>
3952
+ </option>
3953
+ </t>
3954
+ </select>
3955
+ </div>
3956
+ </Section>
3957
+
3958
+ <ChartErrorSection t-if="errorMessages.length" messages="errorMessages"/>
3959
+ </div>
3960
+ </t>
3877
3961
 
3878
3962
  <t t-name="o-spreadsheet.TextStyler">
3879
3963
  <div
@@ -3881,7 +3965,10 @@
3881
3965
  t-att-class="props.class">
3882
3966
  <ActionButton action="boldButtonAction" class="'o-hoverable-button'"/>
3883
3967
  <ActionButton action="italicButtonAction" class="'o-hoverable-button'"/>
3884
- <div class="o-divider" t-if="props.hasHorizontalAlign || props.hasVerticalAlign"/>
3968
+ <div
3969
+ class="o-divider border-start"
3970
+ t-if="props.hasHorizontalAlign || props.hasVerticalAlign"
3971
+ />
3885
3972
  <div class="o-dropdown position-relative" t-if="props.hasHorizontalAlign">
3886
3973
  <ActionButton
3887
3974
  action="horizontalAlignButtonAction"
@@ -3920,13 +4007,13 @@
3920
4007
  </div>
3921
4008
  </div>
3922
4009
  </div>
3923
- <div class="o-divider"/>
4010
+ <div class="o-divider border-start"/>
3924
4011
  <FontSizeEditor
3925
4012
  currentFontSize="currentFontSize"
3926
4013
  onFontSizeChanged.bind="this.updateFontSize"
3927
4014
  class="'o-hoverable-button'"
3928
4015
  />
3929
- <div class="o-divider"/>
4016
+ <div class="o-divider border-start"/>
3930
4017
  <ColorPickerWidget
3931
4018
  currentColor="props.style.color ?? props.defaultStyle?.color"
3932
4019
  toggleColorPicker="(ev) => this.toggleDropdownTool('fillChartColorTool', ev)"
@@ -4251,6 +4338,85 @@
4251
4338
  </Section>
4252
4339
  </t>
4253
4340
 
4341
+ <t t-name="o-spreadsheet-ColorScalePicker">
4342
+ <Section class="'pt-0 o-color-scale'" title.translate="Color Scale">
4343
+ <div class="w-100" style="position:relative">
4344
+ <div
4345
+ class="color-scale-container d-flex justify-content-end"
4346
+ t-on-click.stop="onPointerDown">
4347
+ <span class="color-scale-label">
4348
+ <t t-esc="currentColorScaleLabel"/>
4349
+ </span>
4350
+ <div
4351
+ class="color-scale-preview w-100"
4352
+ t-att-data-test-colorscale="selectedColorScale"
4353
+ t-att-style="currentColorScaleStyle"
4354
+ />
4355
+ <span class="ms-1">
4356
+ <t t-call="o-spreadsheet-Icon.CARET_DOWN"/>
4357
+ </span>
4358
+ </div>
4359
+ <Popover t-if="state.popoverProps" t-props="state.popoverProps">
4360
+ <table t-ref="popoverRef" class="bg-white" t-att-style="state.popoverStyle">
4361
+ <tr
4362
+ class="color-scale-container custom-color-scale-container"
4363
+ t-on-click="() => this.onColorScaleChange('custom')">
4364
+ <td class="p-1 text-end">Custom</td>
4365
+ <td class="w-100 p-1">
4366
+ <div
4367
+ class="color-scale-preview o-checkers-background"
4368
+ data-test-id="custom-color-scale"
4369
+ />
4370
+ </td>
4371
+ </tr>
4372
+ <t t-foreach="colorScales" t-as="colorScale" t-key="colorScale.value">
4373
+ <tr
4374
+ class="color-scale-container"
4375
+ t-on-click="() => this.onColorScaleChange(colorScale.value)"
4376
+ t-att-title="colorScale.label">
4377
+ <td class="p-1 text-end">
4378
+ <t t-esc="colorScale.label"/>
4379
+ </td>
4380
+ <td class="w-100 p-1">
4381
+ <div
4382
+ class="color-scale-preview"
4383
+ t-att-data-test-id="colorScale.className"
4384
+ t-att-style="colorScalePreviewStyle(colorScale.value)"
4385
+ />
4386
+ </td>
4387
+ </tr>
4388
+ </t>
4389
+ </table>
4390
+ </Popover>
4391
+ </div>
4392
+ <div class="ps-3 mt-2">
4393
+ <div class="o-min-color d-flex align-items-center mb-2">
4394
+ <RoundColorPicker
4395
+ currentColor="currentColorScale.minColor"
4396
+ onColorPicked="(color) => this.setCustomColorScaleColor('minColor', color)"
4397
+ disableNoColor="true"
4398
+ />
4399
+ <span class="ps-2">Color of minimum values</span>
4400
+ </div>
4401
+ <div class="o-mid-color d-flex align-items-center mb-2">
4402
+ <RoundColorPicker
4403
+ currentColor="currentColorScale.midColor"
4404
+ onColorPicked="(color) => this.setCustomColorScaleColor('midColor', color)"
4405
+ />
4406
+ <span class="ps-2">Color of middle values</span>
4407
+ </div>
4408
+ <div class="o-max-color d-flex align-items-center">
4409
+ <RoundColorPicker
4410
+ currentColor="currentColorScale.maxColor"
4411
+ onColorPicked="(color) => this.setCustomColorScaleColor('maxColor', color)"
4412
+ disableNoColor="true"
4413
+ />
4414
+ <span class="ps-2">Color of maximum values</span>
4415
+ </div>
4416
+ </div>
4417
+ </Section>
4418
+ </t>
4419
+
4254
4420
  <t t-name="o-spreadsheet.ChartTitle">
4255
4421
  <Section class="'o-chart-title'" title="props.name">
4256
4422
  <TextInput
@@ -4574,7 +4740,7 @@
4574
4740
  class="o-number-editor d-flex align-items-center"
4575
4741
  t-att-class="props.class"
4576
4742
  t-att-title="props.title"
4577
- t-on-click="this.toggleList">
4743
+ t-on-click.stop="this.toggleList">
4578
4744
  <input
4579
4745
  type="number"
4580
4746
  t-att-min="props.min"
@@ -4640,7 +4806,7 @@
4640
4806
  t-on-click.stop=""
4641
4807
  t-on-contextmenu.prevent="">
4642
4808
  <t t-foreach="menuItemsAndSeparators" t-as="menuItem" t-key="menuItem_index">
4643
- <div t-if="menuItem === 'separator'" class="o-separator"/>
4809
+ <div t-if="menuItem === 'separator'" class="o-separator border-bottom"/>
4644
4810
  <t t-else="">
4645
4811
  <t t-set="isMenuRoot" t-value="isRoot(menuItem)"/>
4646
4812
  <t t-set="isMenuEnabled" t-value="isEnabled(menuItem)"/>
@@ -4689,7 +4855,7 @@
4689
4855
 
4690
4856
  <t t-name="o-spreadsheet-LinkEditor">
4691
4857
  <div
4692
- class="o-link-editor bg-white"
4858
+ class="o-link-editor bg-white rounded"
4693
4859
  t-on-click.stop="() => this.menu.isOpen=false"
4694
4860
  t-on-keydown="onKeyDown">
4695
4861
  <div class="o-section">
@@ -4754,7 +4920,7 @@
4754
4920
  </t>
4755
4921
 
4756
4922
  <t t-name="o-spreadsheet-LinkDisplay">
4757
- <div class="o-link-tool d-flex align-items-center bg-white">
4923
+ <div class="o-link-tool d-flex align-items-center bg-white rounded">
4758
4924
  <!-- t-key to prevent owl from re-using the previous img element when the link changes.
4759
4925
  The wrong/previous image would be displayed while the new one loads -->
4760
4926
  <img
@@ -5856,6 +6022,52 @@
5856
6022
  <i class="fa fa-moon-o"/>
5857
6023
  </div>
5858
6024
  </t>
6025
+ <t t-name="o-spreadsheet-Icon.ROTATION-0">
6026
+ <svg
6027
+ width="18"
6028
+ height="18"
6029
+ viewBox="0 0 18 18"
6030
+ transform="rotate(270)"
6031
+ xmlns="http://www.w3.org/2000/svg">
6032
+ <path
6033
+ d="M5 2h1v12h1.5l-2 2-2-2H5m6-5h1v5h1.5l-2 2-2-2H11M8 2l7 2.8V6L8 8.8l-.43-1.12 1.9-.7V3.8l-1.9-.7L8 1.98m2.7 2.25v2.3l2.8-1.1z"
6034
+ fill="currentColor"
6035
+ />
6036
+ </svg>
6037
+ </t>
6038
+ <t t-name="o-spreadsheet-Icon.ROTATION-45">
6039
+ <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
6040
+ <path
6041
+ d="m1.95 6.879.707-.707 8.485 8.485 1.06-1.06v2.828H9.375l1.061-1.061m.706-7.778.707-.707 3.536 3.535 1.06-1.06v2.828h-2.828l1.06-1.06M4.071 4.757l6.93-2.97.848.849-2.97 6.93-1.096-.488.849-1.839-2.249-2.248-1.838.848-.488-1.096m3.5-.318 1.626 1.626 1.203-2.757z"
6042
+ fill="currentColor"
6043
+ />
6044
+ </svg>
6045
+ </t>
6046
+ <t t-name="o-spreadsheet-Icon.ROTATION-90">
6047
+ <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
6048
+ <path
6049
+ d="M5 2h1v12h1.5l-2 2-2-2H5m6-5h1v5h1.5l-2 2-2-2H11M8 2l7 2.8V6L8 8.8l-.43-1.12 1.9-.7V3.8l-1.9-.7L8 1.98m2.7 2.25v2.3l2.8-1.1z"
6050
+ fill="currentColor"
6051
+ />
6052
+ </svg>
6053
+ </t>
6054
+
6055
+ <t t-name="o-spreadsheet-Icon.ROTATION-270">
6056
+ <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
6057
+ <path
6058
+ d="M13 16h-1V4h-1.5l2-2 2 2H13M7 9H6V4H4.5l2-2 2 2H7m3 12-7-2.8V12l7-2.8.43 1.12-1.9.7v3.18l1.9.7-.43 1.12m-2.7-2.25v-2.3l-2.8 1.1z"
6059
+ fill="currentColor"
6060
+ />
6061
+ </svg>
6062
+ </t>
6063
+ <t t-name="o-spreadsheet-Icon.ROTATION-315">
6064
+ <svg width="18" height="18" viewBox="0 0 18 18" xmlns="http://www.w3.org/2000/svg">
6065
+ <path
6066
+ d="m6.879 16.55-.707-.707 8.485-8.485-1.06-1.06h2.828v2.828l-1.061-1.061m-7.778-.707-.707-.707 3.535-3.536-1.06-1.06h2.828v2.828l-1.06-1.06M4.757 14.429l-2.97-6.93.849-.848 6.93 2.97-.488 1.096-1.839-.849-2.248 2.249.848 1.838-1.096.488m-.318-3.5 1.626-1.626-2.757-1.203z"
6067
+ fill="currentColor"
6068
+ />
6069
+ </svg>
6070
+ </t>
5859
6071
 
5860
6072
  <t t-name="o-spreadsheet-IconPicker">
5861
6073
  <div class="o-icon-picker bg-white">
@@ -6024,7 +6236,6 @@
6024
6236
  t-on-mouseleave="onMouseLeave"
6025
6237
  t-on-pointerdown.self.prevent="select"
6026
6238
  t-on-click="onClick"
6027
- t-on-pointerup.self="onMouseUp"
6028
6239
  t-on-contextmenu.self="onContextMenu"
6029
6240
  t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving}">
6030
6241
  <div
@@ -6068,7 +6279,6 @@
6068
6279
  t-on-mouseleave="onMouseLeave"
6069
6280
  t-on-pointerdown.self.prevent="select"
6070
6281
  t-on-click="onClick"
6071
- t-on-pointerup.self="onMouseUp"
6072
6282
  t-on-contextmenu.self="onContextMenu"
6073
6283
  t-att-class="{'o-grab': state.waitingForMove, 'o-dragging': state.isMoving, }">
6074
6284
  <div
@@ -6246,7 +6456,8 @@
6246
6456
  <button
6247
6457
  t-on-click="onConfirm"
6248
6458
  t-att-disabled="state.errorFlag"
6249
- class="o-button flex-grow-0 me-2">
6459
+ class="o-button flex-grow-0 me-2"
6460
+ tabindex="-1">
6250
6461
  Add
6251
6462
  </button>
6252
6463
  <input
@@ -6258,6 +6469,7 @@
6258
6469
  t-on-keydown.stop="onKeydown"
6259
6470
  t-on-pointerdown.stop=""
6260
6471
  t-on-input.stop="onInput"
6472
+ tabindex="-1"
6261
6473
  />
6262
6474
  <span>more rows at the bottom</span>
6263
6475
  <ValidationMessages t-if="state.errorFlag" messages="errorMessages" msgType="'error'"/>
@@ -6329,7 +6541,7 @@
6329
6541
  </t>
6330
6542
  <VerticalScrollBar topOffset="HEADER_HEIGHT"/>
6331
6543
  <HorizontalScrollBar leftOffset="HEADER_WIDTH"/>
6332
- <div class="o-scrollbar corner"/>
6544
+ <div class="o-scrollbar corner border-top border-start"/>
6333
6545
  </div>
6334
6546
  </t>
6335
6547
 
@@ -6399,7 +6611,7 @@
6399
6611
  </i>
6400
6612
  </div>
6401
6613
  <div
6402
- class="o-filter-menu-list d-flex flex-column"
6614
+ class="o-filter-menu-list d-flex flex-column border"
6403
6615
  t-ref="filterValueList"
6404
6616
  t-on-click="this.clearScrolledToValue"
6405
6617
  t-on-scroll="this.clearScrolledToValue">
@@ -6484,7 +6696,7 @@
6484
6696
  </div>
6485
6697
  </t>
6486
6698
  <div class="o-filter-menu-content">
6487
- <div class="o-separator"/>
6699
+ <div class="o-separator border-bottom"/>
6488
6700
  <SidePanelCollapsible
6489
6701
  isInitiallyCollapsed="filterValueType !== 'criterion'"
6490
6702
  title.translate="Filter by criterion">
@@ -6910,7 +7122,7 @@
6910
7122
  <t t-name="o-spreadsheet-TopBarComposer">
6911
7123
  <div class="o-topbar-composer-container w-100">
6912
7124
  <div
6913
- class="o-topbar-composer position-relative bg-white user-select-text d-flex"
7125
+ class="o-topbar-composer position-relative bg-white user-select-text d-flex border"
6914
7126
  t-att-class="{
6915
7127
  'o-topbar-composer-readonly': env.model.getters.isReadonly(),
6916
7128
  'o-topbar-composer-active': focus !== 'inactive',
@@ -6933,7 +7145,7 @@
6933
7145
 
6934
7146
  <t t-name="o-spreadsheet-StandaloneComposer">
6935
7147
  <div
6936
- class="o-standalone-composer"
7148
+ class="o-standalone-composer border-bottom"
6937
7149
  t-on-click.stop=""
6938
7150
  t-att-class="containerClass"
6939
7151
  t-att-title="props.title">
@@ -6950,7 +7162,7 @@
6950
7162
 
6951
7163
  <t t-name="o-spreadsheet-SpeechBubble">
6952
7164
  <t t-portal="'.o-spreadsheet'">
6953
- <div class="o-speech-bubble position-absolute px-3" t-ref="bubble">
7165
+ <div class="o-speech-bubble position-absolute px-3 border" t-ref="bubble">
6954
7166
  <div class="o-speech-content text-truncate pb-1" t-esc="props.content"/>
6955
7167
  </div>
6956
7168
  </t>
@@ -6958,7 +7170,7 @@
6958
7170
 
6959
7171
  <t t-name="o-spreadsheet-GridComposer">
6960
7172
  <div
6961
- class="o-cell-reference"
7173
+ class="o-cell-reference rounded"
6962
7174
  t-if="shouldDisplayCellReference"
6963
7175
  t-att-style="cellReferenceStyle"
6964
7176
  t-esc="cellReference"
@@ -6969,7 +7181,13 @@
6969
7181
  </t>
6970
7182
 
6971
7183
  <t t-name="o-spreadsheet-FunctionDescriptionProvider">
6972
- <div class="o-formula-assistant-container user-select-none shadow">
7184
+ <div
7185
+ class="o-formula-assistant-container shadow"
7186
+ tabindex="-1"
7187
+ t-on-pointerdown=""
7188
+ t-on-pointerup.stop=""
7189
+ t-on-keydown.stop=""
7190
+ t-on-click.stop="">
6973
7191
  <t t-set="context" t-value="getContext()"/>
6974
7192
  <div class="o-formula-assistant bg-white" t-if="context.functionDescription.name">
6975
7193
  <div class="o-formula-assistant-head d-flex flex-row justify-content-between">
@@ -6984,6 +7202,7 @@
6984
7202
  <div
6985
7203
  class="collapsor px-2 d-flex align-items-center rounded"
6986
7204
  t-att-class="state.isCollapsed ? 'collapsed' : ''"
7205
+ t-on-pointerdown.prevent=""
6987
7206
  t-on-click="() => this.toggle()">
6988
7207
  <span class="collapsor-arrow d-inline-block">
6989
7208
  <t t-call="o-spreadsheet-Icon.ANGLE_DOWN"/>
@@ -6992,7 +7211,7 @@
6992
7211
  </div>
6993
7212
 
6994
7213
  <Collapse isCollapsed="state.isCollapsed">
6995
- <div class="o-formula-assistant-core pb-3 m-3">
7214
+ <div class="o-formula-assistant-core pb-3 m-3 border-bottom">
6996
7215
  <div class="o-formula-assistant-gray">ABOUT</div>
6997
7216
  <div t-esc="context.functionDescription.description"/>
6998
7217
  </div>
@@ -7030,7 +7249,7 @@
7030
7249
  </t>
7031
7250
 
7032
7251
  <t t-name="o-spreadsheet-Composer">
7033
- <div class="o-composer-container w-100 h-100">
7252
+ <div class="o-composer-container w-100 h-100" t-ref="composerContainer">
7034
7253
  <t t-set="autoCompleteProposals" t-value="props.composerStore.autoCompleteProposals"/>
7035
7254
  <t t-set="canBeToggled" t-value="props.composerStore.canBeToggled"/>
7036
7255
  <t
@@ -7042,10 +7261,9 @@
7042
7261
  t-if="props.focus !== 'inactive' and assistantIsAvailable and canBeToggled and assistant.forcedClosed"
7043
7262
  role="button"
7044
7263
  title="Show formula help"
7045
- t-on-click="openAssistant"
7264
+ t-on-click.stop="openAssistant"
7046
7265
  t-on-pointerdown.prevent.stop=""
7047
- t-on-click.prevent.stop=""
7048
- t-on-pointerup.prevent.stop=""
7266
+ t-on-pointerup.stop=""
7049
7267
  class="fa-stack position-absolute translate-middle force-open-assistant fs-4">
7050
7268
  <i class="fa fa-circle fa-stack-1x fa-inverse"/>
7051
7269
  <i class="fa fa-question-circle fa-stack-1x"/>
@@ -7081,13 +7299,14 @@
7081
7299
  t-att-style="assistantContainerStyle"
7082
7300
  t-if="props.focus !== 'inactive' and assistantIsAvailable and !(canBeToggled and assistant.forcedClosed)"
7083
7301
  t-on-wheel.stop=""
7084
- t-on-pointerdown.prevent.stop=""
7085
- t-on-pointerup.prevent.stop=""
7086
- t-on-click.prevent.stop="">
7302
+ t-on-pointerdown.stop=""
7303
+ t-on-pointerup.stop=""
7304
+ t-on-click.stop="">
7087
7305
  <span
7088
7306
  t-if="canBeToggled and !assistant.forcedClosed"
7089
7307
  role="button"
7090
7308
  t-on-click="closeAssistant"
7309
+ t-on-pointerdown.prevent.stop=""
7091
7310
  class="fa-stack position-absolute top-0 start-100 translate-middle fs-4">
7092
7311
  <i class="fa fa-circle fa-stack-1x fa-inverse"/>
7093
7312
  <i class="fa fa-times-circle fa-stack-1x"/>
@@ -7123,6 +7342,7 @@
7123
7342
  <t t-name="o-spreadsheet-TextValueProvider">
7124
7343
  <div
7125
7344
  t-ref="autoCompleteList"
7345
+ t-on-pointerdown.prevent=""
7126
7346
  t-att-class="{
7127
7347
  'o-autocomplete-dropdown bg-white': props.proposals.length}">
7128
7348
  <t t-foreach="props.proposals" t-as="proposal" t-key="proposal.text + proposal_index">
@@ -7196,7 +7416,7 @@
7196
7416
  </div>
7197
7417
  </div>
7198
7418
  </div>
7199
- <div class="o-separator"/>
7419
+ <div class="o-separator border-bottom"/>
7200
7420
  <div
7201
7421
  class="o-color-picker-section-name o-color-picker-toggler"
7202
7422
  t-on-click="toggleColorPicker">
@@ -7235,7 +7455,7 @@
7235
7455
  <div class="magnifier pe-none" t-att-style="pointerStyle"/>
7236
7456
  </div>
7237
7457
  <div class="o-hue-container" t-on-pointerdown="dragHuePointer">
7238
- <div class="o-hue-picker" t-on-click.stop=""/>
7458
+ <div class="o-hue-picker border rounded" t-on-click.stop=""/>
7239
7459
  <div class="o-hue-slider pe-none" t-att-style="sliderStyle">
7240
7460
  <t t-call="o-spreadsheet-Icon.CARET_UP"/>
7241
7461
  </div>
@@ -7243,16 +7463,17 @@
7243
7463
  <div class="o-custom-input-preview">
7244
7464
  <input
7245
7465
  type="text"
7466
+ class="border rounded"
7246
7467
  t-att-class="{'o-wrong-color': !isHexColorInputValid }"
7247
7468
  t-on-click.stop=""
7248
7469
  t-att-value="state.customHexColor"
7249
7470
  t-on-input="setHexColor"
7250
7471
  />
7251
- <div class="o-color-preview" t-att-style="colorPreviewStyle"/>
7472
+ <div class="o-color-preview border rounded" t-att-style="colorPreviewStyle"/>
7252
7473
  </div>
7253
7474
  <div class="o-custom-input-buttons">
7254
7475
  <button
7255
- class="o-add-button"
7476
+ class="o-add-button border rounded"
7256
7477
  t-att-class="{'o-disabled': !state.customHexColor or !isHexColorInputValid}"
7257
7478
  t-on-click.stop="addCustomColor">
7258
7479
  Add
@@ -7260,9 +7481,9 @@
7260
7481
  </div>
7261
7482
  </div>
7262
7483
  <t t-if="!props.disableNoColor">
7263
- <div class="o-separator"/>
7484
+ <div class="o-separator border-bottom"/>
7264
7485
  <div class="o-buttons">
7265
- <button t-on-click="resetColor" class="o-cancel">No Color</button>
7486
+ <button t-on-click="resetColor" class="o-cancel border rounded">No Color</button>
7266
7487
  </div>
7267
7488
  </t>
7268
7489
  </div>
@@ -7275,7 +7496,7 @@
7275
7496
 
7276
7497
  <t t-name="o-spreadsheet-BottomBar">
7277
7498
  <div
7278
- class="o-spreadsheet-bottom-bar o-two-columns d-flex flex-fill align-items-center overflow-hidden"
7499
+ class="o-spreadsheet-bottom-bar o-two-columns d-flex flex-fill align-items-center overflow-hidden border-top"
7279
7500
  t-on-click="props.onClick"
7280
7501
  t-ref="bottomBar"
7281
7502
  t-on-contextmenu.prevent="">
@@ -7387,13 +7608,14 @@
7387
7608
  <t t-name="o-spreadsheet-BottomBarSheet">
7388
7609
  <Ripple>
7389
7610
  <div
7390
- class="o-sheet d-flex align-items-center user-select-none text-nowrap "
7611
+ class="o-sheet d-flex align-items-center user-select-none text-nowrap border-start border-end"
7391
7612
  tabindex="-1"
7392
7613
  composerFocusableElement="true"
7393
7614
  t-on-pointerdown="(ev) => this.onMouseDown(ev)"
7394
7615
  t-on-click="onClick"
7395
7616
  t-on-contextmenu.prevent="(ev) => this.onContextMenu(ev)"
7396
7617
  t-ref="sheetDiv"
7618
+ t-key="sheetName"
7397
7619
  t-att-style="props.style"
7398
7620
  t-att-title="sheetName"
7399
7621
  t-att-data-id="props.sheetId"
@@ -7481,7 +7703,7 @@
7481
7703
  </span>
7482
7704
  </div>
7483
7705
  </div>
7484
- <div class="o-divider"/>
7706
+ <div class="o-divider border-end"/>
7485
7707
  <div class="o-border-selector-section">
7486
7708
  <div
7487
7709
  class="m-0 p-0 d-flex align-items-center justify-content-center o-with-color o-hoverable-button"