@formicoidea/labre-core 0.54.0 → 0.56.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 (31) hide show
  1. package/architecture/code.c4 +7547 -0
  2. package/architecture/likec4.config.json +3 -0
  3. package/architecture/model.c4 +128 -0
  4. package/dist/_pkgs/data-view/translations.d.ts +0 -2
  5. package/dist/_pkgs/data-view/translations.js +0 -6
  6. package/dist/_pkgs/data-view/view-presets/flat/flat-view-ui.d.ts +3 -1
  7. package/dist/_pkgs/data-view/view-presets/flat/flat-view-ui.js +5 -1
  8. package/dist/_pkgs/data-view/view-presets/kanban/mobile/card.d.ts +6 -0
  9. package/dist/_pkgs/data-view/view-presets/kanban/mobile/card.js +11 -0
  10. package/dist/_pkgs/data-view/view-presets/kanban/mobile/cell.js +9 -10
  11. package/dist/_pkgs/data-view/view-presets/kanban/mobile/kanban-view-ui-logic.js +3 -0
  12. package/dist/_pkgs/data-view/view-presets/table/mobile/cell.js +7 -4
  13. package/dist/_pkgs/data-view/view-presets/table/mobile/group.js +11 -8
  14. package/dist/_pkgs/data-view/view-presets/table/mobile/header.d.ts +8 -2
  15. package/dist/_pkgs/data-view/view-presets/table/mobile/header.js +47 -15
  16. package/dist/_pkgs/data-view/view-presets/table/mobile/menu.d.ts +3 -1
  17. package/dist/_pkgs/data-view/view-presets/table/mobile/menu.js +7 -3
  18. package/dist/_pkgs/data-view/view-presets/table/mobile/row.d.ts +23 -1
  19. package/dist/_pkgs/data-view/view-presets/table/mobile/row.js +131 -57
  20. package/dist/_pkgs/data-view/view-presets/table/mobile/table-view-ui-logic.d.ts +5 -1
  21. package/dist/_pkgs/data-view/view-presets/table/mobile/table-view-ui-logic.js +9 -2
  22. package/dist/_pkgs/data-view/view-presets/table/pc/row/row.js +5 -1
  23. package/dist/_pkgs/data-view/widget-presets/quick-setting-bar/filter/index.js +1 -2
  24. package/dist/_pkgs/data-view/widget-presets/quick-setting-bar/index.js +8 -8
  25. package/dist/_pkgs/data-view/widget-presets/tools/presets/filter/filter.d.ts +3 -0
  26. package/dist/_pkgs/data-view/widget-presets/tools/presets/filter/filter.js +125 -60
  27. package/dist/_pkgs/data-view/widget-presets/tools/presets/sort/sort.d.ts +3 -0
  28. package/dist/_pkgs/data-view/widget-presets/tools/presets/sort/sort.js +131 -66
  29. package/dist/_pkgs/data-view/widget-presets/tools/presets/table-add-row/add-row.js +49 -10
  30. package/dist/_pkgs/store/model/store/query.js +13 -1
  31. package/package.json +3 -2
@@ -33,24 +33,42 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
33
33
  return useValue ? value : void 0;
34
34
  };
35
35
  import { popupTargetFromElement } from '../../../../affine-components/context-menu/index.js';
36
- import { unsafeCSSVarV2 } from '../../../../affine-shared/theme/index.js';
36
+ import { OPEN_LABEL } from '../../../../affine-components/translations.js';
37
37
  import { SignalWatcher, WithDisposable } from '../../../../global/lit/index.js';
38
- import { CenterPeekIcon, MoreHorizontalIcon } from '@blocksuite/icons/lit';
39
- import { ShadowlessElement } from '../../../../std/index.js';
38
+ import { ShadowlessElement, stdContext } from '../../../../std/index.js';
39
+ import { consume } from '@lit/context';
40
40
  import { cssVarV2 } from '@toeverything/theme/v2';
41
41
  import { css, nothing, unsafeCSS } from 'lit';
42
42
  import { property } from 'lit/decorators.js';
43
43
  import { repeat } from 'lit/directives/repeat.js';
44
44
  import { styleMap } from 'lit/directives/style-map.js';
45
45
  import { html } from 'lit/static-html.js';
46
+ import { wordingOf } from '../../../core/utils/wording.js';
46
47
  import { paintRowColor, ROW_COLOR_PROPERTY, viewRowColor, } from '../../../core/view/color-rules.js';
47
48
  import { cellDivider } from '../styles.js';
48
49
  import { popMobileRowMenu } from './menu.js';
49
50
  import { mobileStickyTitle } from './table-view-style.js';
50
- /** Two 24px ops, the 20px gap between them and their 8px inset. */
51
- const ROW_OPS_WIDTH = 24 * 2 + 20 + 8;
51
+ /** The "Open" chip's widest drawing, its 8px inset and 4px of air. */
52
+ export const ROW_OPEN_WIDTH = 60 + 8 + 4;
53
+ /** How long a finger rests on a row before its menu opens. */
54
+ export const ROW_LONG_PRESS_MS = 500;
55
+ /** A finger that travels further is scrolling, not pressing. */
56
+ const LONG_PRESS_SLOP = 8;
57
+ /**
58
+ * A row of the phone table (P7, "Bases éditables sur mobile", after Notion's
59
+ * phone table). A tap on a cell edits it; the title column carries an "Open"
60
+ * chip that opens the row through the root's detail panel, the path of the
61
+ * desktop row's open button; a long press opens the row menu (open, delete).
62
+ *
63
+ * Up to 0.54 the title cell carried two floating ops (open and "...") drawn
64
+ * over the end of the title. The chip reserves its room instead, and the
65
+ * "..." moved to the long press so deleting a row stays possible on a phone.
66
+ */
52
67
  let MobileTableRow = (() => {
53
68
  let _classSuper = SignalWatcher(WithDisposable(ShadowlessElement));
69
+ let _std_decorators;
70
+ let _std_initializers = [];
71
+ let _std_extraInitializers = [];
54
72
  let _tableViewLogic_decorators;
55
73
  let _tableViewLogic_initializers = [];
56
74
  let _tableViewLogic_extraInitializers = [];
@@ -63,16 +81,18 @@ let MobileTableRow = (() => {
63
81
  return class MobileTableRow extends _classSuper {
64
82
  static {
65
83
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
84
+ _std_decorators = [consume({ context: stdContext })];
66
85
  _tableViewLogic_decorators = [property({ attribute: false })];
67
86
  _rowId_decorators = [property({ attribute: false })];
68
87
  _rowIndex_decorators = [property({ attribute: false })];
88
+ __esDecorate(this, null, _std_decorators, { kind: "accessor", name: "std", static: false, private: false, access: { has: obj => "std" in obj, get: obj => obj.std, set: (obj, value) => { obj.std = value; } }, metadata: _metadata }, _std_initializers, _std_extraInitializers);
69
89
  __esDecorate(this, null, _tableViewLogic_decorators, { kind: "accessor", name: "tableViewLogic", static: false, private: false, access: { has: obj => "tableViewLogic" in obj, get: obj => obj.tableViewLogic, set: (obj, value) => { obj.tableViewLogic = value; } }, metadata: _metadata }, _tableViewLogic_initializers, _tableViewLogic_extraInitializers);
70
90
  __esDecorate(this, null, _rowId_decorators, { kind: "accessor", name: "rowId", static: false, private: false, access: { has: obj => "rowId" in obj, get: obj => obj.rowId, set: (obj, value) => { obj.rowId = value; } }, metadata: _metadata }, _rowId_initializers, _rowId_extraInitializers);
71
91
  __esDecorate(this, null, _rowIndex_decorators, { kind: "accessor", name: "rowIndex", static: false, private: false, access: { has: obj => "rowIndex" in obj, get: obj => obj.rowIndex, set: (obj, value) => { obj.rowIndex = value; } }, metadata: _metadata }, _rowIndex_initializers, _rowIndex_extraInitializers);
72
92
  if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
73
93
  }
74
- // Touch targets are 44px tall (B5, ADR 0035 §1): the row, and each row op
75
- // through an invisible hit area, so the ops keep their drawn size.
94
+ // Touch targets are 44px tall (B5, ADR 0035 §1): the row, and the chip
95
+ // through an invisible hit area, so it keeps its drawn size.
76
96
  static { this.styles = css `
77
97
  .mobile-table-row {
78
98
  width: 100%;
@@ -82,69 +102,105 @@ let MobileTableRow = (() => {
82
102
  position: relative;
83
103
  min-height: 44px;
84
104
  background-color: var(${unsafeCSS(ROW_COLOR_PROPERTY)}, transparent);
105
+ -webkit-touch-callout: none;
85
106
  }
86
107
 
87
- .mobile-row-ops {
88
- position: relative;
89
- width: 0;
90
- margin-top: 5px;
91
- height: max-content;
92
- display: flex;
93
- gap: 20px;
94
- cursor: pointer;
95
- justify-content: end;
96
- right: 8px;
97
- }
98
-
99
- .affine-database-block-row:has([data-editing='true']) .mobile-row-ops {
100
- visibility: hidden;
101
- opacity: 0;
108
+ /* A long press opens the row menu, not a text selection; an edited cell
109
+ keeps its own. */
110
+ .mobile-table-row mobile-table-cell:not([data-editing='true']) {
111
+ -webkit-user-select: none;
112
+ user-select: none;
102
113
  }
103
114
 
104
- .mobile-row-op {
115
+ .mobile-row-open {
116
+ position: absolute;
117
+ top: 10px;
118
+ right: 8px;
105
119
  display: flex;
106
- padding: 4px;
120
+ align-items: center;
121
+ height: 24px;
122
+ max-width: 60px;
123
+ padding: 0 6px;
124
+ box-sizing: border-box;
125
+ border: 1px solid ${unsafeCSS(cssVarV2.layer.insideBorder.border)};
107
126
  border-radius: 4px;
108
- box-shadow: 0px 0px 4px 0px rgba(66, 65, 73, 0.14);
109
127
  background-color: var(--affine-background-primary-color);
110
- position: relative;
111
- font-size: 16px;
112
- color: ${unsafeCSSVarV2('icon/primary')};
128
+ color: ${unsafeCSS(cssVarV2.text.secondary)};
129
+ font-size: 12px;
130
+ font-weight: 500;
131
+ line-height: 20px;
132
+ white-space: nowrap;
133
+ overflow: hidden;
134
+ text-overflow: ellipsis;
135
+ cursor: pointer;
113
136
  }
114
137
 
115
- .mobile-row-op::after {
138
+ .mobile-row-open::after {
116
139
  content: '';
117
140
  position: absolute;
118
- inset: -10px;
141
+ inset: -10px -4px;
142
+ }
143
+
144
+ .mobile-row-title:has(mobile-table-cell[data-editing='true'])
145
+ .mobile-row-open {
146
+ display: none;
119
147
  }
120
148
  `; }
149
+ #std_accessor_storage;
150
+ /** Absent outside an editor host: the wordings read English. */
151
+ get std() { return this.#std_accessor_storage; }
152
+ set std(value) { this.#std_accessor_storage = value; }
121
153
  get groupKey() {
122
154
  return this.closest('affine-data-view-table-group')?.group?.key;
123
155
  }
124
156
  connectedCallback() {
125
157
  super.connectedCallback();
126
158
  this.classList.add('mobile-table-row');
159
+ this.disposables.add(this.cancelPress);
160
+ this.disposables.addFromEvent(this, 'pointerdown', (e) => {
161
+ this.pressFired = false;
162
+ this.cancelPress();
163
+ if (this.view.readonly$.value)
164
+ return;
165
+ this.pressOrigin = { x: e.clientX, y: e.clientY };
166
+ this.pressTimer = setTimeout(() => {
167
+ this.cancelPress();
168
+ this.pressFired = true;
169
+ popMobileRowMenu(popupTargetFromElement(this), this.rowId, this.tableViewLogic, this.view, wordingOf(this.std));
170
+ }, ROW_LONG_PRESS_MS);
171
+ });
172
+ this.disposables.addFromEvent(this, 'pointermove', (e) => {
173
+ const origin = this.pressOrigin;
174
+ if (!origin)
175
+ return;
176
+ const moved = Math.hypot(e.clientX - origin.x, e.clientY - origin.y);
177
+ if (moved > LONG_PRESS_SLOP)
178
+ this.cancelPress();
179
+ });
180
+ this.disposables.addFromEvent(this, 'pointerup', this.cancelPress);
181
+ this.disposables.addFromEvent(this, 'pointercancel', this.cancelPress);
182
+ // Android opens its own menu on a long press; the row's is the one.
183
+ this.disposables.addFromEvent(this, 'contextmenu', (e) => {
184
+ e.preventDefault();
185
+ });
186
+ this.disposables.addFromEvent(this, 'click', (e) => {
187
+ if (!this.pressFired)
188
+ return;
189
+ this.pressFired = false;
190
+ e.stopPropagation();
191
+ e.preventDefault();
192
+ }, { capture: true });
127
193
  }
128
194
  render() {
129
195
  const view = this.view;
130
196
  paintRowColor(this, viewRowColor(view, this.rowId));
197
+ const openLabel = wordingOf(this.std)(OPEN_LABEL);
131
198
  return html `
132
199
  ${repeat(view.properties$.value, v => v.id, (column, i) => {
133
- const clickDetail = () => {
134
- this.tableViewLogic.root.openDetailPanel({
135
- view: this.view,
136
- rowId: this.rowId,
137
- });
138
- };
139
- const openMenu = (e) => {
140
- const ele = e.currentTarget;
141
- popMobileRowMenu(popupTargetFromElement(ele), this.rowId, this.tableViewLogic, this.view);
142
- };
143
200
  const isTitle = column.view.mainProperties$.value.titleColumn === column.id;
144
- const hasOps = isTitle && !column.readonly$.value;
145
201
  return html `
146
202
  <div
147
- class="${isTitle ? mobileStickyTitle : ''}"
203
+ class="${isTitle ? `${mobileStickyTitle} mobile-row-title` : ''}"
148
204
  style="display: flex;"
149
205
  >
150
206
  <mobile-table-cell
@@ -152,8 +208,8 @@ let MobileTableRow = (() => {
152
208
  style=${styleMap({
153
209
  width: `${column.width$.value}px`,
154
210
  border: i === 0 ? 'none' : undefined,
155
- // Room for the two row ops drawn over its right end.
156
- paddingRight: hasOps ? `${ROW_OPS_WIDTH}px` : undefined,
211
+ // Room for the "Open" chip drawn over its right end.
212
+ paddingRight: isTitle ? `${ROW_OPEN_WIDTH}px` : undefined,
157
213
  })}
158
214
  .tableViewLogic="${this.tableViewLogic}"
159
215
  .column="${column}"
@@ -168,16 +224,15 @@ let MobileTableRow = (() => {
168
224
  >
169
225
  </mobile-table-cell>
170
226
  <div class="${cellDivider}"></div>
171
- ${hasOps
172
- ? html ` <div class="mobile-row-ops">
173
- <div class="mobile-row-op" @click="${clickDetail}">
174
- ${CenterPeekIcon()}
175
- </div>
176
- ${!view.readonly$.value
177
- ? html ` <div class="mobile-row-op" @click="${openMenu}">
178
- ${MoreHorizontalIcon()}
179
- </div>`
180
- : nothing}
227
+ ${isTitle
228
+ ? html `<div
229
+ class="mobile-row-open"
230
+ data-testid="dv-row-open"
231
+ role="button"
232
+ aria-label="${openLabel}"
233
+ @click="${this.openRow}"
234
+ >
235
+ ${openLabel}
181
236
  </div>`
182
237
  : nothing}
183
238
  </div>
@@ -186,13 +241,13 @@ let MobileTableRow = (() => {
186
241
  <div class="database-cell add-column-button"></div>
187
242
  `;
188
243
  }
189
- #tableViewLogic_accessor_storage = __runInitializers(this, _tableViewLogic_initializers, void 0);
244
+ #tableViewLogic_accessor_storage;
190
245
  get tableViewLogic() { return this.#tableViewLogic_accessor_storage; }
191
246
  set tableViewLogic(value) { this.#tableViewLogic_accessor_storage = value; }
192
- #rowId_accessor_storage = (__runInitializers(this, _tableViewLogic_extraInitializers), __runInitializers(this, _rowId_initializers, void 0));
247
+ #rowId_accessor_storage;
193
248
  get rowId() { return this.#rowId_accessor_storage; }
194
249
  set rowId(value) { this.#rowId_accessor_storage = value; }
195
- #rowIndex_accessor_storage = (__runInitializers(this, _rowId_extraInitializers), __runInitializers(this, _rowIndex_initializers, void 0));
250
+ #rowIndex_accessor_storage;
196
251
  get rowIndex() { return this.#rowIndex_accessor_storage; }
197
252
  set rowIndex(value) { this.#rowIndex_accessor_storage = value; }
198
253
  get view() {
@@ -200,6 +255,25 @@ let MobileTableRow = (() => {
200
255
  }
201
256
  constructor() {
202
257
  super(...arguments);
258
+ this.#std_accessor_storage = __runInitializers(this, _std_initializers, void 0);
259
+ this.pressTimer = __runInitializers(this, _std_extraInitializers);
260
+ /** A long press fired: the click the finger's release makes is eaten. */
261
+ this.pressFired = false;
262
+ this.cancelPress = () => {
263
+ clearTimeout(this.pressTimer);
264
+ this.pressTimer = undefined;
265
+ this.pressOrigin = undefined;
266
+ };
267
+ this.openRow = (e) => {
268
+ e.stopPropagation();
269
+ this.tableViewLogic.root.openDetailPanel({
270
+ view: this.view,
271
+ rowId: this.rowId,
272
+ });
273
+ };
274
+ this.#tableViewLogic_accessor_storage = __runInitializers(this, _tableViewLogic_initializers, void 0);
275
+ this.#rowId_accessor_storage = (__runInitializers(this, _tableViewLogic_extraInitializers), __runInitializers(this, _rowId_initializers, void 0));
276
+ this.#rowIndex_accessor_storage = (__runInitializers(this, _rowId_extraInitializers), __runInitializers(this, _rowIndex_initializers, void 0));
203
277
  __runInitializers(this, _rowIndex_extraInitializers);
204
278
  }
205
279
  };
@@ -8,7 +8,11 @@ export declare class MobileTableViewUILogic extends DataViewUILogicBase<TableSin
8
8
  ui$: import("@preact/signals-core").Signal<MobileTableViewUI | undefined>;
9
9
  private get readonly();
10
10
  clearSelection: () => void;
11
- addRow: (position: InsertToPosition) => string | undefined;
11
+ /**
12
+ * A new row opens at once, as on the desktop table and the flat views: on a
13
+ * phone its title and properties are typed in the row page.
14
+ */
15
+ addRow: (position: InsertToPosition, groupKey?: string) => string | undefined;
12
16
  focusFirstCell: () => void;
13
17
  showIndicator: (_evt: MouseEvent) => boolean;
14
18
  hideIndicator: () => void;
@@ -13,10 +13,17 @@ export class MobileTableViewUILogic extends DataViewUILogicBase {
13
13
  super(...arguments);
14
14
  this.ui$ = signal(undefined);
15
15
  this.clearSelection = () => { };
16
- this.addRow = (position) => {
16
+ /**
17
+ * A new row opens at once, as on the desktop table and the flat views: on a
18
+ * phone its title and properties are typed in the row page.
19
+ */
20
+ this.addRow = (position, groupKey) => {
17
21
  if (this.readonly)
18
22
  return;
19
- return this.view.rowAdd(position);
23
+ const rowId = this.view.rowAdd(position, groupKey);
24
+ if (rowId)
25
+ this.root.openDetailPanel({ view: this.view, rowId });
26
+ return rowId;
20
27
  };
21
28
  this.focusFirstCell = () => { };
22
29
  this.showIndicator = (_evt) => {
@@ -259,7 +259,11 @@ let TableRowView = (() => {
259
259
  ${!column.readonly$.value &&
260
260
  column.view.mainProperties$.value.titleColumn === column.id
261
261
  ? html `<div class="row-ops show-on-hover-row">
262
- <div class="row-op" @click="${clickDetail}">
262
+ <div
263
+ class="row-op"
264
+ data-testid="dv-row-open"
265
+ @click="${clickDetail}"
266
+ >
263
267
  ${CenterPeekIcon()}
264
268
  </div>
265
269
  ${!view.readonly$.value
@@ -1,4 +1,3 @@
1
- import { IS_MOBILE } from '../../../../global/env/index.js';
2
1
  import { html } from 'lit';
3
2
  import { filterTraitKey } from '../../../core/filter/trait.js';
4
3
  export const renderFilterBar = (props) => {
@@ -6,7 +5,7 @@ export const renderFilterBar = (props) => {
6
5
  if (!filterTrait) {
7
6
  return;
8
7
  }
9
- if (!IS_MOBILE && !filterTrait.hasFilter$.value) {
8
+ if (!filterTrait.hasFilter$.value) {
10
9
  return;
11
10
  }
12
11
  return html ` <filter-bar
@@ -1,5 +1,4 @@
1
1
  import { unsafeCSSVarV2 } from '../../../affine-shared/theme/index.js';
2
- import { IS_MOBILE } from '../../../global/env/index.js';
3
2
  import { html, nothing } from 'lit';
4
3
  import { defineUniComponent, } from '../../core/index.js';
5
4
  import { createDefaultShowQuickSettingBar, ShowQuickSettingBarKey, } from './context.js';
@@ -8,13 +7,14 @@ import { renderSortBar } from './sort/index.js';
8
7
  export const widgetQuickSettingBar = defineUniComponent((props) => {
9
8
  const view = props.dataViewLogic.view;
10
9
  const barList = [renderSortBar(props), renderFilterBar(props)].filter(Boolean);
11
- if (!IS_MOBILE) {
12
- if (!view.serviceGetOrCreate(ShowQuickSettingBarKey, createDefaultShowQuickSettingBar).value[view.id]) {
13
- return html ``;
14
- }
15
- if (!barList.length) {
16
- return html ``;
17
- }
10
+ // The same rule on a phone since its toolbar has the filter and sort
11
+ // buttons (P7): up to 0.54 the bar stood there on every phone, empty but
12
+ // for "+ Add filter", as the only way to filter.
13
+ if (!view.serviceGetOrCreate(ShowQuickSettingBarKey, createDefaultShowQuickSettingBar).value[view.id]) {
14
+ return html ``;
15
+ }
16
+ if (!barList.length) {
17
+ return html ``;
18
18
  }
19
19
  return html ` <div
20
20
  style="display: flex;margin-top: 8px;align-items: center;width: 100%;gap:8px"
@@ -1,3 +1,4 @@
1
+ import { type BlockStdScope } from '../../../../../std/index.js';
1
2
  import { nothing } from 'lit';
2
3
  import { WidgetBase } from '../../../../core/widget/widget-base.js';
3
4
  export declare class DataViewHeaderToolsFilter extends WidgetBase {
@@ -8,6 +9,8 @@ export declare class DataViewHeaderToolsFilter extends WidgetBase {
8
9
  get filterTrait(): import("../../../../core/filter/trait.js").FilterTrait | undefined;
9
10
  private get readonly();
10
11
  private clickFilter;
12
+ /** Absent outside an editor host: the wordings read English. */
13
+ accessor std: BlockStdScope;
11
14
  connectedCallback(): void;
12
15
  render(): import("lit-html").TemplateResult<1> | typeof nothing;
13
16
  toggleShowFilter(show?: boolean): void;
@@ -1,14 +1,51 @@
1
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
2
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
3
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
4
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
5
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
6
+ var _, done = false;
7
+ for (var i = decorators.length - 1; i >= 0; i--) {
8
+ var context = {};
9
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
10
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
11
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
12
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
13
+ if (kind === "accessor") {
14
+ if (result === void 0) continue;
15
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
16
+ if (_ = accept(result.get)) descriptor.get = _;
17
+ if (_ = accept(result.set)) descriptor.set = _;
18
+ if (_ = accept(result.init)) initializers.unshift(_);
19
+ }
20
+ else if (_ = accept(result)) {
21
+ if (kind === "field") initializers.unshift(_);
22
+ else descriptor[key] = _;
23
+ }
24
+ }
25
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
26
+ done = true;
27
+ };
28
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
29
+ var useValue = arguments.length > 2;
30
+ for (var i = 0; i < initializers.length; i++) {
31
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
32
+ }
33
+ return useValue ? value : void 0;
34
+ };
1
35
  import { popupTargetFromElement } from '../../../../../affine-components/context-menu/index.js';
2
- import { IS_MOBILE } from '../../../../../global/env/index.js';
3
36
  import { FilterIcon } from '@blocksuite/icons/lit';
4
37
  import { computed } from '@preact/signals-core';
5
38
  import { cssVarV2 } from '@toeverything/theme/v2';
39
+ import { stdContext } from '../../../../../std/index.js';
40
+ import { consume } from '@lit/context';
6
41
  import { css, html, nothing } from 'lit';
7
42
  import { styleMap } from 'lit/directives/style-map.js';
8
43
  import { popCreateFilter } from '../../../../core/filter/add-filter.js';
9
44
  import { filterTraitKey } from '../../../../core/filter/trait.js';
10
45
  import { emptyFilterGroup } from '../../../../core/filter/utils.js';
46
+ import { wordingOf } from '../../../../core/utils/wording.js';
11
47
  import { WidgetBase } from '../../../../core/widget/widget-base.js';
48
+ import { DATA_VIEW_FILTER } from '../../../../translations.js';
12
49
  import { createDefaultShowQuickSettingBar, ShowQuickSettingBarKey, } from '../../../quick-setting-bar/context.js';
13
50
  const styles = css `
14
51
  .affine-database-filter-button {
@@ -27,72 +64,100 @@ const styles = css `
27
64
  background-color: var(--affine-hover-color);
28
65
  }
29
66
 
30
- .affine-database-filter-button {
67
+ /* Shown on a phone too, its menus as sheets: 44px for a finger (P7). */
68
+ @media (pointer: coarse) {
69
+ .affine-database-filter-button {
70
+ min-width: 44px;
71
+ min-height: 44px;
72
+ justify-content: center;
73
+ }
31
74
  }
32
75
  `;
33
- export class DataViewHeaderToolsFilter extends WidgetBase {
34
- constructor() {
35
- super(...arguments);
36
- this.hasFilter = computed(() => {
37
- return this.filterTrait?.hasFilter$.value ?? false;
38
- });
39
- }
40
- static { this.styles = styles; }
41
- get _filter() {
42
- return this.filterTrait?.filter$.value ?? emptyFilterGroup;
43
- }
44
- set _filter(filter) {
45
- this.filterTrait?.filterSet(filter);
46
- }
47
- get filterTrait() {
48
- return this.view.traitGet(filterTraitKey);
49
- }
50
- get readonly() {
51
- return this.view.readonly$.value;
52
- }
53
- clickFilter(event) {
54
- if (this.hasFilter.value) {
55
- this.toggleShowFilter();
76
+ let DataViewHeaderToolsFilter = (() => {
77
+ let _classSuper = WidgetBase;
78
+ let _std_decorators;
79
+ let _std_initializers = [];
80
+ let _std_extraInitializers = [];
81
+ return class DataViewHeaderToolsFilter extends _classSuper {
82
+ static {
83
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
84
+ _std_decorators = [consume({ context: stdContext })];
85
+ __esDecorate(this, null, _std_decorators, { kind: "accessor", name: "std", static: false, private: false, access: { has: obj => "std" in obj, get: obj => obj.std, set: (obj, value) => { obj.std = value; } }, metadata: _metadata }, _std_initializers, _std_extraInitializers);
86
+ if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
87
+ }
88
+ static { this.styles = styles; }
89
+ get _filter() {
90
+ return this.filterTrait?.filter$.value ?? emptyFilterGroup;
91
+ }
92
+ set _filter(filter) {
93
+ this.filterTrait?.filterSet(filter);
94
+ }
95
+ get filterTrait() {
96
+ return this.view.traitGet(filterTraitKey);
97
+ }
98
+ get readonly() {
99
+ return this.view.readonly$.value;
100
+ }
101
+ clickFilter(event) {
102
+ if (this.hasFilter.value) {
103
+ this.toggleShowFilter();
104
+ return;
105
+ }
106
+ popCreateFilter(popupTargetFromElement(event.currentTarget), {
107
+ vars: this.view.vars$,
108
+ onSelect: filter => {
109
+ this._filter = {
110
+ ...this._filter,
111
+ conditions: [filter],
112
+ };
113
+ this.toggleShowFilter(true);
114
+ this.dataViewLogic.eventTrace('CreateDatabaseFilter', {});
115
+ },
116
+ });
56
117
  return;
57
118
  }
58
- popCreateFilter(popupTargetFromElement(event.currentTarget), {
59
- vars: this.view.vars$,
60
- onSelect: filter => {
61
- this._filter = {
62
- ...this._filter,
63
- conditions: [filter],
64
- };
65
- this.toggleShowFilter(true);
66
- this.dataViewLogic.eventTrace('CreateDatabaseFilter', {});
67
- },
68
- });
69
- return;
70
- }
71
- connectedCallback() {
72
- super.connectedCallback();
73
- this.style.display = IS_MOBILE ? 'none' : 'flex';
74
- }
75
- render() {
76
- if (this.readonly)
77
- return nothing;
78
- const style = styleMap({
79
- color: this.hasFilter.value
80
- ? cssVarV2('text/emphasis')
81
- : cssVarV2('icon/primary'),
82
- });
83
- return html ` <div
119
+ #std_accessor_storage;
120
+ /** Absent outside an editor host: the wordings read English. */
121
+ get std() { return this.#std_accessor_storage; }
122
+ set std(value) { this.#std_accessor_storage = value; }
123
+ connectedCallback() {
124
+ super.connectedCallback();
125
+ this.style.display = 'flex';
126
+ }
127
+ render() {
128
+ if (this.readonly)
129
+ return nothing;
130
+ const style = styleMap({
131
+ color: this.hasFilter.value
132
+ ? cssVarV2('text/emphasis')
133
+ : cssVarV2('icon/primary'),
134
+ });
135
+ return html ` <div
84
136
  @click="${this.clickFilter}"
85
137
  style="${style}"
86
138
  class="affine-database-filter-button"
139
+ data-testid="dv-tools-filter"
140
+ role="button"
141
+ aria-label="${wordingOf(this.std)(DATA_VIEW_FILTER)}"
87
142
  >
88
143
  ${FilterIcon()}
89
144
  </div>`;
90
- }
91
- toggleShowFilter(show) {
92
- const map = this.view.serviceGetOrCreate(ShowQuickSettingBarKey, createDefaultShowQuickSettingBar);
93
- map.value = {
94
- ...map.value,
95
- [this.view.id]: show ?? !map.value[this.view.id],
96
- };
97
- }
98
- }
145
+ }
146
+ toggleShowFilter(show) {
147
+ const map = this.view.serviceGetOrCreate(ShowQuickSettingBarKey, createDefaultShowQuickSettingBar);
148
+ map.value = {
149
+ ...map.value,
150
+ [this.view.id]: show ?? !map.value[this.view.id],
151
+ };
152
+ }
153
+ constructor() {
154
+ super(...arguments);
155
+ this.hasFilter = computed(() => {
156
+ return this.filterTrait?.hasFilter$.value ?? false;
157
+ });
158
+ this.#std_accessor_storage = __runInitializers(this, _std_initializers, void 0);
159
+ __runInitializers(this, _std_extraInitializers);
160
+ }
161
+ };
162
+ })();
163
+ export { DataViewHeaderToolsFilter };
@@ -1,3 +1,4 @@
1
+ import { type BlockStdScope } from '../../../../../std/index.js';
1
2
  import { nothing } from 'lit';
2
3
  import { WidgetBase } from '../../../../core/widget/widget-base.js';
3
4
  export declare class DataViewHeaderToolsSort extends WidgetBase {
@@ -6,6 +7,8 @@ export declare class DataViewHeaderToolsSort extends WidgetBase {
6
7
  hasSort: import("@preact/signals-core").ReadonlySignal<boolean>;
7
8
  private get readonly();
8
9
  private clickSort;
10
+ /** Absent outside an editor host: the wordings read English. */
11
+ accessor std: BlockStdScope;
9
12
  connectedCallback(): void;
10
13
  render(): import("lit-html").TemplateResult<1> | typeof nothing;
11
14
  toggleShowQuickSettingBar(show?: boolean): void;