- Merge UI components, hooks, lib, styles from packages/ui - Merge API client, atoms, provider from packages/clients/react - Move shared pages and components from apps/local/src/web - Direct subpath exports: @executor/react/{api,plugins,pages,components,hooks,lib}/* - No barrel files, no backwards compat shims - Each app owns its own shell/router, imports pages from package - Delete packages/ui and packages/clients/react
Unified · Split
| @@ -26,8 +26,6 @@ · 25 unmodified lines | ||
| 26 | 26 | "@executor/plugin-keychain", |
| 27 | 27 | "@executor/plugin-mcp", |
| 28 | 28 | "@executor/plugin-onepassword", |
| 29 | − "@executor/plugin-openapi", | |
| 30 | − "@executor/ui", | |
| 31 | − "@executor/marketing" | |
| 29 | + "@executor/plugin-openapi" | |
| 32 | 30 | ] |
| 33 | 31 | } |
| @@ -15,7 +15,6 @@ · 14 unmodified lines | ||
| 15 | 15 | "@executor/react": "workspace:*", |
| 16 | 16 | "@executor/sdk": "workspace:*", |
| 17 | 17 | "@executor/storage-postgres": "workspace:*", |
| 18 | − "@executor/ui": "workspace:*", | |
| 19 | 18 | "@tanstack/react-router": "^1.168.10", |
| 20 | 19 | "@workos-inc/node": "^7.0.0", |
| 21 | 20 | "drizzle-orm": "catalog:", |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | // --------------------------------------------------------------------------- |
| 2 | −// Cloud API — core handlers from @executor/api + cloud-specific plugins | |
| 2 | +// Cloud API — core handlers from @executor/api + cloud-specific plugins + auth | |
| 3 | 3 | // --------------------------------------------------------------------------- |
| 4 | 4 | |
| 5 | 5 | import { |
| @@ -20,16 +20,20 @@ import { GraphqlGroup, GraphqlExtensionService, GraphqlHandlers } from "@executo · 14 unmodified lines | ||
| 20 | 20 | |
| 21 | 21 | import { createTeamExecutor } from "./services/executor"; |
| 22 | 22 | import { authenticateRequest } from "./auth/workos"; |
| 23 | +import { CloudAuthApi } from "./auth/api"; | |
| 24 | +import { CloudAuthHandlers } from "./auth/handlers"; | |
| 25 | +import { AuthContext, UserStoreService } from "./auth/context"; | |
| 23 | 26 | import type { DrizzleDb } from "./services/db"; |
| 24 | 27 | |
| 25 | 28 | // --------------------------------------------------------------------------- |
| 26 | −// Cloud API — core + cloud plugins (no onepassword) | |
| 29 | +// Cloud API — core + cloud plugins + cloud auth (no onepassword) | |
| 27 | 30 | // --------------------------------------------------------------------------- |
| 28 | 31 | |
| 29 | 32 | const CloudApi = addGroup(OpenApiGroup) |
| 30 | 33 | .add(McpGroup) |
| 31 | 34 | .add(GoogleDiscoveryGroup) |
| 32 | − .add(GraphqlGroup); | |
| 35 | + .add(GraphqlGroup) | |
| 36 | + .add(CloudAuthApi); | |
| 33 | 37 | |
| 34 | 38 | const CloudApiBase = HttpApiBuilder.api(CloudApi).pipe( |
| 35 | 39 | Layer.provide(CoreHandlers), |
| @@ -38,6 +42,7 @@ const CloudApiBase = HttpApiBuilder.api(CloudApi).pipe( · 2 unmodified lines | ||
| 38 | 42 | McpHandlers, |
| 39 | 43 | GoogleDiscoveryHandlers, |
| 40 | 44 | GraphqlHandlers, |
| 45 | + CloudAuthHandlers, | |
| 41 | 46 | )), |
| 42 | 47 | ); |
| 43 | 48 | |
| @@ -96,13 +101,29 @@ export const createCloudApiHandler = (db: DrizzleDb, encryptionKey: string) => { · 52 unmodified lines | ||
| 96 | 101 | Layer.provideMerge(pluginExtensions), |
| 97 | 102 | Layer.provideMerge(Layer.succeed(ExecutorService, executor)), |
| 98 | 103 | Layer.provideMerge(Layer.succeed(ExecutionEngineService, engine)), |
| 104 | + Layer.provideMerge(Layer.succeed(AuthContext, { | |
| 105 | + userId: auth.userId, | |
| 106 | + email: auth.email, | |
| 107 | + teamId, | |
| 108 | + name: `${auth.firstName ?? ""} ${auth.lastName ?? ""}`.trim() || null, | |
| 109 | + avatarUrl: auth.avatarUrl, | |
| 110 | + })), | |
| 111 | + Layer.provideMerge(Layer.succeed(UserStoreService, userStore)), | |
| 99 | 112 | Layer.provideMerge(HttpServer.layerContext), |
| 100 | 113 | ), |
| 101 | 114 | { middleware: HttpMiddleware.logger }, |
| 102 | 115 | ); |
| 103 | 116 | |
| 104 | 117 | try { |
| 105 | − return await handler.handler(request); | |
| 118 | + const response = await handler.handler(request); | |
| 119 | + | |
| 120 | + if (auth.refreshedCookie) { | |
| 121 | + const newResponse = new Response(response.body, response); | |
| 122 | + newResponse.headers.append("Set-Cookie", auth.refreshedCookie); | |
| 123 | + return newResponse; | |
| 124 | + } | |
| 125 | + | |
| 126 | + return response; | |
| 106 | 127 | } finally { |
| 107 | 128 | await Effect.runPromise(executor.close()).catch(() => undefined); |
| 108 | 129 | handler.dispose(); |
| @@ -0,0 +1,25 @@ | ||
| 1 | +import { HttpApiEndpoint, HttpApiGroup } from "@effect/platform"; | |
| 2 | +import { Schema } from "effect"; | |
| 3 | + | |
| 4 | +const AuthUser = Schema.Struct({ | |
| 5 | + id: Schema.String, | |
| 6 | + email: Schema.String, | |
| 7 | + name: Schema.NullOr(Schema.String), | |
| 8 | + avatarUrl: Schema.NullOr(Schema.String), | |
| 9 | +}); | |
| 10 | + | |
| 11 | +const AuthTeam = Schema.Struct({ | |
| 12 | + id: Schema.String, | |
| 13 | + name: Schema.String, | |
| 14 | +}); | |
| 15 | + | |
| 16 | +const AuthMeResponse = Schema.Struct({ | |
| 17 | + user: AuthUser, | |
| 18 | + team: Schema.NullOr(AuthTeam), | |
| 19 | +}); | |
| 20 | + | |
| 21 | +export class CloudAuthApi extends HttpApiGroup.make("cloudAuth") | |
| 22 | + .add( | |
| 23 | + HttpApiEndpoint.get("me")`/auth/me` | |
| 24 | + .addSuccess(AuthMeResponse), | |
| 25 | + ) {} | |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | import { Context } from "effect"; |
| 2 | +import type { makeUserStore } from "@executor/storage-postgres"; | |
| 2 | 3 | |
| 3 | 4 | export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")< |
| 4 | 5 | AuthContext, |
| @@ -6,5 +7,12 @@ export class AuthContext extends Context.Tag("@executor/cloud/AuthContext")< · 1 unmodified line | ||
| 6 | 7 | readonly userId: string; |
| 7 | 8 | readonly teamId: string; |
| 8 | 9 | readonly email: string; |
| 10 | + readonly name: string | null; | |
| 11 | + readonly avatarUrl: string | null; | |
| 9 | 12 | } |
| 10 | 13 | >() {} |
| 14 | + | |
| 15 | +export class UserStoreService extends Context.Tag("@executor/cloud/UserStoreService")< | |
| 16 | + UserStoreService, | |
| 17 | + ReturnType<typeof makeUserStore> | |
| 18 | +>() {} | |
| @@ -0,0 +1,34 @@ | ||
| 1 | +import { HttpApiBuilder } from "@effect/platform"; | |
| 2 | +import { Effect } from "effect"; | |
| 3 | + | |
| 4 | +import { addGroup } from "@executor/api"; | |
| 5 | +import { CloudAuthApi } from "./api"; | |
| 6 | +import { AuthContext, UserStoreService } from "./context"; | |
| 7 | + | |
| 8 | +const ApiWithCloudAuth = addGroup(CloudAuthApi); | |
| 9 | + | |
| 10 | +export const CloudAuthHandlers = HttpApiBuilder.group( | |
| 11 | + ApiWithCloudAuth, | |
| 12 | + "cloudAuth", | |
| 13 | + (handlers) => | |
| 14 | + handlers.handle("me", () => | |
| 15 | + Effect.gen(function* () { | |
| 16 | + const auth = yield* AuthContext; | |
| 17 | + const userStore = yield* UserStoreService; | |
| 18 | + | |
| 19 | + const team = yield* Effect.tryPromise(() => | |
| 20 | + userStore.getTeam(auth.teamId), | |
| 21 | + ).pipe(Effect.orDie); | |
| 22 | + | |
| 23 | + return { | |
| 24 | + user: { | |
| 25 | + id: auth.userId, | |
| 26 | + email: auth.email, | |
| 27 | + name: auth.name, | |
| 28 | + avatarUrl: auth.avatarUrl, | |
| 29 | + }, | |
| 30 | + team: team ? { id: team.id, name: team.name } : null, | |
| 31 | + }; | |
| 32 | + }), | |
| 33 | + ), | |
| 34 | +); | |
| @@ -48,6 +48,10 @@ export const authenticateWithCode = async (code: string) => { · 47 unmodified lines | ||
| 48 | 48 | * Authenticate a request using the sealed session cookie. |
| 49 | 49 | * Returns user info or null if not authenticated. |
| 50 | 50 | */ |
| 51 | +/** | |
| 52 | + * Authenticate a request using the sealed session cookie. | |
| 53 | + * Automatically refreshes expired tokens and returns a new cookie if needed. | |
| 54 | + */ | |
| 51 | 55 | export const authenticateRequest = async (request: Request) => { |
| 52 | 56 | const cookieHeader = request.headers.get("cookie"); |
| 53 | 57 | const sessionData = parseCookie(cookieHeader, COOKIE_NAME); |
| @@ -60,39 +64,38 @@ export const authenticateRequest = async (request: Request) => { · 6 unmodified lines | ||
| 60 | 64 | }); |
| 61 | 65 | |
| 62 | 66 | const result = await session.authenticate(); |
| 63 | − if (!result.authenticated) return null; | |
| 64 | − | |
| 65 | − return { | |
| 66 | − userId: result.user.id, | |
| 67 | − email: result.user.email, | |
| 68 | − firstName: result.user.firstName, | |
| 69 | − lastName: result.user.lastName, | |
| 70 | − avatarUrl: result.user.profilePictureUrl, | |
| 71 | − sessionId: result.sessionId, | |
| 72 | − }; | |
| 73 | −}; | |
| 74 | − | |
| 75 | −/** | |
| 76 | − * Refresh the sealed session cookie. Returns new cookie value or null. | |
| 77 | − */ | |
| 78 | −export const refreshSession = async (request: Request) => { | |
| 79 | − const cookieHeader = request.headers.get("cookie"); | |
| 80 | − const sessionData = parseCookie(cookieHeader, COOKIE_NAME); | |
| 81 | − if (!sessionData) return null; | |
| 82 | 67 | |
| 83 | − const wos = getWorkOS(); | |
| 84 | − const session = wos.userManagement.loadSealedSession({ | |
| 85 | − sessionData, | |
| 86 | − cookiePassword: getCookiePassword(), | |
| 87 | − }); | |
| 88 | − | |
| 89 | − const result = await session.refresh(); | |
| 90 | − if (!result.authenticated || !result.sealedSession) return null; | |
| 68 | + if (result.authenticated) { | |
| 69 | + return { | |
| 70 | + userId: result.user.id, | |
| 71 | + email: result.user.email, | |
| 72 | + firstName: result.user.firstName, | |
| 73 | + lastName: result.user.lastName, | |
| 74 | + avatarUrl: result.user.profilePictureUrl, | |
| 75 | + sessionId: result.sessionId, | |
| 76 | + refreshedCookie: undefined as string | undefined, | |
| 77 | + }; | |
| 78 | + } | |
| 91 | 79 | |
| 92 | − return { | |
| 93 | − sealedSession: result.sealedSession, | |
| 94 | − cookie: makeSessionCookie(result.sealedSession), | |
| 95 | − }; | |
| 80 | + // Token expired — try refreshing | |
| 81 | + if (result.reason === "no_session_cookie_provided") return null; | |
| 82 | + | |
| 83 | + try { | |
| 84 | + const refreshed = await session.refresh(); | |
| 85 | + if (!refreshed.authenticated || !refreshed.sealedSession) return null; | |
| 86 | + | |
| 87 | + return { | |
| 88 | + userId: refreshed.user.id, | |
| 89 | + email: refreshed.user.email, | |
| 90 | + firstName: refreshed.user.firstName, | |
| 91 | + lastName: refreshed.user.lastName, | |
| 92 | + avatarUrl: refreshed.user.profilePictureUrl, | |
| 93 | + sessionId: refreshed.sessionId, | |
| 94 | + refreshedCookie: makeSessionCookie(refreshed.sealedSession), | |
| 95 | + }; | |
| 96 | + } catch { | |
| 97 | + return null; | |
| 98 | + } | |
| 96 | 99 | }; |
| 97 | 100 | |
| 98 | 101 | /** |
| @@ -1,4 +1,11 @@ | ||
| 1 | −import React, { createContext, useContext, useEffect, useState } from "react"; | |
| 1 | +import React, { createContext, useContext } from "react"; | |
| 2 | +import { useAtomValue, Result } from "@effect-atom/atom-react"; | |
| 3 | + | |
| 4 | +import { CloudApiClient } from "./client"; | |
| 5 | + | |
| 6 | +// --------------------------------------------------------------------------- | |
| 7 | +// Types (from CloudAuthApi response schema) | |
| 8 | +// --------------------------------------------------------------------------- | |
| 2 | 9 | |
| 3 | 10 | type AuthUser = { |
| 4 | 11 | id: string; |
| @@ -12,40 +19,39 @@ type AuthTeam = { · 7 unmodified lines | ||
| 12 | 19 | name: string; |
| 13 | 20 | }; |
| 14 | 21 | |
| 22 | +// --------------------------------------------------------------------------- | |
| 23 | +// Auth atom — typed query against CloudAuthApi | |
| 24 | +// --------------------------------------------------------------------------- | |
| 25 | + | |
| 26 | +export const authAtom = CloudApiClient.query("cloudAuth", "me", { | |
| 27 | + timeToLive: "5 minutes", | |
| 28 | +}); | |
| 29 | + | |
| 30 | +// --------------------------------------------------------------------------- | |
| 31 | +// Provider + hook | |
| 32 | +// --------------------------------------------------------------------------- | |
| 33 | + | |
| 15 | 34 | type AuthState = |
| 16 | 35 | | { status: "loading" } |
| 17 | 36 | | { status: "unauthenticated" } |
| 18 | − | { status: "authenticated"; user: AuthUser; team: AuthTeam }; | |
| 37 | + | { status: "authenticated"; user: AuthUser; team: AuthTeam | null }; | |
| 19 | 38 | |
| 20 | 39 | const AuthContext = createContext<AuthState>({ status: "loading" }); |
| 21 | 40 | |
| 22 | 41 | export const useAuth = () => useContext(AuthContext); |
| 23 | 42 | |
| 24 | 43 | export const AuthProvider = ({ children }: { children: React.ReactNode }) => { |
| 25 | − const [state, setState] = useState<AuthState>({ status: "loading" }); | |
| 26 | − | |
| 27 | − useEffect(() => { | |
| 28 | − fetch("/auth/me") | |
| 29 | − .then((res) => { | |
| 30 | − if (!res.ok) { | |
| 31 | − setState({ status: "unauthenticated" }); | |
| 32 | − return; | |
| 33 | − } | |
| 34 | − return res.json(); | |
| 35 | − }) | |
| 36 | − .then((data) => { | |
| 37 | − if (data?.user) { | |
| 38 | − setState({ | |
| 39 | − status: "authenticated", | |
| 40 | − user: data.user, | |
| 41 | − team: data.team, | |
| 42 | − }); | |
| 43 | − } | |
| 44 | − }) | |
| 45 | − .catch(() => { | |
| 46 | − setState({ status: "unauthenticated" }); | |
| 47 | − }); | |
| 48 | − }, []); | |
| 44 | + const result = useAtomValue(authAtom); | |
| 45 | + | |
| 46 | + const state: AuthState = Result.match(result, { | |
| 47 | + onInitial: () => ({ status: "loading" as const }), | |
| 48 | + onSuccess: ({ value }) => ({ | |
| 49 | + status: "authenticated" as const, | |
| 50 | + user: value.user, | |
| 51 | + team: value.team, | |
| 52 | + }), | |
| 53 | + onFailure: () => ({ status: "unauthenticated" as const }), | |
| 54 | + }); | |
| 49 | 55 | |
| 50 | 56 | return <AuthContext.Provider value={state}>{children}</AuthContext.Provider>; |
| 51 | 57 | }; |
| @@ -0,0 +1,22 @@ | ||
| 1 | +import { AtomHttpApi } from "@effect-atom/atom-react"; | |
| 2 | +import { FetchHttpClient } from "@effect/platform"; | |
| 3 | +import { addGroup } from "@executor/api"; | |
| 4 | +import { getBaseUrl } from "@executor/react/api/base-url"; | |
| 5 | +import { CloudAuthApi } from "../auth/api"; | |
| 6 | + | |
| 7 | +// --------------------------------------------------------------------------- | |
| 8 | +// Cloud API client — core API + cloud auth | |
| 9 | +// --------------------------------------------------------------------------- | |
| 10 | + | |
| 11 | +const CloudApi = addGroup(CloudAuthApi); | |
| 12 | + | |
| 13 | +class CloudApiClient extends AtomHttpApi.Tag<CloudApiClient>()( | |
| 14 | + "CloudApiClient", | |
| 15 | + { | |
| 16 | + api: CloudApi, | |
| 17 | + httpClient: FetchHttpClient.layer, | |
| 18 | + baseUrl: getBaseUrl(), | |
| 19 | + }, | |
| 20 | +) {} | |
| 21 | + | |
| 22 | +export { CloudApiClient }; | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import React from "react"; |
| 2 | 2 | import { createRoot } from "react-dom/client"; |
| 3 | −import "@executor/ui/globals.css"; | |
| 3 | +import "@executor/react/globals.css"; | |
| 4 | 4 | import { App } from "./App"; |
| 5 | 5 | |
| 6 | 6 | const root = createRoot(document.getElementById("root")!); |
| @@ -3,13 +3,13 @@ import { · 2 unmodified lines | ||
| 3 | 3 | createRootRoute, |
| 4 | 4 | createRoute, |
| 5 | 5 | } from "@tanstack/react-router"; |
| 6 | −import { ExecutorProvider } from "@executor/react"; | |
| 7 | −import { ToolsPage } from "@web/pages/tools"; | |
| 8 | −import { SourcesPage } from "@web/pages/sources"; | |
| 9 | −import { SourcesAddPage } from "@web/pages/sources-add"; | |
| 10 | −import { SourceDetailPage } from "@web/pages/source-detail"; | |
| 11 | −import { SecretsPage } from "@web/pages/secrets"; | |
| 12 | −import { Shell } from "@web/shell"; | |
| 6 | +import { ExecutorProvider } from "@executor/react/api/provider"; | |
| 7 | +import { ToolsPage } from "@executor/react/pages/tools"; | |
| 8 | +import { SourcesPage } from "@executor/react/pages/sources"; | |
| 9 | +import { SourcesAddPage } from "@executor/react/pages/sources-add"; | |
| 10 | +import { SourceDetailPage } from "@executor/react/pages/source-detail"; | |
| 11 | +import { SecretsPage } from "@executor/react/pages/secrets"; | |
| 12 | +import { Shell } from "./shell"; | |
| 13 | 13 | |
| 14 | 14 | // --------------------------------------------------------------------------- |
| 15 | 15 | // Root layout — Shell renders <Outlet /> directly |
| @@ -0,0 +1,483 @@ | ||
| 1 | +import { Link, Outlet, useLocation } from "@tanstack/react-router"; | |
| 2 | +import { useCallback, useEffect, useRef, useState } from "react"; | |
| 3 | +import { useAtomRefresh, useAtomValue, Result } from "@effect-atom/atom-react"; | |
| 4 | +import { sourcesAtom, toolsAtom } from "@executor/react/api/atoms"; | |
| 5 | +import { useScope, useScopeInfo } from "@executor/react/api/scope-context"; | |
| 6 | +import { Button } from "@executor/react/components/button"; | |
| 7 | +import { useAuth } from "./auth"; | |
| 8 | + | |
| 9 | +// ── Env ───────────────────────────────────────────────────────────────── | |
| 10 | + | |
| 11 | +type AppMetaEnv = { | |
| 12 | + readonly VITE_APP_VERSION: string; | |
| 13 | + readonly VITE_GITHUB_URL: string; | |
| 14 | +}; | |
| 15 | + | |
| 16 | +const { VITE_APP_VERSION, VITE_GITHUB_URL } = (import.meta as ImportMeta & { | |
| 17 | + readonly env: AppMetaEnv; | |
| 18 | +}).env; | |
| 19 | + | |
| 20 | +// ── Version helpers ───────────────────────────────────────────────────── | |
| 21 | + | |
| 22 | +type UpdateChannel = "latest" | "beta"; | |
| 23 | + | |
| 24 | +const EXECUTOR_DIST_TAGS_PATH = "/v1/app/npm/dist-tags"; | |
| 25 | + | |
| 26 | +type ParsedVersion = { | |
| 27 | + readonly major: number; | |
| 28 | + readonly minor: number; | |
| 29 | + readonly patch: number; | |
| 30 | + readonly prerelease: ReadonlyArray<string | number> | null; | |
| 31 | +}; | |
| 32 | + | |
| 33 | +const semverPattern = | |
| 34 | + /^(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(?:-(?<prerelease>[0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/; | |
| 35 | + | |
| 36 | +const resolveUpdateChannel = (version: string): UpdateChannel => | |
| 37 | + version.includes("-beta.") ? "beta" : "latest"; | |
| 38 | + | |
| 39 | +const parseVersion = (version: string): ParsedVersion | null => { | |
| 40 | + const match = version.trim().match(semverPattern); | |
| 41 | + if (!match?.groups) return null; | |
| 42 | + return { | |
| 43 | + major: Number(match.groups.major), | |
| 44 | + minor: Number(match.groups.minor), | |
| 45 | + patch: Number(match.groups.patch), | |
| 46 | + prerelease: match.groups.prerelease | |
| 47 | + ? match.groups.prerelease.split(".").map((id) => | |
| 48 | + /^\d+$/.test(id) ? Number(id) : id, | |
| 49 | + ) | |
| 50 | + : null, | |
| 51 | + }; | |
| 52 | +}; | |
| 53 | + | |
| 54 | +const comparePrereleaseIdentifiers = ( | |
| 55 | + left: ReadonlyArray<string | number> | null, | |
| 56 | + right: ReadonlyArray<string | number> | null, | |
| 57 | +): number => { | |
| 58 | + if (left === null && right === null) return 0; | |
| 59 | + if (left === null) return 1; | |
| 60 | + if (right === null) return -1; | |
| 61 | + const max = Math.max(left.length, right.length); | |
| 62 | + for (let i = 0; i < max; i++) { | |
| 63 | + const l = left[i]; | |
| 64 | + const r = right[i]; | |
| 65 | + if (l === undefined) return -1; | |
| 66 | + if (r === undefined) return 1; | |
| 67 | + if (l === r) continue; | |
| 68 | + if (typeof l === "number" && typeof r === "number") return l < r ? -1 : 1; | |
| 69 | + if (typeof l === "number") return -1; | |
| 70 | + if (typeof r === "number") return 1; | |
| 71 | + return l < r ? -1 : 1; | |
| 72 | + } | |
| 73 | + return 0; | |
| 74 | +}; | |
| 75 | + | |
| 76 | +const compareVersions = (left: string, right: string): number | null => { | |
| 77 | + const lv = parseVersion(left); | |
| 78 | + const rv = parseVersion(right); | |
| 79 | + if (!lv || !rv) return null; | |
| 80 | + if (lv.major !== rv.major) return lv.major < rv.major ? -1 : 1; | |
| 81 | + if (lv.minor !== rv.minor) return lv.minor < rv.minor ? -1 : 1; | |
| 82 | + if (lv.patch !== rv.patch) return lv.patch < rv.patch ? -1 : 1; | |
| 83 | + return comparePrereleaseIdentifiers(lv.prerelease, rv.prerelease); | |
| 84 | +}; | |
| 85 | + | |
| 86 | +// ── useLatestVersion ──────────────────────────────────────────────────── | |
| 87 | + | |
| 88 | +function useLatestVersion(currentVersion: string) { | |
| 89 | + const channel = resolveUpdateChannel(currentVersion); | |
| 90 | + const [latestVersion, setLatestVersion] = useState<string | null>(null); | |
| 91 | + | |
| 92 | + useEffect(() => { | |
| 93 | + let cancelled = false; | |
| 94 | + fetch(EXECUTOR_DIST_TAGS_PATH) | |
| 95 | + .then(async (res) => { | |
| 96 | + if (!res.ok) throw new Error(`Failed to load dist tags: ${res.status}`); | |
| 97 | + return res.json() as Promise<Partial<Record<UpdateChannel, string>>>; | |
| 98 | + }) | |
| 99 | + .then((data) => { | |
| 100 | + if (!cancelled) setLatestVersion(data[channel] ?? null); | |
| 101 | + }) | |
| 102 | + .catch(() => {}); | |
| 103 | + return () => { cancelled = true; }; | |
| 104 | + }, [channel]); | |
| 105 | + | |
| 106 | + const updateAvailable = | |
| 107 | + latestVersion !== null && compareVersions(currentVersion, latestVersion) === -1; | |
| 108 | + | |
| 109 | + return { latestVersion, updateAvailable, channel }; | |
| 110 | +} | |
| 111 | + | |
| 112 | +// ── UpdateCard ────────────────────────────────────────────────────────── | |
| 113 | + | |
| 114 | +function UpdateCard(props: { latestVersion: string; channel: UpdateChannel }) { | |
| 115 | + const command = `npm i -g executor@${props.channel}`; | |
| 116 | + const [copied, setCopied] = useState(false); | |
| 117 | + | |
| 118 | + const handleCopy = useCallback(() => { | |
| 119 | + void navigator.clipboard.writeText(command).then(() => { | |
| 120 | + setCopied(true); | |
| 121 | + setTimeout(() => setCopied(false), 1500); | |
| 122 | + }); | |
| 123 | + }, [command]); | |
| 124 | + | |
| 125 | + return ( | |
| 126 | + <div className="mx-2 mb-2 rounded-xl border border-primary/25 bg-primary/[0.06] p-3"> | |
| 127 | + <div className="flex items-center gap-2"> | |
| 128 | + <div className="flex size-5 shrink-0 items-center justify-center rounded-full bg-primary/15"> | |
| 129 | + <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary"> | |
| 130 | + <path d="M8 3v7M5 7l3 3 3-3" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" /> | |
| 131 | + <path d="M3 12h10" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" /> | |
| 132 | + </svg> | |
| 133 | + </div> | |
| 134 | + <div className="min-w-0"> | |
| 135 | + <p className="text-[11px] font-semibold text-foreground">Update available</p> | |
| 136 | + <p className="text-[10px] text-muted-foreground"> | |
| 137 | + v{props.latestVersion} | |
| 138 | + </p> | |
| 139 | + </div> | |
| 140 | + </div> | |
| 141 | + <Button | |
| 142 | + type="button" | |
| 143 | + variant="outline" | |
| 144 | + onClick={handleCopy} | |
| 145 | + className="mt-2.5 flex w-full items-center justify-between gap-2 rounded-lg border-border/60 bg-background/50 px-2.5 py-1.5 text-left hover:bg-background/80" | |
| 146 | + > | |
| 147 | + <code className="truncate font-mono text-[10px] text-sidebar-foreground"> | |
| 148 | + {command} | |
| 149 | + </code> | |
| 150 | + <span className="shrink-0 text-muted-foreground transition-colors group-hover:text-foreground"> | |
| 151 | + {copied ? ( | |
| 152 | + <svg viewBox="0 0 16 16" fill="none" className="size-3 text-primary"> | |
| 153 | + <path d="M3 8.5l3.5 3.5L13 4" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" strokeLinejoin="round" /> | |
| 154 | + </svg> | |
| 155 | + ) : ( | |
| 156 | + <svg viewBox="0 0 16 16" fill="none" className="size-3"> | |
| 157 | + <rect x="5" y="5" width="8" height="8" rx="1.5" stroke="currentColor" strokeWidth="1.2" /> | |
| 158 | + <path d="M3 11V3.5A.5.5 0 013.5 3H11" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" /> | |
| 159 | + </svg> | |
| 160 | + )} | |
| 161 | + </span> | |
| 162 | + </Button> | |
| 163 | + </div> | |
| 164 | + ); | |
| 165 | +} | |
| 166 | + | |
| 167 | +// ── NavItem ────────────────────────────────────────────────────────────── | |
| 168 | + | |
| 169 | +function NavItem(props: { to: string; label: string; active: boolean; onNavigate?: () => void }) { | |
| 170 | + return ( | |
| 171 | + <Link | |
| 172 | + to={props.to} | |
| 173 | + onClick={props.onNavigate} | |
| 174 | + className={[ | |
| 175 | + "flex items-center gap-2.5 rounded-md px-2.5 py-1.5 text-[13px] transition-colors", | |
| 176 | + props.active | |
| 177 | + ? "bg-sidebar-active text-foreground font-medium" | |
| 178 | + : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground", | |
| 179 | + ].join(" ")} | |
| 180 | + > | |
| 181 | + {props.label} | |
| 182 | + </Link> | |
| 183 | + ); | |
| 184 | +} | |
| 185 | + | |
| 186 | +// ── SourceList ─────────────────────────────────────────────────────────── | |
| 187 | + | |
| 188 | +function SourceList(props: { pathname: string; onNavigate?: () => void }) { | |
| 189 | + const scopeId = useScope(); | |
| 190 | + const sources = useAtomValue(sourcesAtom(scopeId)); | |
| 191 | + | |
| 192 | + return Result.match(sources, { | |
| 193 | + onInitial: () => ( | |
| 194 | + <div className="px-2.5 py-2 text-[11px] text-muted-foreground/40">Loading…</div> | |
| 195 | + ), | |
| 196 | + onFailure: () => ( | |
| 197 | + <div className="px-2.5 py-2 text-[11px] text-muted-foreground/40">No sources yet</div> | |
| 198 | + ), | |
| 199 | + onSuccess: ({ value }) => | |
| 200 | + value.length === 0 ? ( | |
| 201 | + <div className="px-2.5 py-2 text-[11px] leading-relaxed text-muted-foreground/40"> | |
| 202 | + No sources yet | |
| 203 | + </div> | |
| 204 | + ) : ( | |
| 205 | + <div className="flex flex-col gap-px"> | |
| 206 | + {value.map((s) => { | |
| 207 | + const detailPath = `/sources/${s.id}`; | |
| 208 | + const active = | |
| 209 | + props.pathname === detailPath || | |
| 210 | + props.pathname.startsWith(`${detailPath}/`); | |
| 211 | + return ( | |
| 212 | + <Link | |
| 213 | + key={s.id} | |
| 214 | + to="/sources/$namespace" | |
| 215 | + params={{ namespace: s.id }} | |
| 216 | + onClick={props.onNavigate} | |
| 217 | + className={[ | |
| 218 | + "group flex items-center gap-2 rounded-md px-2.5 py-1.5 text-[13px] transition-colors", | |
| 219 | + active | |
| 220 | + ? "bg-sidebar-active text-foreground font-medium" | |
| 221 | + : "text-sidebar-foreground hover:bg-sidebar-active/60 hover:text-foreground", | |
| 222 | + ].join(" ")} | |
| 223 | + > | |
| 224 | + <span className="flex-1 truncate">{s.name}</span> | |
| 225 | + <span className="rounded bg-secondary/50 px-1 py-px text-[9px] font-medium text-muted-foreground/50"> | |
| 226 | + {s.kind} | |
| 227 | + </span> | |
| 228 | + </Link> | |
| 229 | + ); | |
| 230 | + })} | |
| 231 | + </div> | |
| 232 | + ), | |
| 233 | + }); | |
| 234 | +} | |
| 235 | + | |
| 236 | +// ── ScopeLabel ─────────────────────────────────────────────────────────── | |
| 237 | + | |
| 238 | +function ScopeLabel() { | |
| 239 | + const { name } = useScopeInfo(); | |
| 240 | + // Show just the last folder name, with full path as tooltip | |
| 241 | + const parts = name.replace(/\/+$/, "").split("/"); | |
| 242 | + const folder = parts[parts.length - 1] || name; | |
| 243 | + | |
| 244 | + return ( | |
| 245 | + <div className="mb-1.5 flex items-center gap-1.5 rounded-md px-2.5 py-1.5" title={name}> | |
| 246 | + <svg viewBox="0 0 16 16" fill="none" className="size-3.5 shrink-0 text-muted-foreground/50"> | |
| 247 | + <path | |
| 248 | + d="M2 4.5C2 3.67 2.67 3 3.5 3h3.09a1 1 0 0 1 .7.29l1.42 1.42a1 1 0 0 0 .7.29H12.5c.83 0 1.5.67 1.5 1.5v5.5c0 .83-.67 1.5-1.5 1.5h-9A1.5 1.5 0 0 1 2 12V4.5z" | |
| 249 | + stroke="currentColor" | |
| 250 | + strokeWidth="1.2" | |
| 251 | + /> | |
| 252 | + </svg> | |
| 253 | + <span className="truncate text-[12px] font-medium text-foreground/80"> | |
| 254 | + {folder} | |
| 255 | + </span> | |
| 256 | + </div> | |
| 257 | + ); | |
| 258 | +} | |
| 259 | + | |
| 260 | +// ── UserFooter ────────────────────────────────────────────────────────── | |
| 261 | + | |
| 262 | +function UserFooter() { | |
| 263 | + const auth = useAuth(); | |
| 264 | + if (auth.status !== "authenticated") return null; | |
| 265 | + | |
| 266 | + const initials = auth.user.name | |
| 267 | + ? auth.user.name.split(" ").map((n) => n[0]).join("").slice(0, 2).toUpperCase() | |
| 268 | + : auth.user.email[0]!.toUpperCase(); | |
| 269 | + | |
| 270 | + return ( | |
| 271 | + <div className="shrink-0 border-t border-sidebar-border px-3 py-2.5"> | |
| 272 | + <div className="flex items-center gap-2.5"> | |
| 273 | + {auth.user.avatarUrl ? ( | |
| 274 | + <img | |
| 275 | + src={auth.user.avatarUrl} | |
| 276 | + alt="" | |
| 277 | + className="size-7 shrink-0 rounded-full" | |
| 278 | + /> | |
| 279 | + ) : ( | |
| 280 | + <div className="flex size-7 shrink-0 items-center justify-center rounded-full bg-primary/10 text-[10px] font-semibold text-primary"> | |
| 281 | + {initials} | |
| 282 | + </div> | |
| 283 | + )} | |
| 284 | + <div className="min-w-0 flex-1"> | |
| 285 | + <p className="truncate text-[12px] font-medium text-foreground"> | |
| 286 | + {auth.user.name ?? auth.user.email} | |
| 287 | + </p> | |
| 288 | + {auth.team && ( | |
| 289 | + <p className="truncate text-[10px] text-muted-foreground"> | |
| 290 | + {auth.team.name} | |
| 291 | + </p> | |
| 292 | + )} | |
| 293 | + </div> | |
| 294 | + <a | |
| 295 | + href="/auth/logout" | |
| 296 | + className="shrink-0 rounded-md p-1 text-muted-foreground/50 transition-colors hover:bg-sidebar-active hover:text-foreground" | |
| 297 | + title="Sign out" | |
| 298 | + > | |
| 299 | + <svg viewBox="0 0 16 16" fill="none" className="size-3.5"> | |
| 300 | + <path d="M6 2H3.5A1.5 1.5 0 002 3.5v9A1.5 1.5 0 003.5 14H6M10.5 11.5L14 8l-3.5-3.5M14 8H6" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" strokeLinejoin="round" /> | |
| 301 | + </svg> | |
| 302 | + </a> | |
| 303 | + </div> | |
| 304 | + </div> | |
| 305 | + ); | |
| 306 | +} | |
| 307 | + | |
| 308 | +// ── SidebarContent ─────────────────────────────────────────────────────── | |
| 309 | + | |
| 310 | +function SidebarContent(props: { | |
| 311 | + pathname: string; | |
| 312 | + onNavigate?: () => void; | |
| 313 | + showBrand?: boolean; | |
| 314 | + updateAvailable: boolean; | |
| 315 | + latestVersion: string | null; | |
| 316 | + channel: UpdateChannel; | |
| 317 | +}) { | |
| 318 | + const isHome = props.pathname === "/"; | |
| 319 | + const isSecrets = props.pathname === "/secrets"; | |
| 320 | + | |
| 321 | + return ( | |
| 322 | + <> | |
| 323 | + {props.showBrand !== false && ( | |
| 324 | + <div className="flex h-12 shrink-0 items-center border-b border-sidebar-border px-4"> | |
| 325 | + <Link to="/" className="flex items-center gap-1.5"> | |
| 326 | + <span className="font-display text-base tracking-tight text-foreground"> | |
| 327 | + executor | |
| 328 | + </span> | |
| 329 | + </Link> | |
| 330 | + </div> | |
| 331 | + )} | |
| 332 | + | |
| 333 | + <nav className="flex flex-1 flex-col overflow-y-auto p-2"> | |
| 334 | + <ScopeLabel /> | |
| 335 | + <NavItem | |
| 336 | + to="/" | |
| 337 | + label="Sources" | |
| 338 | + active={isHome} | |
| 339 | + onNavigate={props.onNavigate} | |
| 340 | + /> | |
| 341 | + <NavItem | |
| 342 | + to="/secrets" | |
| 343 | + label="Secrets" | |
| 344 | + active={isSecrets} | |
| 345 | + onNavigate={props.onNavigate} | |
| 346 | + /> | |
| 347 | + | |
| 348 | + {/* Sources list */} | |
| 349 | + <div className="mt-5 mb-1 px-2.5 text-[10px] font-medium uppercase tracking-widest text-muted-foreground/50"> | |
| 350 | + <span>Configured</span> | |
| 351 | + </div> | |
| 352 | + | |
| 353 | + <SourceList pathname={props.pathname} onNavigate={props.onNavigate} /> | |
| 354 | + </nav> | |
| 355 | + | |
| 356 | + {/* User */} | |
| 357 | + <UserFooter /> | |
| 358 | + </> | |
| 359 | + ); | |
| 360 | +} | |
| 361 | + | |
| 362 | +// ── Shell ───────────────────────────────────────────────────────────────── | |
| 363 | + | |
| 364 | +export function Shell() { | |
| 365 | + const location = useLocation(); | |
| 366 | + const pathname = location.pathname; | |
| 367 | + const scopeId = useScope(); | |
| 368 | + const refreshSources = useAtomRefresh(sourcesAtom(scopeId)); | |
| 369 | + const refreshTools = useAtomRefresh(toolsAtom(scopeId)); | |
| 370 | + const { latestVersion, updateAvailable, channel } = useLatestVersion(VITE_APP_VERSION); | |
| 371 | + const lastPathname = useRef(pathname); | |
| 372 | + const [mobileSidebarOpen, setMobileSidebarOpen] = useState(false); | |
| 373 | + if (lastPathname.current !== pathname) { | |
| 374 | + lastPathname.current = pathname; | |
| 375 | + if (mobileSidebarOpen) setMobileSidebarOpen(false); | |
| 376 | + } | |
| 377 | + | |
| 378 | + // Lock scroll when mobile sidebar open | |
| 379 | + useEffect(() => { | |
| 380 | + if (!mobileSidebarOpen) return; | |
| 381 | + const prev = document.body.style.overflow; | |
| 382 | + document.body.style.overflow = "hidden"; | |
| 383 | + return () => { | |
| 384 | + document.body.style.overflow = prev; | |
| 385 | + }; | |
| 386 | + }, [mobileSidebarOpen]); | |
| 387 | + | |
| 388 | + useEffect(() => { | |
| 389 | + if (!import.meta.hot) { | |
| 390 | + return; | |
| 391 | + } | |
| 392 | + | |
| 393 | + const refreshBackendData = () => { | |
| 394 | + refreshSources(); | |
| 395 | + refreshTools(); | |
| 396 | + }; | |
| 397 | + | |
| 398 | + import.meta.hot.on("executor:backend-updated", refreshBackendData); | |
| 399 | + | |
| 400 | + return () => { | |
| 401 | + import.meta.hot?.off("executor:backend-updated", refreshBackendData); | |
| 402 | + }; | |
| 403 | + }, [refreshSources, refreshTools]); | |
| 404 | + | |
| 405 | + return ( | |
| 406 | + <div className="flex h-screen overflow-hidden"> | |
| 407 | + {/* Desktop sidebar */} | |
| 408 | + <aside className="hidden w-52 shrink-0 border-r border-sidebar-border bg-sidebar md:flex md:flex-col lg:w-56"> | |
| 409 | + <SidebarContent | |
| 410 | + pathname={pathname} | |
| 411 | + updateAvailable={updateAvailable} | |
| 412 | + latestVersion={latestVersion} | |
| 413 | + channel={channel} | |
| 414 | + /> | |
| 415 | + </aside> | |
| 416 | + | |
| 417 | + {/* Mobile sidebar overlay */} | |
| 418 | + {mobileSidebarOpen && ( | |
| 419 | + <div className="fixed inset-0 z-50 flex md:hidden"> | |
| 420 | + <button | |
| 421 | + type="button" | |
| 422 | + aria-label="Close navigation" | |
| 423 | + className="absolute inset-0 bg-black/45 backdrop-blur-[1px]" | |
| 424 | + onClick={() => setMobileSidebarOpen(false)} | |
| 425 | + /> | |
| 426 | + <div className="relative flex h-full w-[84vw] max-w-xs flex-col border-r border-sidebar-border bg-sidebar shadow-2xl"> | |
| 427 | + <div className="flex h-12 shrink-0 items-center justify-between border-b border-sidebar-border px-4"> | |
| 428 | + <Link to="/" className="flex items-center gap-1.5"> | |
| 429 | + <span className="font-display text-base tracking-tight text-foreground"> | |
| 430 | + executor | |
| 431 | + </span> | |
| 432 | + </Link> | |
| 433 | + <button | |
| 434 | + type="button" | |
| 435 | + aria-label="Close navigation" | |
| 436 | + onClick={() => setMobileSidebarOpen(false)} | |
| 437 | + className="size-8 flex items-center justify-center rounded-md text-sidebar-foreground hover:bg-sidebar-active hover:text-foreground" | |
| 438 | + > | |
| 439 | + <svg viewBox="0 0 16 16" className="size-3.5"> | |
| 440 | + <path d="M3 3l10 10M13 3L3 13" stroke="currentColor" strokeWidth="1.4" strokeLinecap="round" /> | |
| 441 | + </svg> | |
| 442 | + </button> | |
| 443 | + </div> | |
| 444 | + <SidebarContent | |
| 445 | + pathname={pathname} | |
| 446 | + onNavigate={() => setMobileSidebarOpen(false)} | |
| 447 | + showBrand={false} | |
| 448 | + updateAvailable={updateAvailable} | |
| 449 | + latestVersion={latestVersion} | |
| 450 | + channel={channel} | |
| 451 | + /> | |
| 452 | + </div> | |
| 453 | + </div> | |
| 454 | + )} | |
| 455 | + | |
| 456 | + {/* Main content */} | |
| 457 | + <main className="flex min-h-0 flex-1 flex-col min-w-0 overflow-hidden"> | |
| 458 | + {/* Mobile top bar */} | |
| 459 | + <div className="flex h-12 shrink-0 items-center justify-between border-b border-border bg-background px-4 md:hidden"> | |
| 460 | + <button | |
| 461 | + type="button" | |
| 462 | + aria-label="Open navigation" | |
| 463 | + onClick={() => setMobileSidebarOpen(true)} | |
| 464 | + className="size-8 flex items-center justify-center rounded-md border border-border bg-card hover:bg-accent/50" | |
| 465 | + > | |
| 466 | + <svg viewBox="0 0 16 16" className="size-4"> | |
| 467 | + <path d="M2 4h12M2 8h12M2 12h12" stroke="currentColor" strokeWidth="1.2" strokeLinecap="round" /> | |
| 468 | + </svg> | |
| 469 | + </button> | |
| 470 | + <Link to="/" className="flex items-center gap-1.5"> | |
| 471 | + <span className="font-display text-base tracking-tight text-foreground"> | |
| 472 | + executor | |
| 473 | + </span> | |
| 474 | + </Link> | |
| 475 | + <div className="w-8 shrink-0" /> | |
| 476 | + </div> | |
| 477 | + | |
| 478 | + {/* Outlet — pages control their own padding/scroll */} | |
| 479 | + <Outlet /> | |
| 480 | + </main> | |
| 481 | + </div> | |
| 482 | + ); | |
| 483 | +} | |
| @@ -12,9 +12,6 @@ · 11 unmodified lines | ||
| 12 | 12 | "declarationMap": true, |
| 13 | 13 | "sourceMap": true, |
| 14 | 14 | "jsx": "react-jsx", |
| 15 | − "paths": { | |
| 16 | − "@web/*": ["../local/src/web/*"] | |
| 17 | − }, | |
| 18 | 15 | "plugins": [ |
| 19 | 16 | { |
| 20 | 17 | "name": "@effect/language-service", |
| @@ -1,4 +1,3 @@ | ||
| 1 | −import { resolve } from "node:path"; | |
| 2 | 1 | import { defineConfig } from "vite"; |
| 3 | 2 | import react from "@vitejs/plugin-react"; |
| 4 | 3 | import tailwindcss from "@tailwindcss/vite"; |
| @@ -11,11 +10,6 @@ export default defineConfig({ · 6 unmodified lines | ||
| 11 | 10 | "import.meta.env.VITE_APP_VERSION": JSON.stringify("0.0.0"), |
| 12 | 11 | "import.meta.env.VITE_GITHUB_URL": JSON.stringify("https://github.com/RhysSullivan/executor"), |
| 13 | 12 | }, |
| 14 | − resolve: { | |
| 15 | − alias: { | |
| 16 | − "@web": resolve(__dirname, "../local/src/web"), | |
| 17 | − }, | |
| 18 | − }, | |
| 19 | 13 | server: { |
| 20 | 14 | proxy: { |
| 21 | 15 | "/v1": `http://localhost:${API_PORT}`, |
| @@ -25,7 +25,6 @@ · 24 unmodified lines | ||
| 25 | 25 | "@executor/react": "workspace:*", |
| 26 | 26 | "@executor/sdk": "workspace:*", |
| 27 | 27 | "@executor/storage-file": "workspace:*", |
| 28 | − "@executor/ui": "workspace:*", | |
| 29 | 28 | "@modelcontextprotocol/sdk": "^1.12.1", |
| 30 | 29 | "@shikijs/langs": "^4.0.2", |
| 31 | 30 | "@shikijs/themes": "^4.0.2", |
| @@ -1 +0,0 @@ | ||
| 1 | −export { useScope } from "@executor/react"; | |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import React from "react"; |
| 2 | 2 | import { createRoot } from "react-dom/client"; |
| 3 | −import "@executor/ui/globals.css"; | |
| 3 | +import "@executor/react/globals.css"; | |
| 4 | 4 | import { App } from "./App"; |
| 5 | 5 | |
| 6 | 6 | const root = createRoot(document.getElementById("root")!); |
| @@ -3,12 +3,12 @@ import { · 2 unmodified lines | ||
| 3 | 3 | createRootRoute, |
| 4 | 4 | createRoute, |
| 5 | 5 | } from "@tanstack/react-router"; |
| 6 | −import { ExecutorProvider } from "@executor/react"; | |
| 7 | −import { ToolsPage } from "./pages/tools"; | |
| 8 | −import { SourcesPage } from "./pages/sources"; | |
| 9 | −import { SourcesAddPage } from "./pages/sources-add"; | |
| 10 | −import { SourceDetailPage } from "./pages/source-detail"; | |
| 11 | −import { SecretsPage } from "./pages/secrets"; | |
| 6 | +import { ExecutorProvider } from "@executor/react/api/provider"; | |
| 7 | +import { ToolsPage } from "@executor/react/pages/tools"; | |
| 8 | +import { SourcesPage } from "@executor/react/pages/sources"; | |
| 9 | +import { SourcesAddPage } from "@executor/react/pages/sources-add"; | |
| 10 | +import { SourceDetailPage } from "@executor/react/pages/source-detail"; | |
| 11 | +import { SecretsPage } from "@executor/react/pages/secrets"; | |
| 12 | 12 | import { Shell } from "./shell"; |
| 13 | 13 | |
| 14 | 14 | // --------------------------------------------------------------------------- |
| @@ -1,15 +1,9 @@ | ||
| 1 | 1 | import { Link, Outlet, useLocation } from "@tanstack/react-router"; |
| 2 | 2 | import { useCallback, useEffect, useRef, useState } from "react"; |
| 3 | −import { | |
| 4 | − useAtomRefresh, | |
| 5 | − useAtomValue, | |
| 6 | − Result, | |
| 7 | − sourcesAtom, | |
| 8 | − toolsAtom, | |
| 9 | − useScope, | |
| 10 | − useScopeInfo, | |
| 11 | −} from "@executor/react"; | |
| 12 | −import { Button } from "@executor/ui/components/button"; | |
| 3 | +import { useAtomRefresh, useAtomValue, Result } from "@effect-atom/atom-react"; | |
| 4 | +import { sourcesAtom, toolsAtom } from "@executor/react/api/atoms"; | |
| 5 | +import { useScope, useScopeInfo } from "@executor/react/api/scope-context"; | |
| 6 | +import { Button } from "@executor/react/components/button"; | |
| 13 | 7 | |
| 14 | 8 | // ── Env ───────────────────────────────────────────────────────────────── |
| 15 | 9 | |
| @@ -53,7 +53,6 @@ · 52 unmodified lines | ||
| 53 | 53 | "@executor/react": "workspace:*", |
| 54 | 54 | "@executor/sdk": "workspace:*", |
| 55 | 55 | "@executor/storage-postgres": "workspace:*", |
| 56 | − "@executor/ui": "workspace:*", | |
| 57 | 56 | "@tanstack/react-router": "^1.168.10", |
| 58 | 57 | "@workos-inc/node": "^7.0.0", |
| 59 | 58 | "drizzle-orm": "catalog:", |
| @@ -106,7 +105,6 @@ · 46 unmodified lines | ||
| 106 | 105 | "@executor/react": "workspace:*", |
| 107 | 106 | "@executor/sdk": "workspace:*", |
| 108 | 107 | "@executor/storage-file": "workspace:*", |
| 109 | − "@executor/ui": "workspace:*", | |
| 110 | 108 | "@modelcontextprotocol/sdk": "^1.12.1", |
| 111 | 109 | "@shikijs/langs": "^4.0.2", |
| 112 | 110 | "@shikijs/themes": "^4.0.2", |
| @@ -140,25 +138,6 @@ · 27 unmodified lines | ||
| 140 | 138 | "tailwindcss": "^4.2.2", |
| 141 | 139 | }, |
| 142 | 140 | }, |
| 143 | − "packages/clients/react": { | |
| 144 | − "name": "@executor/react", | |
| 145 | − "version": "1.4.0", | |
| 146 | − "dependencies": { | |
| 147 | − "@effect-atom/atom": "^0.5.3", | |
| 148 | − "@effect-atom/atom-react": "^0.5.0", | |
| 149 | − "@effect/platform": "catalog:", | |
| 150 | − "@executor/api": "workspace:*", | |
| 151 | − "@executor/sdk": "workspace:*", | |
| 152 | − "@executor/ui": "workspace:*", | |
| 153 | − "effect": "catalog:", | |
| 154 | − "react": "^19.1.0", | |
| 155 | − }, | |
| 156 | − "devDependencies": { | |
| 157 | − "@types/node": "catalog:", | |
| 158 | − "@types/react": "^19.1.0", | |
| 159 | − "typescript": "^5.9.3", | |
| 160 | − }, | |
| 161 | − }, | |
| 162 | 141 | "packages/core/api": { |
| 163 | 142 | "name": "@executor/api", |
| 164 | 143 | "version": "1.4.0", |
| @@ -357,7 +336,6 @@ · 192 unmodified lines | ||
| 357 | 336 | "@effect-atom/atom-react": "^0.5.0", |
| 358 | 337 | "@effect/vitest": "catalog:", |
| 359 | 338 | "@executor/react": "workspace:*", |
| 360 | − "@executor/ui": "workspace:*", | |
| 361 | 339 | "@types/node": "catalog:", |
| 362 | 340 | "@types/react": "^19.1.0", |
| 363 | 341 | "bun-types": "catalog:", |
| @@ -367,14 +345,12 @@ · 3 unmodified lines | ||
| 367 | 345 | "peerDependencies": { |
| 368 | 346 | "@effect-atom/atom-react": "^0.5.0", |
| 369 | 347 | "@executor/react": "workspace:*", |
| 370 | − "@executor/ui": "workspace:*", | |
| 371 | 348 | "@tanstack/react-router": "^1.168.10", |
| 372 | 349 | "react": "^19.1.0", |
| 373 | 350 | }, |
| 374 | 351 | "optionalPeers": [ |
| 375 | 352 | "@effect-atom/atom-react", |
| 376 | 353 | "@executor/react", |
| 377 | − "@executor/ui", | |
| 378 | 354 | "@tanstack/react-router", |
| 379 | 355 | "react", |
| 380 | 356 | ], |
| @@ -393,7 +369,6 @@ · 12 unmodified lines | ||
| 393 | 369 | "@effect/vitest": "catalog:", |
| 394 | 370 | "@executor/api": "workspace:*", |
| 395 | 371 | "@executor/react": "workspace:*", |
| 396 | − "@executor/ui": "workspace:*", | |
| 397 | 372 | "@types/node": "catalog:", |
| 398 | 373 | "@types/react": "^19.1.0", |
| 399 | 374 | "bun-types": "catalog:", |
| @@ -404,7 +379,6 @@ · 4 unmodified lines | ||
| 404 | 379 | "@effect-atom/atom-react": "^0.5.0", |
| 405 | 380 | "@executor/api": "workspace:*", |
| 406 | 381 | "@executor/react": "workspace:*", |
| 407 | − "@executor/ui": "workspace:*", | |
| 408 | 382 | "@tanstack/react-router": "^1.168.10", |
| 409 | 383 | "react": "^19.1.0", |
| 410 | 384 | }, |
| @@ -412,7 +386,6 @@ · 1 unmodified line | ||
| 412 | 386 | "@effect-atom/atom-react", |
| 413 | 387 | "@executor/api", |
| 414 | 388 | "@executor/react", |
| 415 | − "@executor/ui", | |
| 416 | 389 | "@tanstack/react-router", |
| 417 | 390 | "react", |
| 418 | 391 | ], |
| @@ -447,7 +420,6 @@ · 28 unmodified lines | ||
| 447 | 420 | "@effect/vitest": "catalog:", |
| 448 | 421 | "@executor/api": "workspace:*", |
| 449 | 422 | "@executor/react": "workspace:*", |
| 450 | − "@executor/ui": "workspace:*", | |
| 451 | 423 | "@types/node": "catalog:", |
| 452 | 424 | "@types/react": "^19.1.0", |
| 453 | 425 | "bun-types": "catalog:", |
| @@ -459,7 +431,6 @@ · 5 unmodified lines | ||
| 459 | 431 | "@effect-atom/atom-react": "^0.5.0", |
| 460 | 432 | "@executor/api": "workspace:*", |
| 461 | 433 | "@executor/react": "workspace:*", |
| 462 | − "@executor/ui": "workspace:*", | |
| 463 | 434 | "@tanstack/react-router": "^1.168.10", |
| 464 | 435 | "react": "^19.1.0", |
| 465 | 436 | }, |
| @@ -467,7 +438,6 @@ · 1 unmodified line | ||
| 467 | 438 | "@effect-atom/atom-react", |
| 468 | 439 | "@executor/api", |
| 469 | 440 | "@executor/react", |
| 470 | − "@executor/ui", | |
| 471 | 441 | "@tanstack/react-router", |
| 472 | 442 | "react", |
| 473 | 443 | ], |
| @@ -495,13 +465,11 @@ · 21 unmodified lines | ||
| 495 | 465 | "peerDependencies": { |
| 496 | 466 | "@effect-atom/atom-react": "^0.5.0", |
| 497 | 467 | "@executor/react": "workspace:*", |
| 498 | − "@executor/ui": "workspace:*", | |
| 499 | 468 | "react": ">=18", |
| 500 | 469 | }, |
| 501 | 470 | "optionalPeers": [ |
| 502 | 471 | "@effect-atom/atom-react", |
| 503 | 472 | "@executor/react", |
| 504 | − "@executor/ui", | |
| 505 | 473 | "react", |
| 506 | 474 | ], |
| 507 | 475 | }, |
| @@ -522,7 +490,6 @@ · 14 unmodified lines | ||
| 522 | 490 | "@effect/vitest": "catalog:", |
| 523 | 491 | "@executor/api": "workspace:*", |
| 524 | 492 | "@executor/react": "workspace:*", |
| 525 | − "@executor/ui": "workspace:*", | |
| 526 | 493 | "@types/node": "catalog:", |
| 527 | 494 | "@types/react": "^19.1.0", |
| 528 | 495 | "bun-types": "catalog:", |
| @@ -533,7 +500,6 @@ · 4 unmodified lines | ||
| 533 | 500 | "@effect-atom/atom-react": "^0.5.0", |
| 534 | 501 | "@executor/api": "workspace:*", |
| 535 | 502 | "@executor/react": "workspace:*", |
| 536 | − "@executor/ui": "workspace:*", | |
| 537 | 503 | "@tanstack/react-router": "^1.168.10", |
| 538 | 504 | "react": "^19.1.0", |
| 539 | 505 | }, |
| @@ -541,16 +507,20 @@ · 1 unmodified line | ||
| 541 | 507 | "@effect-atom/atom-react", |
| 542 | 508 | "@executor/api", |
| 543 | 509 | "@executor/react", |
| 544 | − "@executor/ui", | |
| 545 | 510 | "@tanstack/react-router", |
| 546 | 511 | "react", |
| 547 | 512 | ], |
| 548 | 513 | }, |
| 549 | − "packages/ui": { | |
| 550 | − "name": "@executor/ui", | |
| 514 | + "packages/react": { | |
| 515 | + "name": "@executor/react", | |
| 551 | 516 | "version": "1.4.0", |
| 552 | 517 | "dependencies": { |
| 553 | 518 | "@base-ui/react": "^1.3.0", |
| 519 | + "@effect-atom/atom": "^0.5.3", | |
| 520 | + "@effect-atom/atom-react": "^0.5.0", | |
| 521 | + "@effect/platform": "catalog:", | |
| 522 | + "@executor/api": "workspace:*", | |
| 523 | + "@executor/sdk": "workspace:*", | |
| 554 | 524 | "@hookform/resolvers": "^5.2.2", |
| 555 | 525 | "@shikijs/langs": "^4.0.2", |
| 556 | 526 | "@shikijs/themes": "^4.0.2", |
| @@ -558,6 +528,7 @@ · 1 unmodified line | ||
| 558 | 528 | "clsx": "^2.1.1", |
| 559 | 529 | "cmdk": "^1.1.1", |
| 560 | 530 | "date-fns": "^4.1.0", |
| 531 | + "effect": "catalog:", | |
| 561 | 532 | "embla-carousel-react": "^8.6.0", |
| 562 | 533 | "input-otp": "^1.4.2", |
| 563 | 534 | "lucide-react": "^1.7.0", |
| @@ -576,6 +547,7 @@ · 12 unmodified lines | ||
| 576 | 547 | "zod": "^4.3.6", |
| 577 | 548 | }, |
| 578 | 549 | "devDependencies": { |
| 550 | + "@types/node": "catalog:", | |
| 579 | 551 | "@types/react": "^19.1.0", |
| 580 | 552 | "hast-util-to-jsx-runtime": "^2.3.6", |
| 581 | 553 | "tailwindcss": "^4.1.10", |
| @@ -885,7 +857,7 @@ · 303 unmodified lines | ||
| 885 | 857 | |
| 886 | 858 | "@executor/plugin-openapi": ["@executor/plugin-openapi@workspace:packages/plugins/openapi"], |
| 887 | 859 | |
| 888 | − "@executor/react": ["@executor/react@workspace:packages/clients/react"], | |
| 860 | + "@executor/react": ["@executor/react@workspace:packages/react"], | |
| 889 | 861 | |
| 890 | 862 | "@executor/runtime-deno-subprocess": ["@executor/runtime-deno-subprocess@workspace:packages/kernel/runtime-deno-subprocess"], |
| 891 | 863 | |
| @@ -897,8 +869,6 @@ · 5 unmodified lines | ||
| 897 | 869 | |
| 898 | 870 | "@executor/storage-postgres": ["@executor/storage-postgres@workspace:packages/core/storage-postgres"], |
| 899 | 871 | |
| 900 | − "@executor/ui": ["@executor/ui@workspace:packages/ui"], | |
| 901 | − | |
| 902 | 872 | "@floating-ui/core": ["@floating-ui/core@1.7.5", "", { "dependencies": { "@floating-ui/utils": "^0.2.11" } }, "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ=="], |
| 903 | 873 | |
| 904 | 874 | "@floating-ui/dom": ["@floating-ui/dom@1.7.6", "", { "dependencies": { "@floating-ui/core": "^1.7.5", "@floating-ui/utils": "^0.2.11" } }, "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ=="], |
| @@ -24,7 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | "packageManager": "bun@1.3.11", |
| 25 | 25 | "workspaces": [ |
| 26 | 26 | "packages/*/*", |
| 27 | − "packages/ui", | |
| 27 | + "packages/react", | |
| 28 | 28 | "apps/*" |
| 29 | 29 | ], |
| 30 | 30 | "catalog": { |
| @@ -1,4 +0,0 @@ | ||
| 1 | −# @executor/react changelog | |
| 2 | − | |
| 3 | −This file exists for Changesets release workflow compatibility. | |
| 4 | −Canonical user-facing release notes are published on GitHub Releases. | |
| @@ -1,27 +0,0 @@ | ||
| 1 | −{ | |
| 2 | − "name": "@executor/react", | |
| 3 | − "version": "1.4.0", | |
| 4 | − "private": true, | |
| 5 | − "type": "module", | |
| 6 | − "exports": { | |
| 7 | − ".": "./src/index.ts" | |
| 8 | − }, | |
| 9 | − "dependencies": { | |
| 10 | − "@effect/platform": "catalog:", | |
| 11 | − "@effect-atom/atom": "^0.5.3", | |
| 12 | − "@effect-atom/atom-react": "^0.5.0", | |
| 13 | − "@executor/api": "workspace:*", | |
| 14 | − "@executor/ui": "workspace:*", | |
| 15 | − "@executor/sdk": "workspace:*", | |
| 16 | − "effect": "catalog:", | |
| 17 | − "react": "^19.1.0" | |
| 18 | − }, | |
| 19 | − "devDependencies": { | |
| 20 | − "@types/react": "^19.1.0", | |
| 21 | − "@types/node": "catalog:", | |
| 22 | − "typescript": "^5.9.3" | |
| 23 | − }, | |
| 24 | − "scripts": { | |
| 25 | − "typecheck": "tsc --noEmit" | |
| 26 | − } | |
| 27 | −} | |
| @@ -1,54 +0,0 @@ | ||
| 1 | −// Re-export effect-atom essentials so consumers don't need direct deps | |
| 2 | −export { | |
| 3 | − Atom, | |
| 4 | − AtomHttpApi, | |
| 5 | − Result, | |
| 6 | − RegistryContext, | |
| 7 | − RegistryProvider, | |
| 8 | − useAtom, | |
| 9 | − useAtomMount, | |
| 10 | − useAtomRefresh, | |
| 11 | − useAtomSet, | |
| 12 | − useAtomSuspense, | |
| 13 | − useAtomValue, | |
| 14 | −} from "@effect-atom/atom-react"; | |
| 15 | − | |
| 16 | −// Base URL management | |
| 17 | −export { getBaseUrl, setBaseUrl } from "./base-url"; | |
| 18 | − | |
| 19 | −// Typed API client | |
| 20 | −export { ExecutorApiClient } from "./client"; | |
| 21 | − | |
| 22 | −// Query & mutation atoms | |
| 23 | −export { | |
| 24 | − toolsAtom, | |
| 25 | − sourceToolsAtom, | |
| 26 | − toolSchemaAtom, | |
| 27 | − sourcesAtom, | |
| 28 | − sourceAtom, | |
| 29 | − secretsAtom, | |
| 30 | − secretStatusAtom, | |
| 31 | − setSecret, | |
| 32 | − resolveSecret, | |
| 33 | − removeSecret, | |
| 34 | − removeSource, | |
| 35 | − refreshSource, | |
| 36 | − detectSource, | |
| 37 | −} from "./atoms"; | |
| 38 | − | |
| 39 | −// Scope hook | |
| 40 | −export { useScope, useScopeInfo } from "./use-scope"; | |
| 41 | −export type { ScopeInfo } from "./use-scope"; | |
| 42 | − | |
| 43 | −// Provider | |
| 44 | −export { ExecutorProvider } from "./provider"; | |
| 45 | −export { SecretPicker } from "./secret-picker"; | |
| 46 | −export type { SecretPickerSecret } from "./secret-picker"; | |
| 47 | − | |
| 48 | −// Re-export commonly needed SDK types | |
| 49 | −export { ScopeId, ToolId } from "@executor/sdk"; | |
| 50 | −export type { ScopeId as ScopeIdType, ToolId as ToolIdType } from "@executor/sdk"; | |
| 51 | − | |
| 52 | −// Plugin contracts | |
| 53 | −export type { SourcePlugin, SourcePreset } from "./source-plugin"; | |
| 54 | −export type { SecretProviderPlugin } from "./secret-provider-plugin"; | |
| @@ -1,2 +0,0 @@ | ||
| 1 | −export { useScope, useScopeInfo } from "./scope-context"; | |
| 2 | −export type { ScopeInfo } from "./scope-context"; | |
| @@ -24,8 +24,7 @@ · 23 unmodified lines | ||
| 24 | 24 | "react": "^19.1.0", |
| 25 | 25 | "@effect-atom/atom-react": "^0.5.0", |
| 26 | 26 | "@tanstack/react-router": "^1.168.10", |
| 27 | − "@executor/react": "workspace:*", | |
| 28 | − "@executor/ui": "workspace:*" | |
| 27 | + "@executor/react": "workspace:*" | |
| 29 | 28 | }, |
| 30 | 29 | "peerDependenciesMeta": { |
| 31 | 30 | "react": { |
| @@ -39,16 +38,12 @@ · 7 unmodified lines | ||
| 39 | 38 | }, |
| 40 | 39 | "@executor/react": { |
| 41 | 40 | "optional": true |
| 42 | − }, | |
| 43 | − "@executor/ui": { | |
| 44 | − "optional": true | |
| 45 | 41 | } |
| 46 | 42 | }, |
| 47 | 43 | "devDependencies": { |
| 48 | 44 | "@effect-atom/atom-react": "^0.5.0", |
| 49 | 45 | "@effect/vitest": "catalog:", |
| 50 | 46 | "@executor/react": "workspace:*", |
| 51 | − "@executor/ui": "workspace:*", | |
| 52 | 47 | "@types/node": "catalog:", |
| 53 | 48 | "@types/react": "^19.1.0", |
| 54 | 49 | "bun-types": "catalog:", |
| @@ -1,25 +1,21 @@ | ||
| 1 | 1 | import { useCallback, useEffect, useMemo, useRef, useState } from "react"; |
| 2 | 2 | import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react"; |
| 3 | 3 | |
| 4 | −import { | |
| 5 | − useScope, | |
| 6 | − SecretPicker, | |
| 7 | − secretsAtom, | |
| 8 | − setSecret, | |
| 9 | − type SecretPickerSecret, | |
| 10 | −} from "@executor/react"; | |
| 4 | +import { secretsAtom, setSecret } from "@executor/react/api/atoms"; | |
| 5 | +import { useScope } from "@executor/react/api/scope-context"; | |
| 6 | +import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker"; | |
| 11 | 7 | import { SecretId } from "@executor/sdk"; |
| 12 | −import { Badge } from "@executor/ui/components/badge"; | |
| 13 | −import { Button } from "@executor/ui/components/button"; | |
| 8 | +import { Badge } from "@executor/react/components/badge"; | |
| 9 | +import { Button } from "@executor/react/components/button"; | |
| 14 | 10 | import { |
| 15 | 11 | Collapsible, |
| 16 | 12 | CollapsibleContent, |
| 17 | 13 | CollapsibleTrigger, |
| 18 | −} from "@executor/ui/components/collapsible"; | |
| 19 | −import { Input } from "@executor/ui/components/input"; | |
| 20 | −import { Label } from "@executor/ui/components/label"; | |
| 21 | −import { RadioGroup, RadioGroupItem } from "@executor/ui/components/radio-group"; | |
| 22 | −import { Spinner } from "@executor/ui/components/spinner"; | |
| 14 | +} from "@executor/react/components/collapsible"; | |
| 15 | +import { Input } from "@executor/react/components/input"; | |
| 16 | +import { Label } from "@executor/react/components/label"; | |
| 17 | +import { RadioGroup, RadioGroupItem } from "@executor/react/components/radio-group"; | |
| 18 | +import { Spinner } from "@executor/react/components/spinner"; | |
| 23 | 19 | import { |
| 24 | 20 | addGoogleDiscoverySource, |
| 25 | 21 | probeGoogleDiscovery, |
| @@ -1,5 +1,5 @@ | ||
| 1 | −import { Badge } from "@executor/ui/components/badge"; | |
| 2 | −import { Button } from "@executor/ui/components/button"; | |
| 1 | +import { Badge } from "@executor/react/components/badge"; | |
| 2 | +import { Button } from "@executor/react/components/button"; | |
| 3 | 3 | |
| 4 | 4 | export default function EditGoogleDiscoverySource({ |
| 5 | 5 | sourceId, |
| @@ -1,4 +1,4 @@ | ||
| 1 | −import { Badge } from "@executor/ui/components/badge"; | |
| 1 | +import { Badge } from "@executor/react/components/badge"; | |
| 2 | 2 | |
| 3 | 3 | export default function GoogleDiscoverySourceSummary({ |
| 4 | 4 | sourceId, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { AtomHttpApi } from "@effect-atom/atom-react"; |
| 2 | 2 | import { FetchHttpClient } from "@effect/platform"; |
| 3 | 3 | import { addGroup } from "@executor/api"; |
| 4 | −import { getBaseUrl } from "@executor/react"; | |
| 4 | +import { getBaseUrl } from "@executor/react/api/base-url"; | |
| 5 | 5 | import { GoogleDiscoveryGroup } from "../api/group"; |
| 6 | 6 | |
| 7 | 7 | const GoogleDiscoveryApi = addGroup(GoogleDiscoveryGroup); |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | import { lazy } from "react"; |
| 2 | −import type { SourcePlugin } from "@executor/react"; | |
| 2 | +import type { SourcePlugin } from "@executor/react/plugins/source-plugin"; | |
| 3 | 3 | import { googleDiscoveryPresets } from "../sdk/presets"; |
| 4 | 4 | |
| 5 | 5 | export const googleDiscoverySourcePlugin: SourcePlugin = { |
| @@ -25,8 +25,7 @@ · 24 unmodified lines | ||
| 25 | 25 | "@effect-atom/atom-react": "^0.5.0", |
| 26 | 26 | "@tanstack/react-router": "^1.168.10", |
| 27 | 27 | "@executor/api": "workspace:*", |
| 28 | − "@executor/react": "workspace:*", | |
| 29 | − "@executor/ui": "workspace:*" | |
| 28 | + "@executor/react": "workspace:*" | |
| 30 | 29 | }, |
| 31 | 30 | "peerDependenciesMeta": { |
| 32 | 31 | "react": { |
| @@ -43,9 +42,6 @@ · 10 unmodified lines | ||
| 43 | 42 | }, |
| 44 | 43 | "@executor/react": { |
| 45 | 44 | "optional": true |
| 46 | − }, | |
| 47 | − "@executor/ui": { | |
| 48 | − "optional": true | |
| 49 | 45 | } |
| 50 | 46 | }, |
| 51 | 47 | "devDependencies": { |
| @@ -53,7 +49,6 @@ · 1 unmodified line | ||
| 53 | 49 | "@effect-atom/atom-react": "^0.5.0", |
| 54 | 50 | "@executor/api": "workspace:*", |
| 55 | 51 | "@executor/react": "workspace:*", |
| 56 | − "@executor/ui": "workspace:*", | |
| 57 | 52 | "@types/react": "^19.1.0", |
| 58 | 53 | "@effect/vitest": "catalog:", |
| 59 | 54 | "@types/node": "catalog:", |
| @@ -1,18 +1,14 @@ | ||
| 1 | 1 | import { useState } from "react"; |
| 2 | 2 | import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react"; |
| 3 | 3 | |
| 4 | −import { | |
| 5 | − secretsAtom, | |
| 6 | − setSecret, | |
| 7 | − useScope, | |
| 8 | − SecretPicker, | |
| 9 | − type SecretPickerSecret, | |
| 10 | −} from "@executor/react"; | |
| 4 | +import { secretsAtom, setSecret } from "@executor/react/api/atoms"; | |
| 5 | +import { useScope } from "@executor/react/api/scope-context"; | |
| 6 | +import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker"; | |
| 11 | 7 | import { SecretId } from "@executor/sdk"; |
| 12 | −import { Button } from "@executor/ui/components/button"; | |
| 13 | −import { Input } from "@executor/ui/components/input"; | |
| 14 | −import { Label } from "@executor/ui/components/label"; | |
| 15 | −import { Spinner } from "@executor/ui/components/spinner"; | |
| 8 | +import { Button } from "@executor/react/components/button"; | |
| 9 | +import { Input } from "@executor/react/components/input"; | |
| 10 | +import { Label } from "@executor/react/components/label"; | |
| 11 | +import { Spinner } from "@executor/react/components/spinner"; | |
| 16 | 12 | import { addGraphqlSource } from "./atoms"; |
| 17 | 13 | import type { HeaderValue } from "../sdk/types"; |
| 18 | 14 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { AtomHttpApi } from "@effect-atom/atom-react"; |
| 2 | 2 | import { FetchHttpClient } from "@effect/platform"; |
| 3 | 3 | import { addGroup } from "@executor/api"; |
| 4 | −import { getBaseUrl } from "@executor/react"; | |
| 4 | +import { getBaseUrl } from "@executor/react/api/base-url"; | |
| 5 | 5 | import { GraphqlGroup } from "../api/group"; |
| 6 | 6 | |
| 7 | 7 | // --------------------------------------------------------------------------- |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | import { lazy } from "react"; |
| 2 | −import type { SourcePlugin } from "@executor/react"; | |
| 2 | +import type { SourcePlugin } from "@executor/react/plugins/source-plugin"; | |
| 3 | 3 | import { graphqlPresets } from "../sdk/presets"; |
| 4 | 4 | |
| 5 | 5 | export const graphqlSourcePlugin: SourcePlugin = { |
| @@ -26,8 +26,7 @@ · 25 unmodified lines | ||
| 26 | 26 | "@effect-atom/atom-react": "^0.5.0", |
| 27 | 27 | "@tanstack/react-router": "^1.168.10", |
| 28 | 28 | "@executor/api": "workspace:*", |
| 29 | − "@executor/react": "workspace:*", | |
| 30 | − "@executor/ui": "workspace:*" | |
| 29 | + "@executor/react": "workspace:*" | |
| 31 | 30 | }, |
| 32 | 31 | "peerDependenciesMeta": { |
| 33 | 32 | "react": { |
| @@ -44,9 +43,6 @@ · 10 unmodified lines | ||
| 44 | 43 | }, |
| 45 | 44 | "@executor/react": { |
| 46 | 45 | "optional": true |
| 47 | − }, | |
| 48 | − "@executor/ui": { | |
| 49 | − "optional": true | |
| 50 | 46 | } |
| 51 | 47 | }, |
| 52 | 48 | "devDependencies": { |
| @@ -54,7 +50,6 @@ · 1 unmodified line | ||
| 54 | 50 | "@effect-atom/atom-react": "^0.5.0", |
| 55 | 51 | "@executor/api": "workspace:*", |
| 56 | 52 | "@executor/react": "workspace:*", |
| 57 | − "@executor/ui": "workspace:*", | |
| 58 | 53 | "@types/react": "^19.1.0", |
| 59 | 54 | "@effect/vitest": "catalog:", |
| 60 | 55 | "@types/node": "catalog:", |
| @@ -1,12 +1,12 @@ | ||
| 1 | 1 | import { useReducer, useCallback, useEffect, useRef, useState } from "react"; |
| 2 | 2 | import { useAtomSet } from "@effect-atom/atom-react"; |
| 3 | 3 | |
| 4 | −import { useScope } from "@executor/react"; | |
| 5 | −import { Button } from "@executor/ui/components/button"; | |
| 6 | −import { Input } from "@executor/ui/components/input"; | |
| 7 | −import { Label } from "@executor/ui/components/label"; | |
| 8 | −import { Badge } from "@executor/ui/components/badge"; | |
| 9 | −import { Spinner } from "@executor/ui/components/spinner"; | |
| 4 | +import { useScope } from "@executor/react/api/scope-context"; | |
| 5 | +import { Button } from "@executor/react/components/button"; | |
| 6 | +import { Input } from "@executor/react/components/input"; | |
| 7 | +import { Label } from "@executor/react/components/label"; | |
| 8 | +import { Badge } from "@executor/react/components/badge"; | |
| 9 | +import { Spinner } from "@executor/react/components/spinner"; | |
| 10 | 10 | import { probeMcpEndpoint, addMcpSource, startMcpOAuth } from "./atoms"; |
| 11 | 11 | import { mcpPresets, type McpPreset } from "../sdk/presets"; |
| 12 | 12 | |
| @@ -1,5 +1,5 @@ | ||
| 1 | −import { Button } from "@executor/ui/components/button"; | |
| 2 | −import { Badge } from "@executor/ui/components/badge"; | |
| 1 | +import { Button } from "@executor/react/components/button"; | |
| 2 | +import { Badge } from "@executor/react/components/badge"; | |
| 3 | 3 | |
| 4 | 4 | // --------------------------------------------------------------------------- |
| 5 | 5 | // Edit MCP Source — config view for an existing MCP source |
| @@ -1,4 +1,4 @@ | ||
| 1 | −import { Badge } from "@executor/ui/components/badge"; | |
| 1 | +import { Badge } from "@executor/react/components/badge"; | |
| 2 | 2 | |
| 3 | 3 | // --------------------------------------------------------------------------- |
| 4 | 4 | // MCP Source Summary — shown in the source list |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { AtomHttpApi } from "@effect-atom/atom-react"; |
| 2 | 2 | import { FetchHttpClient } from "@effect/platform"; |
| 3 | 3 | import { addGroup } from "@executor/api"; |
| 4 | −import { getBaseUrl } from "@executor/react"; | |
| 4 | +import { getBaseUrl } from "@executor/react/api/base-url"; | |
| 5 | 5 | import { McpGroup } from "../api/group"; |
| 6 | 6 | |
| 7 | 7 | // --------------------------------------------------------------------------- |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | import { lazy } from "react"; |
| 2 | −import type { SourcePlugin } from "@executor/react"; | |
| 2 | +import type { SourcePlugin } from "@executor/react/plugins/source-plugin"; | |
| 3 | 3 | import { mcpPresets } from "../sdk/presets"; |
| 4 | 4 | |
| 5 | 5 | export const mcpSourcePlugin: SourcePlugin = { |
| @@ -33,8 +33,7 @@ · 32 unmodified lines | ||
| 33 | 33 | "peerDependencies": { |
| 34 | 34 | "react": ">=18", |
| 35 | 35 | "@effect-atom/atom-react": "^0.5.0", |
| 36 | − "@executor/react": "workspace:*", | |
| 37 | − "@executor/ui": "workspace:*" | |
| 36 | + "@executor/react": "workspace:*" | |
| 38 | 37 | }, |
| 39 | 38 | "peerDependenciesMeta": { |
| 40 | 39 | "react": { |
| @@ -45,9 +44,6 @@ · 4 unmodified lines | ||
| 45 | 44 | }, |
| 46 | 45 | "@executor/react": { |
| 47 | 46 | "optional": true |
| 48 | − }, | |
| 49 | − "@executor/ui": { | |
| 50 | − "optional": true | |
| 51 | 47 | } |
| 52 | 48 | } |
| 53 | 49 | } |
| @@ -1,17 +1,17 @@ | ||
| 1 | 1 | import { useState } from "react"; |
| 2 | 2 | import { useAtomSet, useAtomValue, useAtomRefresh } from "@effect-atom/atom-react"; |
| 3 | 3 | import { Result } from "@effect-atom/atom-react"; |
| 4 | −import { useScope } from "@executor/react"; | |
| 5 | −import { Button } from "@executor/ui/components/button"; | |
| 6 | −import { Input } from "@executor/ui/components/input"; | |
| 7 | −import { Label } from "@executor/ui/components/label"; | |
| 4 | +import { useScope } from "@executor/react/api/scope-context"; | |
| 5 | +import { Button } from "@executor/react/components/button"; | |
| 6 | +import { Input } from "@executor/react/components/input"; | |
| 7 | +import { Label } from "@executor/react/components/label"; | |
| 8 | 8 | import { |
| 9 | 9 | Select, |
| 10 | 10 | SelectContent, |
| 11 | 11 | SelectItem, |
| 12 | 12 | SelectTrigger, |
| 13 | 13 | SelectValue, |
| 14 | −} from "@executor/ui/components/select"; | |
| 14 | +} from "@executor/react/components/select"; | |
| 15 | 15 | import { |
| 16 | 16 | Dialog, |
| 17 | 17 | DialogContent, |
| @@ -20,7 +20,7 @@ import { · 2 unmodified lines | ||
| 20 | 20 | DialogDescription, |
| 21 | 21 | DialogFooter, |
| 22 | 22 | DialogClose, |
| 23 | −} from "@executor/ui/components/dialog"; | |
| 23 | +} from "@executor/react/components/dialog"; | |
| 24 | 24 | |
| 25 | 25 | import { |
| 26 | 26 | onepasswordConfigAtom, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { AtomHttpApi } from "@effect-atom/atom-react"; |
| 2 | 2 | import { FetchHttpClient } from "@effect/platform"; |
| 3 | 3 | import { addGroup } from "@executor/api"; |
| 4 | −import { getBaseUrl } from "@executor/react"; | |
| 4 | +import { getBaseUrl } from "@executor/react/api/base-url"; | |
| 5 | 5 | import { OnePasswordGroup } from "../api/group"; |
| 6 | 6 | |
| 7 | 7 | // --------------------------------------------------------------------------- |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | import { lazy } from "react"; |
| 2 | −import type { SecretProviderPlugin } from "@executor/react"; | |
| 2 | +import type { SecretProviderPlugin } from "@executor/react/plugins/secret-provider-plugin"; | |
| 3 | 3 | |
| 4 | 4 | export const onePasswordSecretProviderPlugin: SecretProviderPlugin = { |
| 5 | 5 | key: "onepassword", |
| @@ -28,8 +28,7 @@ · 27 unmodified lines | ||
| 28 | 28 | "@effect-atom/atom-react": "^0.5.0", |
| 29 | 29 | "@tanstack/react-router": "^1.168.10", |
| 30 | 30 | "@executor/api": "workspace:*", |
| 31 | − "@executor/react": "workspace:*", | |
| 32 | − "@executor/ui": "workspace:*" | |
| 31 | + "@executor/react": "workspace:*" | |
| 33 | 32 | }, |
| 34 | 33 | "peerDependenciesMeta": { |
| 35 | 34 | "react": { |
| @@ -46,9 +45,6 @@ · 10 unmodified lines | ||
| 46 | 45 | }, |
| 47 | 46 | "@executor/react": { |
| 48 | 47 | "optional": true |
| 49 | − }, | |
| 50 | − "@executor/ui": { | |
| 51 | − "optional": true | |
| 52 | 48 | } |
| 53 | 49 | }, |
| 54 | 50 | "devDependencies": { |
| @@ -56,7 +52,6 @@ · 1 unmodified line | ||
| 56 | 52 | "@effect-atom/atom-react": "^0.5.0", |
| 57 | 53 | "@executor/api": "workspace:*", |
| 58 | 54 | "@executor/react": "workspace:*", |
| 59 | − "@executor/ui": "workspace:*", | |
| 60 | 55 | "@types/react": "^19.1.0", |
| 61 | 56 | "@effect/vitest": "catalog:", |
| 62 | 57 | "@types/node": "catalog:", |
| @@ -2,22 +2,17 @@ import { useState, useEffect, useRef } from "react"; · 1 unmodified line | ||
| 2 | 2 | import { useAtomSet, useAtomValue, useAtomRefresh, Result } from "@effect-atom/atom-react"; |
| 3 | 3 | import { Option } from "effect"; |
| 4 | 4 | |
| 5 | −import { | |
| 6 | − secretsAtom, | |
| 7 | − setSecret, | |
| 8 | − resolveSecret, | |
| 9 | − useScope, | |
| 10 | − SecretPicker, | |
| 11 | − type SecretPickerSecret, | |
| 12 | −} from "@executor/react"; | |
| 5 | +import { secretsAtom, setSecret, resolveSecret } from "@executor/react/api/atoms"; | |
| 6 | +import { useScope } from "@executor/react/api/scope-context"; | |
| 7 | +import { SecretPicker, type SecretPickerSecret } from "@executor/react/plugins/secret-picker"; | |
| 13 | 8 | import { SecretId } from "@executor/sdk"; |
| 14 | −import { Button } from "@executor/ui/components/button"; | |
| 15 | −import { Input } from "@executor/ui/components/input"; | |
| 16 | −import { Label } from "@executor/ui/components/label"; | |
| 17 | −import { Textarea } from "@executor/ui/components/textarea"; | |
| 18 | −import { Badge } from "@executor/ui/components/badge"; | |
| 19 | −import { RadioGroup, RadioGroupItem } from "@executor/ui/components/radio-group"; | |
| 20 | −import { Spinner } from "@executor/ui/components/spinner"; | |
| 9 | +import { Button } from "@executor/react/components/button"; | |
| 10 | +import { Input } from "@executor/react/components/input"; | |
| 11 | +import { Label } from "@executor/react/components/label"; | |
| 12 | +import { Textarea } from "@executor/react/components/textarea"; | |
| 13 | +import { Badge } from "@executor/react/components/badge"; | |
| 14 | +import { RadioGroup, RadioGroupItem } from "@executor/react/components/radio-group"; | |
| 15 | +import { Spinner } from "@executor/react/components/spinner"; | |
| 21 | 16 | import { previewOpenApiSpec, addOpenApiSpec } from "./atoms"; |
| 22 | 17 | import type { SpecPreview, HeaderPreset } from "../sdk/preview"; |
| 23 | 18 | import type { HeaderValue } from "../sdk/types"; |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import { AtomHttpApi } from "@effect-atom/atom-react"; |
| 2 | 2 | import { FetchHttpClient } from "@effect/platform"; |
| 3 | 3 | import { addGroup } from "@executor/api"; |
| 4 | −import { getBaseUrl } from "@executor/react"; | |
| 4 | +import { getBaseUrl } from "@executor/react/api/base-url"; | |
| 5 | 5 | import { OpenApiGroup } from "../api/group"; |
| 6 | 6 | |
| 7 | 7 | // --------------------------------------------------------------------------- |
| @@ -1,5 +1,5 @@ | ||
| 1 | 1 | import { lazy } from "react"; |
| 2 | −import type { SourcePlugin } from "@executor/react"; | |
| 2 | +import type { SourcePlugin } from "@executor/react/plugins/source-plugin"; | |
| 3 | 3 | import { openApiPresets } from "../sdk/presets"; |
| 4 | 4 | |
| 5 | 5 | export const openApiSourcePlugin: SourcePlugin = { |
| @@ -1,9 +1,12 @@ | ||
| 1 | 1 | { |
| 2 | − "name": "@executor/ui", | |
| 2 | + "name": "@executor/react", | |
| 3 | 3 | "version": "1.4.0", |
| 4 | 4 | "private": true, |
| 5 | 5 | "type": "module", |
| 6 | 6 | "exports": { |
| 7 | + "./api/*": "./src/api/*.tsx", | |
| 8 | + "./plugins/*": "./src/plugins/*.tsx", | |
| 9 | + "./pages/*": "./src/pages/*.tsx", | |
| 7 | 10 | "./components/*": "./src/components/*.tsx", |
| 8 | 11 | "./hooks/*": "./src/hooks/*.ts", |
| 9 | 12 | "./lib/*": "./src/lib/*.ts", |
| @@ -11,6 +14,11 @@ · 1 unmodified line | ||
| 11 | 14 | }, |
| 12 | 15 | "dependencies": { |
| 13 | 16 | "@base-ui/react": "^1.3.0", |
| 17 | + "@effect/platform": "catalog:", | |
| 18 | + "@effect-atom/atom": "^0.5.3", | |
| 19 | + "@effect-atom/atom-react": "^0.5.0", | |
| 20 | + "@executor/api": "workspace:*", | |
| 21 | + "@executor/sdk": "workspace:*", | |
| 14 | 22 | "@hookform/resolvers": "^5.2.2", |
| 15 | 23 | "@shikijs/langs": "^4.0.2", |
| 16 | 24 | "@shikijs/themes": "^4.0.2", |
| @@ -18,6 +26,7 @@ · 1 unmodified line | ||
| 18 | 26 | "clsx": "^2.1.1", |
| 19 | 27 | "cmdk": "^1.1.1", |
| 20 | 28 | "date-fns": "^4.1.0", |
| 29 | + "effect": "catalog:", | |
| 21 | 30 | "embla-carousel-react": "^8.6.0", |
| 22 | 31 | "input-otp": "^1.4.2", |
| 23 | 32 | "lucide-react": "^1.7.0", |
| @@ -37,6 +46,7 @@ · 13 unmodified lines | ||
| 37 | 46 | }, |
| 38 | 47 | "devDependencies": { |
| 39 | 48 | "@types/react": "^19.1.0", |
| 49 | + "@types/node": "catalog:", | |
| 40 | 50 | "hast-util-to-jsx-runtime": "^2.3.6", |
| 41 | 51 | "tailwindcss": "^4.1.10", |
| 42 | 52 | "typescript": "^5.9.3" |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { ChevronDownIcon } from "lucide-react" |
| 3 | 3 | import { Accordion as AccordionPrimitive } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | function Accordion({ |
| 8 | 8 | ...props |
| @@ -3,8 +3,8 @@ · 2 unmodified lines | ||
| 3 | 3 | import * as React from "react" |
| 4 | 4 | import { AlertDialog as AlertDialogPrimitive } from "radix-ui" |
| 5 | 5 | |
| 6 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | −import { Button } from "@executor/ui/components/button" | |
| 6 | +import { cn } from "../lib/utils" | |
| 7 | +import { Button } from "./button" | |
| 8 | 8 | |
| 9 | 9 | function AlertDialog({ |
| 10 | 10 | ...props |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { cva, type VariantProps } from "class-variance-authority" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | const alertVariants = cva( |
| 7 | 7 | "relative grid w-full grid-cols-[0_1fr] items-start gap-y-0.5 rounded-lg border px-4 py-3 text-sm has-[>svg]:grid-cols-[calc(var(--spacing)*4)_1fr] has-[>svg]:gap-x-3 [&>svg]:size-4 [&>svg]:translate-y-0.5 [&>svg]:text-current", |
File renamed without changes.
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Avatar as AvatarPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Avatar({ |
| 7 | 7 | className, |
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { cva, type VariantProps } from "class-variance-authority" |
| 3 | 3 | import { Slot } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | const badgeVariants = cva( |
| 8 | 8 | "inline-flex w-fit shrink-0 items-center justify-center gap-1 overflow-hidden rounded-full border border-transparent px-2 py-0.5 text-xs font-medium whitespace-nowrap transition-[color,box-shadow] focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&>svg]:pointer-events-none [&>svg]:size-3", |
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { ChevronRight, MoreHorizontal } from "lucide-react" |
| 3 | 3 | import { Slot } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | function Breadcrumb({ ...props }: React.ComponentProps<"nav">) { |
| 8 | 8 | return <nav aria-label="breadcrumb" data-slot="breadcrumb" {...props} /> |
| @@ -1,8 +1,8 @@ | ||
| 1 | 1 | import { cva, type VariantProps } from "class-variance-authority" |
| 2 | 2 | import { Slot } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | −import { Separator } from "@executor/ui/components/separator" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | +import { Separator } from "./separator" | |
| 6 | 6 | |
| 7 | 7 | const buttonGroupVariants = cva( |
| 8 | 8 | "flex w-fit items-stretch has-[>[data-slot=button-group]]:gap-2 [&>*]:focus-visible:relative [&>*]:focus-visible:z-10 has-[select[aria-hidden=true]:last-child]:[&>[data-slot=select-trigger]:last-of-type]:rounded-r-md [&>[data-slot=select-trigger]:not([class*='w-'])]:w-fit [&>input]:flex-1", |
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { cva, type VariantProps } from "class-variance-authority" |
| 3 | 3 | import { Slot } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | const buttonVariants = cva( |
| 8 | 8 | "inline-flex shrink-0 items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-all outline-none focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", |
| @@ -10,8 +10,8 @@ import { · 9 unmodified lines | ||
| 10 | 10 | type DayButton, |
| 11 | 11 | } from "react-day-picker" |
| 12 | 12 | |
| 13 | −import { cn } from "@executor/ui/lib/utils" | |
| 14 | −import { Button, buttonVariants } from "@executor/ui/components/button" | |
| 13 | +import { cn } from "../lib/utils" | |
| 14 | +import { Button, buttonVariants } from "./button" | |
| 15 | 15 | |
| 16 | 16 | function Calendar({ |
| 17 | 17 | className, |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | |
| 3 | −import { cn } from "@executor/ui/lib/utils" | |
| 3 | +import { cn } from "../lib/utils" | |
| 4 | 4 | |
| 5 | 5 | function Card({ className, ...props }: React.ComponentProps<"div">) { |
| 6 | 6 | return ( |
| @@ -6,8 +6,8 @@ import useEmblaCarousel, { · 5 unmodified lines | ||
| 6 | 6 | } from "embla-carousel-react" |
| 7 | 7 | import { ArrowLeft, ArrowRight } from "lucide-react" |
| 8 | 8 | |
| 9 | −import { cn } from "@executor/ui/lib/utils" | |
| 10 | −import { Button } from "@executor/ui/components/button" | |
| 9 | +import { cn } from "../lib/utils" | |
| 10 | +import { Button } from "./button" | |
| 11 | 11 | |
| 12 | 12 | type CarouselApi = UseEmblaCarouselType[1] |
| 13 | 13 | type UseCarouselParameters = Parameters<typeof useEmblaCarousel> |
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import * as RechartsPrimitive from "recharts" |
| 3 | 3 | import type { TooltipValueType } from "recharts" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | // Format: { THEME_NAME: CSS_SELECTOR } |
| 8 | 8 | const THEMES = { light: "", dark: ".dark" } as const |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { CheckIcon } from "lucide-react" |
| 5 | 5 | import { Checkbox as CheckboxPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function Checkbox({ |
| 10 | 10 | className, |
File renamed without changes.
File renamed without changes.
| @@ -4,14 +4,14 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { Combobox as ComboboxPrimitive } from "@base-ui/react" |
| 5 | 5 | import { CheckIcon, ChevronDownIcon, XIcon } from "lucide-react" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 8 | −import { Button } from "@executor/ui/components/button" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | +import { Button } from "./button" | |
| 9 | 9 | import { |
| 10 | 10 | InputGroup, |
| 11 | 11 | InputGroupAddon, |
| 12 | 12 | InputGroupButton, |
| 13 | 13 | InputGroupInput, |
| 14 | −} from "@executor/ui/components/input-group" | |
| 14 | +} from "./input-group" | |
| 15 | 15 | |
| 16 | 16 | const Combobox = ComboboxPrimitive.Root |
| 17 | 17 | |
| @@ -4,14 +4,14 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { Command as CommandPrimitive } from "cmdk" |
| 5 | 5 | import { SearchIcon } from "lucide-react" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | import { |
| 9 | 9 | Dialog, |
| 10 | 10 | DialogContent, |
| 11 | 11 | DialogDescription, |
| 12 | 12 | DialogHeader, |
| 13 | 13 | DialogTitle, |
| 14 | −} from "@executor/ui/components/dialog" | |
| 14 | +} from "./dialog" | |
| 15 | 15 | |
| 16 | 16 | function Command({ |
| 17 | 17 | className, |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" |
| 5 | 5 | import { ContextMenu as ContextMenuPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function ContextMenu({ |
| 10 | 10 | ...props |
| @@ -2,8 +2,8 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { XIcon } from "lucide-react" |
| 3 | 3 | import { Dialog as DialogPrimitive } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 6 | −import { Button } from "@executor/ui/components/button" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | +import { Button } from "./button" | |
| 7 | 7 | |
| 8 | 8 | function Dialog({ |
| 9 | 9 | ...props |
File renamed without changes.
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Drawer as DrawerPrimitive } from "vaul" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Drawer({ |
| 7 | 7 | ...props |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" |
| 5 | 5 | import { DropdownMenu as DropdownMenuPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function DropdownMenu({ |
| 10 | 10 | ...props |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import { cva, type VariantProps } from "class-variance-authority" |
| 2 | 2 | |
| 3 | −import { cn } from "@executor/ui/lib/utils" | |
| 3 | +import { cn } from "../lib/utils" | |
| 4 | 4 | |
| 5 | 5 | function Empty({ className, ...props }: React.ComponentProps<"div">) { |
| 6 | 6 | return ( |
| @@ -3,9 +3,9 @@ · 2 unmodified lines | ||
| 3 | 3 | import { useMemo } from "react" |
| 4 | 4 | import { cva, type VariantProps } from "class-variance-authority" |
| 5 | 5 | |
| 6 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | −import { Label } from "@executor/ui/components/label" | |
| 8 | −import { Separator } from "@executor/ui/components/separator" | |
| 6 | +import { cn } from "../lib/utils" | |
| 7 | +import { Label } from "./label" | |
| 8 | +import { Separator } from "./separator" | |
| 9 | 9 | |
| 10 | 10 | function FieldSet({ className, ...props }: React.ComponentProps<"fieldset">) { |
| 11 | 11 | return ( |
| @@ -11,8 +11,8 @@ import { · 10 unmodified lines | ||
| 11 | 11 | type FieldValues, |
| 12 | 12 | } from "react-hook-form" |
| 13 | 13 | |
| 14 | −import { cn } from "@executor/ui/lib/utils" | |
| 15 | −import { Label } from "@executor/ui/components/label" | |
| 14 | +import { cn } from "../lib/utils" | |
| 15 | +import { Label } from "./label" | |
| 16 | 16 | |
| 17 | 17 | const Form = FormProvider |
| 18 | 18 | |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { HoverCard as HoverCardPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function HoverCard({ |
| 7 | 7 | ...props |
| @@ -1,10 +1,10 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { cva, type VariantProps } from "class-variance-authority" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | −import { Button } from "@executor/ui/components/button" | |
| 6 | −import { Input } from "@executor/ui/components/input" | |
| 7 | −import { Textarea } from "@executor/ui/components/textarea" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | +import { Button } from "./button" | |
| 6 | +import { Input } from "./input" | |
| 7 | +import { Textarea } from "./textarea" | |
| 8 | 8 | |
| 9 | 9 | function InputGroup({ className, ...props }: React.ComponentProps<"div">) { |
| 10 | 10 | return ( |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { OTPInput, OTPInputContext } from "input-otp" |
| 5 | 5 | import { MinusIcon } from "lucide-react" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function InputOTP({ |
| 10 | 10 | className, |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | |
| 3 | −import { cn } from "@executor/ui/lib/utils" | |
| 3 | +import { cn } from "../lib/utils" | |
| 4 | 4 | |
| 5 | 5 | function Input({ className, type, ...props }: React.ComponentProps<"input">) { |
| 6 | 6 | return ( |
| @@ -2,8 +2,8 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { cva, type VariantProps } from "class-variance-authority" |
| 3 | 3 | import { Slot } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 6 | −import { Separator } from "@executor/ui/components/separator" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | +import { Separator } from "./separator" | |
| 7 | 7 | |
| 8 | 8 | function ItemGroup({ className, ...props }: React.ComponentProps<"div">) { |
| 9 | 9 | return ( |
| @@ -1,4 +1,4 @@ | ||
| 1 | −import { cn } from "@executor/ui/lib/utils" | |
| 1 | +import { cn } from "../lib/utils" | |
| 2 | 2 | |
| 3 | 3 | function Kbd({ className, ...props }: React.ComponentProps<"kbd">) { |
| 4 | 4 | return ( |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Label as LabelPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Label({ |
| 7 | 7 | className, |
File renamed without changes.
File renamed without changes.
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { CheckIcon, ChevronRightIcon, CircleIcon } from "lucide-react" |
| 5 | 5 | import { Menubar as MenubarPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function Menubar({ |
| 10 | 10 | className, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { ChevronDownIcon } from "lucide-react" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function NativeSelect({ |
| 7 | 7 | className, |
| @@ -3,7 +3,7 @@ import { cva } from "class-variance-authority" · 2 unmodified lines | ||
| 3 | 3 | import { ChevronDownIcon } from "lucide-react" |
| 4 | 4 | import { NavigationMenu as NavigationMenuPrimitive } from "radix-ui" |
| 5 | 5 | |
| 6 | −import { cn } from "@executor/ui/lib/utils" | |
| 6 | +import { cn } from "../lib/utils" | |
| 7 | 7 | |
| 8 | 8 | function NavigationMenu({ |
| 9 | 9 | className, |
| @@ -5,8 +5,8 @@ import { · 4 unmodified lines | ||
| 5 | 5 | MoreHorizontalIcon, |
| 6 | 6 | } from "lucide-react" |
| 7 | 7 | |
| 8 | −import { cn } from "@executor/ui/lib/utils" | |
| 9 | −import { buttonVariants, type Button } from "@executor/ui/components/button" | |
| 8 | +import { cn } from "../lib/utils" | |
| 9 | +import { buttonVariants, type Button } from "./button" | |
| 10 | 10 | |
| 11 | 11 | function Pagination({ className, ...props }: React.ComponentProps<"nav">) { |
| 12 | 12 | return ( |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Popover as PopoverPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Popover({ |
| 7 | 7 | ...props |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | import * as React from "react" |
| 4 | 4 | import { Progress as ProgressPrimitive } from "radix-ui" |
| 5 | 5 | |
| 6 | −import { cn } from "@executor/ui/lib/utils" | |
| 6 | +import { cn } from "../lib/utils" | |
| 7 | 7 | |
| 8 | 8 | function Progress({ |
| 9 | 9 | className, |
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { CircleIcon } from "lucide-react" |
| 3 | 3 | import { RadioGroup as RadioGroupPrimitive } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | function RadioGroup({ |
| 8 | 8 | className, |
| @@ -3,7 +3,7 @@ · 2 unmodified lines | ||
| 3 | 3 | import { GripVerticalIcon } from "lucide-react" |
| 4 | 4 | import * as ResizablePrimitive from "react-resizable-panels" |
| 5 | 5 | |
| 6 | −import { cn } from "@executor/ui/lib/utils" | |
| 6 | +import { cn } from "../lib/utils" | |
| 7 | 7 | |
| 8 | 8 | function ResizablePanelGroup({ |
| 9 | 9 | className, |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { ScrollArea as ScrollAreaPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function ScrollArea({ |
| 7 | 7 | className, |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { CheckIcon, ChevronDownIcon, ChevronUpIcon } from "lucide-react" |
| 5 | 5 | import { Select as SelectPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function Select({ |
| 10 | 10 | ...props |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Separator as SeparatorPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Separator({ |
| 7 | 7 | className, |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { XIcon } from "lucide-react" |
| 5 | 5 | import { Dialog as SheetPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | function Sheet({ ...props }: React.ComponentProps<typeof SheetPrimitive.Root>) { |
| 10 | 10 | return <SheetPrimitive.Root data-slot="sheet" {...props} /> |
| @@ -3,25 +3,25 @@ import { cva, type VariantProps } from "class-variance-authority" · 2 unmodified lines | ||
| 3 | 3 | import { PanelLeftIcon } from "lucide-react" |
| 4 | 4 | import { Slot } from "radix-ui" |
| 5 | 5 | |
| 6 | −import { useIsMobile } from "@executor/ui/hooks/use-mobile" | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 8 | −import { Button } from "@executor/ui/components/button" | |
| 9 | −import { Input } from "@executor/ui/components/input" | |
| 10 | −import { Separator } from "@executor/ui/components/separator" | |
| 6 | +import { useIsMobile } from "../hooks/use-mobile" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | +import { Button } from "./button" | |
| 9 | +import { Input } from "./input" | |
| 10 | +import { Separator } from "./separator" | |
| 11 | 11 | import { |
| 12 | 12 | Sheet, |
| 13 | 13 | SheetContent, |
| 14 | 14 | SheetDescription, |
| 15 | 15 | SheetHeader, |
| 16 | 16 | SheetTitle, |
| 17 | −} from "@executor/ui/components/sheet" | |
| 18 | −import { Skeleton } from "@executor/ui/components/skeleton" | |
| 17 | +} from "./sheet" | |
| 18 | +import { Skeleton } from "./skeleton" | |
| 19 | 19 | import { |
| 20 | 20 | Tooltip, |
| 21 | 21 | TooltipContent, |
| 22 | 22 | TooltipProvider, |
| 23 | 23 | TooltipTrigger, |
| 24 | −} from "@executor/ui/components/tooltip" | |
| 24 | +} from "./tooltip" | |
| 25 | 25 | |
| 26 | 26 | const SIDEBAR_COOKIE_NAME = "sidebar_state" |
| 27 | 27 | const SIDEBAR_COOKIE_MAX_AGE = 60 * 60 * 24 * 7 |
| @@ -1,4 +1,4 @@ | ||
| 1 | −import { cn } from "@executor/ui/lib/utils" | |
| 1 | +import { cn } from "../lib/utils" | |
| 2 | 2 | |
| 3 | 3 | function Skeleton({ className, ...props }: React.ComponentProps<"div">) { |
| 4 | 4 | return ( |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Slider as SliderPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Slider({ |
| 7 | 7 | className, |
File renamed without changes.
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import { Loader2Icon } from "lucide-react" |
| 2 | 2 | |
| 3 | −import { cn } from "@executor/ui/lib/utils" | |
| 3 | +import { cn } from "../lib/utils" | |
| 4 | 4 | |
| 5 | 5 | function Spinner({ className, ...props }: React.ComponentProps<"svg">) { |
| 6 | 6 | return ( |
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Switch as SwitchPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function Switch({ |
| 7 | 7 | className, |
| @@ -2,7 +2,7 @@ · 1 unmodified line | ||
| 2 | 2 | |
| 3 | 3 | import * as React from "react" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | function Table({ className, ...props }: React.ComponentProps<"table">) { |
| 8 | 8 | return ( |
| @@ -2,7 +2,7 @@ import * as React from "react" · 1 unmodified line | ||
| 2 | 2 | import { cva, type VariantProps } from "class-variance-authority" |
| 3 | 3 | import { Tabs as TabsPrimitive } from "radix-ui" |
| 4 | 4 | |
| 5 | −import { cn } from "@executor/ui/lib/utils" | |
| 5 | +import { cn } from "../lib/utils" | |
| 6 | 6 | |
| 7 | 7 | function Tabs({ |
| 8 | 8 | className, |
| @@ -1,6 +1,6 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | |
| 3 | −import { cn } from "@executor/ui/lib/utils" | |
| 3 | +import { cn } from "../lib/utils" | |
| 4 | 4 | |
| 5 | 5 | function Textarea({ className, ...props }: React.ComponentProps<"textarea">) { |
| 6 | 6 | return ( |
| @@ -4,8 +4,8 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { type VariantProps } from "class-variance-authority" |
| 5 | 5 | import { ToggleGroup as ToggleGroupPrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 8 | −import { toggleVariants } from "@executor/ui/components/toggle" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | +import { toggleVariants } from "./toggle" | |
| 9 | 9 | |
| 10 | 10 | const ToggleGroupContext = React.createContext< |
| 11 | 11 | VariantProps<typeof toggleVariants> & { |
| @@ -4,7 +4,7 @@ import * as React from "react" · 3 unmodified lines | ||
| 4 | 4 | import { cva, type VariantProps } from "class-variance-authority" |
| 5 | 5 | import { Toggle as TogglePrimitive } from "radix-ui" |
| 6 | 6 | |
| 7 | −import { cn } from "@executor/ui/lib/utils" | |
| 7 | +import { cn } from "../lib/utils" | |
| 8 | 8 | |
| 9 | 9 | const toggleVariants = cva( |
| 10 | 10 | "inline-flex items-center justify-center gap-2 rounded-md text-sm font-medium whitespace-nowrap transition-[color,box-shadow] outline-none hover:bg-muted hover:text-muted-foreground focus-visible:border-ring focus-visible:ring-[3px] focus-visible:ring-ring/50 disabled:pointer-events-none disabled:opacity-50 aria-invalid:border-destructive aria-invalid:ring-destructive/20 data-[state=on]:bg-accent data-[state=on]:text-accent-foreground dark:aria-invalid:ring-destructive/40 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4", |
| @@ -1,9 +1,11 @@ | ||
| 1 | 1 | import { useMemo, useState } from "react"; |
| 2 | −import { useAtomValue, toolSchemaAtom, Result, ScopeId, ToolId } from "@executor/react"; | |
| 3 | −import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "@executor/ui/components/accordion"; | |
| 4 | −import { Badge } from "@executor/ui/components/badge"; | |
| 5 | −import { CodeBlock } from "@executor/ui/components/code-block"; | |
| 6 | −import { Markdown } from "@executor/ui/components/markdown"; | |
| 2 | +import { useAtomValue, Result } from "@effect-atom/atom-react"; | |
| 3 | +import { toolSchemaAtom } from "../api/atoms"; | |
| 4 | +import { ScopeId, ToolId } from "@executor/sdk"; | |
| 5 | +import { Accordion, AccordionContent, AccordionItem, AccordionTrigger } from "./accordion"; | |
| 6 | +import { Badge } from "./badge"; | |
| 7 | +import { CodeBlock } from "./code-block"; | |
| 8 | +import { Markdown } from "./markdown"; | |
| 7 | 9 | |
| 8 | 10 | // --------------------------------------------------------------------------- |
| 9 | 11 | // Copy button |
File renamed without changes.
| @@ -1,7 +1,7 @@ | ||
| 1 | 1 | import * as React from "react" |
| 2 | 2 | import { Tooltip as TooltipPrimitive } from "radix-ui" |
| 3 | 3 | |
| 4 | −import { cn } from "@executor/ui/lib/utils" | |
| 4 | +import { cn } from "../lib/utils" | |
| 5 | 5 | |
| 6 | 6 | function TooltipProvider({ |
| 7 | 7 | delayDuration = 0, |
File renamed without changes.
| @@ -0,0 +1 @@ | ||
| 1 | +export { useScope } from "../api/scope-context"; | |
File renamed without changes.
File renamed without changes.
| @@ -1,16 +1,9 @@ | ||
| 1 | 1 | import { useState, Suspense } from "react"; |
| 2 | −import { | |
| 3 | − useAtomValue, | |
| 4 | − useAtomSet, | |
| 5 | − useAtomRefresh, | |
| 6 | − Result, | |
| 7 | − secretsAtom, | |
| 8 | − setSecret, | |
| 9 | − removeSecret, | |
| 10 | −} from "@executor/react"; | |
| 11 | −import type { SecretProviderPlugin } from "@executor/react"; | |
| 2 | +import { useAtomValue, useAtomSet, useAtomRefresh, Result } from "@effect-atom/atom-react"; | |
| 3 | +import { secretsAtom, setSecret, removeSecret } from "../api/atoms"; | |
| 4 | +import type { SecretProviderPlugin } from "../plugins/secret-provider-plugin"; | |
| 12 | 5 | import { SecretId } from "@executor/sdk"; |
| 13 | −import { useScope } from "../lib/use-scope"; | |
| 6 | +import { useScope } from "../hooks/use-scope"; | |
| 14 | 7 | import { onePasswordSecretProviderPlugin } from "@executor/plugin-onepassword/react"; |
| 15 | 8 | import { |
| 16 | 9 | Dialog, |
| @@ -20,24 +13,24 @@ import { · 3 unmodified lines | ||
| 20 | 13 | DialogDescription, |
| 21 | 14 | DialogFooter, |
| 22 | 15 | DialogClose, |
| 23 | −} from "@executor/ui/components/dialog"; | |
| 24 | −import { Button } from "@executor/ui/components/button"; | |
| 25 | −import { Input } from "@executor/ui/components/input"; | |
| 26 | −import { Label } from "@executor/ui/components/label"; | |
| 27 | −import { Badge } from "@executor/ui/components/badge"; | |
| 16 | +} from "../components/dialog"; | |
| 17 | +import { Button } from "../components/button"; | |
| 18 | +import { Input } from "../components/input"; | |
| 19 | +import { Label } from "../components/label"; | |
| 20 | +import { Badge } from "../components/badge"; | |
| 28 | 21 | import { |
| 29 | 22 | DropdownMenu, |
| 30 | 23 | DropdownMenuContent, |
| 31 | 24 | DropdownMenuItem, |
| 32 | 25 | DropdownMenuTrigger, |
| 33 | −} from "@executor/ui/components/dropdown-menu"; | |
| 26 | +} from "../components/dropdown-menu"; | |
| 34 | 27 | import { |
| 35 | 28 | Select, |
| 36 | 29 | SelectContent, |
| 37 | 30 | SelectItem, |
| 38 | 31 | SelectTrigger, |
| 39 | 32 | SelectValue, |
| 40 | −} from "@executor/ui/components/select"; | |
| 33 | +} from "../components/select"; | |
| 41 | 34 | |
| 42 | 35 | // --------------------------------------------------------------------------- |
| 43 | 36 | // Add secret dialog |
| @@ -1,20 +1,11 @@ | ||
| 1 | 1 | import { useEffect, useMemo, useState } from "react"; |
| 2 | 2 | import { useNavigate } from "@tanstack/react-router"; |
| 3 | −import { | |
| 4 | − useAtomValue, | |
| 5 | − useAtomSet, | |
| 6 | − useAtomRefresh, | |
| 7 | − sourceToolsAtom, | |
| 8 | − sourcesAtom, | |
| 9 | − sourceAtom, | |
| 10 | − removeSource, | |
| 11 | − refreshSource, | |
| 12 | − Result, | |
| 13 | −} from "@executor/react"; | |
| 3 | +import { useAtomValue, useAtomSet, useAtomRefresh, Result } from "@effect-atom/atom-react"; | |
| 4 | +import { sourceToolsAtom, sourcesAtom, sourceAtom, removeSource, refreshSource } from "../api/atoms"; | |
| 14 | 5 | import { ToolTree } from "../components/tool-tree"; |
| 15 | 6 | import { ToolDetail, ToolDetailEmpty } from "../components/tool-detail"; |
| 16 | 7 | import type { ToolSummary } from "../components/tool-tree"; |
| 17 | −import { useScope } from "../lib/use-scope"; | |
| 8 | +import { useScope } from "../hooks/use-scope"; | |
| 18 | 9 | |
| 19 | 10 | export function SourceDetailPage(props: { namespace: string }) { |
| 20 | 11 | const { namespace } = props; |
| @@ -1,8 +1,9 @@ | ||
| 1 | 1 | import { Suspense } from "react"; |
| 2 | 2 | import { Link, useNavigate } from "@tanstack/react-router"; |
| 3 | −import type { SourcePlugin } from "@executor/react"; | |
| 4 | −import { useAtomRefresh, sourcesAtom } from "@executor/react"; | |
| 5 | −import { useScope } from "../lib/use-scope"; | |
| 3 | +import type { SourcePlugin } from "../plugins/source-plugin"; | |
| 4 | +import { useAtomRefresh } from "@effect-atom/atom-react"; | |
| 5 | +import { sourcesAtom } from "../api/atoms"; | |
| 6 | +import { useScope } from "../hooks/use-scope"; | |
| 6 | 7 | import { openApiSourcePlugin } from "@executor/plugin-openapi/react"; |
| 7 | 8 | import { mcpSourcePlugin } from "@executor/plugin-mcp/react"; |
| 8 | 9 | import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react"; |
| @@ -1,8 +1,9 @@ | ||
| 1 | 1 | import { useState, useCallback, useMemo } from "react"; |
| 2 | 2 | import { Link, useNavigate } from "@tanstack/react-router"; |
| 3 | −import { Result, useAtomValue, useAtomSet, sourcesAtom, detectSource } from "@executor/react"; | |
| 4 | −import { useScope } from "../lib/use-scope"; | |
| 5 | −import type { SourcePlugin, SourcePreset } from "@executor/react"; | |
| 3 | +import { Result, useAtomValue, useAtomSet } from "@effect-atom/atom-react"; | |
| 4 | +import { sourcesAtom, detectSource } from "../api/atoms"; | |
| 5 | +import { useScope } from "../hooks/use-scope"; | |
| 6 | +import type { SourcePlugin, SourcePreset } from "../plugins/source-plugin"; | |
| 6 | 7 | import { openApiSourcePlugin } from "@executor/plugin-openapi/react"; |
| 7 | 8 | import { mcpSourcePlugin } from "@executor/plugin-mcp/react"; |
| 8 | 9 | import { googleDiscoverySourcePlugin } from "@executor/plugin-google-discovery/react"; |
| @@ -1,5 +1,6 @@ | ||
| 1 | −import { useAtomValue, Result, toolsAtom } from "@executor/react"; | |
| 2 | −import { useScope } from "../lib/use-scope"; | |
| 1 | +import { useAtomValue, Result } from "@effect-atom/atom-react"; | |
| 2 | +import { toolsAtom } from "../api/atoms"; | |
| 3 | +import { useScope } from "../hooks/use-scope"; | |
| 3 | 4 | |
| 4 | 5 | export function ToolsPage() { |
| 5 | 6 | const scopeId = useScope(); |
| @@ -1,18 +1,18 @@ | ||
| 1 | 1 | import { useState, type ChangeEvent, type FocusEvent } from "react"; |
| 2 | 2 | |
| 3 | −import { Input } from "@executor/ui/components/input"; | |
| 3 | +import { Input } from "../components/input"; | |
| 4 | 4 | import { |
| 5 | 5 | Command, |
| 6 | 6 | CommandEmpty, |
| 7 | 7 | CommandGroup, |
| 8 | 8 | CommandItem, |
| 9 | 9 | CommandList, |
| 10 | −} from "@executor/ui/components/command"; | |
| 10 | +} from "../components/command"; | |
| 11 | 11 | import { |
| 12 | 12 | Popover, |
| 13 | 13 | PopoverAnchor, |
| 14 | 14 | PopoverContent, |
| 15 | −} from "@executor/ui/components/popover"; | |
| 15 | +} from "../components/popover"; | |
| 16 | 16 | |
| 17 | 17 | export interface SecretPickerSecret { |
| 18 | 18 | readonly id: string; |
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
| @@ -1,4 +0,0 @@ | ||
| 1 | −# @executor/ui changelog | |
| 2 | − | |
| 3 | −This file exists for Changesets release workflow compatibility. | |
| 4 | −Canonical user-facing release notes are published on GitHub Releases. | |
| @@ -1,20 +0,0 @@ | ||
| 1 | −{ | |
| 2 | − "$schema": "https://ui.shadcn.com/schema.json", | |
| 3 | − "style": "new-york", | |
| 4 | − "rsc": false, | |
| 5 | − "tsx": true, | |
| 6 | − "tailwind": { | |
| 7 | − "config": "", | |
| 8 | − "css": "src/styles/globals.css", | |
| 9 | − "baseColor": "neutral", | |
| 10 | − "cssVariables": true | |
| 11 | − }, | |
| 12 | − "iconLibrary": "lucide", | |
| 13 | − "aliases": { | |
| 14 | − "components": "@executor/ui/components", | |
| 15 | − "utils": "@executor/ui/lib/utils", | |
| 16 | − "hooks": "@executor/ui/hooks", | |
| 17 | − "lib": "@executor/ui/lib", | |
| 18 | − "ui": "@executor/ui/components" | |
| 19 | − } | |
| 20 | −} | |
| @@ -1,25 +0,0 @@ | ||
| 1 | −{ | |
| 2 | − "compilerOptions": { | |
| 3 | − "target": "ESNext", | |
| 4 | − "module": "ESNext", | |
| 5 | − "moduleResolution": "bundler", | |
| 6 | − "strict": true, | |
| 7 | − "esModuleInterop": true, | |
| 8 | − "skipLibCheck": true, | |
| 9 | − "outDir": "dist", | |
| 10 | − "rootDir": "src", | |
| 11 | − "declaration": true, | |
| 12 | − "declarationMap": true, | |
| 13 | − "sourceMap": true, | |
| 14 | − "jsx": "react-jsx", | |
| 15 | − "paths": { | |
| 16 | − "@executor/ui/*": ["./src/*"] | |
| 17 | − }, | |
| 18 | − "plugins": [ | |
| 19 | − { | |
| 20 | − "name": "@effect/language-service" | |
| 21 | − } | |
| 22 | − ] | |
| 23 | − }, | |
| 24 | − "include": ["src"] | |
| 25 | −} | |