@qontinui/ui-bridge 0.1.1

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 (47) hide show
  1. package/dist/control/index.d.mts +134 -0
  2. package/dist/control/index.d.ts +134 -0
  3. package/dist/control/index.js +924 -0
  4. package/dist/control/index.js.map +1 -0
  5. package/dist/control/index.mjs +919 -0
  6. package/dist/control/index.mjs.map +1 -0
  7. package/dist/core/index.d.mts +52 -0
  8. package/dist/core/index.d.ts +52 -0
  9. package/dist/core/index.js +1424 -0
  10. package/dist/core/index.js.map +1 -0
  11. package/dist/core/index.mjs +1409 -0
  12. package/dist/core/index.mjs.map +1 -0
  13. package/dist/debug/index.d.mts +93 -0
  14. package/dist/debug/index.d.ts +93 -0
  15. package/dist/debug/index.js +673 -0
  16. package/dist/debug/index.js.map +1 -0
  17. package/dist/debug/index.mjs +664 -0
  18. package/dist/debug/index.mjs.map +1 -0
  19. package/dist/index.d.mts +12 -0
  20. package/dist/index.d.ts +12 -0
  21. package/dist/index.js +4719 -0
  22. package/dist/index.js.map +1 -0
  23. package/dist/index.mjs +4665 -0
  24. package/dist/index.mjs.map +1 -0
  25. package/dist/metrics-BCG7z7Aq.d.mts +147 -0
  26. package/dist/metrics-QCnK0EFw.d.ts +147 -0
  27. package/dist/react/index.d.mts +786 -0
  28. package/dist/react/index.d.ts +786 -0
  29. package/dist/react/index.js +4312 -0
  30. package/dist/react/index.js.map +1 -0
  31. package/dist/react/index.mjs +4290 -0
  32. package/dist/react/index.mjs.map +1 -0
  33. package/dist/registry-CT6BVVKr.d.mts +253 -0
  34. package/dist/registry-D4mQ01B3.d.ts +253 -0
  35. package/dist/render-log/index.d.mts +340 -0
  36. package/dist/render-log/index.d.ts +340 -0
  37. package/dist/render-log/index.js +702 -0
  38. package/dist/render-log/index.js.map +1 -0
  39. package/dist/render-log/index.mjs +695 -0
  40. package/dist/render-log/index.mjs.map +1 -0
  41. package/dist/types-BDkXy5si.d.ts +354 -0
  42. package/dist/types-BpvpStn3.d.mts +802 -0
  43. package/dist/types-BpvpStn3.d.ts +802 -0
  44. package/dist/types-DdJD9yw5.d.mts +354 -0
  45. package/dist/websocket-client-B2LC9CYc.d.mts +124 -0
  46. package/dist/websocket-client-DupH0X7B.d.ts +124 -0
  47. package/package.json +83 -0
@@ -0,0 +1,664 @@
1
+ import { useState, useMemo, useCallback, useEffect } from 'react';
2
+ import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
3
+
4
+ // src/debug/inspector.tsx
5
+
6
+ // src/core/element-identifier.ts
7
+ function generateXPath(element) {
8
+ if (element.id) {
9
+ return `//*[@id="${element.id}"]`;
10
+ }
11
+ const parts = [];
12
+ let current = element;
13
+ while (current && current.nodeType === Node.ELEMENT_NODE) {
14
+ let selector = current.nodeName.toLowerCase();
15
+ const uiId = current.getAttribute("data-ui-id");
16
+ if (uiId) {
17
+ selector += `[@data-ui-id="${uiId}"]`;
18
+ parts.unshift(selector);
19
+ break;
20
+ }
21
+ const testId = current.getAttribute("data-testid");
22
+ if (testId) {
23
+ selector += `[@data-testid="${testId}"]`;
24
+ parts.unshift(selector);
25
+ break;
26
+ }
27
+ const id = current.id;
28
+ if (id) {
29
+ selector += `[@id="${id}"]`;
30
+ parts.unshift(selector);
31
+ break;
32
+ }
33
+ const parentEl = current.parentElement;
34
+ if (parentEl) {
35
+ const currentEl = current;
36
+ const siblings = Array.from(parentEl.children).filter(
37
+ (child) => child.nodeName === currentEl.nodeName
38
+ );
39
+ if (siblings.length > 1) {
40
+ const index = siblings.indexOf(currentEl) + 1;
41
+ selector += `[${index}]`;
42
+ }
43
+ }
44
+ parts.unshift(selector);
45
+ current = parentEl;
46
+ }
47
+ return "/" + parts.join("/");
48
+ }
49
+ function generateCSSSelector(element) {
50
+ const uiId = element.getAttribute("data-ui-id");
51
+ if (uiId) {
52
+ return `[data-ui-id="${uiId}"]`;
53
+ }
54
+ const testId = element.getAttribute("data-testid");
55
+ if (testId) {
56
+ return `[data-testid="${testId}"]`;
57
+ }
58
+ const awasId = element.getAttribute("data-awas-element");
59
+ if (awasId) {
60
+ return `[data-awas-element="${awasId}"]`;
61
+ }
62
+ if (element.id) {
63
+ return `#${CSS.escape(element.id)}`;
64
+ }
65
+ const path = [];
66
+ let current = element;
67
+ while (current && current.nodeType === Node.ELEMENT_NODE) {
68
+ let selector = current.nodeName.toLowerCase();
69
+ const parentUiId = current.getAttribute("data-ui-id");
70
+ if (parentUiId && current !== element) {
71
+ path.unshift(`[data-ui-id="${parentUiId}"]`);
72
+ break;
73
+ }
74
+ const parentTestId = current.getAttribute("data-testid");
75
+ if (parentTestId && current !== element) {
76
+ path.unshift(`[data-testid="${parentTestId}"]`);
77
+ break;
78
+ }
79
+ if (current.id) {
80
+ path.unshift(`#${CSS.escape(current.id)}`);
81
+ break;
82
+ }
83
+ const parentEl = current.parentElement;
84
+ if (parentEl) {
85
+ const currentEl = current;
86
+ const siblings = Array.from(parentEl.children);
87
+ const sameTagSiblings = siblings.filter(
88
+ (s) => s.nodeName === currentEl.nodeName
89
+ );
90
+ if (sameTagSiblings.length > 1) {
91
+ const index = siblings.indexOf(currentEl) + 1;
92
+ selector += `:nth-child(${index})`;
93
+ }
94
+ }
95
+ path.unshift(selector);
96
+ current = current.parentElement;
97
+ }
98
+ return path.join(" > ");
99
+ }
100
+ function getBestIdentifier(element) {
101
+ const uiId = element.getAttribute("data-ui-id");
102
+ if (uiId) return uiId;
103
+ const testId = element.getAttribute("data-testid");
104
+ if (testId) return testId;
105
+ const awasId = element.getAttribute("data-awas-element");
106
+ if (awasId) return awasId;
107
+ if (element.id) return element.id;
108
+ return generateCSSSelector(element);
109
+ }
110
+ function createElementIdentifier(element) {
111
+ return {
112
+ uiId: element.getAttribute("data-ui-id") || void 0,
113
+ testId: element.getAttribute("data-testid") || void 0,
114
+ awasId: element.getAttribute("data-awas-element") || void 0,
115
+ htmlId: element.id || void 0,
116
+ xpath: generateXPath(element),
117
+ selector: generateCSSSelector(element)
118
+ };
119
+ }
120
+ var overlayStyles = {
121
+ position: "fixed",
122
+ pointerEvents: "none",
123
+ zIndex: 999999,
124
+ border: "2px solid #3b82f6",
125
+ backgroundColor: "rgba(59, 130, 246, 0.1)",
126
+ transition: "all 0.1s ease-out"
127
+ };
128
+ var labelStyles = {
129
+ position: "absolute",
130
+ top: "-24px",
131
+ left: "0",
132
+ padding: "2px 8px",
133
+ backgroundColor: "#3b82f6",
134
+ color: "white",
135
+ fontSize: "12px",
136
+ fontFamily: "monospace",
137
+ whiteSpace: "nowrap",
138
+ borderRadius: "4px 4px 0 0"
139
+ };
140
+ var panelStyles = {
141
+ position: "fixed",
142
+ bottom: "20px",
143
+ right: "20px",
144
+ width: "400px",
145
+ maxHeight: "500px",
146
+ overflow: "auto",
147
+ backgroundColor: "#1f2937",
148
+ color: "#f3f4f6",
149
+ borderRadius: "8px",
150
+ boxShadow: "0 4px 20px rgba(0, 0, 0, 0.3)",
151
+ fontFamily: "monospace",
152
+ fontSize: "12px",
153
+ zIndex: 999998
154
+ };
155
+ var headerStyles = {
156
+ padding: "12px 16px",
157
+ backgroundColor: "#111827",
158
+ borderBottom: "1px solid #374151",
159
+ display: "flex",
160
+ justifyContent: "space-between",
161
+ alignItems: "center",
162
+ borderRadius: "8px 8px 0 0"
163
+ };
164
+ var sectionStyles = {
165
+ padding: "12px 16px",
166
+ borderBottom: "1px solid #374151"
167
+ };
168
+ var labelKeyStyles = {
169
+ color: "#9ca3af",
170
+ marginRight: "8px"
171
+ };
172
+ var valueStyles = {
173
+ color: "#60a5fa"
174
+ };
175
+ function getElementState(element) {
176
+ const rect = element.getBoundingClientRect();
177
+ const style = window.getComputedStyle(element);
178
+ const state = {
179
+ visible: rect.width > 0 && rect.height > 0 && style.display !== "none",
180
+ enabled: !("disabled" in element && element.disabled),
181
+ focused: document.activeElement === element,
182
+ rect: {
183
+ x: rect.x,
184
+ y: rect.y,
185
+ width: rect.width,
186
+ height: rect.height,
187
+ top: rect.top,
188
+ right: rect.right,
189
+ bottom: rect.bottom,
190
+ left: rect.left
191
+ },
192
+ computedStyles: {
193
+ display: style.display,
194
+ visibility: style.visibility,
195
+ opacity: style.opacity,
196
+ pointerEvents: style.pointerEvents
197
+ }
198
+ };
199
+ if (element instanceof HTMLInputElement) {
200
+ state.value = element.value;
201
+ if (element.type === "checkbox" || element.type === "radio") {
202
+ state.checked = element.checked;
203
+ }
204
+ }
205
+ return state;
206
+ }
207
+ function InspectorOverlay({ bounds, label }) {
208
+ return /* @__PURE__ */ jsx(
209
+ "div",
210
+ {
211
+ style: {
212
+ ...overlayStyles,
213
+ left: bounds.left + window.scrollX,
214
+ top: bounds.top + window.scrollY,
215
+ width: bounds.width,
216
+ height: bounds.height
217
+ },
218
+ children: /* @__PURE__ */ jsx("span", { style: labelStyles, children: label })
219
+ }
220
+ );
221
+ }
222
+ function InfoPanel({ element, onClose, registeredElement }) {
223
+ if (!element) return null;
224
+ const identifier = createElementIdentifier(element);
225
+ const state = getElementState(element);
226
+ const bestId = getBestIdentifier(element);
227
+ return /* @__PURE__ */ jsxs("div", { style: panelStyles, children: [
228
+ /* @__PURE__ */ jsxs("div", { style: headerStyles, children: [
229
+ /* @__PURE__ */ jsx("span", { style: { fontWeight: "bold", color: "#60a5fa" }, children: "UI Bridge Inspector" }),
230
+ /* @__PURE__ */ jsx(
231
+ "button",
232
+ {
233
+ onClick: onClose,
234
+ style: {
235
+ background: "none",
236
+ border: "none",
237
+ color: "#9ca3af",
238
+ cursor: "pointer",
239
+ fontSize: "16px"
240
+ },
241
+ children: "\xD7"
242
+ }
243
+ )
244
+ ] }),
245
+ /* @__PURE__ */ jsxs("div", { style: sectionStyles, children: [
246
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px", fontWeight: "bold", color: "#f3f4f6" }, children: "Element" }),
247
+ /* @__PURE__ */ jsxs("div", { children: [
248
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Tag:" }),
249
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: element.tagName.toLowerCase() })
250
+ ] }),
251
+ /* @__PURE__ */ jsxs("div", { children: [
252
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Best ID:" }),
253
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: bestId })
254
+ ] }),
255
+ identifier.uiId && /* @__PURE__ */ jsxs("div", { children: [
256
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "data-ui-id:" }),
257
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: identifier.uiId })
258
+ ] }),
259
+ identifier.testId && /* @__PURE__ */ jsxs("div", { children: [
260
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "data-testid:" }),
261
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: identifier.testId })
262
+ ] }),
263
+ identifier.htmlId && /* @__PURE__ */ jsxs("div", { children: [
264
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "id:" }),
265
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: identifier.htmlId })
266
+ ] }),
267
+ registeredElement && /* @__PURE__ */ jsxs("div", { children: [
268
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Registered:" }),
269
+ /* @__PURE__ */ jsxs("span", { style: { color: "#10b981" }, children: [
270
+ "Yes (",
271
+ registeredElement.type,
272
+ ")"
273
+ ] })
274
+ ] })
275
+ ] }),
276
+ /* @__PURE__ */ jsxs("div", { style: sectionStyles, children: [
277
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px", fontWeight: "bold", color: "#f3f4f6" }, children: "State" }),
278
+ /* @__PURE__ */ jsxs("div", { children: [
279
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Visible:" }),
280
+ /* @__PURE__ */ jsx("span", { style: { color: state.visible ? "#10b981" : "#ef4444" }, children: state.visible ? "Yes" : "No" })
281
+ ] }),
282
+ /* @__PURE__ */ jsxs("div", { children: [
283
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Enabled:" }),
284
+ /* @__PURE__ */ jsx("span", { style: { color: state.enabled ? "#10b981" : "#ef4444" }, children: state.enabled ? "Yes" : "No" })
285
+ ] }),
286
+ /* @__PURE__ */ jsxs("div", { children: [
287
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Focused:" }),
288
+ /* @__PURE__ */ jsx("span", { style: { color: state.focused ? "#10b981" : "#9ca3af" }, children: state.focused ? "Yes" : "No" })
289
+ ] }),
290
+ state.value !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
291
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Value:" }),
292
+ /* @__PURE__ */ jsxs("span", { style: valueStyles, children: [
293
+ '"',
294
+ state.value,
295
+ '"'
296
+ ] })
297
+ ] }),
298
+ state.checked !== void 0 && /* @__PURE__ */ jsxs("div", { children: [
299
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Checked:" }),
300
+ /* @__PURE__ */ jsx("span", { style: { color: state.checked ? "#10b981" : "#9ca3af" }, children: state.checked ? "Yes" : "No" })
301
+ ] })
302
+ ] }),
303
+ /* @__PURE__ */ jsxs("div", { style: sectionStyles, children: [
304
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px", fontWeight: "bold", color: "#f3f4f6" }, children: "Bounds" }),
305
+ /* @__PURE__ */ jsxs("div", { children: [
306
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Position:" }),
307
+ /* @__PURE__ */ jsxs("span", { style: valueStyles, children: [
308
+ "(",
309
+ Math.round(state.rect.x),
310
+ ", ",
311
+ Math.round(state.rect.y),
312
+ ")"
313
+ ] })
314
+ ] }),
315
+ /* @__PURE__ */ jsxs("div", { children: [
316
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "Size:" }),
317
+ /* @__PURE__ */ jsxs("span", { style: valueStyles, children: [
318
+ Math.round(state.rect.width),
319
+ " \xD7 ",
320
+ Math.round(state.rect.height)
321
+ ] })
322
+ ] })
323
+ ] }),
324
+ /* @__PURE__ */ jsxs("div", { style: { ...sectionStyles, borderBottom: "none" }, children: [
325
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px", fontWeight: "bold", color: "#f3f4f6" }, children: "Selectors" }),
326
+ /* @__PURE__ */ jsxs("div", { style: { wordBreak: "break-all", marginBottom: "4px" }, children: [
327
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "CSS:" }),
328
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: identifier.selector })
329
+ ] }),
330
+ /* @__PURE__ */ jsxs("div", { style: { wordBreak: "break-all" }, children: [
331
+ /* @__PURE__ */ jsx("span", { style: labelKeyStyles, children: "XPath:" }),
332
+ /* @__PURE__ */ jsx("span", { style: valueStyles, children: identifier.xpath })
333
+ ] })
334
+ ] }),
335
+ registeredElement && registeredElement.actions.length > 0 && /* @__PURE__ */ jsxs("div", { style: { ...sectionStyles, borderBottom: "none" }, children: [
336
+ /* @__PURE__ */ jsx("div", { style: { marginBottom: "8px", fontWeight: "bold", color: "#f3f4f6" }, children: "Actions" }),
337
+ /* @__PURE__ */ jsx("div", { style: { display: "flex", flexWrap: "wrap", gap: "4px" }, children: registeredElement.actions.map((action) => /* @__PURE__ */ jsx(
338
+ "span",
339
+ {
340
+ style: {
341
+ padding: "2px 8px",
342
+ backgroundColor: "#374151",
343
+ borderRadius: "4px",
344
+ color: "#60a5fa"
345
+ },
346
+ children: action
347
+ },
348
+ action
349
+ )) })
350
+ ] })
351
+ ] });
352
+ }
353
+ function useInspector(options = {}) {
354
+ const [active, setActive] = useState(false);
355
+ const [hoveredElement, setHoveredElement] = useState(null);
356
+ const [selectedElement, setSelectedElement] = useState(null);
357
+ const shortcut = useMemo(
358
+ () => options.shortcut ?? { key: "i", ctrl: true, shift: true },
359
+ [options.shortcut]
360
+ );
361
+ const toggle = useCallback(() => {
362
+ setActive((prev) => !prev);
363
+ if (active) {
364
+ setHoveredElement(null);
365
+ setSelectedElement(null);
366
+ }
367
+ }, [active]);
368
+ useEffect(() => {
369
+ const handleKeyDown = (e) => {
370
+ if (e.key.toLowerCase() === shortcut.key && e.ctrlKey === !!shortcut.ctrl && e.shiftKey === !!shortcut.shift && e.altKey === !!shortcut.alt) {
371
+ e.preventDefault();
372
+ toggle();
373
+ }
374
+ };
375
+ window.addEventListener("keydown", handleKeyDown);
376
+ return () => window.removeEventListener("keydown", handleKeyDown);
377
+ }, [toggle, shortcut]);
378
+ useEffect(() => {
379
+ if (!active) return;
380
+ const handleMouseOver = (e) => {
381
+ const target = e.target;
382
+ if (target && target !== hoveredElement) {
383
+ setHoveredElement(target);
384
+ }
385
+ };
386
+ const handleClick = (e) => {
387
+ e.preventDefault();
388
+ e.stopPropagation();
389
+ const target = e.target;
390
+ setSelectedElement(target);
391
+ options.onSelect?.(target);
392
+ };
393
+ document.addEventListener("mouseover", handleMouseOver, true);
394
+ document.addEventListener("click", handleClick, true);
395
+ return () => {
396
+ document.removeEventListener("mouseover", handleMouseOver, true);
397
+ document.removeEventListener("click", handleClick, true);
398
+ };
399
+ }, [active, hoveredElement, options]);
400
+ const displayElement = selectedElement || hoveredElement;
401
+ const bounds = displayElement?.getBoundingClientRect() || null;
402
+ const registeredElement = displayElement ? options.getRegisteredElement?.(displayElement) : void 0;
403
+ return {
404
+ active,
405
+ toggle,
406
+ hoveredElement,
407
+ selectedElement,
408
+ setSelectedElement,
409
+ displayElement,
410
+ bounds,
411
+ registeredElement,
412
+ clearSelection: () => {
413
+ setSelectedElement(null);
414
+ }
415
+ };
416
+ }
417
+ function Inspector({ getRegisteredElement, initialActive }) {
418
+ const inspector = useInspector({
419
+ getRegisteredElement
420
+ });
421
+ useEffect(() => {
422
+ if (initialActive && !inspector.active) {
423
+ inspector.toggle();
424
+ }
425
+ }, [initialActive]);
426
+ if (!inspector.active) return null;
427
+ return /* @__PURE__ */ jsxs(Fragment, { children: [
428
+ inspector.bounds && /* @__PURE__ */ jsx(
429
+ InspectorOverlay,
430
+ {
431
+ bounds: inspector.bounds,
432
+ label: inspector.displayElement ? getBestIdentifier(inspector.displayElement) : ""
433
+ }
434
+ ),
435
+ inspector.selectedElement && /* @__PURE__ */ jsx(
436
+ InfoPanel,
437
+ {
438
+ element: inspector.selectedElement,
439
+ onClose: inspector.clearSelection,
440
+ registeredElement: inspector.registeredElement
441
+ }
442
+ )
443
+ ] });
444
+ }
445
+
446
+ // src/debug/metrics.ts
447
+ function generateId() {
448
+ return `${Date.now()}-${Math.random().toString(36).substr(2, 8)}`;
449
+ }
450
+ var MetricsCollector = class {
451
+ constructor(options = {}) {
452
+ this.history = [];
453
+ this.maxHistoryEntries = options.maxHistoryEntries ?? 1e3;
454
+ this.rateWindow = options.rateWindow ?? 6e4;
455
+ }
456
+ /**
457
+ * Record an element action
458
+ */
459
+ recordElementAction(target, action, response, params) {
460
+ const entry = {
461
+ id: generateId(),
462
+ timestamp: response.timestamp,
463
+ type: "element",
464
+ target,
465
+ action,
466
+ success: response.success,
467
+ durationMs: response.durationMs,
468
+ error: response.error,
469
+ params,
470
+ response: response.elementState
471
+ };
472
+ this.addEntry(entry);
473
+ return entry;
474
+ }
475
+ /**
476
+ * Record a component action
477
+ */
478
+ recordComponentAction(target, action, response, params) {
479
+ const entry = {
480
+ id: generateId(),
481
+ timestamp: response.timestamp,
482
+ type: "component",
483
+ target,
484
+ action,
485
+ success: response.success,
486
+ durationMs: response.durationMs,
487
+ error: response.error,
488
+ params,
489
+ response: response.result
490
+ };
491
+ this.addEntry(entry);
492
+ return entry;
493
+ }
494
+ /**
495
+ * Record a workflow step
496
+ */
497
+ recordWorkflowStep(workflowId, result) {
498
+ const entry = {
499
+ id: generateId(),
500
+ timestamp: result.timestamp,
501
+ type: "workflow-step",
502
+ target: workflowId,
503
+ action: result.stepId,
504
+ success: result.success,
505
+ durationMs: result.durationMs,
506
+ error: result.error,
507
+ response: result.result
508
+ };
509
+ this.addEntry(entry);
510
+ return entry;
511
+ }
512
+ /**
513
+ * Record from a bridge event
514
+ */
515
+ recordEvent(event) {
516
+ if (event.type === "action:completed" || event.type === "action:failed") {
517
+ const data = event.data;
518
+ if (data.elementId) {
519
+ this.recordElementAction(
520
+ data.elementId,
521
+ data.action,
522
+ data.response,
523
+ data.params
524
+ );
525
+ } else if (data.componentId) {
526
+ this.recordComponentAction(
527
+ data.componentId,
528
+ data.action,
529
+ data.response,
530
+ data.params
531
+ );
532
+ }
533
+ }
534
+ }
535
+ /**
536
+ * Get action history
537
+ */
538
+ getHistory(options) {
539
+ let results = [...this.history];
540
+ if (options?.type) {
541
+ results = results.filter((e) => e.type === options.type);
542
+ }
543
+ if (options?.target) {
544
+ results = results.filter((e) => e.target === options.target);
545
+ }
546
+ if (options?.action) {
547
+ results = results.filter((e) => e.action === options.action);
548
+ }
549
+ if (options?.success !== void 0) {
550
+ results = results.filter((e) => e.success === options.success);
551
+ }
552
+ if (options?.since) {
553
+ results = results.filter((e) => e.timestamp >= options.since);
554
+ }
555
+ if (options?.limit) {
556
+ results = results.slice(-options.limit);
557
+ }
558
+ return results;
559
+ }
560
+ /**
561
+ * Get performance metrics
562
+ */
563
+ getMetrics(since) {
564
+ const entries = since ? this.history.filter((e) => e.timestamp >= since) : this.history;
565
+ if (entries.length === 0) {
566
+ return {
567
+ totalActions: 0,
568
+ successfulActions: 0,
569
+ failedActions: 0,
570
+ successRate: 0,
571
+ avgDurationMs: 0,
572
+ minDurationMs: 0,
573
+ maxDurationMs: 0,
574
+ p95DurationMs: 0,
575
+ actionsPerSecond: 0,
576
+ errorsByType: {},
577
+ actionsByType: {}
578
+ };
579
+ }
580
+ const successful = entries.filter((e) => e.success);
581
+ const failed = entries.filter((e) => !e.success);
582
+ const durations = entries.map((e) => e.durationMs).sort((a, b) => a - b);
583
+ const now = Date.now();
584
+ const windowStart = now - this.rateWindow;
585
+ const recentActions = this.history.filter((e) => e.timestamp >= windowStart);
586
+ const windowSeconds = this.rateWindow / 1e3;
587
+ const errorsByType = {};
588
+ for (const entry of failed) {
589
+ const errorType = entry.error?.split(":")[0] || "Unknown";
590
+ errorsByType[errorType] = (errorsByType[errorType] || 0) + 1;
591
+ }
592
+ const actionsByType = {};
593
+ for (const entry of entries) {
594
+ const key = `${entry.type}:${entry.action}`;
595
+ actionsByType[key] = (actionsByType[key] || 0) + 1;
596
+ }
597
+ return {
598
+ totalActions: entries.length,
599
+ successfulActions: successful.length,
600
+ failedActions: failed.length,
601
+ successRate: successful.length / entries.length,
602
+ avgDurationMs: durations.reduce((a, b) => a + b, 0) / durations.length,
603
+ minDurationMs: durations[0],
604
+ maxDurationMs: durations[durations.length - 1],
605
+ p95DurationMs: durations[Math.floor(durations.length * 0.95)],
606
+ actionsPerSecond: recentActions.length / windowSeconds,
607
+ errorsByType,
608
+ actionsByType
609
+ };
610
+ }
611
+ /**
612
+ * Get recent errors
613
+ */
614
+ getRecentErrors(limit = 10) {
615
+ return this.history.filter((e) => !e.success).slice(-limit);
616
+ }
617
+ /**
618
+ * Get slowest actions
619
+ */
620
+ getSlowestActions(limit = 10) {
621
+ return [...this.history].sort((a, b) => b.durationMs - a.durationMs).slice(0, limit);
622
+ }
623
+ /**
624
+ * Clear history
625
+ */
626
+ clearHistory() {
627
+ this.history = [];
628
+ }
629
+ /**
630
+ * Export history as JSON
631
+ */
632
+ exportHistory() {
633
+ return JSON.stringify(this.history, null, 2);
634
+ }
635
+ /**
636
+ * Import history from JSON
637
+ */
638
+ importHistory(json) {
639
+ const entries = JSON.parse(json);
640
+ this.history = entries.slice(-this.maxHistoryEntries);
641
+ }
642
+ addEntry(entry) {
643
+ this.history.push(entry);
644
+ while (this.history.length > this.maxHistoryEntries) {
645
+ this.history.shift();
646
+ }
647
+ }
648
+ };
649
+ function createMetricsCollector(options) {
650
+ return new MetricsCollector(options);
651
+ }
652
+ function formatDuration(ms) {
653
+ if (ms < 1) return "<1ms";
654
+ if (ms < 1e3) return `${Math.round(ms)}ms`;
655
+ if (ms < 6e4) return `${(ms / 1e3).toFixed(1)}s`;
656
+ return `${(ms / 6e4).toFixed(1)}m`;
657
+ }
658
+ function formatPercentage(value) {
659
+ return `${(value * 100).toFixed(1)}%`;
660
+ }
661
+
662
+ export { InfoPanel, Inspector, InspectorOverlay, MetricsCollector, createMetricsCollector, formatDuration, formatPercentage, useInspector };
663
+ //# sourceMappingURL=index.mjs.map
664
+ //# sourceMappingURL=index.mjs.map