@theoremjs/react 0.3.4-next.482.g7e608f2 → 0.3.4-next.508.geda6db0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -276,7 +276,7 @@ import { TheoremDecision } from '@theoremjs/react/ui';
276
276
  ```
277
277
 
278
278
  - `questions` maps each question id to its definition.
279
- - `images` is optional. It holds pictures every decision sends, by the reference the questions write, such as `<ghs02>` in "Which item matches <ghs02>?". The page sees them and refuses its own image under one of their names.
279
+ - `images` is optional. It holds pictures a decision can send, by reference, such as `<ghs02>` in "Which item matches <ghs02>?". The kernel sends only the ones that the state or a question references. The page sees them and refuses its own image under one of their names.
280
280
  - `vault` holds the keys of the profile, by slot.
281
281
  - `metadata` is optional. It adds data, such as the signed-in user, to the trace record of each decision.
282
282
 
@@ -284,9 +284,9 @@ When the profile sets `maxStateBytes` in its `inputs`, `TheoremDecision` shows t
284
284
 
285
285
  In one column, the state sits in the middle of the page until you ask for a decision. It then eases up to the top, and the answers appear under it. With `columns`, the state moves to the left instead and the answers fill the right.
286
286
 
287
- A profile whose model takes images (`images: true`, see the TypeSafe options in `docs/contracts/providers.md`) shows a drop area under the state when a question is a box. Each PNG or JPEG dropped there becomes a state field named after the file. The field holds the image's reference, its name in angle brackets: `pantry shelf.jpg` becomes `{ "pantry_shelf": "<pantry_shelf>" }`. The field shows the image, opens it full size in a lightbox when clicked, and can replace it. A question names the field in backticks, such as "Which jar in `pantry_shelf` is open?". TypeSafe reads a reference anywhere it appears as text. The brackets keep a reference from matching an ordinary word. A decision sends only the images its state still names, as `assets`, and the kernel refuses any that are not PNG or JPEG bytes before a request leaves. Pass `defaultImages`, with a `defaultState` that names them, to start with some.
287
+ The page shows a drop area under the state fields when a question is a box or the decision holds images. The model must take images: on TypeSafe, the binding sets `images: true` (see `docs/contracts/providers.md`). Each PNG or JPEG dropped there becomes a state field named after the file. The field holds the image's reference, its name in angle brackets: `pantry shelf.jpg` becomes `{ "pantry_shelf": "<pantry_shelf>" }`. The field shows the image, opens it full size in a lightbox when clicked, and can replace it. A question names the field in backticks, such as "Which jar in `pantry_shelf` is open?". The model reads a reference anywhere in a string, so the brackets keep a reference from matching an ordinary word. A decision sends only the images its state still holds as a field value, as `assets`, and the kernel refuses any that are not PNG or JPEG bytes before a request leaves. Pass `defaultImages`, with a `defaultState` that names them, to start with some.
288
288
 
289
- A box answer is drawn as the part of the image it covers, with its edges beside it as shares of the image. The image is the one the question's `image` gives, a reference or a state field. Without one, it is the one at the field the instructions first name in backticks, such as `chart` in "Where on `chart` would the green apple in `photo` sit?". Without that, it is the first image the state names, or else the first held. Click the cut-out to open the whole image in a lightbox, with the box outlined in `--color-accent` and the rest shaded in `--color-overlay`.
289
+ A box answer is drawn as the part of the image it covers, with its edges beside it as shares of the image. The image is the one the question's `image` gives, a reference or a state field. Without one, it is the decision's only image. When the page cannot tell which image the box is on, it draws the box in a frame that stands for the whole image. Click the cut-out to open the whole image in a lightbox, with the box outlined in `--color-accent` and the rest shaded in `--color-overlay`.
290
290
 
291
291
  Pass `onQuestion` to open a question where it is set up, such as in an editor. Each answer then has a button that calls it with the question's id.
292
292
 
@@ -40,11 +40,10 @@ export declare function droppedImages(dropped: readonly (readonly [File, Decisio
40
40
  state: Record<string, DecisionJson>;
41
41
  };
42
42
  /**
43
- * The image a box answer is drawn on: `field` itself when it is a held reference, else the one at
44
- * that state field, else the first the state refers to, else the first held. A box answer names no image, so this is the
45
- * page's best reading of where it points.
43
+ * The image a box answer is drawn on: the one its question gives, by reference or by the state
44
+ * field that holds it, else the decision's only image. Otherwise the page cannot tell, so none.
46
45
  */
47
- export declare function boxSource(images: DecisionImages, state: DecisionJson, field?: string): DecisionAsset | undefined;
46
+ export declare function boxSource(images: DecisionImages, state: DecisionJson, image?: string): DecisionAsset | undefined;
48
47
  /** A box answer's edges, each a share of the image from its top or left. */
49
48
  export type DecisionBox = {
50
49
  top: number;
@@ -78,16 +78,15 @@ function at(state, path) {
78
78
  return value;
79
79
  }
80
80
  /**
81
- * The image a box answer is drawn on: `field` itself when it is a held reference, else the one at
82
- * that state field, else the first the state refers to, else the first held. A box answer names no image, so this is the
83
- * page's best reading of where it points.
81
+ * The image a box answer is drawn on: the one its question gives, by reference or by the state
82
+ * field that holds it, else the decision's only image. Otherwise the page cannot tell, so none.
84
83
  */
85
- export function boxSource(images, state, field) {
86
- const names = Object.keys(images);
87
- const pointed = field === undefined || field in images ? field : at(state, field);
88
- const named = (typeof pointed === 'string' && pointed in images ? pointed : undefined) ??
89
- names.find((name) => mentions(state, name));
90
- return images[named ?? names[0] ?? ''];
84
+ export function boxSource(images, state, image) {
85
+ const reference = image === undefined || image in images ? image : at(state, image);
86
+ if (typeof reference === 'string' && reference in images)
87
+ return images[reference];
88
+ const held = Object.values(images);
89
+ return image === undefined && held.length === 1 ? held[0] : undefined;
91
90
  }
92
91
  /** The box in an image's pixels, and an outline that stays visible at any size. */
93
92
  export function boxRect(box, width, height) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@theoremjs/react",
3
- "version": "0.3.4-next.482.g7e608f2",
3
+ "version": "0.3.4-next.508.geda6db0",
4
4
  "description": "React bindings for Theorem: headless hooks + transport, an Astryx chat UI, and a Web-standard server handler.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -60,8 +60,8 @@
60
60
  "@stylexjs/stylex": "0.19.0",
61
61
  "react": "^19.0.0",
62
62
  "react-dom": "^19.0.0",
63
- "@theoremjs/agents": "^0.3.4-next.482.g7e608f2",
64
- "@theoremjs/web": "^0.3.4-next.482.g7e608f2"
63
+ "@theoremjs/agents": "^0.3.4-next.508.geda6db0",
64
+ "@theoremjs/web": "^0.3.4-next.508.geda6db0"
65
65
  },
66
66
  "peerDependenciesMeta": {
67
67
  "@astryxdesign/core": {
@@ -164,10 +164,10 @@ function BoxCrop({ source, box, caption, }) {
164
164
  setMarked(null);
165
165
  }, media: { src: marked ?? src, alt: t('@theorem.decision.box_marked'), caption }, hasZoom: true })] }));
166
166
  }
167
- /** The box cut from the image its question names, or drawn in a frame that stands for the whole image. */
168
- function BoxAnswer({ title, aside, detail, answer, field, asked, }) {
167
+ /** The box cut from its image, or drawn in a frame that stands for the whole image when the page cannot tell which. */
168
+ function BoxAnswer({ title, aside, detail, answer, image, asked, }) {
169
169
  const t = useLabels();
170
- const source = asked && boxSource(asked.images, asked.state, field);
170
+ const source = asked && boxSource(asked.images, asked.state, image);
171
171
  const n = useNumbers();
172
172
  const { top, bottom, left, right } = answer.box;
173
173
  const edges = t('@theorem.decision.box_edges', {
@@ -212,7 +212,7 @@ function AnswerCard({ question, answer, asked, onQuestion, detail, }) {
212
212
  return _jsx(ScoreAnswer, { ...head, answer: answer, labels: question.labels });
213
213
  if (answer.type === 'noul')
214
214
  return _jsx(NumberAnswer, { ...head, answer: answer });
215
- return _jsx(BoxAnswer, { ...head, answer: answer, field: question.field, asked: asked });
215
+ return _jsx(BoxAnswer, { ...head, answer: answer, image: question.image, asked: asked });
216
216
  }
217
217
  /**
218
218
  * A console's result as it streams in: dimmed while the next one runs, then
package/ui/labels.d.ts CHANGED
@@ -501,7 +501,7 @@ export declare const THEOREM_UI_CATALOG: {
501
501
  };
502
502
  readonly '@theorem.decision.confidence': {
503
503
  readonly defaultMessage: "{percent} sure";
504
- readonly description: "How sure the model is of a choice or score; percent is formatted, e.g. '92%'.";
504
+ readonly description: "How sure the model is of a choice, score or box; percent is formatted, e.g. '92%'.";
505
505
  readonly params: readonly ["percent"];
506
506
  };
507
507
  readonly '@theorem.decision.option': {
package/ui/labels.js CHANGED
@@ -464,7 +464,7 @@ export const THEOREM_UI_CATALOG = {
464
464
  },
465
465
  '@theorem.decision.confidence': {
466
466
  defaultMessage: '{percent} sure',
467
- description: "How sure the model is of a choice or score; percent is formatted, e.g. '92%'.",
467
+ description: "How sure the model is of a choice, score or box; percent is formatted, e.g. '92%'.",
468
468
  params: ['percent'],
469
469
  },
470
470
  '@theorem.decision.option': {