@shepai/cli 1.62.0 → 1.64.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/application/ports/output/agents/agent-executor-factory.interface.d.ts +18 -0
- package/dist/packages/core/src/application/ports/output/agents/agent-executor-factory.interface.d.ts.map +1 -1
- package/dist/packages/core/src/application/ports/output/agents/index.d.ts +1 -1
- package/dist/packages/core/src/application/ports/output/agents/index.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/agent-executor-factory.service.js +7 -0
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/mock-executor-factory.service.d.ts +2 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/mock-executor-factory.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/agents/common/executors/mock-executor-factory.service.js +3 -0
- package/dist/packages/core/src/infrastructure/services/filesystem/shep-directory.service.d.ts +7 -0
- package/dist/packages/core/src/infrastructure/services/filesystem/shep-directory.service.d.ts.map +1 -1
- package/dist/packages/core/src/infrastructure/services/filesystem/shep-directory.service.js +9 -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 +18 -4
- package/dist/packages/core/src/infrastructure/services/pr-sync/pr-sync-watcher.service.js +1 -1
- package/dist/src/presentation/cli/commands/daemon/start-daemon.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/daemon/start-daemon.js +24 -15
- package/dist/src/presentation/cli/commands/status.command.d.ts +7 -0
- package/dist/src/presentation/cli/commands/status.command.d.ts.map +1 -1
- package/dist/src/presentation/cli/commands/status.command.js +167 -3
- 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 +9 -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 +143 -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/04d22f0d67c6671b.js +10 -0
- 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/{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/bcd97add650ece51.js +1 -0
- package/web/.next/static/chunks/be784143669bb992.js +1 -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/45f510f84c7c417d.css +0 -2
- package/web/.next/static/chunks/8e4c719503d9387e.js +0 -1
- package/web/.next/static/chunks/cd44f06f18e3425a.js +0 -10
- /package/web/.next/static/{2z-UoCok36_D1hh1-N88G → R37CbaEU-TK9xR6x4aI_Z}/_buildManifest.js +0 -0
- /package/web/.next/static/{2z-UoCok36_D1hh1-N88G → R37CbaEU-TK9xR6x4aI_Z}/_clientMiddlewareManifest.json +0 -0
- /package/web/.next/static/{2z-UoCok36_D1hh1-N88G → R37CbaEU-TK9xR6x4aI_Z}/_ssgManifest.js +0 -0
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
import { useState } from 'react';
|
|
2
|
+
import type { Meta, StoryObj } from '@storybook/react';
|
|
3
|
+
import { BaseDrawer } from './base-drawer';
|
|
4
|
+
import { DrawerTitle, DrawerDescription } from '@/components/ui/drawer';
|
|
5
|
+
import { Button } from '@/components/ui/button';
|
|
6
|
+
|
|
7
|
+
const meta: Meta<typeof BaseDrawer> = {
|
|
8
|
+
title: 'Common/BaseDrawer',
|
|
9
|
+
component: BaseDrawer,
|
|
10
|
+
tags: ['autodocs'],
|
|
11
|
+
parameters: {
|
|
12
|
+
layout: 'fullscreen',
|
|
13
|
+
},
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export default meta;
|
|
17
|
+
type Story = StoryObj<typeof BaseDrawer>;
|
|
18
|
+
|
|
19
|
+
/* ---------------------------------------------------------------------------
|
|
20
|
+
* Trigger wrapper — starts closed, click to open
|
|
21
|
+
* ------------------------------------------------------------------------- */
|
|
22
|
+
|
|
23
|
+
function DrawerTrigger(props: Omit<React.ComponentProps<typeof BaseDrawer>, 'open' | 'onClose'>) {
|
|
24
|
+
const [open, setOpen] = useState(false);
|
|
25
|
+
|
|
26
|
+
return (
|
|
27
|
+
<div className="flex h-screen items-start p-4">
|
|
28
|
+
<Button variant="outline" onClick={() => setOpen(true)}>
|
|
29
|
+
Open Drawer
|
|
30
|
+
</Button>
|
|
31
|
+
<BaseDrawer {...props} open={open} onClose={() => setOpen(false)} />
|
|
32
|
+
</div>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/* ---------------------------------------------------------------------------
|
|
37
|
+
* Stories
|
|
38
|
+
* ------------------------------------------------------------------------- */
|
|
39
|
+
|
|
40
|
+
/** Default drawer with sm size, non-modal, children only. */
|
|
41
|
+
export const Default: Story = {
|
|
42
|
+
render: () => (
|
|
43
|
+
<DrawerTrigger>
|
|
44
|
+
<div className="p-4">
|
|
45
|
+
<p className="text-muted-foreground text-sm">Default drawer content</p>
|
|
46
|
+
</div>
|
|
47
|
+
</DrawerTrigger>
|
|
48
|
+
),
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
/** Explicit sm size with inspector-style content. */
|
|
52
|
+
export const SmallSize: Story = {
|
|
53
|
+
render: () => (
|
|
54
|
+
<DrawerTrigger size="sm">
|
|
55
|
+
<div className="flex flex-col gap-3 p-4">
|
|
56
|
+
<h3 className="text-sm font-semibold">Feature Inspector</h3>
|
|
57
|
+
<div className="flex flex-col gap-1">
|
|
58
|
+
<span className="text-muted-foreground text-xs">Status</span>
|
|
59
|
+
<span className="text-sm">Running</span>
|
|
60
|
+
</div>
|
|
61
|
+
<div className="flex flex-col gap-1">
|
|
62
|
+
<span className="text-muted-foreground text-xs">Progress</span>
|
|
63
|
+
<div className="bg-muted h-2 w-full overflow-hidden rounded-full">
|
|
64
|
+
<div className="bg-primary h-full w-[45%] rounded-full" />
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</div>
|
|
68
|
+
</DrawerTrigger>
|
|
69
|
+
),
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
/** Medium size with content-rich review-style content. */
|
|
73
|
+
export const MediumSize: Story = {
|
|
74
|
+
render: () => (
|
|
75
|
+
<DrawerTrigger size="md">
|
|
76
|
+
<div className="flex flex-col gap-4 p-4">
|
|
77
|
+
<h3 className="text-sm font-semibold">Review Content</h3>
|
|
78
|
+
<p className="text-muted-foreground text-sm">
|
|
79
|
+
This drawer uses size="md" (w-xl / 576px) for content-rich review panels that
|
|
80
|
+
need more horizontal space for diff summaries, tables, and code blocks.
|
|
81
|
+
</p>
|
|
82
|
+
<div className="bg-muted rounded-md p-3">
|
|
83
|
+
<pre className="text-xs">
|
|
84
|
+
{`+ Added authentication middleware\n- Removed legacy session handler\n Updated user model schema`}
|
|
85
|
+
</pre>
|
|
86
|
+
</div>
|
|
87
|
+
</div>
|
|
88
|
+
</DrawerTrigger>
|
|
89
|
+
),
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
/** Modal drawer with overlay. */
|
|
93
|
+
export const Modal: Story = {
|
|
94
|
+
render: () => (
|
|
95
|
+
<DrawerTrigger modal>
|
|
96
|
+
<div className="p-4">
|
|
97
|
+
<p className="text-muted-foreground text-sm">
|
|
98
|
+
This drawer is modal — an overlay blocks background interaction and focus is trapped.
|
|
99
|
+
</p>
|
|
100
|
+
</div>
|
|
101
|
+
</DrawerTrigger>
|
|
102
|
+
),
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/** Drawer with header slot containing DrawerTitle and DrawerDescription. */
|
|
106
|
+
export const WithHeader: Story = {
|
|
107
|
+
render: () => (
|
|
108
|
+
<DrawerTrigger
|
|
109
|
+
header={
|
|
110
|
+
<>
|
|
111
|
+
<DrawerTitle>Feature Details</DrawerTitle>
|
|
112
|
+
<DrawerDescription>FEAT-042 — Authentication Flow</DrawerDescription>
|
|
113
|
+
</>
|
|
114
|
+
}
|
|
115
|
+
>
|
|
116
|
+
<div className="p-4">
|
|
117
|
+
<p className="text-muted-foreground text-sm">Content below the header.</p>
|
|
118
|
+
</div>
|
|
119
|
+
</DrawerTrigger>
|
|
120
|
+
),
|
|
121
|
+
};
|
|
122
|
+
|
|
123
|
+
/** Drawer with footer slot containing action buttons. */
|
|
124
|
+
export const WithFooter: Story = {
|
|
125
|
+
render: () => (
|
|
126
|
+
<DrawerTrigger
|
|
127
|
+
footer={
|
|
128
|
+
<div className="flex gap-2">
|
|
129
|
+
<Button variant="outline" className="flex-1">
|
|
130
|
+
Cancel
|
|
131
|
+
</Button>
|
|
132
|
+
<Button className="flex-1">Save</Button>
|
|
133
|
+
</div>
|
|
134
|
+
}
|
|
135
|
+
>
|
|
136
|
+
<div className="p-4">
|
|
137
|
+
<p className="text-muted-foreground text-sm">Content above the footer.</p>
|
|
138
|
+
</div>
|
|
139
|
+
</DrawerTrigger>
|
|
140
|
+
),
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
/** Drawer with both header and footer slots populated. */
|
|
144
|
+
export const WithHeaderAndFooter: Story = {
|
|
145
|
+
render: () => (
|
|
146
|
+
<DrawerTrigger
|
|
147
|
+
header={
|
|
148
|
+
<>
|
|
149
|
+
<DrawerTitle>Create Feature</DrawerTitle>
|
|
150
|
+
<DrawerDescription>Fill in the details below</DrawerDescription>
|
|
151
|
+
</>
|
|
152
|
+
}
|
|
153
|
+
footer={
|
|
154
|
+
<div className="flex gap-2">
|
|
155
|
+
<Button variant="outline" className="flex-1">
|
|
156
|
+
Cancel
|
|
157
|
+
</Button>
|
|
158
|
+
<Button className="flex-1">Create</Button>
|
|
159
|
+
</div>
|
|
160
|
+
}
|
|
161
|
+
>
|
|
162
|
+
<div className="flex flex-col gap-4 p-4">
|
|
163
|
+
<div className="flex flex-col gap-1">
|
|
164
|
+
<label className="text-sm font-medium">Name</label>
|
|
165
|
+
<input
|
|
166
|
+
type="text"
|
|
167
|
+
className="border-input bg-background rounded-md border px-3 py-2 text-sm"
|
|
168
|
+
placeholder="Feature name"
|
|
169
|
+
/>
|
|
170
|
+
</div>
|
|
171
|
+
<div className="flex flex-col gap-1">
|
|
172
|
+
<label className="text-sm font-medium">Description</label>
|
|
173
|
+
<textarea
|
|
174
|
+
className="border-input bg-background rounded-md border px-3 py-2 text-sm"
|
|
175
|
+
rows={3}
|
|
176
|
+
placeholder="Optional description"
|
|
177
|
+
/>
|
|
178
|
+
</div>
|
|
179
|
+
</div>
|
|
180
|
+
</DrawerTrigger>
|
|
181
|
+
),
|
|
182
|
+
};
|
|
183
|
+
|
|
184
|
+
/** Drawer with content that exceeds viewport to demonstrate scroll behavior. */
|
|
185
|
+
export const ScrollableContent: Story = {
|
|
186
|
+
render: () => (
|
|
187
|
+
<DrawerTrigger
|
|
188
|
+
header={
|
|
189
|
+
<>
|
|
190
|
+
<DrawerTitle>Scrollable Content</DrawerTitle>
|
|
191
|
+
<DrawerDescription>Content below overflows and scrolls</DrawerDescription>
|
|
192
|
+
</>
|
|
193
|
+
}
|
|
194
|
+
>
|
|
195
|
+
<div className="flex flex-col gap-4 p-4">
|
|
196
|
+
{Array.from({ length: 30 }, (_, i) => (
|
|
197
|
+
<div key={i} className="border-border rounded-md border p-3">
|
|
198
|
+
<h4 className="text-sm font-medium">Item {i + 1}</h4>
|
|
199
|
+
<p className="text-muted-foreground text-xs">
|
|
200
|
+
This is a scrollable content item to demonstrate overflow handling.
|
|
201
|
+
</p>
|
|
202
|
+
</div>
|
|
203
|
+
))}
|
|
204
|
+
</div>
|
|
205
|
+
</DrawerTrigger>
|
|
206
|
+
),
|
|
207
|
+
};
|
package/web/.next/standalone/src/presentation/web/components/common/base-drawer/base-drawer.tsx
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
|
|
3
|
+
import { XIcon } from 'lucide-react';
|
|
4
|
+
import { cva, type VariantProps } from 'class-variance-authority';
|
|
5
|
+
import { cn } from '@/lib/utils';
|
|
6
|
+
import {
|
|
7
|
+
Drawer,
|
|
8
|
+
DrawerContent,
|
|
9
|
+
DrawerHeader,
|
|
10
|
+
DrawerFooter,
|
|
11
|
+
DrawerOverlay,
|
|
12
|
+
} from '@/components/ui/drawer';
|
|
13
|
+
|
|
14
|
+
const drawerVariants = cva('', {
|
|
15
|
+
variants: {
|
|
16
|
+
size: {
|
|
17
|
+
sm: 'w-96',
|
|
18
|
+
md: 'w-xl',
|
|
19
|
+
},
|
|
20
|
+
},
|
|
21
|
+
defaultVariants: {
|
|
22
|
+
size: 'sm',
|
|
23
|
+
},
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
export interface BaseDrawerProps extends VariantProps<typeof drawerVariants> {
|
|
27
|
+
open: boolean;
|
|
28
|
+
onClose: () => void;
|
|
29
|
+
modal?: boolean;
|
|
30
|
+
header?: React.ReactNode;
|
|
31
|
+
children: React.ReactNode;
|
|
32
|
+
footer?: React.ReactNode;
|
|
33
|
+
className?: string;
|
|
34
|
+
'data-testid'?: string;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function BaseDrawer({
|
|
38
|
+
open,
|
|
39
|
+
onClose,
|
|
40
|
+
modal = false,
|
|
41
|
+
size,
|
|
42
|
+
header,
|
|
43
|
+
children,
|
|
44
|
+
footer,
|
|
45
|
+
className,
|
|
46
|
+
'data-testid': testId,
|
|
47
|
+
}: BaseDrawerProps) {
|
|
48
|
+
return (
|
|
49
|
+
<Drawer
|
|
50
|
+
direction="right"
|
|
51
|
+
modal={modal}
|
|
52
|
+
handleOnly
|
|
53
|
+
open={open}
|
|
54
|
+
onOpenChange={(isOpen) => {
|
|
55
|
+
if (!isOpen) onClose();
|
|
56
|
+
}}
|
|
57
|
+
>
|
|
58
|
+
{modal ? <DrawerOverlay /> : null}
|
|
59
|
+
<DrawerContent
|
|
60
|
+
direction="right"
|
|
61
|
+
showCloseButton={false}
|
|
62
|
+
className={cn(drawerVariants({ size }), className)}
|
|
63
|
+
data-testid={testId}
|
|
64
|
+
>
|
|
65
|
+
{/* Close button */}
|
|
66
|
+
<button
|
|
67
|
+
type="button"
|
|
68
|
+
aria-label="Close"
|
|
69
|
+
onClick={onClose}
|
|
70
|
+
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"
|
|
71
|
+
data-testid={testId ? `${testId}-close-button` : undefined}
|
|
72
|
+
>
|
|
73
|
+
<XIcon className="size-4" />
|
|
74
|
+
<span className="sr-only">Close</span>
|
|
75
|
+
</button>
|
|
76
|
+
|
|
77
|
+
{/* Header slot */}
|
|
78
|
+
{header ? <DrawerHeader>{header}</DrawerHeader> : null}
|
|
79
|
+
|
|
80
|
+
{/* Scrollable content area */}
|
|
81
|
+
<div className="flex-1 overflow-y-auto">
|
|
82
|
+
<div className="flex flex-col">{children}</div>
|
|
83
|
+
</div>
|
|
84
|
+
|
|
85
|
+
{/* Footer slot */}
|
|
86
|
+
{footer ? <DrawerFooter>{footer}</DrawerFooter> : null}
|
|
87
|
+
</DrawerContent>
|
|
88
|
+
</Drawer>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BaseDrawer, type BaseDrawerProps } from './base-drawer';
|
|
@@ -36,7 +36,7 @@ import { Button } from '@/components/ui/button';
|
|
|
36
36
|
* - Submit button is disabled when name is empty
|
|
37
37
|
* - `approvalGates` always included: `{ allowPrd, allowPlan, allowMerge }` (all false by default)
|
|
38
38
|
* - Non-modal (`modal={false}`) — canvas stays interactive behind the drawer
|
|
39
|
-
* - Fixed width:
|
|
39
|
+
* - Fixed width: 448px (`w-xl`) — matches review drawers (PRD, Plan, Merge)
|
|
40
40
|
* - Attachments use native OS file picker via `pickFiles()` — returns `FileAttachment[]`
|
|
41
41
|
* with full absolute paths, filenames, and sizes
|
|
42
42
|
*/
|
|
@@ -3,7 +3,6 @@
|
|
|
3
3
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
4
4
|
import type { LucideIcon } from 'lucide-react';
|
|
5
5
|
import {
|
|
6
|
-
XIcon,
|
|
7
6
|
PlusIcon,
|
|
8
7
|
FileIcon,
|
|
9
8
|
FileTextIcon,
|
|
@@ -15,14 +14,8 @@ import {
|
|
|
15
14
|
} from 'lucide-react';
|
|
16
15
|
import { cn } from '@/lib/utils';
|
|
17
16
|
import { useSoundAction } from '@/hooks/use-sound-action';
|
|
18
|
-
import {
|
|
19
|
-
|
|
20
|
-
DrawerContent,
|
|
21
|
-
DrawerHeader,
|
|
22
|
-
DrawerTitle,
|
|
23
|
-
DrawerDescription,
|
|
24
|
-
DrawerFooter,
|
|
25
|
-
} from '@/components/ui/drawer';
|
|
17
|
+
import { BaseDrawer } from '@/components/common/base-drawer';
|
|
18
|
+
import { DrawerTitle, DrawerDescription } from '@/components/ui/drawer';
|
|
26
19
|
import { Button } from '@/components/ui/button';
|
|
27
20
|
import { Input } from '@/components/ui/input';
|
|
28
21
|
import { Textarea } from '@/components/ui/textarea';
|
|
@@ -142,16 +135,11 @@ export function FeatureCreateDrawer({
|
|
|
142
135
|
setParentId(undefined);
|
|
143
136
|
}, [defaultGates, defaultPush, defaultOpenPr]);
|
|
144
137
|
|
|
145
|
-
const
|
|
146
|
-
(
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
onClose();
|
|
151
|
-
}
|
|
152
|
-
},
|
|
153
|
-
[onClose, resetForm, drawerCloseSound]
|
|
154
|
-
);
|
|
138
|
+
const handleClose = useCallback(() => {
|
|
139
|
+
drawerCloseSound.play();
|
|
140
|
+
resetForm();
|
|
141
|
+
onClose();
|
|
142
|
+
}, [onClose, resetForm, drawerCloseSound]);
|
|
155
143
|
|
|
156
144
|
const handleSubmit = useCallback(
|
|
157
145
|
(e: React.FormEvent) => {
|
|
@@ -208,23 +196,14 @@ export function FeatureCreateDrawer({
|
|
|
208
196
|
const hasFeatures = features && features.length > 0;
|
|
209
197
|
|
|
210
198
|
return (
|
|
211
|
-
<
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
onClose();
|
|
220
|
-
}}
|
|
221
|
-
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"
|
|
222
|
-
>
|
|
223
|
-
<XIcon className="size-4" />
|
|
224
|
-
</button>
|
|
225
|
-
|
|
226
|
-
{/* Header */}
|
|
227
|
-
<DrawerHeader>
|
|
199
|
+
<BaseDrawer
|
|
200
|
+
open={open}
|
|
201
|
+
onClose={handleClose}
|
|
202
|
+
size="md"
|
|
203
|
+
modal={false}
|
|
204
|
+
data-testid="feature-create-drawer"
|
|
205
|
+
header={
|
|
206
|
+
<>
|
|
228
207
|
<div className="flex items-center gap-2">
|
|
229
208
|
<div className="h-2.5 w-2.5 shrink-0 rounded-full bg-blue-500" />
|
|
230
209
|
<DrawerTitle>NEW FEATURE</DrawerTitle>
|
|
@@ -234,164 +213,156 @@ export function FeatureCreateDrawer({
|
|
|
234
213
|
<Badge variant="secondary">Creating...</Badge>
|
|
235
214
|
</div>
|
|
236
215
|
</DrawerDescription>
|
|
237
|
-
|
|
216
|
+
</>
|
|
217
|
+
}
|
|
218
|
+
footer={
|
|
219
|
+
<div className="flex flex-row justify-end gap-2">
|
|
220
|
+
<Button variant="outline" onClick={handleClose} disabled={isSubmitting}>
|
|
221
|
+
Cancel
|
|
222
|
+
</Button>
|
|
223
|
+
<Button type="submit" form="create-feature-form" disabled={!name.trim() || isSubmitting}>
|
|
224
|
+
{isSubmitting ? 'Creating...' : '+ Create Feature'}
|
|
225
|
+
</Button>
|
|
226
|
+
</div>
|
|
227
|
+
}
|
|
228
|
+
>
|
|
229
|
+
<Separator />
|
|
230
|
+
|
|
231
|
+
{/* Form body */}
|
|
232
|
+
<div className="p-4">
|
|
233
|
+
<form id="create-feature-form" onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
234
|
+
{/* Feature name */}
|
|
235
|
+
<div className="flex flex-col gap-1.5">
|
|
236
|
+
<Label
|
|
237
|
+
htmlFor="feature-name"
|
|
238
|
+
className="text-muted-foreground text-xs font-semibold tracking-wider"
|
|
239
|
+
>
|
|
240
|
+
FEATURE NAME
|
|
241
|
+
</Label>
|
|
242
|
+
<Input
|
|
243
|
+
id="feature-name"
|
|
244
|
+
placeholder="e.g. GitHub OAuth Login"
|
|
245
|
+
value={name}
|
|
246
|
+
onChange={(e) => setName(e.target.value)}
|
|
247
|
+
required
|
|
248
|
+
disabled={isSubmitting}
|
|
249
|
+
/>
|
|
250
|
+
</div>
|
|
238
251
|
|
|
239
|
-
|
|
252
|
+
{/* Description */}
|
|
253
|
+
<div className="flex flex-col gap-1.5">
|
|
254
|
+
<Label
|
|
255
|
+
htmlFor="feature-description"
|
|
256
|
+
className="text-muted-foreground text-xs font-semibold tracking-wider"
|
|
257
|
+
>
|
|
258
|
+
DESCRIPTION
|
|
259
|
+
</Label>
|
|
260
|
+
<Textarea
|
|
261
|
+
id="feature-description"
|
|
262
|
+
placeholder="Describe what this feature does..."
|
|
263
|
+
value={description}
|
|
264
|
+
onChange={(e) => setDescription(e.target.value)}
|
|
265
|
+
rows={4}
|
|
266
|
+
disabled={isSubmitting}
|
|
267
|
+
/>
|
|
268
|
+
</div>
|
|
240
269
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
<form id="create-feature-form" onSubmit={handleSubmit} className="flex flex-col gap-4">
|
|
244
|
-
{/* Feature name */}
|
|
270
|
+
{/* Parent feature selector (only when features are available) */}
|
|
271
|
+
{hasFeatures ? (
|
|
245
272
|
<div className="flex flex-col gap-1.5">
|
|
246
273
|
<Label
|
|
247
|
-
htmlFor="feature
|
|
274
|
+
htmlFor="parent-feature"
|
|
248
275
|
className="text-muted-foreground text-xs font-semibold tracking-wider"
|
|
249
276
|
>
|
|
250
|
-
FEATURE
|
|
277
|
+
PARENT FEATURE
|
|
251
278
|
</Label>
|
|
252
|
-
<
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
onChange={(e) => setName(e.target.value)}
|
|
257
|
-
required
|
|
279
|
+
<ParentFeatureCombobox
|
|
280
|
+
features={features}
|
|
281
|
+
value={parentId}
|
|
282
|
+
onChange={setParentId}
|
|
258
283
|
disabled={isSubmitting}
|
|
259
284
|
/>
|
|
260
285
|
</div>
|
|
286
|
+
) : null}
|
|
287
|
+
|
|
288
|
+
{/* Auto-approve checkboxes */}
|
|
289
|
+
<div className="flex flex-col gap-1.5">
|
|
290
|
+
<Label className="text-muted-foreground text-xs font-semibold tracking-wider">
|
|
291
|
+
APPROVE
|
|
292
|
+
</Label>
|
|
293
|
+
<CheckboxGroup
|
|
294
|
+
label="Autonomous Mode"
|
|
295
|
+
description="YOLO!"
|
|
296
|
+
parentAriaLabel="Auto approve all"
|
|
297
|
+
options={AUTO_APPROVE_OPTIONS}
|
|
298
|
+
value={approvalGates}
|
|
299
|
+
onValueChange={setApprovalGates}
|
|
300
|
+
disabled={isSubmitting}
|
|
301
|
+
/>
|
|
302
|
+
</div>
|
|
261
303
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
304
|
+
{/* Git options */}
|
|
305
|
+
<div className="flex flex-col gap-1.5">
|
|
306
|
+
<Label className="text-muted-foreground text-xs font-semibold tracking-wider">
|
|
307
|
+
GIT
|
|
308
|
+
</Label>
|
|
309
|
+
<div className="flex flex-col gap-2">
|
|
310
|
+
<CheckboxGroupItem
|
|
311
|
+
id="push"
|
|
312
|
+
label="Push"
|
|
313
|
+
description="Push branch to remote after implementation."
|
|
314
|
+
checked={push || openPr}
|
|
315
|
+
onCheckedChange={setPush}
|
|
316
|
+
disabled={openPr || isSubmitting}
|
|
317
|
+
/>
|
|
318
|
+
<CheckboxGroupItem
|
|
319
|
+
id="open-pr"
|
|
320
|
+
label="Create PR"
|
|
321
|
+
description="Open a pull request after pushing."
|
|
322
|
+
checked={openPr}
|
|
323
|
+
onCheckedChange={setOpenPr}
|
|
276
324
|
disabled={isSubmitting}
|
|
277
325
|
/>
|
|
278
326
|
</div>
|
|
327
|
+
</div>
|
|
279
328
|
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
<Label
|
|
284
|
-
htmlFor="parent-feature"
|
|
285
|
-
className="text-muted-foreground text-xs font-semibold tracking-wider"
|
|
286
|
-
>
|
|
287
|
-
PARENT FEATURE
|
|
288
|
-
</Label>
|
|
289
|
-
<ParentFeatureCombobox
|
|
290
|
-
features={features}
|
|
291
|
-
value={parentId}
|
|
292
|
-
onChange={setParentId}
|
|
293
|
-
disabled={isSubmitting}
|
|
294
|
-
/>
|
|
295
|
-
</div>
|
|
296
|
-
) : null}
|
|
297
|
-
|
|
298
|
-
{/* Auto-approve checkboxes */}
|
|
299
|
-
<div className="flex flex-col gap-1.5">
|
|
329
|
+
{/* Attachments */}
|
|
330
|
+
<div className="flex flex-col gap-2">
|
|
331
|
+
<div className="flex items-center justify-between">
|
|
300
332
|
<Label className="text-muted-foreground text-xs font-semibold tracking-wider">
|
|
301
|
-
|
|
333
|
+
ATTACHMENTS
|
|
334
|
+
{attachments.length > 0 && (
|
|
335
|
+
<span className="text-muted-foreground/60 ml-1.5">({attachments.length})</span>
|
|
336
|
+
)}
|
|
302
337
|
</Label>
|
|
303
|
-
<
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
value={approvalGates}
|
|
309
|
-
onValueChange={setApprovalGates}
|
|
338
|
+
<Button
|
|
339
|
+
type="button"
|
|
340
|
+
variant="outline"
|
|
341
|
+
size="xs"
|
|
342
|
+
onClick={handleAddFiles}
|
|
310
343
|
disabled={isSubmitting}
|
|
311
|
-
|
|
344
|
+
>
|
|
345
|
+
<PlusIcon className="size-3" />
|
|
346
|
+
Add Files
|
|
347
|
+
</Button>
|
|
312
348
|
</div>
|
|
313
349
|
|
|
314
|
-
{
|
|
315
|
-
<div className="flex flex-col gap-1.5">
|
|
316
|
-
<Label className="text-muted-foreground text-xs font-semibold tracking-wider">
|
|
317
|
-
GIT
|
|
318
|
-
</Label>
|
|
350
|
+
{attachments.length > 0 && (
|
|
319
351
|
<div className="flex flex-col gap-2">
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
<CheckboxGroupItem
|
|
329
|
-
id="open-pr"
|
|
330
|
-
label="Create PR"
|
|
331
|
-
description="Open a pull request after pushing."
|
|
332
|
-
checked={openPr}
|
|
333
|
-
onCheckedChange={setOpenPr}
|
|
334
|
-
disabled={isSubmitting}
|
|
335
|
-
/>
|
|
352
|
+
{attachments.map((file) => (
|
|
353
|
+
<AttachmentCard
|
|
354
|
+
key={file.path}
|
|
355
|
+
file={file}
|
|
356
|
+
onRemove={() => handleRemoveFile(file.path)}
|
|
357
|
+
disabled={isSubmitting}
|
|
358
|
+
/>
|
|
359
|
+
))}
|
|
336
360
|
</div>
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
<Label className="text-muted-foreground text-xs font-semibold tracking-wider">
|
|
343
|
-
ATTACHMENTS
|
|
344
|
-
{attachments.length > 0 && (
|
|
345
|
-
<span className="text-muted-foreground/60 ml-1.5">({attachments.length})</span>
|
|
346
|
-
)}
|
|
347
|
-
</Label>
|
|
348
|
-
<Button
|
|
349
|
-
type="button"
|
|
350
|
-
variant="outline"
|
|
351
|
-
size="xs"
|
|
352
|
-
onClick={handleAddFiles}
|
|
353
|
-
disabled={isSubmitting}
|
|
354
|
-
>
|
|
355
|
-
<PlusIcon className="size-3" />
|
|
356
|
-
Add Files
|
|
357
|
-
</Button>
|
|
358
|
-
</div>
|
|
359
|
-
|
|
360
|
-
{attachments.length > 0 && (
|
|
361
|
-
<div className="flex flex-col gap-2">
|
|
362
|
-
{attachments.map((file) => (
|
|
363
|
-
<AttachmentCard
|
|
364
|
-
key={file.path}
|
|
365
|
-
file={file}
|
|
366
|
-
onRemove={() => handleRemoveFile(file.path)}
|
|
367
|
-
disabled={isSubmitting}
|
|
368
|
-
/>
|
|
369
|
-
))}
|
|
370
|
-
</div>
|
|
371
|
-
)}
|
|
372
|
-
</div>
|
|
373
|
-
</form>
|
|
374
|
-
</div>
|
|
375
|
-
|
|
376
|
-
{/* Footer */}
|
|
377
|
-
<Separator />
|
|
378
|
-
<DrawerFooter className="flex-row justify-end gap-2">
|
|
379
|
-
<Button
|
|
380
|
-
variant="outline"
|
|
381
|
-
onClick={() => {
|
|
382
|
-
drawerCloseSound.play();
|
|
383
|
-
onClose();
|
|
384
|
-
}}
|
|
385
|
-
disabled={isSubmitting}
|
|
386
|
-
>
|
|
387
|
-
Cancel
|
|
388
|
-
</Button>
|
|
389
|
-
<Button type="submit" form="create-feature-form" disabled={!name.trim() || isSubmitting}>
|
|
390
|
-
{isSubmitting ? 'Creating...' : '+ Create Feature'}
|
|
391
|
-
</Button>
|
|
392
|
-
</DrawerFooter>
|
|
393
|
-
</DrawerContent>
|
|
394
|
-
</Drawer>
|
|
361
|
+
)}
|
|
362
|
+
</div>
|
|
363
|
+
</form>
|
|
364
|
+
</div>
|
|
365
|
+
</BaseDrawer>
|
|
395
366
|
);
|
|
396
367
|
}
|
|
397
368
|
|