@spidunno/desmos-types 1.13.3 → 1.13.5

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.3
9
+ npm install --save-dev @spidunno/desmos-types@~1.13.5
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.3`), not npm's default caret (`^`), so you only
13
+ are fixes to the types. Use a tilde range (`~1.13.5`), not npm's default caret (`^`), so you only
14
14
  get type fixes for the API version you load.
15
15
 
16
16
  ## Usage
@@ -53,6 +53,28 @@ the API only exists as the global that `calculator.js` creates.
53
53
  import type { GraphingCalculator, GraphState } from '@spidunno/desmos-types';
54
54
  ```
55
55
 
56
+ ### Without a global
57
+
58
+ Importing from `@spidunno/desmos-types` (or `/internals`) still declares the global `Desmos`, so
59
+ code that uses the global type-checks even when the program never loaded `calculator.js` as a
60
+ script. If you load the API some other way, for example into a scope of your own so that
61
+ `window.Desmos` never exists, use the module-only entry points instead. They declare the same
62
+ types, but nothing global:
63
+
64
+ ```ts
65
+ import type * as Desmos from '@spidunno/desmos-types/module'; // or '/module/internals'
66
+
67
+ async function loadDesmos(): Promise<typeof Desmos> {
68
+ /* ... */
69
+ }
70
+
71
+ const api = await loadDesmos();
72
+ const calculator: Desmos.GraphingCalculator = api.GraphingCalculator(element);
73
+ ```
74
+
75
+ Don't also include the default entry points (in `compilerOptions.types` or a `/// <reference>`), or
76
+ the global comes back.
77
+
56
78
  ## Layout
57
79
 
58
80
  | File | Contents |
@@ -75,6 +97,7 @@ import type { GraphingCalculator, GraphState } from '@spidunno/desmos-types';
75
97
  | `types/mathquill.d.ts` | The bundled MathQuill fork |
76
98
  | `types/desmos.d.ts` | `enabledFeatures`, `supportedLanguages`, `imageFileToDataURL`, `version`, `Window.Desmos` |
77
99
  | `internals/` | Opt-in internals (see [Internals](#internals)); `internals/generated/` is generated |
100
+ | `module/` | Module-only copies of `index.d.ts` and `internals/index.d.ts` (see [Without a global](#without-a-global)), built by `npm run build:module` |
78
101
  | `scripts/extract-internals.cjs` | Regenerates `internals/generated/` from a bundle |
79
102
 
80
103
  ## Sources and conventions
@@ -134,16 +157,28 @@ Everything here is internal to Desmos and changes between builds, even within v1
134
157
 
135
158
  | Layer | Files | Source |
136
159
  | --- | --- | --- |
137
- | Generated | `internals/generated/objects.d.ts` | The bundle loaded in jsdom; 58 internal objects walked |
160
+ | Generated | `internals/generated/objects.d.ts` | The bundle loaded in jsdom; 60 internal objects walked |
138
161
  | Generated | `internals/generated/actions.d.ts` | Every `dispatch({ type })` call site and `switch (action.type)` reducer, found with acorn. Each of the 341 actions is attributed to the reducer(s) that handle it, giving three unions: `Action` (graph controller), `MathFieldAction` and `BasicCalculatorAction` |
139
162
  | Generated | `internals/generated/views.d.ts` | Props and instance members of the 13 `Private.Fragile` views, from live instances (about 1,400 views rendered), call sites and prop reads, following `{...props}` forwarding into inner views |
140
163
  | Hand-written | `internals/*.d.ts` | Precise types for the parts mods use, checked against the bundle source |
141
164
 
142
165
  In the generated layer, property types come from observed values. A method's return type comes from
143
- static analysis of its source (nothing returned → `void`, only booleans returned → `boolean`), or from
144
- calling side-effect-free getters such as `get*` and `is*`. Anything that couldn't be determined is
145
- `unknown`, and parameters are `unknown` because the bundle is minified. Action payload field names are
146
- reliable, but their value types are often inferred from the field name.
166
+ calling side-effect-free getters such as `get*` and `is*`, or from what its source returns: literals,
167
+ operators, object literals, `this.x` (typed as `this["x"]`, so refinements of `x` carry over), and
168
+ calls to other methods and bundle functions, whose return types are inferred the same way. A return
169
+ type stays `unknown` if any returned value can't be typed. Anything that couldn't be determined is
170
+ `unknown`. Action payload field names are reliable, but their value types are often inferred from the
171
+ field name.
172
+
173
+ The bundle is minified, so parameter names are recovered from how each method uses them:
174
+ `this.x = p` and `{ x: p }` name it `x`, `dispatch({ type, x: p })` also copies the action field's
175
+ type, and passing `p` to another method or bundle function (`this.getItemModel(p)`) reuses that
176
+ function's inferred name and type. Defaults, arithmetic, exhaustive `switch`es and `.type`
177
+ comparisons give types (`id: string`, `index: number`, `'selected' | 'tentatively-selected'`, item
178
+ models). A parameter is optional if it has a default, is checked against `undefined`, or some call
179
+ in the bundle leaves it out. What can't be recovered stays `argN: unknown`. A property is optional if it
180
+ held `undefined` or was added after the calculator loaded (for example, by the first animation frame
181
+ or a UI interaction).
147
182
 
148
183
  The hand-written interfaces *extend* the generated ones (`Internals.Controller extends
149
184
  Generated.Controller`, and so on). TypeScript therefore checks every hand-written type against what
@@ -166,6 +201,10 @@ What's hand-typed:
166
201
  interest (`POI`, `POITypes`), sketch labels, movable points and the grapher's sketch methods.
167
202
  A fixture of 60 real sketches (`test/fixtures/graph-sketches.ts`) is type-checked against
168
203
  these types.
204
+ - **The rest of `grapher2d`:** the projection (math ↔ pixel conversion, with linear and log axes),
205
+ `Viewport`, the viewport controller (jump, animate, zoom, pan), `GrapherSettings` (every graph
206
+ and drawing setting, with typed `observe` / `getProperty` / `setProperty`), the `'redraw'`
207
+ event, draw layers, graph images, screenshots and grapher state.
169
208
  - **Dispatcher:** `register`, `unregister`, `waitFor`, generic over the action type.
170
209
  - **Other controllers:** each math field (`mathField.controller`) and each basic calculator
171
210
  (`calculator.controller`) has its own controller and dispatcher. Keystrokes in a math field are
@@ -291,6 +330,39 @@ sketches['1']?.getPOI().filter((poi) => poi.type === 1004).map((poi) => [poi.x,
291
330
  sketches['1']?.getMovablePoints().map((p) => ({ x: p.x, y: p.y, row: p.tableInfo?.rowIndex }));
292
331
  ```
293
332
 
333
+ ### Projection, viewport and settings
334
+
335
+ `grapher2d.getProjection()` converts between math coordinates and pixels (CSS pixels from the
336
+ graph paper's top-left, y down). The projection is replaced whenever you pan, zoom or resize, so
337
+ get a fresh one each time instead of keeping it.
338
+
339
+ ```js
340
+ const g = Calc.controller.grapher2d;
341
+
342
+ // Math ↔ pixels
343
+ const p = g.getProjection();
344
+ p.map_pt({ x: 0, y: 0 }); // where the origin is on screen
345
+ p.reverse_map_pt({ x: 100, y: 100 }); // the math point under pixel (100, 100)
346
+ p.mathToPixels.dangerouslyGetXScaleFactor(); // pixels per unit (throws on a log axis)
347
+
348
+ // The viewport
349
+ g.getCurrentViewport(); // { xmin, xmax, ymin, ymax }
350
+ g.viewportController.animateToViewport({ xmin: -5, xmax: 5, ymin: -5, ymax: 5 });
351
+ g.viewportController.zoom('in'); // 'in' | 'out' | 'square' | 'default'
352
+
353
+ // Settings: graph settings plus drawing settings like labelSize and graphLineWidth
354
+ g.settings.observe('showGrid.myMod', (name, settings) => console.log(name, settings.showGrid));
355
+ g.settings.setProperty('showGrid', false);
356
+ g.settings.unobserve('.myMod'); // remove every observer in the myMod namespace
357
+
358
+ // Run code after each redraw (the callback gets the redraw time in ms)
359
+ g.events.observeEvent('redraw.myMod', (event, ms) => console.log(`redrew in ${ms}ms`));
360
+ g.events.unobserveEvent('.myMod');
361
+ ```
362
+
363
+ Moving the viewport this way doesn't add an undo step. Call
364
+ `g.debounceUserRequestedViewportChange()` afterwards if you want one.
365
+
294
366
  ### Regenerating for a new bundle
295
367
 
296
368
  ```sh