@pie-players/pie-assessment-toolkit 0.3.74 → 1.0.0-beta.0

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.
Files changed (257) hide show
  1. package/README.md +658 -714
  2. package/custom-elements.json +1315 -0
  3. package/dist/attempt/TestSession.d.ts +1 -21
  4. package/dist/attempt/TestSession.js +16 -102
  5. package/dist/components/ItemScope.custom-element.d.ts +1 -0
  6. package/dist/components/ItemScope.custom-element.js +1 -0
  7. package/dist/components/ItemToolBar.custom-element.js +1 -1
  8. package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
  9. package/dist/components/SectionToolBar.custom-element.js +1 -1
  10. package/dist/components/chunks/ItemToolBar-3zrc4p3d.js +4 -0
  11. package/dist/components/chunks/ItemToolBar-66hcwmfw.js +2 -0
  12. package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
  13. package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
  14. package/dist/components/chunks/{ItemToolBar-gmrryv2v.js → ItemToolBar-kkj69ptr.js} +1 -1
  15. package/dist/components/chunks/ItemToolBar-vdkyn9f3.js +2 -0
  16. package/dist/components/chunks/sre-engine-bj997w4b.js +1 -0
  17. package/dist/components/item-scope-element.d.ts +2 -0
  18. package/dist/components/item-scope-element.js +2 -0
  19. package/dist/context/assessment-toolkit-context.d.ts +33 -6
  20. package/dist/index.d.ts +25 -50
  21. package/dist/index.js +15 -45
  22. package/dist/policy/core/PolicySource.d.ts +2 -2
  23. package/dist/policy/core/ToolPolicyEngine.d.ts +118 -34
  24. package/dist/policy/core/ToolPolicyEngine.js +203 -56
  25. package/dist/policy/core/compose-decision.d.ts +28 -7
  26. package/dist/policy/core/compose-decision.js +95 -74
  27. package/dist/policy/core/decision-types.d.ts +98 -55
  28. package/dist/policy/core/feature-decision.d.ts +28 -19
  29. package/dist/policy/core/feature-decision.js +15 -11
  30. package/dist/policy/core/pnp-policy-inputs.d.ts +29 -35
  31. package/dist/policy/core/pnp-policy-inputs.js +40 -88
  32. package/dist/policy/core/provenance.d.ts +10 -5
  33. package/dist/policy/core/provenance.js +1 -1
  34. package/dist/policy/core/tool-parameters.d.ts +11 -0
  35. package/dist/policy/core/tool-parameters.js +15 -0
  36. package/dist/policy/engine.d.ts +7 -23
  37. package/dist/policy/engine.js +5 -20
  38. package/dist/policy/sources/PnpPolicySource.d.ts +43 -68
  39. package/dist/policy/sources/PnpPolicySource.js +133 -132
  40. package/dist/runtime/SectionControllerBinding.d.ts +283 -0
  41. package/dist/runtime/SectionControllerBinding.js +456 -0
  42. package/dist/runtime/SectionRuntimeEngine.d.ts +26 -289
  43. package/dist/runtime/SectionRuntimeEngine.js +30 -372
  44. package/dist/runtime/adapter/SectionEngineAdapter.d.ts +19 -80
  45. package/dist/runtime/adapter/SectionEngineAdapter.js +19 -92
  46. package/dist/runtime/adapter/dom-event-bridge.d.ts +15 -30
  47. package/dist/runtime/adapter/dom-event-bridge.js +17 -44
  48. package/dist/runtime/adapter/subscriber-fanout.d.ts +1 -3
  49. package/dist/runtime/adapter/subscriber-fanout.js +2 -6
  50. package/dist/runtime/catalog-context.d.ts +19 -0
  51. package/dist/runtime/catalog-context.js +28 -0
  52. package/dist/runtime/composition-emit-scheduler.d.ts +12 -18
  53. package/dist/runtime/composition-emit-scheduler.js +10 -16
  54. package/dist/runtime/content-language.d.ts +32 -0
  55. package/dist/runtime/content-language.js +46 -0
  56. package/dist/runtime/content-region.d.ts +13 -0
  57. package/dist/runtime/content-region.js +29 -0
  58. package/dist/runtime/content-registration.d.ts +13 -0
  59. package/dist/runtime/content-registration.js +25 -0
  60. package/dist/runtime/core/SectionEngineCore.d.ts +2 -4
  61. package/dist/runtime/core/SectionEngineCore.js +2 -6
  62. package/dist/runtime/core/cohort.d.ts +1 -6
  63. package/dist/runtime/core/cohort.js +1 -10
  64. package/dist/runtime/core/engine-input.d.ts +18 -30
  65. package/dist/runtime/core/engine-input.js +11 -12
  66. package/dist/runtime/core/engine-output.d.ts +17 -40
  67. package/dist/runtime/core/engine-output.js +9 -21
  68. package/dist/runtime/core/engine-readiness.d.ts +5 -37
  69. package/dist/runtime/core/engine-readiness.js +8 -41
  70. package/dist/runtime/core/engine-resolver.d.ts +46 -74
  71. package/dist/runtime/core/engine-resolver.js +18 -43
  72. package/dist/runtime/core/engine-state.d.ts +28 -36
  73. package/dist/runtime/core/engine-state.js +18 -21
  74. package/dist/runtime/core/engine-transition.d.ts +14 -19
  75. package/dist/runtime/core/engine-transition.js +74 -53
  76. package/dist/runtime/engine.d.ts +16 -19
  77. package/dist/runtime/engine.js +12 -19
  78. package/dist/runtime/page-warnings.d.ts +13 -0
  79. package/dist/runtime/page-warnings.js +22 -0
  80. package/dist/runtime/policy-input-forwarding.d.ts +25 -0
  81. package/dist/runtime/policy-input-forwarding.js +25 -0
  82. package/dist/runtime/registration-events.d.ts +22 -14
  83. package/dist/runtime/runtime-event-claim.d.ts +8 -0
  84. package/dist/runtime/runtime-event-claim.js +15 -0
  85. package/dist/runtime/runtime-id.d.ts +1 -1
  86. package/dist/runtime/runtime-id.js +1 -1
  87. package/dist/runtime/shell-event-bridge.d.ts +45 -0
  88. package/dist/runtime/shell-event-bridge.js +127 -0
  89. package/dist/runtime/shell-registration.d.ts +73 -0
  90. package/dist/runtime/shell-registration.js +95 -0
  91. package/dist/runtime/shell-scope.d.ts +68 -0
  92. package/dist/runtime/shell-scope.js +194 -0
  93. package/dist/runtime/tool-host-contract.d.ts +8 -14
  94. package/dist/runtime/tool-host-contract.js +12 -12
  95. package/dist/runtime/unclaimed-registration-watch.d.ts +7 -0
  96. package/dist/runtime/unclaimed-registration-watch.js +23 -0
  97. package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
  98. package/dist/services/AccessibilityCatalogResolver.js +29 -42
  99. package/dist/services/ElementToolStateStore.d.ts +42 -67
  100. package/dist/services/ElementToolStateStore.js +65 -71
  101. package/dist/services/HighlightCoordinator.d.ts +28 -40
  102. package/dist/services/HighlightCoordinator.js +459 -381
  103. package/dist/services/RangeSerializer.d.ts +11 -33
  104. package/dist/services/RangeSerializer.js +88 -59
  105. package/dist/services/SSMLExtractor.d.ts +8 -31
  106. package/dist/services/SSMLExtractor.js +18 -40
  107. package/dist/services/TTSService.d.ts +159 -119
  108. package/dist/services/TTSService.js +937 -822
  109. package/dist/services/ToolCoordinator.d.ts +42 -102
  110. package/dist/services/ToolCoordinator.js +178 -256
  111. package/dist/services/ToolRegistry.d.ts +152 -133
  112. package/dist/services/ToolRegistry.js +192 -178
  113. package/dist/services/ToolkitCoordinator.d.ts +233 -237
  114. package/dist/services/ToolkitCoordinator.js +615 -557
  115. package/dist/services/audio-handoff.d.ts +6 -7
  116. package/dist/services/audio-handoff.js +20 -14
  117. package/dist/services/catalog-owner.d.ts +0 -1
  118. package/dist/services/framework-error-bus.d.ts +3 -6
  119. package/dist/services/framework-error-bus.js +3 -6
  120. package/dist/services/framework-error.d.ts +51 -13
  121. package/dist/services/framework-error.js +19 -20
  122. package/dist/services/interfaces.d.ts +189 -184
  123. package/dist/services/section-controller-types.d.ts +7 -7
  124. package/dist/services/section-session-assignment.d.ts +21 -0
  125. package/dist/services/section-session-assignment.js +80 -0
  126. package/dist/services/spoken-audio-cards.d.ts +2 -6
  127. package/dist/services/spoken-audio-cards.js +2 -6
  128. package/dist/services/tool-config-defaults.d.ts +3 -3
  129. package/dist/services/tool-config-defaults.js +3 -3
  130. package/dist/services/tool-config-validation.d.ts +9 -12
  131. package/dist/services/tool-config-validation.js +47 -87
  132. package/dist/services/tool-context.d.ts +7 -31
  133. package/dist/services/tool-context.js +99 -65
  134. package/dist/services/tool-failure.d.ts +30 -0
  135. package/dist/services/tool-failure.js +11 -0
  136. package/dist/services/tool-icons.d.ts +5 -5
  137. package/dist/services/tool-icons.js +6 -5
  138. package/dist/services/tool-instance-id.d.ts +8 -7
  139. package/dist/services/tool-instance-id.js +12 -24
  140. package/dist/services/tool-providers/TTSToolProvider.d.ts +20 -58
  141. package/dist/services/tool-providers/TTSToolProvider.js +32 -85
  142. package/dist/services/tool-providers/ToolProviderApi.d.ts +10 -11
  143. package/dist/services/tool-providers/ToolProviderRegistry.d.ts +29 -60
  144. package/dist/services/tool-providers/ToolProviderRegistry.js +128 -144
  145. package/dist/services/tool-request.d.ts +31 -12
  146. package/dist/services/tool-request.js +31 -16
  147. package/dist/services/toolbar-decided-tools.d.ts +16 -0
  148. package/dist/services/toolbar-decided-tools.js +29 -0
  149. package/dist/services/toolbar-items.js +2 -5
  150. package/dist/services/tools-config-normalizer.d.ts +33 -29
  151. package/dist/services/tools-config-normalizer.js +26 -28
  152. package/dist/services/tts/browser-provider.d.ts +39 -6
  153. package/dist/services/tts/browser-provider.js +280 -160
  154. package/dist/services/tts/catalog-span-alignment.js +14 -7
  155. package/dist/services/tts/flat-tree.d.ts +64 -0
  156. package/dist/services/tts/flat-tree.js +269 -0
  157. package/dist/services/tts/generated-speech/assemble-plan.d.ts +3 -1
  158. package/dist/services/tts/generated-speech/assemble-plan.js +3 -1
  159. package/dist/services/tts/generated-speech/dom/build-dom-plan.d.ts +2 -0
  160. package/dist/services/tts/generated-speech/dom/build-dom-plan.js +1 -1
  161. package/dist/services/tts/generated-speech/dom/to-chunk-inputs.d.ts +2 -2
  162. package/dist/services/tts/generated-speech/index.d.ts +1 -1
  163. package/dist/services/tts/generated-speech/index.js +1 -1
  164. package/dist/services/tts/generated-speech/math-speech-cache.d.ts +3 -1
  165. package/dist/services/tts/generated-speech/math-speech-cache.js +5 -1
  166. package/dist/services/tts/generated-speech/types.d.ts +1 -1
  167. package/dist/services/tts/generated-speech/types.js +1 -1
  168. package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +22 -16
  169. package/dist/services/tts/highlight-pipeline/prose-boundary-resolver.js +6 -4
  170. package/dist/services/tts/highlight-pipeline/readable-region.js +3 -2
  171. package/dist/services/tts/highlight-pipeline/types.d.ts +5 -0
  172. package/dist/services/tts/highlight-pipeline/visible-map-range.d.ts +12 -0
  173. package/dist/services/tts/highlight-pipeline/visible-map-range.js +73 -7
  174. package/dist/services/tts/highlight-target-resolver.d.ts +12 -0
  175. package/dist/services/tts/math-aware-text-processing.d.ts +5 -1
  176. package/dist/services/tts/math-aware-text-processing.js +42 -47
  177. package/dist/services/tts/math-control-names.d.ts +21 -0
  178. package/dist/services/tts/math-control-names.js +142 -0
  179. package/dist/services/tts/math-speech.d.ts +12 -1
  180. package/dist/services/tts/math-speech.js +54 -18
  181. package/dist/services/tts/mathml-sanitization.d.ts +7 -0
  182. package/dist/services/tts/mathml-sanitization.js +9 -1
  183. package/dist/services/tts/provider-options.d.ts +52 -0
  184. package/dist/services/tts/provider-options.js +1 -0
  185. package/dist/services/tts/ssml/spoken-text.d.ts +2 -26
  186. package/dist/services/tts/ssml/spoken-text.js +29 -0
  187. package/dist/services/tts/start-failure.d.ts +4 -0
  188. package/dist/services/tts/start-failure.js +19 -0
  189. package/dist/services/tts/text-processing.d.ts +9 -0
  190. package/dist/services/tts/text-processing.js +46 -33
  191. package/dist/services/tts/text-segmentation.d.ts +12 -0
  192. package/dist/services/tts/text-segmentation.js +60 -10
  193. package/dist/services/tts-runtime-config.d.ts +54 -26
  194. package/dist/services/tts-runtime-config.js +27 -112
  195. package/dist/tools/content-capability-resolution.d.ts +9 -11
  196. package/dist/tools/content-capability-resolution.js +8 -45
  197. package/dist/tools/registration.d.ts +59 -0
  198. package/dist/tools/registration.js +55 -0
  199. package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
  200. package/dist/tools/registrations/toolbar-registration-helpers.js +8 -2
  201. package/dist/tools/tool-surface-host.d.ts +6 -10
  202. package/dist/tools/tool-surface-host.js +45 -50
  203. package/dist/tools/tool-tag-map.d.ts +5 -15
  204. package/dist/tools/tool-tag-map.js +6 -20
  205. package/dist/utils/structural-equality.d.ts +11 -0
  206. package/dist/utils/structural-equality.js +47 -0
  207. package/package.json +15 -29
  208. package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts +0 -49
  209. package/dist/attempt/adapters/activity-to-test-attempt-session.js +0 -138
  210. package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +0 -40
  211. package/dist/components/chunks/ItemToolBar-h4xap0t0.js +0 -4
  212. package/dist/components/chunks/ItemToolBar-wr2myaah.js +0 -2
  213. package/dist/components/chunks/sre-engine-wf9s43gg.js +0 -1
  214. package/dist/context/runtime-context-consumer.d.ts +0 -13
  215. package/dist/context/runtime-context-consumer.js +0 -18
  216. package/dist/item-loader.d.ts +0 -44
  217. package/dist/item-loader.js +0 -61
  218. package/dist/policy/core/engine-context.d.ts +0 -29
  219. package/dist/policy/core/engine-context.js +0 -27
  220. package/dist/policy/core/policy-source-tag.d.ts +0 -31
  221. package/dist/policy/core/policy-source-tag.js +0 -28
  222. package/dist/policy/internal.d.ts +0 -25
  223. package/dist/policy/internal.js +0 -25
  224. package/dist/runtime/adapter/coordinator-bridge.d.ts +0 -92
  225. package/dist/runtime/adapter/coordinator-bridge.js +0 -126
  226. package/dist/runtime/adapter/framework-error-bridge.d.ts +0 -36
  227. package/dist/runtime/adapter/framework-error-bridge.js +0 -46
  228. package/dist/runtime/adapter/instrumentation-bridge.d.ts +0 -31
  229. package/dist/runtime/adapter/instrumentation-bridge.js +0 -38
  230. package/dist/runtime/core/engine-stage-derivation.d.ts +0 -18
  231. package/dist/runtime/core/engine-stage-derivation.js +0 -29
  232. package/dist/runtime/engine-context.d.ts +0 -39
  233. package/dist/runtime/engine-context.js +0 -31
  234. package/dist/runtime/internal.d.ts +0 -43
  235. package/dist/runtime/internal.js +0 -45
  236. package/dist/runtime/section-runtime-engine-host-context.d.ts +0 -74
  237. package/dist/runtime/section-runtime-engine-host-context.js +0 -57
  238. package/dist/runtime/stage-emit-gate.d.ts +0 -92
  239. package/dist/runtime/stage-emit-gate.js +0 -82
  240. package/dist/services/ContextVariableStore.d.ts +0 -113
  241. package/dist/services/ContextVariableStore.js +0 -206
  242. package/dist/services/I18nService.d.ts +0 -47
  243. package/dist/services/I18nService.js +0 -84
  244. package/dist/services/ThemeProvider.d.ts +0 -95
  245. package/dist/services/ThemeProvider.js +0 -334
  246. package/dist/services/defaultPersonalNeedsProfile.d.ts +0 -21
  247. package/dist/services/defaultPersonalNeedsProfile.js +0 -26
  248. package/dist/services/pnp-standard-features.d.ts +0 -238
  249. package/dist/services/pnp-standard-features.js +0 -338
  250. package/dist/services/tts-control-events.d.ts +0 -13
  251. package/dist/services/tts-control-events.js +0 -7
  252. package/dist/tools/client.d.ts +0 -10
  253. package/dist/tools/client.js +0 -10
  254. package/dist/tools/internal.d.ts +0 -44
  255. package/dist/tools/internal.js +0 -39
  256. package/dist/utils/logger.d.ts +0 -6
  257. package/dist/utils/logger.js +0 -10
@@ -0,0 +1,127 @@
1
+ import { commitPendingSessions, createPieLogger, normalizeItemSessionChange, } from "@pie-players/pie-players-shared";
2
+ import { PIE_INTERNAL_CONTENT_LOADED_EVENT, PIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT, PIE_INTERNAL_ITEM_SESSION_CHANGED_EVENT, PIE_ITEM_SESSION_CHANGED_EVENT, } from "./registration-events.js";
3
+ import { dispatchCrossBoundaryEvent } from "./tool-host-contract.js";
4
+ /**
5
+ * Elements repeat themselves, a `complete` echo most often, so a session event
6
+ * is forwarded only when it differs from the last one, apart from when and
7
+ * through which runtime it was stamped.
8
+ */
9
+ function sessionEventFingerprint(detail) {
10
+ const semanticDetail = detail && typeof detail === "object"
11
+ ? { ...detail }
12
+ : detail;
13
+ if (semanticDetail && typeof semanticDetail === "object") {
14
+ delete semanticDetail.timestamp;
15
+ delete semanticDetail.sourceRuntimeId;
16
+ }
17
+ try {
18
+ return JSON.stringify(semanticDetail);
19
+ }
20
+ catch {
21
+ return String(semanticDetail);
22
+ }
23
+ }
24
+ const isCommit = (detail) => Boolean(detail &&
25
+ typeof detail === "object" &&
26
+ detail.sessionCommitReason);
27
+ /**
28
+ * A shell's translation of its player's events into the runtime's, shared by
29
+ * `<pie-item-scope>` and `<pie-passage-shell>`. The dedupe
30
+ * state lives as long as the bridge, so a prop change does not forget what was
31
+ * forwarded.
32
+ */
33
+ export function createShellEventBridge(options) {
34
+ const { host, kind, identity, mode, send } = options;
35
+ const logger = createPieLogger(host.localName || "pie-shell", () => false);
36
+ let lastForwardedFingerprint = "";
37
+ const forwardSession = (detail) => {
38
+ const { itemId, canonicalItemId } = identity();
39
+ if (!itemId)
40
+ return;
41
+ const internal = {
42
+ itemId,
43
+ session: detail,
44
+ };
45
+ // The runtime keeps item state in step from every change; the public
46
+ // stream carries responses only.
47
+ send(PIE_INTERNAL_ITEM_SESSION_CHANGED_EVENT, internal);
48
+ const normalized = normalizeItemSessionChange({
49
+ itemId,
50
+ sessionDetail: detail,
51
+ });
52
+ if (normalized.intent === "metadata-only" || !normalized.session)
53
+ return;
54
+ const payload = {
55
+ itemId,
56
+ canonicalItemId: canonicalItemId || itemId,
57
+ session: normalized.session,
58
+ ...(normalized.sessionCommitReason
59
+ ? { sessionCommitReason: normalized.sessionCommitReason }
60
+ : {}),
61
+ };
62
+ dispatchCrossBoundaryEvent(host, PIE_ITEM_SESSION_CHANGED_EVENT, payload);
63
+ };
64
+ const onSessionChanged = (event) => {
65
+ if (mode() !== "section")
66
+ return;
67
+ event.stopPropagation();
68
+ // A passage carries no response: a passage id on the section's session
69
+ // stream names no item a host has.
70
+ if (kind !== "item")
71
+ return;
72
+ const detail = event.detail;
73
+ const fingerprint = sessionEventFingerprint(detail);
74
+ // A commit is the response's last chance to reach the section.
75
+ if (!isCommit(detail) && fingerprint === lastForwardedFingerprint)
76
+ return;
77
+ lastForwardedFingerprint = fingerprint;
78
+ forwardSession(detail);
79
+ };
80
+ const onLoadComplete = (event) => {
81
+ if (mode() === "section")
82
+ event.stopPropagation();
83
+ const { itemId, canonicalItemId, contentKind } = identity();
84
+ if (!itemId)
85
+ return;
86
+ const detail = {
87
+ itemId,
88
+ canonicalItemId: canonicalItemId || itemId,
89
+ contentKind,
90
+ detail: event.detail,
91
+ };
92
+ send(PIE_INTERNAL_CONTENT_LOADED_EVENT, detail);
93
+ };
94
+ const onPlayerError = (event) => {
95
+ if (mode() === "section")
96
+ event.stopPropagation();
97
+ const { itemId, canonicalItemId, contentKind } = identity();
98
+ if (!itemId)
99
+ return;
100
+ const detail = {
101
+ itemId,
102
+ canonicalItemId: canonicalItemId || itemId,
103
+ contentKind,
104
+ error: event.detail,
105
+ };
106
+ send(PIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT, detail);
107
+ };
108
+ host.addEventListener("session-changed", onSessionChanged);
109
+ host.addEventListener("load-complete", onLoadComplete);
110
+ host.addEventListener("player-error", onPlayerError);
111
+ return {
112
+ disconnect: () => {
113
+ // An escape from the commit must not strand the listeners it needed, so
114
+ // the unbinding runs either way. A plain player commits its own.
115
+ try {
116
+ if (kind === "item" && mode() === "section") {
117
+ commitPendingSessions(host, { reason: "teardown", logger });
118
+ }
119
+ }
120
+ finally {
121
+ host.removeEventListener("session-changed", onSessionChanged);
122
+ host.removeEventListener("load-complete", onLoadComplete);
123
+ host.removeEventListener("player-error", onPlayerError);
124
+ }
125
+ },
126
+ };
127
+ }
@@ -0,0 +1,73 @@
1
+ import type { ItemSettings } from "@pie-players/pie-players-shared/types";
2
+ /**
3
+ * Registration dispatch for the shells, through their shell scope.
4
+ *
5
+ * Registration is a statement of fact to the runtime, and the runtime takes it
6
+ * literally: a `pie-register` makes the toolkit unregister and re-register the
7
+ * content's accessibility catalogs, re-run `sectionBinding.register`, and
8
+ * re-notify the section controller.
9
+ *
10
+ * A shell's effects re-run whenever its props are re-applied, which happens on
11
+ * every update of its parent card's template. Dispatching from such an effect
12
+ * (with `pie-unregister` in its cleanup) announces a teardown and rebuild of
13
+ * state that has not moved, leaves the content without catalogs between the
14
+ * two, and closes a feedback loop: a reader that re-renders on a catalog change
15
+ * re-applies the shell's props, which re-registers, which changes catalogs
16
+ * again, until Svelte abandons the update at its depth limit with the DOM
17
+ * half-applied — while the elements are all present, so assertions about the
18
+ * rendered output still pass.
19
+ *
20
+ * So the dispatcher keeps the last identity it announced and says nothing when
21
+ * the next one matches.
22
+ */
23
+ export type ShellRegistrationIdentity = {
24
+ kind: "item" | "passage";
25
+ host: HTMLElement;
26
+ itemId: string;
27
+ canonicalItemId: string;
28
+ contentKind: string;
29
+ item: unknown;
30
+ /** The item's policy settings, compared structurally like its catalogs. */
31
+ settings: ItemSettings | null;
32
+ };
33
+ /**
34
+ * The runtime a registration is addressed to: its id, and the element it
35
+ * listens on, which a shell whose host has left the document dispatches on.
36
+ */
37
+ export type ShellRuntimeAddress = {
38
+ runtimeId: string;
39
+ eventTarget: EventTarget;
40
+ };
41
+ /**
42
+ * Where a shell's event to `runtime` goes: from the shell host while it is in
43
+ * the document, so the event bubbles through the tree like any other, and on
44
+ * the runtime's own element once it is not.
45
+ */
46
+ export declare function shellEventTarget(host: HTMLElement, runtime: ShellRuntimeAddress | undefined): EventTarget;
47
+ export type ShellRegistrationDispatcher = {
48
+ /**
49
+ * Announce `identity` if it says anything new, and retire the live
50
+ * registration when there is nothing left to describe — a shell without a host
51
+ * or an id no longer stands for content, and leaving its registration behind
52
+ * would strand it in the runtime.
53
+ *
54
+ * Never dispatches `pie-unregister` before a re-register to the same
55
+ * runtime: both registration paths in the toolkit are keyed by element and
56
+ * replace what is there, so the unregister only ever created the gap. A
57
+ * registration moving to a different runtime is retired first, addressed
58
+ * to the runtime that holds it.
59
+ */
60
+ sync: (identity: ShellRegistrationIdentity | null, runtime?: ShellRuntimeAddress) => void;
61
+ /**
62
+ * Retire the live registration, replaying the identity and runtime it was
63
+ * made under rather than whatever the props say now — by the time a
64
+ * registration is retired the props may already describe its replacement,
65
+ * and unregistering under the new identity would leave the old one live.
66
+ * A host already out of the document retires on the runtime's element.
67
+ *
68
+ * Belongs in a teardown that runs on teardown only. Attaching it to an effect
69
+ * that re-runs on prop changes is what made the churn.
70
+ */
71
+ retire: () => void;
72
+ };
73
+ export declare function createShellRegistrationDispatcher(): ShellRegistrationDispatcher;
@@ -0,0 +1,95 @@
1
+ import { catalogSourceSignature, } from "../services/catalog-owner.js";
2
+ import { structurallyEqual } from "../utils/structural-equality.js";
3
+ import { PIE_REGISTER_EVENT, PIE_UNREGISTER_EVENT, } from "./registration-events.js";
4
+ import { dispatchCrossBoundaryEvent } from "./tool-host-contract.js";
5
+ /**
6
+ * Everything a registration says except the item's catalogs.
7
+ */
8
+ function sameOwner(a, b) {
9
+ return (a.kind === b.kind &&
10
+ a.host === b.host &&
11
+ a.itemId === b.itemId &&
12
+ a.canonicalItemId === b.canonicalItemId &&
13
+ a.contentKind === b.contentKind &&
14
+ structurallyEqual(a.settings, b.settings));
15
+ }
16
+ /**
17
+ * The item's part of a registration is its catalogs, which is all the runtime
18
+ * reads from it. Object identity is no guide: the toolkit and the layout kernel
19
+ * hold the composition in deep reactive state, so every republish, each answer
20
+ * included, hands a shell a new proxy of unchanged content.
21
+ */
22
+ function catalogsOf(identity) {
23
+ return catalogSourceSignature(identity.item, identity.kind);
24
+ }
25
+ /**
26
+ * Where a shell's event to `runtime` goes: from the shell host while it is in
27
+ * the document, so the event bubbles through the tree like any other, and on
28
+ * the runtime's own element once it is not.
29
+ */
30
+ export function shellEventTarget(host, runtime) {
31
+ return host.isConnected || !runtime ? host : runtime.eventTarget;
32
+ }
33
+ function dispatch(eventName, identity, runtime) {
34
+ const detail = {
35
+ kind: identity.kind,
36
+ itemId: identity.itemId,
37
+ canonicalItemId: identity.canonicalItemId,
38
+ contentKind: identity.contentKind,
39
+ item: identity.item,
40
+ ...(identity.settings ? { settings: identity.settings } : {}),
41
+ element: identity.host,
42
+ ...(runtime ? { runtimeId: runtime.runtimeId } : {}),
43
+ };
44
+ dispatchCrossBoundaryEvent(shellEventTarget(identity.host, runtime), eventName, detail);
45
+ }
46
+ export function createShellRegistrationDispatcher() {
47
+ /**
48
+ * What the runtime was last told, and the catalogs it was told about.
49
+ * Deliberately not reactive: it is read to decide whether to dispatch, and
50
+ * making it reactive would put that decision inside the graph it exists to
51
+ * keep quiet.
52
+ */
53
+ let dispatched = null;
54
+ let dispatchedCatalogs = null;
55
+ let dispatchedRuntime;
56
+ function retire() {
57
+ const previous = dispatched;
58
+ if (!previous)
59
+ return;
60
+ const previousRuntime = dispatchedRuntime;
61
+ dispatched = null;
62
+ dispatchedCatalogs = null;
63
+ dispatchedRuntime = undefined;
64
+ dispatch(PIE_UNREGISTER_EVENT, previous, previousRuntime);
65
+ }
66
+ function sync(identity, runtime) {
67
+ if (!identity) {
68
+ retire();
69
+ return;
70
+ }
71
+ if (dispatched && dispatchedRuntime?.runtimeId !== runtime?.runtimeId) {
72
+ retire();
73
+ }
74
+ if (dispatched && sameOwner(dispatched, identity)) {
75
+ // A re-render re-applies the object last seen, so identity settles most
76
+ // runs without serializing anything.
77
+ if (dispatched.item === identity.item)
78
+ return;
79
+ const catalogs = catalogsOf(identity);
80
+ if (catalogs !== null && catalogs === dispatchedCatalogs) {
81
+ dispatched = identity;
82
+ return;
83
+ }
84
+ dispatched = identity;
85
+ dispatchedCatalogs = catalogs;
86
+ dispatch(PIE_REGISTER_EVENT, identity, runtime);
87
+ return;
88
+ }
89
+ dispatched = identity;
90
+ dispatchedCatalogs = catalogsOf(identity);
91
+ dispatchedRuntime = runtime;
92
+ dispatch(PIE_REGISTER_EVENT, identity, runtime);
93
+ }
94
+ return { sync, retire };
95
+ }
@@ -0,0 +1,68 @@
1
+ import { type ShellContextKind } from "../context/assessment-toolkit-context.js";
2
+ import type { ItemSettings } from "@pie-players/pie-players-shared/types";
3
+ import type { TTSHighlightTargetResolver } from "../services/tts/highlight-target-resolver.js";
4
+ /** What a shell says about the content it holds. */
5
+ export interface ShellScopeState {
6
+ /** The shell element: it provides the contexts and dispatches the registration. */
7
+ host: HTMLElement;
8
+ kind: ShellContextKind;
9
+ itemId: string;
10
+ canonicalItemId?: string;
11
+ contentKind: string;
12
+ regionPolicy?: string;
13
+ /** The region the shell's tools act on; the shell itself when unset. */
14
+ scopeElement?: HTMLElement | null;
15
+ ttsHighlightTargetResolver?: TTSHighlightTargetResolver | null;
16
+ item?: unknown;
17
+ /** An item's policy settings, registered with the runtime alongside it. */
18
+ settings?: ItemSettings | null;
19
+ }
20
+ export interface ShellScope {
21
+ /**
22
+ * Publishes `state`, or withdraws the scope when there is none. A state that
23
+ * says nothing new publishes nothing.
24
+ */
25
+ publish: (state: ShellScopeState | null) => void;
26
+ /**
27
+ * Retires the runtime registration under the identity it was made with.
28
+ * Teardown only, after anything that still has to reach the runtime.
29
+ */
30
+ retire: () => void;
31
+ /** Stops providing the contexts, and drops the events `send` holds. */
32
+ disconnect: () => void;
33
+ /**
34
+ * Dispatches `type` from the shell host with the id of the runtime that
35
+ * answered the scope in its detail, so that runtime claims it by id. Once
36
+ * the host has left the document, as in a teardown, the event is dispatched
37
+ * on the runtime's element instead, which the scope captured when the
38
+ * runtime answered. Events sent before a runtime has answered, or while the
39
+ * runtime's element is out of the document and the host is in it, are held,
40
+ * the newest {@link MAX_HELD_SHELL_EVENTS}, and delivered in order to the
41
+ * runtime that answers next. `disconnect` and `publish(null)` drop them.
42
+ */
43
+ send: (type: string, detail: object) => void;
44
+ }
45
+ /**
46
+ * A shell's publication of its content: the identity, as the shell context the
47
+ * tools inside it read, the region they act on, as the region scope, and the
48
+ * content itself, registered with the runtime, which files its accessibility
49
+ * catalogs under it. The section player's item and passage shells and
50
+ * `<pie-item-scope>` all publish through this, so a tool resolves its target
51
+ * and its catalogs the same way inside any of them.
52
+ *
53
+ * Content republished unchanged arrives as a new object, the composition being
54
+ * deep reactive state, so items compare by id and catalogs, the measure the
55
+ * registration applies.
56
+ *
57
+ * The registration waits for the runtime the shell sits in to answer through
58
+ * `assessmentToolkitHostRuntimeContext`, and carries that runtime's id, which
59
+ * the runtime claims it by. A shell mounted before its toolkit, which a host
60
+ * composing the elements itself can do, would otherwise register with no one
61
+ * listening, and nothing replays a registration. The document's context root
62
+ * replays the request instead, once the toolkit's provider connects. A
63
+ * different runtime answering later, a nearer toolkit taking over, moves the
64
+ * registration: the old runtime is told to unregister by its id, and the new
65
+ * one gets the registration and the content's last load, which only the old
66
+ * one heard.
67
+ */
68
+ export declare function createShellScope(): ShellScope;
@@ -0,0 +1,194 @@
1
+ import { ContextProvider, } from "@pie-players/pie-context";
2
+ import { assessmentToolkitRegionScopeContext, assessmentToolkitShellContext, } from "../context/assessment-toolkit-context.js";
3
+ import { catalogSourceSignature, } from "../services/catalog-owner.js";
4
+ import { PIE_INTERNAL_CONTENT_LOADED_EVENT } from "./registration-events.js";
5
+ import { createShellRegistrationDispatcher, shellEventTarget, } from "./shell-registration.js";
6
+ import { connectHostRuntimeContext, dispatchCrossBoundaryEvent, } from "./tool-host-contract.js";
7
+ /**
8
+ * The newest events kept until a runtime answers; an older one is dropped. A
9
+ * scope in plain mode sends only load and error events, a section shell its
10
+ * session events too.
11
+ */
12
+ const MAX_HELD_SHELL_EVENTS = 50;
13
+ function provide(host, context, value) {
14
+ const provider = new ContextProvider(host, { context, initialValue: value });
15
+ provider.connect();
16
+ return { provider, value };
17
+ }
18
+ function republish(provided, value, same) {
19
+ if (same(provided.value, value))
20
+ return;
21
+ provided.value = value;
22
+ provided.provider.setValue(value);
23
+ }
24
+ const sameItem = (a, b, kind) => {
25
+ if (a === b)
26
+ return true;
27
+ if (!a || !b)
28
+ return false;
29
+ if (a.id !== b.id)
30
+ return false;
31
+ const catalogs = catalogSourceSignature(a, kind);
32
+ return (catalogs !== null &&
33
+ catalogs === catalogSourceSignature(b, kind));
34
+ };
35
+ const sameShellContext = (a, b) => a.kind === b.kind &&
36
+ a.itemId === b.itemId &&
37
+ a.canonicalItemId === b.canonicalItemId &&
38
+ a.contentKind === b.contentKind &&
39
+ a.regionPolicy === b.regionPolicy &&
40
+ a.scopeElement === b.scopeElement &&
41
+ sameItem(a.item, b.item, a.kind);
42
+ const sameRegionScope = (a, b) => a.scopeElement === b.scopeElement &&
43
+ a.ttsHighlightTargetResolver === b.ttsHighlightTargetResolver;
44
+ const setAttributeIfChanged = (host, name, value) => {
45
+ if (host.getAttribute(name) !== value)
46
+ host.setAttribute(name, value);
47
+ };
48
+ /**
49
+ * A shell's publication of its content: the identity, as the shell context the
50
+ * tools inside it read, the region they act on, as the region scope, and the
51
+ * content itself, registered with the runtime, which files its accessibility
52
+ * catalogs under it. The section player's item and passage shells and
53
+ * `<pie-item-scope>` all publish through this, so a tool resolves its target
54
+ * and its catalogs the same way inside any of them.
55
+ *
56
+ * Content republished unchanged arrives as a new object, the composition being
57
+ * deep reactive state, so items compare by id and catalogs, the measure the
58
+ * registration applies.
59
+ *
60
+ * The registration waits for the runtime the shell sits in to answer through
61
+ * `assessmentToolkitHostRuntimeContext`, and carries that runtime's id, which
62
+ * the runtime claims it by. A shell mounted before its toolkit, which a host
63
+ * composing the elements itself can do, would otherwise register with no one
64
+ * listening, and nothing replays a registration. The document's context root
65
+ * replays the request instead, once the toolkit's provider connects. A
66
+ * different runtime answering later, a nearer toolkit taking over, moves the
67
+ * registration: the old runtime is told to unregister by its id, and the new
68
+ * one gets the registration and the content's last load, which only the old
69
+ * one heard.
70
+ */
71
+ export function createShellScope() {
72
+ const registration = createShellRegistrationDispatcher();
73
+ const contextVersion = Date.now();
74
+ let host = null;
75
+ let shell = null;
76
+ let region = null;
77
+ let stopFindingRuntime = null;
78
+ let runtime = null;
79
+ let identity = null;
80
+ let held = [];
81
+ let loaded = null;
82
+ const syncRegistration = () => {
83
+ if (runtime !== null)
84
+ registration.sync(identity, runtime);
85
+ };
86
+ // A runtime element that left the document while the shell stays in it no
87
+ // longer sits above the shell, so nothing would claim the shell's events.
88
+ const runtimeDeparted = (shellHost, address) => shellHost.isConnected &&
89
+ address.eventTarget.isConnected === false;
90
+ function send(type, detail) {
91
+ if (type === PIE_INTERNAL_CONTENT_LOADED_EVENT)
92
+ loaded = detail;
93
+ if (host && runtime !== null && !runtimeDeparted(host, runtime)) {
94
+ dispatchCrossBoundaryEvent(shellEventTarget(host, runtime), type, {
95
+ ...detail,
96
+ runtimeId: runtime.runtimeId,
97
+ });
98
+ return;
99
+ }
100
+ held.push({ type, detail });
101
+ if (held.length > MAX_HELD_SHELL_EVENTS)
102
+ held.shift();
103
+ }
104
+ // The subscription re-answers whenever the runtime republishes its context:
105
+ // under the same id it only delivers what the scope held meanwhile.
106
+ function onRuntime(value) {
107
+ const moved = runtime !== null && value.runtimeId !== runtime.runtimeId;
108
+ if (value.runtimeId !== runtime?.runtimeId) {
109
+ runtime = { runtimeId: value.runtimeId, eventTarget: value.eventTarget };
110
+ syncRegistration();
111
+ }
112
+ const pending = held;
113
+ held = [];
114
+ for (const event of pending)
115
+ send(event.type, event.detail);
116
+ const replayed = pending.some((event) => event.type === PIE_INTERNAL_CONTENT_LOADED_EVENT);
117
+ if (moved && loaded && !replayed) {
118
+ send(PIE_INTERNAL_CONTENT_LOADED_EVENT, loaded);
119
+ }
120
+ }
121
+ function disconnect() {
122
+ for (const provided of [shell, region])
123
+ provided?.provider.disconnect();
124
+ stopFindingRuntime?.();
125
+ stopFindingRuntime = null;
126
+ runtime = null;
127
+ held = [];
128
+ loaded = null;
129
+ identity = null;
130
+ shell = null;
131
+ region = null;
132
+ host = null;
133
+ }
134
+ function publish(state) {
135
+ if (!state) {
136
+ registration.sync(null);
137
+ disconnect();
138
+ return;
139
+ }
140
+ if (state.host !== host)
141
+ disconnect();
142
+ host = state.host;
143
+ const canonicalItemId = state.canonicalItemId || state.itemId;
144
+ const regionPolicy = state.regionPolicy || "default";
145
+ const scopeElement = state.scopeElement || state.host;
146
+ const shellValue = {
147
+ kind: state.kind,
148
+ itemId: state.itemId,
149
+ canonicalItemId,
150
+ contentKind: state.contentKind,
151
+ regionPolicy,
152
+ scopeElement,
153
+ item: state.item ?? null,
154
+ contextVersion,
155
+ };
156
+ if (shell)
157
+ republish(shell, shellValue, sameShellContext);
158
+ else
159
+ shell = provide(host, assessmentToolkitShellContext, shellValue);
160
+ const regionValue = {
161
+ scopeElement,
162
+ ttsHighlightTargetResolver: state.ttsHighlightTargetResolver ?? null,
163
+ };
164
+ if (region)
165
+ republish(region, regionValue, sameRegionScope);
166
+ else
167
+ region = provide(host, assessmentToolkitRegionScopeContext, regionValue);
168
+ setAttributeIfChanged(host, "data-item-id", state.itemId);
169
+ setAttributeIfChanged(host, "data-canonical-item-id", canonicalItemId);
170
+ setAttributeIfChanged(host, "data-pie-shell-root", state.kind);
171
+ setAttributeIfChanged(host, "data-region-policy", regionPolicy);
172
+ const previousIdentity = identity;
173
+ identity = state.itemId
174
+ ? {
175
+ kind: state.kind,
176
+ host,
177
+ itemId: state.itemId,
178
+ canonicalItemId,
179
+ contentKind: state.contentKind,
180
+ item: state.item ?? null,
181
+ settings: state.settings ?? null,
182
+ }
183
+ : null;
184
+ if (previousIdentity &&
185
+ (previousIdentity.itemId !== identity?.itemId ||
186
+ previousIdentity.canonicalItemId !== identity?.canonicalItemId)) {
187
+ loaded = null;
188
+ }
189
+ // Answers at once when the runtime is already there.
190
+ stopFindingRuntime ??= connectHostRuntimeContext(host, onRuntime);
191
+ syncRegistration();
192
+ }
193
+ return { publish, retire: registration.retire, disconnect, send };
194
+ }
@@ -1,29 +1,27 @@
1
- import type { UnknownContext } from "@pie-players/pie-context";
2
- import { type RegionScopeContextListener, type RuntimeContextListener, type ShellContextListener } from "../context/runtime-context-consumer.js";
1
+ import { type AssessmentToolkitHostRuntimeContext, type AssessmentToolkitRegionScopeContext, type AssessmentToolkitRuntimeContext, type AssessmentToolkitShellContext } from "../context/assessment-toolkit-context.js";
3
2
  import type { ZIndexLayer } from "../services/ToolCoordinator.js";
4
3
  import type { ToolCoordinatorApi } from "../services/interfaces.js";
5
4
  type BaseEventInit = Pick<EventInit, "bubbles" | "composed" | "cancelable">;
6
- /**
7
- * Contract helper for all toolkit/tool events that must cross custom-element boundaries.
8
- */
9
- export declare function createCrossBoundaryEvent<T>(name: string, detail: T, init?: Partial<BaseEventInit>): CustomEvent<T>;
10
5
  /**
11
6
  * Dispatches a cross-boundary event with toolkit defaults.
12
7
  */
13
8
  export declare function dispatchCrossBoundaryEvent<T>(target: EventTarget, name: string, detail: T, init?: Partial<BaseEventInit>): boolean;
14
9
  /**
15
10
  * Shared runtime-context connection contract for tools and shells.
16
- * Uses retry + provider announcements so late providers are tolerated.
11
+ * A provider that connects after the tool answers it through the document's
12
+ * context root.
17
13
  */
18
- export declare function connectToolRuntimeContext(host: HTMLElement, onValue: RuntimeContextListener): () => void;
14
+ export declare function connectToolRuntimeContext(host: HTMLElement, onValue: (value: AssessmentToolkitRuntimeContext) => void): () => void;
19
15
  /**
20
16
  * Shared shell-context connection contract for tools needing item/passage scope.
21
17
  */
22
- export declare function connectToolShellContext(host: HTMLElement, onValue: ShellContextListener): () => void;
18
+ export declare function connectToolShellContext(host: HTMLElement, onValue: (value: AssessmentToolkitShellContext) => void): () => void;
23
19
  /**
24
20
  * Shared region-scope context contract for tools targeting content subregions.
25
21
  */
26
- export declare function connectToolRegionScopeContext(host: HTMLElement, onValue: RegionScopeContextListener): () => void;
22
+ export declare function connectToolRegionScopeContext(host: HTMLElement, onValue: (value: AssessmentToolkitRegionScopeContext) => void): () => void;
23
+ /** Connects a shell or toolkit element to the host runtime context above it. */
24
+ export declare function connectHostRuntimeContext(host: HTMLElement, onValue: (value: AssessmentToolkitHostRuntimeContext) => void): () => void;
27
25
  /** A tool's registration with the coordinator in its runtime context. */
28
26
  export interface ToolCoordinatorRegistration {
29
27
  /**
@@ -42,8 +40,4 @@ export interface ToolCoordinatorRegistration {
42
40
  release(): void;
43
41
  }
44
42
  export declare function createToolCoordinatorRegistration(name: string, layer: ZIndexLayer): ToolCoordinatorRegistration;
45
- /**
46
- * Guard utility: narrows unknown context payloads when needed by callers.
47
- */
48
- export declare function isContextValueDefined<T extends UnknownContext>(value: unknown): value is T["__context__"];
49
43
  export {};
@@ -1,4 +1,5 @@
1
- import { connectAssessmentToolkitRegionScopeContext, connectAssessmentToolkitRuntimeContext, connectAssessmentToolkitShellContext, } from "../context/runtime-context-consumer.js";
1
+ import { connectContextWithRetry } from "@pie-players/pie-context";
2
+ import { assessmentToolkitHostRuntimeContext, assessmentToolkitRegionScopeContext, assessmentToolkitRuntimeContext, assessmentToolkitShellContext, } from "../context/assessment-toolkit-context.js";
2
3
  const CROSS_BOUNDARY_EVENT_INIT = {
3
4
  bubbles: true,
4
5
  composed: true,
@@ -7,7 +8,7 @@ const CROSS_BOUNDARY_EVENT_INIT = {
7
8
  /**
8
9
  * Contract helper for all toolkit/tool events that must cross custom-element boundaries.
9
10
  */
10
- export function createCrossBoundaryEvent(name, detail, init = {}) {
11
+ function createCrossBoundaryEvent(name, detail, init = {}) {
11
12
  return new CustomEvent(name, {
12
13
  detail,
13
14
  ...CROSS_BOUNDARY_EVENT_INIT,
@@ -22,22 +23,27 @@ export function dispatchCrossBoundaryEvent(target, name, detail, init = {}) {
22
23
  }
23
24
  /**
24
25
  * Shared runtime-context connection contract for tools and shells.
25
- * Uses retry + provider announcements so late providers are tolerated.
26
+ * A provider that connects after the tool answers it through the document's
27
+ * context root.
26
28
  */
27
29
  export function connectToolRuntimeContext(host, onValue) {
28
- return connectAssessmentToolkitRuntimeContext(host, onValue);
30
+ return connectContextWithRetry(host, assessmentToolkitRuntimeContext, onValue);
29
31
  }
30
32
  /**
31
33
  * Shared shell-context connection contract for tools needing item/passage scope.
32
34
  */
33
35
  export function connectToolShellContext(host, onValue) {
34
- return connectAssessmentToolkitShellContext(host, onValue);
36
+ return connectContextWithRetry(host, assessmentToolkitShellContext, onValue);
35
37
  }
36
38
  /**
37
39
  * Shared region-scope context contract for tools targeting content subregions.
38
40
  */
39
41
  export function connectToolRegionScopeContext(host, onValue) {
40
- return connectAssessmentToolkitRegionScopeContext(host, onValue);
42
+ return connectContextWithRetry(host, assessmentToolkitRegionScopeContext, onValue);
43
+ }
44
+ /** Connects a shell or toolkit element to the host runtime context above it. */
45
+ export function connectHostRuntimeContext(host, onValue) {
46
+ return connectContextWithRetry(host, assessmentToolkitHostRuntimeContext, onValue);
41
47
  }
42
48
  export function createToolCoordinatorRegistration(name, layer) {
43
49
  let registered = null;
@@ -60,9 +66,3 @@ export function createToolCoordinatorRegistration(name, layer) {
60
66
  release,
61
67
  };
62
68
  }
63
- /**
64
- * Guard utility: narrows unknown context payloads when needed by callers.
65
- */
66
- export function isContextValueDefined(value) {
67
- return value !== null && value !== undefined;
68
- }
@@ -0,0 +1,7 @@
1
+ /**
2
+ * A toolkit stops every registration it claims, so one that reaches the
3
+ * document went unclaimed: its item's catalogs are not filed and it does not
4
+ * count toward its section's loading. Installed from a toolkit's host at
5
+ * connect, once per document across every copy of the toolkit.
6
+ */
7
+ export declare function watchForUnclaimedRegistrations(doc: Document | null | undefined): void;