@shepai/cli 1.61.0 → 1.63.0
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/pr-sync/pr-sync-watcher.service.js +1 -1
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts +17 -0
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.js +23 -0
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.d.ts +22 -0
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/base-drawer/base-drawer.stories.js +56 -0
- package/dist/src/presentation/web/components/common/base-drawer/index.d.ts +2 -0
- package/dist/src/presentation/web/components/common/base-drawer/index.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/base-drawer/index.js +1 -0
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js +11 -16
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.d.ts +1 -1
- package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.js +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/feature-drawer/feature-drawer.js +14 -14
- package/dist/src/presentation/web/components/common/repository-node/index.d.ts +1 -0
- package/dist/src/presentation/web/components/common/repository-node/index.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/repository-node/index.js +1 -0
- package/dist/src/presentation/web/components/common/repository-node/repository-drawer.d.ts +7 -0
- package/dist/src/presentation/web/components/common/repository-node/repository-drawer.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/repository-node/repository-drawer.js +12 -0
- package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.d.ts +9 -0
- package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.d.ts.map +1 -0
- package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.js +34 -0
- package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts.map +1 -1
- package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.js +4 -6
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/control-center/control-center-inner.js +20 -2
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts +3 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/features-canvas/features-canvas.js +4 -2
- package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.d.ts.map +1 -1
- package/dist/src/presentation/web/components/features/skills/skill-detail-drawer.js +3 -6
- 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/cache/.previewinfo +1 -1
- package/web/.next/cache/.rscinfo +1 -1
- package/web/.next/cache/.tsbuildinfo +1 -1
- package/web/.next/cache/config.json +3 -3
- 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/_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/page/server-reference-manifest.json +14 -14
- package/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/server/app/skills/page/server-reference-manifest.json +1 -1
- 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 +1 -1
- 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/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5e0f14e9._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__5e0f14e9._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +4 -4
- package/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ae251147._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ae251147._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b6839c3f._.js +2 -2
- package/web/.next/server/chunks/ssr/[root-of-the-server]__b6839c3f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__da0ade1f._.js +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__da0ade1f._.js.map +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__dd5b62cb._.js +3 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__dd5b62cb._.js.map +1 -0
- package/web/.next/server/chunks/ssr/[root-of-the-server]__fbc89707._.js +1 -1
- package/web/.next/server/chunks/ssr/_73d14b70._.js +3 -0
- package/web/.next/server/chunks/ssr/_73d14b70._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_7f386377._.js +3 -0
- package/web/.next/server/chunks/ssr/_7f386377._.js.map +1 -0
- package/web/.next/server/chunks/ssr/_d3711354._.js +2 -2
- package/web/.next/server/chunks/ssr/_d3711354._.js.map +1 -1
- package/web/.next/server/chunks/ssr/{_a64b7b24._.js → _d81184e2._.js} +2 -2
- package/web/.next/server/chunks/ssr/_d81184e2._.js.map +1 -0
- package/web/.next/{standalone/src/presentation/web/.next/server/chunks/ssr/node_modules__pnpm_fe355030._.js → server/chunks/ssr/node_modules__pnpm_87f920e7._.js} +2 -2
- package/web/.next/server/chunks/ssr/{node_modules__pnpm_fe355030._.js.map → node_modules__pnpm_87f920e7._.js.map} +1 -1
- package/web/.next/server/chunks/ssr/src_presentation_web_components_7a0b09da._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_7a0b09da._.js.map +1 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +3 -0
- package/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.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 +15 -15
- package/web/.next/standalone/src/presentation/web/.next/BUILD_ID +1 -1
- package/web/.next/standalone/src/presentation/web/.next/build-manifest.json +2 -2
- package/web/.next/standalone/src/presentation/web/.next/prerender-manifest.json +3 -3
- package/web/.next/standalone/src/presentation/web/.next/required-server-files.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/__PAGE__.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_full.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_head.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_index.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_global-error.segments/_tree.segment.rsc +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/_not-found/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page/server-reference-manifest.json +14 -14
- package/web/.next/standalone/src/presentation/web/.next/server/app/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/skills/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/tools/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page/server-reference-manifest.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page.js.nft.json +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/app/version/page_client-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__08ba9bd3._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__5e0f14e9._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__6b17a22d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__804c006d._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__9add7c3a._.js +4 -4
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__ae251147._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__b6839c3f._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__da0ade1f._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__dd5b62cb._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__fbc89707._.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_73d14b70._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_7f386377._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_d3711354._.js +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/{_a64b7b24._.js → _d81184e2._.js} +2 -2
- package/web/.next/{server/chunks/ssr/node_modules__pnpm_fe355030._.js → standalone/src/presentation/web/.next/server/chunks/ssr/node_modules__pnpm_87f920e7._.js} +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_7a0b09da._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/src_presentation_web_components_e599bb8c._.js +3 -0
- package/web/.next/standalone/src/presentation/web/.next/server/pages/500.html +2 -2
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.js +1 -1
- package/web/.next/standalone/src/presentation/web/.next/server/server-reference-manifest.json +15 -15
- package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.stories.tsx +207 -0
- package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx +90 -0
- package/web/.next/standalone/src/presentation/web/components/common/base-drawer/index.ts +1 -0
- package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.stories.tsx +1 -1
- package/web/.next/standalone/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx +145 -172
- package/web/.next/standalone/src/presentation/web/components/common/feature-drawer/feature-drawer.tsx +119 -133
- package/web/.next/standalone/src/presentation/web/components/common/repository-node/index.ts +1 -0
- package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-drawer.stories.tsx +58 -0
- package/web/.next/standalone/src/presentation/web/components/common/repository-node/repository-drawer.tsx +82 -0
- package/web/.next/standalone/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx +79 -96
- package/web/.next/standalone/src/presentation/web/components/features/control-center/control-center-inner.tsx +30 -2
- package/web/.next/standalone/src/presentation/web/components/features/features-canvas/features-canvas.tsx +7 -0
- package/web/.next/standalone/src/presentation/web/components/features/skills/skill-detail-drawer.tsx +71 -77
- package/web/.next/standalone/src/presentation/web/server.js +1 -1
- package/web/.next/static/chunks/0c6654ec27f11c7e.js +1 -0
- package/web/.next/static/chunks/12c70bfd5951cf9b.js +1 -0
- package/web/.next/static/chunks/21541b346dd4dd28.js +1 -0
- package/web/.next/static/chunks/{cb1b27e4a21415d3.js → 3b941e59ac013e12.js} +2 -2
- package/web/.next/static/chunks/426292e5fb0b2a61.js +1 -0
- package/web/.next/static/chunks/{09d898be63c54f20.js → 78919481e7c5ad4f.js} +1 -1
- package/web/.next/static/chunks/a5b6a22de303e877.css +2 -0
- package/web/.next/static/chunks/af7a5bcb7c49e46e.js +1 -0
- package/web/.next/static/chunks/be784143669bb992.js +1 -0
- package/web/.next/static/chunks/ea57f9afe9055c7a.js +10 -0
- package/web/.next/trace +1 -1
- package/web/.next/trace-build +1 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2395adc6._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__2395adc6._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__87fda958._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__87fda958._.js.map +0 -1
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ee7cffe1._.js +0 -3
- package/web/.next/server/chunks/ssr/[root-of-the-server]__ee7cffe1._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_9915d2a7._.js +0 -3
- package/web/.next/server/chunks/ssr/_9915d2a7._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_a64b7b24._.js.map +0 -1
- package/web/.next/server/chunks/ssr/_e7a4b0e4._.js +0 -3
- package/web/.next/server/chunks/ssr/_e7a4b0e4._.js.map +0 -1
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__2395adc6._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__87fda958._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/[root-of-the-server]__ee7cffe1._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_9915d2a7._.js +0 -3
- package/web/.next/standalone/src/presentation/web/.next/server/chunks/ssr/_e7a4b0e4._.js +0 -3
- package/web/.next/static/chunks/13664c029245afc8.js +0 -1
- package/web/.next/static/chunks/25f42652257ff43d.js +0 -1
- package/web/.next/static/chunks/2934854f0378f815.js +0 -1
- package/web/.next/static/chunks/2960a70537e4fd12.js +0 -10
- package/web/.next/static/chunks/45f510f84c7c417d.css +0 -2
- package/web/.next/static/chunks/79718b1f5713fdc0.js +0 -1
- /package/web/.next/static/{_DBWexyU1QkK02q15qod2 → 23Y-ea-5g4_fUHZyGpCb0}/_buildManifest.js +0 -0
- /package/web/.next/static/{_DBWexyU1QkK02q15qod2 → 23Y-ea-5g4_fUHZyGpCb0}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{_DBWexyU1QkK02q15qod2 → 23Y-ea-5g4_fUHZyGpCb0}/_ssgManifest.js +0 -0
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* repositoryPath for batch `gh pr list` queries.
|
|
11
11
|
*/
|
|
12
12
|
import { SdlcLifecycle, PrStatus, CiStatus, AgentRunStatus, NotificationEventType, NotificationSeverity, } from '../../../domain/generated/output.js';
|
|
13
|
-
const DEFAULT_POLL_INTERVAL_MS =
|
|
13
|
+
const DEFAULT_POLL_INTERVAL_MS = 30_000;
|
|
14
14
|
const TAG = '[PrSyncWatcher]';
|
|
15
15
|
const CI_STATUS_MAP = {
|
|
16
16
|
success: CiStatus.Success,
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type VariantProps } from 'class-variance-authority';
|
|
2
|
+
declare const drawerVariants: (props?: ({
|
|
3
|
+
size?: "md" | "sm" | null | undefined;
|
|
4
|
+
} & import("class-variance-authority/types").ClassProp) | undefined) => string;
|
|
5
|
+
export interface BaseDrawerProps extends VariantProps<typeof drawerVariants> {
|
|
6
|
+
open: boolean;
|
|
7
|
+
onClose: () => void;
|
|
8
|
+
modal?: boolean;
|
|
9
|
+
header?: React.ReactNode;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
footer?: React.ReactNode;
|
|
12
|
+
className?: string;
|
|
13
|
+
'data-testid'?: string;
|
|
14
|
+
}
|
|
15
|
+
export declare function BaseDrawer({ open, onClose, modal, size, header, children, footer, className, 'data-testid': testId, }: BaseDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=base-drawer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/base-drawer.tsx"],"names":[],"mappings":"AAGA,OAAO,EAAO,KAAK,YAAY,EAAE,MAAM,0BAA0B,CAAC;AAUlE,QAAA,MAAM,cAAc;;8EAUlB,CAAC;AAEH,MAAM,WAAW,eAAgB,SAAQ,YAAY,CAAC,OAAO,cAAc,CAAC;IAC1E,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,wBAAgB,UAAU,CAAC,EACzB,IAAI,EACJ,OAAO,EACP,KAAa,EACb,IAAI,EACJ,MAAM,EACN,QAAQ,EACR,MAAM,EACN,SAAS,EACT,aAAa,EAAE,MAAM,GACtB,EAAE,eAAe,2CA2CjB"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { XIcon } from 'lucide-react';
|
|
4
|
+
import { cva } from 'class-variance-authority';
|
|
5
|
+
import { cn } from '../../../lib/utils.js';
|
|
6
|
+
import { Drawer, DrawerContent, DrawerHeader, DrawerFooter, DrawerOverlay, } from '../../ui/drawer.js';
|
|
7
|
+
const drawerVariants = cva('', {
|
|
8
|
+
variants: {
|
|
9
|
+
size: {
|
|
10
|
+
sm: 'w-96',
|
|
11
|
+
md: 'w-xl',
|
|
12
|
+
},
|
|
13
|
+
},
|
|
14
|
+
defaultVariants: {
|
|
15
|
+
size: 'sm',
|
|
16
|
+
},
|
|
17
|
+
});
|
|
18
|
+
export function BaseDrawer({ open, onClose, modal = false, size, header, children, footer, className, 'data-testid': testId, }) {
|
|
19
|
+
return (_jsxs(Drawer, { direction: "right", modal: modal, handleOnly: true, open: open, onOpenChange: (isOpen) => {
|
|
20
|
+
if (!isOpen)
|
|
21
|
+
onClose();
|
|
22
|
+
}, children: [modal ? _jsx(DrawerOverlay, {}) : null, _jsxs(DrawerContent, { direction: "right", showCloseButton: false, className: cn(drawerVariants({ size }), className), "data-testid": testId, children: [_jsxs("button", { type: "button", "aria-label": "Close", onClick: onClose, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", "data-testid": testId ? `${testId}-close-button` : undefined, children: [_jsx(XIcon, { className: "size-4" }), _jsx("span", { className: "sr-only", children: "Close" })] }), header ? _jsx(DrawerHeader, { children: header }) : null, _jsx("div", { className: "flex-1 overflow-y-auto", children: _jsx("div", { className: "flex flex-col", children: children }) }), footer ? _jsx(DrawerFooter, { children: footer }) : null] })] }));
|
|
23
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { BaseDrawer } from './base-drawer.js';
|
|
3
|
+
declare const meta: Meta<typeof BaseDrawer>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof BaseDrawer>;
|
|
6
|
+
/** Default drawer with sm size, non-modal, children only. */
|
|
7
|
+
export declare const Default: Story;
|
|
8
|
+
/** Explicit sm size with inspector-style content. */
|
|
9
|
+
export declare const SmallSize: Story;
|
|
10
|
+
/** Medium size with content-rich review-style content. */
|
|
11
|
+
export declare const MediumSize: Story;
|
|
12
|
+
/** Modal drawer with overlay. */
|
|
13
|
+
export declare const Modal: Story;
|
|
14
|
+
/** Drawer with header slot containing DrawerTitle and DrawerDescription. */
|
|
15
|
+
export declare const WithHeader: Story;
|
|
16
|
+
/** Drawer with footer slot containing action buttons. */
|
|
17
|
+
export declare const WithFooter: Story;
|
|
18
|
+
/** Drawer with both header and footer slots populated. */
|
|
19
|
+
export declare const WithHeaderAndFooter: Story;
|
|
20
|
+
/** Drawer with content that exceeds viewport to demonstrate scroll behavior. */
|
|
21
|
+
export declare const ScrollableContent: Story;
|
|
22
|
+
//# sourceMappingURL=base-drawer.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"base-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/base-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAI3C,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,UAAU,CAOjC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC;AAuBzC,6DAA6D;AAC7D,eAAO,MAAM,OAAO,EAAE,KAQrB,CAAC;AAEF,qDAAqD;AACrD,eAAO,MAAM,SAAS,EAAE,KAkBvB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,UAAU,EAAE,KAiBxB,CAAC;AAEF,iCAAiC;AACjC,eAAO,MAAM,KAAK,EAAE,KAUnB,CAAC;AAEF,4EAA4E;AAC5E,eAAO,MAAM,UAAU,EAAE,KAexB,CAAC;AAEF,yDAAyD;AACzD,eAAO,MAAM,UAAU,EAAE,KAiBxB,CAAC;AAEF,0DAA0D;AAC1D,eAAO,MAAM,mBAAmB,EAAE,KAsCjC,CAAC;AAEF,gFAAgF;AAChF,eAAO,MAAM,iBAAiB,EAAE,KAsB/B,CAAC"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { BaseDrawer } from './base-drawer.js';
|
|
4
|
+
import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
|
|
5
|
+
import { Button } from '../../ui/button.js';
|
|
6
|
+
const meta = {
|
|
7
|
+
title: 'Common/BaseDrawer',
|
|
8
|
+
component: BaseDrawer,
|
|
9
|
+
tags: ['autodocs'],
|
|
10
|
+
parameters: {
|
|
11
|
+
layout: 'fullscreen',
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
export default meta;
|
|
15
|
+
/* ---------------------------------------------------------------------------
|
|
16
|
+
* Trigger wrapper — starts closed, click to open
|
|
17
|
+
* ------------------------------------------------------------------------- */
|
|
18
|
+
function DrawerTrigger(props) {
|
|
19
|
+
const [open, setOpen] = useState(false);
|
|
20
|
+
return (_jsxs("div", { className: "flex h-screen items-start p-4", children: [_jsx(Button, { variant: "outline", onClick: () => setOpen(true), children: "Open Drawer" }), _jsx(BaseDrawer, { ...props, open: open, onClose: () => setOpen(false) })] }));
|
|
21
|
+
}
|
|
22
|
+
/* ---------------------------------------------------------------------------
|
|
23
|
+
* Stories
|
|
24
|
+
* ------------------------------------------------------------------------- */
|
|
25
|
+
/** Default drawer with sm size, non-modal, children only. */
|
|
26
|
+
export const Default = {
|
|
27
|
+
render: () => (_jsx(DrawerTrigger, { children: _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "Default drawer content" }) }) })),
|
|
28
|
+
};
|
|
29
|
+
/** Explicit sm size with inspector-style content. */
|
|
30
|
+
export const SmallSize = {
|
|
31
|
+
render: () => (_jsx(DrawerTrigger, { size: "sm", children: _jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Feature Inspector" }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: "Status" }), _jsx("span", { className: "text-sm", children: "Running" })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("span", { className: "text-muted-foreground text-xs", children: "Progress" }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: "bg-primary h-full w-[45%] rounded-full" }) })] })] }) })),
|
|
32
|
+
};
|
|
33
|
+
/** Medium size with content-rich review-style content. */
|
|
34
|
+
export const MediumSize = {
|
|
35
|
+
render: () => (_jsx(DrawerTrigger, { size: "md", children: _jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsx("h3", { className: "text-sm font-semibold", children: "Review Content" }), _jsx("p", { className: "text-muted-foreground text-sm", children: "This drawer uses size=\"md\" (w-xl / 576px) for content-rich review panels that need more horizontal space for diff summaries, tables, and code blocks." }), _jsx("div", { className: "bg-muted rounded-md p-3", children: _jsx("pre", { className: "text-xs", children: `+ Added authentication middleware\n- Removed legacy session handler\n Updated user model schema` }) })] }) })),
|
|
36
|
+
};
|
|
37
|
+
/** Modal drawer with overlay. */
|
|
38
|
+
export const Modal = {
|
|
39
|
+
render: () => (_jsx(DrawerTrigger, { modal: true, children: _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "This drawer is modal \u2014 an overlay blocks background interaction and focus is trapped." }) }) })),
|
|
40
|
+
};
|
|
41
|
+
/** Drawer with header slot containing DrawerTitle and DrawerDescription. */
|
|
42
|
+
export const WithHeader = {
|
|
43
|
+
render: () => (_jsx(DrawerTrigger, { header: _jsxs(_Fragment, { children: [_jsx(DrawerTitle, { children: "Feature Details" }), _jsx(DrawerDescription, { children: "FEAT-042 \u2014 Authentication Flow" })] }), children: _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "Content below the header." }) }) })),
|
|
44
|
+
};
|
|
45
|
+
/** Drawer with footer slot containing action buttons. */
|
|
46
|
+
export const WithFooter = {
|
|
47
|
+
render: () => (_jsx(DrawerTrigger, { footer: _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", className: "flex-1", children: "Cancel" }), _jsx(Button, { className: "flex-1", children: "Save" })] }), children: _jsx("div", { className: "p-4", children: _jsx("p", { className: "text-muted-foreground text-sm", children: "Content above the footer." }) }) })),
|
|
48
|
+
};
|
|
49
|
+
/** Drawer with both header and footer slots populated. */
|
|
50
|
+
export const WithHeaderAndFooter = {
|
|
51
|
+
render: () => (_jsx(DrawerTrigger, { header: _jsxs(_Fragment, { children: [_jsx(DrawerTitle, { children: "Create Feature" }), _jsx(DrawerDescription, { children: "Fill in the details below" })] }), footer: _jsxs("div", { className: "flex gap-2", children: [_jsx(Button, { variant: "outline", className: "flex-1", children: "Cancel" }), _jsx(Button, { className: "flex-1", children: "Create" })] }), children: _jsxs("div", { className: "flex flex-col gap-4 p-4", children: [_jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("label", { className: "text-sm font-medium", children: "Name" }), _jsx("input", { type: "text", className: "border-input bg-background rounded-md border px-3 py-2 text-sm", placeholder: "Feature name" })] }), _jsxs("div", { className: "flex flex-col gap-1", children: [_jsx("label", { className: "text-sm font-medium", children: "Description" }), _jsx("textarea", { className: "border-input bg-background rounded-md border px-3 py-2 text-sm", rows: 3, placeholder: "Optional description" })] })] }) })),
|
|
52
|
+
};
|
|
53
|
+
/** Drawer with content that exceeds viewport to demonstrate scroll behavior. */
|
|
54
|
+
export const ScrollableContent = {
|
|
55
|
+
render: () => (_jsx(DrawerTrigger, { header: _jsxs(_Fragment, { children: [_jsx(DrawerTitle, { children: "Scrollable Content" }), _jsx(DrawerDescription, { children: "Content below overflows and scrolls" })] }), children: _jsx("div", { className: "flex flex-col gap-4 p-4", children: Array.from({ length: 30 }, (_, i) => (_jsxs("div", { className: "border-border rounded-md border p-3", children: [_jsxs("h4", { className: "text-sm font-medium", children: ["Item ", i + 1] }), _jsx("p", { className: "text-muted-foreground text-xs", children: "This is a scrollable content item to demonstrate overflow handling." })] }, i))) }) })),
|
|
56
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/base-drawer/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,KAAK,eAAe,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BaseDrawer } from './base-drawer.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feature-create-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAC/F,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qCAAqC,CAAC;AAG5E,YAAY,EAAE,cAAc,EAAE,MAAM,0DAA0D,CAAC;AAE/F,0DAA0D;AAC1D,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,oBAAoB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,cAAc,EAAE,CAAC;IAC9B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE;QACb,QAAQ,EAAE,OAAO,CAAC;QAClB,SAAS,EAAE,OAAO,CAAC;QACnB,UAAU,EAAE,OAAO,CAAC;KACrB,CAAC;IACF,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAcD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,EAAE,CAAC,IAAI,EAAE,oBAAoB,KAAK,IAAI,CAAC;IAC/C,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gBAAgB,CAAC,EAAE,gBAAgB,CAAC;IACpC,qEAAqE;IACrE,QAAQ,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACjC,kGAAkG;IAClG,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED,wBAAgB,mBAAmB,CAAC,EAClC,IAAI,EACJ,OAAO,EACP,QAAQ,EACR,cAAc,EACd,YAAoB,EACpB,gBAAgB,EAChB,QAAQ,EACR,eAAe,GAChB,EAAE,wBAAwB,2CAsR1B"}
|
package/dist/src/presentation/web/components/common/feature-create-drawer/feature-create-drawer.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
3
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
4
|
-
import {
|
|
4
|
+
import { PlusIcon, FileIcon, FileTextIcon, ImageIcon, CodeIcon, Trash2Icon, ChevronsUpDown, CheckIcon, } from 'lucide-react';
|
|
5
5
|
import { cn } from '../../../lib/utils.js';
|
|
6
6
|
import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
7
|
-
import {
|
|
7
|
+
import { BaseDrawer } from '../../common/base-drawer/index.js';
|
|
8
|
+
import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
|
|
8
9
|
import { Button } from '../../ui/button.js';
|
|
9
10
|
import { Input } from '../../ui/input.js';
|
|
10
11
|
import { Textarea } from '../../ui/textarea.js';
|
|
@@ -68,12 +69,10 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
68
69
|
setOpenPr(defaultOpenPr);
|
|
69
70
|
setParentId(undefined);
|
|
70
71
|
}, [defaultGates, defaultPush, defaultOpenPr]);
|
|
71
|
-
const
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
onClose();
|
|
76
|
-
}
|
|
72
|
+
const handleClose = useCallback(() => {
|
|
73
|
+
drawerCloseSound.play();
|
|
74
|
+
resetForm();
|
|
75
|
+
onClose();
|
|
77
76
|
}, [onClose, resetForm, drawerCloseSound]);
|
|
78
77
|
const handleSubmit = useCallback((e) => {
|
|
79
78
|
e.preventDefault();
|
|
@@ -95,6 +94,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
95
94
|
openPr,
|
|
96
95
|
...(parentId ? { parentId } : {}),
|
|
97
96
|
});
|
|
97
|
+
resetForm();
|
|
98
98
|
}, [
|
|
99
99
|
name,
|
|
100
100
|
description,
|
|
@@ -106,6 +106,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
106
106
|
openPr,
|
|
107
107
|
parentId,
|
|
108
108
|
createSound,
|
|
109
|
+
resetForm,
|
|
109
110
|
]);
|
|
110
111
|
const handleAddFiles = useCallback(async () => {
|
|
111
112
|
try {
|
|
@@ -122,13 +123,7 @@ export function FeatureCreateDrawer({ open, onClose, onSubmit, repositoryPath, i
|
|
|
122
123
|
setAttachments((prev) => prev.filter((f) => f.path !== path));
|
|
123
124
|
}, []);
|
|
124
125
|
const hasFeatures = features && features.length > 0;
|
|
125
|
-
return (
|
|
126
|
-
drawerCloseSound.play();
|
|
127
|
-
onClose();
|
|
128
|
-
}, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", children: _jsx(XIcon, { className: "size-4" }) }), _jsxs(DrawerHeader, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), _jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })] }), _jsx(Separator, {}), _jsx("div", { className: "flex-1 overflow-y-auto p-4", children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-name", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "FEATURE NAME" }), _jsx(Input, { id: "feature-name", placeholder: "e.g. GitHub OAuth Login", value: name, onChange: (e) => setName(e.target.value), required: true, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIPTION" }), _jsx(Textarea, { id: "feature-description", placeholder: "Describe what this feature does...", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, disabled: isSubmitting })] }), hasFeatures ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "APPROVE" }), _jsx(CheckboxGroup, { label: "Autonomous Mode", description: "YOLO!", parentAriaLabel: "Auto approve all", options: AUTO_APPROVE_OPTIONS, value: approvalGates, onValueChange: setApprovalGates, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(CheckboxGroupItem, { id: "push", label: "Push", description: "Push branch to remote after implementation.", checked: push || openPr, onCheckedChange: setPush, disabled: openPr || isSubmitting }), _jsx(CheckboxGroupItem, { id: "open-pr", label: "Create PR", description: "Open a pull request after pushing.", checked: openPr, onCheckedChange: setOpenPr, disabled: isSubmitting })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: ["ATTACHMENTS", attachments.length > 0 && (_jsxs("span", { className: "text-muted-foreground/60 ml-1.5", children: ["(", attachments.length, ")"] }))] }), _jsxs(Button, { type: "button", variant: "outline", size: "xs", onClick: handleAddFiles, disabled: isSubmitting, children: [_jsx(PlusIcon, { className: "size-3" }), "Add Files"] })] }), attachments.length > 0 && (_jsx("div", { className: "flex flex-col gap-2", children: attachments.map((file) => (_jsx(AttachmentCard, { file: file, onRemove: () => handleRemoveFile(file.path), disabled: isSubmitting }, file.path))) }))] })] }) }), _jsx(Separator, {}), _jsxs(DrawerFooter, { className: "flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: () => {
|
|
129
|
-
drawerCloseSound.play();
|
|
130
|
-
onClose();
|
|
131
|
-
}, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !name.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] })] }) }));
|
|
126
|
+
return (_jsxs(BaseDrawer, { open: open, onClose: handleClose, size: "md", modal: false, "data-testid": "feature-create-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { className: "flex items-center gap-2", children: [_jsx("div", { className: "h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" }), _jsx(DrawerTitle, { children: "NEW FEATURE" })] }), _jsx(DrawerDescription, { asChild: true, children: _jsx("div", { children: _jsx(Badge, { variant: "secondary", children: "Creating..." }) }) })] }), footer: _jsxs("div", { className: "flex flex-row justify-end gap-2", children: [_jsx(Button, { variant: "outline", onClick: handleClose, disabled: isSubmitting, children: "Cancel" }), _jsx(Button, { type: "submit", form: "create-feature-form", disabled: !name.trim() || isSubmitting, children: isSubmitting ? 'Creating...' : '+ Create Feature' })] }), children: [_jsx(Separator, {}), _jsx("div", { className: "p-4", children: _jsxs("form", { id: "create-feature-form", onSubmit: handleSubmit, className: "flex flex-col gap-4", children: [_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-name", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "FEATURE NAME" }), _jsx(Input, { id: "feature-name", placeholder: "e.g. GitHub OAuth Login", value: name, onChange: (e) => setName(e.target.value), required: true, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "feature-description", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "DESCRIPTION" }), _jsx(Textarea, { id: "feature-description", placeholder: "Describe what this feature does...", value: description, onChange: (e) => setDescription(e.target.value), rows: 4, disabled: isSubmitting })] }), hasFeatures ? (_jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { htmlFor: "parent-feature", className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "PARENT FEATURE" }), _jsx(ParentFeatureCombobox, { features: features, value: parentId, onChange: setParentId, disabled: isSubmitting })] })) : null, _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "APPROVE" }), _jsx(CheckboxGroup, { label: "Autonomous Mode", description: "YOLO!", parentAriaLabel: "Auto approve all", options: AUTO_APPROVE_OPTIONS, value: approvalGates, onValueChange: setApprovalGates, disabled: isSubmitting })] }), _jsxs("div", { className: "flex flex-col gap-1.5", children: [_jsx(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "GIT" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(CheckboxGroupItem, { id: "push", label: "Push", description: "Push branch to remote after implementation.", checked: push || openPr, onCheckedChange: setPush, disabled: openPr || isSubmitting }), _jsx(CheckboxGroupItem, { id: "open-pr", label: "Create PR", description: "Open a pull request after pushing.", checked: openPr, onCheckedChange: setOpenPr, disabled: isSubmitting })] })] }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsxs("div", { className: "flex items-center justify-between", children: [_jsxs(Label, { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: ["ATTACHMENTS", attachments.length > 0 && (_jsxs("span", { className: "text-muted-foreground/60 ml-1.5", children: ["(", attachments.length, ")"] }))] }), _jsxs(Button, { type: "button", variant: "outline", size: "xs", onClick: handleAddFiles, disabled: isSubmitting, children: [_jsx(PlusIcon, { className: "size-3" }), "Add Files"] })] }), attachments.length > 0 && (_jsx("div", { className: "flex flex-col gap-2", children: attachments.map((file) => (_jsx(AttachmentCard, { file: file, onRemove: () => handleRemoveFile(file.path), disabled: isSubmitting }, file.path))) }))] })] }) })] }));
|
|
132
127
|
}
|
|
133
128
|
function ParentFeatureCombobox({ features, value, onChange, disabled, }) {
|
|
134
129
|
const [open, setOpen] = useState(false);
|
|
@@ -26,7 +26,7 @@ import { FeatureCreateDrawer } from './feature-create-drawer.js';
|
|
|
26
26
|
* - Submit button is disabled when name is empty
|
|
27
27
|
* - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
|
|
28
28
|
* - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
|
|
29
|
-
* - Fixed width:
|
|
29
|
+
* - Fixed width: 448px (`w-xl`) — matches review drawers (PRD, Plan, Merge)
|
|
30
30
|
* - Attachments use native OS file picker via `pickFiles()` — returns `FileAttachment[]`
|
|
31
31
|
* with full absolute paths, filenames, and sizes
|
|
32
32
|
*/
|
|
@@ -32,7 +32,7 @@ import { Button } from '../../ui/button.js';
|
|
|
32
32
|
* - Submit button is disabled when name is empty
|
|
33
33
|
* - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
|
|
34
34
|
* - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
|
|
35
|
-
* - Fixed width:
|
|
35
|
+
* - Fixed width: 448px (`w-xl`) — matches review drawers (PRD, Plan, Merge)
|
|
36
36
|
* - Attachments use native OS file picker via `pickFiles()` — returns `FileAttachment[]`
|
|
37
37
|
* with full absolute paths, filenames, and sizes
|
|
38
38
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"feature-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer/feature-drawer.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"feature-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/feature-drawer/feature-drawer.tsx"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAGxE,MAAM,WAAW,kBAAkB;IACjC,YAAY,EAAE,eAAe,GAAG,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,QAAQ,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,wBAAgB,aAAa,CAAC,EAC5B,YAAY,EACZ,OAAO,EACP,QAAQ,EACR,UAAkB,GACnB,EAAE,kBAAkB,2CAoIpB"}
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import {
|
|
3
|
+
import { useCallback, useEffect } from 'react';
|
|
4
|
+
import { Loader2, Trash2, ExternalLink, GitCommitHorizontal } from 'lucide-react';
|
|
4
5
|
import { PrStatus } from '../../../../../../packages/core/src/domain/generated/output.js';
|
|
5
6
|
import { cn } from '../../../lib/utils.js';
|
|
6
7
|
import { useSoundAction } from '../../../hooks/use-sound-action.js';
|
|
7
8
|
import { OpenActionMenu } from '../../common/open-action-menu/index.js';
|
|
8
|
-
import {
|
|
9
|
+
import { BaseDrawer } from '../../common/base-drawer/index.js';
|
|
10
|
+
import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
|
|
9
11
|
import { Button } from '../../ui/button.js';
|
|
10
12
|
import { Badge } from '../../ui/badge.js';
|
|
11
13
|
import { Separator } from '../../ui/separator.js';
|
|
@@ -17,18 +19,16 @@ import { useFeatureActions } from './use-feature-actions.js';
|
|
|
17
19
|
export function FeatureDrawer({ selectedNode, onClose, onDelete, isDeleting = false, }) {
|
|
18
20
|
const drawerOpenSound = useSoundAction('drawer-open');
|
|
19
21
|
const drawerCloseSound = useSoundAction('drawer-close');
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
onClose();
|
|
31
|
-
}, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", children: _jsx(XIcon, { className: "size-4" }) }), _jsxs(DrawerHeader, { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: selectedNode.name }), _jsx(DrawerDescription, { children: selectedNode.featureId })] }), selectedNode.repositoryPath && selectedNode.branch ? (_jsx(DrawerActions, { repositoryPath: selectedNode.repositoryPath, branch: selectedNode.branch, specPath: selectedNode.specPath })) : null, _jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[selectedNode.lifecycle] }), _jsx(StateBadge, { data: selectedNode }), selectedNode.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [selectedNode.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[selectedNode.state].progressClass), style: { width: `${selectedNode.progress}%` } }) })] })) : null] }), selectedNode.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx(PrInfoSection, { pr: selectedNode.pr })] })) : null, _jsx(Separator, {}), _jsx(DetailsSection, { data: selectedNode }), onDelete ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { "data-testid": "feature-drawer-delete", className: "p-4", children: _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsxs(Button, { variant: "destructive", className: "w-full", disabled: isDeleting, children: [_jsx(Trash2, { className: "mr-2 h-4 w-4" }), "Delete feature"] }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: selectedNode.name }), " (", selectedNode.featureId, "). This action cannot be undone.", selectedNode.state === 'running' ? (_jsx(_Fragment, { children: " This feature has a running agent that will be stopped." })) : null] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(selectedNode.featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] }) })] })) : null] })) : null }) }));
|
|
22
|
+
const isOpen = selectedNode !== null;
|
|
23
|
+
useEffect(() => {
|
|
24
|
+
if (isOpen)
|
|
25
|
+
drawerOpenSound.play();
|
|
26
|
+
}, [isOpen, drawerOpenSound]);
|
|
27
|
+
const handleClose = useCallback(() => {
|
|
28
|
+
drawerCloseSound.play();
|
|
29
|
+
onClose();
|
|
30
|
+
}, [onClose, drawerCloseSound]);
|
|
31
|
+
return (_jsx(BaseDrawer, { open: selectedNode !== null, onClose: handleClose, size: "sm", modal: false, "data-testid": "feature-drawer", header: selectedNode ? (_jsxs("div", { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: selectedNode.name }), _jsx(DrawerDescription, { children: selectedNode.featureId })] })) : undefined, children: selectedNode ? (_jsxs(_Fragment, { children: [selectedNode.repositoryPath && selectedNode.branch ? (_jsx(DrawerActions, { repositoryPath: selectedNode.repositoryPath, branch: selectedNode.branch, specPath: selectedNode.specPath })) : null, _jsx(Separator, {}), _jsxs("div", { "data-testid": "feature-drawer-status", className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: lifecycleDisplayLabels[selectedNode.lifecycle] }), _jsx(StateBadge, { data: selectedNode }), selectedNode.progress > 0 ? (_jsxs("div", { "data-testid": "feature-drawer-progress", className: "flex flex-col gap-1", children: [_jsxs("div", { className: "text-muted-foreground flex items-center justify-between text-xs", children: [_jsx("span", { children: "Progress" }), _jsxs("span", { children: [selectedNode.progress, "%"] })] }), _jsx("div", { className: "bg-muted h-2 w-full overflow-hidden rounded-full", children: _jsx("div", { className: cn('h-full rounded-full transition-all', featureNodeStateConfig[selectedNode.state].progressClass), style: { width: `${selectedNode.progress}%` } }) })] })) : null] }), selectedNode.pr ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx(PrInfoSection, { pr: selectedNode.pr })] })) : null, _jsx(Separator, {}), _jsx(DetailsSection, { data: selectedNode }), onDelete ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsx("div", { "data-testid": "feature-drawer-delete", className: "p-4", children: _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsxs(Button, { variant: "destructive", className: "w-full", disabled: isDeleting, children: [_jsx(Trash2, { className: "mr-2 h-4 w-4" }), "Delete feature"] }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: selectedNode.name }), " (", selectedNode.featureId, "). This action cannot be undone.", selectedNode.state === 'running' ? (_jsx(_Fragment, { children: " This feature has a running agent that will be stopped." })) : null] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(selectedNode.featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] }) })] })) : null] })) : null }));
|
|
32
32
|
}
|
|
33
33
|
function StateBadge({ data }) {
|
|
34
34
|
const config = featureNodeStateConfig[data.state];
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
export { RepositoryNode } from './repository-node.js';
|
|
2
|
+
export { RepositoryDrawer, type RepositoryDrawerProps } from './repository-drawer.js';
|
|
2
3
|
export type { RepositoryNodeData, RepositoryNodeType } from './repository-node-config.js';
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,KAAK,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AACnF,YAAY,EAAE,kBAAkB,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC"}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { RepositoryNodeData } from './repository-node-config.js';
|
|
2
|
+
export interface RepositoryDrawerProps {
|
|
3
|
+
data: RepositoryNodeData | null;
|
|
4
|
+
onClose: () => void;
|
|
5
|
+
}
|
|
6
|
+
export declare function RepositoryDrawer({ data, onClose }: RepositoryDrawerProps): import("react/jsx-runtime").JSX.Element;
|
|
7
|
+
//# sourceMappingURL=repository-drawer.d.ts.map
|
package/dist/src/presentation/web/components/common/repository-node/repository-drawer.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository-drawer.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-drawer.tsx"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAGnE,MAAM,WAAW,qBAAqB;IACpC,IAAI,EAAE,kBAAkB,GAAG,IAAI,CAAC;IAChC,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,wBAAgB,gBAAgB,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,EAAE,qBAAqB,2CAkExE"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
+
import { Code2, Terminal, FolderOpen } from 'lucide-react';
|
|
4
|
+
import { BaseDrawer } from '../../common/base-drawer/index.js';
|
|
5
|
+
import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
|
|
6
|
+
import { Separator } from '../../ui/separator.js';
|
|
7
|
+
import { ActionButton } from '../../common/action-button/index.js';
|
|
8
|
+
import { useRepositoryActions } from './use-repository-actions.js';
|
|
9
|
+
export function RepositoryDrawer({ data, onClose }) {
|
|
10
|
+
const actions = useRepositoryActions(data?.repositoryPath ? { repositoryPath: data.repositoryPath } : null);
|
|
11
|
+
return (_jsx(BaseDrawer, { open: data !== null, onClose: onClose, size: "sm", modal: false, "data-testid": "repository-drawer", header: data ? (_jsxs("div", { "data-testid": "repository-drawer-header", children: [_jsx(DrawerTitle, { children: data.name }), data.repositoryPath ? (_jsx(DrawerDescription, { className: "truncate font-mono text-xs", children: data.repositoryPath })) : null] })) : undefined, children: data?.repositoryPath ? (_jsxs(_Fragment, { children: [_jsx(Separator, {}), _jsxs("div", { className: "flex flex-col gap-3 p-4", children: [_jsx("div", { className: "text-muted-foreground text-xs font-semibold tracking-wider", children: "OPEN WITH" }), _jsxs("div", { className: "flex flex-col gap-2", children: [_jsx(ActionButton, { label: "Open in IDE", onClick: actions.openInIde, loading: actions.ideLoading, error: !!actions.ideError, icon: Code2, variant: "outline", size: "sm" }), _jsx(ActionButton, { label: "Open in Shell", onClick: actions.openInShell, loading: actions.shellLoading, error: !!actions.shellError, icon: Terminal, variant: "outline", size: "sm" }), _jsx(ActionButton, { label: "Open Folder", onClick: actions.openFolder, loading: actions.folderLoading, error: !!actions.folderError, icon: FolderOpen, variant: "outline", size: "sm" })] })] })] })) : null }));
|
|
12
|
+
}
|
package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
2
|
+
import { RepositoryDrawer } from './repository-drawer.js';
|
|
3
|
+
declare const meta: Meta<typeof RepositoryDrawer>;
|
|
4
|
+
export default meta;
|
|
5
|
+
type Story = StoryObj<typeof RepositoryDrawer>;
|
|
6
|
+
export declare const Default: Story;
|
|
7
|
+
export declare const LongPath: Story;
|
|
8
|
+
export declare const WithoutPath: Story;
|
|
9
|
+
//# sourceMappingURL=repository-drawer.stories.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repository-drawer.stories.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/repository-node/repository-drawer.stories.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAGvD,QAAA,MAAM,IAAI,EAAE,IAAI,CAAC,OAAO,gBAAgB,CAOvC,CAAC;AAEF,eAAe,IAAI,CAAC;AACpB,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAqB/C,eAAO,MAAM,OAAO,EAAE,KAErB,CAAC;AAEF,eAAO,MAAM,QAAQ,EAAE,KAUtB,CAAC;AAEF,eAAO,MAAM,WAAW,EAAE,KAIzB,CAAC"}
|
package/dist/src/presentation/web/components/common/repository-node/repository-drawer.stories.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useState } from 'react';
|
|
3
|
+
import { Button } from '../../ui/button.js';
|
|
4
|
+
import { RepositoryDrawer } from './repository-drawer.js';
|
|
5
|
+
const meta = {
|
|
6
|
+
title: 'Composed/RepositoryDrawer',
|
|
7
|
+
component: RepositoryDrawer,
|
|
8
|
+
tags: ['autodocs'],
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: 'fullscreen',
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export default meta;
|
|
14
|
+
const repoData = {
|
|
15
|
+
id: 'repo-1',
|
|
16
|
+
name: 'shep-ai/cli',
|
|
17
|
+
repositoryPath: '/home/user/shep-ai/cli',
|
|
18
|
+
};
|
|
19
|
+
function DrawerTrigger({ data, label }) {
|
|
20
|
+
const [selected, setSelected] = useState(null);
|
|
21
|
+
return (_jsxs("div", { className: "flex h-screen items-start p-4", children: [_jsx(Button, { variant: "outline", onClick: () => setSelected(data), children: label }), _jsx(RepositoryDrawer, { data: selected, onClose: () => setSelected(null) })] }));
|
|
22
|
+
}
|
|
23
|
+
export const Default = {
|
|
24
|
+
render: () => _jsx(DrawerTrigger, { data: repoData, label: "Open Repository" }),
|
|
25
|
+
};
|
|
26
|
+
export const LongPath = {
|
|
27
|
+
render: () => (_jsx(DrawerTrigger, { data: {
|
|
28
|
+
...repoData,
|
|
29
|
+
repositoryPath: '/home/user/projects/company/some-very-long-path/shep-ai/cli',
|
|
30
|
+
}, label: "Open Long Path" })),
|
|
31
|
+
};
|
|
32
|
+
export const WithoutPath = {
|
|
33
|
+
render: () => (_jsx(DrawerTrigger, { data: { ...repoData, repositoryPath: undefined }, label: "Open Without Path" })),
|
|
34
|
+
};
|
package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"review-drawer-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"review-drawer-shell.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.tsx"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,8BAA8B,CAAC;AAE3E,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,WAAW,EACX,kBAAkB,EAClB,SAAS,EACT,cAAc,EACd,MAAM,EACN,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,QAAQ,GACT,EAAE,sBAAsB,2CA0FxB"}
|
package/dist/src/presentation/web/components/common/review-drawer-shell/review-drawer-shell.js
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
'use client';
|
|
2
2
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
3
|
-
import { Loader2, Trash2
|
|
4
|
-
import {
|
|
3
|
+
import { Loader2, Trash2 } from 'lucide-react';
|
|
4
|
+
import { BaseDrawer } from '../../common/base-drawer/index.js';
|
|
5
|
+
import { DrawerTitle, DrawerDescription } from '../../ui/drawer.js';
|
|
5
6
|
import { Button } from '../../ui/button.js';
|
|
6
7
|
import { Separator } from '../../ui/separator.js';
|
|
7
8
|
import { AlertDialog, AlertDialogAction, AlertDialogCancel, AlertDialogContent, AlertDialogDescription, AlertDialogFooter, AlertDialogHeader, AlertDialogTitle, AlertDialogTrigger, } from '../../ui/alert-dialog.js';
|
|
@@ -10,8 +11,5 @@ import { useFeatureActions } from '../../common/feature-drawer/use-feature-actio
|
|
|
10
11
|
export function ReviewDrawerShell({ open, onClose, featureName, featureDescription, featureId, repositoryPath, branch, specPath, onDelete, isDeleting, children, }) {
|
|
11
12
|
const actionsInput = repositoryPath && branch ? { repositoryPath, branch, specPath } : null;
|
|
12
13
|
const actions = useFeatureActions(actionsInput);
|
|
13
|
-
return (
|
|
14
|
-
if (!isOpen)
|
|
15
|
-
onClose();
|
|
16
|
-
}, children: _jsxs(DrawerContent, { direction: "right", className: "w-xl", showCloseButton: false, children: [_jsx("button", { type: "button", "aria-label": "Close", onClick: onClose, className: "ring-offset-background focus:ring-ring absolute top-4 right-4 rounded-xs opacity-70 transition-opacity hover:opacity-100 focus:ring-2 focus:ring-offset-2 focus:outline-hidden", children: _jsx(XIcon, { className: "size-4" }) }), _jsxs(DrawerHeader, { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: featureName }), featureDescription ? (_jsx(DrawerDescription, { children: featureDescription })) : featureId ? (_jsx(DrawerDescription, { className: "sr-only", children: featureId })) : null] }), actionsInput ? (_jsxs("div", { className: "flex items-center gap-2 px-4 pb-3", children: [_jsx(OpenActionMenu, { actions: actions, repositoryPath: actionsInput.repositoryPath, showSpecs: !!specPath }), onDelete && featureId ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-border mx-1 h-4 w-px" }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "review-drawer-delete", children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })] })) : null] })) : null, _jsx(Separator, {}), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: children })] }) }));
|
|
14
|
+
return (_jsxs(BaseDrawer, { open: open, onClose: onClose, size: "md", modal: false, "data-testid": "review-drawer", header: _jsxs(_Fragment, { children: [_jsxs("div", { "data-testid": "feature-drawer-header", children: [_jsx(DrawerTitle, { children: featureName }), featureDescription ? (_jsx(DrawerDescription, { children: featureDescription })) : featureId ? (_jsx(DrawerDescription, { className: "sr-only", children: featureId })) : null] }), actionsInput ? (_jsxs("div", { className: "flex items-center gap-2 pt-2", children: [_jsx(OpenActionMenu, { actions: actions, repositoryPath: actionsInput.repositoryPath, showSpecs: !!specPath }), onDelete && featureId ? (_jsxs(_Fragment, { children: [_jsx("div", { className: "bg-border mx-1 h-4 w-px" }), _jsxs(AlertDialog, { children: [_jsx(AlertDialogTrigger, { asChild: true, children: _jsx(Button, { variant: "ghost", size: "icon-sm", "aria-label": "Delete feature", disabled: isDeleting, className: "text-muted-foreground hover:text-destructive", "data-testid": "review-drawer-delete", children: isDeleting ? (_jsx(Loader2, { className: "size-4 animate-spin" })) : (_jsx(Trash2, { className: "size-4" })) }) }), _jsxs(AlertDialogContent, { children: [_jsxs(AlertDialogHeader, { children: [_jsx(AlertDialogTitle, { children: "Delete feature?" }), _jsxs(AlertDialogDescription, { children: ["This will permanently delete ", _jsx("strong", { children: featureName }), " (", featureId, "). This action cannot be undone."] })] }), _jsxs(AlertDialogFooter, { children: [_jsx(AlertDialogCancel, { disabled: isDeleting, children: "Cancel" }), _jsx(AlertDialogAction, { variant: "destructive", disabled: isDeleting, onClick: () => onDelete(featureId), children: isDeleting ? (_jsxs(_Fragment, { children: [_jsx(Loader2, { className: "mr-2 h-4 w-4 animate-spin" }), "Deleting\u2026"] })) : ('Delete') })] })] })] })] })) : null] })) : null] }), children: [_jsx(Separator, {}), _jsx("div", { className: "flex min-h-0 flex-1 flex-col", children: children })] }));
|
|
17
15
|
}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgB1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;
|
|
1
|
+
{"version":3,"file":"control-center-inner.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/control-center/control-center-inner.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAgB1C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uCAAuC,CAAC;AAc5E,UAAU,uBAAuB;IAC/B,YAAY,EAAE,cAAc,EAAE,CAAC;IAC/B,YAAY,EAAE,IAAI,EAAE,CAAC;CACtB;AAED,wBAAgB,kBAAkB,CAAC,EAAE,YAAY,EAAE,YAAY,EAAE,EAAE,uBAAuB,2CAoczF"}
|
package/dist/src/presentation/web/components/features/control-center/control-center-inner.js
CHANGED
|
@@ -10,6 +10,7 @@ import { getWorkflowDefaults } from '../../../app/actions/get-workflow-defaults.
|
|
|
10
10
|
import { getMergeReviewData } from '../../../app/actions/get-merge-review-data.js';
|
|
11
11
|
import { FeaturesCanvas } from '../../features/features-canvas/index.js';
|
|
12
12
|
import { FeatureDrawer, FeatureCreateDrawer } from '../../common/index.js';
|
|
13
|
+
import { RepositoryDrawer } from '../../common/repository-node/index.js';
|
|
13
14
|
import { PrdQuestionnaireDrawer } from '../../common/prd-questionnaire/index.js';
|
|
14
15
|
import { TechDecisionsDrawer } from '../../common/tech-decisions-review/index.js';
|
|
15
16
|
import { MergeReviewDrawer } from '../../common/merge-review/index.js';
|
|
@@ -50,9 +51,26 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
50
51
|
// Merge review drawer state
|
|
51
52
|
const [mergeReviewData, setMergeReviewData] = useState(null);
|
|
52
53
|
const [isLoadingMergeReview, setIsLoadingMergeReview] = useState(false);
|
|
54
|
+
// Repository drawer state
|
|
55
|
+
const [selectedRepoNode, setSelectedRepoNode] = useState(null);
|
|
56
|
+
// Clear all drawers — used for pane click and canvas drag
|
|
57
|
+
const handleClearDrawers = useCallback(() => {
|
|
58
|
+
clearSelection();
|
|
59
|
+
setSelectedRepoNode(null);
|
|
60
|
+
closeCreateDrawer();
|
|
61
|
+
}, [clearSelection, closeCreateDrawer]);
|
|
62
|
+
// Open repository drawer when a repo node is clicked
|
|
63
|
+
const handleRepositoryClick = useCallback((nodeId) => {
|
|
64
|
+
const node = nodes.find((n) => n.id === nodeId);
|
|
65
|
+
if (node?.type === 'repositoryNode') {
|
|
66
|
+
clearSelection();
|
|
67
|
+
setSelectedRepoNode(node.data);
|
|
68
|
+
}
|
|
69
|
+
}, [nodes, clearSelection]);
|
|
53
70
|
const showPrdDrawer = selectedNode?.lifecycle === 'requirements' && selectedNode?.state === 'action-required';
|
|
54
71
|
const showTechDecisionsDrawer = selectedNode?.lifecycle === 'implementation' && selectedNode?.state === 'action-required';
|
|
55
|
-
const showMergeReviewDrawer = selectedNode?.lifecycle === 'review' &&
|
|
72
|
+
const showMergeReviewDrawer = selectedNode?.lifecycle === 'review' &&
|
|
73
|
+
(selectedNode?.state === 'action-required' || selectedNode?.state === 'error');
|
|
56
74
|
const handlePrdSelect = useCallback((questionId, optionId) => {
|
|
57
75
|
setPrdSelections((prev) => ({ ...prev, [questionId]: optionId }));
|
|
58
76
|
}, []);
|
|
@@ -257,5 +275,5 @@ export function ControlCenterInner({ initialNodes, initialEdges }) {
|
|
|
257
275
|
if (!hasRepositories) {
|
|
258
276
|
return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }), _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, repositoryPath: pendingRepositoryPath, workflowDefaults: workflowDefaults, features: featureOptions, initialParentId: pendingParentFeatureId })] }));
|
|
259
277
|
}
|
|
260
|
-
return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick:
|
|
278
|
+
return (_jsxs(_Fragment, { children: [_jsx(NotificationPermissionBanner, {}), _jsx(FeaturesCanvas, { nodes: nodes, edges: edges, onNodesChange: onNodesChange, onConnect: handleConnect, onAddFeature: handleAddFeature, onNodeAction: handleAddFeatureToFeature, onNodeClick: handleNodeClick, onPaneClick: handleClearDrawers, onRepositoryAdd: handleAddFeatureToRepo, onRepositoryClick: handleRepositoryClick, onRepositoryDelete: handleDeleteRepository, onRepositorySelect: handleAddRepository, onCanvasDrag: handleClearDrawers, emptyState: _jsx(ControlCenterEmptyState, { onRepositorySelect: handleAddRepository }) }), _jsx(FeatureDrawer, { selectedNode: showPrdDrawer || showTechDecisionsDrawer || showMergeReviewDrawer ? null : selectedNode, onClose: clearSelection, onDelete: handleDeleteFeature, isDeleting: isDeleting }), showPrdDrawer ? (_jsx(PrdQuestionnaireDrawer, { open: true, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureDescription: selectedNode?.description, featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: questionnaireData, selections: prdSelections, onSelect: handlePrdSelect, onApprove: handlePrdApprove, onReject: handlePrdReject, isRejecting: isRejecting, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingQuestionnaire })) : null, showTechDecisionsDrawer ? (_jsx(TechDecisionsDrawer, { open: true, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: techDecisionsData, onApprove: handleTechDecisionsApprove, onReject: handleTechDecisionsReject, isRejecting: isRejecting, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingTechDecisions })) : null, showMergeReviewDrawer ? (_jsx(MergeReviewDrawer, { open: true, onClose: clearSelection, featureName: selectedNode?.name ?? '', featureId: selectedNode?.featureId, repositoryPath: selectedNode?.repositoryPath, branch: selectedNode?.branch, specPath: selectedNode?.specPath, data: mergeReviewData, onApprove: handleMergeApprove, onReject: handleMergeReject, isRejecting: isRejecting, onDelete: handleDeleteFeature, isDeleting: isDeleting, isProcessing: isLoadingMergeReview })) : null, _jsx(FeatureCreateDrawer, { open: isCreateDrawerOpen, onClose: closeCreateDrawer, onSubmit: handleCreateFeatureSubmit, repositoryPath: pendingRepositoryPath, workflowDefaults: workflowDefaults, features: featureOptions, initialParentId: pendingParentFeatureId }), _jsx(RepositoryDrawer, { data: selectedRepoNode, onClose: () => setSelectedRepoNode(null) })] }));
|
|
261
279
|
}
|
|
@@ -13,11 +13,13 @@ export interface FeaturesCanvasProps {
|
|
|
13
13
|
onNodeClick?: (event: React.MouseEvent, node: CanvasNodeType) => void;
|
|
14
14
|
onPaneClick?: (event: React.MouseEvent) => void;
|
|
15
15
|
onRepositoryAdd?: (repoNodeId: string) => void;
|
|
16
|
+
onRepositoryClick?: (nodeId: string) => void;
|
|
16
17
|
onRepositoryDelete?: (repositoryId: string) => void;
|
|
17
18
|
onConnect?: (connection: Connection) => void;
|
|
18
19
|
onRepositorySelect?: (path: string) => void;
|
|
20
|
+
onCanvasDrag?: () => void;
|
|
19
21
|
toolbar?: React.ReactNode;
|
|
20
22
|
emptyState?: React.ReactNode;
|
|
21
23
|
}
|
|
22
|
-
export declare function FeaturesCanvas({ nodes, edges, onNodesChange, onAddFeature, onNodeAction, onNodeSettings, onConnect, onNodeClick, onPaneClick, onRepositoryAdd, onRepositoryDelete, onRepositorySelect, toolbar, emptyState, }: FeaturesCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
24
|
+
export declare function FeaturesCanvas({ nodes, edges, onNodesChange, onAddFeature, onNodeAction, onNodeSettings, onConnect, onNodeClick, onPaneClick, onRepositoryAdd, onRepositoryClick, onRepositoryDelete, onRepositorySelect, onCanvasDrag, toolbar, emptyState, }: FeaturesCanvasProps): import("react/jsx-runtime").JSX.Element;
|
|
23
25
|
//# sourceMappingURL=features-canvas.d.ts.map
|
package/dist/src/presentation/web/components/features/features-canvas/features-canvas.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"features-canvas.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/features-canvas.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKlE,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,kCAAkC,CAAC;AAEzF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAE9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAGrF,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,kBAAkB,GAAG,qBAAqB,CAAC;AAE1F,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAChE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACtE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAChD,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,EACf,kBAAkB,EAClB,kBAAkB,EAClB,OAAO,EACP,UAAU,GACX,EAAE,mBAAmB,
|
|
1
|
+
{"version":3,"file":"features-canvas.d.ts","sourceRoot":"","sources":["../../../../../../../src/presentation/web/components/features/features-canvas/features-canvas.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAKlE,OAAO,KAAK,EAAE,eAAe,EAAmB,MAAM,kCAAkC,CAAC;AAEzF,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AAE9E,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,yCAAyC,CAAC;AAGrF,MAAM,MAAM,cAAc,GAAG,eAAe,GAAG,kBAAkB,GAAG,qBAAqB,CAAC;AAE1F,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,KAAK,EAAE,IAAI,EAAE,CAAC;IACd,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,UAAU,CAAC,cAAc,CAAC,EAAE,KAAK,IAAI,CAAC;IAChE,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,YAAY,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC1C,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,EAAE,IAAI,EAAE,cAAc,KAAK,IAAI,CAAC;IACtE,WAAW,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,CAAC,UAAU,KAAK,IAAI,CAAC;IAChD,eAAe,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IAC/C,iBAAiB,CAAC,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAC7C,kBAAkB,CAAC,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,SAAS,CAAC,EAAE,CAAC,UAAU,EAAE,UAAU,KAAK,IAAI,CAAC;IAC7C,kBAAkB,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,YAAY,CAAC,EAAE,MAAM,IAAI,CAAC;IAC1B,OAAO,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC1B,UAAU,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;CAC9B;AAED,wBAAgB,cAAc,CAAC,EAC7B,KAAK,EACL,KAAK,EACL,aAAa,EACb,YAAY,EACZ,YAAY,EACZ,cAAc,EACd,SAAS,EACT,WAAW,EACX,WAAW,EACX,eAAe,EACf,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,YAAY,EACZ,OAAO,EACP,UAAU,GACX,EAAE,mBAAmB,2CAsHrB"}
|