pipeup 0.4.0-beta.1 → 0.4.0-beta.3
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 +26 -11
- package/dist/pipeup.core.js +7 -7
- package/dist/pipeup.esm.js +7 -7
- package/dist/pipeup.min.js +7 -7
- package/dist/types/anchor/locate.d.ts +7 -1
- package/dist/types/core.d.ts +1 -1
- package/dist/types/index.d.ts +1 -0
- package/dist/types/ui/comment-mode.d.ts +14 -1
- package/dist/types/ui/context.d.ts +18 -3
- package/dist/types/ui/dom.d.ts +2 -0
- package/dist/types/ui/here.d.ts +62 -0
- package/dist/types/ui/icons.d.ts +2 -0
- package/dist/types/ui/mount.d.ts +3 -0
- package/dist/types/ui/order.d.ts +6 -0
- package/dist/types/ui/pick.d.ts +18 -0
- package/dist/types/ui/styles.d.ts +1 -1
- package/dist/types/ui/thread-view.d.ts +5 -1
- package/package.json +1 -1
|
@@ -1,8 +1,21 @@
|
|
|
1
1
|
import type { Ctx, View } from "./context";
|
|
2
2
|
import { type Look } from "./pick";
|
|
3
|
-
/**
|
|
3
|
+
/** Page controls Enter or Space would activate. */
|
|
4
|
+
export declare const ACTIVATES = "a,button,summary,[role=button],[role=link],[role=switch],[role=tab],[role=checkbox],input[type=checkbox],input[type=radio],input[type=submit],input[type=button],input[type=reset]";
|
|
5
|
+
/** The keyboard's hint: shown as a toast, and read with the block cursor's first landing. */
|
|
6
|
+
export declare const KEYS_HINT = "Tab moves between blocks \u00B7 \u2191 \u2193 change level \u00B7 Enter comments \u00B7 Esc to finish \u00B7 F7 selects text";
|
|
7
|
+
/** Comment mode's view. */
|
|
4
8
|
export interface CommentMode extends View {
|
|
9
|
+
/** Escape's step: clears a chosen block, else puts the block cursor away; false when there was neither. */
|
|
5
10
|
back(): boolean;
|
|
11
|
+
/** The keyboard's block cursor is in use (started, and not put away). */
|
|
12
|
+
cursor(): boolean;
|
|
13
|
+
/** The block cursor was put away: the shortcut brings it back. */
|
|
14
|
+
away(): boolean;
|
|
15
|
+
/** Starts the block cursor, or brings it back: on its last block if still here, else where focus is, else the first block in view. */
|
|
16
|
+
resume(): boolean;
|
|
17
|
+
/** Focuses the block cursor on its block again, as a move, so its name is read afresh. */
|
|
18
|
+
refocus(): void;
|
|
6
19
|
}
|
|
7
20
|
/**
|
|
8
21
|
* Comment mode: the page goes quiet, an outline glides to the obvious block under the pointer, and a click
|
|
@@ -3,6 +3,7 @@ import type { PipeupDocument } from "../document";
|
|
|
3
3
|
import type { CopyAs, ExportItem } from "../export/format";
|
|
4
4
|
import type { Anchor, Thread } from "../model/types";
|
|
5
5
|
import type { DraftBox } from "./draft-view";
|
|
6
|
+
import type { Here } from "./here";
|
|
6
7
|
import type { ThreadActions } from "./thread-view";
|
|
7
8
|
/** A comment being written: what it's on, and where that is now. */
|
|
8
9
|
export interface Draft {
|
|
@@ -57,6 +58,12 @@ export interface Ctx {
|
|
|
57
58
|
readonly pending: ReadonlySet<string>;
|
|
58
59
|
readonly actions: ThreadActions;
|
|
59
60
|
readonly menu: MenuActions;
|
|
61
|
+
/** Where the reviewer is: the slide, or the page's own view. */
|
|
62
|
+
readonly here: Here;
|
|
63
|
+
/** The thread lives on another slide or view, or the page hides its content: nothing of it shows. */
|
|
64
|
+
elsewhere(t: Thread): boolean;
|
|
65
|
+
/** Sorts threads into here and elsewhere again now, re-rendering if that changed anything. */
|
|
66
|
+
recheck(): void;
|
|
60
67
|
visible(t: Thread): boolean;
|
|
61
68
|
/** The shown text comment whose highlight is at (x, y), if any. */
|
|
62
69
|
quoteAt(x: number, y: number): Thread | null;
|
|
@@ -82,14 +89,22 @@ export interface Ctx {
|
|
|
82
89
|
draftEmpty(): boolean;
|
|
83
90
|
/** Runs `fn`, then puts focus and the caret back in the open draft as they were. */
|
|
84
91
|
keepCaret(fn: () => void): void;
|
|
92
|
+
/** Goes back to the open draft: to its slide or view if that has gone, then focus and the caret into it. */
|
|
93
|
+
backToDraft(): void;
|
|
85
94
|
postDraft(text: string): Promise<void>;
|
|
86
95
|
cancelDraft(): void;
|
|
87
|
-
/** Turns comment mode on or off; comments show while it is on. */
|
|
88
|
-
setCommenting(on: boolean): void;
|
|
89
|
-
/** What a click on the page does: cancels an empty draft, else closes the open thread. */
|
|
96
|
+
/** Turns comment mode on or off; comments show while it is on. `keys`: from the keyboard (the block cursor starts). */
|
|
97
|
+
setCommenting(on: boolean, keys?: boolean): void;
|
|
98
|
+
/** What a click on the page does: cancels an empty draft (back to one with words), else closes the open thread. */
|
|
90
99
|
dismiss(): void;
|
|
91
100
|
registerDraft(box: DraftBox | null): void;
|
|
92
101
|
toast(message: string): void;
|
|
102
|
+
/** Tells screen readers (a polite live region), once. */
|
|
103
|
+
say(text: string): void;
|
|
104
|
+
/** Comment mode's hint goes, if it is showing. */
|
|
105
|
+
hideHint(): void;
|
|
106
|
+
/** Escape's step back: the draft, the open thread, then comment mode's own, then comment mode. */
|
|
107
|
+
back(): void;
|
|
93
108
|
/** Tells the reviewer what went wrong. */
|
|
94
109
|
report(e: unknown): void;
|
|
95
110
|
pulse(id: string): void;
|
package/dist/types/ui/dom.d.ts
CHANGED
|
@@ -3,6 +3,8 @@ type Child = Node | string | null | undefined | false;
|
|
|
3
3
|
export declare function h<K extends keyof HTMLElementTagNameMap>(tag: K, props?: Record<string, string | boolean | undefined>, ...children: Child[]): HTMLElementTagNameMap[K];
|
|
4
4
|
/** Takes `el` out of (or back into) the keyboard's reach; focus never stays on something that goes inert. */
|
|
5
5
|
export declare function inert(el: HTMLElement, on: boolean): void;
|
|
6
|
+
/** Puts `els` in this order before `ref` (at the end without one) in `parent`, moving only what is out of place and keeping focus; true when any moved. */
|
|
7
|
+
export declare function reorder(parent: Element, els: readonly Element[], ref?: Node | null): boolean;
|
|
6
8
|
export declare function clip(text: string, n: number): string;
|
|
7
9
|
/** Sizes a fixed overlay (outline, pulse, mark) to a box, with padding around it. */
|
|
8
10
|
export declare function fit(el: HTMLElement, r: {
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
/** Where the reviewer is: the slide ("1"-based) and whatever the page reports about itself. */
|
|
2
|
+
export type ViewState = Record<string, string>;
|
|
3
|
+
/** A deck's own way to say which slide shows and to go to one (both 1-based). */
|
|
4
|
+
export interface SlideHook {
|
|
5
|
+
current(): number;
|
|
6
|
+
go(n: number): void;
|
|
7
|
+
}
|
|
8
|
+
/** What finding the current slide needs from layout (faked in unit tests). */
|
|
9
|
+
export interface SlideLook {
|
|
10
|
+
box(el: Element): {
|
|
11
|
+
left: number;
|
|
12
|
+
top: number;
|
|
13
|
+
width: number;
|
|
14
|
+
height: number;
|
|
15
|
+
};
|
|
16
|
+
/** Not hidden by display:none, visibility:hidden or opacity:0, on it or an ancestor. */
|
|
17
|
+
shown(el: Element): boolean;
|
|
18
|
+
/** Its own opacity, 0 to 1: in a cross-fade the more opaque of two slides wins. */
|
|
19
|
+
opacity(el: Element): number;
|
|
20
|
+
viewport(): {
|
|
21
|
+
width: number;
|
|
22
|
+
height: number;
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
/** Where the reviewer is now, and how to go somewhere else. */
|
|
26
|
+
export interface Here {
|
|
27
|
+
/** The current slide ("3"), or null on a page that isn't a deck. */
|
|
28
|
+
slide(): string | null;
|
|
29
|
+
/**
|
|
30
|
+
* What a new comment on `at` saves: { slide?, ...the page's state }, or undefined when there is nothing. The
|
|
31
|
+
* slide is the marked slide holding `at`, else the current one.
|
|
32
|
+
*/
|
|
33
|
+
view(at?: Node): ViewState | undefined;
|
|
34
|
+
/** A thread saved with view `saved` belongs here (its content is judged by the app). */
|
|
35
|
+
holds(saved: ViewState | undefined): boolean;
|
|
36
|
+
/** Goes to `view`; resolves true once it is here, false after 1 s (or at once when nothing can go there). */
|
|
37
|
+
navigate(view: ViewState): Promise<boolean>;
|
|
38
|
+
destroy(): void;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Reports the page's own view, such as `{ tab: "pricing", label: "Pricing tab" }`: string values only, within
|
|
42
|
+
* the anchor's limits (the slide is Pipeup's own). `label` is the readable name and is never compared. `null`
|
|
43
|
+
* forgets it.
|
|
44
|
+
*/
|
|
45
|
+
export declare function setViewState(state: Record<string, unknown> | null): void;
|
|
46
|
+
/** Registers a handler called with a view when the reviewer chooses a thread elsewhere; returns its removal. */
|
|
47
|
+
export declare function onReveal(fn: (view: ViewState) => void): () => void;
|
|
48
|
+
/** The deck hook from `mount({ slides })`, or null. */
|
|
49
|
+
export declare function setSlideHook(h: SlideHook | null): void;
|
|
50
|
+
/** The marked slide showing most: the most of the window covered, then the more opaque; still tied, `was` stays. */
|
|
51
|
+
export declare function pickSlide(slides: readonly Element[], look: SlideLook, was: Element | null): Element | null;
|
|
52
|
+
/**
|
|
53
|
+
* On a deck, a thread is here when it is on this slide (or on none); on other pages, when every key of its
|
|
54
|
+
* saved view but `label` matches the page's state (always, until the page reports one).
|
|
55
|
+
*/
|
|
56
|
+
export declare function isHere(saved: ViewState | undefined, slide: string | null, state: ViewState | null): boolean;
|
|
57
|
+
export declare function pageSlideLook(): SlideLook;
|
|
58
|
+
/**
|
|
59
|
+
* Follows here: the deck's hook, else reveal.js, else the marked slide that is showing; plus the page's
|
|
60
|
+
* reported state. `onCheck` runs after every re-check (at most once a frame), so the app can re-sort threads.
|
|
61
|
+
*/
|
|
62
|
+
export declare function createHere(root: Element, onCheck: () => void, look?: SlideLook): Here;
|
package/dist/types/ui/icons.d.ts
CHANGED
|
@@ -7,6 +7,8 @@ declare const PATHS: {
|
|
|
7
7
|
readonly lines: readonly ["M4 7h16M4 12h10M4 17h7"];
|
|
8
8
|
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
9
|
readonly expand: readonly ["M14 4h6v6M20 4l-6 6M10 20H4v-6M4 20l6-6M20 14v6h-6M20 20l-6-6M4 10V4h6M4 4l6 6"];
|
|
10
|
+
readonly pin: readonly ["M6 18v-6a6 6 0 1 1 6 6z"];
|
|
11
|
+
readonly shrink: readonly ["M20 10h-6V4M14 10l6-6M4 14h6v6M10 14l-6 6M14 20v-6h6M14 14l6 6M10 4v6H4M10 10L4 4"];
|
|
10
12
|
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"];
|
|
11
13
|
readonly close: readonly ["M6 6l12 12M18 6L6 18"];
|
|
12
14
|
readonly edit: readonly ["M4 20h4L19 9l-4-4L4 16z"];
|
package/dist/types/ui/mount.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PipeupDocument } from "../document";
|
|
2
2
|
import { type OpStore } from "../storage/store";
|
|
3
|
+
import { type SlideHook } from "./here";
|
|
3
4
|
export interface MountOptions {
|
|
4
5
|
/** The area people can comment on. Default: document.body. */
|
|
5
6
|
root?: Element;
|
|
@@ -7,6 +8,8 @@ export interface MountOptions {
|
|
|
7
8
|
name?: string;
|
|
8
9
|
/** Where comments are kept. Default: this browser's IndexedDB. */
|
|
9
10
|
store?: OpStore;
|
|
11
|
+
/** A deck's own slide functions (1-based); they replace Pipeup's following of the deck. */
|
|
12
|
+
slides?: SlideHook;
|
|
10
13
|
}
|
|
11
14
|
export interface PipeupInstance {
|
|
12
15
|
readonly document: PipeupDocument;
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Thread } from "../model/types";
|
|
2
|
+
import type { Ctx } from "./context";
|
|
3
|
+
/** Where a thread's content starts on the page: its words' first node, else its element; null when lost. */
|
|
4
|
+
export declare function nodeOf(ctx: Ctx, t: Thread): Node | null;
|
|
5
|
+
/** Threads in page order: by where their content starts, then a pin's place (top to bottom), else as written. */
|
|
6
|
+
export declare const byPage: (ctx: Ctx) => (a: Thread, b: Thread) => number;
|
package/dist/types/ui/pick.d.ts
CHANGED
|
@@ -15,9 +15,27 @@ export interface Look {
|
|
|
15
15
|
height: number;
|
|
16
16
|
};
|
|
17
17
|
}
|
|
18
|
+
/** `el` is a block a click would choose: big enough to see, and marked, obvious, drawn or grouping things. */
|
|
19
|
+
export declare function isBlock(el: Element, look: Look): boolean;
|
|
18
20
|
/** The obvious block under `from`: what the outline glides to in comment mode. */
|
|
19
21
|
export declare function pickBlock(from: Element, root: Element, look: Look): Element | null;
|
|
20
22
|
/** The next block out from `el` with a different box (wrappers the same size are skipped). */
|
|
21
23
|
export declare function parentBlock(el: Element, root: Element, look: Look): Element | null;
|
|
22
24
|
/** The real page: boxes from layout, "drawn" and "grouped" from computed styles. */
|
|
23
25
|
export declare function pageLook(win?: Window): Look;
|
|
26
|
+
/** A block in the keyboard's tree: the block around it, and its level (0 with no block inside it). */
|
|
27
|
+
export interface Block {
|
|
28
|
+
el: Element;
|
|
29
|
+
up: Block | null;
|
|
30
|
+
level: number;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Every block under `root` in page order, each with the block around it as `parentBlock` finds it: wrappers the
|
|
34
|
+
* same size fold into the innermost, unless the outer one is marked (`data-pipeup-id`) and the inner one isn't.
|
|
35
|
+
* Ignored areas, and subtrees `keep` rejects (hidden, on another slide), are left out.
|
|
36
|
+
*/
|
|
37
|
+
export declare function blockTree(root: Element, look: Look, keep?: (el: Element) => boolean): Block[];
|
|
38
|
+
/** The blocks Tab visits at level `k`: at that level or below, with no block of that level around them. */
|
|
39
|
+
export declare const row: (tree: readonly Block[], k: number) => Block[];
|
|
40
|
+
/** The blocks directly inside `b`, in page order. */
|
|
41
|
+
export declare const childBlocks: (tree: readonly Block[], b: Block) => Block[];
|
|
@@ -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}\n*{box-sizing:border-box}\nbutton{-webkit-appearance:none;appearance:none;font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}\nsvg{display:block}\n.layer{all:initial;display:block;position:fixed;inset:0;pointer-events:none;font:13px/1.5 var(--pu-font,system-ui,sans-serif);color:var(--pu-ink);\n--pu-ink:#2C2C2A;--pu-muted:#5F5E5A;--pu-faint:#888780;--pu-line:#E5E3DA;--pu-rule:#ECEAE2;--pu-soft:#FAFAF7;--pu-surface:#FFFFFF;--pu-hover:#F1EFE8;\n--pu-accent-soft:color-mix(in srgb,var(--pu-accent,#534AB7) 12%,transparent);\n--pu-shadow:0 8px 28px rgba(44,44,42,.10);\n--pu-enter:.26s;--pu-move:.34s;--pu-exit:.2s;--pu-pulse:1.2s;\n--pu-eo:cubic-bezier(.22,.61,.36,1);--pu-eio:cubic-bezier(.4,0,.2,1);--pu-ei:cubic-bezier(.4,0,1,1)}\n.layer.dark{--pu-ink:#ECEBE6;--pu-muted:#B4B2A9;--pu-faint:#8D8B84;--pu-line:#3A3936;--pu-rule:#34332F;--pu-soft:#22221F;--pu-surface:#1B1B19;--pu-hover:#2C2C29;--pu-shadow: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(--pu-ink);white-space:pre-wrap;overflow-wrap:anywhere}\n.tx.del,.who,.rest,.ctx{color:var(--pu-faint)}\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(--pu-enter) var(--pu-eo),opacity var(--pu-enter) var(--pu-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{grid-template-rows:1fr;opacity:1}\n.ft.has-rest>*{grid-area:1/1}\n.ft .hover{opacity:0;transition:opacity var(--pu-enter) var(--pu-eo)}\n.ft .rest{transition:opacity var(--pu-enter) var(--pu-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(--pu-muted);transition:background-color .2s var(--pu-eo),color .2s var(--pu-eo)}\n.ib:hover,.ib:focus-visible{background:var(--pu-hover);color:var(--pu-ink);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(--pu-move) var(--pu-eio)}\n.more>div{overflow:hidden;min-height:0}\n.th:not(.on) .more{grid-template-rows:0fr}\n\n.row{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(--pu-line);outline:none;resize:none;overflow:hidden;\nfont:inherit;font-size:14px;line-height:1.5;padding:3px 0;color:var(--pu-ink);background:transparent;transition:border-color var(--pu-enter) var(--pu-eo)}\n.row:hover .input,.input:hover{border-bottom-color:var(--pu-muted)}\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(--pu-enter) var(--pu-eo),transform var(--pu-enter) var(--pu-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.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(--pu-faint)}\n.you>*{grid-area:1/1;display:flex;align-items:center;min-width:0;transition:opacity var(--pu-enter) var(--pu-eo),transform var(--pu-enter) var(--pu-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(--pu-muted);text-decoration:underline;text-decoration-color:var(--pu-line);text-underline-offset:2px;transition:color .2s var(--pu-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(--pu-enter) var(--pu-eo),background-color .2s var(--pu-eo)}\n.send.show{opacity:1;pointer-events:auto}\n.send:hover{background:var(--pu-accent-soft)}\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(--pu-surface);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(--pu-exit) var(--pu-ei),transform var(--pu-exit) var(--pu-ei)}\n.bub.in{opacity:1;transform:none;transition:opacity var(--pu-enter) var(--pu-eo),transform var(--pu-enter) var(--pu-eo)}\n.bub.in:hover,.bub.on{transform:scale(1.18)}\n.bub.done{background:var(--pu-faint)}\n.bub.ghost{pointer-events:none}\n.tip,.pop,.menu,.all,.toast,.selbar{background:var(--pu-surface);border:1px solid var(--pu-line);box-shadow:var(--pu-shadow)}\n.tip{position:fixed;max-width:260px;border-radius:10px;padding:7px 10px;opacity:0;transform:translateY(3px);\ntransition:opacity .22s var(--pu-eo),transform .26s var(--pu-eo)}\n.tip.show{opacity:1;transform:none;pointer-events:auto;cursor:pointer;\ntransition:opacity .22s var(--pu-eo),transform .26s var(--pu-eo),left var(--pu-move) var(--pu-eio),top var(--pu-move) var(--pu-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(--pu-exit) var(--pu-ei),transform var(--pu-exit) var(--pu-ei)}\n.pop.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--pu-enter) var(--pu-eo),transform var(--pu-move) var(--pu-eo)}\n.pop.show.glide{transition:opacity var(--pu-enter) var(--pu-eo),transform var(--pu-move) var(--pu-eo),left var(--pu-move) var(--pu-eio),top var(--pu-move) var(--pu-eio)}\n.mark{position:fixed;border:2px solid color-mix(in srgb,var(--pu-accent) 50%,transparent);background:var(--pu-accent-soft);border-radius:8px;opacity:0;\ntransition:opacity .3s var(--pu-eo)}\n.mark.show{opacity:1}\n.pulse{position:fixed;border:2px solid var(--pu-accent);border-radius:8px;background:var(--pu-accent-soft);animation:pu-pulse var(--pu-pulse) var(--pu-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(--pu-enter) var(--pu-eo)}\n.th{position:absolute;left:0;right:0;top:0;padding:4px 4px 4px 12px;pointer-events:auto;cursor:pointer;box-shadow:inset 2px 0 0 transparent;\ntransition:transform var(--pu-move) var(--pu-eio),box-shadow var(--pu-enter) var(--pu-eo),opacity var(--pu-enter) var(--pu-eo)}\n.th.hot{box-shadow:inset 2px 0 0 var(--pu-line)}\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(--pu-exit) var(--pu-ei)}\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(--pu-enter) var(--pu-eo),transform .3s var(--pu-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(--pu-eo)}\n.selbar button:hover,.selbar button:focus-visible{background:var(--pu-accent-soft);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(--pu-exit) var(--pu-ei),border-color var(--pu-exit) var(--pu-ei)}\n.pick.show{opacity:1;transition-duration:var(--pu-enter);transition-timing-function:var(--pu-eo)}\n.pick.show.glide{transition-property:all;transition-duration:var(--pu-move);transition-timing-function:var(--pu-eio)}\n.pick.on{border-color:var(--pu-accent)}\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(--pu-muted);\nwhite-space:nowrap;background:var(--pu-surface);border:1px solid var(--pu-line);box-shadow:var(--pu-shadow);pointer-events:none;opacity:0;transform:translateY(4px);\ntransition:opacity var(--pu-exit) var(--pu-ei),transform var(--pu-exit) var(--pu-ei)}\n.namebar.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--pu-enter) var(--pu-eo),transform .3s var(--pu-eo)}\n.namebar.show.glide{transition-property:all;transition-duration:var(--pu-move);transition-timing-function:var(--pu-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(--pu-eo),color .2s var(--pu-eo)}\n.namebar .nb:hover,.namebar .nb:focus-visible{background:var(--pu-hover);color:var(--pu-ink);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{display:grid;place-items:center;width:46px;height:46px;border-radius:50%;background:var(--pu-surface);border:1px solid var(--pu-line);\nbox-shadow:var(--pu-shadow);transition:background-color .3s var(--pu-eo),color .3s var(--pu-eo)}\n.mode>*,.cnt>*{grid-area:1/1}\n.mode>*{display:grid;place-items:center;transition:opacity var(--pu-enter) var(--pu-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(--pu-enter) var(--pu-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(--pu-hover)}\n.launch .mode.on{background:var(--pu-accent);color:#fff}\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;background:var(--pu-surface);border:1px solid var(--pu-line);\nbox-shadow:var(--pu-shadow);pointer-events:none;opacity:0;transform:translateY(3px);transition:opacity var(--pu-exit) var(--pu-ei),transform var(--pu-exit) var(--pu-ei)}\n.ttip small{margin-left:8px}\n.ttip small,.mi .kc{font-size:12px;color:var(--pu-faint)}\n.mode:hover+.ttip,.mode:focus-visible+.ttip{opacity:1;transform:none;transition:opacity var(--pu-enter) var(--pu-eo) .5s,transform var(--pu-enter) var(--pu-eo) .5s}\n.launch .mode[aria-expanded=true]+.ttip{opacity:0;transition:opacity var(--pu-exit) var(--pu-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(--pu-exit) var(--pu-ei),transform var(--pu-exit) var(--pu-ei)}\n.menu.show{opacity:1;transform:none;pointer-events:auto;transition:opacity var(--pu-enter) var(--pu-eo),transform var(--pu-move) var(--pu-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(--pu-eo)}\n.mi:hover,.mi:focus-visible{background:var(--pu-soft);outline:none}\n.mi svg{color:var(--pu-muted);flex:none}\n.mi small{display:block;color:var(--pu-faint);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(--pu-rule)}\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(--pu-muted);background:var(--pu-surface);border:1px solid var(--pu-line);box-shadow:var(--pu-shadow);pointer-events:none;opacity:0;transform:translateX(3px);\ntransition:opacity var(--pu-exit) var(--pu-ei),transform var(--pu-exit) var(--pu-ei)}\n.mi:hover>.tt,.mi:focus-visible>.tt{opacity:1;transform:none;transition:opacity var(--pu-enter) var(--pu-eo) .5s,transform var(--pu-enter) var(--pu-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(--pu-line);transition:background-color var(--pu-move) var(--pu-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(--pu-move) var(--pu-eio),opacity var(--pu-move) var(--pu-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/* All comments: a full-height panel on the right that slides in (fades, with reduced motion). */\n.all{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(--pu-exit) var(--pu-ei),opacity var(--pu-exit) var(--pu-ei)}\n.all.show{opacity:1;transform:none;pointer-events:auto;transition:transform var(--pu-move) var(--pu-eo),opacity var(--pu-enter) var(--pu-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(--pu-faint)}\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(--pu-muted);\ntransition:background-color .2s var(--pu-eo)}\n.hs:hover,.hs:focus-visible{background:var(--pu-hover);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 .av svg{margin:0}\n.all .mi.done{opacity:.6}\n.layer.listing .col{opacity:0;transition:opacity var(--pu-exit) var(--pu-ei)}\n.sec{padding:8px 10px 2px;font-size:12px;color:var(--pu-faint)}\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(--pu-eo),transform .36s var(--pu-eo)}\n.toast.show{opacity:1;transform:translate(-50%,0)}\n\n@media (prefers-reduced-motion: reduce){\n.bub,.bub.in,.bub.in:hover,.bub.on,.tip,.pop,.selbar,.menu,.all,.ttip,.tt,.toast{transform:none!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{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}\n*{box-sizing:border-box}\nbutton{-webkit-appearance:none;appearance:none;font:inherit;color:inherit;background:none;border:0;padding:0;cursor:pointer}\nsvg{display:block}\n.layer{all:initial;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:#888780;--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.layer.dark{--k:#ECEBE6;--mu:#B4B2A9;--fa:#8D8B84;--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{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{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.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,.toast,.selbar{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;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{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;background:var(--su);border:1px solid var(--ln);box-shadow:var(--sh);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%;background:var(--su);border:1px solid var(--ln);\nbox-shadow:var(--sh);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:#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;background:var(--su);border:1px solid var(--ln);\nbox-shadow:var(--sh);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);background:var(--su);border:1px solid var(--ln);box-shadow:var(--sh);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/* All comments: a full-height panel on the right that slides in (fades, with reduced motion). */\n.all{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{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 .av svg{margin:0}\n.all .mi.done{opacity:.6}\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.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@media (forced-colors: active){\n.pick.kf{border:3px solid Highlight}\n.layer :is(.ib,.mi,.nb,.hs,.selbar button,.say button):focus-visible{outline:2px solid Highlight}\n}\n\n@media (prefers-reduced-motion: reduce){\n.bub,.bub.in,.bub.in:hover,.bub.on,.tip,.pop,.selbar,.menu,.all,.ttip,.tt,.toast{transform:none!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{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";
|
|
@@ -10,16 +10,20 @@ export interface ThreadActions {
|
|
|
10
10
|
export interface ThreadViewOptions {
|
|
11
11
|
variant: "column" | "popover";
|
|
12
12
|
quote?: string | null;
|
|
13
|
-
/** Snapshot of content that
|
|
13
|
+
/** Snapshot of content that can't be shown: gone from the page, or somewhere it couldn't be reached. */
|
|
14
14
|
lost?: string | null;
|
|
15
|
+
/** Where that content is, when it isn't gone ("On slide 3"); default "No longer on the page". */
|
|
16
|
+
place?: string | null;
|
|
15
17
|
now?: () => number;
|
|
16
18
|
}
|
|
19
|
+
export declare const plural: (n: number) => string;
|
|
17
20
|
export interface ThreadView {
|
|
18
21
|
readonly element: HTMLElement;
|
|
19
22
|
/** Shows a newer copy of the thread. The reply line is kept, so what's being typed in it (and focus) survives. */
|
|
20
23
|
update(t: Thread, o?: {
|
|
21
24
|
quote?: string | null;
|
|
22
25
|
lost?: string | null;
|
|
26
|
+
place?: string | null;
|
|
23
27
|
}): void;
|
|
24
28
|
}
|
|
25
29
|
/**
|