@formicoidea/labre-core 0.48.0 → 0.49.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 (222) hide show
  1. package/dist/_pkgs/affine-block-data-view/configs/slash-menu.js +3 -1
  2. package/dist/_pkgs/affine-block-data-view/view.d.ts +17 -1
  3. package/dist/_pkgs/affine-block-data-view/view.js +21 -2
  4. package/dist/_pkgs/affine-block-database/commands.d.ts +2 -2
  5. package/dist/_pkgs/affine-block-database/commands.js +3 -3
  6. package/dist/_pkgs/affine-block-database/components/values-banner.d.ts +28 -0
  7. package/dist/_pkgs/affine-block-database/components/values-banner.js +199 -0
  8. package/dist/_pkgs/affine-block-database/configs/slash-menu.d.ts +6 -1
  9. package/dist/_pkgs/affine-block-database/configs/slash-menu.js +57 -70
  10. package/dist/_pkgs/affine-block-database/data-source.d.ts +9 -5
  11. package/dist/_pkgs/affine-block-database/data-source.js +11 -7
  12. package/dist/_pkgs/affine-block-database/database-block-styles.d.ts +2 -0
  13. package/dist/_pkgs/affine-block-database/database-block-styles.js +15 -0
  14. package/dist/_pkgs/affine-block-database/database-block.d.ts +23 -0
  15. package/dist/_pkgs/affine-block-database/database-block.js +141 -19
  16. package/dist/_pkgs/affine-block-database/effects.js +2 -0
  17. package/dist/_pkgs/affine-block-database/external-data-source.d.ts +69 -2
  18. package/dist/_pkgs/affine-block-database/external-data-source.js +88 -16
  19. package/dist/_pkgs/affine-block-database/index.d.ts +2 -0
  20. package/dist/_pkgs/affine-block-database/index.js +2 -0
  21. package/dist/_pkgs/affine-block-database/linked-view.d.ts +38 -0
  22. package/dist/_pkgs/affine-block-database/linked-view.js +109 -0
  23. package/dist/_pkgs/affine-block-database/properties/index.d.ts +2 -0
  24. package/dist/_pkgs/affine-block-database/properties/index.js +2 -0
  25. package/dist/_pkgs/affine-block-database/properties/text/hosted.d.ts +15 -0
  26. package/dist/_pkgs/affine-block-database/properties/text/hosted.js +24 -0
  27. package/dist/_pkgs/affine-block-database/properties/title/hosted.d.ts +16 -0
  28. package/dist/_pkgs/affine-block-database/properties/title/hosted.js +42 -0
  29. package/dist/_pkgs/affine-block-database/service/index.d.ts +3 -0
  30. package/dist/_pkgs/affine-block-database/service/index.js +3 -0
  31. package/dist/_pkgs/affine-block-database/service/new-row-menu.d.ts +49 -0
  32. package/dist/_pkgs/affine-block-database/service/new-row-menu.js +21 -0
  33. package/dist/_pkgs/affine-block-database/service/open-row.d.ts +77 -0
  34. package/dist/_pkgs/affine-block-database/service/open-row.js +62 -0
  35. package/dist/_pkgs/affine-block-database/service/properties-panel.d.ts +23 -0
  36. package/dist/_pkgs/affine-block-database/service/properties-panel.js +33 -0
  37. package/dist/_pkgs/affine-block-database/translations.d.ts +10 -0
  38. package/dist/_pkgs/affine-block-database/translations.js +35 -0
  39. package/dist/_pkgs/affine-block-database/view-creation.d.ts +10 -0
  40. package/dist/_pkgs/affine-block-database/view-creation.js +14 -0
  41. package/dist/_pkgs/affine-block-database/view.d.ts +31 -1
  42. package/dist/_pkgs/affine-block-database/view.js +44 -5
  43. package/dist/_pkgs/affine-block-database/views/index.d.ts +30 -3
  44. package/dist/_pkgs/affine-block-database/views/index.js +44 -3
  45. package/dist/_pkgs/affine-components/date-picker/date-picker.d.ts +20 -0
  46. package/dist/_pkgs/affine-components/date-picker/date-picker.js +60 -26
  47. package/dist/_pkgs/affine-components/date-picker/style.js +1 -0
  48. package/dist/_pkgs/affine-components/translations.d.ts +4 -0
  49. package/dist/_pkgs/affine-components/translations.js +26 -0
  50. package/dist/_pkgs/affine-fragment-doc-title/doc-title.d.ts +18 -0
  51. package/dist/_pkgs/affine-fragment-doc-title/doc-title.js +41 -2
  52. package/dist/_pkgs/affine-fragment-doc-title/title-band/band-cell.d.ts +8 -0
  53. package/dist/_pkgs/affine-fragment-doc-title/title-band/band-cell.js +12 -0
  54. package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.d.ts +5 -0
  55. package/dist/_pkgs/affine-fragment-doc-title/title-band/title-band.js +44 -4
  56. package/dist/_pkgs/affine-model/blocks/database/types.d.ts +16 -0
  57. package/dist/_pkgs/affine-model/blocks/database/types.js +5 -1
  58. package/dist/_pkgs/affine-shared/services/data-source-picker-service.d.ts +139 -0
  59. package/dist/_pkgs/affine-shared/services/data-source-picker-service.js +22 -0
  60. package/dist/_pkgs/affine-shared/services/index.d.ts +1 -0
  61. package/dist/_pkgs/affine-shared/services/index.js +1 -0
  62. package/dist/_pkgs/affine-shared/services/telemetry-service/database.d.ts +59 -0
  63. package/dist/_pkgs/affine-shared/services/title-band-service.d.ts +24 -0
  64. package/dist/_pkgs/data-view/core/component/cell-status/cell-status-css.d.ts +2 -0
  65. package/dist/_pkgs/data-view/core/component/cell-status/cell-status-css.js +16 -0
  66. package/dist/_pkgs/data-view/core/component/cell-status/cell-status.d.ts +10 -0
  67. package/dist/_pkgs/data-view/core/component/cell-status/cell-status.js +23 -0
  68. package/dist/_pkgs/data-view/core/component/index.d.ts +1 -0
  69. package/dist/_pkgs/data-view/core/component/index.js +1 -0
  70. package/dist/_pkgs/data-view/core/component/overflow/fit.d.ts +26 -0
  71. package/dist/_pkgs/data-view/core/component/overflow/fit.js +48 -0
  72. package/dist/_pkgs/data-view/core/component/overflow/overflow.d.ts +26 -3
  73. package/dist/_pkgs/data-view/core/component/overflow/overflow.js +84 -31
  74. package/dist/_pkgs/data-view/core/component/tags/colors.d.ts +7 -0
  75. package/dist/_pkgs/data-view/core/component/tags/colors.js +22 -10
  76. package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.d.ts +18 -0
  77. package/dist/_pkgs/data-view/core/component/tags/multi-tag-select.js +63 -21
  78. package/dist/_pkgs/data-view/core/data-source/base.d.ts +5 -1
  79. package/dist/_pkgs/data-view/core/data-source/base.js +7 -1
  80. package/dist/_pkgs/data-view/core/data-source/hydration.d.ts +44 -0
  81. package/dist/_pkgs/data-view/core/data-source/hydration.js +31 -0
  82. package/dist/_pkgs/data-view/core/data-source/index.d.ts +1 -0
  83. package/dist/_pkgs/data-view/core/data-source/index.js +1 -0
  84. package/dist/_pkgs/data-view/core/data-view.d.ts +22 -2
  85. package/dist/_pkgs/data-view/core/data-view.js +14 -0
  86. package/dist/_pkgs/data-view/core/effect.js +2 -0
  87. package/dist/_pkgs/data-view/core/group-by/collapsed-state.d.ts +3 -0
  88. package/dist/_pkgs/data-view/core/group-by/collapsed-state.js +59 -0
  89. package/dist/_pkgs/data-view/core/group-by/group-properties.d.ts +21 -0
  90. package/dist/_pkgs/data-view/core/group-by/group-properties.js +38 -0
  91. package/dist/_pkgs/data-view/core/group-by/group-title.js +4 -0
  92. package/dist/_pkgs/data-view/core/group-by/group-visibility.d.ts +40 -0
  93. package/dist/_pkgs/data-view/core/group-by/group-visibility.js +291 -0
  94. package/dist/_pkgs/data-view/core/group-by/setting.d.ts +11 -3
  95. package/dist/_pkgs/data-view/core/group-by/setting.js +81 -8
  96. package/dist/_pkgs/data-view/core/group-by/trait.d.ts +22 -0
  97. package/dist/_pkgs/data-view/core/group-by/trait.js +62 -1
  98. package/dist/_pkgs/data-view/core/index.d.ts +3 -0
  99. package/dist/_pkgs/data-view/core/index.js +3 -0
  100. package/dist/_pkgs/data-view/core/property/base-cell.d.ts +15 -1
  101. package/dist/_pkgs/data-view/core/property/base-cell.js +28 -3
  102. package/dist/_pkgs/data-view/core/property/standalone-cell.d.ts +15 -1
  103. package/dist/_pkgs/data-view/core/property/standalone-cell.js +19 -1
  104. package/dist/_pkgs/data-view/core/telemetry.d.ts +16 -0
  105. package/dist/_pkgs/data-view/core/telemetry.js +22 -0
  106. package/dist/_pkgs/data-view/core/utils/new-tab-click.d.ts +2 -0
  107. package/dist/_pkgs/data-view/core/utils/new-tab-click.js +4 -0
  108. package/dist/_pkgs/data-view/core/utils/wording.d.ts +11 -0
  109. package/dist/_pkgs/data-view/core/utils/wording.js +9 -0
  110. package/dist/_pkgs/data-view/core/view/data-view.d.ts +7 -0
  111. package/dist/_pkgs/data-view/core/view/default-name.d.ts +10 -0
  112. package/dist/_pkgs/data-view/core/view/default-name.js +14 -0
  113. package/dist/_pkgs/data-view/core/view/index.d.ts +2 -0
  114. package/dist/_pkgs/data-view/core/view/index.js +2 -0
  115. package/dist/_pkgs/data-view/core/view/open-in.d.ts +27 -0
  116. package/dist/_pkgs/data-view/core/view/open-in.js +39 -0
  117. package/dist/_pkgs/data-view/core/view-manager/cell.d.ts +5 -0
  118. package/dist/_pkgs/data-view/core/view-manager/cell.js +11 -0
  119. package/dist/_pkgs/data-view/core/view-manager/index.d.ts +3 -0
  120. package/dist/_pkgs/data-view/core/view-manager/index.js +3 -0
  121. package/dist/_pkgs/data-view/core/view-manager/new-row-menu-opener.d.ts +18 -0
  122. package/dist/_pkgs/data-view/core/view-manager/new-row-menu-opener.js +2 -0
  123. package/dist/_pkgs/data-view/core/view-manager/properties-panel-opener.d.ts +8 -0
  124. package/dist/_pkgs/data-view/core/view-manager/properties-panel-opener.js +9 -0
  125. package/dist/_pkgs/data-view/core/view-manager/property.d.ts +8 -0
  126. package/dist/_pkgs/data-view/core/view-manager/single-view.d.ts +28 -1
  127. package/dist/_pkgs/data-view/core/view-manager/single-view.js +45 -1
  128. package/dist/_pkgs/data-view/core/view-manager/view-creation.d.ts +49 -0
  129. package/dist/_pkgs/data-view/core/view-manager/view-creation.js +40 -0
  130. package/dist/_pkgs/data-view/core/view-manager/view-manager.d.ts +6 -2
  131. package/dist/_pkgs/data-view/core/view-manager/view-manager.js +2 -2
  132. package/dist/_pkgs/data-view/property-presets/date/cell-renderer.d.ts +2 -0
  133. package/dist/_pkgs/data-view/property-presets/date/cell-renderer.js +11 -2
  134. package/dist/_pkgs/data-view/property-presets/multi-select/cell-renderer.js +2 -0
  135. package/dist/_pkgs/data-view/property-presets/select/cell-renderer.js +2 -0
  136. package/dist/_pkgs/data-view/translations.d.ts +55 -0
  137. package/dist/_pkgs/data-view/translations.js +181 -0
  138. package/dist/_pkgs/data-view/view-presets/calendar/define.js +3 -1
  139. package/dist/_pkgs/data-view/view-presets/convert.js +2 -0
  140. package/dist/_pkgs/data-view/view-presets/effect.js +4 -0
  141. package/dist/_pkgs/data-view/view-presets/flat/flat-converts.d.ts +2 -0
  142. package/dist/_pkgs/data-view/view-presets/flat/flat-converts.js +35 -0
  143. package/dist/_pkgs/data-view/view-presets/flat/flat-view-manager.d.ts +79 -0
  144. package/dist/_pkgs/data-view/view-presets/flat/flat-view-manager.js +194 -0
  145. package/dist/_pkgs/data-view/view-presets/flat/flat-view-ui.d.ts +56 -0
  146. package/dist/_pkgs/data-view/view-presets/flat/flat-view-ui.js +266 -0
  147. package/dist/_pkgs/data-view/view-presets/gallery/define.d.ts +14 -0
  148. package/dist/_pkgs/data-view/view-presets/gallery/define.js +15 -0
  149. package/dist/_pkgs/data-view/view-presets/gallery/effect.d.ts +1 -0
  150. package/dist/_pkgs/data-view/view-presets/gallery/effect.js +4 -0
  151. package/dist/_pkgs/data-view/view-presets/gallery/gallery-view.d.ts +27 -0
  152. package/dist/_pkgs/data-view/view-presets/gallery/gallery-view.js +179 -0
  153. package/dist/_pkgs/data-view/view-presets/gallery/index.d.ts +2 -0
  154. package/dist/_pkgs/data-view/view-presets/gallery/index.js +2 -0
  155. package/dist/_pkgs/data-view/view-presets/gallery/renderer.d.ts +1 -0
  156. package/dist/_pkgs/data-view/view-presets/gallery/renderer.js +11 -0
  157. package/dist/_pkgs/data-view/view-presets/index.d.ts +5 -0
  158. package/dist/_pkgs/data-view/view-presets/index.js +7 -0
  159. package/dist/_pkgs/data-view/view-presets/kanban/define.js +3 -1
  160. package/dist/_pkgs/data-view/view-presets/kanban/kanban-view-manager.js +5 -53
  161. package/dist/_pkgs/data-view/view-presets/kanban/mobile/card.js +8 -1
  162. package/dist/_pkgs/data-view/view-presets/kanban/mobile/cell.js +6 -1
  163. package/dist/_pkgs/data-view/view-presets/kanban/mobile/group.d.ts +4 -2
  164. package/dist/_pkgs/data-view/view-presets/kanban/mobile/group.js +52 -6
  165. package/dist/_pkgs/data-view/view-presets/kanban/mobile/kanban-view-ui-logic.js +5 -1
  166. package/dist/_pkgs/data-view/view-presets/kanban/pc/card.js +2 -0
  167. package/dist/_pkgs/data-view/view-presets/kanban/pc/cell.js +4 -0
  168. package/dist/_pkgs/data-view/view-presets/kanban/pc/group.d.ts +4 -2
  169. package/dist/_pkgs/data-view/view-presets/kanban/pc/group.js +51 -6
  170. package/dist/_pkgs/data-view/view-presets/kanban/pc/kanban-view-ui-logic.js +5 -1
  171. package/dist/_pkgs/data-view/view-presets/list/define.d.ts +14 -0
  172. package/dist/_pkgs/data-view/view-presets/list/define.js +15 -0
  173. package/dist/_pkgs/data-view/view-presets/list/effect.d.ts +1 -0
  174. package/dist/_pkgs/data-view/view-presets/list/effect.js +4 -0
  175. package/dist/_pkgs/data-view/view-presets/list/index.d.ts +2 -0
  176. package/dist/_pkgs/data-view/view-presets/list/index.js +2 -0
  177. package/dist/_pkgs/data-view/view-presets/list/list-view.d.ts +24 -0
  178. package/dist/_pkgs/data-view/view-presets/list/list-view.js +194 -0
  179. package/dist/_pkgs/data-view/view-presets/list/renderer.d.ts +1 -0
  180. package/dist/_pkgs/data-view/view-presets/list/renderer.js +11 -0
  181. package/dist/_pkgs/data-view/view-presets/table/collapsed-state.d.ts +3 -14
  182. package/dist/_pkgs/data-view/view-presets/table/collapsed-state.js +6 -30
  183. package/dist/_pkgs/data-view/view-presets/table/consts.d.ts +2 -0
  184. package/dist/_pkgs/data-view/view-presets/table/consts.js +2 -0
  185. package/dist/_pkgs/data-view/view-presets/table/define.js +3 -1
  186. package/dist/_pkgs/data-view/view-presets/table/mobile/cell.js +4 -1
  187. package/dist/_pkgs/data-view/view-presets/table/mobile/column-header.js +2 -2
  188. package/dist/_pkgs/data-view/view-presets/table/mobile/group.d.ts +3 -1
  189. package/dist/_pkgs/data-view/view-presets/table/mobile/group.js +20 -5
  190. package/dist/_pkgs/data-view/view-presets/table/mobile/row.js +10 -2
  191. package/dist/_pkgs/data-view/view-presets/table/mobile/table-view-ui-logic.js +4 -1
  192. package/dist/_pkgs/data-view/view-presets/table/pc/cell.js +4 -1
  193. package/dist/_pkgs/data-view/view-presets/table/pc/controller/hotkeys.js +1 -1
  194. package/dist/_pkgs/data-view/view-presets/table/pc/group.d.ts +3 -1
  195. package/dist/_pkgs/data-view/view-presets/table/pc/group.js +20 -5
  196. package/dist/_pkgs/data-view/view-presets/table/pc/menu.d.ts +1 -1
  197. package/dist/_pkgs/data-view/view-presets/table/pc/menu.js +2 -1
  198. package/dist/_pkgs/data-view/view-presets/table/pc/row/row.js +3 -2
  199. package/dist/_pkgs/data-view/view-presets/table/pc/table-view-ui-logic.js +4 -1
  200. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/controller/hotkeys.js +1 -1
  201. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/bottom/stats/column-stats-column.js +5 -1
  202. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/group/top/group-title.js +22 -19
  203. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/row/cell.js +4 -1
  204. package/dist/_pkgs/data-view/view-presets/table/pc-virtual/table-view-ui-logic.js +7 -2
  205. package/dist/_pkgs/data-view/view-presets/table/stats/column-stats-column.js +5 -1
  206. package/dist/_pkgs/data-view/view-presets/table/table-view-manager.js +5 -53
  207. package/dist/_pkgs/data-view/widget-presets/tools/presets/table-add-row/add-row.d.ts +1 -0
  208. package/dist/_pkgs/data-view/widget-presets/tools/presets/table-add-row/add-row.js +60 -2
  209. package/dist/_pkgs/data-view/widget-presets/tools/presets/view-options/view-options.d.ts +18 -1
  210. package/dist/_pkgs/data-view/widget-presets/tools/presets/view-options/view-options.js +121 -124
  211. package/dist/_pkgs/data-view/widget-presets/tools/presets/view-options/view-settings.d.ts +43 -0
  212. package/dist/_pkgs/data-view/widget-presets/tools/presets/view-options/view-settings.js +187 -0
  213. package/dist/_pkgs/data-view/widget-presets/views-bar/views-view.d.ts +36 -3
  214. package/dist/_pkgs/data-view/widget-presets/views-bar/views-view.js +187 -59
  215. package/dist/extensions/view.d.ts +2 -2
  216. package/dist/extensions/view.js +10 -3
  217. package/dist/flags.d.ts +8 -4
  218. package/dist/flags.js +8 -4
  219. package/dist/frameworks.d.ts +27 -0
  220. package/dist/frameworks.js +28 -0
  221. package/dist/translations.js +13 -1
  222. package/package.json +5 -1
@@ -44,7 +44,7 @@ import { css, html, nothing } from 'lit';
44
44
  import { property } from 'lit/decorators.js';
45
45
  import { repeat } from 'lit/directives/repeat.js';
46
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';
47
+ import { bandCellData, bandCellMeta, bandCellValue, bandOptionsWritable, bandWriteValue, isBandReadonlyType, sameBandValue, } from './band-cell.js';
48
48
  import { formatPropertyValue, isPropertyValueEmpty } from './format.js';
49
49
  import { showPageHere } from './show-here.js';
50
50
  export const LABRE_TITLE_BAND = 'labre-title-band';
@@ -329,6 +329,31 @@ let TitleBand = (() => {
329
329
  console.error('[title-band] set was refused', error);
330
330
  });
331
331
  }
332
+ /**
333
+ * A definition a select's tag menu commits (a created or renamed option):
334
+ * handed to the host's `setData`, never applied here.
335
+ */
336
+ _writeData(property, data) {
337
+ const service = this._sources?.service;
338
+ if (!service?.setData || this._isReadonlyChip(property))
339
+ return;
340
+ if (property.dataWritable !== true)
341
+ return;
342
+ let written;
343
+ try {
344
+ written = service.setData(this.docId, property.id, {
345
+ ...property.data,
346
+ options: data.options,
347
+ });
348
+ }
349
+ catch (error) {
350
+ console.error('[title-band] setData threw', error);
351
+ return;
352
+ }
353
+ Promise.resolve(written).catch((error) => {
354
+ console.error('[title-band] setData was refused', error);
355
+ });
356
+ }
332
357
  /** A value a cell commits: unchanged, nothing is written. */
333
358
  _commit(prop, cellType, value) {
334
359
  if (sameBandValue(cellType, prop.value, value))
@@ -351,11 +376,14 @@ let TitleBand = (() => {
351
376
  const meta = bandCellMeta(prop.type, cellType => std.getOptional(StandaloneCellMetaProvider(cellType)));
352
377
  if (!meta)
353
378
  return null;
379
+ const cellType = meta.type;
380
+ const optionsWritable = bandOptionsWritable(cellType, prop, !!sources.service.setData) &&
381
+ !this._isReadonlyChip(prop);
354
382
  const cached = sources.cells.get(prop.id);
355
- if (cached?.type === prop.type)
383
+ if (cached?.type === prop.type &&
384
+ cached.optionsWritable === optionsWritable)
356
385
  return cached.cell;
357
386
  const { id, type } = prop;
358
- const cellType = meta.type;
359
387
  const current$ = computed(() => {
360
388
  const state = sources.sheet$.value;
361
389
  if (state.status !== 'ready')
@@ -378,8 +406,20 @@ let TitleBand = (() => {
378
406
  },
379
407
  featureFlags$: this._featureFlags$,
380
408
  serviceGet: key => std.getOptional(key),
409
+ // A chip creates and renames options only, never deletes, recolours
410
+ // or reorders one (product owner, 2026-10-14).
411
+ ...(optionsWritable
412
+ ? {
413
+ dataSet: (data) => {
414
+ const current = current$.peek();
415
+ if (current)
416
+ this._writeData(current, data);
417
+ },
418
+ optionEdits: 'create-rename',
419
+ }
420
+ : {}),
381
421
  });
382
- sources.cells.set(id, { type, cell });
422
+ sources.cells.set(id, { type, optionsWritable, cell });
383
423
  return cell;
384
424
  }
385
425
  _renderFallback(prop) {
@@ -10,8 +10,24 @@ export type CellDataType<ValueType = unknown> = {
10
10
  value: ValueType;
11
11
  };
12
12
  export type SerializedCells = Record<string, Record<string, CellDataType>>;
13
+ /**
14
+ * Where a row of a view opens (ADR 0035 §8). Append-only: a stored value is
15
+ * never renamed or removed. An absent `openIn` reads `side`.
16
+ */
17
+ export declare const DATABASE_VIEW_OPEN_IN: readonly ["side", "center", "full"];
18
+ export type DatabaseViewOpenIn = (typeof DATABASE_VIEW_OPEN_IN)[number];
19
+ /**
20
+ * The stored shape every view in `props.views` shares; each mode adds its own
21
+ * data on top. `sourceId` and `openIn` arrived in 0.49 (ADR 0035 §8, red
22
+ * zone): optional, `undefined` by default and never written on load, so a
23
+ * view stored by 0.48 or earlier is still a valid view and a 0.48 client
24
+ * ignores them. `sourceId` absent means the block's own implicit source.
25
+ * Held by `view-basic-data.unit.spec.ts`.
26
+ */
13
27
  export type ViewBasicDataType = {
14
28
  id: string;
15
29
  name: string;
16
30
  mode: string;
31
+ sourceId?: string;
32
+ openIn?: DatabaseViewOpenIn;
17
33
  };
@@ -1 +1,5 @@
1
- export {};
1
+ /**
2
+ * Where a row of a view opens (ADR 0035 §8). Append-only: a stored value is
3
+ * never renamed or removed. An absent `openIn` reads `side`.
4
+ */
5
+ export const DATABASE_VIEW_OPEN_IN = ['side', 'center', 'full'];
@@ -0,0 +1,139 @@
1
+ import type { ExtensionType } from '../../store/index.js';
2
+ import type { ReadonlySignal } from '@preact/signals-core';
3
+ /** One source of a host database, as the picker lists it. */
4
+ export interface DataSourcePickerSource {
5
+ /** What a view stores as its `sourceId` (ADR 0035 §8). */
6
+ id: string;
7
+ /** Display name, already localized by the host. */
8
+ title: string;
9
+ }
10
+ /** One database the host offers a view of. */
11
+ export interface DataSourcePickerDatabase {
12
+ /**
13
+ * What a linked view stores as its block's `externalSourceId`: the value
14
+ * the host's `DatabaseDataSourceProvider` reads back to build the view's
15
+ * data source. Opaque to the library (the Labre app writes
16
+ * `labre-base:<uuid>`, labre ADR-0046).
17
+ */
18
+ id: string;
19
+ /** Display name, already localized by the host. */
20
+ title: string;
21
+ /** Its live sources, in the host's order; the first is the default. */
22
+ sources: readonly DataSourcePickerSource[];
23
+ }
24
+ /** A property of a source as a view refers to it (an import's correspondence). */
25
+ export interface DataSourcePickerProperty {
26
+ /** The property id the views store. */
27
+ id: string;
28
+ name: string;
29
+ /** The property type (`title`, `select`, `number`…). */
30
+ type: string;
31
+ /** A select's options: a filter on it stores their ids. */
32
+ options?: readonly {
33
+ id: string;
34
+ value: string;
35
+ }[];
36
+ }
37
+ /**
38
+ * A view of another database, or a saved view template, to copy into this
39
+ * database: never linked, the copy is a new view of this database.
40
+ */
41
+ export interface DataSourcePickerImportedView {
42
+ /** The stored view as read there (`props.views[i]`, or a template). */
43
+ view: Readonly<Record<string, unknown>>;
44
+ /** The properties of the source the view read there. */
45
+ properties: readonly DataSourcePickerProperty[];
46
+ /**
47
+ * Source property id → property of this database, or `null` to ignore
48
+ * it. An id left out is ignored. A filter or a sort on an ignored property
49
+ * is removed, a column of it is dropped, a grouping by it is undone.
50
+ */
51
+ mapping: Readonly<Record<string, string | null>>;
52
+ }
53
+ /** What `importView` hands the host: where the copy lands, and the verb. */
54
+ export interface DataSourcePickerImportRequest {
55
+ /** The database the copy lands in, as `list()` names it. */
56
+ databaseId: string;
57
+ /** The source the copy reads (the current view's); absent, the implicit one. */
58
+ sourceId?: string;
59
+ /** The properties of that source, for the correspondence. */
60
+ properties: readonly DataSourcePickerProperty[];
61
+ /** The layouts this database can add (preset types). Any other is refused. */
62
+ layouts: readonly string[];
63
+ /**
64
+ * Add the copy as a new view and show it; its id, or `null` when nothing
65
+ * was added (the page turned read-only, a layout not offered). One undo
66
+ * step.
67
+ */
68
+ add(view: DataSourcePickerImportedView): string | null;
69
+ }
70
+ /**
71
+ * The current view as a template (labre PRD REQ-DB-4): its layout, where its
72
+ * pages open, its properties shown and their order, its grouping. Never its
73
+ * filters, its sorts or a manual order: those belong to one view.
74
+ */
75
+ export interface DataSourcePickerViewTemplate {
76
+ databaseId: string;
77
+ sourceId?: string;
78
+ /** The view's name, as shown. */
79
+ name: string;
80
+ view: Readonly<Record<string, unknown>>;
81
+ properties: readonly DataSourcePickerProperty[];
82
+ }
83
+ /**
84
+ * The data-source picker (ADR 0035 §9c, issue B12): the host lists the
85
+ * databases and sources a view may read, and creates them. The library draws
86
+ * the picker (`@labre/affine-database-editor`), inserts the view and never
87
+ * learns where a database lives.
88
+ *
89
+ * The identifier lives in core, not in the bundle §9c named: core's own
90
+ * slash entries that create a database read `createDatabase` (§5), and a seam
91
+ * identifier lives in the lowest package that reads it (§3).
92
+ */
93
+ export interface DataSourcePickerService {
94
+ /**
95
+ * The databases on offer. MUST return synchronously and MUST NOT throw: the
96
+ * signal may start empty and fill later, the picker redraws.
97
+ */
98
+ list(): ReadonlySignal<readonly DataSourcePickerDatabase[]>;
99
+ /**
100
+ * Create a database; it resolves to the new one, with at least one source,
101
+ * or `null` when nothing was created (the user cancelled, the host
102
+ * refused). Absent, nothing creates a database: this is the host's kill
103
+ * switch, and the creating slash entries ("Table View", "Kanban View")
104
+ * leave the menu.
105
+ */
106
+ createDatabase?(): Promise<DataSourcePickerDatabase | null>;
107
+ /**
108
+ * Create a source in `databaseId`; it resolves to the new source, or
109
+ * `null`. Absent, the picker offers no "New source".
110
+ */
111
+ createSource?(databaseId: string): Promise<DataSourcePickerSource | null>;
112
+ /**
113
+ * Import a view of another database into `request.databaseId` (labre PRD
114
+ * REQ-DB-2, ADR 0035 amendment of 2026-10-14): the host lets the reader
115
+ * pick a view it may read and map its properties, then calls
116
+ * `request.add`. Absent, "+ view" offers no import and the full page lists
117
+ * no "Import a view".
118
+ */
119
+ importView?(request: DataSourcePickerImportRequest): void;
120
+ /**
121
+ * Keep the current view as a template, where the host keeps templates
122
+ * (labre: the workspace's library, REQ-DB-15); a later `importView` may
123
+ * offer it. Resolves `true` once saved. Absent, no "Save as template".
124
+ */
125
+ saveViewTemplate?(template: DataSourcePickerViewTemplate): Promise<boolean>;
126
+ }
127
+ export declare const DataSourcePickerProvider: import("../../global/di/types.js").ServiceIdentifier<DataSourcePickerService> & (<U extends DataSourcePickerService = DataSourcePickerService>(variant: import("../../global/di/types.js").ServiceVariant) => import("../../global/di/types.js").ServiceIdentifier<U>);
128
+ /**
129
+ * Host seam: the host's databases and sources, or `null` to say it has none.
130
+ *
131
+ * Absent or `null`: no "Linked view of a database" entry, "+ view" offers
132
+ * only the sources the block already shows, and the slash entries create a
133
+ * native inline database as in 0.48. With a service but no `createDatabase`,
134
+ * no entry creates a database at all.
135
+ *
136
+ * `di.override`, so a later registration wins and registering twice never
137
+ * throws at boot.
138
+ */
139
+ export declare function DataSourcePickerExtension(service: DataSourcePickerService | null): ExtensionType;
@@ -0,0 +1,22 @@
1
+ import { createIdentifier } from '../../global/di/index.js';
2
+ export const DataSourcePickerProvider = createIdentifier('LabreDataSourcePicker');
3
+ /**
4
+ * Host seam: the host's databases and sources, or `null` to say it has none.
5
+ *
6
+ * Absent or `null`: no "Linked view of a database" entry, "+ view" offers
7
+ * only the sources the block already shows, and the slash entries create a
8
+ * native inline database as in 0.48. With a service but no `createDatabase`,
9
+ * no entry creates a database at all.
10
+ *
11
+ * `di.override`, so a later registration wins and registering twice never
12
+ * throws at boot.
13
+ */
14
+ export function DataSourcePickerExtension(service) {
15
+ return {
16
+ setup: di => {
17
+ // `null` rides through on purpose: `getOptional` then reports no
18
+ // picker, which is the whole "0.48 entries" story.
19
+ di.override(DataSourcePickerProvider, () => service);
20
+ },
21
+ };
22
+ }
@@ -7,6 +7,7 @@ export * from './canvas-local-visibility.js';
7
7
  export * from './citation-service/index.js';
8
8
  export * from './command-usage-service.js';
9
9
  export * from './comment-service/index.js';
10
+ export * from './data-source-picker-service.js';
10
11
  export * from './doc-display-meta-service.js';
11
12
  export * from './doc-mode-service.js';
12
13
  export * from './drag-handle-config.js';
@@ -7,6 +7,7 @@ export * from './canvas-local-visibility.js';
7
7
  export * from './citation-service/index.js';
8
8
  export * from './command-usage-service.js';
9
9
  export * from './comment-service/index.js';
10
+ export * from './data-source-picker-service.js';
10
11
  export * from './doc-display-meta-service.js';
11
12
  export * from './doc-mode-service.js';
12
13
  export * from './drag-handle-config.js';
@@ -1,3 +1,4 @@
1
+ import type { TelemetryEvent } from './types.js';
1
2
  type OrderType = 'desc' | 'asc';
2
3
  export type WithParams<Map, T> = {
3
4
  [K in keyof Map]: Map[K] & T;
@@ -15,13 +16,50 @@ export type ViewParams = {
15
16
  export type DatabaseParams = {
16
17
  blockId: string;
17
18
  };
19
+ /**
20
+ * Where a database row opened (ADR 0035 §8, §9a): the view's stored `openIn`
21
+ * (absent reads `side`), or `full` for a Ctrl/Cmd-click. Mirrors
22
+ * `DatabaseViewOpenIn` of `@labre/affine-model`, which this layer cannot
23
+ * import.
24
+ */
25
+ export type DatabaseRowOpenMode = 'side' | 'center' | 'full';
18
26
  export type DatabaseViewEvents = {
19
27
  DatabaseSortClear: {
20
28
  rulesCount: number;
21
29
  };
30
+ /**
31
+ * The user picked another layout for a view (B17). Replaces the never
32
+ * emitted {@link DatabaseViewEvents.ChangeDatabaseLayout}.
33
+ */
34
+ DatabaseViewTypeChanged: TelemetryEvent & {
35
+ fromViewType: string;
36
+ toViewType: string;
37
+ };
38
+ /**
39
+ * The user grouped a view, changed its grain or removed the grouping (B17).
40
+ * `groupBy` is the group-by config name (`select`, `date-month`…), `none`
41
+ * once removed; `propertyType` the grouped property's type. Never the
42
+ * property's id or name. Replaces the never emitted `CreateDatabaseGroup`.
43
+ */
44
+ DatabaseGroupChanged: TelemetryEvent & {
45
+ groupBy: string;
46
+ propertyType?: string;
47
+ };
48
+ /**
49
+ * A row was opened from a view (B17). `rowKind` says whether the source's
50
+ * rows are documents (`rowsAreDocuments`) or blocks of the database. Never
51
+ * the row's id: a hosted row is a document id (ADR 0035 §12).
52
+ */
53
+ DatabaseRowOpened: TelemetryEvent & {
54
+ mode: DatabaseRowOpenMode;
55
+ newTab: boolean;
56
+ rowKind: 'document' | 'block';
57
+ };
58
+ /** @deprecated never emitted; `DatabaseViewAdded` reports a new view. */
22
59
  CreateDatabaseView: {
23
60
  viewType: string;
24
61
  };
62
+ /** @deprecated never emitted; see `DatabaseViewTypeChanged`. */
25
63
  ChangeDatabaseLayout: {
26
64
  fromViewType: string;
27
65
  toViewType: string;
@@ -36,15 +74,36 @@ export type DatabaseFilterEvents = {
36
74
  CreateDatabaseFilter: {};
37
75
  };
38
76
  export type DatabaseGroupEvents = {
77
+ /** @deprecated never emitted; see `DatabaseGroupChanged`. */
39
78
  CreateDatabaseGroup: {
40
79
  groupBy: string;
41
80
  };
42
81
  };
43
82
  export type DatabaseEvents = {
44
83
  AddDatabase: {};
84
+ /** @deprecated no longer emitted since 0.49; see `DatabaseViewAdded`. */
45
85
  AddDatabaseView: {
46
86
  type: string;
47
87
  };
88
+ /**
89
+ * A view was added by a user gesture (ADR 0035 §12, B17): `existing` when
90
+ * it reads a source the database already has (its own included), `new`
91
+ * when the gesture created the source with it, `import` when it is the
92
+ * copy of another database's view or of a view template (0.49, appended).
93
+ * A database created with its first view reports `BlockCreated`, not this.
94
+ */
95
+ DatabaseViewAdded: TelemetryEvent & {
96
+ viewType: string;
97
+ source: 'existing' | 'new' | 'import';
98
+ };
99
+ /**
100
+ * A hosted source's values could not be loaded (ADR 0035 §9e, B17): once
101
+ * per failure of a source, not per banner drawn. `retryable` says whether
102
+ * the source offers `retryValues`.
103
+ */
104
+ DatabaseValuesLoadFailed: TelemetryEvent & {
105
+ retryable: boolean;
106
+ };
48
107
  };
49
108
  export interface DatabaseAllSortEvents {
50
109
  DatabaseSortAdd: {};
@@ -47,6 +47,14 @@ export interface TitleBandProperty {
47
47
  value: unknown;
48
48
  /** A read-only property draws its chip and opens no editor. */
49
49
  readonly: boolean;
50
+ /**
51
+ * Whether the host takes a write of this property's definition (`data`)
52
+ * through {@link TitleBandService.setData}; absent means `false`. A select
53
+ * or multi-select whose options can be created and renamed from its chip
54
+ * says `true`; one whose option ids are its labels (the Labre app's
55
+ * `tags`) never does.
56
+ */
57
+ dataWritable?: boolean;
50
58
  }
51
59
  /**
52
60
  * The state of one page's sheet. Same four states as ADR 0006: the signal may
@@ -89,6 +97,22 @@ export interface TitleBandService {
89
97
  * clears its pending state. `value` is `null` to clear.
90
98
  */
91
99
  set(docId: string, propertyId: string, value: unknown): Promise<void>;
100
+ /**
101
+ * Write one property's definition, its `data` (a select's `options`): the
102
+ * band's one definition write, distinct from `set` (product owner,
103
+ * 2026-10-14). Called only for a property whose `dataWritable` is `true`
104
+ * on a chip that is not read-only, and only to create an option or rename
105
+ * one: the chip's tag menu offers no delete, no colour and no reordering.
106
+ * `data` is the whole new config, the option list in data-view's shape
107
+ * (`{ id, value, color }`, a created option first, its id minted by the
108
+ * library). The library never applies it: the option shows once it arrives
109
+ * through `sheet$`, so a host applies it to its sheet at once and owns the
110
+ * rollback. Creating an option is followed at once by a `set` that selects
111
+ * it: the host applies the two in the order it receives them. A rejection is
112
+ * the host's to report; the band logs it. Absent, every chip's options are
113
+ * fixed: no "Create", no option menu (the 0.48 band).
114
+ */
115
+ setData?(docId: string, propertyId: string, data: Record<string, unknown>): Promise<void>;
92
116
  /**
93
117
  * The band's "+" (REQ-PR-4): what it does is the host's (open the
94
118
  * workspace's property settings, or create a database property directly
@@ -0,0 +1,2 @@
1
+ export declare const cellSkeletonStyle: string;
2
+ export declare const cellEmptyStyle: string;
@@ -0,0 +1,16 @@
1
+ import { css } from '@emotion/css';
2
+ // The title band's loading chip, in a cell (`labre-title-band-skeleton`):
3
+ // same hover tone, same radius, no motion to honour or disable.
4
+ export const cellSkeletonStyle = css({
5
+ display: 'block',
6
+ width: '60%',
7
+ maxWidth: '120px',
8
+ height: '16px',
9
+ margin: '8px',
10
+ borderRadius: '6px',
11
+ backgroundColor: 'var(--affine-hover-color)',
12
+ });
13
+ export const cellEmptyStyle = css({
14
+ display: 'block',
15
+ minHeight: '32px',
16
+ });
@@ -0,0 +1,10 @@
1
+ import { type TemplateResult } from 'lit';
2
+ import type { Cell } from '../../view-manager/cell.js';
3
+ /**
4
+ * What a cell container draws INSTEAD of its renderer while the cell is not
5
+ * `ready` (ADR 0035 §9e): a skeleton while `pending`, an empty cell on
6
+ * `error`. `undefined` when ready, so the container mounts its renderer as in
7
+ * 0.48. No renderer is mounted otherwise, which is what keeps a cell whose
8
+ * value never arrived from being edited over.
9
+ */
10
+ export declare function renderCellStatus(cell: Cell | undefined): TemplateResult | undefined;
@@ -0,0 +1,23 @@
1
+ import { html } from 'lit';
2
+ import { cellEmptyStyle, cellSkeletonStyle } from './cell-status-css.js';
3
+ /**
4
+ * What a cell container draws INSTEAD of its renderer while the cell is not
5
+ * `ready` (ADR 0035 §9e): a skeleton while `pending`, an empty cell on
6
+ * `error`. `undefined` when ready, so the container mounts its renderer as in
7
+ * 0.48. No renderer is mounted otherwise, which is what keeps a cell whose
8
+ * value never arrived from being edited over.
9
+ */
10
+ export function renderCellStatus(cell) {
11
+ const status = cell?.status$?.value ?? 'ready';
12
+ if (status === 'ready')
13
+ return undefined;
14
+ if (status === 'pending') {
15
+ return html `<span
16
+ class="${cellSkeletonStyle}"
17
+ data-testid="dv-cell-skeleton"
18
+ data-cell-status="pending"
19
+ aria-busy="true"
20
+ ></span>`;
21
+ }
22
+ return html `<span class="${cellEmptyStyle}" data-cell-status="error"></span>`;
23
+ }
@@ -1,3 +1,4 @@
1
1
  export * from './button/button.js';
2
2
  export * from './overflow/overflow.js';
3
3
  export * from './tags/index.js';
4
+ export * from './cell-status/cell-status.js';
@@ -1,3 +1,4 @@
1
1
  export * from './button/button.js';
2
2
  export * from './overflow/overflow.js';
3
3
  export * from './tags/index.js';
4
+ export * from './cell-status/cell-status.js';
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Which items of an overflowing row are drawn, from measured widths (the
3
+ * view bar's tabs, ADR 0035 B11, labre PRD REQ-DB-7: "as many tabs as the
4
+ * width allows, the rest under N more").
5
+ *
6
+ * - Everything fits: every item is drawn and the trailing slot holds only
7
+ * what it holds when nothing is hidden (`trailing`, the "+" of the view
8
+ * bar).
9
+ * - Otherwise the trailing slot also holds the "N more" button
10
+ * (`moreExtra` wider), and the items are drawn in order while they fit,
11
+ * stopping at the first that does not: the order of the row is the order
12
+ * of the views, never reshuffled to pack more in.
13
+ * - The `pinned` item (the current view) is always drawn, even alone and
14
+ * wider than the room: a view you are looking at never hides under "more".
15
+ * Its room is reserved first, so it takes the place of the last item that
16
+ * would have fitted.
17
+ *
18
+ * Returns the drawn indices in ascending order.
19
+ */
20
+ export declare function fitOverflow(input: {
21
+ widths: readonly number[];
22
+ container: number;
23
+ trailing: number;
24
+ moreExtra: number;
25
+ pinned?: number;
26
+ }): number[];
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Which items of an overflowing row are drawn, from measured widths (the
3
+ * view bar's tabs, ADR 0035 B11, labre PRD REQ-DB-7: "as many tabs as the
4
+ * width allows, the rest under N more").
5
+ *
6
+ * - Everything fits: every item is drawn and the trailing slot holds only
7
+ * what it holds when nothing is hidden (`trailing`, the "+" of the view
8
+ * bar).
9
+ * - Otherwise the trailing slot also holds the "N more" button
10
+ * (`moreExtra` wider), and the items are drawn in order while they fit,
11
+ * stopping at the first that does not: the order of the row is the order
12
+ * of the views, never reshuffled to pack more in.
13
+ * - The `pinned` item (the current view) is always drawn, even alone and
14
+ * wider than the room: a view you are looking at never hides under "more".
15
+ * Its room is reserved first, so it takes the place of the last item that
16
+ * would have fitted.
17
+ *
18
+ * Returns the drawn indices in ascending order.
19
+ */
20
+ export function fitOverflow(input) {
21
+ const { widths, container, trailing, moreExtra } = input;
22
+ const pinned = input.pinned !== undefined &&
23
+ input.pinned >= 0 &&
24
+ input.pinned < widths.length
25
+ ? input.pinned
26
+ : -1;
27
+ const total = widths.reduce((sum, width) => sum + width, 0);
28
+ if (total + trailing <= container) {
29
+ return widths.map((_, index) => index);
30
+ }
31
+ const budget = container - trailing - moreExtra;
32
+ const drawn = [];
33
+ let used = pinned >= 0 ? (widths[pinned] ?? 0) : 0;
34
+ for (let index = 0; index < widths.length; index++) {
35
+ if (index === pinned)
36
+ continue;
37
+ const width = widths[index] ?? 0;
38
+ if (used + width > budget)
39
+ break;
40
+ drawn.push(index);
41
+ used += width;
42
+ }
43
+ if (pinned >= 0) {
44
+ drawn.push(pinned);
45
+ drawn.sort((a, b) => a - b);
46
+ }
47
+ return drawn;
48
+ }
@@ -1,19 +1,42 @@
1
1
  import { ShadowlessElement } from '../../../../std/index.js';
2
2
  import { type PropertyValues, type TemplateResult } from 'lit';
3
+ /**
4
+ * Marks the element of the trailing slot that only exists while something is
5
+ * hidden (the "N more" button): the rest of the slot is what stays.
6
+ */
7
+ export declare const OVERFLOW_MORE_ATTR = "data-overflow-more";
3
8
  declare const Overflow_base: typeof ShadowlessElement & import("../../../../global/utils/types.js").Constructor<import("../../../../global/lit/with-disposable.js").DisposableClass>;
9
+ /**
10
+ * A row that draws as many items as its width allows and hands the rest to
11
+ * a trailing slot (`renderMore`). Every item stays in the DOM, a hidden one
12
+ * transparent and out of the flow, so its width is measured on each pass;
13
+ * which ones are drawn is `fitOverflow` (`./fit.ts`), `pinned` included.
14
+ * Until the first measure every item is drawn.
15
+ */
4
16
  export declare class Overflow extends Overflow_base {
5
17
  static styles: import("lit").CSSResult;
6
18
  protected frameId: number | undefined;
7
- protected widthList: number[];
19
+ /** Last measured width of the slot's `OVERFLOW_MORE_ATTR` element. */
20
+ private moreExtraWidth;
8
21
  adjustStyle(): void;
9
22
  connectedCallback(): void;
10
23
  protected doAdjustStyle(): void;
24
+ /** The items `renderMore` holds, in order. */
25
+ get hiddenIndices(): number[];
11
26
  render(): TemplateResult<1>;
27
+ protected willUpdate(changed: PropertyValues<this>): void;
12
28
  protected updated(_changedProperties: PropertyValues): void;
13
29
  accessor items: HTMLDivElement[] & NodeList;
14
30
  accessor more: HTMLDivElement;
15
- accessor renderCount: number;
31
+ /** The drawn items' indices, ascending; `undefined` (all) until measured. */
32
+ accessor drawn: readonly number[] | undefined;
33
+ /** The item that is always drawn (the current view); `-1` for none. */
34
+ accessor pinned: number;
16
35
  accessor renderItem: Array<() => TemplateResult>;
17
- accessor renderMore: (count: number) => TemplateResult;
36
+ /**
37
+ * The trailing slot: `count` items are drawn and `hidden` are the indices
38
+ * it stands for, empty when everything fits.
39
+ */
40
+ accessor renderMore: (count: number, hidden: readonly number[]) => TemplateResult | undefined;
18
41
  }
19
42
  export {};