@formicoidea/labre-core 0.47.0 → 0.48.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/dist/_pkgs/affine-block-attachment/configs/slash-menu.js +2 -2
- package/dist/_pkgs/affine-block-attachment/translations.js +2 -2
- package/dist/_pkgs/affine-block-database/view.js +5 -0
- package/dist/_pkgs/affine-block-embed/embed-html-block/configs/toolbar.js +1 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.d.ts +1 -1
- package/dist/_pkgs/affine-block-embed/embed-iframe-block/configs/toolbar.js +1 -1
- package/dist/_pkgs/affine-block-embed/translations.d.ts +1 -1
- package/dist/_pkgs/affine-block-embed/translations.js +2 -2
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/new-doc.d.ts +25 -0
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/new-doc.js +71 -0
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/slash-menu.js +9 -17
- package/dist/_pkgs/affine-block-embed-doc/embed-linked-doc-block/configs/toolbar.js +1 -1
- package/dist/_pkgs/affine-block-embed-doc/embed-synced-doc-block/configs/toolbar.js +3 -3
- package/dist/_pkgs/affine-block-embed-doc/translations.d.ts +1 -1
- package/dist/_pkgs/affine-block-embed-doc/translations.js +8 -8
- package/dist/_pkgs/affine-block-frame/frame-toolbar.js +2 -2
- package/dist/_pkgs/affine-block-frame/translations.js +1 -1
- package/dist/_pkgs/affine-block-note/translations.js +8 -8
- package/dist/_pkgs/affine-block-root/commands/copy-link-commands.js +2 -2
- package/dist/_pkgs/affine-block-root/configs/toolbar.d.ts +1 -1
- package/dist/_pkgs/affine-block-root/configs/toolbar.js +1 -1
- package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/misc.d.ts +1 -1
- package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.d.ts +1 -1
- package/dist/_pkgs/affine-block-root/edgeless/configs/toolbar/more.js +1 -1
- package/dist/_pkgs/affine-block-root/translations.d.ts +1 -1
- package/dist/_pkgs/affine-block-root/translations.js +2 -2
- package/dist/_pkgs/affine-block-surface/extensions/canvas-grid/commands.js +1 -1
- package/dist/_pkgs/affine-block-surface/extensions/interchange-import.js +1 -1
- package/dist/_pkgs/affine-block-surface/extensions/selection-pane/commands.js +1 -1
- package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.d.ts +8 -2
- package/dist/_pkgs/affine-block-surface/renderer/element-highlight-overlay.js +11 -13
- package/dist/_pkgs/affine-block-surface-ref/translations.js +8 -8
- package/dist/_pkgs/affine-components/translations.js +6 -6
- package/dist/_pkgs/affine-fragment-doc-title/index.d.ts +1 -1
- package/dist/_pkgs/affine-fragment-doc-title/index.js +1 -1
- package/dist/_pkgs/affine-fragment-doc-title/title-band/band-cell.d.ts +22 -0
- package/dist/_pkgs/affine-fragment-doc-title/title-band/band-cell.js +125 -0
- package/dist/_pkgs/affine-fragment-doc-title/title-band/format.d.ts +7 -19
- package/dist/_pkgs/affine-fragment-doc-title/title-band/format.js +0 -38
- package/dist/_pkgs/affine-fragment-doc-title/title-band/show-here.d.ts +19 -0
- package/dist/_pkgs/affine-fragment-doc-title/title-band/show-here.js +61 -0
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.d.ts +28 -18
- package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.js +225 -207
- package/dist/_pkgs/affine-fragment-doc-title/translations.d.ts +7 -4
- package/dist/_pkgs/affine-fragment-doc-title/translations.js +12 -9
- package/dist/_pkgs/affine-gfx-group/toolbar/config.d.ts +2 -2
- package/dist/_pkgs/affine-gfx-group/toolbar/config.js +2 -2
- package/dist/_pkgs/affine-gfx-group/translations.js +1 -1
- package/dist/_pkgs/affine-gfx-note/translations.js +2 -2
- package/dist/_pkgs/affine-shared/services/linked-doc-creation-service.d.ts +15 -6
- package/dist/_pkgs/affine-shared/services/title-band-service.d.ts +10 -7
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.d.ts +3 -3
- package/dist/_pkgs/affine-shared/services/translation-service/chrome.js +17 -17
- package/dist/_pkgs/affine-shared/utils/model/doc.d.ts +10 -2
- package/dist/_pkgs/affine-shared/utils/model/doc.js +17 -7
- package/dist/_pkgs/affine-widget-edgeless-auto-connect/translations.js +2 -2
- package/dist/_pkgs/affine-widget-edgeless-selected-rect/translations.js +1 -1
- package/dist/_pkgs/affine-widget-linked-doc/translations.js +3 -3
- package/dist/_pkgs/affine-widget-slash-menu/translations.js +1 -1
- package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.d.ts +7 -2
- package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.js +22 -15
- package/dist/_pkgs/data-view/core/effect.js +2 -0
- package/dist/_pkgs/data-view/core/property/index.d.ts +1 -0
- package/dist/_pkgs/data-view/core/property/index.js +1 -0
- package/dist/_pkgs/data-view/core/property/standalone-cell.d.ts +95 -0
- package/dist/_pkgs/data-view/core/property/standalone-cell.js +306 -0
- package/dist/_pkgs/data-view/core/view-manager/property.d.ts +6 -0
- package/dist/_pkgs/data-view/property-presets/multi-select/cell-renderer.js +1 -1
- package/dist/_pkgs/data-view/property-presets/select/cell-renderer.js +1 -1
- package/dist/_pkgs/data-view/property-presets/text/cell-renderer.js +3 -1
- package/dist/translations.js +1 -1
- package/package.json +1 -1
|
@@ -32,21 +32,21 @@ var __runInitializers = (this && this.__runInitializers) || function (thisArg, i
|
|
|
32
32
|
}
|
|
33
33
|
return useValue ? value : void 0;
|
|
34
34
|
};
|
|
35
|
-
import { menu, popMenu, popupTargetFromElement, } from '../../affine-components/context-menu/index.js';
|
|
36
|
-
import { DatePicker } from '../../affine-components/date-picker/index.js';
|
|
37
35
|
import { RefNodeSlotsProvider } from '../../affine-inline-reference/index.js';
|
|
38
|
-
import { DOC_UNTITLED, formatLocale, PropertiesPanelProvider, TitleBandProvider, translateKey, } from '../../affine-shared/services/index.js';
|
|
36
|
+
import { DOC_UNTITLED, FeatureFlagService, formatLocale, PropertiesPanelProvider, TitleBandProvider, translateKey, } from '../../affine-shared/services/index.js';
|
|
39
37
|
import { stopPropagation } from '../../affine-shared/utils/index.js';
|
|
38
|
+
import { createStandaloneCell, StandaloneCellMetaProvider, } from '../../data-view/index.js';
|
|
40
39
|
import { SignalWatcher, WithDisposable } from '../../global/lit/index.js';
|
|
41
40
|
import { ShadowlessElement } from '../../std/index.js';
|
|
42
|
-
import {
|
|
41
|
+
import { LinkedPageIcon, PlusIcon, SidebarIcon, ToggleDownIcon, ToggleRightIcon, } from '@blocksuite/icons/lit';
|
|
43
42
|
import { computed, signal } from '@preact/signals-core';
|
|
44
43
|
import { css, html, nothing } from 'lit';
|
|
45
44
|
import { property } from 'lit/decorators.js';
|
|
46
45
|
import { repeat } from 'lit/directives/repeat.js';
|
|
47
|
-
import {
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
46
|
+
import { TITLE_BAND_ADD, TITLE_BAND_COLLAPSE, TITLE_BAND_EMPTY, TITLE_BAND_EXPAND, TITLE_BAND_LABEL, TITLE_BAND_LOADING, TITLE_BAND_NOT_SHOWN, TITLE_BAND_OPEN_PANEL, TITLE_BAND_SHOW_HERE, } from '../translations.js';
|
|
47
|
+
import { bandCellData, bandCellMeta, bandCellValue, bandWriteValue, isBandReadonlyType, sameBandValue, } from './band-cell.js';
|
|
48
|
+
import { formatPropertyValue, isPropertyValueEmpty } from './format.js';
|
|
49
|
+
import { showPageHere } from './show-here.js';
|
|
50
50
|
export const LABRE_TITLE_BAND = 'labre-title-band';
|
|
51
51
|
const NO_PAGES = [];
|
|
52
52
|
/**
|
|
@@ -61,12 +61,19 @@ const NO_PAGES = [];
|
|
|
61
61
|
*
|
|
62
62
|
* Fed by `TitleBandProvider` alone (§9d): no provider, nothing at all. The
|
|
63
63
|
* chips are the sheet's visible properties in the host's order, an empty one
|
|
64
|
-
* included (REQ-PR-1)
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
64
|
+
* included (REQ-PR-1). Each value is drawn and edited by the cell the inline
|
|
65
|
+
* table mounts for its data-view type (`<dv-standalone-cell>`, ADR 0035
|
|
66
|
+
* §11 amended 2026-10-13): the checkbox, the tag menu of a select, the date
|
|
67
|
+
* picker, the number, text and link inputs, with the table's own styles. The
|
|
68
|
+
* value the cell commits goes back through `set`, the chip shows pending
|
|
69
|
+
* until the host settles it, and a type with no cell keeps a plain-text
|
|
70
|
+
* reading that opens the properties panel. The band never applies a value, and writes to
|
|
71
|
+
* the document only the card "Show here" inserts. The "+" is drawn when the
|
|
72
|
+
* host passes `add`; the panel button when a `PropertiesPanelProvider` is
|
|
73
|
+
* registered. The "Not shown on this page" row is drawn in both views
|
|
74
|
+
* from the host's `notShown$` (ADR 0035 §9d, amended 2026-10-13): each page
|
|
75
|
+
* opens through the linked-document path, and "Show here" inserts a card of
|
|
76
|
+
* it into this document; the host then drops the page from its list.
|
|
70
77
|
*/
|
|
71
78
|
let TitleBand = (() => {
|
|
72
79
|
let _classSuper = SignalWatcher(WithDisposable(ShadowlessElement));
|
|
@@ -154,7 +161,7 @@ let TitleBand = (() => {
|
|
|
154
161
|
background-color: transparent;
|
|
155
162
|
}
|
|
156
163
|
|
|
157
|
-
.labre-title-band svg {
|
|
164
|
+
.labre-title-band button > svg {
|
|
158
165
|
flex: none;
|
|
159
166
|
width: 16px;
|
|
160
167
|
height: 16px;
|
|
@@ -165,36 +172,57 @@ let TitleBand = (() => {
|
|
|
165
172
|
padding: 0 6px !important;
|
|
166
173
|
}
|
|
167
174
|
|
|
175
|
+
.labre-title-band-chip {
|
|
176
|
+
display: inline-flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
gap: 6px;
|
|
179
|
+
min-height: 28px;
|
|
180
|
+
max-width: 100%;
|
|
181
|
+
padding: 0 8px;
|
|
182
|
+
border-radius: 6px;
|
|
183
|
+
transition: background-color 150ms;
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
.labre-title-band-chip[data-clickable='true'] {
|
|
187
|
+
cursor: pointer;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
.labre-title-band-chip[data-clickable='true']:hover {
|
|
191
|
+
background-color: var(--affine-hover-color);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
.labre-title-band-chip[aria-busy='true'] {
|
|
195
|
+
cursor: progress;
|
|
196
|
+
opacity: 0.6;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.labre-title-band-chip:focus-visible,
|
|
200
|
+
.labre-title-band-chip dv-standalone-cell:focus-visible {
|
|
201
|
+
outline: 2px solid var(--affine-primary-color);
|
|
202
|
+
outline-offset: 1px;
|
|
203
|
+
border-radius: 4px;
|
|
204
|
+
}
|
|
205
|
+
|
|
168
206
|
.labre-title-band-chip-name {
|
|
169
207
|
color: var(--affine-text-secondary-color);
|
|
170
208
|
white-space: nowrap;
|
|
171
209
|
}
|
|
172
210
|
|
|
211
|
+
/* Room only: what is inside is the cell's own drawing. */
|
|
173
212
|
.labre-title-band-chip-value {
|
|
174
|
-
|
|
175
|
-
align-items: center;
|
|
176
|
-
gap: 4px;
|
|
213
|
+
max-width: 240px;
|
|
177
214
|
overflow: hidden;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
.labre-title-band-chip-text {
|
|
178
218
|
text-overflow: ellipsis;
|
|
179
219
|
white-space: nowrap;
|
|
180
|
-
max-width: 240px;
|
|
181
220
|
}
|
|
182
221
|
|
|
183
|
-
.labre-title-band-chip[data-empty='true']
|
|
222
|
+
.labre-title-band-chip-text[data-empty='true'] {
|
|
184
223
|
color: var(--affine-placeholder-color);
|
|
185
224
|
}
|
|
186
225
|
|
|
187
|
-
.labre-title-band-tag {
|
|
188
|
-
display: inline-block;
|
|
189
|
-
padding: 0 6px;
|
|
190
|
-
border-radius: 4px;
|
|
191
|
-
max-width: 160px;
|
|
192
|
-
overflow: hidden;
|
|
193
|
-
text-overflow: ellipsis;
|
|
194
|
-
white-space: nowrap;
|
|
195
|
-
background-color: var(--affine-tag-white);
|
|
196
|
-
}
|
|
197
|
-
|
|
198
226
|
.labre-title-band-skeleton {
|
|
199
227
|
display: inline-block;
|
|
200
228
|
width: 96px;
|
|
@@ -208,39 +236,34 @@ let TitleBand = (() => {
|
|
|
208
236
|
padding-right: 4px;
|
|
209
237
|
}
|
|
210
238
|
|
|
239
|
+
/* Layout only: the buttons are the band's own, no drawing of their own. */
|
|
240
|
+
.labre-title-band-not-shown-item {
|
|
241
|
+
display: inline-flex;
|
|
242
|
+
align-items: center;
|
|
243
|
+
max-width: 100%;
|
|
244
|
+
}
|
|
245
|
+
|
|
211
246
|
@media (prefers-reduced-motion: reduce) {
|
|
212
|
-
.labre-title-band button
|
|
247
|
+
.labre-title-band button,
|
|
248
|
+
.labre-title-band-chip {
|
|
213
249
|
transition: none;
|
|
214
250
|
}
|
|
215
251
|
}
|
|
216
252
|
|
|
217
253
|
/* A 44px target under a coarse pointer, without changing the drawing. */
|
|
218
254
|
@media (pointer: coarse) {
|
|
219
|
-
.labre-title-band button
|
|
255
|
+
.labre-title-band button,
|
|
256
|
+
.labre-title-band-chip {
|
|
220
257
|
position: relative;
|
|
221
258
|
}
|
|
222
|
-
.labre-title-band button::after
|
|
259
|
+
.labre-title-band button::after,
|
|
260
|
+
.labre-title-band-chip::after {
|
|
223
261
|
content: '';
|
|
224
262
|
position: absolute;
|
|
225
263
|
inset: -8px 0;
|
|
226
264
|
}
|
|
227
265
|
}
|
|
228
266
|
`; }
|
|
229
|
-
_pop(target, title, items) {
|
|
230
|
-
this._menu?.close();
|
|
231
|
-
const handler = popMenu(popupTargetFromElement(target), {
|
|
232
|
-
options: {
|
|
233
|
-
title: { text: title },
|
|
234
|
-
items,
|
|
235
|
-
onClose: () => {
|
|
236
|
-
if (this._menu === handler)
|
|
237
|
-
this._menu = null;
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
});
|
|
241
|
-
this._menu = handler;
|
|
242
|
-
return handler;
|
|
243
|
-
}
|
|
244
267
|
/** Read inside `render` it subscribes, through `SignalWatcher`. */
|
|
245
268
|
get _readonly() {
|
|
246
269
|
return this.std?.store.readonly$.value ?? true;
|
|
@@ -264,7 +287,8 @@ let TitleBand = (() => {
|
|
|
264
287
|
docId,
|
|
265
288
|
sheet$: service.sheet$(docId),
|
|
266
289
|
collapsed$: service.collapsed$?.(docId) ?? null,
|
|
267
|
-
notShown$:
|
|
290
|
+
notShown$: service.notShown$?.(docId) ?? null,
|
|
291
|
+
cells: new Map(),
|
|
268
292
|
};
|
|
269
293
|
this._sources = sources;
|
|
270
294
|
return sources;
|
|
@@ -305,125 +329,109 @@ let TitleBand = (() => {
|
|
|
305
329
|
console.error('[title-band] set was refused', error);
|
|
306
330
|
});
|
|
307
331
|
}
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
>`;
|
|
314
|
-
}
|
|
315
|
-
_clearItem(prop) {
|
|
316
|
-
return menu.action({
|
|
317
|
-
name: this._t(TITLE_BAND_CLEAR),
|
|
318
|
-
select: () => this._write(prop, null),
|
|
319
|
-
});
|
|
320
|
-
}
|
|
321
|
-
_popSelect(target, prop) {
|
|
322
|
-
const items = chipOptions(prop).map(tag => menu.action({
|
|
323
|
-
name: tag.label,
|
|
324
|
-
label: () => this._tagLabel(tag),
|
|
325
|
-
isSelected: tag.id === prop.value,
|
|
326
|
-
select: () => {
|
|
327
|
-
if (tag.id !== prop.value)
|
|
328
|
-
this._write(prop, tag.id);
|
|
329
|
-
},
|
|
330
|
-
}));
|
|
331
|
-
if (prop.value != null)
|
|
332
|
-
items.push(this._clearItem(prop));
|
|
333
|
-
this._pop(target, prop.name, items);
|
|
334
|
-
}
|
|
335
|
-
_popMultiSelect(target, prop) {
|
|
336
|
-
// A draft, because the host's answer arrives later through `sheet$`: two
|
|
337
|
-
// ticks in one open menu must not both start from the stale value.
|
|
338
|
-
const draft$ = signal(Array.isArray(prop.value)
|
|
339
|
-
? prop.value.filter((id) => typeof id === 'string')
|
|
340
|
-
: []);
|
|
341
|
-
const items = chipOptions(prop).map(tag => menu.checkbox({
|
|
342
|
-
name: tag.label,
|
|
343
|
-
label: () => this._tagLabel(tag),
|
|
344
|
-
checked: computed(() => draft$.value.includes(tag.id)),
|
|
345
|
-
select: checked => {
|
|
346
|
-
const next = checked
|
|
347
|
-
? draft$.peek().filter(id => id !== tag.id)
|
|
348
|
-
: [...draft$.peek(), tag.id];
|
|
349
|
-
draft$.value = next;
|
|
350
|
-
this._write(prop, next);
|
|
351
|
-
return !checked;
|
|
352
|
-
},
|
|
353
|
-
}));
|
|
354
|
-
this._pop(target, prop.name, items);
|
|
332
|
+
/** A value a cell commits: unchanged, nothing is written. */
|
|
333
|
+
_commit(prop, cellType, value) {
|
|
334
|
+
if (sameBandValue(cellType, prop.value, value))
|
|
335
|
+
return;
|
|
336
|
+
this._write(prop, bandWriteValue(value));
|
|
355
337
|
}
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
picker.padding = 0;
|
|
360
|
-
picker.value = typeof prop.value === 'number' ? prop.value : Date.now();
|
|
361
|
-
picker.onChange = (date) => {
|
|
362
|
-
if (date.getTime() !== prop.value)
|
|
363
|
-
this._write(prop, date.getTime());
|
|
364
|
-
close();
|
|
365
|
-
};
|
|
366
|
-
picker.onClear = () => {
|
|
367
|
-
this._write(prop, null);
|
|
368
|
-
close();
|
|
369
|
-
};
|
|
370
|
-
picker.onEscape = () => close();
|
|
371
|
-
const items = [() => html `${picker}`];
|
|
372
|
-
const handler = this._pop(target, prop.name, items);
|
|
373
|
-
close = () => handler.close();
|
|
338
|
+
/** Neither the property nor the document can be written, or the type. */
|
|
339
|
+
_isReadonlyChip(prop) {
|
|
340
|
+
return (!prop || prop.readonly || this._readonly || isBandReadonlyType(prop.type));
|
|
374
341
|
}
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
342
|
+
/**
|
|
343
|
+
* The cell that draws `prop`, built once per property and type: its value,
|
|
344
|
+
* name and config are read from the sheet, so a new sheet updates the cell
|
|
345
|
+
* in place and an editor open in it stays open.
|
|
346
|
+
*/
|
|
347
|
+
_cellFor(sources, prop) {
|
|
348
|
+
const std = this.std;
|
|
349
|
+
if (!std)
|
|
350
|
+
return null;
|
|
351
|
+
const meta = bandCellMeta(prop.type, cellType => std.getOptional(StandaloneCellMetaProvider(cellType)));
|
|
352
|
+
if (!meta)
|
|
353
|
+
return null;
|
|
354
|
+
const cached = sources.cells.get(prop.id);
|
|
355
|
+
if (cached?.type === prop.type)
|
|
356
|
+
return cached.cell;
|
|
357
|
+
const { id, type } = prop;
|
|
358
|
+
const cellType = meta.type;
|
|
359
|
+
const current$ = computed(() => {
|
|
360
|
+
const state = sources.sheet$.value;
|
|
361
|
+
if (state.status !== 'ready')
|
|
362
|
+
return undefined;
|
|
363
|
+
return state.properties.find(p => p.id === id && p.type === type);
|
|
364
|
+
});
|
|
365
|
+
const cell = createStandaloneCell(meta, {
|
|
366
|
+
propertyId: id,
|
|
367
|
+
name$: computed(() => current$.value?.name ?? ''),
|
|
368
|
+
data$: computed(() => {
|
|
369
|
+
const current = current$.value;
|
|
370
|
+
return current ? bandCellData(cellType, current) : {};
|
|
392
371
|
}),
|
|
393
|
-
|
|
372
|
+
value$: computed(() => bandCellValue(cellType, current$.value?.value)),
|
|
373
|
+
readonly$: computed(() => this._isReadonlyChip(current$.value)),
|
|
374
|
+
valueSet: value => {
|
|
375
|
+
const current = current$.peek();
|
|
376
|
+
if (current)
|
|
377
|
+
this._commit(current, cellType, value);
|
|
378
|
+
},
|
|
379
|
+
featureFlags$: this._featureFlags$,
|
|
380
|
+
serviceGet: key => std.getOptional(key),
|
|
381
|
+
});
|
|
382
|
+
sources.cells.set(id, { type, cell });
|
|
383
|
+
return cell;
|
|
394
384
|
}
|
|
395
|
-
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
case 'text':
|
|
403
|
-
return view.text;
|
|
404
|
-
default:
|
|
405
|
-
return this._t(TITLE_BAND_EMPTY);
|
|
406
|
-
}
|
|
385
|
+
_renderFallback(prop) {
|
|
386
|
+
const text = formatPropertyValue(prop, this._locale);
|
|
387
|
+
return html `<span
|
|
388
|
+
class="labre-title-band-chip-value labre-title-band-chip-text"
|
|
389
|
+
data-empty=${text ? 'false' : 'true'}
|
|
390
|
+
>${text || this._t(TITLE_BAND_EMPTY)}</span
|
|
391
|
+
>`;
|
|
407
392
|
}
|
|
408
|
-
_renderChip(prop, hasPanel) {
|
|
393
|
+
_renderChip(sources, prop, hasPanel) {
|
|
409
394
|
const pending = this._pending$.value.has(prop.id);
|
|
410
|
-
const
|
|
395
|
+
const cell = this._cellFor(sources, prop);
|
|
396
|
+
const editable = !!cell && !this._isReadonlyChip(prop);
|
|
411
397
|
const clickable = editable || hasPanel;
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
398
|
+
// Without a cell the chip itself is what a keyboard reaches.
|
|
399
|
+
const focusable = !cell && hasPanel;
|
|
400
|
+
return html `<div
|
|
401
|
+
class="labre-title-band-chip"
|
|
415
402
|
data-testid="title-band-chip"
|
|
416
403
|
data-property-id=${prop.id}
|
|
417
|
-
data-empty=${
|
|
404
|
+
data-empty=${isPropertyValueEmpty(prop) ? 'true' : 'false'}
|
|
405
|
+
data-clickable=${clickable ? 'true' : 'false'}
|
|
418
406
|
aria-busy=${pending ? 'true' : 'false'}
|
|
419
|
-
|
|
420
|
-
|
|
407
|
+
role=${focusable ? 'button' : nothing}
|
|
408
|
+
tabindex=${focusable ? '0' : nothing}
|
|
409
|
+
@click=${(event) => {
|
|
410
|
+
if (clickable)
|
|
411
|
+
this._onChip(event, editable);
|
|
412
|
+
}}
|
|
413
|
+
@keydown=${(event) => {
|
|
414
|
+
if (!focusable || event.target !== event.currentTarget)
|
|
415
|
+
return;
|
|
416
|
+
if (event.key !== 'Enter' && event.key !== ' ')
|
|
417
|
+
return;
|
|
418
|
+
event.preventDefault();
|
|
419
|
+
this._onChip(event, false);
|
|
420
|
+
}}
|
|
421
421
|
>
|
|
422
422
|
<span class="labre-title-band-chip-name">${prop.name}</span>
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
423
|
+
${cell
|
|
424
|
+
? html `<dv-standalone-cell
|
|
425
|
+
class="labre-title-band-chip-value"
|
|
426
|
+
data-testid="title-band-cell"
|
|
427
|
+
role=${editable ? 'button' : nothing}
|
|
428
|
+
aria-label=${prop.name}
|
|
429
|
+
.cell=${cell}
|
|
430
|
+
.readonly=${!editable}
|
|
431
|
+
.placeholder=${this._t(TITLE_BAND_EMPTY)}
|
|
432
|
+
></dv-standalone-cell>`
|
|
433
|
+
: this._renderFallback(prop)}
|
|
434
|
+
</div>`;
|
|
427
435
|
}
|
|
428
436
|
_renderTools(sources, hasPanel) {
|
|
429
437
|
const canAdd = !!sources.service.add && !this._readonly;
|
|
@@ -519,7 +527,7 @@ let TitleBand = (() => {
|
|
|
519
527
|
${ToggleDownIcon()}
|
|
520
528
|
</button>`
|
|
521
529
|
: nothing}
|
|
522
|
-
${repeat(properties, prop => prop.id, prop => this._renderChip(prop, hasPanel))}
|
|
530
|
+
${repeat(properties, prop => prop.id, prop => this._renderChip(sources, prop, hasPanel))}
|
|
523
531
|
${this._renderTools(sources, hasPanel)}
|
|
524
532
|
</div>`;
|
|
525
533
|
}
|
|
@@ -530,32 +538,55 @@ let TitleBand = (() => {
|
|
|
530
538
|
// A link that opens nothing is a lie: no linked-document path, no row.
|
|
531
539
|
if (!std || !slots || pages.length === 0)
|
|
532
540
|
return nothing;
|
|
541
|
+
const label = this._t(TITLE_BAND_NOT_SHOWN);
|
|
542
|
+
const showHere = this._readonly ? null : this._t(TITLE_BAND_SHOW_HERE);
|
|
533
543
|
return html `<div
|
|
534
544
|
class="labre-title-band-row"
|
|
545
|
+
role="group"
|
|
546
|
+
aria-label=${label}
|
|
535
547
|
data-testid="title-band-not-shown"
|
|
536
548
|
>
|
|
537
|
-
<span class="labre-title-band-not-shown-label"
|
|
538
|
-
>${
|
|
549
|
+
<span class="labre-title-band-not-shown-label" aria-hidden="true"
|
|
550
|
+
>${label}</span
|
|
539
551
|
>
|
|
540
|
-
${repeat(pages, page => page.docId, page =>
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
event,
|
|
549
|
-
});
|
|
550
|
-
}}
|
|
552
|
+
${repeat(pages, page => page.docId, page => {
|
|
553
|
+
const title = page.title.trim() === '' ? this._t(DOC_UNTITLED) : page.title;
|
|
554
|
+
// A group named after the page, so a screen reader hears which
|
|
555
|
+
// page each "Show here" belongs to without a second wording.
|
|
556
|
+
return html `<span
|
|
557
|
+
class="labre-title-band-not-shown-item"
|
|
558
|
+
role="group"
|
|
559
|
+
aria-label=${title}
|
|
551
560
|
>
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
561
|
+
<button
|
|
562
|
+
data-testid="title-band-not-shown-page"
|
|
563
|
+
data-doc-id=${page.docId}
|
|
564
|
+
@click=${(event) => {
|
|
565
|
+
event.stopPropagation();
|
|
566
|
+
slots.docLinkClicked.next({
|
|
567
|
+
pageId: page.docId,
|
|
568
|
+
host: std.host,
|
|
569
|
+
event,
|
|
570
|
+
});
|
|
571
|
+
}}
|
|
557
572
|
>
|
|
558
|
-
|
|
573
|
+
${LinkedPageIcon()}
|
|
574
|
+
<span class="labre-title-band-chip-value">${title}</span>
|
|
575
|
+
</button>
|
|
576
|
+
${showHere
|
|
577
|
+
? html `<button
|
|
578
|
+
data-testid="title-band-show-here"
|
|
579
|
+
data-doc-id=${page.docId}
|
|
580
|
+
@click=${(event) => {
|
|
581
|
+
event.stopPropagation();
|
|
582
|
+
showPageHere(std, this.surface, page.docId);
|
|
583
|
+
}}
|
|
584
|
+
>
|
|
585
|
+
${showHere}
|
|
586
|
+
</button>`
|
|
587
|
+
: nothing}
|
|
588
|
+
</span>`;
|
|
589
|
+
})}
|
|
559
590
|
</div>`;
|
|
560
591
|
}
|
|
561
592
|
connectedCallback() {
|
|
@@ -565,7 +596,6 @@ let TitleBand = (() => {
|
|
|
565
596
|
// split the title) nor the canvas's (a press would start a drag).
|
|
566
597
|
this._disposables.addFromEvent(this, 'keydown', stopPropagation);
|
|
567
598
|
this._disposables.addFromEvent(this, 'pointerdown', stopPropagation);
|
|
568
|
-
this._disposables.add(() => this._menu?.close());
|
|
569
599
|
}
|
|
570
600
|
render() {
|
|
571
601
|
const std = this.std;
|
|
@@ -576,7 +606,7 @@ let TitleBand = (() => {
|
|
|
576
606
|
return nothing;
|
|
577
607
|
const sources = this._getSources(service);
|
|
578
608
|
const sheet = this._renderSheet(sources);
|
|
579
|
-
const notShown = this.
|
|
609
|
+
const notShown = this._renderNotShown(sources);
|
|
580
610
|
if (sheet === nothing && notShown === nothing)
|
|
581
611
|
return nothing;
|
|
582
612
|
return html `<div
|
|
@@ -594,44 +624,23 @@ let TitleBand = (() => {
|
|
|
594
624
|
get docId() { return this.#docId_accessor_storage; }
|
|
595
625
|
set docId(value) { this.#docId_accessor_storage = value; }
|
|
596
626
|
#surface_accessor_storage;
|
|
597
|
-
/** Where the band is drawn
|
|
627
|
+
/** Where the band is drawn: where "Show here" puts the card. */
|
|
598
628
|
get surface() { return this.#surface_accessor_storage; }
|
|
599
629
|
set surface(value) { this.#surface_accessor_storage = value; }
|
|
600
630
|
constructor() {
|
|
601
631
|
super(...arguments);
|
|
602
632
|
this._sources = null;
|
|
603
|
-
/** The editor menu open now, put away with the band. */
|
|
604
|
-
this._menu = null;
|
|
605
633
|
/** Collapse state when the host does not remember one. */
|
|
606
634
|
this._localCollapsed$ = signal(false);
|
|
607
635
|
/** Property ids whose `set` has not settled yet. */
|
|
608
636
|
this._pending$ = signal(new Set());
|
|
609
|
-
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
case 'select':
|
|
617
|
-
this._popSelect(target, prop);
|
|
618
|
-
return;
|
|
619
|
-
case 'multi-select':
|
|
620
|
-
this._popMultiSelect(target, prop);
|
|
621
|
-
return;
|
|
622
|
-
case 'date':
|
|
623
|
-
this._popDate(target, prop);
|
|
624
|
-
return;
|
|
625
|
-
case 'number':
|
|
626
|
-
this._popInput(target, prop, 'number');
|
|
627
|
-
return;
|
|
628
|
-
case 'text':
|
|
629
|
-
this._popInput(target, prop, 'text');
|
|
630
|
-
return;
|
|
631
|
-
default:
|
|
632
|
-
this._openPanel();
|
|
633
|
-
}
|
|
634
|
-
};
|
|
637
|
+
/** The table's own flags, so a number reads as it does in a cell. */
|
|
638
|
+
this._featureFlags$ = computed(() => ({
|
|
639
|
+
enable_number_formatting: this.std
|
|
640
|
+
?.getOptional(FeatureFlagService)
|
|
641
|
+
?.getFlag('enable_database_number_formatting') ?? false,
|
|
642
|
+
enable_table_virtual_scroll: false,
|
|
643
|
+
}));
|
|
635
644
|
this._openPanel = () => {
|
|
636
645
|
if (!this.std)
|
|
637
646
|
return;
|
|
@@ -639,6 +648,15 @@ let TitleBand = (() => {
|
|
|
639
648
|
.getOptional(PropertiesPanelProvider)
|
|
640
649
|
?.open({ scope: 'page', docId: this.docId });
|
|
641
650
|
};
|
|
651
|
+
this._onChip = (event, editable) => {
|
|
652
|
+
event.stopPropagation();
|
|
653
|
+
const chip = event.currentTarget;
|
|
654
|
+
if (editable) {
|
|
655
|
+
chip.querySelector('dv-standalone-cell')?.edit();
|
|
656
|
+
return;
|
|
657
|
+
}
|
|
658
|
+
this._openPanel();
|
|
659
|
+
};
|
|
642
660
|
this.#std_accessor_storage = __runInitializers(this, _std_initializers, null);
|
|
643
661
|
this.#docId_accessor_storage = (__runInitializers(this, _std_extraInitializers), __runInitializers(this, _docId_initializers, ''));
|
|
644
662
|
this.#surface_accessor_storage = (__runInitializers(this, _docId_extraInitializers), __runInitializers(this, _surface_initializers, 'page'));
|
|
@@ -23,12 +23,15 @@ export declare const TITLE_BAND_COLLAPSE: ChromeWording;
|
|
|
23
23
|
export declare const TITLE_BAND_EXPAND: ChromeWording;
|
|
24
24
|
/** The accessible name of the skeleton drawn while the sheet loads. */
|
|
25
25
|
export declare const TITLE_BAND_LOADING: ChromeWording;
|
|
26
|
-
/** Clears a select or a date from its editor. */
|
|
27
|
-
export declare const TITLE_BAND_CLEAR: ChromeWording;
|
|
28
26
|
/**
|
|
29
|
-
* The
|
|
30
|
-
*
|
|
27
|
+
* The row of child pages the document holds but does not display, under the
|
|
28
|
+
* title and in the note header (ADR 0035 §9d and its 2026-10-13 amendment).
|
|
31
29
|
*/
|
|
32
30
|
export declare const TITLE_BAND_NOT_SHOWN: ChromeWording;
|
|
31
|
+
/**
|
|
32
|
+
* The button beside each page of that row: inserts a card of the page here
|
|
33
|
+
* (labre ADR-0045 §7).
|
|
34
|
+
*/
|
|
35
|
+
export declare const TITLE_BAND_SHOW_HERE: ChromeWording;
|
|
33
36
|
/** Every wording this package declares, in the order it renders them. */
|
|
34
37
|
export declare const DOC_TITLE_WORDINGS: readonly ChromeWording[];
|
|
@@ -47,24 +47,26 @@ export const TITLE_BAND_LOADING = [
|
|
|
47
47
|
'com.labre.title-band.loading',
|
|
48
48
|
'Loading properties',
|
|
49
49
|
];
|
|
50
|
-
/** Clears a select or a date from its editor. */
|
|
51
|
-
export const TITLE_BAND_CLEAR = [
|
|
52
|
-
'com.labre.title-band.clear',
|
|
53
|
-
'Clear value',
|
|
54
|
-
];
|
|
55
50
|
/**
|
|
56
|
-
* The
|
|
57
|
-
*
|
|
51
|
+
* The row of child pages the document holds but does not display, under the
|
|
52
|
+
* title and in the note header (ADR 0035 §9d and its 2026-10-13 amendment).
|
|
58
53
|
*/
|
|
59
54
|
export const TITLE_BAND_NOT_SHOWN = [
|
|
60
55
|
'com.labre.title-band.not-shown',
|
|
61
|
-
'Not shown
|
|
56
|
+
'Not shown on this page',
|
|
57
|
+
];
|
|
58
|
+
/**
|
|
59
|
+
* The button beside each page of that row: inserts a card of the page here
|
|
60
|
+
* (labre ADR-0045 §7).
|
|
61
|
+
*/
|
|
62
|
+
export const TITLE_BAND_SHOW_HERE = [
|
|
63
|
+
'com.labre.title-band.show-here',
|
|
64
|
+
'Show here',
|
|
62
65
|
];
|
|
63
66
|
/** Every wording this package declares, in the order it renders them. */
|
|
64
67
|
export const DOC_TITLE_WORDINGS = [
|
|
65
68
|
DOC_TITLE_PLACEHOLDER,
|
|
66
69
|
TITLE_BAND_ADD,
|
|
67
|
-
TITLE_BAND_CLEAR,
|
|
68
70
|
TITLE_BAND_COLLAPSE,
|
|
69
71
|
TITLE_BAND_EMPTY,
|
|
70
72
|
TITLE_BAND_EXPAND,
|
|
@@ -72,4 +74,5 @@ export const DOC_TITLE_WORDINGS = [
|
|
|
72
74
|
TITLE_BAND_LOADING,
|
|
73
75
|
TITLE_BAND_NOT_SHOWN,
|
|
74
76
|
TITLE_BAND_OPEN_PANEL,
|
|
77
|
+
TITLE_BAND_SHOW_HERE,
|
|
75
78
|
];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
export declare const groupToolbarConfig: {
|
|
2
2
|
readonly actions: [{
|
|
3
3
|
readonly id: "a.insert-into-page";
|
|
4
|
-
readonly label: "Insert into
|
|
4
|
+
readonly label: "Insert into Page";
|
|
5
5
|
readonly labelWording: import("../../affine-shared/services/index.js").ChromeWording;
|
|
6
|
-
readonly tooltip: "Insert into
|
|
6
|
+
readonly tooltip: "Insert into Page";
|
|
7
7
|
readonly tooltipWording: import("../../affine-shared/services/index.js").ChromeWording;
|
|
8
8
|
readonly icon: import("lit-html").TemplateResult<1>;
|
|
9
9
|
readonly when: (ctx: import("../../affine-shared/services/index.js").ToolbarContext) => boolean;
|