@pie-players/pie-section-player 0.3.3 → 0.3.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +123 -5
- package/dist/components/section-player-item-card-element.d.ts +2 -0
- package/dist/components/section-player-item-card-element.d.ts.map +1 -0
- package/dist/components/section-player-items-pane-element.d.ts +2 -0
- package/dist/components/section-player-items-pane-element.d.ts.map +1 -0
- package/dist/components/section-player-kernel-host-element.d.ts +2 -0
- package/dist/components/section-player-kernel-host-element.d.ts.map +1 -0
- package/dist/components/section-player-passage-card-element.d.ts +2 -0
- package/dist/components/section-player-passage-card-element.d.ts.map +1 -0
- package/dist/components/section-player-passages-pane-element.d.ts +2 -0
- package/dist/components/section-player-passages-pane-element.d.ts.map +1 -0
- package/dist/components/section-player-shell-element.d.ts +2 -0
- package/dist/components/section-player-shell-element.d.ts.map +1 -0
- package/dist/components/shared/outer-scrollbars.d.ts +6 -0
- package/dist/components/shared/outer-scrollbars.d.ts.map +1 -0
- package/dist/components/shared/player-action.d.ts +1 -0
- package/dist/components/shared/player-action.d.ts.map +1 -1
- package/dist/components/shared/player-preload.d.ts +5 -0
- package/dist/components/shared/player-preload.d.ts.map +1 -1
- package/dist/components/shared/section-player-card-context.d.ts +15 -0
- package/dist/components/shared/section-player-card-context.d.ts.map +1 -0
- package/dist/components/shared/section-player-props.d.ts +2 -0
- package/dist/components/shared/section-player-props.d.ts.map +1 -0
- package/dist/components/shared/section-player-readiness.d.ts +14 -0
- package/dist/components/shared/section-player-readiness.d.ts.map +1 -0
- package/dist/components/shared/section-player-runtime.d.ts +4 -4
- package/dist/components/shared/section-player-runtime.d.ts.map +1 -1
- package/dist/components/shared/section-player-view-state.d.ts +9 -0
- package/dist/components/shared/section-player-view-state.d.ts.map +1 -1
- package/dist/contracts/layout-contract.d.ts +18 -0
- package/dist/contracts/layout-contract.d.ts.map +1 -0
- package/dist/contracts/layout-parity-metadata.d.ts +4 -0
- package/dist/contracts/layout-parity-metadata.d.ts.map +1 -0
- package/dist/contracts/public-events.d.ts +25 -0
- package/dist/contracts/public-events.d.ts.map +1 -0
- package/dist/contracts/runtime-host-contract.d.ts +29 -0
- package/dist/contracts/runtime-host-contract.d.ts.map +1 -0
- package/dist/controllers/SectionController.d.ts +10 -14
- package/dist/controllers/SectionController.d.ts.map +1 -1
- package/dist/controllers/toolkit-section-contracts.d.ts +1 -1
- package/dist/controllers/toolkit-section-contracts.d.ts.map +1 -1
- package/dist/controllers/types.d.ts +27 -13
- package/dist/controllers/types.d.ts.map +1 -1
- package/dist/index-CGEKDUBQ-C-8EFMUk.js +216 -0
- package/dist/index-DF-Dk87f-lxErM8bo.js +178 -0
- package/dist/pie-section-player.d.ts +7 -0
- package/dist/pie-section-player.d.ts.map +1 -1
- package/dist/pie-section-player.js +8249 -7564
- package/dist/{player-preload-9v0AQsMd.js → player-preload-Boa1VXUc.js} +2707 -2649
- package/dist/policies/guards.d.ts +3 -0
- package/dist/policies/guards.d.ts.map +1 -0
- package/dist/policies/index.d.ts +3 -0
- package/dist/policies/index.d.ts.map +1 -0
- package/dist/policies/types.d.ts +23 -0
- package/dist/policies/types.d.ts.map +1 -0
- package/dist/tool-annotation-toolbar-DJvpXk1K.js +4917 -0
- package/dist/utils/player-preload.js +1 -1
- package/package.json +54 -13
- package/dist/tool-annotation-toolbar-m4Mv2j0H.js +0 -4305
- package/src/components/ItemShellElement.svelte +0 -302
- package/src/components/PassageShellElement.svelte +0 -217
- package/src/components/PieSectionPlayerBaseElement.svelte +0 -245
- package/src/components/PieSectionPlayerSplitPaneElement.svelte +0 -675
- package/src/components/PieSectionPlayerVerticalElement.svelte +0 -439
- package/src/components/shared/SectionItemCard.svelte +0 -92
- package/src/components/shared/SectionPassageCard.svelte +0 -88
|
@@ -1,302 +0,0 @@
|
|
|
1
|
-
<svelte:options
|
|
2
|
-
customElement={{
|
|
3
|
-
tag: "pie-item-shell",
|
|
4
|
-
shadow: "open",
|
|
5
|
-
props: {
|
|
6
|
-
itemId: { attribute: "item-id", type: "String" },
|
|
7
|
-
canonicalItemId: { attribute: "canonical-item-id", type: "String" },
|
|
8
|
-
contentKind: { attribute: "content-kind", type: "String" },
|
|
9
|
-
regionPolicy: { attribute: "region-policy", type: "String" },
|
|
10
|
-
scopeElement: { type: "Object", reflect: false },
|
|
11
|
-
item: { type: "Object", reflect: false },
|
|
12
|
-
},
|
|
13
|
-
}}
|
|
14
|
-
/>
|
|
15
|
-
|
|
16
|
-
<script module lang="ts">
|
|
17
|
-
const crossShellSessionDedupe = new Map<
|
|
18
|
-
string,
|
|
19
|
-
{ fingerprint: string; timestamp: number }
|
|
20
|
-
>();
|
|
21
|
-
</script>
|
|
22
|
-
|
|
23
|
-
<script lang="ts">
|
|
24
|
-
import {
|
|
25
|
-
PIE_INTERNAL_ITEM_SESSION_CHANGED_EVENT,
|
|
26
|
-
PIE_ITEM_SESSION_CHANGED_EVENT,
|
|
27
|
-
PIE_REGISTER_EVENT,
|
|
28
|
-
PIE_UNREGISTER_EVENT,
|
|
29
|
-
assessmentToolkitRegionScopeContext,
|
|
30
|
-
assessmentToolkitShellContext,
|
|
31
|
-
dispatchCrossBoundaryEvent,
|
|
32
|
-
type AssessmentToolkitRegionScopeContext,
|
|
33
|
-
type AssessmentToolkitShellContext,
|
|
34
|
-
type InternalItemSessionChangedDetail,
|
|
35
|
-
type ItemSessionChangedDetail,
|
|
36
|
-
type RuntimeRegistrationDetail,
|
|
37
|
-
} from "@pie-players/pie-assessment-toolkit";
|
|
38
|
-
import { normalizeItemSessionChange } from "@pie-players/pie-players-shared";
|
|
39
|
-
import { ContextProvider, ContextRoot } from "@pie-players/pie-context";
|
|
40
|
-
|
|
41
|
-
const PIE_INTERNAL_CONTENT_LOADED_EVENT = "pie-content-loaded";
|
|
42
|
-
const PIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT = "pie-item-player-error";
|
|
43
|
-
type InternalContentLoadedDetail = {
|
|
44
|
-
itemId: string;
|
|
45
|
-
canonicalItemId?: string;
|
|
46
|
-
contentKind?: string;
|
|
47
|
-
detail?: unknown;
|
|
48
|
-
};
|
|
49
|
-
type InternalItemPlayerErrorDetail = {
|
|
50
|
-
itemId: string;
|
|
51
|
-
canonicalItemId?: string;
|
|
52
|
-
contentKind?: string;
|
|
53
|
-
error: unknown;
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
let {
|
|
57
|
-
itemId = "",
|
|
58
|
-
canonicalItemId = "",
|
|
59
|
-
contentKind = "assessment-item",
|
|
60
|
-
regionPolicy = "default",
|
|
61
|
-
scopeElement = null as HTMLElement | null,
|
|
62
|
-
item = null as unknown,
|
|
63
|
-
} = $props();
|
|
64
|
-
|
|
65
|
-
let anchor = $state<HTMLDivElement | null>(null);
|
|
66
|
-
const shellContextVersion = Date.now();
|
|
67
|
-
let shellContextProvider: ContextProvider<
|
|
68
|
-
typeof assessmentToolkitShellContext
|
|
69
|
-
> | null = null;
|
|
70
|
-
let shellContextRoot: ContextRoot | null = null;
|
|
71
|
-
let regionScopeProvider: ContextProvider<
|
|
72
|
-
typeof assessmentToolkitRegionScopeContext
|
|
73
|
-
> | null = null;
|
|
74
|
-
let regionScopeRoot: ContextRoot | null = null;
|
|
75
|
-
|
|
76
|
-
function getHostElement(): HTMLElement | null {
|
|
77
|
-
if (!anchor) return null;
|
|
78
|
-
const rootNode = anchor.getRootNode();
|
|
79
|
-
if (rootNode && "host" in rootNode) {
|
|
80
|
-
return (rootNode as ShadowRoot).host as HTMLElement;
|
|
81
|
-
}
|
|
82
|
-
return anchor.parentElement as HTMLElement | null;
|
|
83
|
-
}
|
|
84
|
-
const host = $derived.by(() => getHostElement());
|
|
85
|
-
const effectiveScopeElement = $derived(scopeElement || host || null);
|
|
86
|
-
const regionScopeValue = $derived.by(
|
|
87
|
-
(): AssessmentToolkitRegionScopeContext | null => {
|
|
88
|
-
if (!effectiveScopeElement) return null;
|
|
89
|
-
return {
|
|
90
|
-
scopeElement: effectiveScopeElement,
|
|
91
|
-
};
|
|
92
|
-
},
|
|
93
|
-
);
|
|
94
|
-
|
|
95
|
-
const shellContextValue = $derived.by(
|
|
96
|
-
(): AssessmentToolkitShellContext | null => {
|
|
97
|
-
if (!host) return null;
|
|
98
|
-
const canonical = canonicalItemId || itemId;
|
|
99
|
-
return {
|
|
100
|
-
kind: "item",
|
|
101
|
-
itemId,
|
|
102
|
-
canonicalItemId: canonical,
|
|
103
|
-
contentKind,
|
|
104
|
-
regionPolicy,
|
|
105
|
-
scopeElement: effectiveScopeElement,
|
|
106
|
-
item,
|
|
107
|
-
contextVersion: shellContextVersion,
|
|
108
|
-
};
|
|
109
|
-
},
|
|
110
|
-
);
|
|
111
|
-
|
|
112
|
-
function dispatchRegistration(eventName: string): void {
|
|
113
|
-
if (!host || !itemId) return;
|
|
114
|
-
const detail: RuntimeRegistrationDetail = {
|
|
115
|
-
kind: "item",
|
|
116
|
-
itemId,
|
|
117
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
118
|
-
contentKind,
|
|
119
|
-
item,
|
|
120
|
-
element: host,
|
|
121
|
-
};
|
|
122
|
-
dispatchCrossBoundaryEvent(host, eventName, detail);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
function normalizeAndDispatchSession(event: Event): void {
|
|
126
|
-
if (!host || !itemId) return;
|
|
127
|
-
const detail = (event as CustomEvent).detail;
|
|
128
|
-
const internalPayload: InternalItemSessionChangedDetail = {
|
|
129
|
-
itemId,
|
|
130
|
-
session: detail,
|
|
131
|
-
};
|
|
132
|
-
// Internal runtime session wiring must always continue to keep item UI/state synchronized.
|
|
133
|
-
dispatchCrossBoundaryEvent(host, PIE_INTERNAL_ITEM_SESSION_CHANGED_EVENT, internalPayload);
|
|
134
|
-
// Keep public item stream response-focused; metadata-only belongs on canonical session-changed.
|
|
135
|
-
const normalized = normalizeItemSessionChange({
|
|
136
|
-
itemId,
|
|
137
|
-
sessionDetail: detail,
|
|
138
|
-
});
|
|
139
|
-
if (normalized.intent === "metadata-only" || !normalized.session) {
|
|
140
|
-
return;
|
|
141
|
-
}
|
|
142
|
-
const payload: ItemSessionChangedDetail = {
|
|
143
|
-
itemId,
|
|
144
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
145
|
-
session: normalized.session,
|
|
146
|
-
};
|
|
147
|
-
dispatchCrossBoundaryEvent(host, PIE_ITEM_SESSION_CHANGED_EVENT, payload);
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
function dispatchLoaded(detail: unknown): void {
|
|
151
|
-
if (!host || !itemId) return;
|
|
152
|
-
const payload: InternalContentLoadedDetail = {
|
|
153
|
-
itemId,
|
|
154
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
155
|
-
contentKind,
|
|
156
|
-
detail,
|
|
157
|
-
};
|
|
158
|
-
dispatchCrossBoundaryEvent(host, PIE_INTERNAL_CONTENT_LOADED_EVENT, payload);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
function dispatchPlayerError(error: unknown): void {
|
|
162
|
-
if (!host || !itemId) return;
|
|
163
|
-
const payload: InternalItemPlayerErrorDetail = {
|
|
164
|
-
itemId,
|
|
165
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
166
|
-
contentKind,
|
|
167
|
-
error,
|
|
168
|
-
};
|
|
169
|
-
dispatchCrossBoundaryEvent(host, PIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT, payload);
|
|
170
|
-
}
|
|
171
|
-
|
|
172
|
-
function createSessionEventFingerprint(detail: unknown): string {
|
|
173
|
-
const semanticDetail =
|
|
174
|
-
detail && typeof detail === "object"
|
|
175
|
-
? { ...(detail as Record<string, unknown>) }
|
|
176
|
-
: detail;
|
|
177
|
-
if (semanticDetail && typeof semanticDetail === "object") {
|
|
178
|
-
delete (semanticDetail as Record<string, unknown>).timestamp;
|
|
179
|
-
delete (semanticDetail as Record<string, unknown>).sourceRuntimeId;
|
|
180
|
-
}
|
|
181
|
-
try {
|
|
182
|
-
return JSON.stringify(semanticDetail);
|
|
183
|
-
} catch {
|
|
184
|
-
return String(semanticDetail);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
$effect(() => {
|
|
189
|
-
if (!host) return;
|
|
190
|
-
dispatchRegistration(PIE_REGISTER_EVENT);
|
|
191
|
-
|
|
192
|
-
const seenSessionEvents = new WeakSet<Event>();
|
|
193
|
-
let lastForwardedFingerprint = "";
|
|
194
|
-
const CROSS_SHELL_DEDUPE_WINDOW_MS = 500;
|
|
195
|
-
const onSessionChanged = (event: Event) => {
|
|
196
|
-
// Keep framework surface minimal: normalize these descendant events and do not
|
|
197
|
-
// leak raw item-player session events to external listeners.
|
|
198
|
-
event.stopPropagation();
|
|
199
|
-
// Some players emit `session-changed`, others emit `sessionchanged`.
|
|
200
|
-
// Guard against duplicate forwarding when both fire for the same payload.
|
|
201
|
-
if (seenSessionEvents.has(event)) return;
|
|
202
|
-
seenSessionEvents.add(event);
|
|
203
|
-
const fingerprint = createSessionEventFingerprint((event as CustomEvent).detail);
|
|
204
|
-
if (fingerprint === lastForwardedFingerprint) return;
|
|
205
|
-
const dedupeKey = itemId || canonicalItemId || "__unknown-item__";
|
|
206
|
-
const now = Date.now();
|
|
207
|
-
const lastCrossShell = crossShellSessionDedupe.get(dedupeKey);
|
|
208
|
-
if (
|
|
209
|
-
lastCrossShell &&
|
|
210
|
-
lastCrossShell.fingerprint === fingerprint &&
|
|
211
|
-
now - lastCrossShell.timestamp < CROSS_SHELL_DEDUPE_WINDOW_MS
|
|
212
|
-
) {
|
|
213
|
-
return;
|
|
214
|
-
}
|
|
215
|
-
crossShellSessionDedupe.set(dedupeKey, { fingerprint, timestamp: now });
|
|
216
|
-
lastForwardedFingerprint = fingerprint;
|
|
217
|
-
normalizeAndDispatchSession(event);
|
|
218
|
-
};
|
|
219
|
-
host.addEventListener("sessionchanged", onSessionChanged);
|
|
220
|
-
host.addEventListener("session-changed", onSessionChanged);
|
|
221
|
-
const onLoadComplete = (event: Event) => {
|
|
222
|
-
event.stopPropagation();
|
|
223
|
-
dispatchLoaded((event as CustomEvent).detail);
|
|
224
|
-
};
|
|
225
|
-
const onPlayerError = (event: Event) => {
|
|
226
|
-
event.stopPropagation();
|
|
227
|
-
dispatchPlayerError((event as CustomEvent).detail);
|
|
228
|
-
};
|
|
229
|
-
host.addEventListener("load-complete", onLoadComplete);
|
|
230
|
-
host.addEventListener("player-error", onPlayerError);
|
|
231
|
-
|
|
232
|
-
return () => {
|
|
233
|
-
host?.removeEventListener("sessionchanged", onSessionChanged);
|
|
234
|
-
host?.removeEventListener("session-changed", onSessionChanged);
|
|
235
|
-
host?.removeEventListener("load-complete", onLoadComplete);
|
|
236
|
-
host?.removeEventListener("player-error", onPlayerError);
|
|
237
|
-
dispatchRegistration(PIE_UNREGISTER_EVENT);
|
|
238
|
-
};
|
|
239
|
-
});
|
|
240
|
-
|
|
241
|
-
$effect(() => {
|
|
242
|
-
if (!host) return;
|
|
243
|
-
host.setAttribute("data-item-id", itemId);
|
|
244
|
-
host.setAttribute("data-canonical-item-id", canonicalItemId || itemId);
|
|
245
|
-
host.setAttribute("data-pie-shell-root", "item");
|
|
246
|
-
host.setAttribute("data-region-policy", regionPolicy);
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
$effect(() => {
|
|
250
|
-
if (!host || !shellContextValue) return;
|
|
251
|
-
shellContextProvider = new ContextProvider(host, {
|
|
252
|
-
context: assessmentToolkitShellContext,
|
|
253
|
-
initialValue: shellContextValue,
|
|
254
|
-
});
|
|
255
|
-
shellContextProvider.connect();
|
|
256
|
-
shellContextRoot = new ContextRoot(host);
|
|
257
|
-
shellContextRoot.attach();
|
|
258
|
-
|
|
259
|
-
return () => {
|
|
260
|
-
shellContextRoot?.detach();
|
|
261
|
-
shellContextRoot = null;
|
|
262
|
-
shellContextProvider?.disconnect();
|
|
263
|
-
shellContextProvider = null;
|
|
264
|
-
};
|
|
265
|
-
});
|
|
266
|
-
|
|
267
|
-
$effect(() => {
|
|
268
|
-
if (!shellContextValue) return;
|
|
269
|
-
shellContextProvider?.setValue(shellContextValue);
|
|
270
|
-
});
|
|
271
|
-
|
|
272
|
-
$effect(() => {
|
|
273
|
-
if (!host || !regionScopeValue) return;
|
|
274
|
-
regionScopeProvider = new ContextProvider(host, {
|
|
275
|
-
context: assessmentToolkitRegionScopeContext,
|
|
276
|
-
initialValue: regionScopeValue,
|
|
277
|
-
});
|
|
278
|
-
regionScopeProvider.connect();
|
|
279
|
-
regionScopeRoot = new ContextRoot(host);
|
|
280
|
-
regionScopeRoot.attach();
|
|
281
|
-
return () => {
|
|
282
|
-
regionScopeRoot?.detach();
|
|
283
|
-
regionScopeRoot = null;
|
|
284
|
-
regionScopeProvider?.disconnect();
|
|
285
|
-
regionScopeProvider = null;
|
|
286
|
-
};
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
$effect(() => {
|
|
290
|
-
if (!regionScopeValue) return;
|
|
291
|
-
regionScopeProvider?.setValue(regionScopeValue);
|
|
292
|
-
});
|
|
293
|
-
</script>
|
|
294
|
-
|
|
295
|
-
<div bind:this={anchor} class="pie-item-shell-anchor" aria-hidden="true"></div>
|
|
296
|
-
<slot></slot>
|
|
297
|
-
|
|
298
|
-
<style>
|
|
299
|
-
.pie-item-shell-anchor {
|
|
300
|
-
display: none;
|
|
301
|
-
}
|
|
302
|
-
</style>
|
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
<svelte:options
|
|
2
|
-
customElement={{
|
|
3
|
-
tag: "pie-passage-shell",
|
|
4
|
-
shadow: "open",
|
|
5
|
-
props: {
|
|
6
|
-
itemId: { attribute: "item-id", type: "String" },
|
|
7
|
-
canonicalItemId: { attribute: "canonical-item-id", type: "String" },
|
|
8
|
-
contentKind: { attribute: "content-kind", type: "String" },
|
|
9
|
-
regionPolicy: { attribute: "region-policy", type: "String" },
|
|
10
|
-
scopeElement: { type: "Object", reflect: false },
|
|
11
|
-
item: { type: "Object", reflect: false },
|
|
12
|
-
},
|
|
13
|
-
}}
|
|
14
|
-
/>
|
|
15
|
-
|
|
16
|
-
<script lang="ts">
|
|
17
|
-
import {
|
|
18
|
-
PIE_REGISTER_EVENT,
|
|
19
|
-
PIE_UNREGISTER_EVENT,
|
|
20
|
-
assessmentToolkitRegionScopeContext,
|
|
21
|
-
assessmentToolkitShellContext,
|
|
22
|
-
dispatchCrossBoundaryEvent,
|
|
23
|
-
type AssessmentToolkitRegionScopeContext,
|
|
24
|
-
type AssessmentToolkitShellContext,
|
|
25
|
-
type RuntimeRegistrationDetail,
|
|
26
|
-
} from "@pie-players/pie-assessment-toolkit";
|
|
27
|
-
import { ContextProvider, ContextRoot } from "@pie-players/pie-context";
|
|
28
|
-
|
|
29
|
-
const PIE_INTERNAL_CONTENT_LOADED_EVENT = "pie-content-loaded";
|
|
30
|
-
const PIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT = "pie-item-player-error";
|
|
31
|
-
type InternalContentLoadedDetail = {
|
|
32
|
-
itemId: string;
|
|
33
|
-
canonicalItemId?: string;
|
|
34
|
-
contentKind?: string;
|
|
35
|
-
detail?: unknown;
|
|
36
|
-
};
|
|
37
|
-
type InternalItemPlayerErrorDetail = {
|
|
38
|
-
itemId: string;
|
|
39
|
-
canonicalItemId?: string;
|
|
40
|
-
contentKind?: string;
|
|
41
|
-
error: unknown;
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
let {
|
|
45
|
-
itemId = "",
|
|
46
|
-
canonicalItemId = "",
|
|
47
|
-
contentKind = "rubric-block-stimulus",
|
|
48
|
-
regionPolicy = "default",
|
|
49
|
-
scopeElement = null as HTMLElement | null,
|
|
50
|
-
item = null as unknown,
|
|
51
|
-
} = $props();
|
|
52
|
-
|
|
53
|
-
let anchor = $state<HTMLDivElement | null>(null);
|
|
54
|
-
const shellContextVersion = Date.now();
|
|
55
|
-
let shellContextProvider: ContextProvider<
|
|
56
|
-
typeof assessmentToolkitShellContext
|
|
57
|
-
> | null = null;
|
|
58
|
-
let shellContextRoot: ContextRoot | null = null;
|
|
59
|
-
let regionScopeProvider: ContextProvider<
|
|
60
|
-
typeof assessmentToolkitRegionScopeContext
|
|
61
|
-
> | null = null;
|
|
62
|
-
let regionScopeRoot: ContextRoot | null = null;
|
|
63
|
-
|
|
64
|
-
function getHostElement(): HTMLElement | null {
|
|
65
|
-
if (!anchor) return null;
|
|
66
|
-
const rootNode = anchor.getRootNode();
|
|
67
|
-
if (rootNode && "host" in rootNode) {
|
|
68
|
-
return (rootNode as ShadowRoot).host as HTMLElement;
|
|
69
|
-
}
|
|
70
|
-
return anchor.parentElement as HTMLElement | null;
|
|
71
|
-
}
|
|
72
|
-
const host = $derived.by(() => getHostElement());
|
|
73
|
-
const effectiveScopeElement = $derived(scopeElement || host || null);
|
|
74
|
-
const regionScopeValue = $derived.by(
|
|
75
|
-
(): AssessmentToolkitRegionScopeContext | null => {
|
|
76
|
-
if (!effectiveScopeElement) return null;
|
|
77
|
-
return {
|
|
78
|
-
scopeElement: effectiveScopeElement,
|
|
79
|
-
};
|
|
80
|
-
},
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
const shellContextValue = $derived.by(
|
|
84
|
-
(): AssessmentToolkitShellContext | null => {
|
|
85
|
-
if (!host) return null;
|
|
86
|
-
const canonical = canonicalItemId || itemId;
|
|
87
|
-
return {
|
|
88
|
-
kind: "passage",
|
|
89
|
-
itemId,
|
|
90
|
-
canonicalItemId: canonical,
|
|
91
|
-
contentKind,
|
|
92
|
-
regionPolicy,
|
|
93
|
-
scopeElement: effectiveScopeElement,
|
|
94
|
-
item,
|
|
95
|
-
contextVersion: shellContextVersion,
|
|
96
|
-
};
|
|
97
|
-
},
|
|
98
|
-
);
|
|
99
|
-
|
|
100
|
-
function dispatchRegistration(eventName: string): void {
|
|
101
|
-
if (!host || !itemId) return;
|
|
102
|
-
const detail: RuntimeRegistrationDetail = {
|
|
103
|
-
kind: "passage",
|
|
104
|
-
itemId,
|
|
105
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
106
|
-
contentKind,
|
|
107
|
-
item,
|
|
108
|
-
element: host,
|
|
109
|
-
};
|
|
110
|
-
dispatchCrossBoundaryEvent(host, eventName, detail);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
function dispatchLoaded(detail: unknown): void {
|
|
114
|
-
if (!host || !itemId) return;
|
|
115
|
-
const payload: InternalContentLoadedDetail = {
|
|
116
|
-
itemId,
|
|
117
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
118
|
-
contentKind,
|
|
119
|
-
detail,
|
|
120
|
-
};
|
|
121
|
-
dispatchCrossBoundaryEvent(host, PIE_INTERNAL_CONTENT_LOADED_EVENT, payload);
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
function dispatchPlayerError(error: unknown): void {
|
|
125
|
-
if (!host || !itemId) return;
|
|
126
|
-
const payload: InternalItemPlayerErrorDetail = {
|
|
127
|
-
itemId,
|
|
128
|
-
canonicalItemId: canonicalItemId || itemId,
|
|
129
|
-
contentKind,
|
|
130
|
-
error,
|
|
131
|
-
};
|
|
132
|
-
dispatchCrossBoundaryEvent(host, PIE_INTERNAL_ITEM_PLAYER_ERROR_EVENT, payload);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
$effect(() => {
|
|
136
|
-
if (!host) return;
|
|
137
|
-
dispatchRegistration(PIE_REGISTER_EVENT);
|
|
138
|
-
const onLoadComplete = (event: Event) => {
|
|
139
|
-
event.stopPropagation();
|
|
140
|
-
dispatchLoaded((event as CustomEvent).detail);
|
|
141
|
-
};
|
|
142
|
-
const onPlayerError = (event: Event) => {
|
|
143
|
-
event.stopPropagation();
|
|
144
|
-
dispatchPlayerError((event as CustomEvent).detail);
|
|
145
|
-
};
|
|
146
|
-
host.addEventListener("load-complete", onLoadComplete);
|
|
147
|
-
host.addEventListener("player-error", onPlayerError);
|
|
148
|
-
|
|
149
|
-
return () => {
|
|
150
|
-
host?.removeEventListener("load-complete", onLoadComplete);
|
|
151
|
-
host?.removeEventListener("player-error", onPlayerError);
|
|
152
|
-
dispatchRegistration(PIE_UNREGISTER_EVENT);
|
|
153
|
-
};
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
$effect(() => {
|
|
157
|
-
if (!host) return;
|
|
158
|
-
host.setAttribute("data-item-id", itemId);
|
|
159
|
-
host.setAttribute("data-canonical-item-id", canonicalItemId || itemId);
|
|
160
|
-
host.setAttribute("data-pie-shell-root", "passage");
|
|
161
|
-
host.setAttribute("data-region-policy", regionPolicy);
|
|
162
|
-
});
|
|
163
|
-
|
|
164
|
-
$effect(() => {
|
|
165
|
-
if (!host || !shellContextValue) return;
|
|
166
|
-
shellContextProvider = new ContextProvider(host, {
|
|
167
|
-
context: assessmentToolkitShellContext,
|
|
168
|
-
initialValue: shellContextValue,
|
|
169
|
-
});
|
|
170
|
-
shellContextProvider.connect();
|
|
171
|
-
shellContextRoot = new ContextRoot(host);
|
|
172
|
-
shellContextRoot.attach();
|
|
173
|
-
|
|
174
|
-
return () => {
|
|
175
|
-
shellContextRoot?.detach();
|
|
176
|
-
shellContextRoot = null;
|
|
177
|
-
shellContextProvider?.disconnect();
|
|
178
|
-
shellContextProvider = null;
|
|
179
|
-
};
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
$effect(() => {
|
|
183
|
-
if (!shellContextValue) return;
|
|
184
|
-
shellContextProvider?.setValue(shellContextValue);
|
|
185
|
-
});
|
|
186
|
-
|
|
187
|
-
$effect(() => {
|
|
188
|
-
if (!host || !regionScopeValue) return;
|
|
189
|
-
regionScopeProvider = new ContextProvider(host, {
|
|
190
|
-
context: assessmentToolkitRegionScopeContext,
|
|
191
|
-
initialValue: regionScopeValue,
|
|
192
|
-
});
|
|
193
|
-
regionScopeProvider.connect();
|
|
194
|
-
regionScopeRoot = new ContextRoot(host);
|
|
195
|
-
regionScopeRoot.attach();
|
|
196
|
-
return () => {
|
|
197
|
-
regionScopeRoot?.detach();
|
|
198
|
-
regionScopeRoot = null;
|
|
199
|
-
regionScopeProvider?.disconnect();
|
|
200
|
-
regionScopeProvider = null;
|
|
201
|
-
};
|
|
202
|
-
});
|
|
203
|
-
|
|
204
|
-
$effect(() => {
|
|
205
|
-
if (!regionScopeValue) return;
|
|
206
|
-
regionScopeProvider?.setValue(regionScopeValue);
|
|
207
|
-
});
|
|
208
|
-
</script>
|
|
209
|
-
|
|
210
|
-
<div bind:this={anchor} class="pie-passage-shell-anchor" aria-hidden="true"></div>
|
|
211
|
-
<slot></slot>
|
|
212
|
-
|
|
213
|
-
<style>
|
|
214
|
-
.pie-passage-shell-anchor {
|
|
215
|
-
display: none;
|
|
216
|
-
}
|
|
217
|
-
</style>
|