@loopstack/loopstack-studio 0.15.0

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 ADDED
@@ -0,0 +1,75 @@
1
+ # React + TypeScript + Vite
2
+
3
+ This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
4
+
5
+ Currently, two official plugins are available:
6
+
7
+ - [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh
8
+ - [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
9
+
10
+ ## React Compiler
11
+
12
+ The React Compiler is enabled on this template. See [this documentation](https://react.dev/learn/react-compiler) for more information.
13
+
14
+ Note: This will impact Vite dev & build performances.
15
+
16
+ ## Expanding the ESLint configuration
17
+
18
+ If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules:
19
+
20
+ ```js
21
+ export default defineConfig([
22
+ globalIgnores(['dist']),
23
+ {
24
+ files: ['**/*.{ts,tsx}'],
25
+ extends: [
26
+ // Other configs...
27
+
28
+ // Remove tseslint.configs.recommended and replace with this
29
+ tseslint.configs.recommendedTypeChecked,
30
+ // Alternatively, use this for stricter rules
31
+ tseslint.configs.strictTypeChecked,
32
+ // Optionally, add this for stylistic rules
33
+ tseslint.configs.stylisticTypeChecked
34
+
35
+ // Other configs...
36
+ ],
37
+ languageOptions: {
38
+ parserOptions: {
39
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
40
+ tsconfigRootDir: import.meta.dirname
41
+ }
42
+ // other options...
43
+ }
44
+ }
45
+ ]);
46
+ ```
47
+
48
+ You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules:
49
+
50
+ ```js
51
+ // eslint.config.js
52
+ import reactX from 'eslint-plugin-react-x';
53
+ import reactDom from 'eslint-plugin-react-dom';
54
+
55
+ export default defineConfig([
56
+ globalIgnores(['dist']),
57
+ {
58
+ files: ['**/*.{ts,tsx}'],
59
+ extends: [
60
+ // Other configs...
61
+ // Enable lint rules for React
62
+ reactX.configs['recommended-typescript'],
63
+ // Enable lint rules for React DOM
64
+ reactDom.configs.recommended
65
+ ],
66
+ languageOptions: {
67
+ parserOptions: {
68
+ project: ['./tsconfig.node.json', './tsconfig.app.json'],
69
+ tsconfigRootDir: import.meta.dirname
70
+ }
71
+ // other options...
72
+ }
73
+ }
74
+ ]);
75
+ ```
@@ -0,0 +1,5 @@
1
+ const ApiClientEvents = {
2
+ UNAUTHORIZED: "api.unauthorized",
3
+ ERR_NETWORK: "api.ERR_NETWORK"
4
+ };
5
+ export { ApiClientEvents };
@@ -0,0 +1,2 @@
1
+ import { useApiClient } from "./useApi.js";
2
+ import { useIsMobile } from "./use-mobile.js";
@@ -0,0 +1,13 @@
1
+ import { c } from "react/compiler-runtime";
2
+ import * as React from "react";
3
+ var MOBILE_BREAKPOINT = 768;
4
+ function useIsMobile() {
5
+ let r = c(2), [i, a] = React.useState(void 0), o, s;
6
+ return r[0] === Symbol.for("react.memo_cache_sentinel") ? (o = () => {
7
+ let e = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`), n = () => {
8
+ a(window.innerWidth < MOBILE_BREAKPOINT);
9
+ };
10
+ return e.addEventListener("change", n), a(window.innerWidth < MOBILE_BREAKPOINT), () => e.removeEventListener("change", n);
11
+ }, s = [], r[0] = o, r[1] = s) : (o = r[0], s = r[1]), React.useEffect(o, s), !!i;
12
+ }
13
+ export { useIsMobile };
@@ -0,0 +1,38 @@
1
+ import { ApiClientEvents } from "../events/api-client-events.js";
2
+ import { useStudio } from "../providers/StudioProvider.js";
3
+ import { eventBus } from "../services/eventEmitter.js";
4
+ import "../services/index.js";
5
+ import { c } from "react/compiler-runtime";
6
+ import axios from "axios";
7
+ import { ApiV1AuthApi, ApiV1ConfigApi, ApiV1DashboardApi, ApiV1DocumentsApi, ApiV1NamespacesApi, ApiV1PipelinesApi, ApiV1ProcessorApi, ApiV1WorkflowsApi, ApiV1WorkspacesApi, Configuration } from "@loopstack/api-client";
8
+ function useApiClient() {
9
+ let _ = c(24), { environment: v } = useStudio(), y, b = v.url, x, S, C, w, T, E, D, O, k;
10
+ if (_[0] !== v.id || _[1] !== b) {
11
+ let h = new Configuration({ baseOptions: {
12
+ withCredentials: !0,
13
+ headers: { "Content-Type": "application/json" }
14
+ } }), g = axios.create();
15
+ g.interceptors.response.use(_temp, (h) => ([401, 403].includes(h.response?.status) && eventBus.emit(ApiClientEvents.UNAUTHORIZED, v.id), h.code === "ERR_NETWORK" && (console.error("Connection refused - server may be down"), eventBus.emit(ApiClientEvents.ERR_NETWORK, v.id)), Promise.reject(h))), x = new ApiV1AuthApi(h, b, g), S = new ApiV1DashboardApi(h, b, g), C = new ApiV1ConfigApi(h, b, g), w = new ApiV1DocumentsApi(h, b, g), T = new ApiV1NamespacesApi(h, b, g), E = new ApiV1PipelinesApi(h, b, g), D = new ApiV1ProcessorApi(h, b, g), O = new ApiV1WorkflowsApi(h, b, g), k = new ApiV1WorkspacesApi(h, b, g), _[0] = v.id, _[1] = b, _[2] = x, _[3] = S, _[4] = C, _[5] = w, _[6] = T, _[7] = E, _[8] = D, _[9] = O, _[10] = k;
16
+ } else x = _[2], S = _[3], C = _[4], w = _[5], T = _[6], E = _[7], D = _[8], O = _[9], k = _[10];
17
+ let A;
18
+ _[11] !== x || _[12] !== S || _[13] !== C || _[14] !== w || _[15] !== T || _[16] !== E || _[17] !== D || _[18] !== O || _[19] !== k ? (A = {
19
+ ApiV1AuthApi: x,
20
+ ApiV1DashboardApi: S,
21
+ ApiV1ConfigApi: C,
22
+ ApiV1DocumentsApi: w,
23
+ ApiV1NamespacesApi: T,
24
+ ApiV1PipelinesApi: E,
25
+ ApiV1ProcessorApi: D,
26
+ ApiV1WorkflowsApi: O,
27
+ ApiV1WorkspacesApi: k
28
+ }, _[11] = x, _[12] = S, _[13] = C, _[14] = w, _[15] = T, _[16] = E, _[17] = D, _[18] = O, _[19] = k, _[20] = A) : A = _[20];
29
+ let j = A, M;
30
+ return _[21] !== j || _[22] !== v.id ? (M = {
31
+ envKey: v.id,
32
+ api: j
33
+ }, _[21] = j, _[22] = v.id, _[23] = M) : M = _[23], y = M, y;
34
+ }
35
+ function _temp(n) {
36
+ return n;
37
+ }
38
+ export { useApiClient };
@@ -0,0 +1,106 @@
1
+ import { ApiV1AuthApi } from '../../frontend/api-client';
2
+ import { ApiV1ConfigApi } from '../../frontend/api-client';
3
+ import { ApiV1DashboardApi } from '../../frontend/api-client';
4
+ import { ApiV1DocumentsApi } from '../../frontend/api-client';
5
+ import { ApiV1NamespacesApi } from '../../frontend/api-client';
6
+ import { ApiV1PipelinesApi } from '../../frontend/api-client';
7
+ import { ApiV1ProcessorApi } from '../../frontend/api-client';
8
+ import { ApiV1WorkflowsApi } from '../../frontend/api-client';
9
+ import { ApiV1WorkspacesApi } from '../../frontend/api-client';
10
+ import { Context } from 'react';
11
+ import { JSX } from 'react/jsx-runtime';
12
+ import { ReactNode } from 'react';
13
+ import { useNavigate } from 'react-router-dom';
14
+
15
+ export declare function createApiClient(environment: Environment): {
16
+ auth: ApiV1AuthApi;
17
+ };
18
+
19
+ export declare const DebugPage: () => JSX.Element;
20
+
21
+ export declare interface Environment {
22
+ id: string;
23
+ name: string;
24
+ url: string;
25
+ }
26
+
27
+ export declare const eventBus: EventEmitter;
28
+
29
+ declare class EventEmitter {
30
+ private events;
31
+ on(event: string, listener: (...args: any[]) => void): () => void;
32
+ emit(event: string, ...args: any[]): void;
33
+ }
34
+
35
+ export declare class LocalRouter implements StudioRouter {
36
+ private navigate;
37
+ private envId;
38
+ constructor(navigate: ReturnType<typeof useNavigate>, envId: string);
39
+ navigateToHome(): void;
40
+ navigateToEnvironmentInfo(): void;
41
+ getDashboard(): string;
42
+ navigateToDashboard(): void;
43
+ getWorkspaces(): string;
44
+ navigateToWorkspaces(): void;
45
+ getWorkspace(workspaceId: string): string;
46
+ navigateToWorkspace(workspaceId: string): void;
47
+ getPipeline(pipelineId: string): string;
48
+ navigateToPipeline(pipelineId: string): void;
49
+ navigateToWorkflow(pipelineId: string, workflowId: string, clickId: string | undefined): void;
50
+ navigateToPipelineNamespace(workspaceId: string, pipelineId: string, namespaceId: string): void;
51
+ getCurrentEnvironmentId(): string;
52
+ getTheme(): 'local' | 'cloud';
53
+ }
54
+
55
+ declare interface StudioContext {
56
+ router: StudioRouter;
57
+ environment: Environment;
58
+ }
59
+
60
+ declare const StudioContext: Context<StudioContext | null>;
61
+
62
+ export declare const StudioProvider: ({ children, router, environment }: {
63
+ children: ReactNode;
64
+ router: StudioRouter;
65
+ environment: Environment;
66
+ }) => JSX.Element;
67
+
68
+ export declare interface StudioRouter {
69
+ navigateToHome(): void;
70
+ navigateToEnvironmentInfo(): void;
71
+ getDashboard(): string;
72
+ navigateToDashboard(): void;
73
+ getWorkspaces(): string;
74
+ navigateToWorkspaces(): void;
75
+ getWorkspace(workspaceId: string): string;
76
+ navigateToWorkspace(workspaceId: string): void;
77
+ getPipeline(pipelineId: string): string;
78
+ navigateToPipeline(pipelineId: string): void;
79
+ navigateToWorkflow(pipelineId: string, workflowId: string, clickId: string | undefined): void;
80
+ navigateToPipelineNamespace(workspaceId: string, pipelineId: string, namespaceId: string): void;
81
+ getCurrentEnvironmentId(): string;
82
+ getTheme(): 'local' | 'cloud';
83
+ }
84
+
85
+ export declare function useApiClient(): {
86
+ envKey: string;
87
+ api: {
88
+ ApiV1AuthApi: ApiV1AuthApi;
89
+ ApiV1DashboardApi: ApiV1DashboardApi;
90
+ ApiV1ConfigApi: ApiV1ConfigApi;
91
+ ApiV1DocumentsApi: ApiV1DocumentsApi;
92
+ ApiV1NamespacesApi: ApiV1NamespacesApi;
93
+ ApiV1PipelinesApi: ApiV1PipelinesApi;
94
+ ApiV1ProcessorApi: ApiV1ProcessorApi;
95
+ ApiV1WorkflowsApi: ApiV1WorkflowsApi;
96
+ ApiV1WorkspacesApi: ApiV1WorkspacesApi;
97
+ };
98
+ };
99
+
100
+ export declare function useIsMobile(): boolean;
101
+
102
+ export declare const useRouter: (envId: string) => StudioRouter;
103
+
104
+ export declare const useStudio: () => StudioContext;
105
+
106
+ export { }
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ import { StudioProvider, useStudio } from "./providers/StudioProvider.js";
2
+ import { eventBus } from "./services/eventEmitter.js";
3
+ import { createApiClient } from "./services/createApiClient.js";
4
+ import "./services/index.js";
5
+ import { useApiClient } from "./hooks/useApi.js";
6
+ import { useIsMobile } from "./hooks/use-mobile.js";
7
+ import "./hooks/index.js";
8
+ import { LocalRouter, useRouter } from "./routing/LocalRouter.js";
9
+ import DebugPage_default from "./pages/DebugPage.js";
10
+ export { DebugPage_default as DebugPage, LocalRouter, StudioProvider, createApiClient, eventBus, useApiClient, useIsMobile, useRouter, useStudio };
@@ -0,0 +1 @@
1
+ <?xml version="1.0" encoding="UTF-8"?><svg id="Layer_2" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 146.7351 105.6471"><g id="Components"><g id="_2cd1744b-734b-47ef-9eb9-064d0ad46784_1"><path d="M.0022,62.887C.0022,76.377,10.9324,87.3069,24.4221,87.3069h47.2402v-29.86H.0022v5.4401Z" style="fill:#f9b800;"/><path d="M75.072,57.4469v29.86h47.2402c13.4897,0,24.4199-10.9299,24.4199-24.4199v-5.4401h-71.6602Z" style="fill:#f9b800;"/><polygon points="71.6653 90.7137 60.3816 90.7137 24.5833 90.7137 24.5833 105.6471 60.3816 105.6471 71.6653 105.6471 121.9426 105.6471 121.9426 90.7137 71.6653 90.7137" style="fill:#e50a34;"/><polygon points="139.8191 39.104 139.8191 33.2869 126.8884 33.2869 126.8884 39.104 19.8464 39.104 19.8464 33.2869 6.916 33.2869 6.916 39.104 0 39.104 0 54.0374 146.7351 54.0374 146.7351 39.104 139.8191 39.104" style="fill:#009bd8;"/><path d="M92.0762,5.8326h-2.1306V0h-12.9304v5.8326h-7.5056V0h-12.9307v5.8326h-2.1289c-15.4644,0-28.1831,11.7521-29.7124,26.8129-.051.5021-.0896,1.0078-.1152,1.5168-.0259.509-.0391,1.0215-.0391,1.5369h0s97.3594.0001,97.3594.0001h0c0-16.495-13.3716-29.8667-29.8665-29.8667Z" style="fill:#074999;"/></g></g></svg>
@@ -0,0 +1,20 @@
1
+ import { useStudio } from "../providers/StudioProvider.js";
2
+ import { useApiClient } from "../hooks/useApi.js";
3
+ import "../hooks/index.js";
4
+ import { c } from "react/compiler-runtime";
5
+ import { jsxs } from "react/jsx-runtime";
6
+ var DebugPage_default = () => {
7
+ let i = c(10), { environment: a } = useStudio(), { api: o } = useApiClient(), s = o?.ApiV1AuthApi, l = a?.name, u;
8
+ i[0] === l ? u = i[1] : (u = /* @__PURE__ */ jsxs("p", { children: ["Name: ", l] }), i[0] = l, i[1] = u);
9
+ let d = a?.id, f;
10
+ i[2] === d ? f = i[3] : (f = /* @__PURE__ */ jsxs("p", { children: ["Id: ", d] }), i[2] = d, i[3] = f);
11
+ let p = s?.basePath, m;
12
+ i[4] === p ? m = i[5] : (m = /* @__PURE__ */ jsxs("p", { children: ["Base Path: ", p] }), i[4] = p, i[5] = m);
13
+ let h;
14
+ return i[6] !== u || i[7] !== f || i[8] !== m ? (h = /* @__PURE__ */ jsxs("div", { children: [
15
+ u,
16
+ f,
17
+ m
18
+ ] }), i[6] = u, i[7] = f, i[8] = m, i[9] = h) : h = i[9], h;
19
+ };
20
+ export { DebugPage_default as default };
@@ -0,0 +1,21 @@
1
+ import { c } from "react/compiler-runtime";
2
+ import { createContext, useContext } from "react";
3
+ import { jsx } from "react/jsx-runtime";
4
+ var StudioContext = createContext(null);
5
+ const StudioProvider = (r) => {
6
+ let i = c(6), { children: a, router: o, environment: s } = r, l;
7
+ i[0] !== s || i[1] !== o ? (l = {
8
+ router: o,
9
+ environment: s
10
+ }, i[0] = s, i[1] = o, i[2] = l) : l = i[2];
11
+ let u;
12
+ return i[3] !== a || i[4] !== l ? (u = /* @__PURE__ */ jsx(StudioContext.Provider, {
13
+ value: l,
14
+ children: a
15
+ }), i[3] = a, i[4] = l, i[5] = u) : u = i[5], u;
16
+ }, useStudio = () => {
17
+ let e = useContext(StudioContext);
18
+ if (!e) throw Error("useStudio must be used within StudioProvider");
19
+ return e;
20
+ };
21
+ export { StudioProvider, useStudio };
@@ -0,0 +1,54 @@
1
+ import { c } from "react/compiler-runtime";
2
+ import { useNavigate } from "react-router-dom";
3
+ var LocalRouter = class {
4
+ constructor(e, t) {
5
+ this.navigate = e, this.envId = t;
6
+ }
7
+ navigateToHome() {
8
+ this.navigate("/");
9
+ }
10
+ navigateToEnvironmentInfo() {
11
+ this.navigate("/info");
12
+ }
13
+ getDashboard() {
14
+ return "/dashboard";
15
+ }
16
+ navigateToDashboard() {
17
+ this.navigate(this.getDashboard());
18
+ }
19
+ getWorkspaces() {
20
+ return "/workspaces";
21
+ }
22
+ navigateToWorkspaces() {
23
+ this.navigate(this.getWorkspaces());
24
+ }
25
+ getWorkspace(e) {
26
+ return `/workspaces/${e}`;
27
+ }
28
+ navigateToWorkspace(e) {
29
+ this.navigate(this.getWorkspace(e));
30
+ }
31
+ getPipeline(e) {
32
+ return `/pipelines/${e}`;
33
+ }
34
+ navigateToPipeline(e) {
35
+ this.navigate(this.getPipeline(e));
36
+ }
37
+ navigateToWorkflow(e, t, n) {
38
+ this.navigate(`/pipelines/${e}/workflows/${t}/${(n ? parseInt(n) : 0) + 1}`);
39
+ }
40
+ navigateToPipelineNamespace(e, t, n) {
41
+ this.navigate(`/workspaces/${e}/pipelines/${t}/namespaces/${n}`);
42
+ }
43
+ getCurrentEnvironmentId() {
44
+ return this.envId;
45
+ }
46
+ getTheme() {
47
+ return "local";
48
+ }
49
+ };
50
+ const useRouter = (r) => {
51
+ let i = c(3), a = useNavigate(), o;
52
+ return i[0] !== r || i[1] !== a ? (o = new LocalRouter(a, r), i[0] = r, i[1] = a, i[2] = o) : o = i[2], o;
53
+ };
54
+ export { LocalRouter, useRouter };
@@ -0,0 +1,12 @@
1
+ import { ApiClientEvents } from "../events/api-client-events.js";
2
+ import { eventBus } from "./eventEmitter.js";
3
+ import axios from "axios";
4
+ import { ApiV1AuthApi, Configuration } from "@loopstack/api-client";
5
+ function createApiClient(a) {
6
+ let o = new Configuration({ baseOptions: {
7
+ withCredentials: !0,
8
+ headers: { "Content-Type": "application/json" }
9
+ } }), s = axios.create();
10
+ return s.interceptors.response.use((e) => e, (i) => ([401, 403].includes(i.response?.status) && eventBus.emit(ApiClientEvents.UNAUTHORIZED, a.id), i.code === "ERR_NETWORK" && eventBus.emit(ApiClientEvents.ERR_NETWORK, a.id), Promise.reject(i))), { auth: new ApiV1AuthApi(o, a.url, s) };
11
+ }
12
+ export { createApiClient };
@@ -0,0 +1,14 @@
1
+ const eventBus = new class {
2
+ constructor() {
3
+ this.events = {};
4
+ }
5
+ on(e, t) {
6
+ return this.events[e] || (this.events[e] = []), this.events[e].push(t), () => {
7
+ this.events[e] = this.events[e].filter((e) => e !== t);
8
+ };
9
+ }
10
+ emit(e, ...t) {
11
+ this.events[e] && this.events[e].forEach((e) => e(...t));
12
+ }
13
+ }();
14
+ export { eventBus };
@@ -0,0 +1,2 @@
1
+ import { eventBus } from "./eventEmitter.js";
2
+ import { createApiClient } from "./createApiClient.js";
package/package.json ADDED
@@ -0,0 +1,119 @@
1
+ {
2
+ "name": "@loopstack/loopstack-studio",
3
+ "version": "0.15.0",
4
+ "type": "module",
5
+ "main": "./dist/index.js",
6
+ "types": "./dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js"
11
+ },
12
+ "./*": {
13
+ "types": "./dist/*.d.ts",
14
+ "import": "./dist/*.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "scripts": {
21
+ "dev": "vite",
22
+ "build": "vite build",
23
+ "build:lib": "tsc -b && vite build --mode lib",
24
+ "lint": "eslint .",
25
+ "preview": "vite preview",
26
+ "format": "prettier --write './**/*.{js,jsx,ts,tsx,css,md,json}' --config ./.prettierrc",
27
+ "docker:push": "make deploy IMAGE_NAME=jakobklippel/loopstack-studio",
28
+ "test": "vitest"
29
+ },
30
+ "dependencies": {
31
+ "@fontsource/roboto": "^5.2.6",
32
+ "@hookform/resolvers": "^5.2.1",
33
+ "@loopstack/api-client": "^0.14.0",
34
+ "@loopstack/contracts": "^0.14.0",
35
+ "@radix-ui/react-accordion": "^1.2.11",
36
+ "@radix-ui/react-alert-dialog": "^1.1.14",
37
+ "@radix-ui/react-avatar": "^1.1.10",
38
+ "@radix-ui/react-checkbox": "^1.3.2",
39
+ "@radix-ui/react-collapsible": "^1.1.12",
40
+ "@radix-ui/react-dialog": "^1.1.15",
41
+ "@radix-ui/react-dropdown-menu": "^2.1.16",
42
+ "@radix-ui/react-hover-card": "^1.1.15",
43
+ "@radix-ui/react-label": "^2.1.7",
44
+ "@radix-ui/react-popover": "^1.1.14",
45
+ "@radix-ui/react-progress": "^1.1.8",
46
+ "@radix-ui/react-radio-group": "^1.3.7",
47
+ "@radix-ui/react-scroll-area": "^1.2.10",
48
+ "@radix-ui/react-select": "^2.2.6",
49
+ "@radix-ui/react-separator": "^1.1.7",
50
+ "@radix-ui/react-slider": "^1.3.5",
51
+ "@radix-ui/react-slot": "^1.2.3",
52
+ "@radix-ui/react-switch": "^1.2.5",
53
+ "@radix-ui/react-tooltip": "^1.2.8",
54
+ "@radix-ui/react-use-controllable-state": "^1.2.2",
55
+ "@tailwindcss/vite": "^4.1.11",
56
+ "@tanstack/react-query": "^5.84.1",
57
+ "@xyflow/react": "^12.9.3",
58
+ "ai": "^5.0.6",
59
+ "axios": "^1.13.2",
60
+ "class-variance-authority": "^0.7.1",
61
+ "clsx": "^2.1.1",
62
+ "cmdk": "^1.1.1",
63
+ "date-fns": "^4.1.0",
64
+ "embla-carousel-react": "^8.6.0",
65
+ "katex": "^0.16.22",
66
+ "lodash": "^4.17.21",
67
+ "lucide-react": "^0.525.0",
68
+ "mermaid": "^11.9.0",
69
+ "motion": "^12.23.24",
70
+ "nanoid": "^5.1.6",
71
+ "react": "^19.2.0",
72
+ "react-dom": "^19.2.0",
73
+ "react-hook-form": "^7.62.0",
74
+ "react-markdown": "^10.1.0",
75
+ "react-router-dom": "^7.7.1",
76
+ "react-syntax-highlighter": "^15.6.1",
77
+ "rehype-katex": "^7.0.1",
78
+ "remark-gfm": "^4.0.1",
79
+ "remark-math": "^6.0.0",
80
+ "shiki": "^3.15.0",
81
+ "sonner": "^2.0.7",
82
+ "streamdown": "^1.5.0",
83
+ "tailwind-merge": "^3.3.1",
84
+ "tailwindcss": "^4.1.11",
85
+ "tokenlens": "^1.3.1",
86
+ "unique-names-generator": "^4.7.1",
87
+ "use-stick-to-bottom": "^1.1.1",
88
+ "vaul": "^1.1.2",
89
+ "zod": "^4.1.12"
90
+ },
91
+ "devDependencies": {
92
+ "@eslint/js": "^9.39.1",
93
+ "@testing-library/jest-dom": "^6.6.4",
94
+ "@testing-library/react": "^16.3.0",
95
+ "@testing-library/user-event": "^14.6.1",
96
+ "@types/lodash": "^4.17.20",
97
+ "@types/node": "^24.10.1",
98
+ "@types/react": "^19.2.2",
99
+ "@types/react-dom": "^19.2.2",
100
+ "@types/react-syntax-highlighter": "^15.5.13",
101
+ "@vitejs/plugin-react": "^5.1.0",
102
+ "babel-plugin-react-compiler": "^19.1.0-rc.3",
103
+ "eslint": "^9.39.1",
104
+ "eslint-plugin-react-hooks": "^5.2.0",
105
+ "eslint-plugin-react-refresh": "^0.4.24",
106
+ "globals": "^16.5.0",
107
+ "tw-animate-css": "^1.3.6",
108
+ "typescript": "~5.9.3",
109
+ "typescript-eslint": "^8.46.3",
110
+ "vite": "npm:rolldown-vite@7.2.2",
111
+ "vite-plugin-dts": "^4.5.4",
112
+ "vitest": "^4.0.9"
113
+ },
114
+ "pnpm": {
115
+ "overrides": {
116
+ "vite": "npm:rolldown-vite@7.2.2"
117
+ }
118
+ }
119
+ }