@book.dev/ui 1.60.0 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{EmojiGrid-xK5mPJPo.js → EmojiGrid-BjFEmkhL.js} +75 -84
- package/dist/blockeditor/BlockEditor.d.ts +16 -0
- package/dist/blockeditor/EmojiMenu.d.ts +17 -0
- package/dist/blockeditor/__tests__/EmojiMenu.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/readOnly.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/titleHandoff.test.d.ts +1 -0
- package/dist/blockeditor/__tests__/triggerMenus.test.d.ts +1 -0
- package/dist/blockeditor/kit/KitFrame.d.ts +5 -0
- package/dist/blockeditor/kit/groupSync.d.ts +10 -1
- package/dist/blockeditor/kit/lock.d.ts +14 -0
- package/dist/components/LastEditedBy.d.ts +11 -0
- package/dist/components/OnboardingNudge.d.ts +11 -0
- package/dist/components/ShareDialog.d.ts +25 -0
- package/dist/components/__tests__/lastEditedBy.test.d.ts +1 -0
- package/dist/components/__tests__/membersSettings.test.d.ts +1 -0
- package/dist/components/__tests__/sharingSettings.test.d.ts +1 -0
- package/dist/components/settings/AccountSettings.d.ts +4 -0
- package/dist/components/settings/AccountSwitcher.d.ts +12 -0
- package/dist/components/settings/MembersSettings.d.ts +1 -0
- package/dist/components/settings/SharingSettings.d.ts +9 -0
- package/dist/emoji-Bmft6RPl.js +11 -0
- package/dist/{format-CLQoRoYP.js → format-BXeG5xQH.js} +61 -61
- package/dist/i18n/messages/en.d.ts +169 -0
- package/dist/index.js +7328 -6057
- package/dist/lib/__tests__/useCanWrite.test.d.ts +1 -0
- package/dist/lib/hud.d.ts +2 -2
- package/dist/lib/sidebarStyles.d.ts +7 -0
- package/dist/lib/useCanWrite.d.ts +45 -0
- package/dist/{lucideIcons-B6pmC-WQ.js → lucideIcons-DvomlmkS.js} +2093 -1180
- package/dist/providers/AccountProvider.d.ts +47 -7
- package/dist/providers/ForwardingProvider.d.ts +19 -0
- package/dist/providers/PlatformLibraryProvider.d.ts +20 -0
- package/dist/providers/PreferencesProvider.d.ts +8 -1
- package/dist/providers/WorkspaceProvider.d.ts +4 -2
- package/dist/providers/__tests__/AccountProvider.test.d.ts +1 -0
- package/dist/providers/__tests__/forwardingAudience.test.d.ts +9 -0
- package/dist/providers/forwardingAudience.d.ts +165 -0
- package/dist/screens/pageChrome.d.ts +11 -0
- package/dist/style.css +1 -1
- package/dist/{toHtml-BoPr8Ce4.js → toHtml-B6gQeUnu.js} +2 -2
- package/package.json +7 -2
|
@@ -1,18 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
//#region src/lib/emoji.ts
|
|
6
|
-
function f(e, t = 8) {
|
|
7
|
-
let n = e.trim().toLowerCase();
|
|
8
|
-
return n ? d(n).slice().sort((e, t) => p(e.name, n) - p(t.name, n)).slice(0, t) : [];
|
|
9
|
-
}
|
|
10
|
-
function p(e, t) {
|
|
11
|
-
return e === t ? 0 : e.startsWith(t) ? 1 : 2;
|
|
12
|
-
}
|
|
13
|
-
//#endregion
|
|
1
|
+
import { Nt as e, U as t, i as n, n as r, t as i } from "./lucideIcons-DvomlmkS.js";
|
|
2
|
+
import { t as a } from "./emoji-Bmft6RPl.js";
|
|
3
|
+
import { useMemo as o, useRef as s, useState as c } from "react";
|
|
4
|
+
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
14
5
|
//#region src/lib/emojiData.ts
|
|
15
|
-
var
|
|
6
|
+
var f = [
|
|
16
7
|
{
|
|
17
8
|
id: "smileys",
|
|
18
9
|
icon: "😀",
|
|
@@ -54,152 +45,152 @@ var m = [
|
|
|
54
45
|
emojis: /* @__PURE__ */ "❤️.🧡.💛.💚.💙.💜.🖤.🤍.🤎.💔.❣️.💕.💞.💓.💗.💖.💘.💝.💟.☮️.✝️.☪️.🕉️.☸️.✡️.🔯.🕎.☯️.☦️.⛎.♈.♉.♊.♋.♌.♍.♎.♏.♐.♑.♒.♓.🆔.⚛️.🉑.☢️.☣️.📴.✅.❌.❎.➕.➖.➗.✖️.♾️.‼️.⁉️.❓.❔.❕.❗.〰️.⚠️.🚸.🔱.⚜️.🔰.♻️.✳️.❇️.⭐.🌟.💫.⭕.🔴.🟠.🟡.🟢.🔵.🟣.🟤.⚫.⚪.🔺.🔻.🔸.🔹.🔶.🔷.🔳.🔲.▪️.▫️.◼️.◻️.🏁.🚩.🎌.🏴.🏳️.🏳️🌈.🔔.🔕.🎵.🎶.💬.💭".split(".")
|
|
55
46
|
}
|
|
56
47
|
];
|
|
57
|
-
Array.from(new Set(
|
|
48
|
+
Array.from(new Set(f.flatMap((e) => e.emojis)));
|
|
58
49
|
//#endregion
|
|
59
50
|
//#region src/lib/iconRecents.ts
|
|
60
|
-
var
|
|
61
|
-
function
|
|
51
|
+
var p = "openbook.iconRecents", m = 24;
|
|
52
|
+
function h() {
|
|
62
53
|
if (typeof localStorage > "u") return [];
|
|
63
54
|
try {
|
|
64
|
-
let e = localStorage.getItem(
|
|
65
|
-
return Array.isArray(t) ? t.filter((e) => typeof e == "string").slice(0,
|
|
55
|
+
let e = localStorage.getItem(p), t = e ? JSON.parse(e) : [];
|
|
56
|
+
return Array.isArray(t) ? t.filter((e) => typeof e == "string").slice(0, m) : [];
|
|
66
57
|
} catch {
|
|
67
58
|
return [];
|
|
68
59
|
}
|
|
69
60
|
}
|
|
70
|
-
function
|
|
61
|
+
function g(e) {
|
|
71
62
|
if (!(typeof localStorage > "u" || !e)) try {
|
|
72
|
-
let t = [e, ...
|
|
73
|
-
localStorage.setItem(
|
|
63
|
+
let t = [e, ...h().filter((t) => t !== e)].slice(0, m);
|
|
64
|
+
localStorage.setItem(p, JSON.stringify(t));
|
|
74
65
|
} catch {}
|
|
75
66
|
}
|
|
76
67
|
//#endregion
|
|
77
68
|
//#region src/components/EmojiGrid.tsx
|
|
78
|
-
function
|
|
79
|
-
let { t: r } =
|
|
80
|
-
return /* @__PURE__ */
|
|
69
|
+
function _({ value: e, onPick: n }) {
|
|
70
|
+
let { t: r } = t(), [i, a] = c(e?.startsWith("lucide:") ? "icon" : "emoji"), [o, l] = c(""), f = s(h()).current;
|
|
71
|
+
return /* @__PURE__ */ d("div", {
|
|
81
72
|
className: "flex h-[372px] w-[332px] flex-col bg-popover text-popover-foreground",
|
|
82
73
|
children: [
|
|
83
|
-
/* @__PURE__ */
|
|
74
|
+
/* @__PURE__ */ d("div", {
|
|
84
75
|
className: "flex items-center gap-1 p-2 pb-1.5",
|
|
85
|
-
children: [/* @__PURE__ */
|
|
76
|
+
children: [/* @__PURE__ */ u(v, {
|
|
86
77
|
active: i === "emoji",
|
|
87
78
|
onClick: () => a("emoji"),
|
|
88
79
|
label: r("emoji.tabEmoji")
|
|
89
|
-
}), /* @__PURE__ */
|
|
80
|
+
}), /* @__PURE__ */ u(v, {
|
|
90
81
|
active: i === "icon",
|
|
91
82
|
onClick: () => a("icon"),
|
|
92
83
|
label: r("emoji.tabIcons")
|
|
93
84
|
})]
|
|
94
85
|
}),
|
|
95
|
-
/* @__PURE__ */
|
|
86
|
+
/* @__PURE__ */ u("div", {
|
|
96
87
|
className: "px-2 pb-2",
|
|
97
|
-
children: /* @__PURE__ */
|
|
88
|
+
children: /* @__PURE__ */ u("input", {
|
|
98
89
|
autoFocus: !0,
|
|
99
|
-
value:
|
|
100
|
-
onChange: (e) =>
|
|
90
|
+
value: o,
|
|
91
|
+
onChange: (e) => l(e.target.value),
|
|
101
92
|
placeholder: r(i === "emoji" ? "emoji.searchEmoji" : "emoji.searchIcons"),
|
|
102
93
|
className: "h-8 w-full rounded-md border border-input bg-background px-2.5 text-sm outline-hidden placeholder:text-muted-foreground focus-visible:ring-2 focus-visible:ring-ring",
|
|
103
94
|
"aria-label": r("emoji.search")
|
|
104
95
|
})
|
|
105
96
|
}),
|
|
106
|
-
/* @__PURE__ */
|
|
97
|
+
/* @__PURE__ */ u("div", {
|
|
107
98
|
className: "min-h-0 flex-1 overflow-y-auto px-2 pb-2",
|
|
108
|
-
children:
|
|
109
|
-
query:
|
|
99
|
+
children: u(i === "emoji" ? S : w, {
|
|
100
|
+
query: o,
|
|
110
101
|
recents: f,
|
|
111
|
-
current:
|
|
102
|
+
current: e,
|
|
112
103
|
onPick: (e) => {
|
|
113
|
-
|
|
104
|
+
g(e), n(e);
|
|
114
105
|
}
|
|
115
106
|
})
|
|
116
107
|
})
|
|
117
108
|
]
|
|
118
109
|
});
|
|
119
110
|
}
|
|
120
|
-
function
|
|
121
|
-
return /* @__PURE__ */
|
|
111
|
+
function v({ active: t, onClick: n, label: r }) {
|
|
112
|
+
return /* @__PURE__ */ u("button", {
|
|
122
113
|
type: "button",
|
|
123
114
|
onClick: n,
|
|
124
|
-
className:
|
|
115
|
+
className: e("flex-1 cursor-pointer rounded-md px-2.5 py-1 text-sm font-medium transition-colors", t ? "bg-accent text-accent-foreground" : "text-muted-foreground hover:bg-hover"),
|
|
125
116
|
children: r
|
|
126
117
|
});
|
|
127
118
|
}
|
|
128
|
-
function
|
|
129
|
-
return /* @__PURE__ */
|
|
119
|
+
function y({ children: e }) {
|
|
120
|
+
return /* @__PURE__ */ u("div", {
|
|
130
121
|
className: "sticky top-0 z-10 bg-popover px-1 pb-1 pt-1.5 text-xs font-medium uppercase tracking-wide text-muted-foreground/70",
|
|
131
122
|
children: e
|
|
132
123
|
});
|
|
133
124
|
}
|
|
134
|
-
var
|
|
135
|
-
function
|
|
136
|
-
return /* @__PURE__ */
|
|
125
|
+
var b = "grid grid-cols-8 gap-0.5";
|
|
126
|
+
function x({ glyph: t, active: n, onPick: r }) {
|
|
127
|
+
return /* @__PURE__ */ u("button", {
|
|
137
128
|
type: "button",
|
|
138
|
-
onClick: () => r(
|
|
139
|
-
className:
|
|
140
|
-
title:
|
|
141
|
-
children:
|
|
129
|
+
onClick: () => r(t),
|
|
130
|
+
className: e("flex h-9 w-9 items-center justify-center rounded-md text-[20px] leading-none transition-colors hover:bg-hover", n && "bg-accent ring-1 ring-primary"),
|
|
131
|
+
title: t,
|
|
132
|
+
children: t
|
|
142
133
|
});
|
|
143
134
|
}
|
|
144
|
-
function
|
|
145
|
-
let { t:
|
|
146
|
-
return
|
|
147
|
-
className:
|
|
148
|
-
children:
|
|
135
|
+
function S({ query: e, recents: r, current: i, onPick: s }) {
|
|
136
|
+
let { t: c } = t(), p = o(() => e.trim() ? a(e, 64).map((e) => e.emoji) : null, [e]), m = r.filter((e) => !e.startsWith(n));
|
|
137
|
+
return p ? p.length === 0 ? /* @__PURE__ */ u(T, { text: c("emoji.noResults") }) : /* @__PURE__ */ u("div", {
|
|
138
|
+
className: b,
|
|
139
|
+
children: p.map((e, t) => /* @__PURE__ */ u(x, {
|
|
149
140
|
glyph: e,
|
|
150
141
|
active: e === i,
|
|
151
|
-
onPick:
|
|
142
|
+
onPick: s
|
|
152
143
|
}, `${e}-${t}`))
|
|
153
|
-
}) : /* @__PURE__ */
|
|
154
|
-
className:
|
|
155
|
-
children:
|
|
144
|
+
}) : /* @__PURE__ */ d(l, { children: [m.length > 0 && /* @__PURE__ */ d("section", { children: [/* @__PURE__ */ u(y, { children: c("emoji.recent") }), /* @__PURE__ */ u("div", {
|
|
145
|
+
className: b,
|
|
146
|
+
children: m.map((e, t) => /* @__PURE__ */ u(x, {
|
|
156
147
|
glyph: e,
|
|
157
148
|
active: e === i,
|
|
158
|
-
onPick:
|
|
149
|
+
onPick: s
|
|
159
150
|
}, `r-${e}-${t}`))
|
|
160
|
-
})] }),
|
|
161
|
-
className:
|
|
162
|
-
children: e.emojis.map((t, n) => /* @__PURE__ */
|
|
151
|
+
})] }), f.map((e) => /* @__PURE__ */ d("section", { children: [/* @__PURE__ */ u(y, { children: c(`emoji.cat.${e.id}`) }), /* @__PURE__ */ u("div", {
|
|
152
|
+
className: b,
|
|
153
|
+
children: e.emojis.map((t, n) => /* @__PURE__ */ u(x, {
|
|
163
154
|
glyph: t,
|
|
164
155
|
active: t === i,
|
|
165
|
-
onPick:
|
|
156
|
+
onPick: s
|
|
166
157
|
}, `${e.id}-${t}-${n}`))
|
|
167
158
|
})] }, e.id))] });
|
|
168
159
|
}
|
|
169
|
-
function
|
|
170
|
-
let o = i[
|
|
171
|
-
return o ? /* @__PURE__ */
|
|
160
|
+
function C({ name: t, active: r, onPick: a }) {
|
|
161
|
+
let o = i[t];
|
|
162
|
+
return o ? /* @__PURE__ */ u("button", {
|
|
172
163
|
type: "button",
|
|
173
|
-
onClick: () => a(`${n}${
|
|
174
|
-
className:
|
|
175
|
-
title:
|
|
176
|
-
"aria-label":
|
|
177
|
-
children: /* @__PURE__ */
|
|
164
|
+
onClick: () => a(`${n}${t}`),
|
|
165
|
+
className: e("flex h-9 w-9 items-center justify-center rounded-md text-foreground transition-colors hover:bg-hover", r && "bg-accent ring-1 ring-primary"),
|
|
166
|
+
title: t,
|
|
167
|
+
"aria-label": t,
|
|
168
|
+
children: /* @__PURE__ */ u(o, { className: "h-[18px] w-[18px]" })
|
|
178
169
|
}) : null;
|
|
179
170
|
}
|
|
180
|
-
function
|
|
181
|
-
let { t: f } =
|
|
182
|
-
return m.length === 0 ? /* @__PURE__ */
|
|
183
|
-
className:
|
|
184
|
-
children: g.map((e, t) => /* @__PURE__ */
|
|
171
|
+
function w({ query: e, recents: a, current: s, onPick: c }) {
|
|
172
|
+
let { t: f } = t(), p = e.trim().toLowerCase(), m = o(() => p ? r.filter((e) => e.toLowerCase().includes(p)) : r, [p]), h = s?.startsWith("lucide:") ? s.slice(n.length) : void 0, g = a.filter((e) => e.startsWith(n)).map((e) => e.slice(n.length)).filter((e) => i[e]);
|
|
173
|
+
return m.length === 0 ? /* @__PURE__ */ u(T, { text: f("emoji.noResults") }) : /* @__PURE__ */ d(l, { children: [!p && g.length > 0 && /* @__PURE__ */ d("section", { children: [/* @__PURE__ */ u(y, { children: f("emoji.recent") }), /* @__PURE__ */ u("div", {
|
|
174
|
+
className: b,
|
|
175
|
+
children: g.map((e, t) => /* @__PURE__ */ u(C, {
|
|
185
176
|
name: e,
|
|
186
177
|
active: e === h,
|
|
187
|
-
onPick:
|
|
178
|
+
onPick: c
|
|
188
179
|
}, `r-${e}-${t}`))
|
|
189
|
-
})] }), /* @__PURE__ */
|
|
190
|
-
className:
|
|
191
|
-
children: m.map((e) => /* @__PURE__ */
|
|
180
|
+
})] }), /* @__PURE__ */ d("section", { children: [!p && /* @__PURE__ */ u(y, { children: f("emoji.tabIcons") }), /* @__PURE__ */ u("div", {
|
|
181
|
+
className: b,
|
|
182
|
+
children: m.map((e) => /* @__PURE__ */ u(C, {
|
|
192
183
|
name: e,
|
|
193
184
|
active: e === h,
|
|
194
|
-
onPick:
|
|
185
|
+
onPick: c
|
|
195
186
|
}, e))
|
|
196
187
|
})] })] });
|
|
197
188
|
}
|
|
198
|
-
function
|
|
199
|
-
return /* @__PURE__ */
|
|
189
|
+
function T({ text: e }) {
|
|
190
|
+
return /* @__PURE__ */ u("div", {
|
|
200
191
|
className: "flex h-24 items-center justify-center text-sm text-muted-foreground",
|
|
201
192
|
children: e
|
|
202
193
|
});
|
|
203
194
|
}
|
|
204
195
|
//#endregion
|
|
205
|
-
export {
|
|
196
|
+
export { _ as default };
|
|
@@ -14,6 +14,7 @@ import type { InlineAttrs } from './model';
|
|
|
14
14
|
export interface EditorUI {
|
|
15
15
|
slash: SlashState;
|
|
16
16
|
mention: SlashState;
|
|
17
|
+
emoji: SlashState;
|
|
17
18
|
spellcheck: boolean;
|
|
18
19
|
openSlash(blockId: string, anchorOffset: number): void;
|
|
19
20
|
updateSlash(caret: number): void;
|
|
@@ -23,8 +24,19 @@ export interface EditorUI {
|
|
|
23
24
|
updateMention(caret: number): void;
|
|
24
25
|
closeMention(): void;
|
|
25
26
|
mentionKey(key: string): void;
|
|
27
|
+
openEmoji(blockId: string, anchorOffset: number): void;
|
|
28
|
+
updateEmoji(caret: number): void;
|
|
29
|
+
closeEmoji(): void;
|
|
30
|
+
emojiKey(key: string): void;
|
|
26
31
|
toggleFormat(key: keyof InlineAttrs, value?: string): void;
|
|
27
32
|
scheduleToolbar(): void;
|
|
33
|
+
/** Leave the editor for the page title above (↑/←/Backspace at the very top). */
|
|
34
|
+
leaveToTitle?(): void;
|
|
35
|
+
}
|
|
36
|
+
/** Imperative handle the host uses to hand the caret into the editor. */
|
|
37
|
+
export interface BlockEditorHandle {
|
|
38
|
+
/** Focus the first text block at its start, creating a paragraph if empty. */
|
|
39
|
+
focusStart(): void;
|
|
28
40
|
}
|
|
29
41
|
export type DropRegion = 'above' | 'below' | 'left' | 'right';
|
|
30
42
|
interface DragState {
|
|
@@ -47,6 +59,10 @@ export declare const BlockEditor: React.FC<{
|
|
|
47
59
|
spellcheck?: boolean;
|
|
48
60
|
/** The page hosting this editor — powers the "New page/database" commands. */
|
|
49
61
|
pageId?: string;
|
|
62
|
+
/** Imperative handle so the title can hand the caret to the first block. */
|
|
63
|
+
focusRef?: React.Ref<BlockEditorHandle>;
|
|
64
|
+
/** Leave the editor for the title above (caret at the top of the document). */
|
|
65
|
+
onLeaveToTitle?: () => void;
|
|
50
66
|
}>;
|
|
51
67
|
export interface RowShared {
|
|
52
68
|
editor: BlockEditorController;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import type { SlashState } from './SlashMenu';
|
|
3
|
+
import type { BlockEditorController } from './useBlockEditor';
|
|
4
|
+
/**
|
|
5
|
+
* The ":" emoji menu: like the slash and mention menus but for emoji. Trigger
|
|
6
|
+
* detection, query tracking and key forwarding mirror those menus; this only
|
|
7
|
+
* differs in its items (offline `searchEmojis`) and how a pick is inserted —
|
|
8
|
+
* the typed ":query" is removed and the chosen glyph dropped in its place.
|
|
9
|
+
*/
|
|
10
|
+
export declare const EmojiMenu: React.FC<{
|
|
11
|
+
state: SlashState;
|
|
12
|
+
editor: BlockEditorController;
|
|
13
|
+
anchorEl: HTMLElement | null;
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
/** Insert the chosen glyph (plain text) at the offset where ":" was typed. */
|
|
16
|
+
onInsertText: (blockId: string, anchorOffset: number, text: string) => void;
|
|
17
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -44,6 +44,11 @@ export declare const ConfigToggle: React.FC<{
|
|
|
44
44
|
* so it looks like the text it replaces; falls back to a static span when the
|
|
45
45
|
* editor is read-only (or the block's group is locked). `stopPropagation` keeps
|
|
46
46
|
* keystrokes out of the surrounding block editor's shortcuts.
|
|
47
|
+
*
|
|
48
|
+
* On a read-only page the widget's *control* revives (interactive exemption)
|
|
49
|
+
* with a `liveEditor`, so `readOnly` arrives `false` here — but the label is
|
|
50
|
+
* chrome, not a control, and must stay frozen. {@link useKitPageLock} re-freezes
|
|
51
|
+
* it independently of the control's editor.
|
|
47
52
|
*/
|
|
48
53
|
export declare const KitInlineText: React.FC<{
|
|
49
54
|
value: string;
|
|
@@ -18,6 +18,15 @@ export declare const readGroupSync: (key: string) => Values;
|
|
|
18
18
|
*/
|
|
19
19
|
export declare function writeGroupSync(key: string, values: Values): boolean;
|
|
20
20
|
export declare function subscribeGroupSync(key: string, cb: () => void): () => void;
|
|
21
|
-
/**
|
|
21
|
+
/**
|
|
22
|
+
* Loose deep equality for the small value shapes inputs publish: scalars,
|
|
23
|
+
* arrays, and plain objects (e.g. the `location` input's `{lat,lng,label}`).
|
|
24
|
+
*
|
|
25
|
+
* Object-valued inputs MUST compare structurally, not by reference. A render
|
|
26
|
+
* recomputes `inputValue` into a fresh object each time, so a reference compare
|
|
27
|
+
* always reports "changed" — which makes the GroupView publish effect re-write
|
|
28
|
+
* the store and `notify()` every synced pane on every edit (a latent publish↔
|
|
29
|
+
* adopt ping-pong once any object-valued input gains a real `setInputValue`).
|
|
30
|
+
*/
|
|
22
31
|
export declare function valueEqual(a: unknown, b: unknown): boolean;
|
|
23
32
|
export {};
|
|
@@ -10,3 +10,17 @@ export interface KitLockState {
|
|
|
10
10
|
export declare const KitLockContext: import("react").Context<KitLockState>;
|
|
11
11
|
/** Whether the nearest enclosing group is locked. */
|
|
12
12
|
export declare const useKitLock: () => boolean;
|
|
13
|
+
/**
|
|
14
|
+
* Whether the whole page is read-only (a viewer who can't write). Set ONCE at
|
|
15
|
+
* the editor root and never re-provided by groups, so it survives nesting —
|
|
16
|
+
* unlike {@link KitLockContext}, which a locked group flips on for its subtree.
|
|
17
|
+
*
|
|
18
|
+
* Interactive widgets revive under a page lock (their control gets a `liveEditor`
|
|
19
|
+
* with `readOnly:false`), which would otherwise make their kit chrome — the
|
|
20
|
+
* inline label / description — editable again. The {@link KitInlineText} chrome
|
|
21
|
+
* consults this so the control stays live while the label/config text stays
|
|
22
|
+
* frozen for the reader.
|
|
23
|
+
*/
|
|
24
|
+
export declare const KitPageLockContext: import("react").Context<boolean>;
|
|
25
|
+
/** Whether the whole page is read-only (viewer / can't-write). */
|
|
26
|
+
export declare const useKitPageLock: () => boolean;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A subtle "Edited by X · 2h" indicator in the page header cluster (OB-165),
|
|
3
|
+
* read from the change provenance log so the *who* and *when* of the last edit
|
|
4
|
+
* are visible, not just stored. Renders nothing when the server has no edit log
|
|
5
|
+
* (an older build) or the page has no recorded edits yet. Refreshes when the
|
|
6
|
+
* page is saved so it reflects the latest editor (including you).
|
|
7
|
+
*/
|
|
8
|
+
export declare function LastEditedBy({ pageId }: {
|
|
9
|
+
pageId: string;
|
|
10
|
+
}): import("react/jsx-runtime").JSX.Element | null;
|
|
11
|
+
export default LastEditedBy;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A tasteful, dismissible "sign up free to publish" prompt for the genuinely
|
|
3
|
+
* unauthenticated user — the on-ramp from local-first into a first publish
|
|
4
|
+
* (OB-206). It sits at the foot of the sidebar and only ever appears when no
|
|
5
|
+
* account is connected; signing in (or dismissing it) retires it for good. We
|
|
6
|
+
* never force it: local-first stays the default, this is just the door.
|
|
7
|
+
*
|
|
8
|
+
* The CTA opens Settings → Account, where the actual sign-in / add-account flow
|
|
9
|
+
* lives, rather than firing the OAuth popup straight from the sidebar.
|
|
10
|
+
*/
|
|
11
|
+
export default function OnboardingNudge(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { type InstanceInfo } from '@book.dev/sdk';
|
|
2
|
+
/**
|
|
3
|
+
* Does this principal manage sharing instance-wide? The loopback owner, an
|
|
4
|
+
* instance admin, and the claimed owner all do; on a still-unclaimed instance the
|
|
5
|
+
* legacy guest gate governs (anyone who may write). This is the coarse gate for
|
|
6
|
+
* the Share *entry point* — the per-page routes still enforce write server-side,
|
|
7
|
+
* and the dialog degrades to an error state if a specific page load is refused.
|
|
8
|
+
*/
|
|
9
|
+
export declare function canManageSharing(info: InstanceInfo): boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Whether the current user may manage page sharing (gates the Share control).
|
|
12
|
+
* `null` while the one-shot `/api/instance` lookup is in flight; `false` if the
|
|
13
|
+
* server predates multi-user (no endpoint) so the control simply stays hidden.
|
|
14
|
+
*/
|
|
15
|
+
export declare function useCanManageSharing(): boolean | null;
|
|
16
|
+
/**
|
|
17
|
+
* The per-page Share dialog (OB-203). The page owner / admin sets the page's
|
|
18
|
+
* audience-scope visibility and grants individual people read/edit access by
|
|
19
|
+
* email or handle, all against the OB-191 per-page API (`setPageVisibility`,
|
|
20
|
+
* `sharePage`/`listPageAcl`/`unsharePage`). Rendered from the page-actions
|
|
21
|
+
* cluster; only mounted when {@link useCanManageSharing} clears the user.
|
|
22
|
+
*/
|
|
23
|
+
export default function ShareDialog({ pageId }: {
|
|
24
|
+
pageId: string;
|
|
25
|
+
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -2,5 +2,9 @@
|
|
|
2
2
|
* Account & sync: connect this device to account.book.pub (the deep-link OAuth
|
|
3
3
|
* flow) and mirror preferences + the workspace list there. The data server is
|
|
4
4
|
* untouched — only settings sync through the account service.
|
|
5
|
+
*
|
|
6
|
+
* With no account connected this is the sign-in surface; once at least one is
|
|
7
|
+
* connected it hands off to {@link AccountSwitcher} — the multi-account list
|
|
8
|
+
* (switch / add / remove / sign out) introduced in OB-206.
|
|
5
9
|
*/
|
|
6
10
|
export default function AccountSettings(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The multi-account switcher (OB-206): lists every connected account, marks the
|
|
3
|
+
* active one with a live status, and lets the user switch between them, add
|
|
4
|
+
* another, remove one, or sign the active one out — all over the `useAccount()`
|
|
5
|
+
* actions (the provider owns the logic; this is the surface). The single active
|
|
6
|
+
* account's sync details and dashboard link sit below the list.
|
|
7
|
+
*
|
|
8
|
+
* Per Devon's OB-194 note the dormant accounts read as "Signed in" (available),
|
|
9
|
+
* never "syncing": only the active account talks to the server, so only it shows
|
|
10
|
+
* a live status.
|
|
11
|
+
*/
|
|
12
|
+
export default function AccountSwitcher(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function MembersSettings(): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-user access policy (OB-165): who can read/edit this shared workspace
|
|
3
|
+
* without signing in, plus who the server currently sees *you* as. Reads the
|
|
4
|
+
* instance policy from the data server and lets the owner change the guest gate.
|
|
5
|
+
*
|
|
6
|
+
* Hidden when the server doesn't expose `/api/instance` (an older build), so it
|
|
7
|
+
* degrades cleanly against a server that predates multi-user support.
|
|
8
|
+
*/
|
|
9
|
+
export declare function SharingSection(): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { search as e } from "node-emoji";
|
|
2
|
+
//#region src/lib/emoji.ts
|
|
3
|
+
function t(t, r = 8) {
|
|
4
|
+
let i = t.trim().toLowerCase();
|
|
5
|
+
return i ? e(i).slice().sort((e, t) => n(e.name, i) - n(t.name, i)).slice(0, r) : [];
|
|
6
|
+
}
|
|
7
|
+
function n(e, t) {
|
|
8
|
+
return e === t ? 0 : e.startsWith(t) ? 1 : 2;
|
|
9
|
+
}
|
|
10
|
+
//#endregion
|
|
11
|
+
export { t };
|