@okyrychenko-dev/react-action-guard-devtools 0.1.1 → 0.1.2
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 +2 -5
- package/dist/index.cjs +261 -206
- package/dist/index.cjs.map +1 -1
- package/dist/index.css +22 -1
- package/dist/index.css.map +1 -1
- package/dist/index.d.cts +6 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +255 -196
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/dist/index.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { uiBlockingStoreApi } from '@okyrychenko-dev/react-action-guard';
|
|
2
|
-
import { memo, useMemo, useEffect, useCallback } from 'react';
|
|
2
|
+
import { memo, useMemo, useEffect, useRef, Component, useCallback } from 'react';
|
|
3
3
|
import { createShallowStore } from '@okyrychenko-dev/react-zustand-toolkit';
|
|
4
|
-
import
|
|
4
|
+
import { clsx } from 'clsx';
|
|
5
5
|
import { useStore } from 'zustand';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
7
7
|
import { useShallow } from 'zustand/react/shallow';
|
|
@@ -10,122 +10,137 @@ import { useShallow } from 'zustand/react/shallow';
|
|
|
10
10
|
|
|
11
11
|
// src/store/devtoolsStore.constants.ts
|
|
12
12
|
var DEFAULT_FILTER = {
|
|
13
|
-
actions: ["add", "remove", "update", "
|
|
13
|
+
actions: ["add", "remove", "update", "timeout", "clear", "clear_scope"],
|
|
14
14
|
scopes: [],
|
|
15
15
|
search: ""
|
|
16
16
|
};
|
|
17
|
+
var createDefaultFilter = () => ({
|
|
18
|
+
actions: [...DEFAULT_FILTER.actions],
|
|
19
|
+
scopes: [...DEFAULT_FILTER.scopes],
|
|
20
|
+
search: DEFAULT_FILTER.search
|
|
21
|
+
});
|
|
17
22
|
var DEFAULT_MAX_EVENTS = 200;
|
|
18
23
|
var DEFAULT_TAB = "timeline";
|
|
19
24
|
|
|
20
25
|
// src/store/devtoolsStore.actions.ts
|
|
21
|
-
var createDevtoolsActions = (set, get) =>
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
isPaused: false,
|
|
31
|
-
// Actions
|
|
32
|
-
/**
|
|
33
|
-
* Add a new event to history
|
|
34
|
-
*
|
|
35
|
-
* @param eventData - Event data without ID (auto-generated)
|
|
36
|
-
*/
|
|
37
|
-
addEvent: (eventData) => {
|
|
38
|
-
if (get().isPaused) {
|
|
39
|
-
return;
|
|
26
|
+
var createDevtoolsActions = (set, get) => {
|
|
27
|
+
let eventCounter = 0;
|
|
28
|
+
const createEventId = (eventData) => {
|
|
29
|
+
eventCounter += 1;
|
|
30
|
+
return `${String(eventData.timestamp)}-${eventData.blockerId}-${eventCounter.toString(36)}`;
|
|
31
|
+
};
|
|
32
|
+
const trimEvents = (events, maxEvents) => {
|
|
33
|
+
if (events.length <= maxEvents) {
|
|
34
|
+
return events;
|
|
40
35
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
36
|
+
return events.slice(0, maxEvents);
|
|
37
|
+
};
|
|
38
|
+
return {
|
|
39
|
+
// Initial State
|
|
40
|
+
events: [],
|
|
41
|
+
maxEvents: DEFAULT_MAX_EVENTS,
|
|
42
|
+
isOpen: false,
|
|
43
|
+
isMinimized: false,
|
|
44
|
+
activeTab: DEFAULT_TAB,
|
|
45
|
+
filter: createDefaultFilter(),
|
|
46
|
+
selectedEventId: null,
|
|
47
|
+
isPaused: false,
|
|
48
|
+
// Actions
|
|
49
|
+
/**
|
|
50
|
+
* Add a new event to history
|
|
51
|
+
*
|
|
52
|
+
* @param eventData - Event data without ID (auto-generated)
|
|
53
|
+
*/
|
|
54
|
+
addEvent: (eventData) => {
|
|
55
|
+
if (get().isPaused) {
|
|
56
|
+
return;
|
|
49
57
|
}
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
58
|
+
const event = {
|
|
59
|
+
...eventData,
|
|
60
|
+
id: createEventId(eventData)
|
|
61
|
+
};
|
|
62
|
+
set((state) => {
|
|
63
|
+
const newEvents = [event, ...state.events];
|
|
64
|
+
return { events: trimEvents(newEvents, state.maxEvents) };
|
|
65
|
+
});
|
|
66
|
+
},
|
|
67
|
+
/**
|
|
68
|
+
* Clear all events from history
|
|
69
|
+
*/
|
|
70
|
+
clearEvents: () => {
|
|
71
|
+
set({ events: [], selectedEventId: null });
|
|
72
|
+
},
|
|
73
|
+
/**
|
|
74
|
+
* Toggle panel open/closed state
|
|
75
|
+
*/
|
|
76
|
+
toggleOpen: () => {
|
|
77
|
+
set((state) => ({ isOpen: !state.isOpen }));
|
|
78
|
+
},
|
|
79
|
+
/**
|
|
80
|
+
* Set panel open state
|
|
81
|
+
*
|
|
82
|
+
* @param open - Whether panel should be open
|
|
83
|
+
*/
|
|
84
|
+
setOpen: (open) => {
|
|
85
|
+
set({ isOpen: open });
|
|
86
|
+
},
|
|
87
|
+
/**
|
|
88
|
+
* Toggle minimized state
|
|
89
|
+
*/
|
|
90
|
+
toggleMinimized: () => {
|
|
91
|
+
set((state) => ({ isMinimized: !state.isMinimized }));
|
|
92
|
+
},
|
|
93
|
+
/**
|
|
94
|
+
* Set active tab
|
|
95
|
+
*
|
|
96
|
+
* @param tab - Tab to activate
|
|
97
|
+
*/
|
|
98
|
+
setActiveTab: (tab) => {
|
|
99
|
+
set({ activeTab: tab, selectedEventId: null });
|
|
100
|
+
},
|
|
101
|
+
/**
|
|
102
|
+
* Update filter settings (partial update)
|
|
103
|
+
*
|
|
104
|
+
* @param filterUpdate - Partial filter update
|
|
105
|
+
*/
|
|
106
|
+
setFilter: (filterUpdate) => {
|
|
107
|
+
set((state) => ({
|
|
108
|
+
filter: { ...state.filter, ...filterUpdate }
|
|
109
|
+
}));
|
|
110
|
+
},
|
|
111
|
+
/**
|
|
112
|
+
* Reset filters to default
|
|
113
|
+
*/
|
|
114
|
+
resetFilter: () => {
|
|
115
|
+
set({ filter: createDefaultFilter() });
|
|
116
|
+
},
|
|
117
|
+
/**
|
|
118
|
+
* Select an event for detail view
|
|
119
|
+
*
|
|
120
|
+
* @param eventId - Event ID to select (null to deselect)
|
|
121
|
+
*/
|
|
122
|
+
selectEvent: (eventId) => {
|
|
123
|
+
set({ selectedEventId: eventId });
|
|
124
|
+
},
|
|
125
|
+
/**
|
|
126
|
+
* Toggle pause state (stops/resumes recording)
|
|
127
|
+
*/
|
|
128
|
+
togglePause: () => {
|
|
129
|
+
set((state) => ({ isPaused: !state.isPaused }));
|
|
130
|
+
},
|
|
131
|
+
/**
|
|
132
|
+
* Set maximum events limit
|
|
133
|
+
*
|
|
134
|
+
* @param max - Maximum number of events to keep
|
|
135
|
+
*/
|
|
136
|
+
setMaxEvents: (max) => {
|
|
137
|
+
set((state) => ({
|
|
138
|
+
maxEvents: max,
|
|
139
|
+
events: trimEvents(state.events, max)
|
|
140
|
+
}));
|
|
141
|
+
}
|
|
142
|
+
};
|
|
143
|
+
};
|
|
129
144
|
|
|
130
145
|
// src/store/devtoolsStore.store.ts
|
|
131
146
|
var {
|
|
@@ -134,40 +149,50 @@ var {
|
|
|
134
149
|
} = createShallowStore(createDevtoolsActions);
|
|
135
150
|
|
|
136
151
|
// src/store/devtoolsStore.selectors.ts
|
|
152
|
+
function normalizeScopes(scope) {
|
|
153
|
+
if (!scope) {
|
|
154
|
+
return [];
|
|
155
|
+
}
|
|
156
|
+
if (typeof scope === "string") {
|
|
157
|
+
return [scope];
|
|
158
|
+
}
|
|
159
|
+
return scope;
|
|
160
|
+
}
|
|
161
|
+
function matchesActionFilter(event, actions) {
|
|
162
|
+
return actions.length === 0 || actions.includes(event.action);
|
|
163
|
+
}
|
|
164
|
+
function matchesScopeFilter(event, scopes) {
|
|
165
|
+
if (scopes.length === 0) {
|
|
166
|
+
return true;
|
|
167
|
+
}
|
|
168
|
+
const eventScopes = normalizeScopes(event.config?.scope);
|
|
169
|
+
if (eventScopes.length === 0) {
|
|
170
|
+
return false;
|
|
171
|
+
}
|
|
172
|
+
return eventScopes.some((scope) => scopes.includes(scope));
|
|
173
|
+
}
|
|
174
|
+
function matchesSearchQuery(event, search) {
|
|
175
|
+
if (!search) {
|
|
176
|
+
return true;
|
|
177
|
+
}
|
|
178
|
+
const searchLower = search.toLowerCase();
|
|
179
|
+
const matchesId = event.blockerId.toLowerCase().includes(searchLower);
|
|
180
|
+
const matchesReason = (event.config?.reason ?? "").toLowerCase().includes(searchLower);
|
|
181
|
+
const matchesScope = normalizeScopes(event.config?.scope).some(
|
|
182
|
+
(scope) => scope.toLowerCase().includes(searchLower)
|
|
183
|
+
);
|
|
184
|
+
return matchesId || matchesReason || matchesScope;
|
|
185
|
+
}
|
|
137
186
|
function selectFilteredEvents(state) {
|
|
138
187
|
const { events, filter } = state;
|
|
139
188
|
return events.filter((event) => {
|
|
140
|
-
|
|
141
|
-
return false;
|
|
142
|
-
}
|
|
143
|
-
if (filter.scopes.length > 0) {
|
|
144
|
-
if (!event.config?.scope) {
|
|
145
|
-
return false;
|
|
146
|
-
}
|
|
147
|
-
const eventScopes = Array.isArray(event.config.scope) ? event.config.scope : [event.config.scope];
|
|
148
|
-
const hasMatchingScope = eventScopes.some((s) => filter.scopes.includes(s));
|
|
149
|
-
if (!hasMatchingScope) {
|
|
150
|
-
return false;
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
if (filter.search) {
|
|
154
|
-
const searchLower = filter.search.toLowerCase();
|
|
155
|
-
const matchesId = event.blockerId.toLowerCase().includes(searchLower);
|
|
156
|
-
const matchesReason = event.config?.reason?.toLowerCase().includes(searchLower);
|
|
157
|
-
if (!matchesId && !matchesReason) {
|
|
158
|
-
return false;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
return true;
|
|
189
|
+
return matchesActionFilter(event, filter.actions) && matchesScopeFilter(event, filter.scopes) && matchesSearchQuery(event, filter.search);
|
|
162
190
|
});
|
|
163
191
|
}
|
|
164
192
|
function selectUniqueScopes(state) {
|
|
165
193
|
const scopes = /* @__PURE__ */ new Set();
|
|
166
194
|
state.events.forEach((event) => {
|
|
167
|
-
|
|
168
|
-
const eventScopes = Array.isArray(event.config.scope) ? event.config.scope : [event.config.scope];
|
|
169
|
-
eventScopes.forEach((s) => scopes.add(s));
|
|
170
|
-
}
|
|
195
|
+
normalizeScopes(event.config?.scope).forEach((scope) => scopes.add(scope));
|
|
171
196
|
});
|
|
172
197
|
return Array.from(scopes).sort();
|
|
173
198
|
}
|
|
@@ -179,19 +204,29 @@ function selectAllEvents(state) {
|
|
|
179
204
|
var DEVTOOLS_MIDDLEWARE_NAME = "action-guard-devtools";
|
|
180
205
|
function createDevtoolsMiddleware() {
|
|
181
206
|
const addTimestamps = /* @__PURE__ */ new Map();
|
|
207
|
+
const terminalActions = /* @__PURE__ */ new Set([
|
|
208
|
+
"remove",
|
|
209
|
+
"timeout",
|
|
210
|
+
"clear",
|
|
211
|
+
"clear_scope"
|
|
212
|
+
]);
|
|
213
|
+
const getDuration = (action, blockerId, timestamp) => {
|
|
214
|
+
if (!terminalActions.has(action)) {
|
|
215
|
+
return void 0;
|
|
216
|
+
}
|
|
217
|
+
const addTime = addTimestamps.get(blockerId);
|
|
218
|
+
if (addTime === void 0) {
|
|
219
|
+
return void 0;
|
|
220
|
+
}
|
|
221
|
+
addTimestamps.delete(blockerId);
|
|
222
|
+
return timestamp - addTime;
|
|
223
|
+
};
|
|
182
224
|
return (context) => {
|
|
183
225
|
const { addEvent } = devtoolsStoreApi.getState();
|
|
184
226
|
if (context.action === "add") {
|
|
185
227
|
addTimestamps.set(context.blockerId, context.timestamp);
|
|
186
228
|
}
|
|
187
|
-
|
|
188
|
-
if (context.action === "remove" || context.action === "timeout" || context.action === "cancel") {
|
|
189
|
-
const addTime = addTimestamps.get(context.blockerId);
|
|
190
|
-
if (addTime !== void 0) {
|
|
191
|
-
duration = context.timestamp - addTime;
|
|
192
|
-
addTimestamps.delete(context.blockerId);
|
|
193
|
-
}
|
|
194
|
-
}
|
|
229
|
+
const duration = getDuration(context.action, context.blockerId, context.timestamp);
|
|
195
230
|
addEvent({
|
|
196
231
|
action: context.action,
|
|
197
232
|
blockerId: context.blockerId,
|
|
@@ -203,6 +238,33 @@ function createDevtoolsMiddleware() {
|
|
|
203
238
|
};
|
|
204
239
|
}
|
|
205
240
|
|
|
241
|
+
// src/components/actionGuardDevtools/ActionGuardDevtools.utils.ts
|
|
242
|
+
function isTypingTarget(target) {
|
|
243
|
+
return target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement;
|
|
244
|
+
}
|
|
245
|
+
function getDevtoolsKeyboardAction(event, isOpen) {
|
|
246
|
+
if (!isOpen) {
|
|
247
|
+
return null;
|
|
248
|
+
}
|
|
249
|
+
if (isTypingTarget(event.target)) {
|
|
250
|
+
return null;
|
|
251
|
+
}
|
|
252
|
+
switch (event.key) {
|
|
253
|
+
case "Escape":
|
|
254
|
+
return { action: "close", preventDefault: false };
|
|
255
|
+
case " ":
|
|
256
|
+
return { action: "togglePause", preventDefault: true };
|
|
257
|
+
case "c":
|
|
258
|
+
case "C":
|
|
259
|
+
if (!event.metaKey && !event.ctrlKey) {
|
|
260
|
+
return { action: "clearEvents", preventDefault: false };
|
|
261
|
+
}
|
|
262
|
+
return null;
|
|
263
|
+
default:
|
|
264
|
+
return null;
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
|
|
206
268
|
// src/styles/position.module.css
|
|
207
269
|
var position_default = {};
|
|
208
270
|
|
|
@@ -274,19 +336,43 @@ var COLORS = {
|
|
|
274
336
|
var shared_default = {};
|
|
275
337
|
function Badge(props) {
|
|
276
338
|
const { children, className, style } = props;
|
|
277
|
-
return /* @__PURE__ */ jsx("span", { className:
|
|
339
|
+
return /* @__PURE__ */ jsx("span", { className: clsx(shared_default.badge, className), style, children });
|
|
278
340
|
}
|
|
279
341
|
var Badge_default = Badge;
|
|
280
342
|
function Content(props) {
|
|
281
343
|
const { children, className } = props;
|
|
282
|
-
return /* @__PURE__ */ jsx("div", { className:
|
|
344
|
+
return /* @__PURE__ */ jsx("div", { className: clsx(shared_default.content, className), children });
|
|
283
345
|
}
|
|
284
346
|
var Content_default = Content;
|
|
285
347
|
function EmptyState(props) {
|
|
286
348
|
const { children, className } = props;
|
|
287
|
-
return /* @__PURE__ */ jsx("div", { className:
|
|
349
|
+
return /* @__PURE__ */ jsx("div", { className: clsx(shared_default.emptyState, className), children });
|
|
288
350
|
}
|
|
289
351
|
var EmptyState_default = EmptyState;
|
|
352
|
+
var ErrorBoundary = class extends Component {
|
|
353
|
+
constructor(props) {
|
|
354
|
+
super(props);
|
|
355
|
+
this.state = { hasError: false, error: null };
|
|
356
|
+
}
|
|
357
|
+
static getDerivedStateFromError(error) {
|
|
358
|
+
return { hasError: true, error };
|
|
359
|
+
}
|
|
360
|
+
render() {
|
|
361
|
+
const { hasError, error } = this.state;
|
|
362
|
+
const { children, fallback } = this.props;
|
|
363
|
+
if (hasError) {
|
|
364
|
+
if (fallback) {
|
|
365
|
+
return fallback;
|
|
366
|
+
}
|
|
367
|
+
return /* @__PURE__ */ jsxs("div", { className: shared_default.errorBoundary, children: [
|
|
368
|
+
/* @__PURE__ */ jsx("span", { className: shared_default.errorTitle, children: "Devtools Error" }),
|
|
369
|
+
/* @__PURE__ */ jsx("span", { className: shared_default.errorMessage, children: error?.message ?? "Unknown error" })
|
|
370
|
+
] });
|
|
371
|
+
}
|
|
372
|
+
return children;
|
|
373
|
+
}
|
|
374
|
+
};
|
|
375
|
+
var ErrorBoundary_default = ErrorBoundary;
|
|
290
376
|
function EventBadge(props) {
|
|
291
377
|
const { children, className, style, action } = props;
|
|
292
378
|
const classes = clsx(shared_default.eventBadge, action && shared_default.eventBadgeAction, className);
|
|
@@ -295,7 +381,7 @@ function EventBadge(props) {
|
|
|
295
381
|
var EventBadge_default = EventBadge;
|
|
296
382
|
function IconButton(props) {
|
|
297
383
|
const { children, className, type = "button", ...others } = props;
|
|
298
|
-
return /* @__PURE__ */ jsx("button", { type, className:
|
|
384
|
+
return /* @__PURE__ */ jsx("button", { type, className: clsx(shared_default.iconButton, className), ...others, children });
|
|
299
385
|
}
|
|
300
386
|
var IconButton_default = IconButton;
|
|
301
387
|
|
|
@@ -595,7 +681,7 @@ function Timeline() {
|
|
|
595
681
|
);
|
|
596
682
|
const selectedEvent = selectedEventId ? events.find((e) => e.id === selectedEventId) : null;
|
|
597
683
|
useEffect(() => {
|
|
598
|
-
if (selectedEventId && !allEvents.some((
|
|
684
|
+
if (selectedEventId && !allEvents.some((event) => event.id === selectedEventId)) {
|
|
599
685
|
selectEvent(null);
|
|
600
686
|
}
|
|
601
687
|
}, [selectedEventId, allEvents, selectEvent]);
|
|
@@ -627,7 +713,7 @@ function Timeline() {
|
|
|
627
713
|
var Timeline_default2 = Timeline;
|
|
628
714
|
function DevtoolsPanelContent(props) {
|
|
629
715
|
const { activeTab, store } = props;
|
|
630
|
-
return activeTab === "timeline" ? /* @__PURE__ */ jsx(Timeline_default2, {}) : /* @__PURE__ */ jsx(ActiveBlockers_default2, { store });
|
|
716
|
+
return /* @__PURE__ */ jsx(ErrorBoundary_default, { children: activeTab === "timeline" ? /* @__PURE__ */ jsx(Timeline_default2, {}) : /* @__PURE__ */ jsx(ActiveBlockers_default2, { store }) });
|
|
631
717
|
}
|
|
632
718
|
var DevtoolsPanelContent_default = DevtoolsPanelContent;
|
|
633
719
|
var MaximizeIcon = createSvgIcon(/* @__PURE__ */ jsx("path", { d: "M3 3h18v2H3z" }));
|
|
@@ -792,41 +878,8 @@ function ActionGuardDevtoolsContent(props) {
|
|
|
792
878
|
] });
|
|
793
879
|
}
|
|
794
880
|
var ActionGuardDevtoolsContent_default = ActionGuardDevtoolsContent;
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
function isTypingTarget(target) {
|
|
798
|
-
return target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement;
|
|
799
|
-
}
|
|
800
|
-
function getDevtoolsKeyboardAction(event, isOpen) {
|
|
801
|
-
if (!isOpen) {
|
|
802
|
-
return null;
|
|
803
|
-
}
|
|
804
|
-
if (isTypingTarget(event.target)) {
|
|
805
|
-
return null;
|
|
806
|
-
}
|
|
807
|
-
switch (event.key) {
|
|
808
|
-
case "Escape":
|
|
809
|
-
return { action: "close", preventDefault: false };
|
|
810
|
-
case " ":
|
|
811
|
-
return { action: "togglePause", preventDefault: true };
|
|
812
|
-
case "c":
|
|
813
|
-
case "C":
|
|
814
|
-
if (!event.metaKey && !event.ctrlKey) {
|
|
815
|
-
return { action: "clearEvents", preventDefault: false };
|
|
816
|
-
}
|
|
817
|
-
return null;
|
|
818
|
-
default:
|
|
819
|
-
return null;
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
function ActionGuardDevtools(props) {
|
|
823
|
-
const {
|
|
824
|
-
position = "right",
|
|
825
|
-
defaultOpen = false,
|
|
826
|
-
maxEvents = 200,
|
|
827
|
-
showInProduction = false,
|
|
828
|
-
store: customStore
|
|
829
|
-
} = props;
|
|
881
|
+
function ActionGuardDevtoolsInternal(props) {
|
|
882
|
+
const { position = "right", defaultOpen = false, maxEvents = 200, store: customStore } = props;
|
|
830
883
|
const { setOpen, setMaxEvents, isOpen, togglePause, clearEvents } = useDevtoolsStore();
|
|
831
884
|
const targetStore = useMemo(() => customStore ?? uiBlockingStoreApi, [customStore]);
|
|
832
885
|
useEffect(() => {
|
|
@@ -841,9 +894,14 @@ function ActionGuardDevtools(props) {
|
|
|
841
894
|
setOpen(defaultOpen);
|
|
842
895
|
setMaxEvents(maxEvents);
|
|
843
896
|
}, [defaultOpen, maxEvents, setOpen, setMaxEvents]);
|
|
844
|
-
const
|
|
845
|
-
|
|
846
|
-
|
|
897
|
+
const stateRef = useRef({ isOpen, setOpen, togglePause, clearEvents });
|
|
898
|
+
useEffect(() => {
|
|
899
|
+
stateRef.current = { isOpen, setOpen, togglePause, clearEvents };
|
|
900
|
+
}, [isOpen, setOpen, togglePause, clearEvents]);
|
|
901
|
+
useEffect(() => {
|
|
902
|
+
const handleKeyDown = (event) => {
|
|
903
|
+
const { isOpen: isOpen2, setOpen: setOpen2, togglePause: togglePause2, clearEvents: clearEvents2 } = stateRef.current;
|
|
904
|
+
const action = getDevtoolsKeyboardAction(event, isOpen2);
|
|
847
905
|
if (!action) {
|
|
848
906
|
return;
|
|
849
907
|
}
|
|
@@ -852,28 +910,29 @@ function ActionGuardDevtools(props) {
|
|
|
852
910
|
}
|
|
853
911
|
switch (action.action) {
|
|
854
912
|
case "close":
|
|
855
|
-
|
|
913
|
+
setOpen2(false);
|
|
856
914
|
break;
|
|
857
915
|
case "togglePause":
|
|
858
|
-
|
|
916
|
+
togglePause2();
|
|
859
917
|
break;
|
|
860
918
|
case "clearEvents":
|
|
861
|
-
|
|
919
|
+
clearEvents2();
|
|
862
920
|
break;
|
|
863
921
|
}
|
|
864
|
-
}
|
|
865
|
-
[isOpen, setOpen, togglePause, clearEvents]
|
|
866
|
-
);
|
|
867
|
-
useEffect(() => {
|
|
922
|
+
};
|
|
868
923
|
document.addEventListener("keydown", handleKeyDown);
|
|
869
924
|
return () => {
|
|
870
925
|
document.removeEventListener("keydown", handleKeyDown);
|
|
871
926
|
};
|
|
872
|
-
}, [
|
|
927
|
+
}, []);
|
|
928
|
+
return /* @__PURE__ */ jsx(ActionGuardDevtoolsContent_default, { position, store: customStore });
|
|
929
|
+
}
|
|
930
|
+
function ActionGuardDevtools(props) {
|
|
931
|
+
const { showInProduction = false, ...others } = props;
|
|
873
932
|
if (process.env.NODE_ENV === "production" && !showInProduction) {
|
|
874
933
|
return null;
|
|
875
934
|
}
|
|
876
|
-
return /* @__PURE__ */ jsx(
|
|
935
|
+
return /* @__PURE__ */ jsx(ActionGuardDevtoolsInternal, { ...others });
|
|
877
936
|
}
|
|
878
937
|
var ActionGuardDevtools_default = ActionGuardDevtools;
|
|
879
938
|
|