pipeup 0.7.0 → 0.8.0-beta.2
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 +22 -13
- package/cli/init.mjs +581 -0
- package/cli/pipeup.mjs +70 -1
- package/cli/read.mjs +299 -0
- package/dist/addons.json +54 -0
- package/dist/pipeup.agents.js +1 -1
- package/dist/pipeup.core.js +1 -1
- package/dist/pipeup.esm.js +1 -1
- package/dist/pipeup.min.js +1 -1
- package/dist/types/core.d.ts +4 -2
- package/dist/types/document.d.ts +2 -2
- package/dist/types/export/agent.d.ts +1 -1
- package/dist/types/index.d.ts +0 -1
- package/dist/types/ui/addons.d.ts +24 -1
- package/dist/types/ui/app.d.ts +2 -3
- package/dist/types/ui/composer.d.ts +9 -3
- package/dist/types/ui/context.d.ts +10 -4
- package/dist/types/ui/draft-view.d.ts +2 -3
- package/dist/types/ui/host.d.ts +1 -1
- package/dist/types/ui/icons.d.ts +8 -5
- package/dist/types/ui/layout.d.ts +15 -1
- package/dist/types/ui/legible.d.ts +1 -1
- package/dist/types/ui/reactions.d.ts +2 -0
- package/dist/types/ui/select.d.ts +1 -1
- package/dist/types/ui/shortcut.d.ts +6 -0
- package/dist/types/ui/styles.d.ts +1 -1
- package/dist/types/ui/thread-view.d.ts +17 -10
- package/package.json +2 -1
- package/skills/pipeup-add/SKILL.md +4 -4
- package/skills/pipeup-apply/SKILL.md +2 -2
- package/skills/pipeup-integrate/SKILL.md +4 -4
- package/skills/pipeup-send-to-git-setup/SKILL.md +2 -2
- package/skills/pipeup-summarise/SKILL.md +3 -3
- package/dist/types/crypto/portable.d.ts +0 -15
- package/dist/types/ui/identity.d.ts +0 -27
package/dist/types/core.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export declare const VERSION = "0.
|
|
1
|
+
export declare const VERSION = "0.8.0-beta.2";
|
|
2
2
|
/** The day this version was made (set with the version): Pipeup says so, once, in the console when it is over a year old. */
|
|
3
|
-
export declare const BUILT = "2026-10-
|
|
3
|
+
export declare const BUILT = "2026-10-15";
|
|
4
4
|
export { PipeupDocument, UnsavedChangeError, type Listener, type OpenOptions } from "./document";
|
|
5
5
|
export { DEFAULT_PROFILE_NAME, MemoryStore, loadOrCreateProfile, type OpStore, type Profile, } from "./storage/store";
|
|
6
6
|
export { IndexedDbStore } from "./storage/indexeddb";
|
|
@@ -12,5 +12,7 @@ export { describeElement, describeRange } from "./anchor/describe";
|
|
|
12
12
|
export { resolveAnchor, type AnchorState, type Resolved, type ResolveOptions } from "./anchor/resolve";
|
|
13
13
|
export { labelOf, locate, type Location } from "./anchor/locate";
|
|
14
14
|
export { copyAll, copyThread, formatAgo, type CopyAs, type ExportItem, type ExportMeta, } from "./export/format";
|
|
15
|
+
export { readFeedbackFile } from "./storage/feedback-file";
|
|
16
|
+
export { agentComments, type AgentComments, type AgentThread } from "./export/agent";
|
|
15
17
|
export { AI_NAME, ANIMALS, COLOURS, animalName, isAiName, nameOf, type Animal } from "./model/animals";
|
|
16
18
|
export type { Anchor, Comment, OpBody, SignedOp, Thread } from "./model/types";
|
package/dist/types/document.d.ts
CHANGED
|
@@ -54,8 +54,8 @@ export declare class PipeupDocument {
|
|
|
54
54
|
contacts(): Map<string, string>;
|
|
55
55
|
/** This reviewer's identity was made portable, so it has a recovery code (an ordinary one can't leave the browser). */
|
|
56
56
|
get portable(): boolean;
|
|
57
|
-
/** The
|
|
58
|
-
|
|
57
|
+
/** The 32-byte seed of a portable identity, for backing it up; null for an ordinary one. */
|
|
58
|
+
seed(): Promise<Uint8Array | null>;
|
|
59
59
|
/** Marks comments read by this reviewer (one `seen` op each, for those not already marked), so every device knows. */
|
|
60
60
|
seen(commentIds: readonly string[]): Promise<void>;
|
|
61
61
|
/** Reacts to a comment with one emoji; reacting twice with the same emoji changes nothing. */
|
package/dist/types/index.d.ts
CHANGED
|
@@ -3,5 +3,4 @@ export { comments, mount, type MountOptions, type PipeupInstance } from "./ui/mo
|
|
|
3
3
|
export type { Appearance } from "./ui/legible";
|
|
4
4
|
export { setPeople, type Person } from "./ui/mentions";
|
|
5
5
|
export { ADDON_API, addons, use, type AddonDocument, type AddonHost, type AddonInfo, type Capability, type ComposerHandle, type ComposerTool, type Dictation, type ItemHandle, type ListNote, type ReactionPicker, type MenuItem, type NetworkUse, type Off, type PanelHandle, type PanelOptions, type PipeupAddon, type Status, type Teardown, type UiSnapshot, } from "./ui/addons";
|
|
6
|
-
export { type AgentComments, type AgentThread } from "./export/agent";
|
|
7
6
|
export { onReveal, setViewState, type SlideHook, type ViewState } from "./ui/here";
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import type { Identity } from "../crypto/identity";
|
|
1
2
|
import type { Listener, PipeupDocument } from "../document";
|
|
2
3
|
import type { SignedOp, Thread } from "../model/types";
|
|
3
4
|
import { type ComposerTool } from "./composer";
|
|
@@ -7,7 +8,7 @@ import type { ViewState } from "./here";
|
|
|
7
8
|
export declare const ADDON_API = 1;
|
|
8
9
|
export type Teardown = () => void;
|
|
9
10
|
export type Off = () => void;
|
|
10
|
-
export type Capability = "sync" | "menu" | "notify" | "note" | "composer" | "panel" | "styles" | "status" | "overlay" | "here" | "sign" | "listnote" | "reactions";
|
|
11
|
+
export type Capability = "sync" | "menu" | "notify" | "note" | "composer" | "panel" | "styles" | "status" | "overlay" | "here" | "sign" | "listnote" | "reactions" | "identity" | "dialog";
|
|
11
12
|
export interface NetworkUse {
|
|
12
13
|
when: "never" | "after-consent" | "page-configured";
|
|
13
14
|
/** Hosts; "page" is an address the page names. */
|
|
@@ -107,6 +108,22 @@ export interface UiSnapshot {
|
|
|
107
108
|
import type { ReactionPicker } from "./reactions";
|
|
108
109
|
export type { ReactionPicker } from "./reactions";
|
|
109
110
|
export type { ComposerHandle, ComposerTool, Dictation } from "./composer";
|
|
111
|
+
export interface DialogHandle {
|
|
112
|
+
close(): void;
|
|
113
|
+
}
|
|
114
|
+
/** This reviewer's identity, for an add-on that backs it up or replaces it (the add-on is trusted with it, as with any script on the page). */
|
|
115
|
+
export interface IdentityAccess {
|
|
116
|
+
/** The identity was made portable: its key can be backed up. An ordinary one can't leave the browser. */
|
|
117
|
+
readonly portable: boolean;
|
|
118
|
+
/** The 32-byte seed of a portable identity; null for an ordinary one. */
|
|
119
|
+
seed(): Promise<Uint8Array | null>;
|
|
120
|
+
/** Keeps `key`, an extractable Ed25519 private key, as this browser's identity from the next load on. */
|
|
121
|
+
use(key: CryptoKey): Promise<void>;
|
|
122
|
+
/** Shares how to reach this reviewer (an email address or `gh:name`) with everyone who has the comments; false if it isn't one. */
|
|
123
|
+
share(contact: string): Promise<boolean>;
|
|
124
|
+
/** Stops sharing it. */
|
|
125
|
+
unshare(): Promise<void>;
|
|
126
|
+
}
|
|
110
127
|
export interface AddonHost {
|
|
111
128
|
readonly api: number;
|
|
112
129
|
/** The core's version, for diagnostics only. */
|
|
@@ -154,6 +171,9 @@ export interface AddonHost {
|
|
|
154
171
|
onUi(fn: (ui: UiSnapshot) => void): Off;
|
|
155
172
|
avatar(key: string, name: string): HTMLElement;
|
|
156
173
|
sign(name: string, data: string): Promise<string>;
|
|
174
|
+
readonly identity: IdentityAccess;
|
|
175
|
+
/** A small dialog over the page, labelled `label`; Escape closes it, and it goes with the add-on. */
|
|
176
|
+
openDialog(content: Node, label: string): DialogHandle;
|
|
157
177
|
}
|
|
158
178
|
/**
|
|
159
179
|
* Everything add-ons put on the page, held by the app (not by the views) so it survives layout rebuilds. Each
|
|
@@ -231,6 +251,7 @@ export declare class Surface {
|
|
|
231
251
|
private call;
|
|
232
252
|
/** A side panel: the rest of Pipeup's UI is inert while it is open; Escape closes it before anything else. */
|
|
233
253
|
panel(id: string, content: Node, o: PanelOptions): PanelHandle;
|
|
254
|
+
dialog(id: string, content: Node, label: string): DialogHandle;
|
|
234
255
|
/** Removes everything one add-on added. */
|
|
235
256
|
clear(id: string): void;
|
|
236
257
|
destroy(): void;
|
|
@@ -242,6 +263,8 @@ interface Live {
|
|
|
242
263
|
ephemeral: boolean;
|
|
243
264
|
version: string;
|
|
244
265
|
active: boolean;
|
|
266
|
+
/** Keeps another identity for this browser, used from the next load. */
|
|
267
|
+
onIdentity(identity: Identity): Promise<void>;
|
|
245
268
|
}
|
|
246
269
|
/**
|
|
247
270
|
* A Pipeup already on the page when this copy loaded (the classic build assigns its global only when it ends, so
|
package/dist/types/ui/app.d.ts
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
import { type PipeupDocument } from "../document";
|
|
2
|
-
import type { Identity } from "../crypto/identity";
|
|
3
2
|
import type { Ctx, UiState, View } from "./context";
|
|
4
3
|
import { type Appearance } from "./legible";
|
|
5
4
|
export interface AppOptions {
|
|
6
5
|
doc: PipeupDocument;
|
|
7
6
|
root: Element;
|
|
8
7
|
onName(name: string): Promise<void>;
|
|
9
|
-
/**
|
|
10
|
-
|
|
8
|
+
/** Pipeup's stylesheet (passed in so the bundles can carry it last, where it compresses best). */
|
|
9
|
+
styles: string;
|
|
11
10
|
}
|
|
12
11
|
export interface App {
|
|
13
12
|
readonly ctx: Ctx;
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
import { type Person } from "./mentions";
|
|
2
2
|
import type { Mention } from "../model/types";
|
|
3
3
|
export interface ComposerOptions {
|
|
4
|
+
/** The line's name for screen readers, and the send button's word ("Comment", "Reply", "Save"). */
|
|
4
5
|
label: string;
|
|
6
|
+
/** What the empty line says ("Comment or add others with @"). */
|
|
7
|
+
placeholder?: string;
|
|
8
|
+
/** Words already in the line (editing a comment). */
|
|
9
|
+
value?: string;
|
|
5
10
|
/** A new comment, or a reply in `thread()`. */
|
|
6
11
|
kind?: "comment" | "reply";
|
|
7
12
|
thread?: () => string;
|
|
8
|
-
/** Something to show before the line instead, such as the writer's avatar. */
|
|
9
|
-
before?: Node;
|
|
10
13
|
/** `mentions`: the people named in the words, found after trimming. */
|
|
11
14
|
onSend(text: string, mentions: Mention[]): Promise<void> | void;
|
|
12
15
|
onCancel?(): void;
|
|
@@ -60,5 +63,8 @@ export declare const setComposerSource: (s: ComposerSource | null) => void;
|
|
|
60
63
|
export declare const composerNote: () => string | null;
|
|
61
64
|
/** Sent to a writing line or a new-comment box when what add-ons put in it changes. */
|
|
62
65
|
export declare const SOURCE_CHANGED = "pu-source";
|
|
63
|
-
/**
|
|
66
|
+
/**
|
|
67
|
+
* A writing box: what it is for when empty, then Cancel and Send (named for what it does) while it is in use.
|
|
68
|
+
* Enter sends, Shift+Enter breaks, Esc cancels. Send stays grey, and out of Tab's reach, until there are words.
|
|
69
|
+
*/
|
|
64
70
|
export declare function composer(o: ComposerOptions): Composer;
|
|
@@ -22,12 +22,16 @@ export interface UiState {
|
|
|
22
22
|
showResolved: boolean;
|
|
23
23
|
/** All comments shows only the threads that name this reviewer. */
|
|
24
24
|
mine: boolean;
|
|
25
|
-
/**
|
|
25
|
+
/** The reviewer chose Hide comments (remembered for this page in this browser). */
|
|
26
|
+
hide: boolean;
|
|
27
|
+
/** Comments are out of sight: Hide comments is on, and nothing is showing them for a while (comment mode, All comments, a draft). */
|
|
26
28
|
hidden: boolean;
|
|
27
29
|
mode: "column" | "bubbles";
|
|
28
30
|
draft: Draft | null;
|
|
29
31
|
/** Comment mode: the page is quiet and a click chooses a block to comment on. */
|
|
30
32
|
commenting: boolean;
|
|
33
|
+
/** Comment mode is paused while Space is held: the page works as normal. */
|
|
34
|
+
paused: boolean;
|
|
31
35
|
/** All comments is open on the right: in the column layout it takes the column's place. */
|
|
32
36
|
listing: boolean;
|
|
33
37
|
/** A thread chosen from All comments on a narrow screen is open: comments show until it closes. */
|
|
@@ -45,8 +49,8 @@ export interface MenuActions {
|
|
|
45
49
|
copyAll(as: CopyAs): Promise<void>;
|
|
46
50
|
toggleResolved(): void;
|
|
47
51
|
toggleMine(): void;
|
|
48
|
-
/**
|
|
49
|
-
|
|
52
|
+
/** Hide comments on or off, remembered for this page in this browser. */
|
|
53
|
+
setHide(on: boolean): void;
|
|
50
54
|
rename(name: string): Promise<void>;
|
|
51
55
|
/** The reviewer's name; "" until they add one. */
|
|
52
56
|
name(): string;
|
|
@@ -110,11 +114,13 @@ export interface Ctx {
|
|
|
110
114
|
/** Who can be mentioned with `@`: people in this document, agents the page lists, and people supplied. */
|
|
111
115
|
people(): Person[];
|
|
112
116
|
cancelDraft(): void;
|
|
113
|
-
/** Turns comment mode on or off
|
|
117
|
+
/** Turns comment mode on or off. `keys`: from the keyboard (the block cursor starts). */
|
|
114
118
|
setCommenting(on: boolean, keys?: boolean): void;
|
|
115
119
|
/** What a click on the page does: cancels an empty draft (back to one with words), else closes the open thread. */
|
|
116
120
|
dismiss(): void;
|
|
117
121
|
registerDraft(box: DraftBox | null): void;
|
|
122
|
+
/** All comments opens thread `id` in its panel (while the panel is open, opening a thread goes there). */
|
|
123
|
+
registerList(open: ((id: string) => void) | null): void;
|
|
118
124
|
toast(message: string): void;
|
|
119
125
|
/** Tells screen readers (a polite live region), once. */
|
|
120
126
|
say(text: string): void;
|
|
@@ -26,9 +26,8 @@ export interface DraftBox {
|
|
|
26
26
|
isEmpty(): boolean;
|
|
27
27
|
}
|
|
28
28
|
/**
|
|
29
|
-
* The box for a new comment: what it's on, then the writing
|
|
30
|
-
*
|
|
31
|
-
* field in its place.
|
|
29
|
+
* The box for a new comment, as a card: who is writing, what it's on, then the writing box. Nobody has to give a
|
|
30
|
+
* name; the top line says who they are ("You're Otter · add your name") and opens a name field in its place.
|
|
32
31
|
*/
|
|
33
32
|
export declare function renderDraft(o: DraftOptions): DraftBox;
|
|
34
33
|
/**
|
package/dist/types/ui/host.d.ts
CHANGED
|
@@ -9,4 +9,4 @@ export interface Host {
|
|
|
9
9
|
* Pipeup's only element in the page: a fixed, click-through <pipeup-root> under <html> with an open shadow
|
|
10
10
|
* root (open so tools like `pipeup check` can measure it). It never changes the page's layout.
|
|
11
11
|
*/
|
|
12
|
-
export declare function createHost(theme: Theme, doc?: Document): Host;
|
|
12
|
+
export declare function createHost(theme: Theme, styles: string, doc?: Document): Host;
|
package/dist/types/ui/icons.d.ts
CHANGED
|
@@ -1,18 +1,21 @@
|
|
|
1
1
|
declare const PATHS: {
|
|
2
2
|
readonly comment: readonly ["M20.5 11.5a8 8 0 0 1-11.7 7.1L4 19.8l1.2-4.4A8 8 0 1 1 20.5 11.5z", "M12.3 8.2v6.6M9 11.5h6.6"];
|
|
3
|
-
readonly send: readonly ["M21 12L3.5 4.5 6.2 12l-2.7 7.5zM6.2 12H13"];
|
|
4
3
|
readonly copy: readonly ["M10 8h8a2 2 0 0 1 2 2v8a2 2 0 0 1-2 2h-8a2 2 0 0 1-2-2v-8a2 2 0 0 1 2-2z", "M16 8V6a2 2 0 0 0-2-2H6a2 2 0 0 0-2 2v8a2 2 0 0 0 2 2h2"];
|
|
5
4
|
readonly resolve: readonly ["M5 12.5l4.5 4.5L19 7.5"];
|
|
6
5
|
readonly reopen: readonly ["M3 12a9 9 0 1 0 3-6.7", "M3 4v5h5"];
|
|
7
6
|
readonly lines: readonly ["M4 7h16M4 12h10M4 17h7"];
|
|
8
7
|
readonly list: readonly ["M3 6.5a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0-3 0M3 12a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0-3 0M3 17.5a1.5 1.5 0 1 0 3 0a1.5 1.5 0 1 0-3 0M9 6.5h11M9 12h11M9 17.5h7"];
|
|
9
|
-
readonly expand: readonly ["
|
|
10
|
-
readonly pin: readonly ["
|
|
11
|
-
readonly
|
|
8
|
+
readonly expand: readonly ["M5.5 10h7a1.5 1.5 0 0 1 1.5 1.5v7a1.5 1.5 0 0 1-1.5 1.5h-7A1.5 1.5 0 0 1 4 18.5v-7A1.5 1.5 0 0 1 5.5 10z", "M14 10l6-6M15 4h5v5"];
|
|
9
|
+
readonly pin: readonly ["M4 20v-8a8 8 0 1 1 8 8z"];
|
|
10
|
+
readonly at: readonly ["M9.1 12a2.9 2.9 0 1 0 5.8 0a2.9 2.9 0 1 0-5.8 0", "M14.9 12v1.1a1.8 1.8 0 0 0 3.6 0V12a6.5 6.5 0 1 0-3.97 5.98"];
|
|
11
|
+
readonly chev: readonly ["M9 6l6 6-6 6"];
|
|
12
|
+
readonly shrink: readonly ["M7 4h10a3 3 0 0 1 3 3v10a3 3 0 0 1-3 3H7a3 3 0 0 1-3-3V7a3 3 0 0 1 3-3z", "M16 8l-7 7M9 10v5h5"];
|
|
12
13
|
readonly bubble: readonly ["M20.5 11.5a8 8 0 0 1-11.7 7.1L4 19.8l1.2-4.4A8 8 0 1 1 20.5 11.5z"];
|
|
13
14
|
readonly close: readonly ["M6 6l12 12M18 6L6 18"];
|
|
14
|
-
readonly smile: readonly ["M12 3a9 9 0 1 0 0 18a9 9 0 0 0 0-18z", "M8.
|
|
15
|
+
readonly smile: readonly ["M12 3a9 9 0 1 0 0 18a9 9 0 0 0 0-18z", "M8.6 14.2c1.9 2.1 4.9 2.1 6.8 0", "M9.6 9.8a.6.6 0 1 1-1.2 0a.6.6 0 1 1 1.2 0M15.6 9.8a.6.6 0 1 1-1.2 0a.6.6 0 1 1 1.2 0"];
|
|
15
16
|
readonly edit: readonly ["M4 20h4L19 9l-4-4L4 16z"];
|
|
17
|
+
readonly hide: readonly ["M2.5 12S6 5.5 12 5.5 21.5 12 21.5 12 18 18.5 12 18.5 2.5 12 2.5 12z", "M12 9.5a2.5 2.5 0 1 0 0 5a2.5 2.5 0 0 0 0-5z", "M4 4l16 16"];
|
|
18
|
+
readonly more: readonly ["M5.5 12h.01M12 12h.01M18.5 12h.01"];
|
|
16
19
|
readonly look: readonly ["M12 3a9 9 0 1 0 0 18a9 9 0 0 0 0-18z", "M12 3v18"];
|
|
17
20
|
};
|
|
18
21
|
export type IconName = keyof typeof PATHS;
|
|
@@ -19,6 +19,8 @@ export interface AnchorPoint {
|
|
|
19
19
|
y: number;
|
|
20
20
|
/** Text comments open below their line; element comments open beside. */
|
|
21
21
|
below: boolean;
|
|
22
|
+
/** What it is about: with no room beside, an element or pin's popover goes below it or above, not over it. */
|
|
23
|
+
box: Box;
|
|
22
24
|
}
|
|
23
25
|
/** Threads sit level with what they're about; overlaps push down; the open thread aligns exactly. */
|
|
24
26
|
export declare function stackColumn(items: StackItem[], activeId: string | null, gap?: number): Map<string, number>;
|
|
@@ -44,7 +46,8 @@ export declare function placePopover(at: AnchorPoint, size: {
|
|
|
44
46
|
};
|
|
45
47
|
/**
|
|
46
48
|
* An element draft: just below its block, above it when there is no room below, never over the block or the
|
|
47
|
-
* naming bar (which sits above the block, or below it when there is no room above).
|
|
49
|
+
* naming bar (which sits above the block, or below it when there is no room above). A block too tall for either
|
|
50
|
+
* keeps the box on screen, as low as it fits.
|
|
48
51
|
*/
|
|
49
52
|
export declare function placeDraft(block: Box, size: {
|
|
50
53
|
width: number;
|
|
@@ -62,3 +65,14 @@ export declare function placeBar(target: Box, size: {
|
|
|
62
65
|
left: number;
|
|
63
66
|
top: number;
|
|
64
67
|
};
|
|
68
|
+
/**
|
|
69
|
+
* The selection's comment icon: just past the right of its block's text, level with the selection's last line, so it
|
|
70
|
+
* covers no words; above the selection (or below) when there's no room there.
|
|
71
|
+
*/
|
|
72
|
+
export declare function placeIcon(sel: Box, line: Box, textRight: number, size: {
|
|
73
|
+
width: number;
|
|
74
|
+
height: number;
|
|
75
|
+
}, vp: Viewport): {
|
|
76
|
+
left: number;
|
|
77
|
+
top: number;
|
|
78
|
+
};
|
|
@@ -4,7 +4,7 @@ export declare const PAIRS: Record<Look, [string, string]>;
|
|
|
4
4
|
export interface Appearance {
|
|
5
5
|
/** The look Pipeup is showing. */
|
|
6
6
|
look: Look;
|
|
7
|
-
/** Who chose it: the reviewer (the
|
|
7
|
+
/** Who chose it: the reviewer (the Theme row), the author (data-pipeup-theme) or what the page shows. */
|
|
8
8
|
source: "reviewer" | "author" | "page";
|
|
9
9
|
/** Contrast of Pipeup's words on its own surface, as the page's styles leave it; 3 is the least that reads. */
|
|
10
10
|
ratio: number;
|
|
@@ -19,6 +19,8 @@ export interface ReactionOptions {
|
|
|
19
19
|
resolved: boolean;
|
|
20
20
|
/** The quick row is open under this comment. */
|
|
21
21
|
quick: boolean;
|
|
22
|
+
/** Only the quick row, never the chips (a closed card in All comments counts reactions in its last line). */
|
|
23
|
+
bare?: boolean;
|
|
22
24
|
/** Gives or takes back a reaction. */
|
|
23
25
|
react(emoji: string, on: boolean): void;
|
|
24
26
|
/** Chips and quick buttons already on the page once, so only new ones ease in. */
|
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
import type { Ctx, View } from "./context";
|
|
2
|
-
/** In comment mode, selecting text offers commenting: one comment icon
|
|
2
|
+
/** In comment mode, selecting text offers commenting: one comment icon beside the selection's block, never over its words. */
|
|
3
3
|
export declare function createSelection(ctx: Ctx): View;
|
|
@@ -5,6 +5,12 @@ export declare const SHORTCUT: {
|
|
|
5
5
|
};
|
|
6
6
|
/** The key's label: symbols on Apple platforms, words elsewhere. */
|
|
7
7
|
export declare const SHORTCUT_LABEL: string;
|
|
8
|
+
/**
|
|
9
|
+
* The key held to pause comment mode (`KeyboardEvent.key`), and its label: Space, the one key that changes nothing about
|
|
10
|
+
* a click (Command, Ctrl, Shift and Option all make a click on a link do something else).
|
|
11
|
+
*/
|
|
12
|
+
export declare const HOLD = " ";
|
|
13
|
+
export declare const HOLD_LABEL = "Space";
|
|
8
14
|
export declare const SHORTCUT_ARIA = "Shift+Alt+C";
|
|
9
15
|
/**
|
|
10
16
|
* Shift+Option+C (Shift+Alt+C): never a key repeat, Command or Ctrl, or AltGr (which types characters).
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
/** Pipeup's stylesheet, scoped to its shadow root. Light by default; `.dark` follows a dark page. */
|
|
2
|
-
export declare const STYLES = "\n/* Inherited page styles are reset on .layer below; custom properties pass through all:initial. */\n:host{all:initial;direction:ltr;unicode-bidi:normal}\n*{box-sizing:border-box}\nbutton{appearance:none;font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}\nsvg{display:block}\n.layer{all:initial;direction:ltr;unicode-bidi:normal;display:block;position:fixed;inset:0;pointer-events:none;font:13px/1.5 var(--pu-font,system-ui,sans-serif);color:var(--k);\n--k:#2C2C2A;--mu:#5F5E5A;--fa:#6B6A64;--ln:#E5E3DA;--ru:#ECEAE2;--so:#FAFAF7;--su:#FFFFFF;--ho:#F1EFE8;\n--as:color-mix(in srgb,var(--pu-accent,#534AB7) 12%,transparent);\n--sh:0 8px 28px rgba(44,44,42,.10);\n--in:.26s;--mv:.34s;--out:.2s;--pl:1.2s;\n--eo:cubic-bezier(.22,.61,.36,1);--eio:cubic-bezier(.4,0,.2,1);--ei:cubic-bezier(.4,0,1,1);\n--pu-text:var(--k);--pu-muted:var(--mu);--pu-faint:var(--fa);--pu-line:var(--ln);--pu-surface:var(--su);--pu-soft:var(--so);--pu-hover:var(--ho);--pu-shadow:var(--sh);--pu-ease:var(--eo)}\n.layer{transition:opacity .24s var(--eo)}.layer.sw{opacity:0;transition-duration:.16s;transition-timing-function:var(--ei)}\n.layer.dark{--k:#ECEBE6;--mu:#B4B2A9;--fa:#9A9892;--ln:#3A3936;--ru:#34332F;--so:#22221F;--su:#1B1B19;--ho:#2C2C29;--sh:0 8px 28px rgba(0,0,0,.45)}\n.layer.hidden .bub,.layer.hidden .col,.layer.hidden .pop,.layer.hidden .tip,.layer.hidden .mark,.layer.hidden .selbar{opacity:0!important;pointer-events:none!important}\n\n.tx{font-size:14px;line-height:1.5;color:var(--k);white-space:pre-wrap;overflow-wrap:anywhere}\n.tx.del,.who,.rest,.ctx{color:var(--fa)}\n.who,.rest{font-size:12px}\n/* Long names are cut short on one line, never wrapped. */\n.who{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.rft>.who{display:block}\n.ctx[hidden]{display:none}\n.ctx{font-size:12px;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.clamp{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n.tx a{color:var(--pu-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}\n\n/* Footers: details take no space until hovered, then ease open beneath the words. */\n.ft,.rft{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.ft>*,.rft>*{overflow:hidden;min-height:0;display:flex;align-items:center}\n.root:hover>.ft,.root:focus-within>.ft,.it:hover>.rft,.it:focus-within>.rft{grid-template-rows:1fr;opacity:1}\n.ft.has-rest,.ft.open,.rft.open{grid-template-rows:1fr;opacity:1}\n.ft.has-rest>*{grid-area:1/1}\n.ft .hover{opacity:0;transition:opacity var(--in) var(--eo)}\n.ft .rest{transition:opacity var(--in) var(--eo)}\n.root:hover>.ft .hover,.root:focus-within>.ft .hover,.ft:not(.has-rest) .hover{opacity:1}\n.root:hover>.ft .rest,.root:focus-within>.ft .rest{opacity:0}\n.acts{margin-left:6px;display:flex;flex:none}\n.ib{width:24px;height:22px;display:grid;place-items:center;border-radius:6px;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.ib:hover,.ib:focus-visible{background:var(--ho);color:var(--k);outline:none}\n\n/* Replies: one level in, oldest first; the reply line ends the thread at the same indent. */\n.rps,.rbox{padding-left:14px}\n.rps .it{padding-top:6px}\n.more{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--mv) var(--eio)}\n.more>div{overflow:hidden;min-height:0}\n.th:not(.on) .more{grid-template-rows:0fr}\n\n.row{position:relative;display:flex;align-items:center;gap:8px;padding:8px 0 2px;cursor:text}\n.input{flex:1;min-width:0;height:27px;display:block;border:0;border-bottom:1px solid var(--ln);outline:none;resize:none;overflow:hidden;\nfont:inherit;font-size:14px;line-height:1.5;padding:3px 0;color:var(--k);background:transparent;transition:border-color var(--in) var(--eo)}\n.row:hover .input,.input:hover{border-bottom-color:var(--mu)}\n.input:focus{border-bottom-color:var(--pu-accent)}\n.ed{display:flex;gap:10px;align-items:center;min-height:34px;padding:6px 10px}\n.ed .input{font-size:13px;height:22px}\n\n/* Avatars: a squircle with the writer's animal (or initial) on a soft colour. Each comment keeps a fixed area\nat its top right for one, so its words are the same width with or without it. */\n.root,.it{position:relative;padding-right:30px}\n.av{display:grid;place-items:center;width:22px;height:22px;border-radius:32%;\nfont-size:12px;font-weight:600;line-height:1;opacity:0;transform:scale(.85);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.av.in{opacity:1;transform:none}\n.av svg{width:80%;height:80%}\n.root>.av,.it>.av{position:absolute;top:0;right:0}\n.it>.av{top:6px}\n/* Ten colours (.c0 Red to .c9 Grey, as COLOURS): a soft tint and a dark drawing, swapped round on dark pages. */\n.av{--av-l:92%;--av-d:30%;--s:60%;background:hsl(var(--h) var(--s) var(--av-l));color:hsl(var(--h) var(--s) var(--av-d))}\n.dark .av{--av-l:20%;--av-d:78%}\n/* An AI's reply: a plain disc with a violet ring, all inside the avatar's own box so nothing is cropped. */\n.av.ai{position:relative;border-radius:50%;background:var(--su);color:var(--pu-accent);font-size:9px;letter-spacing:.02em}\n.av.ai::before{content:\"\";position:absolute;inset:3px;border-radius:50%;border:1.5px solid var(--pu-accent);pointer-events:none}\n.root>.av.ai,.it>.av.ai{position:absolute}\n.refs{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;white-space:normal}\n.refs .ref{display:inline-flex;align-items:center;gap:5px;max-width:160px;padding:1px 9px;border:1px solid var(--ln);border-radius:999px;background:var(--so);color:var(--mu);font:inherit;font-size:11.5px;line-height:1.6;text-decoration:none;cursor:pointer;transition:background-color .2s var(--eo),color .2s var(--eo),border-color .2s var(--eo)}\n.refs .ref:hover,.refs .ref:focus-visible{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent);outline:none}\n.ref span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.rxp{position:fixed;width:320px;height:340px;border-radius:12px;overflow:hidden;pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.rxp.show{opacity:1;transform:none;pointer-events:auto}\n.mn{border-radius:4px;padding:0 2px;background:var(--as);color:var(--pu-accent)}\n.mn.me{font-weight:600}\n.mnl{position:absolute;left:0;bottom:100%;margin:0 0 4px;padding:4px;list-style:none;min-width:180px;max-width:100%;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh);opacity:0;transform:translateY(4px);pointer-events:none;z-index:4;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.mnl.show{opacity:1;transform:none;pointer-events:auto}\n.mnl li{display:flex;align-items:baseline;gap:8px;padding:5px 8px;border-radius:6px;font-size:13px;color:var(--k);cursor:pointer}\n.mnl li small{font-size:11px;color:var(--fa)}\n.mnl li.on,.mnl li:hover{background:var(--as);color:var(--pu-accent)}\n.dlg{position:fixed;left:50%;top:18vh;width:min(380px,calc(100vw - 32px));padding:16px 18px;border:1px solid var(--ln);border-radius:14px;background:var(--su);box-shadow:var(--sh);color:var(--k);opacity:0;transform:translate(-50%,6px);pointer-events:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.dlg.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}\n.dlg-t{margin:0 0 8px;font-size:15px;font-weight:600}\n.dlg-b p{margin:0 0 8px;font-size:13px;line-height:1.5;color:var(--mu)}\n.dlg-c{display:block;margin:8px 0;padding:8px 10px;border-radius:8px;background:var(--so);font:12px/1.6 ui-monospace,monospace;word-break:break-all;user-select:all}\n.dlg-f{width:100%;margin:6px 0;padding:8px;border:1px solid var(--ln);border-radius:8px;background:var(--so);color:var(--k);font:12px/1.5 ui-monospace,monospace}\n.dlg-m{min-height:1.2em;margin:4px 0;font-size:12px;color:var(--pu-accent)}\n.dlg-a{display:flex;gap:6px;justify-content:flex-end;margin-top:6px}\n.dlg-btn{padding:6px 12px;border:1px solid var(--ln);border-radius:8px;font-size:13px;color:var(--k);transition:background-color .2s var(--eo)}\n.dlg-btn:hover,.dlg-btn:focus-visible{background:var(--ho);outline:none}\n.dlg-btn.primary{border-color:var(--pu-accent);color:var(--pu-accent)}\n.toast.act{pointer-events:auto}\n.ta{margin-left:4px;color:var(--pu-accent);text-decoration:underline;text-underline-offset:2px}\n.dlg-h{margin:12px 0 4px;font-size:13px;font-weight:600}\n.rx .n{font-size:11px}\n.rx.mine{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent)}\n.rx:disabled{cursor:default;opacity:.7}\n.rx.new,.rxq.new{animation:pu-in var(--mv) var(--eo) both}\n.rxs{align-items:center}\n.rxq{display:inline-flex;gap:2px}\n.rxo{padding:2px 5px;border-radius:8px;font-size:16px;line-height:1.3;transition:background-color .2s var(--eo)}\n.rxo:hover,.rxo:focus-visible,.rxo[aria-pressed=true]{background:var(--as);outline:none}\n.rrow{min-width:0;flex:1;display:flex;align-items:center}\n.refs .ref{position:relative}.ref .rc{position:absolute;left:0;top:calc(100% + 6px);z-index:3;width:max-content;max-width:min(240px,70vw);padding:6px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);color:var(--k);font-size:12px;line-height:1.45;white-space:normal;text-align:left;overflow:visible;opacity:0;visibility:hidden;transform:translateY(-3px);pointer-events:none;transition:opacity .2s var(--eo),transform .2s var(--eo),visibility 0s .2s}.ref:hover .rc,.ref:focus-visible .rc{opacity:1;visibility:visible;transform:none;transition-delay:0s}\n.ref .sl{width:10px;height:7px;border:1.3px solid currentColor;border-radius:2px;flex:none}\n.seen{display:flex;align-items:center;gap:6px;padding:6px 0 0 14px;font-size:12px;color:var(--fa)}\n.seen button{margin-left:auto;padding:0 6px;border:0;border-radius:6px;background:none;color:var(--fa);font:inherit;cursor:pointer;transition:color .2s var(--eo),background-color .2s var(--eo)}.seen button:hover,.seen button:focus-visible{color:var(--pu-accent);background:var(--as);outline:none}\n.seen i{width:12px;height:12px;border-radius:50%;border:1.5px solid var(--pu-accent);flex:none}\n.c0{--h:0}.c1{--h:25}.c2{--h:50}.c3{--h:130}.c4{--h:175}.c5{--h:215}.c6{--h:270}.c7{--h:330}.c8{--h:28;--s:35%}.c9{--h:220;--s:8%}\n.me{flex:none;display:grid}\n.me>.av{grid-area:1/1;width:26px;height:26px;font-size:13px}\n/* Who you are, under the comment line; a name field eases open in its place. */\n.you{display:grid;padding:0 34px;min-height:24px;font-size:12px;color:var(--fa)}\n.you>*{grid-area:1/1;display:flex;align-items:center;min-width:0;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.say{white-space:pre;overflow:hidden}\n.nm{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.say button{flex:none}\n.say button{color:var(--mu);text-decoration:underline;text-decoration-color:var(--ln);text-underline-offset:2px;transition:color .2s var(--eo)}\n.say button:hover,.say button:focus-visible{color:var(--pu-accent);outline:none}\n.nf{opacity:0;transform:translateY(-4px);pointer-events:none}\n.nf .input{font-size:13px;height:24px}\n.you.naming .nf{opacity:1;transform:none;pointer-events:auto}\n.you.naming .say{opacity:0;pointer-events:none}\n.send{width:26px;height:26px;border-radius:50%;display:grid;place-items:center;color:var(--pu-accent);flex:none;opacity:0;pointer-events:none;\ntransition:opacity var(--in) var(--eo),background-color .2s var(--eo)}\n.send.show{opacity:1;pointer-events:auto}\n.send:hover{background:var(--as)}\n\n/* Bubbles, tips, popovers, marks, pulses. */\n.bub{position:fixed;left:0;top:0;width:20px;height:20px;margin:-20px 0 0 -2px;border-radius:50% 50% 50% 0;background:var(--pu-accent);\nborder:2px solid var(--su);box-shadow:0 1px 4px rgba(0,0,0,.2);pointer-events:auto;opacity:0;transform:translateY(-6px) scale(.9);transform-origin:2px 20px;\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.bub.in{opacity:1;transform:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.bub.in:hover,.bub.on{transform:scale(1.18)}\n.bub.done{background:var(--fa)}\n.bub.ghost{pointer-events:none}\n.tip,.pop,.menu,.all,.xp,.toast,.selbar,.namebar,.ttip,.tt,.mode,.rxp{background:var(--su);border:1px solid var(--ln);box-shadow:var(--sh)}\n.tip{position:fixed;max-width:260px;border-radius:10px;padding:7px 10px;opacity:0;transform:translateY(3px);\ntransition:opacity .22s var(--eo),transform .26s var(--eo)}\n.tip.show{opacity:1;transform:none;pointer-events:auto;cursor:pointer;\ntransition:opacity .22s var(--eo),transform .26s var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.pop{position:fixed;width:var(--pu-pop);border-radius:12px;padding:10px 12px 8px;pointer-events:none;opacity:0;transform:translateY(6px) scale(.98);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.pop.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n.pop.show.glide{transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.mark{position:fixed;border:2px solid color-mix(in srgb,var(--pu-accent) 50%,transparent);background:var(--as);border-radius:8px;opacity:0;\ntransition:opacity .3s var(--eo)}\n.mark.show{opacity:1}\n.pulse{position:fixed;border:2px solid var(--pu-accent);border-radius:8px;background:var(--as);animation:pu-pulse var(--pl) var(--eio) forwards}\n@keyframes pu-pulse{0%{opacity:0;transform:scale(.985)}35%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.02)}}\n\n/* Document column. */\n.col{position:fixed;left:0;top:0;pointer-events:none;transition:opacity var(--in) var(--eo)}\n.th{position:absolute;left:0;right:0;top:0;padding:4px 4px 4px 12px;background:var(--su);border-radius:8px;pointer-events:auto;cursor:pointer;box-shadow:inset 2px 0 0 transparent;\ntransition:transform var(--mv) var(--eio),box-shadow var(--in) var(--eo),opacity var(--in) var(--eo)}\n.th.hot{box-shadow:inset 2px 0 0 var(--ln)}\n.th.on{box-shadow:inset 2px 0 0 var(--pu-accent);cursor:default}\n.th.dim{opacity:.45}\n.th.resolved:not(.on):not(.hot){opacity:.6}\n.th.lost .ctx{white-space:normal}\n.th.wait{opacity:0!important;pointer-events:none}\n.th.out{opacity:0!important;pointer-events:none;transition:opacity var(--out) var(--ei)}\n/* A closed thread's button has no box of its own: the thread shows its focus. */\n.th:has(.opn:focus-visible){box-shadow:inset 2px 0 0 var(--ln);outline:2px solid var(--pu-accent);outline-offset:2px;border-radius:4px}\n\n/* Selection bar. */\n.selbar{position:fixed;display:flex;border-radius:10px;padding:2px;opacity:0;transform:translateY(4px);pointer-events:none;\ntransition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.selbar.show{opacity:1;transform:none;pointer-events:auto}\n.selbar button{width:32px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--pu-accent);transition:background-color .2s var(--eo)}\n.selbar button:hover,.selbar button:focus-visible{background:var(--as);outline:none}\n\n/* Comment mode's outline: glides between blocks; solid accent once chosen. */\n.pick{position:fixed;left:0;top:0;border:2px solid color-mix(in srgb,var(--pu-accent) 70%,transparent);background:color-mix(in srgb,var(--pu-accent) 6%,transparent);\nborder-radius:8px;pointer-events:none;opacity:0;transition:opacity var(--out) var(--ei),border-color var(--out) var(--ei),border-width var(--out) var(--ei),box-shadow var(--out) var(--ei)}\n.pick.show{opacity:1;transition-duration:var(--in);transition-timing-function:var(--eo)}\n.pick.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n.pick.on{border-color:var(--pu-accent)}\n/* The block cursor: its focus is drawn on the outline (3px accent with a surface halo, 3:1 on any page); the\nmarkers that hold focus are invisible. */\n.pick.kf{border:3px solid var(--pu-accent);box-shadow:0 0 0 2px var(--su)}\n.km{position:fixed;left:0;top:0;pointer-events:none;outline:none}\n.sr,.mn-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n.namebar{position:fixed;left:0;top:0;display:flex;align-items:center;gap:2px;padding:2px 2px 2px 10px;border-radius:10px;font-size:12px;color:var(--mu);\nwhite-space:nowrap;pointer-events:none;opacity:0;transform:translateY(4px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.namebar.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.namebar.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n.namebar .lbl{margin-right:6px;max-width:260px;overflow:hidden;text-overflow:ellipsis}\n.namebar .nb{padding:4px;display:grid;place-items:center;border-radius:7px;transition:background-color .2s var(--eo),color .2s var(--eo)}\n.namebar .nb:hover,.namebar .nb:focus-visible{background:var(--ho);color:var(--k);outline:none}\n.namebar .nb[hidden]{display:none}\n\n/* The comment control: one round button; the open count sits inside a comment bubble. Nothing about it\ngrows or slides: its layers and numbers cross-fade in place. */\n.launch{position:fixed;right:20px;bottom:20px;pointer-events:auto}\n.launch .mode{position:relative;display:grid;place-items:center;width:46px;height:46px;border-radius:50%;transition:background-color .3s var(--eo),color .3s var(--eo)}\n.mode>*,.cnt>*{grid-area:1/1}\n.mode>*{display:grid;place-items:center;transition:opacity var(--in) var(--eo)}\n.cnt,.has>.plus{opacity:0}\n.has>.cnt{opacity:1}\n.n{font-size:12px;font-weight:500;line-height:1;margin:-1.4px 0 0 1.4px;font-variant-numeric:tabular-nums;opacity:0;transition:opacity var(--in) var(--eo)}\n.n.s{font-size:9.5px;letter-spacing:-.04em}\n.n.on{opacity:1}\n.launch .mode:hover,.launch .mode[aria-expanded=true]{background:var(--ho)}\n.launch .mode.on{background:var(--pu-accent);color:var(--pu-on,#fff)}\n/* Open threads on other slides or views: a small dot at the button's top right, easing in and out. */\n.mode>.dot{position:absolute;top:3px;right:3px;width:9px;height:9px;border-radius:50%;background:var(--pu-accent);border:2px solid var(--su);opacity:0}\n.mode.else>.dot{opacity:1}\n/* The tooltip eases in after a moment, above the button, and never moves it. */\n.ttip{position:absolute;right:0;bottom:54px;white-space:nowrap;border-radius:8px;padding:4px 9px;font-size:12px;pointer-events:none;opacity:0;transform:translateY(3px);transition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.ttip small{margin-left:8px}\n.ttip small,.mi .kc{font-size:12px;color:var(--fa)}\n.mode:hover+.ttip,.mode:focus-visible+.ttip{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .5s,transform var(--in) var(--eo) .5s}\n.launch .mode[aria-expanded=true]+.ttip{opacity:0;transition:opacity var(--out) var(--ei)}\n@media (hover:none){.ttip,.tt{display:none}}\n.menu{position:fixed;right:20px;bottom:76px;width:290px;border-radius:12px;padding:4px;pointer-events:none;opacity:0;transform:translateY(6px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.menu.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n/* Menu rows: one line each; the explanation is a tooltip beside the menu that eases in after a moment. */\n.mi{position:relative;display:flex;gap:10px;align-items:center;width:100%;min-height:34px;text-align:left;padding:6px 10px;border-radius:8px;transition:background-color .2s var(--eo)}\n.mi:hover,.mi:focus-visible{background:var(--so);outline:none}\n.mi svg{color:var(--mu);flex:none}\n.mi small{display:block;color:var(--fa);font-size:12px}\n.lb{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ma{flex:none;display:grid;margin:-2px 0}\n.ma .av{width:20px;height:20px;font-size:11px}\n.mi .av svg{color:inherit}\n.sep{height:1px;margin:4px 10px;background:var(--ru)}\n.tt{position:absolute;right:calc(100% + 14px);top:50%;translate:0 -50%;width:max-content;max-width:220px;padding:4px 9px;border-radius:8px;font-size:12px;line-height:1.4;\ncolor:var(--mu);pointer-events:none;opacity:0;transform:translateX(3px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.mi:hover>.tt,.mi:focus-visible>.tt{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .5s,transform var(--in) var(--eo) .5s}\n@media (max-width:600px){.tt{right:8px;top:auto;bottom:100%;translate:none;transform:translateY(3px)}}\n/* Switches: a track and a knob that slides (cross-fades with reduced motion). */\n.sw{position:relative;flex:none;width:26px;height:16px;border-radius:8px;background:var(--ln);transition:background-color var(--mv) var(--eio)}\n.sw::before,.sw::after{content:\"\";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);\ntransition:transform var(--mv) var(--eio),opacity var(--mv) var(--eio)}\n.sw::before{opacity:0;transform:translateX(10px)}\n[aria-checked=true]>.sw{background:var(--pu-accent)}\n[aria-checked=true]>.sw::after{transform:translateX(10px)}\n.tools{display:flex;flex:none;gap:2px}\n.tools[hidden]{display:none}\n.tool[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.note{display:block;padding:0 0 4px;font-size:12px;color:var(--fa)}\n.note[hidden]{display:none}\n.ov{position:absolute;inset:0;pointer-events:none;overflow:hidden}\n/* An add-on's panel (.xp) is the same full-height panel as All comments (.all), with its own body. */\n.xb{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 16px 16px;font-size:13px}\n.xb p{margin:0 0 10px}\n/* All comments: a full-height panel on the right that slides in (fades, with reduced motion). */\n.all,.xp{position:fixed;top:0;right:0;bottom:0;width:var(--pu-panel);display:flex;flex-direction:column;border-width:0 0 0 1px;opacity:0;transform:translateX(100%);\ntransition:transform var(--out) var(--ei),opacity var(--out) var(--ei)}\n.all.show,.xp.show{opacity:1;transform:none;pointer-events:auto;transition:transform var(--mv) var(--eo),opacity var(--in) var(--eo)}\n.all.full{width:100%}\n.hd{display:flex;align-items:center;gap:8px;padding:12px 10px 8px 16px;font-weight:600}\n.pn{font-weight:400;color:var(--fa)}\n.hs{margin-left:auto;display:flex;align-items:center;gap:6px;padding:3px 4px 3px 6px;border-radius:6px;font-size:12px;font-weight:400;color:var(--mu);\ntransition:background-color .2s var(--eo)}\n.hs:hover,.hs:focus-visible{background:var(--ho);outline:none}\n.list{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px}\n.all .mi{align-items:flex-start}\n.all .mi>.av{flex:none}\n.all .mi>span:last-child{flex:1;min-width:0}\n.all .mi small{white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.all .mi.done{opacity:.6}\n.all .mi.open{background:var(--so)}\n.all .mi.open>.av,.all .mi.open .clamp{display:none}\n.xr{padding:2px 12px 10px 16px}\n/* The line from an open thread in the panel to its place on the page. */\n.cx{position:fixed;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;opacity:0;transition:opacity var(--in) var(--eo)}\n.cx.show{opacity:1}\n.cx path{fill:none;stroke:var(--pu-accent);stroke-width:1.5;stroke-linecap:round;opacity:.7}\n.cx circle{fill:var(--pu-accent)}\n.layer.listing .col{opacity:0;transition:opacity var(--out) var(--ei)}\n.sec{padding:8px 10px 2px;font-size:12px;color:var(--fa)}\n.ag{display:flex;align-items:center;gap:8px;padding:6px 14px;font-size:12px;color:var(--fa);border-bottom:1px solid var(--ln)}\n.ag[hidden]{display:none}\n.lns{display:flex;flex-direction:column}\n.ln{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.ln.show{grid-template-rows:1fr;opacity:1}\n.ln>.lw{overflow:hidden;min-height:0}\n.ag button{margin-left:auto;flex:none;padding:0 6px;border-radius:6px;color:var(--fa);transition:color .2s var(--eo),background-color .2s var(--eo)}.ag button:hover:not(:disabled),.ag button:focus-visible{color:var(--pu-accent);background:var(--as);outline:none}.ag button:disabled{opacity:.5;cursor:default}\n.adr{margin:8px 0 0 14px;padding:8px 10px;border-radius:8px;background:var(--so);font-size:13px;color:var(--k);animation:pu-in var(--mv) var(--eo) both}\n.adr small{display:block;font-size:12px;color:var(--fa)}\n.adr .go{display:flex;gap:6px;margin-top:6px}\n.adr .go button{padding:2px 8px;border-radius:6px;font-size:12px;color:var(--mu);transition:color .2s var(--eo),background-color .2s var(--eo)}.adr .go button:hover,.adr .go button:focus-visible{color:var(--pu-accent);background:var(--as);outline:none}\n@keyframes pu-in{0%{opacity:0;transform:translateY(3px)}100%{opacity:1;transform:none}}\n.sec b{margin-left:6px;font-weight:500;color:var(--pu-accent)}\n.toast{position:fixed;left:50%;bottom:28px;border-radius:10px;padding:8px 14px;font-size:13px;opacity:0;transform:translate(-50%,6px);\ntransition:opacity .3s var(--eo),transform .36s var(--eo)}\n.toast.show{opacity:1;transform:translate(-50%,0)}\n\n/* Touch: fingers need bigger targets than pointers (44 px for the menu's rows, 36 and more for buttons). */\n@media (pointer:coarse){\n.mi{min-height:44px}\n.ib{min-width:36px;min-height:36px}\n.rxo{min-width:40px;min-height:40px}\n.refs .ref{min-height:34px}\n.mnl li{min-height:40px}\n.dlg-btn,.hs{min-height:40px}\n.send{min-width:36px;min-height:36px}\n}\n\n@media (forced-colors: active){\n.pick.kf{border:3px solid Highlight}\n.layer :is(.ib,.mi,.nb,.hs,.selbar button,.say button,.xb button):focus-visible{outline:2px solid Highlight}\n}\n\n@media (prefers-reduced-motion: reduce){\n.ln{transition-property:opacity}\n@keyframes pu-in{0%{opacity:0}100%{opacity:1}}\n.bub,.bub.in,.bub.in:hover,.bub.on,.tip,.pop,.selbar,.menu,.all,.xp,.ttip,.tt,.toast,.ref .rc,.rxp,.mnl{transform:none!important}\n.dlg{transform:translate(-50%,0)!important}\n.sw::after{transform:none!important;transition-property:opacity}\n[aria-checked=true]>.sw::after{opacity:0}\n[aria-checked=true]>.sw::before{opacity:1}\n.th{transition-property:opacity,box-shadow}\n.tip.show{transition-property:opacity}\n.pick,.pick.show{transition:opacity .16s ease-in-out}\n.all,.all.show,.xp,.xp.show{transition-property:opacity}\n.namebar,.namebar.show{transform:none!important;transition:opacity .16s ease-in-out}\n.av,.nf{transform:none!important}\n@keyframes pu-pulse{0%{opacity:0}35%{opacity:.85}100%{opacity:0}}\n}\n";
|
|
2
|
+
export declare const STYLES = "\n/* Inherited page styles are reset on .layer below; custom properties pass through all:initial. */\n:host{all:initial;direction:ltr;unicode-bidi:normal}\n*{box-sizing:border-box}\nbutton{appearance:none;font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}\nsvg{display:block}\n.layer{all:initial;direction:ltr;unicode-bidi:normal;display:block;position:fixed;inset:0;pointer-events:none;font:13px/1.5 var(--pu-font,system-ui,sans-serif);color:var(--k);\n--k:#2C2C2A;--mu:#5F5E5A;--fa:#6B6A64;--ln:#E5E3DA;--ru:#ECEAE2;--so:#FAFAF7;--su:#FFFFFF;--ho:#F1EFE8;\n--as:color-mix(in srgb,var(--pu-accent,#534AB7) 12%,transparent);\n--sh:0 8px 28px rgba(44,44,42,.10);\n--in:.26s;--mv:.34s;--out:.2s;--pl:1.2s;\n--eo:cubic-bezier(.22,.61,.36,1);--eio:cubic-bezier(.4,0,.2,1);--ei:cubic-bezier(.4,0,1,1);\n--pu-text:var(--k);--pu-muted:var(--mu);--pu-faint:var(--fa);--pu-line:var(--ln);--pu-surface:var(--su);--pu-soft:var(--so);--pu-hover:var(--ho);--pu-shadow:var(--sh);--pu-ease:var(--eo)}\n.layer{transition:opacity .24s var(--eo)}.layer.sw{opacity:0;transition-duration:.16s;transition-timing-function:var(--ei)}\n.layer.dark{--k:#ECEBE6;--mu:#B4B2A9;--fa:#9A9892;--ln:#3A3936;--ru:#34332F;--so:#22221F;--su:#1B1B19;--ho:#2C2C29;--sh:0 8px 28px rgba(0,0,0,.45)}\n.layer.hidden .bub,.layer.hidden .col,.layer.hidden .pop,.layer.hidden .tip,.layer.hidden .mark,.layer.hidden .selbar{opacity:0!important;pointer-events:none!important}\n\n.tx{font-size:14px;line-height:1.5;color:var(--k);white-space:pre-wrap;overflow-wrap:anywhere}\n.tx.del,.rest,.ctx,.ago{color:var(--fa)}\n.rest,.ago{font-size:12px}\n.rest{display:block;margin-top:3px}\n/* A card's top line: avatar, who (cut short on one line, never wrapped), how long ago, then its actions. */\n.hdr{position:relative;display:flex;align-items:center;gap:7px;min-height:22px}\n.who{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-weight:600;color:var(--k)}\n.ago{flex:none;white-space:nowrap}\n.ago::before{content:\"\u00B7\";margin-right:6px}\n.root>.tx,.it>.tx,.root>.ctx{margin-top:2px}\n.ctx[hidden]{display:none}\n.ctx{font-size:12px;margin-bottom:3px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.cd>.thread .tx{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}\n.tx a{color:var(--pu-accent);text-decoration:underline;text-decoration-thickness:1px;text-underline-offset:2px}\n\n/* Actions sit at the card's top right: always on an open card, on hover (or focus) on one at rest. In All comments a\nclosed card keeps them while its \u22EF menu is open, and focus put there for the keyboard (not a click) shows them. */\n.acts{margin-left:auto;display:flex;flex:none;transition:opacity var(--in) var(--eo)}\n.th:not(.on):not(:hover):not(:focus-within) .acts,.cd:not(.open):not(:hover):not(:has(:focus-visible,.pm)) .acts{opacity:0}\n.th.on .rest{display:none}\n/* A comment's \u22EF menu: Copy thread, Edit, Delete (asked twice). */\n.pm{position:absolute;right:0;top:100%;z-index:5;display:flex;flex-direction:column;min-width:150px;padding:4px;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh);animation:pu-in var(--in) var(--eo) both}\n.pm button{padding:6px 10px;border-radius:7px;text-align:left;font-size:13px;transition:background-color .2s var(--eo)}\n.pm button:hover,.pm button:focus-visible{background:var(--ho);outline:none}\n.pm .dl{color:#C9402F}.dark .pm .dl{color:#F08A7E}\n.edit{margin-top:2px}\n.ib{width:24px;height:22px;display:grid;place-items:center;border-radius:6px;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.ib:hover,.ib:focus-visible{background:var(--ho);color:var(--k);outline:none}\n\n/* Replies: one level in, oldest first; the reply line ends the thread at the same indent. */\n.rps,.rbox{padding-left:14px}\n.rps .it{padding-top:8px}\n.more{display:grid;grid-template-rows:1fr;transition:grid-template-rows var(--mv) var(--eio)}\n.more>div{overflow:hidden;min-height:0}\n.th:not(.on) .more{grid-template-rows:0fr}\n\n/* Writing boxes: a rounded box that says what it's for, then Cancel and Send (named) while it is in use. */\n.row{position:relative;padding-top:6px}\n.line{display:flex;align-items:center;gap:6px;padding:3px 12px;border:1px solid var(--ln);border-radius:16px;cursor:text;transition:border-color var(--in) var(--eo),box-shadow var(--in) var(--eo)}\n.line:hover{border-color:var(--mu)}\n.line:focus-within{border-color:var(--pu-accent);box-shadow:0 0 0 1px var(--pu-accent)}\n.input{flex:1;min-width:0;height:24px;display:block;border:0;outline:none;resize:none;overflow:hidden;\nfont:inherit;font-size:14px;line-height:1.5;padding:1px 0;color:var(--k);background:transparent}\n.input::placeholder{color:var(--fa);opacity:1}\n.bts{display:flex;justify-content:flex-end;gap:4px;max-height:0;opacity:0;overflow:hidden;transition:max-height var(--in) var(--eo),opacity var(--in) var(--eo),padding var(--in) var(--eo)}\n.row:focus-within .bts,.row.has .bts{max-height:40px;opacity:1;padding-top:4px}\n.bts button{padding:2px 10px;border-radius:14px;font-size:13px;font-weight:600;color:var(--pu-accent);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.cnl:hover,.cnl:focus-visible{background:var(--as);outline:none}\n.send{background:var(--pu-accent);color:var(--pu-on,#fff)!important}\n.send:not(.show){background:var(--ru);color:var(--fa)!important;cursor:default}\n.ed{display:flex;gap:10px;align-items:center;min-height:34px;padding:6px 10px}\n.ed .input,.nf .input{font-size:13px;height:22px;border-bottom:1px solid var(--ln)}\n.ed .input:focus,.nf .input:focus{border-bottom-color:var(--pu-accent)}\n\n/* Avatars: a squircle with the writer's animal (or initial) on a soft colour, at the start of the card's top line. */\n.av{flex:none;display:grid;place-items:center;width:22px;height:22px;border-radius:32%;\nfont-size:12px;font-weight:600;line-height:1;opacity:0;transform:scale(.85);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.av.in{opacity:1;transform:none}\n/* The animal nearly fills its tint (its drawing has room round it in its 24 grid), in a lighter line so it stays thin. */\n.av svg{width:122%;height:122%;stroke-width:1.3}\n/* Ten colours (.c0 Red to .c9 Grey, as COLOURS): a soft tint and a dark drawing, swapped round on dark pages. */\n.av{--av-l:92%;--av-d:30%;--s:60%;background:hsl(var(--h) var(--s) var(--av-l));color:hsl(var(--h) var(--s) var(--av-d))}\n.dark .av{--av-l:20%;--av-d:78%}\n/* An AI's reply: a plain disc with a violet ring, all inside the avatar's own box so nothing is cropped. */\n.av.ai{position:relative;border-radius:50%;background:var(--su);color:var(--pu-accent);font-size:9px;letter-spacing:.02em}\n.av.ai::before{content:\"\";position:absolute;inset:3px;border-radius:50%;border:1.5px solid var(--pu-accent);pointer-events:none}\n.refs{display:flex;flex-wrap:wrap;gap:4px;margin-top:6px;white-space:normal}\n.refs .ref{display:inline-flex;align-items:center;gap:5px;max-width:160px;padding:1px 9px;border:1px solid var(--ln);border-radius:999px;background:var(--so);color:var(--mu);font:inherit;font-size:11.5px;line-height:1.6;text-decoration:none;cursor:pointer;transition:background-color .2s var(--eo),color .2s var(--eo),border-color .2s var(--eo)}\n.refs .ref:hover,.refs .ref:focus-visible{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent);outline:none}\n.ref span{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}\n.rxp{position:fixed;width:320px;height:340px;border-radius:12px;overflow:hidden;pointer-events:none;opacity:0;transform:translateY(4px);transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.rxp.show{opacity:1;transform:none;pointer-events:auto}\n.mn{border-radius:4px;padding:0 2px;background:var(--as);color:var(--pu-accent)}\n.mn.me{font-weight:600}\n.mnl{position:absolute;left:0;bottom:100%;margin:0 0 4px;padding:4px;list-style:none;min-width:180px;max-width:100%;border:1px solid var(--ln);border-radius:10px;background:var(--su);box-shadow:var(--sh);opacity:0;transform:translateY(4px);pointer-events:none;z-index:4;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.mnl.show{opacity:1;transform:none;pointer-events:auto}\n.mnl li{display:flex;align-items:baseline;gap:8px;padding:5px 8px;border-radius:6px;font-size:13px;color:var(--k);cursor:pointer}\n.mnl li small{font-size:11px;color:var(--fa)}\n.mnl li.on,.mnl li:hover{background:var(--as);color:var(--pu-accent)}\n.dlg{position:fixed;left:50%;top:18vh;width:min(380px,calc(100vw - 32px));padding:16px 18px;border:1px solid var(--ln);border-radius:14px;background:var(--su);box-shadow:var(--sh);color:var(--k);opacity:0;transform:translate(-50%,6px);pointer-events:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.dlg.show{opacity:1;transform:translate(-50%,0);pointer-events:auto}\n.toast.act{pointer-events:auto}\n.ta{margin-left:4px;color:var(--pu-accent);text-decoration:underline;text-underline-offset:2px}\n.rx .n{font-size:11px}\n.rx.mine{background:var(--as);color:var(--pu-accent);border-color:var(--pu-accent)}\n.rx:disabled{cursor:default;opacity:.7}\n.rx.new,.rxq.new{animation:pu-in var(--mv) var(--eo) both}\n.rxs{align-items:center}\n.rxq{display:inline-flex;gap:2px}\n.rxo{padding:2px 5px;border-radius:8px;font-size:16px;line-height:1.3;transition:background-color .2s var(--eo)}\n.rxo:hover,.rxo:focus-visible,.rxo[aria-pressed=true]{background:var(--as);outline:none}\n.refs .ref{position:relative}.ref .rc{position:absolute;left:0;top:calc(100% + 6px);z-index:3;width:max-content;max-width:min(240px,70vw);padding:6px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);color:var(--k);font-size:12px;line-height:1.45;white-space:normal;text-align:left;overflow:visible;opacity:0;visibility:hidden;transform:translateY(-3px);pointer-events:none;transition:opacity .2s var(--eo),transform .2s var(--eo),visibility 0s .2s}.ref:hover .rc,.ref:focus-visible .rc{opacity:1;visibility:visible;transform:none;transition-delay:0s}\n.ref .sl{width:10px;height:7px;border:1.3px solid currentColor;border-radius:2px;flex:none}\n.seen{display:flex;align-items:center;gap:6px;padding:6px 0 0 14px;font-size:12px;color:var(--fa)}\n.seen button{margin-left:auto;padding:0 6px;border:0;border-radius:6px;background:none;color:var(--fa);font:inherit;cursor:pointer;transition:color .2s var(--eo),background-color .2s var(--eo)}.seen button:hover,.seen button:focus-visible{color:var(--pu-accent);background:var(--as);outline:none}\n.seen i{width:12px;height:12px;border-radius:50%;border:1.5px solid var(--pu-accent);flex:none}\n.c0{--h:0}.c1{--h:25}.c2{--h:50}.c3{--h:130}.c4{--h:175}.c5{--h:215}.c6{--h:270}.c7{--h:330}.c8{--h:28;--s:35%}.c9{--h:220;--s:8%}\nbutton.me{flex:none;display:grid}\nbutton.me>.av{grid-area:1/1}\n/* Who you are, at the top of a new comment; a name field eases open in its place. */\n.you{flex:1;display:grid;min-width:0;min-height:22px;font-size:12px;color:var(--fa)}\n.you .nm{font-size:13px;font-weight:600;color:var(--k)}\n.you>*{grid-area:1/1;display:flex;align-items:center;min-width:0;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.say{white-space:pre;overflow:hidden}\n.nm{min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.say button{flex:none}\n.say button{color:var(--mu);text-decoration:underline;text-decoration-color:var(--ln);text-underline-offset:2px;transition:color .2s var(--eo)}\n.say button:hover,.say button:focus-visible{color:var(--pu-accent);outline:none}\n.nf{opacity:0;transform:translateY(-4px);pointer-events:none}\n.nf .input{font-size:13px;height:24px}\n.you.naming .nf{opacity:1;transform:none;pointer-events:auto}\n.you.naming .say{opacity:0;pointer-events:none}\n\n/* Bubbles, tips, popovers, marks, pulses. */\n.bub{position:fixed;left:0;top:0;width:20px;height:20px;margin:-20px 0 0 -2px;border-radius:50% 50% 50% 0;background:var(--pu-accent);\nborder:2px solid var(--su);box-shadow:0 1px 4px rgba(0,0,0,.2);pointer-events:auto;opacity:0;transform:translateY(-6px) scale(.9);transform-origin:2px 20px;\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.bub.in{opacity:1;transform:none;transition:opacity var(--in) var(--eo),transform var(--in) var(--eo)}\n.bub.in:hover,.bub.on{transform:scale(1.18)}\n.bub.done{background:var(--fa)}\n.bub.ghost{pointer-events:none}\n.tip,.pop,.menu,.all,.xp,.toast,.selbar,.namebar,.tt,.rxp{background:var(--su);border:1px solid var(--ln);box-shadow:var(--sh)}\n.tip{position:fixed;max-width:260px;border-radius:10px;padding:7px 10px;opacity:0;transform:translateY(3px);\ntransition:opacity .22s var(--eo),transform .26s var(--eo)}\n.tip.show{opacity:1;transform:none;pointer-events:auto;cursor:pointer;\ntransition:opacity .22s var(--eo),transform .26s var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.pop{position:fixed;width:var(--pu-pop);border-radius:12px;padding:8px 10px 10px;pointer-events:none;opacity:0;transform:translateY(6px) scale(.98);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.pop.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n.pop.show.glide{transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),left var(--mv) var(--eio),top var(--mv) var(--eio)}\n.mark{position:fixed;border:2px solid color-mix(in srgb,var(--pu-accent) 50%,transparent);background:var(--as);border-radius:8px;opacity:0;\ntransition:opacity .3s var(--eo)}\n.mark.show{opacity:1}\n.pulse{position:fixed;border:2px solid var(--pu-accent);border-radius:8px;background:var(--as);animation:pu-pulse var(--pl) var(--eio) forwards}\n@keyframes pu-pulse{0%{opacity:0;transform:scale(.985)}35%{opacity:.85;transform:scale(1)}100%{opacity:0;transform:scale(1.02)}}\n\n/* Document column. */\n.col{position:fixed;left:0;top:0;pointer-events:none;transition:opacity var(--in) var(--eo)}\n/* Each thread is a compact card; the open one lifts with a soft shadow. */\n.th{position:absolute;left:0;right:0;top:0;padding:8px 10px 10px;background:var(--su);border:1px solid var(--ln);border-radius:10px;pointer-events:auto;cursor:pointer;\ntransition:transform var(--mv) var(--eio),box-shadow var(--in) var(--eo),border-color var(--in) var(--eo),opacity var(--in) var(--eo)}\n.th.hot{border-color:var(--mu)}\n.th.on{border-color:transparent;box-shadow:var(--sh);cursor:default}\n.th.dim{opacity:.45}\n.th.resolved:not(.on):not(.hot){opacity:.6}\n.th.lost .ctx{white-space:normal}\n.th.wait{opacity:0!important;pointer-events:none}\n.th.out{opacity:0!important;pointer-events:none;transition:opacity var(--out) var(--ei)}\n/* A closed thread's button has no box of its own: the thread shows its focus. */\n.th:has(.opn:focus-visible){outline:2px solid var(--pu-accent);outline-offset:2px}\n\n/* Selection bar. */\n.selbar{position:fixed;display:flex;border-radius:10px;padding:2px;opacity:0;transform:translateY(4px);pointer-events:none;\ntransition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.selbar.show{opacity:1;transform:none;pointer-events:auto}\n.selbar button{width:32px;height:30px;display:grid;place-items:center;border-radius:8px;color:var(--pu-accent);transition:background-color .2s var(--eo)}\n.selbar button:hover,.selbar button:focus-visible{background:var(--as);outline:none}\n\n/* Comment mode's outline: glides between blocks; solid accent once chosen. */\n.pick{position:fixed;left:0;top:0;border:2px solid color-mix(in srgb,var(--pu-accent) 70%,transparent);background:color-mix(in srgb,var(--pu-accent) 6%,transparent);\nborder-radius:8px;pointer-events:none;opacity:0;transition:opacity var(--out) var(--ei),border-color var(--out) var(--ei),border-width var(--out) var(--ei),box-shadow var(--out) var(--ei)}\n.pick.show{opacity:1;transition-duration:var(--in);transition-timing-function:var(--eo)}\n.pick.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n.pick.on{border-color:var(--pu-accent)}\n/* The block cursor: its focus is drawn on the outline (3px accent with a surface halo, 3:1 on any page); the\nmarkers that hold focus are invisible. */\n.pick.kf{border:3px solid var(--pu-accent);box-shadow:0 0 0 2px var(--su)}\n.km{position:fixed;left:0;top:0;pointer-events:none;outline:none}\n.sr,.mn-sr{position:absolute;width:1px;height:1px;overflow:hidden;clip-path:inset(50%);white-space:nowrap}\n.namebar{position:fixed;left:0;top:0;display:flex;align-items:center;gap:2px;padding:2px 2px 2px 10px;border-radius:10px;font-size:12px;color:var(--mu);\nwhite-space:nowrap;pointer-events:none;opacity:0;transform:translateY(4px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.namebar.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform .3s var(--eo)}\n.namebar.show.glide{transition-property:all;transition-duration:var(--mv);transition-timing-function:var(--eio)}\n.namebar .lbl{margin-right:6px;max-width:260px;overflow:hidden;text-overflow:ellipsis}\n.namebar .nb{padding:4px;display:grid;place-items:center;border-radius:7px;transition:background-color .2s var(--eo),color .2s var(--eo)}\n.namebar .nb:hover,.namebar .nb:focus-visible{background:var(--ho);color:var(--k);outline:none}\n.namebar .nb[hidden]{display:none}\n\n/* The comment control: a small square of frosted glass tucked into the page's corner (flush right and bottom, its\ntop left rounded), with the open count inside a comment bubble. Pointed at, it reaches left just far enough to show\nits shortcut (and anything add-ons say). Its layers and numbers cross-fade in place. */\n.launch{position:fixed;right:0;bottom:0;display:flex;flex-direction:row-reverse;align-items:center;border-top-left-radius:10px;pointer-events:auto;transform-origin:100% 100%;\nbackground:color-mix(in srgb,var(--su) 62%,transparent);-webkit-backdrop-filter:blur(10px) saturate(1.5);backdrop-filter:blur(10px) saturate(1.5);\ntransition:opacity var(--in) var(--eo),transform var(--mv) var(--eo),background-color .3s var(--eo),color .3s var(--eo)}\n.launch:has(.mode.on){background:color-mix(in srgb,var(--pu-accent) 90%,transparent);color:var(--pu-on,#fff)}\n/* While All comments is open, the control is the panel's footer: it draws in, and the footer takes its place. */\n.layer.listing .launch{opacity:0;transform:scale(.6);pointer-events:none}\n.layer.listing .menu{right:8px;bottom:60px;z-index:1}\n.layer.listing .menu :is([data-item=comment],[data-item=all]){display:none}\n.launch .mode{position:relative;display:grid;place-items:center;width:32px;height:32px;border-radius:10px 0 0}\n.mode>*,.cnt>*{grid-area:1/1}\n.mode>*{display:grid;place-items:center;transition:opacity var(--in) var(--eo)}\n.cnt,.has>.plus{opacity:0}\n.has>.cnt{opacity:1}\n.n{font-size:11px;font-weight:500;line-height:1;margin:-1.2px 0 0 1.2px;font-variant-numeric:tabular-nums;opacity:0;transition:opacity var(--in) var(--eo)}\n.n.s{font-size:8.5px;letter-spacing:-.04em}\n.n.on{opacity:1}\n.launch .mode:focus-visible{outline:2px solid var(--pu-accent);outline-offset:-2px}\n/* Open threads on other slides or views: a small dot at the bubble's top right, easing in and out. */\n.mode>.dot{position:absolute;top:2px;right:2px;width:8px;height:8px;border-radius:50%;background:var(--pu-accent);opacity:0}\n.mode.else>.dot{opacity:1}\n/* What it reaches out to show when pointed at: the shortcut, after anything add-ons say. Its width eases to exactly what\nthe words need (a 0fr to 1fr column), so it opens and folds evenly, and it folds at once when the pointer leaves. */\n.ttip{display:grid;grid-template-columns:minmax(0,0fr);overflow:hidden;font-size:12px;color:var(--mu);pointer-events:none;opacity:0;transition:grid-template-columns var(--out) var(--ei),opacity var(--out) var(--ei)}\n.ttip>span{min-width:0;white-space:nowrap;padding-left:10px}\n.ttip small{font-size:12px}\n.ttip small,.mi .kc{color:var(--fa)}\n.launch:has(.mode.on) :is(.ttip,.ttip small){color:inherit}\n.launch:hover .ttip{grid-template-columns:minmax(0,1fr);opacity:1;transition:grid-template-columns var(--mv) var(--eo) .4s,opacity var(--in) var(--eo) .4s}\n.launch .mode[aria-expanded=true]+.ttip{grid-template-columns:minmax(0,0fr);opacity:0}\n@media (hover:none){.ttip,.tt,.cd>.thread .acts{display:none}}\n.menu{position:fixed;right:8px;bottom:40px;width:290px;border-radius:12px;padding:4px;pointer-events:none;opacity:0;transform:translateY(6px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.menu.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--in) var(--eo),transform var(--mv) var(--eo)}\n/* Menu rows: one line each; the explanation is a tooltip beside the menu that eases in after a moment. */\n.mi{position:relative;display:flex;gap:10px;align-items:center;width:100%;min-height:34px;text-align:left;padding:6px 10px;border-radius:8px;transition:background-color .2s var(--eo)}\n.mi:hover,.mi:focus-visible{background:var(--so);outline:none}\n.mi svg{color:var(--mu);flex:none}\n.mi small{display:block;color:var(--fa);font-size:12px}\n.lb{flex:1;min-width:0;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}\n.ma{flex:none;display:grid;margin:-2px 0}\n.ma .av{width:20px;height:20px;font-size:11px}\n.mi .av svg{color:inherit}\n.sep{height:1px;margin:4px 10px;background:var(--ru)}\n/* Copy comments opens to its two choices beneath it, set in under it; folding and unfolding ease. */\n.subs{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.subs.open{grid-template-rows:1fr;opacity:1}\n.subs>div{min-height:0;overflow:hidden}\n.subs .mi{padding-left:30px}\n.chev{display:grid;transition:transform var(--in) var(--eo)}\n[aria-expanded=true]>.chev{transform:rotate(90deg)}\n.tt{position:absolute;right:calc(100% + 14px);top:50%;translate:0 -50%;width:max-content;max-width:220px;padding:4px 9px;border-radius:8px;font-size:12px;line-height:1.4;\ncolor:var(--mu);pointer-events:none;opacity:0;transform:translateX(3px);\ntransition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.mi:hover>.tt,.mi:focus-visible>.tt{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .5s,transform var(--in) var(--eo) .5s}\n@media (max-width:600px){.tt{right:8px;top:auto;bottom:100%;translate:none;transform:translateY(3px)}}\n/* Switches: a track and a knob that slides (cross-fades with reduced motion). */\n.sw{position:relative;flex:none;width:26px;height:16px;border-radius:8px;background:var(--ln);transition:background-color var(--mv) var(--eio)}\n.sw::before,.sw::after{content:\"\";position:absolute;top:2px;left:2px;width:12px;height:12px;border-radius:50%;background:#fff;box-shadow:0 1px 2px rgba(0,0,0,.25);\ntransition:transform var(--mv) var(--eio),opacity var(--mv) var(--eio)}\n.sw::before{opacity:0;transform:translateX(10px)}\n[aria-checked=true]>.sw{background:var(--pu-accent)}\n[aria-checked=true]>.sw::after{transform:translateX(10px)}\n.tools{display:flex;flex:none;gap:2px}\n.tools[hidden]{display:none}\n.tool[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.note{display:block;padding:0 0 4px;font-size:12px;color:var(--fa)}\n.note[hidden]{display:none}\n.ov{position:absolute;inset:0;pointer-events:none;overflow:hidden}\n/* An add-on's panel (.xp) is the same full-height panel as All comments (.all), with its own body. */\n.xb{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 16px 16px;font-size:13px}\n.xb p{margin:0 0 10px}\n/* All comments: a full-height panel on the right that slides in (fades, with reduced motion). */\n.all,.xp{position:fixed;top:0;right:0;bottom:0;width:var(--pu-panel);display:flex;flex-direction:column;border-width:0 0 0 1px;opacity:0;transform:translateX(100%);\ntransition:transform var(--out) var(--ei),opacity var(--out) var(--ei)}\n.all.show,.xp.show{opacity:1;transform:none;pointer-events:auto;transition:transform var(--mv) var(--eo),opacity var(--in) var(--eo)}\n.all.full{width:100%}\n/* The header: no title, two filters (an icon and a word in a pill: grey off, a soft accent fill on) and Close. */\n.hd{display:flex;align-items:center;gap:4px;padding:8px 8px 6px}\n.sp{flex:1}\n.tg{position:relative;display:flex;align-items:center;gap:5px;height:28px;padding:0 11px 0 9px;border-radius:99px;white-space:nowrap;line-height:1;color:var(--mu);transition:background-color .2s var(--eo),color .2s var(--eo)}\n.tg:hover{background:var(--ho);color:var(--k)}\n.tg[aria-pressed=true]{background:var(--as);color:var(--pu-accent)}\n.tg[aria-pressed=true]:hover{background:color-mix(in srgb,var(--pu-accent) 20%,transparent)}\n.tg:focus-visible{outline:2px solid var(--pu-accent);outline-offset:1px}\n/* What each filter does: a tooltip under it that eases in after a moment, on hover or focus. */\n.tg::after{content:attr(data-tip);position:absolute;left:0;top:calc(100% + 4px);z-index:3;width:max-content;max-width:220px;padding:4px 9px;border:1px solid var(--ln);border-radius:8px;background:var(--su);box-shadow:var(--sh);font-size:12px;line-height:1.4;color:var(--mu);pointer-events:none;opacity:0;transform:translateY(-3px);transition:opacity var(--out) var(--ei),transform var(--out) var(--ei)}\n.tg:hover::after,.tg:focus-visible::after{opacity:1;transform:none;transition:opacity var(--in) var(--eo) .4s,transform var(--in) var(--eo) .4s}\n.list{flex:1;overflow-y:auto;overscroll-behavior:contain;padding:4px 8px 8px;background:var(--so)}\n/* Threads in the panel are the same cards; opened, a card shows the thread beneath the words it's about. */\n.cd{position:relative;margin-top:6px;background:var(--su);border:1px solid var(--ln);border-radius:10px;transition:box-shadow var(--in) var(--eo),border-color var(--in) var(--eo),background-color .2s var(--eo)}\n.cd.open{border-color:transparent;box-shadow:var(--sh)}\n.cd.done{opacity:.6}\n/* Closed, its button lies over it (choosing the card opens it), beneath its actions and what they open. */\n.cd>.mi{position:absolute;inset:0;border-radius:10px;background:none}\n.cd>.thread :is(.acts,.refs,.edit){position:relative;z-index:1}\n.cd:not(.open,.new):is(:hover,:has(>.mi:focus-visible)){background:var(--so)}\n/* Resolved from its actions, it fades and folds away. */\n.cd.out{opacity:0;margin-top:0;border-width:0;overflow:hidden;transition:height var(--mv) var(--eio),margin var(--mv) var(--eio),border-width var(--mv) var(--eio),opacity var(--out) var(--ei)}\n.cd.open>.mi{display:none}\n.cd.open .root>.hdr{cursor:pointer}\n.cd.new,.xr,.cd>.thread{padding:8px 10px 10px}\n/* The footer: who you are, Comment (its shortcut and switch), and \u22EF for the menu. */\n.pf{display:flex;align-items:center;gap:8px;min-height:52px;padding:0 8px 0 14px;border-top:1px solid var(--ln)}\n.fs{display:flex;align-items:center;gap:6px;padding:4px 6px;border-radius:8px;font-size:13px;transition:background-color .2s var(--eo)}\n.fs:hover,.fs:focus-visible{background:var(--ho);outline:none}\n.fs small{font-size:12px;color:var(--fa)}\n.pf .ib{width:30px;height:30px}\n/* The line from an open thread in the panel to its place on the page. */\n.cx{position:fixed;inset:0;width:100%;height:100%;overflow:visible;pointer-events:none;opacity:0;transition:opacity var(--in) var(--eo)}\n.cx.show{opacity:1}\n.cx path{fill:none;stroke:var(--pu-accent);stroke-width:1.5;stroke-linecap:round;opacity:.7}\n.cx circle{fill:var(--pu-accent)}\n.layer.listing .col{opacity:0;transition:opacity var(--out) var(--ei)}\n.sec{padding:8px 10px 2px;font-size:12px;color:var(--fa)}\n.ag{display:flex;align-items:center;gap:8px;padding:6px 14px;font-size:12px;color:var(--fa);border-bottom:1px solid var(--ln)}\n.ag[hidden]{display:none}\n.lns{display:flex;flex-direction:column}\n.ln{display:grid;grid-template-rows:0fr;opacity:0;transition:grid-template-rows var(--in) var(--eo),opacity var(--in) var(--eo)}\n.ln.show{grid-template-rows:1fr;opacity:1}\n.ln>.lw{overflow:hidden;min-height:0}\n.ag button{margin-left:auto;flex:none;padding:0 6px;border-radius:6px;color:var(--fa);transition:color .2s var(--eo),background-color .2s var(--eo)}.ag button:hover:not(:disabled),.ag button:focus-visible{color:var(--pu-accent);background:var(--as);outline:none}.ag button:disabled{opacity:.5;cursor:default}\n.adr{margin:8px 0 0 14px;padding:8px 10px;border-radius:8px;background:var(--so);font-size:13px;color:var(--k);animation:pu-in var(--mv) var(--eo) both}\n.adr small{display:block;font-size:12px;color:var(--fa)}\n.adr .go{display:flex;gap:6px;margin-top:6px}\n.adr .go button{padding:2px 8px;border-radius:6px;font-size:12px;color:var(--mu);transition:color .2s var(--eo),background-color .2s var(--eo)}.adr .go button:hover,.adr .go button:focus-visible{color:var(--pu-accent);background:var(--as);outline:none}\n@keyframes pu-in{0%{opacity:0;transform:translateY(3px)}100%{opacity:1;transform:none}}\n.sec b{margin-left:6px;font-weight:500;color:var(--pu-accent)}\n/* Messages sit beside the comment control, never over the page's own bottom bar; beside the panel while it is open,\nand above its footer when it fills the screen. */\n.toast{--r:40px;position:fixed;right:var(--r);bottom:4px;max-width:min(320px,calc(100vw - var(--r) - 16px));border-radius:10px;padding:8px 14px;font-size:13px;opacity:0;transform:translateY(6px);transition:.3s var(--eo)}\n.toast.show{opacity:1;transform:none}\n.layer:is(.listing,:has(.xp.show)) .toast{--r:calc(var(--pu-panel) + 16px)}\n@media (max-width:480px){.layer:is(.listing,:has(.xp.show)) .toast{--r:12px;bottom:64px}}\n\n/* Touch: fingers need bigger targets than pointers (44 px for the menu's rows, 36 and more for buttons). */\n@media (pointer:coarse){\n.mi{min-height:44px}\n.ib{min-width:36px;min-height:36px}\n.rxo{min-width:40px;min-height:40px}\n.refs .ref{min-height:34px}\n.mnl li{min-height:40px}\n.bts button,.tg{min-height:36px}\n.launch .mode{width:44px;height:44px}\n}\n\n@media (forced-colors: active){\n.pick.kf{border:3px solid Highlight}\n.layer :is(.ib,.mi,.nb,.tg,.fs,.selbar button,.say button,.xb button):focus-visible{outline:2px solid Highlight}\n.tg[aria-pressed=true]{background:Highlight;color:HighlightText}\n}\n\n@media (prefers-reduced-motion: reduce){\n.ln,.subs{transition-property:opacity}\n@keyframes pu-in{0%{opacity:0}100%{opacity:1}}\n.bub,.bub.in,.bub.in:hover,.bub.on,.tip,.pop,.selbar,.menu,.all,.xp,.tt,.toast,.ref .rc,.rxp,.mnl{transform:none!important}\n.ttip{transition-property:opacity!important}\n.dlg{transform:translate(-50%,0)!important}\n.sw::after{transform:none!important;transition-property:opacity}\n[aria-checked=true]>.sw::after{opacity:0}\n[aria-checked=true]>.sw::before{opacity:1}\n.th{transition-property:opacity,box-shadow}\n.tip.show,.toast{transition-property:opacity}\n.pick,.pick.show{transition:opacity .16s ease-in-out}\n.all,.all.show,.xp,.xp.show{transition-property:opacity}\n.namebar,.namebar.show{transform:none!important;transition:opacity .16s ease-in-out}\n.av,.nf,.launch{transform:none!important}\n@keyframes pu-pulse{0%{opacity:0}35%{opacity:.85}100%{opacity:0}}\n}\n";
|
|
@@ -1,10 +1,14 @@
|
|
|
1
|
-
import type { Mention, Thread } from "../model/types";
|
|
1
|
+
import type { Comment, Mention, Thread } from "../model/types";
|
|
2
2
|
import { type Person } from "./mentions";
|
|
3
3
|
import { type ReactionPicker } from "./reactions";
|
|
4
4
|
export interface ThreadActions {
|
|
5
5
|
/** This reviewer's key, to mark their own reactions. */
|
|
6
6
|
readonly me: string;
|
|
7
7
|
reply(parentId: string, text: string, mentions?: Mention[]): Promise<void>;
|
|
8
|
+
/** Changes the words of one of this reviewer's comments. */
|
|
9
|
+
edit(commentId: string, text: string, mentions?: Mention[]): Promise<void>;
|
|
10
|
+
/** Deletes one of this reviewer's comments. */
|
|
11
|
+
remove(commentId: string): Promise<void>;
|
|
8
12
|
/** Who can be mentioned with `@` in a reply. */
|
|
9
13
|
people(): Person[];
|
|
10
14
|
/** Gives (`on`) or takes back this reviewer's reaction to a comment. */
|
|
@@ -20,27 +24,30 @@ export interface ThreadActions {
|
|
|
20
24
|
close(): void;
|
|
21
25
|
}
|
|
22
26
|
export interface ThreadViewOptions {
|
|
23
|
-
|
|
27
|
+
/** `card`: a closed card in All comments, only its first comment: words cut to two lines, no replies or reply box. */
|
|
28
|
+
variant: "column" | "popover" | "card";
|
|
24
29
|
quote?: string | null;
|
|
25
30
|
/** Snapshot of content that can't be shown: gone from the page, or somewhere it couldn't be reached. */
|
|
26
31
|
lost?: string | null;
|
|
27
32
|
/** Where that content is, when it isn't gone ("On slide 3"); default "No longer on the page". */
|
|
28
33
|
place?: string | null;
|
|
34
|
+
/** A card's line about what it's on, as written (in place of the quote). */
|
|
35
|
+
note?: string | null;
|
|
36
|
+
/** A card's quiet last line (its replies and reactions), as written. */
|
|
37
|
+
rest?: string | null;
|
|
29
38
|
now?: () => number;
|
|
30
39
|
}
|
|
31
40
|
export declare const plural: (n: number) => string;
|
|
41
|
+
/** A thread's replies that haven't been deleted: a deleted comment goes away. */
|
|
42
|
+
export declare const replies: (t: Thread) => Comment[];
|
|
32
43
|
export interface ThreadView {
|
|
33
44
|
readonly element: HTMLElement;
|
|
34
45
|
/** Shows a newer copy of the thread. The reply line is kept, so what's being typed in it (and focus) survives. */
|
|
35
|
-
update(t: Thread, o?:
|
|
36
|
-
quote?: string | null;
|
|
37
|
-
lost?: string | null;
|
|
38
|
-
place?: string | null;
|
|
39
|
-
}): void;
|
|
46
|
+
update(t: Thread, o?: Partial<ThreadViewOptions>): void;
|
|
40
47
|
}
|
|
41
48
|
/**
|
|
42
|
-
* One thread
|
|
43
|
-
*
|
|
44
|
-
*
|
|
49
|
+
* One thread, as a compact card: who and how long ago, then the words; its actions sit at the top right (on hover,
|
|
50
|
+
* and always when open). Replies sit one level in beneath the comment, oldest first, and the thread ends with its
|
|
51
|
+
* reply box at the same indent.
|
|
45
52
|
*/
|
|
46
53
|
export declare function threadView(first: Thread, actions: ThreadActions, options: ThreadViewOptions): ThreadView;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pipeup",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0-beta.2",
|
|
4
4
|
"description": "Comments and feedback right on any HTML page: documents, slide decks and whole sites.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"comments",
|
|
@@ -42,6 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"files": [
|
|
44
44
|
"dist/*.js",
|
|
45
|
+
"dist/addons.json",
|
|
45
46
|
"dist/types",
|
|
46
47
|
"cli",
|
|
47
48
|
"skills",
|
|
@@ -5,7 +5,7 @@ description: Use when someone asks you to add comments to an HTML page, make it
|
|
|
5
5
|
|
|
6
6
|
# Add Pipeup to this page
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.
|
|
8
|
+
Written for Pipeup 0.8.0-beta.2 This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-add/SKILL.md. Its companions: [integrate](https://pipeup-ai.github.io/pipeup/skills/pipeup-integrate/SKILL.md) (the full reference: layouts, decks, tabs, every option), [apply](https://pipeup-ai.github.io/pipeup/skills/pipeup-apply/SKILL.md) (answering the comments) and [summarise](https://pipeup-ai.github.io/pipeup/skills/pipeup-summarise/SKILL.md).
|
|
9
9
|
|
|
10
10
|
Pipeup lets people comment on an HTML page in place. **When the page already exists, never change its layout, styling or behaviour to make room for Pipeup**: it draws in its own layer, and you only add attributes and one script tag. Edit the HTML file only; don't download, fetch or run anything yourself.
|
|
11
11
|
|
|
@@ -14,7 +14,7 @@ Pipeup lets people comment on an HTML page in place. **When the page already exi
|
|
|
14
14
|
1. **Pin the script.** Just before `</body>`:
|
|
15
15
|
|
|
16
16
|
```html
|
|
17
|
-
<script src="https://cdn.jsdelivr.net/npm/pipeup@0.
|
|
17
|
+
<script src="https://cdn.jsdelivr.net/npm/pipeup@0.8.0-beta.2/dist/pipeup.min.js"
|
|
18
18
|
integrity="sha384-…" crossorigin="anonymous"></script>
|
|
19
19
|
```
|
|
20
20
|
|
|
@@ -30,7 +30,7 @@ Pipeup lets people comment on an HTML page in place. **When the page already exi
|
|
|
30
30
|
4. **Add-ons: none unless the author asks.** Pipeup itself sends nothing anywhere. If they want sharing, voice, live
|
|
31
31
|
comments, the assistant, the full emoji set for reactions (`@pipeup/emoji`), notes for mentioned people (`@pipeup/inbox`,
|
|
32
32
|
which needs an inbox service address the author gives you), GitHub issues for mentions (`@pipeup/github`, which needs
|
|
33
|
-
`data-pipeup-github-repo`)
|
|
33
|
+
`data-pipeup-github-repo`), update notices (`@pipeup/updates`) or recovery codes so reviewers can move their identity (`@pipeup/identity`), ask first, say in plain words what it sends and to whom, and pin it like the core script.
|
|
34
34
|
Then list its id in `data-pipeup-addons` on `<html>` (append, never remove an entry) so only chosen add-ons run, and
|
|
35
35
|
tell the author about a Content-Security-Policy that allows scripts only from the page and the CDN. Don't apply the
|
|
36
36
|
policy yourself: a strict one can break a page.
|
|
@@ -49,5 +49,5 @@ When you rewrite or regenerate a page, keep `data-pipeup-doc`, `data-pipeup-shar
|
|
|
49
49
|
## Tell the author
|
|
50
50
|
|
|
51
51
|
What you added (one script, a few attributes), how to comment (**⇧⌥C** on a Mac, **Shift+Alt+C** elsewhere, or the round
|
|
52
|
-
button), how comments come back (**Copy
|
|
52
|
+
button), how comments come back (**Copy comments › As Markdown**, or, with the agents add-on, **Copy a prompt for my agent**), and that nothing leaves their
|
|
53
53
|
browser unless they choose it.
|
|
@@ -5,7 +5,7 @@ description: Use when someone asks you to act on Pipeup feedback for an HTML pag
|
|
|
5
5
|
|
|
6
6
|
# Apply Pipeup feedback
|
|
7
7
|
|
|
8
|
-
Written for Pipeup 0.
|
|
8
|
+
Written for Pipeup 0.8.0-beta.2 This skill is published at https://pipeup-ai.github.io/pipeup/skills/pipeup-apply/SKILL.md. Its companions: [integrate](https://pipeup-ai.github.io/pipeup/skills/pipeup-integrate/SKILL.md), [summarise](https://pipeup-ai.github.io/pipeup/skills/pipeup-summarise/SKILL.md).
|
|
9
9
|
|
|
10
10
|
## 1. Read the comments
|
|
11
11
|
|
|
@@ -19,7 +19,7 @@ Use the first of these that works:
|
|
|
19
19
|
`await Pipeup.comments()`. It returns `{ markdown, threads }`: `markdown` is the same text as **Copy as
|
|
20
20
|
Markdown**, and `threads` is the same threads as data (`id`, `state`, `where`, `element`, `quote`, and each
|
|
21
21
|
comment with `by`, `agent` and `text`). Pass `{ all: true }` to include resolved threads.
|
|
22
|
-
2. **The pasted Markdown**: the author clicks **Copy
|
|
22
|
+
2. **The pasted Markdown**: the author clicks **Copy comments › As Markdown** (or, on a page with the agents add-on, **Copy a prompt for my agent**) and pastes it.
|
|
23
23
|
|
|
24
24
|
Each thread has a `- **Thread:** <id>` line: you need it to answer the thread.
|
|
25
25
|
|