@pie-players/pie-section-player 0.3.72 → 0.3.74
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 +198 -37
- package/dist/browser/assets/evaluation-worker-DkU_wGh3.js +155241 -0
- package/dist/browser/chunks/ItemToolBar-wr2myaah-2ce4b643.js +1 -0
- package/dist/browser/chunks/PUA-tLuTiQ7--f2b27953.js +1 -0
- package/dist/browser/chunks/ToolCoordinator-cc2dc319.js +1 -0
- package/dist/browser/chunks/accents-BTUYmhn9-cafeb96e.js +1 -0
- package/dist/browser/chunks/accents-b-i-CngHZsLL-e0eb98fd.js +1 -0
- package/dist/browser/chunks/arabic-BzEHMVZD-30ac1ade.js +1 -0
- package/dist/browser/chunks/arrows-VjxlU-jv-2e17c192.js +1 -0
- package/dist/browser/chunks/base-dfd67c41.js +1 -0
- package/dist/browser/chunks/braille-BeWC_Ruq-a3bb8ef9.js +1 -0
- package/dist/browser/chunks/braille-d-Dk6J96GO-d832bfbf.js +1 -0
- package/dist/browser/chunks/browser-a3c32178.js +36 -0
- package/dist/browser/chunks/calculator-element-271c142f.js +9 -0
- package/dist/browser/chunks/calligraphic-Cew9cU3x-04cf0735.js +1 -0
- package/dist/browser/chunks/cherokee-Cny3FYho-4da7d2f3.js +1 -0
- package/dist/browser/chunks/classPrivateFieldGet2-338e0179.js +1 -0
- package/dist/browser/chunks/custom-element-define-2a92deb0.js +1 -0
- package/dist/browser/chunks/cyrillic-CfCDulXU-5550df0b.js +1 -0
- package/dist/browser/chunks/cyrillic-ss-lU7bNGG9-12eb0188.js +1 -0
- package/dist/browser/chunks/defineProperty-a20a667d.js +1 -0
- package/dist/browser/chunks/devanagari-CDIz2h-r-18c38725.js +1 -0
- package/dist/browser/chunks/dist-41b39e7f.js +1 -0
- package/dist/browser/chunks/dist-59132a53.js +1 -0
- package/dist/browser/chunks/dist-60d7afef.js +1 -0
- package/dist/browser/chunks/dist-ca9b9622.js +1 -0
- package/dist/browser/chunks/double-struck-BpJEQk8y-500ce8dd.js +1 -0
- package/dist/browser/chunks/en-5ff22e17.js +1 -0
- package/dist/browser/chunks/es-a0ba6cb6.js +1 -0
- package/dist/browser/chunks/focus-trap-44913bf3.js +1 -0
- package/dist/browser/chunks/fraktur-rLEq9DEH-44cc14d8.js +1 -0
- package/dist/browser/chunks/greek-BlraJTyL-90ce8924.js +1 -0
- package/dist/browser/chunks/greek-ss-D-EN2PK0-91610739.js +1 -0
- package/dist/browser/chunks/hebrew-GiQZeybp-b583f555.js +1 -0
- package/dist/browser/chunks/latin-b-BhEnC7R2-d13e06ff.js +1 -0
- package/dist/browser/chunks/latin-bi-DqiIKv3U-1dec8705.js +1 -0
- package/dist/browser/chunks/latin-i-B1xtwaE1-21637466.js +1 -0
- package/dist/browser/chunks/latin-xfWFlLkD-5bcea5cf.js +1 -0
- package/dist/browser/chunks/logger-8b07fb72.js +1 -0
- package/dist/browser/chunks/marrows-DD1NgMQi-15b63755.js +1 -0
- package/dist/browser/chunks/math-DpWn1mbG-38eeb914.js +1 -0
- package/dist/browser/chunks/math-rendering-ready-9a0fd90a.js +1 -0
- package/dist/browser/chunks/mathjax-D2JHb_R_-64780dc5.js +232 -0
- package/dist/browser/chunks/module-0191e321.js +74 -0
- package/dist/browser/chunks/module-shim-58659a86.js +0 -0
- package/dist/browser/chunks/module-shim-b4470740.js +12 -0
- package/dist/browser/chunks/monospace-D116QD2a-98d484fd.js +1 -0
- package/dist/browser/chunks/monospace-ex-DcXpouKS-456b403c.js +1 -0
- package/dist/browser/chunks/monospace-l-Ct5wkMDs-f34a4a9e.js +1 -0
- package/dist/browser/chunks/mshapes-DCp86WSX-c0055952.js +1 -0
- package/dist/browser/chunks/nds-icon-button-d602f784.js +194 -0
- package/dist/browser/chunks/nl-NL-364d61b9.js +1 -0
- package/dist/browser/chunks/nl-NL-8b7e6d4b.js +1 -0
- package/dist/browser/chunks/overlay-containment-edaaff13.js +1 -0
- package/dist/browser/chunks/overlay-placement-e8058232.js +1 -0
- package/dist/browser/chunks/phonetics-BwOCw2Y9-d2e3af59.js +1 -0
- package/dist/browser/chunks/phonetics-ss-CRtMn02f-579b6135.js +1 -0
- package/dist/browser/chunks/pie-api-client-687c319a.js +1 -0
- package/dist/browser/chunks/pie-tool-calculator-cortex-0626bc24.js +9 -0
- package/dist/browser/chunks/pie-tool-calculator-geogebra-561236cb.js +9 -0
- package/dist/browser/chunks/pointer-gesture-ce75f0a7.js +1 -0
- package/dist/browser/chunks/preload-helper-6ad28da3.js +1 -0
- package/dist/browser/chunks/provider-4c704118.js +1 -0
- package/dist/browser/chunks/rolldown-runtime-1287ba31.js +1 -0
- package/dist/browser/chunks/runtime-C7H1jS4E-64772f5e.js +8413 -0
- package/dist/browser/chunks/sanitize-svg-icon-b9082bba.js +3 -0
- package/dist/browser/chunks/sans-serif-BYPZKlE9-2efdbcd9.js +1 -0
- package/dist/browser/chunks/sans-serif-b-B0kRKiC--b5530dce.js +1 -0
- package/dist/browser/chunks/sans-serif-bi-DXWul6mu-5370dba4.js +1 -0
- package/dist/browser/chunks/sans-serif-ex-Boux1kMP-aa178f31.js +1 -0
- package/dist/browser/chunks/sans-serif-i-676RFaSO-2db54474.js +1 -0
- package/dist/browser/chunks/sans-serif-r-DrN9xdZt-0fc72eea.js +1 -0
- package/dist/browser/chunks/script-0ohehnXc-526904f4.js +1 -0
- package/dist/browser/chunks/shapes-BG47NodJ-d59b0eca.js +1 -0
- package/dist/browser/chunks/src-BcptuNS5-ed25d7fd.js +191 -0
- package/dist/browser/chunks/sre-engine-wf9s43gg-f09289c5.js +53 -0
- package/dist/browser/chunks/symbols-BqnUxf_t-83087e87.js +1 -0
- package/dist/browser/chunks/symbols-b-i-eg9k5hmF-9c461ac2.js +1 -0
- package/dist/browser/chunks/tool-annotation-toolbar-997438b4.js +248 -0
- package/dist/browser/chunks/tool-answer-eliminator-35483abd.js +13 -0
- package/dist/browser/chunks/tool-color-scheme-b7de5cdf.js +26 -0
- package/dist/browser/chunks/tool-dictionary-cecff3b4.js +7 -0
- package/dist/browser/chunks/tool-graph-cb0338e8.js +11 -0
- package/dist/browser/chunks/tool-host-contract-b93b482c.js +1 -0
- package/dist/browser/chunks/tool-line-reader-f8ef3c6a.js +62 -0
- package/dist/browser/chunks/tool-periodic-table-43b133b8.js +153 -0
- package/dist/browser/chunks/tool-picture-dictionary-33721e91.js +4 -0
- package/dist/browser/chunks/tool-protractor-23f77028.js +17 -0
- package/dist/browser/chunks/tool-ruler-1d9a03a6.js +15 -0
- package/dist/browser/chunks/tool-tts-inline-98c2ce7a.js +179 -0
- package/dist/browser/chunks/variants-2LRNhOUP-966fc49d.js +1 -0
- package/dist/browser/chunks/versioned-tag-54a76be9.js +1 -0
- package/dist/browser/pie-section-player.js +1613 -0
- package/dist/browser.d.ts +10 -0
- package/dist/chunks/ItemToolBar-wr2myaah-1287ba31.js +28 -0
- package/dist/chunks/module-shim-58659a86.js +2129 -0
- package/dist/chunks/{nl-NL-9312c316.js → nl-NL-364d61b9.js} +8 -2
- package/dist/chunks/sre-engine-wf9s43gg-f09289c5.js +8 -0
- package/dist/components/shared/composition.d.ts +0 -1
- package/dist/components/shared/layout-host-methods.d.ts +400 -0
- package/dist/components/shared/missing-tool-providers.d.ts +16 -0
- package/dist/components/shared/player-preload.d.ts +14 -10
- package/dist/contracts/host-hooks.d.ts +4 -5
- package/dist/contracts/host-hooks.js +0 -0
- package/dist/contracts/layout-contract.js +0 -0
- package/dist/contracts/layout-parity-metadata.js +87 -0
- package/dist/contracts/public-events.d.ts +14 -15
- package/dist/contracts/public-events.js +12 -0
- package/dist/contracts/runtime-host-contract.js +0 -0
- package/dist/controllers/SectionController.d.ts +21 -0
- package/dist/controllers/toolkit-section-contracts.d.ts +1 -17
- package/dist/controllers/types.d.ts +17 -10
- package/dist/pie-section-player.js +19353 -37273
- package/dist/policies/index.d.ts +9 -2
- package/dist/policies/index.js +25 -0
- package/package.json +34 -29
- package/dist/chunks/module-a516757f.js +0 -73997
- package/dist/chunks/nl-NL-ef6dd604.js +0 -505
- package/dist/chunks/pie-api-client-22de9d9c.js +0 -161
- package/dist/chunks/rolldown-runtime-1287ba31.js +0 -20
- package/dist/chunks/sre-0162a7a9.js +0 -17637
- package/dist/contracts/stages.d.ts +0 -10
- package/dist/utils/z-index.d.ts +0 -5
package/README.md
CHANGED
|
@@ -36,8 +36,11 @@ import "@pie-players/pie-section-player";
|
|
|
36
36
|
If hosts need explicit registration control, keep using documented component
|
|
37
37
|
entrypoints under `@pie-players/pie-section-player/components/*`.
|
|
38
38
|
|
|
39
|
-
|
|
40
|
-
|
|
39
|
+
The entries are bundler-only: they import `@pie-players/pie-item-player`,
|
|
40
|
+
`@pie-players/pie-default-tool-loaders` and `speech-rule-engine`, with the
|
|
41
|
+
engine's JSON locale tables, by bare specifier and without import attributes.
|
|
42
|
+
Items render through the host's one `@pie-players/pie-item-player`, which this
|
|
43
|
+
package depends on at its own version.
|
|
41
44
|
|
|
42
45
|
## SectionController
|
|
43
46
|
|
|
@@ -59,13 +62,21 @@ the per-method contract.
|
|
|
59
62
|
|
|
60
63
|
```ts
|
|
61
64
|
const host = document.querySelector("pie-section-player-splitpane") as any;
|
|
62
|
-
const controller = await host.waitForSectionController
|
|
65
|
+
const controller = await host.waitForSectionController(5000);
|
|
63
66
|
```
|
|
64
67
|
|
|
65
68
|
`waitForSectionController(timeoutMs)` resolves when the layout CE has wired
|
|
66
69
|
its controller (the same anchor `pie-stage-change` reaches with
|
|
67
|
-
`detail.stage === "engine-ready"`)
|
|
68
|
-
already passed the readiness anchor
|
|
70
|
+
`detail.stage === "engine-ready"`), or with `null` once `timeoutMs` passes.
|
|
71
|
+
Use `getSectionController()` if you've already passed the readiness anchor
|
|
72
|
+
synchronously.
|
|
73
|
+
|
|
74
|
+
The layout elements define their host methods from the moment they are
|
|
75
|
+
created, so a host can call them before the element mounts. Until it mounts,
|
|
76
|
+
`waitForSectionController` waits, `getSectionController()` returns `null`, the
|
|
77
|
+
navigation methods return `false`, and `getSnapshot()` and the `select*` reads
|
|
78
|
+
return `null` (`pie-section-player-kernel-host` returns its bootstrapping
|
|
79
|
+
snapshot).
|
|
69
80
|
|
|
70
81
|
### Session lifecycle
|
|
71
82
|
|
|
@@ -97,11 +108,25 @@ policy](#js-api-example-for-advanced-host-policy). Key event types:
|
|
|
97
108
|
|
|
98
109
|
- `item-selected` — item navigation within the current section.
|
|
99
110
|
- `item-session-data-changed` / `item-session-meta-changed` — per-item
|
|
100
|
-
session updates the persistence layer should observe.
|
|
101
|
-
|
|
111
|
+
session updates the persistence layer should observe. `sectionId` names the
|
|
112
|
+
section. `elementId` names the reporting element when the change carries one,
|
|
113
|
+
and `complete` is then that element's own. A commit carries
|
|
114
|
+
`sessionCommitReason` (see [Commit at a section
|
|
115
|
+
boundary](#commit-at-a-section-boundary)).
|
|
116
|
+
- `item-complete-changed` — an item's completion flipped. An item is complete
|
|
117
|
+
when every element that has reported its completion is complete. A report
|
|
118
|
+
without `elementId`, and a restored session's item-level `complete`, set the
|
|
119
|
+
item's completion directly. A session restored through `applySession`
|
|
120
|
+
without `complete` is complete when it holds a response. A passage's own
|
|
121
|
+
`session-changed` stays inside its shell: a passage holds no response.
|
|
122
|
+
- `content-loaded` — passage / item / rubric finished loading. Carries
|
|
123
|
+
`contentKind`, `itemId`, and `canonicalItemId`.
|
|
102
124
|
- `section-loading-complete` — every renderable in the section finished
|
|
103
125
|
loading.
|
|
104
126
|
- `section-items-complete-changed` — aggregate completion flip.
|
|
127
|
+
- `section-error` — an item player failed (`source: "item-player"`), or the
|
|
128
|
+
section runtime did (`source: "section-runtime"`), a rejected element warmup
|
|
129
|
+
included, which leaves the items unmounted.
|
|
105
130
|
- `section-navigation-change` — the controller's section identity changed.
|
|
106
131
|
- `formative-try-recorded` — a learner checked an answer.
|
|
107
132
|
- `formative-reveal-changed` — the reveal state changed without a Try: a learner
|
|
@@ -119,6 +144,20 @@ policy](#js-api-example-for-advanced-host-policy). Key event types:
|
|
|
119
144
|
- `timed-media-invalid` — authored `timedMedia` that cannot be delivered; the
|
|
120
145
|
section renders without cue behavior.
|
|
121
146
|
|
|
147
|
+
The helpers' default event sets leave out `formative-try-recorded`,
|
|
148
|
+
`formative-reveal-changed`, `section-mastery-changed` and
|
|
149
|
+
`timed-media-audio-started`. Name them in `subscribeItemEvents({ eventTypes })`,
|
|
150
|
+
or subscribe through `subscribeSectionEvents`.
|
|
151
|
+
|
|
152
|
+
Item-scoped events carry both id forms, and both are always populated.
|
|
153
|
+
`itemId` is the bare `item.id` — the form the map returned by
|
|
154
|
+
`getItemSessionsByItemId()` is keyed by, and the form `applySession` expects.
|
|
155
|
+
`canonicalItemId` is that item's adapter identifier, and falls back to `itemId`
|
|
156
|
+
when the section was not built from an adapter or no adapter ref matches it.
|
|
157
|
+
Correlate with formative policy and `runtime.player.resolveBackend` by
|
|
158
|
+
`canonicalItemId`; reach the session by `itemId`. `content-loaded` and
|
|
159
|
+
`item-player-error` both carry the pair.
|
|
160
|
+
|
|
122
161
|
### Formative delivery
|
|
123
162
|
|
|
124
163
|
Set `formative` on the section and the player renders a check-answer control per
|
|
@@ -150,7 +189,7 @@ Read the resolved state from `getFormativeProjection()`, or off
|
|
|
150
189
|
same handle:
|
|
151
190
|
|
|
152
191
|
```ts
|
|
153
|
-
const controller = await host.waitForSectionController
|
|
192
|
+
const controller = await host.waitForSectionController(5000);
|
|
154
193
|
// The learner's actions, budget-respecting.
|
|
155
194
|
controller?.recordFormativeTry?.({ itemId, outcomes }); // outcomes from provideScore()
|
|
156
195
|
controller?.retryFormativeItem?.({ itemId });
|
|
@@ -225,7 +264,7 @@ with its own player registers its own port instead, and that port outranks the
|
|
|
225
264
|
card's discovery for as long as it is attached:
|
|
226
265
|
|
|
227
266
|
```ts
|
|
228
|
-
const controller = await host.waitForSectionController
|
|
267
|
+
const controller = await host.waitForSectionController(5000);
|
|
229
268
|
// No `renderableId`: a host is asserting its own port, where a renderable's adapter
|
|
230
269
|
// has to name itself and is ignored unless it is the resolved stimulus.
|
|
231
270
|
controller?.attachMediaTimeSource?.(myThirdPartyPort);
|
|
@@ -280,15 +319,27 @@ Render in HTML/Svelte/JSX:
|
|
|
280
319
|
<pie-section-player-splitpane></pie-section-player-splitpane>
|
|
281
320
|
```
|
|
282
321
|
|
|
283
|
-
Set complex values (`runtime`, `section
|
|
322
|
+
Set complex values (`runtime`, `section`) as JS properties. `env` is a
|
|
323
|
+
`runtime` field (`runtime.env`); the layout elements have no `env` property.
|
|
324
|
+
|
|
325
|
+
Set `runtime` no later than `section`. When the player builds its own
|
|
326
|
+
coordinator, the section's arrival rebuilds that coordinator from the current
|
|
327
|
+
`runtime`, so both can be set a tick after the element mounts. Once the section
|
|
328
|
+
has initialized, a change to `runtime.tools`, `runtime.assessmentId`,
|
|
329
|
+
`runtime.accessibility`, `runtime.lazyInit`, `runtime.toolConfigStrictness` or
|
|
330
|
+
`toolRegistry` is reported once in the console and does not reach that
|
|
331
|
+
coordinator; `runtime.tools.pnpEnforcement` still applies. Change a running
|
|
332
|
+
coordinator through the one `toolkit-ready` delivers, with
|
|
333
|
+
`updateToolConfig(...)` or `updateToolsPlacement(...)`, or pass your own as
|
|
334
|
+
`runtime.coordinator`.
|
|
284
335
|
|
|
285
336
|
## Runtime Inputs
|
|
286
337
|
|
|
287
|
-
|
|
338
|
+
The layout elements (`pie-section-player-splitpane`,
|
|
339
|
+
`pie-section-player-vertical`, `pie-section-player-tabbed`) support:
|
|
288
340
|
|
|
289
341
|
- `runtime` (object): primary coordinator/tools/player runtime bundle
|
|
290
342
|
- `section` (object): assessment section payload
|
|
291
|
-
- `env` (object): optional top-level override for `{ mode, role }`
|
|
292
343
|
- `debug` (boolean-like): verbose debug logging control (`"true"` enables, `"false"`/`"0"` disables)
|
|
293
344
|
- `toolbar-position` (string): `top|right|bottom|left|none`
|
|
294
345
|
- `narrow-layout-breakpoint` (number, optional): viewport width in px below which the layout collapses (split pane: single column; vertical: toolbar moves to top). Clamped to 400–2000; default 1100.
|
|
@@ -297,7 +348,12 @@ Both layout elements support:
|
|
|
297
348
|
- `split-pane-min-region-width` (number, optional): splitpane minimum pane width in px. Clamped to 160–1200. Unset by default (split bounds stay at 20–80). (Ignored by vertical layout; supported for API parity.)
|
|
298
349
|
- `split-pane-collapse-strategy` (string, optional): splitpane stacked-mode strategy. Supported values: `tabbed` (default) and `vertical`. (Ignored by vertical/tabbed layouts; supported for API parity.)
|
|
299
350
|
- `base-heading-level` (number, optional): the heading level this player's card headings occupy, and the level every descendant's outline derives from. Clamped to 1–6; default 2. See [Heading structure](#heading-structure).
|
|
300
|
-
- `show-toolbar` (boolean-like): accepts `true/false` and common string forms (`"true"`, `"false"`, `"1"`, `"0"`, `"yes"`, `"no"`)
|
|
351
|
+
- `show-toolbar` (boolean-like): accepts `true/false` and common string forms (`"true"`, `"false"`, `"1"`, `"0"`, `"yes"`, `"no"`); default `false`, so tools placed at `section` level render only when it is `true`
|
|
352
|
+
- `locale` (string, optional): BCP-47 locale for the player's own interface text. Mirrored onto `runtime.locale`, which wins when both are set. Unset renders `en-US`.
|
|
353
|
+
- `nds-icons` (boolean): opt in to NDS icon buttons. Mirrored onto `runtime.ndsIcons`, which wins when both are set.
|
|
354
|
+
- `tool-config-strictness` (string, optional): `off|warn|error` for tool-config validation; default `error`. `runtime.toolConfigStrictness` wins when both are set.
|
|
355
|
+
- `split-pane-initial-passage-width` (number, optional): splitpane passage pane width in percent at mount. Clamped to 20–80; default 50.
|
|
356
|
+
- `iife-bundle-host` (string, optional): bundle host for the IIFE element pre-warm when `runtime.player.loaderOptions.bundleHost` is unset.
|
|
301
357
|
- Host extension props (JS properties only): `toolRegistry`, `sectionHostButtons`, `itemHostButtons`, `passageHostButtons`, `hooks`
|
|
302
358
|
|
|
303
359
|
When viewport width is within the collapsed range (~1100px and below), splitpane and
|
|
@@ -534,9 +590,9 @@ Advanced runtime configuration is supplied through the `runtime` object. Set pla
|
|
|
534
590
|
|
|
535
591
|
Hosts can configure item-player backend delivery once at the section-player
|
|
536
592
|
runtime level. Section-player derives a concrete `backend` prop for each
|
|
537
|
-
embedded item player before it renders the item. This is intended for hosts
|
|
538
|
-
|
|
539
|
-
|
|
593
|
+
embedded item player before it renders the item. This is intended for hosts
|
|
594
|
+
that need server-processed PIE models and server scoring without querying every
|
|
595
|
+
nested `<pie-item-player>`.
|
|
540
596
|
|
|
541
597
|
```ts
|
|
542
598
|
import type {
|
|
@@ -577,6 +633,10 @@ each embedded item player. Static delivery fields such as `baseUrl`, `auth`,
|
|
|
577
633
|
`endpoints`, `assignmentId`, and `autosave` are preserved. Use `assignmentId`
|
|
578
634
|
for shared attempt/player identity.
|
|
579
635
|
|
|
636
|
+
An enabled `backend.delivery` also sets `hosted: true` on each embedded item
|
|
637
|
+
player unless `runtime.player.hosted` is set, so the item players load no
|
|
638
|
+
element controllers and render the models the server returns.
|
|
639
|
+
|
|
580
640
|
`runtime.player.resolveBackend` is a section-player-reserved key. It is called
|
|
581
641
|
with `{ itemId, canonicalItemId, item, itemIndex, itemSession, sectionId, env,
|
|
582
642
|
baseBackend }` and is stripped before props reach `<pie-item-player>`. Use it
|
|
@@ -594,12 +654,66 @@ backend config is preserved.
|
|
|
594
654
|
This backend delivery config is separate from the element-loader backend used
|
|
595
655
|
for IIFE/ESM bundle preloading.
|
|
596
656
|
|
|
657
|
+
### Preloaded elements
|
|
658
|
+
|
|
659
|
+
With `runtime.playerType: "preloaded"` the section player loads no element
|
|
660
|
+
code. Its pre-warm asserts that every tag the section's items and passages name
|
|
661
|
+
is registered, so the host registers the elements first:
|
|
662
|
+
|
|
663
|
+
```ts
|
|
664
|
+
import { registerPreloadedElements } from "@pie-players/pie-item-player/preloaded";
|
|
665
|
+
import * as delivery from "@pie-element/multiple-choice/browser/delivery";
|
|
666
|
+
import * as controller from "@pie-element/multiple-choice/browser/controller";
|
|
667
|
+
import manifest from "../package.json"; // pins "@pie-element/multiple-choice" exactly
|
|
668
|
+
|
|
669
|
+
registerPreloadedElements([
|
|
670
|
+
{
|
|
671
|
+
tag: "pie-element-multiple-choice",
|
|
672
|
+
package: "@pie-element/multiple-choice",
|
|
673
|
+
version: manifest.dependencies["@pie-element/multiple-choice"],
|
|
674
|
+
element: delivery,
|
|
675
|
+
controller,
|
|
676
|
+
},
|
|
677
|
+
]);
|
|
678
|
+
|
|
679
|
+
sectionPlayer.runtime = { ...sectionPlayer.runtime, playerType: "preloaded" };
|
|
680
|
+
```
|
|
681
|
+
|
|
682
|
+
- Register before the section player mounts. A tag missing at pre-warm leaves
|
|
683
|
+
the items unmounted and raises a non-recoverable `element-preload` framework
|
|
684
|
+
error.
|
|
685
|
+
- Install element packages with `npm install --save-exact`. npm otherwise saves
|
|
686
|
+
a caret range, which registration rejects as a `version`, and which a fresh
|
|
687
|
+
install can resolve to another release line: `^13.4.0-next.15` resolves to
|
|
688
|
+
the legacy `13.4.4`, which has no `./browser/*` modules.
|
|
689
|
+
- Install every pie-elements-ng package from one release, in one install from
|
|
690
|
+
the same dist-tag, and upgrade them together. Elements whose `./browser/*`
|
|
691
|
+
builds typeset on `window.MathJax` share the MathJax the first of them loads,
|
|
692
|
+
in the build and configuration of that element's release, so in a mixed set
|
|
693
|
+
an element can typeset with a MathJax it was not built for. Elements that
|
|
694
|
+
bundle their own MathJax share none
|
|
695
|
+
([One MathJax version per page](../../docs/item-player/loading-strategies.md#one-mathjax-version-per-page)).
|
|
696
|
+
- Register one version per package. The players align every authored version
|
|
697
|
+
of a package to the registered one, and registering a second version throws.
|
|
698
|
+
- Register each package's `controller` unless the item players are hosted
|
|
699
|
+
(`runtime.player.hosted`, or an enabled `runtime.player.backend.delivery`).
|
|
700
|
+
A player that is not hosted runs `model()` in the browser and warns for each
|
|
701
|
+
tag registered without one.
|
|
702
|
+
- Only `@pie-element/*` builds from pie-elements-ng publish
|
|
703
|
+
`./browser/delivery` and `./browser/controller`.
|
|
704
|
+
- Under TypeScript, the `package.json` import needs `resolveJsonModule`, and a
|
|
705
|
+
package version that ships no declarations for `./browser/*` needs a
|
|
706
|
+
`declare module` shim for those subpaths.
|
|
707
|
+
|
|
708
|
+
See [`strategy="preloaded"`](../../docs/item-player/loading-strategies.md#strategypreloaded)
|
|
709
|
+
for the registration contract.
|
|
710
|
+
|
|
597
711
|
### Host-owned focus
|
|
598
712
|
|
|
599
713
|
Section-player does not move focus on behalf of host-level affordances such
|
|
600
714
|
as "Skip to Main", nor does it make passage/question containers tab stops.
|
|
601
715
|
Hosts own page chrome, skip links, landmarks, and any special focus placement.
|
|
602
|
-
For example,
|
|
716
|
+
For example, a host shell can focus its own
|
|
603
717
|
`main#main-content`; the next Tab then follows the browser's natural order
|
|
604
718
|
into the first actionable control rendered inside the section player.
|
|
605
719
|
|
|
@@ -615,11 +729,16 @@ sequential keyboard navigation.
|
|
|
615
729
|
</main>
|
|
616
730
|
```
|
|
617
731
|
|
|
618
|
-
**
|
|
619
|
-
|
|
732
|
+
**Policy fields.** The layout accepts a partial `policies` object: every
|
|
733
|
+
unset field, a missing section included, takes its value from
|
|
734
|
+
`DEFAULT_SECTION_PLAYER_POLICIES`.
|
|
620
735
|
|
|
621
|
-
- `readiness.mode` (`"progressive"` | `"strict"`) —
|
|
622
|
-
|
|
736
|
+
- `readiness.mode` (`"progressive"` | `"strict"`) — the mode
|
|
737
|
+
`SectionPlayerLayoutKernel` passes to `createReadinessDetail`. Both modes
|
|
738
|
+
hold the `interactive` stage and `pie-loading-complete` until the section's
|
|
739
|
+
element pre-warm resolves and the item cards can mount. The kernel has no
|
|
740
|
+
later loading signal, so the two modes currently emit the same sequence.
|
|
741
|
+
Default: `"progressive"`.
|
|
623
742
|
- `preload.enabled` — when `false`, `SectionItemsPane` short-circuits the
|
|
624
743
|
section-level element warmup pipeline (`warmupSectionElements`). Items
|
|
625
744
|
still mount and item-players register their own elements on demand. Use
|
|
@@ -727,7 +846,7 @@ Minimal pattern for package layout components:
|
|
|
727
846
|
|
|
728
847
|
```ts
|
|
729
848
|
const host = document.querySelector("pie-section-player-splitpane") as any;
|
|
730
|
-
const controller = await host.waitForSectionController
|
|
849
|
+
const controller = await host.waitForSectionController(5000);
|
|
731
850
|
let sectionComplete = false;
|
|
732
851
|
|
|
733
852
|
const unsubscribe = controller?.subscribe?.((event: any) => {
|
|
@@ -815,20 +934,21 @@ Canonical lifecycle stream (engine-routed, dispatched on the outer layout CE):
|
|
|
815
934
|
- `pie-stage-change` — single typed transition stream covering
|
|
816
935
|
`composed` → `engine-ready` → `interactive` → `disposed`. Payload is a
|
|
817
936
|
`StageChangeDetail`.
|
|
818
|
-
- `pie-loading-complete` — fires once per cohort when
|
|
819
|
-
|
|
937
|
+
- `pie-loading-complete` — fires once per cohort, when the section's element
|
|
938
|
+
pre-warm resolves for the current composition and the item cards can mount
|
|
939
|
+
(kernel-routed).
|
|
820
940
|
- `framework-error` — canonical error event for any failure crossing the
|
|
821
941
|
framework boundary. Payload is a `FrameworkErrorModel`. The toolkit's
|
|
822
942
|
package-internal `FrameworkErrorBus` and the `onFrameworkError`
|
|
823
943
|
callback prop deliver each error exactly once regardless of wrapper
|
|
824
|
-
depth
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
engine
|
|
829
|
-
|
|
830
|
-
Direct listeners attached to `<pie-assessment-toolkit>`
|
|
831
|
-
still see the toolkit's own emit.
|
|
944
|
+
depth, including errors from a coordinator the host passes as
|
|
945
|
+
`runtime.coordinator`. The `framework-error` *DOM event* on the outer
|
|
946
|
+
layout CE also delivers each error exactly once: the kernel listener at
|
|
947
|
+
`<pie-section-player-base>` stops the toolkit's bubbled emit, and the
|
|
948
|
+
engine dispatches the error on the layout host without bubbling, so it
|
|
949
|
+
does not reach `document`. `tests/section-player-event-delivery.spec.ts`
|
|
950
|
+
pins these counts. Direct listeners attached to `<pie-assessment-toolkit>`
|
|
951
|
+
itself still see the toolkit's own emit.
|
|
832
952
|
|
|
833
953
|
Callback-prop mirrors with two-tier precedence (`runtime.<key>` wins over
|
|
834
954
|
the top-level prop):
|
|
@@ -847,9 +967,9 @@ Section-player owned instrumentation stream:
|
|
|
847
967
|
|
|
848
968
|
- `pie-section-stage-change`
|
|
849
969
|
- `pie-section-loading-complete`
|
|
850
|
-
- `pie-section-session-changed`
|
|
851
|
-
- `pie-section-composition-changed`
|
|
852
970
|
- `pie-section-framework-error`
|
|
971
|
+
- `pie-section-element-preload-retry`
|
|
972
|
+
- `pie-section-element-preload-error`
|
|
853
973
|
|
|
854
974
|
Build consumers against these canonical lifecycle events:
|
|
855
975
|
|
|
@@ -880,7 +1000,7 @@ Section session data can be managed either through persistence hooks or directly
|
|
|
880
1000
|
|
|
881
1001
|
```ts
|
|
882
1002
|
const host = document.querySelector("pie-section-player-splitpane") as any;
|
|
883
|
-
const controller = await host.waitForSectionController
|
|
1003
|
+
const controller = await host.waitForSectionController(5000);
|
|
884
1004
|
|
|
885
1005
|
// Read current section session snapshot.
|
|
886
1006
|
const currentSession = controller?.getSession?.();
|
|
@@ -908,11 +1028,52 @@ await controller?.updateItemSession?.("q1", {
|
|
|
908
1028
|
The same controller snapshot is what the persistence strategy saves/loads.
|
|
909
1029
|
When a controller is reused for the same `sectionId`/`attemptId`, `updateInput()` refreshes composition input while preserving in-memory section session data.
|
|
910
1030
|
|
|
1031
|
+
### Commit at a section boundary
|
|
1032
|
+
|
|
1033
|
+
A delivery element coalesces its `session-changed` dispatch, so a response the
|
|
1034
|
+
learner has finished entering can still be pending when the section moves. The
|
|
1035
|
+
controller commits pending element sessions before item navigation, before
|
|
1036
|
+
`updateInput()` snapshots the session for a section swap, and before `persist()`.
|
|
1037
|
+
The player also commits when an item shell tears down and when the page goes
|
|
1038
|
+
hidden.
|
|
1039
|
+
|
|
1040
|
+
A committed response travels like any other. A raw element `session-changed`
|
|
1041
|
+
does not leave its `<pie-item-shell>`, which re-dispatches it as the normalized
|
|
1042
|
+
`item-session-changed` (`PIE_ITEM_SESSION_CHANGED_EVENT`); the toolkit then
|
|
1043
|
+
publishes the section's canonical `session-changed`. Both bubble through the
|
|
1044
|
+
layout element to `document`, and a listener on either receives each dispatch
|
|
1045
|
+
once.
|
|
1046
|
+
Host code persists from the controller's events or from its session snapshot.
|
|
1047
|
+
|
|
1048
|
+
Each of those events marks a commit with `sessionCommitReason`
|
|
1049
|
+
(`"teardown" | "navigate" | "page-hidden"`): `item-session-changed`, the
|
|
1050
|
+
toolkit's `session-changed`, and the controller's `item-session-data-changed`
|
|
1051
|
+
and `item-session-meta-changed`. A commit at a section swap or item navigation
|
|
1052
|
+
reports the item being left, which the host may already have moved past, so a
|
|
1053
|
+
handler that sets its current item or navigation state from these events leaves
|
|
1054
|
+
that state alone on a commit and persists the commit's session as usual. The
|
|
1055
|
+
controller's events also carry `sectionId`, the section the item belongs to.
|
|
1056
|
+
|
|
1057
|
+
Navigation inside a section keeps every item mounted, so nothing is discarded
|
|
1058
|
+
and the element's own debounce would complete on its own. The commit still runs
|
|
1059
|
+
there because the response belongs to the item being left: a host that persists
|
|
1060
|
+
on the navigation event, or a `persist()` that follows it, would otherwise
|
|
1061
|
+
snapshot a session the learner had already changed.
|
|
1062
|
+
|
|
1063
|
+
`SectionController` stays DOM-free; the player supplies the commit through
|
|
1064
|
+
`setPendingSessionCommit()`, declared on `SectionControllerHandle`. The player
|
|
1065
|
+
registers it both on the controllers it creates and on one the toolkit has
|
|
1066
|
+
already built, since the first section's controller usually exists before the
|
|
1067
|
+
player can override the factory. A host-built controller that leaves the method
|
|
1068
|
+
unimplemented keeps the behaviour it had before the hook existed, and loses a
|
|
1069
|
+
pending response at those boundaries.
|
|
1070
|
+
|
|
911
1071
|
## Content trust boundary
|
|
912
1072
|
|
|
913
1073
|
Section-player layouts embed `<pie-item-player>` elements for each item.
|
|
914
|
-
Item and passage markup is sanitized by default via DOMPurify; see
|
|
915
|
-
[pie-item-player README](
|
|
1074
|
+
Item and passage markup is sanitized by default via DOMPurify; see the
|
|
1075
|
+
[pie-item-player README](../item-player/README.md#content-trust-boundary)
|
|
1076
|
+
for the allow-list, the `trust-markup` opt-out and the `sanitizeMarkup`
|
|
916
1077
|
property. Hosts can forward those settings through the section-player
|
|
917
1078
|
`runtime.player` overrides — the runtime flattens these onto the embedded
|
|
918
1079
|
`<pie-item-player>` instance, so any field not recognized by the kernel is
|