@appsoftwareltd/etherpk-extension-api 0.10.2 → 0.11.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/README.md +95 -23
- package/dist/auth.d.ts +43 -0
- package/dist/auth.js +8 -0
- package/dist/context.d.ts +55 -21
- package/dist/events.d.ts +3 -3
- package/dist/index.d.ts +3 -1
- package/dist/journal.d.ts +67 -0
- package/dist/journal.js +1 -0
- package/dist/menus.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -123,11 +123,101 @@ person sets it, and hears every change with `context.settings.subscribe`. A swit
|
|
|
123
123
|
graph, the settings follow them to their other devices, encrypted so that only those devices can read
|
|
124
124
|
them.
|
|
125
125
|
|
|
126
|
+
`context.settings.set('api-key', value)` sets one of the manifest's settings, as the person would in
|
|
127
|
+
Settings, or clears it with `null`. It is for a screen of the extension's own where the person types
|
|
128
|
+
the value, such as a setup guide. It throws for a setting the manifest does not declare, and a switch
|
|
129
|
+
takes only `'true'` or `'false'`.
|
|
130
|
+
|
|
126
131
|
### Storage
|
|
127
132
|
|
|
128
133
|
`context.storage` keeps the extension's own values on the device, as JSON, with `get`, `set` and
|
|
129
134
|
`remove`. It is for what the extension works out or caches, not for what the person sets.
|
|
130
135
|
|
|
136
|
+
### Records kept with the person
|
|
137
|
+
|
|
138
|
+
`context.personStorage` keeps the extension's own records with the person rather than on one
|
|
139
|
+
device, such as what signing in to another service gave it. It has `get`, `set`, `remove` and
|
|
140
|
+
`subscribe`, and keeps each record as JSON, at most 64 KB of it, under a key of letters, digits,
|
|
141
|
+
`.`, `_` and `-`. Where the person's account syncs a graph, the records follow them to their other
|
|
142
|
+
devices in the account's vault, encrypted so that only those devices can read them, and the later
|
|
143
|
+
change to a record wins. The person never sees them, and uninstalling the extension clears them on
|
|
144
|
+
every device.
|
|
145
|
+
|
|
146
|
+
A record is no more private than a setting. Any code in EtherPK's page can read it on the device,
|
|
147
|
+
and so can an agent the person gave an agent token for their account, so say in the extension what
|
|
148
|
+
it keeps.
|
|
149
|
+
|
|
150
|
+
### Signing in to another service
|
|
151
|
+
|
|
152
|
+
`context.auth` runs an OAuth 2.0 sign-in in a popup. The service sends the popup back to the
|
|
153
|
+
Client's one return page, `context.auth.redirectUri` (the Client's address followed by
|
|
154
|
+
`/extension-sign-in`), which the person registers with the service once, for every extension.
|
|
155
|
+
|
|
156
|
+
```ts
|
|
157
|
+
const answer = await context.auth.authorize(`https://accounts.example.com/authorize?client_id=…&redirect_uri=${encodeURIComponent(context.auth.redirectUri)}&state=${state}&…`, { signal })
|
|
158
|
+
if (answer.error) throw new Error(answer.error)
|
|
159
|
+
// answer.code: exchange it at the service's token endpoint.
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
- The address must carry a `state`: only a return with the same `state` answers the call.
|
|
163
|
+
- Call `authorize` inside the click that asked for it, with nothing awaited before it, because a
|
|
164
|
+
browser blocks a popup opened later. Work that takes time, such as a PKCE challenge, is done
|
|
165
|
+
before the click.
|
|
166
|
+
- `authorize` resolves with the parameters the service sent back, `error` among them when the
|
|
167
|
+
person refused. It rejects when the browser blocks the popup, when `signal` aborts, or after ten
|
|
168
|
+
minutes. It does not reject when the person closes the popup, which the Client cannot always tell,
|
|
169
|
+
so offer a Cancel that aborts `signal`.
|
|
170
|
+
- The extension builds the request and exchanges the code itself: the Client knows no service.
|
|
171
|
+
|
|
172
|
+
### Journal Panels
|
|
173
|
+
|
|
174
|
+
A Journal Panel draws beneath a journal entry's text, above its backlinks, about that day, such as
|
|
175
|
+
the day's events from a calendar. It is outside the document, so nothing in it is synced with the
|
|
176
|
+
graph, searched or published.
|
|
177
|
+
|
|
178
|
+
```ts
|
|
179
|
+
context.journalPanels.register({
|
|
180
|
+
id: 'weather.day',
|
|
181
|
+
mount(element, { day, visibility }) {
|
|
182
|
+
// `day` is YYYY-MM-DD. Load once `visibility.onScreen` is true.
|
|
183
|
+
element.textContent = `Forecast for ${day}`
|
|
184
|
+
return { destroy: () => element.replaceChildren() }
|
|
185
|
+
},
|
|
186
|
+
})
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
The Client mounts a panel for each journal tab's own entry, a day with nothing written included, and
|
|
190
|
+
never for the older days shown beneath it. A panel is as tall as what it draws, so one that draws
|
|
191
|
+
nothing takes no space, and it draws its own heading and spacing. It mounts in a shadow root with the
|
|
192
|
+
extension's stylesheets, as a View does.
|
|
193
|
+
|
|
194
|
+
### Graph Sidebar buttons
|
|
195
|
+
|
|
196
|
+
A button in the Graph Sidebar, below Search and today's date, runs a Command:
|
|
197
|
+
`context.graphSidebar.register({ id, title, description, icon, order, when, command })`. These rules
|
|
198
|
+
keep the buttons readable together:
|
|
199
|
+
|
|
200
|
+
- **`title`** is short. Two buttons sit side by side in the sidebar at its default width of 304
|
|
201
|
+
pixels, and "Graph Kanban", with its icon, is about the widest that fits.
|
|
202
|
+
- **`description`** says what the button does, such as "Open a map of every place and route in this
|
|
203
|
+
graph". The Client shows it as the button's help text. Don't write a keyboard shortcut in it: the
|
|
204
|
+
Client adds the key chords bound to the button's Command itself.
|
|
205
|
+
- **`icon`** is clear on its own. On a phone the buttons show their icons only.
|
|
206
|
+
- **`when`** hides the button where it does not apply. A button for the desktop alone passes
|
|
207
|
+
`when: () => context.layout.isDesktop()`. A `when` that throws hides the button too.
|
|
208
|
+
- **`order`** places the button among the others. The Graph Map's is 20 and the Graph Kanban's is
|
|
209
|
+
30.
|
|
210
|
+
|
|
211
|
+
### Opening documents, the theme and Events
|
|
212
|
+
|
|
213
|
+
- `context.layout.openDocument(concept)` opens a document as following a wikilink does. A day's
|
|
214
|
+
name, `YYYY-MM-DD`, opens its journal entry.
|
|
215
|
+
- `context.theme.isDark()` says whether the dark theme shows, and the `theme:changed` Event reports a
|
|
216
|
+
switch. EtherPK's `--gk-*` colour tokens reach into a shadow root and change with the theme by
|
|
217
|
+
themselves.
|
|
218
|
+
- `context.events.on(name, listener)` hears the Client's Events: `document:active-changed`,
|
|
219
|
+
`concept:renamed`, `document:deleted`, `documents:changed` and `theme:changed`.
|
|
220
|
+
|
|
131
221
|
### Fence widgets
|
|
132
222
|
|
|
133
223
|
A fence widget draws over a fenced block in a document, in place of its text. The extension
|
|
@@ -254,33 +344,15 @@ code runs under them.
|
|
|
254
344
|
The Proposed parts are for the extensions that come with EtherPK, and may change in any release.
|
|
255
345
|
They include:
|
|
256
346
|
|
|
257
|
-
- Context Menu rows (`contextMenu`)
|
|
258
|
-
|
|
259
|
-
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
- Running another extension's Commands (`commands.execute`) and opening documents
|
|
263
|
-
(`layout.openDocument`).
|
|
347
|
+
- Context Menu rows (`contextMenu`) and key chords (`keybindings`).
|
|
348
|
+
- Questions to the graph's index (`index`) and the rules for naming a concept (`concepts`).
|
|
349
|
+
- The Client's icons (`icons`) and a View that lives in a Sidebar (`resident`).
|
|
350
|
+
- Running another extension's Commands (`commands.execute`), and the document the person is working
|
|
351
|
+
in (`layout.activeDocument`).
|
|
264
352
|
|
|
265
353
|
`contributions`, which reaches the Client's own registries, stays Proposed for good, since its
|
|
266
354
|
shape is the Client's internals.
|
|
267
355
|
|
|
268
|
-
### Graph Sidebar buttons
|
|
269
|
-
|
|
270
|
-
A button in the Graph Sidebar, below Search and today's date, runs a Command. These rules keep the
|
|
271
|
-
buttons readable together:
|
|
272
|
-
|
|
273
|
-
- **`title`** is short. Two buttons sit side by side in the sidebar at its default width of 304
|
|
274
|
-
pixels, and "Graph Kanban", with its icon, is about the widest that fits.
|
|
275
|
-
- **`description`** says what the button does, such as "Open a map of every place and route in this
|
|
276
|
-
graph". The Client shows it as the button's help text. Don't write a keyboard shortcut in it: the
|
|
277
|
-
Client adds the key chords bound to the button's Command itself.
|
|
278
|
-
- **`icon`** is clear on its own. On a phone the buttons show their icons only.
|
|
279
|
-
- **`when`** hides the button where it does not apply. A button for the desktop alone passes
|
|
280
|
-
`when: () => context.layout.isDesktop()`. A `when` that throws hides the button too.
|
|
281
|
-
- **`order`** places the button among the others. The Graph Map's is 20 and the Graph Kanban's is
|
|
282
|
-
30.
|
|
283
|
-
|
|
284
356
|
## Trying an extension
|
|
285
357
|
|
|
286
358
|
To try an extension, build it, and start a development copy of the EtherPK Client with the
|
package/dist/auth.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signing in to another service from an extension (ADR 0140), such as a calendar, with OAuth 2.0 in
|
|
3
|
+
* a popup. Extensions cannot add pages to the Client, so the Client has one page every sign-in
|
|
4
|
+
* returns to, `redirectUri`, which passes what the service sent back to the window that opened the
|
|
5
|
+
* popup. The extension builds the sign-in request itself (its client id, scopes, PKCE and `state`),
|
|
6
|
+
* so nothing in the Client is tied to one service.
|
|
7
|
+
*/
|
|
8
|
+
/**
|
|
9
|
+
* How long a sign-in may take, and how to give up on it.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export interface AuthorizeOptions {
|
|
14
|
+
/** Aborting it gives up on the sign-in: `authorize` rejects, and its popup is closed. */
|
|
15
|
+
signal?: AbortSignal;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Signing in to another service.
|
|
19
|
+
*
|
|
20
|
+
* @public
|
|
21
|
+
*/
|
|
22
|
+
export interface ExtensionAuth {
|
|
23
|
+
/**
|
|
24
|
+
* The address a sign-in returns to: this Client's origin followed by `/extension-sign-in`. It is
|
|
25
|
+
* the same for every extension and every graph, so the person registers it with the service
|
|
26
|
+
* once.
|
|
27
|
+
*/
|
|
28
|
+
readonly redirectUri: string;
|
|
29
|
+
/**
|
|
30
|
+
* Open `url`, the service's sign-in address, in a popup, and wait for the service to send the
|
|
31
|
+
* popup back to `redirectUri`. Resolves with the parameters it came back with, from its query
|
|
32
|
+
* and its fragment, such as `code` and `state`, or `error` when the person refused. The popup is
|
|
33
|
+
* closed by then.
|
|
34
|
+
*
|
|
35
|
+
* `url` must carry a `state` parameter: only a return with the same `state` answers this call,
|
|
36
|
+
* so two sign-ins at once, in this tab or another, never take each other's answer. Call it from
|
|
37
|
+
* a click or a key press, because a browser blocks a popup opened at any other time. Rejects when
|
|
38
|
+
* the popup is blocked, when `options.signal` aborts, or after ten minutes. A person who closes
|
|
39
|
+
* the popup without finishing is not reported, since the Client cannot always tell, so the
|
|
40
|
+
* extension offers a way to give up (`options.signal`).
|
|
41
|
+
*/
|
|
42
|
+
authorize(url: string, options?: AuthorizeOptions): Promise<Record<string, string>>;
|
|
43
|
+
}
|
package/dist/auth.js
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Signing in to another service from an extension (ADR 0140), such as a calendar, with OAuth 2.0 in
|
|
3
|
+
* a popup. Extensions cannot add pages to the Client, so the Client has one page every sign-in
|
|
4
|
+
* returns to, `redirectUri`, which passes what the service sent back to the window that opened the
|
|
5
|
+
* popup. The extension builds the sign-in request itself (its client id, scopes, PKCE and `state`),
|
|
6
|
+
* so nothing in the Client is tied to one service.
|
|
7
|
+
*/
|
|
8
|
+
export {};
|
package/dist/context.d.ts
CHANGED
|
@@ -7,11 +7,13 @@
|
|
|
7
7
|
* only through the index's answers and its own fences, and changes them only through its fences,
|
|
8
8
|
* the blocks it puts at the caret and the Client's Commands.
|
|
9
9
|
*/
|
|
10
|
+
import type { ExtensionAuth } from './auth';
|
|
10
11
|
import type { ExtensionDialogs } from './dialogs';
|
|
11
12
|
import type { ExtensionEditor } from './editor';
|
|
12
13
|
import type { ExtensionEmbeds } from './embeds';
|
|
13
14
|
import type { ExtensionEvents } from './events';
|
|
14
15
|
import type { ExtensionIndex } from './graph-index';
|
|
16
|
+
import type { ExtensionJournalPanels } from './journal';
|
|
15
17
|
import type { CommandMenuItem, ContextMenuItem, GraphSidebarButton } from './menus';
|
|
16
18
|
import type { ViewContribution, ViewRef } from './views';
|
|
17
19
|
/**
|
|
@@ -74,7 +76,7 @@ export interface ExtensionCommandMenu {
|
|
|
74
76
|
/**
|
|
75
77
|
* Adding buttons to the Graph Sidebar's group of action buttons, after Search and today's date.
|
|
76
78
|
*
|
|
77
|
-
* @
|
|
79
|
+
* @public
|
|
78
80
|
*/
|
|
79
81
|
export interface ExtensionGraphSidebar {
|
|
80
82
|
/** Add a button, its id under the extension's id. */
|
|
@@ -128,9 +130,8 @@ export interface ExtensionLayout {
|
|
|
128
130
|
/**
|
|
129
131
|
* Open the document of a concept, under the name it resolves to, as following a wikilink
|
|
130
132
|
* does. `line` scrolls to and selects that line, `inPaneOf` and `beside` place it as for
|
|
131
|
-
* {@link ExtensionLayout.openView}.
|
|
132
|
-
*
|
|
133
|
-
* @beta
|
|
133
|
+
* {@link ExtensionLayout.openView}. A day's name, `YYYY-MM-DD`, opens its Journal Entry, or a Draft
|
|
134
|
+
* of it when nothing is written for that day yet.
|
|
134
135
|
*/
|
|
135
136
|
openDocument(concept: string, options?: {
|
|
136
137
|
line?: number;
|
|
@@ -175,7 +176,8 @@ export interface ExtensionStorage {
|
|
|
175
176
|
* The person's answers to the settings the extension's manifest declares (`settings`, ADR 0134).
|
|
176
177
|
* The Client draws them under the extension's entry in Settings and Extensions → Extensions, and
|
|
177
178
|
* keeps them with the person: on this device, and in their account where it syncs a graph, so they
|
|
178
|
-
* follow the person to their other devices. The extension
|
|
179
|
+
* follow the person to their other devices. The extension reads them, and may set them where it
|
|
180
|
+
* explains them itself, such as a setup screen asking for a key.
|
|
179
181
|
*
|
|
180
182
|
* @public
|
|
181
183
|
*/
|
|
@@ -191,11 +193,49 @@ export interface ExtensionSettings {
|
|
|
191
193
|
* Returns the way to stop.
|
|
192
194
|
*/
|
|
193
195
|
subscribe(listener: () => void): () => void;
|
|
196
|
+
/**
|
|
197
|
+
* Set one of the settings the manifest declares, as the person would in Settings and Extensions,
|
|
198
|
+
* or clear it with null or empty text. A `boolean` setting takes `'true'` or `'false'`. Throws
|
|
199
|
+
* for a setting the manifest does not declare. Call it only for what the person typed or chose:
|
|
200
|
+
* the setting is theirs.
|
|
201
|
+
*/
|
|
202
|
+
set(id: string, value: string | null): void;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* The extension's own records, kept with the person (ADR 0140): on this device, and where the
|
|
206
|
+
* person's account syncs a graph, in that account's vault too, encrypted on the device so only the
|
|
207
|
+
* person's own devices can read them. So a record follows the person to their other devices, as
|
|
208
|
+
* Extension Settings do, such as what signing in to another service gave the extension. The person
|
|
209
|
+
* never sees these records, and uninstalling the extension clears them on every device.
|
|
210
|
+
*
|
|
211
|
+
* Each record is kept as JSON, at most 64 KB of it. Between two devices the later change to a
|
|
212
|
+
* record wins, record by record. A record is readable on the device by any code in the page, as
|
|
213
|
+
* localStorage is, and by a Headless Client given an agent token for the same account, which opens
|
|
214
|
+
* the account's vault.
|
|
215
|
+
*
|
|
216
|
+
* @public
|
|
217
|
+
*/
|
|
218
|
+
export interface ExtensionPersonStorage {
|
|
219
|
+
/** The record under `key`, or undefined when there is none or it cannot be read. */
|
|
220
|
+
get<T>(key: string): T | undefined;
|
|
221
|
+
/**
|
|
222
|
+
* Keep a record under `key`: letters, digits, `.`, `_` and `-`, at most 100 of them. Setting
|
|
223
|
+
* undefined or null removes it. Throws when the key is not one of those, or the record's JSON is
|
|
224
|
+
* longer than 64 KB.
|
|
225
|
+
*/
|
|
226
|
+
set(key: string, value: unknown): void;
|
|
227
|
+
/** Remove the record under `key`. */
|
|
228
|
+
remove(key: string): void;
|
|
229
|
+
/**
|
|
230
|
+
* Hear every change to the extension's records, made on this device or arriving from another.
|
|
231
|
+
* Returns the way to stop.
|
|
232
|
+
*/
|
|
233
|
+
subscribe(listener: () => void): () => void;
|
|
194
234
|
}
|
|
195
235
|
/**
|
|
196
236
|
* The Client's light or dark theme.
|
|
197
237
|
*
|
|
198
|
-
* @
|
|
238
|
+
* @public
|
|
199
239
|
*/
|
|
200
240
|
export interface ExtensionTheme {
|
|
201
241
|
/** True while the dark theme shows. The `theme:changed` Event reports a switch. */
|
|
@@ -293,12 +333,10 @@ export interface ExtensionContext {
|
|
|
293
333
|
readonly contextMenu: ExtensionContextMenu;
|
|
294
334
|
/** Adding Command Menu rows. */
|
|
295
335
|
readonly commandMenu: ExtensionCommandMenu;
|
|
296
|
-
/**
|
|
297
|
-
* Adding buttons to the Graph Sidebar.
|
|
298
|
-
*
|
|
299
|
-
* @beta
|
|
300
|
-
*/
|
|
336
|
+
/** Adding buttons to the Graph Sidebar. */
|
|
301
337
|
readonly graphSidebar: ExtensionGraphSidebar;
|
|
338
|
+
/** Adding panels beneath each Journal Entry. */
|
|
339
|
+
readonly journalPanels: ExtensionJournalPanels;
|
|
302
340
|
/**
|
|
303
341
|
* Adding key chords.
|
|
304
342
|
*
|
|
@@ -311,11 +349,7 @@ export interface ExtensionContext {
|
|
|
311
349
|
* @beta
|
|
312
350
|
*/
|
|
313
351
|
readonly contributions: ExtensionContributions;
|
|
314
|
-
/**
|
|
315
|
-
* Listening to Events.
|
|
316
|
-
*
|
|
317
|
-
* @beta
|
|
318
|
-
*/
|
|
352
|
+
/** Listening to Events. */
|
|
319
353
|
readonly events: ExtensionEvents;
|
|
320
354
|
/**
|
|
321
355
|
* Questions to the open graph's index.
|
|
@@ -335,11 +369,11 @@ export interface ExtensionContext {
|
|
|
335
369
|
readonly storage: ExtensionStorage;
|
|
336
370
|
/** The person's answers to the settings the manifest declares. */
|
|
337
371
|
readonly settings: ExtensionSettings;
|
|
338
|
-
/**
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
372
|
+
/** The extension's own records, kept with the person and following them to their devices. */
|
|
373
|
+
readonly personStorage: ExtensionPersonStorage;
|
|
374
|
+
/** Signing in to another service. */
|
|
375
|
+
readonly auth: ExtensionAuth;
|
|
376
|
+
/** The Client's light or dark theme. */
|
|
343
377
|
readonly theme: ExtensionTheme;
|
|
344
378
|
/**
|
|
345
379
|
* The Client's icons and the extension's own.
|
package/dist/events.d.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Each Event's name and what it carries. Every Event belongs to the open graph, named by
|
|
7
7
|
* `graphId`.
|
|
8
8
|
*
|
|
9
|
-
* @
|
|
9
|
+
* @public
|
|
10
10
|
*/
|
|
11
11
|
export interface ExtensionEventPayloads {
|
|
12
12
|
/** The document the user is working in changed, or there is none (`documentId` is null). */
|
|
@@ -47,13 +47,13 @@ export interface ExtensionEventPayloads {
|
|
|
47
47
|
/**
|
|
48
48
|
* An Event's name.
|
|
49
49
|
*
|
|
50
|
-
* @
|
|
50
|
+
* @public
|
|
51
51
|
*/
|
|
52
52
|
export type ExtensionEventName = keyof ExtensionEventPayloads;
|
|
53
53
|
/**
|
|
54
54
|
* Listening to Events.
|
|
55
55
|
*
|
|
56
|
-
* @
|
|
56
|
+
* @public
|
|
57
57
|
*/
|
|
58
58
|
export interface ExtensionEvents {
|
|
59
59
|
/** Listen to one Event until the returned function is called or the extension stops. */
|
package/dist/index.d.ts
CHANGED
|
@@ -14,12 +14,14 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @packageDocumentation
|
|
16
16
|
*/
|
|
17
|
-
export type { CommandHandler, ExtensionCommandMenu, ExtensionCommands, ExtensionConcepts, ExtensionContext, ExtensionContextMenu, ExtensionContributions, ExtensionGraphSidebar, ExtensionIcons, ExtensionKeybindings, ExtensionLayout, ExtensionModule, ExtensionSettings, ExtensionStorage, ExtensionTheme, ExtensionViews, IconMarkup, Keybinding, } from './context';
|
|
17
|
+
export type { CommandHandler, ExtensionCommandMenu, ExtensionCommands, ExtensionConcepts, ExtensionContext, ExtensionContextMenu, ExtensionContributions, ExtensionGraphSidebar, ExtensionIcons, ExtensionKeybindings, ExtensionLayout, ExtensionModule, ExtensionPersonStorage, ExtensionSettings, ExtensionStorage, ExtensionTheme, ExtensionViews, IconMarkup, Keybinding, } from './context';
|
|
18
|
+
export type { AuthorizeOptions, ExtensionAuth } from './auth';
|
|
18
19
|
export type { ExtensionDialogs, PromptOptions } from './dialogs';
|
|
19
20
|
export type { ExtensionEditor, FenceContext, FenceEdit, FenceInfo, FenceOptions, FencePresentation, FenceWidget, MountedFence, PublishedFence, PublishFenceRequest, } from './editor';
|
|
20
21
|
export type { ExtensionEmbeds, FrameOptions } from './embeds';
|
|
21
22
|
export type { ExtensionEventName, ExtensionEventPayloads, ExtensionEvents } from './events';
|
|
22
23
|
export type { ConceptCandidate, ConceptKind, ExtensionIndex, IndexUpdate, LinkGraph, LinkGraphConcept, LinkGraphLink } from './graph-index';
|
|
24
|
+
export type { ExtensionJournalPanels, JournalPanel, JournalPanelProps, MountedJournalPanel } from './journal';
|
|
23
25
|
export type { ExtensionIsolation, ExtensionManifest, ExtensionPackage, ReadExtensionPackageResult, SettingDeclaration, ViewDeclaration, ViewRegion, } from './manifest';
|
|
24
26
|
export { readExtensionPackage } from './manifest';
|
|
25
27
|
export type { CommandMenuContext, CommandMenuItem, ContextMenuItem, DocumentMenuTarget, ExtensionMenuTarget, GraphSidebarButton, MenuTarget, TabMenuTarget, WikilinkMenuTarget, } from './menus';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The [[Journal Panel]]: a strip an extension draws beneath a Journal Entry's text and above its
|
|
3
|
+
* Backlinks, about the entry's day, such as that day's events from a calendar. It is outside the
|
|
4
|
+
* document: nothing in it is part of the entry's text, so it is never synced with the graph,
|
|
5
|
+
* searched, exported or published.
|
|
6
|
+
*/
|
|
7
|
+
import type { ViewVisibility } from './views';
|
|
8
|
+
/**
|
|
9
|
+
* What a Journal Panel is mounted with.
|
|
10
|
+
*
|
|
11
|
+
* @public
|
|
12
|
+
*/
|
|
13
|
+
export interface JournalPanelProps {
|
|
14
|
+
/** The Journal Entry's day, `YYYY-MM-DD`. */
|
|
15
|
+
day: string;
|
|
16
|
+
/**
|
|
17
|
+
* The id of the panel the entry's tab is open in, on a desktop: what a Layout call names to open
|
|
18
|
+
* something in the same Pane or beside it. A phone passes none. It is fixed for the panel's
|
|
19
|
+
* life: a tab moved to another Pane is drawn afresh there.
|
|
20
|
+
*/
|
|
21
|
+
panelId?: string;
|
|
22
|
+
/**
|
|
23
|
+
* Whether the entry's tab can be seen right now, and when that changes. A panel that loads
|
|
24
|
+
* anything waits until it can be seen.
|
|
25
|
+
*/
|
|
26
|
+
visibility: ViewVisibility;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* A Journal Panel the extension has drawn, as the Client drives it.
|
|
30
|
+
*
|
|
31
|
+
* @public
|
|
32
|
+
*/
|
|
33
|
+
export interface MountedJournalPanel {
|
|
34
|
+
/** The tab closed, the graph closed, or the extension was switched off. */
|
|
35
|
+
destroy(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* A Journal Panel an extension registers.
|
|
39
|
+
*
|
|
40
|
+
* @public
|
|
41
|
+
*/
|
|
42
|
+
export interface JournalPanel {
|
|
43
|
+
/** Under the extension's id. */
|
|
44
|
+
id: string;
|
|
45
|
+
/**
|
|
46
|
+
* Draw the panel into `element`, which is empty and is the extension's alone. For a loaded
|
|
47
|
+
* extension it sits inside a shadow root that holds the extension's own stylesheets, as a View
|
|
48
|
+
* does, and it is as tall as what the extension draws in it: a panel that draws nothing takes no
|
|
49
|
+
* space. The Client calls it once for each journal tab, the tab's own entry only, a Draft
|
|
50
|
+
* included, and never for the older entries of the Journal Roll. A file dropped on the panel is
|
|
51
|
+
* added to the end of the entry, as one dropped below the text is, unless the panel's own drop
|
|
52
|
+
* handler calls `preventDefault`.
|
|
53
|
+
*/
|
|
54
|
+
mount(element: HTMLElement, props: JournalPanelProps): MountedJournalPanel;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Adding Journal Panels.
|
|
58
|
+
*
|
|
59
|
+
* @public
|
|
60
|
+
*/
|
|
61
|
+
export interface ExtensionJournalPanels {
|
|
62
|
+
/**
|
|
63
|
+
* Add a panel beneath every journal tab's entry, those open already included. Panels from
|
|
64
|
+
* several extensions stack in the order they were added.
|
|
65
|
+
*/
|
|
66
|
+
register(panel: JournalPanel): () => void;
|
|
67
|
+
}
|
package/dist/journal.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/dist/menus.d.ts
CHANGED
|
@@ -154,7 +154,7 @@ export interface CommandMenuItem {
|
|
|
154
154
|
* to what the extension shows for the whole graph, such as the Graph Map. Pressing it runs
|
|
155
155
|
* `command`.
|
|
156
156
|
*
|
|
157
|
-
* @
|
|
157
|
+
* @public
|
|
158
158
|
*/
|
|
159
159
|
export interface GraphSidebarButton {
|
|
160
160
|
/** Under the extension's id. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@appsoftwareltd/etherpk-extension-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.11.0",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"description": "The API an EtherPK extension is written against: the context it is started with, its manifest, and the contract its Views follow.",
|
|
6
6
|
"type": "module",
|