@kadal/deck 0.0.0-stage → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/LICENSING.md +40 -0
- package/README.md +170 -2
- package/dist/_virtual/_rolldown/runtime.js +13 -0
- package/dist/audience/index.d.ts +14 -0
- package/dist/audience/index.js +680 -0
- package/dist/backgrounds/index.d.ts +65 -0
- package/dist/backgrounds/index.js +604 -0
- package/dist/backgrounds/shared.d.ts +7 -0
- package/dist/backgrounds/shared.js +89 -0
- package/dist/cli/bin.d.ts +1 -0
- package/dist/cli/bin.js +8 -0
- package/dist/cli/host.js +111 -0
- package/dist/cli/index.d.ts +4 -0
- package/dist/cli/index.js +140 -0
- package/dist/cli/login.js +56 -0
- package/dist/cli/publish.js +159 -0
- package/dist/cli/vite.js +39 -0
- package/dist/compiler/code-meta.d.ts +33 -0
- package/dist/compiler/code-meta.js +81 -0
- package/dist/compiler/index.d.ts +8 -0
- package/dist/compiler/index.js +8 -0
- package/dist/compiler/magic-move.d.ts +26 -0
- package/dist/compiler/magic-move.js +33 -0
- package/dist/compiler/plain-text.js +7 -0
- package/dist/compiler/rehype-code.d.ts +18 -0
- package/dist/compiler/rehype-code.js +66 -0
- package/dist/compiler/rehype-glossary.d.ts +35 -0
- package/dist/compiler/rehype-glossary.js +211 -0
- package/dist/compiler/slots.d.ts +3 -0
- package/dist/compiler/slots.js +36 -0
- package/dist/compiler/split.d.ts +63 -0
- package/dist/compiler/split.js +195 -0
- package/dist/components/Background.d.ts +15 -0
- package/dist/components/Background.js +24 -0
- package/dist/components/Click.d.ts +54 -0
- package/dist/components/Click.js +129 -0
- package/dist/components/Code.d.ts +27 -0
- package/dist/components/Code.js +124 -0
- package/dist/components/Motion.d.ts +25 -0
- package/dist/components/Motion.js +45 -0
- package/dist/components/Sketch.d.ts +44 -0
- package/dist/components/Sketch.js +141 -0
- package/dist/components/Term.d.ts +63 -0
- package/dist/components/Term.js +492 -0
- package/dist/components/bling.d.ts +75 -0
- package/dist/components/bling.js +146 -0
- package/dist/components/content.d.ts +232 -0
- package/dist/components/content.js +637 -0
- package/dist/components/index.d.ts +10 -0
- package/dist/components/index.js +88 -0
- package/dist/core/clicks.d.ts +45 -0
- package/dist/core/clicks.js +75 -0
- package/dist/core/hash.d.ts +33 -0
- package/dist/core/hash.js +49 -0
- package/dist/core/keyboard.d.ts +17 -0
- package/dist/core/keyboard.js +198 -0
- package/dist/core/layout.d.ts +16 -0
- package/dist/core/layout.js +25 -0
- package/dist/core/model.d.ts +259 -0
- package/dist/core/model.js +377 -0
- package/dist/core/navigation.d.ts +74 -0
- package/dist/core/navigation.js +244 -0
- package/dist/core/poster.js +30 -0
- package/dist/core/store.d.ts +20 -0
- package/dist/core/store.js +64 -0
- package/dist/core/touch.js +27 -0
- package/dist/draw/DrawingLayer.js +315 -0
- package/dist/draw/strokes.js +188 -0
- package/dist/export/index.d.ts +68 -0
- package/dist/export/index.js +251 -0
- package/dist/export/run.js +81 -0
- package/dist/glossary/model.d.ts +81 -0
- package/dist/glossary/model.js +156 -0
- package/dist/glossary/parse.d.ts +27 -0
- package/dist/glossary/parse.js +90 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.js +30 -0
- package/dist/live/LiveProvider.d.ts +20 -0
- package/dist/live/LiveProvider.js +450 -0
- package/dist/live/analytics.d.ts +15 -0
- package/dist/live/analytics.js +103 -0
- package/dist/live/client.d.ts +51 -0
- package/dist/live/client.js +193 -0
- package/dist/live/components.d.ts +64 -0
- package/dist/live/components.js +471 -0
- package/dist/live/context.d.ts +15 -0
- package/dist/live/context.js +28 -0
- package/dist/live/index.d.ts +7 -0
- package/dist/live/index.js +7 -0
- package/dist/live/protocol.d.ts +284 -0
- package/dist/live/protocol.js +42 -0
- package/dist/live/turnstile.js +49 -0
- package/dist/presenter/index.d.ts +20 -0
- package/dist/presenter/index.js +1211 -0
- package/dist/react/AutoAnimate.js +92 -0
- package/dist/react/Backgrounds.d.ts +11 -0
- package/dist/react/Backgrounds.js +154 -0
- package/dist/react/ConfettiLayer.js +85 -0
- package/dist/react/Deck.d.ts +35 -0
- package/dist/react/Deck.js +983 -0
- package/dist/react/Frame.d.ts +16 -0
- package/dist/react/Frame.js +174 -0
- package/dist/react/Hints.d.ts +3 -0
- package/dist/react/Hints.js +201 -0
- package/dist/react/Lightbox.js +54 -0
- package/dist/react/Overview.js +93 -0
- package/dist/react/PrintView.js +128 -0
- package/dist/react/ScrollView.js +128 -0
- package/dist/react/SlideFrame.d.ts +51 -0
- package/dist/react/SlideFrame.js +323 -0
- package/dist/react/Stage.js +151 -0
- package/dist/react/ThemeMenu.d.ts +5 -0
- package/dist/react/ThemeMenu.js +124 -0
- package/dist/react/Zoom.js +23 -0
- package/dist/react/chrome.js +339 -0
- package/dist/react/context.d.ts +165 -0
- package/dist/react/context.js +19 -0
- package/dist/react/hooks.d.ts +33 -0
- package/dist/react/hooks.js +70 -0
- package/dist/react/layouts.d.ts +21 -0
- package/dist/react/layouts.js +104 -0
- package/dist/react/mdx.d.ts +4 -0
- package/dist/react/mdx.js +33 -0
- package/dist/react/terms.d.ts +6 -0
- package/dist/react/terms.js +66 -0
- package/dist/renderers/Island.d.ts +57 -0
- package/dist/renderers/Island.js +223 -0
- package/dist/renderers/contract.d.ts +173 -0
- package/dist/renderers/contract.js +152 -0
- package/dist/renderers/index.d.ts +12 -0
- package/dist/renderers/index.js +16 -0
- package/dist/renderers/react.d.ts +16 -0
- package/dist/renderers/react.js +32 -0
- package/dist/renderers/web-components.d.ts +4 -0
- package/dist/renderers/web-components.js +103 -0
- package/dist/sketch/Canvas.js +49 -0
- package/dist/sketch/dsl.d.ts +131 -0
- package/dist/sketch/dsl.js +281 -0
- package/dist/sketch/index.d.ts +4 -0
- package/dist/sketch/index.js +3 -0
- package/dist/sketch/palette.d.ts +21 -0
- package/dist/sketch/palette.js +66 -0
- package/dist/sketch/render.d.ts +43 -0
- package/dist/sketch/render.js +198 -0
- package/dist/themes/base.css +1704 -0
- package/dist/themes/bling.css +592 -0
- package/dist/themes/glossary.css +317 -0
- package/dist/themes/live.css +1557 -0
- package/dist/themes/minimal.css +83 -0
- package/dist/themes/rla.css +92 -0
- package/dist/themes/sketch.css +121 -0
- package/dist/themes/stack.css +62 -0
- package/dist/vite/index.d.ts +15 -0
- package/dist/vite/index.js +320 -0
- package/package.json +159 -4
- package/tools/verify-island.mjs +150 -0
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { Store } from "../core/store.js";
|
|
2
|
+
import { ClientMessage, Role, RoomState, ServerMessage } from "./protocol.js";
|
|
3
|
+
//#region src/live/client.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* The room client: one WebSocket to the deck's room, reconnecting with backoff, holding the
|
|
6
|
+
* room state in a store the React layer subscribes to, and fanning transient messages (pointer,
|
|
7
|
+
* reactions, strokes) to listeners. Works offline too — every store just stays empty.
|
|
8
|
+
*/
|
|
9
|
+
export type Status = "idle" | "connecting" | "open" | "closed" | "offline";
|
|
10
|
+
export interface RoomClientOptions {
|
|
11
|
+
/** e.g. "/api" — the room lives at `${api}/rooms/${room}/ws`. */
|
|
12
|
+
api: string;
|
|
13
|
+
room: string;
|
|
14
|
+
role: Role;
|
|
15
|
+
viewer: string;
|
|
16
|
+
name?: string;
|
|
17
|
+
/** A one-off token appended to the URL (Turnstile), fetched before each connection attempt. */
|
|
18
|
+
token?: () => Promise<string | null>;
|
|
19
|
+
}
|
|
20
|
+
type Listener = (message: ServerMessage) => void;
|
|
21
|
+
export declare function viewerId(): string;
|
|
22
|
+
export declare class RoomClient {
|
|
23
|
+
private readonly options;
|
|
24
|
+
readonly state: Store<RoomState>;
|
|
25
|
+
readonly status: Store<Status>;
|
|
26
|
+
readonly role: Store<Role>;
|
|
27
|
+
private ws;
|
|
28
|
+
private listeners;
|
|
29
|
+
private attempts;
|
|
30
|
+
private closedByUs;
|
|
31
|
+
private timer;
|
|
32
|
+
private heartbeat;
|
|
33
|
+
private queue;
|
|
34
|
+
/** The position to announce on connect; kept current by the provider. */
|
|
35
|
+
position: {
|
|
36
|
+
h: number;
|
|
37
|
+
v: number;
|
|
38
|
+
click: number;
|
|
39
|
+
};
|
|
40
|
+
constructor(options: RoomClientOptions);
|
|
41
|
+
connect(): void;
|
|
42
|
+
private url;
|
|
43
|
+
private open;
|
|
44
|
+
private opening;
|
|
45
|
+
private start;
|
|
46
|
+
private raw;
|
|
47
|
+
send(m: ClientMessage): void;
|
|
48
|
+
on(listener: Listener): () => void;
|
|
49
|
+
close(): void;
|
|
50
|
+
}
|
|
51
|
+
//#endregion
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { createStore } from "../core/store.js";
|
|
2
|
+
import { EMPTY_ROOM } from "./protocol.js";
|
|
3
|
+
//#region src/live/client.ts
|
|
4
|
+
function viewerId() {
|
|
5
|
+
try {
|
|
6
|
+
const key = "deck.viewer";
|
|
7
|
+
let id = localStorage.getItem(key);
|
|
8
|
+
if (!id) {
|
|
9
|
+
id = `v_${Math.random().toString(36).slice(2, 12)}${Date.now().toString(36)}`;
|
|
10
|
+
localStorage.setItem(key, id);
|
|
11
|
+
}
|
|
12
|
+
return id;
|
|
13
|
+
} catch {
|
|
14
|
+
return `v_${Math.random().toString(36).slice(2, 12)}`;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
var RoomClient = class {
|
|
18
|
+
options;
|
|
19
|
+
state = createStore(EMPTY_ROOM);
|
|
20
|
+
status = createStore("idle");
|
|
21
|
+
role = createStore("viewer");
|
|
22
|
+
ws = null;
|
|
23
|
+
listeners = /* @__PURE__ */ new Set();
|
|
24
|
+
attempts = 0;
|
|
25
|
+
closedByUs = false;
|
|
26
|
+
timer = null;
|
|
27
|
+
heartbeat = null;
|
|
28
|
+
queue = [];
|
|
29
|
+
/** The position to announce on connect; kept current by the provider. */
|
|
30
|
+
position = {
|
|
31
|
+
h: 0,
|
|
32
|
+
v: 0,
|
|
33
|
+
click: 0
|
|
34
|
+
};
|
|
35
|
+
constructor(options) {
|
|
36
|
+
this.options = options;
|
|
37
|
+
}
|
|
38
|
+
connect() {
|
|
39
|
+
if (typeof window === "undefined") return;
|
|
40
|
+
this.closedByUs = false;
|
|
41
|
+
this.open();
|
|
42
|
+
}
|
|
43
|
+
url(token) {
|
|
44
|
+
const proto = window.location.protocol === "https:" ? "wss:" : "ws:";
|
|
45
|
+
const base = this.options.api.startsWith("http") ? this.options.api.replace(/^http/, "ws") : `${proto}//${window.location.host}${this.options.api}`;
|
|
46
|
+
const q = new URLSearchParams({ role: this.options.role });
|
|
47
|
+
if (token) q.set("t", token);
|
|
48
|
+
return `${base}/rooms/${encodeURIComponent(this.options.room)}/ws?${q}`;
|
|
49
|
+
}
|
|
50
|
+
open() {
|
|
51
|
+
if (this.ws || this.opening) return;
|
|
52
|
+
this.status.set("connecting");
|
|
53
|
+
this.opening = true;
|
|
54
|
+
const start = (token) => {
|
|
55
|
+
this.opening = false;
|
|
56
|
+
if (this.closedByUs) return;
|
|
57
|
+
this.start(token);
|
|
58
|
+
};
|
|
59
|
+
if (this.options.token) this.options.token().then(start, () => start(null));
|
|
60
|
+
else start(null);
|
|
61
|
+
}
|
|
62
|
+
opening = false;
|
|
63
|
+
start(token) {
|
|
64
|
+
let ws;
|
|
65
|
+
try {
|
|
66
|
+
ws = new WebSocket(this.url(token));
|
|
67
|
+
} catch {
|
|
68
|
+
this.status.set("offline");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.ws = ws;
|
|
72
|
+
ws.onopen = () => {
|
|
73
|
+
this.attempts = 0;
|
|
74
|
+
this.status.set("open");
|
|
75
|
+
this.raw({
|
|
76
|
+
type: "hello",
|
|
77
|
+
role: this.options.role,
|
|
78
|
+
viewer: this.options.viewer,
|
|
79
|
+
name: this.options.name,
|
|
80
|
+
position: this.position
|
|
81
|
+
});
|
|
82
|
+
for (const m of this.queue.splice(0)) this.raw(m);
|
|
83
|
+
this.heartbeat = setInterval(() => this.raw({ type: "ping" }), 25e3);
|
|
84
|
+
};
|
|
85
|
+
ws.onmessage = (e) => {
|
|
86
|
+
let m;
|
|
87
|
+
try {
|
|
88
|
+
m = JSON.parse(String(e.data));
|
|
89
|
+
} catch {
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (m.type === "welcome") {
|
|
93
|
+
this.role.set(m.role);
|
|
94
|
+
const drawings = {};
|
|
95
|
+
for (const [k, list] of Object.entries(m.state.drawings)) drawings[k] = list.filter((s) => !s.fade);
|
|
96
|
+
this.state.set({
|
|
97
|
+
...m.state,
|
|
98
|
+
drawings
|
|
99
|
+
});
|
|
100
|
+
} else if (m.type === "state") this.state.update((s) => ({
|
|
101
|
+
...s,
|
|
102
|
+
...m.patch
|
|
103
|
+
}));
|
|
104
|
+
else if (m.type === "nav") this.state.update((s) => ({
|
|
105
|
+
...s,
|
|
106
|
+
position: m.position,
|
|
107
|
+
term: null
|
|
108
|
+
}));
|
|
109
|
+
else if (m.type === "term") this.state.update((s) => ({
|
|
110
|
+
...s,
|
|
111
|
+
term: {
|
|
112
|
+
slide: m.slide,
|
|
113
|
+
id: m.id,
|
|
114
|
+
n: m.n,
|
|
115
|
+
view: m.view
|
|
116
|
+
}
|
|
117
|
+
}));
|
|
118
|
+
else if (m.type === "term:off") this.state.update((s) => s.term ? {
|
|
119
|
+
...s,
|
|
120
|
+
term: null
|
|
121
|
+
} : s);
|
|
122
|
+
else if (m.type === "pointer") this.state.update((s) => ({
|
|
123
|
+
...s,
|
|
124
|
+
pointer: {
|
|
125
|
+
x: m.x,
|
|
126
|
+
y: m.y
|
|
127
|
+
}
|
|
128
|
+
}));
|
|
129
|
+
else if (m.type === "pointer:off") this.state.update((s) => s.pointer ? {
|
|
130
|
+
...s,
|
|
131
|
+
pointer: null
|
|
132
|
+
} : s);
|
|
133
|
+
else if (m.type === "draw") this.state.update((s) => ({
|
|
134
|
+
...s,
|
|
135
|
+
drawings: {
|
|
136
|
+
...s.drawings,
|
|
137
|
+
[m.slide]: [...(s.drawings[m.slide] ?? []).filter((x) => x.id !== m.stroke.id), m.stroke]
|
|
138
|
+
}
|
|
139
|
+
}));
|
|
140
|
+
else if (m.type === "draw:undo") this.state.update((s) => ({
|
|
141
|
+
...s,
|
|
142
|
+
drawings: {
|
|
143
|
+
...s.drawings,
|
|
144
|
+
[m.slide]: (s.drawings[m.slide] ?? []).slice(0, -1)
|
|
145
|
+
}
|
|
146
|
+
}));
|
|
147
|
+
else if (m.type === "draw:clear") this.state.update((s) => ({
|
|
148
|
+
...s,
|
|
149
|
+
drawings: {
|
|
150
|
+
...s.drawings,
|
|
151
|
+
[m.slide]: []
|
|
152
|
+
}
|
|
153
|
+
}));
|
|
154
|
+
for (const l of this.listeners) l(m);
|
|
155
|
+
};
|
|
156
|
+
ws.onclose = () => {
|
|
157
|
+
this.ws = null;
|
|
158
|
+
if (this.heartbeat) clearInterval(this.heartbeat);
|
|
159
|
+
this.heartbeat = null;
|
|
160
|
+
if (this.closedByUs) {
|
|
161
|
+
this.status.set("closed");
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
this.status.set(this.attempts > 4 ? "offline" : "closed");
|
|
165
|
+
const delay = Math.min(15e3, 500 * 2 ** this.attempts++);
|
|
166
|
+
this.timer = setTimeout(() => this.open(), delay);
|
|
167
|
+
};
|
|
168
|
+
ws.onerror = () => {};
|
|
169
|
+
}
|
|
170
|
+
raw(m) {
|
|
171
|
+
if (this.ws?.readyState === WebSocket.OPEN) this.ws.send(JSON.stringify(m));
|
|
172
|
+
}
|
|
173
|
+
send(m) {
|
|
174
|
+
if (this.ws?.readyState === WebSocket.OPEN) this.raw(m);
|
|
175
|
+
else if (m.type !== "pointer" && m.type !== "presence" && m.type !== "ping") this.queue.push(m);
|
|
176
|
+
}
|
|
177
|
+
on(listener) {
|
|
178
|
+
this.listeners.add(listener);
|
|
179
|
+
return () => {
|
|
180
|
+
this.listeners.delete(listener);
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
close() {
|
|
184
|
+
this.closedByUs = true;
|
|
185
|
+
if (this.timer) clearTimeout(this.timer);
|
|
186
|
+
if (this.heartbeat) clearInterval(this.heartbeat);
|
|
187
|
+
this.ws?.close();
|
|
188
|
+
this.ws = null;
|
|
189
|
+
this.status.set("closed");
|
|
190
|
+
}
|
|
191
|
+
};
|
|
192
|
+
//#endregion
|
|
193
|
+
export { RoomClient, viewerId };
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { PollKind } from "./protocol.js";
|
|
2
|
+
import { ReactNode } from "react";
|
|
3
|
+
//#region src/live/components.d.ts
|
|
4
|
+
/** The QR code and short URL for the audience page. */
|
|
5
|
+
export declare function QrJoin({ size, caption, className }: {
|
|
6
|
+
size?: number;
|
|
7
|
+
caption?: string;
|
|
8
|
+
className?: string;
|
|
9
|
+
}): import("react").JSX.Element;
|
|
10
|
+
/** How many are watching. */
|
|
11
|
+
export declare function Presence({ className }: {
|
|
12
|
+
className?: string;
|
|
13
|
+
}): import("react").JSX.Element | null;
|
|
14
|
+
/** The reaction bar (for slides that invite it; the audience page has its own). */
|
|
15
|
+
export declare function Reactions({ className }: {
|
|
16
|
+
className?: string;
|
|
17
|
+
}): import("react").JSX.Element;
|
|
18
|
+
export interface PollProps {
|
|
19
|
+
id: string;
|
|
20
|
+
question: string;
|
|
21
|
+
options?: string[];
|
|
22
|
+
kind?: PollKind;
|
|
23
|
+
scale?: number;
|
|
24
|
+
/** Show results as they come, or only once closed. */
|
|
25
|
+
liveResults?: boolean;
|
|
26
|
+
className?: string;
|
|
27
|
+
}
|
|
28
|
+
/** A poll: defined by the slide, opened by the presenter, answered from the audience page or here. */
|
|
29
|
+
export declare function Poll({ id, question, options, kind, scale, liveResults, className }: PollProps): import("react").JSX.Element;
|
|
30
|
+
export declare function WordCloudView({ words }: {
|
|
31
|
+
words: Record<string, number>;
|
|
32
|
+
}): import("react").JSX.Element;
|
|
33
|
+
export declare function WordCloud({ id, question, className }: {
|
|
34
|
+
id: string;
|
|
35
|
+
question: string;
|
|
36
|
+
className?: string;
|
|
37
|
+
}): import("react").JSX.Element;
|
|
38
|
+
export interface QuizProps {
|
|
39
|
+
id: string;
|
|
40
|
+
question: string;
|
|
41
|
+
options: string[];
|
|
42
|
+
correct: number;
|
|
43
|
+
seconds?: number;
|
|
44
|
+
className?: string;
|
|
45
|
+
}
|
|
46
|
+
/** A timed quiz question with points for speed and a leaderboard. */
|
|
47
|
+
export declare function Quiz({ id, question, options, correct, seconds, className }: QuizProps): import("react").JSX.Element;
|
|
48
|
+
export declare function nickname(): string;
|
|
49
|
+
/** The leaderboard across every quiz in the room. */
|
|
50
|
+
export declare function Leaderboard({ top, className }: {
|
|
51
|
+
top?: number;
|
|
52
|
+
className?: string;
|
|
53
|
+
}): import("react").JSX.Element;
|
|
54
|
+
/** Questions from the audience, on a slide: most voted first, answered ones dimmed. */
|
|
55
|
+
export declare function Questions({ limit, className, children }: {
|
|
56
|
+
limit?: number;
|
|
57
|
+
className?: string;
|
|
58
|
+
children?: ReactNode;
|
|
59
|
+
}): import("react").JSX.Element;
|
|
60
|
+
/** A gauge of the audience's pace feedback: are they asking for slower or faster? */
|
|
61
|
+
export declare function Pace({ className }: {
|
|
62
|
+
className?: string;
|
|
63
|
+
}): import("react").JSX.Element;
|
|
64
|
+
//#endregion
|