@pie-players/pie-section-player 0.2.12 → 0.2.13

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 (62) hide show
  1. package/README.md +28 -568
  2. package/dist/component-definitions.d.ts +0 -3
  3. package/dist/component-definitions.d.ts.map +1 -1
  4. package/dist/components/section-player-vertical-element.d.ts +2 -0
  5. package/dist/components/section-player-vertical-element.d.ts.map +1 -0
  6. package/dist/components/shared/composition.d.ts +9 -0
  7. package/dist/components/shared/composition.d.ts.map +1 -0
  8. package/dist/components/shared/player-action.d.ts +18 -0
  9. package/dist/components/shared/player-action.d.ts.map +1 -0
  10. package/dist/components/shared/player-preload.d.ts +37 -0
  11. package/dist/components/shared/player-preload.d.ts.map +1 -0
  12. package/dist/components/shared/section-player-runtime.d.ts +104 -0
  13. package/dist/components/shared/section-player-runtime.d.ts.map +1 -0
  14. package/dist/components/shared/section-player-view-state.d.ts +24 -0
  15. package/dist/components/shared/section-player-view-state.d.ts.map +1 -0
  16. package/dist/controllers/SectionContentService.d.ts.map +1 -1
  17. package/dist/controllers/SectionController.d.ts +5 -1
  18. package/dist/controllers/SectionController.d.ts.map +1 -1
  19. package/dist/controllers/SectionSessionService.d.ts +0 -1
  20. package/dist/controllers/SectionSessionService.d.ts.map +1 -1
  21. package/dist/controllers/toolkit-section-contracts.d.ts +2 -28
  22. package/dist/controllers/toolkit-section-contracts.d.ts.map +1 -1
  23. package/dist/controllers/types.d.ts +28 -1
  24. package/dist/controllers/types.d.ts.map +1 -1
  25. package/dist/pie-item-player-B1iGN63e.js +6189 -0
  26. package/dist/pie-section-player.d.ts +0 -8
  27. package/dist/pie-section-player.d.ts.map +1 -1
  28. package/dist/pie-section-player.js +56558 -11
  29. package/dist/player-preload-CQVG0Bih.js +705 -0
  30. package/dist/utils/player-preload.d.ts +2 -0
  31. package/dist/utils/player-preload.d.ts.map +1 -0
  32. package/dist/utils/player-preload.js +8 -0
  33. package/package.json +23 -32
  34. package/src/components/ItemShellElement.svelte +10 -1
  35. package/src/components/PieSectionPlayerBaseElement.svelte +21 -78
  36. package/src/components/PieSectionPlayerSplitPaneElement.svelte +236 -295
  37. package/src/components/PieSectionPlayerVerticalElement.svelte +424 -0
  38. package/src/components/shared/SectionItemCard.svelte +92 -0
  39. package/src/components/shared/SectionPassageCard.svelte +88 -0
  40. package/dist/ItemRenderer-MsjF_Beu.js +0 -467
  41. package/dist/PieItemModeLayoutElement-D7oTzA9T.js +0 -316
  42. package/dist/PieSplitPanelLayoutElement-GUtJ_NlF.js +0 -246
  43. package/dist/PieVerticalLayoutElement-BoA3FO5g.js +0 -194
  44. package/dist/controllers/SectionToolkitService.d.ts +0 -24
  45. package/dist/controllers/SectionToolkitService.d.ts.map +0 -1
  46. package/dist/controllers/SessionPersistenceStrategy.d.ts +0 -15
  47. package/dist/controllers/SessionPersistenceStrategy.d.ts.map +0 -1
  48. package/dist/index.d.ts +0 -2
  49. package/dist/pie-section-player-DJ5NcwdT.js +0 -17078
  50. package/dist/runtime/runtime-event-guards.d.ts +0 -4
  51. package/dist/runtime/runtime-event-guards.d.ts.map +0 -1
  52. package/src/PieSectionPlayer.svelte +0 -826
  53. package/src/components/ItemModeLayout.svelte +0 -172
  54. package/src/components/ItemNavigation.svelte +0 -96
  55. package/src/components/ItemPlayerBridge.svelte +0 -110
  56. package/src/components/ItemRenderer.svelte +0 -248
  57. package/src/components/ItemShell.svelte +0 -86
  58. package/src/components/layout-elements/PieItemModeLayoutElement.svelte +0 -47
  59. package/src/components/layout-elements/PieSplitPanelLayoutElement.svelte +0 -62
  60. package/src/components/layout-elements/PieVerticalLayoutElement.svelte +0 -41
  61. package/src/components/layouts/SplitPanelLayout.svelte +0 -385
  62. package/src/components/layouts/VerticalLayout.svelte +0 -193
@@ -9,7 +9,6 @@
9
9
  section: { type: "Object", reflect: false },
10
10
  sectionId: { attribute: "section-id", type: "String" },
11
11
  attemptId: { attribute: "attempt-id", type: "String" },
12
- view: { type: "String" },
13
12
  playerType: { attribute: "player-type", type: "String" },
14
13
  player: { type: "Object", reflect: false },
15
14
  lazyInit: { attribute: "lazy-init", type: "Boolean" },
@@ -31,70 +30,67 @@
31
30
 
32
31
  <script lang="ts">
33
32
  import "./section-player-base-element.js";
34
- import "./item-shell-element.js";
35
- import "./passage-shell-element.js";
36
- import "@pie-players/pie-iife-player";
37
- import "@pie-players/pie-section-tools-toolbar";
38
- import "@pie-players/pie-assessment-toolkit/components/item-toolbar-element";
39
- import "@pie-players/pie-tool-calculator-inline";
33
+ import * as SectionItemCardModule from "./shared/SectionItemCard.svelte";
34
+ import * as SectionPassageCardModule from "./shared/SectionPassageCard.svelte";
35
+ import "@pie-players/pie-toolbars/components/section-toolbar-element";
40
36
  import "@pie-players/pie-tool-calculator";
41
- import {
42
- normalizeToolsConfig,
43
- parseToolList,
44
- } from "@pie-players/pie-assessment-toolkit";
45
- import { IifeElementLoader } from "@pie-players/pie-players-shared";
37
+ import "@pie-players/pie-tool-graph";
38
+ import "@pie-players/pie-tool-periodic-table";
39
+ import "@pie-players/pie-tool-protractor";
40
+ import "@pie-players/pie-tool-line-reader";
41
+ import "@pie-players/pie-tool-ruler";
42
+ import "@pie-players/pie-tool-theme";
43
+ import type { Component } from "svelte";
46
44
  import type { SectionCompositionModel } from "../controllers/types.js";
47
- import type { AssessmentSection, ItemEntity } from "@pie-players/pie-players-shared/types";
48
-
49
- const EMPTY_COMPOSITION: SectionCompositionModel = {
50
- section: null,
51
- assessmentItemRefs: [],
52
- passages: [],
53
- items: [],
54
- rubricBlocks: [],
55
- instructions: [],
56
- currentItemIndex: 0,
57
- currentItem: null,
58
- isPageMode: false,
59
- itemSessionsByItemId: {},
60
- testAttemptSession: null,
61
- };
62
- const DEFAULT_ASSESSMENT_ID = "section-demo-direct";
63
- const DEFAULT_PLAYER_TYPE = "iife";
64
- const DEFAULT_LAZY_INIT = true;
65
- const DEFAULT_ISOLATION = "inherit";
66
- const LEGACY_RUNTIME_WARNING_KEY = "pie-section-player-splitpane:legacy-runtime-props";
67
- const warnedKeys = new Set<string>();
68
- type RuntimeConfig = {
69
- assessmentId?: string;
70
- playerType?: string;
71
- player?: Record<string, unknown> | null;
72
- lazyInit?: boolean;
73
- tools?: Record<string, unknown> | null;
74
- accessibility?: Record<string, unknown> | null;
75
- coordinator?: unknown;
76
- createSectionController?: unknown;
77
- isolation?: string;
78
- env?: Record<string, unknown>;
79
- };
45
+ import type { AssessmentSection } from "@pie-players/pie-players-shared/types";
46
+ import {
47
+ EMPTY_COMPOSITION,
48
+ } from "./shared/composition.js";
49
+ import {
50
+ createPlayerAction,
51
+ } from "./shared/player-action.js";
52
+ import {
53
+ getRenderablesSignature,
54
+ orchestratePlayerElementPreload,
55
+ type PlayerPreloadState,
56
+ } from "./shared/player-preload.js";
57
+ import {
58
+ getCanonicalItemId,
59
+ getCompositionFromEvent,
60
+ getItemPlayerParams,
61
+ getPassagePlayerParams,
62
+ } from "./shared/section-player-view-state.js";
63
+ import {
64
+ type RuntimeConfig,
65
+ mapRenderablesToItems,
66
+ resolveSectionPlayerRuntimeState,
67
+ } from "./shared/section-player-runtime.js";
68
+
69
+ const SectionItemCard = (
70
+ SectionItemCardModule as unknown as { default: Component<any, any, any> }
71
+ ).default;
72
+ const SectionPassageCard = (
73
+ SectionPassageCardModule as unknown as {
74
+ default: Component<any, any, any>;
75
+ }
76
+ ).default;
80
77
 
81
78
  let {
82
- assessmentId = DEFAULT_ASSESSMENT_ID,
79
+ assessmentId,
83
80
  runtime = null as RuntimeConfig | null,
84
81
  section = null as AssessmentSection | null,
85
82
  sectionId = "",
86
83
  attemptId = "",
87
- view = "candidate",
88
- playerType = DEFAULT_PLAYER_TYPE,
89
- player = null as Record<string, unknown> | null,
90
- lazyInit = DEFAULT_LAZY_INIT,
91
- tools = null as Record<string, unknown> | null,
92
- accessibility = null as Record<string, unknown> | null,
93
- coordinator = null as unknown,
94
- createSectionController = null as unknown,
95
- isolation = DEFAULT_ISOLATION,
96
- env = { mode: "gather", role: "student" } as Record<string, unknown>,
97
- iifeBundleHost = "https://proxy.pie-api.com/bundles",
84
+ playerType,
85
+ player,
86
+ lazyInit,
87
+ tools,
88
+ accessibility,
89
+ coordinator,
90
+ createSectionController,
91
+ isolation,
92
+ env,
93
+ iifeBundleHost,
98
94
  showToolbar = true,
99
95
  toolbarPosition = "right",
100
96
  enabledTools = "",
@@ -107,58 +103,57 @@
107
103
  let isDragging = $state(false);
108
104
  let splitContainerElement = $state<HTMLDivElement | null>(null);
109
105
  let elementsLoaded = $state(false);
106
+ let lastPreloadSignature = $state("");
107
+ let preloadRunToken = $state(0);
110
108
 
111
109
  const passages = $derived(compositionModel.passages || []);
112
110
  const items = $derived(compositionModel.items || []);
113
- const itemSessionsByItemId = $derived(compositionModel.itemSessionsByItemId || {});
114
111
  const hasPassages = $derived(passages.length > 0);
115
112
  const shouldRenderToolbar = $derived(showToolbar && toolbarPosition !== "none");
116
113
  const toolbarBeforeContent = $derived(
117
114
  toolbarPosition === "top" || toolbarPosition === "left",
118
115
  );
119
116
  const toolbarInline = $derived(toolbarPosition === "left" || toolbarPosition === "right");
120
- const preloadedRenderables = $derived.by(() => [
121
- ...(passages as unknown as ItemEntity[]),
122
- ...(items as ItemEntity[]),
123
- ]);
124
- const effectiveToolsConfig = $derived.by(() => {
125
- const runtimeTools = ((runtime as RuntimeConfig | null)?.tools || tools || {}) as any;
126
- const normalized = normalizeToolsConfig(runtimeTools);
127
- const sectionTools = parseToolList(enabledTools);
128
- const itemTools = parseToolList(itemToolbarTools);
129
- const passageTools = parseToolList(passageToolbarTools);
130
- return normalizeToolsConfig({
131
- ...normalized,
132
- placement: {
133
- ...normalized.placement,
134
- section: sectionTools.length > 0 ? sectionTools : normalized.placement.section,
135
- item: itemTools.length > 0 ? itemTools : normalized.placement.item,
136
- passage: passageTools.length > 0 ? passageTools : normalized.placement.passage,
137
- },
138
- });
117
+ const preloadedRenderables = $derived.by(() =>
118
+ mapRenderablesToItems(compositionModel.renderables || []),
119
+ );
120
+ const preloadedRenderablesSignature = $derived.by(() =>
121
+ getRenderablesSignature(compositionModel.renderables || []),
122
+ );
123
+ const runtimeState = $derived.by(() =>
124
+ resolveSectionPlayerRuntimeState({
125
+ assessmentId,
126
+ playerType,
127
+ player,
128
+ lazyInit,
129
+ tools,
130
+ accessibility,
131
+ coordinator,
132
+ createSectionController,
133
+ isolation,
134
+ env,
135
+ runtime,
136
+ enabledTools,
137
+ itemToolbarTools,
138
+ passageToolbarTools,
139
+ }),
140
+ );
141
+ const effectiveRuntime = $derived(runtimeState.effectiveRuntime);
142
+ const playerRuntime = $derived(runtimeState.playerRuntime);
143
+ const resolvedPlayerDefinition = $derived(playerRuntime.resolvedPlayerDefinition);
144
+ const resolvedPlayerTag = $derived(playerRuntime.resolvedPlayerTag);
145
+ const resolvedPlayerAttributes = $derived(playerRuntime.resolvedPlayerAttributes);
146
+ const resolvedPlayerProps = $derived(playerRuntime.resolvedPlayerProps);
147
+ const resolvedPlayerEnv = $derived(playerRuntime.resolvedPlayerEnv);
148
+ const playerStrategy = $derived(playerRuntime.strategy);
149
+ const splitPanePlayerAction = createPlayerAction({
150
+ stateKey: "__splitPaneAppliedParams",
151
+ setSkipElementLoadingOnce: true,
152
+ includeSessionRefInState: true,
139
153
  });
140
- const effectiveRuntime = $derived.by(() => ({
141
- assessmentId,
142
- playerType,
143
- player,
144
- lazyInit,
145
- accessibility,
146
- coordinator,
147
- createSectionController,
148
- isolation,
149
- env,
150
- ...(runtime || {}),
151
- tools: effectiveToolsConfig,
152
- }));
153
154
 
154
155
  function handleBaseCompositionChanged(event: Event) {
155
- const detail = (event as CustomEvent<{ composition?: SectionCompositionModel }>).detail;
156
- compositionModel = detail?.composition || EMPTY_COMPOSITION;
157
- }
158
-
159
- function getSessionForItem(item: ItemEntity): unknown {
160
- const itemId = item.id || "";
161
- return itemSessionsByItemId[itemId];
156
+ compositionModel = getCompositionFromEvent(event);
162
157
  }
163
158
 
164
159
  function handleDividerMouseDown(event: MouseEvent) {
@@ -208,234 +203,172 @@
208
203
  });
209
204
 
210
205
  $effect(() => {
211
- const renderables = preloadedRenderables;
212
- if (renderables.length === 0) {
213
- elementsLoaded = true;
214
- return;
215
- }
216
-
217
- const bundleHost = String(iifeBundleHost || "").trim();
218
- if (!bundleHost) {
219
- console.warn(
220
- "[pie-section-player-splitpane] Missing iifeBundleHost for element preloading; rendering without preload.",
221
- );
222
- elementsLoaded = true;
223
- return;
224
- }
225
-
226
- let cancelled = false;
227
- elementsLoaded = false;
228
- const loader = new IifeElementLoader({
229
- bundleHost,
230
- debugEnabled: () => false,
206
+ resolvedPlayerDefinition?.ensureDefined?.().catch((error) => {
207
+ console.error("[pie-section-player-splitpane] Failed to load item player component:", error);
231
208
  });
232
- const loaderView = (env as any)?.mode === "author" ? "author" : "delivery";
233
-
234
- void loader
235
- .loadFromItems(renderables, {
236
- view: loaderView,
237
- needsControllers: true,
238
- })
239
- .then(() => {
240
- if (!cancelled) elementsLoaded = true;
241
- })
242
- .catch((error) => {
243
- console.error(
244
- "[pie-section-player-splitpane] Failed to preload PIE elements:",
245
- error,
246
- );
247
- if (!cancelled) elementsLoaded = true;
248
- });
249
-
250
- return () => {
251
- cancelled = true;
252
- };
253
209
  });
254
210
 
255
211
  $effect(() => {
256
- if (typeof window === "undefined" || runtime) return;
257
- const usedLegacyProps: string[] = [];
258
- if (assessmentId !== DEFAULT_ASSESSMENT_ID) usedLegacyProps.push("assessmentId");
259
- if (playerType !== DEFAULT_PLAYER_TYPE) usedLegacyProps.push("playerType");
260
- if (player !== null) usedLegacyProps.push("player");
261
- if (lazyInit !== DEFAULT_LAZY_INIT) usedLegacyProps.push("lazyInit");
262
- if (tools !== null) usedLegacyProps.push("tools");
263
- if (accessibility !== null) usedLegacyProps.push("accessibility");
264
- if (coordinator !== null) usedLegacyProps.push("coordinator");
265
- if (createSectionController !== null) usedLegacyProps.push("createSectionController");
266
- if (isolation !== DEFAULT_ISOLATION) usedLegacyProps.push("isolation");
267
- const key = `${LEGACY_RUNTIME_WARNING_KEY}:${usedLegacyProps.sort().join(",")}`;
268
- if (usedLegacyProps.length === 0 || warnedKeys.has(key)) return;
269
- warnedKeys.add(key);
270
- console.warn(
271
- `[pie-section-player-splitpane] Runtime props (${usedLegacyProps.join(", ")}) are deprecated. Prefer the \`runtime\` object prop.`,
272
- );
212
+ orchestratePlayerElementPreload({
213
+ componentTag: "pie-section-player-splitpane",
214
+ strategy: playerStrategy,
215
+ renderables: preloadedRenderables,
216
+ renderablesSignature: preloadedRenderablesSignature,
217
+ resolvedPlayerProps: resolvedPlayerProps as Record<string, unknown>,
218
+ resolvedPlayerEnv: resolvedPlayerEnv as Record<string, unknown>,
219
+ iifeBundleHost,
220
+ getState: () =>
221
+ ({
222
+ lastPreloadSignature,
223
+ preloadRunToken,
224
+ elementsLoaded,
225
+ }) as PlayerPreloadState,
226
+ setState: (next) => {
227
+ if (next.lastPreloadSignature !== undefined) {
228
+ lastPreloadSignature = next.lastPreloadSignature;
229
+ }
230
+ if (next.preloadRunToken !== undefined) {
231
+ preloadRunToken = next.preloadRunToken;
232
+ }
233
+ if (next.elementsLoaded !== undefined) {
234
+ elementsLoaded = next.elementsLoaded;
235
+ }
236
+ },
237
+ });
273
238
  });
274
239
 
275
240
  </script>
276
241
 
277
242
  <pie-section-player-base
278
243
  runtime={effectiveRuntime}
279
- {assessmentId}
280
244
  {section}
281
245
  section-id={sectionId}
282
246
  attempt-id={attemptId}
283
- {view}
284
- player-type={playerType}
285
- {player}
286
- lazy-init={lazyInit}
287
- {tools}
288
- {accessibility}
289
- {coordinator}
290
- create-section-controller={createSectionController}
291
- {isolation}
292
247
  oncomposition-changed={handleBaseCompositionChanged}
293
248
  >
294
- <div class={`player-shell player-shell--${toolbarPosition}`}>
249
+ <div
250
+ class={`pie-section-player-shell pie-section-player-shell--${toolbarPosition}`}
251
+ >
295
252
  {#if shouldRenderToolbar && toolbarBeforeContent}
296
- <pie-section-tools-toolbar
297
- class={`section-toolbar section-toolbar--${toolbarPosition}`}
253
+ <pie-section-toolbar
254
+ class={`pie-section-player-toolbar pie-section-player-toolbar--${toolbarPosition}`}
298
255
  position={toolbarPosition}
299
256
  enabled-tools={enabledTools}
300
- ></pie-section-tools-toolbar>
257
+ ></pie-section-toolbar>
301
258
  {/if}
302
259
 
303
- <div class={`layout-body ${toolbarInline ? "layout-body--inline" : ""}`}>
260
+ <div
261
+ class={`pie-section-player-layout-body ${toolbarInline ? "pie-section-player-layout-body--inline" : ""}`}
262
+ >
304
263
  <div
305
- class={`split-content ${!hasPassages ? "split-content--no-passages" : ""}`}
264
+ class={`pie-section-player-split-content ${!hasPassages ? "pie-section-player-split-content--no-passages" : ""}`}
306
265
  bind:this={splitContainerElement}
307
266
  style={hasPassages
308
267
  ? `grid-template-columns: ${leftPanelWidth}% 0.5rem ${100 - leftPanelWidth - 0.5}%`
309
268
  : "grid-template-columns: 1fr"}
310
269
  >
311
270
  {#if hasPassages}
312
- <aside class="passages-pane" aria-label="Passages">
271
+ <aside class="pie-section-player-passages-pane" aria-label="Passages">
313
272
  {#if !elementsLoaded}
314
- <div class="content-card">
315
- <div class="content-card-body passage-content pie-section-player__passage-content">
273
+ <div class="pie-section-player-content-card">
274
+ <div
275
+ class="pie-section-player-content-card-body pie-section-player-passage-content pie-section-player__passage-content"
276
+ >
316
277
  Loading passage content...
317
278
  </div>
318
279
  </div>
319
280
  {:else}
320
281
  {#each passages as passage, passageIndex (passage.id || passageIndex)}
321
- <pie-passage-shell
322
- item-id={passage.id}
323
- content-kind="rubric-block-stimulus"
324
- item={passage}
325
- >
326
- <div class="content-card">
327
- <div
328
- class="content-card-header passage-header pie-section-player__passage-header"
329
- data-region="header"
330
- >
331
- <h2>Passage {passageIndex + 1}</h2>
332
- <pie-item-toolbar
333
- item-id={passage.id}
334
- catalog-id={passage.id}
335
- tools={passageToolbarTools}
336
- content-kind="rubric-block-stimulus"
337
- size="md"
338
- language="en-US"
339
- ></pie-item-toolbar>
340
- </div>
341
- <div
342
- class="content-card-body passage-content pie-section-player__passage-content"
343
- data-region="content"
344
- >
345
- <pie-iife-player
346
- config={JSON.stringify(passage.config || {})}
347
- env={JSON.stringify({ mode: "view", role: (env as any)?.role || "student" })}
348
- bundle-host={iifeBundleHost}
349
- skip-element-loading={true}
350
- ></pie-iife-player>
351
- </div>
352
- </div>
353
- </pie-passage-shell>
282
+ <SectionPassageCard
283
+ {passage}
284
+ {resolvedPlayerTag}
285
+ playerAction={splitPanePlayerAction}
286
+ playerParams={getPassagePlayerParams({
287
+ passage,
288
+ resolvedPlayerEnv,
289
+ resolvedPlayerAttributes,
290
+ resolvedPlayerProps,
291
+ playerStrategy,
292
+ })}
293
+ {passageToolbarTools}
294
+ />
354
295
  {/each}
355
296
  {/if}
356
297
  </aside>
357
298
 
358
299
  <button
359
300
  type="button"
360
- class={`split-divider ${isDragging ? "split-divider--dragging" : ""}`}
301
+ class={`pie-section-player-split-divider ${isDragging ? "pie-section-player-split-divider--dragging" : ""}`}
361
302
  onmousedown={handleDividerMouseDown}
362
303
  onkeydown={handleDividerKeyDown}
363
304
  aria-label="Resize panels"
364
305
  >
365
- <span class="split-divider-handle"></span>
306
+ <span class="pie-section-player-split-divider-handle"></span>
366
307
  </button>
367
308
  {/if}
368
309
 
369
- <main class="items-pane" aria-label="Items">
310
+ <main class="pie-section-player-items-pane" aria-label="Items">
370
311
  {#if !elementsLoaded}
371
- <div class="content-card">
372
- <div class="content-card-body item-content pie-section-player__item-content">
312
+ <div class="pie-section-player-content-card">
313
+ <div
314
+ class="pie-section-player-content-card-body pie-section-player-item-content pie-section-player__item-content"
315
+ >
373
316
  Loading section content...
374
317
  </div>
375
318
  </div>
376
319
  {:else}
377
320
  {#each items as item, itemIndex (item.id || itemIndex)}
378
- <pie-item-shell item-id={item.id} content-kind="assessment-item" item={item}>
379
- <div class="content-card">
380
- <div
381
- class="content-card-header item-header pie-section-player__item-header"
382
- data-region="header"
383
- >
384
- <h2>Question {itemIndex + 1}</h2>
385
- <pie-item-toolbar
386
- item-id={item.id}
387
- catalog-id={item.id}
388
- tools={itemToolbarTools}
389
- content-kind="assessment-item"
390
- size="md"
391
- language="en-US"
392
- ></pie-item-toolbar>
393
- </div>
394
- <div
395
- class="content-card-body item-content pie-section-player__item-content"
396
- data-region="content"
397
- >
398
- <pie-iife-player
399
- config={JSON.stringify(item.config || {})}
400
- env={JSON.stringify(env)}
401
- session={JSON.stringify(getSessionForItem(item) || { id: "", data: [] })}
402
- bundle-host={iifeBundleHost}
403
- skip-element-loading={true}
404
- ></pie-iife-player>
405
- </div>
406
- <div data-region="footer"></div>
407
- </div>
408
- </pie-item-shell>
321
+ <SectionItemCard
322
+ {item}
323
+ canonicalItemId={getCanonicalItemId({ compositionModel, item })}
324
+ {resolvedPlayerTag}
325
+ playerAction={splitPanePlayerAction}
326
+ playerParams={getItemPlayerParams({
327
+ item,
328
+ compositionModel,
329
+ resolvedPlayerEnv,
330
+ resolvedPlayerAttributes,
331
+ resolvedPlayerProps,
332
+ playerStrategy,
333
+ })}
334
+ {itemToolbarTools}
335
+ />
409
336
  {/each}
410
337
  {/if}
411
338
  </main>
412
339
  </div>
413
340
 
414
341
  {#if shouldRenderToolbar && toolbarInline && toolbarPosition === "right"}
415
- <aside class="section-toolbar-pane section-toolbar-pane--right" aria-label="Section tools">
416
- <pie-section-tools-toolbar
342
+ <aside
343
+ class="pie-section-player-toolbar-pane pie-section-player-toolbar-pane--right"
344
+ aria-label="Section tools"
345
+ >
346
+ <pie-section-toolbar
417
347
  position="right"
418
348
  enabled-tools={enabledTools}
419
- ></pie-section-tools-toolbar>
349
+ ></pie-section-toolbar>
420
350
  </aside>
421
351
  {/if}
422
352
 
423
353
  {#if shouldRenderToolbar && toolbarInline && toolbarPosition === "left"}
424
- <aside class="section-toolbar-pane section-toolbar-pane--left" aria-label="Section tools">
425
- <pie-section-tools-toolbar
354
+ <aside
355
+ class="pie-section-player-toolbar-pane pie-section-player-toolbar-pane--left"
356
+ aria-label="Section tools"
357
+ >
358
+ <pie-section-toolbar
426
359
  position="left"
427
360
  enabled-tools={enabledTools}
428
- ></pie-section-tools-toolbar>
361
+ ></pie-section-toolbar>
429
362
  </aside>
430
363
  {/if}
431
364
  </div>
432
365
 
433
366
  {#if shouldRenderToolbar && !toolbarBeforeContent && !toolbarInline}
434
- <pie-section-tools-toolbar
435
- class={`section-toolbar section-toolbar--${toolbarPosition}`}
367
+ <pie-section-toolbar
368
+ class={`pie-section-player-toolbar pie-section-player-toolbar--${toolbarPosition}`}
436
369
  position={toolbarPosition}
437
370
  enabled-tools={enabledTools}
438
- ></pie-section-tools-toolbar>
371
+ ></pie-section-toolbar>
439
372
  {/if}
440
373
  </div>
441
374
  </pie-section-player-base>
@@ -450,41 +383,43 @@
450
383
  overflow: hidden;
451
384
  }
452
385
 
453
- .player-shell {
386
+ .pie-section-player-shell {
454
387
  display: flex;
455
388
  flex-direction: column;
456
389
  height: 100%;
457
390
  min-height: 0;
458
391
  overflow: hidden;
392
+ background: var(--pie-background-dark, #ecedf1);
459
393
  }
460
394
 
461
- .player-shell--left,
462
- .player-shell--right {
395
+ .pie-section-player-shell--left,
396
+ .pie-section-player-shell--right {
463
397
  flex-direction: row;
464
398
  }
465
399
 
466
- .player-shell--left .layout-body--inline {
400
+ .pie-section-player-shell--left .pie-section-player-layout-body--inline {
467
401
  order: 2;
468
402
  }
469
403
 
470
- .player-shell--left .section-toolbar-pane--left {
404
+ .pie-section-player-shell--left .pie-section-player-toolbar-pane--left {
471
405
  order: 1;
472
406
  }
473
407
 
474
- .layout-body {
408
+ .pie-section-player-layout-body {
475
409
  display: grid;
476
410
  grid-template-columns: minmax(0, 1fr);
477
411
  flex: 1;
478
412
  min-height: 0;
479
413
  overflow: hidden;
414
+ background: var(--pie-background-dark, #ecedf1);
480
415
  }
481
416
 
482
- .layout-body--inline {
417
+ .pie-section-player-layout-body--inline {
483
418
  grid-template-columns: minmax(0, 1fr) auto;
484
419
  gap: 1rem;
485
420
  }
486
421
 
487
- .split-content {
422
+ .pie-section-player-split-content {
488
423
  display: grid;
489
424
  gap: 0;
490
425
  min-height: 0;
@@ -492,12 +427,12 @@
492
427
  overflow: hidden;
493
428
  }
494
429
 
495
- .split-content--no-passages .items-pane {
496
- padding-left: 0;
430
+ .pie-section-player-split-content--no-passages .pie-section-player-items-pane {
431
+ padding-left: 0.5rem;
497
432
  }
498
433
 
499
- .passages-pane,
500
- .items-pane {
434
+ .pie-section-player-passages-pane,
435
+ .pie-section-player-items-pane {
501
436
  height: 100%;
502
437
  max-height: 100%;
503
438
  min-height: 0;
@@ -508,24 +443,36 @@
508
443
  display: flex;
509
444
  flex-direction: column;
510
445
  gap: 1rem;
446
+ padding: 0.5rem;
447
+ box-sizing: border-box;
448
+ background: var(--pie-background-dark, #ecedf1);
511
449
  }
512
450
 
513
- .section-toolbar-pane {
451
+ .pie-section-player-toolbar-pane {
514
452
  min-height: 0;
515
453
  overflow: auto;
454
+ padding: 0.5rem;
455
+ box-sizing: border-box;
456
+ background: var(--pie-background-dark, #ecedf1);
516
457
  }
517
458
 
518
- .section-toolbar-pane--right {
459
+ .pie-section-player-toolbar-pane--right {
519
460
  border-left: 1px solid var(--pie-border-light, #e5e7eb);
520
- padding-left: 0.5rem;
521
461
  }
522
462
 
523
- .section-toolbar-pane--left {
463
+ .pie-section-player-toolbar-pane--left {
524
464
  border-right: 1px solid var(--pie-border-light, #e5e7eb);
525
- padding-right: 0.5rem;
526
465
  }
527
466
 
528
- .split-divider {
467
+ .pie-section-player-toolbar {
468
+ margin: 0.5rem;
469
+ }
470
+
471
+ .pie-section-player-toolbar-pane pie-section-toolbar {
472
+ margin: 0.5rem;
473
+ }
474
+
475
+ .pie-section-player-split-divider {
529
476
  border: none;
530
477
  padding: 0;
531
478
  margin: 0;
@@ -544,16 +491,16 @@
544
491
  transition: background 0.2s ease;
545
492
  }
546
493
 
547
- .split-divider:hover {
494
+ .pie-section-player-split-divider:hover {
548
495
  background: var(--pie-border-light, #e5e7eb);
549
496
  }
550
497
 
551
- .split-divider:focus {
498
+ .pie-section-player-split-divider:focus {
552
499
  outline: 2px solid var(--pie-focus-checked-border, #1976d2);
553
500
  outline-offset: -2px;
554
501
  }
555
502
 
556
- .split-divider-handle {
503
+ .pie-section-player-split-divider-handle {
557
504
  position: absolute;
558
505
  inset: 0;
559
506
  margin: auto;
@@ -565,7 +512,7 @@
565
512
  pointer-events: none;
566
513
  }
567
514
 
568
- .split-divider-handle::before {
515
+ .pie-section-player-split-divider-handle::before {
569
516
  content: "";
570
517
  position: absolute;
571
518
  top: 50%;
@@ -578,25 +525,25 @@
578
525
  opacity: 0.8;
579
526
  }
580
527
 
581
- .split-divider:hover .split-divider-handle,
582
- .split-divider:focus .split-divider-handle,
583
- .split-divider--dragging .split-divider-handle {
528
+ .pie-section-player-split-divider:hover .pie-section-player-split-divider-handle,
529
+ .pie-section-player-split-divider:focus .pie-section-player-split-divider-handle,
530
+ .pie-section-player-split-divider--dragging .pie-section-player-split-divider-handle {
584
531
  background: var(--pie-primary, #1976d2);
585
532
  height: 80px;
586
533
  box-shadow: 0 2px 8px rgba(25, 118, 210, 0.3);
587
534
  }
588
535
 
589
- .split-divider--dragging {
536
+ .pie-section-player-split-divider--dragging {
590
537
  background: var(--pie-primary-light, #dbeafe);
591
538
  }
592
539
 
593
- .content-card {
540
+ .pie-section-player-content-card {
594
541
  border: 1px solid var(--pie-border-light, #e5e7eb);
595
542
  border-radius: 8px;
596
- background: var(--pie-white, #fff);
543
+ background: var(--pie-background, #fff);
597
544
  }
598
545
 
599
- .content-card-header {
546
+ .pie-section-player-content-card-header {
600
547
  display: flex;
601
548
  align-items: center;
602
549
  justify-content: space-between;
@@ -604,36 +551,30 @@
604
551
  border-bottom: 1px solid var(--pie-border-light, #e5e7eb);
605
552
  }
606
553
 
607
- .content-card-header h2 {
608
- margin: 0;
609
- font-size: 0.95rem;
610
- font-weight: 600;
611
- }
612
-
613
- .content-card-body {
554
+ .pie-section-player-content-card-body {
614
555
  padding: 1rem;
615
556
  }
616
557
 
617
558
  @media (max-width: 1100px) {
618
- .player-shell--left,
619
- .player-shell--right {
559
+ .pie-section-player-shell--left,
560
+ .pie-section-player-shell--right {
620
561
  flex-direction: column;
621
562
  }
622
563
 
623
- .layout-body--inline {
564
+ .pie-section-player-layout-body--inline {
624
565
  grid-template-columns: 1fr;
625
566
  }
626
567
 
627
- .split-content {
568
+ .pie-section-player-split-content {
628
569
  grid-template-columns: 1fr !important;
629
570
  }
630
571
 
631
- .split-divider {
572
+ .pie-section-player-split-divider {
632
573
  display: none;
633
574
  }
634
575
 
635
- .section-toolbar-pane--left,
636
- .section-toolbar-pane--right {
576
+ .pie-section-player-toolbar-pane--left,
577
+ .pie-section-player-toolbar-pane--right {
637
578
  border: none;
638
579
  padding: 0;
639
580
  }