@pie-players/pie-section-player-tools-session-debugger 0.3.43 → 0.3.44

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.
@@ -1,3 +1,2 @@
1
1
  declare const _default: import('vite').UserConfig;
2
2
  export default _default;
3
- //# sourceMappingURL=vite.config.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pie-players/pie-section-player-tools-session-debugger",
3
- "version": "0.3.43",
3
+ "version": "0.3.44",
4
4
  "type": "module",
5
5
  "description": "Session debugger panel for PIE section-player flows",
6
6
  "repository": {
@@ -19,7 +19,6 @@
19
19
  "debugger",
20
20
  "web-component"
21
21
  ],
22
- "svelte": "./SectionSessionPanel.svelte",
23
22
  "main": "./dist/section-player-tools-session-debugger.js",
24
23
  "module": "./dist/section-player-tools-session-debugger.js",
25
24
  "unpkg": "./dist/section-player-tools-session-debugger.js",
@@ -27,19 +26,17 @@
27
26
  "exports": {
28
27
  ".": {
29
28
  "types": "./dist/index.d.ts",
30
- "import": "./dist/section-player-tools-session-debugger.js",
31
- "svelte": "./SectionSessionPanel.svelte"
29
+ "import": "./dist/section-player-tools-session-debugger.js"
32
30
  }
33
31
  },
34
32
  "files": [
35
33
  "dist",
36
- "SectionSessionPanel.svelte",
37
34
  "package.json"
38
35
  ],
39
36
  "license": "MIT",
40
37
  "dependencies": {
41
- "@pie-players/pie-section-player-tools-shared": "0.3.43",
42
- "@pie-players/pie-theme": "0.3.43"
38
+ "@pie-players/pie-section-player-tools-shared": "0.3.44",
39
+ "@pie-players/pie-theme": "0.3.44"
43
40
  },
44
41
  "types": "./dist/index.d.ts",
45
42
  "scripts": {
@@ -1,370 +0,0 @@
1
- <svelte:options
2
- customElement={{
3
- tag: 'pie-section-player-tools-session-debugger',
4
- shadow: 'none',
5
- props: {
6
- sectionId: { type: 'String', attribute: 'section-id' },
7
- attemptId: { type: 'String', attribute: 'attempt-id' },
8
- toolkitCoordinator: { type: 'Object', attribute: 'toolkit-coordinator' }
9
- }
10
- }}
11
- />
12
-
13
- <script lang="ts">
14
- import '@pie-players/pie-theme/components.css';
15
- import SharedFloatingPanel from '@pie-players/pie-section-player-tools-shared/SharedFloatingPanel.svelte';
16
- import {
17
- getSectionControllerFromCoordinator,
18
- isMatchingSectionControllerLifecycleEvent
19
- } from '@pie-players/pie-section-player-tools-shared';
20
- import { createEventDispatcher } from 'svelte';
21
- const dispatch = createEventDispatcher<{ close: undefined }>();
22
-
23
-
24
- type SessionPanelSnapshot = {
25
- currentItemIndex: number | null;
26
- currentItemId: string | null;
27
- visitedItemIdentifiers: string[];
28
- loadingComplete: boolean;
29
- totalRegistered: number;
30
- totalLoaded: number;
31
- itemsComplete: boolean;
32
- completedCount: number;
33
- totalItems: number;
34
- updatedAt: number | null;
35
- lastChangedItemId: string | null;
36
- itemSessions: Record<string, unknown>;
37
- };
38
-
39
- type SectionAttemptSliceLike = {
40
- currentItemIndex?: number;
41
- currentItemId?: string;
42
- visitedItemIdentifiers?: string[];
43
- itemSessions?: Record<string, unknown>;
44
- loadingComplete?: boolean;
45
- totalRegistered?: number;
46
- totalLoaded?: number;
47
- itemsComplete?: boolean;
48
- completedCount?: number;
49
- totalItems?: number;
50
- };
51
-
52
- type SectionSessionStateLike = {
53
- itemSessions?: Record<string, unknown>;
54
- };
55
-
56
- type SectionControllerLike = {
57
- getRuntimeState?: () => SectionAttemptSliceLike | null;
58
- getSession?: () => SectionSessionStateLike | null;
59
- subscribe?: (listener: (event: { itemId?: string; timestamp?: number }) => void) => () => void;
60
- };
61
-
62
- type ToolkitCoordinatorLike = {
63
- getSectionController?: (args: { sectionId: string; attemptId?: string }) => SectionControllerLike | undefined;
64
- // Phase D (>=0.3.35): subscribe* helpers follow the toolkit's
65
- // active section cohort automatically and do not accept
66
- // sectionId / attemptId arguments. The session panel keeps
67
- // `sectionId` + `attemptId` in `subscriptionTarget` purely to
68
- // gate same-target re-subscribe and to drive `getSectionController`.
69
- subscribeItemEvents?: (args: {
70
- listener: (event: { itemId?: string; timestamp?: number }) => void;
71
- }) => () => void;
72
- subscribeSectionLifecycleEvents?: (args: {
73
- listener: (event: { itemId?: string; timestamp?: number }) => void;
74
- }) => () => void;
75
- onSectionControllerLifecycle?: (
76
- listener: (event: { type: 'ready' | 'disposed'; key?: { sectionId?: string; attemptId?: string } }) => void
77
- ) => () => void;
78
- };
79
-
80
- let {
81
- toolkitCoordinator = null,
82
- sectionId = '',
83
- attemptId = undefined
84
- }: {
85
- toolkitCoordinator?: ToolkitCoordinatorLike | null;
86
- sectionId: string;
87
- attemptId?: string;
88
- } = $props();
89
-
90
- let sessionPanelSnapshot = $state<SessionPanelSnapshot>({
91
- currentItemIndex: null,
92
- currentItemId: null,
93
- visitedItemIdentifiers: [],
94
- loadingComplete: false,
95
- totalRegistered: 0,
96
- totalLoaded: 0,
97
- itemsComplete: false,
98
- completedCount: 0,
99
- totalItems: 0,
100
- updatedAt: null,
101
- lastChangedItemId: null,
102
- itemSessions: {}
103
- });
104
- let unsubscribeController: (() => void) | null = null;
105
- let unsubscribeLifecycle: (() => void) | null = null;
106
- let controllerAvailable = $state(false);
107
- let resubscribeQueued = false;
108
- const subscriptionTarget: {
109
- controller: SectionControllerLike | null;
110
- sectionId: string;
111
- attemptId?: string;
112
- } = {
113
- controller: null,
114
- sectionId: '',
115
- attemptId: undefined
116
- };
117
-
118
- function cloneSessionSnapshot<T>(value: T): T {
119
- try {
120
- return structuredClone(value);
121
- } catch {
122
- try {
123
- return JSON.parse(JSON.stringify(value)) as T;
124
- } catch {
125
- // Keep debugger resilient if a session payload contains non-serializable values.
126
- return value;
127
- }
128
- }
129
- }
130
-
131
- function getController(): SectionControllerLike | undefined {
132
- return (
133
- getSectionControllerFromCoordinator(
134
- toolkitCoordinator,
135
- sectionId,
136
- attemptId
137
- ) || undefined
138
- );
139
- }
140
-
141
- function refreshFromController(
142
- meta?: { itemId?: string; updatedAt?: number },
143
- controllerOverride?: SectionControllerLike | null
144
- ) {
145
- const controller = controllerOverride || getController();
146
- const sectionSlice = controller?.getRuntimeState?.() || null;
147
- const persistedSlice = controller?.getSession?.() || null;
148
- controllerAvailable = Boolean(controller);
149
- sessionPanelSnapshot = {
150
- currentItemIndex:
151
- typeof sectionSlice?.currentItemIndex === 'number' && sectionSlice.currentItemIndex >= 0
152
- ? sectionSlice.currentItemIndex
153
- : null,
154
- currentItemId:
155
- typeof sectionSlice?.currentItemId === 'string' && sectionSlice.currentItemId
156
- ? sectionSlice.currentItemId
157
- : null,
158
- visitedItemIdentifiers: cloneSessionSnapshot(sectionSlice?.visitedItemIdentifiers || []),
159
- loadingComplete: sectionSlice?.loadingComplete === true,
160
- totalRegistered: typeof sectionSlice?.totalRegistered === 'number' ? sectionSlice.totalRegistered : 0,
161
- totalLoaded: typeof sectionSlice?.totalLoaded === 'number' ? sectionSlice.totalLoaded : 0,
162
- itemsComplete: sectionSlice?.itemsComplete === true,
163
- completedCount: typeof sectionSlice?.completedCount === 'number' ? sectionSlice.completedCount : 0,
164
- totalItems: typeof sectionSlice?.totalItems === 'number' ? sectionSlice.totalItems : 0,
165
- updatedAt: meta?.updatedAt || Date.now(),
166
- lastChangedItemId: meta?.itemId || null,
167
- itemSessions: cloneSessionSnapshot(
168
- sectionSlice?.itemSessions || persistedSlice?.itemSessions || {}
169
- )
170
- };
171
- }
172
-
173
- function detachControllerSubscription() {
174
- unsubscribeController?.();
175
- unsubscribeController = null;
176
- subscriptionTarget.controller = null;
177
- subscriptionTarget.sectionId = '';
178
- subscriptionTarget.attemptId = undefined;
179
- }
180
-
181
- function detachLifecycleSubscription() {
182
- unsubscribeLifecycle?.();
183
- unsubscribeLifecycle = null;
184
- }
185
-
186
- function handleControllerEvent(detail: { itemId?: string; timestamp?: number }): void {
187
- refreshFromController({
188
- itemId: detail?.itemId,
189
- updatedAt: detail?.timestamp || Date.now()
190
- });
191
- }
192
-
193
- function handleItemControllerEvent(detail: { itemId?: string; timestamp?: number }): void {
194
- handleControllerEvent(detail);
195
- }
196
-
197
- function handleSectionControllerEvent(detail: { itemId?: string; timestamp?: number }): void {
198
- handleControllerEvent(detail);
199
- }
200
-
201
- function ensureControllerSubscription() {
202
- const controller = getController() || null;
203
- if (!controller) {
204
- detachControllerSubscription();
205
- controllerAvailable = false;
206
- sessionPanelSnapshot = {
207
- currentItemIndex: null,
208
- currentItemId: null,
209
- visitedItemIdentifiers: [],
210
- loadingComplete: false,
211
- totalRegistered: 0,
212
- totalLoaded: 0,
213
- itemsComplete: false,
214
- completedCount: 0,
215
- totalItems: 0,
216
- updatedAt: Date.now(),
217
- lastChangedItemId: null,
218
- itemSessions: {}
219
- };
220
- return;
221
- }
222
- const nextAttemptId = attemptId || undefined;
223
- const isSameTarget =
224
- subscriptionTarget.controller === controller &&
225
- subscriptionTarget.sectionId === sectionId &&
226
- subscriptionTarget.attemptId === nextAttemptId;
227
- if (isSameTarget && unsubscribeController) {
228
- refreshFromController(undefined, controller);
229
- return;
230
- }
231
- detachControllerSubscription();
232
- const unsubscribeItem = toolkitCoordinator?.subscribeItemEvents?.({
233
- listener: handleItemControllerEvent
234
- }) || null;
235
- const unsubscribeSection = toolkitCoordinator?.subscribeSectionLifecycleEvents?.({
236
- listener: handleSectionControllerEvent
237
- }) || null;
238
- unsubscribeController = () => {
239
- unsubscribeItem?.();
240
- unsubscribeSection?.();
241
- };
242
- subscriptionTarget.controller = controller;
243
- subscriptionTarget.sectionId = sectionId;
244
- subscriptionTarget.attemptId = nextAttemptId;
245
- refreshFromController(undefined, controller);
246
- }
247
-
248
- function queueEnsureControllerSubscription(): void {
249
- if (resubscribeQueued) return;
250
- resubscribeQueued = true;
251
- queueMicrotask(() => {
252
- resubscribeQueued = false;
253
- ensureControllerSubscription();
254
- });
255
- }
256
-
257
- $effect(() => {
258
- if (!toolkitCoordinator || !sectionId) return;
259
- ensureControllerSubscription();
260
- detachLifecycleSubscription();
261
- unsubscribeLifecycle = toolkitCoordinator.onSectionControllerLifecycle?.((event) => {
262
- if (!isMatchingSectionControllerLifecycleEvent(event, sectionId, attemptId)) return;
263
- queueEnsureControllerSubscription();
264
- refreshFromController({
265
- updatedAt: Date.now()
266
- });
267
- }) || null;
268
- return () => {
269
- detachControllerSubscription();
270
- detachLifecycleSubscription();
271
- };
272
- });
273
-
274
- </script>
275
-
276
- <SharedFloatingPanel
277
- title="Session Data"
278
- ariaLabel="Drag session panel"
279
- minWidth={340}
280
- minHeight={260}
281
- initialSizing={{
282
- widthRatio: 0.29,
283
- heightRatio: 0.72,
284
- minWidth: 280,
285
- maxWidth: 560,
286
- minHeight: 360,
287
- maxHeight: 860,
288
- alignX: 'left',
289
- alignY: 'center',
290
- paddingX: 16,
291
- paddingY: 16
292
- }}
293
- className="pie-section-player-tools-session-debugger"
294
- bodyClass="pie-section-player-tools-session-debugger__content-shell"
295
- onClose={() => dispatch('close')}
296
- >
297
- <svelte:fragment slot="icon">
298
- <svg
299
- xmlns="http://www.w3.org/2000/svg"
300
- class="pie-section-player-tools-session-debugger__icon-sm"
301
- fill="none"
302
- viewBox="0 0 24 24"
303
- stroke="currentColor"
304
- >
305
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
306
- </svg>
307
- </svelte:fragment>
308
-
309
- <div class="pie-section-player-tools-session-debugger__content">
310
- <div class="pie-section-player-tools-session-debugger__section-intro">
311
- <div class="pie-section-player-tools-session-debugger__heading">PIE Session Data (Persistent)</div>
312
- </div>
313
-
314
- {#if !controllerAvailable}
315
- <div class="pie-section-player-tools-session-debugger__alert pie-section-player-tools-session-debugger__alert--warning">
316
- <svg
317
- xmlns="http://www.w3.org/2000/svg"
318
- class="pie-section-player-tools-session-debugger__icon-md"
319
- fill="none"
320
- viewBox="0 0 24 24"
321
- >
322
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01M5.07 19h13.86c1.54 0 2.5-1.67 1.73-3L13.73 4c-.77-1.33-2.69-1.33-3.46 0L3.34 16c-.77 1.33.19 3 1.73 3z" />
323
- </svg>
324
- <span class="pie-section-player-tools-session-debugger__text-xs">Section controller not available for this section yet.</span>
325
- </div>
326
- {:else}
327
- {#if Object.keys(sessionPanelSnapshot.itemSessions || {}).length === 0}
328
- <div class="pie-section-player-tools-session-debugger__alert pie-section-player-tools-session-debugger__alert--info">
329
- <svg
330
- xmlns="http://www.w3.org/2000/svg"
331
- class="pie-section-player-tools-session-debugger__icon-md"
332
- fill="none"
333
- viewBox="0 0 24 24"
334
- >
335
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
336
- </svg>
337
- <span class="pie-section-player-tools-session-debugger__text-xs">No section session data yet. Interact with the questions to see updates.</span>
338
- </div>
339
- {/if}
340
- <div class="pie-section-player-tools-session-debugger__card">
341
- <div class="pie-section-player-tools-session-debugger__card-title">
342
- Item Sessions Snapshot
343
- </div>
344
- <div
345
- class="pie-section-player-tools-session-debugger__card-region"
346
- role="textbox"
347
- aria-readonly="true"
348
- tabindex="0"
349
- aria-label="Section session snapshot JSON"
350
- >
351
- <pre class="pie-section-player-tools-session-debugger__card-pre">{JSON.stringify(sessionPanelSnapshot, null, 2)}</pre>
352
- </div>
353
- </div>
354
- {/if}
355
- </div>
356
- </SharedFloatingPanel>
357
-
358
- <style>
359
- .pie-section-player-tools-session-debugger__icon-sm {
360
- width: 1rem;
361
- height: 1rem;
362
- }
363
-
364
- .pie-section-player-tools-session-debugger__card-region:focus-visible {
365
- outline: 2px solid var(--color-primary, #2563eb);
366
- outline-offset: 2px;
367
- border-radius: 0.5rem;
368
- }
369
-
370
- </style>
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,8BAA8B,CAAC;AAEtC,YAAY,EAAE,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"vite.config.d.ts","sourceRoot":"","sources":["../vite.config.ts"],"names":[],"mappings":";AAKA,wBAkCG"}