@shepai/cli 1.90.1 → 1.91.0-pr271.bc71731
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/application/ports/output/services/worktree-service.interface.d.ts +6 -0
- package/dist/packages/core/src/application/ports/output/services/worktree-service.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/cleanup-feature-worktree.use-case.d.ts.map +1 -1
- package/dist/packages/core/src/application/use-cases/features/cleanup-feature-worktree.use-case.js +8 -0
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts +1 -0
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/git/worktree.service.js +8 -0
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts +2 -0
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.d.ts.map +1 -1
- package/dist/src/presentation/web/app/actions/get-feature-phase-timings.js +4 -0
- package/dist/src/presentation/web/app/api/attachments/preview/route.d.ts.map +1 -1
- package/dist/src/presentation/web/app/api/attachments/preview/route.js +47 -11
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts +29 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.js +83 -38
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.d.ts +13 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/activity-tab.stories.js +213 -0
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.js +2 -1
- package/dist/src/presentation/web/components/common/inline-attachments/index.d.ts +3 -0
- package/dist/src/presentation/web/components/common/inline-attachments/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/inline-attachments/index.js +1 -0
- package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.d.ts +20 -0
- package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.js +72 -0
- package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.stories.d.ts +16 -0
- package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.stories.js +46 -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 +1 -1
- package/web/.next/required-server-files.json +1 -1
- package/web/.next/server/app/(dashboard)/@drawer/create/page/server-reference-manifest.json +18 -18
- 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]/page/server-reference-manifest.json +21 -21
- 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 +14 -14
- 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 +18 -18
- 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]/page/server-reference-manifest.json +21 -21
- 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 +14 -14
- 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 +14 -14
- 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_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/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_client-reference-manifest.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__0b10355c._.js +1 -1
- package/web/.next/server/chunks/[root-of-the-server]__0b10355c._.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/7f428_lucide-react_dist_esm_icons_9027d30a._.js +1 -1
- package/web/.next/server/chunks/ssr/7f428_lucide-react_dist_esm_icons_9027d30a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_@drawer_repository_[repositoryId]_page_actions_da7eef33.js.map +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js +1 -1
- package/web/.next/server/chunks/ssr/8ba4b_server_app_(dashboard)_repository_[repositoryId]_page_actions_0a9251aa.js.map +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]__17143953._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__17143953._.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]__4be9a9bb._.js +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]__9de266fa._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9de266fa._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__aad040c0._.js +1 -1
- 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]__b3a4cef4._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b3a4cef4._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c2173b6d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__c2173b6d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__f0d8d054._.js +2 -2
- 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/_752e01fd._.js +1 -1
- package/web/.next/server/chunks/ssr/_752e01fd._.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/{_2fa756cd._.js → _c029c9a4._.js} +2 -2
- package/web/.next/server/chunks/ssr/{_2fa756cd._.js.map → _c029c9a4._.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/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_021a05f2.js +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web__next-internal_server_app_(dashboard)_page_actions_021a05f2.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_c4348b8a._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_c4348b8a._.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_bf50c527._.js.map +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_de814675._.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_e4510d10._.js +2 -2
- package/web/.next/server/chunks/ssr/src_presentation_web_e4510d10._.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 +28 -28
- package/web/.next/static/chunks/{54de5c2f98832b92.js → 14559ed26d88e209.js} +1 -1
- package/web/.next/static/chunks/2a09571d38368a18.css +2 -0
- package/web/.next/static/chunks/{4354b4b30513e7f0.js → 3093f97266ae10d2.js} +1 -1
- package/web/.next/static/chunks/3a43fa3b19c0e203.js +1 -0
- package/web/.next/static/chunks/{38bb02c07a427f1e.js → 3f93c36c5ff5804f.js} +1 -1
- package/web/.next/static/chunks/55e7ff9b53257d70.js +1 -0
- package/web/.next/static/chunks/{bb3e32c60cb2e794.js → 7571697c821fb8ab.js} +1 -1
- package/web/.next/static/chunks/{132ff681f7e12121.js → 92a959d71ebef998.js} +1 -1
- package/web/.next/static/chunks/{0cbb35f940c9feef.js → 93571cb544c4314b.js} +1 -1
- package/web/.next/static/chunks/{4906aba274bc6920.js → b0970305659496af.js} +1 -1
- package/web/.next/static/chunks/{7c7da9e978216d2b.js → cf9b9742eaa0597b.js} +1 -1
- package/web/.next/static/chunks/{c0f23bc23fd8b8ad.js → fc0e743fdc0af440.js} +1 -1
- package/web/.next/static/chunks/5c55da0e28e6cdc8.js +0 -1
- package/web/.next/static/chunks/cb5c85c5e16e82d3.js +0 -1
- package/web/.next/static/chunks/f98eb6cb17b61cb2.css +0 -2
- /package/web/.next/static/{o8F4OKh6WJmRpbTqaCZ67 → qb5URkkFh30LDQB9hFt8M}/_buildManifest.js +0 -0
- /package/web/.next/static/{o8F4OKh6WJmRpbTqaCZ67 → qb5URkkFh30LDQB9hFt8M}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{o8F4OKh6WJmRpbTqaCZ67 → qb5URkkFh30LDQB9hFt8M}/_ssgManifest.js +0 -0
package/dist/src/presentation/web/components/common/feature-drawer-tabs/overview-tab.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"overview-tab.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer-tabs/overview-tab.tsx"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAMxE,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,EAAE,gBAAgB,2CAwCrD"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { ExternalLink, GitBranch, GitCommitHorizontal, Zap } from 'lucide-react';
|
|
4
|
+
import { InlineAttachments } from '../../common/inline-attachments/index.js';
|
|
4
5
|
import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
5
6
|
import { cn } from '../../../lib/utils.js';
|
|
6
7
|
import { Badge } from '../../ui/badge.js';
|
|
@@ -50,7 +51,7 @@ function FeatureInfo({ data }) {
|
|
|
50
51
|
Boolean(data.createdAt);
|
|
51
52
|
if (!hasInfo)
|
|
52
53
|
return null;
|
|
53
|
-
return (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-info", className: "flex flex-col gap-3 p-4", children: [data.branch ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Branch" }), _jsxs("span", { className: "flex items-center gap-1.5 text-sm", children: [_jsx(GitBranch, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" }), _jsx("code", { className: "bg-muted rounded px-1 py-0.5 font-mono text-xs", children: data.branch }), data.baseBranch ? (_jsxs("span", { className: "text-muted-foreground text-xs", children: ["from ", data.baseBranch] })) : null] })] })) : null, data.oneLiner ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "One-Liner" }), _jsx("span", { className: "text-sm leading-relaxed", children: data.oneLiner })] })) : null, data.userQuery ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "User Query" }), _jsx(
|
|
54
|
+
return (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-info", className: "flex flex-col gap-3 p-4", children: [data.branch ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Branch" }), _jsxs("span", { className: "flex items-center gap-1.5 text-sm", children: [_jsx(GitBranch, { className: "text-muted-foreground h-3.5 w-3.5 shrink-0" }), _jsx("code", { className: "bg-muted rounded px-1 py-0.5 font-mono text-xs", children: data.branch }), data.baseBranch ? (_jsxs("span", { className: "text-muted-foreground text-xs", children: ["from ", data.baseBranch] })) : null] })] })) : null, data.oneLiner ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "One-Liner" }), _jsx("span", { className: "text-sm leading-relaxed", children: data.oneLiner })] })) : null, data.userQuery ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "User Query" }), _jsx(InlineAttachments, { text: data.userQuery })] })) : null, data.summary ? (_jsxs("div", { className: "flex flex-col gap-0.5", children: [_jsx("span", { className: "text-muted-foreground text-xs font-medium", children: "Summary" }), _jsx("span", { className: "text-sm leading-relaxed", children: data.summary })] })) : null, data.createdAt ? (_jsx(DetailRow, { label: "Created", value: formatRelativeTime(data.createdAt) })) : null] })] }));
|
|
54
55
|
}
|
|
55
56
|
// ── PR Info section ──────────────────────────────────────────────────
|
|
56
57
|
const prStatusStyles = {
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/inline-attachments/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,sBAAsB,CAAC;AAC9E,YAAY,EAAE,sBAAsB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { InlineAttachments, parseAttachmentRefs } from './inline-attachments.js';
|
package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.d.ts
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface InlineAttachmentsProps {
|
|
2
|
+
/** Text that may contain `@/path/to/file` attachment references. */
|
|
3
|
+
text: string;
|
|
4
|
+
/** Additional attachment paths to render (e.g. from rejection feedback). */
|
|
5
|
+
attachmentPaths?: string[];
|
|
6
|
+
}
|
|
7
|
+
interface TextSegment {
|
|
8
|
+
type: 'text';
|
|
9
|
+
value: string;
|
|
10
|
+
}
|
|
11
|
+
interface AttachmentSegment {
|
|
12
|
+
type: 'attachment';
|
|
13
|
+
path: string;
|
|
14
|
+
}
|
|
15
|
+
type Segment = TextSegment | AttachmentSegment;
|
|
16
|
+
/** Parse text into segments of plain text and attachment references. */
|
|
17
|
+
export declare function parseAttachmentRefs(text: string): Segment[];
|
|
18
|
+
export declare function InlineAttachments({ text, attachmentPaths }: InlineAttachmentsProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|
|
20
|
+
//# sourceMappingURL=inline-attachments.d.ts.map
|
package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline-attachments.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/inline-attachments/inline-attachments.tsx"],"names":[],"mappings":"AA6BA,MAAM,WAAW,sBAAsB;IACrC,oEAAoE;IACpE,IAAI,EAAE,MAAM,CAAC;IACb,4EAA4E;IAC5E,eAAe,CAAC,EAAE,MAAM,EAAE,CAAC;CAC5B;AAED,UAAU,WAAW;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;CACf;AAED,UAAU,iBAAiB;IACzB,IAAI,EAAE,YAAY,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,KAAK,OAAO,GAAG,WAAW,GAAG,iBAAiB,CAAC;AAE/C,wEAAwE;AACxE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAwB3D;AAED,wBAAgB,iBAAiB,CAAC,EAAE,IAAI,EAAE,eAAe,EAAE,EAAE,sBAAsB,2CA4BlF"}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/* eslint-disable @next/next/no-img-element -- Local file preview requires raw <img>, not next/image */
|
|
2
|
+
'use client';
|
|
3
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
4
|
+
import { useState } from 'react';
|
|
5
|
+
import { Dialog, DialogTrigger, DialogContent, DialogTitle } from '../../ui/dialog.js';
|
|
6
|
+
import { VisuallyHidden } from 'radix-ui';
|
|
7
|
+
import { DownloadIcon, ImageOff } from 'lucide-react';
|
|
8
|
+
const IMAGE_EXTS = new Set(['.png', '.jpg', '.jpeg', '.gif', '.svg', '.webp', '.ico', '.bmp']);
|
|
9
|
+
function isImagePath(path) {
|
|
10
|
+
const dot = path.lastIndexOf('.');
|
|
11
|
+
return dot >= 0 && IMAGE_EXTS.has(path.slice(dot).toLowerCase());
|
|
12
|
+
}
|
|
13
|
+
function previewUrl(path) {
|
|
14
|
+
const ext = path.lastIndexOf('.') >= 0 ? path.slice(path.lastIndexOf('.')) : '';
|
|
15
|
+
const mimeGuess = isImagePath(path) ? `image/${ext.slice(1).replace('jpg', 'jpeg')}` : '';
|
|
16
|
+
const params = new URLSearchParams({ path, ...(mimeGuess && { mimeType: mimeGuess }) });
|
|
17
|
+
return `/api/attachments/preview?${params.toString()}`;
|
|
18
|
+
}
|
|
19
|
+
function getFilename(path) {
|
|
20
|
+
return path.split('/').pop() ?? path;
|
|
21
|
+
}
|
|
22
|
+
/** Regex matching `@/absolute/path` attachment references in text. */
|
|
23
|
+
const ATTACHMENT_REF_RE = /(?:^|\s)@(\/[^\s]+)/g;
|
|
24
|
+
/** Parse text into segments of plain text and attachment references. */
|
|
25
|
+
export function parseAttachmentRefs(text) {
|
|
26
|
+
const segments = [];
|
|
27
|
+
let lastIndex = 0;
|
|
28
|
+
for (const match of text.matchAll(ATTACHMENT_REF_RE)) {
|
|
29
|
+
const fullMatchStart = match.index;
|
|
30
|
+
// The path capture starts after the optional leading whitespace
|
|
31
|
+
const leadingWs = match[0].length - match[0].trimStart().length;
|
|
32
|
+
const refStart = fullMatchStart + leadingWs;
|
|
33
|
+
// Add text before this reference (including leading whitespace)
|
|
34
|
+
if (refStart > lastIndex) {
|
|
35
|
+
segments.push({ type: 'text', value: text.slice(lastIndex, refStart) });
|
|
36
|
+
}
|
|
37
|
+
segments.push({ type: 'attachment', path: match[1] });
|
|
38
|
+
lastIndex = fullMatchStart + match[0].length;
|
|
39
|
+
}
|
|
40
|
+
if (lastIndex < text.length) {
|
|
41
|
+
segments.push({ type: 'text', value: text.slice(lastIndex) });
|
|
42
|
+
}
|
|
43
|
+
return segments;
|
|
44
|
+
}
|
|
45
|
+
export function InlineAttachments({ text, attachmentPaths }) {
|
|
46
|
+
const segments = parseAttachmentRefs(text);
|
|
47
|
+
const hasInlineAttachments = segments.some((s) => s.type === 'attachment');
|
|
48
|
+
const extraPaths = attachmentPaths?.filter(Boolean) ?? [];
|
|
49
|
+
if (!hasInlineAttachments && extraPaths.length === 0) {
|
|
50
|
+
return _jsx("span", { className: "text-sm leading-relaxed", children: text });
|
|
51
|
+
}
|
|
52
|
+
return (_jsxs("div", { className: "flex flex-col gap-2", children: [segments.map((segment) => {
|
|
53
|
+
if (segment.type === 'text') {
|
|
54
|
+
const trimmed = segment.value.trim();
|
|
55
|
+
if (!trimmed)
|
|
56
|
+
return null;
|
|
57
|
+
return (_jsx("span", { className: "text-sm leading-relaxed", children: trimmed }, `text-${trimmed.slice(0, 40)}`));
|
|
58
|
+
}
|
|
59
|
+
return _jsx(AttachmentPreview, { path: segment.path }, `att-${segment.path}`);
|
|
60
|
+
}), extraPaths.map((path) => (_jsx(AttachmentPreview, { path: path }, `extra-${path}`)))] }));
|
|
61
|
+
}
|
|
62
|
+
function AttachmentPreview({ path }) {
|
|
63
|
+
const filename = getFilename(path);
|
|
64
|
+
const [loadError, setLoadError] = useState(false);
|
|
65
|
+
if (isImagePath(path)) {
|
|
66
|
+
if (loadError) {
|
|
67
|
+
return (_jsxs("div", { "data-testid": "inline-attachment-image-error", className: "text-muted-foreground flex items-center gap-2 rounded-md border px-3 py-2 text-sm", children: [_jsx(ImageOff, { className: "h-4 w-4 shrink-0" }), _jsx("span", { className: "truncate", children: filename })] }));
|
|
68
|
+
}
|
|
69
|
+
return (_jsxs(Dialog, { children: [_jsx(DialogTrigger, { asChild: true, children: _jsx("img", { src: previewUrl(path), alt: filename, "data-testid": "inline-attachment-image", onError: () => setLoadError(true), className: "max-h-48 max-w-full cursor-pointer rounded-md border object-contain transition-opacity hover:opacity-80" }) }), _jsxs(DialogContent, { className: "max-w-3xl gap-0 overflow-hidden border-0 p-0 [&>button:last-child]:!cursor-pointer [&>button:last-child]:!rounded-full [&>button:last-child]:!bg-black/70 [&>button:last-child]:!p-1.5 [&>button:last-child]:!text-white [&>button:last-child]:!opacity-100 [&>button:last-child]:!shadow-lg [&>button:last-child]:!backdrop-blur-md [&>button:last-child]:hover:!bg-black/90", children: [_jsx(VisuallyHidden.Root, { children: _jsxs(DialogTitle, { children: ["Preview: ", filename] }) }), _jsx("div", { className: "relative bg-black/90", children: _jsx("img", { src: previewUrl(path), alt: filename, className: "h-auto max-h-[70vh] w-full object-contain" }) }), _jsxs("div", { className: "bg-background flex items-center gap-3 px-4 py-3", children: [_jsx("div", { className: "flex min-w-0 flex-1 flex-col", children: _jsx("span", { className: "truncate text-sm font-medium", children: filename }) }), _jsx("a", { href: previewUrl(path), download: filename, className: "text-muted-foreground hover:text-foreground shrink-0 cursor-pointer rounded p-1.5 transition-colors", "aria-label": `Download ${filename}`, children: _jsx(DownloadIcon, { className: "h-4 w-4" }) })] })] })] }));
|
|
70
|
+
}
|
|
71
|
+
return (_jsx("a", { href: previewUrl(path), download: filename, "data-testid": "inline-attachment-file", className: "text-primary text-sm underline underline-offset-2", children: filename }));
|
|
72
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { InlineAttachments } from './inline-attachments.js';
|
|
3
|
+
declare const meta: Meta<typeof InlineAttachments>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof InlineAttachments>;
|
|
6
|
+
/** Plain text with no attachment references. */
|
|
7
|
+
export declare const PlainText: Story;
|
|
8
|
+
/** Text with an image attachment reference. */
|
|
9
|
+
export declare const WithImageAttachment: Story;
|
|
10
|
+
/** Text with multiple attachment references. */
|
|
11
|
+
export declare const MultipleAttachments: Story;
|
|
12
|
+
/** Text with a non-image file attachment. */
|
|
13
|
+
export declare const FileAttachment: Story;
|
|
14
|
+
/** Extra attachment paths passed via prop (e.g. rejection feedback). */
|
|
15
|
+
export declare const ExtraAttachmentPaths: Story;
|
|
16
|
+
//# sourceMappingURL=inline-attachments.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inline-attachments.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/inline-attachments/inline-attachments.stories.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAEzD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,iBAAiB,CAYxC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAEhD,gDAAgD;AAChD,eAAO,MAAM,SAAS,EAAE,KAIvB,CAAC;AAEF,+CAA+C;AAC/C,eAAO,MAAM,mBAAmB,EAAE,KAIjC,CAAC;AAEF,gDAAgD;AAChD,eAAO,MAAM,mBAAmB,EAAE,KAIjC,CAAC;AAEF,6CAA6C;AAC7C,eAAO,MAAM,cAAc,EAAE,KAI5B,CAAC;AAEF,wEAAwE;AACxE,eAAO,MAAM,oBAAoB,EAAE,KAQlC,CAAC"}
|
package/dist/src/presentation/web/components/common/inline-attachments/inline-attachments.stories.js
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { InlineAttachments } from './inline-attachments.js';
|
|
3
|
+
const meta = {
|
|
4
|
+
title: 'Common/InlineAttachments',
|
|
5
|
+
component: InlineAttachments,
|
|
6
|
+
tags: ['autodocs'],
|
|
7
|
+
parameters: { layout: 'padded' },
|
|
8
|
+
decorators: [
|
|
9
|
+
(Story) => (_jsx("div", { style: { maxWidth: '400px', border: '1px solid var(--color-border)', padding: '16px' }, children: _jsx(Story, {}) })),
|
|
10
|
+
],
|
|
11
|
+
};
|
|
12
|
+
export default meta;
|
|
13
|
+
/** Plain text with no attachment references. */
|
|
14
|
+
export const PlainText = {
|
|
15
|
+
args: {
|
|
16
|
+
text: 'Fix the login bug where users cannot sign in with Google OAuth.',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
/** Text with an image attachment reference. */
|
|
20
|
+
export const WithImageAttachment = {
|
|
21
|
+
args: {
|
|
22
|
+
text: 'The button is misaligned, see screenshot:\n@/home/user/.shep/attachments/pending-abc/screenshot.png',
|
|
23
|
+
},
|
|
24
|
+
};
|
|
25
|
+
/** Text with multiple attachment references. */
|
|
26
|
+
export const MultipleAttachments = {
|
|
27
|
+
args: {
|
|
28
|
+
text: 'Before: @/home/user/.shep/attachments/pending-abc/before.png\nAfter: @/home/user/.shep/attachments/pending-abc/after.png',
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
/** Text with a non-image file attachment. */
|
|
32
|
+
export const FileAttachment = {
|
|
33
|
+
args: {
|
|
34
|
+
text: 'See the log file:\n@/home/user/.shep/attachments/pending-abc/error.log',
|
|
35
|
+
},
|
|
36
|
+
};
|
|
37
|
+
/** Extra attachment paths passed via prop (e.g. rejection feedback). */
|
|
38
|
+
export const ExtraAttachmentPaths = {
|
|
39
|
+
args: {
|
|
40
|
+
text: 'Please fix the layout issues',
|
|
41
|
+
attachmentPaths: [
|
|
42
|
+
'/home/user/.shep/attachments/pending-abc/screenshot1.png',
|
|
43
|
+
'/home/user/.shep/attachments/pending-abc/screenshot2.png',
|
|
44
|
+
],
|
|
45
|
+
},
|
|
46
|
+
};
|