@book.dev/ui 1.60.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/dist/EmojiGrid-xK5mPJPo.js +205 -0
- package/dist/blockeditor/BlockEditor.d.ts +68 -0
- package/dist/blockeditor/CodeBlockView.d.ts +19 -0
- package/dist/blockeditor/InlineToolbar.d.ts +18 -0
- package/dist/blockeditor/LinkPicker.d.ts +16 -0
- package/dist/blockeditor/MentionMenu.d.ts +14 -0
- package/dist/blockeditor/PresentBlocks.d.ts +21 -0
- package/dist/blockeditor/RichTextEditor.d.ts +29 -0
- package/dist/blockeditor/SlashMenu.d.ts +49 -0
- package/dist/blockeditor/TextBlockView.d.ts +9 -0
- package/dist/blockeditor/__tests__/LinkPicker.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/SlashMenu.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/aiApply.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/groupLock.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/highlight.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/mergeUp.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/present.test.d.ts +1 -0
- package/dist/blockeditor/aiBlocks.d.ts +9 -0
- package/dist/blockeditor/colors.d.ts +23 -0
- package/dist/blockeditor/exportBlocks.d.ts +25 -0
- package/dist/blockeditor/highlight.d.ts +25 -0
- package/dist/blockeditor/index.d.ts +8 -0
- package/dist/blockeditor/kit/KitFrame.d.ts +95 -0
- package/dist/blockeditor/kit/KitSettings.d.ts +18 -0
- package/dist/blockeditor/kit/OptionsEditor.d.ts +8 -0
- package/dist/blockeditor/kit/__tests__/chartMath.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/dataflow.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/exportKit.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/exportKit2.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/groupSync.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/inputs2Render.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/inputs2Scope.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/inputsRender.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/kitConfig.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/kitPanel.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/options.test.d.ts +1 -0
- package/dist/blockeditor/kit/__tests__/scope.test.d.ts +1 -0
- package/dist/blockeditor/kit/cards.d.ts +51 -0
- package/dist/blockeditor/kit/chartMath.d.ts +62 -0
- package/dist/blockeditor/kit/charts.d.ts +27 -0
- package/dist/blockeditor/kit/completion.d.ts +45 -0
- package/dist/blockeditor/kit/dataflow.d.ts +68 -0
- package/dist/blockeditor/kit/groupSync.d.ts +23 -0
- package/dist/blockeditor/kit/index.d.ts +11 -0
- package/dist/blockeditor/kit/inputs.d.ts +135 -0
- package/dist/blockeditor/kit/inputs2.d.ts +86 -0
- package/dist/blockeditor/kit/kitConfig.d.ts +5 -0
- package/dist/blockeditor/kit/kitPanel.d.ts +31 -0
- package/dist/blockeditor/kit/lock.d.ts +12 -0
- package/dist/blockeditor/kit/options.d.ts +60 -0
- package/dist/blockeditor/kit/progress.d.ts +20 -0
- package/dist/blockeditor/kit/scope.d.ts +100 -0
- package/dist/blockeditor/model.d.ts +236 -0
- package/dist/blockeditor/present.d.ts +18 -0
- package/dist/blockeditor/provider.d.ts +16 -0
- package/dist/blockeditor/reactiveBlocks.d.ts +2 -0
- package/dist/blockeditor/registry.d.ts +38 -0
- package/dist/blockeditor/richtext.d.ts +48 -0
- package/dist/blockeditor/useBlockEditor.d.ts +45 -0
- package/dist/components/AboutDialog.d.ts +9 -0
- package/dist/components/AgentPanel.d.ts +2 -0
- package/dist/components/AiBridgeHost.d.ts +14 -0
- package/dist/components/AiSearchDialog.d.ts +8 -0
- package/dist/components/AiSettings.d.ts +7 -0
- package/dist/components/AppearanceSettings.d.ts +3 -0
- package/dist/components/BackForwardCluster.d.ts +1 -0
- package/dist/components/BackupSettings.d.ts +2 -0
- package/dist/components/BreadcrumbCluster.d.ts +1 -0
- package/dist/components/ColorSchemeMenu.d.ts +1 -0
- package/dist/components/CommandMenu.d.ts +1 -0
- package/dist/components/CommandToggle.d.ts +3 -0
- package/dist/components/DocumentArea.d.ts +8 -0
- package/dist/components/Drawer.d.ts +7 -0
- package/dist/components/EmojiGrid.d.ts +16 -0
- package/dist/components/EmojiPickerHost.d.ts +8 -0
- package/dist/components/ExtensionsSettings.d.ts +7 -0
- package/dist/components/FavoritesNav.d.ts +8 -0
- package/dist/components/GeneralSettings.d.ts +2 -0
- package/dist/components/GlobalShortcuts.d.ts +9 -0
- package/dist/components/HomeButton.d.ts +2 -0
- package/dist/components/IconPicker.d.ts +17 -0
- package/dist/components/NavBar.d.ts +1 -0
- package/dist/components/NavContextMenu.d.ts +7 -0
- package/dist/components/PageActionsCluster.d.ts +9 -0
- package/dist/components/PageAppearanceHost.d.ts +9 -0
- package/dist/components/PageContextMenu.d.ts +17 -0
- package/dist/components/PageCover.d.ts +18 -0
- package/dist/components/PageHeaderControls.d.ts +13 -0
- package/dist/components/PageIcon.d.ts +16 -0
- package/dist/components/PageProperties.d.ts +53 -0
- package/dist/components/PluginBoot.d.ts +2 -0
- package/dist/components/PresentMode.d.ts +7 -0
- package/dist/components/ProfileAvatar.d.ts +17 -0
- package/dist/components/ProfileMenu.d.ts +6 -0
- package/dist/components/Settings.d.ts +7 -0
- package/dist/components/SettingsButton.d.ts +2 -0
- package/dist/components/SettingsPanel.d.ts +14 -0
- package/dist/components/SideNav.d.ts +1 -0
- package/dist/components/SideNavToggle.d.ts +3 -0
- package/dist/components/SidebarSections.d.ts +17 -0
- package/dist/components/SplitPane.d.ts +9 -0
- package/dist/components/TemplateGallery.d.ts +8 -0
- package/dist/components/TitlebarTabs.d.ts +10 -0
- package/dist/components/TrashDialog.d.ts +7 -0
- package/dist/components/WindowActionsCluster.d.ts +6 -0
- package/dist/components/WindowControls.d.ts +6 -0
- package/dist/components/WindowTitle.d.ts +7 -0
- package/dist/components/WorkspaceInfo.d.ts +6 -0
- package/dist/components/WorkspaceNavigationTree.d.ts +14 -0
- package/dist/components/WorkspaceSelectMenu.d.ts +10 -0
- package/dist/components/__tests__/AppearanceSettings.test.d.ts +1 -0
- package/dist/components/__tests__/PageIcon.test.d.ts +1 -0
- package/dist/components/__tests__/SettingsPanel.test.d.ts +1 -0
- package/dist/components/__tests__/buildTree.test.d.ts +1 -0
- package/dist/components/__tests__/profileAvatar.test.d.ts +1 -0
- package/dist/components/appearance/AppearanceControls.d.ts +33 -0
- package/dist/components/appearance/PageCustomiseBody.d.ts +29 -0
- package/dist/components/brand/OpenBookLogo.d.ts +11 -0
- package/dist/components/brand/index.d.ts +1 -0
- package/dist/components/database/DatabaseCard.d.ts +36 -0
- package/dist/components/database/DatabasePicker.d.ts +12 -0
- package/dist/components/database/DatabaseRowProperties.d.ts +13 -0
- package/dist/components/database/DatabaseView.d.ts +9 -0
- package/dist/components/database/InlineDatabaseBlock.d.ts +3 -0
- package/dist/components/database/__tests__/InlineDatabaseBlock.test.d.ts +1 -0
- package/dist/components/database/databaseCells.d.ts +57 -0
- package/dist/components/database/databaseCharts.d.ts +28 -0
- package/dist/components/database/databaseColors.d.ts +12 -0
- package/dist/components/database/databaseGraph.d.ts +16 -0
- package/dist/components/database/databaseLayouts.d.ts +84 -0
- package/dist/components/database/databaseMap.d.ts +21 -0
- package/dist/components/database/databaseMapLeaflet.d.ts +26 -0
- package/dist/components/database/databaseMenus.d.ts +97 -0
- package/dist/components/database/databaseTimeline.d.ts +27 -0
- package/dist/components/database/geocode.d.ts +24 -0
- package/dist/components/database/useDatabase.d.ts +129 -0
- package/dist/components/index.d.ts +12 -0
- package/dist/components/review/BlockReviewMarkers.d.ts +19 -0
- package/dist/components/review/CommentThread.d.ts +20 -0
- package/dist/components/review/ReviewPaneBody.d.ts +12 -0
- package/dist/components/review/SuggestHost.d.ts +13 -0
- package/dist/components/review/SuggestionCard.d.ts +21 -0
- package/dist/components/review/__tests__/review.test.d.ts +1 -0
- package/dist/components/review/useReview.d.ts +27 -0
- package/dist/components/settings/AccountSettings.d.ts +6 -0
- package/dist/components/settings/AdminSettings.d.ts +2 -0
- package/dist/components/settings/ConnectionSettings.d.ts +7 -0
- package/dist/components/settings/CustomisationSettings.d.ts +2 -0
- package/dist/components/settings/ProfileSettings.d.ts +2 -0
- package/dist/components/settings/primitives.d.ts +47 -0
- package/dist/components/settings/stubs.d.ts +8 -0
- package/dist/components/ui/__tests__/kbd.test.d.ts +1 -0
- package/dist/components/ui/__tests__/markdown.test.d.ts +1 -0
- package/dist/components/ui/__tests__/select.test.d.ts +1 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/button.d.ts +11 -0
- package/dist/components/ui/command.d.ts +86 -0
- package/dist/components/ui/context-menu.d.ts +24 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts +27 -0
- package/dist/components/ui/icon-button.d.ts +16 -0
- package/dist/components/ui/input.d.ts +9 -0
- package/dist/components/ui/kbd.d.ts +31 -0
- package/dist/components/ui/label.d.ts +5 -0
- package/dist/components/ui/markdown.d.ts +19 -0
- package/dist/components/ui/navigation-menu.d.ts +12 -0
- package/dist/components/ui/popover.d.ts +6 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/select.d.ts +42 -0
- package/dist/components/ui/skeleton.d.ts +6 -0
- package/dist/components/ui/switch.d.ts +4 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/components/ui/tree.d.ts +37 -0
- package/dist/components/useAppCommands.d.ts +25 -0
- package/dist/data/DataProvider.d.ts +30 -0
- package/dist/data/index.d.ts +1 -0
- package/dist/databaseMapLeaflet-8LYcHcR6.js +87 -0
- package/dist/export/__tests__/chartNormalize.test.d.ts +1 -0
- package/dist/export/__tests__/export.test.d.ts +1 -0
- package/dist/export/__tests__/exportReactive.test.d.ts +1 -0
- package/dist/export/chartNormalize.d.ts +22 -0
- package/dist/export/chartSvg.d.ts +2 -0
- package/dist/export/documentModel.d.ts +136 -0
- package/dist/export/exportSite.d.ts +40 -0
- package/dist/export/format.d.ts +2 -0
- package/dist/export/kitChart.d.ts +21 -0
- package/dist/export/toHtml.d.ts +25 -0
- package/dist/export/toMarkdown.d.ts +7 -0
- package/dist/export/toPdf.d.ts +14 -0
- package/dist/exportBlocks-33D7P_8Q.js +987 -0
- package/dist/exportSite-DlRm4u7W.js +50 -0
- package/dist/format-CLQoRoYP.js +1646 -0
- package/dist/i18n/__tests__/i18n.test.d.ts +1 -0
- package/dist/i18n/index.d.ts +24 -0
- package/dist/i18n/messages/de.d.ts +2 -0
- package/dist/i18n/messages/en.d.ts +977 -0
- package/dist/i18n/messages/ja.d.ts +2 -0
- package/dist/i18n/messages/zh.d.ts +2 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.js +20915 -0
- package/dist/layouts/DefaultLayout.d.ts +4 -0
- package/dist/layouts/index.d.ts +1 -0
- package/dist/lib/__tests__/accountClient.test.d.ts +1 -0
- package/dist/lib/__tests__/backlinks.test.d.ts +1 -0
- package/dist/lib/__tests__/backupBundle.test.d.ts +1 -0
- package/dist/lib/__tests__/blockExport.test.d.ts +1 -0
- package/dist/lib/__tests__/blockModel.test.d.ts +1 -0
- package/dist/lib/__tests__/databaseFormula.test.d.ts +1 -0
- package/dist/lib/__tests__/databaseTypes.test.d.ts +1 -0
- package/dist/lib/__tests__/favorites.test.d.ts +1 -0
- package/dist/lib/__tests__/homePage.test.d.ts +1 -0
- package/dist/lib/__tests__/hud.test.d.ts +1 -0
- package/dist/lib/__tests__/icons.test.d.ts +1 -0
- package/dist/lib/__tests__/mixedContent.test.d.ts +1 -0
- package/dist/lib/__tests__/pageAppearance.test.d.ts +1 -0
- package/dist/lib/__tests__/pageIcon.test.d.ts +1 -0
- package/dist/lib/__tests__/pageLayout.test.d.ts +1 -0
- package/dist/lib/__tests__/pageSaveStatus.test.d.ts +1 -0
- package/dist/lib/__tests__/pageTheme.test.d.ts +1 -0
- package/dist/lib/__tests__/parentGrouping.test.d.ts +1 -0
- package/dist/lib/__tests__/pluginSdk.test.d.ts +1 -0
- package/dist/lib/__tests__/recents.test.d.ts +1 -0
- package/dist/lib/__tests__/relations.test.d.ts +1 -0
- package/dist/lib/__tests__/templates.test.d.ts +1 -0
- package/dist/lib/__tests__/textMerge.test.d.ts +1 -0
- package/dist/lib/__tests__/themes.test.d.ts +1 -0
- package/dist/lib/__tests__/treeMove.test.d.ts +1 -0
- package/dist/lib/aiBridge.d.ts +67 -0
- package/dist/lib/aiFeatures.d.ts +31 -0
- package/dist/lib/aiSettingsNav.d.ts +14 -0
- package/dist/lib/backupBundle.d.ts +23 -0
- package/dist/lib/bookFolderTransfer.d.ts +15 -0
- package/dist/lib/download.d.ts +10 -0
- package/dist/lib/editorChrome.d.ts +14 -0
- package/dist/lib/emoji.d.ts +10 -0
- package/dist/lib/emojiData.d.ts +21 -0
- package/dist/lib/emojiPicker.d.ts +31 -0
- package/dist/lib/favorites.d.ts +11 -0
- package/dist/lib/homePage.d.ts +53 -0
- package/dist/lib/hud.d.ts +70 -0
- package/dist/lib/iconRecents.d.ts +3 -0
- package/dist/lib/iconValue.d.ts +19 -0
- package/dist/lib/lucideIcons.d.ts +21 -0
- package/dist/lib/openDocs.d.ts +5 -0
- package/dist/lib/pageActions.d.ts +17 -0
- package/dist/lib/pageAppearance.d.ts +20 -0
- package/dist/lib/pageCover.d.ts +21 -0
- package/dist/lib/pageCustomise.d.ts +6 -0
- package/dist/lib/pageDocActions.d.ts +20 -0
- package/dist/lib/pageFont.d.ts +25 -0
- package/dist/lib/pageFullWidth.d.ts +10 -0
- package/dist/lib/pageIcon.d.ts +25 -0
- package/dist/lib/pageLinks.d.ts +41 -0
- package/dist/lib/pageSaveStatus.d.ts +14 -0
- package/dist/lib/pageTheme.d.ts +15 -0
- package/dist/lib/pageThemePresets.d.ts +23 -0
- package/dist/lib/recents.d.ts +9 -0
- package/dist/lib/reviewPane.d.ts +23 -0
- package/dist/lib/selection.d.ts +2 -0
- package/dist/lib/shortcuts.d.ts +79 -0
- package/dist/lib/sidebarStyles.d.ts +10 -0
- package/dist/lib/suggestBridge.d.ts +33 -0
- package/dist/lib/textMerge.d.ts +19 -0
- package/dist/lib/themes.d.ts +137 -0
- package/dist/lib/treeMove.d.ts +24 -0
- package/dist/lib/useModifierHeld.d.ts +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/lucideIcons-B6pmC-WQ.js +5003 -0
- package/dist/model-CBxw8JNb.js +734 -0
- package/dist/pageIcon-BWTy7hAh.js +32 -0
- package/dist/plugins/__tests__/host.test.d.ts +1 -0
- package/dist/plugins/__tests__/loader.test.d.ts +1 -0
- package/dist/plugins/__tests__/pagePlugin.test.d.ts +1 -0
- package/dist/plugins/api.d.ts +67 -0
- package/dist/plugins/commandRegistry.d.ts +15 -0
- package/dist/plugins/host.d.ts +32 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/loader.d.ts +19 -0
- package/dist/plugins/pagePlugin.d.ts +21 -0
- package/dist/providers/AccountProvider.d.ts +67 -0
- package/dist/providers/ConfirmProvider.d.ts +30 -0
- package/dist/providers/ForwardingProvider.d.ts +23 -0
- package/dist/providers/HudProvider.d.ts +9 -0
- package/dist/providers/I18nProvider.d.ts +23 -0
- package/dist/providers/NavigationProvider.d.ts +89 -0
- package/dist/providers/PlatformLibraryProvider.d.ts +107 -0
- package/dist/providers/PreferencesProvider.d.ts +47 -0
- package/dist/providers/ThemeProvider.d.ts +26 -0
- package/dist/providers/WorkspaceProvider.d.ts +40 -0
- package/dist/providers/__tests__/PreferencesProvider.test.d.ts +1 -0
- package/dist/providers/__tests__/extractToken.test.d.ts +1 -0
- package/dist/providers/__tests__/windowModel.test.d.ts +1 -0
- package/dist/providers/index.d.ts +10 -0
- package/dist/providers/windowModel.d.ts +69 -0
- package/dist/screens/BlockPageDocument.d.ts +4 -0
- package/dist/screens/ConnectedPageDocument.d.ts +14 -0
- package/dist/screens/DataflowView.d.ts +2 -0
- package/dist/screens/HomeScreen.d.ts +7 -0
- package/dist/screens/index.d.ts +3 -0
- package/dist/screens/pageChrome.d.ts +46 -0
- package/dist/style.css +3 -0
- package/dist/toHtml-BoPr8Ce4.js +394 -0
- package/dist/toPdf-DGtKQSRA.js +133 -0
- package/package.json +94 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { useSyncExternalStore as e } from "react";
|
|
2
|
+
import { ICON_PROPERTY_ID as t } from "@book.dev/sdk";
|
|
3
|
+
//#region src/lib/pageIcon.ts
|
|
4
|
+
var n = "📄", r = "🏠", i = /* @__PURE__ */ new Map(), a = /* @__PURE__ */ new Set(), o = () => a.forEach((e) => e()), s = (e) => (a.add(e), () => a.delete(e)), c = null;
|
|
5
|
+
function l(e) {
|
|
6
|
+
c = e;
|
|
7
|
+
}
|
|
8
|
+
var u = (e) => i.get(e) || null, d = (e) => e === "home" ? r : i.get(e) || "📄", f = (e, t) => {
|
|
9
|
+
let n = t || "";
|
|
10
|
+
i.get(e) !== n && (i.set(e, n), c?.(e, n || null), o());
|
|
11
|
+
}, p = (e) => `openbook.icon.${e}`;
|
|
12
|
+
function m(e) {
|
|
13
|
+
let t = !1;
|
|
14
|
+
for (let { id: n, icon: r } of e) {
|
|
15
|
+
if (!n) continue;
|
|
16
|
+
let e = r ?? "";
|
|
17
|
+
if (!e && typeof localStorage < "u") {
|
|
18
|
+
let e = localStorage.getItem(p(n));
|
|
19
|
+
if (e) {
|
|
20
|
+
localStorage.removeItem(p(n)), i.get(n) !== e && (i.set(n, e), t = !0), c?.(n, e);
|
|
21
|
+
continue;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
i.get(n) !== e && (i.set(n, e), t = !0);
|
|
25
|
+
}
|
|
26
|
+
t && o();
|
|
27
|
+
}
|
|
28
|
+
function h(t) {
|
|
29
|
+
return e(s, () => d(t), () => t === "home" ? r : n);
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { u as a, h as c, d as i, f as l, t as n, l as o, m as r, s, n as t };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { DataClient, PageMeta, StoredPage } from '@book.dev/sdk';
|
|
2
|
+
import { type CustomBlockDef } from '../blockeditor/registry';
|
|
3
|
+
/**
|
|
4
|
+
* The API handed to a plugin's `activate(api)` — the whole contract between
|
|
5
|
+
* a plugin and the app. Everything registered through it is tracked, so
|
|
6
|
+
* disabling or removing the plugin tears its contributions down cleanly.
|
|
7
|
+
*
|
|
8
|
+
* Plugins import this module as `@book.dev/plugin-sdk` (and React as
|
|
9
|
+
* `react`); both resolve to host instances, never bundled copies.
|
|
10
|
+
*/
|
|
11
|
+
export interface PluginBlockDef {
|
|
12
|
+
/** Block type, namespaced automatically as `<pluginId>/<type>`. */
|
|
13
|
+
type: string;
|
|
14
|
+
render: CustomBlockDef['render'];
|
|
15
|
+
slash?: CustomBlockDef['slash'];
|
|
16
|
+
}
|
|
17
|
+
export interface PluginCommandDef {
|
|
18
|
+
id: string;
|
|
19
|
+
title: string;
|
|
20
|
+
keywords?: string;
|
|
21
|
+
run: () => void;
|
|
22
|
+
}
|
|
23
|
+
export interface PluginApi {
|
|
24
|
+
/** The plugin's own manifest (id, name, version…). */
|
|
25
|
+
manifest: {
|
|
26
|
+
id: string;
|
|
27
|
+
name: string;
|
|
28
|
+
version: string;
|
|
29
|
+
};
|
|
30
|
+
/** Register a custom block (renders in documents; optional slash entry). */
|
|
31
|
+
blocks: {
|
|
32
|
+
register(def: PluginBlockDef): void;
|
|
33
|
+
};
|
|
34
|
+
/** Register a command-palette command. */
|
|
35
|
+
commands: {
|
|
36
|
+
register(def: PluginCommandDef): void;
|
|
37
|
+
};
|
|
38
|
+
/** Read and write workspace pages (integration surface). */
|
|
39
|
+
pages: {
|
|
40
|
+
list(): Promise<PageMeta[]>;
|
|
41
|
+
get(id: string): Promise<StoredPage | null>;
|
|
42
|
+
create(name: string, markdownish?: string): Promise<StoredPage>;
|
|
43
|
+
};
|
|
44
|
+
/** Plugin-scoped persistent key-value storage (per browser profile). */
|
|
45
|
+
storage: {
|
|
46
|
+
get<T = unknown>(key: string): T | undefined;
|
|
47
|
+
set(key: string, value: unknown): void;
|
|
48
|
+
};
|
|
49
|
+
/** Network access for integrations (plain fetch — same trust as live code). */
|
|
50
|
+
fetch: typeof fetch;
|
|
51
|
+
}
|
|
52
|
+
/** What `activate` may hand back (everything optional). */
|
|
53
|
+
export interface PluginActivationResult {
|
|
54
|
+
deactivate?: () => void;
|
|
55
|
+
}
|
|
56
|
+
export type PluginModule = {
|
|
57
|
+
default?: (api: PluginApi) => PluginActivationResult | void;
|
|
58
|
+
activate?: (api: PluginApi) => PluginActivationResult | void;
|
|
59
|
+
};
|
|
60
|
+
/** Build a plugin's API instance; `disposables` collects every teardown. */
|
|
61
|
+
export declare function buildPluginApi(manifest: {
|
|
62
|
+
id: string;
|
|
63
|
+
name: string;
|
|
64
|
+
version: string;
|
|
65
|
+
}, client: DataClient, disposables: Array<() => void>): PluginApi;
|
|
66
|
+
/** Host modules importable from plugin code. */
|
|
67
|
+
export declare const hostModulesFor: (api: PluginApi) => Record<string, unknown>;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Palette commands contributed by plugins. Same module-singleton pattern as
|
|
3
|
+
* the custom-block registry: registration works from any layer, and the
|
|
4
|
+
* palette re-reads on every change via subscription.
|
|
5
|
+
*/
|
|
6
|
+
export interface PluginCommand {
|
|
7
|
+
id: string;
|
|
8
|
+
title: string;
|
|
9
|
+
keywords: string;
|
|
10
|
+
run: () => void;
|
|
11
|
+
pluginId: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function registerPluginCommand(command: PluginCommand): () => void;
|
|
14
|
+
export declare const pluginCommands: () => PluginCommand[];
|
|
15
|
+
export declare const subscribePluginCommands: (cb: () => void) => (() => void);
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type DataClient, type StoredPlugin } from '@book.dev/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* The plugin host: loads the workspace's enabled plugins, activates each in
|
|
4
|
+
* isolation (one plugin's crash never takes down another, or the app), and
|
|
5
|
+
* tears contributions down on disable/remove. A module singleton — the same
|
|
6
|
+
* set of plugins serves every editor on the page.
|
|
7
|
+
*/
|
|
8
|
+
export interface PluginStatus {
|
|
9
|
+
plugin: StoredPlugin;
|
|
10
|
+
state: 'active' | 'disabled' | 'error';
|
|
11
|
+
error?: string;
|
|
12
|
+
/** The trusted registry that vouches for this exact content, if any. */
|
|
13
|
+
verifiedBy?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const pluginStatuses: () => PluginStatus[];
|
|
16
|
+
export declare const subscribePlugins: (cb: () => void) => (() => void);
|
|
17
|
+
/** First-party key + any registries the user has chosen to trust. */
|
|
18
|
+
export declare function trustedRegistryKeys(): Array<{
|
|
19
|
+
name: string;
|
|
20
|
+
publicKey: string;
|
|
21
|
+
}>;
|
|
22
|
+
/** Persist a user-trusted registry key (and re-verify on next sync). */
|
|
23
|
+
export declare function addTrustedRegistry(name: string, publicKey: string): void;
|
|
24
|
+
export declare function removeTrustedRegistry(publicKey: string): void;
|
|
25
|
+
/**
|
|
26
|
+
* Reconcile the running set against the server's list: activate newly
|
|
27
|
+
* enabled plugins, dispose disabled/removed ones, verify signatures against
|
|
28
|
+
* the user's trusted keys. Safe to call repeatedly (boot + after changes).
|
|
29
|
+
*/
|
|
30
|
+
export declare function syncPlugins(client: DataClient): Promise<PluginStatus[]>;
|
|
31
|
+
/** Dispose + re-activate one plugin (after an update/re-install). */
|
|
32
|
+
export declare function reloadPlugin(id: string, client: DataClient): Promise<PluginStatus[]>;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export { parsePluginZip, executePlugin } from './loader';
|
|
2
|
+
export { buildPluginApi, type PluginApi, type PluginBlockDef, type PluginCommandDef } from './api';
|
|
3
|
+
export { pluginCommands, subscribePluginCommands } from './commandRegistry';
|
|
4
|
+
export { syncPlugins, reloadPlugin, pluginStatuses, subscribePlugins, trustedRegistryKeys, addTrustedRegistry, removeTrustedRegistry, type PluginStatus } from './host';
|
|
5
|
+
export { pagePluginFiles, pageHasPluginManifest, pageToPluginZip, MANIFEST_FILE } from './pagePlugin';
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type PluginPackage } from '@book.dev/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* The plugin loader: turns a zip of TypeScript source into a running module.
|
|
4
|
+
*
|
|
5
|
+
* - {@link parsePluginZip} reads `openbook.json` + every source file out of
|
|
6
|
+
* the archive (and a `signature.json` when the registry shipped one).
|
|
7
|
+
* - {@link executePlugin} strips types with sucrase (fast, no typechecker)
|
|
8
|
+
* and links the files with a tiny in-memory CommonJS resolver, so plugins
|
|
9
|
+
* can be ordinary multi-file TypeScript programs. `react` and
|
|
10
|
+
* `@book.dev/plugin-sdk` resolve to host-provided modules; anything else
|
|
11
|
+
* must live inside the zip — plugins are self-contained by design.
|
|
12
|
+
*/
|
|
13
|
+
export declare function parsePluginZip(bytes: Uint8Array): PluginPackage;
|
|
14
|
+
/**
|
|
15
|
+
* Execute a plugin package and return its entry module's exports. Host
|
|
16
|
+
* modules (`react`, `@book.dev/plugin-sdk`) come from `hostModules`; every
|
|
17
|
+
* other import resolves inside the package.
|
|
18
|
+
*/
|
|
19
|
+
export declare function executePlugin(pkg: PluginPackage, hostModules: Record<string, unknown>): Record<string, unknown>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import * as Y from 'yjs';
|
|
2
|
+
/**
|
|
3
|
+
* A page can BE a plugin: every named, non-live code block is a file in the
|
|
4
|
+
* package — name a block `openbook.json` for the manifest, `src/index.ts`
|
|
5
|
+
* for the entry, and export the page as an installable zip. Live blocks'
|
|
6
|
+
* names are reactive outputs, not filenames, so they stay out.
|
|
7
|
+
*/
|
|
8
|
+
export declare const MANIFEST_FILE = "openbook.json";
|
|
9
|
+
/** Named, non-live code blocks in document order → path → content. */
|
|
10
|
+
export declare function pagePluginFiles(doc: Y.Doc): Map<string, string>;
|
|
11
|
+
/** Does this page carry a plugin manifest block? Gates the export menu item. */
|
|
12
|
+
export declare const pageHasPluginManifest: (doc: Y.Doc) => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Zip the page's plugin files — the same layout {@link parsePluginZip}
|
|
15
|
+
* installs, so export → install round-trips. Throws with a human-readable
|
|
16
|
+
* reason when the manifest is malformed or the entry file is missing.
|
|
17
|
+
*/
|
|
18
|
+
export declare function pageToPluginZip(doc: Y.Doc): {
|
|
19
|
+
filename: string;
|
|
20
|
+
bytes: Uint8Array;
|
|
21
|
+
};
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Signs the app in to account.book.pub via the deep-link flow and keeps the
|
|
4
|
+
* user's settings synced there (the account service stores settings only; the
|
|
5
|
+
* data server stays single-tenant and untouched).
|
|
6
|
+
*
|
|
7
|
+
* Sign-in: open `/api/connect` in the browser (desktop in the system browser,
|
|
8
|
+
* web in a popup); the account service runs OAuth, mints a one-shot device
|
|
9
|
+
* token, and redirects back — to the desktop's `openbook://auth-callback` deep
|
|
10
|
+
* link, or the web shell's `/account/callback` page, which both hand the token
|
|
11
|
+
* here. The token is then a bearer for `/api/settings`.
|
|
12
|
+
*
|
|
13
|
+
* Sync: pull on connect / app open (remote wins), then push the
|
|
14
|
+
* `{preferences, workspaces}` blob on local change (debounced, last-writer-wins).
|
|
15
|
+
*/
|
|
16
|
+
export type AccountStatus = 'disconnected' | 'connecting' | 'syncing' | 'connected' | 'error';
|
|
17
|
+
interface AccountContextValue {
|
|
18
|
+
status: AccountStatus;
|
|
19
|
+
connected: boolean;
|
|
20
|
+
/** The device bearer token, for same-app account API calls (e.g. forwarding's
|
|
21
|
+
* POST /api/sites). Null when disconnected. Treat as a secret. */
|
|
22
|
+
token: string | null;
|
|
23
|
+
/** The label this device registers under (shown in the account dashboard). */
|
|
24
|
+
deviceName: string;
|
|
25
|
+
/** ISO timestamp of the last successful server sync, or null. */
|
|
26
|
+
lastSyncedAt: string | null;
|
|
27
|
+
/** A human-readable error from the last failed action, or null. */
|
|
28
|
+
error: string | null;
|
|
29
|
+
/** The account service base URL (for an "open dashboard" link). */
|
|
30
|
+
accountUrl: string;
|
|
31
|
+
/** Start the deep-link sign-in flow. */
|
|
32
|
+
signIn: () => void;
|
|
33
|
+
/** Complete sign-in from a manually pasted code — the dev/fallback path for when
|
|
34
|
+
* the `openbook://` deep link can't fire (the user dismisses the "open app?"
|
|
35
|
+
* prompt and pastes the code instead). Accepts a bare token or the whole
|
|
36
|
+
* `openbook://auth-callback#token=…` URL. */
|
|
37
|
+
submitCode: (raw: string) => void;
|
|
38
|
+
/** Abandon a pending sign-in (returns to disconnected when not yet connected). */
|
|
39
|
+
cancel: () => void;
|
|
40
|
+
/** Forget the local token (does not revoke it server-side — do that in the dashboard). */
|
|
41
|
+
signOut: () => void;
|
|
42
|
+
/** Pull-then-push a reconciliation now. */
|
|
43
|
+
syncNow: () => void;
|
|
44
|
+
}
|
|
45
|
+
/** Cross-window handoff (web): the callback page hands the minted token to the
|
|
46
|
+
* running app over this BroadcastChannel (popup case) or localStorage key
|
|
47
|
+
* (same-tab fallback). Exported so the web `/account/callback` page reuses the
|
|
48
|
+
* exact contract. */
|
|
49
|
+
export declare const ACCOUNT_CHANNEL = "openbook.account";
|
|
50
|
+
export declare const ACCOUNT_HANDOFF_KEY = "openbook.account.handoff";
|
|
51
|
+
/**
|
|
52
|
+
* Deliver a token from a web callback page to the running app. A popup posts on
|
|
53
|
+
* the BroadcastChannel (the opener can't be relied on cross-origin); a same-tab
|
|
54
|
+
* fallback writes the localStorage key the app reads on its next load.
|
|
55
|
+
*/
|
|
56
|
+
export declare function handoffAccountToken(token: string, state: string, mode: 'broadcast' | 'storage'): void;
|
|
57
|
+
/**
|
|
58
|
+
* Pull a device token out of a manually pasted value, so the user can paste
|
|
59
|
+
* whatever they managed to copy: a bare token, the full
|
|
60
|
+
* `openbook://auth-callback#token=…&state=…` URL the browser tried to open, a
|
|
61
|
+
* web `…/account/callback#token=…` URL, or just a `#token=…` fragment. Returns
|
|
62
|
+
* the token, or null when nothing usable is found.
|
|
63
|
+
*/
|
|
64
|
+
export declare function extractToken(raw: string): string | null;
|
|
65
|
+
export declare const AccountProvider: React.FC<PropsWithChildren<unknown>>;
|
|
66
|
+
export declare const useAccount: () => AccountContextValue;
|
|
67
|
+
export {};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface ConfirmOptions {
|
|
3
|
+
/** Bold heading, e.g. "Move page to trash?". */
|
|
4
|
+
title: string;
|
|
5
|
+
/** Supporting line under the title. */
|
|
6
|
+
description?: string;
|
|
7
|
+
/** Confirm button label (default "Confirm"). */
|
|
8
|
+
confirmText?: string;
|
|
9
|
+
/** Cancel button label (default "Cancel"). */
|
|
10
|
+
cancelText?: string;
|
|
11
|
+
/** Render the confirm button in the destructive (red) style. */
|
|
12
|
+
destructive?: boolean;
|
|
13
|
+
/** Notice mode: a lone acknowledge button (for errors — there's nothing to cancel). */
|
|
14
|
+
hideCancel?: boolean;
|
|
15
|
+
}
|
|
16
|
+
type ConfirmFn = (options: ConfirmOptions) => Promise<boolean>;
|
|
17
|
+
/**
|
|
18
|
+
* Promise-based confirmation dialog: `const confirm = useConfirm()` then
|
|
19
|
+
* `if (!(await confirm({title: '…'}))) return;`. A drop-in for `window.confirm`
|
|
20
|
+
* that actually works in the desktop WKWebView shell, where the native
|
|
21
|
+
* `window.confirm` returns false without ever showing a dialog and so silently
|
|
22
|
+
* aborts the action. Renders one in-app Radix dialog shared by every caller;
|
|
23
|
+
* all controls are native `<button>`s so clicks fire in WKWebView.
|
|
24
|
+
*/
|
|
25
|
+
export declare function ConfirmProvider({ children }: {
|
|
26
|
+
children: React.ReactNode;
|
|
27
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
28
|
+
/** Access the promise-based confirm dialog. Throws outside a {@link ConfirmProvider}. */
|
|
29
|
+
export declare function useConfirm(): ConfirmFn;
|
|
30
|
+
export {};
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { type TunnelStatus } from '@book.dev/sdk';
|
|
3
|
+
/** Combined provisioning/tunnel status. `idle` = never started this session. */
|
|
4
|
+
export type ForwardingStatus = TunnelStatus | 'idle';
|
|
5
|
+
interface ForwardingContextValue {
|
|
6
|
+
/** The host can forward (desktop with keychain + IPC fetch). */
|
|
7
|
+
supported: boolean;
|
|
8
|
+
/** The user's on/off intent (persisted). */
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
/** Live tunnel status. */
|
|
11
|
+
status: ForwardingStatus;
|
|
12
|
+
/** The assigned `<prefix>.book.pub` host, once known. */
|
|
13
|
+
host: string | null;
|
|
14
|
+
busy: boolean;
|
|
15
|
+
error: string | null;
|
|
16
|
+
/** Turn forwarding on: claim the address (sign-in first if needed) + dial out. */
|
|
17
|
+
enable: () => Promise<void>;
|
|
18
|
+
/** Turn forwarding off: drop the tunnel but keep the site key (stable address). */
|
|
19
|
+
disable: () => void;
|
|
20
|
+
}
|
|
21
|
+
export declare const ForwardingProvider: React.FC<PropsWithChildren>;
|
|
22
|
+
export declare const useForwarding: () => ForwardingContextValue;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { HudProps } from '@/lib/hud';
|
|
3
|
+
export interface HudContext {
|
|
4
|
+
hud: HudProps;
|
|
5
|
+
setHud: React.Dispatch<HudProps | ((draft: HudProps) => HudProps)>;
|
|
6
|
+
}
|
|
7
|
+
export declare const HudContext: React.Context<HudContext>;
|
|
8
|
+
export declare const useHud: () => HudContext;
|
|
9
|
+
export declare const HudProvider: React.FC<PropsWithChildren<unknown>>;
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { LOCALES, type Locale, type TKey } from '@/i18n';
|
|
3
|
+
interface I18nContextValue {
|
|
4
|
+
locale: Locale;
|
|
5
|
+
setLocale: (locale: Locale) => void;
|
|
6
|
+
t: (key: TKey, vars?: Record<string, string | number>) => string;
|
|
7
|
+
locales: typeof LOCALES;
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Provides the current display locale + a reactive `t`. Persists the choice and
|
|
11
|
+
* keeps the module-level locale (used by non-React `t` callers) in sync so the
|
|
12
|
+
* whole app — React and not — renders in the same language this render.
|
|
13
|
+
*
|
|
14
|
+
* SSR note: the first render (server and the client's hydration pass) is always
|
|
15
|
+
* `'en'` so the two agree — reading localStorage/navigator during the initial
|
|
16
|
+
* render would make the client diverge from the server-rendered HTML and trip a
|
|
17
|
+
* hydration mismatch. The persisted/browser locale is adopted right after mount;
|
|
18
|
+
* a non-English user briefly sees English (one frame), the standard tradeoff for
|
|
19
|
+
* localStorage-backed i18n under SSR.
|
|
20
|
+
*/
|
|
21
|
+
export declare const I18nProvider: React.FC<React.PropsWithChildren<unknown>>;
|
|
22
|
+
export declare const useTranslation: () => I18nContextValue;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import { type PageMeta } from '@book.dev/sdk';
|
|
3
|
+
import { type NewViewTarget } from './PlatformLibraryProvider';
|
|
4
|
+
import type { Pane, PaneId } from './windowModel';
|
|
5
|
+
export type { Pane, PaneId, WindowState } from './windowModel';
|
|
6
|
+
export interface NavigationContextValue {
|
|
7
|
+
/** All top-level pages, most-recently-updated first (database rows excluded). */
|
|
8
|
+
pages: PageMeta[];
|
|
9
|
+
/** The page in the focused pane of this window. */
|
|
10
|
+
currentPageId: string | null;
|
|
11
|
+
/** The page in the PRIMARY (left) pane — what side panes (the assistant,
|
|
12
|
+
* review, dataflow) act on, regardless of which pane is focused. */
|
|
13
|
+
primaryPageId: string | null;
|
|
14
|
+
loading: boolean;
|
|
15
|
+
error: string | null;
|
|
16
|
+
/** Whether tabs live inside the window (a custom titlebar tab bar). */
|
|
17
|
+
inWindowTabs: boolean;
|
|
18
|
+
/** The window's tabs, each with the page it shows. */
|
|
19
|
+
tabs: {
|
|
20
|
+
id: string;
|
|
21
|
+
pageId: string;
|
|
22
|
+
}[];
|
|
23
|
+
/** The active tab's id. */
|
|
24
|
+
activeTabId: string;
|
|
25
|
+
/** Activate a tab. */
|
|
26
|
+
selectTab: (tabId: string) => void;
|
|
27
|
+
/** Close a tab (the window keeps at least one). */
|
|
28
|
+
closeTab: (tabId: string) => void;
|
|
29
|
+
/** The panes shown by the active tab (the primary, plus the secondary when split). */
|
|
30
|
+
panes: Pane[];
|
|
31
|
+
/** The focused pane id. */
|
|
32
|
+
focusedPaneId: PaneId;
|
|
33
|
+
/** Whether the active tab is currently split. */
|
|
34
|
+
splitOpen: boolean;
|
|
35
|
+
/** Mark a pane focused (e.g. on click). */
|
|
36
|
+
focusPane: (pane: PaneId) => void;
|
|
37
|
+
/** Open a page beside the current one in the split pane. */
|
|
38
|
+
openInSplit: (id: string) => void;
|
|
39
|
+
/** Close the split pane. */
|
|
40
|
+
closeSplit: () => void;
|
|
41
|
+
/** Close a pane (secondary collapses the split; primary promotes the secondary). */
|
|
42
|
+
closePane: (pane: PaneId) => void;
|
|
43
|
+
/** Open a page in a new tab or window (in-window tab + OS window on desktop, browser tab/window on web). */
|
|
44
|
+
openInNew: (id: string, target: NewViewTarget) => void;
|
|
45
|
+
/** Create a fresh blank page and open it in a new tab or window. */
|
|
46
|
+
newPageIn: (target: NewViewTarget) => Promise<void>;
|
|
47
|
+
/** Remove this window's view of a page (used when a row/subpage is deleted). */
|
|
48
|
+
closePage: (id: string) => void;
|
|
49
|
+
/** A display title for any page id, including open subpages not in `pages`. */
|
|
50
|
+
pageLabel: (id: string) => string;
|
|
51
|
+
/** Seed a known title for a page (e.g. a database row being opened). */
|
|
52
|
+
setPageHint: (id: string, name: string | null) => void;
|
|
53
|
+
/** Navigate the focused pane to a page. */
|
|
54
|
+
selectPage: (id: string) => void;
|
|
55
|
+
/** Navigate (and focus) a SPECIFIC pane, regardless of which is focused. All
|
|
56
|
+
* link / sidebar / breadcrumb navigation targets the primary pane; the side
|
|
57
|
+
* pane stays put as a reference and changes only via "open in split". */
|
|
58
|
+
selectPageInPane: (id: string, pane: PaneId) => void;
|
|
59
|
+
goBack: () => void;
|
|
60
|
+
goForward: () => void;
|
|
61
|
+
canGoBack: boolean;
|
|
62
|
+
canGoForward: boolean;
|
|
63
|
+
/** Create a new page (optionally named, optionally nested) and open it. Returns its id. */
|
|
64
|
+
createPage: (name?: string | null, parentId?: string | null) => Promise<string>;
|
|
65
|
+
/** Create a host page that contains a fresh database (optionally nested), and open it. */
|
|
66
|
+
createDatabasePage: (parentId?: string | null) => Promise<string>;
|
|
67
|
+
/**
|
|
68
|
+
* Create a child page nested under `parentId` without navigating to it (used
|
|
69
|
+
* by the inline subpage blocks). `kind: 'database'` also attaches a database.
|
|
70
|
+
* Returns the new page's id.
|
|
71
|
+
*/
|
|
72
|
+
createSubpage: (parentId: string, kind?: 'page' | 'database') => Promise<string>;
|
|
73
|
+
/** Duplicate a page (its content, name, and icon) as a sibling, then open it. */
|
|
74
|
+
duplicatePage: (id: string) => Promise<void>;
|
|
75
|
+
/** Delete a page; closes its panes and falls back if nothing remains open. */
|
|
76
|
+
deletePage: (id: string) => Promise<void>;
|
|
77
|
+
/** Rename a page (name only). */
|
|
78
|
+
renamePage: (id: string, name: string | null) => Promise<void>;
|
|
79
|
+
/**
|
|
80
|
+
* Reorder / re-nest a page in the sidebar tree: set its parent (`null` = top
|
|
81
|
+
* level) and the new ordered list of sibling ids under that parent (including
|
|
82
|
+
* this page). Drives drag-to-reorder and drag-to-nest.
|
|
83
|
+
*/
|
|
84
|
+
movePage: (id: string, parentId: string | null, orderedIds: string[]) => Promise<void>;
|
|
85
|
+
/** Re-list pages from the store. */
|
|
86
|
+
reload: () => Promise<PageMeta[]>;
|
|
87
|
+
}
|
|
88
|
+
export declare const useNavigation: () => NavigationContextValue;
|
|
89
|
+
export declare const NavigationProvider: React.FC<PropsWithChildren<unknown>>;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import React, { PropsWithChildren } from 'react';
|
|
2
|
+
import type { BookFolderFile, FetchLike, KeyStore, ServerControls } from '@book.dev/sdk';
|
|
3
|
+
/** Where to open a page: a new tab or a separate new window. */
|
|
4
|
+
export type NewViewTarget = 'tab' | 'window';
|
|
5
|
+
/**
|
|
6
|
+
* How the host handles new tabs/windows. The desktop sets `inWindow` so a "new
|
|
7
|
+
* tab" becomes an in-window tab (a custom tab bar in the titlebar) and supplies
|
|
8
|
+
* `openWindow` for a separate OS window. The web shell leaves this undefined, so
|
|
9
|
+
* the UI falls back to `window.open` — a real browser tab or a popup window.
|
|
10
|
+
*/
|
|
11
|
+
export interface TabsPlatform {
|
|
12
|
+
/** Tabs live inside the window (custom titlebar tab bar) rather than as OS tabs. */
|
|
13
|
+
inWindow?: boolean;
|
|
14
|
+
/** Open `pageId` in a separate OS window. */
|
|
15
|
+
openWindow: (pageId: string) => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The window-management buttons a frameless window must draw itself. The
|
|
19
|
+
* desktop supplies these on Windows/Linux (where the window has no native title
|
|
20
|
+
* bar); macOS keeps its native traffic lights, so it leaves this undefined and
|
|
21
|
+
* the UI draws no custom controls.
|
|
22
|
+
*/
|
|
23
|
+
export interface WindowControls {
|
|
24
|
+
minimize: () => void;
|
|
25
|
+
toggleMaximize: () => void;
|
|
26
|
+
close: () => void;
|
|
27
|
+
/**
|
|
28
|
+
* Observe the maximized state (to show maximize vs restore). Calls back with
|
|
29
|
+
* the current value immediately and on every change; returns an unsubscribe.
|
|
30
|
+
*/
|
|
31
|
+
watchMaximized?: (cb: (maximized: boolean) => void) => () => void;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* How the host completes account.book.pub's deep-link sign-in. The desktop sets
|
|
35
|
+
* a custom-scheme `redirectUri` (`openbook://auth-callback`), opens the browser
|
|
36
|
+
* itself, and delivers the minted token back through the OS deep-link
|
|
37
|
+
* (`onCallback`). The web shell leaves this undefined: it falls back to an
|
|
38
|
+
* `${origin}/account/callback` popup that hands the token back same-origin.
|
|
39
|
+
*/
|
|
40
|
+
export interface AccountPlatform {
|
|
41
|
+
/** The OAuth callback URI the account service redirects back to. Omit on web
|
|
42
|
+
* (the provider defaults to `${origin}/account/callback`). */
|
|
43
|
+
redirectUri?: string;
|
|
44
|
+
/** Open the sign-in URL in the system browser. Omit on web (defaults to a popup). */
|
|
45
|
+
openSignIn?: (url: string) => void;
|
|
46
|
+
/** Subscribe to deep-link callbacks carrying the minted token; returns an
|
|
47
|
+
* unsubscribe. Desktop only — web receives the token via its callback page. */
|
|
48
|
+
onCallback?: (cb: (params: {
|
|
49
|
+
token: string;
|
|
50
|
+
state: string;
|
|
51
|
+
}) => void) => () => void;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* How the host reads/writes an on-disk book folder (the human-readable
|
|
55
|
+
* `<book>/<page>.html` layout, lossless `openbook.space.json` sidecar). The
|
|
56
|
+
* desktop supplies a native dialog + filesystem implementation; the web shell
|
|
57
|
+
* leaves this undefined and the UI falls back to the File System Access API
|
|
58
|
+
* (with a zip download/upload fallback for browsers that lack it).
|
|
59
|
+
*/
|
|
60
|
+
export interface BookFolderPlatform {
|
|
61
|
+
/** Write an exported book folder to a host-chosen location. Resolves a summary
|
|
62
|
+
* (`location` to show the user, `count` of pages written), or `null` if the
|
|
63
|
+
* user cancelled. */
|
|
64
|
+
export(files: BookFolderFile[]): Promise<{
|
|
65
|
+
location: string;
|
|
66
|
+
count: number;
|
|
67
|
+
} | null>;
|
|
68
|
+
/** Read a host-chosen book folder back into files, or `null` if cancelled. */
|
|
69
|
+
import?(): Promise<BookFolderFile[] | null>;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* How the host persists the forwarding site identity. Forwarding to *.book.pub
|
|
73
|
+
* needs the Ed25519 device private key kept in the OS keychain, which only the
|
|
74
|
+
* native shell can reach — so the desktop supplies a keychain-backed
|
|
75
|
+
* {@link KeyStore} and the web shell leaves this undefined (forwarding is a
|
|
76
|
+
* desktop-only affordance; the web app *is* the cloud).
|
|
77
|
+
*/
|
|
78
|
+
export interface ForwardingPlatform {
|
|
79
|
+
keyStore: KeyStore;
|
|
80
|
+
/**
|
|
81
|
+
* The `fetch` the forwarding tunnel uses to serve inbound requests against the
|
|
82
|
+
* local data server. On the desktop this is the IPC transport, so forwarded
|
|
83
|
+
* traffic reaches the portless local server without opening a TCP port. Omit to
|
|
84
|
+
* fall back to a normal `fetch` against a real `localOrigin`.
|
|
85
|
+
*/
|
|
86
|
+
localFetch?: FetchLike;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Capabilities the host platform provides to the UI. The Tauri desktop app
|
|
90
|
+
* supplies `serverControls` (inspect/publish the local server), `bookFolder`
|
|
91
|
+
* (native folder export/import), `forwarding` (keychain for *.book.pub),
|
|
92
|
+
* `tabs` (in-window tabs), `windowControls` (frameless min/max/close on
|
|
93
|
+
* Windows/Linux), and `account` (deep-link sign-in); the web shell leaves these
|
|
94
|
+
* undefined and the UI falls back to browser behaviour.
|
|
95
|
+
*/
|
|
96
|
+
export interface PlatformLibrary {
|
|
97
|
+
serverControls?: ServerControls;
|
|
98
|
+
bookFolder?: BookFolderPlatform;
|
|
99
|
+
forwarding?: ForwardingPlatform;
|
|
100
|
+
tabs?: TabsPlatform;
|
|
101
|
+
windowControls?: WindowControls;
|
|
102
|
+
account?: AccountPlatform;
|
|
103
|
+
}
|
|
104
|
+
export declare const usePlatformLibrary: () => PlatformLibrary;
|
|
105
|
+
export declare const PlatformLibraryProvider: React.FC<PropsWithChildren<{
|
|
106
|
+
value?: PlatformLibrary;
|
|
107
|
+
}>>;
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { FeatureVisibility } from '@/lib/aiFeatures';
|
|
3
|
+
/** A user's identity within the app. Cosmetic today (local-first, no accounts). */
|
|
4
|
+
export interface ProfilePreferences {
|
|
5
|
+
name: string;
|
|
6
|
+
displayName: string;
|
|
7
|
+
/** Avatar emoji. Empty = derive a lettered (initials) avatar from the name. */
|
|
8
|
+
avatar: string;
|
|
9
|
+
/** Avatar image as a small data URL. Takes precedence over the emoji. */
|
|
10
|
+
avatarImage: string;
|
|
11
|
+
bio: string;
|
|
12
|
+
}
|
|
13
|
+
/** General behavior toggles that aren't layout (those live in the HUD). */
|
|
14
|
+
export interface GeneralPreferences {
|
|
15
|
+
/** Ask before moving a page to the trash. Default true (today's behavior). */
|
|
16
|
+
confirmOnTrash: boolean;
|
|
17
|
+
/** Spellcheck the editor while typing. */
|
|
18
|
+
spellcheck: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface Preferences {
|
|
21
|
+
profile: ProfilePreferences;
|
|
22
|
+
general: GeneralPreferences;
|
|
23
|
+
/** How AI entry points surface in menus, keyed by feature id. A missing entry
|
|
24
|
+
* defaults to 'recommended' (see lib/aiFeatures). */
|
|
25
|
+
features: Record<string, FeatureVisibility>;
|
|
26
|
+
}
|
|
27
|
+
export declare const DEFAULT_PREFERENCES: Preferences;
|
|
28
|
+
/** A nested partial — every key optional, recursively — for `update(patch)`. */
|
|
29
|
+
type DeepPartial<T> = {
|
|
30
|
+
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
|
|
31
|
+
};
|
|
32
|
+
interface PreferencesContextValue {
|
|
33
|
+
preferences: Preferences;
|
|
34
|
+
/** Shallow-merge a patch per section (one level of nesting), then persist. */
|
|
35
|
+
update: (patch: DeepPartial<Preferences>) => void;
|
|
36
|
+
}
|
|
37
|
+
export declare const PREFERENCES_STORAGE_KEY = "openbook.preferences";
|
|
38
|
+
/**
|
|
39
|
+
* Durable, local-only user preferences (profile + behavior toggles), persisted
|
|
40
|
+
* to localStorage. SSR-safe: the first render (server + the client's hydration
|
|
41
|
+
* pass) uses the defaults so the two agree, and the stored values are adopted in
|
|
42
|
+
* a post-mount effect — reading localStorage during the initial render would
|
|
43
|
+
* diverge from the server HTML and trip a hydration mismatch.
|
|
44
|
+
*/
|
|
45
|
+
export declare const PreferencesProvider: React.FC<React.PropsWithChildren<unknown>>;
|
|
46
|
+
export declare const usePreferences: () => PreferencesContextValue;
|
|
47
|
+
export {};
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { type AppearanceOptions, type Theme } from '@/lib/themes';
|
|
3
|
+
export type ColorScheme = 'light' | 'dark';
|
|
4
|
+
export type ColorMode = ColorScheme | 'system';
|
|
5
|
+
export type ThemeProviderProps = {
|
|
6
|
+
children: React.ReactNode;
|
|
7
|
+
defaultColorMode?: ColorMode;
|
|
8
|
+
storageKey?: string;
|
|
9
|
+
};
|
|
10
|
+
type ThemeProviderState = {
|
|
11
|
+
colorScheme: ColorScheme;
|
|
12
|
+
mode: ColorMode;
|
|
13
|
+
setMode: (theme: ColorMode) => void;
|
|
14
|
+
/** The full appearance choice (accent + tint + intensity + sidebar). */
|
|
15
|
+
appearance: AppearanceOptions;
|
|
16
|
+
/** Shallow-merge a patch into the appearance and persist it. */
|
|
17
|
+
setAppearance: (patch: Partial<AppearanceOptions>) => void;
|
|
18
|
+
/** The active named color theme (palette). Shorthand for `appearance.themeId`. */
|
|
19
|
+
themeId: string;
|
|
20
|
+
setThemeId: (id: string) => void;
|
|
21
|
+
/** All available color themes. */
|
|
22
|
+
themes: Theme[];
|
|
23
|
+
};
|
|
24
|
+
export declare function ThemeProvider({ children, defaultColorMode, storageKey, ...props }: ThemeProviderProps): import("react/jsx-runtime").JSX.Element;
|
|
25
|
+
export declare const useTheme: () => ThemeProviderState;
|
|
26
|
+
export {};
|