@react-trace-enhancer/plugin-open-editor 0.0.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.
- package/README.md +71 -0
- package/dist/index-Boboj3a-.d.ts +19 -0
- package/dist/index-Boboj3a-.d.ts.map +1 -0
- package/dist/index-CXpzVMLC.d.cts +19 -0
- package/dist/index-CXpzVMLC.d.cts.map +1 -0
- package/dist/index.cjs +119 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +2 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +118 -0
- package/dist/index.js.map +1 -0
- package/dist/index.prod.cjs +11 -0
- package/dist/index.prod.cjs.map +1 -0
- package/dist/index.prod.d.cts +12 -0
- package/dist/index.prod.d.cts.map +1 -0
- package/dist/index.prod.d.ts +12 -0
- package/dist/index.prod.d.ts.map +1 -0
- package/dist/index.prod.js +9 -0
- package/dist/index.prod.js.map +1 -0
- package/package.json +80 -0
package/README.md
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
# @react-trace-enhancer/plugin-open-editor
|
|
2
|
+
|
|
3
|
+
Open the currently selected component source in a local editor from the Trace action panel.
|
|
4
|
+
|
|
5
|
+
This plugin adds:
|
|
6
|
+
|
|
7
|
+
- an `Open in Editor` action for the selected source
|
|
8
|
+
- a settings control for choosing the default editor inside the widget
|
|
9
|
+
|
|
10
|
+
## Installation
|
|
11
|
+
|
|
12
|
+
Install the plugin alongside its peer dependencies:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
pnpm add --dev @react-trace-enhancer/core @react-trace-enhancer/ui-components @react-trace-enhancer/plugin-open-editor
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
If you are already using `@react-trace-enhancer/kit`, this plugin is included there by default.
|
|
19
|
+
|
|
20
|
+
## Usage
|
|
21
|
+
|
|
22
|
+
```tsx
|
|
23
|
+
import { Trace } from '@react-trace-enhancer/core'
|
|
24
|
+
import { OpenEditorPlugin } from '@react-trace-enhancer/plugin-open-editor'
|
|
25
|
+
|
|
26
|
+
import App from './App'
|
|
27
|
+
|
|
28
|
+
export function AppWithTrace() {
|
|
29
|
+
return (
|
|
30
|
+
<>
|
|
31
|
+
<App />
|
|
32
|
+
<Trace
|
|
33
|
+
root={import.meta.env.VITE_ROOT}
|
|
34
|
+
plugins={[OpenEditorPlugin({ editor: 'vscode' })]}
|
|
35
|
+
/>
|
|
36
|
+
</>
|
|
37
|
+
)
|
|
38
|
+
}
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`root` should be the absolute project root passed to Trace so the plugin can resolve relative file paths for comments.
|
|
42
|
+
|
|
43
|
+
## `editor` option
|
|
44
|
+
|
|
45
|
+
`OpenEditorPlugin` accepts a single option:
|
|
46
|
+
|
|
47
|
+
```ts
|
|
48
|
+
interface OpenEditorPluginOptions {
|
|
49
|
+
editor?: EditorPreset
|
|
50
|
+
}
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
- Default: `vscode`
|
|
54
|
+
- If the user changes the editor in the widget settings, that's what's used instead.
|
|
55
|
+
|
|
56
|
+
The package also exports the `EditorPreset` type.
|
|
57
|
+
|
|
58
|
+
## Supported editor presets
|
|
59
|
+
|
|
60
|
+
These are the currently implemented presets:
|
|
61
|
+
|
|
62
|
+
- `vscode`
|
|
63
|
+
- `cursor`
|
|
64
|
+
- `windsurf`
|
|
65
|
+
- `zed`
|
|
66
|
+
- `webstorm`
|
|
67
|
+
- `intellij`
|
|
68
|
+
|
|
69
|
+
## Behavior
|
|
70
|
+
|
|
71
|
+
When a source location is selected, the plugin resolves the file path relative to the Trace `root` and opens the generated editor URL with `window.open(...)`.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TracePlugin } from "@react-trace-enhancer/core";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
type EditorPreset = 'vscode' | 'cursor' | 'windsurf' | 'webstorm' | 'intellij' | 'zed';
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/index.d.ts
|
|
7
|
+
interface OpenEditorPluginOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The editor to open files in.
|
|
10
|
+
* @default 'vscode'
|
|
11
|
+
*/
|
|
12
|
+
editor?: EditorPreset;
|
|
13
|
+
}
|
|
14
|
+
declare function OpenEditorPlugin({
|
|
15
|
+
editor
|
|
16
|
+
}?: OpenEditorPluginOptions): TracePlugin;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { OpenEditorPluginOptions as n, EditorPreset as r, OpenEditorPlugin as t };
|
|
19
|
+
//# sourceMappingURL=index-Boboj3a-.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-Boboj3a-.d.ts","names":[],"sources":["../src/types.ts","../src/index.tsx"],"mappings":";;;KAAY,YAAA;;;UCmBK,uBAAA;EDnBO;;;;ECwBtB,MAAA,GAAS,YAAA;AAAA;AAAA,iBA6CK,gBAAA,CAAA;EACd;AAAA,IACC,uBAAA,GAA+B,WAAA"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TracePlugin } from "@react-trace-enhancer/core";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
type EditorPreset = 'vscode' | 'cursor' | 'windsurf' | 'webstorm' | 'intellij' | 'zed';
|
|
5
|
+
//#endregion
|
|
6
|
+
//#region src/index.d.ts
|
|
7
|
+
interface OpenEditorPluginOptions {
|
|
8
|
+
/**
|
|
9
|
+
* The editor to open files in.
|
|
10
|
+
* @default 'vscode'
|
|
11
|
+
*/
|
|
12
|
+
editor?: EditorPreset;
|
|
13
|
+
}
|
|
14
|
+
declare function OpenEditorPlugin({
|
|
15
|
+
editor
|
|
16
|
+
}?: OpenEditorPluginOptions): TracePlugin;
|
|
17
|
+
//#endregion
|
|
18
|
+
export { OpenEditorPluginOptions as n, EditorPreset as r, OpenEditorPlugin as t };
|
|
19
|
+
//# sourceMappingURL=index-CXpzVMLC.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index-CXpzVMLC.d.cts","names":[],"sources":["../src/types.ts","../src/index.tsx"],"mappings":";;;KAAY,YAAA;;;UCmBK,uBAAA;EDnBO;;;;ECwBtB,MAAA,GAAS,YAAA;AAAA;AAAA,iBA6CK,gBAAA,CAAA;EACd;AAAA,IACC,uBAAA,GAA+B,WAAA"}
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
let _react_trace_enhancer_core = require("@react-trace-enhancer/core");
|
|
3
|
+
let _react_trace_enhancer_ui_components = require("@react-trace-enhancer/ui-components");
|
|
4
|
+
let jotai = require("jotai");
|
|
5
|
+
let react_jsx_runtime = require("react/jsx-runtime");
|
|
6
|
+
|
|
7
|
+
//#region src/store.ts
|
|
8
|
+
const openEditorSettingsAtom = (0, _react_trace_enhancer_core.settingsPluginAtom)("openEditor");
|
|
9
|
+
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/index.tsx
|
|
12
|
+
const EDITOR_LABELS = {
|
|
13
|
+
vscode: "VS Code",
|
|
14
|
+
cursor: "Cursor",
|
|
15
|
+
windsurf: "Windsurf",
|
|
16
|
+
zed: "Zed",
|
|
17
|
+
webstorm: "WebStorm",
|
|
18
|
+
intellij: "IntelliJ"
|
|
19
|
+
};
|
|
20
|
+
const editors = Object.entries(EDITOR_LABELS).map(([value, label]) => ({
|
|
21
|
+
value,
|
|
22
|
+
label
|
|
23
|
+
}));
|
|
24
|
+
const LABEL_STYLE = {
|
|
25
|
+
fontSize: 12,
|
|
26
|
+
color: "#d4d4d8",
|
|
27
|
+
fontFamily: "system-ui, sans-serif"
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Builds the editor-specific URL to open a file at a given line/column.
|
|
31
|
+
*
|
|
32
|
+
* VS Code family uses: {editor}://file/{path}:{line}:{col}
|
|
33
|
+
* JetBrains uses: {editor}://open?file={path}&line={line}
|
|
34
|
+
*/
|
|
35
|
+
function buildEditorUrl(editor, path, line, col) {
|
|
36
|
+
if (editor === "webstorm") return `webstorm://open?file=${encodeURIComponent(path)}&line=${line}`;
|
|
37
|
+
if (editor === "intellij") return `idea://open?file=${encodeURIComponent(path)}&line=${line}`;
|
|
38
|
+
return `${editor}://file/${path}:${line}:${col}`;
|
|
39
|
+
}
|
|
40
|
+
function OpenEditorPlugin({ editor = "vscode" } = {}) {
|
|
41
|
+
function OpenEditorActionPanel() {
|
|
42
|
+
const selectedSource = (0, _react_trace_enhancer_core.useSelectedSource)();
|
|
43
|
+
const clearSelectedContext = (0, _react_trace_enhancer_core.useClearSelectedContext)();
|
|
44
|
+
const currentEditor = (0, jotai.useAtomValue)(openEditorSettingsAtom)?.editor ?? editor;
|
|
45
|
+
if (!selectedSource) return null;
|
|
46
|
+
const handleOpenEditor = () => {
|
|
47
|
+
clearSelectedContext();
|
|
48
|
+
const url = buildEditorUrl(currentEditor, selectedSource.absolutePath, selectedSource.lineNumber, selectedSource.columnNumber);
|
|
49
|
+
window.open(url);
|
|
50
|
+
};
|
|
51
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_react_trace_enhancer_ui_components.DropdownMenu.Item, {
|
|
52
|
+
onClick: handleOpenEditor,
|
|
53
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
54
|
+
style: {
|
|
55
|
+
display: "flex",
|
|
56
|
+
alignItems: "center"
|
|
57
|
+
},
|
|
58
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.OpenInEditorIcon, {})
|
|
59
|
+
}), `Open in ${EDITOR_LABELS[currentEditor]}`]
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
function OpenEditorSettings() {
|
|
63
|
+
const portalContainer = (0, _react_trace_enhancer_core.useWidgetPortalContainer)();
|
|
64
|
+
const [editorSettings = { editor }, setEditorSettings] = (0, jotai.useAtom)(openEditorSettingsAtom);
|
|
65
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
66
|
+
style: {
|
|
67
|
+
display: "flex",
|
|
68
|
+
flexDirection: "column",
|
|
69
|
+
gap: 12
|
|
70
|
+
},
|
|
71
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
72
|
+
style: {
|
|
73
|
+
display: "flex",
|
|
74
|
+
flexDirection: "column",
|
|
75
|
+
gap: 6
|
|
76
|
+
},
|
|
77
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("label", {
|
|
78
|
+
style: LABEL_STYLE,
|
|
79
|
+
children: "Default editor"
|
|
80
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_react_trace_enhancer_ui_components.Select.Root, {
|
|
81
|
+
value: editorSettings.editor,
|
|
82
|
+
items: editors,
|
|
83
|
+
onValueChange: (value) => {
|
|
84
|
+
if (value) setEditorSettings({
|
|
85
|
+
...editorSettings,
|
|
86
|
+
editor: value
|
|
87
|
+
});
|
|
88
|
+
},
|
|
89
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.Trigger, {
|
|
90
|
+
onClick: (e) => e.stopPropagation(),
|
|
91
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.Value, {})
|
|
92
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.Portal, {
|
|
93
|
+
container: portalContainer,
|
|
94
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.Positioner, {
|
|
95
|
+
style: {
|
|
96
|
+
zIndex: 1e8,
|
|
97
|
+
pointerEvents: "auto"
|
|
98
|
+
},
|
|
99
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.Popup, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.List, { children: editors.map((option) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.Item, {
|
|
100
|
+
value: option.value,
|
|
101
|
+
onClick: (e) => e.stopPropagation(),
|
|
102
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_react_trace_enhancer_ui_components.Select.ItemText, { children: option.label })
|
|
103
|
+
}, option.value)) }) })
|
|
104
|
+
})
|
|
105
|
+
})]
|
|
106
|
+
})]
|
|
107
|
+
})
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
return {
|
|
111
|
+
name: "open-editor",
|
|
112
|
+
actionPanel: OpenEditorActionPanel,
|
|
113
|
+
settings: OpenEditorSettings
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
//#endregion
|
|
118
|
+
exports.OpenEditorPlugin = OpenEditorPlugin;
|
|
119
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["DropdownMenu","OpenInEditorIcon","Select"],"sources":["../src/store.ts","../src/index.tsx"],"sourcesContent":["import type { TraceSettings } from '@react-trace-enhancer/core'\nimport { settingsPluginAtom } from '@react-trace-enhancer/core'\nimport type { WritableAtom } from 'jotai'\n\nimport type { EditorPreset } from './types'\n\ndeclare module '@react-trace-enhancer/core' {\n interface TraceSettings {\n openEditor?: {\n editor: EditorPreset\n }\n }\n}\n\nexport const openEditorSettingsAtom = settingsPluginAtom(\n 'openEditor',\n) as WritableAtom<\n TraceSettings['openEditor'],\n [TraceSettings['openEditor']],\n void\n>\n","import type { TracePlugin } from '@react-trace-enhancer/core'\nimport {\n useClearSelectedContext,\n useSelectedSource,\n useWidgetPortalContainer,\n} from '@react-trace-enhancer/core'\nimport {\n DropdownMenu,\n OpenInEditorIcon,\n Select,\n} from '@react-trace-enhancer/ui-components'\nimport { useAtom, useAtomValue } from 'jotai'\nimport type { CSSProperties } from 'react'\n\nimport { openEditorSettingsAtom } from './store'\nimport type { EditorPreset } from './types'\n\nexport type { EditorPreset }\n\nexport interface OpenEditorPluginOptions {\n /**\n * The editor to open files in.\n * @default 'vscode'\n */\n editor?: EditorPreset\n}\n\nconst EDITOR_LABELS: Record<EditorPreset, string> = {\n vscode: 'VS Code',\n cursor: 'Cursor',\n windsurf: 'Windsurf',\n zed: 'Zed',\n webstorm: 'WebStorm',\n intellij: 'IntelliJ',\n}\n\nconst editors = Object.entries(EDITOR_LABELS).map(([value, label]) => ({\n value: value as EditorPreset,\n label,\n}))\n\nconst LABEL_STYLE: CSSProperties = {\n fontSize: 12,\n color: '#d4d4d8',\n fontFamily: 'system-ui, sans-serif',\n}\n\n/**\n * Builds the editor-specific URL to open a file at a given line/column.\n *\n * VS Code family uses: {editor}://file/{path}:{line}:{col}\n * JetBrains uses: {editor}://open?file={path}&line={line}\n */\nfunction buildEditorUrl(\n editor: EditorPreset,\n path: string,\n line: number,\n col: number,\n): string {\n if (editor === 'webstorm') {\n return `webstorm://open?file=${encodeURIComponent(path)}&line=${line}`\n }\n if (editor === 'intellij') {\n return `idea://open?file=${encodeURIComponent(path)}&line=${line}`\n }\n // VS Code family + Zed: vscode, cursor, windsurf, zed — identical format, different protocol\n return `${editor}://file/${path}:${line}:${col}`\n}\n\nexport function OpenEditorPlugin({\n editor = 'vscode',\n}: OpenEditorPluginOptions = {}): TracePlugin {\n function OpenEditorActionPanel() {\n const selectedSource = useSelectedSource()\n const clearSelectedContext = useClearSelectedContext()\n const editorSettings = useAtomValue(openEditorSettingsAtom)\n const currentEditor = editorSettings?.editor ?? editor\n\n if (!selectedSource) return null\n\n const handleOpenEditor = () => {\n clearSelectedContext()\n const url = buildEditorUrl(\n currentEditor,\n selectedSource.absolutePath,\n selectedSource.lineNumber,\n selectedSource.columnNumber,\n )\n window.open(url)\n }\n\n return (\n <DropdownMenu.Item onClick={handleOpenEditor}>\n <span style={{ display: 'flex', alignItems: 'center' }}>\n <OpenInEditorIcon />\n </span>\n {`Open in ${EDITOR_LABELS[currentEditor]}`}\n </DropdownMenu.Item>\n )\n }\n\n function OpenEditorSettings() {\n const portalContainer = useWidgetPortalContainer()\n\n const [editorSettings = { editor }, setEditorSettings] = useAtom(\n openEditorSettingsAtom,\n )\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <label style={LABEL_STYLE}>Default editor</label>\n <Select.Root\n value={editorSettings.editor}\n items={editors}\n onValueChange={(value) => {\n if (value) {\n setEditorSettings({ ...editorSettings, editor: value })\n }\n }}\n >\n <Select.Trigger onClick={(e) => e.stopPropagation()}>\n <Select.Value />\n </Select.Trigger>\n\n <Select.Portal container={portalContainer}>\n <Select.Positioner\n style={{ zIndex: 100000000, pointerEvents: 'auto' }}\n >\n <Select.Popup>\n <Select.List>\n {editors.map((option) => (\n <Select.Item\n key={option.value}\n value={option.value}\n onClick={(e) => e.stopPropagation()}\n >\n <Select.ItemText>{option.label}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n </div>\n </div>\n )\n }\n\n return {\n name: 'open-editor',\n actionPanel: OpenEditorActionPanel,\n settings: OpenEditorSettings,\n }\n}\n"],"mappings":";;;;;;;AAcA,MAAa,4EACX,aACD;;;;ACWD,MAAM,gBAA8C;CAClD,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,KAAK;CACL,UAAU;CACV,UAAU;CACX;AAED,MAAM,UAAU,OAAO,QAAQ,cAAc,CAAC,KAAK,CAAC,OAAO,YAAY;CAC9D;CACP;CACD,EAAE;AAEH,MAAM,cAA6B;CACjC,UAAU;CACV,OAAO;CACP,YAAY;CACb;;;;;;;AAQD,SAAS,eACP,QACA,MACA,MACA,KACQ;AACR,KAAI,WAAW,WACb,QAAO,wBAAwB,mBAAmB,KAAK,CAAC,QAAQ;AAElE,KAAI,WAAW,WACb,QAAO,oBAAoB,mBAAmB,KAAK,CAAC,QAAQ;AAG9D,QAAO,GAAG,OAAO,UAAU,KAAK,GAAG,KAAK,GAAG;;AAG7C,SAAgB,iBAAiB,EAC/B,SAAS,aACkB,EAAE,EAAe;CAC5C,SAAS,wBAAwB;EAC/B,MAAM,oEAAoC;EAC1C,MAAM,gFAAgD;EAEtD,MAAM,wCAD8B,uBAAuB,EACrB,UAAU;AAEhD,MAAI,CAAC,eAAgB,QAAO;EAE5B,MAAM,yBAAyB;AAC7B,yBAAsB;GACtB,MAAM,MAAM,eACV,eACA,eAAe,cACf,eAAe,YACf,eAAe,aAChB;AACD,UAAO,KAAK,IAAI;;AAGlB,SACE,4CAACA,iDAAa,MAAd;GAAmB,SAAS;aAA5B,CACE,2CAAC,QAAD;IAAM,OAAO;KAAE,SAAS;KAAQ,YAAY;KAAU;cACpD,2CAACC,sDAAD,EAAoB;IACf,GACN,WAAW,cAAc,iBACR;;;CAIxB,SAAS,qBAAqB;EAC5B,MAAM,4EAA4C;EAElD,MAAM,CAAC,iBAAiB,EAAE,QAAQ,EAAE,wCAClC,uBACD;AAED,SACE,2CAAC,OAAD;GAAK,OAAO;IAAE,SAAS;IAAQ,eAAe;IAAU,KAAK;IAAI;aAC/D,4CAAC,OAAD;IAAK,OAAO;KAAE,SAAS;KAAQ,eAAe;KAAU,KAAK;KAAG;cAAhE,CACE,2CAAC,SAAD;KAAO,OAAO;eAAa;KAAsB,GACjD,4CAACC,2CAAO,MAAR;KACE,OAAO,eAAe;KACtB,OAAO;KACP,gBAAgB,UAAU;AACxB,UAAI,MACF,mBAAkB;OAAE,GAAG;OAAgB,QAAQ;OAAO,CAAC;;eAL7D,CASE,2CAACA,2CAAO,SAAR;MAAgB,UAAU,MAAM,EAAE,iBAAiB;gBACjD,2CAACA,2CAAO,OAAR,EAAgB;MACD,GAEjB,2CAACA,2CAAO,QAAR;MAAe,WAAW;gBACxB,2CAACA,2CAAO,YAAR;OACE,OAAO;QAAE,QAAQ;QAAW,eAAe;QAAQ;iBAEnD,2CAACA,2CAAO,OAAR,YACE,2CAACA,2CAAO,MAAR,YACG,QAAQ,KAAK,WACZ,2CAACA,2CAAO,MAAR;QAEE,OAAO,OAAO;QACd,UAAU,MAAM,EAAE,iBAAiB;kBAEnC,2CAACA,2CAAO,UAAR,YAAkB,OAAO,OAAwB;QACrC,EALP,OAAO,MAKA,CACd,EACU,GACD;OACG;MACN,EACJ;OACV;;GACF;;AAIV,QAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU;EACX"}
|
package/dist/index.d.cts
ADDED
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import { settingsPluginAtom, useClearSelectedContext, useSelectedSource, useWidgetPortalContainer } from "@react-trace-enhancer/core";
|
|
2
|
+
import { DropdownMenu, OpenInEditorIcon, Select } from "@react-trace-enhancer/ui-components";
|
|
3
|
+
import { useAtom, useAtomValue } from "jotai";
|
|
4
|
+
import { jsx, jsxs } from "react/jsx-runtime";
|
|
5
|
+
|
|
6
|
+
//#region src/store.ts
|
|
7
|
+
const openEditorSettingsAtom = settingsPluginAtom("openEditor");
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
//#region src/index.tsx
|
|
11
|
+
const EDITOR_LABELS = {
|
|
12
|
+
vscode: "VS Code",
|
|
13
|
+
cursor: "Cursor",
|
|
14
|
+
windsurf: "Windsurf",
|
|
15
|
+
zed: "Zed",
|
|
16
|
+
webstorm: "WebStorm",
|
|
17
|
+
intellij: "IntelliJ"
|
|
18
|
+
};
|
|
19
|
+
const editors = Object.entries(EDITOR_LABELS).map(([value, label]) => ({
|
|
20
|
+
value,
|
|
21
|
+
label
|
|
22
|
+
}));
|
|
23
|
+
const LABEL_STYLE = {
|
|
24
|
+
fontSize: 12,
|
|
25
|
+
color: "#d4d4d8",
|
|
26
|
+
fontFamily: "system-ui, sans-serif"
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* Builds the editor-specific URL to open a file at a given line/column.
|
|
30
|
+
*
|
|
31
|
+
* VS Code family uses: {editor}://file/{path}:{line}:{col}
|
|
32
|
+
* JetBrains uses: {editor}://open?file={path}&line={line}
|
|
33
|
+
*/
|
|
34
|
+
function buildEditorUrl(editor, path, line, col) {
|
|
35
|
+
if (editor === "webstorm") return `webstorm://open?file=${encodeURIComponent(path)}&line=${line}`;
|
|
36
|
+
if (editor === "intellij") return `idea://open?file=${encodeURIComponent(path)}&line=${line}`;
|
|
37
|
+
return `${editor}://file/${path}:${line}:${col}`;
|
|
38
|
+
}
|
|
39
|
+
function OpenEditorPlugin({ editor = "vscode" } = {}) {
|
|
40
|
+
function OpenEditorActionPanel() {
|
|
41
|
+
const selectedSource = useSelectedSource();
|
|
42
|
+
const clearSelectedContext = useClearSelectedContext();
|
|
43
|
+
const currentEditor = useAtomValue(openEditorSettingsAtom)?.editor ?? editor;
|
|
44
|
+
if (!selectedSource) return null;
|
|
45
|
+
const handleOpenEditor = () => {
|
|
46
|
+
clearSelectedContext();
|
|
47
|
+
const url = buildEditorUrl(currentEditor, selectedSource.absolutePath, selectedSource.lineNumber, selectedSource.columnNumber);
|
|
48
|
+
window.open(url);
|
|
49
|
+
};
|
|
50
|
+
return /* @__PURE__ */ jsxs(DropdownMenu.Item, {
|
|
51
|
+
onClick: handleOpenEditor,
|
|
52
|
+
children: [/* @__PURE__ */ jsx("span", {
|
|
53
|
+
style: {
|
|
54
|
+
display: "flex",
|
|
55
|
+
alignItems: "center"
|
|
56
|
+
},
|
|
57
|
+
children: /* @__PURE__ */ jsx(OpenInEditorIcon, {})
|
|
58
|
+
}), `Open in ${EDITOR_LABELS[currentEditor]}`]
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
function OpenEditorSettings() {
|
|
62
|
+
const portalContainer = useWidgetPortalContainer();
|
|
63
|
+
const [editorSettings = { editor }, setEditorSettings] = useAtom(openEditorSettingsAtom);
|
|
64
|
+
return /* @__PURE__ */ jsx("div", {
|
|
65
|
+
style: {
|
|
66
|
+
display: "flex",
|
|
67
|
+
flexDirection: "column",
|
|
68
|
+
gap: 12
|
|
69
|
+
},
|
|
70
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
71
|
+
style: {
|
|
72
|
+
display: "flex",
|
|
73
|
+
flexDirection: "column",
|
|
74
|
+
gap: 6
|
|
75
|
+
},
|
|
76
|
+
children: [/* @__PURE__ */ jsx("label", {
|
|
77
|
+
style: LABEL_STYLE,
|
|
78
|
+
children: "Default editor"
|
|
79
|
+
}), /* @__PURE__ */ jsxs(Select.Root, {
|
|
80
|
+
value: editorSettings.editor,
|
|
81
|
+
items: editors,
|
|
82
|
+
onValueChange: (value) => {
|
|
83
|
+
if (value) setEditorSettings({
|
|
84
|
+
...editorSettings,
|
|
85
|
+
editor: value
|
|
86
|
+
});
|
|
87
|
+
},
|
|
88
|
+
children: [/* @__PURE__ */ jsx(Select.Trigger, {
|
|
89
|
+
onClick: (e) => e.stopPropagation(),
|
|
90
|
+
children: /* @__PURE__ */ jsx(Select.Value, {})
|
|
91
|
+
}), /* @__PURE__ */ jsx(Select.Portal, {
|
|
92
|
+
container: portalContainer,
|
|
93
|
+
children: /* @__PURE__ */ jsx(Select.Positioner, {
|
|
94
|
+
style: {
|
|
95
|
+
zIndex: 1e8,
|
|
96
|
+
pointerEvents: "auto"
|
|
97
|
+
},
|
|
98
|
+
children: /* @__PURE__ */ jsx(Select.Popup, { children: /* @__PURE__ */ jsx(Select.List, { children: editors.map((option) => /* @__PURE__ */ jsx(Select.Item, {
|
|
99
|
+
value: option.value,
|
|
100
|
+
onClick: (e) => e.stopPropagation(),
|
|
101
|
+
children: /* @__PURE__ */ jsx(Select.ItemText, { children: option.label })
|
|
102
|
+
}, option.value)) }) })
|
|
103
|
+
})
|
|
104
|
+
})]
|
|
105
|
+
})]
|
|
106
|
+
})
|
|
107
|
+
});
|
|
108
|
+
}
|
|
109
|
+
return {
|
|
110
|
+
name: "open-editor",
|
|
111
|
+
actionPanel: OpenEditorActionPanel,
|
|
112
|
+
settings: OpenEditorSettings
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
//#endregion
|
|
117
|
+
export { OpenEditorPlugin };
|
|
118
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/store.ts","../src/index.tsx"],"sourcesContent":["import type { TraceSettings } from '@react-trace-enhancer/core'\nimport { settingsPluginAtom } from '@react-trace-enhancer/core'\nimport type { WritableAtom } from 'jotai'\n\nimport type { EditorPreset } from './types'\n\ndeclare module '@react-trace-enhancer/core' {\n interface TraceSettings {\n openEditor?: {\n editor: EditorPreset\n }\n }\n}\n\nexport const openEditorSettingsAtom = settingsPluginAtom(\n 'openEditor',\n) as WritableAtom<\n TraceSettings['openEditor'],\n [TraceSettings['openEditor']],\n void\n>\n","import type { TracePlugin } from '@react-trace-enhancer/core'\nimport {\n useClearSelectedContext,\n useSelectedSource,\n useWidgetPortalContainer,\n} from '@react-trace-enhancer/core'\nimport {\n DropdownMenu,\n OpenInEditorIcon,\n Select,\n} from '@react-trace-enhancer/ui-components'\nimport { useAtom, useAtomValue } from 'jotai'\nimport type { CSSProperties } from 'react'\n\nimport { openEditorSettingsAtom } from './store'\nimport type { EditorPreset } from './types'\n\nexport type { EditorPreset }\n\nexport interface OpenEditorPluginOptions {\n /**\n * The editor to open files in.\n * @default 'vscode'\n */\n editor?: EditorPreset\n}\n\nconst EDITOR_LABELS: Record<EditorPreset, string> = {\n vscode: 'VS Code',\n cursor: 'Cursor',\n windsurf: 'Windsurf',\n zed: 'Zed',\n webstorm: 'WebStorm',\n intellij: 'IntelliJ',\n}\n\nconst editors = Object.entries(EDITOR_LABELS).map(([value, label]) => ({\n value: value as EditorPreset,\n label,\n}))\n\nconst LABEL_STYLE: CSSProperties = {\n fontSize: 12,\n color: '#d4d4d8',\n fontFamily: 'system-ui, sans-serif',\n}\n\n/**\n * Builds the editor-specific URL to open a file at a given line/column.\n *\n * VS Code family uses: {editor}://file/{path}:{line}:{col}\n * JetBrains uses: {editor}://open?file={path}&line={line}\n */\nfunction buildEditorUrl(\n editor: EditorPreset,\n path: string,\n line: number,\n col: number,\n): string {\n if (editor === 'webstorm') {\n return `webstorm://open?file=${encodeURIComponent(path)}&line=${line}`\n }\n if (editor === 'intellij') {\n return `idea://open?file=${encodeURIComponent(path)}&line=${line}`\n }\n // VS Code family + Zed: vscode, cursor, windsurf, zed — identical format, different protocol\n return `${editor}://file/${path}:${line}:${col}`\n}\n\nexport function OpenEditorPlugin({\n editor = 'vscode',\n}: OpenEditorPluginOptions = {}): TracePlugin {\n function OpenEditorActionPanel() {\n const selectedSource = useSelectedSource()\n const clearSelectedContext = useClearSelectedContext()\n const editorSettings = useAtomValue(openEditorSettingsAtom)\n const currentEditor = editorSettings?.editor ?? editor\n\n if (!selectedSource) return null\n\n const handleOpenEditor = () => {\n clearSelectedContext()\n const url = buildEditorUrl(\n currentEditor,\n selectedSource.absolutePath,\n selectedSource.lineNumber,\n selectedSource.columnNumber,\n )\n window.open(url)\n }\n\n return (\n <DropdownMenu.Item onClick={handleOpenEditor}>\n <span style={{ display: 'flex', alignItems: 'center' }}>\n <OpenInEditorIcon />\n </span>\n {`Open in ${EDITOR_LABELS[currentEditor]}`}\n </DropdownMenu.Item>\n )\n }\n\n function OpenEditorSettings() {\n const portalContainer = useWidgetPortalContainer()\n\n const [editorSettings = { editor }, setEditorSettings] = useAtom(\n openEditorSettingsAtom,\n )\n\n return (\n <div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>\n <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>\n <label style={LABEL_STYLE}>Default editor</label>\n <Select.Root\n value={editorSettings.editor}\n items={editors}\n onValueChange={(value) => {\n if (value) {\n setEditorSettings({ ...editorSettings, editor: value })\n }\n }}\n >\n <Select.Trigger onClick={(e) => e.stopPropagation()}>\n <Select.Value />\n </Select.Trigger>\n\n <Select.Portal container={portalContainer}>\n <Select.Positioner\n style={{ zIndex: 100000000, pointerEvents: 'auto' }}\n >\n <Select.Popup>\n <Select.List>\n {editors.map((option) => (\n <Select.Item\n key={option.value}\n value={option.value}\n onClick={(e) => e.stopPropagation()}\n >\n <Select.ItemText>{option.label}</Select.ItemText>\n </Select.Item>\n ))}\n </Select.List>\n </Select.Popup>\n </Select.Positioner>\n </Select.Portal>\n </Select.Root>\n </div>\n </div>\n )\n }\n\n return {\n name: 'open-editor',\n actionPanel: OpenEditorActionPanel,\n settings: OpenEditorSettings,\n }\n}\n"],"mappings":";;;;;;AAcA,MAAa,yBAAyB,mBACpC,aACD;;;;ACWD,MAAM,gBAA8C;CAClD,QAAQ;CACR,QAAQ;CACR,UAAU;CACV,KAAK;CACL,UAAU;CACV,UAAU;CACX;AAED,MAAM,UAAU,OAAO,QAAQ,cAAc,CAAC,KAAK,CAAC,OAAO,YAAY;CAC9D;CACP;CACD,EAAE;AAEH,MAAM,cAA6B;CACjC,UAAU;CACV,OAAO;CACP,YAAY;CACb;;;;;;;AAQD,SAAS,eACP,QACA,MACA,MACA,KACQ;AACR,KAAI,WAAW,WACb,QAAO,wBAAwB,mBAAmB,KAAK,CAAC,QAAQ;AAElE,KAAI,WAAW,WACb,QAAO,oBAAoB,mBAAmB,KAAK,CAAC,QAAQ;AAG9D,QAAO,GAAG,OAAO,UAAU,KAAK,GAAG,KAAK,GAAG;;AAG7C,SAAgB,iBAAiB,EAC/B,SAAS,aACkB,EAAE,EAAe;CAC5C,SAAS,wBAAwB;EAC/B,MAAM,iBAAiB,mBAAmB;EAC1C,MAAM,uBAAuB,yBAAyB;EAEtD,MAAM,gBADiB,aAAa,uBAAuB,EACrB,UAAU;AAEhD,MAAI,CAAC,eAAgB,QAAO;EAE5B,MAAM,yBAAyB;AAC7B,yBAAsB;GACtB,MAAM,MAAM,eACV,eACA,eAAe,cACf,eAAe,YACf,eAAe,aAChB;AACD,UAAO,KAAK,IAAI;;AAGlB,SACE,qBAAC,aAAa,MAAd;GAAmB,SAAS;aAA5B,CACE,oBAAC,QAAD;IAAM,OAAO;KAAE,SAAS;KAAQ,YAAY;KAAU;cACpD,oBAAC,kBAAD,EAAoB;IACf,GACN,WAAW,cAAc,iBACR;;;CAIxB,SAAS,qBAAqB;EAC5B,MAAM,kBAAkB,0BAA0B;EAElD,MAAM,CAAC,iBAAiB,EAAE,QAAQ,EAAE,qBAAqB,QACvD,uBACD;AAED,SACE,oBAAC,OAAD;GAAK,OAAO;IAAE,SAAS;IAAQ,eAAe;IAAU,KAAK;IAAI;aAC/D,qBAAC,OAAD;IAAK,OAAO;KAAE,SAAS;KAAQ,eAAe;KAAU,KAAK;KAAG;cAAhE,CACE,oBAAC,SAAD;KAAO,OAAO;eAAa;KAAsB,GACjD,qBAAC,OAAO,MAAR;KACE,OAAO,eAAe;KACtB,OAAO;KACP,gBAAgB,UAAU;AACxB,UAAI,MACF,mBAAkB;OAAE,GAAG;OAAgB,QAAQ;OAAO,CAAC;;eAL7D,CASE,oBAAC,OAAO,SAAR;MAAgB,UAAU,MAAM,EAAE,iBAAiB;gBACjD,oBAAC,OAAO,OAAR,EAAgB;MACD,GAEjB,oBAAC,OAAO,QAAR;MAAe,WAAW;gBACxB,oBAAC,OAAO,YAAR;OACE,OAAO;QAAE,QAAQ;QAAW,eAAe;QAAQ;iBAEnD,oBAAC,OAAO,OAAR,YACE,oBAAC,OAAO,MAAR,YACG,QAAQ,KAAK,WACZ,oBAAC,OAAO,MAAR;QAEE,OAAO,OAAO;QACd,UAAU,MAAM,EAAE,iBAAiB;kBAEnC,oBAAC,OAAO,UAAR,YAAkB,OAAO,OAAwB;QACrC,EALP,OAAO,MAKA,CACd,EACU,GACD;OACG;MACN,EACJ;OACV;;GACF;;AAIV,QAAO;EACL,MAAM;EACN,aAAa;EACb,UAAU;EACX"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
|
|
3
|
+
//#region src/index.prod.ts
|
|
4
|
+
/**
|
|
5
|
+
* Production stub for @react-trace-enhancer/plugin-open-editor.
|
|
6
|
+
*/
|
|
7
|
+
const OpenEditorPlugin = () => ({ name: "open-editor" });
|
|
8
|
+
|
|
9
|
+
//#endregion
|
|
10
|
+
exports.OpenEditorPlugin = OpenEditorPlugin;
|
|
11
|
+
//# sourceMappingURL=index.prod.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.cjs","names":[],"sources":["../src/index.prod.ts"],"sourcesContent":["/**\n * Production stub for @react-trace-enhancer/plugin-open-editor.\n */\nexport const OpenEditorPlugin = () => ({ name: 'open-editor' as const })\n\nexport type { OpenEditorPluginOptions } from './index'\n\nexport type { EditorPreset } from './types'\n"],"mappings":";;;;;;AAGA,MAAa,0BAA0B,EAAE,MAAM,eAAwB"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { n as OpenEditorPluginOptions, r as EditorPreset } from "./index-CXpzVMLC.cjs";
|
|
2
|
+
|
|
3
|
+
//#region src/index.prod.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Production stub for @react-trace-enhancer/plugin-open-editor.
|
|
6
|
+
*/
|
|
7
|
+
declare const OpenEditorPlugin: () => {
|
|
8
|
+
name: "open-editor";
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type EditorPreset, OpenEditorPlugin, type OpenEditorPluginOptions };
|
|
12
|
+
//# sourceMappingURL=index.prod.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.d.cts","names":[],"sources":["../src/index.prod.ts"],"mappings":";;;;;;cAGa,gBAAA;EAA2D,IAAA;AAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { n as OpenEditorPluginOptions, r as EditorPreset } from "./index-Boboj3a-.js";
|
|
2
|
+
|
|
3
|
+
//#region src/index.prod.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Production stub for @react-trace-enhancer/plugin-open-editor.
|
|
6
|
+
*/
|
|
7
|
+
declare const OpenEditorPlugin: () => {
|
|
8
|
+
name: "open-editor";
|
|
9
|
+
};
|
|
10
|
+
//#endregion
|
|
11
|
+
export { type EditorPreset, OpenEditorPlugin, type OpenEditorPluginOptions };
|
|
12
|
+
//# sourceMappingURL=index.prod.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.d.ts","names":[],"sources":["../src/index.prod.ts"],"mappings":";;;;;;cAGa,gBAAA;EAA2D,IAAA;AAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.prod.js","names":[],"sources":["../src/index.prod.ts"],"sourcesContent":["/**\n * Production stub for @react-trace-enhancer/plugin-open-editor.\n */\nexport const OpenEditorPlugin = () => ({ name: 'open-editor' as const })\n\nexport type { OpenEditorPluginOptions } from './index'\n\nexport type { EditorPreset } from './types'\n"],"mappings":";;;;AAGA,MAAa,0BAA0B,EAAE,MAAM,eAAwB"}
|
package/package.json
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@react-trace-enhancer/plugin-open-editor",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"description": "react-trace plugin: open inspected component source in your code editor",
|
|
5
|
+
"keywords": [
|
|
6
|
+
"react-trace",
|
|
7
|
+
"react-trace-plugin"
|
|
8
|
+
],
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Vitor Buzinaro",
|
|
11
|
+
"repository": {
|
|
12
|
+
"type": "git",
|
|
13
|
+
"url": "https://github.com/buzinas/react-trace",
|
|
14
|
+
"directory": "packages/plugin-open-editor"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"dist"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "./dist/index.cjs",
|
|
21
|
+
"module": "./dist/index.js",
|
|
22
|
+
"types": "./dist/index.d.ts",
|
|
23
|
+
"exports": {
|
|
24
|
+
".": {
|
|
25
|
+
"development": {
|
|
26
|
+
"import": {
|
|
27
|
+
"types": "./dist/index.d.ts",
|
|
28
|
+
"default": "./dist/index.js"
|
|
29
|
+
},
|
|
30
|
+
"require": {
|
|
31
|
+
"types": "./dist/index.d.cts",
|
|
32
|
+
"default": "./dist/index.cjs"
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"production": {
|
|
36
|
+
"import": {
|
|
37
|
+
"types": "./dist/index.d.ts",
|
|
38
|
+
"default": "./dist/index.prod.js"
|
|
39
|
+
},
|
|
40
|
+
"require": {
|
|
41
|
+
"types": "./dist/index.d.cts",
|
|
42
|
+
"default": "./dist/index.prod.cjs"
|
|
43
|
+
}
|
|
44
|
+
},
|
|
45
|
+
"default": {
|
|
46
|
+
"import": {
|
|
47
|
+
"types": "./dist/index.d.ts",
|
|
48
|
+
"default": "./dist/index.js"
|
|
49
|
+
},
|
|
50
|
+
"require": {
|
|
51
|
+
"types": "./dist/index.d.cts",
|
|
52
|
+
"default": "./dist/index.cjs"
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
"publishConfig": {
|
|
58
|
+
"access": "public"
|
|
59
|
+
},
|
|
60
|
+
"scripts": {
|
|
61
|
+
"build": "tsdown",
|
|
62
|
+
"dev": "tsdown --watch --no-clean",
|
|
63
|
+
"typecheck": "tsc --noEmit",
|
|
64
|
+
"lint": "oxlint src",
|
|
65
|
+
"prepublishOnly": "pnpm build"
|
|
66
|
+
},
|
|
67
|
+
"devDependencies": {
|
|
68
|
+
"@types/react": "^19",
|
|
69
|
+
"oxlint": "latest",
|
|
70
|
+
"react": "^19",
|
|
71
|
+
"tsdown": "^0.21.0-beta.2",
|
|
72
|
+
"typescript": "^5"
|
|
73
|
+
},
|
|
74
|
+
"peerDependencies": {
|
|
75
|
+
"@react-trace-enhancer/core": "^0.0.1",
|
|
76
|
+
"@react-trace-enhancer/ui-components": "^0.0.1",
|
|
77
|
+
"jotai": "^2.18.0",
|
|
78
|
+
"react": ">=18"
|
|
79
|
+
}
|
|
80
|
+
}
|