papyr-react 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +87 -0
- package/dist/blocks/WorkspaceBlock/WorkspaceBlock.d.ts +79 -0
- package/dist/blocks/index.d.ts +2 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +12 -0
- package/dist/components/Breadcrumbs/index.d.ts +2 -0
- package/dist/components/DoubleSidebarLayout/DoubleSidebarLayout.d.ts +49 -0
- package/dist/components/DoubleSidebarLayout/index.d.ts +2 -0
- package/dist/components/EmptyState/EmptyState.d.ts +31 -0
- package/dist/components/EmptyState/index.d.ts +2 -0
- package/dist/components/FileHierarchy/FileHierarchy.d.ts +19 -0
- package/dist/components/FileHierarchy/FileHierarchy.test.d.ts +1 -0
- package/dist/components/FileHierarchy/MemoizedFolderTree.d.ts +16 -0
- package/dist/components/FileHierarchy/index.d.ts +3 -0
- package/dist/components/FileHierarchy/types.d.ts +9 -0
- package/dist/components/FileHierarchy/utils.d.ts +5 -0
- package/dist/components/FileSearch/FileSearch.d.ts +27 -0
- package/dist/components/FileSearch/index.d.ts +2 -0
- package/dist/components/GraphView/GraphView.d.ts +19 -0
- package/dist/components/GraphView/index.d.ts +2 -0
- package/dist/components/HoverPreview/HoverPreview.d.ts +12 -0
- package/dist/components/HoverPreview/index.d.ts +2 -0
- package/dist/components/MiniGraph/MiniGraph.d.ts +8 -0
- package/dist/components/MiniGraph/MiniGraph.test.d.ts +1 -0
- package/dist/components/MiniGraph/index.d.ts +2 -0
- package/dist/components/NotePreview/NotePreviewContent.d.ts +14 -0
- package/dist/components/NotePreview/index.d.ts +2 -0
- package/dist/components/NoteViewer/NoteViewer.d.ts +15 -0
- package/dist/components/NoteViewer/NoteViewer.test.d.ts +1 -0
- package/dist/components/NoteViewer/index.d.ts +2 -0
- package/dist/components/SearchBar/SearchBar.d.ts +9 -0
- package/dist/components/SearchBar/index.d.ts +2 -0
- package/dist/components/SearchDropdown/SearchDropdown.d.ts +12 -0
- package/dist/components/SearchDropdown/index.d.ts +1 -0
- package/dist/components/SidebarLayout/SidebarLayout.d.ts +33 -0
- package/dist/components/SidebarLayout/index.d.ts +2 -0
- package/dist/components/TableOfContents/TableOfContents.d.ts +10 -0
- package/dist/components/TableOfContents/TableOfContents.test.d.ts +1 -0
- package/dist/components/TableOfContents/index.d.ts +1 -0
- package/dist/components/TagFilter/TagFilter.d.ts +9 -0
- package/dist/components/TagFilter/index.d.ts +2 -0
- package/dist/components/Toast/Toast.d.ts +11 -0
- package/dist/components/index.d.ts +16 -0
- package/dist/hooks/index.d.ts +3 -0
- package/dist/hooks/useActiveNote.d.ts +27 -0
- package/dist/hooks/useActiveNote.test.d.ts +1 -0
- package/dist/hooks/useNotes.d.ts +3 -0
- package/dist/hooks/useRoutableActiveNote.d.ts +16 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +3178 -0
- package/dist/index.js.map +1 -0
- package/dist/providers/PapyrProvider.d.ts +24 -0
- package/dist/providers/index.d.ts +2 -0
- package/dist/style.css +1548 -0
- package/dist/styles/index.d.ts +0 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/utils/graphUtils.d.ts +18 -0
- package/dist/utils/hydration.d.ts +8 -0
- package/dist/utils/index.d.ts +3 -0
- package/dist/utils/linkUtils.d.ts +10 -0
- package/package.json +87 -0
- package/src/styles/index.ts +2 -0
- package/src/styles/theme.css +184 -0
- package/style.css +1 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 RayKong
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
# papyr-react
|
|
2
|
+
|
|
3
|
+
## Components vs. Blocks
|
|
4
|
+
|
|
5
|
+
Papyr exposes two layers, similar to shadcn/ui:
|
|
6
|
+
|
|
7
|
+
- **Components** – focused building blocks such as `FileHierarchy`, `FileSearch`, `NoteViewer`, and `TableOfContents`.
|
|
8
|
+
- **Blocks** – opinionated compositions that wire multiple components together. The new `WorkspaceBlock` uses `DoubleSidebarLayout` to render a file hierarchy + main + outline surface with independent scrolling.
|
|
9
|
+
|
|
10
|
+
```tsx
|
|
11
|
+
import {
|
|
12
|
+
WorkspaceBlock,
|
|
13
|
+
hydrateSearchIndex,
|
|
14
|
+
type WorkspaceBlockProps
|
|
15
|
+
} from 'papyr-react'
|
|
16
|
+
|
|
17
|
+
const searchIndex = hydrateSearchIndex(serializedIndex)
|
|
18
|
+
|
|
19
|
+
const workspaceProps: WorkspaceBlockProps = {
|
|
20
|
+
notes,
|
|
21
|
+
tree,
|
|
22
|
+
searchIndex,
|
|
23
|
+
graph,
|
|
24
|
+
initialSlug: notes[0]?.slug
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function App() {
|
|
28
|
+
return <WorkspaceBlock {...workspaceProps} />
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Blocks accept slots so you can swap any pane:
|
|
33
|
+
|
|
34
|
+
```tsx
|
|
35
|
+
<WorkspaceBlock
|
|
36
|
+
{...workspaceProps}
|
|
37
|
+
rightSidebar={({ activeNote }) => (
|
|
38
|
+
<CustomMetadataPanel note={activeNote} />
|
|
39
|
+
)}
|
|
40
|
+
/>
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
Use components directly when you need finer control, or drop in a block for a ready-made layout.
|
|
44
|
+
|
|
45
|
+
## Hydrating build output
|
|
46
|
+
|
|
47
|
+
When you load JSON produced by `papyr-core`, hydrate the search index before
|
|
48
|
+
passing it to `PapyrProvider`:
|
|
49
|
+
|
|
50
|
+
```ts
|
|
51
|
+
import { hydrateSearchIndex } from 'papyr-react'
|
|
52
|
+
import { type SerializedSearchIndex } from 'papyr-core/runtime'
|
|
53
|
+
|
|
54
|
+
const serialized: SerializedSearchIndex = /* build output */
|
|
55
|
+
const searchIndex = hydrateSearchIndex(serialized)
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
This accepts either the serialized payload or an already hydrated index, so it
|
|
59
|
+
can be used safely in shared code paths.
|
|
60
|
+
|
|
61
|
+
## Syncing with a router
|
|
62
|
+
|
|
63
|
+
Use `useRoutableActiveNote` to keep Papyr state in sync with your routing
|
|
64
|
+
library. Provide two callbacks: one to read the current slug from the router and
|
|
65
|
+
another to push updates when the user selects a different note.
|
|
66
|
+
|
|
67
|
+
```tsx
|
|
68
|
+
import { useCallback } from 'react'
|
|
69
|
+
import { useNavigate, useParams } from 'react-router-dom'
|
|
70
|
+
import { useRoutableActiveNote } from 'papyr-react'
|
|
71
|
+
|
|
72
|
+
const navigate = useNavigate()
|
|
73
|
+
const { slug } = useParams<{ slug?: string }>()
|
|
74
|
+
|
|
75
|
+
const { activeNote, activeSlug, setActiveSlug } = useRoutableActiveNote(notes, {
|
|
76
|
+
getCurrentSlug: useCallback(() => slug ?? null, [slug]),
|
|
77
|
+
onSlugChange: useCallback(
|
|
78
|
+
(nextSlug) => {
|
|
79
|
+
navigate(nextSlug ? `/notes/${nextSlug}` : '/')
|
|
80
|
+
},
|
|
81
|
+
[navigate]
|
|
82
|
+
)
|
|
83
|
+
})
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
The hook exposes the same API as `useActiveNote`, so existing components (e.g.
|
|
87
|
+
sidebar or note viewer) continue to work while the URL stays in sync.
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { FolderNode, NoteGraph, SearchIndex, Slug, WebReadyNote } from 'papyr-core/runtime';
|
|
2
|
+
import { ReactNode } from 'react';
|
|
3
|
+
import { DoubleSidebarLayoutProps } from '../../components/DoubleSidebarLayout';
|
|
4
|
+
import { FileHierarchyProps } from '../../components/FileHierarchy';
|
|
5
|
+
import { TableOfContentsProps } from '../../components/TableOfContents';
|
|
6
|
+
|
|
7
|
+
export interface WorkspaceBlockContext {
|
|
8
|
+
notes: WebReadyNote[];
|
|
9
|
+
searchIndex: SearchIndex;
|
|
10
|
+
graph: NoteGraph | null;
|
|
11
|
+
activeSlug: Slug | null;
|
|
12
|
+
activeNote: WebReadyNote | null;
|
|
13
|
+
setActiveSlug: (slug: Slug | null) => void;
|
|
14
|
+
setActiveNote: (note: WebReadyNote | null) => void;
|
|
15
|
+
}
|
|
16
|
+
type SlotRenderer = ReactNode | ((context: WorkspaceBlockContext) => ReactNode);
|
|
17
|
+
type FileHierarchyOverrides = Omit<FileHierarchyProps, 'tree' | 'onNoteClick' | 'activeSlug' | 'notes' | 'searchable' | 'searchIndex'>;
|
|
18
|
+
type TableOfContentsOverrides = Omit<TableOfContentsProps, 'note'>;
|
|
19
|
+
export interface WorkspaceBlockProps {
|
|
20
|
+
notes: WebReadyNote[];
|
|
21
|
+
tree: FolderNode[] | FolderNode;
|
|
22
|
+
searchIndex: SearchIndex;
|
|
23
|
+
graph?: NoteGraph | null;
|
|
24
|
+
/**
|
|
25
|
+
* UNCONTROLLED MODE: Initial slug for internal state management.
|
|
26
|
+
* Use this when you don't need to sync with external state (e.g., router).
|
|
27
|
+
*/
|
|
28
|
+
initialSlug?: Slug | null;
|
|
29
|
+
/**
|
|
30
|
+
* CONTROLLED MODE: Current active slug managed by parent.
|
|
31
|
+
* When provided, WorkspaceBlock delegates state to parent via onActiveSlugChange.
|
|
32
|
+
* Use with useRoutableActiveNote for router integration.
|
|
33
|
+
*/
|
|
34
|
+
activeSlug?: Slug | null;
|
|
35
|
+
/**
|
|
36
|
+
* CONTROLLED MODE: Callback when active slug should change.
|
|
37
|
+
* Required when using controlled mode (activeSlug prop).
|
|
38
|
+
*/
|
|
39
|
+
onActiveSlugChange?: (slug: Slug | null) => void;
|
|
40
|
+
className?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Customise layout widths. Defaults to 280px for each sidebar.
|
|
43
|
+
*/
|
|
44
|
+
leftWidth?: DoubleSidebarLayoutProps['leftWidth'];
|
|
45
|
+
rightWidth?: DoubleSidebarLayoutProps['rightWidth'];
|
|
46
|
+
/**
|
|
47
|
+
* Render custom content for each pane. Provide either a React node or a
|
|
48
|
+
* function that receives the block context.
|
|
49
|
+
*/
|
|
50
|
+
leftSidebar?: SlotRenderer;
|
|
51
|
+
main?: SlotRenderer;
|
|
52
|
+
rightSidebar?: SlotRenderer;
|
|
53
|
+
/**
|
|
54
|
+
* When true, omits the default table of contents from the right sidebar.
|
|
55
|
+
*/
|
|
56
|
+
hideTableOfContents?: boolean;
|
|
57
|
+
/**
|
|
58
|
+
* Called whenever the active note changes.
|
|
59
|
+
*/
|
|
60
|
+
onNoteChange?: (note: WebReadyNote | null) => void;
|
|
61
|
+
/**
|
|
62
|
+
* Optional overrides forwarded to the default FileHierarchy implementation.
|
|
63
|
+
*/
|
|
64
|
+
fileHierarchyProps?: FileHierarchyOverrides;
|
|
65
|
+
/**
|
|
66
|
+
* Optional overrides forwarded to the default TableOfContents implementation.
|
|
67
|
+
*/
|
|
68
|
+
tableOfContentsProps?: TableOfContentsOverrides;
|
|
69
|
+
/**
|
|
70
|
+
* Custom empty state rendered when no note is selected.
|
|
71
|
+
*/
|
|
72
|
+
emptyState?: ReactNode;
|
|
73
|
+
/**
|
|
74
|
+
* Toggle native sidebar scrollbars. Default: hidden.
|
|
75
|
+
*/
|
|
76
|
+
hideSidebarScrollbars?: boolean;
|
|
77
|
+
}
|
|
78
|
+
export declare const WorkspaceBlock: ({ notes, tree, searchIndex, graph, initialSlug, activeSlug: controlledActiveSlug, onActiveSlugChange, className, leftWidth, rightWidth, leftSidebar, main, rightSidebar, hideTableOfContents, onNoteChange, fileHierarchyProps, tableOfContentsProps, emptyState, hideSidebarScrollbars }: WorkspaceBlockProps) => import("react/jsx-runtime").JSX.Element;
|
|
79
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface BreadcrumbItem {
|
|
4
|
+
label: string;
|
|
5
|
+
href?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BreadcrumbsProps {
|
|
8
|
+
trail: BreadcrumbItem[];
|
|
9
|
+
className?: string;
|
|
10
|
+
separator?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare const Breadcrumbs: FC<BreadcrumbsProps>;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
type SidebarWidth = string | number;
|
|
4
|
+
export interface DoubleSidebarLayoutProps {
|
|
5
|
+
/**
|
|
6
|
+
* Node rendered in the left sidebar column.
|
|
7
|
+
*/
|
|
8
|
+
leftSidebar: ReactNode;
|
|
9
|
+
/**
|
|
10
|
+
* Node rendered as the primary content column.
|
|
11
|
+
*/
|
|
12
|
+
main: ReactNode;
|
|
13
|
+
/**
|
|
14
|
+
* Optional node rendered in the right sidebar column.
|
|
15
|
+
*/
|
|
16
|
+
rightSidebar?: ReactNode;
|
|
17
|
+
/**
|
|
18
|
+
* Custom width for the left sidebar column.
|
|
19
|
+
* @default 280
|
|
20
|
+
*/
|
|
21
|
+
leftWidth?: SidebarWidth;
|
|
22
|
+
/**
|
|
23
|
+
* Custom width for the right sidebar column.
|
|
24
|
+
* @default 480
|
|
25
|
+
*/
|
|
26
|
+
rightWidth?: SidebarWidth;
|
|
27
|
+
/**
|
|
28
|
+
* When true (default) the layout stretches to fill the viewport height and
|
|
29
|
+
* constrains scrolling to the individual panes. Set to false to allow the
|
|
30
|
+
* page to dictate overall height/scrolling.
|
|
31
|
+
*/
|
|
32
|
+
fullHeight?: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* When true (default) sidebars hide native scrollbars while keeping their
|
|
35
|
+
* content scrollable.
|
|
36
|
+
*/
|
|
37
|
+
hideSidebarScrollbars?: boolean;
|
|
38
|
+
/**
|
|
39
|
+
* Additional className forwarded to the root container.
|
|
40
|
+
*/
|
|
41
|
+
className?: string;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Three column workspace layout with independent scrolling for each pane.
|
|
45
|
+
* Mirrors the behaviour of the Obsidian help site where the main pane owns the
|
|
46
|
+
* visible scrollbar and sidebars scroll without showing native scrollbars.
|
|
47
|
+
*/
|
|
48
|
+
export declare const DoubleSidebarLayout: FC<DoubleSidebarLayoutProps>;
|
|
49
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface EmptyStateProps {
|
|
4
|
+
icon?: ReactNode;
|
|
5
|
+
title: string;
|
|
6
|
+
description?: string;
|
|
7
|
+
children?: ReactNode;
|
|
8
|
+
className?: string;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Generic empty state component for displaying placeholder content
|
|
12
|
+
* when no data is available.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* // Simple usage
|
|
16
|
+
* <EmptyState
|
|
17
|
+
* title="No notes found"
|
|
18
|
+
* description="Add some markdown files to get started"
|
|
19
|
+
* />
|
|
20
|
+
*
|
|
21
|
+
* @example
|
|
22
|
+
* // With icon and custom content
|
|
23
|
+
* <EmptyState
|
|
24
|
+
* icon="📝"
|
|
25
|
+
* title="No notes selected"
|
|
26
|
+
* description="Choose a note from the sidebar"
|
|
27
|
+
* >
|
|
28
|
+
* <button>Create New Note</button>
|
|
29
|
+
* </EmptyState>
|
|
30
|
+
*/
|
|
31
|
+
export declare const EmptyState: FC<EmptyStateProps>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { FolderNode, Slug, SearchIndex } from 'papyr-core/runtime';
|
|
3
|
+
import { NoteLinkRenderer } from './types';
|
|
4
|
+
|
|
5
|
+
export interface FileHierarchyProps {
|
|
6
|
+
tree: FolderNode[] | FolderNode;
|
|
7
|
+
className?: string;
|
|
8
|
+
onNoteClick?: (slug: Slug) => void;
|
|
9
|
+
renderNoteLink?: NoteLinkRenderer;
|
|
10
|
+
activeSlug?: string;
|
|
11
|
+
notes?: Array<{
|
|
12
|
+
slug: string;
|
|
13
|
+
title?: string;
|
|
14
|
+
}>;
|
|
15
|
+
searchable?: boolean;
|
|
16
|
+
searchIndex?: SearchIndex;
|
|
17
|
+
searchPlaceholder?: string;
|
|
18
|
+
}
|
|
19
|
+
export declare const FileHierarchy: FC<FileHierarchyProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { FolderNode, Slug } from 'papyr-core/runtime';
|
|
3
|
+
import { NoteLinkRenderer } from './types';
|
|
4
|
+
import { NoteTitleMap } from './utils';
|
|
5
|
+
|
|
6
|
+
export interface MemoizedFolderTreeProps {
|
|
7
|
+
node: FolderNode;
|
|
8
|
+
onNoteClick?: (slug: Slug) => void;
|
|
9
|
+
renderNoteLink?: NoteLinkRenderer;
|
|
10
|
+
activeSlug?: string;
|
|
11
|
+
noteTitleMap?: NoteTitleMap;
|
|
12
|
+
depth?: number;
|
|
13
|
+
isSearching?: boolean;
|
|
14
|
+
searchQuery?: string;
|
|
15
|
+
}
|
|
16
|
+
export declare const MemoizedFolderTree: FC<MemoizedFolderTreeProps>;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { ReactNode } from 'react';
|
|
2
|
+
import { Slug } from 'papyr-core/runtime';
|
|
3
|
+
|
|
4
|
+
export interface NoteLinkRenderContext {
|
|
5
|
+
onClick?: () => void;
|
|
6
|
+
isActive: boolean;
|
|
7
|
+
isSearchMatch: boolean;
|
|
8
|
+
}
|
|
9
|
+
export type NoteLinkRenderer = (slug: Slug, context: NoteLinkRenderContext) => ReactNode;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Slug } from 'papyr-core/runtime';
|
|
2
|
+
|
|
3
|
+
export type NoteTitleMap = Record<string, string | undefined>;
|
|
4
|
+
export declare const formatFolderName: (name: string) => string;
|
|
5
|
+
export declare const getNoteDisplayText: (slug: Slug, noteTitleMap?: NoteTitleMap) => string;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface FileSearchProps {
|
|
4
|
+
query: string;
|
|
5
|
+
onChange: (query: string) => void;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
/** When true, applies compact styling suitable for sidebars */
|
|
9
|
+
compact?: boolean;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Standalone search input component for filtering files/notes.
|
|
13
|
+
* Can be used independently or embedded in other components like FileHierarchy.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Standalone usage
|
|
17
|
+
* <FileSearch query={query} onChange={setQuery} />
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* // In sidebar with compact styling
|
|
21
|
+
* <FileSearch query={query} onChange={setQuery} compact />
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* // Custom styling
|
|
25
|
+
* <FileSearch query={query} onChange={setQuery} className="my-search" />
|
|
26
|
+
*/
|
|
27
|
+
export declare const FileSearch: FC<FileSearchProps>;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { GraphNode, NoteGraph, Slug } from 'papyr-core/runtime';
|
|
2
|
+
|
|
3
|
+
interface GraphCanvasProps {
|
|
4
|
+
graph: NoteGraph | null;
|
|
5
|
+
className?: string;
|
|
6
|
+
filterNode?: (node: GraphNode) => boolean;
|
|
7
|
+
focusPredicate?: (node: GraphNode) => boolean;
|
|
8
|
+
nodeColor?: (node: GraphNode) => string;
|
|
9
|
+
zoomExtent?: [number, number];
|
|
10
|
+
focusNodeId?: string | null;
|
|
11
|
+
onNodeSelect?: (node: GraphNode) => void;
|
|
12
|
+
}
|
|
13
|
+
export interface GraphViewProps extends GraphCanvasProps {
|
|
14
|
+
activeSlug?: Slug | null;
|
|
15
|
+
showFullscreenToggle?: boolean;
|
|
16
|
+
fullscreenTitle?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare const GraphView: ({ graph, className, activeSlug, filterNode, focusPredicate, nodeColor, zoomExtent, onNodeSelect, showFullscreenToggle, fullscreenTitle }: GraphViewProps) => import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface HoverPreviewProps {
|
|
4
|
+
trigger: ReactNode;
|
|
5
|
+
renderPreview: () => ReactNode;
|
|
6
|
+
/**
|
|
7
|
+
* When true, applies the default dotted underline styling to visually indicate the trigger is interactive.
|
|
8
|
+
* Set to false when the supplied trigger already communicates interactivity (e.g. buttons, links).
|
|
9
|
+
*/
|
|
10
|
+
highlightTrigger?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const HoverPreview: FC<HoverPreviewProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface NotePreviewData {
|
|
4
|
+
slug: string;
|
|
5
|
+
title?: string | null;
|
|
6
|
+
excerpt?: string | null;
|
|
7
|
+
description?: string | null;
|
|
8
|
+
tags?: string[];
|
|
9
|
+
}
|
|
10
|
+
interface NotePreviewContentProps {
|
|
11
|
+
note: NotePreviewData;
|
|
12
|
+
}
|
|
13
|
+
export declare const NotePreviewContent: FC<NotePreviewContentProps>;
|
|
14
|
+
export {};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
import { WebReadyNote, Slug } from 'papyr-core/runtime';
|
|
3
|
+
|
|
4
|
+
export interface NoteViewerNavigateOptions {
|
|
5
|
+
fragment?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface NoteViewerProps {
|
|
8
|
+
note: WebReadyNote | null;
|
|
9
|
+
emptyState?: ReactNode;
|
|
10
|
+
onNavigateNote?: (slug: Slug, options?: NoteViewerNavigateOptions) => void;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Rich note renderer with link previews, breadcrumbs, and metadata.
|
|
14
|
+
*/
|
|
15
|
+
export declare const NoteViewer: FC<NoteViewerProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { SearchIndex } from 'papyr-core/runtime';
|
|
3
|
+
|
|
4
|
+
export interface SearchDropdownProps {
|
|
5
|
+
searchIndex: SearchIndex;
|
|
6
|
+
onResultClick: (slug: string) => void;
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
maxResults?: number;
|
|
10
|
+
showCategories?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export declare const SearchDropdown: FC<SearchDropdownProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './SearchDropdown';
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { FC, ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface SidebarLayoutProps {
|
|
4
|
+
sidebar: ReactNode;
|
|
5
|
+
main: ReactNode;
|
|
6
|
+
className?: string;
|
|
7
|
+
sidebarWidth?: string | number;
|
|
8
|
+
/**
|
|
9
|
+
* When true (default), the layout fills the viewport height and scrolls the main pane.
|
|
10
|
+
* Set to false to allow the page to control scrolling.
|
|
11
|
+
*/
|
|
12
|
+
fullHeight?: boolean;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Common two-column layout with sidebar and main content area.
|
|
16
|
+
* Provides a responsive, full-height layout pattern.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* // Basic usage
|
|
20
|
+
* <SidebarLayout
|
|
21
|
+
* sidebar={<FileHierarchy tree={tree} />}
|
|
22
|
+
* main={<NoteViewer note={note} />}
|
|
23
|
+
* />
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* // Custom sidebar width
|
|
27
|
+
* <SidebarLayout
|
|
28
|
+
* sidebar={<FileHierarchy tree={tree} />}
|
|
29
|
+
* main={<NoteViewer note={note} />}
|
|
30
|
+
* sidebarWidth={320}
|
|
31
|
+
* />
|
|
32
|
+
*/
|
|
33
|
+
export declare const SidebarLayout: FC<SidebarLayoutProps>;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
import { WebReadyNote, Heading } from 'papyr-core/runtime';
|
|
3
|
+
|
|
4
|
+
export interface TableOfContentsProps {
|
|
5
|
+
note: WebReadyNote | null;
|
|
6
|
+
className?: string;
|
|
7
|
+
title?: string;
|
|
8
|
+
onNavigate?: (heading: Heading) => void;
|
|
9
|
+
}
|
|
10
|
+
export declare const TableOfContents: FC<TableOfContentsProps>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './TableOfContents';
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { FC } from 'react';
|
|
2
|
+
|
|
3
|
+
export interface ToastDescriptor {
|
|
4
|
+
id: string;
|
|
5
|
+
message: string;
|
|
6
|
+
}
|
|
7
|
+
export interface ToastContainerProps {
|
|
8
|
+
toasts: ToastDescriptor[];
|
|
9
|
+
onDismiss: (id: string) => void;
|
|
10
|
+
}
|
|
11
|
+
export declare const ToastContainer: FC<ToastContainerProps>;
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export * from './GraphView';
|
|
2
|
+
export * from './MiniGraph';
|
|
3
|
+
export * from './NoteViewer';
|
|
4
|
+
export * from './SearchBar';
|
|
5
|
+
export * from './Breadcrumbs';
|
|
6
|
+
export * from './HoverPreview';
|
|
7
|
+
export * from './NotePreview';
|
|
8
|
+
export * from './TagFilter';
|
|
9
|
+
export * from './FileHierarchy';
|
|
10
|
+
export * from './FileSearch';
|
|
11
|
+
export * from './EmptyState';
|
|
12
|
+
export * from './SidebarLayout';
|
|
13
|
+
export * from './DoubleSidebarLayout';
|
|
14
|
+
export * from './SearchDropdown';
|
|
15
|
+
export * from './TableOfContents';
|
|
16
|
+
export * from './Toast/Toast';
|