@shepai/cli 1.135.2 → 1.135.3-pr443.1bf56b0
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/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.js +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.js +1 -23
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts +6 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js +22 -2
- package/dist/src/presentation/web/components/common/merge-review/diff-view.d.ts +3 -0
- package/dist/src/presentation/web/components/common/merge-review/diff-view.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/diff-view.js +100 -17
- package/dist/src/presentation/web/components/common/merge-review/diff-view.stories.d.ts +3 -1
- package/dist/src/presentation/web/components/common/merge-review/diff-view.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/diff-view.stories.js +31 -1
- package/dist/src/presentation/web/components/ui/file-tree.d.ts +39 -0
- package/dist/src/presentation/web/components/ui/file-tree.d.ts.map +1 -0
- package/dist/src/presentation/web/components/ui/file-tree.js +194 -0
- package/dist/src/presentation/web/components/ui/file-tree.stories.d.ts +14 -0
- package/dist/src/presentation/web/components/ui/file-tree.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/ui/file-tree.stories.js +92 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/web/.next/BUILD_ID +1 -1
- package/web/.next/build-manifest.json +2 -2
- package/web/.next/fallback-build-manifest.json +2 -2
- package/web/.next/prerender-manifest.json +3 -3
- package/web/.next/required-server-files.js +3 -3
- package/web/.next/required-server-files.json +3 -3
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page/server-reference-manifest.json +24 -24
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/adopt/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +24 -24
- package/web/.next/server/app/(dashboard)/@drawer/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page/server-reference-manifest.json +30 -30
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page/server-reference-manifest.json +30 -30
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page/server-reference-manifest.json +22 -22
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/create/page/server-reference-manifest.json +24 -24
- package/web/.next/server/app/(dashboard)/create/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/create/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page/server-reference-manifest.json +30 -30
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/[tab]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page/server-reference-manifest.json +30 -30
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/feature/[featureId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/page/server-reference-manifest.json +22 -22
- package/web/.next/server/app/(dashboard)/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page/server-reference-manifest.json +22 -22
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page.js.nft.json +1 -1
- package/web/.next/server/app/(dashboard)/repository/[repositoryId]/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/server/app/_not-found/page/server-reference-manifest.json +3 -3
- package/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/api/attachments/preview/route.js.nft.json +1 -1
- package/web/.next/server/app/api/evidence/route.js.nft.json +1 -1
- package/web/.next/server/app/api/graph-data/route.js.nft.json +1 -1
- package/web/.next/server/app/settings/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/settings/page.js.nft.json +1 -1
- package/web/.next/server/app/settings/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/tools/page/server-reference-manifest.json +8 -8
- package/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/version/page/server-reference-manifest.json +3 -3
- package/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__a402b567._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_4e741df2.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web__next-internal_server_app_(dashboard)_@drawer_adopt_page_actions_4e741df2.js.map +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js +1 -1
- package/web/.next/server/chunks/ssr/744ca_web_components_common_control-center-drawer_create-drawer-client_tsx_5e26fc0a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_026fdffa.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_026fdffa.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_8b91e197.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_8b91e197.js.map +1 -1
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7894f27f._.js → [root-of-the-server]__1a3121ff._.js} +2 -2
- package/web/.next/server/chunks/ssr/{[root-of-the-server]__7894f27f._.js.map → [root-of-the-server]__1a3121ff._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__31bc28da._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__31bc28da._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__32ecbed9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__32ecbed9._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__357d99f9._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__3ef34e4c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__43f51aa6._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__815546bd._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__90ce4b6d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__90ce4b6d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__90f9ae71._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__90f9ae71._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__96670392._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b3dbadca._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b3dbadca._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_02ec1aea._.js +1 -1
- package/web/.next/server/chunks/ssr/_02ec1aea._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_67104d9e._.js +1 -1
- package/web/.next/server/chunks/ssr/_67104d9e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_7dca1882._.js +1 -1
- package/web/.next/server/chunks/ssr/_7dca1882._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_69699ffe._.js → _8c62a935._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_69699ffe._.js.map → _8c62a935._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_a9f57758._.js +1 -1
- package/web/.next/server/chunks/ssr/_a9f57758._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_b6960ca0._.js +2 -2
- package/web/.next/server/chunks/ssr/_d0a5c8be._.js +3 -0
- package/web/.next/server/chunks/ssr/{_1f958cbc._.js.map → _d0a5c8be._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_d8575088._.js +1 -1
- package/web/.next/server/chunks/ssr/_d8575088._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_f39a1adb._.js +1 -1
- package/web/.next/server/chunks/ssr/_f39a1adb._.js.map +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js +1 -1
- package/web/.next/server/chunks/ssr/b1a17_presentation_web_components_features_settings_settings-page-client_tsx_6ed9d5f8._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_0111eafd._.js +3 -0
- package/web/.next/server/chunks/ssr/{src_presentation_web_731afe96._.js.map → src_presentation_web_0111eafd._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_8e7fe0d1._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_8e7fe0d1._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_ca051134.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_ca051134.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1b176e3c.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_bd9f0dda.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_b9023017._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_b9023017._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_features_control-center_7ac3562e._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_scroll-area_tsx_53ae5be7._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_ui_scroll-area_tsx_53ae5be7._.js.map +1 -0
- package/web/.next/server/pages/500.html +2 -2
- package/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/server/server-reference-manifest.json +38 -38
- package/web/.next/static/chunks/{3d1b728f59ca0ae6.js → 260c376293ef313f.js} +1 -1
- package/web/.next/static/chunks/2f5948883382134c.js +1 -0
- package/web/.next/static/chunks/{39302cb19904d221.js → 3cdbfd1816f1dae6.js} +1 -1
- package/web/.next/static/chunks/5d8698f0d17c425f.js +2 -0
- package/web/.next/static/chunks/{321178bb6199a3e1.js → 60cfec53f7bd64a7.js} +1 -1
- package/web/.next/static/chunks/66e554b3fb85d07b.js +1 -0
- package/web/.next/static/chunks/72c889d2d1d2c950.js +1 -0
- package/web/.next/static/chunks/7486226f7ac8be26.js +1 -0
- package/web/.next/static/chunks/{d54a9af6cc2a0c58.js → 8bfc9acd71f1884f.js} +1 -1
- package/web/.next/static/chunks/9063a0bcaedece23.js +1 -0
- package/web/.next/static/chunks/{52bbd5a4f8ff74bd.js → 970d4d88a2e46223.js} +1 -1
- package/web/.next/static/chunks/a6b8b76506ed0486.js +1 -0
- package/web/.next/static/chunks/afbe5f1ead5cd56b.js +1 -0
- package/web/.next/static/chunks/{d4fbedd39504661f.js → c733b438f9c3dca2.js} +1 -1
- package/web/.next/static/chunks/{567a5fd9bc141bde.js → ccbca8058fb94fd9.js} +1 -1
- package/web/.next/static/chunks/cea224868e7b317e.css +1 -0
- package/web/.next/server/chunks/ssr/_1f958cbc._.js +0 -3
- package/web/.next/server/chunks/ssr/src_presentation_web_731afe96._.js +0 -3
- package/web/.next/static/chunks/314b8314f77d6921.js +0 -1
- package/web/.next/static/chunks/3e2d7d07926b05bf.css +0 -1
- package/web/.next/static/chunks/52d2796a174182a7.js +0 -1
- package/web/.next/static/chunks/6709ec190dbf8098.js +0 -1
- package/web/.next/static/chunks/688971d5bad5dc7c.js +0 -1
- package/web/.next/static/chunks/88a7aed01a628019.js +0 -1
- package/web/.next/static/chunks/9e13ad97d9c1c52a.js +0 -2
- package/web/.next/static/chunks/ddb9106ee55ddb62.js +0 -1
- /package/web/.next/static/{yv0Tq9-BtqVnENafaiFF6 → dLwf5BeiVENzBHuUxtSGx}/_buildManifest.js +0 -0
- /package/web/.next/static/{yv0Tq9-BtqVnENafaiFF6 → dLwf5BeiVENzBHuUxtSGx}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{yv0Tq9-BtqVnENafaiFF6 → dLwf5BeiVENzBHuUxtSGx}/_ssgManifest.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAEpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"evidence.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAEpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAqDrD;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,cAAc,IAG3C,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAoJ7E"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/evidence.node.js
CHANGED
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
*/
|
|
23
23
|
import yaml from 'js-yaml';
|
|
24
24
|
import { isGraphBubbleUp } from '@langchain/langgraph';
|
|
25
|
-
import { createNodeLogger, getCompletedPhases, markPhaseComplete, readSpecFile, retryExecute, buildExecutorOptions, } from './node-helpers.js';
|
|
25
|
+
import { createNodeLogger, getCompletedPhases, markPhaseComplete, readSpecFile, retryExecute, buildExecutorOptions, saveEvidenceManifest, } from './node-helpers.js';
|
|
26
26
|
import { reportNodeStart } from '../heartbeat.js';
|
|
27
27
|
import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
|
|
28
28
|
import { updateNodeLifecycle } from '../lifecycle-context.js';
|
|
@@ -174,6 +174,7 @@ export function createEvidenceNode(executor) {
|
|
|
174
174
|
throw new Error(`[evidence] ${message}`);
|
|
175
175
|
}
|
|
176
176
|
}
|
|
177
|
+
saveEvidenceManifest(state, allEvidence, log);
|
|
177
178
|
markPhaseComplete(state.specDir, 'evidence', log);
|
|
178
179
|
allMessages.unshift(`[evidence] Complete — ${allEvidence.length} evidence record(s) captured in ${attempt} attempt(s)`, ...(allEvidence.length === 0
|
|
179
180
|
? ['[evidence] Warning: no evidence records parsed from agent output']
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"fast-implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;
|
|
1
|
+
{"version":3,"file":"fast-implement.node.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/fast-implement.node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,+DAA+D,CAAC;AAEpG,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAiBrD;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,QAAQ,EAAE,cAAc,IAGhD,OAAO,iBAAiB,KAAG,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CA0F7E"}
|
|
@@ -10,10 +10,8 @@
|
|
|
10
10
|
* dependency, returns async (state) => Partial<FeatureAgentState>.
|
|
11
11
|
*/
|
|
12
12
|
import { execSync } from 'node:child_process';
|
|
13
|
-
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
14
|
-
import { join, dirname } from 'node:path';
|
|
15
13
|
import { isGraphBubbleUp } from '@langchain/langgraph';
|
|
16
|
-
import { createNodeLogger, buildExecutorOptions, retryExecute, getCompletedPhases, markPhaseComplete, } from './node-helpers.js';
|
|
14
|
+
import { createNodeLogger, buildExecutorOptions, retryExecute, getCompletedPhases, markPhaseComplete, saveEvidenceManifest, } from './node-helpers.js';
|
|
17
15
|
import { reportNodeStart } from '../heartbeat.js';
|
|
18
16
|
import { recordPhaseStart, recordPhaseEnd } from '../phase-timing-context.js';
|
|
19
17
|
import { updateNodeLifecycle } from '../lifecycle-context.js';
|
|
@@ -178,23 +176,3 @@ function hasNewCommits(cwd) {
|
|
|
178
176
|
return false;
|
|
179
177
|
}
|
|
180
178
|
}
|
|
181
|
-
/**
|
|
182
|
-
* Save evidence manifest to the shep home evidence folder so the
|
|
183
|
-
* merge review UI can read it without accessing graph state.
|
|
184
|
-
*/
|
|
185
|
-
function saveEvidenceManifest(state, evidence, log) {
|
|
186
|
-
if (evidence.length === 0)
|
|
187
|
-
return;
|
|
188
|
-
try {
|
|
189
|
-
const cwd = state.worktreePath || state.repositoryPath;
|
|
190
|
-
const repoHashDir = dirname(dirname(cwd));
|
|
191
|
-
const evidenceDir = join(repoHashDir, 'evidence', state.featureId);
|
|
192
|
-
mkdirSync(evidenceDir, { recursive: true });
|
|
193
|
-
writeFileSync(join(evidenceDir, 'manifest.json'), JSON.stringify(evidence, null, 2), 'utf-8');
|
|
194
|
-
log.info(`Saved evidence manifest to ${evidenceDir}/manifest.json`);
|
|
195
|
-
}
|
|
196
|
-
catch (err) {
|
|
197
|
-
const msg = err instanceof Error ? err.message : String(err);
|
|
198
|
-
log.error(`Failed to save evidence manifest: ${msg}`);
|
|
199
|
-
}
|
|
200
|
-
}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.d.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* and error handling so every node follows the same patterns.
|
|
6
6
|
*/
|
|
7
7
|
import type { IAgentExecutor, AgentExecutionOptions, AgentExecutionResult } from '../../../../../application/ports/output/agents/agent-executor.interface.js';
|
|
8
|
-
import type { ApprovalGates } from '../../../../../domain/generated/output.js';
|
|
8
|
+
import type { ApprovalGates, Evidence } from '../../../../../domain/generated/output.js';
|
|
9
9
|
import type { FeatureAgentState } from '../state.js';
|
|
10
10
|
/**
|
|
11
11
|
* Create a scoped logger that prefixes messages with the node name.
|
|
@@ -168,4 +168,9 @@ export declare function buildResumeContext(resumeReason: string | undefined): st
|
|
|
168
168
|
* - Consistent state shape for success and failure
|
|
169
169
|
*/
|
|
170
170
|
export declare function executeNode(nodeName: string, executor: IAgentExecutor, buildPrompt: (state: FeatureAgentState, log: NodeLogger) => string): (state: FeatureAgentState) => Promise<Partial<FeatureAgentState>>;
|
|
171
|
+
/**
|
|
172
|
+
* Save evidence manifest to the shep home evidence folder so the
|
|
173
|
+
* merge review UI can read it without accessing graph state.
|
|
174
|
+
*/
|
|
175
|
+
export declare function saveEvidenceManifest(state: FeatureAgentState, evidence: Evidence[], log: ReturnType<typeof createNodeLogger>): void;
|
|
171
176
|
//# sourceMappingURL=node-helpers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,8BAA8B,CAAC;
|
|
1
|
+
{"version":3,"file":"node-helpers.d.ts","sourceRoot":"","sources":["../../../../../../../../../packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAMH,OAAO,KAAK,EACV,cAAc,EACd,qBAAqB,EACrB,oBAAoB,EACrB,MAAM,+DAA+D,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAC;AAE5E,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AAUrD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM;IAE7C,4DAA4D;gBAChD,IAAI;kBAGF,MAAM,GAAG,IAAI;mBAIZ,MAAM,GAAG,IAAI;EAK/B;AAED,MAAM,MAAM,UAAU,GAAG,UAAU,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE7D;;GAEG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMtE;AAoBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAO1D;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,iBAAiB,EACxB,SAAS,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,SAAS,CAAC,CAAC,EAC3D,QAAQ,CAAC,EAAE,MAAM,GAChB,qBAAqB,CAUvB;AAeD;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAQrD;AAgBD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,CAElD;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,eAAe,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,SAAS,GAAG,OAAO,CAQ3F;AAMD,MAAM,MAAM,aAAa,GAAG,eAAe,GAAG,mBAAmB,GAAG,eAAe,GAAG,SAAS,CAAC;AAMhG;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,YAAY,EAAE,MAAM,GAAG,aAAa,CAKjE;AAED,MAAM,WAAW,YAAY;IAC3B,wDAAwD;IACxD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,0CAA0C;IAC1C,MAAM,CAAC,EAAE,UAAU,CAAC;CACrB;AAED;;;;;;GAMG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,cAAc,EACxB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,qBAAqB,EAC9B,SAAS,CAAC,EAAE,YAAY,GACvB,OAAO,CAAC,oBAAoB,CAAC,CA6B/B;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,CAW5D;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAiB5F;AAED;;GAEG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI;IAAE,QAAQ,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAOhG;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,UAAU,GAAG,IAAI,CAoB1F;AAED;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAa5F;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE;IACzC,IAAI,EAAE,OAAO,CAAC;IACd,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,6FAA6F;IAC7F,gBAAgB,CAAC,EAAE,OAAO,CAAC;CAC5B,GAAG,MAAM,CAiCT;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,YAAY,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAa3E;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CACzB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,cAAc,EACxB,WAAW,EAAE,CAAC,KAAK,EAAE,iBAAiB,EAAE,GAAG,EAAE,UAAU,KAAK,MAAM,GACjE,CAAC,KAAK,EAAE,iBAAiB,KAAK,OAAO,CAAC,OAAO,CAAC,iBAAiB,CAAC,CAAC,CAqInE;AAED;;;GAGG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,iBAAiB,EACxB,QAAQ,EAAE,QAAQ,EAAE,EACpB,GAAG,EAAE,UAAU,CAAC,OAAO,gBAAgB,CAAC,GACvC,IAAI,CAaN"}
|
package/dist/packages/core/src/infrastructure/services/agents/feature-agent/nodes/node-helpers.js
CHANGED
|
@@ -5,8 +5,8 @@
|
|
|
5
5
|
* and error handling so every node follows the same patterns.
|
|
6
6
|
*/
|
|
7
7
|
import yaml from 'js-yaml';
|
|
8
|
-
import { readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
|
|
9
|
-
import { join } from 'node:path';
|
|
8
|
+
import { mkdirSync, readFileSync, writeFileSync, renameSync, unlinkSync } from 'node:fs';
|
|
9
|
+
import { join, dirname } from 'node:path';
|
|
10
10
|
import { interrupt, isGraphBubbleUp } from '@langchain/langgraph';
|
|
11
11
|
import { hasSettings, getSettings } from '../../../../services/settings.service.js';
|
|
12
12
|
import { reportNodeStart } from '../heartbeat.js';
|
|
@@ -525,3 +525,23 @@ export function executeNode(nodeName, executor, buildPrompt) {
|
|
|
525
525
|
}
|
|
526
526
|
};
|
|
527
527
|
}
|
|
528
|
+
/**
|
|
529
|
+
* Save evidence manifest to the shep home evidence folder so the
|
|
530
|
+
* merge review UI can read it without accessing graph state.
|
|
531
|
+
*/
|
|
532
|
+
export function saveEvidenceManifest(state, evidence, log) {
|
|
533
|
+
if (evidence.length === 0)
|
|
534
|
+
return;
|
|
535
|
+
try {
|
|
536
|
+
const cwd = state.worktreePath || state.repositoryPath;
|
|
537
|
+
const repoHashDir = dirname(dirname(cwd));
|
|
538
|
+
const evidenceDir = join(repoHashDir, 'evidence', state.featureId);
|
|
539
|
+
mkdirSync(evidenceDir, { recursive: true });
|
|
540
|
+
writeFileSync(join(evidenceDir, 'manifest.json'), JSON.stringify(evidence, null, 2), 'utf-8');
|
|
541
|
+
log.info(`Saved evidence manifest to ${evidenceDir}/manifest.json`);
|
|
542
|
+
}
|
|
543
|
+
catch (err) {
|
|
544
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
545
|
+
log.error(`Failed to save evidence manifest: ${msg}`);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
+
import { type TreeViewElement } from '../../ui/file-tree.js';
|
|
1
2
|
import type { MergeReviewFileDiff } from './merge-review-config.js';
|
|
3
|
+
/** Build a tree structure from flat file paths. */
|
|
4
|
+
export declare function buildFileTree(fileDiffs: MergeReviewFileDiff[]): TreeViewElement[];
|
|
2
5
|
export interface DiffViewProps {
|
|
3
6
|
fileDiffs: MergeReviewFileDiff[];
|
|
4
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-view.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/diff-view.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,mBAAmB,EAAuB,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"diff-view.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/diff-view.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAsB,KAAK,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACrF,OAAO,KAAK,EAAE,mBAAmB,EAAuB,MAAM,uBAAuB,CAAC;AAStF,mDAAmD;AACnD,wBAAgB,aAAa,CAAC,SAAS,EAAE,mBAAmB,EAAE,GAAG,eAAe,EAAE,CAoCjF;AAgJD,MAAM,WAAW,aAAa;IAC5B,SAAS,EAAE,mBAAmB,EAAE,CAAC;CAClC;AAED,wBAAgB,QAAQ,CAAC,EAAE,SAAS,EAAE,EAAE,aAAa,kDAkEpD"}
|
|
@@ -1,30 +1,113 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs
|
|
3
|
-
import { useState } from 'react';
|
|
4
|
-
import {
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useMemo, useCallback } from 'react';
|
|
4
|
+
import { FileText, FilePlus, FileMinus, FileEdit } from 'lucide-react';
|
|
5
5
|
import { cn } from '../../../lib/utils.js';
|
|
6
|
+
import { Tree, Folder, File } from '../../ui/file-tree.js';
|
|
6
7
|
const STATUS_CONFIG = {
|
|
7
|
-
added: { icon: FilePlus,
|
|
8
|
-
modified: { icon: FileEdit,
|
|
9
|
-
deleted: { icon: FileMinus,
|
|
10
|
-
renamed: { icon: FileEdit,
|
|
8
|
+
added: { icon: FilePlus, className: 'text-green-600' },
|
|
9
|
+
modified: { icon: FileEdit, className: 'text-amber-600' },
|
|
10
|
+
deleted: { icon: FileMinus, className: 'text-red-600' },
|
|
11
|
+
renamed: { icon: FileEdit, className: 'text-blue-600' },
|
|
11
12
|
};
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
const
|
|
15
|
-
|
|
13
|
+
/** Build a tree structure from flat file paths. */
|
|
14
|
+
export function buildFileTree(fileDiffs) {
|
|
15
|
+
const root = [];
|
|
16
|
+
for (const diff of fileDiffs) {
|
|
17
|
+
const parts = diff.path.split('/');
|
|
18
|
+
let currentLevel = root;
|
|
19
|
+
for (let i = 0; i < parts.length; i++) {
|
|
20
|
+
const part = parts[i];
|
|
21
|
+
const isFile = i === parts.length - 1;
|
|
22
|
+
const pathSoFar = parts.slice(0, i + 1).join('/');
|
|
23
|
+
const existing = currentLevel.find((el) => el.name === part && el.type === (isFile ? 'file' : 'folder'));
|
|
24
|
+
if (existing) {
|
|
25
|
+
if (!isFile && existing.children) {
|
|
26
|
+
currentLevel = existing.children;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const node = {
|
|
31
|
+
id: pathSoFar,
|
|
32
|
+
name: part,
|
|
33
|
+
type: isFile ? 'file' : 'folder',
|
|
34
|
+
...(isFile ? {} : { children: [] }),
|
|
35
|
+
};
|
|
36
|
+
currentLevel.push(node);
|
|
37
|
+
if (!isFile && node.children) {
|
|
38
|
+
currentLevel = node.children;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
return collapseSingleChildFolders(root);
|
|
44
|
+
}
|
|
45
|
+
/** Collapse folders that contain only one child folder (e.g. src/components → src/components). */
|
|
46
|
+
function collapseSingleChildFolders(elements) {
|
|
47
|
+
return elements.map((el) => {
|
|
48
|
+
if (el.type === 'folder' && el.children) {
|
|
49
|
+
const collapsed = collapseSingleChildFolders(el.children);
|
|
50
|
+
if (collapsed.length === 1 && collapsed[0].type === 'folder' && collapsed[0].children) {
|
|
51
|
+
return {
|
|
52
|
+
...collapsed[0],
|
|
53
|
+
id: `${el.id}/${collapsed[0].name}`,
|
|
54
|
+
name: `${el.name}/${collapsed[0].name}`,
|
|
55
|
+
children: collapsed[0].children,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
return { ...el, children: collapsed };
|
|
59
|
+
}
|
|
60
|
+
return el;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
/** Collect all folder IDs for expanding the tree by default. */
|
|
64
|
+
function getAllFolderIds(elements) {
|
|
65
|
+
const ids = [];
|
|
66
|
+
for (const el of elements) {
|
|
67
|
+
if (el.type === 'folder') {
|
|
68
|
+
ids.push(el.id);
|
|
69
|
+
if (el.children) {
|
|
70
|
+
ids.push(...getAllFolderIds(el.children));
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return ids;
|
|
16
75
|
}
|
|
17
76
|
function HunkView({ hunk }) {
|
|
18
77
|
return (_jsxs("div", { className: "border-border border-t first:border-t-0", children: [_jsx("div", { className: "bg-muted/50 text-muted-foreground px-3 py-1 font-mono text-[10px]", children: hunk.header }), _jsx("div", { className: "font-mono text-[11px] leading-[18px]", children: hunk.lines.map((line) => (_jsxs("div", { className: cn('flex', line.type === 'added' && 'bg-green-50 dark:bg-green-950/30', line.type === 'removed' && 'bg-red-50 dark:bg-red-950/30'), children: [_jsx("span", { className: "text-muted-foreground w-10 shrink-0 px-1 text-right text-[10px] select-none", children: line.oldNumber ?? '' }), _jsx("span", { className: "text-muted-foreground w-10 shrink-0 px-1 text-right text-[10px] select-none", children: line.newNumber ?? '' }), _jsx("span", { className: cn('w-4 shrink-0 text-center select-none', line.type === 'added' && 'text-green-700 dark:text-green-400', line.type === 'removed' && 'text-red-700 dark:text-red-400'), children: line.type === 'added' ? '+' : line.type === 'removed' ? '-' : ' ' }), _jsx("span", { className: "min-w-0 flex-1 pr-2 break-all whitespace-pre-wrap", children: line.content })] }, `${line.type}-${line.oldNumber ?? ''}-${line.newNumber ?? ''}`))) })] }));
|
|
19
78
|
}
|
|
20
|
-
function
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
79
|
+
function DiffFileIcon({ status }) {
|
|
80
|
+
const config = STATUS_CONFIG[status];
|
|
81
|
+
const Icon = config.icon;
|
|
82
|
+
return _jsx(Icon, { className: cn('size-4 shrink-0', config.className) });
|
|
83
|
+
}
|
|
84
|
+
function DiffStats({ additions, deletions }) {
|
|
85
|
+
return (_jsxs("span", { className: "ml-auto shrink-0 text-[10px]", children: [additions > 0 ? _jsxs("span", { className: "text-green-600", children: ["+", additions] }) : null, additions > 0 && deletions > 0 ? ' ' : null, deletions > 0 ? _jsxs("span", { className: "text-red-600", children: ["-", deletions] }) : null] }));
|
|
86
|
+
}
|
|
87
|
+
function FileTreeNode({ element, diffMap, selectedFile, onSelectFile, }) {
|
|
88
|
+
if (element.type === 'folder' && element.children) {
|
|
89
|
+
return (_jsx(Folder, { value: element.id, element: element.name, isSelectable: false, children: element.children.map((child) => (_jsx(FileTreeNode, { element: child, diffMap: diffMap, selectedFile: selectedFile, onSelectFile: onSelectFile }, child.id))) }, element.id));
|
|
90
|
+
}
|
|
91
|
+
const diff = diffMap.get(element.id);
|
|
92
|
+
const status = diff?.status ?? 'modified';
|
|
93
|
+
return (_jsx(File, { value: element.id, fileIcon: _jsx(DiffFileIcon, { status: status }), isSelect: selectedFile === element.id, handleSelect: onSelectFile, className: "w-full", children: _jsxs("span", { className: "flex min-w-0 flex-1 items-center gap-1", children: [_jsx("span", { className: "truncate", children: element.name }), diff?.oldPath ? (_jsxs("span", { className: "text-muted-foreground truncate text-[10px]", children: ["\u2190 ", diff.oldPath.split('/').pop()] })) : null, diff ? _jsx(DiffStats, { additions: diff.additions, deletions: diff.deletions }) : null] }) }, element.id));
|
|
25
94
|
}
|
|
26
95
|
export function DiffView({ fileDiffs }) {
|
|
96
|
+
const [selectedFile, setSelectedFile] = useState(null);
|
|
97
|
+
const treeElements = useMemo(() => buildFileTree(fileDiffs), [fileDiffs]);
|
|
98
|
+
const allFolderIds = useMemo(() => getAllFolderIds(treeElements), [treeElements]);
|
|
99
|
+
const diffMap = useMemo(() => {
|
|
100
|
+
const map = new Map();
|
|
101
|
+
for (const diff of fileDiffs) {
|
|
102
|
+
map.set(diff.path, diff);
|
|
103
|
+
}
|
|
104
|
+
return map;
|
|
105
|
+
}, [fileDiffs]);
|
|
106
|
+
const handleSelectFile = useCallback((path) => {
|
|
107
|
+
setSelectedFile((prev) => (prev === path ? null : path));
|
|
108
|
+
}, []);
|
|
109
|
+
const selectedDiff = selectedFile ? diffMap.get(selectedFile) : null;
|
|
27
110
|
if (fileDiffs.length === 0)
|
|
28
111
|
return null;
|
|
29
|
-
return (_jsxs("div", { className: "border-border rounded-lg border", children: [_jsx("div", { className: "px-4 py-3", children: _jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(FileText, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-foreground text-xs font-semibold", children: "Changed Files" }), _jsxs("span", { className: "text-muted-foreground text-[10px]", children: ["(", fileDiffs.length, ")"] })] }) }),
|
|
112
|
+
return (_jsxs("div", { className: "border-border rounded-lg border", children: [_jsx("div", { className: "px-4 py-3", children: _jsxs("div", { className: "mb-2 flex items-center gap-2", children: [_jsx(FileText, { className: "text-muted-foreground h-4 w-4" }), _jsx("span", { className: "text-foreground text-xs font-semibold", children: "Changed Files" }), _jsxs("span", { className: "text-muted-foreground text-[10px]", children: ["(", fileDiffs.length, ")"] })] }) }), _jsxs("div", { className: "border-border border-t", children: [_jsx("div", { className: "py-2", children: _jsx(Tree, { elements: treeElements, initialExpandedItems: allFolderIds, indicator: true, sort: "none", className: "text-xs", children: treeElements.map((element) => (_jsx(FileTreeNode, { element: element, diffMap: diffMap, selectedFile: selectedFile, onSelectFile: handleSelectFile }, element.id))) }) }), selectedDiff && selectedDiff.hunks.length > 0 ? (_jsxs("div", { className: "border-border overflow-x-auto border-t", children: [_jsxs("div", { className: "bg-muted/30 flex items-center gap-2 px-3 py-1.5", children: [_jsx(DiffFileIcon, { status: selectedDiff.status }), _jsx("span", { className: "text-foreground font-mono text-xs", children: selectedDiff.path }), _jsx(DiffStats, { additions: selectedDiff.additions, deletions: selectedDiff.deletions })] }), selectedDiff.hunks.map((hunk) => (_jsx(HunkView, { hunk: hunk }, hunk.header)))] })) : null] })] }));
|
|
30
113
|
}
|
|
@@ -3,7 +3,7 @@ import { DiffView } from './diff-view.js';
|
|
|
3
3
|
declare const meta: Meta<typeof DiffView>;
|
|
4
4
|
export default meta;
|
|
5
5
|
type Story = StoryObj<typeof DiffView>;
|
|
6
|
-
/** Default — multiple files with various change types. */
|
|
6
|
+
/** Default — multiple files with various change types shown in a file tree. */
|
|
7
7
|
export declare const Default: Story;
|
|
8
8
|
/** Single modified file. */
|
|
9
9
|
export declare const SingleFile: Story;
|
|
@@ -15,4 +15,6 @@ export declare const OnlyDeletions: Story;
|
|
|
15
15
|
export declare const RenamedFile: Story;
|
|
16
16
|
/** Empty diff list — renders nothing. */
|
|
17
17
|
export declare const EmptyDiffs: Story;
|
|
18
|
+
/** Root-level files without directory nesting. */
|
|
19
|
+
export declare const RootLevelFiles: Story;
|
|
18
20
|
//# sourceMappingURL=diff-view.stories.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"diff-view.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/diff-view.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA2HvC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,QAAQ,CAuB/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEvC
|
|
1
|
+
{"version":3,"file":"diff-view.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/merge-review/diff-view.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AA2HvC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,QAAQ,CAuB/B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,QAAQ,CAAC,CAAC;AAEvC,+EAA+E;AAC/E,eAAO,MAAM,OAAO,EAAE,KAIrB,CAAC;AAEF,4BAA4B;AAC5B,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,4BAA4B;AAC5B,eAAO,MAAM,aAAa,EAAE,KAI3B,CAAC;AAEF,0BAA0B;AAC1B,eAAO,MAAM,aAAa,EAAE,KAI3B,CAAC;AAEF,oBAAoB;AACpB,eAAO,MAAM,WAAW,EAAE,KAIzB,CAAC;AAEF,yCAAyC;AACzC,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,kDAAkD;AAClD,eAAO,MAAM,cAAc,EAAE,KA4B5B,CAAC"}
|
|
@@ -136,7 +136,7 @@ const meta = {
|
|
|
136
136
|
],
|
|
137
137
|
};
|
|
138
138
|
export default meta;
|
|
139
|
-
/** Default — multiple files with various change types. */
|
|
139
|
+
/** Default — multiple files with various change types shown in a file tree. */
|
|
140
140
|
export const Default = {
|
|
141
141
|
args: {
|
|
142
142
|
fileDiffs: sampleFiles,
|
|
@@ -172,3 +172,33 @@ export const EmptyDiffs = {
|
|
|
172
172
|
fileDiffs: [],
|
|
173
173
|
},
|
|
174
174
|
};
|
|
175
|
+
/** Root-level files without directory nesting. */
|
|
176
|
+
export const RootLevelFiles = {
|
|
177
|
+
args: {
|
|
178
|
+
fileDiffs: [
|
|
179
|
+
{
|
|
180
|
+
path: 'package.json',
|
|
181
|
+
additions: 3,
|
|
182
|
+
deletions: 1,
|
|
183
|
+
status: 'modified',
|
|
184
|
+
hunks: [
|
|
185
|
+
{
|
|
186
|
+
header: '@@ -10,3 +10,5 @@',
|
|
187
|
+
lines: [
|
|
188
|
+
{ type: 'context', content: ' "dependencies": {', oldNumber: 10, newNumber: 10 },
|
|
189
|
+
{ type: 'added', content: ' "new-dep": "^1.0.0",', newNumber: 11 },
|
|
190
|
+
{ type: 'context', content: ' }', oldNumber: 11, newNumber: 12 },
|
|
191
|
+
],
|
|
192
|
+
},
|
|
193
|
+
],
|
|
194
|
+
},
|
|
195
|
+
{
|
|
196
|
+
path: 'README.md',
|
|
197
|
+
additions: 10,
|
|
198
|
+
deletions: 0,
|
|
199
|
+
status: 'modified',
|
|
200
|
+
hunks: [],
|
|
201
|
+
},
|
|
202
|
+
],
|
|
203
|
+
},
|
|
204
|
+
};
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Accordion as AccordionPrimitive } from 'radix-ui';
|
|
3
|
+
interface TreeViewElement {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
type?: 'file' | 'folder';
|
|
7
|
+
isSelectable?: boolean;
|
|
8
|
+
children?: TreeViewElement[];
|
|
9
|
+
}
|
|
10
|
+
type TreeSortMode = 'default' | 'none' | ((a: TreeViewElement, b: TreeViewElement) => number);
|
|
11
|
+
declare const Tree: React.ForwardRefExoticComponent<{
|
|
12
|
+
initialSelectedId?: string;
|
|
13
|
+
indicator?: boolean;
|
|
14
|
+
elements?: TreeViewElement[];
|
|
15
|
+
initialExpandedItems?: string[];
|
|
16
|
+
openIcon?: React.ReactNode;
|
|
17
|
+
closeIcon?: React.ReactNode;
|
|
18
|
+
sort?: TreeSortMode;
|
|
19
|
+
} & Omit<Omit<AccordionPrimitive.AccordionSingleProps & React.RefAttributes<HTMLDivElement>, "ref"> | Omit<AccordionPrimitive.AccordionMultipleProps & React.RefAttributes<HTMLDivElement>, "ref">, "type" | "value" | "defaultValue" | "onValueChange"> & React.RefAttributes<HTMLDivElement>>;
|
|
20
|
+
declare const Folder: React.ForwardRefExoticComponent<{
|
|
21
|
+
expandedItems?: string[];
|
|
22
|
+
element: string;
|
|
23
|
+
isSelectable?: boolean;
|
|
24
|
+
isSelect?: boolean;
|
|
25
|
+
} & Omit<AccordionPrimitive.AccordionItemProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.HTMLAttributes<HTMLDivElement> & React.RefAttributes<HTMLDivElement>>;
|
|
26
|
+
declare const File: React.ForwardRefExoticComponent<{
|
|
27
|
+
value: string;
|
|
28
|
+
handleSelect?: (id: string) => void;
|
|
29
|
+
isSelectable?: boolean;
|
|
30
|
+
isSelect?: boolean;
|
|
31
|
+
fileIcon?: React.ReactNode;
|
|
32
|
+
} & React.ButtonHTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>>;
|
|
33
|
+
declare const CollapseButton: React.ForwardRefExoticComponent<{
|
|
34
|
+
elements: TreeViewElement[];
|
|
35
|
+
expandAll?: boolean;
|
|
36
|
+
} & React.HTMLAttributes<HTMLButtonElement> & React.RefAttributes<HTMLButtonElement>>;
|
|
37
|
+
export { CollapseButton, File, Folder, Tree, type TreeViewElement };
|
|
38
|
+
export type { TreeSortMode };
|
|
39
|
+
//# sourceMappingURL=file-tree.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tree.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/components/ui/file-tree.tsx"],"names":[],"mappings":"AAEA,OAAO,KAON,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,SAAS,IAAI,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAO3D,UAAU,eAAe;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IACzB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,KAAK,YAAY,GAAG,SAAS,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,CAAC,EAAE,eAAe,KAAK,MAAM,CAAC,CAAC;AAsH9F,QAAA,MAAM,IAAI;wBAZY,MAAM;gBACd,OAAO;eACR,eAAe,EAAE;2BACL,MAAM,EAAE;eACpB,KAAK,CAAC,SAAS;gBACd,KAAK,CAAC,SAAS;WACpB,YAAY;+RA4GpB,CAAC;AA+BF,QAAA,MAAM,MAAM;oBANM,MAAM,EAAE;aACf,MAAM;mBACA,OAAO;eACX,OAAO;0KAuDnB,CAAC;AAIF,QAAA,MAAM,IAAI;WAGC,MAAM;mBACE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI;mBACpB,OAAO;eACX,OAAO;eACP,KAAK,CAAC,SAAS;2FA6C7B,CAAC;AAIF,QAAA,MAAM,cAAc;cAGN,eAAe,EAAE;gBACf,OAAO;qFAmDrB,CAAC;AAIH,OAAO,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,eAAe,EAAE,CAAC;AACpE,YAAY,EAAE,YAAY,EAAE,CAAC"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { createContext, forwardRef, useCallback, useContext, useEffect, useState, } from 'react';
|
|
4
|
+
import { Accordion as AccordionPrimitive } from 'radix-ui';
|
|
5
|
+
import { FileIcon, FolderIcon, FolderOpenIcon } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../lib/utils.js';
|
|
7
|
+
import { Button } from '../ui/button.js';
|
|
8
|
+
import { ScrollArea } from '../ui/scroll-area.js';
|
|
9
|
+
const TreeContext = createContext(null);
|
|
10
|
+
const useTree = () => {
|
|
11
|
+
const context = useContext(TreeContext);
|
|
12
|
+
if (!context) {
|
|
13
|
+
throw new Error('useTree must be used within a TreeProvider');
|
|
14
|
+
}
|
|
15
|
+
return context;
|
|
16
|
+
};
|
|
17
|
+
const isFolderElement = (element) => {
|
|
18
|
+
if (element.type) {
|
|
19
|
+
return element.type === 'folder';
|
|
20
|
+
}
|
|
21
|
+
return Array.isArray(element.children);
|
|
22
|
+
};
|
|
23
|
+
const mergeExpandedItems = (currentItems, nextItems) => [
|
|
24
|
+
...new Set([...(currentItems ?? []), ...nextItems]),
|
|
25
|
+
];
|
|
26
|
+
const treeCollator = new Intl.Collator('en', {
|
|
27
|
+
numeric: true,
|
|
28
|
+
sensitivity: 'base',
|
|
29
|
+
});
|
|
30
|
+
const defaultTreeComparator = (a, b) => {
|
|
31
|
+
const aIsFolder = isFolderElement(a);
|
|
32
|
+
const bIsFolder = isFolderElement(b);
|
|
33
|
+
if (aIsFolder !== bIsFolder) {
|
|
34
|
+
return aIsFolder ? -1 : 1;
|
|
35
|
+
}
|
|
36
|
+
return treeCollator.compare(a.name, b.name);
|
|
37
|
+
};
|
|
38
|
+
const getTreeComparator = (sort) => {
|
|
39
|
+
if (sort === 'none') {
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
if (sort === 'default') {
|
|
43
|
+
return defaultTreeComparator;
|
|
44
|
+
}
|
|
45
|
+
return sort;
|
|
46
|
+
};
|
|
47
|
+
const sortTreeElements = (elements, sort) => {
|
|
48
|
+
const comparator = getTreeComparator(sort);
|
|
49
|
+
const nextElements = elements.map((element) => {
|
|
50
|
+
if (!Array.isArray(element.children)) {
|
|
51
|
+
return element;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
...element,
|
|
55
|
+
children: sortTreeElements(element.children, sort),
|
|
56
|
+
};
|
|
57
|
+
});
|
|
58
|
+
if (!comparator) {
|
|
59
|
+
return nextElements;
|
|
60
|
+
}
|
|
61
|
+
return [...nextElements].sort(comparator);
|
|
62
|
+
};
|
|
63
|
+
const renderTreeElements = (elements, sort) => sortTreeElements(elements, sort).map((element) => {
|
|
64
|
+
if (isFolderElement(element)) {
|
|
65
|
+
return (_jsx(Folder, { value: element.id, element: element.name, isSelectable: element.isSelectable, children: Array.isArray(element.children) ? renderTreeElements(element.children, sort) : null }, element.id));
|
|
66
|
+
}
|
|
67
|
+
return (_jsx(File, { value: element.id, isSelectable: element.isSelectable, children: _jsx("span", { children: element.name }) }, element.id));
|
|
68
|
+
});
|
|
69
|
+
const Tree = forwardRef(({ className, elements, initialSelectedId, initialExpandedItems, children, indicator = true, openIcon, closeIcon, sort = 'default', dir, ...props }, ref) => {
|
|
70
|
+
const [selectedId, setSelectedId] = useState(initialSelectedId);
|
|
71
|
+
const [expandedItems, setExpandedItems] = useState(initialExpandedItems);
|
|
72
|
+
const selectItem = useCallback((id) => {
|
|
73
|
+
setSelectedId(id);
|
|
74
|
+
}, []);
|
|
75
|
+
const handleExpand = useCallback((id) => {
|
|
76
|
+
setExpandedItems((prev) => {
|
|
77
|
+
if (prev?.includes(id)) {
|
|
78
|
+
return prev.filter((item) => item !== id);
|
|
79
|
+
}
|
|
80
|
+
return [...(prev ?? []), id];
|
|
81
|
+
});
|
|
82
|
+
}, []);
|
|
83
|
+
const expandSpecificTargetedElements = useCallback((elements, selectId) => {
|
|
84
|
+
if (!elements || !selectId)
|
|
85
|
+
return;
|
|
86
|
+
const findParent = (currentElement, currentPath = []) => {
|
|
87
|
+
const isSelectable = currentElement.isSelectable ?? true;
|
|
88
|
+
const newPath = [...currentPath, currentElement.id];
|
|
89
|
+
if (currentElement.id === selectId) {
|
|
90
|
+
if (isSelectable) {
|
|
91
|
+
setExpandedItems((prev) => mergeExpandedItems(prev, newPath));
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
if (newPath.includes(currentElement.id)) {
|
|
95
|
+
newPath.pop();
|
|
96
|
+
setExpandedItems((prev) => mergeExpandedItems(prev, newPath));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
if (Array.isArray(currentElement.children) && currentElement.children.length > 0) {
|
|
102
|
+
currentElement.children.forEach((child) => {
|
|
103
|
+
findParent(child, newPath);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
elements.forEach((element) => {
|
|
108
|
+
findParent(element);
|
|
109
|
+
});
|
|
110
|
+
}, []);
|
|
111
|
+
useEffect(() => {
|
|
112
|
+
if (initialSelectedId) {
|
|
113
|
+
expandSpecificTargetedElements(elements, initialSelectedId);
|
|
114
|
+
}
|
|
115
|
+
}, [initialSelectedId, elements, expandSpecificTargetedElements]);
|
|
116
|
+
const direction = dir === 'rtl' ? 'rtl' : 'ltr';
|
|
117
|
+
const treeChildren = children ?? (elements ? renderTreeElements(elements, sort) : null);
|
|
118
|
+
return (_jsx(TreeContext.Provider, { value: {
|
|
119
|
+
selectedId,
|
|
120
|
+
expandedItems,
|
|
121
|
+
handleExpand,
|
|
122
|
+
selectItem,
|
|
123
|
+
setExpandedItems,
|
|
124
|
+
indicator,
|
|
125
|
+
openIcon,
|
|
126
|
+
closeIcon,
|
|
127
|
+
direction,
|
|
128
|
+
}, children: _jsx("div", { className: cn('size-full', className), children: _jsx(ScrollArea, { ref: ref, className: "relative h-full px-2", dir: dir, children: _jsx(AccordionPrimitive.Root, { ...props, type: "multiple", value: expandedItems, className: "flex flex-col gap-1", dir: dir, children: treeChildren }) }) }) }));
|
|
129
|
+
});
|
|
130
|
+
Tree.displayName = 'Tree';
|
|
131
|
+
const TreeIndicator = forwardRef(({ className, ...props }, ref) => {
|
|
132
|
+
const { direction } = useTree();
|
|
133
|
+
return (_jsx("div", { dir: direction, ref: ref, className: cn('bg-muted absolute left-1.5 h-full w-px rounded-md py-3 duration-300 ease-in-out hover:bg-slate-300 rtl:right-1.5', className), ...props }));
|
|
134
|
+
});
|
|
135
|
+
TreeIndicator.displayName = 'TreeIndicator';
|
|
136
|
+
const Folder = forwardRef(({ className, element, value, isSelectable = true, isSelect, children, ...props }, ref) => {
|
|
137
|
+
const { direction, handleExpand, expandedItems, indicator, selectedId, selectItem, openIcon, closeIcon, } = useTree();
|
|
138
|
+
const isSelected = isSelect ?? selectedId === value;
|
|
139
|
+
return (_jsxs(AccordionPrimitive.Item, { ref: ref, ...props, value: value, className: "relative h-full overflow-hidden", children: [_jsxs(AccordionPrimitive.Trigger, { className: cn('flex items-center gap-1 rounded-md text-sm', className, {
|
|
140
|
+
'bg-muted rounded-md': isSelected && isSelectable,
|
|
141
|
+
'cursor-pointer': isSelectable,
|
|
142
|
+
'cursor-not-allowed opacity-50': !isSelectable,
|
|
143
|
+
}), disabled: !isSelectable, onClick: () => {
|
|
144
|
+
selectItem(value);
|
|
145
|
+
handleExpand(value);
|
|
146
|
+
}, children: [expandedItems?.includes(value)
|
|
147
|
+
? (openIcon ?? _jsx(FolderOpenIcon, { className: "size-4" }))
|
|
148
|
+
: (closeIcon ?? _jsx(FolderIcon, { className: "size-4" })), _jsx("span", { children: element })] }), _jsxs(AccordionPrimitive.Content, { className: "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down relative h-full overflow-hidden text-sm", children: [element && indicator ? _jsx(TreeIndicator, { "aria-hidden": "true" }) : null, _jsx(AccordionPrimitive.Root, { dir: direction, type: "multiple", className: "ml-5 flex flex-col gap-1 py-1 rtl:mr-5", value: expandedItems, children: children })] })] }));
|
|
149
|
+
});
|
|
150
|
+
Folder.displayName = 'Folder';
|
|
151
|
+
const File = forwardRef(({ value, className, handleSelect, onClick, isSelectable = true, isSelect, fileIcon, children, ...props }, ref) => {
|
|
152
|
+
const { direction, selectedId, selectItem } = useTree();
|
|
153
|
+
const isSelected = isSelect ?? selectedId === value;
|
|
154
|
+
return (_jsxs("button", { ref: ref, type: "button", disabled: !isSelectable, className: cn('flex w-fit items-center gap-1 rounded-md pr-1 text-sm duration-200 ease-in-out rtl:pr-0 rtl:pl-1', {
|
|
155
|
+
'bg-muted': isSelected && isSelectable,
|
|
156
|
+
}, isSelectable ? 'cursor-pointer' : 'cursor-not-allowed opacity-50', direction === 'rtl' ? 'rtl' : 'ltr', className), onClick: (event) => {
|
|
157
|
+
selectItem(value);
|
|
158
|
+
handleSelect?.(value);
|
|
159
|
+
onClick?.(event);
|
|
160
|
+
}, ...props, children: [fileIcon ?? _jsx(FileIcon, { className: "size-4" }), children] }));
|
|
161
|
+
});
|
|
162
|
+
File.displayName = 'File';
|
|
163
|
+
const CollapseButton = forwardRef(({ className, elements, expandAll = false, children, ...props }, ref) => {
|
|
164
|
+
const { expandedItems, setExpandedItems } = useTree();
|
|
165
|
+
const expendAllTree = useCallback((elements) => {
|
|
166
|
+
const expandedElementIds = [];
|
|
167
|
+
const expandTree = (element) => {
|
|
168
|
+
const isSelectable = element.isSelectable ?? true;
|
|
169
|
+
if (isSelectable && element.children && element.children.length > 0) {
|
|
170
|
+
expandedElementIds.push(element.id);
|
|
171
|
+
for (const child of element.children) {
|
|
172
|
+
expandTree(child);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
};
|
|
176
|
+
for (const element of elements) {
|
|
177
|
+
expandTree(element);
|
|
178
|
+
}
|
|
179
|
+
return [...new Set(expandedElementIds)];
|
|
180
|
+
}, []);
|
|
181
|
+
const closeAll = useCallback(() => {
|
|
182
|
+
setExpandedItems?.([]);
|
|
183
|
+
}, [setExpandedItems]);
|
|
184
|
+
useEffect(() => {
|
|
185
|
+
if (expandAll) {
|
|
186
|
+
setExpandedItems?.(expendAllTree(elements));
|
|
187
|
+
}
|
|
188
|
+
}, [expandAll, elements, expendAllTree, setExpandedItems]);
|
|
189
|
+
return (_jsxs(Button, { variant: "ghost", className: cn('absolute right-2 bottom-1 h-8 w-fit p-1', className), onClick: expandedItems && expandedItems.length > 0
|
|
190
|
+
? closeAll
|
|
191
|
+
: () => setExpandedItems?.(expendAllTree(elements)), ref: ref, ...props, children: [children, _jsx("span", { className: "sr-only", children: "Toggle" })] }));
|
|
192
|
+
});
|
|
193
|
+
CollapseButton.displayName = 'CollapseButton';
|
|
194
|
+
export { CollapseButton, File, Folder, Tree };
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { Tree } from './file-tree.js';
|
|
3
|
+
declare const meta: Meta<typeof Tree>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof Tree>;
|
|
6
|
+
/** Default file tree with folders expanded. */
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
/** Collapsed tree — no items initially expanded. */
|
|
9
|
+
export declare const Collapsed: Story;
|
|
10
|
+
/** Single file — no folders. */
|
|
11
|
+
export declare const SingleFile: Story;
|
|
12
|
+
/** Deeply nested structure. */
|
|
13
|
+
export declare const DeepNesting: Story;
|
|
14
|
+
//# sourceMappingURL=file-tree.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-tree.stories.d.ts","sourceRoot":"","sources":["../../../../../../src/presentation/web/components/ui/file-tree.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,IAAI,EAAwB,MAAM,aAAa,CAAC;AAkCzD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,CAc3B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,+CAA+C;AAC/C,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,oDAAoD;AACpD,eAAO,MAAM,SAAS,EAAE,KAIvB,CAAC;AAEF,gCAAgC;AAChC,eAAO,MAAM,UAAU,EAAE,KAIxB,CAAC;AAEF,+BAA+B;AAC/B,eAAO,MAAM,WAAW,EAAE,KA0BzB,CAAC"}
|