@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,74 @@
|
|
|
1
|
+
import { Column, DeckConfig } from "./model.js";
|
|
2
|
+
declare namespace navigation_d_exports {
|
|
3
|
+
export { Direction, NavState, Position, Routes, availableRoutes, clampPosition, down, first, formatSlideNumber, goto, initialNav, key, last, left, next, nextClick, prev, prevClick, progressOf, right, setTotal, up };
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
7
|
+
* NAVIGATION
|
|
8
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
9
|
+
*
|
|
10
|
+
* Where the deck is and how it got there. `click` is the step within a slide (reveal.js's
|
|
11
|
+
* fragment index, Slidev's click); `direction` is what the transition reads. Everything is a pure
|
|
12
|
+
* function of the state and the click totals the runtime reports, so the presenter window, the
|
|
13
|
+
* live room and the keyboard all drive the same reducer.
|
|
14
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
15
|
+
*/
|
|
16
|
+
export type Direction = "none" | "forward" | "back" | "up" | "down";
|
|
17
|
+
export interface Position {
|
|
18
|
+
h: number;
|
|
19
|
+
v: number;
|
|
20
|
+
click: number;
|
|
21
|
+
}
|
|
22
|
+
export interface NavState extends Position {
|
|
23
|
+
direction: Direction;
|
|
24
|
+
overview: boolean;
|
|
25
|
+
paused: boolean;
|
|
26
|
+
autoSliding: boolean;
|
|
27
|
+
/** Per visible slide: how many clicks the runtime has registered (by "h,v"). */
|
|
28
|
+
totals: Record<string, number>;
|
|
29
|
+
/** The position the presenter is at, when this window follows one and is not the presenter. */
|
|
30
|
+
presenter: Position | null;
|
|
31
|
+
/** Whether this window follows the presenter's navigation. */
|
|
32
|
+
follow: boolean;
|
|
33
|
+
/** A visible slide id → clamped ok; set by `goto` for hash routing. */
|
|
34
|
+
seq: number;
|
|
35
|
+
}
|
|
36
|
+
export declare const key: (h: number, v: number) => string;
|
|
37
|
+
export declare function initialNav(): NavState;
|
|
38
|
+
export declare function clampPosition(columns: Column[], p: Partial<Position>): Position;
|
|
39
|
+
export interface Routes {
|
|
40
|
+
left: boolean;
|
|
41
|
+
right: boolean;
|
|
42
|
+
up: boolean;
|
|
43
|
+
down: boolean;
|
|
44
|
+
prevClick: boolean;
|
|
45
|
+
nextClick: boolean;
|
|
46
|
+
}
|
|
47
|
+
export declare function availableRoutes(state: NavState, columns: Column[], config: DeckConfig): Routes;
|
|
48
|
+
/** Move to an exact position (a hash, a link, the presenter). Clicks default to 0. */
|
|
49
|
+
export declare function goto(state: NavState, columns: Column[], to: Partial<Position>): NavState;
|
|
50
|
+
export declare function right(state: NavState, columns: Column[], config: DeckConfig): NavState;
|
|
51
|
+
export declare function left(state: NavState, columns: Column[], config: DeckConfig): NavState;
|
|
52
|
+
export declare function down(state: NavState, columns: Column[]): NavState;
|
|
53
|
+
export declare function up(state: NavState, columns: Column[]): NavState;
|
|
54
|
+
export declare function nextClick(state: NavState): NavState;
|
|
55
|
+
export declare function prevClick(state: NavState): NavState;
|
|
56
|
+
/**
|
|
57
|
+
* `next`: the next click, else the slide beneath, else the next column. In linear mode the deck
|
|
58
|
+
* reads like a book: every vertical slide is a page. Matches reveal.js's space bar.
|
|
59
|
+
*/
|
|
60
|
+
export declare function next(state: NavState, columns: Column[], config: DeckConfig): NavState;
|
|
61
|
+
/** `prev`: the previous click, else the slide above, else the previous column. */
|
|
62
|
+
export declare function prev(state: NavState, columns: Column[], config: DeckConfig, opts?: {
|
|
63
|
+
toLastClick?: boolean;
|
|
64
|
+
}): NavState;
|
|
65
|
+
export declare function first(state: NavState, columns: Column[]): NavState;
|
|
66
|
+
export declare function last(state: NavState, columns: Column[]): NavState;
|
|
67
|
+
/** Record the click total the runtime found for a slide; clamps the current click if needed. */
|
|
68
|
+
export declare function setTotal(state: NavState, h: number, v: number, total: number): NavState;
|
|
69
|
+
/** 0 at the first slide, 1 at the last. */
|
|
70
|
+
export declare function progressOf(state: NavState, columns: Column[]): number;
|
|
71
|
+
/** Format the slide number the way reveal.js does. */
|
|
72
|
+
export declare function formatSlideNumber(format: true | "h.v" | "h/v" | "c" | "c/t", state: Position, columns: Column[], oneBased?: boolean): string;
|
|
73
|
+
//#endregion
|
|
74
|
+
export { navigation_d_exports };
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
import { __exportAll } from "../_virtual/_rolldown/runtime.js";
|
|
2
|
+
//#region src/core/navigation.ts
|
|
3
|
+
var navigation_exports = /* @__PURE__ */ __exportAll({
|
|
4
|
+
availableRoutes: () => availableRoutes,
|
|
5
|
+
clampPosition: () => clampPosition,
|
|
6
|
+
down: () => down,
|
|
7
|
+
first: () => first,
|
|
8
|
+
formatSlideNumber: () => formatSlideNumber,
|
|
9
|
+
goto: () => goto,
|
|
10
|
+
initialNav: () => initialNav,
|
|
11
|
+
key: () => key,
|
|
12
|
+
last: () => last,
|
|
13
|
+
left: () => left,
|
|
14
|
+
next: () => next,
|
|
15
|
+
nextClick: () => nextClick,
|
|
16
|
+
prev: () => prev,
|
|
17
|
+
prevClick: () => prevClick,
|
|
18
|
+
progressOf: () => progressOf,
|
|
19
|
+
right: () => right,
|
|
20
|
+
setTotal: () => setTotal,
|
|
21
|
+
up: () => up
|
|
22
|
+
});
|
|
23
|
+
const key = (h, v) => `${h},${v}`;
|
|
24
|
+
function initialNav() {
|
|
25
|
+
return {
|
|
26
|
+
h: 0,
|
|
27
|
+
v: 0,
|
|
28
|
+
click: 0,
|
|
29
|
+
direction: "none",
|
|
30
|
+
overview: false,
|
|
31
|
+
paused: false,
|
|
32
|
+
autoSliding: false,
|
|
33
|
+
totals: {},
|
|
34
|
+
presenter: null,
|
|
35
|
+
follow: true,
|
|
36
|
+
seq: 0
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
function clampPosition(columns, p) {
|
|
40
|
+
const h = Math.min(Math.max(0, p.h ?? 0), Math.max(0, columns.length - 1));
|
|
41
|
+
const col = columns[h];
|
|
42
|
+
return {
|
|
43
|
+
h,
|
|
44
|
+
v: Math.min(Math.max(0, p.v ?? 0), Math.max(0, (col?.slides.length ?? 1) - 1)),
|
|
45
|
+
click: Math.max(0, p.click ?? 0)
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
function availableRoutes(state, columns, config) {
|
|
49
|
+
const col = columns[state.h];
|
|
50
|
+
const total = state.totals[key(state.h, state.v)] ?? 0;
|
|
51
|
+
const left = state.h > 0 || config.loop;
|
|
52
|
+
const right = state.h < columns.length - 1 || config.loop;
|
|
53
|
+
return {
|
|
54
|
+
left: config.rtl ? right : left,
|
|
55
|
+
right: config.rtl ? left : right,
|
|
56
|
+
up: state.v > 0,
|
|
57
|
+
down: !!col && state.v < col.slides.length - 1,
|
|
58
|
+
prevClick: state.click > 0,
|
|
59
|
+
nextClick: state.click < total
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
function step(state, next, direction, columns) {
|
|
63
|
+
const p = clampPosition(columns, {
|
|
64
|
+
...state,
|
|
65
|
+
...next
|
|
66
|
+
});
|
|
67
|
+
return {
|
|
68
|
+
...state,
|
|
69
|
+
...p,
|
|
70
|
+
direction,
|
|
71
|
+
seq: state.seq + 1
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
/** Move to an exact position (a hash, a link, the presenter). Clicks default to 0. */
|
|
75
|
+
function goto(state, columns, to) {
|
|
76
|
+
const p = clampPosition(columns, {
|
|
77
|
+
h: to.h ?? state.h,
|
|
78
|
+
v: to.v ?? state.v,
|
|
79
|
+
click: to.click ?? 0
|
|
80
|
+
});
|
|
81
|
+
const direction = p.h > state.h ? "forward" : p.h < state.h ? "back" : p.v > state.v ? "down" : p.v < state.v ? "up" : "none";
|
|
82
|
+
return {
|
|
83
|
+
...state,
|
|
84
|
+
...p,
|
|
85
|
+
direction,
|
|
86
|
+
seq: state.seq + 1
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
function right(state, columns, config) {
|
|
90
|
+
const last = columns.length - 1;
|
|
91
|
+
if (state.h < last) {
|
|
92
|
+
const v = config.navigationMode === "grid" ? Math.min(state.v, columns[state.h + 1].slides.length - 1) : 0;
|
|
93
|
+
return step(state, {
|
|
94
|
+
h: state.h + 1,
|
|
95
|
+
v,
|
|
96
|
+
click: 0
|
|
97
|
+
}, "forward", columns);
|
|
98
|
+
}
|
|
99
|
+
if (config.loop) return step(state, {
|
|
100
|
+
h: 0,
|
|
101
|
+
v: 0,
|
|
102
|
+
click: 0
|
|
103
|
+
}, "forward", columns);
|
|
104
|
+
return state;
|
|
105
|
+
}
|
|
106
|
+
function left(state, columns, config) {
|
|
107
|
+
if (state.h > 0) {
|
|
108
|
+
const col = columns[state.h - 1];
|
|
109
|
+
const v = config.navigationMode === "grid" ? Math.min(state.v, col.slides.length - 1) : config.navigationMode === "linear" ? col.slides.length - 1 : 0;
|
|
110
|
+
return step(state, {
|
|
111
|
+
h: state.h - 1,
|
|
112
|
+
v,
|
|
113
|
+
click: 0
|
|
114
|
+
}, "back", columns);
|
|
115
|
+
}
|
|
116
|
+
if (config.loop) return step(state, {
|
|
117
|
+
h: columns.length - 1,
|
|
118
|
+
v: 0,
|
|
119
|
+
click: 0
|
|
120
|
+
}, "back", columns);
|
|
121
|
+
return state;
|
|
122
|
+
}
|
|
123
|
+
function down(state, columns) {
|
|
124
|
+
const col = columns[state.h];
|
|
125
|
+
if (col && state.v < col.slides.length - 1) return step(state, {
|
|
126
|
+
v: state.v + 1,
|
|
127
|
+
click: 0
|
|
128
|
+
}, "down", columns);
|
|
129
|
+
return state;
|
|
130
|
+
}
|
|
131
|
+
function up(state, columns) {
|
|
132
|
+
if (state.v > 0) return step(state, {
|
|
133
|
+
v: state.v - 1,
|
|
134
|
+
click: 0
|
|
135
|
+
}, "up", columns);
|
|
136
|
+
return state;
|
|
137
|
+
}
|
|
138
|
+
function nextClick(state) {
|
|
139
|
+
const total = state.totals[key(state.h, state.v)] ?? 0;
|
|
140
|
+
if (state.click < total) return {
|
|
141
|
+
...state,
|
|
142
|
+
click: state.click + 1,
|
|
143
|
+
direction: "forward",
|
|
144
|
+
seq: state.seq + 1
|
|
145
|
+
};
|
|
146
|
+
return state;
|
|
147
|
+
}
|
|
148
|
+
function prevClick(state) {
|
|
149
|
+
if (state.click > 0) return {
|
|
150
|
+
...state,
|
|
151
|
+
click: state.click - 1,
|
|
152
|
+
direction: "back",
|
|
153
|
+
seq: state.seq + 1
|
|
154
|
+
};
|
|
155
|
+
return state;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* `next`: the next click, else the slide beneath, else the next column. In linear mode the deck
|
|
159
|
+
* reads like a book: every vertical slide is a page. Matches reveal.js's space bar.
|
|
160
|
+
*/
|
|
161
|
+
function next(state, columns, config) {
|
|
162
|
+
const clicked = nextClick(state);
|
|
163
|
+
if (clicked !== state) return clicked;
|
|
164
|
+
const routes = availableRoutes(state, columns, config);
|
|
165
|
+
if (routes.down) return down(state, columns);
|
|
166
|
+
if (config.rtl ? routes.left : routes.right) return config.rtl ? left(state, columns, config) : right(state, columns, config);
|
|
167
|
+
return state;
|
|
168
|
+
}
|
|
169
|
+
/** `prev`: the previous click, else the slide above, else the previous column. */
|
|
170
|
+
function prev(state, columns, config, opts = {}) {
|
|
171
|
+
const unclicked = prevClick(state);
|
|
172
|
+
if (unclicked !== state) return unclicked;
|
|
173
|
+
const routes = availableRoutes(state, columns, config);
|
|
174
|
+
let moved = state;
|
|
175
|
+
if (routes.up) moved = up(state, columns);
|
|
176
|
+
else if (config.rtl ? routes.right : routes.left) moved = config.rtl ? right(state, columns, config) : left(state, columns, config);
|
|
177
|
+
if (moved === state) return state;
|
|
178
|
+
if (opts.toLastClick !== false) {
|
|
179
|
+
const total = moved.totals[key(moved.h, moved.v)] ?? 0;
|
|
180
|
+
return {
|
|
181
|
+
...moved,
|
|
182
|
+
click: total
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
return moved;
|
|
186
|
+
}
|
|
187
|
+
function first(state, columns) {
|
|
188
|
+
return step(state, {
|
|
189
|
+
h: 0,
|
|
190
|
+
v: 0,
|
|
191
|
+
click: 0
|
|
192
|
+
}, "back", columns);
|
|
193
|
+
}
|
|
194
|
+
function last(state, columns) {
|
|
195
|
+
const h = Math.max(0, columns.length - 1);
|
|
196
|
+
return step(state, {
|
|
197
|
+
h,
|
|
198
|
+
v: Math.max(0, (columns[h]?.slides.length ?? 1) - 1),
|
|
199
|
+
click: 0
|
|
200
|
+
}, "forward", columns);
|
|
201
|
+
}
|
|
202
|
+
/** Record the click total the runtime found for a slide; clamps the current click if needed. */
|
|
203
|
+
function setTotal(state, h, v, total) {
|
|
204
|
+
const k = key(h, v);
|
|
205
|
+
if (state.totals[k] === total) return state;
|
|
206
|
+
const totals = {
|
|
207
|
+
...state.totals,
|
|
208
|
+
[k]: total
|
|
209
|
+
};
|
|
210
|
+
const click = h === state.h && v === state.v ? Math.min(state.click, total) : state.click;
|
|
211
|
+
return {
|
|
212
|
+
...state,
|
|
213
|
+
totals,
|
|
214
|
+
click
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
/** 0 at the first slide, 1 at the last. */
|
|
218
|
+
function progressOf(state, columns) {
|
|
219
|
+
const total = columns.reduce((n, c) => n + c.slides.length, 0);
|
|
220
|
+
if (total <= 1) return 1;
|
|
221
|
+
let flat = 0;
|
|
222
|
+
for (let i = 0; i < state.h; i++) flat += columns[i].slides.length;
|
|
223
|
+
flat += state.v;
|
|
224
|
+
return flat / (total - 1);
|
|
225
|
+
}
|
|
226
|
+
/** Format the slide number the way reveal.js does. */
|
|
227
|
+
function formatSlideNumber(format, state, columns, oneBased = true) {
|
|
228
|
+
const offset = oneBased ? 1 : 0;
|
|
229
|
+
const flat = (() => {
|
|
230
|
+
let n = 0;
|
|
231
|
+
for (let i = 0; i < state.h; i++) n += columns[i].slides.length;
|
|
232
|
+
return n + state.v + offset;
|
|
233
|
+
})();
|
|
234
|
+
const total = columns.reduce((n, c) => n + c.slides.length, 0);
|
|
235
|
+
const hasVertical = columns.some((c) => c.slides.length > 1);
|
|
236
|
+
switch (format) {
|
|
237
|
+
case "c": return String(flat);
|
|
238
|
+
case "c/t": return `${flat} / ${total}`;
|
|
239
|
+
case "h/v": return hasVertical && state.v > 0 ? `${state.h + offset} / ${state.v + offset}` : String(state.h + offset);
|
|
240
|
+
default: return hasVertical && state.v > 0 ? `${state.h + offset}.${state.v + offset}` : String(state.h + offset);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
//#endregion
|
|
244
|
+
export { availableRoutes, clampPosition, down, first, formatSlideNumber, goto, initialNav, key, last, left, navigation_exports, next, nextClick, prev, prevClick, progressOf, right, setTotal, up };
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
//#region src/core/poster.ts
|
|
2
|
+
/**
|
|
3
|
+
* Posters stand in for an embedded page wherever it cannot be live: the print pages, the
|
|
4
|
+
* overview tiles, the presenter's next-slide box, the scroll view — and behind the shield while
|
|
5
|
+
* the real page loads. A deck names one (`poster: shots/map.jpg` on an iframe slide, or
|
|
6
|
+
* `<Iframe poster>`); without one, `deck export` captures a screenshot of the URL at the pane's
|
|
7
|
+
* size into `public/posters/` under a name both sides derive from the URL, so nothing else has
|
|
8
|
+
* to be wired.
|
|
9
|
+
*/
|
|
10
|
+
const POSTER_DEFAULT_SIZE = [1600, 900];
|
|
11
|
+
/** FNV-1a over the URL, in base 36: short, stable, filename-safe. */
|
|
12
|
+
function posterHash(url) {
|
|
13
|
+
let h = 2166136261;
|
|
14
|
+
for (let i = 0; i < url.length; i++) {
|
|
15
|
+
h ^= url.charCodeAt(i);
|
|
16
|
+
h = Math.imul(h, 16777619);
|
|
17
|
+
}
|
|
18
|
+
return (h >>> 0).toString(36);
|
|
19
|
+
}
|
|
20
|
+
/** The path under `public/` where a captured poster for this URL at this pane size lives. */
|
|
21
|
+
function posterName(url, width, height) {
|
|
22
|
+
return `posters/${posterHash(url)}@${Math.round(width)}x${Math.round(height)}.jpg`;
|
|
23
|
+
}
|
|
24
|
+
/** A poster path as written in a deck → a URL the page can load. */
|
|
25
|
+
function resolvePoster(path, base) {
|
|
26
|
+
if (/^(https?:)?\/\//.test(path) || path.startsWith("data:") || path.startsWith("/")) return path;
|
|
27
|
+
return `${base.replace(/\/?$/, "/")}${path}`;
|
|
28
|
+
}
|
|
29
|
+
//#endregion
|
|
30
|
+
export { POSTER_DEFAULT_SIZE, posterHash, posterName, resolvePoster };
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
//#region src/core/store.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* A minimal external store: one value, subscribers, selectors through `useSyncExternalStore`.
|
|
4
|
+
* The deck keeps its navigation state here rather than in React state so the keyboard, the hash,
|
|
5
|
+
* the live room and the presenter window can all read and write it without a render in between.
|
|
6
|
+
*/
|
|
7
|
+
export interface Store<T> {
|
|
8
|
+
get(): T;
|
|
9
|
+
set(next: T): void;
|
|
10
|
+
update(fn: (prev: T) => T): void;
|
|
11
|
+
subscribe(listener: (value: T, prev: T) => void): () => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createStore<T>(initial: T): Store<T>;
|
|
14
|
+
/**
|
|
15
|
+
* Read a slice of a store; re-renders only when the selected slice changes. Selectors may return
|
|
16
|
+
* fresh objects (`(s) => ({ h: s.h, v: s.v })`): the last result is kept and returned again while
|
|
17
|
+
* it is shallow-equal, which is what keeps `useSyncExternalStore` from looping.
|
|
18
|
+
*/
|
|
19
|
+
export declare function useStore<T, S = T>(store: Store<T>, selector?: (value: T) => S): S;
|
|
20
|
+
//#endregion
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import { useRef, useSyncExternalStore } from "react";
|
|
2
|
+
//#region src/core/store.ts
|
|
3
|
+
function createStore(initial) {
|
|
4
|
+
let value = initial;
|
|
5
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
6
|
+
return {
|
|
7
|
+
get: () => value,
|
|
8
|
+
set(next) {
|
|
9
|
+
if (Object.is(next, value)) return;
|
|
10
|
+
const prev = value;
|
|
11
|
+
value = next;
|
|
12
|
+
for (const l of listeners) l(value, prev);
|
|
13
|
+
},
|
|
14
|
+
update(fn) {
|
|
15
|
+
this.set(fn(value));
|
|
16
|
+
},
|
|
17
|
+
subscribe(listener) {
|
|
18
|
+
listeners.add(listener);
|
|
19
|
+
return () => {
|
|
20
|
+
listeners.delete(listener);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
}
|
|
25
|
+
const identity = (v) => v;
|
|
26
|
+
function shallowEqual(a, b) {
|
|
27
|
+
if (Object.is(a, b)) return true;
|
|
28
|
+
if (typeof a !== "object" || typeof b !== "object" || a === null || b === null) return false;
|
|
29
|
+
if (Array.isArray(a) !== Array.isArray(b)) return false;
|
|
30
|
+
const ka = Object.keys(a);
|
|
31
|
+
const kb = Object.keys(b);
|
|
32
|
+
if (ka.length !== kb.length) return false;
|
|
33
|
+
for (const k of ka) if (!Object.is(a[k], b[k])) return false;
|
|
34
|
+
return true;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Read a slice of a store; re-renders only when the selected slice changes. Selectors may return
|
|
38
|
+
* fresh objects (`(s) => ({ h: s.h, v: s.v })`): the last result is kept and returned again while
|
|
39
|
+
* it is shallow-equal, which is what keeps `useSyncExternalStore` from looping.
|
|
40
|
+
*/
|
|
41
|
+
function useStore(store, selector = identity) {
|
|
42
|
+
const last = useRef(null);
|
|
43
|
+
const snapshot = () => {
|
|
44
|
+
const input = store.get();
|
|
45
|
+
const cached = last.current;
|
|
46
|
+
if (cached && Object.is(cached.input, input)) return cached.output;
|
|
47
|
+
const output = selector(input);
|
|
48
|
+
if (cached && shallowEqual(cached.output, output)) {
|
|
49
|
+
last.current = {
|
|
50
|
+
input,
|
|
51
|
+
output: cached.output
|
|
52
|
+
};
|
|
53
|
+
return cached.output;
|
|
54
|
+
}
|
|
55
|
+
last.current = {
|
|
56
|
+
input,
|
|
57
|
+
output
|
|
58
|
+
};
|
|
59
|
+
return output;
|
|
60
|
+
};
|
|
61
|
+
return useSyncExternalStore((cb) => store.subscribe(() => cb()), snapshot, snapshot);
|
|
62
|
+
}
|
|
63
|
+
//#endregion
|
|
64
|
+
export { createStore, useStore };
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
//#region src/core/touch.ts
|
|
2
|
+
function createSwipeTracker(threshold = 40, maxDuration = 800) {
|
|
3
|
+
let sx = 0;
|
|
4
|
+
let sy = 0;
|
|
5
|
+
let st = 0;
|
|
6
|
+
let active = false;
|
|
7
|
+
return {
|
|
8
|
+
start(x, y, t) {
|
|
9
|
+
sx = x;
|
|
10
|
+
sy = y;
|
|
11
|
+
st = t;
|
|
12
|
+
active = true;
|
|
13
|
+
},
|
|
14
|
+
end(x, y, t) {
|
|
15
|
+
if (!active) return null;
|
|
16
|
+
active = false;
|
|
17
|
+
if (t - st > maxDuration) return null;
|
|
18
|
+
const dx = x - sx;
|
|
19
|
+
const dy = y - sy;
|
|
20
|
+
if (Math.abs(dx) < threshold && Math.abs(dy) < threshold) return null;
|
|
21
|
+
if (Math.abs(dx) > Math.abs(dy)) return dx < 0 ? "left" : "right";
|
|
22
|
+
return dy < 0 ? "up" : "down";
|
|
23
|
+
}
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
//#endregion
|
|
27
|
+
export { createSwipeTracker };
|