@connextar/house 0.16.1 → 0.18.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 (54) hide show
  1. package/README.md +205 -3
  2. package/dist/ai/index.d.ts +1 -1
  3. package/dist/ai/index.d.ts.map +1 -1
  4. package/dist/ai/index.js +1 -1
  5. package/dist/ai/index.js.map +1 -1
  6. package/dist/ai/provider.d.ts +30 -4
  7. package/dist/ai/provider.d.ts.map +1 -1
  8. package/dist/ai/provider.js +25 -4
  9. package/dist/ai/provider.js.map +1 -1
  10. package/dist/guides/guide-article.d.ts +13 -2
  11. package/dist/guides/guide-article.d.ts.map +1 -1
  12. package/dist/guides/guide-article.js +5 -3
  13. package/dist/guides/guide-article.js.map +1 -1
  14. package/dist/guides/guide-figure-zoom.d.ts +62 -0
  15. package/dist/guides/guide-figure-zoom.d.ts.map +1 -0
  16. package/dist/guides/guide-figure-zoom.js +272 -0
  17. package/dist/guides/guide-figure-zoom.js.map +1 -0
  18. package/dist/guides/guide-figure.d.ts +21 -0
  19. package/dist/guides/guide-figure.d.ts.map +1 -0
  20. package/dist/guides/guide-figure.js +19 -0
  21. package/dist/guides/guide-figure.js.map +1 -0
  22. package/dist/guides/index.d.ts +2 -0
  23. package/dist/guides/index.d.ts.map +1 -1
  24. package/dist/guides/index.js +2 -0
  25. package/dist/guides/index.js.map +1 -1
  26. package/dist/guides/library.d.ts +13 -0
  27. package/dist/guides/library.d.ts.map +1 -1
  28. package/dist/guides/library.js +8 -0
  29. package/dist/guides/library.js.map +1 -1
  30. package/dist/health/health.d.ts +65 -0
  31. package/dist/health/health.d.ts.map +1 -0
  32. package/dist/health/health.js +93 -0
  33. package/dist/health/health.js.map +1 -0
  34. package/dist/health/index.d.ts +2 -0
  35. package/dist/health/index.d.ts.map +1 -0
  36. package/dist/health/index.js +2 -0
  37. package/dist/health/index.js.map +1 -0
  38. package/dist/markdown/figure.d.ts +44 -0
  39. package/dist/markdown/figure.d.ts.map +1 -0
  40. package/dist/markdown/figure.js +56 -0
  41. package/dist/markdown/figure.js.map +1 -0
  42. package/dist/markdown/figures.d.ts +94 -0
  43. package/dist/markdown/figures.d.ts.map +1 -0
  44. package/dist/markdown/figures.js +126 -0
  45. package/dist/markdown/figures.js.map +1 -0
  46. package/dist/markdown/guide.d.ts +15 -3
  47. package/dist/markdown/guide.d.ts.map +1 -1
  48. package/dist/markdown/guide.js +20 -3
  49. package/dist/markdown/guide.js.map +1 -1
  50. package/dist/markdown/index.d.ts +2 -0
  51. package/dist/markdown/index.d.ts.map +1 -1
  52. package/dist/markdown/index.js +2 -0
  53. package/dist/markdown/index.js.map +1 -1
  54. package/package.json +5 -1
@@ -0,0 +1,272 @@
1
+ "use client";
2
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
+ import * as DialogPrimitive from "@radix-ui/react-dialog";
4
+ import { Maximize2, X, ZoomIn, ZoomOut } from "lucide-react";
5
+ import { useCallback, useEffect, useRef, useState, } from "react";
6
+ import { cx } from "../internal/cx.js";
7
+ import { GUIDES_LABELS } from "./library.js";
8
+ export const GUIDE_ZOOM_CLASS_NAMES = {
9
+ trigger: "group relative block w-full cursor-zoom-in rounded-xl text-left focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:ring-offset-2 focus-visible:ring-offset-background focus-visible:outline-none",
10
+ hint: "pointer-events-none absolute right-2 bottom-2 inline-flex items-center gap-1 rounded-full border border-border bg-background/90 px-2 py-0.5 text-xs font-medium text-muted-foreground shadow-sm transition-colors group-hover:text-foreground group-focus-visible:text-foreground motion-reduce:transition-none",
11
+ overlay: "fixed inset-0 z-50 bg-black/70 backdrop-blur-sm",
12
+ content: "fixed inset-0 z-50 flex flex-col overflow-hidden bg-background text-foreground shadow-2xl outline-none sm:inset-4 sm:rounded-xl sm:border sm:border-border",
13
+ toolbar: "flex shrink-0 items-center gap-1 border-b border-border px-2 py-1.5 sm:px-3",
14
+ instructions: "mr-auto hidden min-w-0 truncate pl-1 text-xs text-muted-foreground sm:block",
15
+ button: "inline-flex size-10 items-center justify-center rounded-lg text-muted-foreground hover:bg-accent hover:text-foreground focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:outline-none disabled:pointer-events-none disabled:opacity-40",
16
+ level: "h-10 min-w-16 rounded-lg px-2 text-sm font-medium text-foreground tabular-nums hover:bg-accent focus-visible:ring-2 focus-visible:ring-primary/40 focus-visible:outline-none",
17
+ stage: "relative min-h-0 flex-1 touch-none overflow-hidden bg-muted/40 select-none",
18
+ footer: "max-h-[30%] shrink-0 overflow-y-auto border-t border-border px-4 py-3 text-sm",
19
+ caption: "font-medium text-foreground",
20
+ alt: "mt-1 text-muted-foreground",
21
+ };
22
+ /** Each button press or key multiplies or divides the zoom by this. */
23
+ export const ZOOM_STEP = 1.25;
24
+ /** The margin kept around a fitted picture, in CSS pixels, each side. */
25
+ const FIT_MARGIN = 16;
26
+ /** Used when nothing can be measured (a page not laid out yet, or a test's DOM). */
27
+ const FALLBACK_SIZE = { w: 800, h: 600 };
28
+ const clamp = (value, min, max) => Math.min(max, Math.max(min, value));
29
+ const near = (a, b) => Math.abs(a - b) < 0.005;
30
+ /** The scale that fits `natural` inside `stage`, never past full size for a picture with a natural size. */
31
+ export function fitScale(natural, stage, capAtFull) {
32
+ const w = stage.w - 2 * FIT_MARGIN;
33
+ const h = stage.h - 2 * FIT_MARGIN;
34
+ if (w <= 0 || h <= 0 || natural.w <= 0 || natural.h <= 0)
35
+ return 1;
36
+ const fit = Math.min(w / natural.w, h / natural.h);
37
+ return capAtFull ? Math.min(fit, 1) : fit;
38
+ }
39
+ /**
40
+ * A guide's picture, opened full-size: a button around the article's picture (with a "Click to
41
+ * enlarge" hint) that opens a dialog fitting it to the screen. In there it zooms with the
42
+ * buttons, `+` and `−`, ⌘/Ctrl + scroll (a trackpad pinch) and a touch pinch; drags to pan
43
+ * when it is bigger than the screen (and scrolls, and moves with the arrow keys); a double-click
44
+ * or double-tap switches between fit and full size, and `0` fits again. Escape closes it and
45
+ * focus goes back to the picture. The caption and alt text are shown under it.
46
+ *
47
+ * Zooming eases unless the reader prefers reduced motion; dragging and pinching never do.
48
+ */
49
+ export function GuideFigureZoom({ children, full, width, height, alt, caption, labels, classNames, }) {
50
+ const text = { ...GUIDES_LABELS, ...labels };
51
+ const c = { ...GUIDE_ZOOM_CLASS_NAMES, ...classNames };
52
+ const known = width !== undefined && height !== undefined && width > 0 && height > 0;
53
+ const [open, setOpen] = useState(false);
54
+ const [natural, setNatural] = useState(known ? { w: width, h: height } : FALLBACK_SIZE);
55
+ const [stage, setStage] = useState({ w: 0, h: 0 });
56
+ const [stageEl, setStageEl] = useState(null);
57
+ /** null: fitted, and staying fitted as the window changes size. */
58
+ const [zoom, setZoom] = useState(null);
59
+ const [offset, setOffset] = useState({ x: 0, y: 0 });
60
+ const [gesture, setGesture] = useState(null);
61
+ const thumb = useRef(null);
62
+ const fit = fitScale(natural, stage, known);
63
+ const min = fit;
64
+ const max = Math.max(fit, 1) * 4;
65
+ const scale = clamp(zoom ?? fit, min, max);
66
+ /** Where a double-click goes from fit: full size, or twice the fit when that is already full size. */
67
+ const detail = clamp(known && fit < 1 ? 1 : fit * 2, min, max);
68
+ /** An offset that keeps the picture over the stage: centred on an axis where it fits, edge to edge where not. */
69
+ const bound = useCallback((point, s) => {
70
+ const limitX = Math.max(0, (natural.w * s - stage.w) / 2);
71
+ const limitY = Math.max(0, (natural.h * s - stage.h) / 2);
72
+ return { x: clamp(point.x, -limitX, limitX), y: clamp(point.y, -limitY, limitY) };
73
+ }, [natural, stage]);
74
+ // The latest view, for the listeners and gestures that outlive a render.
75
+ const view = useRef({ scale, offset, fit, min, max, detail, bound });
76
+ view.current = { scale, offset, fit, min, max, detail, bound };
77
+ /** Zoom to `next`, keeping the point `origin` (from the stage's centre) where it is. */
78
+ const zoomTo = useCallback((next, origin = { x: 0, y: 0 }) => {
79
+ const v = view.current;
80
+ const s = clamp(next, v.min, v.max);
81
+ const ratio = s / v.scale;
82
+ const moved = {
83
+ x: origin.x - (origin.x - v.offset.x) * ratio,
84
+ y: origin.y - (origin.y - v.offset.y) * ratio,
85
+ };
86
+ setZoom(near(s, v.fit) ? null : s);
87
+ setOffset(near(s, v.fit) ? { x: 0, y: 0 } : v.bound(moved, s));
88
+ }, []);
89
+ const panBy = useCallback((dx, dy) => {
90
+ const v = view.current;
91
+ setOffset(v.bound({ x: v.offset.x + dx, y: v.offset.y + dy }, v.scale));
92
+ }, []);
93
+ const toggle = useCallback((origin) => {
94
+ const v = view.current;
95
+ zoomTo(near(v.scale, v.fit) ? v.detail : v.fit, origin);
96
+ }, [zoomTo]);
97
+ /** A point on the screen, measured from the stage's centre. */
98
+ const fromCentre = useCallback((clientX, clientY) => {
99
+ if (!stageEl)
100
+ return { x: 0, y: 0 };
101
+ const rect = stageEl.getBoundingClientRect();
102
+ return { x: clientX - rect.left - rect.width / 2, y: clientY - rect.top - rect.height / 2 };
103
+ }, [stageEl]);
104
+ // The stage's size, kept as the window changes.
105
+ useEffect(() => {
106
+ if (!stageEl)
107
+ return;
108
+ const measure = () => {
109
+ const rect = stageEl.getBoundingClientRect();
110
+ setStage({ w: rect.width, h: rect.height });
111
+ };
112
+ measure();
113
+ window.addEventListener("resize", measure);
114
+ const observer = typeof ResizeObserver === "undefined" ? null : new ResizeObserver(measure);
115
+ observer?.observe(stageEl);
116
+ return () => {
117
+ window.removeEventListener("resize", measure);
118
+ observer?.disconnect();
119
+ };
120
+ }, [stageEl]);
121
+ // ⌘/Ctrl + wheel (and a trackpad pinch, which arrives as one) zooms at the pointer; a plain wheel pans a zoomed
122
+ // picture. Not React's onWheel: that listener is passive, so it can't stop the page zooming instead.
123
+ useEffect(() => {
124
+ if (!stageEl)
125
+ return;
126
+ const onWheel = (event) => {
127
+ const v = view.current;
128
+ if (event.ctrlKey || event.metaKey) {
129
+ event.preventDefault();
130
+ const rect = stageEl.getBoundingClientRect();
131
+ const origin = { x: event.clientX - rect.left - rect.width / 2, y: event.clientY - rect.top - rect.height / 2 };
132
+ zoomTo(v.scale * Math.exp(-clamp(event.deltaY, -50, 50) / 100), origin);
133
+ }
134
+ else if (!near(v.scale, v.fit)) {
135
+ event.preventDefault();
136
+ panBy(-event.deltaX, -event.deltaY);
137
+ }
138
+ };
139
+ stageEl.addEventListener("wheel", onWheel, { passive: false });
140
+ return () => stageEl.removeEventListener("wheel", onWheel);
141
+ }, [stageEl, zoomTo, panBy]);
142
+ // Pointers on the stage: one drags, two pinch. A quick second tap (touch or pen) switches fit and full size.
143
+ const pointers = useRef(new Map());
144
+ const start = useRef(null);
145
+ const lastTap = useRef(null);
146
+ const beginGesture = () => {
147
+ const points = [...pointers.current.values()];
148
+ const [a, b] = points;
149
+ if (!a)
150
+ return;
151
+ const point = b ? { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 } : a;
152
+ const distance = b ? Math.hypot(a.x - b.x, a.y - b.y) : 0;
153
+ start.current = {
154
+ scale: view.current.scale,
155
+ offset: view.current.offset,
156
+ point,
157
+ distance,
158
+ at: Date.now(),
159
+ moved: false,
160
+ };
161
+ setGesture(b ? "pinch" : "drag");
162
+ };
163
+ const onPointerDown = (event) => {
164
+ if (event.pointerType === "mouse" && event.button !== 0)
165
+ return;
166
+ event.currentTarget.setPointerCapture?.(event.pointerId);
167
+ pointers.current.set(event.pointerId, fromCentre(event.clientX, event.clientY));
168
+ if (pointers.current.size <= 2)
169
+ beginGesture();
170
+ };
171
+ const onPointerMove = (event) => {
172
+ if (!pointers.current.has(event.pointerId) || !start.current)
173
+ return;
174
+ pointers.current.set(event.pointerId, fromCentre(event.clientX, event.clientY));
175
+ const s = start.current;
176
+ const [a, b] = [...pointers.current.values()];
177
+ if (!a)
178
+ return;
179
+ if (b && s.distance > 0) {
180
+ s.moved = true;
181
+ const mid = { x: (a.x + b.x) / 2, y: (a.y + b.y) / 2 };
182
+ const v = view.current;
183
+ const next = clamp((s.scale * Math.hypot(a.x - b.x, a.y - b.y)) / s.distance, v.min, v.max);
184
+ const ratio = next / s.scale;
185
+ setZoom(near(next, v.fit) ? null : next);
186
+ setOffset(v.bound({ x: mid.x - (s.point.x - s.offset.x) * ratio, y: mid.y - (s.point.y - s.offset.y) * ratio }, next));
187
+ }
188
+ else if (!b) {
189
+ const dx = a.x - s.point.x;
190
+ const dy = a.y - s.point.y;
191
+ if (Math.hypot(dx, dy) > 4)
192
+ s.moved = true;
193
+ setOffset(view.current.bound({ x: s.offset.x + dx, y: s.offset.y + dy }, view.current.scale));
194
+ }
195
+ };
196
+ const onPointerUp = (event) => {
197
+ if (!pointers.current.has(event.pointerId))
198
+ return;
199
+ const point = pointers.current.get(event.pointerId);
200
+ const wasTap = pointers.current.size === 1 && start.current && !start.current.moved && Date.now() - start.current.at < 300;
201
+ pointers.current.delete(event.pointerId);
202
+ if (pointers.current.size > 0) {
203
+ beginGesture(); // the finger left on the screen carries on as a drag
204
+ return;
205
+ }
206
+ start.current = null;
207
+ setGesture(null);
208
+ if (!wasTap || event.pointerType === "mouse")
209
+ return; // a mouse has onDoubleClick
210
+ const previous = lastTap.current;
211
+ if (previous &&
212
+ Date.now() - previous.at < 350 &&
213
+ Math.hypot(point.x - previous.point.x, point.y - previous.point.y) < 30) {
214
+ lastTap.current = null;
215
+ toggle(point);
216
+ }
217
+ else {
218
+ lastTap.current = { at: Date.now(), point };
219
+ }
220
+ };
221
+ const onKeyDown = (event) => {
222
+ if (event.metaKey || event.ctrlKey || event.altKey)
223
+ return; // ⌘/Ctrl + and − stay the browser's page zoom
224
+ const v = view.current;
225
+ const step = 48;
226
+ const keys = {
227
+ "+": () => zoomTo(v.scale * ZOOM_STEP),
228
+ "=": () => zoomTo(v.scale * ZOOM_STEP),
229
+ "-": () => zoomTo(v.scale / ZOOM_STEP),
230
+ _: () => zoomTo(v.scale / ZOOM_STEP),
231
+ "−": () => zoomTo(v.scale / ZOOM_STEP),
232
+ "0": () => zoomTo(v.fit),
233
+ ArrowLeft: () => panBy(step, 0),
234
+ ArrowRight: () => panBy(-step, 0),
235
+ ArrowUp: () => panBy(0, step),
236
+ ArrowDown: () => panBy(0, -step),
237
+ };
238
+ const action = keys[event.key];
239
+ // Arrow keys move only a zoomed picture, so they still move between the buttons' focus otherwise.
240
+ if (!action || (event.key.startsWith("Arrow") && near(v.scale, v.fit)))
241
+ return;
242
+ event.preventDefault();
243
+ action();
244
+ };
245
+ const change = (next) => {
246
+ if (next && !known) {
247
+ const rect = thumb.current?.getBoundingClientRect();
248
+ setNatural(rect && rect.width > 0 && rect.height > 0 ? { w: rect.width, h: rect.height } : FALLBACK_SIZE);
249
+ }
250
+ if (!next) {
251
+ setZoom(null);
252
+ setOffset({ x: 0, y: 0 });
253
+ setGesture(null);
254
+ pointers.current.clear();
255
+ start.current = null;
256
+ }
257
+ setOpen(next);
258
+ };
259
+ const zoomed = !near(scale, fit);
260
+ const percent = Math.round(scale * 100);
261
+ const title = caption || alt;
262
+ return (_jsxs(DialogPrimitive.Root, { open: open, onOpenChange: change, children: [_jsx(DialogPrimitive.Trigger, { asChild: true, children: _jsxs("button", { type: "button", className: c.trigger, "aria-label": text.zoomOpen.replace("{alt}", alt), children: [_jsx("span", { ref: thumb, className: "block", children: children }), _jsxs("span", { className: c.hint, "aria-hidden": true, children: [_jsx(Maximize2, { className: "size-3" }), text.zoomHint] })] }) }), _jsxs(DialogPrimitive.Portal, { children: [_jsx(DialogPrimitive.Overlay, { className: c.overlay }), _jsxs(DialogPrimitive.Content, { className: c.content, onKeyDown: onKeyDown, ...(caption ? {} : { "aria-describedby": undefined }), onOpenAutoFocus: (event) => {
263
+ // The close button, not the first zoom button: Enter on open shouldn't zoom.
264
+ event.preventDefault();
265
+ event.currentTarget?.querySelector("[data-house-zoom-close]")?.focus();
266
+ }, children: [_jsxs("div", { className: c.toolbar, children: [_jsx("p", { className: c.instructions, children: text.zoomInstructions }), _jsx("button", { type: "button", className: cx(c.button, "ml-auto sm:ml-0"), onClick: () => zoomTo(scale / ZOOM_STEP), disabled: scale <= min + 0.001, "aria-label": text.zoomOut, title: text.zoomOut, children: _jsx(ZoomOut, { className: "size-5", "aria-hidden": true }) }), _jsxs("button", { type: "button", className: c.level, onClick: () => toggle(), "aria-label": text.zoomToggle, title: text.zoomToggle, children: [percent, "%"] }), _jsx("button", { type: "button", className: c.button, onClick: () => zoomTo(scale * ZOOM_STEP), disabled: scale >= max - 0.001, "aria-label": text.zoomIn, title: text.zoomIn, children: _jsx(ZoomIn, { className: "size-5", "aria-hidden": true }) }), _jsx(DialogPrimitive.Close, { className: c.button, "aria-label": text.zoomClose, title: text.zoomClose, "data-house-zoom-close": "", children: _jsx(X, { className: "size-5", "aria-hidden": true }) }), _jsx("span", { className: "sr-only", "aria-live": "polite", children: text.zoomLevel.replace("{percent}", String(percent)) })] }), _jsx("div", { ref: setStageEl, "data-house-zoom-stage": "", className: cx(c.stage, zoomed ? (gesture === "drag" ? "cursor-grabbing" : "cursor-grab") : "cursor-zoom-in"), onPointerDown: onPointerDown, onPointerMove: onPointerMove, onPointerUp: onPointerUp, onPointerCancel: onPointerUp, onDoubleClick: (event) => toggle(fromCentre(event.clientX, event.clientY)), children: _jsx("div", { "data-house-zoom-picture": "", "data-scale": scale.toFixed(3), className: cx("absolute top-1/2 left-1/2 origin-center", gesture ? "" : "motion-safe:transition-transform motion-safe:duration-150 motion-safe:ease-out"), style: {
267
+ width: natural.w,
268
+ height: natural.h,
269
+ transform: `translate(-50%, -50%) translate(${offset.x}px, ${offset.y}px) scale(${scale})`,
270
+ }, children: full ?? children }) }), _jsxs("div", { className: c.footer, children: [_jsx(DialogPrimitive.Title, { className: c.caption, children: title }), caption ? _jsx(DialogPrimitive.Description, { className: c.alt, children: alt }) : null] })] })] })] }));
271
+ }
272
+ //# sourceMappingURL=guide-figure-zoom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide-figure-zoom.js","sourceRoot":"","sources":["../../src/guides/guide-figure-zoom.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,21 @@
1
+ import type { ReactNode } from "react";
2
+ import { type GuideFigureClassNames } from "../markdown/figure.js";
3
+ import type { GuideFigureBlock, GuideFigures } from "../markdown/figures.js";
4
+ import { type GuideZoomClassNames } from "./guide-figure-zoom.js";
5
+ import type { GuidesLabels } from "./library.js";
6
+ export interface GuideFigureProps {
7
+ figure: GuideFigureBlock;
8
+ figures?: GuideFigures;
9
+ /** Open full-size on a click, Enter or Space. Default: on. */
10
+ zoom?: boolean;
11
+ labels?: Partial<GuidesLabels>;
12
+ classNames?: Partial<GuideFigureClassNames>;
13
+ zoomClassNames?: Partial<GuideZoomClassNames>;
14
+ }
15
+ /**
16
+ * A guide's picture with its caption, as `GuideArticle` draws it: the picture is a button that
17
+ * opens it full-size (`GuideFigureZoom`). Server-safe — a diagram registered as a component is
18
+ * drawn here, on the server, and only the drawn element crosses into the zoom dialog.
19
+ */
20
+ export declare function GuideFigure({ figure, figures, zoom, labels, classNames, zoomClassNames, }: GuideFigureProps): ReactNode;
21
+ //# sourceMappingURL=guide-figure.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide-figure.d.ts","sourceRoot":"","sources":["../../src/guides/guide-figure.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAqC,KAAK,qBAAqB,EAAE,MAAM,uBAAuB,CAAC;AACtG,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC7E,OAAO,EAAmB,KAAK,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAEjD,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,gBAAgB,CAAC;IACzB,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,8DAA8D;IAC9D,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,qBAAqB,CAAC,CAAC;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC/C;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,EAC1B,MAAM,EACN,OAAO,EACP,IAAW,EACX,MAAM,EACN,UAAU,EACV,cAAc,GACf,EAAE,gBAAgB,GAAG,SAAS,CAiC9B"}
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { GuideFigureMedia, GuideFigureView } from "../markdown/figure.js";
3
+ import { GuideFigureZoom } from "./guide-figure-zoom.js";
4
+ /**
5
+ * A guide's picture with its caption, as `GuideArticle` draws it: the picture is a button that
6
+ * opens it full-size (`GuideFigureZoom`). Server-safe — a diagram registered as a component is
7
+ * drawn here, on the server, and only the drawn element crosses into the zoom dialog.
8
+ */
9
+ export function GuideFigure({ figure, figures, zoom = true, labels, classNames, zoomClassNames, }) {
10
+ if (!zoom)
11
+ return _jsx(GuideFigureView, { figure: figure, figures: figures, classNames: classNames });
12
+ const thumbnail = _jsx(GuideFigureMedia, { figure: figure, figures: figures, classNames: classNames });
13
+ // In the dialog a screenshot fills the box laid out at its natural size, loaded straight away; a diagram is drawn
14
+ // again as it is in the article, at the size it was measured at, and scaled.
15
+ const full = figure.kind === "screenshot" ? (_jsx(GuideFigureMedia, { figure: figure, classNames: { ...classNames, image: "size-full rounded-md bg-card align-top", imageWithoutDark: "" }, eager: true })) : undefined;
16
+ const size = figure.kind === "screenshot" ? { width: figure.width, height: figure.height } : {};
17
+ return (_jsx(GuideFigureView, { figure: figure, figures: figures, classNames: classNames, media: _jsx(GuideFigureZoom, { full: full, ...size, alt: figure.alt, ...(figure.caption ? { caption: figure.caption } : {}), labels: labels, classNames: zoomClassNames, children: thumbnail }) }));
18
+ }
19
+ //# sourceMappingURL=guide-figure.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide-figure.js","sourceRoot":"","sources":["../../src/guides/guide-figure.tsx"],"names":[],"mappings":";AAEA,OAAO,EAAE,gBAAgB,EAAE,eAAe,EAA8B,MAAM,uBAAuB,CAAC;AAEtG,OAAO,EAAE,eAAe,EAA4B,MAAM,wBAAwB,CAAC;AAanF;;;;GAIG;AACH,MAAM,UAAU,WAAW,CAAC,EAC1B,MAAM,EACN,OAAO,EACP,IAAI,GAAG,IAAI,EACX,MAAM,EACN,UAAU,EACV,cAAc,GACG;IACjB,IAAI,CAAC,IAAI;QAAE,OAAO,KAAC,eAAe,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAI,CAAC;IAChG,MAAM,SAAS,GAAG,KAAC,gBAAgB,IAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,GAAI,CAAC;IACjG,kHAAkH;IAClH,6EAA6E;IAC7E,MAAM,IAAI,GACR,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,CAC7B,KAAC,gBAAgB,IACf,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,EAAE,GAAG,UAAU,EAAE,KAAK,EAAE,wCAAwC,EAAE,gBAAgB,EAAE,EAAE,EAAE,EACpG,KAAK,SACL,CACH,CAAC,CAAC,CAAC,SAAS,CAAC;IAChB,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;IAChG,OAAO,CACL,KAAC,eAAe,IACd,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,UAAU,EAAE,UAAU,EACtB,KAAK,EACH,KAAC,eAAe,IACd,IAAI,EAAE,IAAI,KACN,IAAI,EACR,GAAG,EAAE,MAAM,CAAC,GAAG,KACX,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,MAAM,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,EACvD,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,cAAc,YAEzB,SAAS,GACM,GAEpB,CACH,CAAC;AACJ,CAAC"}
@@ -5,4 +5,6 @@ export { GuidesSearch, type GuidesSearchProps } from "./guides-search.js";
5
5
  export { GuidesShell, type GuidesShellProps } from "./guides-shell.js";
6
6
  export { GuidesSidebar, type GuidesSidebarProps } from "./guides-sidebar.js";
7
7
  export { GuideToc, useActiveHeading, type GuideTocProps } from "./guide-toc.js";
8
+ export { GuideFigure, type GuideFigureProps } from "./guide-figure.js";
9
+ export { fitScale, GUIDE_ZOOM_CLASS_NAMES, GuideFigureZoom, ZOOM_STEP, type GuideFigureZoomProps, type GuideZoomClassNames, } from "./guide-figure-zoom.js";
8
10
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guides/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/guides/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,YAAY,EACjB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,YAAY,GAClB,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAAE,KAAK,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAAE,KAAK,kBAAkB,EAAE,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAE,KAAK,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EACL,QAAQ,EACR,sBAAsB,EACtB,eAAe,EACf,SAAS,EACT,KAAK,oBAAoB,EACzB,KAAK,mBAAmB,GACzB,MAAM,wBAAwB,CAAC"}
@@ -5,4 +5,6 @@ export { GuidesSearch } from "./guides-search.js";
5
5
  export { GuidesShell } from "./guides-shell.js";
6
6
  export { GuidesSidebar } from "./guides-sidebar.js";
7
7
  export { GuideToc, useActiveHeading } from "./guide-toc.js";
8
+ export { GuideFigure } from "./guide-figure.js";
9
+ export { fitScale, GUIDE_ZOOM_CLASS_NAMES, GuideFigureZoom, ZOOM_STEP, } from "./guide-figure-zoom.js";
8
10
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/guides/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,GAOb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAA0B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAA0B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAyB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAsB,MAAM,gBAAgB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/guides/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,oBAAoB,EACpB,UAAU,EACV,aAAa,EACb,kBAAkB,EAClB,YAAY,GAOb,MAAM,cAAc,CAAC;AACtB,OAAO,EAAE,YAAY,EAA0B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,YAAY,EAA0B,MAAM,oBAAoB,CAAC;AAC1E,OAAO,EAAE,WAAW,EAAyB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,aAAa,EAA2B,MAAM,qBAAqB,CAAC;AAC7E,OAAO,EAAE,QAAQ,EAAE,gBAAgB,EAAsB,MAAM,gBAAgB,CAAC;AAChF,OAAO,EAAE,WAAW,EAAyB,MAAM,mBAAmB,CAAC;AACvE,OAAO,EACL,QAAQ,EACR,sBAAsB,EACtB,eAAe,EACf,SAAS,GAGV,MAAM,wBAAwB,CAAC"}
@@ -79,6 +79,19 @@ export interface GuidesLabels {
79
79
  menu: string;
80
80
  onThisPage: string;
81
81
  allGuides: string;
82
+ /** The hint on a picture in a guide that opens it full-size. */
83
+ zoomHint: string;
84
+ /** The name of that button; `{alt}` is replaced with the picture's alt text. */
85
+ zoomOpen: string;
86
+ zoomIn: string;
87
+ zoomOut: string;
88
+ /** The button showing the zoom level, which switches between fit and full size. */
89
+ zoomToggle: string;
90
+ /** Read out as the zoom changes; `{percent}` is replaced. */
91
+ zoomLevel: string;
92
+ zoomClose: string;
93
+ /** Shown above the picture on wider screens. */
94
+ zoomInstructions: string;
82
95
  }
83
96
  export declare const GUIDES_LABELS: GuidesLabels;
84
97
  export declare function withQuery(label: string, query: string): string;
@@ -1 +1 @@
1
- {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../src/guides/library.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,gBAAgB,EAAE,CAAC;IACxB,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE5F;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAC6G,CAAC;AAE/I,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAEpH;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,iBAAiB,EAAE,CAoBlH;AAED,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,aAAa,EAAE,YAa3B,CAAC;AAEF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D"}
1
+ {"version":3,"file":"library.d.ts","sourceRoot":"","sources":["../../src/guides/library.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,iEAAiE;IACjE,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,+DAA+D;IAC/D,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,YAAY,EAAE,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,qFAAqF;IACrF,QAAQ,EAAE;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC1C;AAED,MAAM,WAAW,YAAY;IAC3B,GAAG,EAAE,gBAAgB,EAAE,CAAC;IACxB,MAAM,EAAE,gBAAgB,EAAE,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qEAAqE;AACrE,wBAAgB,UAAU,CAAC,OAAO,EAAE,YAAY,EAAE,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAE5F;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,QAC6G,CAAC;AAE/I,8FAA8F;AAC9F,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,SAAS;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,GAAG;IAAE,EAAE,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAEpH;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,gBAAgB,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,SAAK,GAAG,iBAAiB,EAAE,CAoBlH;AAED,mEAAmE;AACnE,MAAM,WAAW,YAAY;IAC3B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;IACpB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,4EAA4E;IAC5E,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,qEAAqE;IACrE,WAAW,EAAE,MAAM,CAAC;IACpB,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,MAAM,CAAC;IAClB,gEAAgE;IAChE,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,UAAU,EAAE,MAAM,CAAC;IACnB,6DAA6D;IAC7D,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,eAAO,MAAM,aAAa,EAAE,YAqB3B,CAAC;AAEF,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAE9D"}
@@ -56,6 +56,14 @@ export const GUIDES_LABELS = {
56
56
  menu: "Guides",
57
57
  onThisPage: "On this page",
58
58
  allGuides: "All guides",
59
+ zoomHint: "Click to enlarge",
60
+ zoomOpen: "Enlarge picture: {alt}",
61
+ zoomIn: "Zoom in",
62
+ zoomOut: "Zoom out",
63
+ zoomToggle: "Switch between fit and full size",
64
+ zoomLevel: "Zoom {percent}%",
65
+ zoomClose: "Close",
66
+ zoomInstructions: "Pinch or ⌘/Ctrl + scroll to zoom · drag to move · double-click for full size",
59
67
  };
60
68
  export function withQuery(label, query) {
61
69
  return label.replace("{query}", query.trim());
@@ -1 +1 @@
1
- {"version":3,"file":"library.js","sourceRoot":"","sources":["../../src/guides/library.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"library.js","sourceRoot":"","sources":["../../src/guides/library.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAyCH,qEAAqE;AACrE,MAAM,UAAU,UAAU,CAAC,OAAqB,EAAE,IAAY;IAC5D,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC;AAC3F,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAC/B,4IAA4I,CAAC;AAE/I,8FAA8F;AAC9F,MAAM,UAAU,kBAAkB,CAAC,QAAiD;IAClF,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,oBAAoB,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAC1G,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAkC,EAAE,QAAgB,EAAE,KAAK,GAAG,EAAE;IAC3F,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACnC,IAAI,EAAE,KAAK,CAAC,IAAI;QAChB,KAAK,EAAE,KAAK,CAAC,KAAK;QAClB,MAAM,EAAE,GAAG,KAAK,CAAC,QAAQ,MAAM,KAAK,CAAC,OAAO,EAAE;QAC9C,OAAO,EAAE,KAAK;KACf,CAAC,CAAC,CAAC;IACJ,IAAI,CAAC,KAAK;QAAE,OAAO,MAAM,CAAC;IAC1B,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IACjC,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;IAC7F,MAAM,QAAQ,GAAG,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CACvC,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;QAC/B,IAAI,EAAE,GAAG,KAAK,CAAC,IAAI,IAAI,OAAO,CAAC,EAAE,EAAE;QACnC,KAAK,EAAE,OAAO,CAAC,IAAI;QACnB,MAAM,EAAE,KAAK,CAAC,KAAK;QACnB,OAAO,EAAE,IAAI;KACd,CAAC,CAAC,CACJ,CAAC;IACF,OAAO,CAAC,GAAG,MAAM,EAAE,GAAG,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;AAC/G,CAAC;AAiCD,MAAM,CAAC,MAAM,aAAa,GAAiB;IACzC,aAAa,EAAE,oBAAoB;IACnC,iBAAiB,EAAE,6BAA6B;IAChD,WAAW,EAAE,mBAAmB;IAChC,SAAS,EAAE,YAAY;IACvB,aAAa,EAAE,SAAS;IACxB,WAAW,EAAE,8CAA8C;IAC3D,WAAW,EAAE,eAAe;IAC5B,iBAAiB,EAAE,gBAAgB;IACnC,WAAW,EAAE,6BAA6B;IAC1C,IAAI,EAAE,QAAQ;IACd,UAAU,EAAE,cAAc;IAC1B,SAAS,EAAE,YAAY;IACvB,QAAQ,EAAE,kBAAkB;IAC5B,QAAQ,EAAE,wBAAwB;IAClC,MAAM,EAAE,SAAS;IACjB,OAAO,EAAE,UAAU;IACnB,UAAU,EAAE,kCAAkC;IAC9C,SAAS,EAAE,iBAAiB;IAC5B,SAAS,EAAE,OAAO;IAClB,gBAAgB,EAAE,8EAA8E;CACjG,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,KAAa,EAAE,KAAa;IACpD,OAAO,KAAK,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;AAChD,CAAC"}
@@ -0,0 +1,65 @@
1
+ /**
2
+ * A liveness check that says which release is running: `GET /healthz` answers
3
+ * `ok 0.24.1 2c9a3cf`, so a deploy can be confirmed from outside with one curl.
4
+ *
5
+ * Lifted from PharmaLineAI's voice relay (v0.24.1), generalised for the Next.js
6
+ * apps on Vercel and anything on Render. The endpoint is public, so it says only
7
+ * a version and a short commit hash, and only when each looks like one: a value
8
+ * that came from the environment is never echoed as-is. It always answers 200
9
+ * with `ok` first, which is what a host's health check looks for.
10
+ *
11
+ * Liveness only: no database, no provider, nothing that can be slow or fail. A
12
+ * readiness check is a separate route of the app's own (see the README).
13
+ *
14
+ * Imports no package: the route handler is plain web `Request` and `Response`,
15
+ * which is what a Next route handler takes and returns.
16
+ */
17
+ /** The release and commit a running app was built from. Either may be unknown. */
18
+ export interface BuildInfo {
19
+ version?: string;
20
+ commit?: string;
21
+ }
22
+ /**
23
+ * Where each host puts the commit it deployed, in the order they are read:
24
+ * Vercel (a system environment variable, exposed by default), Render, then a
25
+ * `GIT_COMMIT` an app or another host sets itself.
26
+ */
27
+ export declare const COMMIT_ENV_VARS: readonly ["VERCEL_GIT_COMMIT_SHA", "RENDER_GIT_COMMIT", "GIT_COMMIT"];
28
+ /**
29
+ * The build from a version (package.json's, passed in) and the commit the host
30
+ * deployed, cut to 7. A version that isn't semver-shaped is dropped; the commit
31
+ * is the first of `COMMIT_ENV_VARS` that is a whole hex hash, so a variable set
32
+ * to something else is skipped rather than repeated on a public page.
33
+ */
34
+ export declare function buildInfo(version: unknown, env?: Record<string, string | undefined>): BuildInfo;
35
+ /** What the check says: `ok`, then the version and commit when known — `ok 1.2.3 abc1234`. */
36
+ export declare function healthText(build?: BuildInfo): string;
37
+ export type HealthFormat = "text" | "json";
38
+ /**
39
+ * The format a request asks for: `?format=json` or `?format=text` first, then an
40
+ * `Accept` header that names `application/json`. Anything else — a browser, curl's
41
+ * `*\/*`, a host's checker — gets text.
42
+ */
43
+ export declare function healthFormat(request: Request): HealthFormat;
44
+ /** The answer itself: 200, `text/plain` by default, `{ status: "ok", version, commit }` as JSON. */
45
+ export declare function healthResponse(build?: BuildInfo, { format }?: {
46
+ format?: HealthFormat;
47
+ }): Response;
48
+ export interface HealthRouteOptions {
49
+ /** The app's release: `pkg.version` from its own package.json, imported in the route file. */
50
+ version: unknown;
51
+ /** Where the commit is read from. Default: `process.env`, read on each request. */
52
+ env?: Record<string, string | undefined>;
53
+ }
54
+ /**
55
+ * A Next route handler for `app/healthz/route.ts`, where `pkg` is the app's own package.json
56
+ * imported in that file (a route file is server-only, so it never reaches the browser):
57
+ *
58
+ * export const { GET } = createHealthRoute({ version: pkg.version });
59
+ *
60
+ * Next answers `HEAD` from `GET` on its own.
61
+ */
62
+ export declare function createHealthRoute({ version, env }: HealthRouteOptions): {
63
+ GET: (request: Request) => Response;
64
+ };
65
+ //# sourceMappingURL=health.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.d.ts","sourceRoot":"","sources":["../../src/health/health.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAEH,kFAAkF;AAClF,MAAM,WAAW,SAAS;IACxB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAOD;;;;GAIG;AACH,eAAO,MAAM,eAAe,uEAAwE,CAAC;AAErG;;;;;GAKG;AACH,wBAAgB,SAAS,CAAC,OAAO,EAAE,OAAO,EAAE,GAAG,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAe,GAAG,SAAS,CAO5G;AAED,8FAA8F;AAC9F,wBAAgB,UAAU,CAAC,KAAK,GAAE,SAAc,GAAG,MAAM,CAExD;AAED,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,OAAO,GAAG,YAAY,CAK3D;AAQD,oGAAoG;AACpG,wBAAgB,cAAc,CAAC,KAAK,GAAE,SAAc,EAAE,EAAE,MAAe,EAAE,GAAE;IAAE,MAAM,CAAC,EAAE,YAAY,CAAA;CAAO,GAAG,QAAQ,CAgBnH;AAED,MAAM,WAAW,kBAAkB;IACjC,8FAA8F;IAC9F,OAAO,EAAE,OAAO,CAAC;IACjB,mFAAmF;IACnF,GAAG,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAC;CAC1C;AAED;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,OAAO,EAAE,GAAG,EAAE,EAAE,kBAAkB,GAAG;IAAE,GAAG,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,QAAQ,CAAA;CAAE,CAK/G"}
@@ -0,0 +1,93 @@
1
+ /**
2
+ * A liveness check that says which release is running: `GET /healthz` answers
3
+ * `ok 0.24.1 2c9a3cf`, so a deploy can be confirmed from outside with one curl.
4
+ *
5
+ * Lifted from PharmaLineAI's voice relay (v0.24.1), generalised for the Next.js
6
+ * apps on Vercel and anything on Render. The endpoint is public, so it says only
7
+ * a version and a short commit hash, and only when each looks like one: a value
8
+ * that came from the environment is never echoed as-is. It always answers 200
9
+ * with `ok` first, which is what a host's health check looks for.
10
+ *
11
+ * Liveness only: no database, no provider, nothing that can be slow or fail. A
12
+ * readiness check is a separate route of the app's own (see the README).
13
+ *
14
+ * Imports no package: the route handler is plain web `Request` and `Response`,
15
+ * which is what a Next route handler takes and returns.
16
+ */
17
+ /** MAJOR.MINOR.PATCH with an optional pre-release (`1.2.3-rc.1`). No `v`, no build metadata. */
18
+ const SEMVER = /^\d+\.\d+\.\d+(?:-[0-9A-Za-z.-]+)?$/;
19
+ /** A git object name: 7 to 64 hex digits (SHA-1 or SHA-256), nothing else. */
20
+ const HEX_HASH = /^[0-9a-f]{7,64}$/i;
21
+ /**
22
+ * Where each host puts the commit it deployed, in the order they are read:
23
+ * Vercel (a system environment variable, exposed by default), Render, then a
24
+ * `GIT_COMMIT` an app or another host sets itself.
25
+ */
26
+ export const COMMIT_ENV_VARS = ["VERCEL_GIT_COMMIT_SHA", "RENDER_GIT_COMMIT", "GIT_COMMIT"];
27
+ /**
28
+ * The build from a version (package.json's, passed in) and the commit the host
29
+ * deployed, cut to 7. A version that isn't semver-shaped is dropped; the commit
30
+ * is the first of `COMMIT_ENV_VARS` that is a whole hex hash, so a variable set
31
+ * to something else is skipped rather than repeated on a public page.
32
+ */
33
+ export function buildInfo(version, env = process.env) {
34
+ const v = typeof version === "string" ? version.trim() : "";
35
+ const commit = COMMIT_ENV_VARS.map((name) => (env[name] ?? "").trim()).find((value) => HEX_HASH.test(value));
36
+ return {
37
+ ...(SEMVER.test(v) ? { version: v } : {}),
38
+ ...(commit ? { commit: commit.slice(0, 7).toLowerCase() } : {}),
39
+ };
40
+ }
41
+ /** What the check says: `ok`, then the version and commit when known — `ok 1.2.3 abc1234`. */
42
+ export function healthText(build = {}) {
43
+ return ["ok", build.version, build.commit].filter(Boolean).join(" ");
44
+ }
45
+ /**
46
+ * The format a request asks for: `?format=json` or `?format=text` first, then an
47
+ * `Accept` header that names `application/json`. Anything else — a browser, curl's
48
+ * `*\/*`, a host's checker — gets text.
49
+ */
50
+ export function healthFormat(request) {
51
+ const asked = new URL(request.url).searchParams.get("format")?.trim().toLowerCase();
52
+ if (asked === "json" || asked === "text")
53
+ return asked;
54
+ const accept = (request.headers.get("accept") ?? "").toLowerCase();
55
+ return /(^|[\s,])application\/json(\s*;|\s*,|\s*$)/.test(accept) ? "json" : "text";
56
+ }
57
+ const HEADERS = {
58
+ // A health check must never be answered from a cache: it would say a deploy is live that isn't.
59
+ "cache-control": "no-store",
60
+ "x-content-type-options": "nosniff",
61
+ };
62
+ /** The answer itself: 200, `text/plain` by default, `{ status: "ok", version, commit }` as JSON. */
63
+ export function healthResponse(build = {}, { format = "text" } = {}) {
64
+ if (format === "json") {
65
+ const body = {
66
+ status: "ok",
67
+ ...(build.version ? { version: build.version } : {}),
68
+ ...(build.commit ? { commit: build.commit } : {}),
69
+ };
70
+ return new Response(JSON.stringify(body), {
71
+ status: 200,
72
+ headers: { ...HEADERS, "content-type": "application/json; charset=utf-8" },
73
+ });
74
+ }
75
+ return new Response(healthText(build), {
76
+ status: 200,
77
+ headers: { ...HEADERS, "content-type": "text/plain; charset=utf-8" },
78
+ });
79
+ }
80
+ /**
81
+ * A Next route handler for `app/healthz/route.ts`, where `pkg` is the app's own package.json
82
+ * imported in that file (a route file is server-only, so it never reaches the browser):
83
+ *
84
+ * export const { GET } = createHealthRoute({ version: pkg.version });
85
+ *
86
+ * Next answers `HEAD` from `GET` on its own.
87
+ */
88
+ export function createHealthRoute({ version, env }) {
89
+ return {
90
+ GET: (request) => healthResponse(buildInfo(version, env ?? process.env), { format: healthFormat(request) }),
91
+ };
92
+ }
93
+ //# sourceMappingURL=health.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"health.js","sourceRoot":"","sources":["../../src/health/health.ts"],"names":[],"mappings":"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"}