@wildwinter/app-shell 0.4.1 → 0.15.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 +35 -0
- package/dist/about.css +76 -0
- package/dist/about.css.map +1 -0
- package/dist/anchored.css +104 -0
- package/dist/anchored.css.map +1 -0
- package/dist/app-store.cjs +74 -0
- package/dist/app-store.cjs.map +1 -0
- package/dist/app-store.d.cts +75 -0
- package/dist/app-store.d.ts +75 -0
- package/dist/app-store.js +72 -0
- package/dist/app-store.js.map +1 -0
- package/dist/chunk-MDGOIT3O.js +58 -0
- package/dist/chunk-MDGOIT3O.js.map +1 -0
- package/dist/chunk-R6RO5TXB.js +16 -0
- package/dist/chunk-R6RO5TXB.js.map +1 -0
- package/dist/comments.css +134 -0
- package/dist/comments.css.map +1 -0
- package/dist/confirm.css +62 -0
- package/dist/confirm.css.map +1 -0
- package/dist/identity.css +62 -0
- package/dist/identity.css.map +1 -0
- package/dist/index.cjs +1020 -6
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +429 -3
- package/dist/index.d.ts +429 -3
- package/dist/index.js +987 -8
- package/dist/index.js.map +1 -1
- package/dist/job.cjs +61 -0
- package/dist/job.cjs.map +1 -0
- package/dist/job.css +70 -0
- package/dist/job.css.map +1 -0
- package/dist/job.d.cts +56 -0
- package/dist/job.d.ts +56 -0
- package/dist/job.js +3 -0
- package/dist/job.js.map +1 -0
- package/dist/menu.cjs +7 -0
- package/dist/menu.cjs.map +1 -1
- package/dist/menu.d.cts +20 -1
- package/dist/menu.d.ts +20 -1
- package/dist/menu.js +1 -1
- package/dist/notes-editor.css +107 -0
- package/dist/notes-editor.css.map +1 -0
- package/dist/session.cjs +52 -0
- package/dist/session.cjs.map +1 -0
- package/dist/session.d.cts +79 -0
- package/dist/session.d.ts +79 -0
- package/dist/session.js +50 -0
- package/dist/session.js.map +1 -0
- package/dist/tool-window.cjs +79 -0
- package/dist/tool-window.cjs.map +1 -0
- package/dist/tool-window.css +60 -0
- package/dist/tool-window.css.map +1 -0
- package/dist/tool-window.d.cts +63 -0
- package/dist/tool-window.d.ts +63 -0
- package/dist/tool-window.js +73 -0
- package/dist/tool-window.js.map +1 -0
- package/dist/tooltip.css +22 -0
- package/dist/tooltip.css.map +1 -0
- package/dist/updater.cjs +315 -0
- package/dist/updater.cjs.map +1 -0
- package/dist/updater.d.cts +53 -0
- package/dist/updater.d.ts +53 -0
- package/dist/updater.js +306 -0
- package/dist/updater.js.map +1 -0
- package/dist/vc-status.cjs +77 -0
- package/dist/vc-status.cjs.map +1 -0
- package/dist/vc-status.d.cts +40 -0
- package/dist/vc-status.d.ts +40 -0
- package/dist/vc-status.js +71 -0
- package/dist/vc-status.js.map +1 -0
- package/dist/vc.css +41 -0
- package/dist/vc.css.map +1 -0
- package/package.json +90 -1
- package/dist/chunk-KQT3XYRS.js +0 -10
- package/dist/chunk-KQT3XYRS.js.map +0 -1
- package/dist/pane-shell.d.cts +0 -2
- package/dist/pane-shell.d.ts +0 -2
- package/dist/settings.d.cts +0 -2
- package/dist/settings.d.ts +0 -2
- package/dist/tokens.d.cts +0 -2
- package/dist/tokens.d.ts +0 -2
package/dist/index.d.cts
CHANGED
|
@@ -1,14 +1,23 @@
|
|
|
1
|
-
export { MenuLabel, PANE_MENU } from './menu.cjs';
|
|
1
|
+
export { EDIT_MENU, MenuLabel, PANE_MENU } from './menu.cjs';
|
|
2
|
+
export { JOB_PROGRESS, JobProgress } from './job.cjs';
|
|
2
3
|
|
|
3
4
|
type Child = Node | string | null | undefined;
|
|
4
5
|
interface ElProps {
|
|
5
6
|
className?: string;
|
|
6
7
|
text?: string;
|
|
8
|
+
/** A NATIVE rollover. Prefer `tip`: `title` is OS chrome on the platform's own
|
|
9
|
+
* slow delay, which is the seam the themed tooltip exists to close. */
|
|
7
10
|
title?: string;
|
|
11
|
+
/** A themed rollover (`data-tip`, picked up by the delegated controller that
|
|
12
|
+
* `initTooltips()` wires). Also the accessible name, since the elements that
|
|
13
|
+
* want one are usually icon buttons with no text of their own. */
|
|
14
|
+
tip?: string;
|
|
8
15
|
onClick?: (event: MouseEvent) => void;
|
|
9
16
|
}
|
|
10
17
|
declare function el<K extends keyof HTMLElementTagNameMap>(tag: K, classNameOrProps?: string | ElProps, ...children: Child[]): HTMLElementTagNameMap[K];
|
|
11
|
-
/** A small square glyph button (the move/delete controls list editors share).
|
|
18
|
+
/** A small square glyph button (the move/delete controls list editors share).
|
|
19
|
+
* Its rollover is the THEMED one (`data-tip`), so an app that has called
|
|
20
|
+
* `initTooltips()` gets our bubble rather than the platform's. */
|
|
12
21
|
declare function iconBtn(glyph: string, title: string, onClick: () => void, disabled?: boolean, danger?: boolean): HTMLButtonElement;
|
|
13
22
|
/** A captioned field: `<label class="shell-labelled"><span class="shell-fieldcap">…</span>control</label>`. */
|
|
14
23
|
declare function labelled(label: string, control: HTMLElement): HTMLElement;
|
|
@@ -31,6 +40,72 @@ declare function colourIndex(name: string): number;
|
|
|
31
40
|
/** The theme-aware CSS variable reference for a name's slot. */
|
|
32
41
|
declare function colourFor(name: string): string;
|
|
33
42
|
|
|
43
|
+
/**
|
|
44
|
+
* Named by what it MEANS. Grouped by the job, because that is how a caller
|
|
45
|
+
* looks for one.
|
|
46
|
+
*/
|
|
47
|
+
declare const icon: {
|
|
48
|
+
/** Close a panel, a dialog, a popover. Patterpad's, twelve times over. */
|
|
49
|
+
readonly close: "✕";
|
|
50
|
+
/** The overflow menu on a document or a row: "more about this". */
|
|
51
|
+
readonly more: "⋯";
|
|
52
|
+
/** Collapsed disclosure, pointing at what would open. */
|
|
53
|
+
readonly collapsed: "▸";
|
|
54
|
+
/** Expanded disclosure. */
|
|
55
|
+
readonly expanded: "▾";
|
|
56
|
+
/** A dropdown's affordance, where it is not a real <select>. */
|
|
57
|
+
readonly dropdown: "▾";
|
|
58
|
+
/** Back / previous, in a breadcrumb or a stepper. */
|
|
59
|
+
readonly back: "‹";
|
|
60
|
+
/** Forward / next. */
|
|
61
|
+
readonly forward: "›";
|
|
62
|
+
/** Up one, in a list. */
|
|
63
|
+
readonly up: "↑";
|
|
64
|
+
/** Down one. */
|
|
65
|
+
readonly down: "↓";
|
|
66
|
+
/** Done, applied, agreed. */
|
|
67
|
+
readonly tick: "✓";
|
|
68
|
+
/** Somebody else holds this: the version-control lock. */
|
|
69
|
+
readonly locked: "⊘";
|
|
70
|
+
/** Read-only on disk with no other holder: the resting state of everything
|
|
71
|
+
* in a lock-based working copy that nobody has checked out yet. */
|
|
72
|
+
readonly readOnly: "○";
|
|
73
|
+
/** Something needs attention but is not fatal. */
|
|
74
|
+
readonly warning: "‼";
|
|
75
|
+
/** A live thing: the running position, an active marker. */
|
|
76
|
+
readonly dot: "●";
|
|
77
|
+
/** Play, in the sense of "run this". */
|
|
78
|
+
readonly play: "▶";
|
|
79
|
+
/** The drag grip on a reorderable row. */
|
|
80
|
+
readonly grip: "⠿";
|
|
81
|
+
/** Add one of whatever this list holds. */
|
|
82
|
+
readonly add: "+";
|
|
83
|
+
/** Documentation notes: the pencil. Both apps had chosen it independently,
|
|
84
|
+
* which is the happiest way for a vocabulary entry to arrive. */
|
|
85
|
+
readonly note: "✎";
|
|
86
|
+
/** A comment thread. Speech, not a pencil: documentation states the reason,
|
|
87
|
+
* comments are the conversation, and the two must never look alike. */
|
|
88
|
+
readonly comment: "❝";
|
|
89
|
+
};
|
|
90
|
+
type IconName = keyof typeof icon;
|
|
91
|
+
/**
|
|
92
|
+
* The few shapes no glyph says honestly, as inline SVG.
|
|
93
|
+
*
|
|
94
|
+
* `currentColor` throughout, so they take the colour of the button they sit in
|
|
95
|
+
* exactly as the glyphs do, and sized in the markup for the same reason: an icon
|
|
96
|
+
* that needs a CSS rule to be the right size is an icon that will be the wrong
|
|
97
|
+
* size somewhere.
|
|
98
|
+
*
|
|
99
|
+
* Lifted from Patterpad, which drew them first.
|
|
100
|
+
*/
|
|
101
|
+
declare const iconSvg: {
|
|
102
|
+
/** A document with lines: notes exist on this thing. */
|
|
103
|
+
readonly noteFilled: "<svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"currentColor\" fill-rule=\"evenodd\" aria-hidden=\"true\"><path d=\"M3.4 1.4h5.3L12.6 5.3v8.1a1.2 1.2 0 0 1-1.2 1.2H3.4a1.2 1.2 0 0 1-1.2-1.2V2.6A1.2 1.2 0 0 1 3.4 1.4ZM4.9 6.8h6.2v1.1H4.9Zm0 2.1h6.2v1.1H4.9Zm0 2.1h3.7v1.1H4.9Z\"/></svg>";
|
|
104
|
+
/** The same document, empty: nothing written here yet. */
|
|
105
|
+
readonly noteOutline: "<svg viewBox=\"0 0 16 16\" width=\"13\" height=\"13\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"1.1\" stroke-linejoin=\"round\" stroke-linecap=\"round\" aria-hidden=\"true\"><path d=\"M3.4 2h4.9l3.9 3.9v7.5a1 1 0 0 1-1 1H3.4a1 1 0 0 1-1-1V3a1 1 0 0 1 1-1Z\"/><path d=\"M8.3 2.2v3.8h3.8\"/><path d=\"M4.9 8h6.2M4.9 10h6.2M4.9 12h3.7\" stroke-width=\"0.95\"/></svg>";
|
|
106
|
+
};
|
|
107
|
+
type IconSvgName = keyof typeof iconSvg;
|
|
108
|
+
|
|
34
109
|
type PaneSide = "nav" | "inspector";
|
|
35
110
|
interface PaneSideConfig {
|
|
36
111
|
/** The open width as a CSS length, e.g. "14rem" or "224px". */
|
|
@@ -135,4 +210,355 @@ interface SettingsDialog {
|
|
|
135
210
|
* (with a validation gate), and Cancel; the sections own their content + state. */
|
|
136
211
|
declare function mountSettingsDialog(opts: SettingsDialogOptions): SettingsDialog;
|
|
137
212
|
|
|
138
|
-
|
|
213
|
+
interface PinButtonOptions {
|
|
214
|
+
pinned: boolean;
|
|
215
|
+
/** Persist the choice (the button keeps its own visual state). */
|
|
216
|
+
onToggle: (on: boolean) => void;
|
|
217
|
+
}
|
|
218
|
+
/** The always-on-top pin: `.swin-pin`, aria-pressed, and a tooltip that says
|
|
219
|
+
* what a click will do (the richest of the family's variants, kept). */
|
|
220
|
+
declare function pinButton(opts: PinButtonOptions): HTMLButtonElement;
|
|
221
|
+
|
|
222
|
+
interface ConfirmOptions {
|
|
223
|
+
title: string;
|
|
224
|
+
body: string;
|
|
225
|
+
/** The destructive button's label ("Delete box", "Restart"). */
|
|
226
|
+
confirmLabel: string;
|
|
227
|
+
}
|
|
228
|
+
/** Resolves true on confirm; false on Cancel / Esc / backdrop. */
|
|
229
|
+
declare function confirmDialog(opts: ConfirmOptions): Promise<boolean>;
|
|
230
|
+
|
|
231
|
+
interface AboutOptions {
|
|
232
|
+
/** The product's name, large. */
|
|
233
|
+
appName: string;
|
|
234
|
+
/** "1.4.2" - shown as "Version 1.4.2". */
|
|
235
|
+
version: string;
|
|
236
|
+
/** One or two sentences: what this app is for. */
|
|
237
|
+
blurb?: string;
|
|
238
|
+
/** Licence, authorship, the suite it belongs to. Newlines are respected. */
|
|
239
|
+
credits?: string;
|
|
240
|
+
links?: {
|
|
241
|
+
label: string;
|
|
242
|
+
url: string;
|
|
243
|
+
}[];
|
|
244
|
+
/** Inline SVG for the product wordmark, if it has one. */
|
|
245
|
+
wordmark?: string;
|
|
246
|
+
/** Open a URL in the real browser. Omit and the links render as text. */
|
|
247
|
+
onOpenLink?: (url: string) => void;
|
|
248
|
+
}
|
|
249
|
+
/** Show the About dialog. Resolves when it closes. */
|
|
250
|
+
declare function showAbout(opts: AboutOptions): Promise<void>;
|
|
251
|
+
|
|
252
|
+
interface AnchoredPanel {
|
|
253
|
+
panel: HTMLElement;
|
|
254
|
+
/** The content area to populate: the header is built for you. */
|
|
255
|
+
body: HTMLElement;
|
|
256
|
+
/** Idempotent; fires the caller's `onClose` exactly once. */
|
|
257
|
+
close: () => void;
|
|
258
|
+
}
|
|
259
|
+
interface AnchoredPanelOptions {
|
|
260
|
+
anchor: HTMLElement;
|
|
261
|
+
/** Extra class(es) on the panel, for app-specific sizing or colour. */
|
|
262
|
+
className?: string;
|
|
263
|
+
title: string;
|
|
264
|
+
width: number;
|
|
265
|
+
/**
|
|
266
|
+
* Which side to try first.
|
|
267
|
+
*
|
|
268
|
+
* `"left"` suits a panel hung off a row in a right-hand pane (Patterpad's
|
|
269
|
+
* inspector); `"below"` suits one hung off a button in a document's header
|
|
270
|
+
* (Storyletter's topline). Either way it flips when the room is not there.
|
|
271
|
+
*/
|
|
272
|
+
prefer?: "left" | "below" | "centre";
|
|
273
|
+
/** Selectors for chrome the panel must not cover - a problems bar, a review
|
|
274
|
+
* bar - so those stay usable while it is open. */
|
|
275
|
+
keepClear?: string[];
|
|
276
|
+
/** A pointerdown inside something matching this does NOT close the panel. */
|
|
277
|
+
ignoreDown?: string;
|
|
278
|
+
/** While something matching this exists, Escape belongs to it, not to us. */
|
|
279
|
+
deferEscape?: string;
|
|
280
|
+
onClose?: () => void;
|
|
281
|
+
}
|
|
282
|
+
declare function openAnchoredPanel(opts: AnchoredPanelOptions): AnchoredPanel | null;
|
|
283
|
+
/** Close whatever is open. For a navigation or a re-render: a panel anchored to
|
|
284
|
+
* an element that no longer exists would hang in the air. */
|
|
285
|
+
declare function closeAnchoredPanel(): void;
|
|
286
|
+
/** Patterpad's placement, with the side as a parameter. */
|
|
287
|
+
declare function placeAnchored(panel: HTMLElement, anchor: HTMLElement, width: number, prefer: "left" | "below" | "centre", keepClear: string[]): void;
|
|
288
|
+
|
|
289
|
+
/**
|
|
290
|
+
* Slugify a name into hyphen form: lower case, apostrophes dropped, runs of
|
|
291
|
+
* anything else to a single hyphen, no leading or trailing hyphen.
|
|
292
|
+
*
|
|
293
|
+
* May return "", when there was nothing usable in the input. Callers treat that
|
|
294
|
+
* as "no pinned address" rather than as an address.
|
|
295
|
+
*/
|
|
296
|
+
declare function gameIdify(text: string): string;
|
|
297
|
+
/** Is this a legal address? Lower case, digits and hyphens, starting and ending
|
|
298
|
+
* with a letter or a digit. Note "" is NOT legal: an empty pinned address means
|
|
299
|
+
* "derive one", which is a different thing from an address. */
|
|
300
|
+
declare function isValidGameId(gameId: string): boolean;
|
|
301
|
+
|
|
302
|
+
interface GameIdEditorOptions {
|
|
303
|
+
anchor: HTMLElement;
|
|
304
|
+
/** The pinned address, or "" when it is being derived. */
|
|
305
|
+
value: string;
|
|
306
|
+
/** What it derives to, shown as the placeholder. */
|
|
307
|
+
derived: string;
|
|
308
|
+
/** Persist. "" means "stop pinning, go back to deriving". */
|
|
309
|
+
onCommit: (gameId: string) => void;
|
|
310
|
+
/** The panel's title. Both apps say "Game ID"; a third may not. */
|
|
311
|
+
title?: string;
|
|
312
|
+
/** Override the rules. Defaults are the shell's, which is what a new app
|
|
313
|
+
* should use; an app whose domain layer owns them can pass its own. */
|
|
314
|
+
slugify?: (text: string) => string;
|
|
315
|
+
validate?: (gameId: string) => boolean;
|
|
316
|
+
/** Where the panel goes, for hosts that anchor it somewhere tight. */
|
|
317
|
+
prefer?: "left" | "below" | "centre";
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Open it. Returns false when that click TOGGLED the panel shut, which is the
|
|
321
|
+
* anchored panel's contract and worth passing on: a caller that repaints on open
|
|
322
|
+
* needs to know it did not.
|
|
323
|
+
*/
|
|
324
|
+
declare function openGameIdEditor(opts: GameIdEditorOptions): boolean;
|
|
325
|
+
|
|
326
|
+
/** One shard's state as the renderer sees it. The app's own DTO will be this
|
|
327
|
+
* shape (it crosses its own bridge); this is what the view needs. */
|
|
328
|
+
interface ShardVc {
|
|
329
|
+
key: string;
|
|
330
|
+
writable: boolean;
|
|
331
|
+
lockedBy?: string[];
|
|
332
|
+
outOfDate?: boolean;
|
|
333
|
+
}
|
|
334
|
+
/** A snapshot, keyed by shard key. Absent = clean, writable, up to date. */
|
|
335
|
+
type VcMap = ReadonlyMap<string, ShardVc>;
|
|
336
|
+
/** Fold the state of the shard key(s) an item stands for (a box row spans its
|
|
337
|
+
* box + tags + hands shards), most actionable winning: any holder locks it,
|
|
338
|
+
* any stale shard makes it stale, any read-only shard makes it read-only. */
|
|
339
|
+
declare function foldVc(shards: VcMap, keys: string | undefined): ShardVc | undefined;
|
|
340
|
+
/** The one badge an item flies, by priority, or null when there is nothing to
|
|
341
|
+
* say. Monochrome typographic glyphs (never colour emoji), so each inherits
|
|
342
|
+
* its themed colour and reads the same in Linen and Baize. */
|
|
343
|
+
declare function vcBadgeFor(s: ShardVc | undefined): {
|
|
344
|
+
glyph: string;
|
|
345
|
+
cls: string;
|
|
346
|
+
title: string;
|
|
347
|
+
} | null;
|
|
348
|
+
/** Repaint the badge on every item under `root` that names a shard (its
|
|
349
|
+
* `data-vc`). In place: no re-render, so nothing loses focus or scroll. */
|
|
350
|
+
declare function paintVcBadges(root: ParentNode, shards: VcMap): void;
|
|
351
|
+
/** Turn a region's editing controls off - or back on, but only the ones WE
|
|
352
|
+
* turned off, so a control disabled for its own reasons (the first card's
|
|
353
|
+
* "previous", a redraw-turns box on "always") stays disabled. */
|
|
354
|
+
declare function lockControls(host: HTMLElement, off: boolean, staysLive: string): void;
|
|
355
|
+
/** The notice a locked document opens with: who holds it, and why nothing types. */
|
|
356
|
+
declare function lockNotice(holders: string[]): HTMLElement;
|
|
357
|
+
|
|
358
|
+
interface Identity {
|
|
359
|
+
name: string;
|
|
360
|
+
email?: string;
|
|
361
|
+
}
|
|
362
|
+
interface IdentityOptions {
|
|
363
|
+
/** What it already says, if anything. */
|
|
364
|
+
current?: Identity;
|
|
365
|
+
/** A name to offer when there is none: the VCS's, one day. */
|
|
366
|
+
suggested?: Identity;
|
|
367
|
+
}
|
|
368
|
+
/** Ask, and record the answer. Resolves when the dialog closes, either way. */
|
|
369
|
+
declare function askIdentity(opts?: IdentityOptions): Promise<Identity | undefined>;
|
|
370
|
+
|
|
371
|
+
/** One line of documentation. `type` names its class; absent = editor-only. */
|
|
372
|
+
interface DocLine {
|
|
373
|
+
type?: string;
|
|
374
|
+
text: string;
|
|
375
|
+
}
|
|
376
|
+
/** What applies to one thing: its own notes, and the ancestors' that reach it.
|
|
377
|
+
* Inherited notes are READ-ONLY - they are edited where they live, which is
|
|
378
|
+
* what stops a note being copied down and then disagreeing with itself. */
|
|
379
|
+
interface Notes {
|
|
380
|
+
own: DocLine[];
|
|
381
|
+
inherited: {
|
|
382
|
+
id: string;
|
|
383
|
+
label: string;
|
|
384
|
+
lines: DocLine[];
|
|
385
|
+
}[];
|
|
386
|
+
/** The classes this app offers, in the order they should appear. */
|
|
387
|
+
classes: string[];
|
|
388
|
+
}
|
|
389
|
+
interface NotesEditorOptions {
|
|
390
|
+
/** What this is about, for the dialog's title ("Notes: Arrive at the gate"). */
|
|
391
|
+
subject: string;
|
|
392
|
+
notes: Notes;
|
|
393
|
+
/** Commit. Called once, on close, and only when something changed. */
|
|
394
|
+
save: (lines: DocLine[]) => void;
|
|
395
|
+
}
|
|
396
|
+
/** Open the notes modal. Resolves when it closes. */
|
|
397
|
+
declare function openNotesEditor(opts: NotesEditorOptions): void;
|
|
398
|
+
|
|
399
|
+
/** One message. The author is a NAME stamped at posting time, not a reference:
|
|
400
|
+
* people leave projects and their words stay. */
|
|
401
|
+
interface CommentMessage {
|
|
402
|
+
author: string;
|
|
403
|
+
ts: string;
|
|
404
|
+
body: string;
|
|
405
|
+
/** A TOMBSTONE: the words are gone, the turn in the conversation is not.
|
|
406
|
+
* Deleting a reply out of a thread would renumber the argument around it, so
|
|
407
|
+
* what is left says who spoke and when and that they withdrew it. The body is
|
|
408
|
+
* emptied on the way out, so "deleted" means deleted from the file too. */
|
|
409
|
+
deleted?: boolean;
|
|
410
|
+
}
|
|
411
|
+
/** A thread, anchored to the id of whatever it is about. */
|
|
412
|
+
interface Comment {
|
|
413
|
+
id: string;
|
|
414
|
+
anchor: string;
|
|
415
|
+
resolved?: boolean;
|
|
416
|
+
messages: CommentMessage[];
|
|
417
|
+
}
|
|
418
|
+
interface CommentsOptions {
|
|
419
|
+
anchor: HTMLElement;
|
|
420
|
+
/** What is being discussed, for the panel's title. */
|
|
421
|
+
subject: string;
|
|
422
|
+
/** Every thread on this thing, resolved ones included. */
|
|
423
|
+
threads: Comment[];
|
|
424
|
+
/** Review ▸ Show Resolved Comments. */
|
|
425
|
+
showResolved: boolean;
|
|
426
|
+
/** A fresh thread id, minted by the caller so main never has to. */
|
|
427
|
+
newThreadId: () => string;
|
|
428
|
+
post: (threadId: string, body: string) => void;
|
|
429
|
+
setResolved: (threadId: string, resolved: boolean) => void;
|
|
430
|
+
/**
|
|
431
|
+
* Withdraw one message. Absent = the host does not offer deletion.
|
|
432
|
+
*
|
|
433
|
+
* By INDEX, because a message has no id of its own and giving every message
|
|
434
|
+
* one would be a format change to every stored thread for the sake of one
|
|
435
|
+
* verb. The index is read off the list the reader is looking at, and these
|
|
436
|
+
* files are edited by one person at a time with a VCS underneath.
|
|
437
|
+
*
|
|
438
|
+
* The host decides what deleting MEANS: the agreed rule is that the message
|
|
439
|
+
* becomes a tombstone, and the whole thread goes when nothing readable would
|
|
440
|
+
* be left (which covers the common case of withdrawing a comment nobody had
|
|
441
|
+
* replied to).
|
|
442
|
+
*/
|
|
443
|
+
deleteMessage?: (threadId: string, index: number) => void;
|
|
444
|
+
/** Where the panel sits: "centre" for a point on a canvas (see anchored.ts). */
|
|
445
|
+
prefer?: "left" | "below" | "centre";
|
|
446
|
+
}
|
|
447
|
+
declare function openComments(opts: CommentsOptions): void;
|
|
448
|
+
|
|
449
|
+
interface JobProgressView {
|
|
450
|
+
/** The strip; mount it where the job belongs. */
|
|
451
|
+
readonly element: HTMLElement;
|
|
452
|
+
/** Show the strip, reset to zero, and (optionally) name what is running. */
|
|
453
|
+
begin(label?: string): void;
|
|
454
|
+
/** Feed it a progress message from the main-side host. */
|
|
455
|
+
update(done: number, total: number, elapsedMs: number): void;
|
|
456
|
+
/** Hide the strip (the job finished, failed, or was cancelled). */
|
|
457
|
+
end(): void;
|
|
458
|
+
readonly visible: boolean;
|
|
459
|
+
}
|
|
460
|
+
interface JobProgressOptions {
|
|
461
|
+
/** Called when Cancel is clicked. The button disables itself and says so;
|
|
462
|
+
* the job stops at its next yield, and the host then calls end(). */
|
|
463
|
+
onCancel: () => void;
|
|
464
|
+
/** The word for the units, for the count readout (default "runs"). */
|
|
465
|
+
units?: string;
|
|
466
|
+
}
|
|
467
|
+
declare function mountJobProgress(host: HTMLElement, opts: JobProgressOptions): JobProgressView;
|
|
468
|
+
|
|
469
|
+
/** Wrap `s` so it renders bold inside a tooltip (see the marker note above). */
|
|
470
|
+
declare function tipBold(s: string): string;
|
|
471
|
+
interface TooltipOptions {
|
|
472
|
+
/** Called before every show: return true to keep the bubble down. For a mode
|
|
473
|
+
* that wants no chrome at all (Patterpad's Writing View). */
|
|
474
|
+
suppressed?: () => boolean;
|
|
475
|
+
}
|
|
476
|
+
/** A rectangle in VIEWPORT coordinates, for anchoring a tip to something that is
|
|
477
|
+
* not a DOM element: a shape on a canvas, a run of text inside one. */
|
|
478
|
+
interface TipRect {
|
|
479
|
+
left: number;
|
|
480
|
+
top: number;
|
|
481
|
+
width: number;
|
|
482
|
+
height: number;
|
|
483
|
+
}
|
|
484
|
+
/**
|
|
485
|
+
* Show a tip for something that has no DOM node of its own: a card on a canvas,
|
|
486
|
+
* a zone, a pin. The caller says WHERE (a viewport rectangle) and WHAT, and
|
|
487
|
+
* identifies the subject with `key`.
|
|
488
|
+
*
|
|
489
|
+
* The key is what makes this usable from a canvas. Re-calling with the same key
|
|
490
|
+
* re-places the bubble WITHOUT restarting the delay, so a tip can follow its
|
|
491
|
+
* shape while the camera moves; calling with a different key starts the wait
|
|
492
|
+
* again, so sweeping the pointer across a dense board does not strobe.
|
|
493
|
+
*
|
|
494
|
+
* The bubble is ordinary DOM, so it holds its size whatever the canvas is
|
|
495
|
+
* zoomed to. That is the point of it: the label it stands in for is the one
|
|
496
|
+
* thing on a canvas that must not shrink with everything else.
|
|
497
|
+
*/
|
|
498
|
+
declare function tipAt(key: string, rect: TipRect, text: string): void;
|
|
499
|
+
/** Take any tip down: the pointer has left, or a gesture has started. */
|
|
500
|
+
declare function hideTip(): void;
|
|
501
|
+
/** Wire the one delegated controller. Idempotent; later options are ignored. */
|
|
502
|
+
declare function initTooltips(opts?: TooltipOptions): void;
|
|
503
|
+
|
|
504
|
+
/**
|
|
505
|
+
* Three states, not a boolean.
|
|
506
|
+
*
|
|
507
|
+
* "saving" earns its place: on a slow disk or a slow VC hook a save takes long
|
|
508
|
+
* enough to see, and a status that flips straight from unsaved to saved leaves
|
|
509
|
+
* the author wondering whether the click did anything.
|
|
510
|
+
*/
|
|
511
|
+
type SaveStatus = "saved" | "unsaved" | "saving";
|
|
512
|
+
interface SaveControllerOptions {
|
|
513
|
+
/**
|
|
514
|
+
* Write whatever is pending. Return false if it failed: the controller stays
|
|
515
|
+
* "unsaved" and will try again on the next touch or flush, rather than
|
|
516
|
+
* quietly reporting success over a write that did not happen.
|
|
517
|
+
*
|
|
518
|
+
* Called only when something is pending, and never twice at once.
|
|
519
|
+
*/
|
|
520
|
+
write: () => Promise<boolean> | boolean;
|
|
521
|
+
/** Told every time the status changes, and only when it changes. */
|
|
522
|
+
onStatus?: (status: SaveStatus) => void;
|
|
523
|
+
/** How long after the last edit to write. Storyletter's 700ms by default. */
|
|
524
|
+
delayMs?: number;
|
|
525
|
+
/**
|
|
526
|
+
* The longest an edit may go unwritten while more keep arriving.
|
|
527
|
+
*
|
|
528
|
+
* This is the interval half of the two apps put back in: without it, steady
|
|
529
|
+
* typing defers the write for as long as the typing lasts.
|
|
530
|
+
*/
|
|
531
|
+
maxWaitMs?: number;
|
|
532
|
+
}
|
|
533
|
+
interface SaveController {
|
|
534
|
+
/** What the indicator should say. */
|
|
535
|
+
readonly status: SaveStatus;
|
|
536
|
+
/** Is anything unwritten? For a close guard, or an updater asking whether it
|
|
537
|
+
* may restart. True while a write is in flight, too: it is not on disk yet. */
|
|
538
|
+
readonly pending: boolean;
|
|
539
|
+
/** Something changed. Starts (or extends) the countdown. */
|
|
540
|
+
touch(): void;
|
|
541
|
+
/**
|
|
542
|
+
* Write now, and wait for it.
|
|
543
|
+
*
|
|
544
|
+
* Call on every transition that must see current bytes: switching what is
|
|
545
|
+
* being edited, opening a tool window that reads the disk, closing the
|
|
546
|
+
* window, Cmd+S. Safe to call when nothing is pending (it does nothing) and
|
|
547
|
+
* safe to call during a write (it waits for it, then writes again if more
|
|
548
|
+
* arrived while it ran).
|
|
549
|
+
*/
|
|
550
|
+
flush(): Promise<void>;
|
|
551
|
+
/** Give up on what is pending without writing it. For a project close after
|
|
552
|
+
* the author has said to discard, and for teardown. */
|
|
553
|
+
cancel(): void;
|
|
554
|
+
/**
|
|
555
|
+
* Autosave on or off (Patterpad's per-project setting).
|
|
556
|
+
*
|
|
557
|
+
* Off does not mean "never write": touch() still marks the work unsaved, and
|
|
558
|
+
* flush() still writes on transitions and on Cmd+S. It only stops the clock.
|
|
559
|
+
*/
|
|
560
|
+
setAuto(on: boolean): void;
|
|
561
|
+
}
|
|
562
|
+
declare function createSaveController(opts: SaveControllerOptions): SaveController;
|
|
563
|
+
|
|
564
|
+
export { type AboutOptions, type AnchoredPanel, type AnchoredPanelOptions, type Child, type Comment, type CommentMessage, type CommentsOptions, type ConfirmOptions, type DocLine, type DupGuard, type ElProps, type GameIdEditorOptions, type IconName, type IconSvgName, type Identity, type IdentityOptions, type JobProgressOptions, type JobProgressView, type Notes, type NotesEditorOptions, PALETTE, PALETTE_SIZE, type PaneShell, type PaneShellOptions, type PaneShellState, type PaneSide, type PaneSideConfig, type PinButtonOptions, type SaveController, type SaveControllerOptions, type SaveStatus, type SettingsDialog, type SettingsDialogOptions, type SettingsSection, type SettingsSectionHandle, type ShardVc, type TipRect, type TooltipOptions, type VcMap, askIdentity, closeAnchoredPanel, colourFor, colourIndex, confirmDialog, createSaveController, dupGuard, el, expandableRow, focusNewRow, foldVc, gameIdify, hideTip, icon, iconBtn, iconSvg, initTooltips, isValidGameId, labelled, lockControls, lockNotice, mountJobProgress, mountPaneShell, mountSettingsDialog, moveItem, openAnchoredPanel, openComments, openGameIdEditor, openNotesEditor, paintVcBadges, pinButton, placeAnchored, showAbout, tagChips, tipAt, tipBold, vcBadgeFor };
|