@openpawlabs/diy-guides-ui 1.8.0 → 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.
Files changed (31) hide show
  1. package/README.md +22 -0
  2. package/bin/diy-guide-images.mjs +317 -0
  3. package/dist/components/GuideLayout/GuideLayout.d.ts.map +1 -1
  4. package/dist/components/GuideLayout/GuideLayout.stories.d.ts.map +1 -1
  5. package/dist/components/GuideResponsiveImage/GuideResponsiveImage.d.ts +23 -0
  6. package/dist/components/GuideResponsiveImage/GuideResponsiveImage.d.ts.map +1 -0
  7. package/dist/components/MediaFigure/MediaCropEditor.d.ts +9 -7
  8. package/dist/components/MediaFigure/MediaCropEditor.d.ts.map +1 -1
  9. package/dist/components/MediaFigure/MediaFigure.d.ts +6 -4
  10. package/dist/components/MediaFigure/MediaFigure.d.ts.map +1 -1
  11. package/dist/components/MediaFigure/MediaFigure.stories.d.ts.map +1 -1
  12. package/dist/components/MediaFigure/MediaFigureClipFrame.d.ts +13 -1
  13. package/dist/components/MediaFigure/MediaFigureClipFrame.d.ts.map +1 -1
  14. package/dist/components/MediaFigure/MediaFigureThumbnail.d.ts +2 -2
  15. package/dist/components/MediaFigure/MediaFigureThumbnail.d.ts.map +1 -1
  16. package/dist/components/ToolList/ToolList.d.ts.map +1 -1
  17. package/dist/context/guideImageVariants.d.ts +16 -0
  18. package/dist/context/guideImageVariants.d.ts.map +1 -0
  19. package/dist/diy-guides-ui.cjs +6 -6
  20. package/dist/diy-guides-ui.cjs.map +1 -1
  21. package/dist/diy-guides-ui.js +3106 -2905
  22. package/dist/diy-guides-ui.js.map +1 -1
  23. package/dist/index.d.ts +7 -1
  24. package/dist/index.d.ts.map +1 -1
  25. package/dist/utils/guideImageSources.d.ts +73 -0
  26. package/dist/utils/guideImageSources.d.ts.map +1 -0
  27. package/dist/utils/guideImageSources.test.d.ts +2 -0
  28. package/dist/utils/guideImageSources.test.d.ts.map +1 -0
  29. package/dist/utils/mediaCrop.d.ts +40 -13
  30. package/dist/utils/mediaCrop.d.ts.map +1 -1
  31. 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,EAEL,KAAK,UAAU,EAChB,MAAM,oBAAoB,CAAC;AAE5B,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,+BA2CxB;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
+ {"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;;;;;;;qBAyDY,CAAC;;;;qBAQa,CAAC;;;;;;;;;;;;;;;CAxDD,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"}
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"}
@@ -3,20 +3,22 @@ export interface MediaCropEditorProps {
3
3
  /** Image source to crop. */
4
4
  src: string;
5
5
  /**
6
- * Current 4:3 region in source pixels. When omitted, the editor starts from the
7
- * largest centered region (the same view the fixed frame center-crops to).
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 &gt; 100) are accepted and
9
+ * normalized.
8
10
  */
9
11
  region?: MediaDisplayRegion;
10
- /** Reports a new region (source pixels) when the user finishes a drag. */
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 pixels.
17
- * Drag the box to move it, drag a corner to resize. The component owns all
18
- * pixel geometry and reports the chosen region — selection chrome and persistence
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,EAKL,KAAK,kBAAkB,EACxB,MAAM,uBAAuB,CAAC;AA2E/B,MAAM,WAAW,oBAAoB;IACnC,4BAA4B;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,MAAM,CAAC,EAAE,kBAAkB,CAAC;IAC5B,0EAA0E;IAC1E,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,+BA6ItB"}
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-pixel rect (`height` is `round(width × 3 / 4)`),
89
- * scaled to fill the frame without re-encoding the image.
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 &gt; 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-pixel crop. Point markers use
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":"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"}
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;AAmEvB,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
+ {"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;AAM/B,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,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,QAAQ,GACT,EAAE,yBAAyB,+BAwF3B;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;CAChC;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"}
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-pixel rect in the thumbnail, matching the main
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,+BAwB3B"}
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":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAGvC,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,+BAmCnB;AAED,iBAAS,YAAY,CAAC,EACpB,KAAuB,EACvB,QAAQ,EACR,SAAS,GACV,EAAE,aAAa,+BAaf;AAED;;;GAGG;AACH,eAAO,MAAM,QAAQ;;CAAsD,CAAC"}
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"}