@openpawlabs/diy-guides-ui 1.7.5 → 1.9.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/README.md +23 -1
- package/bin/diy-guide-images.mjs +317 -0
- package/dist/components/GuideLayout/GuideLayout.d.ts.map +1 -1
- package/dist/components/GuideLayout/GuideLayout.stories.d.ts.map +1 -1
- package/dist/components/GuideResponsiveImage/GuideResponsiveImage.d.ts +23 -0
- package/dist/components/GuideResponsiveImage/GuideResponsiveImage.d.ts.map +1 -0
- package/dist/components/GuideStep/GuideStep.d.ts +4 -1
- package/dist/components/GuideStep/GuideStep.d.ts.map +1 -1
- package/dist/components/GuideStep/GuideStep.stories.d.ts.map +1 -1
- package/dist/components/MediaFigure/MediaCropEditor.d.ts +9 -7
- package/dist/components/MediaFigure/MediaCropEditor.d.ts.map +1 -1
- package/dist/components/MediaFigure/MediaFigure.d.ts +6 -4
- package/dist/components/MediaFigure/MediaFigure.d.ts.map +1 -1
- package/dist/components/MediaFigure/MediaFigure.stories.d.ts.map +1 -1
- package/dist/components/MediaFigure/MediaFigureClipFrame.d.ts +13 -1
- package/dist/components/MediaFigure/MediaFigureClipFrame.d.ts.map +1 -1
- package/dist/components/MediaFigure/MediaFigureThumbnail.d.ts +2 -2
- package/dist/components/MediaFigure/MediaFigureThumbnail.d.ts.map +1 -1
- package/dist/components/ToolList/ToolList.d.ts.map +1 -1
- package/dist/context/guideImageVariants.d.ts +16 -0
- package/dist/context/guideImageVariants.d.ts.map +1 -0
- package/dist/diy-guides-ui.cjs +6 -6
- package/dist/diy-guides-ui.cjs.map +1 -1
- package/dist/diy-guides-ui.js +3603 -3377
- package/dist/diy-guides-ui.js.map +1 -1
- package/dist/index.d.ts +7 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/utils/guideImageSources.d.ts +73 -0
- package/dist/utils/guideImageSources.d.ts.map +1 -0
- package/dist/utils/guideImageSources.test.d.ts +2 -0
- package/dist/utils/guideImageSources.test.d.ts.map +1 -0
- package/dist/utils/mediaCrop.d.ts +40 -13
- package/dist/utils/mediaCrop.d.ts.map +1 -1
- package/package.json +17 -3
package/README.md
CHANGED
|
@@ -126,6 +126,28 @@ export function BatteryGuide() {
|
|
|
126
126
|
}
|
|
127
127
|
```
|
|
128
128
|
|
|
129
|
+
## Responsive images CLI
|
|
130
|
+
|
|
131
|
+
Publishers can generate AVIF size variants for every raster referenced by
|
|
132
|
+
`guide.mdx` without changing the authored MDX. Requires the optional peer
|
|
133
|
+
`sharp` in the project that runs the CLI (it is **not** part of the browser
|
|
134
|
+
bundle):
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
pnpm add -D sharp
|
|
138
|
+
pnpm exec diy-guide-images ./path/to/guide # or a tree of guides
|
|
139
|
+
# Writes images/thumbnails/foo.w240.avif … and images/thumbnails/variants.json
|
|
140
|
+
# Existing files are skipped — delete images/thumbnails/ to regenerate
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
Wrap the rendered guide in `GuideImageVariantsProvider` with that manifest so
|
|
144
|
+
`MediaFigure`, thumbnails, heroes, and tool list images emit `<picture>` + AVIF
|
|
145
|
+
`srcset`. Without a manifest, components fall back to the single canonical `src`.
|
|
146
|
+
Lightbox always loads the full canonical file, and only while open.
|
|
147
|
+
|
|
148
|
+
See `bin/diy-guide-images.mjs` and the openpaw-docs / diy-guide-example deploy
|
|
149
|
+
pipelines for the full pattern.
|
|
150
|
+
|
|
129
151
|
## License
|
|
130
152
|
|
|
131
|
-
|
|
153
|
+
AGPL-3.0 — see [LICENSE](./LICENSE).
|
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* diy-guide-images — generate AVIF size variants for guide rasters.
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* diy-guide-images <path> [--dry-run] [--quality 50]
|
|
7
|
+
*
|
|
8
|
+
* `<path>` may be a single guide folder (containing guide.mdx) or a tree of
|
|
9
|
+
* guides. Writes `{stem}.w{width}.avif` under `images/thumbnails/` for each
|
|
10
|
+
* referenced raster and an `images/thumbnails/variants.json` manifest so
|
|
11
|
+
* @openpawlabs/diy-guides-ui can emit srcset without 404s.
|
|
12
|
+
*
|
|
13
|
+
* Existing variant files are skipped (delete `images/thumbnails/` to regenerate).
|
|
14
|
+
*
|
|
15
|
+
* Requires the optional peer dependency `sharp` (not shipped in the UI bundle).
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, writeFileSync } from "node:fs";
|
|
19
|
+
import { basename, dirname, extname, join, resolve } from "node:path";
|
|
20
|
+
|
|
21
|
+
const VARIANT_WIDTHS = [240, 480, 800, 1600];
|
|
22
|
+
const VARIANT_FORMAT = "avif";
|
|
23
|
+
const THUMBNAILS_DIR = "thumbnails";
|
|
24
|
+
const MANIFEST_NAME = "variants.json";
|
|
25
|
+
const RASTER_EXTENSIONS = new Set([".png", ".jpg", ".jpeg", ".webp", ".avif"]);
|
|
26
|
+
const IMAGE_REF_RE = /['"]((?:\.\/)?images\/[^'"]+)['"]/g;
|
|
27
|
+
|
|
28
|
+
async function loadSharp() {
|
|
29
|
+
try {
|
|
30
|
+
return (await import("sharp")).default;
|
|
31
|
+
} catch {
|
|
32
|
+
console.error(`error: sharp is required to run diy-guide-images.
|
|
33
|
+
|
|
34
|
+
Install it in the project that runs this CLI (it is an optional peer of
|
|
35
|
+
@openpawlabs/diy-guides-ui so browser consumers do not download native binaries):
|
|
36
|
+
|
|
37
|
+
pnpm add -D sharp
|
|
38
|
+
# or: npm install --save-dev sharp
|
|
39
|
+
`);
|
|
40
|
+
process.exit(1);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function printHelp() {
|
|
45
|
+
console.log(`Usage: diy-guide-images <path> [--dry-run] [--quality <0-100>]
|
|
46
|
+
|
|
47
|
+
Generate AVIF width variants for rasters referenced by guide.mdx files.
|
|
48
|
+
|
|
49
|
+
Writes under images/thumbnails/ (skipped when files already exist).
|
|
50
|
+
Delete that folder to force a full regenerate.
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
--dry-run Show planned work without writing files
|
|
54
|
+
--quality <n> AVIF quality 0-100 (default: 75)
|
|
55
|
+
-h, --help Show this help
|
|
56
|
+
|
|
57
|
+
Requires optional peer dependency: sharp
|
|
58
|
+
`);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function normalizeImageRef(ref) {
|
|
62
|
+
if (ref.startsWith("./images/")) return ref;
|
|
63
|
+
if (ref.startsWith("images/")) return `./${ref}`;
|
|
64
|
+
return ref;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function findGuideMdx(root) {
|
|
68
|
+
const guides = [];
|
|
69
|
+
function walk(dir) {
|
|
70
|
+
for (const entry of readdirSync(dir, { withFileTypes: true })) {
|
|
71
|
+
const full = join(dir, entry.name);
|
|
72
|
+
if (entry.isDirectory()) {
|
|
73
|
+
if (entry.name === "node_modules" || entry.name === ".git") continue;
|
|
74
|
+
walk(full);
|
|
75
|
+
} else if (entry.name === "guide.mdx") {
|
|
76
|
+
guides.push(full);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
walk(root);
|
|
81
|
+
return guides.sort();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
function collectRefs(guidePath) {
|
|
85
|
+
const text = readFileSync(guidePath, "utf8");
|
|
86
|
+
const refs = new Map();
|
|
87
|
+
for (const match of text.matchAll(IMAGE_REF_RE)) {
|
|
88
|
+
const raw = match[1];
|
|
89
|
+
const ref = normalizeImageRef(raw);
|
|
90
|
+
const ext = extname(ref).toLowerCase();
|
|
91
|
+
if (!RASTER_EXTENSIONS.has(ext)) continue;
|
|
92
|
+
// Ignore accidental refs into the thumbnails output dir
|
|
93
|
+
if (ref.includes("/thumbnails/")) continue;
|
|
94
|
+
const sourcePath = resolve(dirname(guidePath), ref);
|
|
95
|
+
refs.set(sourcePath, ref);
|
|
96
|
+
}
|
|
97
|
+
return refs;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function thumbnailsDirFor(sourcePath) {
|
|
101
|
+
return join(dirname(sourcePath), THUMBNAILS_DIR);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function variantPath(sourcePath, width) {
|
|
105
|
+
const stem = basename(sourcePath, extname(sourcePath));
|
|
106
|
+
return join(thumbnailsDirFor(sourcePath), `${stem}.w${width}.${VARIANT_FORMAT}`);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function loadExistingManifest(imagesDir) {
|
|
110
|
+
const manifestPath = join(imagesDir, THUMBNAILS_DIR, MANIFEST_NAME);
|
|
111
|
+
if (!existsSync(manifestPath)) return null;
|
|
112
|
+
try {
|
|
113
|
+
return JSON.parse(readFileSync(manifestPath, "utf8"));
|
|
114
|
+
} catch {
|
|
115
|
+
return null;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function isFreshVariant(sourcePath, destPath) {
|
|
120
|
+
if (!existsSync(destPath)) return false;
|
|
121
|
+
try {
|
|
122
|
+
return statSync(destPath).mtimeMs >= statSync(sourcePath).mtimeMs;
|
|
123
|
+
} catch {
|
|
124
|
+
return false;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
async function processSource(
|
|
129
|
+
sourcePath,
|
|
130
|
+
{ dryRun, quality, manifestImages, existingManifest, getSharp },
|
|
131
|
+
) {
|
|
132
|
+
const name = basename(sourcePath);
|
|
133
|
+
if (!existsSync(sourcePath)) {
|
|
134
|
+
console.log(` SKIP missing: ${name}`);
|
|
135
|
+
return { generated: 0, skipped: 1 };
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (/\.w\d+\.avif$/i.test(name)) {
|
|
139
|
+
return { generated: 0, skipped: 1 };
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
const prior = existingManifest?.images?.[name];
|
|
143
|
+
// Fast path: no sharp when every listed variant exists and is newer than source
|
|
144
|
+
if (prior?.variants?.length && prior.width > 0) {
|
|
145
|
+
const priorWidths = prior.variants;
|
|
146
|
+
if (priorWidths.every((width) => isFreshVariant(sourcePath, variantPath(sourcePath, width)))) {
|
|
147
|
+
manifestImages[name] = {
|
|
148
|
+
width: prior.width,
|
|
149
|
+
height: prior.height,
|
|
150
|
+
variants: priorWidths,
|
|
151
|
+
};
|
|
152
|
+
return { generated: 0, skipped: priorWidths.length };
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
const sharp = await getSharp();
|
|
157
|
+
const meta = await sharp(sourcePath).metadata();
|
|
158
|
+
const sourceWidth = meta.width ?? 0;
|
|
159
|
+
const sourceHeight = meta.height ?? 0;
|
|
160
|
+
if (sourceWidth <= 0) {
|
|
161
|
+
console.log(` SKIP no width: ${name}`);
|
|
162
|
+
return { generated: 0, skipped: 1 };
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const widths = VARIANT_WIDTHS.filter((w) => w < sourceWidth);
|
|
166
|
+
manifestImages[name] = {
|
|
167
|
+
width: sourceWidth,
|
|
168
|
+
height: sourceHeight,
|
|
169
|
+
variants: widths,
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
if (widths.length === 0) {
|
|
173
|
+
return { generated: 0, skipped: 0 };
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const outDir = thumbnailsDirFor(sourcePath);
|
|
177
|
+
if (!dryRun && !existsSync(outDir)) {
|
|
178
|
+
mkdirSync(outDir, { recursive: true });
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
let generated = 0;
|
|
182
|
+
let skipped = 0;
|
|
183
|
+
for (const width of widths) {
|
|
184
|
+
const dest = variantPath(sourcePath, width);
|
|
185
|
+
if (isFreshVariant(sourcePath, dest)) {
|
|
186
|
+
skipped += 1;
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
if (dryRun) {
|
|
190
|
+
console.log(` WOULD WRITE ${THUMBNAILS_DIR}/${basename(dest)} (${width}w)`);
|
|
191
|
+
generated += 1;
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
await sharp(sourcePath)
|
|
195
|
+
.resize({ width, withoutEnlargement: true })
|
|
196
|
+
.avif({ quality })
|
|
197
|
+
.toFile(dest);
|
|
198
|
+
console.log(` WRITE ${THUMBNAILS_DIR}/${basename(dest)}`);
|
|
199
|
+
generated += 1;
|
|
200
|
+
}
|
|
201
|
+
return { generated, skipped };
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
async function processGuide(guidePath, options) {
|
|
205
|
+
const refs = collectRefs(guidePath);
|
|
206
|
+
if (refs.size === 0) {
|
|
207
|
+
console.log(`No raster refs in ${guidePath}`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
console.log(`Guide: ${guidePath}`);
|
|
212
|
+
const imagesDir = join(dirname(guidePath), "images");
|
|
213
|
+
const existingManifest = loadExistingManifest(imagesDir);
|
|
214
|
+
const manifestImages = {};
|
|
215
|
+
let generated = 0;
|
|
216
|
+
let skipped = 0;
|
|
217
|
+
|
|
218
|
+
for (const sourcePath of [...refs.keys()].sort()) {
|
|
219
|
+
const result = await processSource(sourcePath, {
|
|
220
|
+
...options,
|
|
221
|
+
manifestImages,
|
|
222
|
+
existingManifest,
|
|
223
|
+
});
|
|
224
|
+
generated += result.generated;
|
|
225
|
+
skipped += result.skipped;
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
const manifest = {
|
|
229
|
+
version: 1,
|
|
230
|
+
format: VARIANT_FORMAT,
|
|
231
|
+
widths: VARIANT_WIDTHS,
|
|
232
|
+
images: manifestImages,
|
|
233
|
+
};
|
|
234
|
+
const thumbDir = join(imagesDir, THUMBNAILS_DIR);
|
|
235
|
+
const manifestPath = join(thumbDir, MANIFEST_NAME);
|
|
236
|
+
|
|
237
|
+
if (options.dryRun) {
|
|
238
|
+
console.log(
|
|
239
|
+
` WOULD WRITE ${THUMBNAILS_DIR}/${MANIFEST_NAME} (${Object.keys(manifestImages).length} images)`,
|
|
240
|
+
);
|
|
241
|
+
} else if (!existsSync(imagesDir)) {
|
|
242
|
+
console.log(` SKIP manifest: no images/ directory`);
|
|
243
|
+
} else {
|
|
244
|
+
if (!existsSync(thumbDir)) {
|
|
245
|
+
mkdirSync(thumbDir, { recursive: true });
|
|
246
|
+
}
|
|
247
|
+
writeFileSync(manifestPath, `${JSON.stringify(manifest, null, 2)}\n`, "utf8");
|
|
248
|
+
console.log(` WRITE ${THUMBNAILS_DIR}/${MANIFEST_NAME}`);
|
|
249
|
+
}
|
|
250
|
+
console.log(` Generated ${generated}, skipped ${skipped} variant(s)\n`);
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
async function main(argv) {
|
|
254
|
+
const args = argv.slice(2);
|
|
255
|
+
if (args.length === 0 || args.includes("-h") || args.includes("--help")) {
|
|
256
|
+
printHelp();
|
|
257
|
+
process.exit(args.length === 0 ? 1 : 0);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
let dryRun = false;
|
|
261
|
+
let quality = 75;
|
|
262
|
+
let root = null;
|
|
263
|
+
|
|
264
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
265
|
+
const arg = args[i];
|
|
266
|
+
if (arg === "--dry-run") {
|
|
267
|
+
dryRun = true;
|
|
268
|
+
} else if (arg === "--quality") {
|
|
269
|
+
quality = Number(args[++i]);
|
|
270
|
+
if (!Number.isFinite(quality) || quality < 0 || quality > 100) {
|
|
271
|
+
console.error("error: --quality must be 0–100");
|
|
272
|
+
process.exit(2);
|
|
273
|
+
}
|
|
274
|
+
} else if (arg.startsWith("-")) {
|
|
275
|
+
console.error(`Unknown option: ${arg}`);
|
|
276
|
+
printHelp();
|
|
277
|
+
process.exit(2);
|
|
278
|
+
} else {
|
|
279
|
+
root = resolve(arg);
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (!root) {
|
|
284
|
+
printHelp();
|
|
285
|
+
process.exit(1);
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
if (!existsSync(root) || !statSync(root).isDirectory()) {
|
|
289
|
+
console.error(`error: not a directory: ${root}`);
|
|
290
|
+
process.exit(1);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const guideAtRoot = join(root, "guide.mdx");
|
|
294
|
+
const guides = existsSync(guideAtRoot) ? [guideAtRoot] : findGuideMdx(root);
|
|
295
|
+
if (guides.length === 0) {
|
|
296
|
+
console.error(`error: no guide.mdx found under ${root}`);
|
|
297
|
+
process.exit(1);
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
let sharpPromise = null;
|
|
301
|
+
const getSharp = () => {
|
|
302
|
+
sharpPromise ??= loadSharp();
|
|
303
|
+
return sharpPromise;
|
|
304
|
+
};
|
|
305
|
+
|
|
306
|
+
console.log(`Root: ${root}`);
|
|
307
|
+
console.log(`Mode: quality=${quality}${dryRun ? " (dry-run)" : ""}\n`);
|
|
308
|
+
|
|
309
|
+
for (const guide of guides) {
|
|
310
|
+
await processGuide(guide, { dryRun, quality, getSharp });
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
main(process.argv).catch((error) => {
|
|
315
|
+
console.error(error);
|
|
316
|
+
process.exit(1);
|
|
317
|
+
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuideLayout.d.ts","sourceRoot":"","sources":["../../../src/components/GuideLayout/GuideLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAS5E,OAAO,
|
|
1
|
+
{"version":3,"file":"GuideLayout.d.ts","sourceRoot":"","sources":["../../../src/components/GuideLayout/GuideLayout.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuC,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAS5E,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAGtE,MAAM,WAAW,gBAAgB;IAC/B,mGAAmG;IACnG,QAAQ,EAAE,SAAS,CAAC;IACpB;;;;OAIG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,sBAAsB;IACrC,mBAAmB;IACnB,KAAK,EAAE,SAAS,CAAC;IACjB,uFAAuF;IACvF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+DAA+D;IAC/D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,0DAA0D;IAC1D,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,kDAAkD;IAClD,YAAY,CAAC,EAAE,SAAS,CAAC;IACzB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,qBAAqB;IACpC,6DAA6D;IAC7D,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,iBAAiB,CAAC,EACzB,KAAK,EACL,SAAS,EACT,YAAY,EACZ,UAAU,EACV,YAAY,EACZ,IAAI,EACJ,SAAS,GACV,EAAE,sBAAsB,+BA4CxB;AAED,+DAA+D;AAC/D,iBAAS,gBAAgB,CAAC,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,qBAAqB,+BAMvE;AAED,iEAAiE;AACjE,iBAAS,kBAAkB,CAAC,EAC1B,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAMA;AAED,kEAAkE;AAClE,iBAAS,kBAAkB,CAAC,EAC1B,QAAQ,EACR,SAAS,GACV,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAWA;AAED;;;;;GAKG;AACH,eAAO,MAAM,WAAW,+CAKnB,gBAAgB;;;;;CAwCpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuideLayout.stories.d.ts","sourceRoot":"","sources":["../../../src/components/GuideLayout/GuideLayout.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAqC5D,QAAA,MAAM,IAAI;;;;;;;
|
|
1
|
+
{"version":3,"file":"GuideLayout.stories.d.ts","sourceRoot":"","sources":["../../../src/components/GuideLayout/GuideLayout.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAqC5D,QAAA,MAAM,IAAI;;;;;;;qBA2DS,CAAC;;;;qBAO+C,CAAC;;;;;;;;;;;;;;;CAzDhC,CAAC;AAErC,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAKnC,eAAO,MAAM,SAAS,EAAE,KAwGvB,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KA2B3B,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAsD5B,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ImgHTMLAttributes } from "react";
|
|
2
|
+
import { type GuideImageRole } from "../../utils/guideImageSources";
|
|
3
|
+
export interface GuideResponsiveImageProps extends Omit<ImgHTMLAttributes<HTMLImageElement>, "src" | "srcSet" | "sizes"> {
|
|
4
|
+
src: string;
|
|
5
|
+
/** Layout role — picks default `sizes` and preferred variant width. */
|
|
6
|
+
role?: GuideImageRole;
|
|
7
|
+
/**
|
|
8
|
+
* When true, wrap in `<picture>` with an AVIF `<source>` when variants exist.
|
|
9
|
+
* @default true
|
|
10
|
+
*/
|
|
11
|
+
responsive?: boolean;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Guide raster that opts into AVIF `srcset` when a {@link GuideImageVariantsProvider}
|
|
15
|
+
* supplies a manifest. Falls back to a single `src` otherwise.
|
|
16
|
+
*
|
|
17
|
+
* When variants exist, a `<picture>` with `display: contents` wraps the AVIF
|
|
18
|
+
* source so layout classes on the `<img>` still fill the parent frame.
|
|
19
|
+
*/
|
|
20
|
+
export declare function GuideResponsiveImage({ src, role, responsive, loading, decoding, alt, className, style, onLoad, ...imgProps }: GuideResponsiveImageProps): import("react").JSX.Element;
|
|
21
|
+
/** Preferred single-URL variant for a role (e.g. catalog cards that need one file). */
|
|
22
|
+
export declare function useGuideImagePreferredSrc(src: string | undefined, role: GuideImageRole): string | undefined;
|
|
23
|
+
//# sourceMappingURL=GuideResponsiveImage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"GuideResponsiveImage.d.ts","sourceRoot":"","sources":["../../../src/components/GuideResponsiveImage/GuideResponsiveImage.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,OAAO,CAAC;AAE/C,OAAO,EAEL,KAAK,cAAc,EACpB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,WAAW,yBACf,SAAQ,IAAI,CAAC,iBAAiB,CAAC,gBAAgB,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,OAAO,CAAC;IAC7E,GAAG,EAAE,MAAM,CAAC;IACZ,uEAAuE;IACvE,IAAI,CAAC,EAAE,cAAc,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,GAAG,EACH,IAAgB,EAChB,UAAiB,EACjB,OAAgB,EAChB,QAAkB,EAClB,GAAQ,EACR,SAAS,EACT,KAAK,EACL,MAAM,EACN,GAAG,QAAQ,EACZ,EAAE,yBAAyB,+BA+B3B;AAED,uFAAuF;AACvF,wBAAgB,yBAAyB,CACvC,GAAG,EAAE,MAAM,GAAG,SAAS,EACvB,IAAI,EAAE,cAAc,GACnB,MAAM,GAAG,SAAS,CAMpB"}
|
|
@@ -4,13 +4,16 @@ import { type GuideColor } from "../../types/colors";
|
|
|
4
4
|
* Optional, editor-only media affordances. Presence switches `GuideStep.Media`
|
|
5
5
|
* into edit mode: an empty-state add target, an "Edit annotations" / "Adjust crop"
|
|
6
6
|
* overlay on the main image, a remove control per thumbnail, a "+" tile to append,
|
|
7
|
-
* and (with `onReorderImage`) drag-to-reorder thumbnails.
|
|
7
|
+
* and (with `onReorderImage`) drag-to-reorder thumbnails. When `onAddMediaFiles` is
|
|
8
|
+
* set, the empty target and "+" tile also accept file drag-and-drop. All members are intent
|
|
8
9
|
* callbacks — the library performs no file or menu logic. Omit entirely for the
|
|
9
10
|
* read-only reader experience.
|
|
10
11
|
*/
|
|
11
12
|
export interface GuideStepMediaEditing {
|
|
12
13
|
/** Append a new image (e.g. open a file picker). Drives the empty target and "+" tile. */
|
|
13
14
|
onAddImage?: () => void;
|
|
15
|
+
/** Files dropped onto an add target (empty frame or "+" tile). */
|
|
16
|
+
onAddMediaFiles?: (files: File[]) => void;
|
|
14
17
|
/** Edit annotations for the image at `index` (fired from the main image overlay). */
|
|
15
18
|
onEditAnnotations?: (index: number) => void;
|
|
16
19
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuideStep.d.ts","sourceRoot":"","sources":["../../../src/components/GuideStep/GuideStep.tsx"],"names":[],"mappings":"AAEA,OAAO,EASL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAgB7D
|
|
1
|
+
{"version":3,"file":"GuideStep.d.ts","sourceRoot":"","sources":["../../../src/components/GuideStep/GuideStep.tsx"],"names":[],"mappings":"AAEA,OAAO,EASL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,OAAO,EAAU,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAgB7D;;;;;;;;GAQG;AACH,MAAM,WAAW,qBAAqB;IACpC,0FAA0F;IAC1F,UAAU,CAAC,EAAE,MAAM,IAAI,CAAC;IACxB,kEAAkE;IAClE,eAAe,CAAC,EAAE,CAAC,KAAK,EAAE,IAAI,EAAE,KAAK,IAAI,CAAC;IAC1C,qFAAqF;IACrF,iBAAiB,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C;;;OAGG;IACH,UAAU,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,2EAA2E;IAC3E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,8EAA8E;IAC9E,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,6EAA6E;IAC7E,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,iFAAiF;IACjF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oBAAoB;IACpB,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,mCAAmC;IACnC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,6DAA6D;IAC7D,iBAAiB,CAAC,EAAE,CAAC,SAAS,EAAE,OAAO,KAAK,IAAI,CAAC;IACjD,yDAAyD;IACzD,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB;;;OAGG;IACH,YAAY,CAAC,EAAE,qBAAqB,CAAC;IACrC,6FAA6F;IAC7F,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,8FAA8F;IAC9F,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,gEAAgE;IAChE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;GAIG;AACH,MAAM,MAAM,sBAAsB,GAC9B,KAAK,GACL,SAAS,GACT,UAAU,GACV,MAAM,GACN,QAAQ,CAAC;AAEb;;;;;GAKG;AACH,MAAM,WAAW,uBAAuB;IACtC,6DAA6D;IAC7D,WAAW,CAAC,EAAE,MAAM,IAAI,CAAC;IACzB,0EAA0E;IAC1E,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IACzC,iGAAiG;IACjG,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACtD;AAcD,MAAM,WAAW,oBAAoB;IACnC;;;;;OAKG;IACH,OAAO,CAAC,EAAE,sBAAsB,CAAC;IACjC,iGAAiG;IACjG,KAAK,CAAC,EAAE,UAAU,CAAC;IACnB,mEAAmE;IACnE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,mFAAmF;IACnF,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;OAGG;IACH,aAAa,CAAC,EAAE,MAAM,IAAI,CAAC;IAC3B,0EAA0E;IAC1E,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAoPD,0FAA0F;AAC1F,iBAAS,cAAc,CAAC,MAAM,EAAE;IAAE,QAAQ,CAAC,EAAE,SAAS,CAAA;CAAE,QAEvD;AAED,iDAAiD;AACjD,iBAAS,gBAAgB,CAAC,EACxB,QAAQ,EACR,SAAS,EACT,OAAO,GACR,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,0FAA0F;IAC1F,OAAO,CAAC,EAAE,uBAAuB,CAAC;CACnC,+BAuDA;AAED,6FAA6F;AAC7F,iBAAS,eAAe,CAAC,KAAK,EAAE,oBAAoB,+BAmKnD;AAuYD;;;;;GAKG;AACH,eAAO,MAAM,SAAS;;;;CAIpB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"GuideStep.stories.d.ts","sourceRoot":"","sources":["../../../src/components/GuideStep/GuideStep.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"GuideStep.stories.d.ts","sourceRoot":"","sources":["../../../src/components/GuideStep/GuideStep.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AA0E5D,QAAA,MAAM,IAAI;;;;oBA4QU,CAAA;;;;qBAOZ,CAAP;mBAE2D,CAAC;;;;;;;;;;;;;;;;;CAzQ3B,CAAC;AAEnC,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAgCrB,CAAC;AAEF,eAAO,MAAM,cAAc,EAAE,KAmC5B,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAiDxB,CAAC;AAEF,eAAO,MAAM,UAAU,EAAE,KAsCxB,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,KAoC7B,CAAC;AAEF,eAAO,MAAM,YAAY,EAAE,KAsC1B,CAAC;AAEF,eAAO,MAAM,SAAS,EAAE,KAwBvB,CAAC;AAEF,eAAO,MAAM,kBAAkB,EAAE,KAyHhC,CAAC;AAEF,eAAO,MAAM,iBAAiB,EAAE,KA0B/B,CAAC"}
|
|
@@ -3,20 +3,22 @@ export interface MediaCropEditorProps {
|
|
|
3
3
|
/** Image source to crop. */
|
|
4
4
|
src: string;
|
|
5
5
|
/**
|
|
6
|
-
* Current 4:3 region
|
|
7
|
-
* largest centered region (the same view the fixed frame
|
|
6
|
+
* Current 4:3 region as percentages of the source. When omitted, the editor
|
|
7
|
+
* starts from the largest centered region (the same view the fixed frame
|
|
8
|
+
* center-crops to). Legacy pixel regions (any axis > 100) are accepted and
|
|
9
|
+
* normalized.
|
|
8
10
|
*/
|
|
9
11
|
region?: MediaDisplayRegion;
|
|
10
|
-
/** Reports a new region (source
|
|
12
|
+
/** Reports a new region (source %) when the user finishes a drag. */
|
|
11
13
|
onChange: (region: MediaDisplayRegion) => void;
|
|
12
14
|
className?: string;
|
|
13
15
|
}
|
|
14
16
|
/**
|
|
15
17
|
* Interactive crop tool: shows the full source image with a draggable, 4:3-locked
|
|
16
|
-
* selection that maps directly to a {@link MediaDisplayRegion} in source
|
|
17
|
-
* Drag the box to move it, drag a corner to resize. The component
|
|
18
|
-
*
|
|
19
|
-
* stay with the consumer (see the authoring tool's crop modal).
|
|
18
|
+
* selection that maps directly to a {@link MediaDisplayRegion} in source
|
|
19
|
+
* percentages. Drag the box to move it, drag a corner to resize. The component
|
|
20
|
+
* owns all geometry and reports the chosen region — selection chrome and
|
|
21
|
+
* persistence stay with the consumer (see the authoring tool's crop modal).
|
|
20
22
|
*
|
|
21
23
|
* Once the source loads, the editor publishes its aspect ratio as the
|
|
22
24
|
* `--crop-aspect` custom property on its root, so a sized container can fit the
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaCropEditor.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaCropEditor.tsx"],"names":[],"mappings":"AAUA,OAAO,
|
|
1
|
+
{"version":3,"file":"MediaCropEditor.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaCropEditor.tsx"],"names":[],"mappings":"AAUA,OAAO,EAOL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAwF/B,MAAM,WAAW,oBAAoB;IACnC,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ;;;;;OAKG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,qEAAqE;IACrE,QAAQ,EAAE,CAAC,MAAM,EAAE,kBAAkB,KAAK,IAAI,CAAC;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,eAAe,CAAC,EAC9B,GAAG,EACH,MAAM,EACN,QAAQ,EACR,SAAS,GACV,EAAE,oBAAoB,+BAgJtB"}
|
|
@@ -85,8 +85,9 @@ export interface MediaFigureProps {
|
|
|
85
85
|
/** Markers overlaid on the media, positioned by percentage of the visible frame. */
|
|
86
86
|
annotations?: MediaAnnotation[];
|
|
87
87
|
/**
|
|
88
|
-
* When set, show this 4:3 source
|
|
89
|
-
*
|
|
88
|
+
* When set, show this 4:3 source region as percentages of the source image
|
|
89
|
+
* (`{ x, y, width }` in 0–100; height is 4:3-derived), scaled to fill the frame
|
|
90
|
+
* without re-encoding. Legacy pixel regions (any axis > 100) are still accepted.
|
|
90
91
|
*/
|
|
91
92
|
displayRegion?: MediaDisplayRegion;
|
|
92
93
|
/**
|
|
@@ -110,11 +111,12 @@ export interface MediaFigureProps {
|
|
|
110
111
|
/**
|
|
111
112
|
* Instructional image, video, or 3D model with percentage-positioned annotation overlays.
|
|
112
113
|
* The frame is always 4:3; non-4:3 sources are center-cropped unless
|
|
113
|
-
* `displayRegion` selects a source-
|
|
114
|
+
* `displayRegion` selects a source-percentage crop. Point markers use
|
|
114
115
|
* {@link GuideColor} values so they can be visually linked to matching `GuideStep`
|
|
115
116
|
* bullets; circles and rectangles use the same color for their outline and fill.
|
|
116
117
|
* Image figures are zoomable by default: clicking opens the full-size source in a
|
|
117
|
-
* modal lightbox (see `zoomable`).
|
|
118
|
+
* modal lightbox (see `zoomable`). The lightbox mounts the canonical `src` only while
|
|
119
|
+
* open so in-page figures can stay on smaller AVIF variants.
|
|
118
120
|
*/
|
|
119
121
|
export declare function MediaFigure({ src, type, modelFileName, annotations, displayRegion, zoomable, annotationEditing, layoutSettleKey, className, }: MediaFigureProps): import("react").JSX.Element;
|
|
120
122
|
/** Recognizes MDX preview wrappers as MediaFigure slots in `GuideStep.Media`. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFigure.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigure.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"MediaFigure.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigure.tsx"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFigure.stories.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigure.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EACL,WAAW,EAGZ,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"MediaFigure.stories.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigure.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EACL,WAAW,EAGZ,MAAM,eAAe,CAAC;AAoEvB,QAAA,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;;CAc0B,CAAC;AAErC,eAAe,IAAI,CAAC;AAEpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,eAAO,MAAM,OAAO,EAAE,KAcrB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAiBtB,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KAqBlC,CAAC;AAEF,eAAO,MAAM,oBAAoB,EAAE,KA2ClC,CAAC;AAEF,eAAO,MAAM,KAAK,EAAE,KAkBnB,CAAC;AAEF,eAAO,MAAM,OAAO,EAAE,KAkBrB,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,KAiBjC,CAAC;AAEF,eAAO,MAAM,aAAa,EAAE,KAkB3B,CAAC;AAKF,eAAO,MAAM,gBAAgB,EAAE,KA0F9B,CAAC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type ReactNode } from "react";
|
|
2
2
|
import { type MediaDisplayRegion } from "../../utils/mediaCrop";
|
|
3
|
+
import type { GuideImageRole } from "../../utils/guideImageSources";
|
|
3
4
|
export interface MediaFigureClipFrameProps {
|
|
4
5
|
className?: string;
|
|
5
6
|
src: string;
|
|
@@ -8,6 +9,14 @@ export interface MediaFigureClipFrameProps {
|
|
|
8
9
|
modelFileName?: string;
|
|
9
10
|
layoutSettleKey?: boolean | number | string;
|
|
10
11
|
remeasureWhenVisible?: boolean;
|
|
12
|
+
/** Image role for responsive `sizes` / preferred width. @default "display" */
|
|
13
|
+
imageRole?: GuideImageRole;
|
|
14
|
+
/**
|
|
15
|
+
* When false, always use the canonical `src` (lightbox). @default true
|
|
16
|
+
*/
|
|
17
|
+
responsive?: boolean;
|
|
18
|
+
/** Override image loading (lightbox uses eager). */
|
|
19
|
+
loading?: "lazy" | "eager";
|
|
11
20
|
children?: ReactNode;
|
|
12
21
|
}
|
|
13
22
|
/**
|
|
@@ -15,7 +24,7 @@ export interface MediaFigureClipFrameProps {
|
|
|
15
24
|
* taken on this element's border box so crop math matches the visible area — including
|
|
16
25
|
* inside modals and container-query layouts.
|
|
17
26
|
*/
|
|
18
|
-
export declare function MediaFigureClipFrame({ className, src, type, displayRegion, modelFileName, layoutSettleKey, remeasureWhenVisible, children, }: MediaFigureClipFrameProps): import("react").JSX.Element;
|
|
27
|
+
export declare function MediaFigureClipFrame({ className, src, type, displayRegion, modelFileName, layoutSettleKey, remeasureWhenVisible, imageRole, responsive, loading, children, }: MediaFigureClipFrameProps): import("react").JSX.Element;
|
|
19
28
|
export interface MediaFigureMediaProps {
|
|
20
29
|
src: string;
|
|
21
30
|
type: "image" | "video" | "model";
|
|
@@ -23,6 +32,9 @@ export interface MediaFigureMediaProps {
|
|
|
23
32
|
modelFileName?: string;
|
|
24
33
|
layoutSettleKey?: boolean | number | string;
|
|
25
34
|
remeasureWhenVisible?: boolean;
|
|
35
|
+
imageRole?: GuideImageRole;
|
|
36
|
+
responsive?: boolean;
|
|
37
|
+
loading?: "lazy" | "eager";
|
|
26
38
|
}
|
|
27
39
|
/** Fills an existing relative clip frame (used inside {@link MediaFigure}). */
|
|
28
40
|
export declare function MediaFigureMedia({ className, ...props }: MediaFigureMediaProps & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFigureClipFrame.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigureClipFrame.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAEjF,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"MediaFigureClipFrame.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigureClipFrame.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAuB,KAAK,SAAS,EAAuB,MAAM,OAAO,CAAC;AAEjF,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AAG/B,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+BAA+B,CAAC;AAKpE,MAAM,WAAW,yBAAyB;IACxC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IACnC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,8EAA8E;IAC9E,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,oDAAoD;IACpD,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IAC3B,QAAQ,CAAC,EAAE,SAAS,CAAC;CACtB;AAED;;;;GAIG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,SAAS,EACT,GAAG,EACH,IAAc,EACd,aAAa,EACb,aAAa,EACb,eAAe,EACf,oBAA4B,EAC5B,SAAqB,EACrB,UAAiB,EACjB,OAAgB,EAChB,QAAQ,GACT,EAAE,yBAAyB,+BA2F3B;AAED,MAAM,WAAW,qBAAqB;IACpC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,OAAO,GAAG,OAAO,GAAG,OAAO,CAAC;IAClC,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,GAAG,MAAM,GAAG,MAAM,CAAC;IAC5C,oBAAoB,CAAC,EAAE,OAAO,CAAC;IAC/B,SAAS,CAAC,EAAE,cAAc,CAAC;IAC3B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;CAC5B;AAED,+EAA+E;AAC/E,wBAAgB,gBAAgB,CAAC,EAC/B,SAA8B,EAC9B,GAAG,KAAK,EACT,EAAE,qBAAqB,GAAG;IAAE,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,+BAEhD"}
|
|
@@ -8,8 +8,8 @@ export interface MediaFigureThumbnailProps {
|
|
|
8
8
|
/** Markers overlaid on the media, positioned by percentage of the visible frame. */
|
|
9
9
|
annotations?: MediaAnnotation[];
|
|
10
10
|
/**
|
|
11
|
-
* When set, show this 4:3 source-
|
|
12
|
-
* {@link MediaFigure} crop.
|
|
11
|
+
* When set, show this 4:3 source-percentage rect in the thumbnail, matching the
|
|
12
|
+
* main {@link MediaFigure} crop.
|
|
13
13
|
*/
|
|
14
14
|
displayRegion?: MediaDisplayRegion;
|
|
15
15
|
className?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"MediaFigureThumbnail.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigureThumbnail.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAqBhE,MAAM,WAAW,yBAAyB;IACxC,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAChC,oFAAoF;IACpF,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC;;;OAGG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,GAAG,EACH,IAAc,EACd,WAAgB,EAChB,aAAa,EACb,SAAS,GACV,EAAE,yBAAyB,+
|
|
1
|
+
{"version":3,"file":"MediaFigureThumbnail.d.ts","sourceRoot":"","sources":["../../../src/components/MediaFigure/MediaFigureThumbnail.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACvE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAqBhE,MAAM,WAAW,yBAAyB;IACxC,0CAA0C;IAC1C,GAAG,EAAE,MAAM,CAAC;IACZ,iFAAiF;IACjF,IAAI,CAAC,EAAE,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAChC,oFAAoF;IACpF,WAAW,CAAC,EAAE,eAAe,EAAE,CAAC;IAChC;;;OAGG;IACH,aAAa,CAAC,EAAE,kBAAkB,CAAC;IACnC,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,GAAG,EACH,IAAc,EACd,WAAgB,EAChB,aAAa,EACb,SAAS,GACV,EAAE,yBAAyB,+BAyB3B"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolList.d.ts","sourceRoot":"","sources":["../../../src/components/ToolList/ToolList.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ToolList.d.ts","sourceRoot":"","sources":["../../../src/components/ToolList/ToolList.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAIvC,MAAM,WAAW,aAAa;IAC5B,qEAAqE;IACrE,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,gCAAgC;IAChC,QAAQ,EAAE,SAAS,CAAC;IACpB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,iBAAiB;IAChC,yBAAyB;IACzB,IAAI,EAAE,SAAS,CAAC;IAChB,oCAAoC;IACpC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mCAAmC;IACnC,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,8CAA8C;IAC9C,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,iBAAS,YAAY,CAAC,EACpB,IAAI,EACJ,SAAS,EACT,IAAI,EACJ,QAAQ,EACR,KAAK,EACL,QAAQ,EACR,SAAS,GACV,EAAE,iBAAiB,+BAoCnB;AAED,iBAAS,YAAY,CAAC,EACpB,KAAuB,EACvB,QAAQ,EACR,SAAS,GACV,EAAE,aAAa,+BAaf;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ;;CAAsD,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
import type { GuideImageVariantsManifest } from "../utils/guideImageSources";
|
|
3
|
+
export interface GuideImageVariantsProviderProps {
|
|
4
|
+
/** Manifest from `images/thumbnails/variants.json`, or `null` to disable responsive variants. */
|
|
5
|
+
manifest?: GuideImageVariantsManifest | null;
|
|
6
|
+
children: ReactNode;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Supplies a per-guide {@link GuideImageVariantsManifest} so `MediaFigure`,
|
|
10
|
+
* thumbnails, heroes, and tool list images can emit AVIF `srcset` without
|
|
11
|
+
* speculative URLs. Omit the provider (or pass `null`) for single-`src` fallback.
|
|
12
|
+
*/
|
|
13
|
+
export declare function GuideImageVariantsProvider({ manifest, children, }: GuideImageVariantsProviderProps): import("react").JSX.Element;
|
|
14
|
+
/** Current guide image variants manifest, or `null` when unset. */
|
|
15
|
+
export declare function useGuideImageVariants(): GuideImageVariantsManifest | null;
|
|
16
|
+
//# sourceMappingURL=guideImageVariants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"guideImageVariants.d.ts","sourceRoot":"","sources":["../../src/context/guideImageVariants.tsx"],"names":[],"mappings":"AAAA,OAAO,EAA6B,KAAK,SAAS,EAAE,MAAM,OAAO,CAAC;AAClE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AAM7E,MAAM,WAAW,+BAA+B;IAC9C,iGAAiG;IACjG,QAAQ,CAAC,EAAE,0BAA0B,GAAG,IAAI,CAAC;IAC7C,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CAAC,EACzC,QAAe,EACf,QAAQ,GACT,EAAE,+BAA+B,+BAMjC;AAED,mEAAmE;AACnE,wBAAgB,qBAAqB,IAAI,0BAA0B,GAAG,IAAI,CAEzE"}
|