@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.
Files changed (305) hide show
  1. package/LICENSE +21 -0
  2. package/dist/EmojiGrid-xK5mPJPo.js +205 -0
  3. package/dist/blockeditor/BlockEditor.d.ts +68 -0
  4. package/dist/blockeditor/CodeBlockView.d.ts +19 -0
  5. package/dist/blockeditor/InlineToolbar.d.ts +18 -0
  6. package/dist/blockeditor/LinkPicker.d.ts +16 -0
  7. package/dist/blockeditor/MentionMenu.d.ts +14 -0
  8. package/dist/blockeditor/PresentBlocks.d.ts +21 -0
  9. package/dist/blockeditor/RichTextEditor.d.ts +29 -0
  10. package/dist/blockeditor/SlashMenu.d.ts +49 -0
  11. package/dist/blockeditor/TextBlockView.d.ts +9 -0
  12. package/dist/blockeditor/__tests__/LinkPicker.test.d.ts +1 -0
  13. package/dist/blockeditor/__tests__/SlashMenu.test.d.ts +1 -0
  14. package/dist/blockeditor/__tests__/aiApply.test.d.ts +1 -0
  15. package/dist/blockeditor/__tests__/groupLock.test.d.ts +1 -0
  16. package/dist/blockeditor/__tests__/highlight.test.d.ts +1 -0
  17. package/dist/blockeditor/__tests__/mergeUp.test.d.ts +1 -0
  18. package/dist/blockeditor/__tests__/present.test.d.ts +1 -0
  19. package/dist/blockeditor/aiBlocks.d.ts +9 -0
  20. package/dist/blockeditor/colors.d.ts +23 -0
  21. package/dist/blockeditor/exportBlocks.d.ts +25 -0
  22. package/dist/blockeditor/highlight.d.ts +25 -0
  23. package/dist/blockeditor/index.d.ts +8 -0
  24. package/dist/blockeditor/kit/KitFrame.d.ts +95 -0
  25. package/dist/blockeditor/kit/KitSettings.d.ts +18 -0
  26. package/dist/blockeditor/kit/OptionsEditor.d.ts +8 -0
  27. package/dist/blockeditor/kit/__tests__/chartMath.test.d.ts +1 -0
  28. package/dist/blockeditor/kit/__tests__/dataflow.test.d.ts +1 -0
  29. package/dist/blockeditor/kit/__tests__/exportKit.test.d.ts +1 -0
  30. package/dist/blockeditor/kit/__tests__/exportKit2.test.d.ts +1 -0
  31. package/dist/blockeditor/kit/__tests__/groupSync.test.d.ts +1 -0
  32. package/dist/blockeditor/kit/__tests__/inputs2Render.test.d.ts +1 -0
  33. package/dist/blockeditor/kit/__tests__/inputs2Scope.test.d.ts +1 -0
  34. package/dist/blockeditor/kit/__tests__/inputsRender.test.d.ts +1 -0
  35. package/dist/blockeditor/kit/__tests__/kitConfig.test.d.ts +1 -0
  36. package/dist/blockeditor/kit/__tests__/kitPanel.test.d.ts +1 -0
  37. package/dist/blockeditor/kit/__tests__/options.test.d.ts +1 -0
  38. package/dist/blockeditor/kit/__tests__/scope.test.d.ts +1 -0
  39. package/dist/blockeditor/kit/cards.d.ts +51 -0
  40. package/dist/blockeditor/kit/chartMath.d.ts +62 -0
  41. package/dist/blockeditor/kit/charts.d.ts +27 -0
  42. package/dist/blockeditor/kit/completion.d.ts +45 -0
  43. package/dist/blockeditor/kit/dataflow.d.ts +68 -0
  44. package/dist/blockeditor/kit/groupSync.d.ts +23 -0
  45. package/dist/blockeditor/kit/index.d.ts +11 -0
  46. package/dist/blockeditor/kit/inputs.d.ts +135 -0
  47. package/dist/blockeditor/kit/inputs2.d.ts +86 -0
  48. package/dist/blockeditor/kit/kitConfig.d.ts +5 -0
  49. package/dist/blockeditor/kit/kitPanel.d.ts +31 -0
  50. package/dist/blockeditor/kit/lock.d.ts +12 -0
  51. package/dist/blockeditor/kit/options.d.ts +60 -0
  52. package/dist/blockeditor/kit/progress.d.ts +20 -0
  53. package/dist/blockeditor/kit/scope.d.ts +100 -0
  54. package/dist/blockeditor/model.d.ts +236 -0
  55. package/dist/blockeditor/present.d.ts +18 -0
  56. package/dist/blockeditor/provider.d.ts +16 -0
  57. package/dist/blockeditor/reactiveBlocks.d.ts +2 -0
  58. package/dist/blockeditor/registry.d.ts +38 -0
  59. package/dist/blockeditor/richtext.d.ts +48 -0
  60. package/dist/blockeditor/useBlockEditor.d.ts +45 -0
  61. package/dist/components/AboutDialog.d.ts +9 -0
  62. package/dist/components/AgentPanel.d.ts +2 -0
  63. package/dist/components/AiBridgeHost.d.ts +14 -0
  64. package/dist/components/AiSearchDialog.d.ts +8 -0
  65. package/dist/components/AiSettings.d.ts +7 -0
  66. package/dist/components/AppearanceSettings.d.ts +3 -0
  67. package/dist/components/BackForwardCluster.d.ts +1 -0
  68. package/dist/components/BackupSettings.d.ts +2 -0
  69. package/dist/components/BreadcrumbCluster.d.ts +1 -0
  70. package/dist/components/ColorSchemeMenu.d.ts +1 -0
  71. package/dist/components/CommandMenu.d.ts +1 -0
  72. package/dist/components/CommandToggle.d.ts +3 -0
  73. package/dist/components/DocumentArea.d.ts +8 -0
  74. package/dist/components/Drawer.d.ts +7 -0
  75. package/dist/components/EmojiGrid.d.ts +16 -0
  76. package/dist/components/EmojiPickerHost.d.ts +8 -0
  77. package/dist/components/ExtensionsSettings.d.ts +7 -0
  78. package/dist/components/FavoritesNav.d.ts +8 -0
  79. package/dist/components/GeneralSettings.d.ts +2 -0
  80. package/dist/components/GlobalShortcuts.d.ts +9 -0
  81. package/dist/components/HomeButton.d.ts +2 -0
  82. package/dist/components/IconPicker.d.ts +17 -0
  83. package/dist/components/NavBar.d.ts +1 -0
  84. package/dist/components/NavContextMenu.d.ts +7 -0
  85. package/dist/components/PageActionsCluster.d.ts +9 -0
  86. package/dist/components/PageAppearanceHost.d.ts +9 -0
  87. package/dist/components/PageContextMenu.d.ts +17 -0
  88. package/dist/components/PageCover.d.ts +18 -0
  89. package/dist/components/PageHeaderControls.d.ts +13 -0
  90. package/dist/components/PageIcon.d.ts +16 -0
  91. package/dist/components/PageProperties.d.ts +53 -0
  92. package/dist/components/PluginBoot.d.ts +2 -0
  93. package/dist/components/PresentMode.d.ts +7 -0
  94. package/dist/components/ProfileAvatar.d.ts +17 -0
  95. package/dist/components/ProfileMenu.d.ts +6 -0
  96. package/dist/components/Settings.d.ts +7 -0
  97. package/dist/components/SettingsButton.d.ts +2 -0
  98. package/dist/components/SettingsPanel.d.ts +14 -0
  99. package/dist/components/SideNav.d.ts +1 -0
  100. package/dist/components/SideNavToggle.d.ts +3 -0
  101. package/dist/components/SidebarSections.d.ts +17 -0
  102. package/dist/components/SplitPane.d.ts +9 -0
  103. package/dist/components/TemplateGallery.d.ts +8 -0
  104. package/dist/components/TitlebarTabs.d.ts +10 -0
  105. package/dist/components/TrashDialog.d.ts +7 -0
  106. package/dist/components/WindowActionsCluster.d.ts +6 -0
  107. package/dist/components/WindowControls.d.ts +6 -0
  108. package/dist/components/WindowTitle.d.ts +7 -0
  109. package/dist/components/WorkspaceInfo.d.ts +6 -0
  110. package/dist/components/WorkspaceNavigationTree.d.ts +14 -0
  111. package/dist/components/WorkspaceSelectMenu.d.ts +10 -0
  112. package/dist/components/__tests__/AppearanceSettings.test.d.ts +1 -0
  113. package/dist/components/__tests__/PageIcon.test.d.ts +1 -0
  114. package/dist/components/__tests__/SettingsPanel.test.d.ts +1 -0
  115. package/dist/components/__tests__/buildTree.test.d.ts +1 -0
  116. package/dist/components/__tests__/profileAvatar.test.d.ts +1 -0
  117. package/dist/components/appearance/AppearanceControls.d.ts +33 -0
  118. package/dist/components/appearance/PageCustomiseBody.d.ts +29 -0
  119. package/dist/components/brand/OpenBookLogo.d.ts +11 -0
  120. package/dist/components/brand/index.d.ts +1 -0
  121. package/dist/components/database/DatabaseCard.d.ts +36 -0
  122. package/dist/components/database/DatabasePicker.d.ts +12 -0
  123. package/dist/components/database/DatabaseRowProperties.d.ts +13 -0
  124. package/dist/components/database/DatabaseView.d.ts +9 -0
  125. package/dist/components/database/InlineDatabaseBlock.d.ts +3 -0
  126. package/dist/components/database/__tests__/InlineDatabaseBlock.test.d.ts +1 -0
  127. package/dist/components/database/databaseCells.d.ts +57 -0
  128. package/dist/components/database/databaseCharts.d.ts +28 -0
  129. package/dist/components/database/databaseColors.d.ts +12 -0
  130. package/dist/components/database/databaseGraph.d.ts +16 -0
  131. package/dist/components/database/databaseLayouts.d.ts +84 -0
  132. package/dist/components/database/databaseMap.d.ts +21 -0
  133. package/dist/components/database/databaseMapLeaflet.d.ts +26 -0
  134. package/dist/components/database/databaseMenus.d.ts +97 -0
  135. package/dist/components/database/databaseTimeline.d.ts +27 -0
  136. package/dist/components/database/geocode.d.ts +24 -0
  137. package/dist/components/database/useDatabase.d.ts +129 -0
  138. package/dist/components/index.d.ts +12 -0
  139. package/dist/components/review/BlockReviewMarkers.d.ts +19 -0
  140. package/dist/components/review/CommentThread.d.ts +20 -0
  141. package/dist/components/review/ReviewPaneBody.d.ts +12 -0
  142. package/dist/components/review/SuggestHost.d.ts +13 -0
  143. package/dist/components/review/SuggestionCard.d.ts +21 -0
  144. package/dist/components/review/__tests__/review.test.d.ts +1 -0
  145. package/dist/components/review/useReview.d.ts +27 -0
  146. package/dist/components/settings/AccountSettings.d.ts +6 -0
  147. package/dist/components/settings/AdminSettings.d.ts +2 -0
  148. package/dist/components/settings/ConnectionSettings.d.ts +7 -0
  149. package/dist/components/settings/CustomisationSettings.d.ts +2 -0
  150. package/dist/components/settings/ProfileSettings.d.ts +2 -0
  151. package/dist/components/settings/primitives.d.ts +47 -0
  152. package/dist/components/settings/stubs.d.ts +8 -0
  153. package/dist/components/ui/__tests__/kbd.test.d.ts +1 -0
  154. package/dist/components/ui/__tests__/markdown.test.d.ts +1 -0
  155. package/dist/components/ui/__tests__/select.test.d.ts +1 -0
  156. package/dist/components/ui/badge.d.ts +9 -0
  157. package/dist/components/ui/button.d.ts +11 -0
  158. package/dist/components/ui/command.d.ts +86 -0
  159. package/dist/components/ui/context-menu.d.ts +24 -0
  160. package/dist/components/ui/dialog.d.ts +18 -0
  161. package/dist/components/ui/dropdown-menu.d.ts +27 -0
  162. package/dist/components/ui/icon-button.d.ts +16 -0
  163. package/dist/components/ui/input.d.ts +9 -0
  164. package/dist/components/ui/kbd.d.ts +31 -0
  165. package/dist/components/ui/label.d.ts +5 -0
  166. package/dist/components/ui/markdown.d.ts +19 -0
  167. package/dist/components/ui/navigation-menu.d.ts +12 -0
  168. package/dist/components/ui/popover.d.ts +6 -0
  169. package/dist/components/ui/scroll-area.d.ts +5 -0
  170. package/dist/components/ui/select.d.ts +42 -0
  171. package/dist/components/ui/skeleton.d.ts +6 -0
  172. package/dist/components/ui/switch.d.ts +4 -0
  173. package/dist/components/ui/tooltip.d.ts +7 -0
  174. package/dist/components/ui/tree.d.ts +37 -0
  175. package/dist/components/useAppCommands.d.ts +25 -0
  176. package/dist/data/DataProvider.d.ts +30 -0
  177. package/dist/data/index.d.ts +1 -0
  178. package/dist/databaseMapLeaflet-8LYcHcR6.js +87 -0
  179. package/dist/export/__tests__/chartNormalize.test.d.ts +1 -0
  180. package/dist/export/__tests__/export.test.d.ts +1 -0
  181. package/dist/export/__tests__/exportReactive.test.d.ts +1 -0
  182. package/dist/export/chartNormalize.d.ts +22 -0
  183. package/dist/export/chartSvg.d.ts +2 -0
  184. package/dist/export/documentModel.d.ts +136 -0
  185. package/dist/export/exportSite.d.ts +40 -0
  186. package/dist/export/format.d.ts +2 -0
  187. package/dist/export/kitChart.d.ts +21 -0
  188. package/dist/export/toHtml.d.ts +25 -0
  189. package/dist/export/toMarkdown.d.ts +7 -0
  190. package/dist/export/toPdf.d.ts +14 -0
  191. package/dist/exportBlocks-33D7P_8Q.js +987 -0
  192. package/dist/exportSite-DlRm4u7W.js +50 -0
  193. package/dist/format-CLQoRoYP.js +1646 -0
  194. package/dist/i18n/__tests__/i18n.test.d.ts +1 -0
  195. package/dist/i18n/index.d.ts +24 -0
  196. package/dist/i18n/messages/de.d.ts +2 -0
  197. package/dist/i18n/messages/en.d.ts +977 -0
  198. package/dist/i18n/messages/ja.d.ts +2 -0
  199. package/dist/i18n/messages/zh.d.ts +2 -0
  200. package/dist/index.d.ts +11 -0
  201. package/dist/index.js +20915 -0
  202. package/dist/layouts/DefaultLayout.d.ts +4 -0
  203. package/dist/layouts/index.d.ts +1 -0
  204. package/dist/lib/__tests__/accountClient.test.d.ts +1 -0
  205. package/dist/lib/__tests__/backlinks.test.d.ts +1 -0
  206. package/dist/lib/__tests__/backupBundle.test.d.ts +1 -0
  207. package/dist/lib/__tests__/blockExport.test.d.ts +1 -0
  208. package/dist/lib/__tests__/blockModel.test.d.ts +1 -0
  209. package/dist/lib/__tests__/databaseFormula.test.d.ts +1 -0
  210. package/dist/lib/__tests__/databaseTypes.test.d.ts +1 -0
  211. package/dist/lib/__tests__/favorites.test.d.ts +1 -0
  212. package/dist/lib/__tests__/homePage.test.d.ts +1 -0
  213. package/dist/lib/__tests__/hud.test.d.ts +1 -0
  214. package/dist/lib/__tests__/icons.test.d.ts +1 -0
  215. package/dist/lib/__tests__/mixedContent.test.d.ts +1 -0
  216. package/dist/lib/__tests__/pageAppearance.test.d.ts +1 -0
  217. package/dist/lib/__tests__/pageIcon.test.d.ts +1 -0
  218. package/dist/lib/__tests__/pageLayout.test.d.ts +1 -0
  219. package/dist/lib/__tests__/pageSaveStatus.test.d.ts +1 -0
  220. package/dist/lib/__tests__/pageTheme.test.d.ts +1 -0
  221. package/dist/lib/__tests__/parentGrouping.test.d.ts +1 -0
  222. package/dist/lib/__tests__/pluginSdk.test.d.ts +1 -0
  223. package/dist/lib/__tests__/recents.test.d.ts +1 -0
  224. package/dist/lib/__tests__/relations.test.d.ts +1 -0
  225. package/dist/lib/__tests__/templates.test.d.ts +1 -0
  226. package/dist/lib/__tests__/textMerge.test.d.ts +1 -0
  227. package/dist/lib/__tests__/themes.test.d.ts +1 -0
  228. package/dist/lib/__tests__/treeMove.test.d.ts +1 -0
  229. package/dist/lib/aiBridge.d.ts +67 -0
  230. package/dist/lib/aiFeatures.d.ts +31 -0
  231. package/dist/lib/aiSettingsNav.d.ts +14 -0
  232. package/dist/lib/backupBundle.d.ts +23 -0
  233. package/dist/lib/bookFolderTransfer.d.ts +15 -0
  234. package/dist/lib/download.d.ts +10 -0
  235. package/dist/lib/editorChrome.d.ts +14 -0
  236. package/dist/lib/emoji.d.ts +10 -0
  237. package/dist/lib/emojiData.d.ts +21 -0
  238. package/dist/lib/emojiPicker.d.ts +31 -0
  239. package/dist/lib/favorites.d.ts +11 -0
  240. package/dist/lib/homePage.d.ts +53 -0
  241. package/dist/lib/hud.d.ts +70 -0
  242. package/dist/lib/iconRecents.d.ts +3 -0
  243. package/dist/lib/iconValue.d.ts +19 -0
  244. package/dist/lib/lucideIcons.d.ts +21 -0
  245. package/dist/lib/openDocs.d.ts +5 -0
  246. package/dist/lib/pageActions.d.ts +17 -0
  247. package/dist/lib/pageAppearance.d.ts +20 -0
  248. package/dist/lib/pageCover.d.ts +21 -0
  249. package/dist/lib/pageCustomise.d.ts +6 -0
  250. package/dist/lib/pageDocActions.d.ts +20 -0
  251. package/dist/lib/pageFont.d.ts +25 -0
  252. package/dist/lib/pageFullWidth.d.ts +10 -0
  253. package/dist/lib/pageIcon.d.ts +25 -0
  254. package/dist/lib/pageLinks.d.ts +41 -0
  255. package/dist/lib/pageSaveStatus.d.ts +14 -0
  256. package/dist/lib/pageTheme.d.ts +15 -0
  257. package/dist/lib/pageThemePresets.d.ts +23 -0
  258. package/dist/lib/recents.d.ts +9 -0
  259. package/dist/lib/reviewPane.d.ts +23 -0
  260. package/dist/lib/selection.d.ts +2 -0
  261. package/dist/lib/shortcuts.d.ts +79 -0
  262. package/dist/lib/sidebarStyles.d.ts +10 -0
  263. package/dist/lib/suggestBridge.d.ts +33 -0
  264. package/dist/lib/textMerge.d.ts +19 -0
  265. package/dist/lib/themes.d.ts +137 -0
  266. package/dist/lib/treeMove.d.ts +24 -0
  267. package/dist/lib/useModifierHeld.d.ts +1 -0
  268. package/dist/lib/utils.d.ts +2 -0
  269. package/dist/lucideIcons-B6pmC-WQ.js +5003 -0
  270. package/dist/model-CBxw8JNb.js +734 -0
  271. package/dist/pageIcon-BWTy7hAh.js +32 -0
  272. package/dist/plugins/__tests__/host.test.d.ts +1 -0
  273. package/dist/plugins/__tests__/loader.test.d.ts +1 -0
  274. package/dist/plugins/__tests__/pagePlugin.test.d.ts +1 -0
  275. package/dist/plugins/api.d.ts +67 -0
  276. package/dist/plugins/commandRegistry.d.ts +15 -0
  277. package/dist/plugins/host.d.ts +32 -0
  278. package/dist/plugins/index.d.ts +5 -0
  279. package/dist/plugins/loader.d.ts +19 -0
  280. package/dist/plugins/pagePlugin.d.ts +21 -0
  281. package/dist/providers/AccountProvider.d.ts +67 -0
  282. package/dist/providers/ConfirmProvider.d.ts +30 -0
  283. package/dist/providers/ForwardingProvider.d.ts +23 -0
  284. package/dist/providers/HudProvider.d.ts +9 -0
  285. package/dist/providers/I18nProvider.d.ts +23 -0
  286. package/dist/providers/NavigationProvider.d.ts +89 -0
  287. package/dist/providers/PlatformLibraryProvider.d.ts +107 -0
  288. package/dist/providers/PreferencesProvider.d.ts +47 -0
  289. package/dist/providers/ThemeProvider.d.ts +26 -0
  290. package/dist/providers/WorkspaceProvider.d.ts +40 -0
  291. package/dist/providers/__tests__/PreferencesProvider.test.d.ts +1 -0
  292. package/dist/providers/__tests__/extractToken.test.d.ts +1 -0
  293. package/dist/providers/__tests__/windowModel.test.d.ts +1 -0
  294. package/dist/providers/index.d.ts +10 -0
  295. package/dist/providers/windowModel.d.ts +69 -0
  296. package/dist/screens/BlockPageDocument.d.ts +4 -0
  297. package/dist/screens/ConnectedPageDocument.d.ts +14 -0
  298. package/dist/screens/DataflowView.d.ts +2 -0
  299. package/dist/screens/HomeScreen.d.ts +7 -0
  300. package/dist/screens/index.d.ts +3 -0
  301. package/dist/screens/pageChrome.d.ts +46 -0
  302. package/dist/style.css +3 -0
  303. package/dist/toHtml-BoPr8Ce4.js +394 -0
  304. package/dist/toPdf-DGtKQSRA.js +133 -0
  305. package/package.json +94 -0
@@ -0,0 +1,5003 @@
1
+ import { a as e, i as t, l as n, r } from "./pageIcon-BWTy7hAh.js";
2
+ import * as i from "react";
3
+ import a, { createContext as o, useCallback as s, useContext as c, useEffect as l, useMemo as u, useRef as d, useState as f } from "react";
4
+ import { jsx as p, jsxs as m } from "react/jsx-runtime";
5
+ import { clsx as h } from "clsx";
6
+ import { twMerge as g } from "tailwind-merge";
7
+ import { Cross2Icon as _ } from "@radix-ui/react-icons";
8
+ import { AccountClient as v, AccountError as ee, ForwardingClient as te, defaultDatabaseSchema as y, emptyPageSnapshot as b, getServerUrlOverride as x, resolveAccountUrl as ne, setServerUrlOverride as S } from "@book.dev/sdk";
9
+ import * as C from "@radix-ui/react-dialog";
10
+ import { Slot as w } from "@radix-ui/react-slot";
11
+ import { cva as T } from "class-variance-authority";
12
+ import { useImmer as E } from "use-immer";
13
+ import { Activity as D, AlarmClock as O, AlertTriangle as k, Anchor as A, Aperture as j, Archive as M, Award as N, Backpack as P, BarChart3 as re, Battery as F, Beaker as I, Bell as L, Bike as R, Binary as ie, Bird as ae, Book as z, BookOpen as oe, Bookmark as se, Box as ce, Brain as le, Briefcase as ue, Brush as de, Bug as fe, Building2 as B, Bus as pe, Cake as me, Calculator as he, Calendar as ge, Camera as _e, Car as ve, Carrot as ye, Check as be, CheckCircle2 as xe, ChefHat as Se, Cherry as Ce, Circle as we, Clapperboard as Te, Clipboard as Ee, Clock as De, Cloud as Oe, Code2 as ke, Coffee as Ae, Cog as je, Coins as Me, Compass as Ne, Cpu as Pe, CreditCard as Fe, Crown as Ie, Database as Le, Diamond as Re, Dog as ze, DollarSign as Be, Download as Ve, Droplet as He, Dumbbell as Ue, Egg as We, Eye as Ge, Feather as Ke, FileText as qe, Film as Je, Filter as Ye, Flag as Xe, Flame as Ze, FlaskConical as Qe, Flower2 as $e, Folder as et, Footprints as tt, Gamepad2 as nt, Gauge as rt, Gem as it, Gift as at, GitBranch as ot, Globe as st, GraduationCap as ct, Grid3x3 as lt, Hammer as ut, Hand as dt, Hash as ft, Headphones as pt, Heart as mt, HelpCircle as ht, Home as gt, Image as _t, Inbox as vt, Infinity as yt, Info as bt, Key as xt, Keyboard as St, Lamp as Ct, Laptop as wt, Layers as Tt, Layout as Et, Leaf as Dt, Library as Ot, Lightbulb as kt, Link as At, List as jt, Lock as Mt, Mail as Nt, Map as Pt, MapPin as Ft, Megaphone as It, MessageCircle as Lt, MessageSquare as Rt, Mic as zt, Monitor as Bt, Moon as Vt, Mountain as Ht, Mouse as Ut, Music as Wt, Navigation as Gt, Newspaper as Kt, Package as qt, Palette as Jt, PanelLeft as Yt, Paperclip as Xt, PartyPopper as Zt, PenTool as Qt, Pencil as $t, Phone as en, PieChart as tn, PiggyBank as nn, Pin as rn, Plane as an, Play as on, Plug as sn, Plus as cn, Puzzle as ln, Rabbit as un, Radio as dn, Rocket as fn, Ruler as pn, Save as mn, Scale as hn, Scissors as gn, Search as _n, Send as vn, Settings as yn, Share2 as bn, Shield as xn, ShoppingBag as Sn, ShoppingCart as Cn, Smile as wn, Snowflake as Tn, Sparkles as En, Speaker as Dn, Sprout as On, Star as kn, Sticker as An, Sun as jn, Sword as Mn, Table as Nn, Tag as Pn, Target as Fn, Tent as In, Terminal as Ln, ThumbsUp as Rn, Ticket as zn, Timer as Bn, ToggleLeft as Vn, Trash2 as Hn, TreePine as Un, TrendingUp as Wn, Trophy as Gn, Truck as Kn, Tv as qn, Umbrella as Jn, User as Yn, Users as Xn, Utensils as Zn, Video as Qn, Wallet as $n, Wand2 as er, Watch as tr, Waves as nr, Wifi as rr, Wind as ir, Wrench as ar, Zap as or } from "lucide-react";
14
+ //#region src/lib/utils.ts
15
+ function V(...e) {
16
+ return g(h(e));
17
+ }
18
+ //#endregion
19
+ //#region src/providers/PlatformLibraryProvider.tsx
20
+ var sr = o({}), cr = () => c(sr), lr = ({ value: e = {}, children: t }) => /* @__PURE__ */ p(sr.Provider, {
21
+ value: e,
22
+ children: t
23
+ }), H = {
24
+ profile: {
25
+ name: "",
26
+ displayName: "",
27
+ avatar: "",
28
+ avatarImage: "",
29
+ bio: ""
30
+ },
31
+ general: {
32
+ confirmOnTrash: !0,
33
+ spellcheck: !0
34
+ },
35
+ features: {}
36
+ }, ur = o(null), dr = "openbook.preferences";
37
+ function fr(e) {
38
+ return {
39
+ profile: {
40
+ ...H.profile,
41
+ ...e?.profile
42
+ },
43
+ general: {
44
+ ...H.general,
45
+ ...e?.general
46
+ },
47
+ features: {
48
+ ...H.features,
49
+ ...e?.features
50
+ }
51
+ };
52
+ }
53
+ function pr() {
54
+ if (typeof window > "u") return H;
55
+ try {
56
+ let e = localStorage.getItem(dr);
57
+ return e ? fr(JSON.parse(e)) : H;
58
+ } catch {
59
+ return H;
60
+ }
61
+ }
62
+ var mr = ({ children: e }) => {
63
+ let [t, n] = f(H);
64
+ l(() => {
65
+ let e = pr();
66
+ e !== H && n(e);
67
+ }, []);
68
+ let r = s((e) => {
69
+ n((t) => {
70
+ let n = {
71
+ profile: {
72
+ ...t.profile,
73
+ ...e.profile
74
+ },
75
+ general: {
76
+ ...t.general,
77
+ ...e.general
78
+ },
79
+ features: {
80
+ ...t.features,
81
+ ...e.features
82
+ }
83
+ };
84
+ try {
85
+ localStorage.setItem(dr, JSON.stringify(n));
86
+ } catch {}
87
+ return n;
88
+ });
89
+ }, []), i = u(() => ({
90
+ preferences: t,
91
+ update: r
92
+ }), [t, r]);
93
+ return /* @__PURE__ */ p(ur.Provider, {
94
+ value: i,
95
+ children: e
96
+ });
97
+ }, hr = () => {
98
+ let e = c(ur);
99
+ if (!e) throw Error("usePreferences must be used within a <PreferencesProvider>");
100
+ return e;
101
+ }, gr = "openbook.workspaces", U = {
102
+ id: "local",
103
+ icon: "🏡",
104
+ name: "My Workspace",
105
+ serverUrl: null
106
+ }, _r = (e, t) => (e ?? null) === (t ?? null), vr = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID() : `ws-${Math.random().toString(36).slice(2)}`, yr = (e) => {
107
+ if (!e) return "This device";
108
+ try {
109
+ return new URL(e).host || e;
110
+ } catch {
111
+ return e;
112
+ }
113
+ }, br = () => {
114
+ if (typeof localStorage > "u") return [U];
115
+ let e = [U];
116
+ try {
117
+ let t = localStorage.getItem(gr), n = t ? JSON.parse(t) : null;
118
+ Array.isArray(n) && n.length > 0 && (e = n);
119
+ } catch {}
120
+ e.some((e) => e.serverUrl === null) || (e = [U, ...e]);
121
+ let t = x();
122
+ return t && !e.some((e) => _r(e.serverUrl, t)) && (e = [...e, {
123
+ id: vr(),
124
+ icon: "🌐",
125
+ name: yr(t),
126
+ serverUrl: t
127
+ }]), e;
128
+ }, W = (e) => {
129
+ typeof localStorage > "u" || localStorage.setItem(gr, JSON.stringify(e));
130
+ }, xr = (e) => {
131
+ let t = x();
132
+ return (e.find((e) => _r(e.serverUrl, t)) ?? e[0]).id;
133
+ }, Sr = (e) => {
134
+ if (e === null) return !0;
135
+ if (typeof e != "string") return !1;
136
+ try {
137
+ let { protocol: t } = new URL(e);
138
+ return t === "http:" || t === "https:";
139
+ } catch {
140
+ return !1;
141
+ }
142
+ }, Cr = (e) => !!e && typeof e == "object" && typeof e.id == "string" && typeof e.name == "string" && Sr(e.serverUrl), wr = o({
143
+ workspaces: [U],
144
+ workspace: U,
145
+ selectWorkspace: () => void 0,
146
+ addWorkspace: () => U,
147
+ removeWorkspace: () => void 0,
148
+ updateWorkspace: () => void 0,
149
+ replaceWorkspaces: () => void 0
150
+ }), Tr = () => c(wr), Er = ({ children: e }) => {
151
+ let [t, n] = f([U]), [r, i] = f(U.id);
152
+ l(() => {
153
+ let e = br();
154
+ n(e), i(xr(e)), W(e);
155
+ }, []);
156
+ let a = u(() => t.find((e) => e.id === r) ?? t[0] ?? U, [t, r]), o = s((e) => {
157
+ let n = t.find((t) => t.id === e);
158
+ if (n) {
159
+ if (_r(n.serverUrl, x())) {
160
+ i(e);
161
+ return;
162
+ }
163
+ S(n.serverUrl), typeof window < "u" && window.location.reload();
164
+ }
165
+ }, [t]), c = s((e) => {
166
+ let t = e.serverUrl?.trim(), r = {
167
+ id: vr(),
168
+ icon: e.icon?.trim() || "📓",
169
+ name: e.name.trim() || yr(t || null),
170
+ serverUrl: t && t.length > 0 ? t : null
171
+ };
172
+ return n((e) => {
173
+ let t = [...e, r];
174
+ return W(t), t;
175
+ }), r;
176
+ }, []), d = s((e) => {
177
+ n((t) => {
178
+ if (t.length <= 1 || e === r) return t;
179
+ let n = t.filter((t) => t.id !== e);
180
+ return W(n), n;
181
+ });
182
+ }, [r]), m = s((e, t) => {
183
+ n((n) => {
184
+ let r = n.map((n) => n.id === e ? {
185
+ ...n,
186
+ ...t
187
+ } : n);
188
+ return W(r), r;
189
+ });
190
+ }, []), h = s((e) => {
191
+ let t = (Array.isArray(e) ? e : []).filter(Cr);
192
+ t.some((e) => e.serverUrl === null) || (t = [U, ...t]);
193
+ let r = x();
194
+ r && !t.some((e) => _r(e.serverUrl, r)) && (t = [...t, {
195
+ id: vr(),
196
+ icon: "🌐",
197
+ name: yr(r),
198
+ serverUrl: r
199
+ }]), n(t), i(xr(t)), W(t);
200
+ }, []), g = u(() => ({
201
+ workspaces: t,
202
+ workspace: a,
203
+ selectWorkspace: o,
204
+ addWorkspace: c,
205
+ removeWorkspace: d,
206
+ updateWorkspace: m,
207
+ replaceWorkspaces: h
208
+ }), [
209
+ t,
210
+ a,
211
+ o,
212
+ c,
213
+ d,
214
+ m,
215
+ h
216
+ ]);
217
+ return /* @__PURE__ */ p(wr.Provider, {
218
+ value: g,
219
+ children: e
220
+ });
221
+ }, Dr = o(null), G = "openbook.account", Or = "openbook.deviceId", kr = "openbook.account", Ar = "openbook.account.handoff";
222
+ function jr(e, t, n) {
223
+ let r = {
224
+ type: "openbook-account-token",
225
+ token: e,
226
+ state: t
227
+ };
228
+ if (n === "broadcast") try {
229
+ let e = new BroadcastChannel(kr);
230
+ e.postMessage(r), e.close();
231
+ } catch {}
232
+ try {
233
+ n === "storage" && localStorage.setItem(Ar, JSON.stringify(r));
234
+ } catch {}
235
+ }
236
+ function Mr(e) {
237
+ let t = (e ?? "").trim();
238
+ if (!t) return null;
239
+ let n = t.match(/[#?&]token=([^&\s#]+)/) ?? t.match(/^token=([^&\s#]+)/);
240
+ if (n) try {
241
+ return decodeURIComponent(n[1]);
242
+ } catch {
243
+ return n[1];
244
+ }
245
+ return /\s/.test(t) || t.includes("://") ? null : t;
246
+ }
247
+ var Nr = () => typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID().replace(/-/g, "") : Math.random().toString(36).slice(2) + Math.random().toString(36).slice(2);
248
+ function Pr() {
249
+ if (typeof localStorage > "u") return "web";
250
+ let e = localStorage.getItem(Or);
251
+ return e || (e = Nr().slice(0, 12), localStorage.setItem(Or, e)), e;
252
+ }
253
+ function Fr() {
254
+ if (typeof localStorage > "u") return null;
255
+ try {
256
+ let e = localStorage.getItem(G);
257
+ if (!e) return null;
258
+ let t = JSON.parse(e);
259
+ return t && typeof t.token == "string" && t.token ? t : null;
260
+ } catch {
261
+ return null;
262
+ }
263
+ }
264
+ var Ir = "openbook.account.pending", Lr = 600 * 1e3;
265
+ function Rr(e) {
266
+ try {
267
+ sessionStorage.setItem(Ir, JSON.stringify({
268
+ state: e,
269
+ at: Date.now()
270
+ }));
271
+ } catch {}
272
+ }
273
+ function zr() {
274
+ try {
275
+ let e = sessionStorage.getItem(Ir);
276
+ if (!e) return null;
277
+ let t = JSON.parse(e);
278
+ if (typeof t.state == "string" && typeof t.at == "number" && Date.now() - t.at < Lr) return t.state;
279
+ } catch {}
280
+ return null;
281
+ }
282
+ function Br() {
283
+ try {
284
+ sessionStorage.removeItem(Ir);
285
+ } catch {}
286
+ }
287
+ var Vr = ({ children: e }) => {
288
+ let { account: t } = cr(), { preferences: n, update: r } = hr(), { workspaces: i, replaceWorkspaces: a } = Tr(), [o, c] = f("disconnected"), [m, h] = f(null), [g, _] = f(null), [te, y] = f(null), b = u(() => new v(), []), x = u(() => ne(), []), S = u(() => `OpenBook ${t?.redirectUri?.startsWith("openbook:") ? "Desktop" : "Web"} · ${Pr()}`, [t]), C = d(null), w = d(null), T = d({
289
+ preferences: n,
290
+ workspaces: i
291
+ });
292
+ T.current = {
293
+ preferences: n,
294
+ workspaces: i
295
+ };
296
+ let E = s(() => ({
297
+ preferences: T.current.preferences,
298
+ workspaces: T.current.workspaces
299
+ }), []), D = s((e, t) => {
300
+ let n = {
301
+ token: e,
302
+ connectedAt: Date.now(),
303
+ lastServerUpdatedAt: t
304
+ };
305
+ try {
306
+ localStorage.setItem(G, JSON.stringify(n));
307
+ } catch {}
308
+ h(e), _(t);
309
+ }, []), O = s((e) => {
310
+ e.preferences && typeof e.preferences == "object" && r(e.preferences), Array.isArray(e.workspaces) && a(e.workspaces);
311
+ }, [r, a]), k = s(async (e) => {
312
+ c("syncing"), y(null);
313
+ try {
314
+ let { settings: t, updatedAt: n } = await b.getSettings(e);
315
+ if (n === null || !t.preferences && !t.workspaces) {
316
+ let t = E(), n = await b.putSettings(e, t);
317
+ w.current = JSON.stringify(t), D(e, n.updatedAt);
318
+ } else O(t), w.current = JSON.stringify(t), D(e, n);
319
+ c("connected");
320
+ } catch (t) {
321
+ if (t instanceof ee && t.status === 401) {
322
+ try {
323
+ localStorage.removeItem(G);
324
+ } catch {}
325
+ h(null), c("error"), y("That sign-in was rejected. Please try again.");
326
+ } else c(e ? "error" : "disconnected"), y("Could not reach account.book.pub. Check your connection.");
327
+ }
328
+ }, [
329
+ b,
330
+ E,
331
+ O,
332
+ D
333
+ ]), A = s((e, t) => {
334
+ let n = C.current ?? zr();
335
+ !e || !n || !t || t !== n || (C.current = null, Br(), k(e));
336
+ }, [k]);
337
+ l(() => {
338
+ if (t?.onCallback) return t.onCallback(({ token: e, state: t }) => A(e, t));
339
+ if (typeof window > "u") return;
340
+ let e = (e) => {
341
+ let t = e;
342
+ t?.type === "openbook-account-token" && typeof t.token == "string" && A(t.token, t.state ?? "");
343
+ }, n = typeof BroadcastChannel < "u" ? new BroadcastChannel(kr) : null;
344
+ n?.addEventListener("message", (t) => e(t.data));
345
+ let r = (t) => {
346
+ if (t.key === "openbook.account.handoff" && t.newValue) try {
347
+ e(JSON.parse(t.newValue));
348
+ } catch {}
349
+ };
350
+ window.addEventListener("storage", r);
351
+ try {
352
+ let t = localStorage.getItem(Ar);
353
+ t && (localStorage.removeItem(Ar), e(JSON.parse(t)));
354
+ } catch {}
355
+ return () => {
356
+ n?.close(), window.removeEventListener("storage", r);
357
+ };
358
+ }, [t, A]);
359
+ let j = d(k);
360
+ j.current = k, l(() => {
361
+ let e = Fr();
362
+ e && (h(e.token), _(e.lastServerUpdatedAt), j.current(e.token));
363
+ }, []), l(() => {
364
+ if (!m) return;
365
+ let e = {
366
+ preferences: n,
367
+ workspaces: i
368
+ }, t = JSON.stringify(e);
369
+ if (t === w.current) return;
370
+ let r = setTimeout(() => {
371
+ c("syncing"), b.putSettings(m, e).then((e) => {
372
+ w.current = t, _(e.updatedAt), c("connected"), y(null);
373
+ let n = Fr();
374
+ if (n) try {
375
+ localStorage.setItem(G, JSON.stringify({
376
+ ...n,
377
+ lastServerUpdatedAt: e.updatedAt
378
+ }));
379
+ } catch {}
380
+ }).catch(() => {
381
+ c("error"), y("Sync failed — will retry on the next change.");
382
+ });
383
+ }, 1200);
384
+ return () => clearTimeout(r);
385
+ }, [
386
+ m,
387
+ n,
388
+ i,
389
+ b
390
+ ]);
391
+ let M = s(() => {
392
+ let e = Nr();
393
+ C.current = e, Rr(e), c("connecting"), y(null);
394
+ let n = t?.redirectUri ?? (typeof window < "u" ? `${window.location.origin}/account/callback` : ""), r = b.connectUrl({
395
+ redirectUri: n,
396
+ state: e,
397
+ name: S
398
+ });
399
+ t?.openSignIn ? t.openSignIn(r) : typeof window < "u" && (window.open(r, "openbook-signin", "width=520,height=720") || (window.location.href = r));
400
+ }, [
401
+ b,
402
+ S,
403
+ t
404
+ ]), N = s((e) => {
405
+ let t = Mr(e);
406
+ if (!t) {
407
+ c((e) => m ? e : "error"), y("That doesn’t look like a valid code. Paste the code (or the whole openbook:// link) from the browser.");
408
+ return;
409
+ }
410
+ C.current = null, Br(), c("connecting"), y(null), k(t);
411
+ }, [k, m]), P = s(() => {
412
+ C.current = null, Br(), c((e) => m ? e : "disconnected"), y(null);
413
+ }, [m]), re = s(() => {
414
+ try {
415
+ localStorage.removeItem(G);
416
+ } catch {}
417
+ C.current = null, Br(), w.current = null, h(null), _(null), y(null), c("disconnected");
418
+ }, []), F = s(() => {
419
+ m && k(m);
420
+ }, [m, k]), I = u(() => ({
421
+ status: o,
422
+ connected: !!m && (o === "connected" || o === "syncing"),
423
+ token: m,
424
+ deviceName: S,
425
+ lastSyncedAt: g,
426
+ error: te,
427
+ accountUrl: x,
428
+ signIn: M,
429
+ submitCode: N,
430
+ cancel: P,
431
+ signOut: re,
432
+ syncNow: F
433
+ }), [
434
+ o,
435
+ m,
436
+ S,
437
+ g,
438
+ te,
439
+ x,
440
+ M,
441
+ N,
442
+ P,
443
+ re,
444
+ F
445
+ ]);
446
+ return /* @__PURE__ */ p(Dr.Provider, {
447
+ value: I,
448
+ children: e
449
+ });
450
+ }, Hr = () => {
451
+ let e = c(Dr);
452
+ if (!e) throw Error("useAccount must be used within an <AccountProvider>");
453
+ return e;
454
+ }, Ur = C.Root, Wr = C.Trigger, Gr = C.Portal, Kr = i.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ p(C.Overlay, {
455
+ ref: n,
456
+ className: V("fixed inset-0 z-50 bg-background/80 backdrop-blur-[var(--overlay-blur)] data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", e),
457
+ ...t
458
+ }));
459
+ Kr.displayName = C.Overlay.displayName;
460
+ var qr = i.forwardRef(({ className: e, children: t, ...n }, r) => /* @__PURE__ */ m(Gr, { children: [/* @__PURE__ */ p(Kr, {}), /* @__PURE__ */ p("div", {
461
+ className: "fixed inset-0 z-50 flex items-center justify-center p-4",
462
+ children: /* @__PURE__ */ m(C.Content, {
463
+ ref: r,
464
+ className: V("relative grid w-full max-w-lg gap-4 border bg-background p-6 shadow-overlay duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 sm:rounded-lg", e),
465
+ ...n,
466
+ children: [t, /* @__PURE__ */ m(C.Close, {
467
+ className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-hover data-[state=open]:text-muted-foreground",
468
+ children: [/* @__PURE__ */ p(_, { className: "h-4 w-4" }), /* @__PURE__ */ p("span", {
469
+ className: "sr-only",
470
+ children: "Close"
471
+ })]
472
+ })]
473
+ })
474
+ })] }));
475
+ qr.displayName = C.Content.displayName;
476
+ var Jr = ({ className: e, ...t }) => /* @__PURE__ */ p("div", {
477
+ className: V("flex flex-col space-y-1.5 text-center sm:text-left", e),
478
+ ...t
479
+ });
480
+ Jr.displayName = "DialogHeader";
481
+ var Yr = ({ className: e, ...t }) => /* @__PURE__ */ p("div", {
482
+ className: V("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", e),
483
+ ...t
484
+ });
485
+ Yr.displayName = "DialogFooter";
486
+ var Xr = i.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ p(C.Title, {
487
+ ref: n,
488
+ className: V("text-lg font-semibold leading-none tracking-tight", e),
489
+ ...t
490
+ }));
491
+ Xr.displayName = C.Title.displayName;
492
+ var Zr = i.forwardRef(({ className: e, ...t }, n) => /* @__PURE__ */ p(C.Description, {
493
+ ref: n,
494
+ className: V("text-sm text-muted-foreground", e),
495
+ ...t
496
+ }));
497
+ Zr.displayName = C.Description.displayName;
498
+ //#endregion
499
+ //#region src/components/ui/button.tsx
500
+ var Qr = T("inline-flex items-center justify-center rounded-md text-sm font-medium transition-[color,background-color,border-color,box-shadow,transform] active:scale-[0.97] focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:pointer-events-none disabled:opacity-50 disabled:active:scale-100", {
501
+ variants: {
502
+ variant: {
503
+ default: "bg-primary text-primary-foreground shadow-sm hover:bg-primary/90",
504
+ destructive: "bg-destructive text-destructive-foreground shadow-xs hover:bg-destructive/90",
505
+ outline: "border border-input bg-transparent shadow-xs hover:bg-hover hover:text-accent-foreground",
506
+ secondary: "bg-secondary text-secondary-foreground shadow-xs hover:bg-secondary/80",
507
+ ghost: "hover:bg-hover hover:text-accent-foreground",
508
+ link: "text-primary underline-offset-4 hover:underline"
509
+ },
510
+ size: {
511
+ default: "h-9 px-4 py-2",
512
+ sm: "h-8 rounded-md px-3 text-xs",
513
+ lg: "h-10 rounded-md px-8",
514
+ icon: "h-9 w-9"
515
+ }
516
+ },
517
+ defaultVariants: {
518
+ variant: "default",
519
+ size: "default"
520
+ }
521
+ }), $r = i.forwardRef(({ className: e, variant: t, size: n, asChild: r = !1, ...i }, a) => /* @__PURE__ */ p(r ? w : "button", {
522
+ className: V(Qr({
523
+ variant: t,
524
+ size: n,
525
+ className: e
526
+ })),
527
+ ref: a,
528
+ ...i
529
+ }));
530
+ $r.displayName = "Button";
531
+ //#endregion
532
+ //#region src/providers/ConfirmProvider.tsx
533
+ var ei = o(null);
534
+ function ti({ children: e }) {
535
+ let [t, n] = f(null), r = d(null), i = s((e) => {
536
+ r.current?.(e), r.current = null, n(null);
537
+ }, []), a = s((e) => (r.current?.(!1), new Promise((t) => {
538
+ r.current = t, n(e);
539
+ })), []), o = s((e) => {
540
+ e || i(!1);
541
+ }, [i]);
542
+ return /* @__PURE__ */ m(ei.Provider, {
543
+ value: a,
544
+ children: [e, /* @__PURE__ */ p(Ur, {
545
+ open: t !== null,
546
+ onOpenChange: o,
547
+ children: t && /* @__PURE__ */ m(qr, {
548
+ className: "sm:max-w-[420px]",
549
+ children: [/* @__PURE__ */ m(Jr, { children: [/* @__PURE__ */ p(Xr, { children: t.title }), t.description && /* @__PURE__ */ p(Zr, { children: t.description })] }), /* @__PURE__ */ m(Yr, { children: [!t.hideCancel && /* @__PURE__ */ p($r, {
550
+ variant: "outline",
551
+ onClick: () => i(!1),
552
+ children: t.cancelText ?? "Cancel"
553
+ }), /* @__PURE__ */ p($r, {
554
+ variant: t.destructive ? "destructive" : "default",
555
+ onClick: () => i(!0),
556
+ children: t.confirmText ?? "Confirm"
557
+ })] })]
558
+ })
559
+ })]
560
+ });
561
+ }
562
+ function ni() {
563
+ let e = c(ei);
564
+ if (!e) throw Error("useConfirm must be used within a <ConfirmProvider>");
565
+ return e;
566
+ }
567
+ //#endregion
568
+ //#region src/providers/ForwardingProvider.tsx
569
+ var ri = "openbook.forwarding.enabled", ii = o({
570
+ supported: !1,
571
+ enabled: !1,
572
+ status: "idle",
573
+ host: null,
574
+ busy: !1,
575
+ error: null,
576
+ enable: async () => void 0,
577
+ disable: () => void 0
578
+ }), ai = () => typeof localStorage < "u" && localStorage.getItem(ri) === "1", oi = (e) => {
579
+ typeof localStorage < "u" && localStorage.setItem(ri, e ? "1" : "0");
580
+ }, si = ({ children: e }) => {
581
+ let { forwarding: t } = cr(), { connected: n, token: r, accountUrl: i, signIn: a } = Hr(), o = !!t, c = d(null), [m, h] = f(() => ai()), [g, _] = f("idle"), [v, ee] = f(null), [y, b] = f(!1), [x, ne] = f(null);
582
+ l(() => {
583
+ t && t.keyStore.load().then((e) => e && ee(e.host)).catch(() => void 0);
584
+ }, [t]);
585
+ let S = s(async () => {
586
+ if (!(!t || !r || c.current)) {
587
+ b(!0), ne(null);
588
+ try {
589
+ let e = new te({
590
+ accountUrl: i,
591
+ authToken: r,
592
+ keyStore: t.keyStore,
593
+ localOrigin: "",
594
+ localFetchImpl: t.localFetch,
595
+ onStatus: _
596
+ });
597
+ c.current = e;
598
+ let { host: n } = await e.start();
599
+ ee(n);
600
+ } catch (e) {
601
+ c.current = null, _("offline"), ne(e instanceof Error ? e.message : String(e));
602
+ } finally {
603
+ b(!1);
604
+ }
605
+ }
606
+ }, [
607
+ t,
608
+ r,
609
+ i
610
+ ]);
611
+ l(() => {
612
+ o && m && n && r && !c.current && S();
613
+ }, [
614
+ o,
615
+ m,
616
+ n,
617
+ r,
618
+ S
619
+ ]), l(() => () => c.current?.stop(), []);
620
+ let C = s(async () => {
621
+ if (!n || !r) {
622
+ a();
623
+ return;
624
+ }
625
+ h(!0), oi(!0), await S();
626
+ }, [
627
+ n,
628
+ r,
629
+ a,
630
+ S
631
+ ]), w = s(() => {
632
+ c.current?.stop(), c.current = null, _("offline"), h(!1), oi(!1);
633
+ }, []), T = u(() => ({
634
+ supported: o,
635
+ enabled: m,
636
+ status: g,
637
+ host: v,
638
+ busy: y,
639
+ error: x,
640
+ enable: C,
641
+ disable: w
642
+ }), [
643
+ o,
644
+ m,
645
+ g,
646
+ v,
647
+ y,
648
+ x,
649
+ C,
650
+ w
651
+ ]);
652
+ return /* @__PURE__ */ p(ii.Provider, {
653
+ value: T,
654
+ children: e
655
+ });
656
+ }, ci = () => c(ii), li = [
657
+ {
658
+ id: "preferences",
659
+ tabs: [
660
+ "general",
661
+ "appearance",
662
+ "customisation"
663
+ ]
664
+ },
665
+ {
666
+ id: "account",
667
+ tabs: [
668
+ "profile",
669
+ "signup",
670
+ "signin",
671
+ "support"
672
+ ]
673
+ },
674
+ {
675
+ id: "workspace",
676
+ tabs: [
677
+ "connection",
678
+ "integrations",
679
+ "extensions",
680
+ "ai",
681
+ "admin"
682
+ ]
683
+ }
684
+ ], ui = li.flatMap((e) => e.tabs), di = li[0].tabs[0], fi = (e) => typeof e == "string" && ui.includes(e), pi = {
685
+ server: "connection",
686
+ backup: "admin"
687
+ }, mi = (e) => fi(e) ? e : typeof e == "string" && e in pi ? pi[e] : di, K = {
688
+ commandPalette: { open: !1 },
689
+ settings: {
690
+ open: !1,
691
+ mode: "modal",
692
+ tab: di
693
+ },
694
+ present: {
695
+ open: !1,
696
+ mode: "fullscreen",
697
+ pageId: null
698
+ },
699
+ sideNav: {
700
+ open: !0,
701
+ docked: !0
702
+ },
703
+ trash: { open: !1 },
704
+ templates: { open: !1 },
705
+ ai: { open: !1 },
706
+ agent: { open: !1 }
707
+ }, hi = () => {
708
+ if (typeof window > "u" || localStorage.getItem("hud") === null) return K;
709
+ let e = JSON.parse(localStorage.getItem("hud") ?? "{}"), t = {
710
+ ...K.settings,
711
+ ...e.settings
712
+ };
713
+ return {
714
+ commandPalette: {
715
+ ...K.commandPalette,
716
+ ...e.commandPalette
717
+ },
718
+ settings: {
719
+ ...t,
720
+ tab: mi(t.tab)
721
+ },
722
+ sideNav: {
723
+ ...K.sideNav,
724
+ ...e.sideNav
725
+ },
726
+ trash: { open: !1 },
727
+ templates: { open: !1 },
728
+ ai: { open: !1 },
729
+ agent: { open: !1 },
730
+ present: { ...K.present }
731
+ };
732
+ }, gi = (e) => {
733
+ let t = {
734
+ ...e,
735
+ settings: {
736
+ ...e.settings,
737
+ open: !1
738
+ },
739
+ trash: { open: !1 },
740
+ templates: { open: !1 },
741
+ ai: { open: !1 },
742
+ agent: { open: !1 },
743
+ present: { ...K.present }
744
+ };
745
+ localStorage.setItem("hud", JSON.stringify(t));
746
+ }, _i = o({
747
+ hud: K,
748
+ setHud: () => !1
749
+ }), vi = () => c(_i), yi = ({ children: e }) => {
750
+ let [t, n] = E(hi), r = a.useRef(typeof window < "u" && localStorage.getItem("hud") !== null);
751
+ a.useEffect(() => {
752
+ gi(t);
753
+ }, [t]), a.useEffect(() => {
754
+ !r.current && window.innerWidth < 768 && n((e) => (e.sideNav.open = !1, e.sideNav.docked = !1, e));
755
+ }, [n]);
756
+ let i = a.useCallback((e) => {
757
+ t.sideNav.docked || (e.clientX > 320 || e.clientX <= 1 ? n((e) => (e.sideNav.open = !1, e)) : e.clientX < 16 && n((e) => (e.sideNav.open = !0, e)));
758
+ }, [
759
+ t,
760
+ t.sideNav,
761
+ n
762
+ ]);
763
+ a.useEffect(() => (document.addEventListener("mousemove", i), () => document.removeEventListener("mousemove", i)), [i]);
764
+ let o = {
765
+ hud: t,
766
+ setHud: n
767
+ };
768
+ return /* @__PURE__ */ p(_i.Provider, {
769
+ value: o,
770
+ children: e
771
+ });
772
+ }, bi = {
773
+ common: {
774
+ cancel: "Cancel",
775
+ close: "Close",
776
+ delete: "Delete",
777
+ save: "Save",
778
+ add: "Add",
779
+ remove: "Remove",
780
+ untitled: "Untitled",
781
+ settings: "Settings"
782
+ },
783
+ settings: {
784
+ title: "Settings",
785
+ comingSoon: "These settings are coming soon.",
786
+ fullscreen: "Full screen",
787
+ exitFullscreen: "Exit full screen",
788
+ enterFullscreen: "Enter full screen",
789
+ closeSettings: "Close settings",
790
+ section: {
791
+ preferences: "Preferences",
792
+ account: "Account",
793
+ workspace: "Workspace"
794
+ },
795
+ tab: {
796
+ general: "General",
797
+ profile: "Profile",
798
+ appearance: "Appearance",
799
+ customisation: "Customisation",
800
+ signup: "Sign up",
801
+ signin: "Sign-in & email",
802
+ support: "Support OpenBook",
803
+ connection: "Connection",
804
+ integrations: "Integrations",
805
+ extensions: "Extensions",
806
+ ai: "AI",
807
+ admin: "Admin"
808
+ }
809
+ },
810
+ appearance: {
811
+ title: "Appearance",
812
+ colorMode: "Color mode",
813
+ light: "Light",
814
+ dark: "Dark",
815
+ system: "System",
816
+ colorScheme: "Color scheme",
817
+ colorTheme: "Accent color",
818
+ colorThemeHint: "The accent threads through buttons, links, the sidebar, and the logo.",
819
+ accentGray: "Gray",
820
+ accentBold: "Bold",
821
+ accentPastel: "Pastel",
822
+ accentNeutral: "Neutral",
823
+ interfaceIntensity: "Interface",
824
+ interfaceIntensityHint: "How saturated the neutral gray surfaces read.",
825
+ neutralWarm: "Warm",
826
+ neutralCool: "Cool",
827
+ neutralNeutral: "Neutral",
828
+ controlIntensity: "Control intensity",
829
+ controlIntensityHint: "How strongly buttons and rows shade on hover and when selected.",
830
+ blurOverlays: "Blur behind overlays",
831
+ blurOverlaysHint: "Blur the page when a dialog or search opens.",
832
+ levelOff: "Off",
833
+ levelSubtle: "Subtle",
834
+ levelMedium: "Medium",
835
+ levelStrong: "Strong",
836
+ levelSoft: "Soft",
837
+ levelVivid: "Vivid",
838
+ pageTheme: "Page theme",
839
+ pageThemeHint: "Override the accent and style for this page only.",
840
+ presets: "Page theme",
841
+ presetsHint: "A coordinated look — control colour, font, background, and cover in one tap.",
842
+ preset: {
843
+ clean: "Clean",
844
+ editorial: "Editorial",
845
+ notebook: "Notebook",
846
+ technical: "Technical",
847
+ vibrant: "Vibrant",
848
+ calm: "Calm"
849
+ },
850
+ controlColor: "Control colour",
851
+ controlColorHint: "The accent for buttons, links, and selection.",
852
+ matchApp: "Match app",
853
+ pageCustomiseSubtitle: "Appearance & typefaces for this page",
854
+ pageCustomiseEmpty: "Open a page to customise it here.",
855
+ cover: "Cover",
856
+ coverHint: "A banner image or gradient above the title.",
857
+ background: "Background",
858
+ backgroundHint: "Tint the page canvas.",
859
+ fontBody: "Body font",
860
+ fontBodyHint: "The primary typeface, used for paragraphs.",
861
+ fontHeading: "Heading font",
862
+ fontHeadingHint: "The secondary typeface, used for the title and headings.",
863
+ fontSans: "Sans",
864
+ fontSerif: "Serif",
865
+ fontMono: "Mono",
866
+ fontCustom: "Custom",
867
+ fontCustomPlaceholder: "e.g. \"Inter\", system-ui"
868
+ },
869
+ theme: {
870
+ default: "Default",
871
+ sandstone: "Sandstone",
872
+ slate: "Slate",
873
+ ocean: "Ocean",
874
+ forest: "Forest",
875
+ violet: "Violet",
876
+ sunset: "Sunset",
877
+ rose: "Rose",
878
+ teal: "Teal",
879
+ amber: "Amber",
880
+ graphite: "Graphite",
881
+ "pastel-sky": "Sky",
882
+ "pastel-mint": "Mint",
883
+ "pastel-lavender": "Lavender",
884
+ "pastel-rose": "Blush",
885
+ "pastel-peach": "Peach",
886
+ "pastel-butter": "Butter"
887
+ },
888
+ nav: {
889
+ pages: "Pages",
890
+ newPage: "New page",
891
+ newDatabase: "New database",
892
+ back: "Back",
893
+ forward: "Forward",
894
+ goBack: "Go back",
895
+ goForward: "Go forward",
896
+ toggleSidebar: "Toggle sidebar",
897
+ trash: "Trash",
898
+ more: "More actions",
899
+ favorites: "Favorites",
900
+ recents: "Recents",
901
+ suggested: "Suggested",
902
+ home: "Home",
903
+ templates: "Templates"
904
+ },
905
+ tabs: {
906
+ new: "New tab",
907
+ close: "Close tab"
908
+ },
909
+ menu: {
910
+ openTab: "Open in new tab",
911
+ openWindow: "Open in new window",
912
+ openSplit: "Open in split view",
913
+ favorite: "Add to favorites",
914
+ unfavorite: "Remove from favorites",
915
+ rename: "Rename",
916
+ copyLink: "Copy link",
917
+ duplicate: "Duplicate",
918
+ addSubpage: "Add subpage",
919
+ addDatabase: "Add database",
920
+ moveToTrash: "Move to trash",
921
+ viewOptions: "View options",
922
+ options: "Menu",
923
+ fullWidth: "Full width",
924
+ favourite: "Favourite",
925
+ sectionPage: "Page",
926
+ block: {
927
+ sectionBlock: "Block",
928
+ moveUp: "Move up",
929
+ moveDown: "Move down",
930
+ duplicate: "Duplicate",
931
+ deleteBlock: "Delete block",
932
+ linkToPage: "Link to page"
933
+ }
934
+ },
935
+ command: {
936
+ title: "Command palette",
937
+ placeholder: "Search pages or run a command…",
938
+ noResults: "No results found.",
939
+ search: "Search",
940
+ pages: "Pages",
941
+ noPages: "No pages yet",
942
+ actions: "Actions",
943
+ groupFavorites: "Favorites",
944
+ groupRecent: "Recent",
945
+ groupCreate: "Create",
946
+ groupView: "View",
947
+ groupNavigation: "Navigation",
948
+ groupApp: "App",
949
+ favorite: "Add to favorites",
950
+ unfavorite: "Remove from favorites",
951
+ createPage: "Create new page",
952
+ newDatabase: "New database",
953
+ insertSample: "Insert sample document",
954
+ newFromTemplate: "New from template",
955
+ aiSearch: "Search notes with AI",
956
+ askAssistant: "Ask the assistant",
957
+ openSettings: "Open settings",
958
+ openTrash: "Open trash",
959
+ toggleSidebar: "Toggle sidebar",
960
+ toggleFullWidth: "Toggle full width",
961
+ themeToLight: "Switch to light mode",
962
+ themeToDark: "Switch to dark mode",
963
+ splitView: "Split view",
964
+ closeSplit: "Close split view",
965
+ goBack: "Go back",
966
+ goForward: "Go forward",
967
+ current: "current"
968
+ },
969
+ page: {
970
+ saving: "Saving…",
971
+ saved: "Saved",
972
+ saveFailed: "Couldn’t save",
973
+ actions: "Page actions",
974
+ delete: "Delete page",
975
+ titleLabel: "Page title",
976
+ changeIcon: "Change page icon",
977
+ addCover: "Add cover",
978
+ coverChoose: "Choose a cover",
979
+ coverChange: "Change cover",
980
+ coverReposition: "Reposition",
981
+ coverDone: "Save position",
982
+ coverRemove: "Remove",
983
+ coverDragHint: "Drag to reposition",
984
+ coverImageUrl: "Image URL",
985
+ coverApply: "Apply",
986
+ editorPlaceholder: "Write something, or press Tab for blocks…",
987
+ export: "Export",
988
+ exportMarkdown: "Markdown (.md)",
989
+ exportHtml: "Interactive HTML",
990
+ exportPdfPaged: "PDF — paged",
991
+ exportPdfContinuous: "PDF — continuous",
992
+ exportPdfSlides: "Slides (PDF)",
993
+ exportHtmlSlides: "Slides (HTML)",
994
+ exportPlugin: "Plugin (.zip)",
995
+ exportPluginFailed: "Can’t export this page as a plugin",
996
+ exportPluginFailedOk: "OK",
997
+ present: "Present",
998
+ presentFull: "Full screen",
999
+ presentPresenter: "Presenter view"
1000
+ },
1001
+ home: {
1002
+ morning: "Good morning",
1003
+ afternoon: "Good afternoon",
1004
+ evening: "Good evening",
1005
+ customize: "Customize Home",
1006
+ widgetActions: "Quick actions",
1007
+ widgetRecents: "Jump back in",
1008
+ widgetFavorites: "Favorites",
1009
+ widgetEdited: "Recently edited",
1010
+ justNow: "just now"
1011
+ },
1012
+ flow: {
1013
+ title: "Dataflow",
1014
+ open: "Dataflow view",
1015
+ empty: "Nothing reactive on this page yet",
1016
+ emptyHint: "Add named inputs, live code, charts or status lights — their wiring appears here as a live graph."
1017
+ },
1018
+ mention: {
1019
+ label: "Link to page",
1020
+ create: "Create page “{name}”",
1021
+ empty: "No pages — keep typing to create one."
1022
+ },
1023
+ properties: {
1024
+ owner: "Owner",
1025
+ setOwner: "Set owner",
1026
+ ownerPlaceholder: "Type a name…",
1027
+ you: "You",
1028
+ clear: "Clear",
1029
+ verification: "Verification",
1030
+ verified: "Verified",
1031
+ verify: "Verify",
1032
+ unverify: "Remove verification",
1033
+ verifiedBy: "by {name}",
1034
+ verifyExpired: "Verification expired",
1035
+ verifyExpiryPrompt: "Verify · choose an expiry",
1036
+ verifyReverify: "Re-verify · update expiry",
1037
+ verifyExpiry30: "Expires in 30 days",
1038
+ verifyExpiry90: "Expires in 90 days",
1039
+ verifyExpiry365: "Expires in 1 year",
1040
+ verifyNoExpiry: "No expiry",
1041
+ verifyExpiresOn: "Expires {date}",
1042
+ verifyExpiredOn: "Expired {date}",
1043
+ backlinks: "Backlinks",
1044
+ backlinkCount: "{count} backlinks",
1045
+ backlinkCountOne: "1 backlink",
1046
+ noBacklinks: "No backlinks",
1047
+ refresh: "Refresh"
1048
+ },
1049
+ emoji: {
1050
+ label: "Emoji",
1051
+ search: "Search emoji",
1052
+ tabEmoji: "Emoji",
1053
+ tabIcons: "Icons",
1054
+ searchEmoji: "Search emoji…",
1055
+ searchIcons: "Search icons…",
1056
+ recent: "Recent",
1057
+ noResults: "No matches",
1058
+ cat: {
1059
+ smileys: "Smileys",
1060
+ people: "People",
1061
+ nature: "Animals & Nature",
1062
+ food: "Food & Drink",
1063
+ activity: "Activity",
1064
+ travel: "Travel & Places",
1065
+ objects: "Objects",
1066
+ symbols: "Symbols"
1067
+ }
1068
+ },
1069
+ confirm: {
1070
+ trashTitle: "Move this page to the trash?",
1071
+ trashBody: "You can restore it later from the trash.",
1072
+ trashConfirm: "Move to trash"
1073
+ },
1074
+ backup: {
1075
+ heading: "Backup & restore",
1076
+ intro: "Export your whole workspace to a single file, or restore one — choosing which pages to bring back.",
1077
+ export: "Export backup",
1078
+ exporting: "Exporting…",
1079
+ restore: "Restore backup…",
1080
+ exported: "Exported {count} pages.",
1081
+ exportFailed: "Export failed: {error}",
1082
+ readFailed: "Couldn’t read backup: {error}",
1083
+ folderHeading: "Book folder",
1084
+ folderIntro: "Save your workspace as a folder of readable .html files (one per page), or load one back. The folder round-trips losslessly.",
1085
+ folderExport: "Export to folder…",
1086
+ folderExporting: "Exporting…",
1087
+ folderImport: "Import from folder…",
1088
+ folderExported: "Exported {count} pages to {location}.",
1089
+ folderEmpty: "No OpenBook pages found in that folder.",
1090
+ restored: "Restored {count} pages{detail}.",
1091
+ restoreFailed: "Restore failed: {error}",
1092
+ added: "{count} added",
1093
+ overwrittenCount: "{count} overwritten",
1094
+ renamedCount: "{count} renamed",
1095
+ dialog: {
1096
+ title: "Restore backup",
1097
+ summary: "{count} pages. Pick what to restore.",
1098
+ summaryDated: "{count} pages · exported {date}. Pick what to restore.",
1099
+ selected: "{count} selected",
1100
+ all: "All",
1101
+ none: "None",
1102
+ overwrite: "Overwrite existing pages",
1103
+ overwriteHint: "Restore in place by id. Off (default) imports as copies, suffixing names that clash.",
1104
+ restoreN: "Restore {count}",
1105
+ confirmTitle: "Overwrite {count} existing pages?",
1106
+ confirmBody: "Restoring in place will replace the current content of {count} pages. This can’t be undone.",
1107
+ confirmBodyNone: "No existing pages match — these will be added as new pages.",
1108
+ confirmOverwrite: "Overwrite"
1109
+ }
1110
+ },
1111
+ workspace: {
1112
+ workspaces: "Workspaces",
1113
+ addWorkspace: "Add a workspace…",
1114
+ addTitle: "Add a workspace",
1115
+ addDescription: "Connect to another OpenBook server. Switching to it re-points this device at that server.",
1116
+ icon: "Icon",
1117
+ name: "Name",
1118
+ serverUrl: "Server URL",
1119
+ namePlaceholder: "Home wiki",
1120
+ urlPlaceholder: "https://my-server.example:4319",
1121
+ addButton: "Add workspace",
1122
+ urlRequired: "Enter the server URL for this workspace.",
1123
+ urlInvalid: "That doesn’t look like a valid URL.",
1124
+ removeWorkspace: "Remove {name}",
1125
+ thisDevice: "This device"
1126
+ },
1127
+ ai: {
1128
+ description: "An optional model powers note search, task breakdown, and document completion. Run a local model — nothing leaves your machine — or connect the Claude API.",
1129
+ providerLabel: "Engine",
1130
+ defaultEngine: "Default engine",
1131
+ defaultEngineHint: "Used everywhere by default. Each provider below is configured separately — the agent can switch between them per conversation.",
1132
+ provider: {
1133
+ off: "Off",
1134
+ offHint: "No model. Note search still works (keyword ranking).",
1135
+ llama: "Built-in (llama.cpp)",
1136
+ llamaHint: "Runs inside OpenBook on any platform. Download a model below.",
1137
+ mlx: "MLX (Apple Silicon)",
1138
+ mlxHint: "Uses mlx_lm.server for the fastest local inference on Apple Silicon.",
1139
+ openai: "Local server (OpenAI-compatible)",
1140
+ openaiHint: "Ollama, LM Studio, llama-server, or any compatible endpoint.",
1141
+ claude: "Claude (Anthropic API)",
1142
+ claudeHint: "Anthropic’s hosted Claude models. Needs an API key — prompts are sent to Anthropic.",
1143
+ mock: "Mock (test)"
1144
+ },
1145
+ providerShort: {
1146
+ llama: "Built-in",
1147
+ mlx: "MLX",
1148
+ openai: "Local server",
1149
+ claude: "Claude"
1150
+ },
1151
+ ready: "Engine ready · {embeddings}",
1152
+ semantic: "semantic search enabled",
1153
+ lexicalOnly: "keyword search only",
1154
+ notReady: "Engine not ready.",
1155
+ model: "Model",
1156
+ modelFile: "Model file (GGUF)",
1157
+ modelFileHint: "A file in the server’s models directory.",
1158
+ downloadDefault: "Download recommended model (~1 GB)",
1159
+ downloading: "Downloading… {progress}%",
1160
+ downloadingNoPct: "Downloading…",
1161
+ downloadDone: "Model downloaded.",
1162
+ endpoint: "Endpoint",
1163
+ baseUrl: "Server URL",
1164
+ mlxUrlHint: "Where mlx_lm.server listens. Started automatically when possible.",
1165
+ openaiUrlHint: "The OpenAI-compatible server’s address.",
1166
+ modelName: "Model",
1167
+ mlxModelHint: "An MLX model id, e.g. mlx-community/Qwen2.5-1.5B-Instruct-4bit.",
1168
+ openaiModelHint: "The model name your server expects.",
1169
+ apiKey: "API key",
1170
+ apiKeyHint: "An Anthropic API key from console.anthropic.com (starts with “sk-ant-api…”) — not a `claude setup-token`. Stored in this workspace.",
1171
+ claudeModelHint: "A Claude model id, e.g. claude-sonnet-4-6 or claude-haiku-4-5.",
1172
+ search: "Note search",
1173
+ searchHint: "Notes are indexed for search automatically; rebuild if results look stale.",
1174
+ reindex: "Rebuild index",
1175
+ indexing: "Indexing…",
1176
+ indexed: "{pages} pages indexed",
1177
+ notIndexed: "Index builds on first search.",
1178
+ assistant: "Assistant",
1179
+ assistantHint: "Defaults for the workspace agent. These can be overridden per conversation.",
1180
+ effort: "Effort",
1181
+ effortHint: "How hard the agent works: more effort means more reasoning, more steps, and slower replies.",
1182
+ effortLow: "Low",
1183
+ effortMed: "Medium",
1184
+ effortHigh: "High",
1185
+ thinking: "Show reasoning",
1186
+ thinkingHint: "Surface the model’s thinking as a collapsible block (when it emits any).",
1187
+ skills: "Skills",
1188
+ skillsHint: "Reusable prompt recipes the assistant can follow. Markdown instructions, no code.",
1189
+ skillName: "Name",
1190
+ skillNamePlaceholder: "weekly-review",
1191
+ skillDescription: "Description",
1192
+ skillDescriptionPlaceholder: "What this skill is for",
1193
+ skillInstructions: "Instructions",
1194
+ skillInstructionsPlaceholder: "Steps the assistant should follow…",
1195
+ skillAdd: "Add skill",
1196
+ skillSave: "Save",
1197
+ skillCancel: "Cancel",
1198
+ skillDelete: "Delete",
1199
+ skillEmpty: "No skills yet. Add one to teach the assistant a repeatable recipe.",
1200
+ features: "Features",
1201
+ featuresHint: "Choose how each AI feature shows up in menus. Recommended keeps it up front; Enabled hides it until you search for it; Disabled removes it.",
1202
+ featureVisibility: {
1203
+ recommended: "Recommended",
1204
+ enabled: "Enabled",
1205
+ disabled: "Disabled"
1206
+ },
1207
+ feature: {
1208
+ assistant: "Assistant",
1209
+ search: "AI note search",
1210
+ continue: "Continue writing",
1211
+ tasks: "Break into tasks"
1212
+ }
1213
+ },
1214
+ aiSearch: {
1215
+ title: "Search notes",
1216
+ semantic: "semantic",
1217
+ lexical: "keyword",
1218
+ placeholder: "What are you looking for?",
1219
+ empty: "No matching notes.",
1220
+ hint: "Searches every page’s content — results improve with a local model."
1221
+ },
1222
+ agent: {
1223
+ title: "Assistant",
1224
+ hint: "Ask about your notes — the assistant can search, read, create pages, and build databases in this workspace.",
1225
+ placeholder: "Ask anything…",
1226
+ thinking: "Working…",
1227
+ reset: "New conversation",
1228
+ close: "Close assistant",
1229
+ error: "Something went wrong: {error}",
1230
+ notReady: "The assistant needs a model — enable one in Settings → AI.",
1231
+ openSettings: "Open AI settings",
1232
+ send: "Send",
1233
+ stop: "Stop",
1234
+ inputHint: "Enter to send · Shift+Enter for a new line",
1235
+ suggestion1: "What pages do I have?",
1236
+ suggestion2: "Find my notes about planning",
1237
+ suggestion3: "Create a page with a plan for today",
1238
+ reasoning: "Reasoning",
1239
+ suggestionsTitle: "Proposed {count} suggestion(s)",
1240
+ suggestionsHint: "The assistant proposed these changes. Open Review to accept or reject each.",
1241
+ review: "Review",
1242
+ proposalTitle: "Proposed changes",
1243
+ proposalHint: "The assistant wants to make these changes. Review and approve.",
1244
+ approve: "Approve",
1245
+ reject: "Discard",
1246
+ applied: "Applied {count} change(s).",
1247
+ appliedPartial: "Applied {applied} change(s); {failed} could not be applied.",
1248
+ applyFailed: "Some changes could not be applied.",
1249
+ rejected: "Changes discarded.",
1250
+ permissionTitle: "Apply changes directly?",
1251
+ permissionHint: "The assistant is asking to {summary} for you, skipping the review step.",
1252
+ permissionAllow: "Allow direct edits",
1253
+ permissionKeepReview: "Keep reviewing",
1254
+ permissionAllowed: "✓ Direct edits allowed for this conversation.",
1255
+ permissionDeclined: "Kept the review flow.",
1256
+ permissionGrantedMsg: "Yes — you may apply changes directly, without the review step.",
1257
+ permissionDeniedMsg: "No — please keep proposing changes for me to review.",
1258
+ interviewTitle: "A few questions",
1259
+ interviewStep: "Step {current} of {total}",
1260
+ interviewBack: "Back",
1261
+ interviewNext: "Next",
1262
+ interviewSubmit: "Send answers",
1263
+ interviewPlaceholder: "Type your answer…",
1264
+ interviewSent: "Answers sent.",
1265
+ interviewAnswersHeader: "Here are my answers:",
1266
+ effortLow: "Low",
1267
+ effortMed: "Medium",
1268
+ effortHigh: "High",
1269
+ thinkingToggle: "Reasoning",
1270
+ provider: "Provider for this conversation",
1271
+ model: "Model for this conversation",
1272
+ modelPlaceholder: "Default model",
1273
+ modelAuto: "Default",
1274
+ modelCustom: "Custom model",
1275
+ modelSettings: "Conversation model & effort",
1276
+ tool: {
1277
+ search_notes: "Searching notes",
1278
+ read_page: "Reading a page",
1279
+ list_pages: "Listing pages",
1280
+ create_page: "Creating a page",
1281
+ append_to_page: "Adding to a page",
1282
+ inspect_page_structure: "Inspecting page structure",
1283
+ get_kit_values: "Reading input values",
1284
+ list_db_views: "Listing database views",
1285
+ get_db_row: "Reading a database row",
1286
+ describe_database: "Inspecting a database",
1287
+ update_block: "Editing a block",
1288
+ update_block_props: "Formatting a block",
1289
+ delete_block: "Deleting a block",
1290
+ move_page: "Rearranging pages",
1291
+ request_edit_access: "Requesting edit access",
1292
+ ask_user: "Asking you",
1293
+ set_kit_value: "Setting an input value",
1294
+ set_db_cell: "Setting a database cell",
1295
+ create_database: "Creating a database",
1296
+ update_database: "Renaming a database",
1297
+ create_property: "Adding a column",
1298
+ update_property: "Editing a column",
1299
+ create_row: "Adding a row",
1300
+ update_row: "Updating a row",
1301
+ add_blocks: "Adding blocks",
1302
+ set_page_appearance: "Restyling the page"
1303
+ }
1304
+ },
1305
+ link: {
1306
+ pageTitle: "Link to page",
1307
+ databaseTitle: "Link to database",
1308
+ pagePlaceholder: "Search pages…",
1309
+ databasePlaceholder: "Search databases…",
1310
+ noPages: "No pages found",
1311
+ noDatabases: "No databases found"
1312
+ },
1313
+ slash: {
1314
+ group: {
1315
+ pages: "Pages",
1316
+ basic: "Basic blocks",
1317
+ interactive: "Interactive blocks",
1318
+ extensions: "Extensions",
1319
+ ai: "AI"
1320
+ },
1321
+ newpage: {
1322
+ label: "New page",
1323
+ hint: "Create a nested page and link it here"
1324
+ },
1325
+ newdatabase: {
1326
+ label: "New database",
1327
+ hint: "Create a nested database and link it here"
1328
+ },
1329
+ linkpage: {
1330
+ label: "Link to page",
1331
+ hint: "Insert a link to an existing page"
1332
+ },
1333
+ linkdatabase: {
1334
+ label: "Link to database",
1335
+ hint: "Insert a link to an existing database"
1336
+ },
1337
+ text: {
1338
+ label: "Text",
1339
+ hint: "Plain paragraph"
1340
+ },
1341
+ h1: {
1342
+ label: "Heading 1",
1343
+ hint: "Large section heading"
1344
+ },
1345
+ h2: {
1346
+ label: "Heading 2",
1347
+ hint: "Medium section heading"
1348
+ },
1349
+ h3: {
1350
+ label: "Heading 3",
1351
+ hint: "Small section heading"
1352
+ },
1353
+ bullet: {
1354
+ label: "Bulleted list",
1355
+ hint: "Simple list"
1356
+ },
1357
+ number: {
1358
+ label: "Numbered list",
1359
+ hint: "Ordered list"
1360
+ },
1361
+ todo: {
1362
+ label: "To-do",
1363
+ hint: "Checkbox item"
1364
+ },
1365
+ quote: {
1366
+ label: "Quote",
1367
+ hint: "Pull quote"
1368
+ },
1369
+ callout: {
1370
+ label: "Callout",
1371
+ hint: "Highlighted note"
1372
+ },
1373
+ code: {
1374
+ label: "Code",
1375
+ hint: "Monospaced block"
1376
+ },
1377
+ livecode: {
1378
+ label: "Live code",
1379
+ hint: "Computes over inputs; name the output to chain"
1380
+ },
1381
+ divider: {
1382
+ label: "Divider",
1383
+ hint: "Horizontal rule"
1384
+ },
1385
+ table: {
1386
+ label: "Table",
1387
+ hint: "3 × 3 to start"
1388
+ },
1389
+ cols2: {
1390
+ label: "2 columns",
1391
+ hint: "Side-by-side layout"
1392
+ },
1393
+ cols3: {
1394
+ label: "3 columns",
1395
+ hint: "Three-across layout"
1396
+ },
1397
+ cols4: {
1398
+ label: "4 columns",
1399
+ hint: "Four-across layout"
1400
+ },
1401
+ "ai-continue": {
1402
+ label: "Continue writing",
1403
+ hint: "AI continues from here"
1404
+ },
1405
+ "ai-tasks": {
1406
+ label: "Break into tasks",
1407
+ hint: "AI drafts to-dos for this"
1408
+ },
1409
+ custom: {
1410
+ slider: {
1411
+ label: "Slider",
1412
+ hint: "A named live input"
1413
+ },
1414
+ formula: {
1415
+ label: "Formula",
1416
+ hint: "Live code over inputs"
1417
+ },
1418
+ number: {
1419
+ label: "Number stepper",
1420
+ hint: "A named number with − / + buttons"
1421
+ },
1422
+ textfield: {
1423
+ label: "Text field",
1424
+ hint: "A named text input"
1425
+ },
1426
+ radio: {
1427
+ label: "Radio group",
1428
+ hint: "Pick one of several options"
1429
+ },
1430
+ checklist: {
1431
+ label: "Choice checklist",
1432
+ hint: "Pick any of several options"
1433
+ },
1434
+ dropdown: {
1435
+ label: "Dropdown",
1436
+ hint: "Pick one option from a select"
1437
+ },
1438
+ toggle: {
1439
+ label: "Toggle switch",
1440
+ hint: "A named on/off switch"
1441
+ },
1442
+ location: {
1443
+ label: "Location",
1444
+ hint: "A place with coordinates"
1445
+ },
1446
+ actionbutton: {
1447
+ label: "Button",
1448
+ hint: "Set, step, or toggle an input — or open a link"
1449
+ },
1450
+ kitchart: {
1451
+ label: "Chart",
1452
+ hint: "Line, bar, pie, scatter, funnel — live over inputs"
1453
+ },
1454
+ statuslight: {
1455
+ label: "Status light",
1456
+ hint: "Green / amber / red from a live value"
1457
+ },
1458
+ tooltipcard: {
1459
+ label: "Tooltip",
1460
+ hint: "A term that explains itself on hover"
1461
+ },
1462
+ linkcard: {
1463
+ label: "Link card",
1464
+ hint: "A titled card that opens a URL"
1465
+ }
1466
+ }
1467
+ },
1468
+ extensions: {
1469
+ description: "Extend OpenBook with plugins: custom blocks, commands, and integrations, installed from a zip of TypeScript source.",
1470
+ install: "Install from .zip…",
1471
+ installing: "Installing…",
1472
+ installHint: "A zip with openbook.json and TypeScript sources.",
1473
+ empty: "No extensions installed",
1474
+ emptyHint: "Install one from a zip — it can add blocks to the editor, commands to the palette, and integrations.",
1475
+ verified: "Verified",
1476
+ verifiedBy: "Signed and verified by {registry}",
1477
+ unverified: "Unverified",
1478
+ unverifiedHint: "Not signed by a registry you trust. It runs with the same access as your own live code.",
1479
+ loadError: "Failed to load: {error}",
1480
+ enable: "Enable {name}",
1481
+ remove: "Remove {name}",
1482
+ trustNote: "Extensions run with the same privileges as your documents’ live code. A “Verified” badge means a registry you trust signed this exact content — it is provenance, not a sandbox.",
1483
+ registries: "Trusted registries",
1484
+ registriesHint: "Extensions signed by any of these keys show as Verified.",
1485
+ builtIn: "Built-in",
1486
+ registryName: "Registry name",
1487
+ registryKey: "Ed25519 public key (base64)",
1488
+ addRegistry: "Trust registry",
1489
+ removeRegistry: "Remove registry {name}",
1490
+ registryKeyInvalid: "Enter a 32-byte Ed25519 public key in base64."
1491
+ },
1492
+ templates: {
1493
+ title: "Start with a template",
1494
+ description: "Ready-made pages with sensible structure — pick one and make it yours.",
1495
+ creating: "Creating…",
1496
+ groceryTracker: {
1497
+ name: "Grocery price tracker",
1498
+ description: "Price a weekly basket across shops — live charts, a budget light, and the maths tucked in a code block."
1499
+ },
1500
+ taskBoard: {
1501
+ name: "Project task board",
1502
+ description: "Tasks with status, priority, owner and effort — a kanban board grouped by status, plus a table."
1503
+ },
1504
+ readingList: {
1505
+ name: "Reading list",
1506
+ description: "A gallery of books grouped by shelf, with authors and star ratings — plus a table view."
1507
+ },
1508
+ projectIntake: {
1509
+ name: "Project intake",
1510
+ description: "A gated brief that unlocks stage by stage, with a live effort-vs-impact prioritisation."
1511
+ },
1512
+ savingsPlanner: {
1513
+ name: "Savings & investing",
1514
+ description: "A safety-net check, then sliders feed a live compound-growth projection toward a goal."
1515
+ },
1516
+ roadmap: {
1517
+ name: "Product roadmap",
1518
+ description: "Initiatives on a timeline and a board, both split into swimlanes by area."
1519
+ },
1520
+ fieldMap: {
1521
+ name: "Field map",
1522
+ description: "Offices and partners pinned on a map, coloured by region — with a table view."
1523
+ }
1524
+ },
1525
+ blocks: {
1526
+ subpagePage: "Page",
1527
+ subpageDatabase: "Database",
1528
+ expression: "Expression",
1529
+ chart: "Chart",
1530
+ slider: "Slider",
1531
+ sliderEdit: "Edit slider",
1532
+ creating: "Creating {kind}…",
1533
+ referenceHint: "reference cells with",
1534
+ chartPick: "Pick at least one cell to plot",
1535
+ chartNoData: "No numeric array data in the selected cells",
1536
+ chartPlot: "plot",
1537
+ chartAnd: "and",
1538
+ chartAddSeries: "add series",
1539
+ chartRemoveSeries: "Remove series",
1540
+ chartPickCell: "— pick a cell —",
1541
+ table: "Table",
1542
+ todo: "To-do list",
1543
+ listUnordered: "Bulleted list",
1544
+ listOrdered: "Numbered list",
1545
+ callout: "Callout",
1546
+ calloutInfo: "Info",
1547
+ calloutWarning: "Warning",
1548
+ calloutSuccess: "Success",
1549
+ calloutDanger: "Danger",
1550
+ calloutEmoji: "Change emoji",
1551
+ calloutPlaceholder: "Write a callout…",
1552
+ accordion: "Toggle",
1553
+ accordionToggle: "Expand or collapse",
1554
+ accordionTitlePlaceholder: "Toggle title",
1555
+ accordionContentPlaceholder: "Hidden content…",
1556
+ divider: "Divider",
1557
+ dividerLine: "Line",
1558
+ dividerDashed: "Dashed",
1559
+ dividerDotted: "Dotted",
1560
+ dividerThick: "Thick",
1561
+ dividerLabeled: "Labeled",
1562
+ dividerLabelPlaceholder: "Label",
1563
+ button: "Button",
1564
+ buttonDefault: "Button",
1565
+ buttonLabelPlaceholder: "Button label",
1566
+ buttonEdit: "Edit button",
1567
+ buttonUrlPlaceholder: "https://… or /page",
1568
+ toc: "Table of contents",
1569
+ tocTitle: "On this page",
1570
+ tocEmpty: "No headings yet — add a heading to build the outline."
1571
+ },
1572
+ general: {
1573
+ title: "General",
1574
+ description: "Language and how the app behaves.",
1575
+ languageSection: "Language",
1576
+ language: "Language",
1577
+ languageHint: "Display language for the app.",
1578
+ behavior: "Behavior",
1579
+ confirmTrash: "Confirm before trashing pages",
1580
+ confirmTrashHint: "Ask before moving a page to the trash.",
1581
+ spellcheck: "Spellcheck while typing",
1582
+ spellcheckHint: "Underline misspelled words in the editor."
1583
+ },
1584
+ profile: {
1585
+ title: "Profile",
1586
+ description: "How you appear in OpenBook on this device.",
1587
+ identity: "Identity",
1588
+ name: "Name",
1589
+ nameHint: "Your full name.",
1590
+ namePlaceholder: "Ada Lovelace",
1591
+ displayName: "Display name",
1592
+ displayNameHint: "A shorter name shown around the app.",
1593
+ displayNamePlaceholder: "ada",
1594
+ avatar: "Avatar",
1595
+ avatarHint: "Your initials by default — or pick an emoji or upload a picture.",
1596
+ avatarEmoji: "Choose emoji",
1597
+ avatarUpload: "Upload image…",
1598
+ avatarReset: "Use initials",
1599
+ editProfile: "Edit profile",
1600
+ aboutApp: "About OpenBook",
1601
+ bio: "About",
1602
+ bioHint: "A sentence or two about yourself.",
1603
+ bioPlaceholder: "Mathematician and writer.",
1604
+ preview: "Preview",
1605
+ anonymous: "Anonymous"
1606
+ },
1607
+ customisation: {
1608
+ title: "Customisation & shortcuts",
1609
+ description: "Tailor the layout and review keyboard shortcuts.",
1610
+ layout: "Layout",
1611
+ fullWidth: "Full-width editor",
1612
+ fullWidthHint: "Use the whole page width instead of a centered column.",
1613
+ autoHideSidebar: "Auto-hide sidebar",
1614
+ autoHideSidebarHint: "Collapse the sidebar until you move to the screen edge.",
1615
+ shortcuts: "Keyboard shortcuts",
1616
+ shortcutsHint: "Available anywhere in the app.",
1617
+ shortcut: {
1618
+ commandPalette: "Open the command palette",
1619
+ newPage: "Create a new page",
1620
+ toggleSidebar: "Show or hide the sidebar",
1621
+ fullWidth: "Toggle full-width view",
1622
+ theme: "Switch between light and dark",
1623
+ back: "Go back",
1624
+ forward: "Go forward",
1625
+ openSettings: "Open settings",
1626
+ trash: "Open the trash",
1627
+ closeOverlay: "Close a dialog or menu",
1628
+ slashMenu: "Insert a block",
1629
+ mention: "Link or mention a page"
1630
+ }
1631
+ },
1632
+ account: {
1633
+ signup: {
1634
+ title: "Create an account",
1635
+ description: "Accounts and cloud sync aren’t part of OpenBook yet. Today your pages live locally on the server you connect to."
1636
+ },
1637
+ signin: {
1638
+ title: "Account & sync",
1639
+ description: "Sign in to account.book.pub to sync your preferences and workspaces across devices. Local-first stays the default — this is opt-in.",
1640
+ signInButton: "Continue with account.book.pub",
1641
+ connecting: "Waiting for sign-in in your browser…",
1642
+ cancel: "Cancel",
1643
+ connectedTitle: "Synced",
1644
+ connectedAs: "This device",
1645
+ lastSynced: "Last synced",
1646
+ never: "not yet",
1647
+ syncing: "Syncing…",
1648
+ syncNow: "Sync now",
1649
+ signOut: "Sign out",
1650
+ openDashboard: "Manage devices",
1651
+ whatSyncs: "Your profile, general preferences, feature visibility, and workspace list sync. Pages and documents are not synced here — they stay on your data server.",
1652
+ signOutHint: "Signing out forgets the token on this device. To fully revoke it, remove the device in your account dashboard.",
1653
+ manualToggle: "App didn’t open? Enter a code manually",
1654
+ manualHint: "Dismiss the “open OpenBook?” prompt in your browser, copy the code (or the whole openbook:// link), and paste it here.",
1655
+ manualPlaceholder: "Paste your code or openbook://auth-callback#token=… link",
1656
+ manualSubmit: "Sign in with code"
1657
+ },
1658
+ support: {
1659
+ title: "Support OpenBook",
1660
+ description: "OpenBook is independent and open source. Sharing it and sending feedback helps it grow. Sponsorship options are on the way."
1661
+ }
1662
+ },
1663
+ forwarding: {
1664
+ title: "Forward to the web",
1665
+ description: "Claim a private ✦.book.pub address that opens this device’s books in any browser — nothing to host, nothing to expose on your network.",
1666
+ toggle: "Forward this device",
1667
+ signInHint: "Sign in to your account first to claim an address.",
1668
+ signIn: "Sign in",
1669
+ registering: "Connecting…",
1670
+ address: "Your address",
1671
+ addressHint: "Opens this device’s books in any browser while it’s online.",
1672
+ copy: "Copy",
1673
+ copied: "Copied",
1674
+ failed: "Couldn’t register: {error}",
1675
+ status: {
1676
+ live: "Live",
1677
+ connecting: "Connecting",
1678
+ offline: "Offline"
1679
+ }
1680
+ },
1681
+ connection: {
1682
+ title: "Connection",
1683
+ description: "Choose where this device reads and writes pages.",
1684
+ server: "Server",
1685
+ usingLocal: "Your books are stored in this app, on this device.",
1686
+ usingRemote: "Currently using the remote server",
1687
+ remoteUrl: "Remote server URL",
1688
+ remoteUrlPlaceholder: "https://my-server.example:4319",
1689
+ mixedContentWarning: "This is a secure (https) site, so it can’t reach a plain http:// address on your local network — the browser blocks it. Use the device’s https ✦.book.pub forwarding address instead (turn on Forwarding in the OpenBook app on that device), or open OpenBook directly on the same machine.",
1690
+ remoteTokenPlaceholder: "Only if the server requires one",
1691
+ remoteTokenHint: "A published or shared server requires its access token; leave blank for an open server.",
1692
+ connect: "Connect",
1693
+ useLocal: "Use this app",
1694
+ inApp: "Storage",
1695
+ inAppDescription: "Your books live in this app, on this device — no server, no open port. Share on the network below to also serve them to your other devices.",
1696
+ localServer: "Local server",
1697
+ running: "Shared from",
1698
+ stopped: "Stopped.",
1699
+ checking: "Checking…",
1700
+ unmanaged: "Managed by the dev environment — start/stop is unavailable here.",
1701
+ start: "Start",
1702
+ stop: "Stop",
1703
+ refresh: "Refresh",
1704
+ publish: "Share on the network",
1705
+ publishDescription: "Spin up a shareable server so other devices on your network can open this workspace.",
1706
+ publishToggle: "Share this workspace on the LAN",
1707
+ publishWarning: "No login: anyone who can reach the address below — with the access token — can read and edit this workspace. Only enable on networks you trust.",
1708
+ lanAddress: "Network address",
1709
+ accessToken: "Access token",
1710
+ copy: "Copy",
1711
+ copied: "Copied",
1712
+ notPublished: "Not shared — this device only.",
1713
+ bookFiles: "Book files",
1714
+ bookFilesDescription: "A readable folder of HTML pages, mirrored from your workspace for backup and external sync.",
1715
+ bookFolder: "Folder",
1716
+ changeFolder: "Change…",
1717
+ reveal: "Reveal in Finder"
1718
+ },
1719
+ integrations: {
1720
+ title: "Integrations",
1721
+ description: "Connect OpenBook to other tools. Integrations aren’t available yet — this is where they’ll live."
1722
+ },
1723
+ admin: {
1724
+ title: "Admin",
1725
+ description: "Backup, restore, and workspace maintenance.",
1726
+ dangerZone: "Danger zone",
1727
+ dangerZoneHint: "These actions affect this device’s local data, not your pages.",
1728
+ resetPrefs: "Reset preferences & layout",
1729
+ resetPrefsHint: "Restore default appearance, language, and layout on this device. Your pages and workspaces are kept.",
1730
+ resetPrefsButton: "Reset",
1731
+ resetConfirmTitle: "Reset preferences & layout?",
1732
+ resetConfirmBody: "This clears appearance, language, and layout settings on this device and reloads. Your pages and workspaces are not affected.",
1733
+ resetConfirmButton: "Reset"
1734
+ }
1735
+ }, xi = {
1736
+ common: {
1737
+ cancel: "Abbrechen",
1738
+ close: "Schließen",
1739
+ delete: "Löschen",
1740
+ save: "Speichern",
1741
+ add: "Hinzufügen",
1742
+ remove: "Entfernen",
1743
+ untitled: "Unbenannt",
1744
+ settings: "Einstellungen"
1745
+ },
1746
+ settings: {
1747
+ title: "Einstellungen",
1748
+ comingSoon: "Diese Einstellungen folgen in Kürze.",
1749
+ fullscreen: "Vollbild",
1750
+ exitFullscreen: "Vollbild verlassen",
1751
+ enterFullscreen: "Vollbild",
1752
+ closeSettings: "Einstellungen schließen",
1753
+ section: {
1754
+ preferences: "Präferenzen",
1755
+ account: "Konto",
1756
+ workspace: "Arbeitsbereich"
1757
+ },
1758
+ tab: {
1759
+ general: "Allgemein",
1760
+ profile: "Profil",
1761
+ appearance: "Darstellung",
1762
+ customisation: "Anpassung",
1763
+ signup: "Registrieren",
1764
+ signin: "Anmeldung & E-Mail",
1765
+ support: "OpenBook unterstützen",
1766
+ connection: "Verbindung",
1767
+ integrations: "Integrationen",
1768
+ extensions: "Erweiterungen",
1769
+ ai: "KI",
1770
+ admin: "Verwaltung"
1771
+ }
1772
+ },
1773
+ appearance: {
1774
+ title: "Darstellung",
1775
+ colorMode: "Farbmodus",
1776
+ light: "Hell",
1777
+ dark: "Dunkel",
1778
+ system: "System",
1779
+ colorScheme: "Farbschema",
1780
+ colorTheme: "Farbthema",
1781
+ colorThemeHint: "Wähle die App-Akzentfarbe."
1782
+ },
1783
+ theme: {
1784
+ default: "Standard",
1785
+ sandstone: "Sandstein",
1786
+ slate: "Schiefer",
1787
+ ocean: "Ozean",
1788
+ forest: "Wald",
1789
+ violet: "Violett",
1790
+ sunset: "Sonnenuntergang",
1791
+ rose: "Rosé",
1792
+ graphite: "Graphit"
1793
+ },
1794
+ nav: {
1795
+ favorites: "Favoriten",
1796
+ recents: "Zuletzt besucht",
1797
+ suggested: "Vorgeschlagen",
1798
+ home: "Start",
1799
+ templates: "Vorlagen",
1800
+ more: "Weitere Aktionen",
1801
+ pages: "Seiten",
1802
+ newPage: "Neue Seite",
1803
+ newDatabase: "Neue Datenbank",
1804
+ back: "Zurück",
1805
+ forward: "Vor",
1806
+ goBack: "Zurück",
1807
+ goForward: "Vor",
1808
+ toggleSidebar: "Seitenleiste umschalten",
1809
+ trash: "Papierkorb"
1810
+ },
1811
+ tabs: {
1812
+ new: "Neuer Tab",
1813
+ close: "Tab schließen"
1814
+ },
1815
+ menu: {
1816
+ openTab: "In neuem Tab öffnen",
1817
+ openWindow: "In neuem Fenster öffnen",
1818
+ addSubpage: "Unterseite hinzufügen",
1819
+ addDatabase: "Datenbank hinzufügen",
1820
+ moveToTrash: "In den Papierkorb",
1821
+ viewOptions: "Ansichtsoptionen",
1822
+ options: "Menü",
1823
+ fullWidth: "Volle Breite",
1824
+ favourite: "Favorit",
1825
+ favorite: "Zu Favoriten hinzufügen",
1826
+ unfavorite: "Aus Favoriten entfernen",
1827
+ openSplit: "In geteilter Ansicht öffnen",
1828
+ rename: "Umbenennen",
1829
+ copyLink: "Link kopieren",
1830
+ duplicate: "Duplizieren",
1831
+ sectionPage: "Seite",
1832
+ block: {
1833
+ sectionBlock: "Block",
1834
+ moveUp: "Nach oben",
1835
+ moveDown: "Nach unten",
1836
+ duplicate: "Duplizieren",
1837
+ deleteBlock: "Block löschen",
1838
+ linkToPage: "Mit Seite verknüpfen"
1839
+ }
1840
+ },
1841
+ command: {
1842
+ title: "Befehlspalette",
1843
+ search: "Suchen",
1844
+ noPages: "Noch keine Seiten",
1845
+ groupFavorites: "Favoriten",
1846
+ groupRecent: "Zuletzt besucht",
1847
+ groupCreate: "Erstellen",
1848
+ groupView: "Ansicht",
1849
+ groupNavigation: "Navigation",
1850
+ groupApp: "App",
1851
+ favorite: "Zu Favoriten hinzufügen",
1852
+ unfavorite: "Aus Favoriten entfernen",
1853
+ newDatabase: "Neue Datenbank",
1854
+ openTrash: "Papierkorb öffnen",
1855
+ toggleSidebar: "Seitenleiste umschalten",
1856
+ toggleFullWidth: "Volle Breite umschalten",
1857
+ themeToLight: "Zum hellen Modus wechseln",
1858
+ themeToDark: "Zum dunklen Modus wechseln",
1859
+ splitView: "Geteilte Ansicht",
1860
+ closeSplit: "Geteilte Ansicht schließen",
1861
+ goBack: "Zurück",
1862
+ goForward: "Vorwärts",
1863
+ placeholder: "Seiten suchen oder Befehl ausführen…",
1864
+ noResults: "Keine Ergebnisse.",
1865
+ pages: "Seiten",
1866
+ actions: "Aktionen",
1867
+ createPage: "Neue Seite erstellen",
1868
+ insertSample: "Beispieldokument einfügen",
1869
+ newFromTemplate: "Neu aus Vorlage",
1870
+ aiSearch: "Notizen mit KI durchsuchen",
1871
+ askAssistant: "Assistent fragen",
1872
+ openSettings: "Einstellungen öffnen",
1873
+ current: "aktuell"
1874
+ },
1875
+ page: {
1876
+ saving: "Speichern…",
1877
+ saved: "Gespeichert",
1878
+ saveFailed: "Speichern fehlgeschlagen",
1879
+ actions: "Seitenaktionen",
1880
+ delete: "Seite löschen",
1881
+ titleLabel: "Seitentitel",
1882
+ changeIcon: "Seitensymbol ändern",
1883
+ editorPlaceholder: "Schreibe etwas oder drücke Tab für Blöcke…",
1884
+ export: "Exportieren",
1885
+ exportMarkdown: "Markdown (.md)",
1886
+ exportHtml: "Interaktives HTML",
1887
+ exportPdfPaged: "PDF — seitenweise",
1888
+ exportPdfContinuous: "PDF — fortlaufend",
1889
+ exportPdfSlides: "Folien (PDF)",
1890
+ exportHtmlSlides: "Folien (HTML)",
1891
+ present: "Präsentieren",
1892
+ presentFull: "Vollbild",
1893
+ presentPresenter: "Referentenansicht",
1894
+ exportPlugin: "Plugin (.zip)",
1895
+ exportPluginFailed: "Diese Seite lässt sich nicht als Plugin exportieren",
1896
+ exportPluginFailedOk: "OK"
1897
+ },
1898
+ home: {
1899
+ morning: "Guten Morgen",
1900
+ afternoon: "Guten Tag",
1901
+ evening: "Guten Abend",
1902
+ customize: "Start anpassen",
1903
+ widgetActions: "Schnellaktionen",
1904
+ widgetRecents: "Weitermachen",
1905
+ widgetFavorites: "Favoriten",
1906
+ widgetEdited: "Zuletzt bearbeitet",
1907
+ justNow: "gerade eben"
1908
+ },
1909
+ flow: {
1910
+ title: "Datenfluss",
1911
+ open: "Datenfluss-Ansicht",
1912
+ empty: "Auf dieser Seite ist noch nichts reaktiv",
1913
+ emptyHint: "Füge benannte Eingaben, Live-Code, Diagramme oder Statusleuchten hinzu — ihre Verdrahtung erscheint hier als Live-Graph."
1914
+ },
1915
+ mention: {
1916
+ label: "Mit Seite verknüpfen",
1917
+ create: "Seite „{name}“ erstellen",
1918
+ empty: "Keine Seiten — weiter tippen, um eine zu erstellen."
1919
+ },
1920
+ emoji: {
1921
+ label: "Emoji",
1922
+ search: "Emoji suchen"
1923
+ },
1924
+ confirm: {
1925
+ trashTitle: "Diese Seite in den Papierkorb verschieben?",
1926
+ trashBody: "Du kannst sie später aus dem Papierkorb wiederherstellen.",
1927
+ trashConfirm: "In den Papierkorb"
1928
+ },
1929
+ backup: {
1930
+ heading: "Sichern & Wiederherstellen",
1931
+ intro: "Exportiere deinen gesamten Arbeitsbereich in eine Datei oder stelle eine wieder her — wähle dabei, welche Seiten zurückkommen.",
1932
+ export: "Sicherung exportieren",
1933
+ exporting: "Exportieren…",
1934
+ restore: "Sicherung wiederherstellen…",
1935
+ exported: "{count} Seiten exportiert.",
1936
+ exportFailed: "Export fehlgeschlagen: {error}",
1937
+ readFailed: "Sicherung konnte nicht gelesen werden: {error}",
1938
+ restored: "{count} Seiten wiederhergestellt{detail}.",
1939
+ restoreFailed: "Wiederherstellung fehlgeschlagen: {error}",
1940
+ added: "{count} hinzugefügt",
1941
+ overwrittenCount: "{count} überschrieben",
1942
+ renamedCount: "{count} umbenannt",
1943
+ dialog: {
1944
+ title: "Sicherung wiederherstellen",
1945
+ summary: "{count} Seiten. Wähle, was wiederhergestellt wird.",
1946
+ summaryDated: "{count} Seiten · exportiert {date}. Wähle, was wiederhergestellt wird.",
1947
+ selected: "{count} ausgewählt",
1948
+ all: "Alle",
1949
+ none: "Keine",
1950
+ overwrite: "Vorhandene Seiten überschreiben",
1951
+ overwriteHint: "An Ort und Stelle per ID wiederherstellen. Aus (Standard) importiert als Kopien und hängt bei Namenskonflikten ein Suffix an.",
1952
+ restoreN: "{count} wiederherstellen",
1953
+ confirmTitle: "{count} vorhandene Seiten überschreiben?",
1954
+ confirmBody: "Beim Wiederherstellen wird der aktuelle Inhalt von {count} Seiten ersetzt. Das kann nicht rückgängig gemacht werden.",
1955
+ confirmBodyNone: "Keine vorhandenen Seiten passen — diese werden als neue Seiten hinzugefügt.",
1956
+ confirmOverwrite: "Überschreiben"
1957
+ }
1958
+ },
1959
+ workspace: {
1960
+ workspaces: "Arbeitsbereiche",
1961
+ addWorkspace: "Arbeitsbereich hinzufügen…",
1962
+ addTitle: "Arbeitsbereich hinzufügen",
1963
+ addDescription: "Mit einem anderen OpenBook-Server verbinden. Beim Wechsel zeigt dieses Gerät auf jenen Server.",
1964
+ icon: "Symbol",
1965
+ name: "Name",
1966
+ serverUrl: "Server-URL",
1967
+ namePlaceholder: "Heim-Wiki",
1968
+ urlPlaceholder: "https://mein-server.example:4319",
1969
+ addButton: "Arbeitsbereich hinzufügen",
1970
+ urlRequired: "Gib die Server-URL für diesen Arbeitsbereich ein.",
1971
+ urlInvalid: "Das sieht nicht nach einer gültigen URL aus.",
1972
+ removeWorkspace: "{name} entfernen",
1973
+ thisDevice: "Dieses Gerät"
1974
+ },
1975
+ ai: {
1976
+ description: "Ein optionales lokales Modell ermöglicht Notizsuche, Aufgabenplanung und Textvervollständigung. Alles läuft auf deinem Gerät.",
1977
+ providerLabel: "Engine",
1978
+ provider: {
1979
+ off: "Aus",
1980
+ offHint: "Kein Modell. Die Notizsuche funktioniert weiterhin (Stichwort-Ranking).",
1981
+ llama: "Integriert (llama.cpp)",
1982
+ llamaHint: "Läuft plattformübergreifend in OpenBook. Modell unten herunterladen.",
1983
+ mlx: "MLX (Apple Silicon)",
1984
+ mlxHint: "Nutzt mlx_lm.server für schnellste lokale Inferenz auf Apple Silicon.",
1985
+ openai: "Lokaler Server (OpenAI-kompatibel)",
1986
+ openaiHint: "Ollama, LM Studio, llama-server oder ein kompatibler Endpunkt."
1987
+ },
1988
+ ready: "Engine bereit · {embeddings}",
1989
+ semantic: "semantische Suche aktiv",
1990
+ lexicalOnly: "nur Stichwortsuche",
1991
+ notReady: "Engine nicht bereit.",
1992
+ model: "Modell",
1993
+ modelFile: "Modelldatei (GGUF)",
1994
+ modelFileHint: "Eine Datei im Modellverzeichnis des Servers.",
1995
+ downloadDefault: "Empfohlenes Modell laden (~1 GB)",
1996
+ downloading: "Wird geladen… {progress}%",
1997
+ downloadingNoPct: "Wird geladen…",
1998
+ downloadDone: "Modell heruntergeladen.",
1999
+ endpoint: "Endpunkt",
2000
+ baseUrl: "Server-URL",
2001
+ mlxUrlHint: "Adresse von mlx_lm.server. Wird wenn möglich automatisch gestartet.",
2002
+ openaiUrlHint: "Adresse des OpenAI-kompatiblen Servers.",
2003
+ modelName: "Modell",
2004
+ mlxModelHint: "Eine MLX-Modell-ID, z. B. mlx-community/Qwen2.5-1.5B-Instruct-4bit.",
2005
+ openaiModelHint: "Der Modellname, den dein Server erwartet.",
2006
+ search: "Notizsuche",
2007
+ searchHint: "Notizen werden automatisch indiziert; bei veralteten Ergebnissen neu aufbauen.",
2008
+ reindex: "Index neu aufbauen",
2009
+ indexing: "Indizierung…",
2010
+ indexed: "{pages} Seiten indiziert",
2011
+ notIndexed: "Index entsteht bei der ersten Suche."
2012
+ },
2013
+ aiSearch: {
2014
+ title: "Notizen durchsuchen",
2015
+ semantic: "semantisch",
2016
+ lexical: "Stichwort",
2017
+ placeholder: "Wonach suchst du?",
2018
+ empty: "Keine passenden Notizen.",
2019
+ hint: "Durchsucht alle Seiteninhalte — mit lokalem Modell werden die Ergebnisse besser."
2020
+ },
2021
+ agent: {
2022
+ title: "Assistent",
2023
+ hint: "Frag zu deinen Notizen — der Assistent kann Seiten suchen, lesen und anlegen.",
2024
+ placeholder: "Frag etwas…",
2025
+ thinking: "Arbeitet…",
2026
+ reset: "Neue Unterhaltung",
2027
+ close: "Assistent schließen",
2028
+ error: "Etwas ist schiefgelaufen: {error}",
2029
+ notReady: "Der Assistent braucht ein Modell — aktiviere eines unter Einstellungen → KI.",
2030
+ openSettings: "KI-Einstellungen öffnen",
2031
+ send: "Senden",
2032
+ stop: "Stopp",
2033
+ inputHint: "Enter zum Senden · Shift+Enter für neue Zeile",
2034
+ suggestion1: "Welche Seiten habe ich?",
2035
+ suggestion2: "Finde meine Notizen zur Planung",
2036
+ suggestion3: "Erstelle eine Seite mit einem Plan für heute",
2037
+ tool: {
2038
+ search_notes: "Durchsucht Notizen",
2039
+ read_page: "Liest eine Seite",
2040
+ list_pages: "Listet Seiten auf",
2041
+ create_page: "Erstellt eine Seite",
2042
+ append_to_page: "Ergänzt eine Seite"
2043
+ }
2044
+ },
2045
+ slash: {
2046
+ text: {
2047
+ label: "Text",
2048
+ hint: "Einfacher Absatz"
2049
+ },
2050
+ h1: {
2051
+ label: "Überschrift 1",
2052
+ hint: "Große Abschnittsüberschrift"
2053
+ },
2054
+ h2: {
2055
+ label: "Überschrift 2",
2056
+ hint: "Mittlere Abschnittsüberschrift"
2057
+ },
2058
+ h3: {
2059
+ label: "Überschrift 3",
2060
+ hint: "Kleine Abschnittsüberschrift"
2061
+ },
2062
+ bullet: {
2063
+ label: "Aufzählung",
2064
+ hint: "Einfache Liste"
2065
+ },
2066
+ number: {
2067
+ label: "Nummerierte Liste",
2068
+ hint: "Geordnete Liste"
2069
+ },
2070
+ todo: {
2071
+ label: "To-do",
2072
+ hint: "Eintrag mit Checkbox"
2073
+ },
2074
+ quote: {
2075
+ label: "Zitat",
2076
+ hint: "Hervorgehobenes Zitat"
2077
+ },
2078
+ callout: {
2079
+ label: "Hinweis",
2080
+ hint: "Hervorgehobene Notiz"
2081
+ },
2082
+ code: {
2083
+ label: "Code",
2084
+ hint: "Monospace-Block"
2085
+ },
2086
+ livecode: {
2087
+ label: "Live-Code",
2088
+ hint: "Rechnet über Eingaben; benannte Ausgabe zum Verketten"
2089
+ },
2090
+ divider: {
2091
+ label: "Trennlinie",
2092
+ hint: "Horizontale Linie"
2093
+ },
2094
+ table: {
2095
+ label: "Tabelle",
2096
+ hint: "3 × 3 zum Start"
2097
+ },
2098
+ cols2: {
2099
+ label: "2 Spalten",
2100
+ hint: "Nebeneinander-Layout"
2101
+ },
2102
+ cols3: {
2103
+ label: "3 Spalten",
2104
+ hint: "Dreispaltiges Layout"
2105
+ },
2106
+ cols4: {
2107
+ label: "4 Spalten",
2108
+ hint: "Vierspaltiges Layout"
2109
+ },
2110
+ "ai-continue": {
2111
+ label: "Weiterschreiben",
2112
+ hint: "KI schreibt ab hier weiter"
2113
+ },
2114
+ "ai-tasks": {
2115
+ label: "In Aufgaben zerlegen",
2116
+ hint: "KI entwirft To-dos dafür"
2117
+ },
2118
+ custom: {
2119
+ slider: {
2120
+ label: "Schieberegler",
2121
+ hint: "Ein benannter Live-Eingang"
2122
+ },
2123
+ formula: {
2124
+ label: "Formel",
2125
+ hint: "Live-Code über Eingaben"
2126
+ },
2127
+ number: {
2128
+ label: "Zahlen-Stepper",
2129
+ hint: "Eine benannte Zahl mit − / + Tasten"
2130
+ },
2131
+ textfield: {
2132
+ label: "Textfeld",
2133
+ hint: "Eine benannte Texteingabe"
2134
+ },
2135
+ radio: {
2136
+ label: "Optionsfeld",
2137
+ hint: "Eine von mehreren Optionen wählen"
2138
+ },
2139
+ checklist: {
2140
+ label: "Auswahl-Checkliste",
2141
+ hint: "Beliebig viele Optionen wählen"
2142
+ },
2143
+ dropdown: {
2144
+ label: "Dropdown",
2145
+ hint: "Eine Option aus einer Liste wählen"
2146
+ },
2147
+ toggle: {
2148
+ label: "Schalter",
2149
+ hint: "Ein benannter Ein/Aus-Schalter"
2150
+ },
2151
+ location: {
2152
+ label: "Ort",
2153
+ hint: "Ein Ort mit Koordinaten"
2154
+ },
2155
+ actionbutton: {
2156
+ label: "Button",
2157
+ hint: "Eingabe setzen, schrittweise ändern oder Link öffnen"
2158
+ },
2159
+ kitchart: {
2160
+ label: "Diagramm",
2161
+ hint: "Linie, Balken, Kreis, Streu, Trichter — live über Eingaben"
2162
+ },
2163
+ statuslight: {
2164
+ label: "Statusleuchte",
2165
+ hint: "Grün / Gelb / Rot aus einem Live-Wert"
2166
+ },
2167
+ tooltipcard: {
2168
+ label: "Tooltip",
2169
+ hint: "Ein Begriff, der sich beim Überfahren erklärt"
2170
+ },
2171
+ linkcard: {
2172
+ label: "Link-Karte",
2173
+ hint: "Eine betitelte Karte, die eine URL öffnet"
2174
+ }
2175
+ }
2176
+ },
2177
+ extensions: {
2178
+ description: "Erweitere OpenBook mit Plugins: eigene Blöcke, Befehle und Integrationen, installiert aus einem Zip mit TypeScript-Quellcode.",
2179
+ install: "Aus .zip installieren…",
2180
+ installing: "Installiere…",
2181
+ installHint: "Ein Zip mit openbook.json und TypeScript-Quellen.",
2182
+ empty: "Keine Erweiterungen installiert",
2183
+ emptyHint: "Installiere eine aus einem Zip — sie kann Blöcke, Palettenbefehle und Integrationen hinzufügen.",
2184
+ verified: "Verifiziert",
2185
+ verifiedBy: "Signiert und verifiziert von {registry}",
2186
+ unverified: "Nicht verifiziert",
2187
+ unverifiedHint: "Nicht von einer vertrauten Registry signiert. Läuft mit denselben Rechten wie dein eigener Live-Code.",
2188
+ loadError: "Laden fehlgeschlagen: {error}",
2189
+ enable: "{name} aktivieren",
2190
+ remove: "{name} entfernen",
2191
+ trustNote: "Erweiterungen laufen mit denselben Rechten wie der Live-Code deiner Dokumente. „Verifiziert“ bedeutet: eine vertraute Registry hat genau diesen Inhalt signiert — Herkunft, keine Sandbox.",
2192
+ registries: "Vertraute Registries",
2193
+ registriesHint: "Erweiterungen, die mit einem dieser Schlüssel signiert sind, gelten als verifiziert.",
2194
+ builtIn: "Integriert",
2195
+ registryName: "Registry-Name",
2196
+ registryKey: "Öffentlicher Ed25519-Schlüssel (Base64)",
2197
+ addRegistry: "Registry vertrauen",
2198
+ removeRegistry: "Registry {name} entfernen",
2199
+ registryKeyInvalid: "Gib einen öffentlichen Ed25519-Schlüssel (32 Byte, Base64) ein."
2200
+ },
2201
+ templates: {
2202
+ title: "Mit einer Vorlage starten",
2203
+ description: "Fertige Seiten mit sinnvoller Struktur — auswählen und anpassen.",
2204
+ creating: "Wird erstellt…",
2205
+ groceryTracker: {
2206
+ name: "Lebensmittelpreis-Tracker",
2207
+ description: "Einen Wocheneinkauf über mehrere Läden bepreisen — Live-Diagramme, eine Budgetleuchte und die Rechnung im Code-Block."
2208
+ },
2209
+ taskBoard: {
2210
+ name: "Projekt-Aufgabenboard",
2211
+ description: "Aufgaben mit Status, Priorität, Verantwortlichem und Aufwand — ein Kanban-Board nach Status, plus Tabelle."
2212
+ },
2213
+ readingList: {
2214
+ name: "Leseliste",
2215
+ description: "Eine Galerie von Büchern nach Regal, mit Autoren und Sternebewertungen — plus Tabellenansicht."
2216
+ },
2217
+ projectIntake: {
2218
+ name: "Projektaufnahme",
2219
+ description: "Ein gestuftes Briefing, das sich Schritt für Schritt freischaltet, mit Live-Priorisierung nach Aufwand vs. Wirkung."
2220
+ },
2221
+ savingsPlanner: {
2222
+ name: "Sparen & Anlegen",
2223
+ description: "Erst der Notgroschen-Check, dann speisen Regler eine Live-Zinseszins-Projektion auf ein Ziel hin."
2224
+ },
2225
+ roadmap: {
2226
+ name: "Produkt-Roadmap",
2227
+ description: "Vorhaben auf Timeline und Board, beide nach Bereich in Swimlanes aufgeteilt."
2228
+ },
2229
+ fieldMap: {
2230
+ name: "Standortkarte",
2231
+ description: "Büros und Partner auf einer Karte, nach Region eingefärbt — mit Tabellenansicht."
2232
+ }
2233
+ },
2234
+ blocks: {
2235
+ subpagePage: "Seite",
2236
+ subpageDatabase: "Datenbank",
2237
+ expression: "Ausdruck",
2238
+ chart: "Diagramm",
2239
+ slider: "Schieberegler",
2240
+ sliderEdit: "Slider bearbeiten",
2241
+ creating: "{kind} wird erstellt…",
2242
+ referenceHint: "Zellen referenzieren mit",
2243
+ chartPick: "Wähle mindestens eine Zelle zum Plotten",
2244
+ chartNoData: "Keine numerischen Array-Daten in den gewählten Zellen",
2245
+ chartPlot: "plotten",
2246
+ chartAnd: "und",
2247
+ chartAddSeries: "Reihe hinzufügen",
2248
+ chartRemoveSeries: "Reihe entfernen",
2249
+ chartPickCell: "— Zelle wählen —",
2250
+ table: "Tabelle",
2251
+ todo: "To-do-Liste",
2252
+ listUnordered: "Aufzählungsliste",
2253
+ listOrdered: "Nummerierte Liste",
2254
+ callout: "Hinweis",
2255
+ calloutInfo: "Info",
2256
+ calloutWarning: "Warnung",
2257
+ calloutSuccess: "Erfolg",
2258
+ calloutDanger: "Gefahr",
2259
+ calloutEmoji: "Emoji ändern",
2260
+ calloutPlaceholder: "Hinweis schreiben…",
2261
+ accordion: "Umschalter",
2262
+ accordionToggle: "Ein- oder ausklappen",
2263
+ accordionTitlePlaceholder: "Titel des Umschalters",
2264
+ accordionContentPlaceholder: "Verborgener Inhalt…",
2265
+ divider: "Trennlinie",
2266
+ dividerLine: "Linie",
2267
+ dividerDashed: "Gestrichelt",
2268
+ dividerDotted: "Gepunktet",
2269
+ dividerThick: "Dick",
2270
+ dividerLabeled: "Mit Beschriftung",
2271
+ dividerLabelPlaceholder: "Beschriftung",
2272
+ button: "Schaltfläche",
2273
+ buttonDefault: "Schaltfläche",
2274
+ buttonLabelPlaceholder: "Beschriftung",
2275
+ buttonEdit: "Button bearbeiten",
2276
+ buttonUrlPlaceholder: "https://… oder /seite",
2277
+ toc: "Inhaltsverzeichnis",
2278
+ tocTitle: "Auf dieser Seite",
2279
+ tocEmpty: "Noch keine Überschriften — füge eine hinzu, um die Gliederung zu erstellen."
2280
+ },
2281
+ general: {
2282
+ title: "Allgemein",
2283
+ description: "Sprache und das Verhalten der App.",
2284
+ languageSection: "Sprache",
2285
+ language: "Sprache",
2286
+ languageHint: "Anzeigesprache der App.",
2287
+ behavior: "Verhalten",
2288
+ confirmTrash: "Vor dem Papierkorb nachfragen",
2289
+ confirmTrashHint: "Vor dem Verschieben einer Seite in den Papierkorb nachfragen.",
2290
+ spellcheck: "Rechtschreibprüfung beim Tippen",
2291
+ spellcheckHint: "Falsch geschriebene Wörter im Editor unterstreichen."
2292
+ },
2293
+ profile: {
2294
+ title: "Profil",
2295
+ description: "Wie du auf diesem Gerät in OpenBook erscheinst.",
2296
+ identity: "Identität",
2297
+ name: "Name",
2298
+ nameHint: "Dein vollständiger Name.",
2299
+ namePlaceholder: "Ada Lovelace",
2300
+ displayName: "Anzeigename",
2301
+ displayNameHint: "Ein kürzerer Name, der in der App gezeigt wird.",
2302
+ displayNamePlaceholder: "ada",
2303
+ avatar: "Avatar",
2304
+ avatarHint: "Standardmäßig deine Initialen — oder wähle ein Emoji oder lade ein Bild hoch.",
2305
+ avatarEmoji: "Emoji wählen",
2306
+ avatarUpload: "Bild hochladen…",
2307
+ avatarReset: "Initialen verwenden",
2308
+ editProfile: "Profil bearbeiten",
2309
+ aboutApp: "Über OpenBook",
2310
+ bio: "Über dich",
2311
+ bioHint: "Ein, zwei Sätze über dich.",
2312
+ bioPlaceholder: "Mathematikerin und Autorin.",
2313
+ preview: "Vorschau",
2314
+ anonymous: "Anonym"
2315
+ },
2316
+ customisation: {
2317
+ title: "Anpassung & Tastenkürzel",
2318
+ description: "Layout anpassen und Tastenkürzel ansehen.",
2319
+ layout: "Layout",
2320
+ fullWidth: "Editor in voller Breite",
2321
+ fullWidthHint: "Die gesamte Seitenbreite statt einer zentrierten Spalte nutzen.",
2322
+ autoHideSidebar: "Seitenleiste automatisch ausblenden",
2323
+ autoHideSidebarHint: "Die Seitenleiste einklappen, bis du an den Bildschirmrand fährst.",
2324
+ shortcuts: "Tastenkürzel",
2325
+ shortcutsHint: "Überall in der App verfügbar.",
2326
+ shortcut: {
2327
+ newPage: "Neue Seite erstellen",
2328
+ toggleSidebar: "Seitenleiste ein- oder ausblenden",
2329
+ fullWidth: "Volle Breite umschalten",
2330
+ theme: "Zwischen hell und dunkel wechseln",
2331
+ back: "Zurück",
2332
+ forward: "Vorwärts",
2333
+ openSettings: "Einstellungen öffnen",
2334
+ trash: "Papierkorb öffnen",
2335
+ commandPalette: "Befehlspalette öffnen",
2336
+ closeOverlay: "Dialog oder Menü schließen",
2337
+ slashMenu: "Block einfügen",
2338
+ mention: "Seite verknüpfen oder erwähnen"
2339
+ }
2340
+ },
2341
+ account: {
2342
+ signup: {
2343
+ title: "Konto erstellen",
2344
+ description: "Konten und Cloud-Sync gehören noch nicht zu OpenBook. Heute liegen deine Seiten lokal auf dem Server, mit dem du dich verbindest."
2345
+ },
2346
+ signin: {
2347
+ title: "Anmeldung & E-Mail",
2348
+ description: "E-Mail und verbundene Anmeldung (Google, GitHub, Apple) kommen mit den Konten. Es gibt noch nichts, wo man sich anmelden könnte."
2349
+ },
2350
+ support: {
2351
+ title: "OpenBook unterstützen",
2352
+ description: "OpenBook ist unabhängig und quelloffen. Es zu teilen und Feedback zu senden hilft beim Wachsen. Sponsoring-Optionen sind in Arbeit."
2353
+ }
2354
+ },
2355
+ connection: {
2356
+ title: "Verbindung",
2357
+ description: "Wähle, wo dieses Gerät Seiten liest und schreibt.",
2358
+ server: "Server",
2359
+ usingLocal: "Es wird der lokale Server dieses Geräts verwendet.",
2360
+ usingRemote: "Es wird der entfernte Server verwendet",
2361
+ remoteUrl: "URL des entfernten Servers",
2362
+ remoteUrlPlaceholder: "https://mein-server.example:4319",
2363
+ connect: "Verbinden",
2364
+ useLocal: "Lokal verwenden",
2365
+ localServer: "Lokaler Server",
2366
+ running: "Läuft auf",
2367
+ stopped: "Gestoppt.",
2368
+ checking: "Wird geprüft…",
2369
+ unmanaged: "Von der Entwicklungsumgebung verwaltet — Start/Stopp ist hier nicht verfügbar.",
2370
+ start: "Starten",
2371
+ stop: "Stoppen",
2372
+ refresh: "Aktualisieren"
2373
+ },
2374
+ integrations: {
2375
+ title: "Integrationen",
2376
+ description: "Verbinde OpenBook mit anderen Tools. Integrationen sind noch nicht verfügbar — hier werden sie zu finden sein."
2377
+ },
2378
+ admin: {
2379
+ title: "Verwaltung",
2380
+ description: "Sicherung, Wiederherstellung und Wartung des Arbeitsbereichs.",
2381
+ dangerZone: "Gefahrenzone",
2382
+ dangerZoneHint: "Diese Aktionen betreffen die lokalen Daten dieses Geräts, nicht deine Seiten.",
2383
+ resetPrefs: "Einstellungen & Layout zurücksetzen",
2384
+ resetPrefsHint: "Standard-Darstellung, -Sprache und -Layout auf diesem Gerät wiederherstellen. Deine Seiten und Arbeitsbereiche bleiben erhalten.",
2385
+ resetPrefsButton: "Zurücksetzen",
2386
+ resetConfirmTitle: "Einstellungen & Layout zurücksetzen?",
2387
+ resetConfirmBody: "Dies löscht Darstellungs-, Sprach- und Layout-Einstellungen auf diesem Gerät und lädt neu. Deine Seiten und Arbeitsbereiche sind nicht betroffen.",
2388
+ resetConfirmButton: "Zurücksetzen"
2389
+ },
2390
+ properties: {
2391
+ owner: "Verantwortlich",
2392
+ setOwner: "Verantwortliche Person festlegen",
2393
+ ownerPlaceholder: "Name eingeben…",
2394
+ you: "Du",
2395
+ clear: "Entfernen",
2396
+ verification: "Verifizierung",
2397
+ verified: "Verifiziert",
2398
+ verify: "Verifizieren",
2399
+ unverify: "Entfernen",
2400
+ verifiedBy: "von {name}",
2401
+ backlinks: "Backlinks",
2402
+ noBacklinks: "Noch keine Backlinks",
2403
+ refresh: "Aktualisieren"
2404
+ }
2405
+ }, Si = {
2406
+ common: {
2407
+ cancel: "キャンセル",
2408
+ close: "閉じる",
2409
+ delete: "削除",
2410
+ save: "保存",
2411
+ add: "追加",
2412
+ remove: "削除",
2413
+ untitled: "無題",
2414
+ settings: "設定"
2415
+ },
2416
+ settings: {
2417
+ title: "設定",
2418
+ comingSoon: "この設定は近日公開予定です。",
2419
+ fullscreen: "全画面",
2420
+ exitFullscreen: "全画面を終了",
2421
+ enterFullscreen: "全画面",
2422
+ closeSettings: "設定を閉じる",
2423
+ section: {
2424
+ preferences: "環境設定",
2425
+ account: "アカウント",
2426
+ workspace: "ワークスペース"
2427
+ },
2428
+ tab: {
2429
+ general: "一般",
2430
+ profile: "プロフィール",
2431
+ appearance: "外観",
2432
+ customisation: "カスタマイズ",
2433
+ signup: "登録",
2434
+ signin: "サインインとメール",
2435
+ support: "OpenBook を支援",
2436
+ connection: "接続",
2437
+ integrations: "連携",
2438
+ extensions: "拡張機能",
2439
+ ai: "AI",
2440
+ admin: "管理"
2441
+ }
2442
+ },
2443
+ appearance: {
2444
+ title: "外観",
2445
+ colorMode: "カラーモード",
2446
+ light: "ライト",
2447
+ dark: "ダーク",
2448
+ system: "システム",
2449
+ colorScheme: "カラースキーム",
2450
+ colorTheme: "カラーテーマ",
2451
+ colorThemeHint: "アプリ全体のアクセントカラーを選択します。"
2452
+ },
2453
+ theme: {
2454
+ default: "デフォルト",
2455
+ sandstone: "サンドストーン",
2456
+ slate: "スレート",
2457
+ ocean: "オーシャン",
2458
+ forest: "フォレスト",
2459
+ violet: "バイオレット",
2460
+ sunset: "サンセット",
2461
+ rose: "ローズ",
2462
+ graphite: "グラファイト"
2463
+ },
2464
+ nav: {
2465
+ favorites: "お気に入り",
2466
+ recents: "最近",
2467
+ suggested: "おすすめ",
2468
+ home: "ホーム",
2469
+ templates: "テンプレート",
2470
+ more: "その他の操作",
2471
+ pages: "ページ",
2472
+ newPage: "新規ページ",
2473
+ newDatabase: "新規データベース",
2474
+ back: "戻る",
2475
+ forward: "進む",
2476
+ goBack: "戻る",
2477
+ goForward: "進む",
2478
+ toggleSidebar: "サイドバーを切り替え",
2479
+ trash: "ゴミ箱"
2480
+ },
2481
+ tabs: {
2482
+ new: "新規タブ",
2483
+ close: "タブを閉じる"
2484
+ },
2485
+ menu: {
2486
+ openTab: "新しいタブで開く",
2487
+ openWindow: "新しいウィンドウで開く",
2488
+ addSubpage: "サブページを追加",
2489
+ addDatabase: "データベースを追加",
2490
+ moveToTrash: "ゴミ箱へ移動",
2491
+ viewOptions: "表示オプション",
2492
+ options: "メニュー",
2493
+ fullWidth: "全幅",
2494
+ favourite: "お気に入り",
2495
+ favorite: "お気に入りに追加",
2496
+ unfavorite: "お気に入りから削除",
2497
+ openSplit: "分割ビューで開く",
2498
+ rename: "名前を変更",
2499
+ copyLink: "リンクをコピー",
2500
+ duplicate: "複製",
2501
+ sectionPage: "ページ",
2502
+ block: {
2503
+ sectionBlock: "ブロック",
2504
+ moveUp: "上へ移動",
2505
+ moveDown: "下へ移動",
2506
+ duplicate: "複製",
2507
+ deleteBlock: "ブロックを削除",
2508
+ linkToPage: "ページにリンク"
2509
+ }
2510
+ },
2511
+ command: {
2512
+ title: "コマンドパレット",
2513
+ search: "検索",
2514
+ noPages: "ページがまだありません",
2515
+ groupFavorites: "お気に入り",
2516
+ groupRecent: "最近",
2517
+ groupCreate: "作成",
2518
+ groupView: "表示",
2519
+ groupNavigation: "ナビゲーション",
2520
+ groupApp: "アプリ",
2521
+ favorite: "お気に入りに追加",
2522
+ unfavorite: "お気に入りから削除",
2523
+ newDatabase: "新しいデータベース",
2524
+ openTrash: "ゴミ箱を開く",
2525
+ toggleSidebar: "サイドバーを切り替え",
2526
+ toggleFullWidth: "全幅表示を切り替え",
2527
+ themeToLight: "ライトモードに切り替え",
2528
+ themeToDark: "ダークモードに切り替え",
2529
+ splitView: "分割ビュー",
2530
+ closeSplit: "分割ビューを閉じる",
2531
+ goBack: "戻る",
2532
+ goForward: "進む",
2533
+ placeholder: "ページを検索またはコマンドを実行…",
2534
+ noResults: "結果がありません。",
2535
+ pages: "ページ",
2536
+ actions: "アクション",
2537
+ createPage: "新規ページを作成",
2538
+ insertSample: "サンプル文書を挿入",
2539
+ newFromTemplate: "テンプレートから作成",
2540
+ aiSearch: "AIでノートを検索",
2541
+ askAssistant: "アシスタントに質問",
2542
+ openSettings: "設定を開く",
2543
+ current: "現在"
2544
+ },
2545
+ page: {
2546
+ saving: "保存中…",
2547
+ saved: "保存済み",
2548
+ saveFailed: "保存できませんでした",
2549
+ actions: "ページ操作",
2550
+ delete: "ページを削除",
2551
+ titleLabel: "ページタイトル",
2552
+ changeIcon: "ページアイコンを変更",
2553
+ editorPlaceholder: "入力するか、Tab でブロックを選択…",
2554
+ export: "エクスポート",
2555
+ exportMarkdown: "Markdown (.md)",
2556
+ exportHtml: "インタラクティブ HTML",
2557
+ exportPdfPaged: "PDF — ページ区切り",
2558
+ exportPdfContinuous: "PDF — 連続",
2559
+ exportPdfSlides: "スライド(PDF)",
2560
+ exportHtmlSlides: "スライド(HTML)",
2561
+ present: "プレゼン",
2562
+ presentFull: "全画面",
2563
+ presentPresenter: "発表者ビュー",
2564
+ exportPlugin: "プラグイン(.zip)",
2565
+ exportPluginFailed: "このページはプラグインとしてエクスポートできません",
2566
+ exportPluginFailedOk: "OK"
2567
+ },
2568
+ home: {
2569
+ morning: "おはようございます",
2570
+ afternoon: "こんにちは",
2571
+ evening: "こんばんは",
2572
+ customize: "ホームをカスタマイズ",
2573
+ widgetActions: "クイックアクション",
2574
+ widgetRecents: "続きから",
2575
+ widgetFavorites: "お気に入り",
2576
+ widgetEdited: "最近編集",
2577
+ justNow: "たった今"
2578
+ },
2579
+ flow: {
2580
+ title: "データフロー",
2581
+ open: "データフロー表示",
2582
+ empty: "このページにはまだリアクティブな要素がありません",
2583
+ emptyHint: "名前付き入力・ライブコード・チャート・ステータスライトを追加すると、その配線がライブグラフとして表示されます。"
2584
+ },
2585
+ mention: {
2586
+ label: "ページにリンク",
2587
+ create: "ページ「{name}」を作成",
2588
+ empty: "ページがありません — 入力を続けると作成できます。"
2589
+ },
2590
+ emoji: {
2591
+ label: "絵文字",
2592
+ search: "絵文字を検索"
2593
+ },
2594
+ confirm: {
2595
+ trashTitle: "このページをゴミ箱へ移動しますか?",
2596
+ trashBody: "後でゴミ箱から復元できます。",
2597
+ trashConfirm: "ゴミ箱へ移動"
2598
+ },
2599
+ backup: {
2600
+ heading: "バックアップと復元",
2601
+ intro: "ワークスペース全体を 1 つのファイルに書き出すか、復元します。復元するページを選べます。",
2602
+ export: "バックアップを書き出す",
2603
+ exporting: "書き出し中…",
2604
+ restore: "バックアップを復元…",
2605
+ exported: "{count} ページを書き出しました。",
2606
+ exportFailed: "書き出しに失敗しました: {error}",
2607
+ readFailed: "バックアップを読み込めませんでした: {error}",
2608
+ restored: "{count} ページを復元しました{detail}。",
2609
+ restoreFailed: "復元に失敗しました: {error}",
2610
+ added: "{count} 件追加",
2611
+ overwrittenCount: "{count} 件上書き",
2612
+ renamedCount: "{count} 件名前変更",
2613
+ dialog: {
2614
+ title: "バックアップを復元",
2615
+ summary: "{count} ページ。復元する項目を選択してください。",
2616
+ summaryDated: "{count} ページ · {date} に書き出し。復元する項目を選択してください。",
2617
+ selected: "{count} 件選択中",
2618
+ all: "すべて",
2619
+ none: "なし",
2620
+ overwrite: "既存のページを上書き",
2621
+ overwriteHint: "ID で上書き復元します。オフ(既定)ではコピーとして取り込み、名前が重複すると接尾辞を付けます。",
2622
+ restoreN: "{count} 件を復元",
2623
+ confirmTitle: "既存の {count} ページを上書きしますか?",
2624
+ confirmBody: "上書き復元すると {count} ページの現在の内容が置き換えられます。元に戻せません。",
2625
+ confirmBodyNone: "一致する既存ページはありません — 新規ページとして追加されます。",
2626
+ confirmOverwrite: "上書き"
2627
+ }
2628
+ },
2629
+ workspace: {
2630
+ workspaces: "ワークスペース",
2631
+ addWorkspace: "ワークスペースを追加…",
2632
+ addTitle: "ワークスペースを追加",
2633
+ addDescription: "別の OpenBook サーバーに接続します。切り替えるとこのデバイスはそのサーバーを参照します。",
2634
+ icon: "アイコン",
2635
+ name: "名前",
2636
+ serverUrl: "サーバー URL",
2637
+ namePlaceholder: "ホーム Wiki",
2638
+ urlPlaceholder: "https://my-server.example:4319",
2639
+ addButton: "ワークスペースを追加",
2640
+ urlRequired: "このワークスペースのサーバー URL を入力してください。",
2641
+ urlInvalid: "有効な URL ではないようです。",
2642
+ removeWorkspace: "{name} を削除",
2643
+ thisDevice: "このデバイス"
2644
+ },
2645
+ ai: {
2646
+ description: "オプションのローカルモデルで、ノート検索・タスク分解・文書補完ができます。すべて端末内で動作します。",
2647
+ providerLabel: "エンジン",
2648
+ provider: {
2649
+ off: "オフ",
2650
+ offHint: "モデルなし。ノート検索はキーワードランキングで動作します。",
2651
+ llama: "内蔵 (llama.cpp)",
2652
+ llamaHint: "すべてのプラットフォームで OpenBook 内で動作。下からモデルをダウンロード。",
2653
+ mlx: "MLX (Apple Silicon)",
2654
+ mlxHint: "mlx_lm.server を使い、Apple Silicon で最速のローカル推論。",
2655
+ openai: "ローカルサーバー (OpenAI互換)",
2656
+ openaiHint: "Ollama、LM Studio、llama-server など互換エンドポイント。"
2657
+ },
2658
+ ready: "エンジン準備完了 · {embeddings}",
2659
+ semantic: "セマンティック検索が有効",
2660
+ lexicalOnly: "キーワード検索のみ",
2661
+ notReady: "エンジンが準備できていません。",
2662
+ model: "モデル",
2663
+ modelFile: "モデルファイル (GGUF)",
2664
+ modelFileHint: "サーバーのモデルディレクトリ内のファイル。",
2665
+ downloadDefault: "推奨モデルをダウンロード (~1 GB)",
2666
+ downloading: "ダウンロード中… {progress}%",
2667
+ downloadingNoPct: "ダウンロード中…",
2668
+ downloadDone: "モデルをダウンロードしました。",
2669
+ endpoint: "エンドポイント",
2670
+ baseUrl: "サーバーURL",
2671
+ mlxUrlHint: "mlx_lm.server のアドレス。可能なら自動起動します。",
2672
+ openaiUrlHint: "OpenAI互換サーバーのアドレス。",
2673
+ modelName: "モデル",
2674
+ mlxModelHint: "MLXモデルID。例: mlx-community/Qwen2.5-1.5B-Instruct-4bit",
2675
+ openaiModelHint: "サーバーが想定するモデル名。",
2676
+ search: "ノート検索",
2677
+ searchHint: "ノートは自動でインデックスされます。結果が古い場合は再構築してください。",
2678
+ reindex: "インデックス再構築",
2679
+ indexing: "インデックス中…",
2680
+ indexed: "{pages} ページをインデックス済み",
2681
+ notIndexed: "初回検索時にインデックスを作成します。"
2682
+ },
2683
+ aiSearch: {
2684
+ title: "ノートを検索",
2685
+ semantic: "セマンティック",
2686
+ lexical: "キーワード",
2687
+ placeholder: "何を探していますか?",
2688
+ empty: "一致するノートがありません。",
2689
+ hint: "全ページの内容を検索します。ローカルモデルで精度が向上します。"
2690
+ },
2691
+ agent: {
2692
+ title: "アシスタント",
2693
+ hint: "ノートについて質問できます。アシスタントはページの検索・閲覧・作成ができます。",
2694
+ placeholder: "何でも聞いてください…",
2695
+ thinking: "処理中…",
2696
+ reset: "新しい会話",
2697
+ close: "アシスタントを閉じる",
2698
+ error: "問題が発生しました: {error}",
2699
+ notReady: "アシスタントにはモデルが必要です。設定 → AI で有効にしてください。",
2700
+ openSettings: "AI設定を開く",
2701
+ send: "送信",
2702
+ stop: "停止",
2703
+ inputHint: "Enterで送信 · Shift+Enterで改行",
2704
+ suggestion1: "どんなページがありますか?",
2705
+ suggestion2: "計画に関するノートを探して",
2706
+ suggestion3: "今日の計画ページを作成して",
2707
+ tool: {
2708
+ search_notes: "ノートを検索",
2709
+ read_page: "ページを読み取り",
2710
+ list_pages: "ページ一覧を取得",
2711
+ create_page: "ページを作成",
2712
+ append_to_page: "ページに追記"
2713
+ }
2714
+ },
2715
+ slash: {
2716
+ text: {
2717
+ label: "テキスト",
2718
+ hint: "プレーンな段落"
2719
+ },
2720
+ h1: {
2721
+ label: "見出し 1",
2722
+ hint: "大見出し"
2723
+ },
2724
+ h2: {
2725
+ label: "見出し 2",
2726
+ hint: "中見出し"
2727
+ },
2728
+ h3: {
2729
+ label: "見出し 3",
2730
+ hint: "小見出し"
2731
+ },
2732
+ bullet: {
2733
+ label: "箇条書き",
2734
+ hint: "シンプルなリスト"
2735
+ },
2736
+ number: {
2737
+ label: "番号付きリスト",
2738
+ hint: "順序付きリスト"
2739
+ },
2740
+ todo: {
2741
+ label: "To-do",
2742
+ hint: "チェックボックス項目"
2743
+ },
2744
+ quote: {
2745
+ label: "引用",
2746
+ hint: "強調引用"
2747
+ },
2748
+ callout: {
2749
+ label: "コールアウト",
2750
+ hint: "強調メモ"
2751
+ },
2752
+ code: {
2753
+ label: "コード",
2754
+ hint: "等幅ブロック"
2755
+ },
2756
+ livecode: {
2757
+ label: "ライブコード",
2758
+ hint: "入力値を計算。出力に名前を付けて連鎖できます"
2759
+ },
2760
+ divider: {
2761
+ label: "区切り線",
2762
+ hint: "水平線"
2763
+ },
2764
+ table: {
2765
+ label: "テーブル",
2766
+ hint: "はじめは 3 × 3"
2767
+ },
2768
+ cols2: {
2769
+ label: "2 列",
2770
+ hint: "横並びレイアウト"
2771
+ },
2772
+ cols3: {
2773
+ label: "3 列",
2774
+ hint: "3 列レイアウト"
2775
+ },
2776
+ cols4: {
2777
+ label: "4 列",
2778
+ hint: "4 列レイアウト"
2779
+ },
2780
+ "ai-continue": {
2781
+ label: "続きを書く",
2782
+ hint: "AI がここから続けます"
2783
+ },
2784
+ "ai-tasks": {
2785
+ label: "タスクに分解",
2786
+ hint: "AI が To-do を下書きします"
2787
+ },
2788
+ custom: {
2789
+ slider: {
2790
+ label: "スライダー",
2791
+ hint: "名前付きライブ入力"
2792
+ },
2793
+ formula: {
2794
+ label: "数式",
2795
+ hint: "入力値のライブ計算"
2796
+ },
2797
+ number: {
2798
+ label: "数値ステッパー",
2799
+ hint: "− / + ボタン付きの名前付き数値"
2800
+ },
2801
+ textfield: {
2802
+ label: "テキスト欄",
2803
+ hint: "名前付きテキスト入力"
2804
+ },
2805
+ radio: {
2806
+ label: "ラジオグループ",
2807
+ hint: "選択肢からひとつ選ぶ"
2808
+ },
2809
+ checklist: {
2810
+ label: "選択チェックリスト",
2811
+ hint: "選択肢から複数選ぶ"
2812
+ },
2813
+ dropdown: {
2814
+ label: "ドロップダウン",
2815
+ hint: "リストから1つ選択"
2816
+ },
2817
+ toggle: {
2818
+ label: "トグルスイッチ",
2819
+ hint: "名前付きオン/オフスイッチ"
2820
+ },
2821
+ location: {
2822
+ label: "場所",
2823
+ hint: "座標つきの場所"
2824
+ },
2825
+ actionbutton: {
2826
+ label: "ボタン",
2827
+ hint: "入力の設定・増減・切替、またはリンクを開く"
2828
+ },
2829
+ kitchart: {
2830
+ label: "チャート",
2831
+ hint: "折れ線・棒・円・散布・ファネル — 入力にライブ連動"
2832
+ },
2833
+ statuslight: {
2834
+ label: "ステータスライト",
2835
+ hint: "ライブ値から緑 / 黄 / 赤"
2836
+ },
2837
+ tooltipcard: {
2838
+ label: "ツールチップ",
2839
+ hint: "ホバーで説明が出る用語"
2840
+ },
2841
+ linkcard: {
2842
+ label: "リンクカード",
2843
+ hint: "URL を開くタイトル付きカード"
2844
+ }
2845
+ }
2846
+ },
2847
+ extensions: {
2848
+ description: "プラグインで OpenBook を拡張:TypeScript ソースの zip からインストールし、ブロック・コマンド・連携を追加します。",
2849
+ install: ".zip からインストール…",
2850
+ installing: "インストール中…",
2851
+ installHint: "openbook.json と TypeScript ソースを含む zip。",
2852
+ empty: "拡張機能はありません",
2853
+ emptyHint: "zip からインストールすると、エディタのブロックやパレットのコマンド、連携を追加できます。",
2854
+ verified: "検証済み",
2855
+ verifiedBy: "{registry} が署名・検証済み",
2856
+ unverified: "未検証",
2857
+ unverifiedHint: "信頼するレジストリの署名がありません。ライブコードと同じ権限で動作します。",
2858
+ loadError: "読み込み失敗: {error}",
2859
+ enable: "{name} を有効化",
2860
+ remove: "{name} を削除",
2861
+ trustNote: "拡張機能はドキュメントのライブコードと同じ権限で動作します。「検証済み」は信頼するレジストリがこの内容に署名したことを意味します — 出所の証明であり、サンドボックスではありません。",
2862
+ registries: "信頼するレジストリ",
2863
+ registriesHint: "これらの鍵で署名された拡張機能は「検証済み」と表示されます。",
2864
+ builtIn: "組み込み",
2865
+ registryName: "レジストリ名",
2866
+ registryKey: "Ed25519 公開鍵(base64)",
2867
+ addRegistry: "レジストリを信頼",
2868
+ removeRegistry: "レジストリ {name} を削除",
2869
+ registryKeyInvalid: "32 バイトの Ed25519 公開鍵を base64 で入力してください。"
2870
+ },
2871
+ templates: {
2872
+ title: "テンプレートから始める",
2873
+ description: "構成済みのページ — 選んで自分用に編集できます。",
2874
+ creating: "作成中…",
2875
+ groceryTracker: {
2876
+ name: "食料品の価格トラッカー",
2877
+ description: "毎週の買い物かごを店ごとに比較 — ライブチャート、予算ライト、計算はコードブロックに。"
2878
+ },
2879
+ taskBoard: {
2880
+ name: "プロジェクトタスクボード",
2881
+ description: "ステータス・優先度・担当・工数つきのタスク — ステータスで分けたかんばんボードとテーブル。"
2882
+ },
2883
+ readingList: {
2884
+ name: "読書リスト",
2885
+ description: "本棚ごとに並ぶ本のギャラリー — 著者と星評価つき、テーブルビューも。"
2886
+ },
2887
+ projectIntake: {
2888
+ name: "プロジェクト受付",
2889
+ description: "段階ごとに解放される要件ブリーフと、労力対効果のライブ優先度づけ。"
2890
+ },
2891
+ savingsPlanner: {
2892
+ name: "貯蓄と投資",
2893
+ description: "まず生活防衛資金をチェック、次にスライダーが目標へ向けた複利のライブ予測を更新。"
2894
+ },
2895
+ roadmap: {
2896
+ name: "プロダクトロードマップ",
2897
+ description: "タイムラインとボードで計画を管理。どちらも領域ごとのスイムレーンに分割。"
2898
+ },
2899
+ fieldMap: {
2900
+ name: "拠点マップ",
2901
+ description: "オフィスやパートナーを地図にピン留めし、地域ごとに色分け — テーブルビュー付き。"
2902
+ }
2903
+ },
2904
+ blocks: {
2905
+ subpagePage: "ページ",
2906
+ subpageDatabase: "データベース",
2907
+ expression: "式",
2908
+ chart: "チャート",
2909
+ slider: "スライダー",
2910
+ sliderEdit: "スライダーを編集",
2911
+ creating: "{kind}を作成中…",
2912
+ referenceHint: "セルの参照",
2913
+ chartPick: "プロットするセルを 1 つ以上選択",
2914
+ chartNoData: "選択したセルに数値配列データがありません",
2915
+ chartPlot: "プロット",
2916
+ chartAnd: "と",
2917
+ chartAddSeries: "系列を追加",
2918
+ chartRemoveSeries: "系列を削除",
2919
+ chartPickCell: "— セルを選択 —",
2920
+ table: "テーブル",
2921
+ todo: "To-Do リスト",
2922
+ listUnordered: "箇条書きリスト",
2923
+ listOrdered: "番号付きリスト",
2924
+ callout: "コールアウト",
2925
+ calloutInfo: "情報",
2926
+ calloutWarning: "警告",
2927
+ calloutSuccess: "成功",
2928
+ calloutDanger: "危険",
2929
+ calloutEmoji: "絵文字を変更",
2930
+ calloutPlaceholder: "コールアウトを入力…",
2931
+ accordion: "トグル",
2932
+ accordionToggle: "展開または折りたたみ",
2933
+ accordionTitlePlaceholder: "トグルのタイトル",
2934
+ accordionContentPlaceholder: "非表示のコンテンツ…",
2935
+ divider: "区切り線",
2936
+ dividerLine: "実線",
2937
+ dividerDashed: "破線",
2938
+ dividerDotted: "点線",
2939
+ dividerThick: "太線",
2940
+ dividerLabeled: "ラベル付き",
2941
+ dividerLabelPlaceholder: "ラベル",
2942
+ button: "ボタン",
2943
+ buttonDefault: "ボタン",
2944
+ buttonLabelPlaceholder: "ボタンのラベル",
2945
+ buttonEdit: "ボタンを編集",
2946
+ buttonUrlPlaceholder: "https://… または /page",
2947
+ toc: "目次",
2948
+ tocTitle: "このページの内容",
2949
+ tocEmpty: "見出しがありません — 見出しを追加すると目次が作成されます。"
2950
+ },
2951
+ general: {
2952
+ title: "一般",
2953
+ description: "言語とアプリの動作。",
2954
+ languageSection: "言語",
2955
+ language: "言語",
2956
+ languageHint: "アプリの表示言語。",
2957
+ behavior: "動作",
2958
+ confirmTrash: "ゴミ箱へ移動する前に確認",
2959
+ confirmTrashHint: "ページをゴミ箱へ移動する前に確認します。",
2960
+ spellcheck: "入力中にスペルチェック",
2961
+ spellcheckHint: "エディターでスペルミスの単語に下線を引きます。"
2962
+ },
2963
+ profile: {
2964
+ title: "プロフィール",
2965
+ description: "このデバイスで OpenBook 上にどう表示されるか。",
2966
+ identity: "アイデンティティ",
2967
+ name: "名前",
2968
+ nameHint: "フルネーム。",
2969
+ namePlaceholder: "Ada Lovelace",
2970
+ displayName: "表示名",
2971
+ displayNameHint: "アプリ内で表示される短い名前。",
2972
+ displayNamePlaceholder: "ada",
2973
+ avatar: "アバター",
2974
+ avatarHint: "初期設定はイニシャル — 絵文字を選ぶか画像をアップロードできます。",
2975
+ avatarEmoji: "絵文字を選ぶ",
2976
+ avatarUpload: "画像をアップロード…",
2977
+ avatarReset: "イニシャルを使う",
2978
+ editProfile: "プロフィールを編集",
2979
+ aboutApp: "OpenBook について",
2980
+ bio: "自己紹介",
2981
+ bioHint: "自分について一言、二言。",
2982
+ bioPlaceholder: "数学者であり作家。",
2983
+ preview: "プレビュー",
2984
+ anonymous: "匿名"
2985
+ },
2986
+ customisation: {
2987
+ title: "カスタマイズとショートカット",
2988
+ description: "レイアウトを調整し、キーボードショートカットを確認します。",
2989
+ layout: "レイアウト",
2990
+ fullWidth: "全幅エディター",
2991
+ fullWidthHint: "中央寄せの列ではなくページ全幅を使用します。",
2992
+ autoHideSidebar: "サイドバーを自動的に隠す",
2993
+ autoHideSidebarHint: "画面の端に移動するまでサイドバーを折りたたみます。",
2994
+ shortcuts: "キーボードショートカット",
2995
+ shortcutsHint: "アプリのどこでも使えます。",
2996
+ shortcut: {
2997
+ newPage: "新しいページを作成",
2998
+ toggleSidebar: "サイドバーの表示を切り替え",
2999
+ fullWidth: "全幅表示を切り替え",
3000
+ theme: "ライト/ダークを切り替え",
3001
+ back: "戻る",
3002
+ forward: "進む",
3003
+ openSettings: "設定を開く",
3004
+ trash: "ゴミ箱を開く",
3005
+ commandPalette: "コマンドパレットを開く",
3006
+ closeOverlay: "ダイアログやメニューを閉じる",
3007
+ slashMenu: "ブロックを挿入",
3008
+ mention: "ページをリンクまたはメンション"
3009
+ }
3010
+ },
3011
+ account: {
3012
+ signup: {
3013
+ title: "アカウントを作成",
3014
+ description: "アカウントとクラウド同期はまだ OpenBook の機能ではありません。現在、ページは接続先のサーバーにローカルで保存されます。"
3015
+ },
3016
+ signin: {
3017
+ title: "サインインとメール",
3018
+ description: "メールと連携サインイン(Google、GitHub、Apple)はアカウントとともに登場します。まだサインインできる先はありません。"
3019
+ },
3020
+ support: {
3021
+ title: "OpenBook を支援",
3022
+ description: "OpenBook は独立したオープンソースです。共有やフィードバックが成長を助けます。スポンサーの仕組みも準備中です。"
3023
+ }
3024
+ },
3025
+ connection: {
3026
+ title: "接続",
3027
+ description: "このデバイスがページを読み書きする場所を選びます。",
3028
+ server: "サーバー",
3029
+ usingLocal: "現在、このデバイスのローカルサーバーを使用しています。",
3030
+ usingRemote: "現在、リモートサーバーを使用しています:",
3031
+ remoteUrl: "リモートサーバー URL",
3032
+ remoteUrlPlaceholder: "https://my-server.example:4319",
3033
+ connect: "接続",
3034
+ useLocal: "ローカルを使用",
3035
+ localServer: "ローカルサーバー",
3036
+ running: "実行中:",
3037
+ stopped: "停止中。",
3038
+ checking: "確認中…",
3039
+ unmanaged: "開発環境によって管理されています — ここでは開始/停止できません。",
3040
+ start: "開始",
3041
+ stop: "停止",
3042
+ refresh: "更新"
3043
+ },
3044
+ integrations: {
3045
+ title: "連携",
3046
+ description: "OpenBook を他のツールと連携します。連携はまだ利用できません — ここに表示される予定です。"
3047
+ },
3048
+ admin: {
3049
+ title: "管理",
3050
+ description: "バックアップ、復元、ワークスペースのメンテナンス。",
3051
+ dangerZone: "危険ゾーン",
3052
+ dangerZoneHint: "これらの操作はこのデバイスのローカルデータに影響します。ページには影響しません。",
3053
+ resetPrefs: "設定とレイアウトをリセット",
3054
+ resetPrefsHint: "このデバイスの外観・言語・レイアウトを既定に戻します。ページとワークスペースは保持されます。",
3055
+ resetPrefsButton: "リセット",
3056
+ resetConfirmTitle: "設定とレイアウトをリセットしますか?",
3057
+ resetConfirmBody: "このデバイスの外観・言語・レイアウト設定を消去して再読み込みします。ページとワークスペースには影響しません。",
3058
+ resetConfirmButton: "リセット"
3059
+ },
3060
+ properties: {
3061
+ owner: "担当者",
3062
+ setOwner: "担当者を設定",
3063
+ ownerPlaceholder: "名前を入力…",
3064
+ you: "自分",
3065
+ clear: "クリア",
3066
+ verification: "検証",
3067
+ verified: "検証済み",
3068
+ verify: "検証する",
3069
+ unverify: "解除",
3070
+ verifiedBy: "{name} による",
3071
+ backlinks: "バックリンク",
3072
+ noBacklinks: "バックリンクはまだありません",
3073
+ refresh: "更新"
3074
+ }
3075
+ }, Ci = {
3076
+ common: {
3077
+ cancel: "取消",
3078
+ close: "关闭",
3079
+ delete: "删除",
3080
+ save: "保存",
3081
+ add: "添加",
3082
+ remove: "移除",
3083
+ untitled: "无标题",
3084
+ settings: "设置"
3085
+ },
3086
+ settings: {
3087
+ title: "设置",
3088
+ comingSoon: "此设置即将推出。",
3089
+ fullscreen: "全屏",
3090
+ exitFullscreen: "退出全屏",
3091
+ enterFullscreen: "全屏",
3092
+ closeSettings: "关闭设置",
3093
+ section: {
3094
+ preferences: "偏好设置",
3095
+ account: "账户",
3096
+ workspace: "工作区"
3097
+ },
3098
+ tab: {
3099
+ general: "通用",
3100
+ profile: "个人资料",
3101
+ appearance: "外观",
3102
+ customisation: "自定义",
3103
+ signup: "注册",
3104
+ signin: "登录与邮箱",
3105
+ support: "支持 OpenBook",
3106
+ connection: "连接",
3107
+ integrations: "集成",
3108
+ extensions: "扩展",
3109
+ ai: "AI",
3110
+ admin: "管理"
3111
+ }
3112
+ },
3113
+ appearance: {
3114
+ title: "外观",
3115
+ colorMode: "颜色模式",
3116
+ light: "浅色",
3117
+ dark: "深色",
3118
+ system: "系统",
3119
+ colorScheme: "配色方案",
3120
+ colorTheme: "配色主题",
3121
+ colorThemeHint: "选择整个应用使用的强调色。"
3122
+ },
3123
+ theme: {
3124
+ default: "默认",
3125
+ sandstone: "砂岩",
3126
+ slate: "板岩",
3127
+ ocean: "海洋",
3128
+ forest: "森林",
3129
+ violet: "紫罗兰",
3130
+ sunset: "日落",
3131
+ rose: "玫瑰",
3132
+ graphite: "石墨"
3133
+ },
3134
+ nav: {
3135
+ favorites: "收藏",
3136
+ recents: "最近",
3137
+ suggested: "推荐",
3138
+ home: "主页",
3139
+ templates: "模板",
3140
+ more: "更多操作",
3141
+ pages: "页面",
3142
+ newPage: "新建页面",
3143
+ newDatabase: "新建数据库",
3144
+ back: "后退",
3145
+ forward: "前进",
3146
+ goBack: "后退",
3147
+ goForward: "前进",
3148
+ toggleSidebar: "切换侧边栏",
3149
+ trash: "回收站"
3150
+ },
3151
+ tabs: {
3152
+ new: "新建标签页",
3153
+ close: "关闭标签页"
3154
+ },
3155
+ menu: {
3156
+ openTab: "在新标签页中打开",
3157
+ openWindow: "在新窗口中打开",
3158
+ addSubpage: "添加子页面",
3159
+ addDatabase: "添加数据库",
3160
+ moveToTrash: "移到回收站",
3161
+ viewOptions: "视图选项",
3162
+ options: "菜单",
3163
+ fullWidth: "全宽",
3164
+ favourite: "收藏",
3165
+ favorite: "添加到收藏",
3166
+ unfavorite: "从收藏中移除",
3167
+ openSplit: "在拆分视图中打开",
3168
+ rename: "重命名",
3169
+ copyLink: "复制链接",
3170
+ duplicate: "创建副本",
3171
+ sectionPage: "页面",
3172
+ block: {
3173
+ sectionBlock: "块",
3174
+ moveUp: "上移",
3175
+ moveDown: "下移",
3176
+ duplicate: "复制",
3177
+ deleteBlock: "删除块",
3178
+ linkToPage: "链接到页面"
3179
+ }
3180
+ },
3181
+ command: {
3182
+ title: "命令面板",
3183
+ search: "搜索",
3184
+ noPages: "还没有页面",
3185
+ groupFavorites: "收藏",
3186
+ groupRecent: "最近",
3187
+ groupCreate: "创建",
3188
+ groupView: "视图",
3189
+ groupNavigation: "导航",
3190
+ groupApp: "应用",
3191
+ favorite: "添加到收藏",
3192
+ unfavorite: "从收藏中移除",
3193
+ newDatabase: "新建数据库",
3194
+ openTrash: "打开回收站",
3195
+ toggleSidebar: "切换侧边栏",
3196
+ toggleFullWidth: "切换全宽",
3197
+ themeToLight: "切换到浅色模式",
3198
+ themeToDark: "切换到深色模式",
3199
+ splitView: "拆分视图",
3200
+ closeSplit: "关闭拆分视图",
3201
+ goBack: "后退",
3202
+ goForward: "前进",
3203
+ placeholder: "搜索页面或运行命令…",
3204
+ noResults: "没有结果。",
3205
+ pages: "页面",
3206
+ actions: "操作",
3207
+ createPage: "新建页面",
3208
+ insertSample: "插入示例文档",
3209
+ newFromTemplate: "从模板新建",
3210
+ aiSearch: "用 AI 搜索笔记",
3211
+ askAssistant: "询问助手",
3212
+ openSettings: "打开设置",
3213
+ current: "当前"
3214
+ },
3215
+ page: {
3216
+ saving: "保存中…",
3217
+ saved: "已保存",
3218
+ saveFailed: "无法保存",
3219
+ actions: "页面操作",
3220
+ delete: "删除页面",
3221
+ titleLabel: "页面标题",
3222
+ changeIcon: "更改页面图标",
3223
+ editorPlaceholder: "输入内容,或按 Tab 选择块…",
3224
+ export: "导出",
3225
+ exportMarkdown: "Markdown (.md)",
3226
+ exportHtml: "交互式 HTML",
3227
+ exportPdfPaged: "PDF — 分页",
3228
+ exportPdfContinuous: "PDF — 连续",
3229
+ exportPdfSlides: "幻灯片(PDF)",
3230
+ exportHtmlSlides: "幻灯片(HTML)",
3231
+ present: "演示",
3232
+ presentFull: "全屏",
3233
+ presentPresenter: "演讲者视图",
3234
+ exportPlugin: "插件(.zip)",
3235
+ exportPluginFailed: "此页面无法导出为插件",
3236
+ exportPluginFailedOk: "好的"
3237
+ },
3238
+ home: {
3239
+ morning: "早上好",
3240
+ afternoon: "下午好",
3241
+ evening: "晚上好",
3242
+ customize: "自定义主页",
3243
+ widgetActions: "快捷操作",
3244
+ widgetRecents: "继续阅读",
3245
+ widgetFavorites: "收藏",
3246
+ widgetEdited: "最近编辑",
3247
+ justNow: "刚刚"
3248
+ },
3249
+ flow: {
3250
+ title: "数据流",
3251
+ open: "数据流视图",
3252
+ empty: "此页面还没有响应式内容",
3253
+ emptyHint: "添加命名输入、实时代码、图表或状态灯——它们的连接会在这里以实时图形显示。"
3254
+ },
3255
+ mention: {
3256
+ label: "链接到页面",
3257
+ create: "创建页面“{name}”",
3258
+ empty: "没有页面 — 继续输入即可创建。"
3259
+ },
3260
+ emoji: {
3261
+ label: "表情",
3262
+ search: "搜索表情"
3263
+ },
3264
+ confirm: {
3265
+ trashTitle: "将此页面移到回收站?",
3266
+ trashBody: "之后可从回收站恢复。",
3267
+ trashConfirm: "移到回收站"
3268
+ },
3269
+ backup: {
3270
+ heading: "备份与恢复",
3271
+ intro: "将整个工作区导出为单个文件,或恢复一个文件 — 可选择要恢复哪些页面。",
3272
+ export: "导出备份",
3273
+ exporting: "导出中…",
3274
+ restore: "恢复备份…",
3275
+ exported: "已导出 {count} 个页面。",
3276
+ exportFailed: "导出失败:{error}",
3277
+ readFailed: "无法读取备份:{error}",
3278
+ restored: "已恢复 {count} 个页面{detail}。",
3279
+ restoreFailed: "恢复失败:{error}",
3280
+ added: "新增 {count}",
3281
+ overwrittenCount: "覆盖 {count}",
3282
+ renamedCount: "重命名 {count}",
3283
+ dialog: {
3284
+ title: "恢复备份",
3285
+ summary: "{count} 个页面。选择要恢复的内容。",
3286
+ summaryDated: "{count} 个页面 · 导出于 {date}。选择要恢复的内容。",
3287
+ selected: "已选择 {count}",
3288
+ all: "全部",
3289
+ none: "无",
3290
+ overwrite: "覆盖现有页面",
3291
+ overwriteHint: "按 ID 原地恢复。关闭(默认)会作为副本导入,名称冲突时添加后缀。",
3292
+ restoreN: "恢复 {count}",
3293
+ confirmTitle: "覆盖 {count} 个现有页面?",
3294
+ confirmBody: "原地恢复将替换 {count} 个页面的当前内容,且无法撤销。",
3295
+ confirmBodyNone: "没有匹配的现有页面 — 将作为新页面添加。",
3296
+ confirmOverwrite: "覆盖"
3297
+ }
3298
+ },
3299
+ workspace: {
3300
+ workspaces: "工作区",
3301
+ addWorkspace: "添加工作区…",
3302
+ addTitle: "添加工作区",
3303
+ addDescription: "连接到另一个 OpenBook 服务器。切换后本设备将指向该服务器。",
3304
+ icon: "图标",
3305
+ name: "名称",
3306
+ serverUrl: "服务器 URL",
3307
+ namePlaceholder: "家庭 Wiki",
3308
+ urlPlaceholder: "https://my-server.example:4319",
3309
+ addButton: "添加工作区",
3310
+ urlRequired: "请输入此工作区的服务器 URL。",
3311
+ urlInvalid: "这看起来不是有效的 URL。",
3312
+ removeWorkspace: "移除 {name}",
3313
+ thisDevice: "本设备"
3314
+ },
3315
+ ai: {
3316
+ description: "可选的本地模型支持笔记搜索、任务分解和文档补全。一切都在你的设备上运行。",
3317
+ providerLabel: "引擎",
3318
+ provider: {
3319
+ off: "关闭",
3320
+ offHint: "无模型。笔记搜索仍可用(关键词排序)。",
3321
+ llama: "内置 (llama.cpp)",
3322
+ llamaHint: "在所有平台上于 OpenBook 内运行。在下方下载模型。",
3323
+ mlx: "MLX (Apple Silicon)",
3324
+ mlxHint: "使用 mlx_lm.server,在 Apple Silicon 上最快的本地推理。",
3325
+ openai: "本地服务器 (OpenAI 兼容)",
3326
+ openaiHint: "Ollama、LM Studio、llama-server 或任何兼容端点。"
3327
+ },
3328
+ ready: "引擎就绪 · {embeddings}",
3329
+ semantic: "已启用语义搜索",
3330
+ lexicalOnly: "仅关键词搜索",
3331
+ notReady: "引擎未就绪。",
3332
+ model: "模型",
3333
+ modelFile: "模型文件 (GGUF)",
3334
+ modelFileHint: "服务器模型目录中的文件。",
3335
+ downloadDefault: "下载推荐模型 (~1 GB)",
3336
+ downloading: "下载中… {progress}%",
3337
+ downloadingNoPct: "下载中…",
3338
+ downloadDone: "模型已下载。",
3339
+ endpoint: "端点",
3340
+ baseUrl: "服务器地址",
3341
+ mlxUrlHint: "mlx_lm.server 的地址。可能时自动启动。",
3342
+ openaiUrlHint: "OpenAI 兼容服务器的地址。",
3343
+ modelName: "模型",
3344
+ mlxModelHint: "MLX 模型 ID,例如 mlx-community/Qwen2.5-1.5B-Instruct-4bit。",
3345
+ openaiModelHint: "服务器期望的模型名称。",
3346
+ search: "笔记搜索",
3347
+ searchHint: "笔记会自动建立索引;结果过期时可重建。",
3348
+ reindex: "重建索引",
3349
+ indexing: "索引中…",
3350
+ indexed: "已索引 {pages} 个页面",
3351
+ notIndexed: "首次搜索时建立索引。"
3352
+ },
3353
+ aiSearch: {
3354
+ title: "搜索笔记",
3355
+ semantic: "语义",
3356
+ lexical: "关键词",
3357
+ placeholder: "你在找什么?",
3358
+ empty: "没有匹配的笔记。",
3359
+ hint: "搜索所有页面内容——使用本地模型可获得更好的结果。"
3360
+ },
3361
+ agent: {
3362
+ title: "助手",
3363
+ hint: "询问你的笔记——助手可以搜索、阅读和创建页面。",
3364
+ placeholder: "随便问…",
3365
+ thinking: "处理中…",
3366
+ reset: "新对话",
3367
+ close: "关闭助手",
3368
+ error: "出了点问题:{error}",
3369
+ notReady: "助手需要一个模型——请在 设置 → AI 中启用。",
3370
+ openSettings: "打开 AI 设置",
3371
+ send: "发送",
3372
+ stop: "停止",
3373
+ inputHint: "Enter 发送 · Shift+Enter 换行",
3374
+ suggestion1: "我有哪些页面?",
3375
+ suggestion2: "查找我关于计划的笔记",
3376
+ suggestion3: "创建一个今日计划页面",
3377
+ tool: {
3378
+ search_notes: "搜索笔记",
3379
+ read_page: "阅读页面",
3380
+ list_pages: "列出页面",
3381
+ create_page: "创建页面",
3382
+ append_to_page: "追加到页面"
3383
+ }
3384
+ },
3385
+ slash: {
3386
+ text: {
3387
+ label: "文本",
3388
+ hint: "普通段落"
3389
+ },
3390
+ h1: {
3391
+ label: "标题 1",
3392
+ hint: "大节标题"
3393
+ },
3394
+ h2: {
3395
+ label: "标题 2",
3396
+ hint: "中节标题"
3397
+ },
3398
+ h3: {
3399
+ label: "标题 3",
3400
+ hint: "小节标题"
3401
+ },
3402
+ bullet: {
3403
+ label: "无序列表",
3404
+ hint: "简单列表"
3405
+ },
3406
+ number: {
3407
+ label: "有序列表",
3408
+ hint: "编号列表"
3409
+ },
3410
+ todo: {
3411
+ label: "待办",
3412
+ hint: "复选框条目"
3413
+ },
3414
+ quote: {
3415
+ label: "引用",
3416
+ hint: "突出引文"
3417
+ },
3418
+ callout: {
3419
+ label: "标注",
3420
+ hint: "高亮备注"
3421
+ },
3422
+ code: {
3423
+ label: "代码",
3424
+ hint: "等宽代码块"
3425
+ },
3426
+ livecode: {
3427
+ label: "实时代码",
3428
+ hint: "基于输入计算;为输出命名以便链式引用"
3429
+ },
3430
+ divider: {
3431
+ label: "分隔线",
3432
+ hint: "水平线"
3433
+ },
3434
+ table: {
3435
+ label: "表格",
3436
+ hint: "初始 3 × 3"
3437
+ },
3438
+ cols2: {
3439
+ label: "2 栏",
3440
+ hint: "并排布局"
3441
+ },
3442
+ cols3: {
3443
+ label: "3 栏",
3444
+ hint: "三栏布局"
3445
+ },
3446
+ cols4: {
3447
+ label: "4 栏",
3448
+ hint: "四栏布局"
3449
+ },
3450
+ "ai-continue": {
3451
+ label: "继续写作",
3452
+ hint: "AI 从此处续写"
3453
+ },
3454
+ "ai-tasks": {
3455
+ label: "拆解为任务",
3456
+ hint: "AI 草拟相关待办"
3457
+ },
3458
+ custom: {
3459
+ slider: {
3460
+ label: "滑块",
3461
+ hint: "具名实时输入"
3462
+ },
3463
+ formula: {
3464
+ label: "公式",
3465
+ hint: "基于输入的实时计算"
3466
+ },
3467
+ number: {
3468
+ label: "数字步进器",
3469
+ hint: "带 − / + 按钮的具名数字"
3470
+ },
3471
+ textfield: {
3472
+ label: "文本框",
3473
+ hint: "具名文本输入"
3474
+ },
3475
+ radio: {
3476
+ label: "单选组",
3477
+ hint: "从多个选项中选一个"
3478
+ },
3479
+ checklist: {
3480
+ label: "多选清单",
3481
+ hint: "从多个选项中任选"
3482
+ },
3483
+ dropdown: {
3484
+ label: "下拉选择",
3485
+ hint: "从列表中选择一项"
3486
+ },
3487
+ toggle: {
3488
+ label: "开关",
3489
+ hint: "具名开/关切换"
3490
+ },
3491
+ location: {
3492
+ label: "位置",
3493
+ hint: "带坐标的地点"
3494
+ },
3495
+ actionbutton: {
3496
+ label: "按钮",
3497
+ hint: "设置、步进或切换输入,或打开链接"
3498
+ },
3499
+ kitchart: {
3500
+ label: "图表",
3501
+ hint: "折线、柱状、饼图、散点、漏斗 — 随输入实时变化"
3502
+ },
3503
+ statuslight: {
3504
+ label: "状态灯",
3505
+ hint: "由实时值得出绿 / 黄 / 红"
3506
+ },
3507
+ tooltipcard: {
3508
+ label: "工具提示",
3509
+ hint: "悬停即可自我解释的术语"
3510
+ },
3511
+ linkcard: {
3512
+ label: "链接卡片",
3513
+ hint: "带标题、可打开 URL 的卡片"
3514
+ }
3515
+ }
3516
+ },
3517
+ extensions: {
3518
+ description: "用插件扩展 OpenBook:从 TypeScript 源码 zip 安装,添加自定义块、命令和集成。",
3519
+ install: "从 .zip 安装…",
3520
+ installing: "安装中…",
3521
+ installHint: "包含 openbook.json 与 TypeScript 源码的 zip。",
3522
+ empty: "未安装扩展",
3523
+ emptyHint: "从 zip 安装——可向编辑器添加块、向面板添加命令,以及集成。",
3524
+ verified: "已验证",
3525
+ verifiedBy: "由 {registry} 签名并验证",
3526
+ unverified: "未验证",
3527
+ unverifiedHint: "未经你信任的注册表签名。它以与你的实时代码相同的权限运行。",
3528
+ loadError: "加载失败:{error}",
3529
+ enable: "启用 {name}",
3530
+ remove: "移除 {name}",
3531
+ trustNote: "扩展与文档实时代码拥有相同权限。“已验证”表示你信任的注册表对该内容签了名——这是来源证明,不是沙箱。",
3532
+ registries: "信任的注册表",
3533
+ registriesHint: "由这些密钥签名的扩展会显示为“已验证”。",
3534
+ builtIn: "内置",
3535
+ registryName: "注册表名称",
3536
+ registryKey: "Ed25519 公钥(base64)",
3537
+ addRegistry: "信任注册表",
3538
+ removeRegistry: "移除注册表 {name}",
3539
+ registryKeyInvalid: "请输入 32 字节的 base64 Ed25519 公钥。"
3540
+ },
3541
+ templates: {
3542
+ title: "从模板开始",
3543
+ description: "结构合理的现成页面 — 选一个,改成你的。",
3544
+ creating: "创建中…",
3545
+ groceryTracker: {
3546
+ name: "杂货价格追踪",
3547
+ description: "把每周购物篮在多家商店比价——实时图表、预算状态灯,计算都藏在代码块里。"
3548
+ },
3549
+ taskBoard: {
3550
+ name: "项目任务看板",
3551
+ description: "带状态、优先级、负责人和工作量的任务——按状态分组的看板,外加表格视图。"
3552
+ },
3553
+ readingList: {
3554
+ name: "阅读清单",
3555
+ description: "按书架分组的书籍画廊——含作者与星级评分,并提供表格视图。"
3556
+ },
3557
+ projectIntake: {
3558
+ name: "项目受理",
3559
+ description: "逐阶段解锁的需求简报,配合实时的“投入对收益”优先级评估。"
3560
+ },
3561
+ savingsPlanner: {
3562
+ name: "储蓄与投资",
3563
+ description: "先做应急金检查,再用滑块驱动面向目标的实时复利预测。"
3564
+ },
3565
+ roadmap: {
3566
+ name: "产品路线图",
3567
+ description: "在时间线和看板中规划事项,二者都按领域分成泳道。"
3568
+ },
3569
+ fieldMap: {
3570
+ name: "据点地图",
3571
+ description: "把办公室与合作伙伴标在地图上,按区域着色——并提供表格视图。"
3572
+ }
3573
+ },
3574
+ blocks: {
3575
+ subpagePage: "页面",
3576
+ subpageDatabase: "数据库",
3577
+ expression: "表达式",
3578
+ chart: "图表",
3579
+ slider: "滑块",
3580
+ sliderEdit: "编辑滑块",
3581
+ creating: "正在创建{kind}…",
3582
+ referenceHint: "引用单元格使用",
3583
+ chartPick: "至少选择一个单元格进行绘制",
3584
+ chartNoData: "所选单元格中没有数值数组数据",
3585
+ chartPlot: "绘制",
3586
+ chartAnd: "和",
3587
+ chartAddSeries: "添加系列",
3588
+ chartRemoveSeries: "移除系列",
3589
+ chartPickCell: "— 选择单元格 —",
3590
+ table: "表格",
3591
+ todo: "待办清单",
3592
+ listUnordered: "无序列表",
3593
+ listOrdered: "有序列表",
3594
+ callout: "标注",
3595
+ calloutInfo: "信息",
3596
+ calloutWarning: "警告",
3597
+ calloutSuccess: "成功",
3598
+ calloutDanger: "危险",
3599
+ calloutEmoji: "更改表情",
3600
+ calloutPlaceholder: "输入标注…",
3601
+ accordion: "折叠块",
3602
+ accordionToggle: "展开或折叠",
3603
+ accordionTitlePlaceholder: "折叠块标题",
3604
+ accordionContentPlaceholder: "隐藏的内容…",
3605
+ divider: "分隔线",
3606
+ dividerLine: "实线",
3607
+ dividerDashed: "虚线",
3608
+ dividerDotted: "点线",
3609
+ dividerThick: "粗线",
3610
+ dividerLabeled: "带标签",
3611
+ dividerLabelPlaceholder: "标签",
3612
+ button: "按钮",
3613
+ buttonDefault: "按钮",
3614
+ buttonLabelPlaceholder: "按钮文字",
3615
+ buttonEdit: "编辑按钮",
3616
+ buttonUrlPlaceholder: "https://… 或 /page",
3617
+ toc: "目录",
3618
+ tocTitle: "本页内容",
3619
+ tocEmpty: "还没有标题 — 添加标题即可生成大纲。"
3620
+ },
3621
+ general: {
3622
+ title: "通用",
3623
+ description: "语言以及应用的行为。",
3624
+ languageSection: "语言",
3625
+ language: "语言",
3626
+ languageHint: "应用的显示语言。",
3627
+ behavior: "行为",
3628
+ confirmTrash: "移到回收站前确认",
3629
+ confirmTrashHint: "将页面移到回收站前先询问。",
3630
+ spellcheck: "输入时拼写检查",
3631
+ spellcheckHint: "在编辑器中为拼写错误的单词加下划线。"
3632
+ },
3633
+ profile: {
3634
+ title: "个人资料",
3635
+ description: "你在本设备上的 OpenBook 中的显示方式。",
3636
+ identity: "身份",
3637
+ name: "姓名",
3638
+ nameHint: "你的全名。",
3639
+ namePlaceholder: "Ada Lovelace",
3640
+ displayName: "显示名称",
3641
+ displayNameHint: "在应用中显示的较短名称。",
3642
+ displayNamePlaceholder: "ada",
3643
+ avatar: "头像",
3644
+ avatarHint: "默认显示首字母——也可以选择表情符号或上传图片。",
3645
+ avatarEmoji: "选择表情",
3646
+ avatarUpload: "上传图片…",
3647
+ avatarReset: "使用首字母",
3648
+ editProfile: "编辑个人资料",
3649
+ aboutApp: "关于 OpenBook",
3650
+ bio: "简介",
3651
+ bioHint: "用一两句话介绍自己。",
3652
+ bioPlaceholder: "数学家兼作家。",
3653
+ preview: "预览",
3654
+ anonymous: "匿名"
3655
+ },
3656
+ customisation: {
3657
+ title: "自定义与快捷键",
3658
+ description: "调整布局并查看键盘快捷键。",
3659
+ layout: "布局",
3660
+ fullWidth: "全宽编辑器",
3661
+ fullWidthHint: "使用整个页面宽度,而非居中的列。",
3662
+ autoHideSidebar: "自动隐藏侧边栏",
3663
+ autoHideSidebarHint: "折叠侧边栏,直到你移到屏幕边缘。",
3664
+ shortcuts: "键盘快捷键",
3665
+ shortcutsHint: "在应用的任何地方都可用。",
3666
+ shortcut: {
3667
+ newPage: "新建页面",
3668
+ toggleSidebar: "显示或隐藏侧边栏",
3669
+ fullWidth: "切换全宽视图",
3670
+ theme: "在浅色与深色间切换",
3671
+ back: "后退",
3672
+ forward: "前进",
3673
+ openSettings: "打开设置",
3674
+ trash: "打开回收站",
3675
+ commandPalette: "打开命令面板",
3676
+ closeOverlay: "关闭对话框或菜单",
3677
+ slashMenu: "插入块",
3678
+ mention: "链接或提及页面"
3679
+ }
3680
+ },
3681
+ account: {
3682
+ signup: {
3683
+ title: "创建账户",
3684
+ description: "账户和云同步尚未加入 OpenBook。目前你的页面保存在你所连接的服务器本地。"
3685
+ },
3686
+ signin: {
3687
+ title: "登录与邮箱",
3688
+ description: "邮箱和第三方登录(Google、GitHub、Apple)将随账户一起推出。目前还没有可登录的对象。"
3689
+ },
3690
+ support: {
3691
+ title: "支持 OpenBook",
3692
+ description: "OpenBook 是独立的开源项目。分享它并提供反馈有助于它成长。赞助方式即将推出。"
3693
+ }
3694
+ },
3695
+ connection: {
3696
+ title: "连接",
3697
+ description: "选择本设备读写页面的位置。",
3698
+ server: "服务器",
3699
+ usingLocal: "当前使用本设备的本地服务器。",
3700
+ usingRemote: "当前使用远程服务器:",
3701
+ remoteUrl: "远程服务器 URL",
3702
+ remoteUrlPlaceholder: "https://my-server.example:4319",
3703
+ connect: "连接",
3704
+ useLocal: "使用本地",
3705
+ localServer: "本地服务器",
3706
+ running: "正在运行于",
3707
+ stopped: "已停止。",
3708
+ checking: "检查中…",
3709
+ unmanaged: "由开发环境管理 — 此处无法启动/停止。",
3710
+ start: "启动",
3711
+ stop: "停止",
3712
+ refresh: "刷新"
3713
+ },
3714
+ integrations: {
3715
+ title: "集成",
3716
+ description: "将 OpenBook 与其他工具连接。集成尚不可用 — 此处将是它们的所在。"
3717
+ },
3718
+ admin: {
3719
+ title: "管理",
3720
+ description: "备份、恢复以及工作区维护。",
3721
+ dangerZone: "危险区域",
3722
+ dangerZoneHint: "这些操作会影响本设备的本地数据,而非你的页面。",
3723
+ resetPrefs: "重置偏好与布局",
3724
+ resetPrefsHint: "将本设备的外观、语言和布局恢复为默认。你的页面和工作区会保留。",
3725
+ resetPrefsButton: "重置",
3726
+ resetConfirmTitle: "重置偏好与布局?",
3727
+ resetConfirmBody: "这将清除本设备上的外观、语言和布局设置并重新加载。你的页面和工作区不受影响。",
3728
+ resetConfirmButton: "重置"
3729
+ },
3730
+ properties: {
3731
+ owner: "负责人",
3732
+ setOwner: "设置负责人",
3733
+ ownerPlaceholder: "输入名字…",
3734
+ you: "我",
3735
+ clear: "清除",
3736
+ verification: "验证",
3737
+ verified: "已验证",
3738
+ verify: "验证",
3739
+ unverify: "移除",
3740
+ verifiedBy: "由 {name}",
3741
+ backlinks: "反向链接",
3742
+ noBacklinks: "还没有反向链接",
3743
+ refresh: "刷新"
3744
+ }
3745
+ }, wi = [
3746
+ {
3747
+ code: "en",
3748
+ name: "English"
3749
+ },
3750
+ {
3751
+ code: "de",
3752
+ name: "Deutsch"
3753
+ },
3754
+ {
3755
+ code: "ja",
3756
+ name: "日本語"
3757
+ },
3758
+ {
3759
+ code: "zh",
3760
+ name: "中文"
3761
+ }
3762
+ ];
3763
+ function q(e, t = "", n = {}) {
3764
+ for (let [r, i] of Object.entries(e)) {
3765
+ let e = t ? `${t}.${r}` : r;
3766
+ typeof i == "string" ? n[e] = i : i && typeof i == "object" && q(i, e, n);
3767
+ }
3768
+ return n;
3769
+ }
3770
+ var Ti = {
3771
+ en: q(bi),
3772
+ de: q(xi),
3773
+ ja: q(Si),
3774
+ zh: q(Ci)
3775
+ };
3776
+ function Ei(e, t) {
3777
+ return e.replace(/\{(\w+)\}/g, (e, n) => n in t ? String(t[n]) : `{${n}}`);
3778
+ }
3779
+ var Di = "en", Oi = () => Di, ki = (e) => {
3780
+ Di = e;
3781
+ }, Ai = new Set([
3782
+ "en",
3783
+ "de",
3784
+ "ja",
3785
+ "zh"
3786
+ ]);
3787
+ function ji(e) {
3788
+ let t = (e ?? "").toLowerCase().split("-")[0];
3789
+ return Ai.has(t) ? t : "en";
3790
+ }
3791
+ function Mi(e, t) {
3792
+ let n = e, r = Ti[Di][n] ?? Ti.en[n] ?? n;
3793
+ return t ? Ei(r, t) : r;
3794
+ }
3795
+ //#endregion
3796
+ //#region src/providers/I18nProvider.tsx
3797
+ var Ni = o(null), Pi = "openbook.locale";
3798
+ function Fi() {
3799
+ if (typeof window > "u") return "en";
3800
+ try {
3801
+ let e = localStorage.getItem(Pi);
3802
+ if (e) return ji(e);
3803
+ } catch {}
3804
+ return ji(navigator.language);
3805
+ }
3806
+ var Ii = ({ children: e }) => {
3807
+ let [t, n] = f("en");
3808
+ l(() => {
3809
+ let e = Fi();
3810
+ e !== "en" && n(e);
3811
+ }, []), Oi() !== t && ki(t), l(() => {
3812
+ typeof document < "u" && (document.documentElement.lang = t);
3813
+ }, [t]);
3814
+ let r = s((e) => {
3815
+ n(e);
3816
+ try {
3817
+ localStorage.setItem(Pi, e);
3818
+ } catch {}
3819
+ }, []), i = u(() => ({
3820
+ locale: t,
3821
+ setLocale: r,
3822
+ t: Mi,
3823
+ locales: wi
3824
+ }), [t, r]);
3825
+ return /* @__PURE__ */ p(Ni.Provider, {
3826
+ value: i,
3827
+ children: e
3828
+ });
3829
+ }, Li = () => {
3830
+ let e = c(Ni);
3831
+ if (!e) throw Error("useTranslation must be used within an <I18nProvider>");
3832
+ return e;
3833
+ }, Ri = o(null), zi = ({ client: e, children: t }) => /* @__PURE__ */ p(Ri.Provider, {
3834
+ value: e,
3835
+ children: t
3836
+ }), Bi = () => {
3837
+ let e = c(Ri);
3838
+ if (!e) throw Error("useData must be used within a <DataProvider>");
3839
+ return e;
3840
+ }, Vi = (e, t) => {
3841
+ let n = Bi();
3842
+ return {
3843
+ onLoad: s(async () => {
3844
+ let t = await n.getPage(e);
3845
+ return t ? t.data : null;
3846
+ }, [n, e]),
3847
+ onSave: s(async (r) => {
3848
+ await n.savePage({
3849
+ id: e,
3850
+ name: t ?? null,
3851
+ data: r
3852
+ });
3853
+ }, [
3854
+ n,
3855
+ e,
3856
+ t
3857
+ ])
3858
+ };
3859
+ }, Hi = "openbook.currentPageId", Ui = () => {
3860
+ let [e, t] = f(null);
3861
+ return l(() => {
3862
+ t(Wi());
3863
+ }, []), e;
3864
+ }, Wi = () => {
3865
+ if (typeof localStorage > "u") throw Error("getOrCreateCurrentPageId requires a browser environment");
3866
+ let e = localStorage.getItem(Hi);
3867
+ return e || (e = crypto.randomUUID(), localStorage.setItem(Hi, e)), e;
3868
+ }, J = null, Gi = /* @__PURE__ */ new Set(), Ki = (e) => {
3869
+ J = e, Gi.forEach((e) => e());
3870
+ }, qi = (e) => (Gi.add(e), () => Gi.delete(e)), Ji = {
3871
+ createSubpage: (e, t) => J ? J.createSubpage(e, t) : Promise.reject(/* @__PURE__ */ Error("page links not ready")),
3872
+ openPage: (e, t) => J?.openPage(e, t),
3873
+ label: (e) => J?.label(e) ?? "Untitled",
3874
+ icon: (e) => J?.icon(e) ?? "📄",
3875
+ searchPages: (e, t) => J?.searchPages(e, t) ?? [],
3876
+ createPage: (e) => J ? J.createPage(e) : Promise.reject(/* @__PURE__ */ Error("page links not ready"))
3877
+ }, Yi = "openbook.recents";
3878
+ function Xi(e, t, n = 12) {
3879
+ return [t, ...e.filter((e) => e !== t)].slice(0, n);
3880
+ }
3881
+ var Zi = () => {
3882
+ if (typeof localStorage > "u") return [];
3883
+ try {
3884
+ let e = localStorage.getItem(Yi), t = e ? JSON.parse(e) : [];
3885
+ return Array.isArray(t) ? t.filter((e) => typeof e == "string") : [];
3886
+ } catch {
3887
+ return [];
3888
+ }
3889
+ }, Qi = /* @__PURE__ */ new Set(), $i = (e) => {
3890
+ typeof localStorage < "u" && localStorage.setItem(Yi, JSON.stringify(e)), Qi.forEach((e) => e());
3891
+ }, ea = () => Zi(), ta = (e) => {
3892
+ let t = Xi(Zi(), e), n = Zi();
3893
+ n[0] === e && n.length === t.length || $i(t);
3894
+ }, na = (e) => (Qi.add(e), () => Qi.delete(e)), ra = "home", ia = "flow", aa = "config", oa = "customise", sa = "review", ca = "agent", la = {
3895
+ actions: !0,
3896
+ recents: !0,
3897
+ favorites: !0,
3898
+ edited: !0
3899
+ }, ua = "openbook.home.widgets";
3900
+ function da() {
3901
+ try {
3902
+ let e = typeof localStorage < "u" ? localStorage.getItem(ua) : null, t = e ? JSON.parse(e) : {};
3903
+ return {
3904
+ ...la,
3905
+ ...t
3906
+ };
3907
+ } catch {
3908
+ return la;
3909
+ }
3910
+ }
3911
+ function fa(e) {
3912
+ try {
3913
+ localStorage.setItem(ua, JSON.stringify(e));
3914
+ } catch {}
3915
+ }
3916
+ function pa(e) {
3917
+ return e >= 5 && e < 12 ? "morning" : e >= 12 && e < 18 ? "afternoon" : "evening";
3918
+ }
3919
+ //#endregion
3920
+ //#region src/blockeditor/kit/kitPanel.ts
3921
+ var ma = null, ha = /* @__PURE__ */ new Set(), ga = null, _a = /* @__PURE__ */ new Set(), va = null, ya = null, ba = (e) => e.forEach((e) => e());
3922
+ function xa(e, t) {
3923
+ ma = {
3924
+ blockId: e,
3925
+ title: t
3926
+ }, ba(ha), va?.(e);
3927
+ }
3928
+ function Sa(e) {
3929
+ ma && (ma = null, ba(ha), e?.keepPane || ya?.());
3930
+ }
3931
+ var Ca = () => ma;
3932
+ function wa(e) {
3933
+ return ha.add(e), () => ha.delete(e);
3934
+ }
3935
+ function Ta(e) {
3936
+ ga !== e && (ga = e, ba(_a));
3937
+ }
3938
+ var Ea = () => ga;
3939
+ function Da(e) {
3940
+ return _a.add(e), () => _a.delete(e);
3941
+ }
3942
+ function Oa(e, t) {
3943
+ return va = e, ya = t, () => {
3944
+ va === e && (va = null), ya === t && (ya = null);
3945
+ };
3946
+ }
3947
+ //#endregion
3948
+ //#region src/lib/favorites.ts
3949
+ var ka = "openbook.favorites";
3950
+ function Aa(e, t) {
3951
+ return e.includes(t) ? e.filter((e) => e !== t) : [t, ...e];
3952
+ }
3953
+ var ja = () => {
3954
+ if (typeof localStorage > "u") return [];
3955
+ try {
3956
+ let e = localStorage.getItem(ka), t = e ? JSON.parse(e) : [];
3957
+ return Array.isArray(t) ? t.filter((e) => typeof e == "string") : [];
3958
+ } catch {
3959
+ return [];
3960
+ }
3961
+ }, Ma = /* @__PURE__ */ new Set(), Na = (e) => {
3962
+ typeof localStorage < "u" && localStorage.setItem(ka, JSON.stringify(e)), Ma.forEach((e) => e());
3963
+ }, Pa = () => ja(), Fa = (e) => ja().includes(e), Ia = (e) => Na(Aa(ja(), e)), La = (e) => {
3964
+ let t = ja();
3965
+ t.includes(e) && Na(t.filter((t) => t !== e));
3966
+ }, Ra = (e) => (Ma.add(e), () => Ma.delete(e)), za = 0, Ba = () => (za += 1, `tab_${typeof crypto < "u" && "randomUUID" in crypto ? crypto.randomUUID().slice(0, 8) : `${za}`}`), Va = (e, t = null) => ({
3967
+ id: Ba(),
3968
+ history: [e],
3969
+ index: 0,
3970
+ split: t && t !== e ? t : null,
3971
+ focused: "primary"
3972
+ }), Y = (e) => e.history[e.index], Ha = (e) => e.split !== null, Ua = (e) => {
3973
+ let t = [{
3974
+ id: "primary",
3975
+ pageId: Y(e)
3976
+ }];
3977
+ return e.split !== null && t.push({
3978
+ id: "secondary",
3979
+ pageId: e.split
3980
+ }), t;
3981
+ }, Wa = (e) => e.focused === "secondary" && e.split !== null ? e.split : Y(e), Ga = (e, t) => {
3982
+ if (Y(e) === t) return e;
3983
+ let n = e.history.slice(0, e.index + 1);
3984
+ return n.push(t), {
3985
+ ...e,
3986
+ history: n,
3987
+ index: n.length - 1
3988
+ };
3989
+ }, Ka = (e, t, n) => t === "secondary" && Ha(e) ? e.split === n ? e : {
3990
+ ...e,
3991
+ split: n
3992
+ } : Ga(e, n), qa = (e, t) => Ka(e, e.focused, t), Ja = (e, t) => {
3993
+ let n = e.index + t;
3994
+ return n >= 0 && n < e.history.length ? {
3995
+ ...e,
3996
+ index: n
3997
+ } : e;
3998
+ }, Ya = (e, t) => ({
3999
+ ...e,
4000
+ split: t,
4001
+ focused: "secondary"
4002
+ }), Xa = (e) => Ha(e) ? {
4003
+ ...e,
4004
+ split: null,
4005
+ focused: "primary"
4006
+ } : e, Za = (e, t) => t === "secondary" ? Xa(e) : Ha(e) ? {
4007
+ ...e,
4008
+ history: [e.split],
4009
+ index: 0,
4010
+ split: null,
4011
+ focused: "primary"
4012
+ } : e, Qa = (e, t) => t === e.focused ? e : {
4013
+ ...e,
4014
+ focused: t
4015
+ }, $a = (e, t) => {
4016
+ let n = e.history.filter(t), r = e;
4017
+ if (n.length !== e.history.length) {
4018
+ if (n.length === 0) return null;
4019
+ r = {
4020
+ ...r,
4021
+ history: n,
4022
+ index: Math.min(e.index, n.length - 1)
4023
+ };
4024
+ }
4025
+ return r.split !== null && !t(r.split) && (r = {
4026
+ ...r,
4027
+ split: null,
4028
+ focused: "primary"
4029
+ }), r;
4030
+ }, eo = (e, t = null) => {
4031
+ let n = Va(e, t);
4032
+ return {
4033
+ tabs: [n],
4034
+ activeTabId: n.id
4035
+ };
4036
+ }, X = (e) => e.tabs.find((t) => t.id === e.activeTabId) ?? e.tabs[0], Z = (e, t) => {
4037
+ let n = X(e), r = t(n);
4038
+ return r === n ? e : {
4039
+ ...e,
4040
+ tabs: e.tabs.map((e) => e.id === n.id ? r : e)
4041
+ };
4042
+ }, to = (e) => Y(e), no = (e) => Y(X(e)), ro = (e) => Ua(X(e)), io = (e) => Wa(X(e)), ao = (e) => X(e).focused, oo = (e) => X(e).split !== null, so = (e) => X(e).index > 0, co = (e) => {
4043
+ let t = X(e);
4044
+ return t.index < t.history.length - 1;
4045
+ }, lo = (e, t) => Z(e, (e) => qa(e, t)), uo = (e, t, n) => Z(e, (e) => {
4046
+ let r = t === "secondary" && Ha(e) ? "secondary" : "primary";
4047
+ return Ka(Qa(e, r), r, n);
4048
+ }), fo = (e) => Z(e, (e) => Ja(e, -1)), po = (e) => Z(e, (e) => Ja(e, 1)), mo = (e, t) => Z(e, (e) => Ya(e, t)), ho = (e) => Z(e, Xa), go = (e, t) => Z(e, (e) => Za(e, t)), _o = (e, t) => Z(e, (e) => Qa(e, t)), vo = (e, t) => {
4049
+ let n = Va(t);
4050
+ return {
4051
+ tabs: [...e.tabs, n],
4052
+ activeTabId: n.id
4053
+ };
4054
+ }, yo = (e, t) => e.tabs.some((e) => e.id === t) ? {
4055
+ ...e,
4056
+ activeTabId: t
4057
+ } : e, bo = (e, t) => {
4058
+ if (e.tabs.length <= 1) return e;
4059
+ let n = e.tabs.findIndex((e) => e.id === t), r = e.tabs.filter((e) => e.id !== t);
4060
+ return {
4061
+ tabs: r,
4062
+ activeTabId: e.activeTabId === t ? r[Math.min(n, r.length - 1)].id : e.activeTabId
4063
+ };
4064
+ }, xo = (e, t, n) => {
4065
+ let r = !1, i = [];
4066
+ for (let n of e.tabs) {
4067
+ let e = $a(n, t);
4068
+ e === null ? r = !0 : (e !== n && (r = !0), i.push(e));
4069
+ }
4070
+ return i.length === 0 ? n ? eo(n) : e : r ? {
4071
+ tabs: i,
4072
+ activeTabId: i.some((t) => t.id === e.activeTabId) ? e.activeTabId : i[0].id
4073
+ } : e;
4074
+ }, So = o(null), Co = () => {
4075
+ let e = c(So);
4076
+ if (!e) throw Error("useNavigation must be used within a <NavigationProvider>");
4077
+ return e;
4078
+ }, wo = "openbook.currentPageId", To = () => {
4079
+ if (typeof window > "u") return {
4080
+ page: null,
4081
+ split: null
4082
+ };
4083
+ let e = new URLSearchParams(window.location.search);
4084
+ return {
4085
+ page: e.get("page"),
4086
+ split: e.get("split")
4087
+ };
4088
+ }, Eo = (e, t) => {
4089
+ if (typeof window > "u") return;
4090
+ let n = new URL(window.location.href);
4091
+ n.searchParams.set("page", e), t ? n.searchParams.set("split", t) : n.searchParams.delete("split"), window.history.replaceState(null, "", `${n.pathname}${n.search}${n.hash}`);
4092
+ try {
4093
+ localStorage.setItem(wo, e);
4094
+ } catch {}
4095
+ }, Do = (e) => {
4096
+ let t = new URL(window.location.href);
4097
+ return t.searchParams.set("page", e), t.searchParams.delete("split"), t.toString();
4098
+ }, Oo = () => {
4099
+ try {
4100
+ return typeof localStorage < "u" ? localStorage.getItem(wo) : null;
4101
+ } catch {
4102
+ return null;
4103
+ }
4104
+ }, ko = ({ children: i }) => {
4105
+ let a = Bi(), o = cr(), [c, m] = f([]), [h, g] = f(null), [_, v] = f({}), [ee, te] = f(!0), [x, ne] = f(null), S = d(null), C = d(/* @__PURE__ */ new Set());
4106
+ l(() => {
4107
+ if (!h) return;
4108
+ let e = X(h).split, t = e === "config" || e === "customise" || e === "review";
4109
+ Eo(no(h), t ? null : e);
4110
+ }, [h]);
4111
+ let w = s((e) => {
4112
+ g((t) => t && e(t));
4113
+ }, []), T = s(async () => {
4114
+ let e = await a.listPages();
4115
+ return m(e), e;
4116
+ }, [a]), E = s((e) => w((t) => lo(t, e)), [w]), D = s((e, t) => w((n) => uo(n, t, e)), [w]), O = s(() => w(fo), [w]), k = s(() => w(po), [w]), A = s((e) => w((t) => _o(t, e)), [w]), j = s((e) => w((t) => mo(t, e)), [w]), M = s(() => w(ho), [w]), N = s((e) => w((t) => go(t, e)), [w]), P = s((e) => w((t) => yo(t, e)), [w]), re = s((e) => w((t) => bo(t, e)), [w]), F = s((e) => g((t) => t && xo(t, (t) => t !== e, c[0]?.id ?? null)), [c]), I = s((e, t) => {
4117
+ if (t === "tab") {
4118
+ o.tabs?.inWindow ? w((t) => vo(t, e)) : typeof window < "u" && window.open(Do(e), "_blank", "noopener");
4119
+ return;
4120
+ }
4121
+ o.tabs ? o.tabs.openWindow(e) : typeof window < "u" && window.open(Do(e), "_blank", "noopener,popup,width=1280,height=860");
4122
+ }, [o, w]), L = s((e, t) => {
4123
+ v((n) => {
4124
+ let r = t && t.trim().length > 0 ? t : "Untitled";
4125
+ return n[e] === r ? n : {
4126
+ ...n,
4127
+ [e]: r
4128
+ };
4129
+ });
4130
+ }, []), R = s((e) => {
4131
+ if (e === "home") return Mi("nav.home");
4132
+ if (e === "flow") return Mi("flow.title");
4133
+ if (e === "config") return "Settings";
4134
+ if (e === "customise") return "Customise";
4135
+ if (e === "review") return "Review";
4136
+ let t = c.find((t) => t.id === e);
4137
+ return t ? t.name && t.name.trim().length > 0 ? t.name : "Untitled" : _[e] ?? "Untitled";
4138
+ }, [c, _]), ie = s(async (e = null, t = null) => {
4139
+ let n = await a.savePage({
4140
+ name: e,
4141
+ data: b(),
4142
+ parentId: t
4143
+ });
4144
+ return await T(), E(n.id), n.id;
4145
+ }, [
4146
+ a,
4147
+ T,
4148
+ E
4149
+ ]), ae = s(async (e = null) => {
4150
+ let t = await a.savePage({
4151
+ name: null,
4152
+ data: b(),
4153
+ parentId: e
4154
+ });
4155
+ return await a.createDatabase({
4156
+ pageId: t.id,
4157
+ name: null,
4158
+ schema: y()
4159
+ }), await T(), E(t.id), t.id;
4160
+ }, [
4161
+ a,
4162
+ T,
4163
+ E
4164
+ ]), z = s(async (e, t = "page") => {
4165
+ let n = await a.savePage({
4166
+ name: null,
4167
+ data: b(),
4168
+ parentId: e
4169
+ });
4170
+ return t === "database" && await a.createDatabase({
4171
+ pageId: n.id,
4172
+ name: null,
4173
+ schema: y()
4174
+ }), await T(), n.id;
4175
+ }, [a, T]), oe = s(async (e) => {
4176
+ let t = await a.savePage({
4177
+ name: null,
4178
+ data: b()
4179
+ });
4180
+ await T(), I(t.id, e);
4181
+ }, [
4182
+ a,
4183
+ T,
4184
+ I
4185
+ ]), se = s(async (t) => {
4186
+ let r = await a.getPage(t);
4187
+ if (!r) return;
4188
+ let i = r.name && r.name.trim().length > 0 ? `${r.name} (copy)` : null, o = await a.savePage({
4189
+ name: i,
4190
+ data: r.data,
4191
+ parentId: r.parentId
4192
+ }), s = e(t);
4193
+ s && n(o.id, s), await T(), E(o.id);
4194
+ }, [
4195
+ a,
4196
+ T,
4197
+ E
4198
+ ]), ce = s(async (e) => {
4199
+ await a.deletePage(e), La(e);
4200
+ let t = await T();
4201
+ g((n) => n && xo(n, (t) => t !== e, t[0]?.id ?? null));
4202
+ }, [a, T]), le = s(async (e, t) => {
4203
+ await a.renamePage(e, t), L(e, t), await T();
4204
+ }, [
4205
+ a,
4206
+ T,
4207
+ L
4208
+ ]), ue = s(async (e, t, n) => {
4209
+ await a.movePage(e, {
4210
+ parentId: t,
4211
+ orderedIds: n
4212
+ }), await T();
4213
+ }, [a, T]), de = s((e, n) => {
4214
+ let r = e.trim().toLowerCase(), i = c.filter((e) => !n?.databasesOnly || e.hostedDatabaseId).map((e) => ({
4215
+ id: e.id,
4216
+ label: R(e.id),
4217
+ icon: t(e.id)
4218
+ })).filter((e) => r === "" || e.label.toLowerCase().includes(r)), a = (e) => {
4219
+ let t = e.toLowerCase();
4220
+ return t === r ? 2 : +!!t.startsWith(r);
4221
+ };
4222
+ return i.sort((e, t) => a(t.label) - a(e.label)).slice(0, 8);
4223
+ }, [c, R]), fe = s(async (e) => {
4224
+ let t = await a.savePage({
4225
+ name: e.trim() || null,
4226
+ data: b()
4227
+ });
4228
+ return await T(), t.id;
4229
+ }, [a, T]);
4230
+ l(() => {
4231
+ S.current ||= (async () => {
4232
+ try {
4233
+ let e = await a.listPages();
4234
+ e.length === 0 && (await a.savePage({
4235
+ name: null,
4236
+ data: b()
4237
+ }), e = await a.listPages()), m(e), C.current = new Set(e.map((e) => e.id));
4238
+ let t = new Set(e.map((e) => e.id)), n = async (e) => e ? e === "home" || e === "flow" || t.has(e) ? e : await a.getPage(e) === null ? null : e : null, { page: r, split: i } = To(), o = await n(r);
4239
+ o ||= await n(Oo()), o ||= e[0]?.id ?? null;
4240
+ let s = o ? await n(i && i !== o ? i : null) : null;
4241
+ g(o ? eo(o, s) : null);
4242
+ } catch (e) {
4243
+ ne(e instanceof Error ? e.message : String(e));
4244
+ } finally {
4245
+ te(!1);
4246
+ }
4247
+ })();
4248
+ }, [a]), l(() => {
4249
+ r(c);
4250
+ }, [c]), l(() => a.subscribePages((e) => {
4251
+ m(e);
4252
+ let t = new Set(e.map((e) => e.id)), n = [...C.current].filter((e) => !t.has(e));
4253
+ if (C.current = t, n.length === 0) return;
4254
+ n.forEach(La);
4255
+ let r = new Set(n);
4256
+ g((t) => t && xo(t, (e) => !r.has(e), e[0]?.id ?? null));
4257
+ }), [a]), l(() => (Ki({
4258
+ createSubpage: (e, t) => z(e, t),
4259
+ openPage: (e, t) => t ? D(e, t) : E(e),
4260
+ label: (e) => R(e),
4261
+ icon: (e) => t(e),
4262
+ searchPages: de,
4263
+ createPage: fe
4264
+ }), () => Ki(null)), [
4265
+ z,
4266
+ E,
4267
+ D,
4268
+ R,
4269
+ de,
4270
+ fe
4271
+ ]), l(() => Oa(() => j(aa), () => M()), [j, M]), l(() => {
4272
+ c.length !== 0 && v((e) => {
4273
+ let t = { ...e };
4274
+ for (let e of c) t[e.id] = e.name && e.name.trim().length > 0 ? e.name : "Untitled";
4275
+ return t;
4276
+ });
4277
+ }, [c]);
4278
+ let B = h ? io(h) : null, pe = h ? no(h) : null;
4279
+ l(() => {
4280
+ B && B !== "home" && B !== "flow" && B !== "config" && B !== "customise" && B !== "review" && ta(B);
4281
+ }, [B]);
4282
+ let me = h ? ro(h) : [], he = h ? ao(h) : "primary", ge = h ? oo(h) : !1, _e = h ? so(h) : !1, ve = h ? co(h) : !1, ye = o.tabs?.inWindow ?? !1, be = h ? h.tabs.map((e) => ({
4283
+ id: e.id,
4284
+ pageId: to(e)
4285
+ })) : [], xe = h?.activeTabId ?? "", Se = u(() => ({
4286
+ pages: c,
4287
+ currentPageId: B,
4288
+ primaryPageId: pe,
4289
+ loading: ee,
4290
+ error: x,
4291
+ inWindowTabs: ye,
4292
+ tabs: be,
4293
+ activeTabId: xe,
4294
+ selectTab: P,
4295
+ closeTab: re,
4296
+ panes: me,
4297
+ focusedPaneId: he,
4298
+ splitOpen: ge,
4299
+ focusPane: A,
4300
+ openInSplit: j,
4301
+ closeSplit: M,
4302
+ closePane: N,
4303
+ openInNew: I,
4304
+ newPageIn: oe,
4305
+ closePage: F,
4306
+ pageLabel: R,
4307
+ setPageHint: L,
4308
+ selectPage: E,
4309
+ selectPageInPane: D,
4310
+ goBack: O,
4311
+ goForward: k,
4312
+ canGoBack: _e,
4313
+ canGoForward: ve,
4314
+ createPage: ie,
4315
+ createDatabasePage: ae,
4316
+ createSubpage: z,
4317
+ duplicatePage: se,
4318
+ deletePage: ce,
4319
+ renamePage: le,
4320
+ movePage: ue,
4321
+ reload: T
4322
+ }), [
4323
+ c,
4324
+ B,
4325
+ pe,
4326
+ ee,
4327
+ x,
4328
+ ye,
4329
+ be,
4330
+ xe,
4331
+ P,
4332
+ re,
4333
+ me,
4334
+ he,
4335
+ ge,
4336
+ A,
4337
+ j,
4338
+ M,
4339
+ N,
4340
+ I,
4341
+ oe,
4342
+ F,
4343
+ R,
4344
+ L,
4345
+ E,
4346
+ D,
4347
+ O,
4348
+ k,
4349
+ _e,
4350
+ ve,
4351
+ ie,
4352
+ ae,
4353
+ z,
4354
+ se,
4355
+ ce,
4356
+ le,
4357
+ ue,
4358
+ T
4359
+ ]);
4360
+ return /* @__PURE__ */ p(So.Provider, {
4361
+ value: Se,
4362
+ children: i
4363
+ });
4364
+ }, Ao = {
4365
+ background: "0 0% 100%",
4366
+ foreground: "34 9% 19%",
4367
+ card: "0 0% 100%",
4368
+ cardForeground: "34 9% 19%",
4369
+ popover: "0 0% 100%",
4370
+ popoverForeground: "34 9% 19%",
4371
+ primary: "207 75% 49%",
4372
+ primaryForeground: "0 0% 100%",
4373
+ secondary: "40 9% 96%",
4374
+ secondaryForeground: "34 9% 19%",
4375
+ muted: "40 9% 96%",
4376
+ mutedForeground: "40 3% 48%",
4377
+ accent: "40 12% 93%",
4378
+ accentForeground: "34 9% 19%",
4379
+ destructive: "4 74% 53%",
4380
+ destructiveForeground: "0 0% 100%",
4381
+ border: "40 8% 90%",
4382
+ input: "40 8% 87%",
4383
+ ring: "207 75% 49%",
4384
+ sheet1: "40 14% 97.5%",
4385
+ sheet1Foreground: "34 9% 19%",
4386
+ sheet2: "40 11% 93.5%",
4387
+ sheet2Foreground: "34 9% 19%",
4388
+ brand: "207 76% 47%",
4389
+ brandForeground: "0 0% 100%",
4390
+ brandSubtle: "207 86% 95%"
4391
+ }, jo = {
4392
+ background: "0 0% 13%",
4393
+ foreground: "0 0% 82%",
4394
+ card: "0 0% 16%",
4395
+ cardForeground: "0 0% 82%",
4396
+ popover: "0 0% 16.5%",
4397
+ popoverForeground: "0 0% 82%",
4398
+ primary: "207 68% 55%",
4399
+ primaryForeground: "0 0% 100%",
4400
+ secondary: "0 0% 18.5%",
4401
+ secondaryForeground: "0 0% 82%",
4402
+ muted: "0 0% 18.5%",
4403
+ mutedForeground: "0 0% 56%",
4404
+ accent: "0 0% 22%",
4405
+ accentForeground: "0 0% 86%",
4406
+ destructive: "4 58% 52%",
4407
+ destructiveForeground: "0 0% 100%",
4408
+ border: "0 0% 22%",
4409
+ input: "0 0% 26%",
4410
+ ring: "207 68% 55%",
4411
+ sheet1: "0 0% 15.5%",
4412
+ sheet1Foreground: "0 0% 82%",
4413
+ sheet2: "0 0% 18.5%",
4414
+ sheet2Foreground: "0 0% 82%",
4415
+ brand: "207 70% 57%",
4416
+ brandForeground: "0 0% 100%",
4417
+ brandSubtle: "208 48% 22%"
4418
+ };
4419
+ function Q(e, t, n, r, i) {
4420
+ let a = (e, t) => ({
4421
+ ...e,
4422
+ primary: t.primary,
4423
+ primaryForeground: t.primaryForeground ?? "0 0% 100%",
4424
+ ring: t.ring ?? t.primary,
4425
+ brand: t.brand ?? t.primary,
4426
+ brandForeground: t.primaryForeground ?? "0 0% 100%",
4427
+ brandSubtle: t.brandSubtle
4428
+ });
4429
+ return {
4430
+ id: e,
4431
+ nameKey: `theme.${e}`,
4432
+ group: t,
4433
+ neutral: i,
4434
+ light: a(Ao, n),
4435
+ dark: a(jo, r)
4436
+ };
4437
+ }
4438
+ var Mo = "default", $ = [
4439
+ {
4440
+ id: "default",
4441
+ nameKey: "theme.default",
4442
+ group: "bold",
4443
+ light: Ao,
4444
+ dark: jo
4445
+ },
4446
+ Q("sandstone", "gray", {
4447
+ primary: "28 12% 34%",
4448
+ brandSubtle: "30 24% 92%"
4449
+ }, {
4450
+ primary: "30 10% 70%",
4451
+ primaryForeground: "30 16% 12%",
4452
+ brandSubtle: "30 12% 22%"
4453
+ }, "warm"),
4454
+ Q("graphite", "gray", {
4455
+ primary: "0 0% 34%",
4456
+ brandSubtle: "0 0% 92%"
4457
+ }, {
4458
+ primary: "0 0% 72%",
4459
+ primaryForeground: "0 0% 12%",
4460
+ brandSubtle: "0 0% 22%"
4461
+ }, "neutral"),
4462
+ Q("slate", "gray", {
4463
+ primary: "220 14% 36%",
4464
+ brandSubtle: "216 24% 92%"
4465
+ }, {
4466
+ primary: "218 12% 72%",
4467
+ primaryForeground: "220 22% 12%",
4468
+ brandSubtle: "218 16% 22%"
4469
+ }, "cool"),
4470
+ Q("ocean", "bold", {
4471
+ primary: "221 83% 53%",
4472
+ brandSubtle: "221 86% 95%"
4473
+ }, {
4474
+ primary: "217 91% 60%",
4475
+ brandSubtle: "221 55% 21%"
4476
+ }),
4477
+ Q("forest", "bold", {
4478
+ primary: "142 71% 38%",
4479
+ brandSubtle: "142 60% 94%"
4480
+ }, {
4481
+ primary: "142 65% 45%",
4482
+ brandSubtle: "142 40% 18%"
4483
+ }),
4484
+ Q("violet", "bold", {
4485
+ primary: "262 83% 58%",
4486
+ brandSubtle: "262 80% 96%"
4487
+ }, {
4488
+ primary: "263 70% 55%",
4489
+ brandSubtle: "263 45% 24%"
4490
+ }),
4491
+ Q("sunset", "bold", {
4492
+ primary: "25 95% 53%",
4493
+ brandSubtle: "28 90% 94%"
4494
+ }, {
4495
+ primary: "21 90% 50%",
4496
+ brandSubtle: "25 60% 22%"
4497
+ }),
4498
+ Q("rose", "bold", {
4499
+ primary: "346 77% 50%",
4500
+ brandSubtle: "346 80% 96%"
4501
+ }, {
4502
+ primary: "346 75% 55%",
4503
+ brandSubtle: "346 45% 24%"
4504
+ }),
4505
+ Q("teal", "bold", {
4506
+ primary: "174 72% 38%",
4507
+ brandSubtle: "174 60% 93%"
4508
+ }, {
4509
+ primary: "173 70% 46%",
4510
+ brandSubtle: "174 45% 18%"
4511
+ }),
4512
+ Q("amber", "bold", {
4513
+ primary: "38 92% 48%",
4514
+ primaryForeground: "30 40% 14%",
4515
+ brandSubtle: "40 90% 92%"
4516
+ }, {
4517
+ primary: "41 96% 56%",
4518
+ primaryForeground: "30 45% 12%",
4519
+ brandSubtle: "38 55% 20%"
4520
+ }),
4521
+ Q("pastel-sky", "pastel", {
4522
+ primary: "205 74% 70%",
4523
+ primaryForeground: "205 50% 22%",
4524
+ brandSubtle: "205 70% 95%"
4525
+ }, {
4526
+ primary: "205 60% 64%",
4527
+ primaryForeground: "205 45% 14%",
4528
+ brandSubtle: "205 38% 24%"
4529
+ }),
4530
+ Q("pastel-mint", "pastel", {
4531
+ primary: "152 48% 66%",
4532
+ primaryForeground: "152 45% 20%",
4533
+ brandSubtle: "152 50% 94%"
4534
+ }, {
4535
+ primary: "152 42% 58%",
4536
+ primaryForeground: "152 45% 12%",
4537
+ brandSubtle: "152 32% 22%"
4538
+ }),
4539
+ Q("pastel-lavender", "pastel", {
4540
+ primary: "258 60% 76%",
4541
+ primaryForeground: "258 45% 28%",
4542
+ brandSubtle: "258 60% 96%"
4543
+ }, {
4544
+ primary: "258 48% 68%",
4545
+ primaryForeground: "258 40% 14%",
4546
+ brandSubtle: "258 35% 26%"
4547
+ }),
4548
+ Q("pastel-rose", "pastel", {
4549
+ primary: "344 72% 78%",
4550
+ primaryForeground: "344 50% 30%",
4551
+ brandSubtle: "344 72% 96%"
4552
+ }, {
4553
+ primary: "344 56% 70%",
4554
+ primaryForeground: "344 45% 14%",
4555
+ brandSubtle: "344 38% 26%"
4556
+ }),
4557
+ Q("pastel-peach", "pastel", {
4558
+ primary: "24 84% 74%",
4559
+ primaryForeground: "20 55% 28%",
4560
+ brandSubtle: "26 84% 94%"
4561
+ }, {
4562
+ primary: "22 70% 66%",
4563
+ primaryForeground: "20 50% 14%",
4564
+ brandSubtle: "24 45% 24%"
4565
+ }),
4566
+ Q("pastel-butter", "pastel", {
4567
+ primary: "46 80% 70%",
4568
+ primaryForeground: "40 55% 24%",
4569
+ brandSubtle: "46 84% 92%"
4570
+ }, {
4571
+ primary: "46 66% 62%",
4572
+ primaryForeground: "40 50% 12%",
4573
+ brandSubtle: "44 42% 22%"
4574
+ })
4575
+ ], No = {
4576
+ warm: "sandstone",
4577
+ neutral: "graphite",
4578
+ cool: "slate"
4579
+ }, Po = (e) => $.find((t) => t.id === e) ?? $.find((t) => t.id === No[e]) ?? $[0], Fo = {
4580
+ gray: {
4581
+ light: "0 0% 96.5%",
4582
+ dark: "0 0% 15%"
4583
+ },
4584
+ red: {
4585
+ light: "6 60% 97.5%",
4586
+ dark: "4 26% 14.5%"
4587
+ },
4588
+ orange: {
4589
+ light: "28 70% 96.5%",
4590
+ dark: "24 28% 14.5%"
4591
+ },
4592
+ yellow: {
4593
+ light: "46 78% 96%",
4594
+ dark: "44 26% 14%"
4595
+ },
4596
+ green: {
4597
+ light: "140 42% 96.5%",
4598
+ dark: "140 22% 14%"
4599
+ },
4600
+ blue: {
4601
+ light: "210 58% 97.5%",
4602
+ dark: "210 28% 15%"
4603
+ },
4604
+ purple: {
4605
+ light: "265 48% 97.5%",
4606
+ dark: "265 24% 15.5%"
4607
+ },
4608
+ pink: {
4609
+ light: "330 58% 97.5%",
4610
+ dark: "330 24% 15.5%"
4611
+ }
4612
+ }, Io = {
4613
+ themeId: Mo,
4614
+ interfaceIntensity: 2,
4615
+ controlIntensity: 2,
4616
+ blurOverlays: !1
4617
+ };
4618
+ function Lo(e) {
4619
+ let t = { ...e };
4620
+ return t.tint !== void 0 && t.interfaceIntensity === void 0 && (t.interfaceIntensity = t.tint), t.accentIntensity !== void 0 && t.controlIntensity === void 0 && (t.controlIntensity = t.accentIntensity), typeof t.themeId == "string" && No[t.themeId] && (t.themeId = No[t.themeId]), delete t.tint, delete t.accentIntensity, delete t.neutral, delete t.tintedSidebar, t;
4621
+ }
4622
+ function Ro(e, t) {
4623
+ if (!t) return e;
4624
+ let n = { ...e };
4625
+ for (let e of Object.keys(t)) {
4626
+ let r = t[e];
4627
+ r !== void 0 && (n[e] = r);
4628
+ }
4629
+ return n;
4630
+ }
4631
+ var zo = (e, t, n) => Math.min(n, Math.max(t, e));
4632
+ function Bo(e) {
4633
+ let [t, n, r] = e.replace(/%/g, "").trim().split(/\s+/).map(Number);
4634
+ return {
4635
+ h: t || 0,
4636
+ s: n || 0,
4637
+ l: r || 0
4638
+ };
4639
+ }
4640
+ var Vo = (e) => String(Number.isInteger(e) ? e : Math.round(e * 10) / 10), Ho = ({ h: e, s: t, l: n }) => `${Vo((e % 360 + 360) % 360)} ${Vo(zo(t, 0, 100))}% ${Vo(zo(n, 0, 100))}%`, Uo = (e) => Bo(e).h, Wo = [
4641
+ 0,
4642
+ .55,
4643
+ 1,
4644
+ 1.5
4645
+ ], Go = [
4646
+ 0,
4647
+ 0,
4648
+ 0,
4649
+ 3
4650
+ ], Ko = [
4651
+ 0,
4652
+ 0,
4653
+ 0,
4654
+ 6
4655
+ ], qo = [
4656
+ 0,
4657
+ .55,
4658
+ 1,
4659
+ 1.7
4660
+ ], Jo = [
4661
+ 0,
4662
+ 0,
4663
+ 0,
4664
+ 6
4665
+ ], Yo = [
4666
+ 0,
4667
+ 0,
4668
+ 0,
4669
+ 11
4670
+ ], Xo = {
4671
+ background: .35,
4672
+ card: .35,
4673
+ popover: .32,
4674
+ secondary: .85,
4675
+ muted: .85,
4676
+ input: .9,
4677
+ border: .85,
4678
+ sheet1: 1.2,
4679
+ sheet2: 1.3
4680
+ }, Zo = Object.keys(Xo), Qo = {
4681
+ warm: 40,
4682
+ cool: 220,
4683
+ neutral: 0
4684
+ };
4685
+ function $o(e, t) {
4686
+ let n = Po(e.themeId), r = t === "dark" ? n.dark : n.light, i = { ...r }, a = Uo(r.primary), o = n.neutral ?? "warm", s = Qo[o], c = o === "neutral", l = (t === "dark" ? Ko : Go)[e.interfaceIntensity];
4687
+ for (let t of Zo) {
4688
+ let n = Bo(r[t]), a = Xo[t], o = c ? 0 : Math.max(n.s * Wo[e.interfaceIntensity], l * a);
4689
+ i[t] = Ho({
4690
+ h: c ? n.h : s,
4691
+ s: o,
4692
+ l: n.l
4693
+ });
4694
+ }
4695
+ {
4696
+ let n = Bo(r.accent), a = (t === "dark" ? Yo : Jo)[e.controlIntensity], o = c ? 0 : Math.max(n.s * qo[e.controlIntensity], a);
4697
+ i.accent = Ho({
4698
+ h: c ? n.h : s,
4699
+ s: o,
4700
+ l: n.l
4701
+ });
4702
+ }
4703
+ e.background && Fo[e.background] && (i.background = Fo[e.background][t]);
4704
+ {
4705
+ let n = Wo[e.interfaceIntensity], r = t === "dark" ? {
4706
+ s1: 34,
4707
+ l1: 16,
4708
+ s2: 40,
4709
+ l2: 19.5
4710
+ } : {
4711
+ s1: 42,
4712
+ l1: 96,
4713
+ s2: 50,
4714
+ l2: 90.5
4715
+ };
4716
+ i.sheet1 = Ho({
4717
+ h: a,
4718
+ s: c ? 0 : r.s1 * n,
4719
+ l: r.l1
4720
+ }), i.sheet2 = Ho({
4721
+ h: a,
4722
+ s: c ? 0 : r.s2 * n,
4723
+ l: r.l2
4724
+ });
4725
+ }
4726
+ return i;
4727
+ }
4728
+ var es = (e) => `--${e.replace(/([A-Z0-9])/g, "-$1").toLowerCase()}`;
4729
+ function ts(e, t) {
4730
+ let n = $o(e, t), r = {};
4731
+ for (let [e, t] of Object.entries(n)) r[es(e)] = t;
4732
+ return r;
4733
+ }
4734
+ function ns(e, t, n) {
4735
+ let r = n ?? (typeof document > "u" ? null : document.documentElement);
4736
+ if (!r) return;
4737
+ let i = $o(e, t);
4738
+ for (let [e, t] of Object.entries(i)) r.style.setProperty(es(e), t);
4739
+ }
4740
+ //#endregion
4741
+ //#region src/providers/ThemeProvider.tsx
4742
+ var rs = "openbook.appearance", is = "openbook.theme";
4743
+ function as() {
4744
+ if (typeof window > "u") return Io;
4745
+ try {
4746
+ let e = localStorage.getItem(rs);
4747
+ if (e) return {
4748
+ ...Io,
4749
+ ...Lo(JSON.parse(e))
4750
+ };
4751
+ } catch {}
4752
+ let e = localStorage.getItem(is);
4753
+ return e ? {
4754
+ ...Io,
4755
+ themeId: e
4756
+ } : Io;
4757
+ }
4758
+ var os = {
4759
+ mode: "system",
4760
+ colorScheme: "light",
4761
+ setMode: () => null,
4762
+ appearance: Io,
4763
+ setAppearance: () => null,
4764
+ themeId: Mo,
4765
+ setThemeId: () => null,
4766
+ themes: $
4767
+ }, ss = a.createContext(os);
4768
+ function cs({ children: e, defaultColorMode: t = "system", storageKey: n = "theme", ...r }) {
4769
+ let [i, o] = a.useState(() => typeof window < "u" && localStorage.getItem(n) || t), [s, c] = a.useState("light"), [l, u] = a.useState(as), d = i === "system" ? s : i;
4770
+ a.useEffect(() => {
4771
+ ns(l, d);
4772
+ }, [l, d]), a.useEffect(() => {
4773
+ typeof document > "u" || document.documentElement.style.setProperty("--overlay-blur", l.blurOverlays ? "8px" : "0px");
4774
+ }, [l.blurOverlays]), a.useEffect(() => {
4775
+ let e = (e) => {
4776
+ i === "system" && c(e.matches ? "dark" : "light");
4777
+ };
4778
+ return typeof window < "u" && window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", e), () => {
4779
+ typeof window < "u" && window.matchMedia("(prefers-color-scheme: dark)").removeEventListener("change", e);
4780
+ };
4781
+ }, []), a.useEffect(() => {
4782
+ let e = window.document.documentElement;
4783
+ e.classList.remove("light", "dark"), i === "system" ? (c(window.matchMedia("(prefers-color-scheme: dark)").matches ? "dark" : "light"), e.classList.add(s)) : e.classList.add(i);
4784
+ }, [i, s]);
4785
+ let f = a.useCallback((e) => {
4786
+ u((t) => {
4787
+ let n = {
4788
+ ...t,
4789
+ ...e
4790
+ };
4791
+ try {
4792
+ localStorage.setItem(rs, JSON.stringify(n));
4793
+ } catch {}
4794
+ return n;
4795
+ });
4796
+ }, []), m = {
4797
+ mode: i,
4798
+ colorScheme: d,
4799
+ setMode: (e) => {
4800
+ localStorage.setItem(n, e), o(e);
4801
+ },
4802
+ appearance: l,
4803
+ setAppearance: f,
4804
+ themeId: l.themeId,
4805
+ setThemeId: (e) => f({ themeId: e }),
4806
+ themes: $
4807
+ };
4808
+ return /* @__PURE__ */ p(ss.Provider, {
4809
+ ...r,
4810
+ value: m,
4811
+ children: e
4812
+ });
4813
+ }
4814
+ var ls = () => {
4815
+ let e = a.useContext(ss);
4816
+ if (e === void 0) throw Error("useTheme must be used within a ThemeProvider");
4817
+ return e;
4818
+ }, us = "lucide:", ds = (e) => !!e && e.startsWith("lucide:"), fs = (e) => !e || ds(e) ? "" : e, ps = {
4819
+ Star: kn,
4820
+ Heart: mt,
4821
+ Bookmark: se,
4822
+ Flag: Xe,
4823
+ Pin: rn,
4824
+ Tag: Pn,
4825
+ Crown: Ie,
4826
+ Award: N,
4827
+ Trophy: Gn,
4828
+ Gem: it,
4829
+ Diamond: Re,
4830
+ Sparkles: En,
4831
+ Flame: Ze,
4832
+ Zap: or,
4833
+ Gift: at,
4834
+ PartyPopper: Zt,
4835
+ Smile: wn,
4836
+ ThumbsUp: Rn,
4837
+ Check: be,
4838
+ CheckCircle2: xe,
4839
+ Target: Fn,
4840
+ Infinity: yt,
4841
+ FileText: qe,
4842
+ Folder: et,
4843
+ Book: z,
4844
+ BookOpen: oe,
4845
+ Library: Ot,
4846
+ Newspaper: Kt,
4847
+ Clipboard: Ee,
4848
+ List: jt,
4849
+ Archive: M,
4850
+ Inbox: vt,
4851
+ Briefcase: ue,
4852
+ Calendar: ge,
4853
+ Clock: De,
4854
+ AlarmClock: O,
4855
+ Timer: Bn,
4856
+ Paperclip: Xt,
4857
+ BarChart3: re,
4858
+ PieChart: tn,
4859
+ TrendingUp: Wn,
4860
+ Table: Nn,
4861
+ Grid3x3: lt,
4862
+ Database: Le,
4863
+ Layers: Tt,
4864
+ Gauge: rt,
4865
+ Calculator: he,
4866
+ DollarSign: Be,
4867
+ Coins: Me,
4868
+ Wallet: $n,
4869
+ CreditCard: Fe,
4870
+ PiggyBank: nn,
4871
+ ShoppingBag: Sn,
4872
+ ShoppingCart: Cn,
4873
+ Scale: hn,
4874
+ Code2: ke,
4875
+ Terminal: Ln,
4876
+ Cpu: Pe,
4877
+ Binary: ie,
4878
+ GitBranch: ot,
4879
+ Bug: fe,
4880
+ Cog: je,
4881
+ Settings: yn,
4882
+ Wrench: ar,
4883
+ Hammer: ut,
4884
+ Plug: sn,
4885
+ Key: xt,
4886
+ Lock: Mt,
4887
+ Shield: xn,
4888
+ Wifi: rr,
4889
+ Monitor: Bt,
4890
+ Laptop: wt,
4891
+ Keyboard: St,
4892
+ Mouse: Ut,
4893
+ Mail: Nt,
4894
+ MessageCircle: Lt,
4895
+ MessageSquare: Rt,
4896
+ Send: vn,
4897
+ Bell: L,
4898
+ Megaphone: It,
4899
+ Phone: en,
4900
+ Share2: bn,
4901
+ Link: At,
4902
+ Hash: ft,
4903
+ Image: _t,
4904
+ Camera: _e,
4905
+ Video: Qn,
4906
+ Film: Je,
4907
+ Clapperboard: Te,
4908
+ Music: Wt,
4909
+ Headphones: pt,
4910
+ Mic: zt,
4911
+ Speaker: Dn,
4912
+ Radio: dn,
4913
+ Tv: qn,
4914
+ Play: on,
4915
+ Gamepad2: nt,
4916
+ Palette: Jt,
4917
+ Brush: de,
4918
+ PenTool: Qt,
4919
+ Pencil: $t,
4920
+ Aperture: j,
4921
+ User: Yn,
4922
+ Users: Xn,
4923
+ Hand: dt,
4924
+ Eye: Ge,
4925
+ Brain: le,
4926
+ Footprints: tt,
4927
+ GraduationCap: ct,
4928
+ Dumbbell: Ue,
4929
+ Leaf: Dt,
4930
+ Sprout: On,
4931
+ Flower2: $e,
4932
+ TreePine: Un,
4933
+ Mountain: Ht,
4934
+ Globe: st,
4935
+ Sun: jn,
4936
+ Moon: Vt,
4937
+ Cloud: Oe,
4938
+ Snowflake: Tn,
4939
+ Droplet: He,
4940
+ Waves: nr,
4941
+ Wind: ir,
4942
+ Umbrella: Jn,
4943
+ Feather: Ke,
4944
+ Bird: ae,
4945
+ Dog: ze,
4946
+ Rabbit: un,
4947
+ Coffee: Ae,
4948
+ Utensils: Zn,
4949
+ Cake: me,
4950
+ ChefHat: Se,
4951
+ Carrot: ye,
4952
+ Cherry: Ce,
4953
+ Egg: We,
4954
+ Beaker: I,
4955
+ FlaskConical: Qe,
4956
+ Home: gt,
4957
+ Building2: B,
4958
+ Tent: In,
4959
+ MapPin: Ft,
4960
+ Map: Pt,
4961
+ Compass: Ne,
4962
+ Navigation: Gt,
4963
+ Rocket: fn,
4964
+ Plane: an,
4965
+ Car: ve,
4966
+ Bus: pe,
4967
+ Bike: R,
4968
+ Truck: Kn,
4969
+ Anchor: A,
4970
+ Backpack: P,
4971
+ Ticket: zn,
4972
+ Lamp: Ct,
4973
+ Lightbulb: kt,
4974
+ Box: ce,
4975
+ Package: qt,
4976
+ Puzzle: ln,
4977
+ Ruler: pn,
4978
+ Scissors: gn,
4979
+ Sword: Mn,
4980
+ Sticker: An,
4981
+ Watch: tr,
4982
+ Battery: F,
4983
+ Wand2: er,
4984
+ Activity: D,
4985
+ Search: _n,
4986
+ Filter: Ye,
4987
+ Plus: cn,
4988
+ Download: Ve,
4989
+ Save: mn,
4990
+ Trash2: Hn,
4991
+ Info: bt,
4992
+ HelpCircle: ht,
4993
+ AlertTriangle: k,
4994
+ ToggleLeft: Vn,
4995
+ PanelLeft: Yt,
4996
+ Layout: Et,
4997
+ Circle: we
4998
+ }, ms = Object.keys(ps);
4999
+ function hs(e) {
5000
+ return ps[e.startsWith("lucide:") ? e.slice(7) : e] ?? null;
5001
+ }
5002
+ //#endregion
5003
+ export { li as $, oa as A, lr as At, Ji as B, Ea as C, Er as Ct, Da as D, dr as Dt, wa as E, H as Et, pa as F, Bi as G, zi as H, da as I, Li as J, Vi as K, fa as L, ia as M, V as Mt, ra as N, ca as O, mr as Ot, sa as P, vi as Q, ea as R, Ca as S, wr as St, Ta as T, yr as Tt, Wi as U, qi as V, Ui as W, _i as X, Mi as Y, yi as Z, Fa as _, Ar as _t, ds as a, ni as at, Ia as b, jr as bt, ls as c, qr as ct, Po as d, Jr as dt, ui as et, Ro as f, Kr as ft, Co as g, kr as gt, ko as h, Wr as ht, us as i, ti as it, la as j, cr as jt, aa as k, hr as kt, Fo as l, Zr as lt, $ as m, Xr as mt, ms as n, si as nt, fs as o, $r as ot, Lo as p, Gr as pt, Ii as q, hs as r, ci as rt, cs as s, Ur as st, ps as t, fi as tt, ts as u, Yr as ut, Pa as v, Vr as vt, xa as w, Tr as wt, Sa as x, Hr as xt, Ra as y, Mr as yt, na as z };