@shepai/cli 1.110.1 → 1.110.2-pr343.55002ac
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/node-helpers.d.ts +1 -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 +3 -2
- package/dist/src/presentation/web/components/common/merge-review/index.d.ts +1 -0
- package/dist/src/presentation/web/components/common/merge-review/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/index.js +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-diff-viewer.d.ts +7 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-diff-viewer.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-diff-viewer.js +160 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-diff-viewer.stories.d.ts +18 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-diff-viewer.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-diff-viewer.stories.js +240 -0
- package/dist/src/presentation/web/components/common/merge-review/merge-review.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/merge-review/merge-review.js +2 -2
- package/dist/src/presentation/web/components/ui/code-block.d.ts +28 -0
- package/dist/src/presentation/web/components/ui/code-block.d.ts.map +1 -0
- package/dist/src/presentation/web/components/ui/code-block.js +47 -0
- package/dist/src/presentation/web/components/ui/code-block.stories.d.ts +16 -0
- package/dist/src/presentation/web/components/ui/code-block.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/ui/code-block.stories.js +89 -0
- package/dist/src/presentation/web/components/ui/file-tree.d.ts +22 -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 +61 -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 +116 -0
- package/dist/tsconfig.build.tsbuildinfo +1 -1
- package/package.json +2 -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/create/page/server-reference-manifest.json +20 -20
- 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 +26 -26
- 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 +26 -26
- 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 +18 -18
- 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 +20 -20
- 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 +26 -26
- 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 +26 -26
- 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 +18 -18
- 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 +18 -18
- 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 +1 -1
- 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/settings/page/server-reference-manifest.json +5 -5
- 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 +6 -6
- 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 +6 -6
- 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 +1 -1
- 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_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/7f428_lucide-react_dist_esm_icons_d0119342._.js +1 -1
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_d0119342._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_a1104008.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_92642200.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__039967e3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__07a39ff2._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__11033878._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__24dd0927._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2773312c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5d87af2e._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__89e8a5cc._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__cbd8062c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d52e4ffa._.js +4 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d52e4ffa._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d91fdd51._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__d91fdd51._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__e70c5627._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f4e2e929._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f4e2e929._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fdc75809._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js +1 -1
- package/web/.next/server/chunks/ssr/_135edb9c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/_6d26a08f._.js +1 -1
- package/web/.next/server/chunks/ssr/_6d26a08f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_d4d44f39._.js → _72bc8b0e._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_d4d44f39._.js.map → _72bc8b0e._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js +1 -1
- package/web/.next/server/chunks/ssr/_8dacd1e7._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_f3c9f75e._.js → _ba7a3d30._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_f3c9f75e._.js.map → _ba7a3d30._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js +1 -1
- package/web/.next/server/chunks/ssr/_cc77a143._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_ccec5866._.js → _f728cbf8._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_ccec5866._.js.map → _f728cbf8._.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__next-internal_server_app_(dashboard)_page_actions_888633e1.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_888633e1.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_skills_page_actions_1fa8042e.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_tools_page_actions_24684200.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_ce7cbc3c._.js.map +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_bf50c527._.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_de814675._.js +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/chunks/ssr/src_presentation_web_e2604413._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_e2604413._.js.map +1 -1
- 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 +31 -31
- package/web/.next/static/chunks/{0abe4c1aa4868d43.js → 05417418b2a9cee3.js} +1 -1
- package/web/.next/static/chunks/{fd69e290a23f42db.js → 101ecf26d6966833.js} +1 -1
- package/web/.next/static/chunks/{d2696b56eaa27811.js → 1337f3e3c08718c7.js} +1 -1
- package/web/.next/static/chunks/2ec28c90ceaf4a13.js +11 -0
- package/web/.next/static/chunks/302445eb4ccd97da.css +1 -0
- package/web/.next/static/chunks/31776630de2d206b.js +1 -0
- package/web/.next/static/chunks/{c5d0ea070fd28a5f.js → 3a91978763f307a4.js} +1 -1
- package/web/.next/static/chunks/4943e3f713ca59b9.js +1 -0
- package/web/.next/static/chunks/{ff30b8acb47c382f.js → 7a5a5fd6ca5f68b0.js} +1 -1
- package/web/.next/static/chunks/aa4d2f43278ff233.js +2 -0
- package/web/.next/static/chunks/c271f980766af122.js +1 -0
- package/web/.next/static/chunks/{1b53abdc3e0915fa.js → c2cf5f8de6e440f4.js} +1 -1
- package/web/.next/static/chunks/d721d84d863d8f7d.js +1 -0
- package/web/.next/static/chunks/db88d096c40852ed.js +1 -0
- package/web/.next/static/chunks/{d332c5a1d5b931b6.js → f9b654bc46c065d1.js} +2 -2
- package/web/package.json +3 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__845a9d2a._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +0 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js.map +0 -1
- package/web/.next/static/chunks/07b853e29af1e5f2.js +0 -1
- package/web/.next/static/chunks/303a1217006489b9.js +0 -1
- package/web/.next/static/chunks/4e97c46640657f42.js +0 -11
- package/web/.next/static/chunks/5543614d36607aef.js +0 -1
- package/web/.next/static/chunks/5558a658fa82a01f.css +0 -1
- package/web/.next/static/chunks/d14c7aec739301f8.js +0 -2
- package/web/.next/static/chunks/d7fa87cf3302ec81.js +0 -1
- /package/web/.next/static/{OhzCWJVe_Ly9xvRRY6B0s → kP5AxZfxARVpUZmGJasAa}/_buildManifest.js +0 -0
- /package/web/.next/static/{OhzCWJVe_Ly9xvRRY6B0s → kP5AxZfxARVpUZmGJasAa}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{OhzCWJVe_Ly9xvRRY6B0s → kP5AxZfxARVpUZmGJasAa}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { CodeBlock } from './code-block.js';
|
|
2
|
+
const sampleTsx = `import { useState } from 'react';
|
|
3
|
+
import { Button } from '../ui/button.js';
|
|
4
|
+
|
|
5
|
+
export function Counter() {
|
|
6
|
+
const [count, setCount] = useState(0);
|
|
7
|
+
|
|
8
|
+
return (
|
|
9
|
+
<div className="flex items-center gap-2">
|
|
10
|
+
<span>{count}</span>
|
|
11
|
+
<Button onClick={() => setCount(count + 1)}>Increment</Button>
|
|
12
|
+
</div>
|
|
13
|
+
);
|
|
14
|
+
}`;
|
|
15
|
+
const sampleCss = `body {
|
|
16
|
+
font-family: sans-serif;
|
|
17
|
+
margin: 0;
|
|
18
|
+
padding: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.container {
|
|
22
|
+
max-width: 1200px;
|
|
23
|
+
margin: 0 auto;
|
|
24
|
+
}`;
|
|
25
|
+
const meta = {
|
|
26
|
+
title: 'Primitives/CodeBlock',
|
|
27
|
+
component: CodeBlock,
|
|
28
|
+
parameters: {
|
|
29
|
+
layout: 'padded',
|
|
30
|
+
},
|
|
31
|
+
tags: ['autodocs'],
|
|
32
|
+
};
|
|
33
|
+
export default meta;
|
|
34
|
+
/** Default — single code block with syntax highlighting. */
|
|
35
|
+
export const Default = {
|
|
36
|
+
args: {
|
|
37
|
+
language: 'tsx',
|
|
38
|
+
filename: 'Counter.tsx',
|
|
39
|
+
code: sampleTsx,
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
/** Highlighted lines to draw attention to specific code. */
|
|
43
|
+
export const HighlightedLines = {
|
|
44
|
+
args: {
|
|
45
|
+
language: 'tsx',
|
|
46
|
+
filename: 'Counter.tsx',
|
|
47
|
+
code: sampleTsx,
|
|
48
|
+
highlightLines: [4, 5, 6],
|
|
49
|
+
},
|
|
50
|
+
};
|
|
51
|
+
/** Tabbed code view with multiple files. */
|
|
52
|
+
export const WithTabs = {
|
|
53
|
+
args: {
|
|
54
|
+
language: 'tsx',
|
|
55
|
+
filename: 'App.tsx',
|
|
56
|
+
tabs: [
|
|
57
|
+
{ name: 'Counter.tsx', code: sampleTsx, language: 'tsx' },
|
|
58
|
+
{ name: 'styles.css', code: sampleCss, language: 'css' },
|
|
59
|
+
],
|
|
60
|
+
},
|
|
61
|
+
};
|
|
62
|
+
/** JSON content. */
|
|
63
|
+
export const JsonContent = {
|
|
64
|
+
args: {
|
|
65
|
+
language: 'json',
|
|
66
|
+
filename: 'package.json',
|
|
67
|
+
code: JSON.stringify({ name: '@my/package', version: '1.0.0', dependencies: { react: '^18.0.0' } }, null, 2),
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
const sampleDiff = ` import { useState } from 'react';
|
|
71
|
+
import { Button } from '../ui/button.js';
|
|
72
|
+
+ import { Input } from '../ui/input.js';
|
|
73
|
+
+ import { Label } from '../ui/label.js';
|
|
74
|
+
|
|
75
|
+
- export function LoginForm() {
|
|
76
|
+
+ export function LoginForm({ onSubmit }: LoginFormProps) {
|
|
77
|
+
const [email, setEmail] = useState('');
|
|
78
|
+
const [password, setPassword] = useState('');
|
|
79
|
+
+ const [isLoading, setIsLoading] = useState(false);`;
|
|
80
|
+
/** Diff-style highlighting with green (added) and red (removed) backgrounds. */
|
|
81
|
+
export const DiffHighlighting = {
|
|
82
|
+
args: {
|
|
83
|
+
language: 'tsx',
|
|
84
|
+
filename: 'login-form.tsx',
|
|
85
|
+
code: sampleDiff,
|
|
86
|
+
addedLines: [3, 4, 7, 10],
|
|
87
|
+
removedLines: [6],
|
|
88
|
+
},
|
|
89
|
+
};
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/** A node in the file tree data model. */
|
|
3
|
+
export interface TreeViewElement {
|
|
4
|
+
id: string;
|
|
5
|
+
name: string;
|
|
6
|
+
type?: 'file' | 'folder';
|
|
7
|
+
isSelectable?: boolean;
|
|
8
|
+
children?: TreeViewElement[];
|
|
9
|
+
/** Optional custom icon for file nodes. */
|
|
10
|
+
icon?: React.ReactNode;
|
|
11
|
+
/** Optional badge/suffix rendered after the name (e.g. "+5 -2" for diffs). */
|
|
12
|
+
badge?: React.ReactNode;
|
|
13
|
+
}
|
|
14
|
+
export interface TreeProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
15
|
+
elements: TreeViewElement[];
|
|
16
|
+
initialSelectedId?: string;
|
|
17
|
+
initialExpandedItems?: string[];
|
|
18
|
+
indicator?: boolean;
|
|
19
|
+
onSelectChange?: (id: string) => void;
|
|
20
|
+
}
|
|
21
|
+
export declare function Tree({ elements, initialSelectedId, initialExpandedItems, indicator, onSelectChange, className, ...props }: TreeProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
//# 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,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,0CAA0C;AAC1C,MAAM,WAAW,eAAe;IAC9B,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;IAC7B,2CAA2C;IAC3C,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,8EAA8E;IAC9E,KAAK,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CACzB;AAoBD,MAAM,WAAW,SAAU,SAAQ,KAAK,CAAC,cAAc,CAAC,cAAc,CAAC;IACrE,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,oBAAoB,CAAC,EAAE,MAAM,EAAE,CAAC;IAChC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,cAAc,CAAC,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAC;CACvC;AAaD,wBAAgB,IAAI,CAAC,EACnB,QAAQ,EACR,iBAAiB,EACjB,oBAAoB,EACpB,SAAgB,EAChB,cAAc,EACd,SAAS,EACT,GAAG,KAAK,EACT,EAAE,SAAS,2CA2CX"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import * as React from 'react';
|
|
4
|
+
import { Accordion as AccordionPrimitive } from 'radix-ui';
|
|
5
|
+
import { FileIcon, FolderIcon, FolderOpenIcon, ChevronRight } from 'lucide-react';
|
|
6
|
+
import { cn } from '../../lib/utils.js';
|
|
7
|
+
import { ScrollArea } from '../ui/scroll-area.js';
|
|
8
|
+
const TreeContext = React.createContext(undefined);
|
|
9
|
+
function useTree() {
|
|
10
|
+
const ctx = React.useContext(TreeContext);
|
|
11
|
+
if (!ctx)
|
|
12
|
+
throw new Error('useTree must be used within a Tree');
|
|
13
|
+
return ctx;
|
|
14
|
+
}
|
|
15
|
+
function collectFolderIds(elements) {
|
|
16
|
+
const ids = [];
|
|
17
|
+
for (const el of elements) {
|
|
18
|
+
if (el.children && el.children.length > 0) {
|
|
19
|
+
ids.push(el.id);
|
|
20
|
+
ids.push(...collectFolderIds(el.children));
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return ids;
|
|
24
|
+
}
|
|
25
|
+
export function Tree({ elements, initialSelectedId, initialExpandedItems, indicator = true, onSelectChange, className, ...props }) {
|
|
26
|
+
const [selectedId, setSelectedId] = React.useState(initialSelectedId);
|
|
27
|
+
const [expandedItems, setExpandedItems] = React.useState(() => initialExpandedItems ?? collectFolderIds(elements));
|
|
28
|
+
const handleSelect = React.useCallback((id) => {
|
|
29
|
+
setSelectedId(id);
|
|
30
|
+
onSelectChange?.(id);
|
|
31
|
+
}, [onSelectChange]);
|
|
32
|
+
const handleExpand = React.useCallback((id) => {
|
|
33
|
+
setExpandedItems((prev) => prev.includes(id) ? prev.filter((item) => item !== id) : [...prev, id]);
|
|
34
|
+
}, []);
|
|
35
|
+
const ctx = React.useMemo(() => ({ selectedId, expandedItems, handleSelect, handleExpand, indicator }), [selectedId, expandedItems, handleSelect, handleExpand, indicator]);
|
|
36
|
+
return (_jsx(TreeContext.Provider, { value: ctx, children: _jsx("div", { className: cn('relative overflow-hidden rounded-md', className), ...props, children: _jsx(ScrollArea, { className: "h-full", children: _jsx(AccordionPrimitive.Root, { type: "multiple", value: expandedItems, onValueChange: setExpandedItems, className: "flex flex-col gap-px", children: elements.map((el) => (_jsx(TreeNode, { element: el, depth: 0 }, el.id))) }) }) }) }));
|
|
37
|
+
}
|
|
38
|
+
/* ─── Internal recursive node ─── */
|
|
39
|
+
function TreeNode({ element, depth }) {
|
|
40
|
+
const isFolder = element.type === 'folder' || (element.children && element.children.length > 0);
|
|
41
|
+
if (isFolder) {
|
|
42
|
+
return _jsx(FolderNode, { element: element, depth: depth });
|
|
43
|
+
}
|
|
44
|
+
return _jsx(FileNode, { element: element, depth: depth, fileIcon: element.icon });
|
|
45
|
+
}
|
|
46
|
+
function FolderNode({ element, depth }) {
|
|
47
|
+
const { selectedId, expandedItems, handleSelect, indicator } = useTree();
|
|
48
|
+
const isSelected = selectedId === element.id;
|
|
49
|
+
const isOpen = expandedItems.includes(element.id);
|
|
50
|
+
return (_jsxs(AccordionPrimitive.Item, { value: element.id, className: "relative", children: [indicator && depth > 0 ? (_jsx("span", { className: "bg-muted absolute top-0 left-3 h-full w-px", style: { marginLeft: `${(depth - 1) * 16}px` } })) : null, _jsxs(AccordionPrimitive.Trigger, { className: cn('hover:bg-muted/80 flex w-full cursor-pointer items-center gap-1.5 rounded-sm px-2 py-1 text-xs', isSelected && 'bg-muted'), style: { paddingLeft: `${depth * 16 + 8}px` }, onClick: (e) => {
|
|
51
|
+
if (element.isSelectable !== false) {
|
|
52
|
+
e.stopPropagation();
|
|
53
|
+
handleSelect(element.id);
|
|
54
|
+
}
|
|
55
|
+
}, children: [_jsx(ChevronRight, { className: cn('text-muted-foreground h-3 w-3 shrink-0 transition-transform duration-150', isOpen && 'rotate-90') }), isOpen ? (_jsx(FolderOpenIcon, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" })) : (_jsx(FolderIcon, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" })), _jsx("span", { className: "text-foreground truncate", children: element.name })] }), _jsx(AccordionPrimitive.Content, { className: "data-[state=closed]:animate-accordion-up data-[state=open]:animate-accordion-down overflow-hidden", children: element.children?.map((child) => (_jsx(TreeNode, { element: child, depth: depth + 1 }, child.id))) })] }));
|
|
56
|
+
}
|
|
57
|
+
function FileNode({ element, depth, fileIcon, }) {
|
|
58
|
+
const { selectedId, handleSelect, indicator } = useTree();
|
|
59
|
+
const isSelected = selectedId === element.id;
|
|
60
|
+
return (_jsxs("div", { className: "relative", children: [indicator && depth > 0 ? (_jsx("span", { className: "bg-muted absolute top-0 left-3 h-full w-px", style: { marginLeft: `${(depth - 1) * 16}px` } })) : null, _jsxs("button", { type: "button", className: cn('hover:bg-muted/80 flex w-full cursor-pointer items-center gap-1.5 rounded-sm px-2 py-1 text-xs', isSelected && 'bg-accent text-accent-foreground'), style: { paddingLeft: `${depth * 16 + 8 + 16}px` }, onClick: () => element.isSelectable !== false && handleSelect(element.id), children: [fileIcon ?? _jsx(FileIcon, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" }), _jsx("span", { className: "min-w-0 flex-1 truncate", children: element.name }), element.badge ? _jsx("span", { className: "shrink-0", children: element.badge }) : null] })] }));
|
|
61
|
+
}
|
|
@@ -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 — hierarchical file tree with diff badges. */
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
/** Without indicator lines. */
|
|
9
|
+
export declare const NoIndicator: Story;
|
|
10
|
+
/** Flat file list (no folders). */
|
|
11
|
+
export declare const FlatList: Story;
|
|
12
|
+
/** Single file. */
|
|
13
|
+
export declare const SingleFile: 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;AAEvD,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AA6EnC,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,IAAI,CAqB3B,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,IAAI,CAAC,CAAC;AAEnC,yDAAyD;AACzD,eAAO,MAAM,OAAO,EAAE,KAKrB,CAAC;AAEF,+BAA+B;AAC/B,eAAO,MAAM,WAAW,EAAE,KAKzB,CAAC;AAEF,mCAAmC;AACnC,eAAO,MAAM,QAAQ,EAAE,KAQtB,CAAC;AAEF,mBAAmB;AACnB,eAAO,MAAM,UAAU,EAAE,KAYxB,CAAC"}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { FilePlus, FileEdit, FileMinus } from 'lucide-react';
|
|
3
|
+
import { Tree } from './file-tree.js';
|
|
4
|
+
const sampleElements = [
|
|
5
|
+
{
|
|
6
|
+
id: 'src',
|
|
7
|
+
name: 'src',
|
|
8
|
+
type: 'folder',
|
|
9
|
+
children: [
|
|
10
|
+
{
|
|
11
|
+
id: 'src/components',
|
|
12
|
+
name: 'components',
|
|
13
|
+
type: 'folder',
|
|
14
|
+
children: [
|
|
15
|
+
{
|
|
16
|
+
id: 'src/components/button.tsx',
|
|
17
|
+
name: 'button.tsx',
|
|
18
|
+
type: 'file',
|
|
19
|
+
icon: _jsx(FileEdit, { className: "h-3.5 w-3.5 shrink-0 text-amber-600" }),
|
|
20
|
+
badge: (_jsxs("span", { className: "flex items-center gap-1 text-[10px]", children: [_jsx("span", { className: "text-green-600", children: "+12" }), _jsx("span", { className: "text-red-600", children: "-3" })] })),
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
id: 'src/components/input.tsx',
|
|
24
|
+
name: 'input.tsx',
|
|
25
|
+
type: 'file',
|
|
26
|
+
icon: _jsx(FilePlus, { className: "h-3.5 w-3.5 shrink-0 text-green-600" }),
|
|
27
|
+
badge: _jsx("span", { className: "text-[10px] text-green-600", children: "+45" }),
|
|
28
|
+
},
|
|
29
|
+
],
|
|
30
|
+
},
|
|
31
|
+
{
|
|
32
|
+
id: 'src/lib',
|
|
33
|
+
name: 'lib',
|
|
34
|
+
type: 'folder',
|
|
35
|
+
children: [
|
|
36
|
+
{
|
|
37
|
+
id: 'src/lib/utils.ts',
|
|
38
|
+
name: 'utils.ts',
|
|
39
|
+
type: 'file',
|
|
40
|
+
icon: _jsx(FileEdit, { className: "h-3.5 w-3.5 shrink-0 text-amber-600" }),
|
|
41
|
+
badge: (_jsxs("span", { className: "flex items-center gap-1 text-[10px]", children: [_jsx("span", { className: "text-green-600", children: "+5" }), _jsx("span", { className: "text-red-600", children: "-2" })] })),
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
},
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
id: 'package.json',
|
|
49
|
+
name: 'package.json',
|
|
50
|
+
type: 'file',
|
|
51
|
+
icon: _jsx(FileEdit, { className: "h-3.5 w-3.5 shrink-0 text-amber-600" }),
|
|
52
|
+
badge: (_jsxs("span", { className: "flex items-center gap-1 text-[10px]", children: [_jsx("span", { className: "text-green-600", children: "+1" }), _jsx("span", { className: "text-red-600", children: "-1" })] })),
|
|
53
|
+
},
|
|
54
|
+
{
|
|
55
|
+
id: 'old-file.ts',
|
|
56
|
+
name: 'old-file.ts',
|
|
57
|
+
type: 'file',
|
|
58
|
+
icon: _jsx(FileMinus, { className: "h-3.5 w-3.5 shrink-0 text-red-600" }),
|
|
59
|
+
badge: _jsx("span", { className: "text-[10px] text-red-600", children: "-20" }),
|
|
60
|
+
},
|
|
61
|
+
];
|
|
62
|
+
const meta = {
|
|
63
|
+
title: 'Primitives/FileTree',
|
|
64
|
+
component: Tree,
|
|
65
|
+
parameters: {
|
|
66
|
+
layout: 'padded',
|
|
67
|
+
},
|
|
68
|
+
tags: ['autodocs'],
|
|
69
|
+
decorators: [
|
|
70
|
+
(Story) => (_jsx("div", { style: {
|
|
71
|
+
width: 280,
|
|
72
|
+
height: 400,
|
|
73
|
+
border: '1px solid var(--color-border)',
|
|
74
|
+
borderRadius: 8,
|
|
75
|
+
}, children: _jsx(Story, {}) })),
|
|
76
|
+
],
|
|
77
|
+
};
|
|
78
|
+
export default meta;
|
|
79
|
+
/** Default — hierarchical file tree with diff badges. */
|
|
80
|
+
export const Default = {
|
|
81
|
+
args: {
|
|
82
|
+
elements: sampleElements,
|
|
83
|
+
initialSelectedId: 'src/components/button.tsx',
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
/** Without indicator lines. */
|
|
87
|
+
export const NoIndicator = {
|
|
88
|
+
args: {
|
|
89
|
+
elements: sampleElements,
|
|
90
|
+
indicator: false,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
/** Flat file list (no folders). */
|
|
94
|
+
export const FlatList = {
|
|
95
|
+
args: {
|
|
96
|
+
elements: [
|
|
97
|
+
{ id: 'README.md', name: 'README.md', type: 'file' },
|
|
98
|
+
{ id: 'index.ts', name: 'index.ts', type: 'file' },
|
|
99
|
+
{ id: 'package.json', name: 'package.json', type: 'file' },
|
|
100
|
+
],
|
|
101
|
+
},
|
|
102
|
+
};
|
|
103
|
+
/** Single file. */
|
|
104
|
+
export const SingleFile = {
|
|
105
|
+
args: {
|
|
106
|
+
elements: [
|
|
107
|
+
{
|
|
108
|
+
id: 'app.tsx',
|
|
109
|
+
name: 'app.tsx',
|
|
110
|
+
type: 'file',
|
|
111
|
+
icon: _jsx(FilePlus, { className: "h-3.5 w-3.5 shrink-0 text-green-600" }),
|
|
112
|
+
badge: _jsx("span", { className: "text-[10px] text-green-600", children: "+100" }),
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
},
|
|
116
|
+
};
|