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

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.
@@ -3,18 +3,22 @@
3
3
  showSessionPanel: boolean;
4
4
  showEventPanel: boolean;
5
5
  showDbPanel?: boolean;
6
+ showInstrumentationPanel?: boolean;
6
7
  onToggleSessionPanel: () => void;
7
8
  onToggleEventPanel: () => void;
8
9
  onToggleDbPanel?: () => void;
10
+ onToggleInstrumentationPanel?: () => void;
9
11
  }
10
12
 
11
13
  let {
12
14
  showSessionPanel,
13
15
  showEventPanel,
14
16
  showDbPanel = false,
17
+ showInstrumentationPanel = false,
15
18
  onToggleSessionPanel,
16
19
  onToggleEventPanel,
17
20
  onToggleDbPanel,
21
+ onToggleInstrumentationPanel,
18
22
  }: Props = $props();
19
23
  </script>
20
24
 
@@ -62,3 +66,19 @@
62
66
  </svg>
63
67
  </button>
64
68
  {/if}
69
+
70
+ {#if onToggleInstrumentationPanel}
71
+ <button
72
+ type="button"
73
+ class="btn btn-sm btn-outline btn-square"
74
+ class:btn-active={showInstrumentationPanel}
75
+ onclick={onToggleInstrumentationPanel}
76
+ title="Instrumentation"
77
+ aria-label="Toggle instrumentation panel"
78
+ aria-pressed={showInstrumentationPanel}
79
+ >
80
+ <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">
81
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M4 13h4l2 6 4-14 2 8h4" />
82
+ </svg>
83
+ </button>
84
+ {/if}
@@ -17,6 +17,8 @@
17
17
  minWidth = 320,
18
18
  minHeight = 260,
19
19
  defaultMinimized = false,
20
+ persistenceScope = "",
21
+ persistencePanelId = "",
20
22
  onClose,
21
23
  className = "",
22
24
  bodyClass = "",
@@ -31,6 +33,8 @@
31
33
  minWidth?: number;
32
34
  minHeight?: number;
33
35
  defaultMinimized?: boolean;
36
+ persistenceScope?: string;
37
+ persistencePanelId?: string;
34
38
  onClose?: () => void;
35
39
  className?: string;
36
40
  bodyClass?: string;
@@ -46,6 +50,9 @@
46
50
  let panelHeight = $state(480);
47
51
  let panelZIndex = $state(claimNextFloatingPanelZIndex());
48
52
  let isMinimized = $state(untrack(() => defaultMinimized));
53
+ let hasMounted = $state(false);
54
+
55
+ const STORAGE_KEY_PREFIX = "pie:debug-panels:v1";
49
56
 
50
57
  const pointerController = createFloatingPanelPointerController({
51
58
  getState: () => ({
@@ -71,15 +78,94 @@
71
78
  panelZIndex = claimNextFloatingPanelZIndex();
72
79
  }
73
80
 
81
+ function getPersistenceKey(): string | null {
82
+ const scope = String(persistenceScope || "").trim();
83
+ const panelId = String(persistencePanelId || "").trim();
84
+ if (!scope || !panelId) return null;
85
+ return `${STORAGE_KEY_PREFIX}:${scope}:${panelId}:layout`;
86
+ }
87
+
88
+ function clampPanelStateToViewport(state: {
89
+ x: number;
90
+ y: number;
91
+ width: number;
92
+ height: number;
93
+ minimized: boolean;
94
+ }): {
95
+ x: number;
96
+ y: number;
97
+ width: number;
98
+ height: number;
99
+ minimized: boolean;
100
+ } {
101
+ const viewportWidth = window.innerWidth;
102
+ const viewportHeight = window.innerHeight;
103
+ const width = Math.max(minWidth, Math.min(viewportWidth, state.width));
104
+ const height = Math.max(minHeight, Math.min(viewportHeight, state.height));
105
+ const maxX = Math.max(0, viewportWidth - width);
106
+ // Keep restore bounds aligned with drag bounds in floating-panel pointer controller.
107
+ const maxY = Math.max(0, viewportHeight - 100);
108
+ return {
109
+ x: Math.max(0, Math.min(maxX, state.x)),
110
+ y: Math.max(0, Math.min(maxY, state.y)),
111
+ width,
112
+ height,
113
+ minimized: Boolean(state.minimized),
114
+ };
115
+ }
116
+
117
+ function restorePersistedLayout(): boolean {
118
+ const key = getPersistenceKey();
119
+ if (!key) return false;
120
+ if (typeof localStorage === "undefined") return false;
121
+ try {
122
+ const raw = localStorage.getItem(key);
123
+ if (!raw) return false;
124
+ const parsed = JSON.parse(raw) as {
125
+ x?: number;
126
+ y?: number;
127
+ width?: number;
128
+ height?: number;
129
+ minimized?: boolean;
130
+ };
131
+ if (
132
+ typeof parsed.x !== "number" ||
133
+ typeof parsed.y !== "number" ||
134
+ typeof parsed.width !== "number" ||
135
+ typeof parsed.height !== "number"
136
+ ) {
137
+ return false;
138
+ }
139
+ const clamped = clampPanelStateToViewport({
140
+ x: parsed.x,
141
+ y: parsed.y,
142
+ width: parsed.width,
143
+ height: parsed.height,
144
+ minimized: Boolean(parsed.minimized),
145
+ });
146
+ panelX = clamped.x;
147
+ panelY = clamped.y;
148
+ panelWidth = clamped.width;
149
+ panelHeight = clamped.height;
150
+ isMinimized = clamped.minimized;
151
+ return true;
152
+ } catch {
153
+ return false;
154
+ }
155
+ }
156
+
74
157
  onMount(() => {
75
- const initial = computePanelSizeFromViewport(
76
- { width: window.innerWidth, height: window.innerHeight },
77
- initialSizing,
78
- );
79
- panelX = initial.x;
80
- panelY = initial.y;
81
- panelWidth = initial.width;
82
- panelHeight = initial.height;
158
+ if (!restorePersistedLayout()) {
159
+ const initial = computePanelSizeFromViewport(
160
+ { width: window.innerWidth, height: window.innerHeight },
161
+ initialSizing,
162
+ );
163
+ panelX = initial.x;
164
+ panelY = initial.y;
165
+ panelWidth = initial.width;
166
+ panelHeight = initial.height;
167
+ }
168
+ hasMounted = true;
83
169
  });
84
170
 
85
171
  onDestroy(() => {
@@ -95,6 +181,27 @@
95
181
  const resolvedHeaderClass = $derived.by(() =>
96
182
  ["pie-shared-floating-panel__header", headerClass || ""].join(" ").trim(),
97
183
  );
184
+
185
+ $effect(() => {
186
+ if (!hasMounted) return;
187
+ const key = getPersistenceKey();
188
+ if (!key) return;
189
+ if (typeof localStorage === "undefined") return;
190
+ try {
191
+ localStorage.setItem(
192
+ key,
193
+ JSON.stringify({
194
+ x: panelX,
195
+ y: panelY,
196
+ width: panelWidth,
197
+ height: panelHeight,
198
+ minimized: isMinimized,
199
+ }),
200
+ );
201
+ } catch {
202
+ // ignore storage write failures
203
+ }
204
+ });
98
205
  </script>
99
206
 
100
207
  <section