@shepai/cli 1.75.0 → 1.76.0-pr238.49844a7

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.
Files changed (195) hide show
  1. package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
  2. package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +6 -1
  3. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +5 -2
  4. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
  5. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +14 -5
  6. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.d.ts +2 -0
  7. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.d.ts.map +1 -1
  8. package/dist/src/presentation/web/components/features/features-canvas/features-canvas.stories.js +16 -0
  9. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts +11 -0
  10. package/dist/src/presentation/web/hooks/use-viewport-persistence.d.ts.map +1 -0
  11. package/dist/src/presentation/web/hooks/use-viewport-persistence.js +64 -0
  12. package/dist/tsconfig.build.tsbuildinfo +1 -1
  13. package/package.json +1 -1
  14. package/web/.next/BUILD_ID +1 -1
  15. package/web/.next/build-manifest.json +2 -2
  16. package/web/.next/cache/.previewinfo +1 -1
  17. package/web/.next/cache/.rscinfo +1 -1
  18. package/web/.next/cache/.tsbuildinfo +1 -1
  19. package/web/.next/cache/config.json +3 -3
  20. package/web/.next/fallback-build-manifest.json +2 -2
  21. package/web/.next/prerender-manifest.json +3 -3
  22. package/web/.next/required-server-files.js +1 -1
  23. package/web/.next/required-server-files.json +1 -1
  24. package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +16 -16
  25. package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  26. package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  27. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +19 -19
  28. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  29. package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  30. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  31. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  32. package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  33. package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +16 -16
  34. package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  35. package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  36. package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +19 -19
  37. package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  38. package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  39. package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  40. package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  41. package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  42. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  43. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  44. package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  45. package/web/.next/server/app/_global-error.html +2 -2
  46. package/web/.next/server/app/_global-error.rsc +1 -1
  47. package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  48. package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  49. package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  50. package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  51. package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  52. package/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  53. package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  54. package/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  55. package/web/.next/server/app/skills/page.js.nft.json +1 -1
  56. package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  57. package/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  58. package/web/.next/server/app/tools/page.js.nft.json +1 -1
  59. package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  60. package/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  61. package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  62. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  63. package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
  64. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  65. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -1
  66. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  67. package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +1 -1
  68. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  69. package/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js.map +1 -1
  70. package/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  71. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  72. package/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js.map +1 -1
  73. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js +1 -1
  74. package/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js.map +1 -1
  75. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  76. package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
  77. package/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  78. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  79. package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
  80. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js +1 -1
  81. package/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js.map +1 -1
  82. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  83. package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
  84. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  85. package/web/.next/server/chunks/ssr/_0e9d6bf7._.js.map +1 -1
  86. package/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  87. package/web/.next/server/chunks/ssr/_61351ed3._.js.map +1 -1
  88. package/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  89. package/web/.next/server/chunks/ssr/_8400c8bb._.js.map +1 -1
  90. package/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  91. package/web/.next/server/chunks/ssr/_9f940437._.js.map +1 -1
  92. package/web/.next/server/chunks/ssr/{_fd351734._.js → _e091d951._.js} +3 -3
  93. package/web/.next/server/chunks/ssr/{_fd351734._.js.map → _e091d951._.js.map} +1 -1
  94. package/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js +2 -2
  95. package/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js.map +1 -1
  96. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +1 -1
  97. package/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js.map +1 -1
  98. package/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js +2 -2
  99. package/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js.map +1 -1
  100. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +1 -1
  101. package/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js.map +1 -1
  102. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  103. package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js.map +1 -1
  104. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  105. package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
  106. package/web/.next/server/pages/500.html +2 -2
  107. package/web/.next/server/server-reference-manifest.js +1 -1
  108. package/web/.next/server/server-reference-manifest.json +22 -22
  109. package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
  110. package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
  111. package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
  112. package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
  113. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +16 -16
  114. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
  115. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
  116. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +19 -19
  117. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
  118. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
  119. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  120. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
  121. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  122. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +16 -16
  123. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
  124. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
  125. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +19 -19
  126. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
  127. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
  128. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +14 -14
  129. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
  130. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
  131. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +14 -14
  132. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
  133. package/web/.next/standalone/src/presentation/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
  134. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
  135. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
  136. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
  137. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
  138. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
  139. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
  140. package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
  141. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
  142. package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
  143. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +6 -6
  144. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
  145. package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
  146. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +6 -6
  147. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
  148. package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
  149. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
  150. package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
  151. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
  152. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
  153. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
  154. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__17a611f0._.js +2 -2
  155. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__249c74f6._.js +1 -1
  156. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__45dbf93d._.js +2 -2
  157. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6258349c._.js +1 -1
  158. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
  159. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6cbc1149._.js +2 -2
  160. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
  161. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__94a6d275._.js +1 -1
  162. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
  163. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_0e9d6bf7._.js +1 -1
  164. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_61351ed3._.js +1 -1
  165. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_8400c8bb._.js +1 -1
  166. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9f940437._.js +1 -1
  167. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_fd351734._.js → _e091d951._.js} +3 -3
  168. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_163038ba._.js +2 -2
  169. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_30d7eeda._.js +1 -1
  170. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_459cb687._.js +2 -2
  171. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_565a14f8._.js +1 -1
  172. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.js +1 -1
  173. package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
  174. package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
  175. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
  176. package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +22 -22
  177. package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +18 -1
  178. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.stories.tsx +18 -0
  179. package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +32 -6
  180. package/web/.next/standalone/src/presentation/web/hooks/use-viewport-persistence.ts +79 -0
  181. package/web/.next/standalone/src/presentation/web/server.js +1 -1
  182. package/web/.next/static/chunks/{3ce5a1e5f4215598.js → 067dc08b689d8955.js} +2 -2
  183. package/web/.next/static/chunks/{d1c098005f96b0c2.js → 1e7380ea9e3c019e.js} +1 -1
  184. package/web/.next/static/chunks/{c98e709ebd484e56.js → 3d88e23beec6608e.js} +1 -1
  185. package/web/.next/static/chunks/{7fc4ef147139e5d7.js → 5d28ad531ad6b65c.js} +1 -1
  186. package/web/.next/static/chunks/{25c39fb56c1fb992.js → 65b5bd3861131047.js} +1 -1
  187. package/web/.next/static/chunks/{09e8bde4c8c36032.js → 71d33d172eb1f602.js} +1 -1
  188. package/web/.next/static/chunks/{2a37d25332b5648b.js → 8305a3f93197e23a.js} +1 -1
  189. package/web/.next/static/chunks/{0351dfb1a2c04651.js → 8fe874fd92309313.js} +1 -1
  190. package/web/.next/static/chunks/{409477e14c0251ad.js → eb2dc4b01d975cef.js} +1 -1
  191. package/web/.next/trace +1 -1
  192. package/web/.next/trace-build +1 -1
  193. /package/web/.next/static/{noYkP21cohTYVGvhHBqjY → IVTB-1bqXTCz0djYEeD2G}/_buildManifest.js +0 -0
  194. /package/web/.next/static/{noYkP21cohTYVGvhHBqjY → IVTB-1bqXTCz0djYEeD2G}/_clientMiddlewareManifest.json +0 -0
  195. /package/web/.next/static/{noYkP21cohTYVGvhHBqjY → IVTB-1bqXTCz0djYEeD2G}/_ssgManifest.js +0 -0
@@ -1,9 +1,9 @@
1
1
  'use client';
2
2
 
3
- import { useMemo } from 'react';
4
- import { ReactFlow, Background, Controls } from '@xyflow/react';
5
- import type { Connection, Edge, NodeChange } from '@xyflow/react';
6
- import { Plus } from 'lucide-react';
3
+ import { useCallback, useMemo } from 'react';
4
+ import { ReactFlow, Background, Controls, ControlButton, useReactFlow } from '@xyflow/react';
5
+ import type { Connection, Edge, NodeChange, OnMoveEnd, Viewport } from '@xyflow/react';
6
+ import { Plus, RotateCcw } from 'lucide-react';
7
7
  import { Button } from '@/components/ui/button';
8
8
  import { EmptyState } from '@/components/common/empty-state';
9
9
  import { FeatureNode } from '@/components/common/feature-node';
@@ -18,26 +18,49 @@ export interface FeaturesCanvasProps {
18
18
  nodes: CanvasNodeType[];
19
19
  edges: Edge[];
20
20
  selectedFeatureId?: string | null;
21
+ defaultViewport?: Viewport;
21
22
  onNodesChange?: (changes: NodeChange<CanvasNodeType>[]) => void;
22
23
  onAddFeature?: () => void;
23
24
  onNodeClick?: (event: React.MouseEvent, node: CanvasNodeType) => void;
24
25
  onPaneClick?: (event: React.MouseEvent) => void;
25
26
  onConnect?: (connection: Connection) => void;
26
27
  onCanvasDrag?: () => void;
28
+ onMoveEnd?: OnMoveEnd;
29
+ onResetViewport?: () => Viewport;
27
30
  toolbar?: React.ReactNode;
28
31
  emptyState?: React.ReactNode;
29
32
  }
30
33
 
34
+ const FALLBACK_VIEWPORT: Viewport = { x: 30, y: 30, zoom: 0.85 };
35
+
36
+ function ResetButton({ onResetViewport }: { onResetViewport: () => Viewport }) {
37
+ const { setViewport } = useReactFlow();
38
+
39
+ const handleReset = useCallback(() => {
40
+ const viewport = onResetViewport();
41
+ setViewport(viewport, { duration: 400 });
42
+ }, [onResetViewport, setViewport]);
43
+
44
+ return (
45
+ <ControlButton onClick={handleReset} title="Reset view" aria-label="Reset view">
46
+ <RotateCcw />
47
+ </ControlButton>
48
+ );
49
+ }
50
+
31
51
  export function FeaturesCanvas({
32
52
  nodes,
33
53
  edges,
34
54
  selectedFeatureId,
55
+ defaultViewport,
35
56
  onNodesChange,
36
57
  onAddFeature,
37
58
  onConnect,
38
59
  onNodeClick,
39
60
  onPaneClick,
40
61
  onCanvasDrag,
62
+ onMoveEnd,
63
+ onResetViewport,
41
64
  toolbar,
42
65
  emptyState,
43
66
  }: FeaturesCanvasProps) {
@@ -111,14 +134,17 @@ export function FeaturesCanvas({
111
134
  onNodeClick={onNodeClick}
112
135
  onPaneClick={onPaneClick}
113
136
  onMoveStart={onCanvasDrag}
114
- defaultViewport={{ x: 30, y: 30, zoom: 0.85 }}
137
+ onMoveEnd={onMoveEnd}
138
+ defaultViewport={defaultViewport ?? FALLBACK_VIEWPORT}
115
139
  nodesDraggable={false}
116
140
  nodesConnectable={false}
117
141
  elementsSelectable={false}
118
142
  proOptions={{ hideAttribution: true }}
119
143
  >
120
144
  <Background />
121
- <Controls />
145
+ <Controls showInteractive={false}>
146
+ {onResetViewport ? <ResetButton onResetViewport={onResetViewport} /> : null}
147
+ </Controls>
122
148
  {toolbar}
123
149
  </ReactFlow>
124
150
  </div>
@@ -0,0 +1,79 @@
1
+ 'use client';
2
+
3
+ import { useCallback, useEffect, useRef } from 'react';
4
+ import type { Viewport } from '@xyflow/react';
5
+
6
+ export const STORAGE_KEY = 'shep-canvas-viewport';
7
+ export const DEBOUNCE_MS = 500;
8
+
9
+ export const DEFAULT_VIEWPORT: Viewport = { x: 30, y: 30, zoom: 0.85 };
10
+
11
+ export interface UseViewportPersistenceResult {
12
+ defaultViewport: Viewport;
13
+ onMoveEnd: (viewport: Viewport) => void;
14
+ resetViewport: () => Viewport;
15
+ }
16
+
17
+ function isValidViewport(value: unknown): value is Viewport {
18
+ if (value == null || typeof value !== 'object' || Array.isArray(value)) {
19
+ return false;
20
+ }
21
+ const v = value as Record<string, unknown>;
22
+ return (
23
+ typeof v.x === 'number' &&
24
+ typeof v.y === 'number' &&
25
+ typeof v.zoom === 'number' &&
26
+ Number.isFinite(v.x) &&
27
+ Number.isFinite(v.y) &&
28
+ Number.isFinite(v.zoom) &&
29
+ v.zoom > 0
30
+ );
31
+ }
32
+
33
+ function readViewport(): Viewport {
34
+ try {
35
+ const raw = localStorage.getItem(STORAGE_KEY);
36
+ if (raw == null) return DEFAULT_VIEWPORT;
37
+ const parsed: unknown = JSON.parse(raw);
38
+ return isValidViewport(parsed) ? parsed : DEFAULT_VIEWPORT;
39
+ } catch {
40
+ return DEFAULT_VIEWPORT;
41
+ }
42
+ }
43
+
44
+ export function useViewportPersistence(): UseViewportPersistenceResult {
45
+ const defaultViewport = useRef<Viewport>(readViewport()).current;
46
+ const timerRef = useRef<ReturnType<typeof setTimeout> | null>(null);
47
+
48
+ useEffect(() => {
49
+ return () => {
50
+ if (timerRef.current != null) {
51
+ clearTimeout(timerRef.current);
52
+ }
53
+ };
54
+ }, []);
55
+
56
+ const onMoveEnd = useCallback((viewport: Viewport) => {
57
+ if (timerRef.current != null) {
58
+ clearTimeout(timerRef.current);
59
+ }
60
+ timerRef.current = setTimeout(() => {
61
+ try {
62
+ localStorage.setItem(STORAGE_KEY, JSON.stringify(viewport));
63
+ } catch {
64
+ // Silently ignore localStorage errors (quota exceeded, private browsing, etc.)
65
+ }
66
+ }, DEBOUNCE_MS);
67
+ }, []);
68
+
69
+ const resetViewport = useCallback((): Viewport => {
70
+ try {
71
+ localStorage.removeItem(STORAGE_KEY);
72
+ } catch {
73
+ // Silently ignore localStorage errors
74
+ }
75
+ return DEFAULT_VIEWPORT;
76
+ }, []);
77
+
78
+ return { defaultViewport, onMoveEnd, resetViewport };
79
+ }
@@ -15,7 +15,7 @@ const currentPort = parseInt(process.env.PORT, 10) || 3000
15
15
  const hostname = process.env.HOSTNAME || '0.0.0.0'
16
16
 
17
17
  let keepAliveTimeout = parseInt(process.env.KEEP_ALIVE_TIMEOUT, 10)
18
- const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.74.0","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
18
+ const nextConfig = {"env":{"NEXT_PUBLIC_SHEP_VERSION":"1.76.0","NEXT_PUBLIC_SHEP_PACKAGE_NAME":"@shepai/cli","NEXT_PUBLIC_SHEP_DESCRIPTION":"Autonomous AI Native SDLC Platform - Automate the development cycle from idea to deploy"},"webpack":null,"typescript":{"ignoreBuildErrors":false},"typedRoutes":true,"distDir":"./.next","cleanDistDir":true,"assetPrefix":"","cacheMaxMemorySize":52428800,"configOrigin":"next.config.ts","useFileSystemPublicRoutes":true,"generateEtags":true,"pageExtensions":["tsx","ts","jsx","js"],"poweredByHeader":true,"compress":true,"images":{"deviceSizes":[640,750,828,1080,1200,1920,2048,3840],"imageSizes":[32,48,64,96,128,256,384],"path":"/_next/image","loader":"default","loaderFile":"","domains":[],"disableStaticImages":false,"minimumCacheTTL":14400,"formats":["image/webp"],"maximumRedirects":3,"maximumResponseBody":50000000,"dangerouslyAllowLocalIP":false,"dangerouslyAllowSVG":false,"contentSecurityPolicy":"script-src 'none'; frame-src 'none'; sandbox;","contentDispositionType":"attachment","localPatterns":[{"pathname":"**","search":""}],"remotePatterns":[],"qualities":[75],"unoptimized":false},"devIndicators":{"position":"bottom-left"},"onDemandEntries":{"maxInactiveAge":60000,"pagesBufferLength":5},"basePath":"","sassOptions":{},"trailingSlash":false,"i18n":null,"productionBrowserSourceMaps":false,"excludeDefaultMomentLocales":true,"reactProductionProfiling":false,"reactStrictMode":null,"reactMaxHeadersLength":6000,"httpAgentOptions":{"keepAlive":true},"logging":{},"compiler":{},"expireTime":31536000,"staticPageGenerationTimeout":60,"output":"standalone","modularizeImports":{"@mui/icons-material":{"transform":"@mui/icons-material/{{member}}"},"lodash":{"transform":"lodash/{{member}}"}},"outputFileTracingRoot":"/home/runner/work/cli/cli","cacheComponents":false,"cacheLife":{"default":{"stale":300,"revalidate":900,"expire":4294967294},"seconds":{"stale":30,"revalidate":1,"expire":60},"minutes":{"stale":300,"revalidate":60,"expire":3600},"hours":{"stale":300,"revalidate":3600,"expire":86400},"days":{"stale":300,"revalidate":86400,"expire":604800},"weeks":{"stale":300,"revalidate":604800,"expire":2592000},"max":{"stale":300,"revalidate":2592000,"expire":31536000}},"cacheHandlers":{},"experimental":{"useSkewCookie":false,"cssChunking":true,"multiZoneDraftMode":false,"appNavFailHandling":false,"prerenderEarlyExit":true,"serverMinification":true,"linkNoTouchStart":false,"caseSensitiveRoutes":false,"dynamicOnHover":false,"preloadEntriesOnStart":true,"clientRouterFilter":true,"clientRouterFilterRedirects":false,"fetchCacheKeyPrefix":"","proxyPrefetch":"flexible","optimisticClientCache":true,"manualClientBasePath":false,"cpus":3,"memoryBasedWorkersCount":false,"imgOptConcurrency":null,"imgOptTimeoutInSeconds":7,"imgOptMaxInputPixels":268402689,"imgOptSequentialRead":null,"imgOptSkipMetadata":null,"isrFlushToDisk":true,"workerThreads":false,"optimizeCss":false,"nextScriptWorkers":false,"scrollRestoration":false,"externalDir":false,"disableOptimizedLoading":false,"gzipSize":true,"craCompat":false,"esmExternals":true,"fullySpecified":false,"swcTraceProfiling":false,"forceSwcTransforms":false,"largePageDataBytes":128000,"typedEnv":false,"parallelServerCompiles":false,"parallelServerBuildTraces":false,"ppr":false,"authInterrupts":false,"webpackMemoryOptimizations":false,"optimizeServerReact":true,"viewTransition":false,"removeUncaughtErrorAndRejectionListeners":false,"validateRSCRequestHeaders":false,"staleTimes":{"dynamic":0,"static":300},"reactDebugChannel":false,"serverComponentsHmrCache":true,"staticGenerationMaxConcurrency":8,"staticGenerationMinPagesPerWorker":25,"transitionIndicator":false,"inlineCss":false,"useCache":false,"globalNotFound":false,"browserDebugInfoInTerminal":false,"lockDistDir":true,"isolatedDevBuild":true,"proxyClientMaxBodySize":10485760,"hideLogsAfterAbort":false,"mcpServer":true,"turbopackFileSystemCacheForDev":true,"turbopackFileSystemCacheForBuild":false,"turbopackInferModuleSideEffects":false,"optimizePackageImports":["lucide-react","date-fns","lodash-es","ramda","antd","react-bootstrap","ahooks","@ant-design/icons","@headlessui/react","@headlessui-float/react","@heroicons/react/20/solid","@heroicons/react/24/solid","@heroicons/react/24/outline","@visx/visx","@tremor/react","rxjs","@mui/material","@mui/icons-material","recharts","react-use","effect","@effect/schema","@effect/platform","@effect/platform-node","@effect/platform-browser","@effect/platform-bun","@effect/sql","@effect/sql-mssql","@effect/sql-mysql2","@effect/sql-pg","@effect/sql-sqlite-node","@effect/sql-sqlite-bun","@effect/sql-sqlite-wasm","@effect/sql-sqlite-react-native","@effect/rpc","@effect/rpc-http","@effect/typeclass","@effect/experimental","@effect/opentelemetry","@material-ui/core","@material-ui/icons","@tabler/icons-react","mui-core","react-icons/ai","react-icons/bi","react-icons/bs","react-icons/cg","react-icons/ci","react-icons/di","react-icons/fa","react-icons/fa6","react-icons/fc","react-icons/fi","react-icons/gi","react-icons/go","react-icons/gr","react-icons/hi","react-icons/hi2","react-icons/im","react-icons/io","react-icons/io5","react-icons/lia","react-icons/lib","react-icons/lu","react-icons/md","react-icons/pi","react-icons/ri","react-icons/rx","react-icons/si","react-icons/sl","react-icons/tb","react-icons/tfi","react-icons/ti","react-icons/vsc","react-icons/wi"],"trustHostHeader":false,"isExperimentalCompile":false},"htmlLimitedBots":"[\\w-]+-Google|Google-[\\w-]+|Chrome-Lighthouse|Slurp|DuckDuckBot|baiduspider|yandex|sogou|bitlybot|tumblr|vkShare|quora link preview|redditbot|ia_archiver|Bingbot|BingPreview|applebot|facebookexternalhit|facebookcatalog|Twitterbot|LinkedInBot|Slackbot|Discordbot|WhatsApp|SkypeUriPreview|Yeti|googleweblight","bundlePagesRouterDependencies":false,"configFileName":"next.config.ts","turbopack":{"root":"/home/runner/work/cli/cli"},"serverExternalPackages":["tsyringe","reflect-metadata","better-sqlite3","node:os","node:child_process","node:fs"],"distDirRoot":".next"}
19
19
 
20
20
  process.env.__NEXT_PRIVATE_STANDALONE_CONFIG = JSON.stringify(nextConfig)
21
21