@formicoidea/labre-core 1.1.0 → 2.1.0

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.
Files changed (185) hide show
  1. package/architecture/code.c4 +37 -34
  2. package/dist/_pkgs/affine-components/context-menu/input.d.ts +6 -0
  3. package/dist/_pkgs/affine-components/context-menu/input.js +3 -0
  4. package/dist/_pkgs/affine-components/context-menu/menu-all.d.ts +1 -0
  5. package/dist/_pkgs/affine-components/context-menu/menu-renderer.d.ts +3 -1
  6. package/dist/_pkgs/affine-components/context-menu/menu-renderer.js +9 -1
  7. package/dist/_pkgs/affine-components/context-menu/menu.d.ts +7 -0
  8. package/dist/_pkgs/affine-components/context-menu/menu.js +5 -0
  9. package/dist/_pkgs/affine-components/context-menu/sub-menu.d.ts +16 -1
  10. package/dist/_pkgs/affine-components/context-menu/sub-menu.js +32 -5
  11. package/dist/_pkgs/affine-database-block/configs/slash-menu.js +14 -6
  12. package/dist/_pkgs/affine-database-block/database-block-styles.js +4 -3
  13. package/dist/_pkgs/affine-database-block/database-block.js +6 -18
  14. package/dist/_pkgs/affine-database-block/database-dnd-preview-block.js +5 -1
  15. package/dist/_pkgs/affine-database-block/detail-panel/block-renderer.js +5 -2
  16. package/dist/_pkgs/affine-database-block/detail-panel/note-renderer.js +3 -2
  17. package/dist/_pkgs/affine-database-block/external-data-source.d.ts +10 -0
  18. package/dist/_pkgs/affine-database-block/external-data-source.js +24 -0
  19. package/dist/_pkgs/affine-database-block/properties/created-time/define.js +3 -1
  20. package/dist/_pkgs/affine-database-block/properties/link/cell-renderer.js +3 -2
  21. package/dist/_pkgs/affine-database-block/properties/link/define.js +3 -1
  22. package/dist/_pkgs/affine-database-block/properties/rich-text/define.js +3 -1
  23. package/dist/_pkgs/affine-database-block/properties/text/hosted.js +1 -0
  24. package/dist/_pkgs/affine-database-block/properties/title/define.js +3 -1
  25. package/dist/_pkgs/affine-database-block/properties/title/hosted.js +1 -0
  26. package/dist/_pkgs/affine-database-block/service/new-row-menu.d.ts +1 -1
  27. package/dist/_pkgs/affine-database-block/service/new-row-menu.js +1 -1
  28. package/dist/_pkgs/affine-database-block/translations.d.ts +11 -0
  29. package/dist/_pkgs/affine-database-block/translations.js +57 -0
  30. package/dist/_pkgs/affine-database-block/views/index.d.ts +7 -9
  31. package/dist/_pkgs/affine-database-block/views/index.js +7 -10
  32. package/dist/_pkgs/affine-database-engine/core/common/properties.js +7 -7
  33. package/dist/_pkgs/affine-database-engine/core/common/property-menu.d.ts +18 -2
  34. package/dist/_pkgs/affine-database-engine/core/common/property-menu.js +78 -27
  35. package/dist/_pkgs/affine-database-engine/core/data-source/base.d.ts +11 -0
  36. package/dist/_pkgs/affine-database-engine/core/data-source/base.js +3 -0
  37. package/dist/_pkgs/affine-database-engine/core/detail/detail.js +8 -5
  38. package/dist/_pkgs/affine-database-engine/core/detail/field.js +14 -7
  39. package/dist/_pkgs/affine-database-engine/core/filter/add-filter.js +4 -2
  40. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/boolean.js +7 -4
  41. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/create.d.ts +9 -1
  42. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/create.js +2 -0
  43. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/date.js +7 -4
  44. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/multi-tag.js +17 -8
  45. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/number.js +6 -6
  46. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/string.js +19 -12
  47. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/tag.js +9 -4
  48. package/dist/_pkgs/affine-database-engine/core/filter/filter-fn/unknown.js +7 -4
  49. package/dist/_pkgs/affine-database-engine/core/filter/literal/define.js +6 -4
  50. package/dist/_pkgs/affine-database-engine/core/filter/literal/matcher.d.ts +2 -1
  51. package/dist/_pkgs/affine-database-engine/core/filter/literal/matcher.js +3 -2
  52. package/dist/_pkgs/affine-database-engine/core/filter/literal/types.d.ts +4 -1
  53. package/dist/_pkgs/affine-database-engine/core/filter/literal/types.js +1 -1
  54. package/dist/_pkgs/affine-database-engine/core/group-by/define.js +11 -9
  55. package/dist/_pkgs/affine-database-engine/core/group-by/group-title.js +16 -6
  56. package/dist/_pkgs/affine-database-engine/core/group-by/locate-row.d.ts +16 -0
  57. package/dist/_pkgs/affine-database-engine/core/group-by/locate-row.js +32 -0
  58. package/dist/_pkgs/affine-database-engine/core/group-by/renderer/date-group.js +10 -3
  59. package/dist/_pkgs/affine-database-engine/core/group-by/setting.d.ts +2 -0
  60. package/dist/_pkgs/affine-database-engine/core/group-by/setting.js +40 -28
  61. package/dist/_pkgs/affine-database-engine/core/group-by/trait.d.ts +3 -0
  62. package/dist/_pkgs/affine-database-engine/core/group-by/trait.js +8 -0
  63. package/dist/_pkgs/affine-database-engine/core/group-by/types.d.ts +3 -1
  64. package/dist/_pkgs/affine-database-engine/core/group-by/types.js +1 -1
  65. package/dist/_pkgs/affine-database-engine/core/property/types.d.ts +7 -0
  66. package/dist/_pkgs/affine-database-engine/core/property/types.js +1 -1
  67. package/dist/_pkgs/affine-database-engine/core/sort/add-sort.js +3 -1
  68. package/dist/_pkgs/affine-database-engine/core/statistics/any.js +43 -21
  69. package/dist/_pkgs/affine-database-engine/core/statistics/checkbox.js +29 -14
  70. package/dist/_pkgs/affine-database-engine/core/statistics/number.js +54 -31
  71. package/dist/_pkgs/affine-database-engine/core/statistics/types.d.ts +8 -0
  72. package/dist/_pkgs/affine-database-engine/core/statistics/types.js +2 -1
  73. package/dist/_pkgs/affine-database-engine/core/utils/wording.d.ts +20 -1
  74. package/dist/_pkgs/affine-database-engine/core/utils/wording.js +24 -0
  75. package/dist/_pkgs/affine-database-engine/core/view-manager/property.d.ts +7 -0
  76. package/dist/_pkgs/affine-database-engine/core/view-manager/property.js +29 -5
  77. package/dist/_pkgs/affine-database-engine/core/view-manager/single-view.d.ts +14 -0
  78. package/dist/_pkgs/affine-database-engine/core/view-manager/single-view.js +11 -0
  79. package/dist/_pkgs/affine-database-engine/property-presets/checkbox/define.js +3 -1
  80. package/dist/_pkgs/affine-database-engine/property-presets/date/define.js +3 -1
  81. package/dist/_pkgs/affine-database-engine/property-presets/multi-select/define.js +3 -1
  82. package/dist/_pkgs/affine-database-engine/property-presets/number/define.js +3 -1
  83. package/dist/_pkgs/affine-database-engine/property-presets/number/utils/formats.d.ts +3 -0
  84. package/dist/_pkgs/affine-database-engine/property-presets/number/utils/formats.js +56 -9
  85. package/dist/_pkgs/affine-database-engine/property-presets/progress/define.js +3 -1
  86. package/dist/_pkgs/affine-database-engine/property-presets/select/define.js +3 -1
  87. package/dist/_pkgs/affine-database-engine/property-presets/text/define.js +3 -1
  88. package/dist/_pkgs/affine-database-engine/translations.d.ts +133 -5
  89. package/dist/_pkgs/affine-database-engine/translations.js +625 -9
  90. package/dist/_pkgs/affine-database-engine/view-presets/convert.js +0 -28
  91. package/dist/_pkgs/affine-database-engine/view-presets/effect.js +0 -2
  92. package/dist/_pkgs/affine-database-engine/view-presets/flat/flat-converts.js +2 -4
  93. package/dist/_pkgs/affine-database-engine/view-presets/flat/flat-view-ui.d.ts +57 -0
  94. package/dist/_pkgs/affine-database-engine/view-presets/flat/flat-view-ui.js +113 -4
  95. package/dist/_pkgs/affine-database-engine/view-presets/gallery/gallery-view.js +2 -1
  96. package/dist/_pkgs/affine-database-engine/view-presets/index.d.ts +0 -2
  97. package/dist/_pkgs/affine-database-engine/view-presets/index.js +0 -3
  98. package/dist/_pkgs/affine-database-engine/view-presets/kanban/kanban-view-manager.js +2 -0
  99. package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/group.js +7 -5
  100. package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/kanban-view-ui-logic.d.ts +5 -0
  101. package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/kanban-view-ui-logic.js +25 -3
  102. package/dist/_pkgs/affine-database-engine/view-presets/kanban/mobile/menu.js +12 -6
  103. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/controller/selection.d.ts +8 -0
  104. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/controller/selection.js +35 -12
  105. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/group.js +7 -5
  106. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/header.js +5 -1
  107. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/kanban-view-ui-logic.d.ts +5 -0
  108. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/kanban-view-ui-logic.js +8 -4
  109. package/dist/_pkgs/affine-database-engine/view-presets/kanban/pc/menu.js +12 -6
  110. package/dist/_pkgs/affine-database-engine/view-presets/list/list-view.js +2 -1
  111. package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/column-header.js +6 -4
  112. package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/group.js +6 -5
  113. package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/header.js +2 -2
  114. package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/table-view-ui-logic.d.ts +4 -3
  115. package/dist/_pkgs/affine-database-engine/view-presets/table/mobile/table-view-ui-logic.js +29 -5
  116. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/controller/clipboard.js +6 -2
  117. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/controller/selection.js +2 -0
  118. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/group.js +6 -5
  119. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/header/column-header.js +11 -7
  120. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/header/database-header-column.js +16 -12
  121. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/header/number-format-bar.js +4 -2
  122. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/menu.js +9 -6
  123. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/table-view-ui-logic.d.ts +8 -1
  124. package/dist/_pkgs/affine-database-engine/view-presets/table/pc/table-view-ui-logic.js +29 -7
  125. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/controller/clipboard.js +6 -2
  126. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/controller/selection.js +2 -0
  127. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/bottom/group-footer.js +5 -2
  128. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/bottom/stats/column-stats-column.d.ts +1 -1
  129. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/bottom/stats/column-stats-column.js +14 -6
  130. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/group-header.js +5 -2
  131. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/group-title.js +5 -3
  132. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/header/column-header.js +17 -10
  133. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/header/number-format-bar.js +4 -2
  134. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/group/top/header/single-column-header.js +20 -14
  135. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/row/menu.js +9 -6
  136. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/table-view-ui-logic.d.ts +6 -1
  137. package/dist/_pkgs/affine-database-engine/view-presets/table/pc-virtual/table-view-ui-logic.js +30 -3
  138. package/dist/_pkgs/affine-database-engine/view-presets/table/stats/column-stats-column.d.ts +1 -1
  139. package/dist/_pkgs/affine-database-engine/view-presets/table/stats/column-stats-column.js +14 -6
  140. package/dist/_pkgs/affine-database-engine/view-presets/table/table-view-manager.js +2 -0
  141. package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/condition-view.d.ts +2 -0
  142. package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/condition-view.js +13 -6
  143. package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/group-panel-view.js +20 -13
  144. package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/filter/root-panel-view.js +10 -5
  145. package/dist/_pkgs/affine-database-engine/widget-presets/quick-setting-bar/sort/root-panel.js +8 -5
  146. package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/search/search.js +2 -2
  147. package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/table-add-row/add-row.d.ts +6 -0
  148. package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/table-add-row/add-row.js +49 -4
  149. package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/view-options/view-settings.d.ts +3 -3
  150. package/dist/_pkgs/affine-database-engine/widget-presets/tools/presets/view-options/view-settings.js +3 -3
  151. package/dist/_pkgs/affine-database-engine/widget-presets/views-bar/views-view.js +5 -0
  152. package/dist/_pkgs/affine-database-view-block/configs/slash-menu.js +6 -3
  153. package/dist/_pkgs/affine-database-view-block/data-view-block.js +5 -4
  154. package/dist/_pkgs/affine-fragment-doc-title/doc-title.d.ts +3 -2
  155. package/dist/_pkgs/affine-fragment-doc-title/doc-title.js +3 -2
  156. package/dist/_pkgs/affine-shared/services/data-source-picker-service.d.ts +67 -2
  157. package/package.json +1 -1
  158. package/dist/_pkgs/affine-database-engine/view-presets/calendar/calendar-view-manager.d.ts +0 -70
  159. package/dist/_pkgs/affine-database-engine/view-presets/calendar/calendar-view-manager.js +0 -449
  160. package/dist/_pkgs/affine-database-engine/view-presets/calendar/define.d.ts +0 -10
  161. package/dist/_pkgs/affine-database-engine/view-presets/calendar/define.js +0 -29
  162. package/dist/_pkgs/affine-database-engine/view-presets/calendar/effect.d.ts +0 -1
  163. package/dist/_pkgs/affine-database-engine/view-presets/calendar/effect.js +0 -4
  164. package/dist/_pkgs/affine-database-engine/view-presets/calendar/index.d.ts +0 -6
  165. package/dist/_pkgs/affine-database-engine/view-presets/calendar/index.js +0 -6
  166. package/dist/_pkgs/affine-database-engine/view-presets/calendar/layout.d.ts +0 -37
  167. package/dist/_pkgs/affine-database-engine/view-presets/calendar/layout.js +0 -138
  168. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/actions.d.ts +0 -7
  169. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/actions.js +0 -64
  170. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/dnd.d.ts +0 -32
  171. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/dnd.js +0 -159
  172. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/effect.d.ts +0 -1
  173. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/effect.js +0 -7
  174. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/hit-test.d.ts +0 -1
  175. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/hit-test.js +0 -28
  176. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/styles.d.ts +0 -1
  177. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/styles.js +0 -707
  178. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/view.d.ts +0 -89
  179. package/dist/_pkgs/affine-database-engine/view-presets/calendar/pc/view.js +0 -849
  180. package/dist/_pkgs/affine-database-engine/view-presets/calendar/renderer.d.ts +0 -2
  181. package/dist/_pkgs/affine-database-engine/view-presets/calendar/renderer.js +0 -8
  182. package/dist/_pkgs/affine-database-engine/view-presets/calendar/source.d.ts +0 -8
  183. package/dist/_pkgs/affine-database-engine/view-presets/calendar/source.js +0 -3
  184. package/dist/_pkgs/affine-database-engine/view-presets/calendar/types.d.ts +0 -79
  185. package/dist/_pkgs/affine-database-engine/view-presets/calendar/types.js +0 -1
@@ -5,10 +5,11 @@ import { cssVarV2 } from '@toeverything/theme/v2';
5
5
  import { styleMap } from 'lit/directives/style-map.js';
6
6
  import { html } from 'lit/static-html.js';
7
7
  import { dv } from '../../../core/common/dv-css.js';
8
+ import { locateRow } from '../../../core/group-by/locate-row.js';
8
9
  import { groupTraitKey, } from '../../../core/group-by/trait.js';
9
10
  import { createUniComponentFromWebComponent, renderUniLit, } from '../../../core/index.js';
10
11
  import { DataViewUIBase, DataViewUILogicBase, } from '../../../core/view/data-view-base.js';
11
- import { TableViewRowSelection, } from '../../index.js';
12
+ import { TableViewAreaSelection, TableViewRowSelection, } from '../../index.js';
12
13
  import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
13
14
  import { TableClipboardController } from './controller/clipboard.js';
14
15
  import { TableDragController } from './controller/drag.js';
@@ -21,6 +22,8 @@ import { TableRowHeader } from './row/row-header.js';
21
22
  import { TableRowLast } from './row/row-last.js';
22
23
  import * as styles from './table-view-css.js';
23
24
  import { getScrollContainer, GridVirtualScroll, } from './virtual/virtual-scroll.js';
25
+ import { DATA_VIEW_GROUP_NEW } from '../../../translations.js';
26
+ import { wordingFrom } from '../../../core/utils/wording.js';
24
27
  export class VirtualTableViewUILogic extends DataViewUILogicBase {
25
28
  constructor() {
26
29
  super(...arguments);
@@ -72,8 +75,32 @@ export class VirtualTableViewUILogic extends DataViewUILogicBase {
72
75
  this.clearSelection = () => {
73
76
  this.selectionController.clear();
74
77
  };
78
+ /**
79
+ * "New" adds the row and puts its title in editing, as the table's own
80
+ * "New record" footer does: it no longer opens the row (product owner,
81
+ * recette P3-15). Nothing is written but the row.
82
+ */
75
83
  this.addRow = (position) => {
76
- return this.view.rowAdd(position);
84
+ if (this.view.readonly$.peek())
85
+ return;
86
+ const rowId = this.view.rowAdd(position);
87
+ if (!rowId)
88
+ return;
89
+ requestAnimationFrame(() => {
90
+ const view = this.view;
91
+ const at = locateRow(view.groupTrait, view.rows$.peek(), rowId);
92
+ const columnIndex = view.properties$
93
+ .peek()
94
+ .findIndex(property => property.type$.peek() === 'title');
95
+ if (!at || columnIndex < 0)
96
+ return;
97
+ this.selectionController.selection = TableViewAreaSelection.create({
98
+ groupKey: at.groupKey,
99
+ focus: { rowIndex: at.rowIndex, columnIndex },
100
+ isEditing: true,
101
+ });
102
+ });
103
+ return rowId;
77
104
  };
78
105
  this.focusFirstCell = () => {
79
106
  this.selectionController.focusFirstCell();
@@ -132,7 +159,7 @@ export class VirtualTableViewUILogic extends DataViewUILogicBase {
132
159
  return html ` <div style="display:flex;">
133
160
  <div class="${dv.hover} ${dv.round8} ${styles.addGroup}" @click="${add}">
134
161
  <div class="${dv.icon16}" style="display:flex;">${AddCursorIcon()}</div>
135
- <div>New Group</div>
162
+ <div>${wordingFrom(this.ui$.value)(DATA_VIEW_GROUP_NEW)}</div>
136
163
  </div>
137
164
  </div>`;
138
165
  };
@@ -12,7 +12,7 @@ export declare class DatabaseColumnStatsCell extends DatabaseColumnStatsCell_bas
12
12
  statsFunc$: import("@preact/signals-core").ReadonlySignal<StatisticsConfig | undefined>;
13
13
  values$: import("@preact/signals-core").Signal<unknown[]>;
14
14
  statsResult$: import("@preact/signals-core").ReadonlySignal<{
15
- name: string | undefined;
15
+ name: string;
16
16
  value: string;
17
17
  } | null>;
18
18
  subscriptionMap: Map<unknown, () => void>;
@@ -44,6 +44,9 @@ import { property } from 'lit/decorators.js';
44
44
  import { styleMap } from 'lit/directives/style-map.js';
45
45
  import { typeSystem, VALUES_PENDING_MARK, valuesReady, } from '../../../core/index.js';
46
46
  import { statsFunctions } from '../../../core/statistics/index.js';
47
+ import { sayLabel, wordingFrom } from '../../../core/utils/wording.js';
48
+ import { DATA_VIEW_STATS_CALCULATE } from '../../../translations.js';
49
+ import { LINE_STYLE_NONE } from '../../../../affine-components/translations.js';
47
50
  const styles = css `
48
51
  .stats-cell {
49
52
  cursor: pointer;
@@ -158,7 +161,8 @@ let DatabaseColumnStatsCell = (() => {
158
161
  >
159
162
  <div class="content">
160
163
  ${!this.statsResult$.value
161
- ? html `Calculate ${ArrowDownSmallIcon()}`
164
+ ? html `${wordingFrom(this)(DATA_VIEW_STATS_CALCULATE)}
165
+ ${ArrowDownSmallIcon()}`
162
166
  : html `
163
167
  <span class="label">${this.statsResult$.value.name}</span>
164
168
  <span class="value">${this.statsResult$.value.value} </span>
@@ -205,14 +209,15 @@ let DatabaseColumnStatsCell = (() => {
205
209
  return groups;
206
210
  });
207
211
  this.openMenu = (ev) => {
212
+ const wording = wordingFrom(this);
208
213
  const menus = Object.entries(this.groups$.value).map(([group, funcs]) => {
209
214
  return menu.subMenu({
210
- name: group,
215
+ name: sayLabel(wording, group, Object.values(funcs)[0]?.groupWording),
211
216
  options: {
212
217
  items: Object.values(funcs).map(func => {
213
218
  return menu.action({
214
219
  isSelected: func.type === this.column.statCalcOp$.value,
215
- name: func.menuName ?? func.type,
220
+ name: sayLabel(wording, func.menuName ?? func.type, func.menuWording),
216
221
  select: () => {
217
222
  this.column.updateStatCalcOp(func.type);
218
223
  },
@@ -226,7 +231,7 @@ let DatabaseColumnStatsCell = (() => {
226
231
  items: [
227
232
  menu.action({
228
233
  isSelected: !this.column.statCalcOp$.value,
229
- name: 'None',
234
+ name: wording(LINE_STYLE_NONE),
230
235
  select: () => {
231
236
  this.column.updateStatCalcOp();
232
237
  },
@@ -256,14 +261,17 @@ let DatabaseColumnStatsCell = (() => {
256
261
  return null;
257
262
  }
258
263
  const dataSource = this.column.view.manager.dataSource;
264
+ const wording = wordingFrom(this);
265
+ const name = sayLabel(wording, func.displayName ?? '', func.displayWording);
259
266
  if (!valuesReady(dataSource)) {
260
- return { name: func.displayName, value: VALUES_PENDING_MARK };
267
+ return { name, value: VALUES_PENDING_MARK };
261
268
  }
262
269
  return {
263
- name: func.displayName,
270
+ name,
264
271
  value: func.impl?.(this.values$.value, {
265
272
  meta,
266
273
  dataSource: this.column.view.manager.dataSource,
274
+ wording,
267
275
  }) ?? '',
268
276
  };
269
277
  });
@@ -124,6 +124,8 @@ export class TableSingleView extends SingleViewBase {
124
124
  }
125
125
  rowAdd(insertPosition, groupKey) {
126
126
  const id = super.rowAdd(insertPosition);
127
+ if (!id)
128
+ return id;
127
129
  const filter = this.filter$.value;
128
130
  if (filter.conditions.length > 0) {
129
131
  const defaultValues = generateDefaultValues(filter, this.vars$.value);
@@ -6,6 +6,8 @@ import type { Filter, SingleFilter } from '../../../core/filter/types.js';
6
6
  import { type TypeInstance } from '../../../core/index.js';
7
7
  declare const FilterConditionView_base: typeof ShadowlessElement;
8
8
  export declare class FilterConditionView extends FilterConditionView_base {
9
+ /** The words of the editor this condition is drawn in; English outside. */
10
+ private get wording();
9
11
  static styles: import("lit").CSSResult;
10
12
  private readonly onClickButton;
11
13
  private readonly popConditionEdit;
@@ -43,6 +43,9 @@ import { getRefType } from '../../../core/expression/ref/ref.js';
43
43
  import { filterMatcher } from '../../../core/filter/filter-fn/matcher.js';
44
44
  import { literalItemsMatcher } from '../../../core/filter/literal/index.js';
45
45
  import { renderUniLit, t, typeSystem, } from '../../../core/index.js';
46
+ import { TOOLBAR_DELETE } from '../../../../affine-shared/services/index.js';
47
+ import { sayLabel, wordingFrom, } from '../../../core/utils/wording.js';
48
+ import { DATA_VIEW_FILTER_INVALID } from '../../../translations.js';
46
49
  let FilterConditionView = (() => {
47
50
  let _classSuper = SignalWatcher(ShadowlessElement);
48
51
  let _value_decorators;
@@ -70,6 +73,10 @@ let FilterConditionView = (() => {
70
73
  __esDecorate(this, null, _onChange_decorators, { kind: "accessor", name: "onChange", static: false, private: false, access: { has: obj => "onChange" in obj, get: obj => obj.onChange, set: (obj, value) => { obj.onChange = value; } }, metadata: _metadata }, _onChange_initializers, _onChange_extraInitializers);
71
74
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
72
75
  }
76
+ /** The words of the editor this condition is drawn in; English outside. */
77
+ get wording() {
78
+ return wordingFrom(this);
79
+ }
73
80
  static { this.styles = css `
74
81
  filter-condition-view {
75
82
  }
@@ -141,7 +148,7 @@ let FilterConditionView = (() => {
141
148
  ...filter,
142
149
  args: args,
143
150
  });
144
- });
151
+ }, this.wording);
145
152
  }
146
153
  getArgsItems() {
147
154
  return (this.fnType$.value?.args
@@ -153,7 +160,7 @@ let FilterConditionView = (() => {
153
160
  if (!leftVar) {
154
161
  return html ` <data-view-component-button
155
162
  hoverType="border"
156
- .text="${html `Invalid filter rule`}"
163
+ .text="${this.wording(DATA_VIEW_FILTER_INVALID)}"
157
164
  ></data-view-component-button>`;
158
165
  }
159
166
  return html `
@@ -196,7 +203,7 @@ let FilterConditionView = (() => {
196
203
  menu.group({
197
204
  items: [
198
205
  menu.action({
199
- name: fn.label,
206
+ name: sayLabel(this.wording, fn.label, fn.labelWording),
200
207
  postfix: ArrowRightSmallIcon(),
201
208
  select: ele => {
202
209
  popMenu(popupTargetFromElement(ele), {
@@ -220,7 +227,7 @@ let FilterConditionView = (() => {
220
227
  menu.group({
221
228
  items: [
222
229
  menu.action({
223
- name: 'Delete',
230
+ name: this.wording(TOOLBAR_DELETE),
224
231
  class: { 'delete-item': true },
225
232
  prefix: DeleteIcon(),
226
233
  select: () => {
@@ -275,7 +282,7 @@ let FilterConditionView = (() => {
275
282
  return filterMatcher.filterListBySelfType(type).map(v => {
276
283
  const selected = v.name === filter.function;
277
284
  return menu.action({
278
- name: v.label,
285
+ name: sayLabel(this.wording, v.label, v.labelWording),
279
286
  isSelected: selected,
280
287
  select: () => {
281
288
  this.setFilter({
@@ -312,7 +319,7 @@ let FilterConditionView = (() => {
312
319
  return undefined;
313
320
  return { value: v, type: argType };
314
321
  });
315
- const valueString = data.shortString?.(...argDataList) ?? '';
322
+ const valueString = data.shortString?.(this.wording, ...argDataList) ?? '';
316
323
  if (valueString) {
317
324
  return `${name}${valueString}`;
318
325
  }
@@ -43,10 +43,13 @@ import { property, state } from 'lit/decorators.js';
43
43
  import { classMap } from 'lit/directives/class-map.js';
44
44
  import { repeat } from 'lit/directives/repeat.js';
45
45
  import { firstFilter, firstFilterInGroup } from '../../../core/filter/utils.js';
46
+ import { DATA_VIEW_FILTER_AND, DATA_VIEW_FILTER_OR, DATA_VIEW_FILTER_TURN_INTO_GROUP, DATA_VIEW_FILTER_WRAP_IN_GROUP, DATA_VIEW_FILTER_WHERE, DATA_VIEW_ADD_FILTER, DATA_VIEW_FILTER_ADD_GROUP, DATA_VIEW_FILTER_GROUP, } from '../../../translations.js';
47
+ import { TOOLBAR_DUPLICATE, TOOLBAR_DELETE, } from '../../../../affine-shared/services/index.js';
48
+ import { wordingFrom } from '../../../core/utils/wording.js';
46
49
  export const popAddNewFilter = (target, props) => {
47
50
  popFilterableSimpleMenu(target, [
48
51
  menu.action({
49
- name: 'Add filter',
52
+ name: wordingFrom(target.element)(DATA_VIEW_ADD_FILTER),
50
53
  select: () => {
51
54
  props.onChange({
52
55
  ...props.value,
@@ -55,7 +58,7 @@ export const popAddNewFilter = (target, props) => {
55
58
  },
56
59
  }),
57
60
  menu.action({
58
- name: 'Add filter group',
61
+ name: wordingFrom(target.element)(DATA_VIEW_FILTER_ADD_GROUP),
59
62
  select: () => {
60
63
  props.onChange({
61
64
  ...props.value,
@@ -239,7 +242,9 @@ let FilterGroupView = (() => {
239
242
  menu.group({
240
243
  items: [
241
244
  menu.action({
242
- name: filter.type === 'filter' ? 'Turn into group' : 'Wrap in group',
245
+ name: wordingFrom(this)(filter.type === 'filter'
246
+ ? DATA_VIEW_FILTER_TURN_INTO_GROUP
247
+ : DATA_VIEW_FILTER_WRAP_IN_GROUP),
243
248
  prefix: ConvertIcon(),
244
249
  onHover: hover => {
245
250
  this.containerClass = hover
@@ -256,7 +261,7 @@ let FilterGroupView = (() => {
256
261
  },
257
262
  }),
258
263
  menu.action({
259
- name: 'Duplicate',
264
+ name: wordingFrom(this)(TOOLBAR_DUPLICATE),
260
265
  prefix: DuplicateIcon(),
261
266
  onHover: hover => {
262
267
  this.containerClass = hover
@@ -278,7 +283,7 @@ let FilterGroupView = (() => {
278
283
  name: '',
279
284
  items: [
280
285
  menu.action({
281
- name: 'Delete',
286
+ name: wordingFrom(this)(TOOLBAR_DELETE),
282
287
  prefix: DeleteIcon(),
283
288
  class: { 'delete-item': true },
284
289
  onHover: hover => {
@@ -311,7 +316,9 @@ let FilterGroupView = (() => {
311
316
  };
312
317
  let op;
313
318
  if (i === 0) {
314
- op = html ` <div class="filter-group-op">Where</div>`;
319
+ op = html ` <div class="filter-group-op">
320
+ ${wordingFrom(this)(DATA_VIEW_FILTER_WHERE)}
321
+ </div>`;
315
322
  }
316
323
  else {
317
324
  op = html `
@@ -319,7 +326,7 @@ let FilterGroupView = (() => {
319
326
  class="filter-group-op filter-group-op-clickable"
320
327
  @click="${this._selectOp}"
321
328
  >
322
- ${this.opMap[data.op]}
329
+ ${wordingFrom(this)(this.opMap[data.op])}
323
330
  </div>
324
331
  `;
325
332
  }
@@ -402,7 +409,7 @@ let FilterGroupView = (() => {
402
409
  this._selectOp = (event) => {
403
410
  popFilterableSimpleMenu(popupTargetFromElement(event.currentTarget), [
404
411
  menu.action({
405
- name: 'And',
412
+ name: wordingFrom(this)(DATA_VIEW_FILTER_AND),
406
413
  select: () => {
407
414
  this.onChange({
408
415
  ...this.filterGroup.value,
@@ -411,7 +418,7 @@ let FilterGroupView = (() => {
411
418
  },
412
419
  }),
413
420
  menu.action({
414
- name: 'Or',
421
+ name: wordingFrom(this)(DATA_VIEW_FILTER_OR),
415
422
  select: () => {
416
423
  this.onChange({
417
424
  ...this.filterGroup.value,
@@ -428,8 +435,8 @@ let FilterGroupView = (() => {
428
435
  });
429
436
  };
430
437
  this.opMap = {
431
- and: 'And',
432
- or: 'Or',
438
+ and: DATA_VIEW_FILTER_AND,
439
+ or: DATA_VIEW_FILTER_OR,
433
440
  };
434
441
  this.#filterGroup_accessor_storage = __runInitializers(this, _filterGroup_initializers, void 0);
435
442
  this.conditions$ = (__runInitializers(this, _filterGroup_extraInitializers), computed(() => {
@@ -460,7 +467,7 @@ export const popFilterGroup = (target, props) => {
460
467
  popMenu(target, {
461
468
  options: {
462
469
  title: {
463
- text: 'Filter group',
470
+ text: wordingFrom(target.element)(DATA_VIEW_FILTER_GROUP),
464
471
  onBack: props.onBack,
465
472
  },
466
473
  items: [
@@ -478,7 +485,7 @@ export const popFilterGroup = (target, props) => {
478
485
  menu.group({
479
486
  items: [
480
487
  menu.action({
481
- name: 'Delete',
488
+ name: wordingFrom(target.element)(TOOLBAR_DELETE),
482
489
  class: { 'delete-item': true },
483
490
  prefix: DeleteIcon(),
484
491
  select: () => {
@@ -43,6 +43,9 @@ import { classMap } from 'lit/directives/class-map.js';
43
43
  import { repeat } from 'lit/directives/repeat.js';
44
44
  import { popCreateFilter, } from '../../../core/index.js';
45
45
  import { getDepth, popFilterGroup, } from './group-panel-view.js';
46
+ import { TOOLBAR_DUPLICATE, TOOLBAR_DELETE, } from '../../../../affine-shared/services/index.js';
47
+ import { wordingFrom } from '../../../core/utils/wording.js';
48
+ import { DATA_VIEW_FILTERS, DATA_VIEW_FILTER_TURN_INTO_GROUP, DATA_VIEW_FILTER_WRAP_IN_GROUP, DATA_VIEW_GROUP_ADD, } from '../../../translations.js';
46
49
  let FilterRootView = (() => {
47
50
  let _classSuper = SignalWatcher(ShadowlessElement);
48
51
  let _filterGroup_decorators;
@@ -208,7 +211,9 @@ let FilterRootView = (() => {
208
211
  }
209
212
  popFilterableSimpleMenu(popupTargetFromElement(target), [
210
213
  menu.action({
211
- name: filter.type === 'filter' ? 'Turn into group' : 'Wrap in group',
214
+ name: wordingFrom(this)(filter.type === 'filter'
215
+ ? DATA_VIEW_FILTER_TURN_INTO_GROUP
216
+ : DATA_VIEW_FILTER_WRAP_IN_GROUP),
212
217
  prefix: ConvertIcon(),
213
218
  onHover: hover => {
214
219
  this.containerClass = hover
@@ -225,7 +230,7 @@ let FilterRootView = (() => {
225
230
  },
226
231
  }),
227
232
  menu.action({
228
- name: 'Duplicate',
233
+ name: wordingFrom(this)(TOOLBAR_DUPLICATE),
229
234
  prefix: DuplicateIcon(),
230
235
  onHover: hover => {
231
236
  this.containerClass = hover
@@ -242,7 +247,7 @@ let FilterRootView = (() => {
242
247
  name: '',
243
248
  items: [
244
249
  menu.action({
245
- name: 'Delete',
250
+ name: wordingFrom(this)(TOOLBAR_DELETE),
246
251
  prefix: DeleteIcon(),
247
252
  class: { 'delete-item': true },
248
253
  onHover: hover => {
@@ -398,7 +403,7 @@ export const popFilterRoot = (target, props) => {
398
403
  popMenu(target, {
399
404
  options: {
400
405
  title: {
401
- text: 'Filters',
406
+ text: wordingFrom(target.element)(DATA_VIEW_FILTERS),
402
407
  onBack: props.onBack,
403
408
  },
404
409
  items: [
@@ -417,7 +422,7 @@ export const popFilterRoot = (target, props) => {
417
422
  menu.group({
418
423
  items: [
419
424
  menu.action({
420
- name: 'Add',
425
+ name: wordingFrom(target.element)(DATA_VIEW_GROUP_ADD),
421
426
  prefix: PlusIcon(),
422
427
  select: ele => {
423
428
  const value = filterTrait.filter$.value;
@@ -48,6 +48,9 @@ import { dragHandler } from '../../../core/utils/wc-dnd/dnd-context.js';
48
48
  import { defaultActivators } from '../../../core/utils/wc-dnd/sensors/index.js';
49
49
  import { createSortContext, sortable, } from '../../../core/utils/wc-dnd/sort/sort-context.js';
50
50
  import { verticalListSortingStrategy } from '../../../core/utils/wc-dnd/sort/strategies/index.js';
51
+ import { DATA_VIEW_SORT_ADD, DATA_VIEW_SORT_ASC, DATA_VIEW_SORT_DESC, DATA_VIEW_SORT_INVALID, } from '../../../translations.js';
52
+ import { TOOLBAR_DELETE } from '../../../../affine-shared/services/index.js';
53
+ import { wordingFrom } from '../../../core/utils/wording.js';
51
54
  let SortRootView = (() => {
52
55
  let _classSuper = SignalWatcher(WithDisposable(ShadowlessElement));
53
56
  let _sortUtils_decorators;
@@ -123,12 +126,12 @@ let SortRootView = (() => {
123
126
  <data-view-component-button
124
127
  style="color: var(--affine-error-color);border-color: color: var(--affine-error-color)"
125
128
  @click="${deleteRule}"
126
- .text="${html `This rule is invalid, click to delete`}"
129
+ .text="${wordingFrom(this)(DATA_VIEW_SORT_INVALID)}"
127
130
  ></data-view-component-button>
128
131
  `;
129
132
  }
130
133
  else {
131
- const descName = sort.desc ? 'Descending' : 'Ascending';
134
+ const descName = wordingFrom(this)(sort.desc ? DATA_VIEW_SORT_DESC : DATA_VIEW_SORT_ASC);
132
135
  const clickField = (event) => {
133
136
  popMenu(popupTargetFromElement(event.currentTarget), {
134
137
  options: {
@@ -153,7 +156,7 @@ let SortRootView = (() => {
153
156
  options: {
154
157
  items: [false, true].map(desc => {
155
158
  return menu.action({
156
- name: desc ? 'Descending' : 'Ascending',
159
+ name: wordingFrom(this)(desc ? DATA_VIEW_SORT_DESC : DATA_VIEW_SORT_ASC),
157
160
  isSelected: desc === sort.desc,
158
161
  select: () => {
159
162
  changeRule({ ...sort, desc });
@@ -217,7 +220,7 @@ export const popSortRoot = (target, props) => {
217
220
  ></sort-root-view>`;
218
221
  },
219
222
  menu.action({
220
- name: 'Add sort',
223
+ name: wordingFrom(this)(DATA_VIEW_SORT_ADD),
221
224
  prefix: PlusIcon(),
222
225
  select: ele => {
223
226
  popCreateSort(popupTargetFromElement(ele), {
@@ -227,7 +230,7 @@ export const popSortRoot = (target, props) => {
227
230
  },
228
231
  }),
229
232
  menu.action({
230
- name: 'Delete',
233
+ name: wordingFrom(this)(TOOLBAR_DELETE),
231
234
  class: { 'delete-item': true },
232
235
  prefix: DeleteIcon(),
233
236
  select: () => {
@@ -44,7 +44,7 @@ import { styleMap } from 'lit/directives/style-map.js';
44
44
  import { stopPropagation } from '../../../../core/utils/event.js';
45
45
  import { wordingOf } from '../../../../core/utils/wording.js';
46
46
  import { WidgetBase } from '../../../../core/widget/widget-base.js';
47
- import { DATA_VIEW_SEARCH_CLEAR_HINT, DATA_VIEW_SEARCH_PLACEHOLDER, } from '../../../../translations.js';
47
+ import { DATA_VIEW_SEARCH_CLEAR_HINT, DATA_VIEW_SEARCH_PLACEHOLDER, DATA_VIEW_SEARCH_ESCAPE, } from '../../../../translations.js';
48
48
  const styles = css `
49
49
  .affine-database-search-container {
50
50
  position: relative;
@@ -198,7 +198,7 @@ let DataViewHeaderToolsSearch = (() => {
198
198
  borderRadius: '4px',
199
199
  background: 'var(--affine-white-10)',
200
200
  })}
201
- >Esc</span
201
+ >${wordingOf(this.std)(DATA_VIEW_SEARCH_ESCAPE)}</span
202
202
  >
203
203
  ${wordingOf(this.std)(DATA_VIEW_SEARCH_CLEAR_HINT)}
204
204
  </affine-tooltip>
@@ -7,6 +7,12 @@ export declare class DataViewHeaderToolsAddRow extends WidgetBase {
7
7
  /** Absent outside an editor host: the wordings read English. */
8
8
  accessor std: BlockStdScope;
9
9
  private get readonly$();
10
+ /**
11
+ * The host locked new rows of this source (ADR 0035 amendment of
12
+ * 2026-10-29): "New" stays where it was, disabled, with the reason, and
13
+ * its menu (the host's templates) goes, since applying one adds a row.
14
+ */
15
+ private renderLocked;
10
16
  render(): import("lit-html").TemplateResult<1> | undefined;
11
17
  }
12
18
  declare global {
@@ -37,11 +37,11 @@ import { IS_MOBILE } from '../../../../../global/env/index.js';
37
37
  import { ArrowDownSmallIcon, PlusIcon } from '@blocksuite/icons/lit';
38
38
  import { stdContext } from '../../../../../std/index.js';
39
39
  import { consume } from '@lit/context';
40
- import { css, html } from 'lit';
40
+ import { css, html, nothing } from 'lit';
41
41
  import { wordingOf } from '../../../../core/utils/wording.js';
42
42
  import { NewRowMenuOpenerKey } from '../../../../core/view-manager/new-row-menu-opener.js';
43
43
  import { WidgetBase } from '../../../../core/widget/widget-base.js';
44
- import { DATA_VIEW_NEW_PAGE, DATA_VIEW_NEW_RECORD, } from '../../../../translations.js';
44
+ import { DATA_VIEW_NEW_PAGE, DATA_VIEW_NEW_RECORD, DATA_VIEW_ROWS_LOCKED, } from '../../../../translations.js';
45
45
  const styles = css `
46
46
  .new-record {
47
47
  font-weight: 500;
@@ -87,6 +87,28 @@ const styles = css `
87
87
  color: ${unsafeCSSVarV2('icon/primary')};
88
88
  }
89
89
 
90
+ .new-record-locked {
91
+ display: flex;
92
+ align-items: center;
93
+ gap: 4px;
94
+ padding: 2px 8px;
95
+ border: none;
96
+ border-radius: 4px;
97
+ background: transparent;
98
+ color: ${unsafeCSSVarV2('text/disable')};
99
+ font-size: 14px;
100
+ cursor: not-allowed;
101
+ }
102
+
103
+ .new-record-phone.new-record-locked {
104
+ padding: 0;
105
+ background-color: ${unsafeCSSVarV2('button/disable')};
106
+ }
107
+
108
+ .new-record-locked svg {
109
+ color: inherit;
110
+ }
111
+
90
112
  /* A split button only when the host offers a menu beside "New"
91
113
  (NewRowMenuOpenerKey): without it, the single button above. */
92
114
  .new-record-split {
@@ -138,11 +160,34 @@ let DataViewHeaderToolsAddRow = (() => {
138
160
  get readonly$() {
139
161
  return this.view.readonly$;
140
162
  }
163
+ /**
164
+ * The host locked new rows of this source (ADR 0035 amendment of
165
+ * 2026-10-29): "New" stays where it was, disabled, with the reason, and
166
+ * its menu (the host's templates) goes, since applying one adds a row.
167
+ */
168
+ renderLocked(wording) {
169
+ const hint = wording(DATA_VIEW_ROWS_LOCKED);
170
+ return html `<button
171
+ class="${IS_MOBILE ? 'new-record-phone' : 'new-record'} new-record-locked"
172
+ data-testid="dv-tools-new-row-locked"
173
+ aria-disabled="true"
174
+ aria-label="${hint}"
175
+ title="${hint}"
176
+ >
177
+ ${PlusIcon()}${IS_MOBILE
178
+ ? nothing
179
+ : html `<span style="font-weight: 500"
180
+ >${wording(DATA_VIEW_NEW_RECORD)}</span
181
+ >`}
182
+ </button>`;
183
+ }
141
184
  render() {
142
185
  if (this.readonly$.value) {
143
186
  return;
144
187
  }
145
188
  const wording = wordingOf(this.std);
189
+ if (this.view.rowsLocked$.value)
190
+ return this.renderLocked(wording);
146
191
  const button = IS_MOBILE
147
192
  ? html `<button
148
193
  class="new-record-phone"
@@ -184,13 +229,13 @@ let DataViewHeaderToolsAddRow = (() => {
184
229
  constructor() {
185
230
  super(...arguments);
186
231
  this.onAddNewRecord = () => {
187
- if (this.readonly$.value)
232
+ if (this.readonly$.value || this.view.rowsLocked$.value)
188
233
  return;
189
234
  this.dataViewLogic.addRow?.('start');
190
235
  };
191
236
  this.onOpenMenu = (event) => {
192
237
  event.stopPropagation();
193
- if (this.readonly$.value)
238
+ if (this.readonly$.value || this.view.rowsLocked$.value)
194
239
  return;
195
240
  this.view
196
241
  .serviceGet(NewRowMenuOpenerKey)
@@ -16,9 +16,9 @@ export type ViewSettingKey = 'layout' | 'properties' | 'group' | 'open-in' | 'co
16
16
  /**
17
17
  * Whether the current view offers `key`: grouping needs the group trait,
18
18
  * "Open pages in" a source whose rows are pages (B8), conditional colours
19
- * the filter trait, whose conditions a rule is made of (ADR 0036; the
20
- * calendar has none, and paints no rule). A read-only or
21
- * fallback view offers nothing: its settings menu is not drawn either.
19
+ * the filter trait, whose conditions a rule is made of (ADR 0036). A
20
+ * read-only or fallback view offers nothing: its settings menu is not drawn
21
+ * either.
22
22
  */
23
23
  export declare function viewSettingAvailable(dataViewLogic: DataViewUILogicBase, key: ViewSettingKey): boolean;
24
24
  /** The current "Open pages in" choice, with its wording, for a postfix. */
@@ -21,9 +21,9 @@ const OPEN_IN_CHOICES = [
21
21
  /**
22
22
  * Whether the current view offers `key`: grouping needs the group trait,
23
23
  * "Open pages in" a source whose rows are pages (B8), conditional colours
24
- * the filter trait, whose conditions a rule is made of (ADR 0036; the
25
- * calendar has none, and paints no rule). A read-only or
26
- * fallback view offers nothing: its settings menu is not drawn either.
24
+ * the filter trait, whose conditions a rule is made of (ADR 0036). A
25
+ * read-only or fallback view offers nothing: its settings menu is not drawn
26
+ * either.
27
27
  */
28
28
  export function viewSettingAvailable(dataViewLogic, key) {
29
29
  const view = dataViewLogic.view;
@@ -82,12 +82,17 @@ let DataViewHeaderViews = (() => {
82
82
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
83
83
  }
84
84
  static { this.styles = css `
85
+ /* The bar hangs its first tab's inset into the gutter: the tab keeps
86
+ its 4px padding for its hover background, and its icon lines up with
87
+ the database title and the rows above and below (labre recette of
88
+ 1.1: the icon sat 4px right of both). */
85
89
  data-view-header-views {
86
90
  height: 28px;
87
91
  display: flex;
88
92
  user-select: none;
89
93
  gap: 4px;
90
94
  min-width: 0;
95
+ margin-left: -4px;
91
96
  }
92
97
  data-view-header-views.mobile {
93
98
  height: ${VIEWS_BAR_TOUCH_TARGET}px;