@texuli/deck 0.0.0-stage → 0.5.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 +21 -0
- package/README.md +183 -2
- package/dist/authoring/builder.d.ts +351 -0
- package/dist/authoring/builder.js +64 -0
- package/dist/authoring/index.d.ts +6 -0
- package/dist/authoring/index.js +6 -0
- package/dist/authoring/lint.d.ts +36 -0
- package/dist/authoring/lint.js +325 -0
- package/dist/authoring/outlines.d.ts +34 -0
- package/dist/authoring/outlines.js +255 -0
- package/dist/authoring/patch.d.ts +23 -0
- package/dist/authoring/patch.js +166 -0
- package/dist/authoring/select-layouts.d.ts +19 -0
- package/dist/authoring/select-layouts.js +90 -0
- package/dist/engine/auto-slide.d.ts +32 -0
- package/dist/engine/auto-slide.js +67 -0
- package/dist/engine/canvas.d.ts +56 -0
- package/dist/engine/canvas.js +48 -0
- package/dist/engine/controller.d.ts +126 -0
- package/dist/engine/controller.js +248 -0
- package/dist/engine/controls.d.ts +128 -0
- package/dist/engine/controls.js +460 -0
- package/dist/engine/hash.d.ts +42 -0
- package/dist/engine/hash.js +86 -0
- package/dist/engine/index.d.ts +88 -0
- package/dist/engine/index.js +88 -0
- package/dist/engine/messages.d.ts +138 -0
- package/dist/engine/messages.js +140 -0
- package/dist/engine/motion.d.ts +64 -0
- package/dist/engine/motion.js +112 -0
- package/dist/engine/navigation.d.ts +87 -0
- package/dist/engine/navigation.js +156 -0
- package/dist/engine/presenter.d.ts +58 -0
- package/dist/engine/presenter.js +157 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.js +9 -0
- package/dist/markdown/attributes.d.ts +24 -0
- package/dist/markdown/attributes.js +94 -0
- package/dist/markdown/attrs-closed.d.ts +52 -0
- package/dist/markdown/attrs-closed.js +520 -0
- package/dist/markdown/blocks.d.ts +112 -0
- package/dist/markdown/blocks.js +766 -0
- package/dist/markdown/frontmatter.d.ts +30 -0
- package/dist/markdown/frontmatter.js +165 -0
- package/dist/markdown/index.d.ts +29 -0
- package/dist/markdown/index.js +29 -0
- package/dist/markdown/issues.d.ts +68 -0
- package/dist/markdown/issues.js +83 -0
- package/dist/markdown/json.d.ts +21 -0
- package/dist/markdown/json.js +236 -0
- package/dist/markdown/limits.d.ts +32 -0
- package/dist/markdown/limits.js +32 -0
- package/dist/markdown/parse.d.ts +31 -0
- package/dist/markdown/parse.js +283 -0
- package/dist/markdown/scan.d.ts +26 -0
- package/dist/markdown/scan.js +138 -0
- package/dist/markdown/slides.d.ts +32 -0
- package/dist/markdown/slides.js +854 -0
- package/dist/markdown/text.d.ts +76 -0
- package/dist/markdown/text.js +447 -0
- package/dist/markdown/twin.d.ts +41 -0
- package/dist/markdown/twin.js +374 -0
- package/dist/markdown/write.d.ts +17 -0
- package/dist/markdown/write.js +688 -0
- package/dist/math/index.d.ts +14 -0
- package/dist/math/index.js +14 -0
- package/dist/math/parse.d.ts +9 -0
- package/dist/math/parse.js +648 -0
- package/dist/math/symbols.d.ts +44 -0
- package/dist/math/symbols.js +333 -0
- package/dist/math/types.d.ts +59 -0
- package/dist/math/types.js +69 -0
- package/dist/model/backgrounds/contrast.d.ts +77 -0
- package/dist/model/backgrounds/contrast.js +186 -0
- package/dist/model/backgrounds/index.d.ts +7 -0
- package/dist/model/backgrounds/index.js +7 -0
- package/dist/model/backgrounds/resolve.d.ts +86 -0
- package/dist/model/backgrounds/resolve.js +215 -0
- package/dist/model/backgrounds/schema.d.ts +178 -0
- package/dist/model/backgrounds/schema.js +203 -0
- package/dist/model/codes.d.ts +73 -0
- package/dist/model/codes.js +67 -0
- package/dist/model/deck.d.ts +392 -0
- package/dist/model/deck.js +338 -0
- package/dist/model/index.d.ts +19 -0
- package/dist/model/index.js +19 -0
- package/dist/model/layouts/catalog.d.ts +433 -0
- package/dist/model/layouts/catalog.js +495 -0
- package/dist/model/layouts/index.d.ts +5 -0
- package/dist/model/layouts/index.js +5 -0
- package/dist/model/layouts/props.d.ts +302 -0
- package/dist/model/layouts/props.js +272 -0
- package/dist/model/loader.d.ts +37 -0
- package/dist/model/loader.js +317 -0
- package/dist/model/migrate.d.ts +34 -0
- package/dist/model/migrate.js +453 -0
- package/dist/model/motion/index.d.ts +6 -0
- package/dist/model/motion/index.js +6 -0
- package/dist/model/motion/transition.d.ts +96 -0
- package/dist/model/motion/transition.js +127 -0
- package/dist/model/parse.d.ts +57 -0
- package/dist/model/parse.js +307 -0
- package/dist/model/plain.d.ts +40 -0
- package/dist/model/plain.js +275 -0
- package/dist/model/shared.d.ts +63 -0
- package/dist/model/shared.js +86 -0
- package/dist/model/steps/index.d.ts +7 -0
- package/dist/model/steps/index.js +7 -0
- package/dist/model/steps/phase.d.ts +34 -0
- package/dist/model/steps/phase.js +50 -0
- package/dist/model/steps/slide-steps.d.ts +129 -0
- package/dist/model/steps/slide-steps.js +256 -0
- package/dist/model/style/index.d.ts +8 -0
- package/dist/model/style/index.js +8 -0
- package/dist/model/style/resolve.d.ts +87 -0
- package/dist/model/style/resolve.js +174 -0
- package/dist/model/style/schema.d.ts +85 -0
- package/dist/model/style/schema.js +53 -0
- package/dist/model/style/theme.d.ts +69 -0
- package/dist/model/style/theme.js +84 -0
- package/dist/schema/builders.d.ts +146 -0
- package/dist/schema/builders.js +285 -0
- package/dist/schema/diagnostics.d.ts +78 -0
- package/dist/schema/diagnostics.js +81 -0
- package/dist/schema/index.d.ts +15 -0
- package/dist/schema/index.js +14 -0
- package/dist/schema/internal.d.ts +40 -0
- package/dist/schema/internal.js +209 -0
- package/dist/schema/json-schema.d.ts +12 -0
- package/dist/schema/json-schema.js +213 -0
- package/dist/schema/types.d.ts +166 -0
- package/dist/schema/types.js +1 -0
- package/dist/schema/validate.d.ts +51 -0
- package/dist/schema/validate.js +765 -0
- package/dist/templates/index.d.ts +2 -0
- package/dist/templates/index.js +2 -0
- package/dist/templates/templates.d.ts +11 -0
- package/dist/templates/templates.js +47 -0
- package/package.json +60 -4
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Steps and fragments of one slide (model-v2 §3.7, ported from Protoyard's
|
|
3
|
+
* `motion/steps.ts` and extended with v1's list `items` kind).
|
|
4
|
+
*
|
|
5
|
+
* A slide starts at step 0 (its initial state) and advances one step per
|
|
6
|
+
* "next". Authors give fragments an authored step number (0 to
|
|
7
|
+
* `MAX_AUTHORED_STEP`); the engine sorts the distinct non-zero numbers and
|
|
8
|
+
* renumbers them 1, 2, 3…, so gaps ("step": 2 then 5) never cost an empty
|
|
9
|
+
* click. A fragment at authored step 0 belongs to the initial state.
|
|
10
|
+
*
|
|
11
|
+
* Sources, in document order:
|
|
12
|
+
* - a block or component item with `step` (nested blocks may step too);
|
|
13
|
+
* - a `list` block with `step`: item *i* enters at `step + i`;
|
|
14
|
+
* - a `code` block's `highlights` (or a props `{ source, highlights }` code
|
|
15
|
+
* object): highlight *i* at `step + i`, `step` defaulting to 0;
|
|
16
|
+
* - props markers `{ step, fragment | reveal, tone }` anywhere in `props`
|
|
17
|
+
* (a marker off the layout's steppable paths still counts, with a
|
|
18
|
+
* `step-unrevealed` warning, as in Protoyard); a props object with
|
|
19
|
+
* `fragment` or `reveal` but no `step` reveals nothing and is reported as
|
|
20
|
+
* the warning `step-missing`;
|
|
21
|
+
* - `slide.steps` labels, which name steps 1… and may extend the count.
|
|
22
|
+
* A `custom` slide's props belong to its host component: labels only.
|
|
23
|
+
*
|
|
24
|
+
* The input is structural (plain objects, validated or not): anything that is
|
|
25
|
+
* not a valid step, effect or tone is ignored rather than thrown on.
|
|
26
|
+
*/
|
|
27
|
+
import { createDiagnostic, toJsonPath, } from "../../schema/index.js";
|
|
28
|
+
import { BLOCK_REVEALS, FRAGMENT_EFFECTS, FRAGMENT_TONES, MAX_AUTHORED_STEP, MAX_SLIDE_STEPS, } from "../shared.js";
|
|
29
|
+
/** The legacy block `reveal` vocabulary in fragment terms (`fade` is a plain `in`). */
|
|
30
|
+
export const REVEAL_EFFECT = Object.freeze({
|
|
31
|
+
fade: 'in',
|
|
32
|
+
'fade-up': 'fade-up',
|
|
33
|
+
grow: 'grow',
|
|
34
|
+
highlight: 'highlight',
|
|
35
|
+
strike: 'strike',
|
|
36
|
+
});
|
|
37
|
+
/** The step codes this pass reports (model-v2 §3.9 cross-field and lint groups). */
|
|
38
|
+
export const STEP_CODES = Object.freeze({
|
|
39
|
+
fragmentConflict: 'fragment-conflict',
|
|
40
|
+
tooManySteps: 'too-many-steps',
|
|
41
|
+
stepUnrevealed: 'step-unrevealed',
|
|
42
|
+
stepMissing: 'step-missing',
|
|
43
|
+
});
|
|
44
|
+
/** Nesting guards: well above the model's limits, low enough to stay cheap. */
|
|
45
|
+
const MAX_BLOCK_DEPTH = 32;
|
|
46
|
+
const MAX_PROP_DEPTH = 16;
|
|
47
|
+
function isRecord(value) {
|
|
48
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
49
|
+
}
|
|
50
|
+
function validStep(value) {
|
|
51
|
+
return (typeof value === 'number' && Number.isInteger(value) && value >= 0 && value <= MAX_AUTHORED_STEP);
|
|
52
|
+
}
|
|
53
|
+
function isEffect(value) {
|
|
54
|
+
return typeof value === 'string' && FRAGMENT_EFFECTS.includes(value);
|
|
55
|
+
}
|
|
56
|
+
function isReveal(value) {
|
|
57
|
+
return typeof value === 'string' && BLOCK_REVEALS.includes(value);
|
|
58
|
+
}
|
|
59
|
+
function isTone(value) {
|
|
60
|
+
return typeof value === 'string' && FRAGMENT_TONES.includes(value);
|
|
61
|
+
}
|
|
62
|
+
/** `['cards', 2]` → `cards.*`; the props object itself is `''`. */
|
|
63
|
+
export function steppablePattern(path) {
|
|
64
|
+
return path.map((part) => (typeof part === 'number' ? '*' : part)).join('.');
|
|
65
|
+
}
|
|
66
|
+
class Collector {
|
|
67
|
+
raw = [];
|
|
68
|
+
issues = [];
|
|
69
|
+
base;
|
|
70
|
+
slideId;
|
|
71
|
+
constructor(base, slideId) {
|
|
72
|
+
this.base = base;
|
|
73
|
+
this.slideId = slideId;
|
|
74
|
+
}
|
|
75
|
+
issue(code, message, path, fix, warn = false) {
|
|
76
|
+
this.issues.push(createDiagnostic(code, message, [...this.base, ...path], {
|
|
77
|
+
severity: warn ? 'warning' : 'error',
|
|
78
|
+
fix,
|
|
79
|
+
...(this.slideId === undefined ? {} : { slideId: this.slideId }),
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
/** The effect and tone a marker asks for, reporting `fragment` + `reveal` together. */
|
|
83
|
+
effectOf(fields, path) {
|
|
84
|
+
if (fields.fragment !== undefined && fields.reveal !== undefined) {
|
|
85
|
+
this.issue(STEP_CODES.fragmentConflict, 'A step marker sets both "fragment" and "reveal"; "fragment" wins.', [...path, 'reveal'], 'Keep one: "fragment" (the v2 effects) or "reveal" (the legacy block effects).');
|
|
86
|
+
}
|
|
87
|
+
if (isEffect(fields.fragment))
|
|
88
|
+
return fields.fragment;
|
|
89
|
+
if (isReveal(fields.reveal))
|
|
90
|
+
return REVEAL_EFFECT[fields.reveal];
|
|
91
|
+
return 'in';
|
|
92
|
+
}
|
|
93
|
+
push(entry) {
|
|
94
|
+
this.raw.push({ ...entry, order: this.raw.length });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
function toneOf(fields) {
|
|
98
|
+
return isTone(fields.tone) ? { tone: fields.tone } : {};
|
|
99
|
+
}
|
|
100
|
+
function fromBlocks(list, path, depth, out) {
|
|
101
|
+
if (!Array.isArray(list) || depth > MAX_BLOCK_DEPTH)
|
|
102
|
+
return;
|
|
103
|
+
list.forEach((value, i) => {
|
|
104
|
+
if (isRecord(value))
|
|
105
|
+
fromBlock(value, [...path, i], depth, out);
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
function fromBlock(block, path, depth, out) {
|
|
109
|
+
const blockId = typeof block.id === 'string' ? { blockId: block.id } : {};
|
|
110
|
+
const tone = toneOf(block);
|
|
111
|
+
const stepped = validStep(block.step);
|
|
112
|
+
const effect = out.effectOf(block, path);
|
|
113
|
+
const base = stepped ? block.step : 0;
|
|
114
|
+
if (stepped)
|
|
115
|
+
out.push({ kind: 'block', path, authored: base, effect, ...tone, ...blockId });
|
|
116
|
+
if (block.type === 'list' && stepped && Array.isArray(block.items)) {
|
|
117
|
+
block.items.forEach((_, i) => {
|
|
118
|
+
out.push({
|
|
119
|
+
kind: 'item',
|
|
120
|
+
path: [...path, 'items', i],
|
|
121
|
+
authored: base + i,
|
|
122
|
+
effect,
|
|
123
|
+
...tone,
|
|
124
|
+
...blockId,
|
|
125
|
+
item: i,
|
|
126
|
+
});
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
if (block.type === 'code')
|
|
130
|
+
fromHighlights(block.highlights, base, path, tone, blockId, out);
|
|
131
|
+
// Nested blocks may step (Protoyard); a component item's props are its own.
|
|
132
|
+
if (block.type === 'component')
|
|
133
|
+
return;
|
|
134
|
+
fromBlocks(block.blocks, [...path, 'blocks'], depth + 1, out);
|
|
135
|
+
fromBlocks(block.children, [...path, 'children'], depth + 1, out);
|
|
136
|
+
if (Array.isArray(block.columns)) {
|
|
137
|
+
block.columns.forEach((column, c) => {
|
|
138
|
+
fromBlocks(column, [...path, 'columns', c], depth + 1, out);
|
|
139
|
+
});
|
|
140
|
+
}
|
|
141
|
+
if (Array.isArray(block.panels)) {
|
|
142
|
+
block.panels.forEach((panel, p) => {
|
|
143
|
+
if (isRecord(panel))
|
|
144
|
+
fromBlocks(panel.blocks, [...path, 'panels', p, 'blocks'], depth + 1, out);
|
|
145
|
+
});
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
function fromHighlights(highlights, base, path, tone, blockId, out) {
|
|
149
|
+
if (!Array.isArray(highlights))
|
|
150
|
+
return;
|
|
151
|
+
highlights.forEach((lines, i) => {
|
|
152
|
+
if (typeof lines !== 'string')
|
|
153
|
+
return;
|
|
154
|
+
out.push({
|
|
155
|
+
kind: 'highlight',
|
|
156
|
+
path: [...path, 'highlights', i],
|
|
157
|
+
authored: base + i,
|
|
158
|
+
effect: 'highlight',
|
|
159
|
+
...tone,
|
|
160
|
+
...blockId,
|
|
161
|
+
lines,
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
function fromProps(value, path, depth, walk) {
|
|
166
|
+
if (depth > MAX_PROP_DEPTH || value === null || typeof value !== 'object')
|
|
167
|
+
return;
|
|
168
|
+
if (Array.isArray(value)) {
|
|
169
|
+
value.forEach((item, i) => {
|
|
170
|
+
fromProps(item, [...path, i], depth + 1, walk);
|
|
171
|
+
});
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
const record = value;
|
|
175
|
+
const stepped = validStep(record.step);
|
|
176
|
+
const base = stepped ? record.step : 0;
|
|
177
|
+
// A props code object (`{ source, highlights }`, as in code-with-callout).
|
|
178
|
+
if (typeof record.source === 'string' && Array.isArray(record.highlights)) {
|
|
179
|
+
fromHighlights(record.highlights, base, path, toneOf(record), {}, walk.out);
|
|
180
|
+
}
|
|
181
|
+
if (record.step === undefined && (record.fragment !== undefined || record.reveal !== undefined)) {
|
|
182
|
+
const field = record.fragment !== undefined ? 'fragment' : 'reveal';
|
|
183
|
+
walk.out.issue(STEP_CODES.stepMissing, `This marker sets "${field}" but no "step", so it is ignored and never reveals.`, path, `Add "step": 1 (or the step it should enter on), or remove "${field}".`, true);
|
|
184
|
+
}
|
|
185
|
+
if (stepped) {
|
|
186
|
+
const effect = walk.out.effectOf(record, path);
|
|
187
|
+
walk.out.push({ kind: 'prop', path, authored: base, effect, ...toneOf(record) });
|
|
188
|
+
const relative = path.slice(1);
|
|
189
|
+
if (walk.steppable && !walk.steppable.has(steppablePattern(relative))) {
|
|
190
|
+
const allowed = [...walk.steppable].map((p) => (p === '' ? '(props)' : p)).join(', ');
|
|
191
|
+
walk.out.issue(STEP_CODES.stepUnrevealed, 'This step marker counts as a step, but the layout reveals nothing at this path.', path, allowed
|
|
192
|
+
? `Move the marker to a steppable path: ${allowed}.`
|
|
193
|
+
: 'This layout has no steppable props; remove the marker.', true);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
for (const key of Object.keys(record)) {
|
|
197
|
+
if (key === 'step' || key === 'fragment' || key === 'reveal' || key === 'tone')
|
|
198
|
+
continue;
|
|
199
|
+
fromProps(record[key], [...path, key], depth + 1, walk);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
/** Derives the ordered, densely numbered steps of a slide. Never throws. */
|
|
203
|
+
export function slideSteps(slide, options = {}) {
|
|
204
|
+
const slideId = typeof slide?.id === 'string' ? slide.id : undefined;
|
|
205
|
+
const out = new Collector(options.path ?? [], slideId);
|
|
206
|
+
if (isRecord(slide)) {
|
|
207
|
+
if (Array.isArray(slide.blocks))
|
|
208
|
+
fromBlocks(slide.blocks, ['blocks'], 0, out);
|
|
209
|
+
if (slide.layout !== 'custom' && slide.props !== undefined) {
|
|
210
|
+
const steppable = options.steppablePaths ? new Set(options.steppablePaths) : null;
|
|
211
|
+
fromProps(slide.props, ['props'], 0, { steppable, out });
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
const ordered = [...out.raw].sort((a, b) => a.authored - b.authored || a.order - b.order);
|
|
215
|
+
const distinct = [...new Set(ordered.map((r) => r.authored).filter((n) => n > 0))];
|
|
216
|
+
if (distinct.length > MAX_SLIDE_STEPS) {
|
|
217
|
+
const first = ordered.find((r) => r.authored === distinct[MAX_SLIDE_STEPS]);
|
|
218
|
+
out.issue(STEP_CODES.tooManySteps, `The slide has ${distinct.length} distinct steps; at most ${MAX_SLIDE_STEPS} are allowed (the rest play on step ${MAX_SLIDE_STEPS}).`, first ? first.path : [], 'Group fragments onto shared steps, or split the slide.');
|
|
219
|
+
}
|
|
220
|
+
const dense = new Map(distinct.map((n, i) => [n, Math.min(i + 1, MAX_SLIDE_STEPS)]));
|
|
221
|
+
const labels = Array.isArray(slide?.steps) ? slide.steps : [];
|
|
222
|
+
const count = Math.min(MAX_SLIDE_STEPS, Math.max(Math.min(distinct.length, MAX_SLIDE_STEPS), labels.length));
|
|
223
|
+
const steps = Array.from({ length: count + 1 }, (_, index) => {
|
|
224
|
+
const label = index > 0 ? labels[index - 1] : undefined;
|
|
225
|
+
return { index, ...(typeof label === 'string' ? { label } : {}), fragments: [] };
|
|
226
|
+
});
|
|
227
|
+
for (const r of ordered) {
|
|
228
|
+
const step = r.authored === 0 ? 0 : dense.get(r.authored);
|
|
229
|
+
const fragment = {
|
|
230
|
+
kind: r.kind,
|
|
231
|
+
path: r.path,
|
|
232
|
+
jsonPath: toJsonPath(r.path),
|
|
233
|
+
effect: r.effect,
|
|
234
|
+
step,
|
|
235
|
+
authored: r.authored,
|
|
236
|
+
};
|
|
237
|
+
if (r.tone !== undefined)
|
|
238
|
+
fragment.tone = r.tone;
|
|
239
|
+
if (r.blockId !== undefined)
|
|
240
|
+
fragment.blockId = r.blockId;
|
|
241
|
+
if (r.item !== undefined)
|
|
242
|
+
fragment.item = r.item;
|
|
243
|
+
if (r.lines !== undefined)
|
|
244
|
+
fragment.lines = r.lines;
|
|
245
|
+
steps[step].fragments.push(fragment);
|
|
246
|
+
}
|
|
247
|
+
return { count, initial: 0, steps, issues: out.issues };
|
|
248
|
+
}
|
|
249
|
+
/** How many "next" presses a slide takes before the deck moves on. */
|
|
250
|
+
export function slideStepCount(slide, options = {}) {
|
|
251
|
+
return slideSteps(slide, options).count;
|
|
252
|
+
}
|
|
253
|
+
/** Every fragment of a slide, initial state first, in step order. */
|
|
254
|
+
export function slideFragments(steps) {
|
|
255
|
+
return steps.steps.flatMap((step) => step.fragments);
|
|
256
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deck style (model v2 §3.1, §3.8): the `DeckStyle` schema and defaults,
|
|
3
|
+
* theme references, and the pure resolver to `--tx-deck-*` CSS variables.
|
|
4
|
+
* Theme data itself is resolved by the stage with `@texuli/tokens`.
|
|
5
|
+
*/
|
|
6
|
+
export { DECK_ASPECT_RATIOS, DECK_DENSITY_SCALE, DECK_RADIUS_VALUES, DECK_REDUCED_MOTION_MS, DECK_SUBTLE_FACTOR, DECK_TRANSITION_CAP_MS, DECK_TRANSITION_MS, DECK_VAR_PREFIX, type DeckCssVar, type DeckResolvedTransition, type DeckStyleResolution, type ResolveDeckStyleOptions, type ResolvedDeckStyle, resolveDeckStyle, resolveDeckTransition, STYLE_CODES, } from './resolve.js';
|
|
7
|
+
export { DECK_DENSITIES, DECK_MOTIONS, DECK_PROGRESS, DECK_RADII, DECK_STYLE_DEFAULTS, type DeckDensity, type DeckMotion, type DeckProgress, type DeckRadius, type DeckStyle, deckStyle, logoSrc, } from './schema.js';
|
|
8
|
+
export { DECK_THEME_MODES, DECK_THEME_SEED_MAX, type DeckResolvedThemeMode, type DeckThemeInput, type DeckThemeMode, type DeckThemeReference, deckThemeObject, deckThemeReference, EMBEDDED_THEME_LIMITS, normalizeThemeReference, resolveThemeMode, STYLE_SLUG_PATTERN, styleSlug, THEME_CODES, } from './theme.js';
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deck style (model v2 §3.1, §3.8): the `DeckStyle` schema and defaults,
|
|
3
|
+
* theme references, and the pure resolver to `--tx-deck-*` CSS variables.
|
|
4
|
+
* Theme data itself is resolved by the stage with `@texuli/tokens`.
|
|
5
|
+
*/
|
|
6
|
+
export { DECK_ASPECT_RATIOS, DECK_DENSITY_SCALE, DECK_RADIUS_VALUES, DECK_REDUCED_MOTION_MS, DECK_SUBTLE_FACTOR, DECK_TRANSITION_CAP_MS, DECK_TRANSITION_MS, DECK_VAR_PREFIX, resolveDeckStyle, resolveDeckTransition, STYLE_CODES, } from "./resolve.js";
|
|
7
|
+
export { DECK_DENSITIES, DECK_MOTIONS, DECK_PROGRESS, DECK_RADII, DECK_STYLE_DEFAULTS, deckStyle, logoSrc, } from "./schema.js";
|
|
8
|
+
export { DECK_THEME_MODES, DECK_THEME_SEED_MAX, deckThemeObject, deckThemeReference, EMBEDDED_THEME_LIMITS, normalizeThemeReference, resolveThemeMode, STYLE_SLUG_PATTERN, styleSlug, THEME_CODES, } from "./theme.js";
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a deck style (plus an optional slide override) into a complete
|
|
3
|
+
* style with every default applied, a normalized theme reference, the
|
|
4
|
+
* transition the stage plays, and the `--tx-deck-*` CSS variables. Theme and
|
|
5
|
+
* font resolution need token data, so they happen in the stage; here the
|
|
6
|
+
* caller may pass the known ids to get `unknown-*` warnings.
|
|
7
|
+
*
|
|
8
|
+
* Pure and deterministic. It never throws: invalid fields are reported in
|
|
9
|
+
* `issues` and fall back to their defaults; author strings (footer, logo)
|
|
10
|
+
* never reach a CSS variable.
|
|
11
|
+
*/
|
|
12
|
+
import { type DeckDiagnostic, type PathSegment } from '../../schema/index.js';
|
|
13
|
+
import { type DeckAspect, type DeckTransition } from '../shared.js';
|
|
14
|
+
import { DECK_STYLE_DEFAULTS, type DeckDensity, type DeckMotion, type DeckRadius, type DeckStyle } from './schema.js';
|
|
15
|
+
import { type DeckResolvedThemeMode, type DeckThemeReference } from './theme.js';
|
|
16
|
+
export declare const STYLE_CODES: Readonly<{
|
|
17
|
+
readonly unknownTheme: "unknown-theme";
|
|
18
|
+
readonly unknownFontPair: "unknown-font-pair";
|
|
19
|
+
readonly unknownCodeTheme: "unknown-code-theme";
|
|
20
|
+
}>;
|
|
21
|
+
/** Every CSS variable the style sets starts with this prefix. */
|
|
22
|
+
export declare const DECK_VAR_PREFIX = "--tx-deck-";
|
|
23
|
+
export type DeckCssVar = `--tx-deck-${string}`;
|
|
24
|
+
/** Density multipliers (inside `@texuli/tokens` `DENSITY_MIN`..`DENSITY_MAX`, 0.75..1.25). */
|
|
25
|
+
export declare const DECK_DENSITY_SCALE: Readonly<Record<DeckDensity, number>>;
|
|
26
|
+
export declare const DECK_RADIUS_VALUES: Readonly<Record<DeckRadius, string>>;
|
|
27
|
+
export declare const DECK_ASPECT_RATIOS: Readonly<Record<DeckAspect, string>>;
|
|
28
|
+
/** Full-motion durations in milliseconds (the motion module's table). */
|
|
29
|
+
export declare const DECK_TRANSITION_MS: Readonly<Record<DeckTransition, number>>;
|
|
30
|
+
/** `subtle` motion scales durations by this factor (and plays `zoom` as `fade`). */
|
|
31
|
+
export declare const DECK_SUBTLE_FACTOR = 0.6;
|
|
32
|
+
/** Under reduced motion every transition is a short fade. */
|
|
33
|
+
export declare const DECK_REDUCED_MOTION_MS = 150;
|
|
34
|
+
/** No transition runs longer than this. */
|
|
35
|
+
export declare const DECK_TRANSITION_CAP_MS = 400;
|
|
36
|
+
export interface DeckResolvedTransition {
|
|
37
|
+
name: DeckTransition;
|
|
38
|
+
durationMs: number;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* The transition the stage plays: `none` motion or transition → none;
|
|
42
|
+
* reduced motion → a 150 ms fade; `subtle` → ×0.6 and zoom → fade; capped at
|
|
43
|
+
* 400 ms. Delegates to the one resolver, `resolveSlideTransition`.
|
|
44
|
+
*/
|
|
45
|
+
export declare function resolveDeckTransition(transition: DeckTransition, motion: DeckMotion, reducedMotion?: boolean): DeckResolvedTransition;
|
|
46
|
+
type Defaulted = typeof DECK_STYLE_DEFAULTS;
|
|
47
|
+
/** A style with every default applied and the theme in its object form. */
|
|
48
|
+
export type ResolvedDeckStyle = Omit<DeckStyle, 'theme' | keyof Defaulted> & {
|
|
49
|
+
-readonly [K in keyof Defaulted]-?: NonNullable<DeckStyle[K]>;
|
|
50
|
+
} & {
|
|
51
|
+
theme?: DeckThemeReference;
|
|
52
|
+
};
|
|
53
|
+
export interface ResolveDeckStyleOptions {
|
|
54
|
+
/** Slide-level fields (`theme`, `background`, `transition`, …) that win over the deck's. */
|
|
55
|
+
override?: DeckStyle;
|
|
56
|
+
/** The host's reduced-motion preference: lowers `motion`, never raises it. */
|
|
57
|
+
reducedMotion?: boolean;
|
|
58
|
+
/** The host's mode, used when the theme names none (or `system`). Default `light`. */
|
|
59
|
+
hostMode?: DeckResolvedThemeMode;
|
|
60
|
+
/** Known catalog theme ids; when given, an unknown one warns and falls back to the host default. */
|
|
61
|
+
knownThemes?: readonly string[];
|
|
62
|
+
/** Known font pairing ids; when given, an unknown one warns and uses the theme font. */
|
|
63
|
+
knownFontPairs?: readonly string[];
|
|
64
|
+
/** Known code highlight themes; when given, an unknown one warns and uses the default. */
|
|
65
|
+
knownCodeThemes?: readonly string[];
|
|
66
|
+
/** A prefix for issue paths, e.g. `['style']`. */
|
|
67
|
+
path?: readonly PathSegment[];
|
|
68
|
+
}
|
|
69
|
+
export interface DeckStyleResolution {
|
|
70
|
+
style: ResolvedDeckStyle;
|
|
71
|
+
/** The concrete mode: theme reference, else host, else `light`. */
|
|
72
|
+
mode: DeckResolvedThemeMode;
|
|
73
|
+
/** The motion actually allowed (reduced motion lowers `full` to `subtle`). */
|
|
74
|
+
motion: DeckMotion;
|
|
75
|
+
transition: DeckResolvedTransition;
|
|
76
|
+
/** The fixed virtual canvas for the aspect, in CSS pixels. */
|
|
77
|
+
canvas: {
|
|
78
|
+
width: number;
|
|
79
|
+
height: number;
|
|
80
|
+
};
|
|
81
|
+
cssVars: Record<DeckCssVar, string>;
|
|
82
|
+
/** Invalid fields (errors, recovered with the default) and unknown ids (warnings). */
|
|
83
|
+
issues: DeckDiagnostic[];
|
|
84
|
+
}
|
|
85
|
+
/** Resolve `style` (and `options.override`) into defaults, transition and `--tx-deck-*` variables. */
|
|
86
|
+
export declare function resolveDeckStyle(style?: unknown, options?: ResolveDeckStyleOptions): DeckStyleResolution;
|
|
87
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve a deck style (plus an optional slide override) into a complete
|
|
3
|
+
* style with every default applied, a normalized theme reference, the
|
|
4
|
+
* transition the stage plays, and the `--tx-deck-*` CSS variables. Theme and
|
|
5
|
+
* font resolution need token data, so they happen in the stage; here the
|
|
6
|
+
* caller may pass the known ids to get `unknown-*` warnings.
|
|
7
|
+
*
|
|
8
|
+
* Pure and deterministic. It never throws: invalid fields are reported in
|
|
9
|
+
* `issues` and fall back to their defaults; author strings (footer, logo)
|
|
10
|
+
* never reach a CSS variable.
|
|
11
|
+
*/
|
|
12
|
+
import { createDiagnostic, validate, } from "../../schema/index.js";
|
|
13
|
+
import { isDeckBackgroundPreset } from "../backgrounds/schema.js";
|
|
14
|
+
import { MAX_MOTION_MS, REDUCED_FADE_MS, resolveSlideTransition, SUBTLE_SCALE, TRANSITION_MS, } from "../motion/transition.js";
|
|
15
|
+
import { DECK_CANVAS } from "../shared.js";
|
|
16
|
+
import { DECK_STYLE_DEFAULTS, deckStyle, } from "./schema.js";
|
|
17
|
+
import { normalizeThemeReference, resolveThemeMode, THEME_CODES, } from "./theme.js";
|
|
18
|
+
export const STYLE_CODES = Object.freeze({
|
|
19
|
+
unknownTheme: THEME_CODES.unknownTheme,
|
|
20
|
+
unknownFontPair: 'unknown-font-pair',
|
|
21
|
+
unknownCodeTheme: 'unknown-code-theme',
|
|
22
|
+
});
|
|
23
|
+
/** Every CSS variable the style sets starts with this prefix. */
|
|
24
|
+
export const DECK_VAR_PREFIX = '--tx-deck-';
|
|
25
|
+
/** Density multipliers (inside `@texuli/tokens` `DENSITY_MIN`..`DENSITY_MAX`, 0.75..1.25). */
|
|
26
|
+
export const DECK_DENSITY_SCALE = Object.freeze({
|
|
27
|
+
compact: 0.875,
|
|
28
|
+
default: 1,
|
|
29
|
+
comfortable: 1.125,
|
|
30
|
+
spacious: 1.25,
|
|
31
|
+
});
|
|
32
|
+
export const DECK_RADIUS_VALUES = Object.freeze({
|
|
33
|
+
none: '0',
|
|
34
|
+
small: '0.25rem',
|
|
35
|
+
medium: '0.625rem',
|
|
36
|
+
large: '1rem',
|
|
37
|
+
full: '9999px',
|
|
38
|
+
});
|
|
39
|
+
export const DECK_ASPECT_RATIOS = Object.freeze({
|
|
40
|
+
'16:9': '16 / 9',
|
|
41
|
+
'4:3': '4 / 3',
|
|
42
|
+
'9:16': '9 / 16',
|
|
43
|
+
'1:1': '1 / 1',
|
|
44
|
+
});
|
|
45
|
+
/** Full-motion durations in milliseconds (the motion module's table). */
|
|
46
|
+
export const DECK_TRANSITION_MS = TRANSITION_MS;
|
|
47
|
+
/** `subtle` motion scales durations by this factor (and plays `zoom` as `fade`). */
|
|
48
|
+
export const DECK_SUBTLE_FACTOR = SUBTLE_SCALE;
|
|
49
|
+
/** Under reduced motion every transition is a short fade. */
|
|
50
|
+
export const DECK_REDUCED_MOTION_MS = REDUCED_FADE_MS;
|
|
51
|
+
/** No transition runs longer than this. */
|
|
52
|
+
export const DECK_TRANSITION_CAP_MS = MAX_MOTION_MS;
|
|
53
|
+
/**
|
|
54
|
+
* The transition the stage plays: `none` motion or transition → none;
|
|
55
|
+
* reduced motion → a 150 ms fade; `subtle` → ×0.6 and zoom → fade; capped at
|
|
56
|
+
* 400 ms. Delegates to the one resolver, `resolveSlideTransition`.
|
|
57
|
+
*/
|
|
58
|
+
export function resolveDeckTransition(transition, motion, reducedMotion = false) {
|
|
59
|
+
const resolved = resolveSlideTransition({ slide: { transition }, motion, reducedMotion });
|
|
60
|
+
return { name: resolved.name, durationMs: resolved.durationMs };
|
|
61
|
+
}
|
|
62
|
+
const SHAPE = deckStyle.shape;
|
|
63
|
+
/** Validate each field on its own so one bad field never discards the rest. */
|
|
64
|
+
function salvage(input, path, issues) {
|
|
65
|
+
if (input === undefined)
|
|
66
|
+
return {};
|
|
67
|
+
const whole = validate(deckStyle, input, { path, maxIssues: 50 });
|
|
68
|
+
issues.push(...whole.issues);
|
|
69
|
+
if (whole.ok)
|
|
70
|
+
return whole.value;
|
|
71
|
+
if (input === null || typeof input !== 'object' || Array.isArray(input))
|
|
72
|
+
return {};
|
|
73
|
+
const out = {};
|
|
74
|
+
for (const key of Object.keys(SHAPE)) {
|
|
75
|
+
if (!Object.hasOwn(input, key))
|
|
76
|
+
continue;
|
|
77
|
+
let value;
|
|
78
|
+
try {
|
|
79
|
+
value = input[key];
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const field = validate(SHAPE[key], value, { maxIssues: 1 });
|
|
85
|
+
if (field.ok && field.value !== undefined)
|
|
86
|
+
out[key] = field.value;
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
function knownOr(value, known, code, label, path, issues) {
|
|
91
|
+
if (value === undefined || known === undefined || known.includes(value))
|
|
92
|
+
return value;
|
|
93
|
+
issues.push(createDiagnostic(code, `Unknown ${label} "${value}"; using the default.`, path, {
|
|
94
|
+
severity: 'warning',
|
|
95
|
+
fix: `Use one of: ${known
|
|
96
|
+
.slice(0, 20)
|
|
97
|
+
.map((id) => JSON.stringify(id))
|
|
98
|
+
.join(', ')}${known.length > 20 ? ', …' : ''}.`,
|
|
99
|
+
}));
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
/** Resolve `style` (and `options.override`) into defaults, transition and `--tx-deck-*` variables. */
|
|
103
|
+
export function resolveDeckStyle(style, options = {}) {
|
|
104
|
+
const path = [...(options.path ?? [])];
|
|
105
|
+
const issues = [];
|
|
106
|
+
const base = salvage(style, path, issues);
|
|
107
|
+
const override = salvage(options.override, path, issues);
|
|
108
|
+
const merged = { ...base };
|
|
109
|
+
for (const [key, value] of Object.entries(override)) {
|
|
110
|
+
if (value !== undefined)
|
|
111
|
+
merged[key] = value;
|
|
112
|
+
}
|
|
113
|
+
let theme = normalizeThemeReference(merged.theme);
|
|
114
|
+
if (theme?.kind === 'catalog' && options.knownThemes !== undefined) {
|
|
115
|
+
const id = knownOr(theme.id, options.knownThemes, STYLE_CODES.unknownTheme, 'theme', [...path, 'theme'], issues);
|
|
116
|
+
if (id === undefined)
|
|
117
|
+
theme = undefined;
|
|
118
|
+
}
|
|
119
|
+
const fontPair = knownOr(merged.fontPair, options.knownFontPairs, STYLE_CODES.unknownFontPair, 'font pairing', [...path, 'fontPair'], issues);
|
|
120
|
+
const codeTheme = knownOr(merged.codeTheme, options.knownCodeThemes, STYLE_CODES.unknownCodeTheme, 'code theme', [...path, 'codeTheme'], issues);
|
|
121
|
+
const resolved = {
|
|
122
|
+
aspect: merged.aspect ?? DECK_STYLE_DEFAULTS.aspect,
|
|
123
|
+
density: merged.density ?? DECK_STYLE_DEFAULTS.density,
|
|
124
|
+
radius: merged.radius ?? DECK_STYLE_DEFAULTS.radius,
|
|
125
|
+
motion: merged.motion ?? DECK_STYLE_DEFAULTS.motion,
|
|
126
|
+
transition: merged.transition ?? DECK_STYLE_DEFAULTS.transition,
|
|
127
|
+
background: merged.background ?? DECK_STYLE_DEFAULTS.background,
|
|
128
|
+
slideNumbers: merged.slideNumbers ?? DECK_STYLE_DEFAULTS.slideNumbers,
|
|
129
|
+
progress: merged.progress ?? DECK_STYLE_DEFAULTS.progress,
|
|
130
|
+
math: merged.math ?? DECK_STYLE_DEFAULTS.math,
|
|
131
|
+
};
|
|
132
|
+
if (theme !== undefined)
|
|
133
|
+
resolved.theme = theme;
|
|
134
|
+
if (fontPair !== undefined)
|
|
135
|
+
resolved.fontPair = fontPair;
|
|
136
|
+
if (codeTheme !== undefined)
|
|
137
|
+
resolved.codeTheme = codeTheme;
|
|
138
|
+
if (merged.logo !== undefined)
|
|
139
|
+
resolved.logo = merged.logo;
|
|
140
|
+
if (merged.footer !== undefined)
|
|
141
|
+
resolved.footer = merged.footer;
|
|
142
|
+
const reduced = options.reducedMotion === true;
|
|
143
|
+
const motion = reduced && resolved.motion === 'full' ? 'subtle' : resolved.motion;
|
|
144
|
+
const transition = resolveDeckTransition(resolved.transition, resolved.motion, reduced);
|
|
145
|
+
const canvas = { ...DECK_CANVAS[resolved.aspect] };
|
|
146
|
+
const background = resolved.background;
|
|
147
|
+
const cssVars = {
|
|
148
|
+
'--tx-deck-aspect-ratio': DECK_ASPECT_RATIOS[resolved.aspect],
|
|
149
|
+
'--tx-deck-canvas-width': `${canvas.width}px`,
|
|
150
|
+
'--tx-deck-canvas-height': `${canvas.height}px`,
|
|
151
|
+
'--tx-deck-density': String(DECK_DENSITY_SCALE[resolved.density]),
|
|
152
|
+
'--tx-deck-radius': DECK_RADIUS_VALUES[resolved.radius],
|
|
153
|
+
'--tx-deck-motion': motion,
|
|
154
|
+
'--tx-deck-transition': transition.name,
|
|
155
|
+
'--tx-deck-transition-duration': `${transition.durationMs}ms`,
|
|
156
|
+
// A preset id or the spec kind: enum keywords only, never an author string.
|
|
157
|
+
'--tx-deck-background': isDeckBackgroundPreset(background)
|
|
158
|
+
? background
|
|
159
|
+
: typeof background === 'object'
|
|
160
|
+
? background.kind
|
|
161
|
+
: DECK_STYLE_DEFAULTS.background,
|
|
162
|
+
'--tx-deck-progress': resolved.progress,
|
|
163
|
+
'--tx-deck-slide-numbers': resolved.slideNumbers ? '1' : '0',
|
|
164
|
+
};
|
|
165
|
+
return {
|
|
166
|
+
style: resolved,
|
|
167
|
+
mode: resolveThemeMode(theme, options.hostMode),
|
|
168
|
+
motion,
|
|
169
|
+
transition,
|
|
170
|
+
canvas,
|
|
171
|
+
cssVars,
|
|
172
|
+
issues,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `DeckStyle` (model v2 §3.1, §3.2): every field is optional. The schema
|
|
3
|
+
* keeps the authored document as written (no defaults injected, so text
|
|
4
|
+
* twins, patches and migration stay faithful); `DECK_STYLE_DEFAULTS` holds
|
|
5
|
+
* the documented defaults and `resolveDeckStyle` applies them.
|
|
6
|
+
*/
|
|
7
|
+
import { type Infer } from '../../schema/index.js';
|
|
8
|
+
export declare const DECK_DENSITIES: readonly ["compact", "default", "comfortable", "spacious"];
|
|
9
|
+
export type DeckDensity = (typeof DECK_DENSITIES)[number];
|
|
10
|
+
export declare const DECK_RADII: readonly ["none", "small", "medium", "large", "full"];
|
|
11
|
+
export type DeckRadius = (typeof DECK_RADII)[number];
|
|
12
|
+
/** A ceiling: the host's reduced-motion preference only lowers it. */
|
|
13
|
+
export declare const DECK_MOTIONS: readonly ["full", "subtle", "none"];
|
|
14
|
+
export type DeckMotion = (typeof DECK_MOTIONS)[number];
|
|
15
|
+
export declare const DECK_PROGRESS: readonly ["none", "top", "bottom"];
|
|
16
|
+
export type DeckProgress = (typeof DECK_PROGRESS)[number];
|
|
17
|
+
/** `style.logo`: media syntax (an image), at most 512 code points. */
|
|
18
|
+
export declare const logoSrc: import("../../index.js").StringSchema;
|
|
19
|
+
export declare const deckStyle: import("../../index.js").ObjectSchema<{
|
|
20
|
+
readonly theme: import("../../index.js").OptionalSchema<import("../../index.js").UnionSchema<readonly [import("../../index.js").StringSchema, import("../../index.js").UnionSchema<readonly [import("../../index.js").ObjectSchema<{
|
|
21
|
+
readonly kind: import("../../index.js").LiteralSchema<"catalog">;
|
|
22
|
+
readonly id: import("../../index.js").StringSchema;
|
|
23
|
+
readonly mode: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"dark" | "light" | "high-contrast" | "system">, false>;
|
|
24
|
+
}>, import("../../index.js").ObjectSchema<{
|
|
25
|
+
readonly kind: import("../../index.js").LiteralSchema<"embedded">;
|
|
26
|
+
readonly theme: import("../../index.js").RefineSchema<import("../../index.js").JsonValueSchema>;
|
|
27
|
+
readonly mode: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"dark" | "light" | "high-contrast" | "system">, false>;
|
|
28
|
+
}>, import("../../index.js").ObjectSchema<{
|
|
29
|
+
readonly kind: import("../../index.js").LiteralSchema<"seed">;
|
|
30
|
+
readonly seed: import("../../index.js").NumberSchema;
|
|
31
|
+
readonly mode: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"dark" | "light" | "high-contrast" | "system">, false>;
|
|
32
|
+
}>]>]>, false>;
|
|
33
|
+
readonly fontPair: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
34
|
+
readonly aspect: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"16:9" | "4:3" | "9:16" | "1:1">, false>;
|
|
35
|
+
readonly density: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"compact" | "default" | "comfortable" | "spacious">, false>;
|
|
36
|
+
readonly radius: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"none" | "small" | "medium" | "large" | "full">, false>;
|
|
37
|
+
readonly motion: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"none" | "full" | "subtle">, false>;
|
|
38
|
+
readonly transition: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"fade-up" | "fade" | "none" | "slide" | "zoom" | "morph">, false>;
|
|
39
|
+
readonly background: import("../../index.js").OptionalSchema<import("../../index.js").UnionSchema<readonly [import("../../index.js").EnumSchema<"solid-color" | "solid-surface" | "solid-primary" | "solid-accent" | "solid-muted" | "solid-inverse" | "gradient-brand" | "gradient-dusk" | "gradient-dawn" | "gradient-forest" | "gradient-mist" | "pattern-dots" | "pattern-grid">, import("../../index.js").UnionSchema<readonly [import("../../index.js").RefineSchema<import("../../index.js").ObjectSchema<{
|
|
40
|
+
readonly kind: import("../../index.js").LiteralSchema<"solid">;
|
|
41
|
+
readonly token: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"accent" | "background" | "surface" | "primary" | "muted" | "inverse">, false>;
|
|
42
|
+
readonly color: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
43
|
+
}>>, import("../../index.js").ObjectSchema<{
|
|
44
|
+
readonly kind: import("../../index.js").LiteralSchema<"gradient">;
|
|
45
|
+
readonly gradient: import("../../index.js").EnumSchema<"brand" | "dusk" | "dawn" | "forest" | "mist">;
|
|
46
|
+
readonly angle: import("../../index.js").OptionalSchema<import("../../index.js").NumberSchema, false>;
|
|
47
|
+
}>, import("../../index.js").ObjectSchema<{
|
|
48
|
+
readonly kind: import("../../index.js").LiteralSchema<"pattern">;
|
|
49
|
+
readonly pattern: import("../../index.js").EnumSchema<"dots" | "grid">;
|
|
50
|
+
}>, import("../../index.js").RefineSchema<import("../../index.js").ObjectSchema<{
|
|
51
|
+
readonly tone: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"dark" | "light">, false>;
|
|
52
|
+
readonly overlay: import("../../index.js").OptionalSchema<import("../../index.js").NumberSchema, false>;
|
|
53
|
+
readonly position: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"center" | "top" | "bottom" | "left" | "right">, false>;
|
|
54
|
+
readonly kind: import("../../index.js").EnumSchema<"image" | "image-full">;
|
|
55
|
+
readonly src: import("../../index.js").StringSchema;
|
|
56
|
+
readonly alt: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
57
|
+
readonly fit: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"cover" | "contain">, false>;
|
|
58
|
+
}>>, import("../../index.js").RefineSchema<import("../../index.js").ObjectSchema<{
|
|
59
|
+
readonly tone: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"dark" | "light">, false>;
|
|
60
|
+
readonly overlay: import("../../index.js").OptionalSchema<import("../../index.js").NumberSchema, false>;
|
|
61
|
+
readonly position: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"center" | "top" | "bottom" | "left" | "right">, false>;
|
|
62
|
+
readonly kind: import("../../index.js").EnumSchema<"video" | "video-full">;
|
|
63
|
+
readonly src: import("../../index.js").StringSchema;
|
|
64
|
+
readonly poster: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
65
|
+
}>>]>]>, false>;
|
|
66
|
+
readonly logo: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
67
|
+
readonly footer: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
68
|
+
readonly slideNumbers: import("../../index.js").OptionalSchema<import("../../index.js").BooleanSchema, false>;
|
|
69
|
+
readonly progress: import("../../index.js").OptionalSchema<import("../../index.js").EnumSchema<"none" | "top" | "bottom">, false>;
|
|
70
|
+
readonly codeTheme: import("../../index.js").OptionalSchema<import("../../index.js").StringSchema, false>;
|
|
71
|
+
readonly math: import("../../index.js").OptionalSchema<import("../../index.js").BooleanSchema, false>;
|
|
72
|
+
}>;
|
|
73
|
+
export type DeckStyle = Infer<typeof deckStyle>;
|
|
74
|
+
/** The documented defaults for every field that has one. */
|
|
75
|
+
export declare const DECK_STYLE_DEFAULTS: Readonly<{
|
|
76
|
+
readonly aspect: "16:9";
|
|
77
|
+
readonly density: "default";
|
|
78
|
+
readonly radius: "medium";
|
|
79
|
+
readonly motion: "full";
|
|
80
|
+
readonly transition: "fade";
|
|
81
|
+
readonly background: "solid-color";
|
|
82
|
+
readonly slideNumbers: true;
|
|
83
|
+
readonly progress: "bottom";
|
|
84
|
+
readonly math: false;
|
|
85
|
+
}>;
|