@motiadev/workbench 0.13.1-beta.163-660633 → 0.13.1-beta.163-584961
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/index.d.ts +10 -189
- package/dist/index.html +1 -1
- package/dist/index.js +7 -1065
- package/dist/middleware.d.ts +8 -66
- package/dist/middleware.js +86 -694
- package/dist/motia-plugin/__tests__/generator.test.d.ts +1 -0
- package/dist/motia-plugin/__tests__/generator.test.js +97 -0
- package/dist/motia-plugin/__tests__/resolver.test.d.ts +1 -0
- package/dist/motia-plugin/__tests__/resolver.test.js +64 -0
- package/dist/motia-plugin/__tests__/validator.test.d.ts +1 -0
- package/dist/motia-plugin/__tests__/validator.test.js +59 -0
- package/dist/motia-plugin/generator.d.ts +78 -0
- package/dist/motia-plugin/{generator.ts → generator.js} +35 -37
- package/dist/motia-plugin/hmr.d.ts +22 -0
- package/dist/motia-plugin/hmr.js +100 -0
- package/dist/motia-plugin/index.d.ts +3 -0
- package/dist/motia-plugin/index.js +153 -0
- package/dist/motia-plugin/{resolver.ts → resolver.d.ts} +5 -38
- package/dist/motia-plugin/resolver.js +92 -0
- package/dist/motia-plugin/types.d.ts +169 -0
- package/dist/motia-plugin/types.js +36 -0
- package/dist/motia-plugin/{utils.ts → utils.d.ts} +4 -17
- package/dist/motia-plugin/utils.js +75 -0
- package/dist/motia-plugin/validator.d.ts +19 -0
- package/dist/motia-plugin/validator.js +163 -0
- package/dist/src/App.d.ts +2 -0
- package/dist/src/App.js +35 -0
- package/dist/src/components/NotFoundPage.d.ts +1 -0
- package/dist/src/components/NotFoundPage.js +3 -0
- package/dist/src/components/bottom-panel.d.ts +1 -0
- package/dist/src/components/bottom-panel.js +15 -0
- package/dist/src/components/flow/base-edge.d.ts +3 -0
- package/dist/src/components/flow/base-edge.js +39 -0
- package/dist/src/components/flow/flow-loader.d.ts +1 -0
- package/dist/src/components/flow/flow-loader.js +4 -0
- package/dist/src/components/flow/flow-page.d.ts +1 -0
- package/dist/src/components/flow/flow-page.js +25 -0
- package/dist/src/components/flow/flow-tab-menu-item.d.ts +1 -0
- package/dist/src/components/flow/flow-tab-menu-item.js +18 -0
- package/dist/src/components/flow/flow-view.d.ts +12 -0
- package/dist/src/components/flow/flow-view.js +22 -0
- package/dist/src/components/flow/hooks/use-get-flow-state.d.ts +10 -0
- package/dist/src/components/flow/hooks/use-get-flow-state.js +133 -0
- package/dist/src/components/flow/hooks/use-save-workflow-config.d.ts +2 -0
- package/dist/src/components/flow/hooks/use-save-workflow-config.js +22 -0
- package/dist/src/components/flow/node-organizer.d.ts +10 -0
- package/dist/src/components/flow/node-organizer.js +82 -0
- package/dist/src/components/flow/nodes/api-flow-node.d.ts +2 -0
- package/dist/src/components/flow/nodes/api-flow-node.js +5 -0
- package/dist/src/components/flow/nodes/cron-flow-node.d.ts +2 -0
- package/dist/src/components/flow/nodes/cron-flow-node.js +5 -0
- package/dist/src/components/flow/nodes/event-flow-node.d.ts +2 -0
- package/dist/src/components/flow/nodes/event-flow-node.js +5 -0
- package/dist/src/components/flow/nodes/noop-flow-node.d.ts +2 -0
- package/dist/src/components/flow/nodes/noop-flow-node.js +5 -0
- package/dist/src/components/header/deploy-button.d.ts +1 -0
- package/dist/src/components/header/deploy-button.js +28 -0
- package/dist/src/components/header/header.d.ts +2 -0
- package/dist/src/components/header/header.js +23 -0
- package/dist/src/components/root-motia.d.ts +2 -0
- package/dist/src/components/root-motia.js +7 -0
- package/dist/src/components/top-panel.d.ts +1 -0
- package/dist/src/components/top-panel.js +15 -0
- package/dist/src/components/tutorial/engine/tutorial-engine.d.ts +12 -0
- package/dist/src/components/tutorial/engine/tutorial-engine.js +36 -0
- package/dist/src/components/tutorial/engine/tutorial-types.d.ts +22 -0
- package/dist/src/components/tutorial/engine/tutorial-types.js +1 -0
- package/dist/src/components/tutorial/engine/workbench-xpath.d.ts +45 -0
- package/dist/src/components/tutorial/engine/workbench-xpath.js +45 -0
- package/dist/src/components/tutorial/hooks/tutorial-utils.d.ts +1 -0
- package/dist/src/components/tutorial/hooks/tutorial-utils.js +17 -0
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.d.ts +15 -0
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.js +183 -0
- package/dist/src/components/tutorial/hooks/use-tutorial.d.ts +5 -0
- package/dist/src/components/tutorial/hooks/use-tutorial.js +10 -0
- package/dist/src/components/tutorial/tutorial-button.d.ts +2 -0
- package/dist/src/components/tutorial/tutorial-button.js +21 -0
- package/dist/src/components/tutorial/tutorial-step.d.ts +14 -0
- package/dist/src/components/tutorial/tutorial-step.js +19 -0
- package/dist/src/components/tutorial/tutorial.css +2 -2
- package/dist/src/components/tutorial/tutorial.d.ts +2 -0
- package/dist/src/components/tutorial/tutorial.js +32 -0
- package/dist/src/components/ui/json-editor.d.ts +12 -0
- package/dist/src/components/ui/json-editor.js +35 -0
- package/dist/src/components/ui/table.d.ts +10 -0
- package/dist/src/components/ui/table.js +20 -0
- package/dist/src/components/ui/theme-toggle.d.ts +2 -0
- package/dist/src/components/ui/theme-toggle.js +19 -0
- package/dist/src/components/ui/tooltip.d.ts +6 -0
- package/dist/src/components/ui/tooltip.js +3 -0
- package/dist/src/hooks/use-debounced.d.ts +1 -0
- package/dist/src/hooks/use-debounced.js +18 -0
- package/dist/src/hooks/use-fetch-flows.d.ts +1 -0
- package/dist/src/hooks/use-fetch-flows.js +26 -0
- package/dist/src/hooks/use-mobile.d.ts +1 -0
- package/dist/src/hooks/use-mobile.js +15 -0
- package/dist/src/hooks/use-update-handle-positions.d.ts +10 -0
- package/dist/src/hooks/use-update-handle-positions.js +35 -0
- package/dist/src/index.css +5 -5
- package/dist/src/lib/__tests__/utils.test.d.ts +1 -0
- package/dist/src/lib/__tests__/utils.test.js +94 -0
- package/dist/src/lib/motia-analytics.d.ts +38 -0
- package/dist/src/lib/motia-analytics.js +132 -0
- package/dist/src/lib/plugins.d.ts +2 -0
- package/dist/src/lib/plugins.js +105 -0
- package/dist/src/lib/utils.d.ts +7 -0
- package/dist/src/lib/utils.js +34 -0
- package/dist/src/main.d.ts +2 -0
- package/dist/src/main.js +17 -0
- package/dist/src/project-view-mode.d.ts +1 -0
- package/dist/src/project-view-mode.js +20 -0
- package/dist/src/publicComponents/api-node.d.ts +5 -0
- package/dist/src/publicComponents/api-node.js +5 -0
- package/dist/src/publicComponents/base-node/base-handle.d.ts +9 -0
- package/dist/src/publicComponents/base-node/base-handle.js +8 -0
- package/dist/src/publicComponents/base-node/base-node.d.ts +15 -0
- package/dist/src/publicComponents/base-node/base-node.js +30 -0
- package/dist/src/publicComponents/base-node/code-display.d.ts +9 -0
- package/dist/src/publicComponents/base-node/code-display.js +64 -0
- package/dist/src/publicComponents/base-node/emits.d.ts +5 -0
- package/dist/src/publicComponents/base-node/emits.js +5 -0
- package/dist/src/publicComponents/base-node/feature-card.d.ts +10 -0
- package/dist/src/publicComponents/base-node/feature-card.js +5 -0
- package/dist/src/publicComponents/base-node/language-indicator.d.ts +10 -0
- package/dist/src/publicComponents/base-node/language-indicator.js +29 -0
- package/dist/src/publicComponents/base-node/node-header.d.ts +13 -0
- package/dist/src/publicComponents/base-node/node-header.js +30 -0
- package/dist/src/publicComponents/base-node/node-sidebar.d.ts +14 -0
- package/dist/src/publicComponents/base-node/node-sidebar.js +9 -0
- package/dist/src/publicComponents/base-node/subscribe.d.ts +4 -0
- package/dist/src/publicComponents/base-node/subscribe.js +4 -0
- package/dist/src/publicComponents/cron-node.d.ts +4 -0
- package/dist/src/publicComponents/cron-node.js +6 -0
- package/dist/src/publicComponents/event-node.d.ts +4 -0
- package/dist/src/publicComponents/event-node.js +5 -0
- package/dist/src/publicComponents/node-props.d.ts +21 -0
- package/dist/src/publicComponents/node-props.js +1 -0
- package/dist/src/publicComponents/noop-node.d.ts +4 -0
- package/dist/src/publicComponents/noop-node.js +5 -0
- package/dist/src/setupTests.d.ts +1 -0
- package/dist/src/setupTests.js +1 -0
- package/dist/src/stores/use-app-tabs-store.d.ts +16 -0
- package/dist/src/stores/use-app-tabs-store.js +31 -0
- package/dist/src/stores/use-flow-store.d.ts +21 -0
- package/dist/src/stores/use-flow-store.js +16 -0
- package/dist/src/stores/use-global-store.d.ts +18 -0
- package/dist/src/stores/use-global-store.js +12 -0
- package/dist/src/stores/use-motia-config-store.d.ts +12 -0
- package/dist/src/stores/use-motia-config-store.js +24 -0
- package/dist/src/stores/use-tabs-store.d.ts +19 -0
- package/dist/src/stores/use-tabs-store.js +22 -0
- package/dist/src/system-view-mode.d.ts +1 -0
- package/dist/src/system-view-mode.js +10 -0
- package/dist/src/types/endpoint.d.ts +14 -0
- package/dist/src/types/endpoint.js +1 -0
- package/dist/src/types/file.d.ts +7 -0
- package/dist/src/types/file.js +1 -0
- package/dist/src/types/flow.d.ts +115 -0
- package/dist/src/types/flow.js +1 -0
- package/dist/tsconfig.app.tsbuildinfo +1 -0
- package/dist/tsconfig.node.tsbuildinfo +1 -0
- package/package.json +51 -55
- package/dist/motia-plugin/__tests__/generator.test.ts +0 -129
- package/dist/motia-plugin/__tests__/resolver.test.ts +0 -82
- package/dist/motia-plugin/__tests__/validator.test.ts +0 -71
- package/dist/motia-plugin/hmr.ts +0 -123
- package/dist/motia-plugin/index.ts +0 -183
- package/dist/motia-plugin/types.ts +0 -198
- package/dist/motia-plugin/validator.ts +0 -197
- package/dist/src/App.tsx +0 -41
- package/dist/src/components/NotFoundPage.tsx +0 -11
- package/dist/src/components/bottom-panel.tsx +0 -39
- package/dist/src/components/flow/base-edge.tsx +0 -61
- package/dist/src/components/flow/flow-loader.tsx +0 -3
- package/dist/src/components/flow/flow-page.tsx +0 -75
- package/dist/src/components/flow/flow-tab-menu-item.tsx +0 -50
- package/dist/src/components/flow/flow-view.tsx +0 -66
- package/dist/src/components/flow/hooks/use-get-flow-state.tsx +0 -171
- package/dist/src/components/flow/hooks/use-save-workflow-config.ts +0 -25
- package/dist/src/components/flow/node-organizer.tsx +0 -103
- package/dist/src/components/flow/nodes/api-flow-node.tsx +0 -6
- package/dist/src/components/flow/nodes/cron-flow-node.tsx +0 -6
- package/dist/src/components/flow/nodes/event-flow-node.tsx +0 -6
- package/dist/src/components/flow/nodes/noop-flow-node.tsx +0 -6
- package/dist/src/components/header/deploy-button.tsx +0 -110
- package/dist/src/components/header/header.tsx +0 -39
- package/dist/src/components/root-motia.tsx +0 -10
- package/dist/src/components/top-panel.tsx +0 -40
- package/dist/src/components/tutorial/engine/tutorial-engine.ts +0 -26
- package/dist/src/components/tutorial/engine/tutorial-types.ts +0 -26
- package/dist/src/components/tutorial/engine/workbench-xpath.ts +0 -53
- package/dist/src/components/tutorial/hooks/tutorial-utils.ts +0 -26
- package/dist/src/components/tutorial/hooks/use-tutorial-engine.ts +0 -213
- package/dist/src/components/tutorial/hooks/use-tutorial.ts +0 -14
- package/dist/src/components/tutorial/tutorial-button.tsx +0 -46
- package/dist/src/components/tutorial/tutorial-step.tsx +0 -82
- package/dist/src/components/tutorial/tutorial.tsx +0 -59
- package/dist/src/components/ui/json-editor.tsx +0 -68
- package/dist/src/components/ui/table.tsx +0 -75
- package/dist/src/components/ui/theme-toggle.tsx +0 -54
- package/dist/src/components/ui/tooltip.tsx +0 -26
- package/dist/src/hooks/use-debounced.ts +0 -22
- package/dist/src/hooks/use-fetch-flows.ts +0 -33
- package/dist/src/hooks/use-mobile.ts +0 -19
- package/dist/src/hooks/use-update-handle-positions.ts +0 -42
- package/dist/src/lib/__tests__/utils.test.ts +0 -110
- package/dist/src/lib/motia-analytics.ts +0 -140
- package/dist/src/lib/plugins.tsx +0 -132
- package/dist/src/lib/utils.ts +0 -37
- package/dist/src/main.tsx +0 -30
- package/dist/src/project-view-mode.tsx +0 -32
- package/dist/src/publicComponents/api-node.tsx +0 -26
- package/dist/src/publicComponents/base-node/base-handle.tsx +0 -50
- package/dist/src/publicComponents/base-node/base-node.tsx +0 -114
- package/dist/src/publicComponents/base-node/code-display.tsx +0 -119
- package/dist/src/publicComponents/base-node/emits.tsx +0 -17
- package/dist/src/publicComponents/base-node/feature-card.tsx +0 -32
- package/dist/src/publicComponents/base-node/language-indicator.tsx +0 -131
- package/dist/src/publicComponents/base-node/node-header.tsx +0 -49
- package/dist/src/publicComponents/base-node/node-sidebar.tsx +0 -41
- package/dist/src/publicComponents/base-node/subscribe.tsx +0 -13
- package/dist/src/publicComponents/cron-node.tsx +0 -24
- package/dist/src/publicComponents/event-node.tsx +0 -20
- package/dist/src/publicComponents/node-props.tsx +0 -15
- package/dist/src/publicComponents/noop-node.tsx +0 -19
- package/dist/src/setupTests.ts +0 -1
- package/dist/src/stores/use-app-tabs-store.ts +0 -49
- package/dist/src/stores/use-flow-store.ts +0 -31
- package/dist/src/stores/use-global-store.ts +0 -24
- package/dist/src/stores/use-motia-config-store.ts +0 -36
- package/dist/src/stores/use-tabs-store.ts +0 -34
- package/dist/src/system-view-mode.tsx +0 -28
- package/dist/src/types/endpoint.ts +0 -12
- package/dist/src/types/file.ts +0 -7
- package/dist/src/types/flow.ts +0 -103
- package/eslint.config.cjs +0 -22
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import { cn, type Theme, useThemeStore } from '@motiadev/ui'
|
|
2
|
-
import { Moon, Sun } from 'lucide-react'
|
|
3
|
-
import type React from 'react'
|
|
4
|
-
import { useEffect } from 'react'
|
|
5
|
-
|
|
6
|
-
export const ThemeToggle: React.FC = () => {
|
|
7
|
-
const theme = useThemeStore((state) => state.theme)
|
|
8
|
-
const setTheme = useThemeStore((state) => state.setTheme)
|
|
9
|
-
|
|
10
|
-
const toggleTheme = () => {
|
|
11
|
-
setTheme(theme === 'light' ? 'dark' : 'light')
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
useEffect(() => {
|
|
15
|
-
const url = new URL(window.location.href)
|
|
16
|
-
const colorScheme = url.searchParams.get('color-scheme') as Theme
|
|
17
|
-
if (colorScheme) {
|
|
18
|
-
setTheme(colorScheme)
|
|
19
|
-
}
|
|
20
|
-
}, [setTheme])
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<button
|
|
24
|
-
onClick={toggleTheme}
|
|
25
|
-
className="relative flex items-center cursor-pointer w-16 h-8 border bg-muted-foreground/10 rounded-full p-1 transition-colors duration-200 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
|
26
|
-
aria-label={`Switch to ${theme === 'light' ? 'dark' : 'light'} theme`}
|
|
27
|
-
>
|
|
28
|
-
<div
|
|
29
|
-
className={cn(
|
|
30
|
-
'absolute w-6 h-6 bg-background border border-border rounded-full shadow-sm transition-transform duration-200 ease-in-out',
|
|
31
|
-
theme === 'dark' ? 'translate-x-8' : 'translate-x-0',
|
|
32
|
-
)}
|
|
33
|
-
/>
|
|
34
|
-
|
|
35
|
-
<div className="flex items-center justify-center w-6 h-6 z-10">
|
|
36
|
-
<Sun
|
|
37
|
-
className={cn(
|
|
38
|
-
'h-3.5 w-3.5 transition-colors duration-200',
|
|
39
|
-
theme === 'light' ? 'text-foreground' : 'text-muted-foreground',
|
|
40
|
-
)}
|
|
41
|
-
/>
|
|
42
|
-
</div>
|
|
43
|
-
|
|
44
|
-
<div className="flex items-center justify-center w-6 h-6 z-10 ml-2">
|
|
45
|
-
<Moon
|
|
46
|
-
className={cn(
|
|
47
|
-
'h-3.5 w-3.5 transition-colors duration-200',
|
|
48
|
-
theme === 'dark' ? 'text-foreground' : 'text-muted-foreground',
|
|
49
|
-
)}
|
|
50
|
-
/>
|
|
51
|
-
</div>
|
|
52
|
-
</button>
|
|
53
|
-
)
|
|
54
|
-
}
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
import * as TooltipPrimitive from '@radix-ui/react-tooltip'
|
|
2
|
-
import type { ReactNode } from 'react'
|
|
3
|
-
|
|
4
|
-
export const Tooltip = ({
|
|
5
|
-
children,
|
|
6
|
-
content,
|
|
7
|
-
disabled,
|
|
8
|
-
}: {
|
|
9
|
-
children: ReactNode
|
|
10
|
-
content: string | ReactNode
|
|
11
|
-
disabled?: boolean
|
|
12
|
-
}) => (
|
|
13
|
-
<TooltipPrimitive.Provider disableHoverableContent={disabled}>
|
|
14
|
-
<TooltipPrimitive.Root>
|
|
15
|
-
<TooltipPrimitive.Trigger asChild>{children}</TooltipPrimitive.Trigger>
|
|
16
|
-
<TooltipPrimitive.Portal>
|
|
17
|
-
<TooltipPrimitive.Content className="TooltipContent" side="bottom">
|
|
18
|
-
<div className="p-2 bg-background text-popover-foreground text-sm rounded-lg border border-light-800">
|
|
19
|
-
{content}
|
|
20
|
-
</div>
|
|
21
|
-
<TooltipPrimitive.Arrow className="TooltipArrow" />
|
|
22
|
-
</TooltipPrimitive.Content>
|
|
23
|
-
</TooltipPrimitive.Portal>
|
|
24
|
-
</TooltipPrimitive.Root>
|
|
25
|
-
</TooltipPrimitive.Provider>
|
|
26
|
-
)
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
import { useCallback, useEffect, useRef } from 'react'
|
|
2
|
-
|
|
3
|
-
export const useDebounced = (fn: () => void, delay = 500) => {
|
|
4
|
-
const saveTimeoutRef = useRef<NodeJS.Timeout>(null)
|
|
5
|
-
|
|
6
|
-
const debouncedFn = useCallback(() => {
|
|
7
|
-
if (saveTimeoutRef.current) {
|
|
8
|
-
clearTimeout(saveTimeoutRef.current)
|
|
9
|
-
}
|
|
10
|
-
saveTimeoutRef.current = setTimeout(fn, delay)
|
|
11
|
-
}, [fn, delay])
|
|
12
|
-
|
|
13
|
-
useEffect(() => {
|
|
14
|
-
return () => {
|
|
15
|
-
if (saveTimeoutRef.current) {
|
|
16
|
-
clearTimeout(saveTimeoutRef.current)
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}, [])
|
|
20
|
-
|
|
21
|
-
return debouncedFn
|
|
22
|
-
}
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { useStreamGroup } from '@motiadev/stream-client-react'
|
|
2
|
-
import { useEffect } from 'react'
|
|
3
|
-
import { useFlowStore } from '../stores/use-flow-store'
|
|
4
|
-
import type { FlowResponse } from '../types/flow'
|
|
5
|
-
|
|
6
|
-
const streamGroupArgs = { streamName: '__motia.flows', groupId: 'default' }
|
|
7
|
-
|
|
8
|
-
export const useFetchFlows = () => {
|
|
9
|
-
const setFlows = useFlowStore((state) => state.setFlows)
|
|
10
|
-
const selectFlowId = useFlowStore((state) => state.selectFlowId)
|
|
11
|
-
const clearSelectedFlowId = useFlowStore((state) => state.clearSelectedFlowId)
|
|
12
|
-
const selectedFlowId = useFlowStore((state) => state.selectedFlowId)
|
|
13
|
-
|
|
14
|
-
const { data: flows } = useStreamGroup<FlowResponse>(streamGroupArgs)
|
|
15
|
-
|
|
16
|
-
useEffect(() => {
|
|
17
|
-
if (flows) setFlows(flows.map((flow) => flow.id))
|
|
18
|
-
}, [flows, setFlows])
|
|
19
|
-
|
|
20
|
-
useEffect(() => {
|
|
21
|
-
const hasFlows = flows.length > 0
|
|
22
|
-
const isSelectedFlowValid = selectedFlowId && flows.some((flow) => flow.id === selectedFlowId)
|
|
23
|
-
|
|
24
|
-
if (!hasFlows && selectedFlowId) {
|
|
25
|
-
clearSelectedFlowId()
|
|
26
|
-
return
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
if (hasFlows && (!selectedFlowId || !isSelectedFlowValid)) {
|
|
30
|
-
selectFlowId(flows[0].id)
|
|
31
|
-
}
|
|
32
|
-
}, [flows, selectedFlowId, selectFlowId, clearSelectedFlowId])
|
|
33
|
-
}
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
import * as React from 'react'
|
|
2
|
-
|
|
3
|
-
const MOBILE_BREAKPOINT = 768
|
|
4
|
-
|
|
5
|
-
export function useIsMobile() {
|
|
6
|
-
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined)
|
|
7
|
-
|
|
8
|
-
React.useEffect(() => {
|
|
9
|
-
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`)
|
|
10
|
-
const onChange = () => {
|
|
11
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
12
|
-
}
|
|
13
|
-
mql.addEventListener('change', onChange)
|
|
14
|
-
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT)
|
|
15
|
-
return () => mql.removeEventListener('change', onChange)
|
|
16
|
-
}, [])
|
|
17
|
-
|
|
18
|
-
return !!isMobile
|
|
19
|
-
}
|
|
@@ -1,42 +0,0 @@
|
|
|
1
|
-
import { Position, useReactFlow, useUpdateNodeInternals } from '@xyflow/react'
|
|
2
|
-
import type { BaseNodeProps } from '../publicComponents/node-props'
|
|
3
|
-
|
|
4
|
-
export const useHandlePositions = (data: BaseNodeProps) => {
|
|
5
|
-
const reactFlow = useReactFlow()
|
|
6
|
-
const updateNodeInternals = useUpdateNodeInternals()
|
|
7
|
-
const sourcePosition = data.nodeConfig?.sourceHandlePosition === 'bottom' ? Position.Bottom : Position.Right
|
|
8
|
-
const targetPosition = data.nodeConfig?.targetHandlePosition === 'top' ? Position.Top : Position.Left
|
|
9
|
-
|
|
10
|
-
const updateSourcePosition = (position: 'bottom' | 'right') => {
|
|
11
|
-
reactFlow.updateNode(data.id, {
|
|
12
|
-
data: { ...data, nodeConfig: { ...data.nodeConfig, sourceHandlePosition: position } },
|
|
13
|
-
})
|
|
14
|
-
updateNodeInternals(data.id)
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
const updateTargetPosition = (position: 'top' | 'left') => {
|
|
18
|
-
reactFlow.updateNode(data.id, {
|
|
19
|
-
data: { ...data, nodeConfig: { ...data.nodeConfig, targetHandlePosition: position } },
|
|
20
|
-
})
|
|
21
|
-
updateNodeInternals(data.id)
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
const toggleTargetPosition = () => {
|
|
25
|
-
const newPosition = targetPosition === Position.Top ? Position.Left : Position.Top
|
|
26
|
-
updateTargetPosition(newPosition)
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
const toggleSourcePosition = () => {
|
|
30
|
-
const newPosition = sourcePosition === Position.Bottom ? Position.Right : Position.Bottom
|
|
31
|
-
updateSourcePosition(newPosition)
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
return {
|
|
35
|
-
sourcePosition,
|
|
36
|
-
targetPosition,
|
|
37
|
-
updateSourcePosition,
|
|
38
|
-
updateTargetPosition,
|
|
39
|
-
toggleTargetPosition,
|
|
40
|
-
toggleSourcePosition,
|
|
41
|
-
}
|
|
42
|
-
}
|
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
import { formatDuration } from '../utils'
|
|
2
|
-
|
|
3
|
-
describe('formatDuration', () => {
|
|
4
|
-
describe('milliseconds', () => {
|
|
5
|
-
it('should format values under 1 second as milliseconds', () => {
|
|
6
|
-
expect(formatDuration(0)).toBe('0ms')
|
|
7
|
-
expect(formatDuration(1)).toBe('1ms')
|
|
8
|
-
expect(formatDuration(250)).toBe('250ms')
|
|
9
|
-
expect(formatDuration(500)).toBe('500ms')
|
|
10
|
-
expect(formatDuration(999)).toBe('999ms')
|
|
11
|
-
})
|
|
12
|
-
})
|
|
13
|
-
|
|
14
|
-
describe('seconds', () => {
|
|
15
|
-
it('should format values between 1 second and 1 minute as seconds with 1 decimal', () => {
|
|
16
|
-
expect(formatDuration(1000)).toBe('1.0s')
|
|
17
|
-
expect(formatDuration(1500)).toBe('1.5s')
|
|
18
|
-
expect(formatDuration(15000)).toBe('15.0s')
|
|
19
|
-
expect(formatDuration(45500)).toBe('45.5s')
|
|
20
|
-
expect(formatDuration(59999)).toBe('60.0s')
|
|
21
|
-
})
|
|
22
|
-
|
|
23
|
-
it('should round to 1 decimal place', () => {
|
|
24
|
-
expect(formatDuration(1234)).toBe('1.2s')
|
|
25
|
-
expect(formatDuration(1567)).toBe('1.6s')
|
|
26
|
-
expect(formatDuration(12345)).toBe('12.3s')
|
|
27
|
-
})
|
|
28
|
-
})
|
|
29
|
-
|
|
30
|
-
describe('minutes', () => {
|
|
31
|
-
it('should format values between 1 minute and 1 hour as minutes with 1 decimal', () => {
|
|
32
|
-
expect(formatDuration(60000)).toBe('1.0min')
|
|
33
|
-
expect(formatDuration(90000)).toBe('1.5min')
|
|
34
|
-
expect(formatDuration(300000)).toBe('5.0min')
|
|
35
|
-
expect(formatDuration(1800000)).toBe('30.0min')
|
|
36
|
-
expect(formatDuration(3599999)).toBe('60.0min')
|
|
37
|
-
})
|
|
38
|
-
|
|
39
|
-
it('should round to 1 decimal place', () => {
|
|
40
|
-
expect(formatDuration(123456)).toBe('2.1min')
|
|
41
|
-
expect(formatDuration(567890)).toBe('9.5min')
|
|
42
|
-
})
|
|
43
|
-
})
|
|
44
|
-
|
|
45
|
-
describe('hours', () => {
|
|
46
|
-
it('should format values 1 hour or more as hours with 1 decimal', () => {
|
|
47
|
-
expect(formatDuration(3600000)).toBe('1.0h')
|
|
48
|
-
expect(formatDuration(5400000)).toBe('1.5h')
|
|
49
|
-
expect(formatDuration(7200000)).toBe('2.0h')
|
|
50
|
-
expect(formatDuration(36000000)).toBe('10.0h')
|
|
51
|
-
})
|
|
52
|
-
|
|
53
|
-
it('should round to 1 decimal place', () => {
|
|
54
|
-
expect(formatDuration(3661000)).toBe('1.0h')
|
|
55
|
-
expect(formatDuration(5432100)).toBe('1.5h')
|
|
56
|
-
expect(formatDuration(9000000)).toBe('2.5h')
|
|
57
|
-
})
|
|
58
|
-
})
|
|
59
|
-
|
|
60
|
-
describe('edge cases', () => {
|
|
61
|
-
it('should return "N/A" for undefined', () => {
|
|
62
|
-
expect(formatDuration(undefined)).toBe('N/A')
|
|
63
|
-
})
|
|
64
|
-
|
|
65
|
-
it('should return "N/A" for null', () => {
|
|
66
|
-
expect(formatDuration(null as any)).toBe('N/A')
|
|
67
|
-
})
|
|
68
|
-
|
|
69
|
-
it('should return "N/A" for 0 when treated as falsy', () => {
|
|
70
|
-
expect(formatDuration(0)).toBe('0ms')
|
|
71
|
-
})
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
describe('boundary values', () => {
|
|
75
|
-
it('should correctly handle millisecond-second boundary (999ms vs 1.0s)', () => {
|
|
76
|
-
expect(formatDuration(999)).toBe('999ms')
|
|
77
|
-
expect(formatDuration(1000)).toBe('1.0s')
|
|
78
|
-
})
|
|
79
|
-
|
|
80
|
-
it('should correctly handle second-minute boundary (59.9s vs 1.0min)', () => {
|
|
81
|
-
expect(formatDuration(59999)).toBe('60.0s')
|
|
82
|
-
expect(formatDuration(60000)).toBe('1.0min')
|
|
83
|
-
})
|
|
84
|
-
|
|
85
|
-
it('should correctly handle minute-hour boundary (59.9min vs 1.0h)', () => {
|
|
86
|
-
expect(formatDuration(3599999)).toBe('60.0min')
|
|
87
|
-
expect(formatDuration(3600000)).toBe('1.0h')
|
|
88
|
-
})
|
|
89
|
-
})
|
|
90
|
-
|
|
91
|
-
describe('real-world scenarios', () => {
|
|
92
|
-
it('should format typical API response times', () => {
|
|
93
|
-
expect(formatDuration(50)).toBe('50ms')
|
|
94
|
-
expect(formatDuration(150)).toBe('150ms')
|
|
95
|
-
expect(formatDuration(2500)).toBe('2.5s')
|
|
96
|
-
})
|
|
97
|
-
|
|
98
|
-
it('should format typical workflow execution times', () => {
|
|
99
|
-
expect(formatDuration(5000)).toBe('5.0s')
|
|
100
|
-
expect(formatDuration(30000)).toBe('30.0s')
|
|
101
|
-
expect(formatDuration(120000)).toBe('2.0min')
|
|
102
|
-
})
|
|
103
|
-
|
|
104
|
-
it('should format long-running tasks', () => {
|
|
105
|
-
expect(formatDuration(600000)).toBe('10.0min')
|
|
106
|
-
expect(formatDuration(1800000)).toBe('30.0min')
|
|
107
|
-
expect(formatDuration(7200000)).toBe('2.0h')
|
|
108
|
-
})
|
|
109
|
-
})
|
|
110
|
-
})
|
|
@@ -1,140 +0,0 @@
|
|
|
1
|
-
import { useCallback } from 'react'
|
|
2
|
-
|
|
3
|
-
interface AmplitudeInstance {
|
|
4
|
-
setOptOut(optOut: boolean): void
|
|
5
|
-
track(eventName: string, eventProperties?: Record<string, any>): void
|
|
6
|
-
identify(userId: string, userProperties?: Record<string, any>): void
|
|
7
|
-
setUserId(userId: string): void
|
|
8
|
-
getUserId(): string | undefined
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
declare global {
|
|
12
|
-
interface Window {
|
|
13
|
-
amplitude: AmplitudeInstance
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
|
|
17
|
-
interface AnalyticsUserData {
|
|
18
|
-
userId: string
|
|
19
|
-
projectId: string
|
|
20
|
-
motiaVersion: string
|
|
21
|
-
analyticsEnabled: boolean
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
class WorkbenchAnalytics {
|
|
25
|
-
private isInitialized = false
|
|
26
|
-
private userIdCache: string | null = null
|
|
27
|
-
private projectIdCache: string | null = null
|
|
28
|
-
private motiaVersion: string | null = null
|
|
29
|
-
|
|
30
|
-
constructor() {
|
|
31
|
-
this.initialize()
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
private async initialize() {
|
|
35
|
-
if (typeof window !== 'undefined' && window.amplitude) {
|
|
36
|
-
await this.fetchUserData()
|
|
37
|
-
this.isInitialized = true
|
|
38
|
-
this.identifyUser()
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
private async fetchUserData(): Promise<void> {
|
|
43
|
-
try {
|
|
44
|
-
const response = await fetch('/motia/analytics/user')
|
|
45
|
-
if (response.ok) {
|
|
46
|
-
const data: AnalyticsUserData = await response.json()
|
|
47
|
-
this.userIdCache = data.userId
|
|
48
|
-
this.projectIdCache = data.projectId
|
|
49
|
-
this.motiaVersion = data.motiaVersion
|
|
50
|
-
|
|
51
|
-
window.amplitude.setOptOut(!data.analyticsEnabled)
|
|
52
|
-
// Set the user ID in Amplitude to match backend
|
|
53
|
-
if (window.amplitude && data.userId) {
|
|
54
|
-
window.amplitude.setUserId(data.userId)
|
|
55
|
-
}
|
|
56
|
-
} else {
|
|
57
|
-
console.warn('Failed to fetch user data from backend, using fallback')
|
|
58
|
-
this.userIdCache = this.generateFallbackUserId()
|
|
59
|
-
}
|
|
60
|
-
} catch (error) {
|
|
61
|
-
console.warn('Error fetching user data:', error)
|
|
62
|
-
this.userIdCache = this.generateFallbackUserId()
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
private generateFallbackUserId(): string {
|
|
67
|
-
let userId = localStorage.getItem('motia-user-id')
|
|
68
|
-
if (!userId) {
|
|
69
|
-
userId = `user-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`
|
|
70
|
-
localStorage.setItem('motia-user-id', userId)
|
|
71
|
-
}
|
|
72
|
-
return userId
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
private identifyUser() {
|
|
76
|
-
if (!this.isInitialized || !this.userIdCache) return
|
|
77
|
-
|
|
78
|
-
try {
|
|
79
|
-
window.amplitude.identify(this.userIdCache, {
|
|
80
|
-
project_id: this.projectIdCache,
|
|
81
|
-
browser: this.getBrowserInfo(),
|
|
82
|
-
screen_resolution: `${window.screen.width}x${window.screen.height}`,
|
|
83
|
-
workbench_version: this.motiaVersion,
|
|
84
|
-
})
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.warn('Analytics user identification failed:', error)
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
private getBrowserInfo(): string {
|
|
91
|
-
const ua = navigator.userAgent
|
|
92
|
-
if (ua.includes('Chrome')) return 'Chrome'
|
|
93
|
-
if (ua.includes('Firefox')) return 'Firefox'
|
|
94
|
-
if (ua.includes('Safari')) return 'Safari'
|
|
95
|
-
if (ua.includes('Edge')) return 'Edge'
|
|
96
|
-
return 'Unknown'
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Method to get current user and project IDs for external use
|
|
100
|
-
getAnalyticsIds() {
|
|
101
|
-
return {
|
|
102
|
-
userId: this.userIdCache,
|
|
103
|
-
projectId: this.projectIdCache,
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
// Simple track method that preserves the user binding
|
|
108
|
-
track(eventName: string, properties?: Record<string, any>) {
|
|
109
|
-
if (!this.isInitialized) return
|
|
110
|
-
|
|
111
|
-
const eventProperties = {
|
|
112
|
-
project_id: this.projectIdCache,
|
|
113
|
-
source: 'frontend',
|
|
114
|
-
...properties,
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
try {
|
|
118
|
-
window.amplitude.track(eventName, eventProperties)
|
|
119
|
-
} catch (error) {
|
|
120
|
-
console.warn('Analytics tracking failed:', error)
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
export const motiaAnalytics = new WorkbenchAnalytics()
|
|
126
|
-
|
|
127
|
-
export const useAnalytics = () => {
|
|
128
|
-
const track = useCallback((eventName: string, properties?: Record<string, any>) => {
|
|
129
|
-
motiaAnalytics.track(eventName, properties)
|
|
130
|
-
}, [])
|
|
131
|
-
|
|
132
|
-
const getAnalyticsIds = useCallback(() => {
|
|
133
|
-
return motiaAnalytics.getAnalyticsIds()
|
|
134
|
-
}, [])
|
|
135
|
-
|
|
136
|
-
return {
|
|
137
|
-
track,
|
|
138
|
-
getAnalyticsIds,
|
|
139
|
-
}
|
|
140
|
-
}
|
package/dist/src/lib/plugins.tsx
DELETED
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
import { plugins } from 'virtual:motia-plugins'
|
|
2
|
-
import { DynamicIcon, dynamicIconImports, type IconName } from 'lucide-react/dynamic'
|
|
3
|
-
import { memo } from 'react'
|
|
4
|
-
import { type AppTab, TabLocation, useAppTabsStore } from '../stores/use-app-tabs-store'
|
|
5
|
-
import { isValidTabLocation } from './utils'
|
|
6
|
-
|
|
7
|
-
export const registerPluginTabs = (addTab: (position: TabLocation, tab: AppTab) => void): void => {
|
|
8
|
-
if (!Array.isArray(plugins)) {
|
|
9
|
-
console.warn('[Motia] Invalid plugins configuration: expected array')
|
|
10
|
-
return
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
plugins.forEach((plugin, index) => {
|
|
14
|
-
try {
|
|
15
|
-
if (!plugin.label) {
|
|
16
|
-
console.warn(`[Motia] Plugin at index ${index} missing label, skipping`)
|
|
17
|
-
return
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
if (!plugin.component) {
|
|
21
|
-
console.warn(`[Motia] Plugin "${plugin.label}" missing component, skipping`)
|
|
22
|
-
return
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
const position = plugin.position || 'top'
|
|
26
|
-
if (!isValidTabLocation(position)) {
|
|
27
|
-
console.warn(`[Motia] Plugin "${plugin.label}" has invalid position "${position}", defaulting to "top"`)
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
const tabLocation = isValidTabLocation(position) ? position : TabLocation.TOP
|
|
31
|
-
|
|
32
|
-
const PluginTabLabel = memo(() => {
|
|
33
|
-
const hasIcon = Object.keys(dynamicIconImports).includes(plugin.labelIcon as IconName)
|
|
34
|
-
const iconName = hasIcon ? (plugin.labelIcon as IconName) : 'toy-brick'
|
|
35
|
-
|
|
36
|
-
if (!hasIcon) {
|
|
37
|
-
console.warn(
|
|
38
|
-
`[Motia] Plugin "${plugin.label}" has invalid icon "${plugin.labelIcon}", defaulting to "toy-brick"`,
|
|
39
|
-
)
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
return (
|
|
43
|
-
<>
|
|
44
|
-
<DynamicIcon name={iconName} />
|
|
45
|
-
<span>{plugin.label}</span>
|
|
46
|
-
</>
|
|
47
|
-
)
|
|
48
|
-
})
|
|
49
|
-
PluginTabLabel.displayName = `${plugin.label}TabLabel`
|
|
50
|
-
|
|
51
|
-
const PluginContent = memo(() => {
|
|
52
|
-
const Component = plugin.component
|
|
53
|
-
const props = plugin.props || {}
|
|
54
|
-
|
|
55
|
-
if (!Component) {
|
|
56
|
-
return <div>Error: Plugin component not found</div>
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
return <Component {...props} />
|
|
60
|
-
})
|
|
61
|
-
PluginContent.displayName = `${plugin.label}Content`
|
|
62
|
-
|
|
63
|
-
addTab(tabLocation, {
|
|
64
|
-
id: plugin.label.toLowerCase(),
|
|
65
|
-
tabLabel: PluginTabLabel,
|
|
66
|
-
content: PluginContent,
|
|
67
|
-
})
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error(`[Motia] Error registering plugin "${plugin.label}":`, error)
|
|
70
|
-
}
|
|
71
|
-
})
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
const refreshPluginTabs = (nextPlugins: typeof plugins): void => {
|
|
75
|
-
try {
|
|
76
|
-
const state = useAppTabsStore.getState()
|
|
77
|
-
const { removeTab, addTab } = state
|
|
78
|
-
|
|
79
|
-
const idsToRefresh = new Set(nextPlugins.map((p) => (p.label || '').toLowerCase()))
|
|
80
|
-
|
|
81
|
-
idsToRefresh.forEach((id) => {
|
|
82
|
-
removeTab(TabLocation.TOP, id)
|
|
83
|
-
removeTab(TabLocation.BOTTOM, id)
|
|
84
|
-
})
|
|
85
|
-
|
|
86
|
-
nextPlugins.forEach((plugin, index) => {
|
|
87
|
-
try {
|
|
88
|
-
if (!plugin.label || !plugin.component) return
|
|
89
|
-
|
|
90
|
-
const position = plugin.position || 'top'
|
|
91
|
-
const tabLocation = isValidTabLocation(position) ? position : TabLocation.TOP
|
|
92
|
-
|
|
93
|
-
const PluginTabLabel = memo(() => {
|
|
94
|
-
const hasIcon = Object.keys(dynamicIconImports).includes(plugin.labelIcon as IconName)
|
|
95
|
-
const iconName: IconName = hasIcon ? (plugin.labelIcon as IconName) : 'toy-brick'
|
|
96
|
-
return (
|
|
97
|
-
<>
|
|
98
|
-
<DynamicIcon name={iconName} />
|
|
99
|
-
<span>{plugin.label}</span>
|
|
100
|
-
</>
|
|
101
|
-
)
|
|
102
|
-
})
|
|
103
|
-
PluginTabLabel.displayName = `${plugin.label}TabLabel_HMR_${index}`
|
|
104
|
-
|
|
105
|
-
const PluginContent = memo(() => {
|
|
106
|
-
const Component = plugin.component as React.ElementType
|
|
107
|
-
const props = plugin.props || {}
|
|
108
|
-
if (!Component) return <div>Error: Plugin component not found</div>
|
|
109
|
-
return <Component {...props} />
|
|
110
|
-
})
|
|
111
|
-
PluginContent.displayName = `${plugin.label}Content_HMR_${index}`
|
|
112
|
-
|
|
113
|
-
addTab(tabLocation, {
|
|
114
|
-
id: plugin.label.toLowerCase(),
|
|
115
|
-
tabLabel: PluginTabLabel,
|
|
116
|
-
content: PluginContent,
|
|
117
|
-
})
|
|
118
|
-
} catch (error) {
|
|
119
|
-
console.error(`[Motia] Error refreshing plugin "${plugin.label}":`, error)
|
|
120
|
-
}
|
|
121
|
-
})
|
|
122
|
-
} catch (err) {
|
|
123
|
-
console.error('[Motia] Failed to refresh plugin tabs via HMR:', err)
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
if (import.meta.hot) {
|
|
128
|
-
import.meta.hot.accept('virtual:motia-plugins', (mod) => {
|
|
129
|
-
const next = (mod as unknown as { plugins?: typeof plugins })?.plugins || []
|
|
130
|
-
refreshPluginTabs(next)
|
|
131
|
-
})
|
|
132
|
-
}
|
package/dist/src/lib/utils.ts
DELETED
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
import { TabLocation } from '../stores/use-app-tabs-store'
|
|
2
|
-
|
|
3
|
-
export const formatDuration = (duration?: number) => {
|
|
4
|
-
if (duration === undefined || duration === null) return 'N/A'
|
|
5
|
-
if (duration < 1000) return `${duration}ms`
|
|
6
|
-
if (duration < 60000) return `${(duration / 1000).toFixed(1)}s`
|
|
7
|
-
if (duration < 3600000) return `${(duration / 60000).toFixed(1)}min`
|
|
8
|
-
return `${(duration / 3600000).toFixed(1)}h`
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
export const formatTimestamp = (time: number) => {
|
|
12
|
-
const date = new Date(Number(time))
|
|
13
|
-
return `${date.toLocaleDateString('en-US', { year: undefined, month: 'short', day: '2-digit' })}, ${date.toLocaleTimeString('en-US', { hour: '2-digit', minute: '2-digit', second: '2-digit', hourCycle: 'h24' })}.${date.getMilliseconds().toString().padStart(3, '0')}`
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
export type ViewMode = 'project' | 'system'
|
|
17
|
-
export const DEFAULT_VIEW_MODE: ViewMode = 'system'
|
|
18
|
-
|
|
19
|
-
export const getViewModeFromURL = (): ViewMode => {
|
|
20
|
-
try {
|
|
21
|
-
const url = new URL(window.location.href)
|
|
22
|
-
const viewMode = url.searchParams.get('view-mode')
|
|
23
|
-
|
|
24
|
-
if (viewMode === 'project' || viewMode === 'system') {
|
|
25
|
-
return viewMode
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
return DEFAULT_VIEW_MODE
|
|
29
|
-
} catch (error) {
|
|
30
|
-
console.error('[Motia] Error parsing URL:', error)
|
|
31
|
-
return DEFAULT_VIEW_MODE
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export const isValidTabLocation = (position: string): position is TabLocation => {
|
|
36
|
-
return Object.values(TabLocation).includes(position as TabLocation)
|
|
37
|
-
}
|
package/dist/src/main.tsx
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
import { MotiaStreamProvider } from '@motiadev/stream-client-react'
|
|
2
|
-
import { StrictMode } from 'react'
|
|
3
|
-
import { createRoot } from 'react-dom/client'
|
|
4
|
-
import { BrowserRouter, Route, Routes } from 'react-router-dom'
|
|
5
|
-
import { App } from './App'
|
|
6
|
-
import { NotFoundPage } from './components/NotFoundPage'
|
|
7
|
-
import { RootMotia } from './components/root-motia'
|
|
8
|
-
import './index.css'
|
|
9
|
-
|
|
10
|
-
const rootElement = document.getElementById('root')!
|
|
11
|
-
if (!rootElement.innerHTML) {
|
|
12
|
-
const basePath = workbenchBase
|
|
13
|
-
const root = createRoot(rootElement)
|
|
14
|
-
const address = window.location.origin.replace('http', 'ws')
|
|
15
|
-
|
|
16
|
-
root.render(
|
|
17
|
-
<StrictMode>
|
|
18
|
-
<MotiaStreamProvider address={address}>
|
|
19
|
-
<RootMotia>
|
|
20
|
-
<BrowserRouter>
|
|
21
|
-
<Routes>
|
|
22
|
-
<Route path={basePath} element={<App />} />
|
|
23
|
-
<Route path="*" element={<NotFoundPage />} />
|
|
24
|
-
</Routes>
|
|
25
|
-
</BrowserRouter>
|
|
26
|
-
</RootMotia>
|
|
27
|
-
</MotiaStreamProvider>
|
|
28
|
-
</StrictMode>,
|
|
29
|
-
)
|
|
30
|
-
}
|
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import { APP_SIDEBAR_CONTAINER_ID, Panel } from '@motiadev/ui'
|
|
2
|
-
import { memo } from 'react'
|
|
3
|
-
import { useShallow } from 'zustand/react/shallow'
|
|
4
|
-
import { type AppTabsState, TabLocation, useAppTabsStore } from './stores/use-app-tabs-store'
|
|
5
|
-
|
|
6
|
-
const topTabs = (state: AppTabsState) => state.tabs[TabLocation.TOP]
|
|
7
|
-
|
|
8
|
-
export const ProjectViewMode = memo(() => {
|
|
9
|
-
const tabs = useAppTabsStore(useShallow(topTabs))
|
|
10
|
-
|
|
11
|
-
return (
|
|
12
|
-
<div className="grid grid-rows-1 grid-cols-[1fr_auto] bg-background text-foreground h-screen ">
|
|
13
|
-
<main className="m-2 overflow-hidden">
|
|
14
|
-
<Panel
|
|
15
|
-
contentClassName={'p-0'}
|
|
16
|
-
tabs={tabs.map((tab) => {
|
|
17
|
-
const Element = tab.content
|
|
18
|
-
const LabelComponent = tab.tabLabel
|
|
19
|
-
return {
|
|
20
|
-
label: tab.id,
|
|
21
|
-
labelComponent: <LabelComponent />,
|
|
22
|
-
content: <Element />,
|
|
23
|
-
'data-testid': tab.id,
|
|
24
|
-
}
|
|
25
|
-
})}
|
|
26
|
-
/>
|
|
27
|
-
</main>
|
|
28
|
-
<div id={APP_SIDEBAR_CONTAINER_ID} />
|
|
29
|
-
</div>
|
|
30
|
-
)
|
|
31
|
-
})
|
|
32
|
-
ProjectViewMode.displayName = 'ProjectViewMode'
|