@motiadev/workbench 0.7.3-beta.135 → 0.8.0-beta.137
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/App.js +2 -2
- package/dist/src/components/flow/base-edge.js +4 -2
- package/dist/src/components/flow/flow-view.js +2 -1
- package/dist/src/components/flow/hooks/use-save-workflow-config.js +1 -1
- package/dist/src/components/header/header.js +1 -1
- package/dist/src/components/logs/log-detail.js +1 -1
- package/dist/src/components/logs/logs-page.js +4 -4
- package/dist/src/components/observability/trace-item/trace-item-detail.js +1 -2
- package/dist/src/components/observability/trace-item/trace-item.js +1 -1
- package/dist/src/components/observability/trace-timeline.js +1 -1
- package/dist/src/components/observability/traces-groups.js +1 -1
- package/dist/src/components/observability/traces-page.js +17 -5
- package/dist/src/components/states/hooks/states-hooks.d.ts +7 -1
- package/dist/src/components/states/hooks/states-hooks.js +11 -3
- package/dist/src/components/states/state-editor.js +1 -1
- package/dist/src/components/states/state-sidebar.js +1 -1
- package/dist/src/components/states/states-page.js +46 -8
- package/dist/src/components/tutorial/engine/workbench-xpath.d.ts +5 -0
- package/dist/src/components/tutorial/engine/workbench-xpath.js +7 -2
- package/dist/src/components/tutorial/tutorial-step.js +2 -1
- package/dist/src/components/{endpoints → ui}/json-editor.js +1 -1
- package/dist/src/components/ui/table.js +1 -1
- package/dist/src/components/ui/theme-toggle.js +1 -2
- package/dist/src/index.css +10 -6
- package/dist/src/lib/utils.d.ts +0 -2
- package/dist/src/lib/utils.js +0 -5
- package/dist/src/publicComponents/base-node/base-node.js +1 -1
- package/dist/src/publicComponents/base-node/code-display.js +3 -3
- package/dist/src/publicComponents/base-node/feature-card.js +1 -1
- package/dist/src/publicComponents/base-node/node-header.js +1 -1
- package/dist/src/publicComponents/base-node/node-sidebar.js +1 -1
- package/dist/src/stores/use-flow-store.d.ts +5 -3
- package/dist/src/stores/use-global-store.d.ts +5 -3
- package/dist/src/stores/use-tabs-store.d.ts +5 -3
- package/dist/tsconfig.app.tsbuildinfo +1 -1
- package/dist/tsconfig.node.tsbuildinfo +1 -1
- package/package.json +4 -3
- package/dist/src/components/endpoints/endpoint-badge.d.ts +0 -10
- package/dist/src/components/endpoints/endpoint-badge.js +0 -22
- package/dist/src/components/endpoints/endpoint-body-panel.d.ts +0 -13
- package/dist/src/components/endpoints/endpoint-body-panel.js +0 -16
- package/dist/src/components/endpoints/endpoint-call.d.ts +0 -7
- package/dist/src/components/endpoints/endpoint-call.js +0 -58
- package/dist/src/components/endpoints/endpoint-description.d.ts +0 -7
- package/dist/src/components/endpoints/endpoint-description.js +0 -13
- package/dist/src/components/endpoints/endpoint-path-params-panel.d.ts +0 -8
- package/dist/src/components/endpoints/endpoint-path-params-panel.js +0 -17
- package/dist/src/components/endpoints/endpoint-query-params-panel.d.ts +0 -8
- package/dist/src/components/endpoints/endpoint-query-params-panel.js +0 -16
- package/dist/src/components/endpoints/endpoint-response-schema.d.ts +0 -10
- package/dist/src/components/endpoints/endpoint-response-schema.js +0 -17
- package/dist/src/components/endpoints/endpoint-response.d.ts +0 -8
- package/dist/src/components/endpoints/endpoint-response.js +0 -50
- package/dist/src/components/endpoints/endpoint-side-panel.d.ts +0 -8
- package/dist/src/components/endpoints/endpoint-side-panel.js +0 -25
- package/dist/src/components/endpoints/endpoints-page.d.ts +0 -1
- package/dist/src/components/endpoints/endpoints-page.js +0 -14
- package/dist/src/components/endpoints/hooks/use-get-endpoints.d.ts +0 -2
- package/dist/src/components/endpoints/hooks/use-get-endpoints.js +0 -8
- package/dist/src/components/endpoints/hooks/use-json-schema-to-json.d.ts +0 -4
- package/dist/src/components/endpoints/hooks/use-json-schema-to-json.js +0 -11
- package/dist/src/components/endpoints/hooks/use-path-params.d.ts +0 -1
- package/dist/src/components/endpoints/hooks/use-path-params.js +0 -4
- package/dist/src/components/endpoints/hooks/use-state-stream.d.ts +0 -7
- package/dist/src/components/endpoints/hooks/use-state-stream.js +0 -11
- package/dist/src/components/endpoints/hooks/utils.d.ts +0 -1
- package/dist/src/components/endpoints/hooks/utils.js +0 -29
- package/dist/src/components/endpoints/response-body.d.ts +0 -7
- package/dist/src/components/endpoints/response-body.js +0 -6
- package/dist/src/components/sidebar/sidebar.d.ts +0 -8
- package/dist/src/components/sidebar/sidebar.js +0 -39
- package/dist/src/stores/use-theme-store.d.ts +0 -16
- package/dist/src/stores/use-theme-store.js +0 -26
- /package/dist/src/components/{endpoints → ui}/json-editor.d.ts +0 -0
package/dist/src/App.js
CHANGED
|
@@ -4,15 +4,15 @@ import { analytics } from '@/lib/analytics';
|
|
|
4
4
|
import { ReactFlowProvider } from '@xyflow/react';
|
|
5
5
|
import { File, GanttChart, Link2, LogsIcon } from 'lucide-react';
|
|
6
6
|
import { useCallback, useEffect, useMemo, useState } from 'react';
|
|
7
|
-
import { EndpointsPage } from './components/endpoints/endpoints-page';
|
|
8
7
|
import { FlowPage } from './components/flow/flow-page';
|
|
9
8
|
import { FlowTabMenuItem } from './components/flow/flow-tab-menu-item';
|
|
10
9
|
import { Header } from './components/header/header';
|
|
11
10
|
import { LogsPage } from './components/logs/logs-page';
|
|
12
11
|
import { TracesPage } from './components/observability/traces-page';
|
|
13
|
-
import { APP_SIDEBAR_CONTAINER_ID } from '
|
|
12
|
+
import { APP_SIDEBAR_CONTAINER_ID } from '@motiadev/ui';
|
|
14
13
|
import { StatesPage } from './components/states/states-page';
|
|
15
14
|
import { useTabsStore } from './stores/use-tabs-store';
|
|
15
|
+
import { EndpointsPage } from '@motiadev/plugin-endpoint';
|
|
16
16
|
var TabLocation;
|
|
17
17
|
(function (TabLocation) {
|
|
18
18
|
TabLocation["TOP"] = "top";
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { BaseEdge as BaseReactFlowEdge, EdgeLabelRenderer, getSmoothStepPath } from '@xyflow/react';
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
|
-
import { cn } from '
|
|
4
|
+
import { cn, useThemeStore } from '@motiadev/ui';
|
|
5
5
|
const labelVariants = cva('absolute pointer-events-all text-cs border p-1 px-2', {
|
|
6
6
|
variants: {
|
|
7
7
|
color: {
|
|
@@ -14,9 +14,11 @@ const labelVariants = cva('absolute pointer-events-all text-cs border p-1 px-2',
|
|
|
14
14
|
},
|
|
15
15
|
});
|
|
16
16
|
export const BaseEdge = (props) => {
|
|
17
|
+
const theme = useThemeStore((state) => state.theme);
|
|
17
18
|
const { sourceX, sourceY, targetX, targetY, sourcePosition, targetPosition, data } = props;
|
|
18
19
|
const label = data?.label;
|
|
19
20
|
const labelVariant = data?.labelVariant;
|
|
21
|
+
const virtualColor = theme === 'dark' ? 'rgb(225, 225, 225)' : 'rgb(85, 85, 85)';
|
|
20
22
|
const [edgePath, labelX, labelY] = getSmoothStepPath({
|
|
21
23
|
sourceX,
|
|
22
24
|
sourceY,
|
|
@@ -28,7 +30,7 @@ export const BaseEdge = (props) => {
|
|
|
28
30
|
offset: 10,
|
|
29
31
|
});
|
|
30
32
|
return (_jsxs(_Fragment, { children: [_jsx(BaseReactFlowEdge, { path: edgePath, style: {
|
|
31
|
-
stroke: data?.variant === 'virtual' ?
|
|
33
|
+
stroke: data?.variant === 'virtual' ? virtualColor : '#0094FF',
|
|
32
34
|
strokeWidth: 2,
|
|
33
35
|
shapeRendering: 'geometricPrecision',
|
|
34
36
|
fill: 'none',
|
|
@@ -6,6 +6,7 @@ import { FlowLoader } from './flow-loader';
|
|
|
6
6
|
import { useGetFlowState } from './hooks/use-get-flow-state';
|
|
7
7
|
import { NodeOrganizer } from './node-organizer';
|
|
8
8
|
import '@xyflow/react/dist/style.css';
|
|
9
|
+
import { BackgroundEffect } from '@motiadev/ui';
|
|
9
10
|
const edgeTypes = {
|
|
10
11
|
base: BaseEdge,
|
|
11
12
|
};
|
|
@@ -17,5 +18,5 @@ export const FlowView = ({ flow, flowConfig }) => {
|
|
|
17
18
|
if (!nodeTypes) {
|
|
18
19
|
return null;
|
|
19
20
|
}
|
|
20
|
-
return (_jsxs("div", { className: "w-full h-full relative", children: [!initialized && _jsx(FlowLoader, {}), _jsxs(ReactFlow, { minZoom: 0.1, nodes: nodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodesChange: onNodesChangeHandler, onEdgesChange: onEdgesChange, children: [_jsx(Background, { variant: BackgroundVariant.Dots, gap:
|
|
21
|
+
return (_jsxs("div", { className: "w-full h-full relative", children: [!initialized && _jsx(FlowLoader, {}), _jsxs(ReactFlow, { minZoom: 0.1, nodes: nodes, edges: edges, nodeTypes: nodeTypes, edgeTypes: edgeTypes, onNodesChange: onNodesChangeHandler, onEdgesChange: onEdgesChange, className: "isolate", children: [_jsx(BackgroundEffect, {}), _jsx(Background, { variant: BackgroundVariant.Dots, gap: 20, size: 1 }), _jsx(NodeOrganizer, { onInitialized: onInitialized, nodes: nodes, edges: edges })] })] }));
|
|
21
22
|
};
|
|
@@ -2,7 +2,7 @@ import { useCallback } from 'react';
|
|
|
2
2
|
export const useSaveWorkflowConfig = () => {
|
|
3
3
|
return useCallback(async (body) => {
|
|
4
4
|
try {
|
|
5
|
-
const response = await fetch(`/flows/${body.id}/config`, {
|
|
5
|
+
const response = await fetch(`/__motia/flows/${body.id}/config`, {
|
|
6
6
|
method: 'POST',
|
|
7
7
|
headers: {
|
|
8
8
|
'Content-Type': 'application/json',
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import motiaLogoDark from '@/assets/motia-dark.png';
|
|
3
3
|
import motiaLogoLight from '@/assets/motia-light.png';
|
|
4
|
-
import { useThemeStore } from '
|
|
4
|
+
import { useThemeStore } from '@motiadev/ui';
|
|
5
5
|
import { useEffect, useState } from 'react';
|
|
6
6
|
import { Tutorial } from '../tutorial/tutorial';
|
|
7
7
|
import { TutorialButton } from '../tutorial/tutorial-button';
|
|
@@ -5,7 +5,7 @@ import ReactJson from 'react18-json-view';
|
|
|
5
5
|
import 'react18-json-view/src/dark.css';
|
|
6
6
|
import 'react18-json-view/src/style.css';
|
|
7
7
|
import { LogLevelDot } from './log-level-dot';
|
|
8
|
-
import { Sidebar } from '
|
|
8
|
+
import { Sidebar } from '@motiadev/ui';
|
|
9
9
|
import { X } from 'lucide-react';
|
|
10
10
|
const defaultProps = ['id', 'msg', 'time', 'level', 'step', 'flows', 'traceId'];
|
|
11
11
|
export const LogDetail = ({ log, onClose }) => {
|
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { Table, TableBody, TableCell, TableRow } from '@/components/ui/table';
|
|
3
3
|
import { formatTimestamp } from '@/lib/utils';
|
|
4
4
|
import { useGlobalStore } from '@/stores/use-global-store';
|
|
5
5
|
import { useLogsStore } from '@/stores/use-logs-store';
|
|
6
|
+
import { Button, cn, Input } from '@motiadev/ui';
|
|
7
|
+
import { Search, Trash, X } from 'lucide-react';
|
|
6
8
|
import { useMemo, useState } from 'react';
|
|
7
9
|
import { LogDetail } from './log-detail';
|
|
8
10
|
import { LogLevelDot } from './log-level-dot';
|
|
9
|
-
import { Button, cn, Input } from '@motiadev/ui';
|
|
10
|
-
import { CircleX, Trash } from 'lucide-react';
|
|
11
11
|
export const LogsPage = () => {
|
|
12
12
|
const logs = useLogsStore((state) => state.logs);
|
|
13
13
|
const resetLogs = useLogsStore((state) => state.resetLogs);
|
|
@@ -22,7 +22,7 @@ export const LogsPage = () => {
|
|
|
22
22
|
log.step.toLowerCase().includes(search.toLowerCase()));
|
|
23
23
|
});
|
|
24
24
|
}, [logs, search]);
|
|
25
|
-
return (_jsxs("div", { className: "h-full
|
|
25
|
+
return (_jsxs(_Fragment, { children: [_jsxs("div", { className: "grid grid-rows-[auto_1fr] h-full", "data-testid": "logs-container", children: [_jsxs("div", { className: "flex p-2 border-b gap-2", "data-testid": "logs-search-container", children: [_jsxs("div", { className: "flex-1 relative", children: [_jsx(Input, { variant: "shade", value: search, onChange: (e) => setSearch(e.target.value), className: "px-9 font-medium", placeholder: "Search by Trace ID or Message" }), _jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50" }), _jsx(X, { className: "cursor-pointer absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50 hover:text-muted-foreground", onClick: () => setSearch('') })] }), _jsxs(Button, { variant: "default", onClick: resetLogs, className: "h-[34px]", children: [_jsx(Trash, {}), " Clear"] })] }), _jsx(Table, { children: _jsx(TableBody, { className: "font-mono font-medium", children: filteredLogs.map((log, index) => (_jsxs(TableRow, { "data-testid": "log-row", className: cn('font-mono font-semibold cursor-pointer border-0', {
|
|
26
26
|
'bg-muted-foreground/10 hover:bg-muted-foreground/20': selectedLogId === log.id,
|
|
27
27
|
'hover:bg-muted-foreground/10': selectedLogId !== log.id,
|
|
28
28
|
}), onClick: () => selectLogId(log.id), children: [_jsxs(TableCell, { "data-testid": `time-${index}`, className: "whitespace-nowrap flex items-center gap-2 text-muted-foreground", children: [_jsx(LogLevelDot, { level: log.level }), formatTimestamp(log.time)] }), _jsx(TableCell, { "data-testid": `trace-${log.traceId}`, className: "whitespace-nowrap cursor-pointer hover:text-primary text-muted-foreground", onClick: () => setSearch(log.traceId), children: log.traceId }), _jsx(TableCell, { "data-testid": `step-${index}`, "aria-label": log.step, className: "whitespace-nowrap", children: log.step }), _jsx(TableCell, { "data-testid": `msg-${index}`, "aria-label": log.msg, className: "whitespace-nowrap max-w-[500px] truncate w-full", children: log.msg })] }, index))) }) })] }), _jsx(LogDetail, { log: selectedLog, onClose: () => selectLogId(undefined) })] }));
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Sidebar } from '
|
|
3
|
-
import { Badge } from '@motiadev/ui';
|
|
2
|
+
import { Sidebar, Badge } from '@motiadev/ui';
|
|
4
3
|
import { formatDuration } from '@/lib/utils';
|
|
5
4
|
import { X } from 'lucide-react';
|
|
6
5
|
import { memo } from 'react';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from '
|
|
2
|
+
import { cn } from '@motiadev/ui';
|
|
3
3
|
export const TraceItem = ({ trace, group, groupEndTime, onExpand }) => {
|
|
4
4
|
return (_jsxs("div", { className: "flex hover:bg-muted-foreground/10 relative cursor-pointer", onClick: () => onExpand(trace.id), "data-testid": "trace-timeline-item", children: [_jsx("div", { className: "flex items-center min-w-[200px] max-w-[200px] h-[32px] max-h-[32px] py-4 px-2 text-sm font-semibold text-foreground truncate sticky left-0 bg-card z-9", children: trace.name }), _jsx("div", { className: "flex w-full flex-row items-center hover:bg-muted/50 rounded-md", children: _jsx("div", { className: "relative w-full h-[32px] flex items-center", children: _jsx("div", { className: cn('h-[24px] rounded-[4px] hover:opacity-80 transition-all duration-200', {
|
|
5
5
|
'bg-[repeating-linear-gradient(140deg,#BEFE29,#BEFE29_8px,#ABE625_8px,#ABE625_16px)]': trace.status === 'running',
|
|
@@ -25,5 +25,5 @@ export const TraceTimeline = memo(({ groupId }) => {
|
|
|
25
25
|
};
|
|
26
26
|
if (!group)
|
|
27
27
|
return null;
|
|
28
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex flex-col flex-1 overflow-x-auto h-full relative", children: _jsxs("div", { className: "flex flex-col items-center min-w-full sticky top-0", style: { width: `${zoom * 1000}px` }, children: [_jsxs("div", { className: "flex flex-1 w-full sticky top-0 bg-background z-10", children: [_jsxs("div", { className: "w-full min-h-[37px] h-[37px] min-w-[200px] max-w-[200px] flex items-center justify-center gap-2 sticky left-0 top-0 bg-card", children: [_jsx(Button, { variant: "icon", size: "sm", className: "px-2", onClick: zoomMinus, children: _jsx(Minus, { className: "w-4 h-4 cursor-pointer" }) }), _jsxs("span", { className: "text-sm font-bold text-muted-foreground", children: [Math.floor(zoom * 100), "%"] }), _jsx(Button, { variant: "icon", size: "sm", className: "px-2", onClick: () => setZoom(zoom + 0.1), children: _jsx(Plus, { className: "w-4 h-4 cursor-pointer" }) })] }), _jsxs("div", { className: "flex justify-between font-mono p-2 w-full text-xs text-muted-foreground bg-card", children: [_jsx("span", { children: "0ms" }), _jsxs("span", { children: [Math.floor((endTime - group.startTime) * 0.25), "ms"] }), _jsxs("span", { children: [Math.floor((endTime - group.startTime) * 0.5), "ms"] }), _jsxs("span", { children: [Math.floor((endTime - group.startTime) * 0.75), "ms"] }), _jsxs("span", { children: [Math.floor(endTime - group.startTime), "ms"] }), _jsxs("div", { className: "absolute bottom-[-4px] w-full flex justify-between", children: [_jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" })] })] })] }), _jsx("div", { className: "flex flex-col w-full h-full", children: data?.map((trace) => (_jsx(TraceItem, { trace: trace, group: group, groupEndTime: endTime, onExpand: selectTraceId }, trace.id))) })] }) }), selectedTrace && _jsx(TraceItemDetail, { trace: selectedTrace, onClose: () => selectTraceId(undefined) })] }));
|
|
28
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { className: "flex flex-col flex-1 overflow-x-auto h-full relative", children: _jsxs("div", { className: "flex flex-col items-center min-w-full sticky top-0", style: { width: `${zoom * 1000}px` }, children: [_jsxs("div", { className: "flex flex-1 w-full sticky top-0 bg-background z-10", children: [_jsxs("div", { className: "w-full min-h-[37px] h-[37px] min-w-[200px] max-w-[200px] flex items-center justify-center gap-2 sticky left-0 top-0 bg-card backdrop-blur-[4px] backdrop-filter", children: [_jsx(Button, { variant: "icon", size: "sm", className: "px-2", onClick: zoomMinus, children: _jsx(Minus, { className: "w-4 h-4 cursor-pointer" }) }), _jsxs("span", { className: "text-sm font-bold text-muted-foreground", children: [Math.floor(zoom * 100), "%"] }), _jsx(Button, { variant: "icon", size: "sm", className: "px-2", onClick: () => setZoom(zoom + 0.1), children: _jsx(Plus, { className: "w-4 h-4 cursor-pointer" }) })] }), _jsxs("div", { className: "flex justify-between font-mono p-2 w-full text-xs text-muted-foreground bg-card", children: [_jsx("span", { children: "0ms" }), _jsxs("span", { children: [Math.floor((endTime - group.startTime) * 0.25), "ms"] }), _jsxs("span", { children: [Math.floor((endTime - group.startTime) * 0.5), "ms"] }), _jsxs("span", { children: [Math.floor((endTime - group.startTime) * 0.75), "ms"] }), _jsxs("span", { children: [Math.floor(endTime - group.startTime), "ms"] }), _jsxs("div", { className: "absolute bottom-[-4px] w-full flex justify-between", children: [_jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" }), _jsx("span", { className: "w-[1px] h-full bg-blue-500" })] })] })] }), _jsx("div", { className: "flex flex-col w-full h-full", children: data?.map((trace) => (_jsx(TraceItem, { trace: trace, group: group, groupEndTime: endTime, onExpand: selectTraceId }, trace.id))) })] }) }), selectedTrace && _jsx(TraceItemDetail, { trace: selectedTrace, onClose: () => selectTraceId(undefined) })] }));
|
|
29
29
|
});
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from '
|
|
2
|
+
import { cn } from '@motiadev/ui';
|
|
3
3
|
import { formatDistanceToNow } from 'date-fns';
|
|
4
4
|
import { memo } from 'react';
|
|
5
5
|
import { TraceStatusBadge } from './trace-status';
|
|
@@ -3,19 +3,31 @@ import { TraceTimeline } from '@/components/observability/trace-timeline';
|
|
|
3
3
|
import { useStreamGroup } from '@motiadev/stream-client-react';
|
|
4
4
|
import { TracesGroups } from '@/components/observability/traces-groups';
|
|
5
5
|
import { useGlobalStore } from '../../stores/use-global-store';
|
|
6
|
-
import { useEffect } from 'react';
|
|
6
|
+
import { useEffect, useMemo, useState } from 'react';
|
|
7
|
+
import { Button, cn, Input } from '@motiadev/ui';
|
|
8
|
+
import { Search, Trash, X } from 'lucide-react';
|
|
7
9
|
export const TracesPage = () => {
|
|
8
10
|
const selectedGroupId = useGlobalStore((state) => state.selectedTraceGroupId);
|
|
9
11
|
const selectTraceGroupId = useGlobalStore((state) => state.selectTraceGroupId);
|
|
10
12
|
const { data } = useStreamGroup({ streamName: 'motia-trace-group', groupId: 'default' });
|
|
11
13
|
const handleGroupSelect = (group) => selectTraceGroupId(group.id);
|
|
14
|
+
const [search, setSearch] = useState('');
|
|
15
|
+
const clearTraces = () => fetch('/__motia/trace/clear', { method: 'POST' });
|
|
16
|
+
const traceGroups = useMemo(() => data?.filter((group) => group.name.toLowerCase().includes(search.toLowerCase()) ||
|
|
17
|
+
group.id.toLowerCase().includes(search.toLowerCase())), [data, search]);
|
|
12
18
|
useEffect(() => {
|
|
13
|
-
if (
|
|
14
|
-
const group =
|
|
19
|
+
if (traceGroups && traceGroups.length > 0) {
|
|
20
|
+
const group = traceGroups[traceGroups.length - 1];
|
|
15
21
|
if (group && group.status === 'running' && group.id !== selectedGroupId) {
|
|
16
22
|
selectTraceGroupId(group.id);
|
|
17
23
|
}
|
|
18
24
|
}
|
|
19
|
-
|
|
20
|
-
|
|
25
|
+
else if (selectedGroupId) {
|
|
26
|
+
selectTraceGroupId(undefined);
|
|
27
|
+
}
|
|
28
|
+
}, [traceGroups]);
|
|
29
|
+
return (_jsxs("div", { className: "grid grid-rows-[auto_1fr] h-full", children: [_jsxs("div", { className: "flex p-2 border-b gap-2", "data-testid": "logs-search-container", children: [_jsxs("div", { className: "flex-1 relative", children: [_jsx(Input, { variant: "shade", value: search, onChange: (e) => setSearch(e.target.value), className: "px-9 font-medium", placeholder: "Search by Trace ID or Step Name" }), _jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50" }), _jsx(X, { className: cn('cursor-pointer absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50 hover:text-muted-foreground', {
|
|
30
|
+
visible: search !== '',
|
|
31
|
+
invisible: search === '',
|
|
32
|
+
}), onClick: () => setSearch('') })] }), _jsxs(Button, { variant: "default", onClick: clearTraces, className: "h-[34px]", children: [_jsx(Trash, {}), " Clear"] })] }), _jsxs("div", { className: "grid grid-cols-[300px_1fr] overflow-hidden", children: [_jsx("div", { className: "w-[300px] border-r border-border overflow-auto h-full", "data-testid": "traces-container", children: _jsx(TracesGroups, { groups: traceGroups, selectedGroupId: selectedGroupId, onGroupSelect: handleGroupSelect }) }), _jsxs("div", { className: "overflow-auto", "data-testid": "trace-details", children: [selectedGroupId && _jsx(TraceTimeline, { groupId: selectedGroupId }), !selectedGroupId && (_jsx("div", { className: "flex items-center justify-center h-full text-muted-foreground", children: "Select a trace or trace group to view the timeline" }))] })] })] }));
|
|
21
33
|
};
|
|
@@ -4,4 +4,10 @@ export interface StateItem {
|
|
|
4
4
|
type: 'string' | 'number' | 'boolean' | 'object' | 'array' | 'null';
|
|
5
5
|
value: string | number | boolean | object | unknown[] | null;
|
|
6
6
|
}
|
|
7
|
-
|
|
7
|
+
type Output = {
|
|
8
|
+
items: StateItem[];
|
|
9
|
+
deleteItems: (ids: string[]) => void;
|
|
10
|
+
refetch: () => void;
|
|
11
|
+
};
|
|
12
|
+
export declare const useGetStateItems: () => Output;
|
|
13
|
+
export {};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useEffect, useState } from 'react';
|
|
1
|
+
import { useEffect, useState, useCallback } from 'react';
|
|
2
2
|
export const useGetStateItems = () => {
|
|
3
3
|
const [items, setItems] = useState([]);
|
|
4
|
-
|
|
4
|
+
const refetch = useCallback(() => {
|
|
5
5
|
fetch('/__motia/state')
|
|
6
6
|
.then(async (res) => {
|
|
7
7
|
if (res.ok) {
|
|
@@ -14,5 +14,13 @@ export const useGetStateItems = () => {
|
|
|
14
14
|
.then(setItems)
|
|
15
15
|
.catch((err) => console.error(err));
|
|
16
16
|
}, []);
|
|
17
|
-
|
|
17
|
+
const deleteItems = (ids) => {
|
|
18
|
+
fetch('/__motia/state/delete', {
|
|
19
|
+
method: 'POST',
|
|
20
|
+
headers: { 'Content-Type': 'application/json' },
|
|
21
|
+
body: JSON.stringify({ ids }),
|
|
22
|
+
}).then(() => refetch());
|
|
23
|
+
};
|
|
24
|
+
useEffect(refetch, [refetch]);
|
|
25
|
+
return { items, deleteItems, refetch };
|
|
18
26
|
};
|
|
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { Button } from '@motiadev/ui';
|
|
3
3
|
import { AlertCircle, Check, Loader2, Save } from 'lucide-react';
|
|
4
4
|
import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
|
|
5
|
-
import { JsonEditor } from '../
|
|
5
|
+
import { JsonEditor } from '../ui/json-editor';
|
|
6
6
|
export const StateEditor = ({ state }) => {
|
|
7
7
|
const [isRequestLoading, setIsRequestLoading] = useState(false);
|
|
8
8
|
const [isValid, setIsValid] = useState(true);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Sidebar } from '
|
|
2
|
+
import { Sidebar } from '@motiadev/ui';
|
|
3
3
|
import { X } from 'lucide-react';
|
|
4
4
|
import { StateDetails } from './state-details';
|
|
5
5
|
import { StateEditor } from './state-editor';
|
|
@@ -1,18 +1,56 @@
|
|
|
1
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import { useGlobalStore } from '@/stores/use-global-store';
|
|
3
|
-
import { cn } from '@motiadev/ui';
|
|
4
|
-
import {
|
|
3
|
+
import { Checkbox, Button, cn, Input } from '@motiadev/ui';
|
|
4
|
+
import { RefreshCw, Search, Trash, X } from 'lucide-react';
|
|
5
|
+
import { useMemo, useState } from 'react';
|
|
5
6
|
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../ui/table';
|
|
6
7
|
import { useGetStateItems } from './hooks/states-hooks';
|
|
7
8
|
import { StateSidebar } from './state-sidebar';
|
|
8
9
|
export const StatesPage = () => {
|
|
9
10
|
const selectedStateId = useGlobalStore((state) => state.selectedStateId);
|
|
10
11
|
const selectStateId = useGlobalStore((state) => state.selectStateId);
|
|
11
|
-
const items = useGetStateItems();
|
|
12
|
-
const
|
|
12
|
+
const { items, deleteItems, refetch } = useGetStateItems();
|
|
13
|
+
const [search, setSearch] = useState('');
|
|
14
|
+
const filteredItems = useMemo(() => {
|
|
15
|
+
return items.filter((item) => {
|
|
16
|
+
return (item.groupId.toLowerCase().includes(search.toLowerCase()) ||
|
|
17
|
+
item.key.toLowerCase().includes(search.toLowerCase()));
|
|
18
|
+
});
|
|
19
|
+
}, [items, search]);
|
|
20
|
+
const selectedItem = useMemo(() => (selectedStateId ? filteredItems.find((item) => `${item.groupId}:${item.key}` === selectedStateId) : null), [filteredItems, selectedStateId]);
|
|
21
|
+
const [checkedItems, setCheckedItems] = useState(new Set());
|
|
13
22
|
const handleRowClick = (item) => selectStateId(`${item.groupId}:${item.key}`);
|
|
14
23
|
const onClose = () => selectStateId(undefined);
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
24
|
+
const deleteStates = () => {
|
|
25
|
+
deleteItems(Array.from(checkedItems));
|
|
26
|
+
setCheckedItems(new Set());
|
|
27
|
+
};
|
|
28
|
+
const handleCheckboxChange = (item) => {
|
|
29
|
+
const isChecked = checkedItems.has(`${item.groupId}:${item.key}`);
|
|
30
|
+
setCheckedItems((prev) => {
|
|
31
|
+
const newSet = new Set(prev);
|
|
32
|
+
if (isChecked) {
|
|
33
|
+
newSet.delete(`${item.groupId}:${item.key}`);
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
newSet.add(`${item.groupId}:${item.key}`);
|
|
37
|
+
}
|
|
38
|
+
return newSet;
|
|
39
|
+
});
|
|
40
|
+
};
|
|
41
|
+
const toggleSelectAll = (checked) => {
|
|
42
|
+
setCheckedItems((prev) => {
|
|
43
|
+
const newSet = new Set(prev);
|
|
44
|
+
if (checked) {
|
|
45
|
+
filteredItems.forEach((item) => newSet.add(`${item.groupId}:${item.key}`));
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
filteredItems.forEach((item) => newSet.delete(`${item.groupId}:${item.key}`));
|
|
49
|
+
}
|
|
50
|
+
return newSet;
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
return (_jsxs(_Fragment, { children: [selectedItem && _jsx(StateSidebar, { state: selectedItem, onClose: onClose }), _jsxs("div", { className: "grid grid-rows-[auto_1fr] h-full", "data-testid": "states-container", children: [_jsxs("div", { className: "flex p-2 border-b gap-2", "data-testid": "logs-search-container", children: [_jsxs("div", { className: "flex-1 relative", children: [_jsx(Input, { variant: "shade", value: search, onChange: (e) => setSearch(e.target.value), className: "px-9 font-medium", placeholder: "Search by Group ID or Key" }), _jsx(Search, { className: "absolute left-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50" }), _jsx(X, { className: "cursor-pointer absolute right-3 top-1/2 -translate-y-1/2 w-4 h-4 text-muted-foreground/50 hover:text-muted-foreground", onClick: () => setSearch('') })] }), _jsxs(Button, { variant: "default", className: "h-[34px]", disabled: checkedItems.size === 0, onClick: deleteStates, children: [_jsx(Trash, {}), " Delete"] }), _jsx(Button, { variant: "default", className: "h-[34px]", onClick: refetch, children: _jsx(RefreshCw, { className: "w-4 h-4 text-muted-foreground" }) })] }), _jsxs(Table, { children: [_jsx(TableHeader, { className: "sticky top-0 bg-background/20 backdrop-blur-sm", children: _jsxs(TableRow, { children: [_jsx(TableHead, { children: _jsx(Checkbox, { onClick: (evt) => evt.stopPropagation(), onCheckedChange: toggleSelectAll }) }), _jsx(TableHead, { className: "rounded-0", children: "Group ID" }), _jsx(TableHead, { children: "Key" }), _jsx(TableHead, { children: "Type" })] }) }), _jsx(TableBody, { children: filteredItems.map((item) => (_jsxs(TableRow, { "data-testid": `item-${item}`, onClick: () => handleRowClick(item), className: cn('font-mono font-semibold cursor-pointer border-0', selectedItem === item
|
|
54
|
+
? 'bg-muted-foreground/10 hover:bg-muted-foreground/20'
|
|
55
|
+
: 'hover:bg-muted-foreground/10'), children: [_jsx(TableCell, { onClick: (evt) => evt.stopPropagation(), children: _jsx(Checkbox, { checked: checkedItems.has(`${item.groupId}:${item.key}`), onClick: () => handleCheckboxChange(item) }) }), _jsx(TableCell, { className: "hover:bg-transparent", children: item.groupId }), _jsx(TableCell, { className: "hover:bg-transparent", children: item.key }), _jsx(TableCell, { className: "hover:bg-transparent", children: item.type })] }, `${item.groupId}:${item.key}`))) })] })] })] }));
|
|
18
56
|
};
|
|
@@ -9,8 +9,13 @@ export declare const workbenchXPath: {
|
|
|
9
9
|
node: (stepId: string) => string;
|
|
10
10
|
};
|
|
11
11
|
endpoints: {
|
|
12
|
+
endpointsList: string;
|
|
12
13
|
endpoint: (method: string, path: string) => string;
|
|
13
14
|
callPanel: string;
|
|
15
|
+
specButton: string;
|
|
16
|
+
bodyTab: string;
|
|
17
|
+
headersTab: string;
|
|
18
|
+
paramsTab: string;
|
|
14
19
|
callTab: string;
|
|
15
20
|
response: string;
|
|
16
21
|
playButton: string;
|
|
@@ -9,9 +9,14 @@ export const workbenchXPath = {
|
|
|
9
9
|
node: (stepId) => `//div[@data-testid="node-${stepId}"]`,
|
|
10
10
|
},
|
|
11
11
|
endpoints: {
|
|
12
|
+
endpointsList: '//div[@data-testid="endpoints-list"]',
|
|
12
13
|
endpoint: (method, path) => `//div[@data-testid="endpoint-${method}-${path}"]`,
|
|
13
|
-
callPanel: '//div[@data-testid="endpoint-
|
|
14
|
-
|
|
14
|
+
callPanel: '//div[@data-testid="endpoint-details-panel"]',
|
|
15
|
+
specButton: '//button[@data-testid="endpoint-spec-button"]',
|
|
16
|
+
bodyTab: '//button[@data-testid="endpoint-body-tab"]',
|
|
17
|
+
headersTab: '//button[@data-testid="endpoint-headers-tab"]',
|
|
18
|
+
paramsTab: '//button[@data-testid="endpoint-params-tab"]',
|
|
19
|
+
callTab: '//button[@data-testid="endpoint-body-tab"]', // deprecated
|
|
15
20
|
response: '//div[@data-testid="endpoint-response-container"]',
|
|
16
21
|
playButton: '//button[@data-testid="endpoint-play-button"]',
|
|
17
22
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { forwardRef, useEffect } from 'react';
|
|
3
|
+
import { BackgroundEffect } from '@motiadev/ui';
|
|
3
4
|
export const TutorialStep = forwardRef(({ step, totalSteps, title, description, link, image, onNext, onClose }, ref) => {
|
|
4
5
|
useEffect(() => {
|
|
5
6
|
const handleKeyDown = (e) => {
|
|
@@ -13,6 +14,6 @@ export const TutorialStep = forwardRef(({ step, totalSteps, title, description,
|
|
|
13
14
|
window.addEventListener('keydown', handleKeyDown);
|
|
14
15
|
return () => window.removeEventListener('keydown', handleKeyDown);
|
|
15
16
|
}, [onClose, onNext]);
|
|
16
|
-
return (_jsxs("div", { ref: ref, className: "driver-popover", children: [image && (_jsx("img", { src: image.src, alt: "Step visual", className: "driver-popover-image object-cover", style: { height: image.height, width: '100%' } })), _jsx("div", { className: "driver-popover-title", children: _jsx("h2", { className: "popover-title", children: title }) }), _jsx("div", { className: "driver-popover-description", children: description }), link && (_jsx("a", { href: link, target: "_blank", className: "text-foreground text-xs font-semibold px-4 hover:underline", children: "Learn more" })), _jsxs("div", { className: "driver-popover-footer flex items-center justify-between", children: [_jsxs("div", { className: "text-sm text-muted-foreground font-semibold", children: [step, " ", _jsx("span", { className: "text-foreground", children: "/" }), " ", totalSteps] }), _jsx("div", { className: "driver-popover-navigation-btns driver-popover-navigation-btns-hint flex gap-2", children: _jsx("button", { className: "driver-popover-next-btn", onClick: onNext, children: step < totalSteps ? 'Continue' : 'Finish' }) })] }), step < totalSteps && (_jsx("div", { className: "tutorial-opt-out-container", children: _jsx("button", { className: "tutorial-opt-out-button", onClick: onClose, children: "Close" }) }))] }));
|
|
17
|
+
return (_jsxs("div", { ref: ref, className: "driver-popover ", children: [image && (_jsx("img", { src: image.src, alt: "Step visual", className: "driver-popover-image object-cover", style: { height: image.height, width: '100%' } })), _jsxs("div", { className: "isolate relative", children: [_jsx(BackgroundEffect, {}), _jsx("div", { className: "driver-popover-title", children: _jsx("h2", { className: "popover-title", children: title }) }), _jsx("div", { className: "driver-popover-description", children: description }), link && (_jsx("a", { href: link, target: "_blank", className: "text-foreground text-xs font-semibold px-4 hover:underline", children: "Learn more" })), _jsxs("div", { className: "driver-popover-footer flex items-center justify-between", children: [_jsxs("div", { className: "text-sm text-muted-foreground font-semibold", children: [step, " ", _jsx("span", { className: "text-foreground", children: "/" }), " ", totalSteps] }), _jsx("div", { className: "driver-popover-navigation-btns driver-popover-navigation-btns-hint flex gap-2", children: _jsx("button", { className: "driver-popover-next-btn", onClick: onNext, children: step < totalSteps ? 'Continue' : 'Finish' }) })] }), step < totalSteps && (_jsx("div", { className: "tutorial-opt-out-container", children: _jsx("button", { className: "tutorial-opt-out-button", onClick: onClose, children: "Close" }) }))] })] }));
|
|
17
18
|
});
|
|
18
19
|
TutorialStep.displayName = 'TutorialStep';
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { useThemeStore } from '
|
|
2
|
+
import { useThemeStore } from '@motiadev/ui';
|
|
3
3
|
import Editor, { useMonaco } from '@monaco-editor/react';
|
|
4
4
|
import { useEffect, useMemo } from 'react';
|
|
5
5
|
export const JsonEditor = ({ value, height = 300, schema, onChange, onValidate, language = 'json', readOnly = false, }) => {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import * as React from 'react';
|
|
3
|
-
import { cn } from '
|
|
3
|
+
import { cn } from '@motiadev/ui';
|
|
4
4
|
const Table = React.forwardRef(({ className, ...props }, ref) => (_jsx("div", { className: "relative w-full overflow-auto", children: _jsx("table", { ref: ref, className: cn('w-full caption-bottom text-sm', className), ...props }) })));
|
|
5
5
|
Table.displayName = 'Table';
|
|
6
6
|
const TableHeader = React.forwardRef(({ className, ...props }, ref) => _jsx("thead", { ref: ref, className: cn('[&_tr]:border-b', className), ...props }));
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { cn, useThemeStore } from '@motiadev/ui';
|
|
2
3
|
import { Moon, Sun } from 'lucide-react';
|
|
3
|
-
import { useThemeStore } from '@/stores/use-theme-store';
|
|
4
|
-
import { cn } from '@/lib/utils';
|
|
5
4
|
import { useEffect } from 'react';
|
|
6
5
|
export const ThemeToggle = () => {
|
|
7
6
|
const theme = useThemeStore((state) => state.theme);
|
package/dist/src/index.css
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
@import
|
|
2
|
-
@import
|
|
1
|
+
@import '@motiadev/plugin-endpoint/styles.css';
|
|
2
|
+
@import '@motiadev/ui/styles.css';
|
|
3
|
+
@import '@motiadev/ui/globals.css';
|
|
4
|
+
|
|
3
5
|
@import 'tw-animate-css';
|
|
4
6
|
@config "../tailwind.config.js";
|
|
5
7
|
|
|
@@ -13,12 +15,12 @@
|
|
|
13
15
|
}
|
|
14
16
|
|
|
15
17
|
.json-view {
|
|
16
|
-
background:rgba(0, 0, 0, 0.1);
|
|
18
|
+
background: rgba(0, 0, 0, 0.1);
|
|
17
19
|
}
|
|
18
20
|
|
|
19
21
|
.dark {
|
|
20
22
|
.react-flow__panel {
|
|
21
|
-
background: var(--background)
|
|
23
|
+
background: var(--background);
|
|
22
24
|
}
|
|
23
25
|
.json-view {
|
|
24
26
|
background: rgba(0, 0, 0, 0.8);
|
|
@@ -45,10 +47,12 @@
|
|
|
45
47
|
font-weight: 500;
|
|
46
48
|
}
|
|
47
49
|
|
|
48
|
-
.json-view--pair,
|
|
50
|
+
.json-view--pair,
|
|
51
|
+
.json-view--property,
|
|
52
|
+
.json-view > span {
|
|
49
53
|
line-height: 24px;
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
.json-view--property {
|
|
53
57
|
font-weight: 600;
|
|
54
|
-
}
|
|
58
|
+
}
|
package/dist/src/lib/utils.d.ts
CHANGED
package/dist/src/lib/utils.js
CHANGED
|
@@ -24,7 +24,7 @@ export const BaseNode = ({ title, variant, children, disableSourceHandle, disabl
|
|
|
24
24
|
}, [data.id, isOpen, fetchContent]);
|
|
25
25
|
return (_jsxs("div", { className: cn('p-1 rounded-lg max-w-[350px]', {
|
|
26
26
|
'bg-muted-foreground/20': isOpen,
|
|
27
|
-
}), children: [_jsx("div", { className: "rounded-lg dark:bg-[#
|
|
27
|
+
}), children: [_jsx("div", { className: "rounded-lg dark:bg-[#101010] bg-background border-1 border-muted-foreground/30 border-solid", "data-testid": `node-${title?.toLowerCase().replace(/ /g, '-')}`, children: _jsxs("div", { className: "group relative", children: [_jsx(NodeHeader, { text: title, variant: variant, className: "border-b-2 border-muted-foreground/10", children: _jsx("div", { className: "flex justify-end", children: _jsx(Button, { "data-testid": `open-code-preview-button-${title?.toLowerCase()}`, variant: "ghost", className: "h-5 p-0.5", onClick: () => setIsOpen(true), children: _jsx(ScanSearch, { className: "w-4 h-4" }) }) }) }), subtitle && _jsx("div", { className: "py-4 px-6 text-sm text-muted-foreground", children: subtitle }), children && (_jsx("div", { className: "p-2", children: _jsx("div", { className: cn('space-y-3 p-4 text-sm text-muted-foreground', {
|
|
28
28
|
'bg-card': variant !== 'noop',
|
|
29
29
|
}), children: children }) })), !disableTargetHandle && (_jsx(BaseHandle, { type: "target", position: targetPosition, onTogglePosition: toggleTargetPosition })), !disableSourceHandle && (_jsx(BaseHandle, { type: "source", position: sourcePosition, onTogglePosition: toggleSourcePosition }))] }) }), content && (_jsx(NodeSidebar, { features: features, content: content, title: title, subtitle: subtitle, variant: variant, language: language, isOpen: isOpen, onClose: () => setIsOpen(false) }))] }));
|
|
30
30
|
};
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useThemeStore } from '
|
|
2
|
+
import { useThemeStore } from '@motiadev/ui';
|
|
3
3
|
import { FeatureCard } from './feature-card';
|
|
4
4
|
import { useRef, useState } from 'react';
|
|
5
5
|
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
|
|
6
|
-
import {
|
|
6
|
+
import { oneDark, oneLight } from 'react-syntax-highlighter/dist/esm/styles/prism';
|
|
7
7
|
import { LanguageIndicator } from './language-indicator';
|
|
8
8
|
const codeTagProps = {
|
|
9
9
|
style: {
|
|
@@ -31,7 +31,7 @@ const getFirstLineNumber = (line) => {
|
|
|
31
31
|
};
|
|
32
32
|
export const CodeDisplay = ({ code, language, features }) => {
|
|
33
33
|
const theme = useThemeStore((state) => state.theme);
|
|
34
|
-
const themeStyle = theme === 'dark' ?
|
|
34
|
+
const themeStyle = theme === 'dark' ? oneDark : oneLight;
|
|
35
35
|
const [highlightedLines, setHighlightedLines] = useState([]);
|
|
36
36
|
const [selectedFeature, setSelectedFeature] = useState(null);
|
|
37
37
|
const ref = useRef(null);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from '
|
|
2
|
+
import { cn } from '@motiadev/ui';
|
|
3
3
|
export const FeatureCard = ({ feature, highlighted, onClick, onHover }) => {
|
|
4
4
|
return (_jsxs("div", { "data-feature-id": feature.id, className: cn('p-4 rounded-lg bg-card shadow-sm cursor-pointer hover:bg-card/50 border-2 border-transparent', highlighted && 'border-2 border-accent-1000 bg-accent-100'), onClick: onClick, onMouseEnter: onHover, children: [_jsx("div", { className: "text-md font-semibold text-foreground leading-tight whitespace-nowrap mb-2", children: feature.title }), _jsx("div", { className: "text-sm font-medium text-muted-foreground leading-tight", children: feature.description }), feature.link && (_jsx("div", { className: "text-sm font-medium text-muted-foreground leading-tight", children: _jsx("a", { href: feature.link, children: "Learn more" }) }))] }));
|
|
5
5
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { cn } from '
|
|
2
|
+
import { cn } from '@motiadev/ui';
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
4
|
import { CalendarClock, CircleOff, Link2, Waypoints } from 'lucide-react';
|
|
5
5
|
const baseIcon = cva('rounded-md p-2', {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import { Sidebar } from '
|
|
2
|
+
import { Sidebar } from '@motiadev/ui';
|
|
3
3
|
import { X } from 'lucide-react';
|
|
4
4
|
import { CodeDisplay } from './code-display';
|
|
5
5
|
export const NodeSidebar = ({ content, title, subtitle, language, isOpen, onClose, features, }) => {
|
|
@@ -4,15 +4,17 @@ type UseFlowStore = {
|
|
|
4
4
|
flows: string[];
|
|
5
5
|
setFlows: (flows: string[]) => void;
|
|
6
6
|
};
|
|
7
|
-
export declare const useFlowStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<UseFlowStore>, "persist"> & {
|
|
7
|
+
export declare const useFlowStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<UseFlowStore>, "setState" | "persist"> & {
|
|
8
|
+
setState(partial: UseFlowStore | Partial<UseFlowStore> | ((state: UseFlowStore) => UseFlowStore | Partial<UseFlowStore>), replace?: false | undefined): unknown;
|
|
9
|
+
setState(state: UseFlowStore | ((state: UseFlowStore) => UseFlowStore), replace: true): unknown;
|
|
8
10
|
persist: {
|
|
9
|
-
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<UseFlowStore, UseFlowStore>>) => void;
|
|
11
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<UseFlowStore, UseFlowStore, unknown>>) => void;
|
|
10
12
|
clearStorage: () => void;
|
|
11
13
|
rehydrate: () => Promise<void> | void;
|
|
12
14
|
hasHydrated: () => boolean;
|
|
13
15
|
onHydrate: (fn: (state: UseFlowStore) => void) => () => void;
|
|
14
16
|
onFinishHydration: (fn: (state: UseFlowStore) => void) => () => void;
|
|
15
|
-
getOptions: () => Partial<import("zustand/middleware").PersistOptions<UseFlowStore, UseFlowStore>>;
|
|
17
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<UseFlowStore, UseFlowStore, unknown>>;
|
|
16
18
|
};
|
|
17
19
|
}>;
|
|
18
20
|
export {};
|
|
@@ -10,15 +10,17 @@ type UseGlobalStore = {
|
|
|
10
10
|
selectedLogId?: string;
|
|
11
11
|
selectLogId: (logId?: string) => void;
|
|
12
12
|
};
|
|
13
|
-
export declare const useGlobalStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<UseGlobalStore>, "persist"> & {
|
|
13
|
+
export declare const useGlobalStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<UseGlobalStore>, "setState" | "persist"> & {
|
|
14
|
+
setState(partial: UseGlobalStore | Partial<UseGlobalStore> | ((state: UseGlobalStore) => UseGlobalStore | Partial<UseGlobalStore>), replace?: false | undefined): unknown;
|
|
15
|
+
setState(state: UseGlobalStore | ((state: UseGlobalStore) => UseGlobalStore), replace: true): unknown;
|
|
14
16
|
persist: {
|
|
15
|
-
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<UseGlobalStore, UseGlobalStore>>) => void;
|
|
17
|
+
setOptions: (options: Partial<import("zustand/middleware").PersistOptions<UseGlobalStore, UseGlobalStore, unknown>>) => void;
|
|
16
18
|
clearStorage: () => void;
|
|
17
19
|
rehydrate: () => Promise<void> | void;
|
|
18
20
|
hasHydrated: () => boolean;
|
|
19
21
|
onHydrate: (fn: (state: UseGlobalStore) => void) => () => void;
|
|
20
22
|
onFinishHydration: (fn: (state: UseGlobalStore) => void) => () => void;
|
|
21
|
-
getOptions: () => Partial<import("zustand/middleware").PersistOptions<UseGlobalStore, UseGlobalStore>>;
|
|
23
|
+
getOptions: () => Partial<import("zustand/middleware").PersistOptions<UseGlobalStore, UseGlobalStore, unknown>>;
|
|
22
24
|
};
|
|
23
25
|
}>;
|
|
24
26
|
export {};
|