@spidunno/desmos-types 1.13.2 → 1.13.3

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
@@ -6,11 +6,11 @@ the graphing calculator, geometry tool, 3D calculator, and the four-function and
6
6
  ## Install
7
7
 
8
8
  ```sh
9
- npm install --save-dev @spidunno/desmos-types@~1.13.2
9
+ npm install --save-dev @spidunno/desmos-types@~1.13.3
10
10
  ```
11
11
 
12
12
  The package's major and minor version match the Desmos API version it describes; patch releases
13
- are fixes to the types. Use a tilde range (`~1.13.2`), not npm's default caret (`^`), so you only
13
+ are fixes to the types. Use a tilde range (`~1.13.3`), not npm's default caret (`^`), so you only
14
14
  get type fixes for the API version you load.
15
15
 
16
16
  ## Usage
@@ -158,6 +158,14 @@ What's hand-typed:
158
158
  `ImageModel` and `TickerModel` as a discriminated union (`ItemModel`), plus `ListModel`.
159
159
  - **Actions:** `Action` is the full union. About 25 common actions have checked payloads, and
160
160
  `ActionOfType<'set-item-latex'>` picks one.
161
+ - **Graph sketches** (`controller.grapher2d.graphSketches`): one `GraphSketch` per graphed
162
+ expression, holding `GraphBranch`es as a union over the 20 branch modes the 2D grapher
163
+ draws (`BranchModes` names them). Each mode's `segments` layout is typed: flat `[x, y, …]`
164
+ for most curves, `[y, x, …]` for `x = f(y)`, `[θ, r, …]` for polar, `[x, y]` tuples for
165
+ points, and fixed tuples like `[cx, cy, r]` for geometry objects. Also covered: points of
166
+ interest (`POI`, `POITypes`), sketch labels, movable points and the grapher's sketch methods.
167
+ A fixture of 60 real sketches (`test/fixtures/graph-sketches.ts`) is type-checked against
168
+ these types.
161
169
  - **Dispatcher:** `register`, `unregister`, `waitFor`, generic over the action type.
162
170
  - **Other controllers:** each math field (`mathField.controller`) and each basic calculator
163
171
  (`calculator.controller`) has its own controller and dispatcher. Keystrokes in a math field are
@@ -184,14 +192,117 @@ What's hand-typed:
184
192
  `getReconciledExpressionProps`, `currentLanguage`, `manageFocusHelper` / `mathquillFocusHelper`,
185
193
  and `List`.
186
194
 
195
+ ### Graph sketches
196
+
197
+ `controller.grapher2d.graphSketches` holds what the 2D grapher draws, keyed by expression id. Each
198
+ sketch has `branches`, and each branch has a numeric `branchMode` that tells you what it is and
199
+ how to read its `segments`. One expression often produces several branches: one per list element,
200
+ boundary curves plus a fill for an inequality, an outline plus a fill for a polygon.
201
+
202
+ The examples below are plain JavaScript, so you can paste them into the browser console. On
203
+ desmos.com the calculator is the global `Calc`; in your own page it's whatever you called
204
+ `Desmos.GraphingCalculator(...)`. desmos.com runs the same v1.13 line, but it is redeployed
205
+ continuously, so an internal field can change before these types are regenerated.
206
+
207
+ ```js
208
+ // Every branch of every sketch, with its mode
209
+ for (const [id, sketch] of Object.entries(Calc.controller.grapher2d.graphSketches)) {
210
+ console.log(id, sketch.branches.map((b) => b.branchMode));
211
+ }
212
+ ```
213
+
214
+ #### Branch modes
215
+
216
+ | Mode | Name | Drawn for | `segments` | Other notable fields |
217
+ | ---: | --- | --- | --- | --- |
218
+ | 1 | X | `x = f(y)`, `x` inequalities | flat `[y0, x0, y1, x1, …]` (**y first**) | `operator`, `compiled`, `poi` |
219
+ | 2 | Y | `y = f(x)`, `y` inequalities, distributions, solvable implicit equations | flat `[x0, y0, x1, y1, …]` | `operator`, `compiled`, `poi`, `boundingBox` |
220
+ | 3 | XYPOINT | points, point lists, dot plots | arrays of `[x, y]` | `labels`, `pointSize`, `pointOpacity`, `showLabel` |
221
+ | 4 | XYPOINT_MOVABLE | draggable points | arrays of `[x, y]` | `movablePointInfo` |
222
+ | 5 | PARAMETRIC | parametrics, point-list and table lines, polygon outlines, box plots | flat `[x0, y0, …]` | `compiled`, `tableId` |
223
+ | 6 | POLAR | `r = f(θ)`, polar inequalities | flat `[θ0, r0, θ1, r1, …]` (**polar**) | `sampledDomain` |
224
+ | 7 | POLYGONFILL | inequality shading, polygon and parametric fills, histogram bars | flat `[x0, y0, …]` polygons (empty for inequality shading) | `fillOpacity` |
225
+ | 8 | IMPLICIT | implicit curves | flat `[x0, y0, …]` | `compiled` |
226
+ | 15 | ERROR | an expression that failed while graphing | `[]` | `error` (`{ key, vars }`) |
227
+ | 17 | SEGMENT | `segment` | `[x1, y1, x2, y2]` | `arrowMode` |
228
+ | 18 | LINE | `line` | `[x1, y1, x2, y2]`: two points on the line | `arrowMode` |
229
+ | 19 | RAY | `ray` | `[startX, startY, throughX, throughY]` | `arrowMode` |
230
+ | 20 | CIRCLE | `circle` | `[cx, cy, r]` | |
231
+ | 21 | ARC | `arc` | `[cx, cy, r, startAngle, endAngle]` | |
232
+ | 22 | LABEL | label of a segment, polygon or angle | placement data | `labels` (text), `objectType` (17, 16 or 23) |
233
+ | 23 | ANGLE_MARKER | `angle`, `directedangle` | `[vx, vy, startAngle, angle, directed]` | |
234
+ | 24 | VECTOR | `vector` | `[tailX, tailY, headX, headY]` | `arrowMode` |
235
+ | 25 | COMPLEX_NUMBER | complex numbers in complex mode | arrays of `[re, im]` | like XYPOINT |
236
+ | 26 | COMPLEX_NUMBER_MOVABLE | draggable complex numbers | arrays of `[re, im]` | `movablePointInfo` |
237
+ | 27 | IMAGE | images | `[]` | `dimensions` (`x`, `y`, `width`, `height`, `radianAngle`, `opacity`) |
238
+
239
+ Modes 17–24 only appear in the geometry tool. Angles are in radians. In each row, `segments` is a
240
+ list of these: a curve broken at discontinuities has several flat arrays, and a list of circles has
241
+ several `[cx, cy, r]` entries. In TypeScript, hovering `branchMode` shows this table, and comparing
242
+ it to a number (`branch.branchMode === 20`) narrows the branch to that mode's type.
243
+
244
+ #### Points of interest
245
+
246
+ `sketch.getPOI()` returns the points of interest the grapher shows when an expression is selected.
247
+ `poi.type` is:
248
+
249
+ | Type | Meaning | Comes from |
250
+ | ---: | --- | --- |
251
+ | 1001 | intersection | `X` / `Y` branches |
252
+ | 1002 | zero (root) | `X` / `Y` branches |
253
+ | 1003 | axis intercept | `X` / `Y` branches |
254
+ | 1004 | extremum | `X` / `Y` branches |
255
+ | 1006 | plotted point without a visible label | point branches |
256
+ | 1008 | labeled point, or a geometry label's anchor | point branches, labels |
257
+
258
+ #### Examples
259
+
260
+ ```js
261
+ const sketches = Calc.controller.grapher2d.graphSketches;
262
+
263
+ // Turn any curve branch into a list of {x, y} points, handling the modes
264
+ // whose coordinates aren't (x, y)
265
+ function curvePoints(branch) {
266
+ const points = [];
267
+ for (const flat of branch.segments) {
268
+ for (let i = 0; i < flat.length; i += 2) {
269
+ const [a, b] = [flat[i], flat[i + 1]];
270
+ if (branch.branchMode === 1) points.push({ x: b, y: a }); // x = f(y): (y, x)
271
+ else if (branch.branchMode === 6) points.push({ x: b * Math.cos(a), y: b * Math.sin(a) }); // polar: (θ, r)
272
+ else points.push({ x: a, y: b });
273
+ }
274
+ }
275
+ return points;
276
+ }
277
+
278
+ // Circles in the geometry tool
279
+ for (const sketch of Object.values(sketches)) {
280
+ for (const branch of sketch.branches) {
281
+ if (branch.branchMode === 20) {
282
+ for (const [cx, cy, r] of branch.segments) console.log(`circle at (${cx}, ${cy}), radius ${r}`);
283
+ }
284
+ }
285
+ }
286
+
287
+ // Extrema of the expression with id "1"
288
+ sketches['1']?.getPOI().filter((poi) => poi.type === 1004).map((poi) => [poi.x, poi.y]);
289
+
290
+ // Draggable points, with table row info for table columns
291
+ sketches['1']?.getMovablePoints().map((p) => ({ x: p.x, y: p.y, row: p.tableInfo?.rowIndex }));
292
+ ```
293
+
187
294
  ### Regenerating for a new bundle
188
295
 
189
296
  ```sh
190
297
  curl -o calculator.js "https://www.desmos.com/api/v1.13/calculator.js?apiKey=YOUR_API_KEY"
191
298
  npm run generate:internals -- calculator.js
299
+ npm run snapshot:sketches -- calculator.js
192
300
  npm test
193
301
  ```
194
302
 
303
+ `snapshot:sketches` re-renders real graph sketches into `test/fixtures/graph-sketches.ts`. If a
304
+ branch shape changed, `npm test` reports which field of which branch mode no longer matches.
305
+
195
306
  The generator executes the bundle inside jsdom, so only run it on a bundle from desmos.com.
196
307
  If `npm test` fails afterwards, the bundle changed in a way that contradicts a hand-written type.
197
308
  The error names the field.
@@ -1120,7 +1120,7 @@ declare namespace Desmos.Internals.Generated {
1120
1120
  graphLineWidth: number;
1121
1121
  guid: string;
1122
1122
  hideCustomColors: boolean;
1123
- highlight?: unknown;
1123
+ highlight: boolean;
1124
1124
  highlightPropertyMultipliers: Record<string, number[]>;
1125
1125
  includeFunctionParametersInRandomSeed: boolean;
1126
1126
  labelHangingColor: string;
@@ -0,0 +1,631 @@
1
+ /**
2
+ * `controller.grapher2d.graphSketches`: what the 2D grapher draws for each
3
+ * expression.
4
+ *
5
+ * Every graphed expression has one {@link GraphSketch}, keyed by expression
6
+ * id. A sketch holds one or more {@link GraphBranch}es, which are the units
7
+ * the grapher actually draws. One expression often produces several branches:
8
+ * a list produces one per element, an inequality produces boundary curves plus
9
+ * a fill, a polygon produces a fill plus an outline, an angle produces a marker
10
+ * plus a label.
11
+ *
12
+ * Branches are a discriminated union on the numeric `branchMode`; see
13
+ * {@link BranchModes} for the names. The meaning of `segments` depends on the
14
+ * mode, so always narrow on `branchMode` before reading it.
15
+ *
16
+ * Typed from the v1.13 bundle: every branch mode below was observed at runtime
17
+ * except `ERROR` (15), whose shape comes from the code that builds it.
18
+ */
19
+ declare namespace Desmos.Internals {
20
+ // ---------------------------------------------------------------------------
21
+ // Enums (numeric at runtime; there is no exported enum object)
22
+ // ---------------------------------------------------------------------------
23
+
24
+ /**
25
+ * Names of the `branchMode` values that reach the 2D grapher. Use as a type:
26
+ * `BranchModes['Y']` is `2`.
27
+ *
28
+ * The bundle also defines `NONE` (10), `VISUALIZATION` (11), `POLYGON` (16)
29
+ * and the 3D modes (100+), but the 2D grapher never receives them.
30
+ */
31
+ interface BranchModes {
32
+ /** `x` as a function of `y`. */
33
+ X: 1;
34
+ /** `y` as a function of `x`. */
35
+ Y: 2;
36
+ /** Static points. */
37
+ XYPOINT: 3;
38
+ /** Draggable points. */
39
+ XYPOINT_MOVABLE: 4;
40
+ /** Parametric curves; also point-list lines, table lines and box plots. */
41
+ PARAMETRIC: 5;
42
+ POLAR: 6;
43
+ /** A filled region: inequality shading, polygon interiors, histogram bars. */
44
+ POLYGONFILL: 7;
45
+ IMPLICIT: 8;
46
+ /** The expression failed while graphing. */
47
+ ERROR: 15;
48
+ SEGMENT: 17;
49
+ LINE: 18;
50
+ RAY: 19;
51
+ CIRCLE: 20;
52
+ ARC: 21;
53
+ /** A text label attached to a geometry object (segment, polygon or angle). */
54
+ LABEL: 22;
55
+ ANGLE_MARKER: 23;
56
+ VECTOR: 24;
57
+ /** Complex numbers plotted as points (complex mode). */
58
+ COMPLEX_NUMBER: 25;
59
+ COMPLEX_NUMBER_MOVABLE: 26;
60
+ IMAGE: 27;
61
+ }
62
+
63
+ type BranchModeName = keyof BranchModes;
64
+ type BranchMode = BranchModes[BranchModeName];
65
+
66
+ /** Kinds of point of interest. `type` on {@link POI}. */
67
+ interface POITypes {
68
+ /** Intersection with another curve. */
69
+ INTERSECTION: 1001;
70
+ /** Zero (root). */
71
+ ZERO: 1002;
72
+ /** Axis intercept. */
73
+ INTERCEPT: 1003;
74
+ /** Local minimum or maximum. */
75
+ EXTREMUM: 1004;
76
+ /** A plotted point without a visible label. */
77
+ DEFINED: 1006;
78
+ /** A traced point. Not created by sketches. */
79
+ TRACE: 1007;
80
+ /** A point with a visible (or interactive) label, or a geometry label anchor. */
81
+ LABEL: 1008;
82
+ }
83
+
84
+ type POIType = POITypes[keyof POITypes];
85
+
86
+ /** The comparison of the expression that produced a branch. */
87
+ type GraphOperator = '=' | '<' | '>' | '<=' | '>=' | '!=';
88
+
89
+ // ---------------------------------------------------------------------------
90
+ // Shared parts
91
+ // ---------------------------------------------------------------------------
92
+
93
+ /** Coordinates of a group of points of interest, as parallel arrays. */
94
+ interface POICoordinates {
95
+ x: number[];
96
+ y: number[];
97
+ /** For intersections: what each point intersects with. */
98
+ intersects?: unknown[];
99
+ }
100
+
101
+ /** Points of interest of a curve. Only `X` and `Y` branches turn these into {@link POI}s. */
102
+ interface CurvePOIs {
103
+ zeros?: POICoordinates;
104
+ intercept?: POICoordinates;
105
+ extrema?: POICoordinates;
106
+ /** Set by the grapher after intersections are computed. */
107
+ intersections?: POICoordinates;
108
+ }
109
+
110
+ /** Points of interest of a point branch: the points themselves. */
111
+ interface PointPOIs {
112
+ defined: POICoordinates;
113
+ intersections?: POICoordinates;
114
+ }
115
+
116
+ /** Branches without their own points of interest. */
117
+ interface NoPOIs {
118
+ intersections?: POICoordinates;
119
+ }
120
+
121
+ /** The JavaScript compiled from an expression, used for tracing and evaluation. */
122
+ interface CompiledFunction {
123
+ source: string;
124
+ /** Parameter names, e.g. `['x']`, `['t']`, `['theta']`, `['x', 'y']`. */
125
+ args: string[];
126
+ constants: unknown[];
127
+ executionMetadata: Record<string, unknown>;
128
+ /** Created lazily from `source`. */
129
+ fn?: (...args: number[]) => number;
130
+ }
131
+
132
+ /** Extent of a statistical object or table, used for "zoom to fit". */
133
+ interface BranchBoundingBox {
134
+ type: 'continuousDistribution' | 'discreteDistribution' | 'histogram' | 'dotplot' | 'boxplot' | 'table';
135
+ xmin: number;
136
+ xmax: number;
137
+ ymin: number;
138
+ ymax: number;
139
+ /** For histograms and dot plots. */
140
+ binWidth?: number;
141
+ /** For tables: the column variable, e.g. `'y_1'`. */
142
+ symbol?: string;
143
+ }
144
+
145
+ /** A localized message: a translation key plus its substitutions. */
146
+ interface LocalizedMessage {
147
+ key: string;
148
+ vars?: Record<string, unknown>;
149
+ }
150
+
151
+ /** Fields every branch can have. */
152
+ interface GraphBranchBase<M extends BranchMode> {
153
+ /**
154
+ * What kind of branch this is, and so how to read `segments`. A plain
155
+ * number at runtime; compare against it directly (`branch.branchMode === 20`),
156
+ * which in TypeScript also narrows the branch type.
157
+ *
158
+ * | Mode | Name | Drawn for | `segments` |
159
+ * | ---: | --- | --- | --- |
160
+ * | 1 | X | `x = f(y)`, `x` inequalities | flat `[y0, x0, y1, x1, …]` (⚠ y first) |
161
+ * | 2 | Y | `y = f(x)`, `y` inequalities, distributions, solvable implicits | flat `[x0, y0, x1, y1, …]` |
162
+ * | 3 | XYPOINT | points and point lists, dot plots | `[x, y][]` per group |
163
+ * | 4 | XYPOINT_MOVABLE | draggable points | `[x, y][]` per group |
164
+ * | 5 | PARAMETRIC | parametrics, point-list/table lines, polygon outlines, box plots | flat `[x0, y0, …]` |
165
+ * | 6 | POLAR | `r = f(θ)`, polar inequalities | flat `[θ0, r0, θ1, r1, …]` (⚠ polar) |
166
+ * | 7 | POLYGONFILL | inequality shading, polygon/parametric fills, histogram bars | flat `[x0, y0, …]` polygons |
167
+ * | 8 | IMPLICIT | implicit curves | flat `[x0, y0, …]` |
168
+ * | 15 | ERROR | an expression that failed while graphing | `[]`; see `error` |
169
+ * | 17 | SEGMENT | `segment` | `[x1, y1, x2, y2]` |
170
+ * | 18 | LINE | `line` | `[x1, y1, x2, y2]` (two points on it) |
171
+ * | 19 | RAY | `ray` | `[startX, startY, throughX, throughY]` |
172
+ * | 20 | CIRCLE | `circle` | `[cx, cy, r]` |
173
+ * | 21 | ARC | `arc` | `[cx, cy, r, startAngle, endAngle]` |
174
+ * | 22 | LABEL | label of a segment, polygon or angle | placement data; text in `labels` |
175
+ * | 23 | ANGLE_MARKER | `angle`, `directedangle` | `[vx, vy, startAngle, angle, directed]` |
176
+ * | 24 | VECTOR | `vector` | `[tailX, tailY, headX, headY]` |
177
+ * | 25 | COMPLEX_NUMBER | complex numbers (complex mode) | `[re, im][]` per group |
178
+ * | 26 | COMPLEX_NUMBER_MOVABLE | draggable complex numbers | `[re, im][]` per group |
179
+ * | 27 | IMAGE | images | `[]`; see `dimensions` |
180
+ *
181
+ * Modes 17–24 only occur in the geometry tool. Angles are in radians.
182
+ */
183
+ branchMode: M;
184
+ color: HexColor;
185
+ /** Index of the list element this branch was drawn for. */
186
+ listIndex?: number;
187
+ /** `false` when the curve couldn't be fully resolved (detail may be missing). */
188
+ resolved?: boolean;
189
+ boundingBox?: BranchBoundingBox;
190
+ /** The table this branch comes from, if any. */
191
+ tableId?: ExpressionId;
192
+ /** Why values became NaN, if known. Copied to the item model. */
193
+ nanBlame?: unknown;
194
+ /** Set when a recursive function hit the depth limit. Copied to the item model. */
195
+ recursionTerminationStatus?: unknown;
196
+ }
197
+
198
+ /** Styling of stroked branches. */
199
+ interface StrokeFields {
200
+ style?: LineStyle;
201
+ lineWidth?: number;
202
+ lineOpacity?: number;
203
+ operator?: GraphOperator;
204
+ /** Fill opacity for inequality boundaries and filled curves. */
205
+ fillOpacity?: number;
206
+ /** Geometry: a dashed extension of an object used to construct an intersection. */
207
+ isIntersectionExtension?: boolean;
208
+ }
209
+
210
+ /** Styling of point branches. Several fields may be per-point arrays. */
211
+ interface PointFields {
212
+ style: PointStyle;
213
+ /**
214
+ * A single color, or one per point. The grapher supports per-point
215
+ * arrays; the API's `colorLatex` was not observed to produce them.
216
+ */
217
+ color: HexColor | HexColor[];
218
+ /**
219
+ * Pixels; a single size or one per point (e.g. `pointSize: '[5,10,15]'`).
220
+ * Absent on some branches (e.g. discrete distributions); the grapher then uses 8.
221
+ */
222
+ pointSize?: number | number[];
223
+ /** 0–1; a single opacity or one per point. Absent means 1. */
224
+ pointOpacity?: number | number[];
225
+ pointOutline?: boolean;
226
+ showLabel?: boolean;
227
+ /** One label per point; LaTeX in backticks is already evaluated. */
228
+ labels?: string[];
229
+ labelSize?: number;
230
+ /** Radians. */
231
+ labelAngle?: number;
232
+ labelOrientation?: LabelOrientation;
233
+ suppressTextOutline?: boolean;
234
+ interactiveLabel?: boolean;
235
+ editableLabel?: boolean;
236
+ /** Draw the label without its point. */
237
+ nakedLabel?: boolean;
238
+ /** Indices of points dropped because a coordinate was NaN. */
239
+ droppedIndices?: Record<number, true>;
240
+ }
241
+
242
+ /** How a movable point can be dragged. */
243
+ interface MovablePointInfo {
244
+ /** Index of the point (for tables, the row). */
245
+ index: number;
246
+ dragX: boolean;
247
+ dragY: boolean;
248
+ }
249
+
250
+ // ---------------------------------------------------------------------------
251
+ // Branches
252
+ // ---------------------------------------------------------------------------
253
+
254
+ /**
255
+ * `x` as a function of `y`.
256
+ *
257
+ * ⚠ `segments` are flat `[y0, x0, y1, x1, ...]` arrays: the independent
258
+ * variable `y` comes first, unlike every other curve mode.
259
+ */
260
+ interface XBranch extends GraphBranchBase<1>, StrokeFields {
261
+ /** Polylines, each a flat `[y0, x0, y1, x1, ...]` array. */
262
+ segments: number[][];
263
+ poi: CurvePOIs;
264
+ compiled?: CompiledFunction;
265
+ }
266
+
267
+ /** `y` as a function of `x`. Also distribution curves and solved implicit equations. */
268
+ interface YBranch extends GraphBranchBase<2>, StrokeFields {
269
+ /** Polylines, each a flat `[x0, y0, x1, y1, ...]` array. */
270
+ segments: number[][];
271
+ poi: CurvePOIs;
272
+ compiled?: CompiledFunction;
273
+ }
274
+
275
+ /** Static points. */
276
+ interface PointBranch extends Omit<GraphBranchBase<3>, 'color'>, PointFields {
277
+ /** Groups of points, each an array of `[x, y]`. */
278
+ segments: Array<Array<[x: number, y: number]>>;
279
+ poi: PointPOIs;
280
+ showPoint: boolean;
281
+ /** Dot plots: whether the x positions still need computing. */
282
+ needsDotplotXMode?: boolean;
283
+ }
284
+
285
+ /** Draggable points. */
286
+ interface MovablePointBranch extends Omit<GraphBranchBase<4>, 'color'>, PointFields {
287
+ /** Groups of points, each an array of `[x, y]`. */
288
+ segments: Array<Array<[x: number, y: number]>>;
289
+ poi: PointPOIs;
290
+ showPoint?: boolean;
291
+ /** One entry per point in `segments[0]`. */
292
+ movablePointInfo: MovablePointInfo[];
293
+ /** Image scaling handles: per point, the `[x, y]` scale factor it controls. */
294
+ scaleFactors?: Array<Array<[number, number]>>;
295
+ }
296
+
297
+ /**
298
+ * Parametric curves. Also produced for lines through point lists and table
299
+ * columns (with `tableId`) and for box plots.
300
+ */
301
+ interface ParametricBranch extends GraphBranchBase<5>, StrokeFields {
302
+ /** Polylines, each a flat `[x0, y0, x1, y1, ...]` array. */
303
+ segments: number[][];
304
+ poi: CurvePOIs;
305
+ compiled?: CompiledFunction;
306
+ }
307
+
308
+ /**
309
+ * Polar curves.
310
+ *
311
+ * ⚠ `segments` are flat `[θ0, r0, θ1, r1, ...]` arrays in polar coordinates.
312
+ */
313
+ interface PolarBranch extends GraphBranchBase<6>, StrokeFields {
314
+ /** Polylines, each a flat `[θ0, r0, θ1, r1, ...]` array (radians). */
315
+ segments: number[][];
316
+ poi: CurvePOIs;
317
+ compiled?: CompiledFunction;
318
+ /** The θ range that was sampled. */
319
+ sampledDomain?: { min?: number; max?: number };
320
+ }
321
+
322
+ /**
323
+ * A filled region: inequality shading, the inside of polygons and filled
324
+ * parametric curves, histogram bars.
325
+ */
326
+ interface PolygonFillBranch extends GraphBranchBase<7> {
327
+ /**
328
+ * Polygons, each a flat `[x0, y0, x1, y1, ...]` array. Empty for inequality
329
+ * shading, which is drawn from the boundary branches.
330
+ */
331
+ segments: number[][];
332
+ poi: NoPOIs;
333
+ fillOpacity: number;
334
+ lineOpacity?: number;
335
+ style?: undefined;
336
+ }
337
+
338
+ interface ImplicitBranch extends GraphBranchBase<8>, StrokeFields {
339
+ /** Polylines, each a flat `[x0, y0, x1, y1, ...]` array. */
340
+ segments: number[][];
341
+ poi: CurvePOIs;
342
+ compiled?: CompiledFunction;
343
+ }
344
+
345
+ /** The expression failed while graphing. Copied to the model as `errorFromGraphing`. */
346
+ interface ErrorBranch extends Omit<GraphBranchBase<15>, 'color'> {
347
+ error: LocalizedMessage;
348
+ segments: [];
349
+ }
350
+
351
+ /** Fields shared by the geometry object branches. */
352
+ interface GeometryStrokeFields extends StrokeFields {
353
+ poi: NoPOIs;
354
+ }
355
+
356
+ /** A segment between two points. */
357
+ interface SegmentBranch extends GraphBranchBase<17>, GeometryStrokeFields {
358
+ segments: Array<[x1: number, y1: number, x2: number, y2: number]>;
359
+ arrowMode?: ExpressionArrowMode;
360
+ }
361
+
362
+ /** An infinite line through two points. */
363
+ interface LineBranch extends GraphBranchBase<18>, GeometryStrokeFields {
364
+ /** Two points the line passes through. */
365
+ segments: Array<[x1: number, y1: number, x2: number, y2: number]>;
366
+ arrowMode?: ExpressionArrowMode;
367
+ }
368
+
369
+ /** A ray from a start point through a second point. */
370
+ interface RayBranch extends GraphBranchBase<19>, GeometryStrokeFields {
371
+ segments: Array<[startX: number, startY: number, throughX: number, throughY: number]>;
372
+ arrowMode?: ExpressionArrowMode;
373
+ }
374
+
375
+ interface CircleBranch extends GraphBranchBase<20>, GeometryStrokeFields {
376
+ segments: Array<[centerX: number, centerY: number, radius: number]>;
377
+ }
378
+
379
+ /** A circular arc from `startAngle` to `endAngle` (radians; either direction). */
380
+ interface ArcBranch extends GraphBranchBase<21>, GeometryStrokeFields {
381
+ segments: Array<[centerX: number, centerY: number, radius: number, startAngle: number, endAngle: number]>;
382
+ }
383
+
384
+ /** A text label for a geometry object; the text is in `labels`. */
385
+ interface LabelBranch extends GraphBranchBase<22> {
386
+ /** The kind of object labeled: segment (17), polygon (16) or angle (23). */
387
+ objectType: 16 | 17 | 23;
388
+ /**
389
+ * Placement data for the label. For angles:
390
+ * `[vertexX, vertexY, startAngle, angle]`.
391
+ */
392
+ segments: number[][];
393
+ showLabel: boolean;
394
+ labels: string[];
395
+ labelSize: number;
396
+ labelAngle: number;
397
+ labelOrientation: LabelOrientation;
398
+ }
399
+
400
+ /**
401
+ * The arc marking an angle. `angle` is signed; `directed` is `1` for
402
+ * `directedangle`, `0` for `angle`.
403
+ */
404
+ interface AngleMarkerBranch extends GraphBranchBase<23>, GeometryStrokeFields {
405
+ segments: Array<[vertexX: number, vertexY: number, startAngle: number, angle: number, directed: 0 | 1]>;
406
+ }
407
+
408
+ interface VectorBranch extends GraphBranchBase<24>, GeometryStrokeFields {
409
+ segments: Array<[tailX: number, tailY: number, headX: number, headY: number]>;
410
+ arrowMode?: ExpressionArrowMode;
411
+ }
412
+
413
+ /** Complex numbers, plotted as points `[re, im]`. */
414
+ interface ComplexNumberBranch extends Omit<GraphBranchBase<25>, 'color'>, PointFields {
415
+ segments: Array<Array<[re: number, im: number]>>;
416
+ poi: PointPOIs;
417
+ showPoint: boolean;
418
+ }
419
+
420
+ /** Draggable complex numbers. */
421
+ interface MovableComplexNumberBranch extends Omit<GraphBranchBase<26>, 'color'>, PointFields {
422
+ segments: Array<Array<[re: number, im: number]>>;
423
+ poi: PointPOIs;
424
+ showPoint?: boolean;
425
+ movablePointInfo: MovablePointInfo[];
426
+ }
427
+
428
+ /** An image. Placement is in `dimensions`, one entry per image (for lists). */
429
+ interface ImageBranch extends GraphBranchBase<27> {
430
+ segments: [];
431
+ dimensions: {
432
+ /** Center x. */
433
+ x: number[];
434
+ /** Center y. */
435
+ y: number[];
436
+ radianAngle: number[];
437
+ width: number[];
438
+ height: number[];
439
+ opacity: number[];
440
+ };
441
+ }
442
+
443
+ /** Any branch the 2D grapher draws. Narrow on `branchMode`. */
444
+ type GraphBranch =
445
+ | XBranch
446
+ | YBranch
447
+ | PointBranch
448
+ | MovablePointBranch
449
+ | ParametricBranch
450
+ | PolarBranch
451
+ | PolygonFillBranch
452
+ | ImplicitBranch
453
+ | ErrorBranch
454
+ | SegmentBranch
455
+ | LineBranch
456
+ | RayBranch
457
+ | CircleBranch
458
+ | ArcBranch
459
+ | LabelBranch
460
+ | AngleMarkerBranch
461
+ | VectorBranch
462
+ | ComplexNumberBranch
463
+ | MovableComplexNumberBranch
464
+ | ImageBranch;
465
+
466
+ /** The branch type for a mode, e.g. `BranchOfMode<BranchModes['CIRCLE']>`. */
467
+ type BranchOfMode<M extends BranchMode> = Extract<GraphBranch, { branchMode: M }>;
468
+
469
+ /** Branches drawn as points (modes 3, 4, 25, 26). */
470
+ type PointLikeBranch = PointBranch | MovablePointBranch | ComplexNumberBranch | MovableComplexNumberBranch;
471
+
472
+ /** Branches whose points can be dragged (modes 4, 26). */
473
+ type MovableBranch = MovablePointBranch | MovableComplexNumberBranch;
474
+
475
+ // ---------------------------------------------------------------------------
476
+ // Points of interest, labels, movable points
477
+ // ---------------------------------------------------------------------------
478
+
479
+ /** A point of interest: a root, intercept, extremum, intersection or plotted point. */
480
+ interface POI {
481
+ x: number;
482
+ y: number;
483
+ type: POIType;
484
+ sketch: GraphSketch;
485
+ /** Index of the branch in `sketch.branches`. */
486
+ branch: number;
487
+ /** Index of the point within that branch. */
488
+ pointIdxOnBranch: number;
489
+ bareLabel: boolean;
490
+ /** Unique across all sketches. */
491
+ id: number;
492
+ intersects?: unknown;
493
+ /** The point's label text, or `''`. */
494
+ getLabel(): string;
495
+ getGraphMode(): BranchMode;
496
+ /** The branch's compiled function, if it has one. */
497
+ getCompiledFunction(): ((...args: number[]) => number) | undefined;
498
+ /** `true` for plotted points (`DEFINED` or `LABEL`). */
499
+ isAttachedToPlottedPoint(): boolean;
500
+ isMovable(): boolean;
501
+ /** `true` for `LABEL`: shown even when the sketch isn't selected. */
502
+ isPersistent(): boolean;
503
+ getLabelSize(): number;
504
+ getLabelRotation(): number;
505
+ getPointOpacity(): number;
506
+ getPointSize(): number;
507
+ getTextOutline(): boolean;
508
+ hasInteractiveLabel(): boolean;
509
+ hasEditableLabel(): boolean;
510
+ isBareLabel(): boolean;
511
+ getMovablePoint(): MovablePoint | undefined;
512
+ isSelected(): boolean;
513
+ }
514
+
515
+ /** A label drawn for a sketch. */
516
+ type SketchLabel =
517
+ | { type: 'poi'; poi: POI }
518
+ | {
519
+ type: 'segment' | 'polygon' | 'angle';
520
+ /** `label-<expression id>-<list index>`. */
521
+ id: string;
522
+ /** An anchor POI of type `LABEL`. */
523
+ poi: POI;
524
+ /** The label branch's placement data. */
525
+ segments: number[];
526
+ text: string;
527
+ };
528
+
529
+ /** A draggable point, from `sketch.getMovablePoints()`. */
530
+ interface MovablePoint {
531
+ type: 'movable-point';
532
+ /** `movable:[<expression id>,<index>]`. */
533
+ id: string;
534
+ listIndex: number;
535
+ sketch: GraphSketch;
536
+ x: number;
537
+ y: number;
538
+ color: HexColor;
539
+ pointOpacity: number | number[];
540
+ pointSize: number | number[];
541
+ pointStyle: PointStyle;
542
+ /** For table points: where the point lives and how it can be dragged. */
543
+ tableInfo?: { tableId: ExpressionId; columnId: ExpressionId; rowIndex: number; dragX: boolean; dragY: boolean };
544
+ /** Image scaling handles: the scale factor this point controls. */
545
+ scaleFactor?: [number, number];
546
+ label?: string;
547
+ ariaLabel?: string;
548
+ }
549
+
550
+ /** A labeled static point, from `sketch.getStaticLabeledPoints()`. */
551
+ interface StaticLabeledPoint {
552
+ type: 'static-labeled-point';
553
+ /** `static[<expression id>,<POI id>]`. */
554
+ id: string;
555
+ listIndex: number;
556
+ sketch: GraphSketch;
557
+ x: number;
558
+ y: number;
559
+ label: string;
560
+ ariaLabel?: string;
561
+ }
562
+
563
+ // ---------------------------------------------------------------------------
564
+ // Sketch
565
+ // ---------------------------------------------------------------------------
566
+
567
+ /** Everything the 2D grapher draws for one expression. */
568
+ interface GraphSketch {
569
+ /** The expression id. */
570
+ id: ExpressionId;
571
+ branches: GraphBranch[];
572
+ is3d: false;
573
+ /** Copied from the first branch. `'#000000'` when that branch is an error. */
574
+ color: HexColor | HexColor[];
575
+ /** Copied from the first branch; `'normal'` when it has no style. */
576
+ style: LineStyle | PointStyle | 'normal';
577
+ /** Show points of interest (set while selected, if tracing is enabled). */
578
+ showPOI: boolean;
579
+ showHighlight: boolean;
580
+ /** Draw above other sketches. */
581
+ hoistToTop: boolean;
582
+ selected: boolean;
583
+ tokenHovered: boolean;
584
+ tokenSelected: boolean;
585
+ labels: SketchLabel[];
586
+ /** Cache behind `getPOI()`. */
587
+ __cachedPOI: POI[];
588
+ /** Cache behind `getPOIById()`. */
589
+ __cachedPOIIds: Record<number, POI>;
590
+ __cachedMovablePoints?: MovablePoint[];
591
+ __cachedStaticLabeledPoints?: StaticLabeledPoint[];
592
+
593
+ /**
594
+ * All points of interest, cached. `X`/`Y` branches contribute zeros,
595
+ * intercepts, extrema and intersections; point branches contribute their
596
+ * points (`LABEL` if labeled, else `DEFINED`). Other modes contribute none.
597
+ */
598
+ getPOI(): POI[];
599
+ /** Points of interest of one branch. */
600
+ getBranchPOI(branchIndex: number): POI[];
601
+ getPOIById(id: number): POI | undefined;
602
+ getImageBranch(): ImageBranch | undefined;
603
+ getMovablePointsBranch(): MovableBranch | undefined;
604
+ getMovablePoints(): MovablePoint[];
605
+ getMovablePointByIndex(index: number): MovablePoint | undefined;
606
+ /** Points with a visible label (point and complex-number sketches). */
607
+ getStaticLabeledPoints(): StaticLabeledPoint[];
608
+ /** Set `poi.intersections` on each branch (indexed like `branches`) and rebuild the POI cache. */
609
+ updateIntersections(intersections: Array<POICoordinates | undefined>): void;
610
+ /** Carry selection and highlight state over from the sketch this one replaces. */
611
+ updateFrom(previous: GraphSketch | undefined): void;
612
+ _pushPOI(coordinates: POICoordinates, branchIndex: number, type: POIType, bareLabel?: boolean): void;
613
+ }
614
+
615
+ /**
616
+ * The sketch members of the 2D grapher (merged into the `Grapher2D`
617
+ * declared in controller.d.ts, which checks them against the generated type).
618
+ */
619
+ interface Grapher2D {
620
+ /** One sketch per graphed expression, keyed by expression id. */
621
+ graphSketches: Record<ExpressionId, GraphSketch>;
622
+ getGraphSketch(id: ExpressionId): GraphSketch | undefined;
623
+ addGraphSketch(sketch: GraphSketch): void;
624
+ removeGraphSketch(id: ExpressionId): void;
625
+ /** Replace an expression's sketch with one built from `branches`, keeping its selection state. */
626
+ updateSketch(id: ExpressionId, branches: GraphBranch[]): void;
627
+ selectSketch(id: ExpressionId): void;
628
+ deselectSketch(id: ExpressionId): void;
629
+ setSketchHoistedToTop(id: ExpressionId, hoisted: boolean): void;
630
+ }
631
+ }
@@ -17,6 +17,7 @@
17
17
  /// <reference path="./list-model.d.ts" />
18
18
  /// <reference path="./actions.d.ts" />
19
19
  /// <reference path="./dispatcher.d.ts" />
20
+ /// <reference path="./graph-sketches.d.ts" />
20
21
  /// <reference path="./controller.d.ts" />
21
22
  /// <reference path="./sub-controllers.d.ts" />
22
23
  /// <reference path="./dcgview.d.ts" />
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@spidunno/desmos-types",
3
- "version": "1.13.2",
3
+ "version": "1.13.3",
4
4
  "description": "TypeScript type definitions for the Desmos API v1.13",
5
5
  "types": "index.d.ts",
6
6
  "publishConfig": {
@@ -21,7 +21,8 @@
21
21
  ],
22
22
  "scripts": {
23
23
  "test": "tsc -p tsconfig.json && tsc -p tsconfig.internals.json",
24
- "generate:internals": "node scripts/extract-internals.cjs"
24
+ "generate:internals": "node scripts/extract-internals.cjs",
25
+ "snapshot:sketches": "node scripts/snapshot-sketches.cjs"
25
26
  },
26
27
  "keywords": [
27
28
  "desmos",