@pie-players/pie-section-player-tools-shared 0.3.13 → 0.3.17

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.
@@ -0,0 +1,64 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ showSessionPanel: boolean;
4
+ showEventPanel: boolean;
5
+ showDbPanel?: boolean;
6
+ onToggleSessionPanel: () => void;
7
+ onToggleEventPanel: () => void;
8
+ onToggleDbPanel?: () => void;
9
+ }
10
+
11
+ let {
12
+ showSessionPanel,
13
+ showEventPanel,
14
+ showDbPanel = false,
15
+ onToggleSessionPanel,
16
+ onToggleEventPanel,
17
+ onToggleDbPanel,
18
+ }: Props = $props();
19
+ </script>
20
+
21
+ <button
22
+ type="button"
23
+ class="btn btn-sm btn-outline btn-square"
24
+ class:btn-active={showSessionPanel}
25
+ onclick={onToggleSessionPanel}
26
+ title="Session"
27
+ aria-label="Toggle session panel"
28
+ aria-pressed={showSessionPanel}
29
+ >
30
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor">
31
+ <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" />
32
+ </svg>
33
+ </button>
34
+
35
+ <button
36
+ type="button"
37
+ class="btn btn-sm btn-outline btn-square"
38
+ class:btn-active={showEventPanel}
39
+ onclick={onToggleEventPanel}
40
+ title="Events"
41
+ aria-label="Toggle event broadcast panel"
42
+ aria-pressed={showEventPanel}
43
+ >
44
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor">
45
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M13 7h8m0 0l-3-3m3 3l-3 3M3 17h8m0 0l-3-3m3 3l-3 3M3 7h5m8 10h5" />
46
+ </svg>
47
+ </button>
48
+
49
+ {#if onToggleDbPanel}
50
+ <button
51
+ type="button"
52
+ class="btn btn-sm btn-outline btn-square"
53
+ class:btn-active={showDbPanel}
54
+ onclick={onToggleDbPanel}
55
+ title="Database state"
56
+ aria-label="Toggle database state panel"
57
+ aria-pressed={showDbPanel}
58
+ >
59
+ <svg xmlns="http://www.w3.org/2000/svg" class="h-4 w-4" width="16" height="16" fill="none" viewBox="0 0 24 24" stroke="currentColor">
60
+ <ellipse cx="12" cy="5" rx="7" ry="3" stroke-width="2"></ellipse>
61
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 5v7c0 1.66 3.13 3 7 3s7-1.34 7-3V5M5 12v7c0 1.66 3.13 3 7 3s7-1.34 7-3v-7"></path>
62
+ </svg>
63
+ </button>
64
+ {/if}
@@ -0,0 +1,546 @@
1
+ <script lang="ts">
2
+ import { onMount } from "svelte";
3
+ import SharedFloatingPanel from "./SharedFloatingPanel.svelte";
4
+
5
+ type PanelMode = "section" | "assessment";
6
+ type DbTableName = "attempt_sessions" | "section_sessions" | "item_sessions" | "assessment_sessions";
7
+
8
+ interface Props {
9
+ mode?: PanelMode;
10
+ assessmentId: string;
11
+ attemptId: string;
12
+ sectionId?: string;
13
+ apiBasePath?: string;
14
+ onResetDb: () => void | Promise<void>;
15
+ onClose: () => void;
16
+ }
17
+
18
+ let {
19
+ mode = "section",
20
+ assessmentId,
21
+ attemptId,
22
+ sectionId = "",
23
+ apiBasePath = "/api/session-demo",
24
+ onResetDb,
25
+ onClose,
26
+ }: Props = $props();
27
+
28
+ let pollError = $state<string | null>(null);
29
+ let activeView = $state<"raw-tables" | "reconstructed" | "request-view">("raw-tables");
30
+ let isResettingDb = $state(false);
31
+ let requestViewJson = $state<string>("{}");
32
+ let requestViewError = $state<string | null>(null);
33
+ let isLoadingRequestView = $state(false);
34
+ const POLL_TIMEOUT_MS = 4500;
35
+
36
+ let scopedRows = $state<Record<DbTableName, Array<Record<string, unknown>>>>({
37
+ attempt_sessions: [],
38
+ section_sessions: [],
39
+ item_sessions: [],
40
+ assessment_sessions: [],
41
+ });
42
+ let scopedColumns = $state<Record<DbTableName, string[]>>({
43
+ attempt_sessions: [],
44
+ section_sessions: [],
45
+ item_sessions: [],
46
+ assessment_sessions: [],
47
+ });
48
+ let reconstructedSnapshotJson = $state<string>("{}");
49
+
50
+ const tableOrder = $derived.by(() =>
51
+ mode === "section"
52
+ ? (["attempt_sessions", "section_sessions", "item_sessions"] as DbTableName[])
53
+ : (["attempt_sessions", "assessment_sessions"] as DbTableName[]),
54
+ );
55
+
56
+ const viewTitle = $derived.by(() =>
57
+ mode === "section" ? "Show section request" : "Show assessment request",
58
+ );
59
+
60
+ function collectColumns(rows: Array<Record<string, unknown>>): string[] {
61
+ const seen = new Set<string>();
62
+ const columns: string[] = [];
63
+ for (const row of rows) {
64
+ for (const key of Object.keys(row)) {
65
+ if (seen.has(key)) continue;
66
+ seen.add(key);
67
+ columns.push(key);
68
+ }
69
+ }
70
+ return columns;
71
+ }
72
+
73
+ function formatCellValue(value: unknown): string {
74
+ if (value === null || value === undefined) return "";
75
+ if (typeof value === "object") {
76
+ try {
77
+ return JSON.stringify(value);
78
+ } catch {
79
+ return "[unserializable]";
80
+ }
81
+ }
82
+ return String(value);
83
+ }
84
+
85
+ const COLUMN_HEADER_LABELS: Record<string, string> = {
86
+ id: "id",
87
+ assessment_id: "asm_id",
88
+ attempt_id: "att_id",
89
+ demo_user_id: "demo_uid",
90
+ created_at: "created",
91
+ updated_at: "updated",
92
+ attempt_session_id: "att_sess_id",
93
+ section_id: "sec_id",
94
+ current_item_identifier: "curr_item_id",
95
+ visited_item_identifiers: "visited_item_ids",
96
+ section_session_id: "sec_sess_id",
97
+ item_identifier: "item_id",
98
+ canonical_item_id: "canon_item_id",
99
+ session_payload: "payload",
100
+ snapshot_payload: "payload",
101
+ };
102
+
103
+ function abbreviateColumnName(column: string): string {
104
+ const explicit = COLUMN_HEADER_LABELS[column];
105
+ if (explicit) return explicit;
106
+ if (column.length <= 14) return column;
107
+ const parts = column.split("_").filter(Boolean);
108
+ if (parts.length <= 1) return column.slice(0, 14);
109
+ const abbreviated = parts
110
+ .map((part, index) => (index === parts.length - 1 ? part.slice(0, 4) : part.slice(0, 3)))
111
+ .join("_");
112
+ return abbreviated.slice(0, 18);
113
+ }
114
+
115
+ function scopedSnapshotKey(): string {
116
+ return mode === "section"
117
+ ? `${assessmentId}:${sectionId}:${attemptId}`
118
+ : `${assessmentId}:${attemptId}`;
119
+ }
120
+
121
+ function applyStatePayload(payload: unknown): void {
122
+ const state = (payload as { state?: Record<string, unknown> } | null)?.state || {};
123
+ const stateTables = (state?.tables as Record<string, unknown> | undefined) || {};
124
+
125
+ const attemptRows = Array.isArray(stateTables.attempt_sessions)
126
+ ? (stateTables.attempt_sessions as Array<Record<string, unknown>>)
127
+ : [];
128
+ const targetAttemptRows = attemptRows.filter(
129
+ (row) => row.assessment_id === assessmentId && row.attempt_id === attemptId,
130
+ );
131
+ const targetAttemptIds = new Set(
132
+ targetAttemptRows
133
+ .map((row) => row.id)
134
+ .filter((id): id is number => typeof id === "number"),
135
+ );
136
+
137
+ const nextRows: Record<DbTableName, Array<Record<string, unknown>>> = {
138
+ attempt_sessions: targetAttemptRows,
139
+ section_sessions: [],
140
+ item_sessions: [],
141
+ assessment_sessions: [],
142
+ };
143
+
144
+ if (mode === "section") {
145
+ const sectionRows = Array.isArray(stateTables.section_sessions)
146
+ ? (stateTables.section_sessions as Array<Record<string, unknown>>)
147
+ : [];
148
+ const targetSectionRows = sectionRows.filter(
149
+ (row) =>
150
+ targetAttemptIds.has(row.attempt_session_id as number) &&
151
+ row.section_id === sectionId,
152
+ );
153
+ nextRows.section_sessions = targetSectionRows;
154
+ const targetSectionIds = new Set(
155
+ targetSectionRows
156
+ .map((row) => row.id)
157
+ .filter((id): id is number => typeof id === "number"),
158
+ );
159
+ const itemRows = Array.isArray(stateTables.item_sessions)
160
+ ? (stateTables.item_sessions as Array<Record<string, unknown>>)
161
+ : [];
162
+ nextRows.item_sessions = itemRows.filter((row) =>
163
+ targetSectionIds.has(row.section_session_id as number),
164
+ );
165
+ } else {
166
+ const assessmentRows = Array.isArray(stateTables.assessment_sessions)
167
+ ? (stateTables.assessment_sessions as Array<Record<string, unknown>>)
168
+ : [];
169
+ nextRows.assessment_sessions = assessmentRows.filter((row) =>
170
+ targetAttemptIds.has(row.attempt_session_id as number),
171
+ );
172
+ }
173
+
174
+ scopedRows = nextRows;
175
+ scopedColumns = {
176
+ attempt_sessions: collectColumns(nextRows.attempt_sessions),
177
+ section_sessions: collectColumns(nextRows.section_sessions),
178
+ item_sessions: collectColumns(nextRows.item_sessions),
179
+ assessment_sessions: collectColumns(nextRows.assessment_sessions),
180
+ };
181
+
182
+ const snapshots =
183
+ (state.reconstructedSnapshots as Record<string, unknown> | undefined) || {};
184
+ const key = scopedSnapshotKey();
185
+ reconstructedSnapshotJson = JSON.stringify(snapshots[key] || {}, null, 2);
186
+ }
187
+
188
+ async function handleResetDb(): Promise<void> {
189
+ if (isResettingDb) return;
190
+ isResettingDb = true;
191
+ try {
192
+ await onResetDb();
193
+ } finally {
194
+ isResettingDb = false;
195
+ }
196
+ }
197
+
198
+ async function fetchDbStateOnce(): Promise<void> {
199
+ const controller = new AbortController();
200
+ const timeoutId = setTimeout(() => controller.abort(), POLL_TIMEOUT_MS);
201
+ try {
202
+ const response = await fetch(`${apiBasePath}/state`, {
203
+ signal: controller.signal,
204
+ cache: "no-store",
205
+ });
206
+ if (!response.ok) {
207
+ throw new Error(`DB state request failed (${response.status})`);
208
+ }
209
+ applyStatePayload(await response.json());
210
+ pollError = null;
211
+ } catch (error) {
212
+ if (error instanceof Error && error.name === "AbortError") {
213
+ pollError = `DB state request timed out after ${POLL_TIMEOUT_MS}ms`;
214
+ } else {
215
+ pollError = error instanceof Error ? error.message : String(error);
216
+ }
217
+ } finally {
218
+ clearTimeout(timeoutId);
219
+ }
220
+ }
221
+
222
+ async function fetchRequestView(): Promise<void> {
223
+ if (activeView !== "request-view") return;
224
+ isLoadingRequestView = true;
225
+ requestViewError = null;
226
+ const query = new URLSearchParams({
227
+ assessmentId,
228
+ attemptId,
229
+ });
230
+ if (mode === "section" && sectionId) {
231
+ query.set("sectionId", sectionId);
232
+ }
233
+ try {
234
+ const response = await fetch(`${apiBasePath}/activity/load?${query.toString()}`, {
235
+ cache: "no-store",
236
+ });
237
+ if (!response.ok) {
238
+ throw new Error(`Request view failed (${response.status})`);
239
+ }
240
+ requestViewJson = JSON.stringify(await response.json(), null, 2);
241
+ } catch (error) {
242
+ requestViewError = error instanceof Error ? error.message : String(error);
243
+ } finally {
244
+ isLoadingRequestView = false;
245
+ }
246
+ }
247
+
248
+ $effect(() => {
249
+ if (typeof EventSource === "undefined") {
250
+ pollError = "Live updates are not supported in this browser";
251
+ void fetchDbStateOnce();
252
+ return;
253
+ }
254
+ const eventSource = new EventSource(`${apiBasePath}/state/stream`);
255
+ const onState = (event: MessageEvent<string>) => {
256
+ try {
257
+ applyStatePayload(JSON.parse(event.data));
258
+ if (activeView === "request-view") {
259
+ void fetchRequestView();
260
+ }
261
+ pollError = null;
262
+ } catch (error) {
263
+ pollError = error instanceof Error ? error.message : String(error);
264
+ }
265
+ };
266
+ eventSource.addEventListener("state", onState as EventListener);
267
+ eventSource.onerror = () => {
268
+ pollError = "Live updates disconnected; retrying...";
269
+ };
270
+ return () => {
271
+ eventSource.removeEventListener("state", onState as EventListener);
272
+ eventSource.close();
273
+ };
274
+ });
275
+
276
+ $effect(() => {
277
+ void activeView;
278
+ void assessmentId;
279
+ void sectionId;
280
+ void attemptId;
281
+ void mode;
282
+ if (activeView !== "request-view") return;
283
+ void fetchRequestView();
284
+ });
285
+
286
+ onMount(() => {
287
+ void fetchDbStateOnce();
288
+ });
289
+ </script>
290
+
291
+ <SharedFloatingPanel
292
+ title="Session DB (Server)"
293
+ ariaLabel="Drag session DB panel"
294
+ minWidth={420}
295
+ minHeight={320}
296
+ initialSizing={{
297
+ widthRatio: 0.38,
298
+ heightRatio: 0.78,
299
+ minWidth: 440,
300
+ maxWidth: 900,
301
+ minHeight: 380,
302
+ maxHeight: 900,
303
+ alignX: "right",
304
+ alignY: "bottom",
305
+ paddingX: 18,
306
+ paddingY: 18,
307
+ }}
308
+ className="pie-demo-session-db-panel"
309
+ bodyClass="pie-demo-session-db-panel__content-shell"
310
+ onClose={onClose}
311
+ >
312
+ <div class="pie-demo-session-db-panel__content">
313
+ <div class="pie-demo-session-db-panel__meta">
314
+ <div><strong>assessmentId:</strong> <code>{assessmentId}</code></div>
315
+ {#if mode === "section"}
316
+ <div><strong>sectionId:</strong> <code>{sectionId}</code></div>
317
+ {/if}
318
+ <div><strong>attemptId:</strong> <code>{attemptId}</code></div>
319
+ <div><strong>mode:</strong> <code>{mode}</code></div>
320
+ </div>
321
+
322
+ <div class="pie-demo-session-db-panel__actions">
323
+ <button
324
+ type="button"
325
+ class="pie-demo-session-db-panel__button"
326
+ onclick={() => void handleResetDb()}
327
+ disabled={isResettingDb}
328
+ aria-busy={isResettingDb}
329
+ >
330
+ {isResettingDb ? "Resetting to baseline..." : "Reset DB to baseline"}
331
+ </button>
332
+ <button
333
+ type="button"
334
+ class="pie-demo-session-db-panel__button"
335
+ onclick={() => (activeView = "raw-tables")}
336
+ aria-pressed={activeView === "raw-tables"}
337
+ >
338
+ Show raw tables
339
+ </button>
340
+ <button
341
+ type="button"
342
+ class="pie-demo-session-db-panel__button"
343
+ onclick={() => (activeView = "reconstructed")}
344
+ aria-pressed={activeView === "reconstructed"}
345
+ >
346
+ Show reconstructed snapshots
347
+ </button>
348
+ <button
349
+ type="button"
350
+ class="pie-demo-session-db-panel__button"
351
+ onclick={() => (activeView = "request-view")}
352
+ aria-pressed={activeView === "request-view"}
353
+ >
354
+ {viewTitle}
355
+ </button>
356
+ </div>
357
+
358
+ {#if pollError}
359
+ <div class="pie-demo-session-db-panel__error">{pollError}</div>
360
+ {/if}
361
+
362
+ {#if activeView === "raw-tables"}
363
+ <div class="pie-demo-session-db-panel__tables">
364
+ {#each tableOrder as tableName}
365
+ <h4 class="pie-demo-session-db-panel__table-title">{tableName}</h4>
366
+ <div class="pie-demo-session-db-panel__table-wrap">
367
+ <table class="pie-demo-session-db-panel__table">
368
+ <thead>
369
+ <tr>
370
+ {#each scopedColumns[tableName] as column}
371
+ <th title={column}>{abbreviateColumnName(column)}</th>
372
+ {/each}
373
+ </tr>
374
+ </thead>
375
+ <tbody>
376
+ {#if scopedRows[tableName].length === 0}
377
+ <tr>
378
+ <td colspan={Math.max(scopedColumns[tableName].length, 1)}>No rows</td>
379
+ </tr>
380
+ {:else}
381
+ {#each scopedRows[tableName] as row}
382
+ <tr>
383
+ {#each scopedColumns[tableName] as column}
384
+ <td>{formatCellValue(row[column])}</td>
385
+ {/each}
386
+ </tr>
387
+ {/each}
388
+ {/if}
389
+ </tbody>
390
+ </table>
391
+ </div>
392
+ {/each}
393
+ </div>
394
+ {:else if activeView === "reconstructed"}
395
+ <textarea
396
+ class="pie-demo-session-db-panel__json"
397
+ readonly
398
+ value={reconstructedSnapshotJson}
399
+ spellcheck="false"
400
+ ></textarea>
401
+ {:else}
402
+ {#if requestViewError}
403
+ <div class="pie-demo-session-db-panel__error">{requestViewError}</div>
404
+ {/if}
405
+ <textarea
406
+ class="pie-demo-session-db-panel__json"
407
+ readonly
408
+ value={isLoadingRequestView ? "Loading request view..." : requestViewJson}
409
+ spellcheck="false"
410
+ ></textarea>
411
+ {/if}
412
+ </div>
413
+ </SharedFloatingPanel>
414
+
415
+ <style>
416
+ .pie-demo-session-db-panel__content {
417
+ display: flex;
418
+ flex-direction: column;
419
+ flex: 1;
420
+ height: 100%;
421
+ min-height: 0;
422
+ overflow-y: hidden;
423
+ overflow-x: hidden;
424
+ padding: 12px;
425
+ font-size: 0.8rem;
426
+ }
427
+
428
+ .pie-demo-session-db-panel__meta {
429
+ display: grid;
430
+ gap: 0.2rem;
431
+ margin-bottom: 0.55rem;
432
+ font-size: 0.78rem;
433
+ }
434
+
435
+ .pie-demo-session-db-panel__actions {
436
+ display: flex;
437
+ gap: 0.45rem;
438
+ margin-bottom: 0.5rem;
439
+ }
440
+
441
+ .pie-demo-session-db-panel__button {
442
+ border: 1px solid var(--color-base-300, #d1d5db);
443
+ background: var(--color-base-100, #fff);
444
+ color: var(--color-base-content);
445
+ border-radius: 6px;
446
+ padding: 6px 8px;
447
+ font-size: 0.78rem;
448
+ cursor: pointer;
449
+ }
450
+
451
+ .pie-demo-session-db-panel__button:hover {
452
+ background: color-mix(in srgb, var(--color-base-200) 65%, white);
453
+ }
454
+
455
+ .pie-demo-session-db-panel__button[aria-pressed="true"] {
456
+ background: color-mix(in srgb, var(--color-primary, #2563eb) 18%, transparent);
457
+ font-weight: 600;
458
+ }
459
+
460
+ .pie-demo-session-db-panel__button:disabled {
461
+ opacity: 0.6;
462
+ cursor: not-allowed;
463
+ }
464
+
465
+ .pie-demo-session-db-panel__error {
466
+ margin-bottom: 0.5rem;
467
+ padding: 0.4rem 0.45rem;
468
+ border-radius: 0.3rem;
469
+ background: color-mix(in srgb, var(--color-error) 12%, var(--color-base-100));
470
+ border: 1px solid color-mix(in srgb, var(--color-error) 35%, var(--color-base-300));
471
+ }
472
+
473
+ .pie-demo-session-db-panel__tables {
474
+ display: flex;
475
+ flex-direction: column;
476
+ gap: 0.5rem;
477
+ flex: 1;
478
+ min-height: 0;
479
+ overflow: auto;
480
+ }
481
+
482
+ .pie-demo-session-db-panel__table-title {
483
+ margin: 0;
484
+ font-size: 0.75rem;
485
+ font-weight: 700;
486
+ text-transform: lowercase;
487
+ }
488
+
489
+ .pie-demo-session-db-panel__table-wrap {
490
+ border: 1px solid color-mix(in srgb, var(--color-base-content) 25%, transparent);
491
+ border-radius: 0.3rem;
492
+ background: color-mix(in srgb, var(--color-base-200) 65%, white);
493
+ overflow: auto;
494
+ max-height: 9.5rem;
495
+ }
496
+
497
+ .pie-demo-session-db-panel__table {
498
+ width: 100%;
499
+ border-collapse: collapse;
500
+ font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
501
+ font-size: 0.72rem;
502
+ }
503
+
504
+ .pie-demo-session-db-panel__table th,
505
+ .pie-demo-session-db-panel__table td {
506
+ padding: 0.25rem 0.35rem;
507
+ border-bottom: 1px solid color-mix(in srgb, var(--color-base-content) 14%, transparent);
508
+ vertical-align: top;
509
+ text-align: left;
510
+ }
511
+
512
+ .pie-demo-session-db-panel__table th {
513
+ position: sticky;
514
+ top: 0;
515
+ background: color-mix(in srgb, var(--color-base-200) 85%, white);
516
+ font-weight: 700;
517
+ font-size: 0.66rem;
518
+ line-height: 1.15;
519
+ padding: 0.18rem 0.3rem;
520
+ white-space: nowrap;
521
+ }
522
+
523
+ .pie-demo-session-db-panel__table td {
524
+ white-space: nowrap;
525
+ }
526
+
527
+ .pie-demo-session-db-panel__meta code,
528
+ .pie-demo-session-db-panel__json {
529
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
530
+ }
531
+
532
+ .pie-demo-session-db-panel__json {
533
+ width: 100%;
534
+ flex: 1;
535
+ min-height: 14rem;
536
+ resize: none;
537
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
538
+ font-size: 0.75rem;
539
+ border: 1px solid color-mix(in srgb, var(--color-base-content) 25%, transparent);
540
+ border-radius: 0.3rem;
541
+ padding: 0.45rem;
542
+ background: color-mix(in srgb, var(--color-base-200) 65%, white);
543
+ color: var(--color-base-content);
544
+ box-sizing: border-box;
545
+ }
546
+ </style>
@@ -0,0 +1 @@
1
+ export { SvelteComponent as default } from 'svelte';
@@ -0,0 +1 @@
1
+ export { SvelteComponent as default } from 'svelte';
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
1
  export { default as PanelWindowControls } from './PanelWindowControls.svelte';
2
2
  export { default as PanelResizeHandle } from './PanelResizeHandle.svelte';
3
3
  export { default as SharedFloatingPanel } from './SharedFloatingPanel.svelte';
4
+ export { default as SessionDbPanel } from './SessionDbPanel.svelte';
5
+ export { default as DebugPanelToggles } from './DebugPanelToggles.svelte';
4
6
  export { createFloatingPanelPointerController, computePanelSizeFromViewport, claimNextFloatingPanelZIndex, type FloatingPanelPointerController, type FloatingPanelState, type FloatingPanelViewportSizing, } from './floating-panel.js';
5
7
  export { getSectionControllerFromCoordinator, isMatchingSectionControllerLifecycleEvent, optionalIdsEqual, type SectionControllerLifecycleEventLike, type SectionControllerKeyLike, type ToolkitCoordinatorWithSectionController, } from './section-controller.js';
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EACN,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,EAC5B,KAAK,8BAA8B,EACnC,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,GAChC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,mCAAmC,EACnC,yCAAyC,EACzC,gBAAgB,EAChB,KAAK,mCAAmC,EACxC,KAAK,wBAAwB,EAC7B,KAAK,uCAAuC,GAC5C,MAAM,yBAAyB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EAAE,OAAO,IAAI,mBAAmB,EAAE,MAAM,8BAA8B,CAAC;AAC9E,OAAO,EAAE,OAAO,IAAI,cAAc,EAAE,MAAM,yBAAyB,CAAC;AACpE,OAAO,EAAE,OAAO,IAAI,iBAAiB,EAAE,MAAM,4BAA4B,CAAC;AAC1E,OAAO,EACN,oCAAoC,EACpC,4BAA4B,EAC5B,4BAA4B,EAC5B,KAAK,8BAA8B,EACnC,KAAK,kBAAkB,EACvB,KAAK,2BAA2B,GAChC,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACN,mCAAmC,EACnC,yCAAyC,EACzC,gBAAgB,EAChB,KAAK,mCAAmC,EACxC,KAAK,wBAAwB,EAC7B,KAAK,uCAAuC,GAC5C,MAAM,yBAAyB,CAAC"}