@ecsplico/editor 4.0.0 → 4.2.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 (61) hide show
  1. package/CHANGELOG.md +18 -0
  2. package/dist/code/CodeSurface.vue.d.ts +3 -3
  3. package/dist/document/DocumentSurface.vue.d.ts +3 -3
  4. package/dist/features/image-studio/components/ImageStudioDialog.js +149 -86
  5. package/dist/features/image-studio/components/ImageStudioDialog.js.map +1 -1
  6. package/dist/features/image-studio/components/ImageStudioDialog.vue.d.ts +4 -0
  7. package/dist/features/image-studio/components/ImageStudioLibraryPanel.js +186 -0
  8. package/dist/features/image-studio/components/ImageStudioLibraryPanel.js.map +1 -0
  9. package/dist/features/image-studio/components/ImageStudioLibraryTile.js +134 -0
  10. package/dist/features/image-studio/components/ImageStudioLibraryTile.js.map +1 -0
  11. package/dist/features/image-studio/index.d.ts +3 -2
  12. package/dist/features/image-studio/index.js +2 -2
  13. package/dist/features/image-studio/library.d.ts +35 -0
  14. package/dist/features/image-studio/react/ImageStudioDialog.js +45 -4
  15. package/dist/features/image-studio/react/ImageStudioDialog.js.map +1 -1
  16. package/dist/features/image-studio/react/ImageStudioLibraryPanel.js +141 -0
  17. package/dist/features/image-studio/react/ImageStudioLibraryPanel.js.map +1 -0
  18. package/dist/features/image-studio/react/ImageStudioLibraryTile.js +105 -0
  19. package/dist/features/image-studio/react/ImageStudioLibraryTile.js.map +1 -0
  20. package/dist/features/image-studio/react/store.d.ts +5 -0
  21. package/dist/features/image-studio/react/store.js.map +1 -1
  22. package/dist/features/image-studio/react.d.ts +3 -2
  23. package/dist/features/image-studio/react.js +2 -2
  24. package/dist/features/image-studio/react.js.map +1 -1
  25. package/dist/features/image-studio/state.d.ts +5 -0
  26. package/dist/features/image-studio/state.js +9 -1
  27. package/dist/features/image-studio/state.js.map +1 -1
  28. package/dist/features/image-studio/store.d.ts +5 -0
  29. package/dist/features/image-studio/vue.d.ts +3 -2
  30. package/dist/features/image-studio/vue.js +2 -2
  31. package/dist/features/image-studio/vue.js.map +1 -1
  32. package/dist/features/media/index.js +1 -1
  33. package/dist/features/media/react/AudioRecorderModal.js +1 -1
  34. package/dist/features/media/react.js +1 -1
  35. package/dist/i18n/de/image-studio.js +9 -0
  36. package/dist/i18n/de/image-studio.js.map +1 -1
  37. package/dist/i18n/de.d.ts +9 -0
  38. package/dist/i18n/en/image-studio.js +9 -0
  39. package/dist/i18n/en/image-studio.js.map +1 -1
  40. package/dist/integrations/composite-ai/transfer-transforms.js +1 -1
  41. package/dist/markdown/MarkdownSurface.vue.d.ts +5 -5
  42. package/dist/nuxt/module.d.ts +18 -0
  43. package/dist/presets/compose.js +1 -1
  44. package/dist/react/compose.js +1 -1
  45. package/dist/tree/react/use-tree-view.d.ts +3 -1
  46. package/dist/tree/react/use-tree-view.js +3 -1
  47. package/dist/tree/react/use-tree-view.js.map +1 -1
  48. package/dist/tree/tree-host.js +1 -1
  49. package/dist/tree/tree-model.js +12 -10
  50. package/dist/tree/tree-model.js.map +1 -1
  51. package/dist/tree/tree-view-model.d.ts +5 -0
  52. package/dist/tree/tree-view-model.js +1 -0
  53. package/dist/tree/tree-view-model.js.map +1 -1
  54. package/dist/tree/tree-view.d.ts +4 -2
  55. package/dist/tree/tree-view.js +4 -2
  56. package/dist/tree/tree-view.js.map +1 -1
  57. package/dist/vue/AdvancedEditor.vue.d.ts +4 -4
  58. package/dist/vue/SimpleEditor.vue.d.ts +4 -4
  59. package/dist/vue/components/EditorSurface.vue.d.ts +4 -4
  60. package/dist/vue/compose.js +1 -1
  61. package/package.json +1 -1
@@ -1,6 +1,7 @@
1
1
  import { ImageStudioImage, ImageStudioPromptBlock } from "../../core/backend-types.js";
2
2
  import { VueFeature } from "../../vue/index.js";
3
- import { EMPTY_IMAGE_STUDIO_STATE, ImageStudioState, ImageStudioTurn, addGeneration, addReference, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock } from "./state.js";
3
+ import { EMPTY_IMAGE_STUDIO_STATE, ImageStudioState, ImageStudioTurn, addGeneration, addReference, adoptImage, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock } from "./state.js";
4
+ import { ImageStudioLibrary, ImageStudioLibraryFacet, ImageStudioLibraryItem, ImageStudioLibraryQuery } from "./library.js";
4
5
  import { ImageStudioStore } from "./store.js";
5
6
  import _default from "./components/ImageStudioDialog.vue.js";
6
7
  import { ImageStudioNodeStore, ImageStudioNodeStoreOptions, createImageStudioNodeStore } from "./node-store.js";
@@ -13,5 +14,5 @@ import { ImageStudioNodeStore, ImageStudioNodeStoreOptions, createImageStudioNod
13
14
  */
14
15
  export declare function imageStudioFeature(): VueFeature;
15
16
  //#endregion
16
- export { EMPTY_IMAGE_STUDIO_STATE, _default as ImageStudioDialog, type ImageStudioImage, type ImageStudioNodeStore, type ImageStudioNodeStoreOptions, type ImageStudioPromptBlock, type ImageStudioState, type ImageStudioStore, type ImageStudioTurn, addGeneration, addReference, createImageStudioNodeStore, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock };
17
+ export { EMPTY_IMAGE_STUDIO_STATE, _default as ImageStudioDialog, type ImageStudioImage, type ImageStudioLibrary, type ImageStudioLibraryFacet, type ImageStudioLibraryItem, type ImageStudioLibraryQuery, type ImageStudioNodeStore, type ImageStudioNodeStoreOptions, type ImageStudioPromptBlock, type ImageStudioState, type ImageStudioStore, type ImageStudioTurn, addGeneration, addReference, adoptImage, createImageStudioNodeStore, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock };
17
18
  //# sourceMappingURL=vue.d.ts.map
@@ -1,4 +1,4 @@
1
- import { EMPTY_IMAGE_STUDIO_STATE, addGeneration, addReference, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock } from "./state.js";
1
+ import { EMPTY_IMAGE_STUDIO_STATE, addGeneration, addReference, adoptImage, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock } from "./state.js";
2
2
  import { imageStudioFeatureCore } from "./feature.js";
3
3
  import { createImageStudioNodeStore } from "./node-store.js";
4
4
  import _sfc_main from "./components/ImageStudioDialog.js";
@@ -15,6 +15,6 @@ function imageStudioFeature() {
15
15
  return imageStudioFeatureCore({ nodeView: VueNodeViewRenderer(_sfc_main$1) });
16
16
  }
17
17
  //#endregion
18
- export { EMPTY_IMAGE_STUDIO_STATE, _sfc_main as ImageStudioDialog, addGeneration, addReference, createImageStudioNodeStore, imageStudioFeature, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock };
18
+ export { EMPTY_IMAGE_STUDIO_STATE, _sfc_main as ImageStudioDialog, addGeneration, addReference, adoptImage, createImageStudioNodeStore, imageStudioFeature, isEmptyImageStudioState, normalizeImageStudioState, removeImage, select, selectedImage, setDescription, toggleImage, togglePromptBlock };
19
19
 
20
20
  //# sourceMappingURL=vue.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"vue.js","names":["ImageStudioView"],"sources":["../../../src/features/image-studio/vue.ts"],"sourcesContent":["import { VueNodeViewRenderer } from '@tiptap/vue-3'\nimport type { VueFeature } from '../../vue'\nimport ImageStudioView from './components/ImageStudioView.vue'\nimport { imageStudioFeatureCore } from './feature'\n\nexport { default as ImageStudioDialog } from './components/ImageStudioDialog.vue'\nexport { createImageStudioNodeStore, type ImageStudioNodeStore, type ImageStudioNodeStoreOptions } from './node-store'\nexport {\n addGeneration,\n addReference,\n EMPTY_IMAGE_STUDIO_STATE,\n type ImageStudioImage,\n type ImageStudioPromptBlock,\n type ImageStudioState,\n type ImageStudioTurn,\n isEmptyImageStudioState,\n normalizeImageStudioState,\n removeImage,\n select,\n selectedImage,\n setDescription,\n toggleImage,\n togglePromptBlock,\n} from './state'\nexport type { ImageStudioStore } from './store'\n\n/**\n * The Vue Bild-Studio feature: the `imageStudio` block with its Vue view (picture or description placeholder, opens the\n * studio dialog on double-click and through the block action `image-studio.open`), the `/` entry `bild-studio` and the\n * action. Generation, upload and the prompt blocks need a backend with the `images` capability; without it the view\n * says that generation is not set up.\n */\nexport function imageStudioFeature(): VueFeature {\n return imageStudioFeatureCore({ nodeView: VueNodeViewRenderer(ImageStudioView) })\n}\n"],"mappings":";;;;;;;;;;;;;AAgCA,SAAgB,qBAAiC;CAC/C,OAAO,uBAAuB,EAAE,UAAU,oBAAoBA,WAAe,EAAE,CAAC;AAClF"}
1
+ {"version":3,"file":"vue.js","names":["ImageStudioView"],"sources":["../../../src/features/image-studio/vue.ts"],"sourcesContent":["import { VueNodeViewRenderer } from '@tiptap/vue-3'\nimport type { VueFeature } from '../../vue'\nimport ImageStudioView from './components/ImageStudioView.vue'\nimport { imageStudioFeatureCore } from './feature'\n\nexport { default as ImageStudioDialog } from './components/ImageStudioDialog.vue'\nexport { createImageStudioNodeStore, type ImageStudioNodeStore, type ImageStudioNodeStoreOptions } from './node-store'\nexport {\n addGeneration,\n addReference,\n adoptImage,\n EMPTY_IMAGE_STUDIO_STATE,\n type ImageStudioImage,\n type ImageStudioPromptBlock,\n type ImageStudioState,\n type ImageStudioTurn,\n isEmptyImageStudioState,\n normalizeImageStudioState,\n removeImage,\n select,\n selectedImage,\n setDescription,\n toggleImage,\n togglePromptBlock,\n} from './state'\nexport type { ImageStudioLibrary, ImageStudioLibraryFacet, ImageStudioLibraryItem, ImageStudioLibraryQuery } from './library'\nexport type { ImageStudioStore } from './store'\n\n/**\n * The Vue Bild-Studio feature: the `imageStudio` block with its Vue view (picture or description placeholder, opens the\n * studio dialog on double-click and through the block action `image-studio.open`), the `/` entry `bild-studio` and the\n * action. Generation, upload and the prompt blocks need a backend with the `images` capability; without it the view\n * says that generation is not set up.\n */\nexport function imageStudioFeature(): VueFeature {\n return imageStudioFeatureCore({ nodeView: VueNodeViewRenderer(ImageStudioView) })\n}\n"],"mappings":";;;;;;;;;;;;;AAkCA,SAAgB,qBAAiC;CAC/C,OAAO,uBAAuB,EAAE,UAAU,oBAAoBA,WAAe,EAAE,CAAC;AAClF"}
@@ -1,7 +1,7 @@
1
1
  import { MAX_MEDIA_BYTES, MEDIA_TYPES, acceptFor, mediaKindOf, mediaMime } from "./schema.js";
2
+ import { createAudioRecorder } from "./audio-recorder.js";
2
3
  import { AUDIO_RECORDER_OPEN, Media, fileNodeFor, formatBytes, mediaNodeFor, openAudioRecorder, pickFiles, uploadOf } from "./upload.js";
3
4
  import { MAX_TEXT_BYTES, fileImport, isTextFile } from "./file-import.js";
4
5
  import { mediaBlocks, playerOptions } from "./node-views.js";
5
6
  import { mediaFeatureCore } from "./feature.js";
6
- import { createAudioRecorder } from "./audio-recorder.js";
7
7
  export { AUDIO_RECORDER_OPEN, MAX_MEDIA_BYTES, MAX_TEXT_BYTES, MEDIA_TYPES, Media, acceptFor, createAudioRecorder, fileImport, fileNodeFor, formatBytes, isTextFile, mediaBlocks, mediaFeatureCore, mediaKindOf, mediaMime, mediaNodeFor, openAudioRecorder, pickFiles, playerOptions, uploadOf };
@@ -5,8 +5,8 @@ import { cn } from "../../../react/ui/utils.js";
5
5
  import { Icon } from "../../../react/Icon.js";
6
6
  import { Button } from "../../../react/ui/button.js";
7
7
  import { Dialog, DialogContent, DialogFooter, DialogHeader, DialogTitle } from "../../../react/ui/dialog.js";
8
- import { useNotifier } from "../../../react/use-notifier.js";
9
8
  import "../upload.js";
9
+ import { useNotifier } from "../../../react/use-notifier.js";
10
10
  import { useAudioRecorder } from "./use-audio-recorder.js";
11
11
  import { useCallback, useEffect, useRef, useState } from "react";
12
12
  import { jsx, jsxs } from "react/jsx-runtime";
@@ -1,8 +1,8 @@
1
1
  import { useEditorI18n } from "../../react/use-editor-i18n.js";
2
- import { useNotifier } from "../../react/use-notifier.js";
3
2
  import { fileImport } from "./file-import.js";
4
3
  import { playerOptions } from "./node-views.js";
5
4
  import { mediaFeatureCore } from "./feature.js";
5
+ import { useNotifier } from "../../react/use-notifier.js";
6
6
  import { useAudioRecorder } from "./react/use-audio-recorder.js";
7
7
  import { AudioRecorderModal } from "./react/AudioRecorderModal.js";
8
8
  import { AudioView } from "./react/AudioView.js";
@@ -27,6 +27,15 @@ const de = {
27
27
  "imageStudio.dialog.chat.running": "Wird erzeugt …",
28
28
  "imageStudio.dialog.chat.fromDescription": "Aus der Beschreibung",
29
29
  "imageStudio.dialog.chat.turnImage": "Erzeugtes Bild: {instruction}",
30
+ "imageStudio.dialog.tabs.block": "Dieser Block",
31
+ "imageStudio.dialog.tabs.library": "Galerie",
32
+ "imageStudio.dialog.library.search": "Galerie durchsuchen",
33
+ "imageStudio.dialog.library.loading": "Wird geladen …",
34
+ "imageStudio.dialog.library.empty": "Keine passenden Bilder.",
35
+ "imageStudio.dialog.library.failed": "Galerie nicht geladen: {message}",
36
+ "imageStudio.dialog.library.reference": "Als Referenz",
37
+ "imageStudio.dialog.library.rename": "Umbenennen",
38
+ "imageStudio.dialog.library.remove": "Aus der Galerie entfernen",
30
39
  "imageStudio.node.noDescription": "Noch keine Beschreibung",
31
40
  "imageStudio.node.open": "Bild-Studio öffnen",
32
41
  "imageStudio.node.dialogTitle": "Bild-Studio",
@@ -1 +1 @@
1
- {"version":3,"file":"image-studio.js","names":[],"sources":["../../../src/i18n/de/image-studio.ts"],"sourcesContent":["export const de = {\n 'imageStudio.slash.insert': 'Bild-Studio',\n 'imageStudio.dialog.title': 'Bild-Studio',\n 'imageStudio.dialog.description.heading': 'Beschreibung',\n 'imageStudio.dialog.description.placeholder': 'Beschreibe das Bild …',\n 'imageStudio.dialog.blocks.heading': 'Prompt-Blöcke',\n 'imageStudio.dialog.blocks.empty': 'Es sind keine Prompt-Blöcke eingerichtet.',\n 'imageStudio.dialog.references.heading': 'Referenzen',\n 'imageStudio.dialog.references.upload': 'Bild hochladen',\n 'imageStudio.dialog.references.uploading': 'Wird hochgeladen …',\n 'imageStudio.dialog.references.drop': 'Bilder hierher ziehen oder hochladen',\n 'imageStudio.dialog.references.failed': 'Hochladen fehlgeschlagen: {message}',\n 'imageStudio.dialog.generations.heading': 'Frühere Erzeugungen',\n 'imageStudio.dialog.generations.empty': 'Noch keine Erzeugungen.',\n 'imageStudio.dialog.tile.toggle': 'Für die nächste Erzeugung verwenden: {title}',\n 'imageStudio.dialog.tile.use': 'Als Bild verwenden',\n 'imageStudio.dialog.tile.remove': 'Entfernen',\n 'imageStudio.dialog.tile.untitled': 'Bild ohne Titel',\n 'imageStudio.dialog.preview.heading': 'Bild',\n 'imageStudio.dialog.preview.empty': 'Noch kein Bild',\n 'imageStudio.dialog.chat.heading': 'Chat',\n 'imageStudio.dialog.chat.empty': 'Noch keine Anweisungen.',\n 'imageStudio.dialog.chat.label': 'Anweisung',\n 'imageStudio.dialog.chat.placeholder': 'Anweisung eingeben, z. B. „heller, mit mehr Kontrast“',\n 'imageStudio.dialog.chat.send': 'Erzeugen',\n 'imageStudio.dialog.chat.running': 'Wird erzeugt …',\n 'imageStudio.dialog.chat.fromDescription': 'Aus der Beschreibung',\n 'imageStudio.dialog.chat.turnImage': 'Erzeugtes Bild: {instruction}',\n 'imageStudio.node.noDescription': 'Noch keine Beschreibung',\n 'imageStudio.node.open': 'Bild-Studio öffnen',\n 'imageStudio.node.dialogTitle': 'Bild-Studio',\n 'imageStudio.action.open': 'Im Bild-Studio öffnen',\n 'imageStudio.action.notConfigured': 'Bildgenerierung ist nicht eingerichtet',\n} as const\n"],"mappings":";AAAA,MAAa,KAAK;CAChB,4BAA4B;CAC5B,4BAA4B;CAC5B,0CAA0C;CAC1C,8CAA8C;CAC9C,qCAAqC;CACrC,mCAAmC;CACnC,yCAAyC;CACzC,wCAAwC;CACxC,2CAA2C;CAC3C,sCAAsC;CACtC,wCAAwC;CACxC,0CAA0C;CAC1C,wCAAwC;CACxC,kCAAkC;CAClC,+BAA+B;CAC/B,kCAAkC;CAClC,oCAAoC;CACpC,sCAAsC;CACtC,oCAAoC;CACpC,mCAAmC;CACnC,iCAAiC;CACjC,iCAAiC;CACjC,uCAAuC;CACvC,gCAAgC;CAChC,mCAAmC;CACnC,2CAA2C;CAC3C,qCAAqC;CACrC,kCAAkC;CAClC,yBAAyB;CACzB,gCAAgC;CAChC,2BAA2B;CAC3B,oCAAoC;AACtC"}
1
+ {"version":3,"file":"image-studio.js","names":[],"sources":["../../../src/i18n/de/image-studio.ts"],"sourcesContent":["export const de = {\n 'imageStudio.slash.insert': 'Bild-Studio',\n 'imageStudio.dialog.title': 'Bild-Studio',\n 'imageStudio.dialog.description.heading': 'Beschreibung',\n 'imageStudio.dialog.description.placeholder': 'Beschreibe das Bild …',\n 'imageStudio.dialog.blocks.heading': 'Prompt-Blöcke',\n 'imageStudio.dialog.blocks.empty': 'Es sind keine Prompt-Blöcke eingerichtet.',\n 'imageStudio.dialog.references.heading': 'Referenzen',\n 'imageStudio.dialog.references.upload': 'Bild hochladen',\n 'imageStudio.dialog.references.uploading': 'Wird hochgeladen …',\n 'imageStudio.dialog.references.drop': 'Bilder hierher ziehen oder hochladen',\n 'imageStudio.dialog.references.failed': 'Hochladen fehlgeschlagen: {message}',\n 'imageStudio.dialog.generations.heading': 'Frühere Erzeugungen',\n 'imageStudio.dialog.generations.empty': 'Noch keine Erzeugungen.',\n 'imageStudio.dialog.tile.toggle': 'Für die nächste Erzeugung verwenden: {title}',\n 'imageStudio.dialog.tile.use': 'Als Bild verwenden',\n 'imageStudio.dialog.tile.remove': 'Entfernen',\n 'imageStudio.dialog.tile.untitled': 'Bild ohne Titel',\n 'imageStudio.dialog.preview.heading': 'Bild',\n 'imageStudio.dialog.preview.empty': 'Noch kein Bild',\n 'imageStudio.dialog.chat.heading': 'Chat',\n 'imageStudio.dialog.chat.empty': 'Noch keine Anweisungen.',\n 'imageStudio.dialog.chat.label': 'Anweisung',\n 'imageStudio.dialog.chat.placeholder': 'Anweisung eingeben, z. B. „heller, mit mehr Kontrast“',\n 'imageStudio.dialog.chat.send': 'Erzeugen',\n 'imageStudio.dialog.chat.running': 'Wird erzeugt …',\n 'imageStudio.dialog.chat.fromDescription': 'Aus der Beschreibung',\n 'imageStudio.dialog.chat.turnImage': 'Erzeugtes Bild: {instruction}',\n 'imageStudio.dialog.tabs.block': 'Dieser Block',\n 'imageStudio.dialog.tabs.library': 'Galerie',\n 'imageStudio.dialog.library.search': 'Galerie durchsuchen',\n 'imageStudio.dialog.library.loading': 'Wird geladen …',\n 'imageStudio.dialog.library.empty': 'Keine passenden Bilder.',\n 'imageStudio.dialog.library.failed': 'Galerie nicht geladen: {message}',\n 'imageStudio.dialog.library.reference': 'Als Referenz',\n 'imageStudio.dialog.library.rename': 'Umbenennen',\n 'imageStudio.dialog.library.remove': 'Aus der Galerie entfernen',\n 'imageStudio.node.noDescription': 'Noch keine Beschreibung',\n 'imageStudio.node.open': 'Bild-Studio öffnen',\n 'imageStudio.node.dialogTitle': 'Bild-Studio',\n 'imageStudio.action.open': 'Im Bild-Studio öffnen',\n 'imageStudio.action.notConfigured': 'Bildgenerierung ist nicht eingerichtet',\n} as const\n"],"mappings":";AAAA,MAAa,KAAK;CAChB,4BAA4B;CAC5B,4BAA4B;CAC5B,0CAA0C;CAC1C,8CAA8C;CAC9C,qCAAqC;CACrC,mCAAmC;CACnC,yCAAyC;CACzC,wCAAwC;CACxC,2CAA2C;CAC3C,sCAAsC;CACtC,wCAAwC;CACxC,0CAA0C;CAC1C,wCAAwC;CACxC,kCAAkC;CAClC,+BAA+B;CAC/B,kCAAkC;CAClC,oCAAoC;CACpC,sCAAsC;CACtC,oCAAoC;CACpC,mCAAmC;CACnC,iCAAiC;CACjC,iCAAiC;CACjC,uCAAuC;CACvC,gCAAgC;CAChC,mCAAmC;CACnC,2CAA2C;CAC3C,qCAAqC;CACrC,iCAAiC;CACjC,mCAAmC;CACnC,qCAAqC;CACrC,sCAAsC;CACtC,oCAAoC;CACpC,qCAAqC;CACrC,wCAAwC;CACxC,qCAAqC;CACrC,qCAAqC;CACrC,kCAAkC;CAClC,yBAAyB;CACzB,gCAAgC;CAChC,2BAA2B;CAC3B,oCAAoC;AACtC"}
package/dist/i18n/de.d.ts CHANGED
@@ -236,6 +236,15 @@ export declare const de: {
236
236
  readonly 'imageStudio.dialog.chat.running': "Wird erzeugt …";
237
237
  readonly 'imageStudio.dialog.chat.fromDescription': "Aus der Beschreibung";
238
238
  readonly 'imageStudio.dialog.chat.turnImage': "Erzeugtes Bild: {instruction}";
239
+ readonly 'imageStudio.dialog.tabs.block': "Dieser Block";
240
+ readonly 'imageStudio.dialog.tabs.library': "Galerie";
241
+ readonly 'imageStudio.dialog.library.search': "Galerie durchsuchen";
242
+ readonly 'imageStudio.dialog.library.loading': "Wird geladen …";
243
+ readonly 'imageStudio.dialog.library.empty': "Keine passenden Bilder.";
244
+ readonly 'imageStudio.dialog.library.failed': "Galerie nicht geladen: {message}";
245
+ readonly 'imageStudio.dialog.library.reference': "Als Referenz";
246
+ readonly 'imageStudio.dialog.library.rename': "Umbenennen";
247
+ readonly 'imageStudio.dialog.library.remove': "Aus der Galerie entfernen";
239
248
  readonly 'imageStudio.node.noDescription': "Noch keine Beschreibung";
240
249
  readonly 'imageStudio.node.open': "Bild-Studio öffnen";
241
250
  readonly 'imageStudio.node.dialogTitle': "Bild-Studio";
@@ -27,6 +27,15 @@ const en = {
27
27
  "imageStudio.dialog.chat.running": "Generating …",
28
28
  "imageStudio.dialog.chat.fromDescription": "From the description",
29
29
  "imageStudio.dialog.chat.turnImage": "Generated image: {instruction}",
30
+ "imageStudio.dialog.tabs.block": "This block",
31
+ "imageStudio.dialog.tabs.library": "Gallery",
32
+ "imageStudio.dialog.library.search": "Search the gallery",
33
+ "imageStudio.dialog.library.loading": "Loading …",
34
+ "imageStudio.dialog.library.empty": "No matching images.",
35
+ "imageStudio.dialog.library.failed": "Gallery not loaded: {message}",
36
+ "imageStudio.dialog.library.reference": "As reference",
37
+ "imageStudio.dialog.library.rename": "Rename",
38
+ "imageStudio.dialog.library.remove": "Remove from gallery",
30
39
  "imageStudio.node.noDescription": "No description yet",
31
40
  "imageStudio.node.open": "Open image studio",
32
41
  "imageStudio.node.dialogTitle": "Image studio",
@@ -1 +1 @@
1
- {"version":3,"file":"image-studio.js","names":[],"sources":["../../../src/i18n/en/image-studio.ts"],"sourcesContent":["import type { de } from '../de/image-studio'\n\nexport const en: { [K in keyof typeof de]: string } = {\n 'imageStudio.slash.insert': 'Image studio',\n 'imageStudio.dialog.title': 'Image studio',\n 'imageStudio.dialog.description.heading': 'Description',\n 'imageStudio.dialog.description.placeholder': 'Describe the image …',\n 'imageStudio.dialog.blocks.heading': 'Prompt blocks',\n 'imageStudio.dialog.blocks.empty': 'No prompt blocks are set up.',\n 'imageStudio.dialog.references.heading': 'References',\n 'imageStudio.dialog.references.upload': 'Upload image',\n 'imageStudio.dialog.references.uploading': 'Uploading …',\n 'imageStudio.dialog.references.drop': 'Drop images here or upload',\n 'imageStudio.dialog.references.failed': 'Upload failed: {message}',\n 'imageStudio.dialog.generations.heading': 'Previous generations',\n 'imageStudio.dialog.generations.empty': 'No generations yet.',\n 'imageStudio.dialog.tile.toggle': 'Use for the next generation: {title}',\n 'imageStudio.dialog.tile.use': 'Use as image',\n 'imageStudio.dialog.tile.remove': 'Remove',\n 'imageStudio.dialog.tile.untitled': 'Untitled image',\n 'imageStudio.dialog.preview.heading': 'Image',\n 'imageStudio.dialog.preview.empty': 'No image yet',\n 'imageStudio.dialog.chat.heading': 'Chat',\n 'imageStudio.dialog.chat.empty': 'No instructions yet.',\n 'imageStudio.dialog.chat.label': 'Instruction',\n 'imageStudio.dialog.chat.placeholder': 'Type an instruction, e.g. “brighter, more contrast”',\n 'imageStudio.dialog.chat.send': 'Generate',\n 'imageStudio.dialog.chat.running': 'Generating …',\n 'imageStudio.dialog.chat.fromDescription': 'From the description',\n 'imageStudio.dialog.chat.turnImage': 'Generated image: {instruction}',\n 'imageStudio.node.noDescription': 'No description yet',\n 'imageStudio.node.open': 'Open image studio',\n 'imageStudio.node.dialogTitle': 'Image studio',\n 'imageStudio.action.open': 'Open in the image studio',\n 'imageStudio.action.notConfigured': 'Image generation is not set up',\n}\n"],"mappings":";AAEA,MAAa,KAAyC;CACpD,4BAA4B;CAC5B,4BAA4B;CAC5B,0CAA0C;CAC1C,8CAA8C;CAC9C,qCAAqC;CACrC,mCAAmC;CACnC,yCAAyC;CACzC,wCAAwC;CACxC,2CAA2C;CAC3C,sCAAsC;CACtC,wCAAwC;CACxC,0CAA0C;CAC1C,wCAAwC;CACxC,kCAAkC;CAClC,+BAA+B;CAC/B,kCAAkC;CAClC,oCAAoC;CACpC,sCAAsC;CACtC,oCAAoC;CACpC,mCAAmC;CACnC,iCAAiC;CACjC,iCAAiC;CACjC,uCAAuC;CACvC,gCAAgC;CAChC,mCAAmC;CACnC,2CAA2C;CAC3C,qCAAqC;CACrC,kCAAkC;CAClC,yBAAyB;CACzB,gCAAgC;CAChC,2BAA2B;CAC3B,oCAAoC;AACtC"}
1
+ {"version":3,"file":"image-studio.js","names":[],"sources":["../../../src/i18n/en/image-studio.ts"],"sourcesContent":["import type { de } from '../de/image-studio'\n\nexport const en: { [K in keyof typeof de]: string } = {\n 'imageStudio.slash.insert': 'Image studio',\n 'imageStudio.dialog.title': 'Image studio',\n 'imageStudio.dialog.description.heading': 'Description',\n 'imageStudio.dialog.description.placeholder': 'Describe the image …',\n 'imageStudio.dialog.blocks.heading': 'Prompt blocks',\n 'imageStudio.dialog.blocks.empty': 'No prompt blocks are set up.',\n 'imageStudio.dialog.references.heading': 'References',\n 'imageStudio.dialog.references.upload': 'Upload image',\n 'imageStudio.dialog.references.uploading': 'Uploading …',\n 'imageStudio.dialog.references.drop': 'Drop images here or upload',\n 'imageStudio.dialog.references.failed': 'Upload failed: {message}',\n 'imageStudio.dialog.generations.heading': 'Previous generations',\n 'imageStudio.dialog.generations.empty': 'No generations yet.',\n 'imageStudio.dialog.tile.toggle': 'Use for the next generation: {title}',\n 'imageStudio.dialog.tile.use': 'Use as image',\n 'imageStudio.dialog.tile.remove': 'Remove',\n 'imageStudio.dialog.tile.untitled': 'Untitled image',\n 'imageStudio.dialog.preview.heading': 'Image',\n 'imageStudio.dialog.preview.empty': 'No image yet',\n 'imageStudio.dialog.chat.heading': 'Chat',\n 'imageStudio.dialog.chat.empty': 'No instructions yet.',\n 'imageStudio.dialog.chat.label': 'Instruction',\n 'imageStudio.dialog.chat.placeholder': 'Type an instruction, e.g. “brighter, more contrast”',\n 'imageStudio.dialog.chat.send': 'Generate',\n 'imageStudio.dialog.chat.running': 'Generating …',\n 'imageStudio.dialog.chat.fromDescription': 'From the description',\n 'imageStudio.dialog.chat.turnImage': 'Generated image: {instruction}',\n 'imageStudio.dialog.tabs.block': 'This block',\n 'imageStudio.dialog.tabs.library': 'Gallery',\n 'imageStudio.dialog.library.search': 'Search the gallery',\n 'imageStudio.dialog.library.loading': 'Loading …',\n 'imageStudio.dialog.library.empty': 'No matching images.',\n 'imageStudio.dialog.library.failed': 'Gallery not loaded: {message}',\n 'imageStudio.dialog.library.reference': 'As reference',\n 'imageStudio.dialog.library.rename': 'Rename',\n 'imageStudio.dialog.library.remove': 'Remove from gallery',\n 'imageStudio.node.noDescription': 'No description yet',\n 'imageStudio.node.open': 'Open image studio',\n 'imageStudio.node.dialogTitle': 'Image studio',\n 'imageStudio.action.open': 'Open in the image studio',\n 'imageStudio.action.notConfigured': 'Image generation is not set up',\n}\n"],"mappings":";AAEA,MAAa,KAAyC;CACpD,4BAA4B;CAC5B,4BAA4B;CAC5B,0CAA0C;CAC1C,8CAA8C;CAC9C,qCAAqC;CACrC,mCAAmC;CACnC,yCAAyC;CACzC,wCAAwC;CACxC,2CAA2C;CAC3C,sCAAsC;CACtC,wCAAwC;CACxC,0CAA0C;CAC1C,wCAAwC;CACxC,kCAAkC;CAClC,+BAA+B;CAC/B,kCAAkC;CAClC,oCAAoC;CACpC,sCAAsC;CACtC,oCAAoC;CACpC,mCAAmC;CACnC,iCAAiC;CACjC,iCAAiC;CACjC,uCAAuC;CACvC,gCAAgC;CAChC,mCAAmC;CACnC,2CAA2C;CAC3C,qCAAqC;CACrC,iCAAiC;CACjC,mCAAmC;CACnC,qCAAqC;CACrC,sCAAsC;CACtC,oCAAoC;CACpC,qCAAqC;CACrC,wCAAwC;CACxC,qCAAqC;CACrC,qCAAqC;CACrC,kCAAkC;CAClC,yBAAyB;CACzB,gCAAgC;CAChC,2BAA2B;CAC3B,oCAAoC;AACtC"}
@@ -4,10 +4,10 @@ import { newBlockId } from "../../core/schema/block-ids.js";
4
4
  import { aiContextOf } from "../../core/pipeline.js";
5
5
  import "../../core/derivation.js";
6
6
  import { compositeJSON } from "../../features/composites/nodes.js";
7
+ import { transferKindOf, transferSourceHash } from "../../features/transfer/transforms.js";
7
8
  import { modelProfiles } from "../../features/ai/model-profiles.js";
8
9
  import { notifyAiRateLimited } from "../../features/ai/rate-limit.js";
9
10
  import { postAiSse } from "../../features/ai/ai-sse.js";
10
- import { transferKindOf, transferSourceHash } from "../../features/transfer/transforms.js";
11
11
  import { discardDerived, writeDerivedBody } from "./derive.js";
12
12
  //#region src/integrations/composite-ai/transfer-transforms.ts
13
13
  /** The body of the `generate` request an AI transform sends: the dragged block's Markdown (cut to the task limit) as the selection. */
@@ -41,28 +41,28 @@ declare const __VLS_base: import("vue").DefineComponent<__VLS_PublicProps, {
41
41
  settingsOpen: import("vue").WritableComputedRef<boolean, boolean>;
42
42
  settingsTab: import("vue").WritableComputedRef<string | undefined, string | undefined>;
43
43
  }, {}, {}, {}, import("vue").ComponentOptionsMixin, import("vue").ComponentOptionsMixin, {
44
+ "update:modelValue": (markdown: string) => any;
45
+ ready: (editor: Editor) => any;
44
46
  settingsOpen: (tab?: string | undefined) => any;
45
47
  "update:sidebarOpen": (value: boolean) => any;
46
48
  "update:commentsOpen": (value: boolean) => any;
47
- "update:modelValue": (markdown: string) => any;
48
49
  frontmatter: (frontmatter: string | null) => any;
49
- ready: (editor: Editor) => any;
50
50
  metadataCreate: (list: string, item: MetadataItem) => any;
51
51
  contentError: (error: Error) => any;
52
52
  diagnostics: (diagnostics: MarkdownDiagnostic[]) => any;
53
53
  }, string, import("vue").PublicProps, Readonly<__VLS_PublicProps> & Readonly<{
54
+ "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
55
+ onReady?: ((editor: Editor) => any) | undefined;
54
56
  onSettingsOpen?: ((tab?: string | undefined) => any) | undefined;
55
57
  "onUpdate:sidebarOpen"?: ((value: boolean) => any) | undefined;
56
58
  "onUpdate:commentsOpen"?: ((value: boolean) => any) | undefined;
57
- "onUpdate:modelValue"?: ((markdown: string) => any) | undefined;
58
59
  onFrontmatter?: ((frontmatter: string | null) => any) | undefined;
59
- onReady?: ((editor: Editor) => any) | undefined;
60
60
  onMetadataCreate?: ((list: string, item: MetadataItem) => any) | undefined;
61
61
  onContentError?: ((error: Error) => any) | undefined;
62
62
  onDiagnostics?: ((diagnostics: MarkdownDiagnostic[]) => any) | undefined;
63
63
  }>, {
64
- modelValue: string;
65
64
  editable: boolean;
65
+ modelValue: string;
66
66
  settingsUi: "internal" | "external";
67
67
  }, {}, {}, {}, string, import("vue").ComponentProvideOptions, false, {}, any>;
68
68
  declare const __VLS_export: __VLS_WithSlots<typeof __VLS_base, __VLS_Slots>;
@@ -246,6 +246,15 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
246
246
  "imageStudio.dialog.chat.running"?: string | undefined;
247
247
  "imageStudio.dialog.chat.fromDescription"?: string | undefined;
248
248
  "imageStudio.dialog.chat.turnImage"?: string | undefined;
249
+ "imageStudio.dialog.tabs.block"?: string | undefined;
250
+ "imageStudio.dialog.tabs.library"?: string | undefined;
251
+ "imageStudio.dialog.library.search"?: string | undefined;
252
+ "imageStudio.dialog.library.loading"?: string | undefined;
253
+ "imageStudio.dialog.library.empty"?: string | undefined;
254
+ "imageStudio.dialog.library.failed"?: string | undefined;
255
+ "imageStudio.dialog.library.reference"?: string | undefined;
256
+ "imageStudio.dialog.library.rename"?: string | undefined;
257
+ "imageStudio.dialog.library.remove"?: string | undefined;
249
258
  "imageStudio.node.noDescription"?: string | undefined;
250
259
  "imageStudio.node.open"?: string | undefined;
251
260
  "imageStudio.node.dialogTitle"?: string | undefined;
@@ -1036,6 +1045,15 @@ declare const _default: import("@nuxt/schema").NuxtModule<{
1036
1045
  "imageStudio.dialog.chat.running"?: string | undefined;
1037
1046
  "imageStudio.dialog.chat.fromDescription"?: string | undefined;
1038
1047
  "imageStudio.dialog.chat.turnImage"?: string | undefined;
1048
+ "imageStudio.dialog.tabs.block"?: string | undefined;
1049
+ "imageStudio.dialog.tabs.library"?: string | undefined;
1050
+ "imageStudio.dialog.library.search"?: string | undefined;
1051
+ "imageStudio.dialog.library.loading"?: string | undefined;
1052
+ "imageStudio.dialog.library.empty"?: string | undefined;
1053
+ "imageStudio.dialog.library.failed"?: string | undefined;
1054
+ "imageStudio.dialog.library.reference"?: string | undefined;
1055
+ "imageStudio.dialog.library.rename"?: string | undefined;
1056
+ "imageStudio.dialog.library.remove"?: string | undefined;
1039
1057
  "imageStudio.node.noDescription"?: string | undefined;
1040
1058
  "imageStudio.node.open"?: string | undefined;
1041
1059
  "imageStudio.node.dialogTitle"?: string | undefined;
@@ -1,8 +1,8 @@
1
1
  import { defineEditor } from "../core/define-editor.js";
2
2
  import { coreContentFeature, coreUiFeature } from "../core/core-feature.js";
3
3
  import { CommentMark } from "../features/comments/schema.js";
4
- import { copyTransform } from "../features/transfer/transforms.js";
5
4
  import { mentionsFeature } from "../features/mentions/index.js";
5
+ import { copyTransform } from "../features/transfer/transforms.js";
6
6
  import { tablesFeature } from "../features/tables/feature.js";
7
7
  import { compositeMediaFeature } from "../integrations/composite-media/index.js";
8
8
  //#region src/presets/compose.ts
@@ -1,4 +1,5 @@
1
1
  import { coreUiFeature } from "../core/core-feature.js";
2
+ import { composeEditor as composeEditor$1 } from "../presets/compose.js";
2
3
  import { EditorCommandPalette } from "./EditorCommandPalette.js";
3
4
  import { aiFeature } from "../features/ai/react.js";
4
5
  import { authorsFeature } from "../features/authors/react.js";
@@ -13,7 +14,6 @@ import { transcriptFeature } from "../features/transcript/react.js";
13
14
  import { bulletsTransform, summaryTransform } from "../integrations/composite-ai/transfer-transforms.js";
14
15
  import { compositeAiFeature } from "../integrations/composite-ai/index.js";
15
16
  import { transcriptAiFeature } from "../integrations/transcript-ai/index.js";
16
- import { composeEditor as composeEditor$1 } from "../presets/compose.js";
17
17
  //#region src/react/compose.ts
18
18
  /** The React bindings of every UI-bound catalog feature. */
19
19
  const REACT_BINDINGS = {
@@ -3,11 +3,13 @@ import { NodeFilters, TreeViewModel } from "../tree-view-model.js";
3
3
  /**
4
4
  * The React view of the file browser's `TreeViewModel` (shared by every tree below one `EditorContextProvider`):
5
5
  * `nodeFilters` (the kinds hidden below each tree item, by item key) persists in localStorage, `expanded` (tree item
6
- * keys) lasts for the session. Change them through `model` (`expand`, `setKindHidden`, `clearAllFilters`, or `model.expanded.set`).
6
+ * keys) and `collapsedOutline` (the closed outline rows, `outline:<block id>`) last for the session. Change them
7
+ * through `model` (`expand`, `setKindHidden`, `clearAllFilters`, `model.expanded.set` or `model.collapsedOutline.set`).
7
8
  */
8
9
  export declare function useTreeView(): {
9
10
  nodeFilters: NodeFilters;
10
11
  expanded: string[];
12
+ collapsedOutline: string[];
11
13
  model: TreeViewModel;
12
14
  };
13
15
  //#endregion
@@ -5,13 +5,15 @@ import { treeView } from "../tree-view-model.js";
5
5
  /**
6
6
  * The React view of the file browser's `TreeViewModel` (shared by every tree below one `EditorContextProvider`):
7
7
  * `nodeFilters` (the kinds hidden below each tree item, by item key) persists in localStorage, `expanded` (tree item
8
- * keys) lasts for the session. Change them through `model` (`expand`, `setKindHidden`, `clearAllFilters`, or `model.expanded.set`).
8
+ * keys) and `collapsedOutline` (the closed outline rows, `outline:<block id>`) last for the session. Change them
9
+ * through `model` (`expand`, `setKindHidden`, `clearAllFilters`, `model.expanded.set` or `model.collapsedOutline.set`).
9
10
  */
10
11
  function useTreeView() {
11
12
  const model = treeView(useEditorContext());
12
13
  return {
13
14
  nodeFilters: useStore(model.nodeFilters),
14
15
  expanded: useStore(model.expanded),
16
+ collapsedOutline: useStore(model.collapsedOutline),
15
17
  model
16
18
  };
17
19
  }
@@ -1 +1 @@
1
- {"version":3,"file":"use-tree-view.js","names":[],"sources":["../../../src/tree/react/use-tree-view.ts"],"sourcesContent":["import { useEditorContext } from '../../react/context'\nimport { useStore } from '../../react/use-store'\nimport { type NodeFilters, treeView, type TreeViewModel } from '../tree-view-model'\n\n/**\n * The React view of the file browser's `TreeViewModel` (shared by every tree below one `EditorContextProvider`):\n * `nodeFilters` (the kinds hidden below each tree item, by item key) persists in localStorage, `expanded` (tree item\n * keys) lasts for the session. Change them through `model` (`expand`, `setKindHidden`, `clearAllFilters`, or `model.expanded.set`).\n */\nexport function useTreeView(): { nodeFilters: NodeFilters, expanded: string[], model: TreeViewModel } {\n const model = treeView(useEditorContext())\n return { nodeFilters: useStore(model.nodeFilters), expanded: useStore(model.expanded), model }\n}\n"],"mappings":";;;;;;;;;AASA,SAAgB,cAAsF;CACpG,MAAM,QAAQ,SAAS,iBAAiB,CAAC;CACzC,OAAO;EAAE,aAAa,SAAS,MAAM,WAAW;EAAG,UAAU,SAAS,MAAM,QAAQ;EAAG;CAAM;AAC/F"}
1
+ {"version":3,"file":"use-tree-view.js","names":[],"sources":["../../../src/tree/react/use-tree-view.ts"],"sourcesContent":["import { useEditorContext } from '../../react/context'\nimport { useStore } from '../../react/use-store'\nimport { type NodeFilters, treeView, type TreeViewModel } from '../tree-view-model'\n\n/**\n * The React view of the file browser's `TreeViewModel` (shared by every tree below one `EditorContextProvider`):\n * `nodeFilters` (the kinds hidden below each tree item, by item key) persists in localStorage, `expanded` (tree item\n * keys) and `collapsedOutline` (the closed outline rows, `outline:<block id>`) last for the session. Change them\n * through `model` (`expand`, `setKindHidden`, `clearAllFilters`, `model.expanded.set` or `model.collapsedOutline.set`).\n */\nexport function useTreeView(): { nodeFilters: NodeFilters, expanded: string[], collapsedOutline: string[], model: TreeViewModel } {\n const model = treeView(useEditorContext())\n return { nodeFilters: useStore(model.nodeFilters), expanded: useStore(model.expanded), collapsedOutline: useStore(model.collapsedOutline), model }\n}\n"],"mappings":";;;;;;;;;;AAUA,SAAgB,cAAkH;CAChI,MAAM,QAAQ,SAAS,iBAAiB,CAAC;CACzC,OAAO;EAAE,aAAa,SAAS,MAAM,WAAW;EAAG,UAAU,SAAS,MAAM,QAAQ;EAAG,kBAAkB,SAAS,MAAM,gBAAgB;EAAG;CAAM;AACnJ"}
@@ -1,8 +1,8 @@
1
1
  import { findBlockById } from "../core/schema/block-ids.js";
2
2
  import { blockTypesOf, compositeBasketsOf, compositeJSON } from "../features/composites/nodes.js";
3
3
  import { revealBlockInEditor } from "../outline/heading-outline.js";
4
- import { compositeFocusOf } from "../features/composites/focus.js";
5
4
  import { pickFiles } from "../features/media/upload.js";
5
+ import { compositeFocusOf } from "../features/composites/focus.js";
6
6
  import { moveBlockInto, moveIntoVerdict } from "../features/composites/outline.js";
7
7
  import { readOutline } from "./tree-items.js";
8
8
  //#region src/tree/tree-host.ts
@@ -73,7 +73,7 @@ function createTreeModel(options) {
73
73
  basketFilter: shared.basketFilter.get(),
74
74
  focusKey: null,
75
75
  expanded: shared.expanded.get(),
76
- collapsedOutline: [],
76
+ collapsedOutline: shared.collapsedOutline.get(),
77
77
  filterText: "",
78
78
  filterOverrides: NO_FILTERS,
79
79
  selectedFolder: options.selectedFolder ?? "",
@@ -230,7 +230,8 @@ function createTreeModel(options) {
230
230
  activeId,
231
231
  nodeFilters: shared.nodeFilters.get(),
232
232
  basketFilter: shared.basketFilter.get(),
233
- expanded: shared.expanded.get()
233
+ expanded: shared.expanded.get(),
234
+ collapsedOutline: shared.collapsedOutline.get()
234
235
  });
235
236
  const activeFolder = documents.find((d) => d.id === activeId)?.folder;
236
237
  if (activeFolder !== lastActiveFolder) {
@@ -249,7 +250,8 @@ function createTreeModel(options) {
249
250
  store.activeId.subscribe(sync),
250
251
  shared.nodeFilters.subscribe(sync),
251
252
  shared.basketFilter.subscribe(sync),
252
- shared.expanded.subscribe(sync)
253
+ shared.expanded.subscribe(sync),
254
+ shared.collapsedOutline.subscribe(sync)
253
255
  ];
254
256
  function readOutline() {
255
257
  patch({ outline: editor ? editor.outline(structure) : EMPTY_OUTLINE });
@@ -311,18 +313,18 @@ function createTreeModel(options) {
311
313
  ...core.filterOverrides,
312
314
  [key]: open
313
315
  } });
314
- else if (isOutlineKey(key)) patch({ collapsedOutline: open ? core.collapsedOutline.filter((k) => k !== key) : [...core.collapsedOutline.filter((k) => k !== key), key] });
315
- else if (open) shared.expand([key]);
316
+ else if (isOutlineKey(key)) {
317
+ const rest = shared.collapsedOutline.get().filter((k) => k !== key);
318
+ shared.collapsedOutline.set(open ? rest : [...rest, key]);
319
+ } else if (open) shared.expand([key]);
316
320
  else shared.expanded.set(shared.expanded.get().filter((k) => k !== key));
317
321
  }
318
322
  function expand(keys) {
319
323
  const outlineKeys = keys.filter(isOutlineKey);
320
324
  const { filterOverrides } = core;
321
- const overridden = keys.some((key) => key in filterOverrides);
322
- if (overridden || outlineKeys.some((key) => core.collapsedOutline.includes(key))) patch({
323
- collapsedOutline: core.collapsedOutline.filter((key) => !outlineKeys.includes(key)),
324
- filterOverrides: overridden ? Object.fromEntries(Object.entries(filterOverrides).filter(([key]) => !keys.includes(key))) : filterOverrides
325
- });
325
+ if (keys.some((key) => key in filterOverrides)) patch({ filterOverrides: Object.fromEntries(Object.entries(filterOverrides).filter(([key]) => !keys.includes(key))) });
326
+ const collapsed = shared.collapsedOutline.get();
327
+ if (outlineKeys.some((key) => collapsed.includes(key))) shared.collapsedOutline.set(collapsed.filter((key) => !outlineKeys.includes(key)));
326
328
  shared.expand(keys.filter((key) => !isOutlineKey(key)));
327
329
  }
328
330
  function setFilterText(text) {