@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.
- package/architecture/code.c4 +7547 -0
- package/architecture/likec4.config.json +3 -0
- package/architecture/model.c4 +128 -0
- package/dist/_pkgs/data-view/translations.d.ts +0 -2
- package/dist/_pkgs/data-view/translations.js +0 -6
- package/dist/_pkgs/data-view/view-presets/flat/flat-view-ui.d.ts +3 -1
- package/dist/_pkgs/data-view/view-presets/flat/flat-view-ui.js +5 -1
- package/dist/_pkgs/data-view/view-presets/kanban/mobile/card.d.ts +6 -0
- package/dist/_pkgs/data-view/view-presets/kanban/mobile/card.js +11 -0
- package/dist/_pkgs/data-view/view-presets/kanban/mobile/cell.js +9 -10
- package/dist/_pkgs/data-view/view-presets/kanban/mobile/kanban-view-ui-logic.js +3 -0
- package/dist/_pkgs/data-view/view-presets/table/mobile/cell.js +7 -4
- package/dist/_pkgs/data-view/view-presets/table/mobile/group.js +11 -8
- package/dist/_pkgs/data-view/view-presets/table/mobile/header.d.ts +8 -2
- package/dist/_pkgs/data-view/view-presets/table/mobile/header.js +47 -15
- package/dist/_pkgs/data-view/view-presets/table/mobile/menu.d.ts +3 -1
- package/dist/_pkgs/data-view/view-presets/table/mobile/menu.js +7 -3
- package/dist/_pkgs/data-view/view-presets/table/mobile/row.d.ts +23 -1
- package/dist/_pkgs/data-view/view-presets/table/mobile/row.js +131 -57
- package/dist/_pkgs/data-view/view-presets/table/mobile/table-view-ui-logic.d.ts +5 -1
- package/dist/_pkgs/data-view/view-presets/table/mobile/table-view-ui-logic.js +9 -2
- package/dist/_pkgs/data-view/view-presets/table/pc/row/row.js +5 -1
- package/dist/_pkgs/data-view/widget-presets/quick-setting-bar/filter/index.js +1 -2
- package/dist/_pkgs/data-view/widget-presets/quick-setting-bar/index.js +8 -8
- package/dist/_pkgs/data-view/widget-presets/tools/presets/filter/filter.d.ts +3 -0
- package/dist/_pkgs/data-view/widget-presets/tools/presets/filter/filter.js +125 -60
- package/dist/_pkgs/data-view/widget-presets/tools/presets/sort/sort.d.ts +3 -0
- package/dist/_pkgs/data-view/widget-presets/tools/presets/sort/sort.js +131 -66
- package/dist/_pkgs/data-view/widget-presets/tools/presets/table-add-row/add-row.js +49 -10
- package/dist/_pkgs/store/model/store/query.js +13 -1
- package/package.json +3 -2
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
// Hand-written half of the library's architecture map (ADR 0040): the
|
|
2
|
+
// element and relationship kinds, and the views. Every element and relation
|
|
3
|
+
// lives in code.c4, generated by `yarn architecture`; a view here selects
|
|
4
|
+
// them by predicate (kind, scope, wildcard), never by naming a package or a
|
|
5
|
+
// folder, so a new package shows up without touching this file. A scoped
|
|
6
|
+
// view names its layer or family: a new packages/affine/<kind> folder (a new
|
|
7
|
+
// family) needs a new family view here.
|
|
8
|
+
specification {
|
|
9
|
+
element layer {
|
|
10
|
+
notation 'Layer: uses the layers below it, never above'
|
|
11
|
+
style {
|
|
12
|
+
color slate
|
|
13
|
+
opacity 10%
|
|
14
|
+
border dashed
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
element family {
|
|
18
|
+
notation 'Package family: packages/affine/<kind>'
|
|
19
|
+
style {
|
|
20
|
+
color slate
|
|
21
|
+
opacity 20%
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
element package {
|
|
25
|
+
notation 'Workspace package'
|
|
26
|
+
style {
|
|
27
|
+
color primary
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
element folder {
|
|
31
|
+
notation 'Folder under the package src/'
|
|
32
|
+
style {
|
|
33
|
+
color secondary
|
|
34
|
+
size small
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
relationship uses {
|
|
38
|
+
notation 'Package imports package (count of importing/imported file pairs)'
|
|
39
|
+
color primary
|
|
40
|
+
}
|
|
41
|
+
relationship imports {
|
|
42
|
+
notation 'Folder imports folder (count of importing/imported file pairs)'
|
|
43
|
+
color gray
|
|
44
|
+
line dotted
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
views {
|
|
49
|
+
// A view of packages excludes `imports` (folder to folder): those
|
|
50
|
+
// relations stay in the model for the relationship browser and the MCP
|
|
51
|
+
// tools, but would double every package edge on the diagram.
|
|
52
|
+
view index {
|
|
53
|
+
title 'blocksuite-labre: layers'
|
|
54
|
+
description 'Four layers, one direction, and the tooling above them. Click a layer to zoom.'
|
|
55
|
+
include *
|
|
56
|
+
exclude * -> * where kind is imports
|
|
57
|
+
autoLayout BottomTop
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
view layer-framework of framework {
|
|
61
|
+
title 'framework/*'
|
|
62
|
+
include *
|
|
63
|
+
exclude * -> * where kind is imports
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// A layer of one package shows that package's folders instead.
|
|
67
|
+
view layer-model of model_ {
|
|
68
|
+
title 'affine/model'
|
|
69
|
+
description 'The file format, folder by folder.'
|
|
70
|
+
include model_.**
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
view layer-features of features {
|
|
74
|
+
title 'affine/* features'
|
|
75
|
+
description 'Package families and standalone feature packages.'
|
|
76
|
+
include *
|
|
77
|
+
exclude * -> * where kind is imports
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// A family view shows its packages and the edges among them only: the
|
|
81
|
+
// edges to every package outside the family flatten the diagram.
|
|
82
|
+
view family-blocks of features.blocks {
|
|
83
|
+
title 'affine/blocks'
|
|
84
|
+
include features.blocks.*
|
|
85
|
+
exclude * -> * where kind is imports
|
|
86
|
+
autoLayout LeftRight
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
view family-fragments of features.fragments {
|
|
90
|
+
title 'affine/fragments'
|
|
91
|
+
include features.fragments.*
|
|
92
|
+
exclude * -> * where kind is imports
|
|
93
|
+
autoLayout LeftRight
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
view family-gfx of features.gfx {
|
|
97
|
+
title 'affine/gfx'
|
|
98
|
+
include features.gfx.*
|
|
99
|
+
exclude * -> * where kind is imports
|
|
100
|
+
autoLayout LeftRight
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
view family-inlines of features.inlines {
|
|
104
|
+
title 'affine/inlines'
|
|
105
|
+
include features.inlines.*
|
|
106
|
+
exclude * -> * where kind is imports
|
|
107
|
+
autoLayout LeftRight
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
view family-widgets of features.widgets {
|
|
111
|
+
title 'affine/widgets'
|
|
112
|
+
include features.widgets.*
|
|
113
|
+
exclude * -> * where kind is imports
|
|
114
|
+
autoLayout LeftRight
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
view layer-assembly of assembly {
|
|
118
|
+
title 'affine/all'
|
|
119
|
+
description 'The assembly, folder by folder.'
|
|
120
|
+
include assembly.**
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
view layer-tooling of tooling {
|
|
124
|
+
title 'tooling'
|
|
125
|
+
include *
|
|
126
|
+
exclude * -> * where kind is imports
|
|
127
|
+
}
|
|
128
|
+
}
|
|
@@ -87,8 +87,6 @@ export declare const DATA_VIEW_PROPERTY_HIDE_IN_VIEW: ChromeWording;
|
|
|
87
87
|
export declare const DATA_VIEW_PROPERTY_TYPE: ChromeWording;
|
|
88
88
|
/** The toolbar button and a group's footer row that add a row. */
|
|
89
89
|
export declare const DATA_VIEW_NEW_RECORD: ChromeWording;
|
|
90
|
-
/** The same button on a phone, where the toolbar has no room for two words. */
|
|
91
|
-
export declare const DATA_VIEW_NEW_RECORD_SHORT: ChromeWording;
|
|
92
90
|
/**
|
|
93
91
|
* The title of the group holding the rows with no value. Display only: the
|
|
94
92
|
* stored group key stays `'Ungroups'` (`core/group-by/define.ts`).
|
|
@@ -224,11 +224,6 @@ export const DATA_VIEW_NEW_RECORD = [
|
|
|
224
224
|
'com.labre.data-view.new-record',
|
|
225
225
|
'New Record',
|
|
226
226
|
];
|
|
227
|
-
/** The same button on a phone, where the toolbar has no room for two words. */
|
|
228
|
-
export const DATA_VIEW_NEW_RECORD_SHORT = [
|
|
229
|
-
'com.labre.data-view.new-record.short',
|
|
230
|
-
'New',
|
|
231
|
-
];
|
|
232
227
|
/**
|
|
233
228
|
* The title of the group holding the rows with no value. Display only: the
|
|
234
229
|
* stored group key stays `'Ungroups'` (`core/group-by/define.ts`).
|
|
@@ -330,7 +325,6 @@ export const DATA_VIEW_WORDINGS = [
|
|
|
330
325
|
VIEW_DUPLICATE_AS_TABLE,
|
|
331
326
|
DATA_VIEW_NEW_PAGE,
|
|
332
327
|
DATA_VIEW_NEW_RECORD,
|
|
333
|
-
DATA_VIEW_NEW_RECORD_SHORT,
|
|
334
328
|
DATA_VIEW_UNGROUPED,
|
|
335
329
|
DATA_VIEW_ADD_FILTER,
|
|
336
330
|
DATA_VIEW_SEARCH_PLACEHOLDER,
|
|
@@ -36,7 +36,9 @@ export declare abstract class FlatViewUI<Logic extends FlatViewUILogic = FlatVie
|
|
|
36
36
|
/**
|
|
37
37
|
* One property's value, drawn and edited by the cell renderer a table cell
|
|
38
38
|
* mounts. `readonly` draws the value only and lets a click through to the
|
|
39
|
-
* card or row, which is how the title opens its row.
|
|
39
|
+
* card or row, which is how the title opens its row. On a phone every value
|
|
40
|
+
* is drawn so: a tap on a card or a row opens it, its values are edited in
|
|
41
|
+
* the row page (P7, after Notion's phone gallery and list).
|
|
40
42
|
*/
|
|
41
43
|
protected renderCell(property: Property, rowId: string, readonly?: boolean): import("lit-html").TemplateResult<1>;
|
|
42
44
|
protected renderOpenButton(rowId: string): import("lit-html").TemplateResult<1>;
|
|
@@ -35,6 +35,7 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
35
35
|
import { popFilterableSimpleMenu, popupTargetFromElement, } from '../../../affine-components/context-menu/index.js';
|
|
36
36
|
import { translateKey } from '../../../affine-shared/services/index.js';
|
|
37
37
|
import { OPEN_LABEL } from '../../../affine-components/translations.js';
|
|
38
|
+
import { IS_MOBILE } from '../../../global/env/index.js';
|
|
38
39
|
import { CenterPeekIcon } from '@blocksuite/icons/lit';
|
|
39
40
|
import { stdContext } from '../../../std/index.js';
|
|
40
41
|
import { consume } from '@lit/context';
|
|
@@ -112,7 +113,9 @@ let FlatViewUI = (() => {
|
|
|
112
113
|
/**
|
|
113
114
|
* One property's value, drawn and edited by the cell renderer a table cell
|
|
114
115
|
* mounts. `readonly` draws the value only and lets a click through to the
|
|
115
|
-
* card or row, which is how the title opens its row.
|
|
116
|
+
* card or row, which is how the title opens its row. On a phone every value
|
|
117
|
+
* is drawn so: a tap on a card or a row opens it, its values are edited in
|
|
118
|
+
* the row page (P7, after Notion's phone gallery and list).
|
|
116
119
|
*/
|
|
117
120
|
renderCell(property, rowId, readonly = false) {
|
|
118
121
|
const view = this.view;
|
|
@@ -127,6 +130,7 @@ let FlatViewUI = (() => {
|
|
|
127
130
|
data-property-id="${property.id}"
|
|
128
131
|
.cell="${cell}"
|
|
129
132
|
.readonly="${readonly ||
|
|
133
|
+
IS_MOBILE ||
|
|
130
134
|
view.readonly$.value ||
|
|
131
135
|
property.readonly$.value}"
|
|
132
136
|
.onEditingChange="${(editing) => view.lockRows(editing)}"
|
|
@@ -4,6 +4,12 @@ declare const MobileKanbanCard_base: typeof ShadowlessElement & import("../../..
|
|
|
4
4
|
export declare class MobileKanbanCard extends MobileKanbanCard_base {
|
|
5
5
|
static styles: import("lit").CSSResult;
|
|
6
6
|
private readonly clickCenterPeek;
|
|
7
|
+
/**
|
|
8
|
+
* A tap on a phone's card opens its row, the path of the open button, as on
|
|
9
|
+
* Notion's phone board (P7); its "..." keeps the card's menu.
|
|
10
|
+
*/
|
|
11
|
+
private readonly openCard;
|
|
12
|
+
connectedCallback(): void;
|
|
7
13
|
private readonly clickMore;
|
|
8
14
|
private renderBody;
|
|
9
15
|
private renderHeader;
|
|
@@ -155,6 +155,10 @@ let MobileKanbanCard = (() => {
|
|
|
155
155
|
if (_metadata) Object.defineProperty(this, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
156
156
|
}
|
|
157
157
|
static { this.styles = styles; }
|
|
158
|
+
connectedCallback() {
|
|
159
|
+
super.connectedCallback();
|
|
160
|
+
this.disposables.addFromEvent(this, 'click', this.openCard);
|
|
161
|
+
}
|
|
158
162
|
renderBody(columns) {
|
|
159
163
|
if (columns.length === 0) {
|
|
160
164
|
return '';
|
|
@@ -254,6 +258,13 @@ let MobileKanbanCard = (() => {
|
|
|
254
258
|
super(...arguments);
|
|
255
259
|
this.clickCenterPeek = (e) => {
|
|
256
260
|
e.stopPropagation();
|
|
261
|
+
this.openCard();
|
|
262
|
+
};
|
|
263
|
+
/**
|
|
264
|
+
* A tap on a phone's card opens its row, the path of the open button, as on
|
|
265
|
+
* Notion's phone board (P7); its "..." keeps the card's menu.
|
|
266
|
+
*/
|
|
267
|
+
this.openCard = () => {
|
|
257
268
|
this.kanbanViewLogic.root.openDetailPanel({
|
|
258
269
|
view: this.view,
|
|
259
270
|
rowId: this.cardId,
|
|
@@ -124,12 +124,8 @@ let MobileKanbanCell = (() => {
|
|
|
124
124
|
this.isEditing$.value = false;
|
|
125
125
|
}
|
|
126
126
|
}));
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
if (!this.isEditing$.value) {
|
|
130
|
-
this.selectCurrentCell(!this.column.readonly$.value);
|
|
131
|
-
}
|
|
132
|
-
});
|
|
127
|
+
// No tap-to-edit here: a tap anywhere on a phone's card opens the row
|
|
128
|
+
// (`MobileKanbanCard`), where its values are edited (P7, after Notion).
|
|
133
129
|
}
|
|
134
130
|
render() {
|
|
135
131
|
const props = {
|
|
@@ -203,13 +199,16 @@ let MobileKanbanCell = (() => {
|
|
|
203
199
|
if (this.view.readonly$.value) {
|
|
204
200
|
return;
|
|
205
201
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
202
|
+
// Called on the logic, never detached: `setSelection` is a method of
|
|
203
|
+
// `DataViewUILogicBase`, and up to 0.54 a detached call threw on every
|
|
204
|
+
// tap, so no value of a phone card ever entered editing.
|
|
205
|
+
const logic = this.kanbanViewLogic;
|
|
206
|
+
const viewId = logic.view.id;
|
|
207
|
+
if (viewId) {
|
|
209
208
|
if (editing && this.cell?.beforeEnterEditMode() === false) {
|
|
210
209
|
return;
|
|
211
210
|
}
|
|
212
|
-
setSelection({
|
|
211
|
+
logic.setSelection({
|
|
213
212
|
viewId,
|
|
214
213
|
type: 'kanban',
|
|
215
214
|
selectionType: 'cell',
|
|
@@ -43,6 +43,9 @@ export class MobileKanbanViewUILogic extends DataViewUILogicBase {
|
|
|
43
43
|
return;
|
|
44
44
|
const id = this.view.rowAdd(position);
|
|
45
45
|
this.ui$.value?.requestUpdate();
|
|
46
|
+
// The toolbar's "+" opens the new card, as on the desktop board (P7).
|
|
47
|
+
if (id)
|
|
48
|
+
this.root.openDetailPanel({ view: this.view, rowId: id });
|
|
46
49
|
return id;
|
|
47
50
|
};
|
|
48
51
|
this.focusFirstCell = () => { };
|
|
@@ -196,13 +196,16 @@ let MobileTableCell = (() => {
|
|
|
196
196
|
if (this.view.readonly$.value) {
|
|
197
197
|
return;
|
|
198
198
|
}
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
199
|
+
// Called on the logic, never detached: `setSelection` is a method of
|
|
200
|
+
// `DataViewUILogicBase`, and up to 0.54 a detached call threw on every
|
|
201
|
+
// tap, so no cell of a phone table ever entered editing.
|
|
202
|
+
const logic = this.tableViewLogic;
|
|
203
|
+
const viewId = logic.view.id;
|
|
204
|
+
if (viewId) {
|
|
202
205
|
if (editing && this.cell?.beforeEnterEditMode() === false) {
|
|
203
206
|
return;
|
|
204
207
|
}
|
|
205
|
-
setSelection({
|
|
208
|
+
logic.setSelection({
|
|
206
209
|
viewId,
|
|
207
210
|
type: 'table',
|
|
208
211
|
...TableViewAreaSelection.create({
|
|
@@ -45,14 +45,17 @@ import { repeat } from 'lit/directives/repeat.js';
|
|
|
45
45
|
import { GroupTitle } from '../../../core/group-by/group-title.js';
|
|
46
46
|
import { hideGroupAction } from '../../../core/group-by/group-visibility.js';
|
|
47
47
|
import { wordingOf } from '../../../core/utils/wording.js';
|
|
48
|
-
import { DATA_VIEW_GROUP_COLLAPSE, DATA_VIEW_GROUP_EXPAND,
|
|
48
|
+
import { DATA_VIEW_GROUP_COLLAPSE, DATA_VIEW_GROUP_EXPAND, DATA_VIEW_NEW_PAGE, } from '../../../translations.js';
|
|
49
49
|
import { getCollapsedState, setCollapsedState } from '../collapsed-state.js';
|
|
50
50
|
import { LEFT_TOOL_BAR_WIDTH } from '../consts.js';
|
|
51
51
|
const styles = css `
|
|
52
|
+
/* "+ New page" under the rows: a full row, 44px for a finger (P7). */
|
|
52
53
|
.data-view-table-group-add-row {
|
|
53
54
|
display: flex;
|
|
54
55
|
width: 100%;
|
|
55
|
-
height:
|
|
56
|
+
min-height: 44px;
|
|
57
|
+
box-sizing: border-box;
|
|
58
|
+
align-items: center;
|
|
56
59
|
position: relative;
|
|
57
60
|
z-index: 0;
|
|
58
61
|
cursor: pointer;
|
|
@@ -69,8 +72,8 @@ const styles = css `
|
|
|
69
72
|
justify-content: center;
|
|
70
73
|
gap: 10px;
|
|
71
74
|
user-select: none;
|
|
72
|
-
font-size:
|
|
73
|
-
line-height:
|
|
75
|
+
font-size: 14px;
|
|
76
|
+
line-height: 22px;
|
|
74
77
|
color: var(--affine-text-secondary-color);
|
|
75
78
|
}
|
|
76
79
|
|
|
@@ -168,8 +171,8 @@ let MobileTableGroup = (() => {
|
|
|
168
171
|
data-test-id="affine-database-add-row-button"
|
|
169
172
|
role="button"
|
|
170
173
|
>
|
|
171
|
-
${PlusIcon()}<span
|
|
172
|
-
>${wordingOf(this.std)(
|
|
174
|
+
${PlusIcon()}<span
|
|
175
|
+
>${wordingOf(this.std)(DATA_VIEW_NEW_PAGE)}</span
|
|
173
176
|
>
|
|
174
177
|
</div>
|
|
175
178
|
</div>`}
|
|
@@ -218,11 +221,11 @@ let MobileTableGroup = (() => {
|
|
|
218
221
|
}
|
|
219
222
|
};
|
|
220
223
|
this.clickAddRow = () => {
|
|
221
|
-
this.
|
|
224
|
+
this.tableViewLogic.addRow('end', this.group?.key);
|
|
222
225
|
this.requestUpdate();
|
|
223
226
|
};
|
|
224
227
|
this.clickAddRowInStart = () => {
|
|
225
|
-
this.
|
|
228
|
+
this.tableViewLogic.addRow('start', this.group?.key);
|
|
226
229
|
this.requestUpdate();
|
|
227
230
|
};
|
|
228
231
|
this.clickGroupOptions = (e) => {
|
|
@@ -1,11 +1,17 @@
|
|
|
1
|
-
import { ShadowlessElement } from '../../../../std/index.js';
|
|
1
|
+
import { type BlockStdScope, ShadowlessElement } from '../../../../std/index.js';
|
|
2
2
|
import { type TemplateResult } from 'lit';
|
|
3
3
|
import type { TableSingleView } from '../table-view-manager.js';
|
|
4
4
|
declare const MobileTableHeader_base: typeof ShadowlessElement & import("../../../../global/utils/types.js").Constructor<import("../../../../global/lit/with-disposable.js").DisposableClass>;
|
|
5
5
|
export declare class MobileTableHeader extends MobileTableHeader_base {
|
|
6
6
|
static styles: import("lit").CSSResult;
|
|
7
|
+
/** Absent outside an editor host: the wordings read English. */
|
|
8
|
+
accessor std: BlockStdScope;
|
|
9
|
+
/**
|
|
10
|
+
* "+" adds a property and opens ITS "Property settings" sheet. Up to 0.54
|
|
11
|
+
* the last header was looked up in the same tick, before the header had
|
|
12
|
+
* drawn the new column, so the sheet opened on the previous last property.
|
|
13
|
+
*/
|
|
7
14
|
private readonly _onAddColumn;
|
|
8
|
-
editLastColumnTitle: () => void;
|
|
9
15
|
private get readonly();
|
|
10
16
|
render(): TemplateResult;
|
|
11
17
|
accessor renderGroupHeader: (() => TemplateResult) | undefined;
|
|
@@ -35,16 +35,22 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
35
35
|
import { unsafeCSSVarV2 } from '../../../../affine-shared/theme/index.js';
|
|
36
36
|
import { SignalWatcher, WithDisposable } from '../../../../global/lit/index.js';
|
|
37
37
|
import { PlusIcon } from '@blocksuite/icons/lit';
|
|
38
|
-
import { ShadowlessElement } from '../../../../std/index.js';
|
|
39
|
-
import {
|
|
38
|
+
import { ShadowlessElement, stdContext } from '../../../../std/index.js';
|
|
39
|
+
import { consume } from '@lit/context';
|
|
40
|
+
import { css, nothing } from 'lit';
|
|
40
41
|
import { property, query } from 'lit/decorators.js';
|
|
41
42
|
import { repeat } from 'lit/directives/repeat.js';
|
|
42
43
|
import { styleMap } from 'lit/directives/style-map.js';
|
|
43
44
|
import { html } from 'lit/static-html.js';
|
|
45
|
+
import { wordingOf } from '../../../core/utils/wording.js';
|
|
46
|
+
import { DATA_VIEW_NEW_PROPERTY } from '../../../translations.js';
|
|
44
47
|
import { cellDivider } from '../styles.js';
|
|
45
48
|
import { mobileStickyTitle } from './table-view-style.js';
|
|
46
49
|
let MobileTableHeader = (() => {
|
|
47
50
|
let _classSuper = SignalWatcher(WithDisposable(ShadowlessElement));
|
|
51
|
+
let _std_decorators;
|
|
52
|
+
let _std_initializers = [];
|
|
53
|
+
let _std_extraInitializers = [];
|
|
48
54
|
let _renderGroupHeader_decorators;
|
|
49
55
|
let _renderGroupHeader_initializers = [];
|
|
50
56
|
let _renderGroupHeader_extraInitializers = [];
|
|
@@ -57,9 +63,11 @@ let MobileTableHeader = (() => {
|
|
|
57
63
|
return class MobileTableHeader extends _classSuper {
|
|
58
64
|
static {
|
|
59
65
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
66
|
+
_std_decorators = [consume({ context: stdContext })];
|
|
60
67
|
_renderGroupHeader_decorators = [property({ attribute: false })];
|
|
61
68
|
_scaleDiv_decorators = [query('.scale-div')];
|
|
62
69
|
_tableViewManager_decorators = [property({ attribute: false })];
|
|
70
|
+
__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);
|
|
63
71
|
__esDecorate(this, null, _renderGroupHeader_decorators, { kind: "accessor", name: "renderGroupHeader", static: false, private: false, access: { has: obj => "renderGroupHeader" in obj, get: obj => obj.renderGroupHeader, set: (obj, value) => { obj.renderGroupHeader = value; } }, metadata: _metadata }, _renderGroupHeader_initializers, _renderGroupHeader_extraInitializers);
|
|
64
72
|
__esDecorate(this, null, _scaleDiv_decorators, { kind: "accessor", name: "scaleDiv", static: false, private: false, access: { has: obj => "scaleDiv" in obj, get: obj => obj.scaleDiv, set: (obj, value) => { obj.scaleDiv = value; } }, metadata: _metadata }, _scaleDiv_initializers, _scaleDiv_extraInitializers);
|
|
65
73
|
__esDecorate(this, null, _tableViewManager_decorators, { kind: "accessor", name: "tableViewManager", static: false, private: false, access: { has: obj => "tableViewManager" in obj, get: obj => obj.tableViewManager, set: (obj, value) => { obj.tableViewManager = value; } }, metadata: _metadata }, _tableViewManager_initializers, _tableViewManager_extraInitializers);
|
|
@@ -69,11 +77,18 @@ let MobileTableHeader = (() => {
|
|
|
69
77
|
.mobile-table-add-column {
|
|
70
78
|
font-size: 18px;
|
|
71
79
|
color: ${unsafeCSSVarV2('icon/primary')};
|
|
72
|
-
margin-left: 8px;
|
|
73
80
|
display: flex;
|
|
74
81
|
align-items: center;
|
|
82
|
+
justify-content: center;
|
|
83
|
+
min-width: 44px;
|
|
84
|
+
min-height: 44px;
|
|
85
|
+
cursor: pointer;
|
|
75
86
|
}
|
|
76
87
|
`; }
|
|
88
|
+
#std_accessor_storage;
|
|
89
|
+
/** Absent outside an editor host: the wordings read English. */
|
|
90
|
+
get std() { return this.#std_accessor_storage; }
|
|
91
|
+
set std(value) { this.#std_accessor_storage = value; }
|
|
77
92
|
get readonly() {
|
|
78
93
|
return this.tableViewManager.readonly$.value;
|
|
79
94
|
}
|
|
@@ -105,9 +120,17 @@ let MobileTableHeader = (() => {
|
|
|
105
120
|
</div>
|
|
106
121
|
`;
|
|
107
122
|
})}
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
123
|
+
${this.readonly
|
|
124
|
+
? nothing
|
|
125
|
+
: html `<div
|
|
126
|
+
@click="${this._onAddColumn}"
|
|
127
|
+
class="mobile-table-add-column"
|
|
128
|
+
data-testid="dv-table-add-property"
|
|
129
|
+
role="button"
|
|
130
|
+
aria-label="${wordingOf(this.std)(DATA_VIEW_NEW_PROPERTY)}"
|
|
131
|
+
>
|
|
132
|
+
${PlusIcon()}
|
|
133
|
+
</div>`}
|
|
111
134
|
<div class="scale-div" style="width: 1px;height: 1px;"></div>
|
|
112
135
|
</div>
|
|
113
136
|
`;
|
|
@@ -123,17 +146,26 @@ let MobileTableHeader = (() => {
|
|
|
123
146
|
set tableViewManager(value) { this.#tableViewManager_accessor_storage = value; }
|
|
124
147
|
constructor() {
|
|
125
148
|
super(...arguments);
|
|
126
|
-
this
|
|
149
|
+
this.#std_accessor_storage = __runInitializers(this, _std_initializers, void 0);
|
|
150
|
+
/**
|
|
151
|
+
* "+" adds a property and opens ITS "Property settings" sheet. Up to 0.54
|
|
152
|
+
* the last header was looked up in the same tick, before the header had
|
|
153
|
+
* drawn the new column, so the sheet opened on the previous last property.
|
|
154
|
+
*/
|
|
155
|
+
this._onAddColumn = (__runInitializers(this, _std_extraInitializers), () => {
|
|
127
156
|
if (this.readonly)
|
|
128
157
|
return;
|
|
129
|
-
this.tableViewManager.propertyAdd('end');
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
158
|
+
const id = this.tableViewManager.propertyAdd('end');
|
|
159
|
+
if (!id)
|
|
160
|
+
return;
|
|
161
|
+
this.updateComplete
|
|
162
|
+
.then(() => {
|
|
163
|
+
Array.from(this.querySelectorAll('mobile-table-column-header'))
|
|
164
|
+
.find(header => header.column.id === id)
|
|
165
|
+
?.editTitle();
|
|
166
|
+
})
|
|
167
|
+
.catch(console.error);
|
|
168
|
+
});
|
|
137
169
|
this.#renderGroupHeader_accessor_storage = __runInitializers(this, _renderGroupHeader_initializers, void 0);
|
|
138
170
|
this.#scaleDiv_accessor_storage = (__runInitializers(this, _renderGroupHeader_extraInitializers), __runInitializers(this, _scaleDiv_initializers, void 0));
|
|
139
171
|
this.#tableViewManager_accessor_storage = (__runInitializers(this, _scaleDiv_extraInitializers), __runInitializers(this, _tableViewManager_initializers, void 0));
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { type PopupTarget } from '../../../../affine-components/context-menu/index.js';
|
|
2
2
|
import type { SingleView } from '../../../core/index.js';
|
|
3
|
+
import { type Wording } from '../../../core/utils/wording.js';
|
|
3
4
|
import type { MobileTableViewUILogic } from './table-view-ui-logic.js';
|
|
4
|
-
|
|
5
|
+
/** A row's menu on a phone, opened by a long press on the row. */
|
|
6
|
+
export declare const popMobileRowMenu: (target: PopupTarget, rowId: string, tableViewLogic: MobileTableViewUILogic, view: SingleView, wording?: Wording) => void;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import { menu, popFilterableSimpleMenu, } from '../../../../affine-components/context-menu/index.js';
|
|
2
|
+
import { OPEN_LABEL } from '../../../../affine-components/translations.js';
|
|
3
|
+
import { TOOLBAR_DELETE } from '../../../../affine-shared/services/index.js';
|
|
2
4
|
import { DeleteIcon, ExpandFullIcon } from '@blocksuite/icons/lit';
|
|
3
|
-
|
|
5
|
+
import { englishWording } from '../../../core/utils/wording.js';
|
|
6
|
+
/** A row's menu on a phone, opened by a long press on the row. */
|
|
7
|
+
export const popMobileRowMenu = (target, rowId, tableViewLogic, view, wording = englishWording) => {
|
|
4
8
|
popFilterableSimpleMenu(target, [
|
|
5
9
|
menu.group({
|
|
6
10
|
items: [
|
|
7
11
|
menu.action({
|
|
8
|
-
name:
|
|
12
|
+
name: wording(OPEN_LABEL),
|
|
9
13
|
prefix: ExpandFullIcon(),
|
|
10
14
|
select: () => {
|
|
11
15
|
tableViewLogic.root.openDetailPanel({
|
|
@@ -20,7 +24,7 @@ export const popMobileRowMenu = (target, rowId, tableViewLogic, view) => {
|
|
|
20
24
|
name: '',
|
|
21
25
|
items: [
|
|
22
26
|
menu.action({
|
|
23
|
-
name:
|
|
27
|
+
name: wording(TOOLBAR_DELETE),
|
|
24
28
|
class: { 'delete-item': true },
|
|
25
29
|
prefix: DeleteIcon(),
|
|
26
30
|
select: () => {
|
|
@@ -1,8 +1,30 @@
|
|
|
1
|
-
import { ShadowlessElement } from '../../../../std/index.js';
|
|
1
|
+
import { type BlockStdScope, ShadowlessElement } from '../../../../std/index.js';
|
|
2
2
|
import type { MobileTableViewUILogic } from './table-view-ui-logic.js';
|
|
3
|
+
/** The "Open" chip's widest drawing, its 8px inset and 4px of air. */
|
|
4
|
+
export declare const ROW_OPEN_WIDTH: number;
|
|
5
|
+
/** How long a finger rests on a row before its menu opens. */
|
|
6
|
+
export declare const ROW_LONG_PRESS_MS = 500;
|
|
3
7
|
declare const MobileTableRow_base: typeof ShadowlessElement & import("../../../../global/utils/types.js").Constructor<import("../../../../global/lit/with-disposable.js").DisposableClass>;
|
|
8
|
+
/**
|
|
9
|
+
* A row of the phone table (P7, "Bases éditables sur mobile", after Notion's
|
|
10
|
+
* phone table). A tap on a cell edits it; the title column carries an "Open"
|
|
11
|
+
* chip that opens the row through the root's detail panel, the path of the
|
|
12
|
+
* desktop row's open button; a long press opens the row menu (open, delete).
|
|
13
|
+
*
|
|
14
|
+
* Up to 0.54 the title cell carried two floating ops (open and "...") drawn
|
|
15
|
+
* over the end of the title. The chip reserves its room instead, and the
|
|
16
|
+
* "..." moved to the long press so deleting a row stays possible on a phone.
|
|
17
|
+
*/
|
|
4
18
|
export declare class MobileTableRow extends MobileTableRow_base {
|
|
5
19
|
static styles: import("lit").CSSResult;
|
|
20
|
+
/** Absent outside an editor host: the wordings read English. */
|
|
21
|
+
accessor std: BlockStdScope;
|
|
22
|
+
private pressTimer;
|
|
23
|
+
private pressOrigin;
|
|
24
|
+
/** A long press fired: the click the finger's release makes is eaten. */
|
|
25
|
+
private pressFired;
|
|
26
|
+
private readonly cancelPress;
|
|
27
|
+
private readonly openRow;
|
|
6
28
|
get groupKey(): string | undefined;
|
|
7
29
|
connectedCallback(): void;
|
|
8
30
|
protected render(): unknown;
|