@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
package/README.md CHANGED
@@ -666,6 +666,34 @@ export function Markdown({ content }: { content: string }) {
666
666
 
667
667
  `classNames` replaces the look of any element for an app without theme tokens.
668
668
 
669
+ **Pictures.** A guide names a screenshot or a diagram on a line of its own, with a
670
+ blank line either side:
671
+
672
+ ```md
673
+ ![The calls log, newest call first, with the ID-checked column](/guide-images/calls-log.webp "Every call, newest first")
674
+
675
+ ![A caller reaches the line, then the assistant answers or hands over](diagram:call-routing)
676
+ ```
677
+
678
+ `GuideMarkdown` draws one only when it is in the app's registry, `figures` — a
679
+ screenshot with its `width` and `height` (so the page doesn't jump as it loads) and
680
+ optionally a `dark` capture of the same size, or a diagram by name — and has alt
681
+ text; anything else is left out, so a guide can't pull an image in from elsewhere
682
+ and a typo never shows a broken image. (Before 0.18.0 such a line came out as a
683
+ `!` and a link.) A screenshot is a plain lazy `<img>`; with a `dark` capture both
684
+ are drawn and the theme's `dark:` variant shows one; without one, the light
685
+ picture is toned down a little on a dark page. A diagram registered as a component
686
+ is given the alt text as `label` for its own `<svg role="img" aria-label>`; one
687
+ registered as an element is wrapped in `role="img"`. Headings keep their ids
688
+ across pictures, and a picture ends a list.
689
+
690
+ `guideFigureProblems(body, figures, { minAltLength })` is the check an app's test
691
+ asserts empty for every guide: an unregistered picture, missing (or too short) alt
692
+ text, a picture without a blank line either side or indented as if in a list, and
693
+ an image written inside a line of text. `splitGuideFigures` is the same split as
694
+ data; `renderFigure` replaces the drawing. `GuideArticle` adds zoom — see
695
+ [Pictures and zoom](#pictures-and-zoom).
696
+
669
697
  ### `@connextar/house/guides`
670
698
 
671
699
  The frame a help centre's pages sit in, so every app's guides read and are found
@@ -706,6 +734,170 @@ export default async function GuidePage({ params }) {
706
734
  }
707
735
  ```
708
736
 
737
+ #### Pictures and zoom
738
+
739
+ Pass the registry and `GuideArticle` draws a guide's pictures
740
+ ([the Markdown](#connextarhousemarkdown)), each one a button: a "Click to enlarge"
741
+ hint in its corner and a zoom-in cursor. A click, Enter or Space opens it in a
742
+ dialog fitted to the screen (the whole screen on a phone):
743
+
744
+ - zoom with the buttons, `+` and `−`, ⌘/Ctrl + scroll (a trackpad pinch arrives as
745
+ one) or a touch pinch, from fit up to four times full size, at the pointer;
746
+ - when it is bigger than the screen, drag it, scroll it, or move it with the arrow
747
+ keys — never past its edges;
748
+ - a double-click or double-tap, or the zoom level between the buttons, switches
749
+ between fit and full size (one image pixel to one CSS pixel); `0` fits again;
750
+ - the caption and the alt text are shown under it; Escape or the close button
751
+ closes it and focus goes back to the picture. Zoom eases only without
752
+ `prefers-reduced-motion`; dragging and pinching never do.
753
+
754
+ Diagrams zoom too. They are vector, so the dialog lays the diagram out at the size
755
+ it had in the article and scales it: fit fills the screen, and "full size" is twice
756
+ the fit. `zoom={false}` draws plain pictures. `labels` changes the words (`zoomHint`,
757
+ `zoomOpen`, `zoomIn`, `zoomOut`, `zoomToggle`, `zoomLevel`, `zoomClose`,
758
+ `zoomInstructions`), `classNames.figure` the picture's parts and `zoomClassNames`
759
+ the button and dialog's (`GUIDE_ZOOM_CLASS_NAMES` lists them), all on the theme
760
+ tokens. `GuideFigure` and `GuideFigureZoom` are there for a page laid out without
761
+ `GuideArticle`. The zoom's classes appear only in this package, so the
762
+ [Tailwind `@source`](#tailwind-setup-required-for-every-component) line is what
763
+ styles it.
764
+
765
+ Adopting it (PharmaLineAI's v0.23.1 pictures, which this generalises):
766
+
767
+ 1. **Screenshots** live in `public/guide-images/`, as WebP about 1600px wide (sharp
768
+ in a 768px column on a 2× screen) and under ~150 KB each. A dark capture, if
769
+ the app makes one, sits beside it at the same size (`calls-log-dark.webp`).
770
+ 2. **The registry.** Sizes in `lib/guide-screenshots.json`, written by the capture
771
+ script, and the diagrams beside them:
772
+
773
+ ```json
774
+ {
775
+ "/guide-images/calls-log.webp": { "width": 1600, "height": 986 },
776
+ "/guide-images/overview.webp": { "width": 1600, "height": 506, "dark": "/guide-images/overview-dark.webp" }
777
+ }
778
+ ```
779
+
780
+ ```tsx
781
+ // lib/guide-figures.tsx
782
+ import type { GuideFigures } from "@connextar/house/markdown";
783
+
784
+ import { CallRouting, IdentityCheck } from "@components/guides/guide-diagrams";
785
+ import screenshots from "@lib/guide-screenshots.json";
786
+
787
+ export const GUIDE_FIGURES: GuideFigures = {
788
+ screenshots,
789
+ diagrams: { "call-routing": CallRouting, "identity-check": IdentityCheck }, // each takes { label }
790
+ };
791
+ ```
792
+
793
+ 3. **The pages** pass it: `<GuideArticle … figures={GUIDE_FIGURES} />`, on the public
794
+ and the signed-in guide pages alike. A diagram component is drawn on the server;
795
+ only what it drew crosses into the dialog.
796
+ 4. **The app's test** reads the real guides:
797
+
798
+ ```ts
799
+ for (const { slug } of GUIDES) {
800
+ expect(guideFigureProblems(body(slug), GUIDE_FIGURES, { minAltLength: 20 }), slug).toEqual([]);
801
+ }
802
+ ```
803
+
804
+ and, because the package can't see the app's disk, checks the files: every
805
+ registered screenshot (and `dark`) exists at its recorded size (the app's own
806
+ `sharp`), every file in `public/guide-images/` is registered and used, all
807
+ WebP and small.
808
+
809
+ 5. **Capturing them (optional).** PharmaLineAI's `scripts/guide-screenshots.ts` is
810
+ the pattern, and stays in the app — this package ships no Playwright. It runs
811
+ only against the local harness (it refuses any base URL that isn't
812
+ `localhost`/`127.0.0.1`), signed in as the seeded owner from the harness's
813
+ cookie jar, in headless Chromium at 1440px, 2× pixels, light mode and reduced
814
+ motion. Each shot names a page, an optional `before` step (open a call, pick a
815
+ setting), and a crop to the panel its guide talks about, found from the page
816
+ (a heading, a bordered card). It hides the dev overlay, replaces seed text a
817
+ public page mustn't show (a real brand in a seed name), puts back any seed data
818
+ it changed for a shot in a `finally`, resizes to 1600px WebP with sharp, and
819
+ writes the sizes to `lib/guide-screenshots.json`. A dark set is the same run
820
+ with `colorScheme: "dark"` writing `-dark.webp` files and each entry's `dark`.
821
+
822
+ PharmaLineAI's own `components/guides/guide-article.tsx` and the split in
823
+ `lib/guide-figures.ts` go; its diagrams and its JSON stay, and its list of diagram
824
+ names becomes the `diagrams` record.
825
+
826
+ ### `@connextar/house/health`
827
+
828
+ A liveness check that says which release is running, so a deploy can be confirmed
829
+ from outside: `curl https://app.example/healthz` answers `ok 0.18.0 2c9a3cf`.
830
+ From PharmaLineAI's voice relay (v0.24.1), for every app.
831
+
832
+ - `buildInfo(version, env = process.env)` → `{ version?, commit? }`. The version
833
+ must be semver-shaped (`1.2.3`, `1.2.3-rc.1`); the commit is the first of
834
+ `VERCEL_GIT_COMMIT_SHA`, `RENDER_GIT_COMMIT` and `GIT_COMMIT` that is a whole
835
+ hex hash, cut to 7. Anything else is dropped, never echoed: the endpoint is
836
+ public.
837
+ - `healthText(build)` → `ok 1.2.3 abc1234` (just `ok` when nothing is known).
838
+ - `healthResponse(build, { format })` → always 200, `Cache-Control: no-store`;
839
+ `text/plain` by default, `{ "status": "ok", "version", "commit" }` for
840
+ `format: "json"`. `healthFormat(request)` picks: `?format=json|text`, then an
841
+ `Accept` that names `application/json`; a browser, curl and a host's checker get
842
+ text.
843
+ - `createHealthRoute({ version })` → `{ GET }`, the two above as a Next route
844
+ handler. Next answers `HEAD` from `GET` itself. No Next import, no package at all:
845
+ it is web `Request` and `Response`.
846
+
847
+ The whole adoption is one file, `app/healthz/route.ts` (`src/app/…` adds a `../`):
848
+
849
+ ```ts
850
+ import { createHealthRoute } from "@connextar/house/health";
851
+
852
+ // A route handler is server-only, so package.json is bundled into the server and never reaches the browser.
853
+ import pkg from "../../package.json";
854
+
855
+ export const { GET } = createHealthRoute({ version: pkg.version });
856
+ ```
857
+
858
+ (Next's default `tsconfig` has `resolveJsonModule`.) **Not**
859
+ `process.env.npm_package_version`: npm sets it only in a process npm itself
860
+ started — `node -e 'console.log(process.env.npm_package_version)'` prints
861
+ `undefined`, and the same line under `npm run` prints the version. A Vercel
862
+ function is started by Vercel's runtime, not `npm start`, so it is unset when the
863
+ route runs; it is set during `npm run build`, so it could be inlined through
864
+ `next.config`'s `env`, but only for as long as the build goes through npm. It works
865
+ on Render under `npm start`, which is why it looks reliable until it isn't.
866
+
867
+ The commit: Vercel sets `VERCEL_GIT_COMMIT_SHA` on Git deployments while "Automatically
868
+ expose System Environment Variables" is on (the default); Render sets
869
+ `RENDER_GIT_COMMIT`; anywhere else, set `GIT_COMMIT`. On Render, point the service's
870
+ Health Check Path at `/healthz`; it needs the 200 and nothing else. A plain Node
871
+ server (PharmaLineAI's relay) uses `buildInfo` and `healthText` directly.
872
+
873
+ **Let it through.** `/healthz` must answer without signing in: exclude it from the
874
+ app's `proxy.ts` (`middleware.ts` before Next 16) — e.g.
875
+ `matcher: ["/((?!healthz|_next/static|_next/image|favicon.ico).*)"]` — and from any
876
+ auth redirect, maintenance switch or locale rewrite in it. Vercel Deployment
877
+ Protection on preview deployments answers 401 before the app does; that is
878
+ expected, and production should be unprotected.
879
+
880
+ **Liveness only.** It touches no database and no provider, so it can't be slow and
881
+ a provider's outage never makes a host restart a healthy app. An app that wants a
882
+ readiness check writes its own, separately — never as the host's health check:
883
+
884
+ ```ts
885
+ // app/readyz/route.ts — the app's own; says only ready / not ready
886
+ export async function GET() {
887
+ const ok = await Promise.race([
888
+ prisma.$queryRaw`select 1`.then(
889
+ () => true,
890
+ () => false,
891
+ ),
892
+ new Promise<boolean>((resolve) => setTimeout(() => resolve(false), 2000)),
893
+ ]);
894
+ return new Response(ok ? "ready" : "not ready", {
895
+ status: ok ? 200 : 503,
896
+ headers: { "cache-control": "no-store", "content-type": "text/plain; charset=utf-8" },
897
+ });
898
+ }
899
+ ```
900
+
709
901
  ### `@connextar/house/trail`
710
902
 
711
903
  Where you came from, rather than where the URL says you are. A breadcrumb built
@@ -1438,15 +1630,25 @@ Rules the module holds so no app has to rediscover them:
1438
1630
  - **Thinking belongs to the job.** Adaptive thinking is sent to Anthropic only
1439
1631
  for a job declared `thinking: true` (or a call that asks) — the small fast
1440
1632
  models reject it with a 400, and the job's default model is where that is
1441
- known. Effort is Anthropic-only; OpenAI's reasoning is the model's own.
1633
+ known. `effort` is Anthropic's; for OpenAI a call may pass `reasoningEffort`
1634
+ (`"minimal" | "low" | "medium" | "high"`, 0.17.0), sent only to models that
1635
+ reason (`takesReasoningEffort`: the gpt-5 family but its `-chat` models, and the
1636
+ o-series), so a non-reasoning model an operator picks still works. Omitted, the
1637
+ model reasons at its own default.
1442
1638
  - **OpenAI output budgets get a floor** (`OPENAI_MIN_OUTPUT_TOKENS`, 4,000): a
1443
- reasoning model spends the budget thinking before it writes a word.
1639
+ reasoning model spends the budget thinking before it writes a word. A job that
1640
+ reads and lists rather than solves can pass `reasoningEffort: "low"` and keep
1641
+ most of that budget, and time, for the answer (AltEd tranche 169: a year-long
1642
+ targets sheet took ~14,700 tokens and ~170 s at the default).
1444
1643
  - **Structured calls stream**, because both SDKs refuse a non-streaming call that
1445
1644
  could outlive their timeout. A `timeoutMs` call makes one attempt, no retries.
1446
1645
  - **Failures are three classes.** `AiUnavailableError` — off, nothing was sent.
1447
1646
  `AiServiceError` — the provider said no, in its own words, with its status.
1448
1647
  `AiUnusableAnswerError` — a refusal, a cut-off or the wrong shape; the tokens
1449
- were spent anyway, so `error.usage` carries them for the caller to record.
1648
+ were spent anyway, so `error.usage` carries them for the caller to record, and
1649
+ `error.reason` (`"cut-off" | "refused" | "wrong-shape"`, 0.17.0) says which. A
1650
+ cut-off is the output budget running out — the app's choice of `maxTokens`, so
1651
+ an app may decide not to charge a person for it.
1450
1652
  - **Usage is cache-aware.** Every result carries input, output, cache-read and
1451
1653
  cache-write tokens. OpenAI counts cached tokens inside `input_tokens`; they are
1452
1654
  moved out, not added, so nothing is billed twice.
@@ -4,5 +4,5 @@
4
4
  * imports `@connextar/house/ai/config` instead.
5
5
  */
6
6
  export * from "./config-index.js";
7
- export { AiServiceError, AiUnavailableError, AiUnusableAnswerError, OPENAI_MIN_OUTPUT_TOKENS, createAiHarness, type AiCallResult, type AiHarness, type AiHarnessOptions, type AiStructuredCall, type AiTextCall, } from "./provider.js";
7
+ export { AiServiceError, AiUnavailableError, AiUnusableAnswerError, OPENAI_MIN_OUTPUT_TOKENS, createAiHarness, takesReasoningEffort, type AiCallResult, type AiHarness, type AiHarnessOptions, type AiStructuredCall, type AiTextCall, type AiUnusableReason, type OpenAiReasoningEffort, } from "./provider.js";
8
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,GAChB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,oBAAoB,EACpB,KAAK,YAAY,EACjB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,gBAAgB,EACrB,KAAK,qBAAqB,GAC3B,MAAM,eAAe,CAAC"}
package/dist/ai/index.js CHANGED
@@ -4,5 +4,5 @@
4
4
  * imports `@connextar/house/ai/config` instead.
5
5
  */
6
6
  export * from "./config-index.js";
7
- export { AiServiceError, AiUnavailableError, AiUnusableAnswerError, OPENAI_MIN_OUTPUT_TOKENS, createAiHarness, } from "./provider.js";
7
+ export { AiServiceError, AiUnavailableError, AiUnusableAnswerError, OPENAI_MIN_OUTPUT_TOKENS, createAiHarness, takesReasoningEffort, } from "./provider.js";
8
8
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,GAMhB,MAAM,eAAe,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/ai/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,cAAc,mBAAmB,CAAC;AAClC,OAAO,EACL,cAAc,EACd,kBAAkB,EAClB,qBAAqB,EACrB,wBAAwB,EACxB,eAAe,EACf,oBAAoB,GAQrB,MAAM,eAAe,CAAC"}
@@ -35,16 +35,41 @@ export declare class AiServiceError extends Error {
35
35
  readonly status: number | undefined;
36
36
  constructor(message: string, status?: number);
37
37
  }
38
+ /**
39
+ * Why an answer was unusable (0.17.0):
40
+ *
41
+ * - `cut-off` — it ran out of output budget before it finished: the caller's
42
+ * `maxTokens`, which an OpenAI reasoning model also spends its thinking from.
43
+ * Trying again with the same budget usually fails the same way, and the
44
+ * budget is the app's choice, not the person's — an app may decide not to
45
+ * charge for it.
46
+ * - `refused` — the model declined, or the provider's filter stopped it.
47
+ * - `wrong-shape` — it finished, but not in the schema asked for.
48
+ */
49
+ export type AiUnusableReason = "cut-off" | "refused" | "wrong-shape";
38
50
  /**
39
51
  * The provider answered, but not with something usable — a refusal, a cut-off
40
52
  * or an answer in the wrong shape. The tokens were spent all the same, so the
41
53
  * usage travels with the error for the caller to record (AltEd round 10: these
42
- * were free, and a failed step could be tried again without limit).
54
+ * were free, and a failed step could be tried again without limit). `reason`
55
+ * says which, for a caller whose charging or wording depends on it.
43
56
  */
44
57
  export declare class AiUnusableAnswerError extends AiUnavailableError {
45
58
  readonly usage: AiCallResult;
46
- constructor(message: string, usage: AiCallResult);
59
+ readonly reason: AiUnusableReason;
60
+ constructor(message: string, usage: AiCallResult, reason?: AiUnusableReason);
47
61
  }
62
+ /**
63
+ * How hard an OpenAI reasoning model thinks before it answers (0.17.0).
64
+ * Its thinking is billed as output and shares `maxTokens`, so a job that is
65
+ * reading and listing rather than solving can save most of its time and cost
66
+ * with `"low"`. Sent only to models that reason — the gpt-5 family (not its
67
+ * `-chat` models) and the o-series — so a non-reasoning model an operator
68
+ * chooses still works. Anthropic ignores it; it has `thinking` and `effort`.
69
+ */
70
+ export type OpenAiReasoningEffort = "minimal" | "low" | "medium" | "high";
71
+ /** Whether an OpenAI model takes a reasoning effort. By name: the API has no way to ask. */
72
+ export declare function takesReasoningEffort(model: string): boolean;
48
73
  export interface AiCallResult {
49
74
  provider: AiProviderName;
50
75
  model: string;
@@ -66,6 +91,8 @@ export interface AiTextCall<Task extends string> {
66
91
  * the function being killed mid-call.
67
92
  */
68
93
  timeoutMs?: number;
94
+ /** OpenAI reasoning models only; omitted = the model's own default. See `OpenAiReasoningEffort`. */
95
+ reasoningEffort?: OpenAiReasoningEffort;
69
96
  }
70
97
  export interface AiStructuredCall<Task extends string, T> extends AiTextCall<Task> {
71
98
  schema: z.ZodType<T>;
@@ -87,8 +114,7 @@ export interface AiStructuredCall<Task extends string, T> extends AiTextCall<Tas
87
114
  thinking?: boolean;
88
115
  /**
89
116
  * How hard to think, on providers and models that take the instruction.
90
- * Anthropic-only: OpenAI's reasoning effort is left at the model's default so
91
- * that a non-reasoning model an operator chooses still works.
117
+ * Anthropic-only; for OpenAI see `reasoningEffort`.
92
118
  */
93
119
  effort?: "medium" | "high";
94
120
  }
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAE7B,OAAO,EAKL,KAAK,KAAK,EACV,KAAK,cAAc,EACnB,KAAK,QAAQ,EACb,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,UAAU,EAChB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH,gEAAgE;AAChE,qBAAa,kBAAmB,SAAQ,KAAK;gBAC/B,OAAO,SAAkE;CAItF;AAED,0FAA0F;AAC1F,qBAAa,cAAe,SAAQ,KAAK;IACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAK7C;AAED;;;;;;;;;;GAUG;AACH,MAAM,MAAM,gBAAgB,GAAG,SAAS,GAAG,SAAS,GAAG,aAAa,CAAC;AAErE;;;;;;GAMG;AACH,qBAAa,qBAAsB,SAAQ,kBAAkB;IAC3D,QAAQ,CAAC,KAAK,EAAE,YAAY,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,gBAAgB,CAAC;gBAEtB,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,YAAY,EAAE,MAAM,GAAE,gBAAgC;CAM3F;AAED;;;;;;;GAOG;AACH,MAAM,MAAM,qBAAqB,GAAG,SAAS,GAAG,KAAK,GAAG,QAAQ,GAAG,MAAM,CAAC;AAE1E,4FAA4F;AAC5F,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAE3D;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,EAAE,cAAc,CAAC;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,uFAAuF;IACvF,eAAe,EAAE,MAAM,CAAC;IACxB,gBAAgB,EAAE,MAAM,CAAC;CAC1B;AAED,MAAM,WAAW,UAAU,CAAC,IAAI,SAAS,MAAM;IAC7C,IAAI,EAAE,IAAI,CAAC;IACX,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,2FAA2F;IAC3F,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,oGAAoG;IACpG,eAAe,CAAC,EAAE,qBAAqB,CAAC;CACzC;AAED,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,MAAM,EAAE,CAAC,CAAE,SAAQ,UAAU,CAAC,IAAI,CAAC;IAChF,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;IACrB,wEAAwE;IACxE,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC;IACnB;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;OAGG;IACH,MAAM,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAC5B;AAED;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,OAAO,CAAC;AAgD7C,MAAM,WAAW,gBAAgB,CAAC,IAAI,SAAS,MAAM;IACnD,sDAAsD;IACtD,KAAK,EAAE,WAAW,CAAC,IAAI,CAAC,CAAC;IACzB,kFAAkF;IAClF,GAAG,CAAC,EAAE,MAAM,KAAK,CAAC;CACnB;AAED,MAAM,WAAW,SAAS,CAAC,IAAI,SAAS,MAAM;IAC5C,sGAAsG;IACtG,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,UAAU,GAAG,IAAI,CAAC;IACvC,uEAAuE;IACvE,MAAM,IAAI,QAAQ,CAAC,IAAI,CAAC,CAAC;IACzB,yDAAyD;IACzD,YAAY,IAAI,cAAc,CAAC,IAAI,CAAC,CAAC;IACrC,wDAAwD;IACxD,YAAY,CAAC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG;QAAE,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IAC/E,4FAA4F;IAC5F,kBAAkB,CAAC,CAAC,EAAE,IAAI,EAAE,gBAAgB,CAAC,IAAI,EAAE,CAAC,CAAC,GAAG,OAAO,CAAC,YAAY,GAAG;QAAE,MAAM,EAAE,CAAC,CAAA;KAAE,CAAC,CAAC;CAC/F;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,eAAe,CAAC,IAAI,SAAS,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,IAAI,CAAC,GAAG,SAAS,CAAC,IAAI,CAAC,CAwJrG"}
@@ -48,16 +48,23 @@ export class AiServiceError extends Error {
48
48
  * The provider answered, but not with something usable — a refusal, a cut-off
49
49
  * or an answer in the wrong shape. The tokens were spent all the same, so the
50
50
  * usage travels with the error for the caller to record (AltEd round 10: these
51
- * were free, and a failed step could be tried again without limit).
51
+ * were free, and a failed step could be tried again without limit). `reason`
52
+ * says which, for a caller whose charging or wording depends on it.
52
53
  */
53
54
  export class AiUnusableAnswerError extends AiUnavailableError {
54
55
  usage;
55
- constructor(message, usage) {
56
+ reason;
57
+ constructor(message, usage, reason = "wrong-shape") {
56
58
  super(message);
57
59
  this.name = "AiUnusableAnswerError";
58
60
  this.usage = usage;
61
+ this.reason = reason;
59
62
  }
60
63
  }
64
+ /** Whether an OpenAI model takes a reasoning effort. By name: the API has no way to ask. */
65
+ export function takesReasoningEffort(model) {
66
+ return /^(gpt-5|o\d)/.test(model) && !/-chat/.test(model);
67
+ }
61
68
  /**
62
69
  * An OpenAI reasoning model bills its thinking against the same budget as its
63
70
  * answer, so a 900-token ceiling can be spent entirely before the prose starts.
@@ -95,6 +102,10 @@ function anthropicUsage(provider, message) {
95
102
  cacheWriteTokens: message.usage.cache_creation_input_tokens ?? 0,
96
103
  };
97
104
  }
105
+ /** The `reasoning` field for an OpenAI request, or nothing when the model doesn't reason or none was asked for. */
106
+ function openAiReasoning(model, effort) {
107
+ return effort && takesReasoningEffort(model) ? { reasoning: { effort } } : {};
108
+ }
98
109
  /**
99
110
  * Bind the harness to an app's jobs.
100
111
  *
@@ -141,6 +152,7 @@ export function createAiHarness(options) {
141
152
  instructions: call.system,
142
153
  input: call.prompt,
143
154
  max_output_tokens: Math.max(call.maxTokens, OPENAI_MIN_OUTPUT_TOKENS),
155
+ ...openAiReasoning(model, call.reasoningEffort),
144
156
  }, requestOptions);
145
157
  return { text: response.output_text.trim(), ...openAiUsage(provider, response.model, response.usage) };
146
158
  }
@@ -177,7 +189,10 @@ export function createAiHarness(options) {
177
189
  const response = await stream.finalMessage();
178
190
  const usage = anthropicUsage(provider, response);
179
191
  if (response.stop_reason === "refusal") {
180
- throw new AiUnusableAnswerError("The model declined to process this request.", usage);
192
+ throw new AiUnusableAnswerError("The model declined to process this request.", usage, "refused");
193
+ }
194
+ if (response.stop_reason === "max_tokens") {
195
+ throw new AiUnusableAnswerError("The answer was cut off before it was complete (max_tokens). Try a model with more room, or a shorter input.", usage, "cut-off");
181
196
  }
182
197
  if (response.parsed_output === null || response.parsed_output === undefined) {
183
198
  throw new AiUnusableAnswerError("The model's answer did not match the expected shape.", usage);
@@ -201,11 +216,17 @@ export function createAiHarness(options) {
201
216
  input: [{ role: "user", content }],
202
217
  max_output_tokens: Math.max(call.maxTokens, OPENAI_MIN_OUTPUT_TOKENS),
203
218
  text: { format: zodTextFormat(call.schema, call.schemaName) },
219
+ ...openAiReasoning(model, call.reasoningEffort),
204
220
  }, requestOptions);
205
221
  const response = await stream.finalResponse();
206
222
  const usage = openAiUsage(provider, response.model, response.usage);
207
223
  if (response.status === "incomplete") {
208
- throw new AiUnusableAnswerError(`The answer was cut off before it was complete (${response.incomplete_details?.reason ?? "no reason given"}). Try a model with more room, or a shorter input.`, usage);
224
+ const why = response.incomplete_details?.reason;
225
+ // A content filter stopping it is a refusal by another name; anything else is the budget running out.
226
+ if (why === "content_filter") {
227
+ throw new AiUnusableAnswerError("The provider's content filter stopped the answer.", usage, "refused");
228
+ }
229
+ throw new AiUnusableAnswerError(`The answer was cut off before it was complete (${why ?? "no reason given"}). Try a model with more room, or a shorter input.`, usage, "cut-off");
209
230
  }
210
231
  if (response.output_parsed === null || response.output_parsed === undefined) {
211
232
  throw new AiUnusableAnswerError("The model's answer did not match the expected shape.", usage);
@@ -1 +1 @@
1
- {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"provider.js","sourceRoot":"","sources":["../../src/ai/provider.ts"],"names":[],"mappings":"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"}
@@ -1,4 +1,6 @@
1
+ import type { GuideFigures } from "../markdown/figures.js";
1
2
  import { type GuideClassNames } from "../markdown/guide.js";
3
+ import type { GuideZoomClassNames } from "./guide-figure-zoom.js";
2
4
  import { type GuidesLabels } from "./library.js";
3
5
  export interface GuideArticleProps {
4
6
  /** The guide as `parseGuideFrontmatter` splits it. */
@@ -15,13 +17,22 @@ export interface GuideArticleProps {
15
17
  category?: string;
16
18
  labels?: Partial<GuidesLabels>;
17
19
  classNames?: Partial<GuideClassNames>;
20
+ /**
21
+ * The pictures this app's guides may show (`![alt](/guide-images/x.webp "Caption")` and
22
+ * `![alt](diagram:name)` on a line of their own). Unregistered ones are left out.
23
+ */
24
+ figures?: GuideFigures;
25
+ /** Open a picture full-size on a click, Enter or Space. Default: on. */
26
+ zoom?: boolean;
27
+ zoomClassNames?: Partial<GuideZoomClassNames>;
18
28
  }
19
29
  /**
20
30
  * One guide, laid out for reading inside `GuidesShell`: a way back to all guides, the category,
21
31
  * the title and lede, the article drawn by `GuideMarkdown`, and "On this page" — a rail that
22
32
  * follows the reader on wide screens, a collapsible list above the article on narrow ones. The
23
33
  * contents use the same heading ids the renderer gives, so `#<heading id>` links land.
24
- * Server-safe; the contents are the only client part.
34
+ * Registered pictures are drawn where the guide names them, each opening full-size.
35
+ * Server-safe; the contents and the zoom are the only client parts.
25
36
  */
26
- export declare function GuideArticle({ guide, guidesPath, indexSlug, category, labels, classNames }: GuideArticleProps): import("react").JSX.Element;
37
+ export declare function GuideArticle({ guide, guidesPath, indexSlug, category, labels, classNames, figures, zoom, zoomClassNames, }: GuideArticleProps): import("react").JSX.Element;
27
38
  //# sourceMappingURL=guide-article.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"guide-article.d.ts","sourceRoot":"","sources":["../../src/guides/guide-article.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAkC,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5F,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;CACvC;AAED;;;;;;GAMG;AACH,wBAAgB,YAAY,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,iBAAiB,+BA0B7G"}
1
+ {"version":3,"file":"guide-article.d.ts","sourceRoot":"","sources":["../../src/guides/guide-article.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAC3D,OAAO,EAAkC,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAE5F,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAElE,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhE,MAAM,WAAW,iBAAiB;IAChC,sDAAsD;IACtD,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAA;KAAE,CAAC;IACtD,iFAAiF;IACjF,UAAU,EAAE,MAAM,CAAC;IACnB,4FAA4F;IAC5F,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,eAAe,CAAC,CAAC;IACtC;;;OAGG;IACH,OAAO,CAAC,EAAE,YAAY,CAAC;IACvB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,cAAc,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC/C;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,EAC3B,KAAK,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,cAAc,GACf,EAAE,iBAAiB,+BA0CnB"}
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { ChevronLeft } from "lucide-react";
3
3
  import { Link } from "../internal/next-link.js";
4
4
  import { extractHeadings, GuideMarkdown } from "../markdown/guide.js";
5
+ import { GuideFigure } from "./guide-figure.js";
5
6
  import { GuideToc } from "./guide-toc.js";
6
7
  import { GUIDES_LABELS } from "./library.js";
7
8
  /**
@@ -9,11 +10,12 @@ import { GUIDES_LABELS } from "./library.js";
9
10
  * the title and lede, the article drawn by `GuideMarkdown`, and "On this page" — a rail that
10
11
  * follows the reader on wide screens, a collapsible list above the article on narrow ones. The
11
12
  * contents use the same heading ids the renderer gives, so `#<heading id>` links land.
12
- * Server-safe; the contents are the only client part.
13
+ * Registered pictures are drawn where the guide names them, each opening full-size.
14
+ * Server-safe; the contents and the zoom are the only client parts.
13
15
  */
14
- export function GuideArticle({ guide, guidesPath, indexSlug, category, labels, classNames }) {
16
+ export function GuideArticle({ guide, guidesPath, indexSlug, category, labels, classNames, figures, zoom, zoomClassNames, }) {
15
17
  const text = { ...GUIDES_LABELS, ...labels };
16
18
  const headings = extractHeadings(guide.body);
17
- return (_jsxs("div", { className: "xl:grid xl:grid-cols-[minmax(0,1fr)_13rem] xl:gap-12", children: [_jsxs("article", { className: "max-w-3xl min-w-0", children: [_jsxs(Link, { href: guidesPath, className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground", children: [_jsx(ChevronLeft, { className: "size-4", "aria-hidden": true }), " ", text.allGuides] }), category ? (_jsx("p", { className: "mt-5 text-xs font-bold tracking-[0.14em] text-primary uppercase", children: category })) : null, _jsx("h1", { className: "mt-2 text-3xl font-bold tracking-tight text-foreground sm:text-4xl", children: guide.title }), guide.lede ? _jsx("p", { className: "mt-3 text-lg text-muted-foreground", children: guide.lede }) : null, _jsx("div", { className: "mt-8", children: _jsx(GuideToc, { headings: headings, variant: "inline", labels: labels }) }), _jsx(GuideMarkdown, { content: guide.body, guidesPath: guidesPath, indexSlug: indexSlug, classNames: classNames })] }), _jsx(GuideToc, { headings: headings, variant: "rail", labels: labels })] }));
19
+ return (_jsxs("div", { className: "xl:grid xl:grid-cols-[minmax(0,1fr)_13rem] xl:gap-12", children: [_jsxs("article", { className: "max-w-3xl min-w-0", children: [_jsxs(Link, { href: guidesPath, className: "inline-flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground", children: [_jsx(ChevronLeft, { className: "size-4", "aria-hidden": true }), " ", text.allGuides] }), category ? (_jsx("p", { className: "mt-5 text-xs font-bold tracking-[0.14em] text-primary uppercase", children: category })) : null, _jsx("h1", { className: "mt-2 text-3xl font-bold tracking-tight text-foreground sm:text-4xl", children: guide.title }), guide.lede ? _jsx("p", { className: "mt-3 text-lg text-muted-foreground", children: guide.lede }) : null, _jsx("div", { className: "mt-8", children: _jsx(GuideToc, { headings: headings, variant: "inline", labels: labels }) }), _jsx(GuideMarkdown, { content: guide.body, guidesPath: guidesPath, indexSlug: indexSlug, classNames: classNames, figures: figures, renderFigure: (figure) => (_jsx(GuideFigure, { figure: figure, figures: figures, zoom: zoom, labels: labels, classNames: classNames?.figure, zoomClassNames: zoomClassNames })) })] }), _jsx(GuideToc, { headings: headings, variant: "rail", labels: labels })] }));
18
20
  }
19
21
  //# sourceMappingURL=guide-article.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"guide-article.js","sourceRoot":"","sources":["../../src/guides/guide-article.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAwB,MAAM,sBAAsB,CAAC;AAC5F,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAqB,MAAM,cAAc,CAAC;AAehE;;;;;;GAMG;AACH,MAAM,UAAU,YAAY,CAAC,EAAE,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAqB;IAC5G,MAAM,IAAI,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE7C,OAAO,CACL,eAAK,SAAS,EAAC,sDAAsD,aACnE,mBAAS,SAAS,EAAC,mBAAmB,aACpC,MAAC,IAAI,IACH,IAAI,EAAE,UAAU,EAChB,SAAS,EAAC,oFAAoF,aAE9F,KAAC,WAAW,IAAC,SAAS,EAAC,QAAQ,wBAAe,OAAE,IAAI,CAAC,SAAS,IACzD,EACN,QAAQ,CAAC,CAAC,CAAC,CACV,YAAG,SAAS,EAAC,iEAAiE,YAAE,QAAQ,GAAK,CAC9F,CAAC,CAAC,CAAC,IAAI,EACR,aAAI,SAAS,EAAC,oEAAoE,YAAE,KAAK,CAAC,KAAK,GAAM,EACpG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,oCAAoC,YAAE,KAAK,CAAC,IAAI,GAAK,CAAC,CAAC,CAAC,IAAI,EACvF,cAAK,SAAS,EAAC,MAAM,YACnB,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAC,QAAQ,EAAC,MAAM,EAAE,MAAM,GAAI,GAC7D,EACN,KAAC,aAAa,IAAC,OAAO,EAAE,KAAK,CAAC,IAAI,EAAE,UAAU,EAAE,UAAU,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,GAAI,IACpG,EACV,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,EAAC,MAAM,EAAE,MAAM,GAAI,IAC3D,CACP,CAAC;AACJ,CAAC"}
1
+ {"version":3,"file":"guide-article.js","sourceRoot":"","sources":["../../src/guides/guide-article.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE3C,OAAO,EAAE,IAAI,EAAE,MAAM,0BAA0B,CAAC;AAEhD,OAAO,EAAE,eAAe,EAAE,aAAa,EAAwB,MAAM,sBAAsB,CAAC;AAC5F,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAEhD,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAqB,MAAM,cAAc,CAAC;AAuBhE;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,EAC3B,KAAK,EACL,UAAU,EACV,SAAS,EACT,QAAQ,EACR,MAAM,EACN,UAAU,EACV,OAAO,EACP,IAAI,EACJ,cAAc,GACI;IAClB,MAAM,IAAI,GAAG,EAAE,GAAG,aAAa,EAAE,GAAG,MAAM,EAAE,CAAC;IAC7C,MAAM,QAAQ,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAE7C,OAAO,CACL,eAAK,SAAS,EAAC,sDAAsD,aACnE,mBAAS,SAAS,EAAC,mBAAmB,aACpC,MAAC,IAAI,IACH,IAAI,EAAE,UAAU,EAChB,SAAS,EAAC,oFAAoF,aAE9F,KAAC,WAAW,IAAC,SAAS,EAAC,QAAQ,wBAAe,OAAE,IAAI,CAAC,SAAS,IACzD,EACN,QAAQ,CAAC,CAAC,CAAC,CACV,YAAG,SAAS,EAAC,iEAAiE,YAAE,QAAQ,GAAK,CAC9F,CAAC,CAAC,CAAC,IAAI,EACR,aAAI,SAAS,EAAC,oEAAoE,YAAE,KAAK,CAAC,KAAK,GAAM,EACpG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,YAAG,SAAS,EAAC,oCAAoC,YAAE,KAAK,CAAC,IAAI,GAAK,CAAC,CAAC,CAAC,IAAI,EACvF,cAAK,SAAS,EAAC,MAAM,YACnB,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAC,QAAQ,EAAC,MAAM,EAAE,MAAM,GAAI,GAC7D,EACN,KAAC,aAAa,IACZ,OAAO,EAAE,KAAK,CAAC,IAAI,EACnB,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,UAAU,EACtB,OAAO,EAAE,OAAO,EAChB,YAAY,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CACxB,KAAC,WAAW,IACV,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,IAAI,EAAE,IAAI,EACV,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,UAAU,EAAE,MAAM,EAC9B,cAAc,EAAE,cAAc,GAC9B,CACH,GACD,IACM,EACV,KAAC,QAAQ,IAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAC,MAAM,EAAC,MAAM,EAAE,MAAM,GAAI,IAC3D,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1,62 @@
1
+ import { type ReactNode } from "react";
2
+ import { type GuidesLabels } from "./library.js";
3
+ /** Every element the zoom draws. Each value replaces the default for that element. */
4
+ export interface GuideZoomClassNames {
5
+ /** The button around the picture in the article. */
6
+ trigger: string;
7
+ /** "Click to enlarge", over the picture's corner. */
8
+ hint: string;
9
+ overlay: string;
10
+ /** The dialog: the whole screen on a phone, inset on wider ones. */
11
+ content: string;
12
+ toolbar: string;
13
+ instructions: string;
14
+ button: string;
15
+ /** The zoom level, a button that switches between fit and full size. */
16
+ level: string;
17
+ /** The area the picture is zoomed and dragged in. */
18
+ stage: string;
19
+ /** Under the picture: the caption and the alt text. */
20
+ footer: string;
21
+ caption: string;
22
+ alt: string;
23
+ }
24
+ export declare const GUIDE_ZOOM_CLASS_NAMES: GuideZoomClassNames;
25
+ export interface GuideFigureZoomProps {
26
+ /** The picture as the article draws it: the button's content. */
27
+ children: ReactNode;
28
+ /** What the dialog shows, laid out at the natural size and scaled. Default: `children` again. */
29
+ full?: ReactNode;
30
+ /**
31
+ * The picture's natural size in CSS pixels — a screenshot's registered size, so "full size"
32
+ * is one image pixel to one CSS pixel. Left out (a diagram), it is measured from the article's
33
+ * picture when the dialog opens, and full size is twice the fit.
34
+ */
35
+ width?: number;
36
+ height?: number;
37
+ alt: string;
38
+ caption?: string;
39
+ labels?: Partial<GuidesLabels>;
40
+ classNames?: Partial<GuideZoomClassNames>;
41
+ }
42
+ interface Size {
43
+ w: number;
44
+ h: number;
45
+ }
46
+ /** Each button press or key multiplies or divides the zoom by this. */
47
+ export declare const ZOOM_STEP = 1.25;
48
+ /** The scale that fits `natural` inside `stage`, never past full size for a picture with a natural size. */
49
+ export declare function fitScale(natural: Size, stage: Size, capAtFull: boolean): number;
50
+ /**
51
+ * A guide's picture, opened full-size: a button around the article's picture (with a "Click to
52
+ * enlarge" hint) that opens a dialog fitting it to the screen. In there it zooms with the
53
+ * buttons, `+` and `−`, ⌘/Ctrl + scroll (a trackpad pinch) and a touch pinch; drags to pan
54
+ * when it is bigger than the screen (and scrolls, and moves with the arrow keys); a double-click
55
+ * or double-tap switches between fit and full size, and `0` fits again. Escape closes it and
56
+ * focus goes back to the picture. The caption and alt text are shown under it.
57
+ *
58
+ * Zooming eases unless the reader prefers reduced motion; dragging and pinching never do.
59
+ */
60
+ export declare function GuideFigureZoom({ children, full, width, height, alt, caption, labels, classNames, }: GuideFigureZoomProps): import("react").JSX.Element;
61
+ export {};
62
+ //# sourceMappingURL=guide-figure-zoom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"guide-figure-zoom.d.ts","sourceRoot":"","sources":["../../src/guides/guide-figure-zoom.tsx"],"names":[],"mappings":"AAIA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAGf,OAAO,EAAiB,KAAK,YAAY,EAAE,MAAM,cAAc,CAAC;AAEhE,sFAAsF;AACtF,MAAM,WAAW,mBAAmB;IAClC,oDAAoD;IACpD,OAAO,EAAE,MAAM,CAAC;IAChB,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,oEAAoE;IACpE,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,MAAM,EAAE,MAAM,CAAC;IACf,wEAAwE;IACxE,KAAK,EAAE,MAAM,CAAC;IACd,qDAAqD;IACrD,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,sBAAsB,EAAE,mBAiBpC,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,iEAAiE;IACjE,QAAQ,EAAE,SAAS,CAAC;IACpB,iGAAiG;IACjG,IAAI,CAAC,EAAE,SAAS,CAAC;IACjB;;;;OAIG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,CAAC,YAAY,CAAC,CAAC;IAC/B,UAAU,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,CAAC;CAC3C;AAED,UAAU,IAAI;IACZ,CAAC,EAAE,MAAM,CAAC;IACV,CAAC,EAAE,MAAM,CAAC;CACX;AAMD,uEAAuE;AACvE,eAAO,MAAM,SAAS,OAAO,CAAC;AAS9B,4GAA4G;AAC5G,wBAAgB,QAAQ,CAAC,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,GAAG,MAAM,CAM/E;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,EAC9B,QAAQ,EACR,IAAI,EACJ,KAAK,EACL,MAAM,EACN,GAAG,EACH,OAAO,EACP,MAAM,EACN,UAAU,GACX,EAAE,oBAAoB,+BAuVtB"}