@pie-players/pie-calculator-cortex 0.3.68
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/LICENSE.md +14 -0
- package/README.md +256 -0
- package/dist/assets/evaluation-worker-BI6KdSur.js +115523 -0
- package/dist/chunks/runtime-BiXEoJDs.js +163543 -0
- package/dist/chunks/settings-C0zxv5EL.js +389 -0
- package/dist/chunks/src-D05hiMPJ.js +31307 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +63 -0
- package/dist/src/CalculatorView.svelte.d.ts +1 -0
- package/dist/src/GraphView.svelte.d.ts +1 -0
- package/dist/src/Icon.svelte.d.ts +1 -0
- package/dist/src/Keypad.svelte.d.ts +1 -0
- package/dist/src/MathFieldInput.svelte.d.ts +1 -0
- package/dist/src/calculator-controller.d.ts +65 -0
- package/dist/src/cortex-provider.d.ts +18 -0
- package/dist/src/errors.d.ts +10 -0
- package/dist/src/evaluation-client.d.ts +26 -0
- package/dist/src/evaluation-engine.d.ts +9 -0
- package/dist/src/evaluation-worker.d.ts +1 -0
- package/dist/src/function-policy.d.ts +15 -0
- package/dist/src/icons.d.ts +33 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/keypad-layouts.d.ts +70 -0
- package/dist/src/localization.d.ts +35 -0
- package/dist/src/mathlive-runtime.d.ts +17 -0
- package/dist/src/runtime.d.ts +5 -0
- package/dist/src/settings.d.ts +29 -0
- package/dist/src/state-codec.d.ts +10 -0
- package/dist/src/types.d.ts +157 -0
- package/dist/src/worker-protocol.d.ts +58 -0
- package/package.json +74 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# License and third-party notices
|
|
2
|
+
|
|
3
|
+
`@pie-players/pie-calculator-cortex` is distributed under the MIT license, as
|
|
4
|
+
declared in its package manifest and the PIE Players repository.
|
|
5
|
+
|
|
6
|
+
The built package includes these open-source dependencies. Exact versions are
|
|
7
|
+
recorded in `package.json` and the repository lockfile.
|
|
8
|
+
|
|
9
|
+
- MathLive — MIT
|
|
10
|
+
- CortexJS Compute Engine — MIT
|
|
11
|
+
- JSXGraph — MIT or LGPL-3.0-or-later
|
|
12
|
+
|
|
13
|
+
The upstream packages carry their full license texts. Distribution review must
|
|
14
|
+
confirm these identifiers against the exact locked versions before release.
|
package/README.md
ADDED
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# `@pie-players/pie-calculator-cortex`
|
|
2
|
+
|
|
3
|
+
A fully bundled, open-source basic, scientific, and graphing calculator
|
|
4
|
+
implementation for PIE Players. It implements the provider-neutral contracts
|
|
5
|
+
from `@pie-players/pie-calculator` using MathLive, Cortex Compute Engine, and
|
|
6
|
+
JSXGraph.
|
|
7
|
+
|
|
8
|
+
```ts
|
|
9
|
+
import { CortexCalculatorProvider } from "@pie-players/pie-calculator-cortex";
|
|
10
|
+
|
|
11
|
+
const provider = new CortexCalculatorProvider();
|
|
12
|
+
await provider.initialize();
|
|
13
|
+
const calculator = await provider.createCalculator(
|
|
14
|
+
"scientific",
|
|
15
|
+
document.querySelector("#calculator")!,
|
|
16
|
+
{
|
|
17
|
+
locale: "nl-NL",
|
|
18
|
+
theme: "auto",
|
|
19
|
+
},
|
|
20
|
+
);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The package bundles all runtime code and required assets. It does not require
|
|
24
|
+
an API key, CDN, or network connection.
|
|
25
|
+
|
|
26
|
+
`initialize()` takes `CortexCalculatorProviderInit`, narrowed to `onTelemetry`
|
|
27
|
+
for that reason -- there is no credential to supply. `createCalculator()` takes
|
|
28
|
+
`CortexCalculatorProviderConfig`, which is the provider-neutral configuration
|
|
29
|
+
with `settings` typed as `CortexCalculatorSettings`.
|
|
30
|
+
|
|
31
|
+
## Isolated demos
|
|
32
|
+
|
|
33
|
+
Run `bun run --cwd packages/calculator-cortex demo`, then open the basic,
|
|
34
|
+
scientific, or graphing page from the mode navigation. Each page mounts one
|
|
35
|
+
calculator directly through `CortexCalculatorProvider`; it does not load an
|
|
36
|
+
assessment player, toolkit coordinator, or tool wrapper.
|
|
37
|
+
|
|
38
|
+
The demo controls switch interface language, theme, and text direction by
|
|
39
|
+
destroying and recreating only that calculator instance. **Panel size** does not
|
|
40
|
+
recreate anything — it resizes the container to the box the tool shell actually
|
|
41
|
+
gives the calculator. Check every change at both sizes it offers: *Shipped tool
|
|
42
|
+
panel* is what the panel opens at for that type, *Panel minimum* is its configured
|
|
43
|
+
resize floor, and the package's size-dependent rules are container queries on width
|
|
44
|
+
and density tiers on height, so a fluid demo at 1280px reaches neither.
|
|
45
|
+
|
|
46
|
+
## Localization
|
|
47
|
+
|
|
48
|
+
The package ships complete English (`en-US`) and Dutch (`nl-NL`) interface
|
|
49
|
+
catalogs. Locale matching is by primary language, so `nl`, `nl-NL`, and
|
|
50
|
+
`nl-BE` select Dutch. Other locales fall back to English while still configuring
|
|
51
|
+
MathLive, decimal input, locale-aware graph numbers, the decimal separator in a
|
|
52
|
+
displayed answer, and writing direction.
|
|
53
|
+
|
|
54
|
+
One resolver serves the mathfield, the keypad's separator key and the displayed
|
|
55
|
+
answer, so an `nl-NL` calculator whose keypad writes `1,5` answers `1,5`. The
|
|
56
|
+
locale reaches the display only: `getResult`, the history entries a host reads and
|
|
57
|
+
the serialized state stay `.`-separated, so state saved under one locale is not
|
|
58
|
+
reinterpreted under another. It is a separator swap rather than a reformat, which
|
|
59
|
+
is what keeps `displayPrecision` and an exponential answer like `2.432902008e+18`
|
|
60
|
+
intact.
|
|
61
|
+
|
|
62
|
+
Every package-owned visible string, accessible name, status, and recoverable
|
|
63
|
+
error can be replaced with typed per-instance messages:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
await provider.createCalculator("basic", container, {
|
|
67
|
+
locale: "cy-GB",
|
|
68
|
+
settings: {
|
|
69
|
+
messages: {
|
|
70
|
+
basicCalculator: "Cyfrifiannell sylfaenol",
|
|
71
|
+
calculate: "Cyfrifo",
|
|
72
|
+
clear: "Clirio",
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Unspecified messages fall back to the selected built-in catalog, then English.
|
|
79
|
+
Message templates retain their named placeholders, such as `{index}`,
|
|
80
|
+
`{lineStyle}`, and `{result}`. `settings.direction` defaults to `"auto"`, which
|
|
81
|
+
derives `ltr` or `rtl` from the locale; a host may explicitly set `"ltr"` or
|
|
82
|
+
`"rtl"` when its language policy requires it.
|
|
83
|
+
|
|
84
|
+
## Keypad
|
|
85
|
+
|
|
86
|
+
Basic and scientific render a display and a keypad; graphing puts the keypad in its
|
|
87
|
+
expression rail. The keypad is this package's own — real `<button>` elements with
|
|
88
|
+
localized accessible names, one tab stop with arrow-key movement inside it, and PIE
|
|
89
|
+
tokens throughout.
|
|
90
|
+
|
|
91
|
+
It is deliberately not MathLive's virtual keyboard, which is switched off entirely
|
|
92
|
+
(`mathVirtualKeyboardPolicy = "manual"`) rather than merely hidden. MathLive's is a
|
|
93
|
+
viewport-fixed singleton whose keycaps are `div[tabindex="-1"]` with no `role` and
|
|
94
|
+
whose toggle is a `div[role="button"]` with no `tabindex`, so it contains no
|
|
95
|
+
focusable elements at all and cannot be opened or operated by keyboard or switch
|
|
96
|
+
access; under `"auto"` it also auto-shows on any touch-capable device, dropping
|
|
97
|
+
itself across the bottom of the assessment rather than inside the tool panel. Its
|
|
98
|
+
`container` setter throws inside an iframe, which is how assessments are commonly
|
|
99
|
+
delivered.
|
|
100
|
+
|
|
101
|
+
Keys are gated on `settings.allowedFunctions`, so a host that narrows the set gets a
|
|
102
|
+
keypad that cannot offer a key the validator would reject. Basic omits the constants
|
|
103
|
+
outright, matching `validateSymbol`. Scientific and graphing put their function keys
|
|
104
|
+
on a second layer rather than in extra rows: a row costs about 50px of panel height
|
|
105
|
+
at every size that ships, and eight rows in one layer puts the keypad past the
|
|
106
|
+
panel's 480px floor. Four rows is the budget; the graphing layer spends five because
|
|
107
|
+
it carries the graph keys too. The e2e suite switches to every layer and measures it
|
|
108
|
+
at both the size the panel opens at and its resize floor.
|
|
109
|
+
|
|
110
|
+
The commit key is on every layer, in the same corner. On the numeric layer alone it
|
|
111
|
+
was unreachable from the function keys — Enter still committed, but a pointer or
|
|
112
|
+
switch-access user has no Enter.
|
|
113
|
+
|
|
114
|
+
Every key inserts a template with at most one placeholder. A second is
|
|
115
|
+
unreachable: `ArrowRight` leaves a subscript or a fraction rather than crossing to
|
|
116
|
+
the next placeholder, and MathLive binds `moveToNextPlaceholder` to Tab, which this
|
|
117
|
+
keypad spends on being a single tab stop. `nth-root` and `fraction` therefore use
|
|
118
|
+
`#@` to take the expression already typed as their second operand, and `log-base-n`
|
|
119
|
+
fills its base and lets the argument follow the subscript.
|
|
120
|
+
|
|
121
|
+
Layouts live as data in `src/keypad-layouts.ts`. Adding a key needs a message key in
|
|
122
|
+
both catalogs — `as const satisfies CortexCalculatorMessages` makes that a
|
|
123
|
+
compile-time obligation. Where a key's visible label is a word, its accessible name
|
|
124
|
+
must contain that word (WCAG 2.5.3, and what voice control speaks): `keySine` is
|
|
125
|
+
`"sin, sine"`, not `"sine of"`.
|
|
126
|
+
|
|
127
|
+
## Fitting the panel
|
|
128
|
+
|
|
129
|
+
The panel is two surfaces with no card between them: a screen and a console, each
|
|
130
|
+
running to its edges. The screen holds the tape, the live expression and the answer,
|
|
131
|
+
with the angle mode pinned above its scroller so history passes behind it; the
|
|
132
|
+
console is the keypad's recessed plane, carrying the layer tabs and the backspace and
|
|
133
|
+
clear icons above the grid — inline SVG in `currentColor`, because `⌫` is the face a
|
|
134
|
+
backspace button wants and the code point least likely to be in a host's font stack. Nothing sits on bare card, and the type's name is not drawn — the
|
|
135
|
+
tool shell's header already carries it, and a second copy cost 46px of a 500px panel.
|
|
136
|
+
It stays as visually-hidden text for the document outline. `--cortex-tape-inset` and
|
|
137
|
+
the keypad's inline padding are one value, so the mathfield's text and the first key
|
|
138
|
+
column share a left edge.
|
|
139
|
+
|
|
140
|
+
A tool panel is resizable, so the height available is a runtime fact and every fixed
|
|
141
|
+
size in the tool answers to it. `CalculatorView.svelte` measures its own box with a
|
|
142
|
+
`ResizeObserver` and stamps `data-pie-density` — `comfortable` at 400px of content
|
|
143
|
+
and up, `compact` to 320, `tight` below — and the metrics live as tokens that each
|
|
144
|
+
tier re-declares in one place: key and control target sizes, the display's floor,
|
|
145
|
+
the result's type size and the board's floor. A `ResizeObserver` rather than a
|
|
146
|
+
`container-type: size` query, which carries `contain: layout` and would make the
|
|
147
|
+
calculator the containing block for every fixed-position descendant, MathLive's
|
|
148
|
+
popovers among them.
|
|
149
|
+
|
|
150
|
+
Keys hold the 44px of WCAG 2.5.5 at every size a panel opens at, which is what the
|
|
151
|
+
tiers are measured against: basic needs 398px of content and scientific 385px, and
|
|
152
|
+
both open at more. Below that, keys give up height before the keypad gives up rows —
|
|
153
|
+
a row scrolled out of the panel costs a pointer or switch-access learner the key
|
|
154
|
+
entirely — and the smallest tier is 28px, clear of 2.5.8's 24px floor at Level AA.
|
|
155
|
+
|
|
156
|
+
Nothing is ever clipped. The calculator root scrolls its own content as the floor
|
|
157
|
+
case; it cannot be left to the tool shell, because the wrapper pins the calculator to
|
|
158
|
+
`height: 100% !important` inside an `overflow: hidden` box, so the shell's
|
|
159
|
+
`overflow-y: auto` never sees anything to scroll. Above that floor the graphing view
|
|
160
|
+
places the pressure deliberately: stacked, the two panels hold their content and the
|
|
161
|
+
calculator takes one scroll; side by side they scroll in their own columns instead,
|
|
162
|
+
so a readout does not push the plot off the panel. Flex shrinking is what makes this
|
|
163
|
+
load-bearing — an item shrunk below its content paints outside its box rather than
|
|
164
|
+
clipping, which is how keypad rows were drawn over the graph controls.
|
|
165
|
+
|
|
166
|
+
## Theming
|
|
167
|
+
|
|
168
|
+
`theme: "light" | "dark" | "auto"` supplies accessible package defaults.
|
|
169
|
+
`"auto"` follows `prefers-color-scheme`.
|
|
170
|
+
|
|
171
|
+
Those defaults are **fallbacks**, not declarations. Every colour resolves as
|
|
172
|
+
`var(--pie-x, var(--cortex-x))`, so a host's tokens reach the tool and the
|
|
173
|
+
package's own values apply only where the host has none. This matters beyond
|
|
174
|
+
looks: `@pie-players/pie-theme` publishes ten `[data-color-scheme]` PNP palettes
|
|
175
|
+
and marks every token used here as `required`, and declaring `--pie-*` on the
|
|
176
|
+
calculator element — as this package once did — wins over anything an ancestor
|
|
177
|
+
sets, so a learner's colour-scheme accommodation stopped at the calculator's edge.
|
|
178
|
+
`tests/calculator-cortex-style-contract.test.ts` fails if such a declaration
|
|
179
|
+
returns.
|
|
180
|
+
|
|
181
|
+
Consumed: `--pie-text`, `--pie-white`, `--pie-background-dark`, `--pie-border`,
|
|
182
|
+
`--pie-border-gray`, `--pie-blue-grey-300`, `--pie-button-bg`,
|
|
183
|
+
`--pie-button-color`, `--pie-button-hover-bg`, `--pie-button-active-bg`,
|
|
184
|
+
`--pie-button-focus-outline`, `--pie-primary`, `--pie-primary-dark`,
|
|
185
|
+
`--pie-incorrect`, `--pie-incorrect-secondary`, and `--pie-content-emphasis`.
|
|
186
|
+
|
|
187
|
+
`--pie-background` is deliberately **not** among them. It is the page token, which
|
|
188
|
+
a host may point at its own backdrop or at a translucent value, and a calculator
|
|
189
|
+
resolving its fill through it would take every contrast guarantee out of this
|
|
190
|
+
package's hands. Surfaces take `--pie-white` for the card and
|
|
191
|
+
`--pie-background-dark` for the recessed keypad plane, both opaque in the base
|
|
192
|
+
themes and in all ten schemes. A host wanting different surfaces has package
|
|
193
|
+
hooks: `--pie-calculator-surface` and `--pie-calculator-surface-raised`.
|
|
194
|
+
Both are package-private rather than registered host tokens: read as
|
|
195
|
+
`var(--x, fallback)` and so overridable, with no compatibility guarantee.
|
|
196
|
+
|
|
197
|
+
`--pie-font-scale` is **not** consumed, matching the recorded decision in
|
|
198
|
+
`section-player/tests/content-text-follows-font-scale.test.ts`: the font
|
|
199
|
+
accommodation applies to what the learner reads, and a keypad growing with the
|
|
200
|
+
passage is a layout problem rather than an accommodation.
|
|
201
|
+
|
|
202
|
+
Graph colors have package-owned hooks because no canonical series palette
|
|
203
|
+
exists: `--pie-calculator-series-1`, `--pie-calculator-series-2`,
|
|
204
|
+
`--pie-calculator-series-3`, `--pie-calculator-series-4`,
|
|
205
|
+
`--pie-calculator-series-5`, and `--pie-calculator-series-6`. Each series also
|
|
206
|
+
has a solid, dashed, or dotted line style; hosts overriding colors must retain
|
|
207
|
+
3:1 contrast against the graph surface and keep the palette distinguishable.
|
|
208
|
+
|
|
209
|
+
The plot's axes, tick labels and grid are themed from the resolved tokens and
|
|
210
|
+
re-applied when `theme: "auto"` follows the OS across a change. They have to be:
|
|
211
|
+
JSXGraph initialised with bare `axis: true` / `grid: true` uses its light defaults
|
|
212
|
+
in every theme, which put black tick labels on a dark plot at 1.43:1. The plot div
|
|
213
|
+
is `aria-hidden`, so axe never sees inside it — the contrast is asserted directly
|
|
214
|
+
in `e2e/calculator-cortex.spec.ts` instead, tick labels at 4.5:1 as text and axes
|
|
215
|
+
at 3:1 as a graphical object.
|
|
216
|
+
|
|
217
|
+
## Coverage
|
|
218
|
+
|
|
219
|
+
Feature coverage rests on three suites with different jobs.
|
|
220
|
+
|
|
221
|
+
`tests/calculator-cortex-keypad-coverage.test.ts` is the self-maintaining one:
|
|
222
|
+
every shipped keypad key must map to an expression proven to validate and
|
|
223
|
+
evaluate. A key with no entry fails, and an entry naming a retired key fails.
|
|
224
|
+
Implicit multiplication, parenthesised groups and the inverse-trigonometric keys
|
|
225
|
+
were all refused by the expression policy until this test reached them.
|
|
226
|
+
|
|
227
|
+
`tests/calculator-cortex-scenarios.test.ts` pins values, traced from the PRD's
|
|
228
|
+
capability spec: precedence, boundary values, display thresholds, the domain
|
|
229
|
+
edges of every function, and the refusals each mode owes. Its LaTeX entry shapes
|
|
230
|
+
are derived from the public corner-case corpora in `mathquill` and Doenet's
|
|
231
|
+
`math-expressions`, which test their own parsers — the shapes carry over, the
|
|
232
|
+
expectations do not.
|
|
233
|
+
|
|
234
|
+
`tests/calculator-cortex-corpus.test.ts` covers volume, and asserts properties
|
|
235
|
+
rather than values, because a fixture of individual expectations at corpus size
|
|
236
|
+
fails in ways nobody can act on. The corpus is GSM8K's inline calculator
|
|
237
|
+
annotations — `<<48/2=24>>`, expression/result pairs authored to be executed by a
|
|
238
|
+
calculator — over `0-9 + - * / . ( )` alone, which is exactly basic mode's
|
|
239
|
+
capability set. Four properties hold: every outcome is a declared error code or an
|
|
240
|
+
answer, never an undeclared throw; every answer matches its authored result
|
|
241
|
+
numerically, since the annotations carry their author's currency formatting;
|
|
242
|
+
capability sets nest, so what basic accepts scientific and graphing accept
|
|
243
|
+
identically; and a displayed answer re-entered answers itself. Only the second
|
|
244
|
+
uses the labels — the rest would hold against any corpus.
|
|
245
|
+
|
|
246
|
+
300 entries are committed under `tests/fixtures/`, chosen by a deterministic
|
|
247
|
+
stride so regenerating produces no diff. For the full 10770:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
bun run test:corpus
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
Playwright covers what no unit test can reach: what MathLive builds from real
|
|
254
|
+
keystrokes. Those tests assert only the answer, because turning `/` into a
|
|
255
|
+
fraction is MathLive's behaviour, while the LaTeX it hands to `validateExpression`
|
|
256
|
+
is this package's seam — and the two have disagreed, `2x` and `(4+5)` among them.
|