@fileverse-dev/ddoc 7.0.2 → 7.1.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 (29) hide show
  1. package/dist/{ddoc-persistence-DLdSviUr.mjs → ddoc-persistence-DwgX_Jov.mjs} +1 -1
  2. package/dist/headless-editor-utils.es.js +1 -1
  3. package/dist/{index-DzUWhgai.mjs → index-C27hDm2f.mjs} +1 -1
  4. package/dist/index.es.js +8100 -7662
  5. package/dist/package/components/inline-comment/comment-drawer-desktop.d.ts +1 -0
  6. package/dist/package/components/inline-comment/comment-drawer.d.ts +1 -1
  7. package/dist/package/components/inline-comment/types.d.ts +1 -0
  8. package/dist/package/components/inline-comment/use-comment-drawer-filters.d.ts +6 -2
  9. package/dist/package/components/tabs/confirm-delete-modal.d.ts +1 -1
  10. package/dist/package/components/tabs/document-mobile-tab-panel.d.ts +3 -1
  11. package/dist/package/components/tabs/document-tabs-sidebar.d.ts +13 -4
  12. package/dist/package/components/tabs/tab-item.d.ts +9 -3
  13. package/dist/package/components/tabs/use-tab-tree-view.d.ts +36 -0
  14. package/dist/package/components/tabs/utils/__tests__/subtab-test-helpers.d.ts +11 -0
  15. package/dist/package/components/tabs/utils/__tests__/v7/v7-tab-ops.d.ts +15 -0
  16. package/dist/package/components/tabs/utils/__tests__/v7/v7-tab-utils.d.ts +45 -0
  17. package/dist/package/components/tabs/utils/tab-operations.d.ts +37 -0
  18. package/dist/package/components/tabs/utils/tab-utils.d.ts +25 -1
  19. package/dist/package/components/toc/document-outline.d.ts +1 -1
  20. package/dist/package/components/toc/types.d.ts +4 -0
  21. package/dist/package/hooks/use-tab-manager.d.ts +1 -0
  22. package/dist/package/types.d.ts +5 -0
  23. package/dist/package/use-ddoc-editor.d.ts +1 -0
  24. package/dist/persistence.es.js +1 -1
  25. package/dist/style.css +1 -1
  26. package/dist/tab-utils-Cvs3qmhi.mjs +340 -0
  27. package/dist/{use-headless-editor-CbMBM1S_.mjs → use-headless-editor-Bs_4LOHk.mjs} +3 -3
  28. package/package.json +2 -2
  29. package/dist/tab-utils-BNFvrUAj.mjs +0 -284
@@ -3,6 +3,7 @@ import { IComment } from '../../extensions/comment';
3
3
  interface DrawerSelectOption {
4
4
  id: string;
5
5
  label: string;
6
+ depth?: number;
6
7
  }
7
8
  interface CommentDrawerDesktopProps {
8
9
  activeCommentId: string | null;
@@ -1,3 +1,3 @@
1
1
  import { CommentDrawerProps } from './types';
2
2
 
3
- export declare const CommentDrawer: ({ isOpen, onClose, isNavbarVisible, isPresentationMode, activeCommentId, activeTabId, onTabChange, isPreviewMode, tabs, }: CommentDrawerProps) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const CommentDrawer: ({ isOpen, onClose, isNavbarVisible, isPresentationMode, activeCommentId, activeTabId, onTabChange, isPreviewMode, tabs, mobileContainer, }: CommentDrawerProps) => import("react/jsx-runtime").JSX.Element;
@@ -36,6 +36,7 @@ export interface CommentDrawerProps {
36
36
  onTabChange?: (tabId: string) => void;
37
37
  isPreviewMode: boolean;
38
38
  tabs: Tab[];
39
+ mobileContainer?: HTMLElement | null;
39
40
  }
40
41
  export interface CommentCardProps extends IComment {
41
42
  comment?: string;
@@ -29,10 +29,14 @@ export declare const useCommentDrawerFilters: ({ activeTabId, comments, tabs, }:
29
29
  selectedTabLabel: string;
30
30
  setCommentType: import('react').Dispatch<import('react').SetStateAction<string>>;
31
31
  setTab: import('react').Dispatch<import('react').SetStateAction<string>>;
32
- tabList: {
32
+ tabList: ({
33
33
  id: string;
34
34
  label: string;
35
- }[];
35
+ depth: number;
36
+ } | {
37
+ id: string;
38
+ label: string;
39
+ })[];
36
40
  tabNameById: {
37
41
  [k: string]: string;
38
42
  };
@@ -15,5 +15,5 @@ interface IConfirmDeleteModalProps {
15
15
  hasCloseIcon?: boolean;
16
16
  hideTitleIcon?: boolean;
17
17
  }
18
- export declare const ConfirmDeleteModal: ({ onClose, onConfirm, isOpen, isLoading, title, overlayClasses, noOverlay, hasCloseIcon, primaryLabel, hideTitleIcon, }: IConfirmDeleteModalProps) => import("react/jsx-runtime").JSX.Element;
18
+ export declare const ConfirmDeleteModal: ({ onClose, onConfirm, isOpen, isLoading, title, overlayClasses, noOverlay, hasCloseIcon, primaryLabel, hideTitleIcon, text, }: IConfirmDeleteModalProps) => import("react/jsx-runtime").JSX.Element;
19
19
  export {};
@@ -16,6 +16,7 @@ export interface DocumentMobileTabPanelProps {
16
16
  emoji?: string;
17
17
  }) => void;
18
18
  createTab: () => void;
19
+ createSubtab?: (parentId: string) => void;
19
20
  duplicateTab: (tabId: string) => void;
20
21
  orderTab: DocumentOutlineProps['orderTab'];
21
22
  deleteTab?: (tabId: string) => void;
@@ -27,5 +28,6 @@ export interface DocumentMobileTabPanelProps {
27
28
  isFocusMode?: boolean;
28
29
  layout?: DocumentOutlineProps['layout'];
29
30
  tabPanelSlot?: HTMLElement | null;
31
+ ddocId?: string;
30
32
  }
31
- export declare const DocumentMobileTabPanel: ({ tabs, activeTabId, setActiveTabId, editor, items, setItems, orientation, renameTab, createTab, duplicateTab, orderTab, deleteTab, tabCommentCounts, isPreviewMode, tabConfig, isVersionHistoryMode, isConnected, isFocusMode, layout, tabPanelSlot, }: DocumentMobileTabPanelProps) => import("react/jsx-runtime").JSX.Element | null;
33
+ export declare const DocumentMobileTabPanel: ({ tabs, activeTabId, setActiveTabId, editor, items, setItems, orientation, renameTab, createTab, createSubtab, duplicateTab, orderTab, deleteTab, tabCommentCounts, isPreviewMode, tabConfig, isVersionHistoryMode, isConnected, isFocusMode, layout, tabPanelSlot, ddocId, }: DocumentMobileTabPanelProps) => import("react/jsx-runtime").JSX.Element | null;
@@ -2,6 +2,7 @@ import { default as React } from 'react';
2
2
  import { DocumentOutlineProps } from '../toc/types';
3
3
  import { Tab } from './utils/tab-utils';
4
4
  import { Editor } from '@tiptap/core';
5
+ import { TabExpandState } from './use-tab-tree-view';
5
6
 
6
7
  import * as Y from 'yjs';
7
8
  export interface DocumentTabsSidebarProps {
@@ -18,6 +19,7 @@ export interface DocumentTabsSidebarProps {
18
19
  setItems: DocumentOutlineProps['setItems'];
19
20
  orientation?: DocumentOutlineProps['orientation'];
20
21
  createTab: () => void;
22
+ createSubtab?: (parentId: string) => void;
21
23
  renameTab: (tabId: string, payload: {
22
24
  newName?: string;
23
25
  emoji?: string;
@@ -33,13 +35,20 @@ export interface DocumentTabsSidebarProps {
33
35
  isConnected?: boolean;
34
36
  isFocusMode?: boolean;
35
37
  layout?: DocumentOutlineProps['layout'];
38
+ ddocId?: string;
36
39
  }
37
40
  export declare const DocumentTabsSidebar: ({ tabSectionContainer, ...rest }: DocumentTabsSidebarProps) => import("react/jsx-runtime").JSX.Element | null;
38
- export declare const TabSidebar: ({ tabs, activeTabId, setActiveTabId, showTOC, setShowTOC, hasToC, isPreviewMode, editor, items, setItems, orientation, createTab, renameTab, duplicateTab, orderTab, tabCommentCounts, isVersionHistoryMode, tabConfig, deleteTab, isConnected, isFocusMode, layout, }: DocumentTabsSidebarProps) => import("react/jsx-runtime").JSX.Element;
39
- export declare const DdocTab: ({ tab, tabIndex, tabCount, handleEmojiChange, handleNameChange, onClick, editor, tocItem, setTocItems, orientation, activeTabId, duplicateTab, commentCount, moveTabUp, moveTabDown, isPreviewMode, isVersionHistoryMode, tabConfig, onDelete, showOutline, onShowOutlineChange, isConnected, }: {
41
+ export declare const TabSidebar: ({ tabs, activeTabId, setActiveTabId, showTOC, setShowTOC, hasToC, isPreviewMode, editor, items, setItems, orientation, createTab, createSubtab, renameTab, duplicateTab, orderTab, tabCommentCounts, isVersionHistoryMode, tabConfig, deleteTab, isConnected, isFocusMode, layout, ddocId, }: DocumentTabsSidebarProps) => import("react/jsx-runtime").JSX.Element;
42
+ export declare const DdocTab: ({ tab, canMoveUp, canMoveDown, canDelete, indent, expandState, onToggleExpand, onAddSubtab, children, handleEmojiChange, handleNameChange, onClick, editor, tocItem, setTocItems, orientation, activeTabId, duplicateTab, commentCount, moveTabUp, moveTabDown, isPreviewMode, isVersionHistoryMode, tabConfig, onDelete, showOutline, onShowOutlineChange, isConnected, }: {
40
43
  tab: Tab;
41
- tabIndex: number;
42
- tabCount: number;
44
+ canMoveUp: boolean;
45
+ canMoveDown: boolean;
46
+ canDelete: boolean;
47
+ indent: number;
48
+ expandState?: TabExpandState;
49
+ onToggleExpand: () => void;
50
+ onAddSubtab?: () => void;
51
+ children?: React.ReactNode;
43
52
  handleNameChange: (tabId: string, nextName: string, nextEmoji?: string) => void;
44
53
  handleEmojiChange: (tabId: string, nextEmoji: string) => void;
45
54
  onClick: () => void;
@@ -1,4 +1,4 @@
1
- import { ComponentProps, HTMLAttributes } from 'react';
1
+ import { ComponentProps, HTMLAttributes, ReactNode } from 'react';
2
2
  import { LucideIcon } from '@fileverse/ui';
3
3
 
4
4
  export interface TabItemProps {
@@ -29,9 +29,15 @@ export interface TabItemProps {
29
29
  onCopyLink?: () => void;
30
30
  onDelete?: () => void;
31
31
  isConnected?: boolean;
32
+ onAddSubtab?: () => void;
33
+ /** Left offset in px for the row's level. */
34
+ indent?: number;
35
+ expandState?: 'expanded' | 'collapsed' | 'leaf';
36
+ onToggleExpand?: () => void;
32
37
  }
33
38
  interface SortableTabItemProps extends Omit<TabItemProps, 'dragHandleProps' | 'isEditing' | 'setIsEditing'> {
34
39
  id: string;
40
+ children?: ReactNode;
35
41
  }
36
42
  interface TabContextMenuItem {
37
43
  id: string;
@@ -50,8 +56,8 @@ interface TabContextMenuProps {
50
56
  popoverSide?: 'top' | 'bottom';
51
57
  popoverClassName?: string;
52
58
  }
53
- export declare const SortableTabItem: (props: SortableTabItemProps) => import("react/jsx-runtime").JSX.Element;
54
- export declare const TabItem: ({ isEditing, setIsEditing, tabId, name, emoji, commentCount, onNameChange, onEmojiChange, onClick, isActive, onDuplicate, dragHandleProps, hideContentMenu, alwaysShowMenu, menuPopoverClassName, onRename, showOutline, handleShowOutline, canMoveUp, canMoveDown, onMoveUp, onMoveDown, isPreviewMode, isVersionHistoryMode, onCopyLink, onDelete, isConnected, }: TabItemProps) => import("react/jsx-runtime").JSX.Element;
59
+ export declare const SortableTabItem: ({ children, ...props }: SortableTabItemProps) => import("react/jsx-runtime").JSX.Element;
60
+ export declare const TabItem: ({ isEditing, setIsEditing, tabId, name, emoji, commentCount, onNameChange, onEmojiChange, onClick, isActive, onDuplicate, dragHandleProps, hideContentMenu, alwaysShowMenu, menuPopoverClassName, onRename, showOutline, handleShowOutline, canMoveUp, canMoveDown, onMoveUp, onMoveDown, isPreviewMode, isVersionHistoryMode, onCopyLink, onDelete, isConnected, onAddSubtab, indent, expandState, onToggleExpand, }: TabItemProps) => import("react/jsx-runtime").JSX.Element;
55
61
  export declare const TabDragPreview: ({ name, emoji, }: {
56
62
  name: string;
57
63
  emoji: string;
@@ -0,0 +1,36 @@
1
+ import { Tab } from './utils/tab-utils';
2
+
3
+ export type TabExpandState = 'expanded' | 'collapsed' | 'leaf';
4
+ export interface TabTreeView {
5
+ /** Rows to render, in reading order, without those inside collapsed groups. */
6
+ visibleTabs: Tab[];
7
+ /** Tabs directly under a parent (or at the top level), in reading order. */
8
+ childrenOf: (parentId: string | null) => Tab[];
9
+ /** Arrow state for a row; undefined when the doc has no subtabs at all. */
10
+ expandStateOf: (tab: Tab) => TabExpandState | undefined;
11
+ toggleExpand: (tabId: string) => void;
12
+ expand: (tabId: string) => void;
13
+ /** The tab just before / after this one among its siblings. */
14
+ previousSiblingOf: (tab: Tab) => Tab | undefined;
15
+ nextSiblingOf: (tab: Tab) => Tab | undefined;
16
+ /** The last top-level tab cannot be deleted; a subtab always can. */
17
+ canDelete: (tab: Tab) => boolean;
18
+ /** A subtab can be added unless the tab is already at level 3. */
19
+ canAddSubtabTo: (tab: Tab) => boolean;
20
+ /** Left offset in px for a row at this tab's level. */
21
+ indentOf: (tab: Tab) => number;
22
+ }
23
+ export declare const TAB_INDENT_PX = 16;
24
+ export declare const useTabTreeView: ({ tabs, activeTabId, ddocId, }: {
25
+ tabs: Tab[];
26
+ activeTabId: string;
27
+ ddocId?: string;
28
+ }) => TabTreeView;
29
+ /** The delete dialog's wording: a tab with subtabs says so. */
30
+ export declare const deleteTabDialogCopy: (tab: Tab | null) => {
31
+ title: string;
32
+ text: string;
33
+ } | {
34
+ title: undefined;
35
+ text: undefined;
36
+ };
@@ -0,0 +1,11 @@
1
+ import * as Y from 'yjs';
2
+ /** A doc with a fixed client id, so two runs of the same writes give equal bytes. */
3
+ export declare const makeDoc: (clientID?: number) => Y.Doc;
4
+ export declare const encode: (doc: Y.Doc) => string;
5
+ export declare const copyDoc: (doc: Y.Doc, clientID?: number) => Y.Doc;
6
+ export declare const writeText: (doc: Y.Doc, tabId: string, text: string) => void;
7
+ /** Every word stored in the doc, in every tab's text, deleted tabs included. */
8
+ export declare const allStoredText: (doc: Y.Doc) => string;
9
+ /** Sends each doc's missing updates to every other doc until they agree. */
10
+ export declare const syncAll: (...docs: Y.Doc[]) => void;
11
+ export declare const existingDocFixtures: Record<string, () => string>;
@@ -0,0 +1,15 @@
1
+ import * as Y from 'yjs';
2
+ export interface V7DeleteSnapshot {
3
+ tabId: string;
4
+ name: string;
5
+ emoji: string | null;
6
+ orderIndex: number;
7
+ }
8
+ export declare const v7CreateTab: (ydoc: Y.Doc, tabId: string, shouldSyncActiveTab?: boolean) => string;
9
+ export declare const v7DeleteTab: (ydoc: Y.Doc, tabId: string, shouldSyncActiveTab?: boolean) => {
10
+ snapshot: V7DeleteSnapshot | null;
11
+ fallbackId: string | null;
12
+ };
13
+ export declare const v7RestoreDeletedTab: (ydoc: Y.Doc, snapshot: V7DeleteSnapshot, shouldSyncActiveTab?: boolean) => boolean;
14
+ export declare const v7DuplicateTab: (ydoc: Y.Doc, tabId: string, newTabId: string, shouldSyncActiveTab?: boolean) => string | undefined;
15
+ export declare const v7OrderTab: (ydoc: Y.Doc, destinationTabId: string, movedTabId: string) => void;
@@ -0,0 +1,45 @@
1
+ import * as Y from 'yjs';
2
+ export interface Tab {
3
+ id: string;
4
+ name: string;
5
+ emoji: string | null;
6
+ }
7
+ export interface TabsYdocNodes {
8
+ order: Y.Array<string>;
9
+ nameById: Y.Map<string>;
10
+ emojiById: Y.Map<string | null>;
11
+ tabState: Y.Map<unknown>;
12
+ deletedById: Y.Map<boolean>;
13
+ }
14
+ export interface SyncedTabsYdocNodes extends TabsYdocNodes {
15
+ didWrite: boolean;
16
+ }
17
+ interface TabSyncOptions {
18
+ createDefaultTabIfMissing?: boolean;
19
+ }
20
+ export declare const DEFAULT_TAB_ID = "default";
21
+ export declare const DEFAULT_TAB_NAME = "Tab 1";
22
+ export declare const LEGACY_ROOT_KEY = "ddocTabs";
23
+ export declare const ORDER_ROOT_KEY = "tabs_order";
24
+ export declare const NAME_ROOT_KEY = "tabs_name_registry";
25
+ export declare const EMOJI_ROOT_KEY = "tabs_emoji_registry";
26
+ export declare const STATE_ROOT_KEY = "tabs_state";
27
+ export declare const DELETED_ROOT_KEY = "tabs_delete_registry";
28
+ export declare const ACTIVE_TAB_STATE_KEY = "activeTabId";
29
+ export declare function syncTabState(doc: Y.Doc, options?: TabSyncOptions, transactionOrigin?: unknown): boolean;
30
+ export declare function deriveTabsFromEncodedState(yjsEncodedState: string | string[] | null | undefined, doc: Y.Doc, options?: TabSyncOptions): {
31
+ tabList: Tab[];
32
+ activeTabId: string;
33
+ didWrite: boolean;
34
+ };
35
+ export declare function getTabsYdocNodes(doc: Y.Doc): TabsYdocNodes;
36
+ export declare function syncTabStateAndGetNodes(doc: Y.Doc, options?: TabSyncOptions, transactionOrigin?: unknown): SyncedTabsYdocNodes;
37
+ export declare function mergeTabAwareYjsUpdates(encodedUpdates: string[], options?: TabSyncOptions): string;
38
+ export declare function getActiveTabIdFromNodes(tabNodes: Pick<TabsYdocNodes, 'tabState'>): string | null;
39
+ export declare function getTabMetadata(tabNodes: Pick<TabsYdocNodes, 'nameById' | 'emojiById'>, tabId: string): {
40
+ name: string;
41
+ emoji: string | null;
42
+ } | null;
43
+ export declare function getTabListFromNodes(tabNodes: Pick<TabsYdocNodes, 'order' | 'nameById' | 'emojiById'>): Tab[];
44
+ export declare function cloneFragmentContent(fragment: Y.XmlFragment): (Y.XmlElement | Y.XmlText)[];
45
+ export {};
@@ -0,0 +1,37 @@
1
+ import { Tab } from './tab-utils';
2
+ import * as Y from 'yjs';
3
+ export interface DeletedTabSnapshot {
4
+ tabId: string;
5
+ name: string;
6
+ emoji: string | null;
7
+ orderIndex: number;
8
+ }
9
+ export declare const getTabTree: (doc: Y.Doc) => Tab[];
10
+ /** The tab and every tab shown under it, in reading order. */
11
+ export declare const getSubtreeIds: (tabs: Tab[], tabId: string) => string[];
12
+ export declare const canAddSubtab: (tab: Tab | undefined) => boolean;
13
+ /**
14
+ * Adds already-named tabs as siblings of `tabId`, right after its block. A
15
+ * top-level tab keeps the 7.0 write: the new tabs go at the end.
16
+ */
17
+ export declare const insertSiblingTabsInDoc: (doc: Y.Doc, tabId: string, newTabIds: string[]) => void;
18
+ export declare const createSubtabInDoc: (doc: Y.Doc, parentId: string, newTabId: string, shouldSyncActiveTab: boolean) => string | null;
19
+ /**
20
+ * Moves `movedTabId` (with its subtabs) to the place of `destinationTabId`.
21
+ * Only between siblings: a destination under another parent is ignored.
22
+ */
23
+ export declare const moveTabInDoc: (doc: Y.Doc, destinationTabId: string, movedTabId: string) => boolean;
24
+ export declare const duplicateTabInDoc: (doc: Y.Doc, tabId: string, createId: () => string, shouldSyncActiveTab: boolean) => string | undefined;
25
+ export interface DeleteTabResult {
26
+ snapshots: DeletedTabSnapshot[];
27
+ /** The tab to open if the deleted tab, or one under it, was open. */
28
+ fallbackId: string | null;
29
+ }
30
+ /**
31
+ * Soft-deletes the tab and every tab under it: name and emoji removed, a
32
+ * deleted mark added, the id taken out of the order. Text and parent entries
33
+ * are kept, so undo can rebuild the group and nothing is erased.
34
+ */
35
+ export declare const deleteTabInDoc: (doc: Y.Doc, tabId: string, activeTabId: string, shouldSyncActiveTab: boolean) => DeleteTabResult;
36
+ /** Undo of deleteTabInDoc: brings the whole group back where it was. */
37
+ export declare const restoreDeletedTabsInDoc: (doc: Y.Doc, snapshots: DeletedTabSnapshot[], shouldSyncActiveTab: boolean) => boolean;
@@ -3,6 +3,9 @@ export interface Tab {
3
3
  id: string;
4
4
  name: string;
5
5
  emoji: string | null;
6
+ parentId?: string | null;
7
+ depth?: number;
8
+ hasChildren?: boolean;
6
9
  }
7
10
  export interface TabsYdocNodes {
8
11
  order: Y.Array<string>;
@@ -10,6 +13,7 @@ export interface TabsYdocNodes {
10
13
  emojiById: Y.Map<string | null>;
11
14
  tabState: Y.Map<unknown>;
12
15
  deletedById: Y.Map<boolean>;
16
+ parentById: Y.Map<string>;
13
17
  }
14
18
  export interface SyncedTabsYdocNodes extends TabsYdocNodes {
15
19
  didWrite: boolean;
@@ -26,6 +30,13 @@ export declare const EMOJI_ROOT_KEY = "tabs_emoji_registry";
26
30
  export declare const STATE_ROOT_KEY = "tabs_state";
27
31
  export declare const DELETED_ROOT_KEY = "tabs_delete_registry";
28
32
  export declare const ACTIVE_TAB_STATE_KEY = "activeTabId";
33
+ export declare const PARENT_ROOT_KEY = "tabs_parent_registry";
34
+ export declare const MAX_TAB_DEPTH = 3;
35
+ /**
36
+ * The heading level of a tab's title in exports: 1 for a tab, 2 or 3 for a
37
+ * subtab, so an exported file keeps the tree. Deeper data stays at 3.
38
+ */
39
+ export declare const getTabHeadingLevel: (tab: Pick<Tab, "depth">) => number;
29
40
  export declare function syncTabState(doc: Y.Doc, options?: TabSyncOptions, transactionOrigin?: unknown): boolean;
30
41
  export declare function deriveTabsFromEncodedState(yjsEncodedState: string | string[] | null | undefined, doc: Y.Doc, options?: TabSyncOptions): {
31
42
  tabList: Tab[];
@@ -40,6 +51,19 @@ export declare function getTabMetadata(tabNodes: Pick<TabsYdocNodes, 'nameById'
40
51
  name: string;
41
52
  emoji: string | null;
42
53
  } | null;
43
- export declare function getTabListFromNodes(tabNodes: Pick<TabsYdocNodes, 'order' | 'nameById' | 'emojiById'>): Tab[];
54
+ /**
55
+ * The tab list every screen and export reads, in reading order: a parent, then
56
+ * its subtabs. A doc without subtabs takes the flat path, unchanged since 7.0.
57
+ *
58
+ * The tree rules, the same on every device for the same stored data:
59
+ * T1 a tab is live if it is in the order list with a name;
60
+ * T2 a tab under a deleted tab is hidden (its text stays in the doc), unless
61
+ * that would hide every tab;
62
+ * T3 siblings keep the order of their first appearance in tabs_order;
63
+ * T4 a tab whose parent is unknown, or whose parent chain loops, is shown at
64
+ * the top level, so bad or half-synced data never hides a tab;
65
+ * T5 depth is reported as found; the sidebar caps the indent.
66
+ */
67
+ export declare function getTabListFromNodes(tabNodes: Pick<TabsYdocNodes, 'order' | 'nameById' | 'emojiById'> & Partial<Pick<TabsYdocNodes, 'parentById' | 'deletedById'>>): Tab[];
44
68
  export declare function cloneFragmentContent(fragment: Y.XmlFragment): (Y.XmlElement | Y.XmlText)[];
45
69
  export {};
@@ -1,3 +1,3 @@
1
1
  import { DocumentOutlineProps } from './types';
2
2
 
3
- export declare const DocumentOutline: ({ editor, hasToC, items, setItems, showTOC, setShowTOC, isPreviewMode, orientation, tabs, setTabs, activeTabId, setActiveTabId, createTab, renameTab, duplicateTab, orderTab, ydoc, tabCommentCounts, tabSectionContainer, isVersionHistoryMode, tabConfig, deleteTab, isConnected, isFocusMode, layout, tabPanelSlot, }: DocumentOutlineProps) => import("react/jsx-runtime").JSX.Element;
3
+ export declare const DocumentOutline: ({ editor, hasToC, items, setItems, showTOC, setShowTOC, isPreviewMode, orientation, tabs, setTabs, activeTabId, setActiveTabId, createTab, createSubtab, renameTab, duplicateTab, orderTab, ydoc, tabCommentCounts, tabSectionContainer, isVersionHistoryMode, tabConfig, deleteTab, isConnected, isFocusMode, layout, tabPanelSlot, ddocId, }: DocumentOutlineProps) => import("react/jsx-runtime").JSX.Element;
@@ -41,6 +41,7 @@ export interface DocumentOutlineProps {
41
41
  activeTabId: string;
42
42
  setActiveTabId: (id: string) => void;
43
43
  createTab: () => void;
44
+ createSubtab?: (parentId: string) => void;
44
45
  renameTab: (tabId: string, payload: {
45
46
  newName?: string;
46
47
  emoji?: string;
@@ -54,6 +55,7 @@ export interface DocumentOutlineProps {
54
55
  tabConfig?: {
55
56
  onCopyTabLink?: (tabId: string) => void;
56
57
  defaultTabId?: string;
58
+ enableSubtabs?: boolean;
57
59
  };
58
60
  deleteTab?: (tabId: string) => void;
59
61
  isConnected?: boolean;
@@ -61,4 +63,6 @@ export interface DocumentOutlineProps {
61
63
  /** 'contained': sized from the editor canvas. Only DdocEditor passes it. */
62
64
  layout?: 'viewport' | 'contained';
63
65
  tabPanelSlot?: HTMLElement | null;
66
+ /** Lets the sidebar remember collapsed tabs per document in this browser. */
67
+ ddocId?: string;
64
68
  }
@@ -25,6 +25,7 @@ export declare const useTabManager: ({ ydoc, initialContent, enableCollaboration
25
25
  setTabs: import('react').Dispatch<import('react').SetStateAction<Tab[]>>;
26
26
  setActiveTabId: (id: string) => void;
27
27
  createTab: () => string;
28
+ createSubtab: (parentId: string) => string | null;
28
29
  deleteTab: (tabId: string) => void;
29
30
  renameTab: (tabId: string, { newName, emoji }: {
30
31
  newName?: string;
@@ -144,6 +144,11 @@ export interface DdocProps extends CommentAccountProps {
144
144
  tabConfig?: {
145
145
  onCopyTabLink?: (tabId: string) => void;
146
146
  defaultTabId?: string;
147
+ /**
148
+ * Shows "Add subtab" in the tab menu. Off by default. Docs that already
149
+ * have subtabs show them either way.
150
+ */
151
+ enableSubtabs?: boolean;
147
152
  };
148
153
  versionHistoryState?: {
149
154
  enabled: boolean;
@@ -24,6 +24,7 @@ export declare const useDdocEditor: ({ isPreviewMode, viewerMode, initialContent
24
24
  setTabs: import('react').Dispatch<import('react').SetStateAction<import('./components/tabs/utils/tab-utils').Tab[]>>;
25
25
  setActiveTabId: (id: string) => void;
26
26
  createTab: () => string;
27
+ createSubtab: (parentId: string) => string | null;
27
28
  deleteTab: (tabId: string) => void;
28
29
  renameTab: (tabId: string, { newName, emoji }: {
29
30
  newName?: string;
@@ -1,4 +1,4 @@
1
- import { D as n, a as o, d as D, g as a, m as r, r as d, b as C } from "./ddoc-persistence-DLdSviUr.mjs";
1
+ import { D as n, a as o, d as D, g as a, m as r, r as d, b as C } from "./ddoc-persistence-DwgX_Jov.mjs";
2
2
  export {
3
3
  n as DDOC_STORE_REPAIRED,
4
4
  o as DEFAULT_DDOC_PERSISTENCE_TIMEOUT_MS,