@locusai/web 0.1.7 → 0.2.2
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/CHANGELOG.md +26 -0
- package/next.config.js +15 -2
- package/package.json +26 -3
- package/src/app/(auth)/invite/page.tsx +109 -0
- package/src/app/(auth)/layout.tsx +19 -0
- package/src/app/(auth)/login/page.tsx +65 -0
- package/src/app/(auth)/onboarding/workspace/page.tsx +46 -0
- package/src/app/(auth)/register/page.tsx +165 -0
- package/src/app/(dashboard)/activity/page.tsx +7 -0
- package/src/app/(dashboard)/backlog/page.tsx +195 -0
- package/src/app/(dashboard)/board/page.tsx +141 -0
- package/src/app/(dashboard)/layout.tsx +32 -0
- package/src/app/(dashboard)/page.tsx +14 -0
- package/src/app/(dashboard)/settings/page.tsx +161 -0
- package/src/app/(dashboard)/settings/team/page.tsx +75 -0
- package/src/app/globals.css +259 -0
- package/src/app/layout.tsx +10 -20
- package/src/app/providers.tsx +26 -3
- package/src/components/AuthLayoutUI.tsx +53 -0
- package/src/components/BoardFilter.tsx +75 -74
- package/src/components/CreateModal/CreateModal.tsx +142 -0
- package/src/components/CreateModal/index.ts +1 -0
- package/src/components/Editor.tsx +279 -0
- package/src/components/Header.tsx +99 -12
- package/src/components/PageLayout.tsx +69 -0
- package/src/components/PropertyItem.tsx +55 -9
- package/src/components/Sidebar.tsx +280 -36
- package/src/components/SprintCreateModal.tsx +84 -0
- package/src/components/TaskCard.tsx +196 -78
- package/src/components/TaskCreateModal.tsx +181 -178
- package/src/components/TaskPanel.tsx +140 -692
- package/src/components/WorkspaceCreateModal.tsx +97 -0
- package/src/components/WorkspaceProtected.tsx +91 -0
- package/src/components/auth/InviteSteps.tsx +220 -0
- package/src/components/auth/LoginSteps.tsx +86 -0
- package/src/components/auth/RegisterSteps.tsx +371 -0
- package/src/components/auth/index.ts +3 -0
- package/src/components/backlog/BacklogList.tsx +92 -0
- package/src/components/backlog/BacklogSection.tsx +137 -0
- package/src/components/backlog/CompletedSprintItem.tsx +95 -0
- package/src/components/backlog/CompletedSprintsSection.tsx +77 -0
- package/src/components/backlog/SprintSection.tsx +155 -0
- package/src/components/backlog/constants.ts +26 -0
- package/src/components/board/BoardColumn.tsx +97 -0
- package/src/components/board/BoardContent.tsx +84 -0
- package/src/components/board/BoardEmptyState.tsx +82 -0
- package/src/components/board/BoardHeader.tsx +47 -0
- package/src/components/board/SprintMindmap.tsx +65 -0
- package/src/components/board/constants.ts +40 -0
- package/src/components/board/index.ts +5 -0
- package/src/components/common/ErrorState.tsx +124 -0
- package/src/components/common/LoadingState.tsx +83 -0
- package/src/components/common/index.ts +40 -0
- package/src/components/dashboard/ActivityFeed.tsx +77 -0
- package/src/components/dashboard/ActivityItem.tsx +207 -0
- package/src/components/dashboard/QuickActions.tsx +50 -0
- package/src/components/dashboard/StatCard.tsx +79 -0
- package/src/components/dnd/index.tsx +51 -0
- package/src/components/docs/DocsEditorArea.tsx +87 -0
- package/src/components/docs/DocsHeaderActions.tsx +121 -0
- package/src/components/docs/DocsSidebar.tsx +351 -0
- package/src/components/index.ts +7 -0
- package/src/components/onboarding/StepProgress.tsx +21 -0
- package/src/components/onboarding/index.ts +1 -0
- package/src/components/settings/ApiKeyConfirmationModal.tsx +81 -0
- package/src/components/settings/ApiKeyCreatedModal.tsx +96 -0
- package/src/components/settings/ApiKeysList.tsx +143 -0
- package/src/components/settings/ApiKeysSettings.tsx +144 -0
- package/src/components/settings/InviteMemberModal.tsx +106 -0
- package/src/components/settings/ProjectSetupGuide.tsx +147 -0
- package/src/components/settings/SettingItem.tsx +32 -0
- package/src/components/settings/SettingSection.tsx +50 -0
- package/src/components/settings/TeamInvitationsList.tsx +90 -0
- package/src/components/settings/TeamMembersList.tsx +95 -0
- package/src/components/settings/index.ts +8 -0
- package/src/components/task-panel/TaskActivity.tsx +127 -0
- package/src/components/task-panel/TaskChecklist.tsx +142 -0
- package/src/components/task-panel/TaskDescription.tsx +201 -0
- package/src/components/task-panel/TaskDocs.tsx +137 -0
- package/src/components/task-panel/TaskHeader.tsx +125 -0
- package/src/components/task-panel/TaskProperties.tsx +111 -0
- package/src/components/task-panel/index.ts +12 -0
- package/src/components/typography/EmptyStateText.tsx +59 -0
- package/src/components/typography/MetadataText.tsx +65 -0
- package/src/components/typography/SecondaryText.tsx +60 -0
- package/src/components/typography/SectionLabel.tsx +60 -0
- package/src/components/typography/index.ts +14 -0
- package/src/components/typography-scales.tsx +218 -0
- package/src/components/ui/Avatar.tsx +123 -0
- package/src/components/ui/Badge.tsx +69 -2
- package/src/components/ui/Button.tsx +71 -30
- package/src/components/ui/Checkbox.tsx +34 -0
- package/src/components/ui/Dropdown.tsx +67 -1
- package/src/components/ui/EmptyState.tsx +129 -0
- package/src/components/ui/Input.tsx +53 -6
- package/src/components/ui/Modal.tsx +45 -12
- package/src/components/ui/OtpInput.tsx +148 -0
- package/src/components/ui/Skeleton.tsx +36 -0
- package/src/components/ui/Spinner.tsx +112 -0
- package/src/components/ui/Textarea.tsx +28 -3
- package/src/components/ui/Toast.tsx +99 -0
- package/src/components/ui/Toggle.tsx +63 -0
- package/src/components/ui/constants.ts +108 -0
- package/src/components/ui/index.ts +7 -0
- package/src/context/AuthContext.tsx +140 -0
- package/src/context/index.ts +1 -0
- package/src/hooks/backlog/index.ts +13 -0
- package/src/hooks/backlog/useBacklogActions.ts +144 -0
- package/src/hooks/backlog/useBacklogComposite.ts +73 -0
- package/src/hooks/backlog/useBacklogData.ts +74 -0
- package/src/hooks/backlog/useBacklogDragDrop.ts +118 -0
- package/src/hooks/backlog/useBacklogUI.ts +74 -0
- package/src/hooks/index.ts +22 -0
- package/src/hooks/task-panel/index.ts +13 -0
- package/src/hooks/task-panel/useTaskActions.ts +200 -0
- package/src/hooks/task-panel/useTaskComputedValues.ts +30 -0
- package/src/hooks/task-panel/useTaskData.ts +78 -0
- package/src/hooks/task-panel/useTaskPanelComposite.ts +161 -0
- package/src/hooks/task-panel/useTaskUIState.ts +80 -0
- package/src/hooks/useAuthLayoutLogic.ts +43 -0
- package/src/hooks/useAuthenticatedUser.ts +36 -0
- package/src/hooks/useAuthenticatedUserWithOrg.ts +41 -0
- package/src/hooks/useBacklog.ts +303 -0
- package/src/hooks/useBoard.ts +230 -0
- package/src/hooks/useDashboardLayout.ts +49 -0
- package/src/hooks/useDocs.ts +279 -0
- package/src/hooks/useDocsQuery.ts +99 -0
- package/src/hooks/useDocsSidebarState.ts +104 -0
- package/src/hooks/useFormState.ts +40 -0
- package/src/hooks/useGlobalKeydowns.ts +52 -0
- package/src/hooks/useInviteForm.ts +122 -0
- package/src/hooks/useLoginForm.ts +84 -0
- package/src/hooks/useMutationWithToast.ts +56 -0
- package/src/hooks/useOrganizationQuery.ts +55 -0
- package/src/hooks/useRegisterForm.ts +216 -0
- package/src/hooks/useSprintsQuery.ts +38 -0
- package/src/hooks/useTaskDescription.ts +102 -0
- package/src/hooks/useTaskPanel.ts +341 -0
- package/src/hooks/useTasksQuery.ts +39 -0
- package/src/hooks/useTeamManagement.ts +92 -0
- package/src/hooks/useWorkspaceCreateForm.ts +70 -0
- package/src/hooks/useWorkspaceId.ts +29 -0
- package/src/lib/api-client.ts +40 -23
- package/src/lib/config.ts +25 -0
- package/src/lib/constants.ts +83 -0
- package/src/lib/options.ts +96 -0
- package/src/lib/query-keys.ts +91 -0
- package/src/lib/typography.ts +103 -0
- package/src/lib/utils.ts +4 -0
- package/src/lib/validation.ts +192 -0
- package/src/services/index.ts +7 -3
- package/src/services/notifications.ts +80 -0
- package/src/utils/env.utils.ts +15 -0
- package/src/views/ActivityView.tsx +123 -0
- package/src/views/Dashboard.tsx +126 -0
- package/src/views/Docs.tsx +98 -612
- package/tsconfig.tsbuildinfo +1 -1
- package/.next/BUILD_ID +0 -1
- package/.next/app-build-manifest.json +0 -55
- package/.next/app-path-routes-manifest.json +0 -8
- package/.next/build-manifest.json +0 -33
- package/.next/cache/.previewinfo +0 -1
- package/.next/cache/.rscinfo +0 -1
- package/.next/cache/.tsbuildinfo +0 -1
- package/.next/cache/config.json +0 -7
- package/.next/cache/webpack/client-production/0.pack +0 -0
- package/.next/cache/webpack/client-production/index.pack +0 -0
- package/.next/cache/webpack/edge-server-production/0.pack +0 -0
- package/.next/cache/webpack/edge-server-production/index.pack +0 -0
- package/.next/cache/webpack/server-production/0.pack +0 -0
- package/.next/cache/webpack/server-production/index.pack +0 -0
- package/.next/diagnostics/build-diagnostics.json +0 -6
- package/.next/diagnostics/framework.json +0 -1
- package/.next/export-detail.json +0 -5
- package/.next/export-marker.json +0 -6
- package/.next/images-manifest.json +0 -57
- package/.next/next-minimal-server.js.nft.json +0 -1
- package/.next/next-server.js.nft.json +0 -1
- package/.next/package.json +0 -1
- package/.next/prerender-manifest.json +0 -137
- package/.next/react-loadable-manifest.json +0 -32
- package/.next/required-server-files.json +0 -324
- package/.next/routes-manifest.json +0 -77
- package/.next/server/app/_not-found/page.js +0 -2
- package/.next/server/app/_not-found/page.js.nft.json +0 -1
- package/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
- package/.next/server/app/_not-found.html +0 -1
- package/.next/server/app/_not-found.meta +0 -8
- package/.next/server/app/_not-found.rsc +0 -21
- package/.next/server/app/backlog/page.js +0 -2
- package/.next/server/app/backlog/page.js.nft.json +0 -1
- package/.next/server/app/backlog/page_client-reference-manifest.js +0 -1
- package/.next/server/app/backlog.html +0 -1
- package/.next/server/app/backlog.meta +0 -7
- package/.next/server/app/backlog.rsc +0 -25
- package/.next/server/app/docs/page.js +0 -97
- package/.next/server/app/docs/page.js.nft.json +0 -1
- package/.next/server/app/docs/page_client-reference-manifest.js +0 -1
- package/.next/server/app/docs.html +0 -1
- package/.next/server/app/docs.meta +0 -7
- package/.next/server/app/docs.rsc +0 -26
- package/.next/server/app/favicon.ico/route.js +0 -1
- package/.next/server/app/favicon.ico/route.js.nft.json +0 -1
- package/.next/server/app/favicon.ico.body +0 -0
- package/.next/server/app/favicon.ico.meta +0 -1
- package/.next/server/app/index.html +0 -1
- package/.next/server/app/index.meta +0 -7
- package/.next/server/app/index.rsc +0 -25
- package/.next/server/app/page.js +0 -2
- package/.next/server/app/page.js.nft.json +0 -1
- package/.next/server/app/page_client-reference-manifest.js +0 -1
- package/.next/server/app/settings/page.js +0 -2
- package/.next/server/app/settings/page.js.nft.json +0 -1
- package/.next/server/app/settings/page_client-reference-manifest.js +0 -1
- package/.next/server/app/settings.html +0 -1
- package/.next/server/app/settings.meta +0 -7
- package/.next/server/app/settings.rsc +0 -25
- package/.next/server/app-paths-manifest.json +0 -8
- package/.next/server/chunks/496.js +0 -6
- package/.next/server/chunks/585.js +0 -1
- package/.next/server/chunks/665.js +0 -1
- package/.next/server/chunks/699.js +0 -22
- package/.next/server/chunks/852.js +0 -7
- package/.next/server/functions-config-manifest.json +0 -4
- package/.next/server/interception-route-rewrite-manifest.js +0 -1
- package/.next/server/middleware-build-manifest.js +0 -1
- package/.next/server/middleware-manifest.json +0 -6
- package/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/.next/server/next-font-manifest.js +0 -1
- package/.next/server/next-font-manifest.json +0 -1
- package/.next/server/pages/404.html +0 -1
- package/.next/server/pages/500.html +0 -1
- package/.next/server/pages/_app.js +0 -1
- package/.next/server/pages/_app.js.nft.json +0 -1
- package/.next/server/pages/_document.js +0 -1
- package/.next/server/pages/_document.js.nft.json +0 -1
- package/.next/server/pages/_error.js +0 -19
- package/.next/server/pages/_error.js.nft.json +0 -1
- package/.next/server/pages-manifest.json +0 -6
- package/.next/server/server-reference-manifest.js +0 -1
- package/.next/server/server-reference-manifest.json +0 -1
- package/.next/server/webpack-runtime.js +0 -1
- package/.next/static/D0NXe04ZCLNDckV_quc8g/_buildManifest.js +0 -1
- package/.next/static/D0NXe04ZCLNDckV_quc8g/_ssgManifest.js +0 -1
- package/.next/static/chunks/138.b98511c56423f8bb.js +0 -1
- package/.next/static/chunks/146-34259952c594a3b0.js +0 -1
- package/.next/static/chunks/337-d3bb75304d130513.js +0 -1
- package/.next/static/chunks/477.1a6ecfe53375bd9c.js +0 -1
- package/.next/static/chunks/487-1808785ba665f784.js +0 -1
- package/.next/static/chunks/544.a9569941cc886e9d.js +0 -1
- package/.next/static/chunks/87c73c54-1f4741035a95c140.js +0 -1
- package/.next/static/chunks/902-d6926825a9fe8784.js +0 -1
- package/.next/static/chunks/955-c8f8f6235ae8f8c6.js +0 -1
- package/.next/static/chunks/996.e0a334e6ae90900e.js +0 -1
- package/.next/static/chunks/app/_not-found/page-44b1804abb44a34d.js +0 -1
- package/.next/static/chunks/app/backlog/page-dce1450769bfae8f.js +0 -1
- package/.next/static/chunks/app/docs/page-1efee819f25492cb.js +0 -1
- package/.next/static/chunks/app/layout-05f504c042b9f7ee.js +0 -1
- package/.next/static/chunks/app/page-3fd91aaaa4776ced.js +0 -1
- package/.next/static/chunks/app/settings/page-84e16c9638d657e4.js +0 -1
- package/.next/static/chunks/framework-152a1bc8c81c7458.js +0 -1
- package/.next/static/chunks/main-843ab130fc1be309.js +0 -1
- package/.next/static/chunks/main-app-123e879c5a937a00.js +0 -1
- package/.next/static/chunks/pages/_app-a050a8e6e4fb04cf.js +0 -1
- package/.next/static/chunks/pages/_error-3e422ffd891594de.js +0 -1
- package/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/.next/static/chunks/webpack-99a10a055b5bb9c4.js +0 -1
- package/.next/static/css/13e8617b72f9d3aa.css +0 -1
- package/.next/static/css/8aea088cdc4338f0.css +0 -1
- package/.next/static/css/b301ab0424111664.css +0 -1
- package/.next/static/media/24c15609eaa28576-s.woff2 +0 -0
- package/.next/static/media/2c07349e02a7b712-s.woff2 +0 -0
- package/.next/static/media/456105d6ea6d39e0-s.woff2 +0 -0
- package/.next/static/media/47cbc4e2adbc5db9-s.p.woff2 +0 -0
- package/.next/static/media/4f77bef990aad698-s.woff2 +0 -0
- package/.next/static/media/627d916fd739a539-s.woff2 +0 -0
- package/.next/static/media/63b255f18bea0ca9-s.woff2 +0 -0
- package/.next/static/media/70bd82ac89b4fa42-s.woff2 +0 -0
- package/.next/static/media/84602850c8fd81c3-s.woff2 +0 -0
- package/.next/trace +0 -46
- package/.next/types/app/backlog/page.ts +0 -84
- package/.next/types/app/docs/page.ts +0 -84
- package/.next/types/app/layout.ts +0 -84
- package/.next/types/app/page.ts +0 -84
- package/.next/types/app/settings/page.ts +0 -84
- package/.next/types/cache-life.d.ts +0 -141
- package/.next/types/package.json +0 -1
- package/next-env.d.ts +0 -5
- package/out/404.html +0 -1
- package/out/_next/static/D0NXe04ZCLNDckV_quc8g/_buildManifest.js +0 -1
- package/out/_next/static/D0NXe04ZCLNDckV_quc8g/_ssgManifest.js +0 -1
- package/out/_next/static/chunks/138.b98511c56423f8bb.js +0 -1
- package/out/_next/static/chunks/146-34259952c594a3b0.js +0 -1
- package/out/_next/static/chunks/337-d3bb75304d130513.js +0 -1
- package/out/_next/static/chunks/477.1a6ecfe53375bd9c.js +0 -1
- package/out/_next/static/chunks/487-1808785ba665f784.js +0 -1
- package/out/_next/static/chunks/544.a9569941cc886e9d.js +0 -1
- package/out/_next/static/chunks/87c73c54-1f4741035a95c140.js +0 -1
- package/out/_next/static/chunks/902-d6926825a9fe8784.js +0 -1
- package/out/_next/static/chunks/955-c8f8f6235ae8f8c6.js +0 -1
- package/out/_next/static/chunks/996.e0a334e6ae90900e.js +0 -1
- package/out/_next/static/chunks/app/_not-found/page-44b1804abb44a34d.js +0 -1
- package/out/_next/static/chunks/app/backlog/page-dce1450769bfae8f.js +0 -1
- package/out/_next/static/chunks/app/docs/page-1efee819f25492cb.js +0 -1
- package/out/_next/static/chunks/app/layout-05f504c042b9f7ee.js +0 -1
- package/out/_next/static/chunks/app/page-3fd91aaaa4776ced.js +0 -1
- package/out/_next/static/chunks/app/settings/page-84e16c9638d657e4.js +0 -1
- package/out/_next/static/chunks/framework-152a1bc8c81c7458.js +0 -1
- package/out/_next/static/chunks/main-843ab130fc1be309.js +0 -1
- package/out/_next/static/chunks/main-app-123e879c5a937a00.js +0 -1
- package/out/_next/static/chunks/pages/_app-a050a8e6e4fb04cf.js +0 -1
- package/out/_next/static/chunks/pages/_error-3e422ffd891594de.js +0 -1
- package/out/_next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/out/_next/static/chunks/webpack-99a10a055b5bb9c4.js +0 -1
- package/out/_next/static/css/13e8617b72f9d3aa.css +0 -1
- package/out/_next/static/css/8aea088cdc4338f0.css +0 -1
- package/out/_next/static/css/b301ab0424111664.css +0 -1
- package/out/_next/static/media/24c15609eaa28576-s.woff2 +0 -0
- package/out/_next/static/media/2c07349e02a7b712-s.woff2 +0 -0
- package/out/_next/static/media/456105d6ea6d39e0-s.woff2 +0 -0
- package/out/_next/static/media/47cbc4e2adbc5db9-s.p.woff2 +0 -0
- package/out/_next/static/media/4f77bef990aad698-s.woff2 +0 -0
- package/out/_next/static/media/627d916fd739a539-s.woff2 +0 -0
- package/out/_next/static/media/63b255f18bea0ca9-s.woff2 +0 -0
- package/out/_next/static/media/70bd82ac89b4fa42-s.woff2 +0 -0
- package/out/_next/static/media/84602850c8fd81c3-s.woff2 +0 -0
- package/out/backlog.html +0 -1
- package/out/backlog.txt +0 -25
- package/out/docs.html +0 -1
- package/out/docs.txt +0 -26
- package/out/favicon.ico +0 -0
- package/out/index.html +0 -1
- package/out/index.txt +0 -25
- package/out/logo.png +0 -0
- package/out/settings.html +0 -1
- package/out/settings.txt +0 -25
- package/src/app/backlog/page.tsx +0 -19
- package/src/app/page.tsx +0 -16
- package/src/app/settings/page.tsx +0 -194
- package/src/hooks/useTasks.ts +0 -119
- package/src/services/doc.service.ts +0 -27
- package/src/services/sprint.service.ts +0 -24
- package/src/services/task.service.ts +0 -75
- package/src/views/Backlog.tsx +0 -691
- package/src/views/Board.tsx +0 -306
- /package/src/app/{docs → (dashboard)/docs}/page.tsx +0 -0
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Properties Component
|
|
3
|
+
*
|
|
4
|
+
* Displays and allows editing of task metadata like status, priority, assignee, etc.
|
|
5
|
+
*
|
|
6
|
+
* @example
|
|
7
|
+
* <TaskProperties task={task} onUpdate={handleUpdate} />
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
"use client";
|
|
11
|
+
|
|
12
|
+
import {
|
|
13
|
+
AssigneeRole,
|
|
14
|
+
type Task,
|
|
15
|
+
TaskPriority,
|
|
16
|
+
TaskStatus,
|
|
17
|
+
} from "@locusai/shared";
|
|
18
|
+
import { format } from "date-fns";
|
|
19
|
+
import { PropertyItem, SectionLabel } from "@/components";
|
|
20
|
+
|
|
21
|
+
interface TaskPropertiesProps {
|
|
22
|
+
/** Task to display */
|
|
23
|
+
task: Task;
|
|
24
|
+
/** Whether a mutation is loading */
|
|
25
|
+
isLoading?: boolean;
|
|
26
|
+
/** Callback when task properties are updated */
|
|
27
|
+
onUpdate: (updates: Partial<Task>) => void;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Task Properties Component
|
|
32
|
+
*
|
|
33
|
+
* Features:
|
|
34
|
+
* - Editable status dropdown
|
|
35
|
+
* - Assignee role selection
|
|
36
|
+
* - Priority level
|
|
37
|
+
* - Due date picker
|
|
38
|
+
* - Operator/assignee field
|
|
39
|
+
*
|
|
40
|
+
* @component
|
|
41
|
+
*/
|
|
42
|
+
export function TaskProperties({
|
|
43
|
+
task,
|
|
44
|
+
isLoading = false,
|
|
45
|
+
onUpdate,
|
|
46
|
+
}: TaskPropertiesProps) {
|
|
47
|
+
const formatDate = (date: string | number | Date) => {
|
|
48
|
+
return format(new Date(date), "MMM d, yyyy");
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<div className="mb-10">
|
|
53
|
+
<SectionLabel as="h4" className="mb-6 pb-2 border-b border-border/40">
|
|
54
|
+
Mission Specs
|
|
55
|
+
</SectionLabel>
|
|
56
|
+
<div className="space-y-3">
|
|
57
|
+
<PropertyItem
|
|
58
|
+
label="State"
|
|
59
|
+
value={task.status}
|
|
60
|
+
onEdit={(newValue: string) =>
|
|
61
|
+
onUpdate({ status: newValue as TaskStatus })
|
|
62
|
+
}
|
|
63
|
+
options={Object.values(TaskStatus)}
|
|
64
|
+
type="dropdown"
|
|
65
|
+
disabled={isLoading}
|
|
66
|
+
/>
|
|
67
|
+
<PropertyItem
|
|
68
|
+
label="Role"
|
|
69
|
+
value={task.assigneeRole || "Unassigned"}
|
|
70
|
+
onEdit={(newValue: string) =>
|
|
71
|
+
onUpdate({
|
|
72
|
+
assigneeRole: newValue as AssigneeRole,
|
|
73
|
+
})
|
|
74
|
+
}
|
|
75
|
+
options={Object.values(AssigneeRole)}
|
|
76
|
+
type="dropdown"
|
|
77
|
+
disabled={isLoading}
|
|
78
|
+
/>
|
|
79
|
+
<PropertyItem
|
|
80
|
+
label="Priority"
|
|
81
|
+
value={task.priority || TaskPriority.MEDIUM}
|
|
82
|
+
onEdit={(newValue: string) =>
|
|
83
|
+
onUpdate({ priority: newValue as TaskPriority })
|
|
84
|
+
}
|
|
85
|
+
options={Object.values(TaskPriority)}
|
|
86
|
+
type="dropdown"
|
|
87
|
+
disabled={isLoading}
|
|
88
|
+
/>
|
|
89
|
+
<PropertyItem
|
|
90
|
+
label="Deadline"
|
|
91
|
+
value={task.dueDate ? formatDate(task.dueDate) : "Undetermined"}
|
|
92
|
+
onEdit={(newValue: string) =>
|
|
93
|
+
onUpdate({ dueDate: newValue ? new Date(newValue) : null })
|
|
94
|
+
}
|
|
95
|
+
type="date"
|
|
96
|
+
disabled={isLoading}
|
|
97
|
+
/>
|
|
98
|
+
<PropertyItem
|
|
99
|
+
label="Operator"
|
|
100
|
+
value={task.assignedTo || "Available"}
|
|
101
|
+
onEdit={(newValue: string) =>
|
|
102
|
+
onUpdate({ assignedTo: newValue || null })
|
|
103
|
+
}
|
|
104
|
+
type="text"
|
|
105
|
+
disabled={isLoading}
|
|
106
|
+
placeholder="Enter operator name or ID"
|
|
107
|
+
/>
|
|
108
|
+
</div>
|
|
109
|
+
</div>
|
|
110
|
+
);
|
|
111
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Task Panel Components
|
|
3
|
+
*
|
|
4
|
+
* Modular components for the task detail panel.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export * from "./TaskActivity";
|
|
8
|
+
export * from "./TaskChecklist";
|
|
9
|
+
export * from "./TaskDescription";
|
|
10
|
+
export * from "./TaskDocs";
|
|
11
|
+
export * from "./TaskHeader";
|
|
12
|
+
export * from "./TaskProperties";
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Empty State Text Component
|
|
3
|
+
*
|
|
4
|
+
* Displays text for empty states with proper styling and visibility.
|
|
5
|
+
* Replaces scattered custom empty state typography throughout UI.
|
|
6
|
+
*
|
|
7
|
+
* Usage: Replace inline `text-[9px] font-black uppercase tracking-[0.2em] opacity-30`
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <EmptyStateText>No items found</EmptyStateText>
|
|
11
|
+
* <EmptyStateText icon={<Box />}>Empty workspace</EmptyStateText>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
"use client";
|
|
15
|
+
|
|
16
|
+
import React from "react";
|
|
17
|
+
import { cn } from "@/lib/utils";
|
|
18
|
+
|
|
19
|
+
interface EmptyStateTextProps {
|
|
20
|
+
/** Text content */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/** Optional icon to display */
|
|
23
|
+
icon?: React.ReactNode;
|
|
24
|
+
/** Optional className override */
|
|
25
|
+
className?: string;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Standardized empty state text component
|
|
30
|
+
*
|
|
31
|
+
* Features:
|
|
32
|
+
* - Proper contrast for empty states
|
|
33
|
+
* - Icon support
|
|
34
|
+
* - Readable but secondary appearance
|
|
35
|
+
* - Consistent spacing
|
|
36
|
+
* - Replaces scattered custom opacity patterns
|
|
37
|
+
*
|
|
38
|
+
* @component
|
|
39
|
+
*/
|
|
40
|
+
export function EmptyStateText({
|
|
41
|
+
children,
|
|
42
|
+
icon,
|
|
43
|
+
className,
|
|
44
|
+
}: EmptyStateTextProps) {
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
className={cn(
|
|
48
|
+
"flex flex-col items-center justify-center",
|
|
49
|
+
"text-[9px] font-black uppercase tracking-[0.2em]",
|
|
50
|
+
"text-foreground/40",
|
|
51
|
+
"gap-2",
|
|
52
|
+
className
|
|
53
|
+
)}
|
|
54
|
+
>
|
|
55
|
+
{icon && <div className="text-foreground/30">{icon}</div>}
|
|
56
|
+
{children}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Metadata Text Component
|
|
3
|
+
*
|
|
4
|
+
* Displays metadata, IDs, timestamps, or other secondary information.
|
|
5
|
+
* Replaces custom inline typography for technical info throughout UI.
|
|
6
|
+
*
|
|
7
|
+
* Usage: Replace inline `text-[8px] font-bold uppercase tracking-widest text-muted-foreground/50`
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <MetadataText>ID: abc-123</MetadataText>
|
|
11
|
+
* <MetadataText>Updated 2 hours ago</MetadataText>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
"use client";
|
|
15
|
+
|
|
16
|
+
import React from "react";
|
|
17
|
+
import { cn } from "@/lib/utils";
|
|
18
|
+
|
|
19
|
+
interface MetadataTextProps {
|
|
20
|
+
/** Metadata content */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/** Size variant */
|
|
23
|
+
size?: "xs" | "sm";
|
|
24
|
+
/** Optional className override */
|
|
25
|
+
className?: string;
|
|
26
|
+
/** HTML element (default: div) */
|
|
27
|
+
as?: "div" | "span" | "p";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Standardized metadata text component
|
|
32
|
+
*
|
|
33
|
+
* Features:
|
|
34
|
+
* - Smaller text for secondary metadata
|
|
35
|
+
* - Readable yet de-emphasized (60% opacity)
|
|
36
|
+
* - Wide letter spacing for technical info
|
|
37
|
+
* - Uppercase styling
|
|
38
|
+
* - Replaces scattered custom metadata classes
|
|
39
|
+
*
|
|
40
|
+
* @component
|
|
41
|
+
*/
|
|
42
|
+
export function MetadataText({
|
|
43
|
+
children,
|
|
44
|
+
size = "xs",
|
|
45
|
+
className,
|
|
46
|
+
as: Component = "div",
|
|
47
|
+
}: MetadataTextProps) {
|
|
48
|
+
const sizeClasses = {
|
|
49
|
+
xs: "text-[8px]",
|
|
50
|
+
sm: "text-[9px]",
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Component
|
|
55
|
+
className={cn(
|
|
56
|
+
sizeClasses[size],
|
|
57
|
+
"font-bold uppercase tracking-widest",
|
|
58
|
+
"text-foreground/60",
|
|
59
|
+
className
|
|
60
|
+
)}
|
|
61
|
+
>
|
|
62
|
+
{children}
|
|
63
|
+
</Component>
|
|
64
|
+
);
|
|
65
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Secondary Text Component
|
|
3
|
+
*
|
|
4
|
+
* Displays secondary or helper text with standardized styling.
|
|
5
|
+
* Replaces custom inline opacity classes like `text-muted-foreground/50` or `text-foreground/60`
|
|
6
|
+
*
|
|
7
|
+
* Usage: Replace inline text-[9px] text-muted-foreground/60
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <SecondaryText>Last updated 2 hours ago</SecondaryText>
|
|
11
|
+
* <SecondaryText size="sm">Optional description</SecondaryText>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
"use client";
|
|
15
|
+
|
|
16
|
+
import React from "react";
|
|
17
|
+
import { cn } from "@/lib/utils";
|
|
18
|
+
|
|
19
|
+
interface SecondaryTextProps {
|
|
20
|
+
/** Text content */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/** Text size variant */
|
|
23
|
+
size?: "xs" | "sm";
|
|
24
|
+
/** Optional className override */
|
|
25
|
+
className?: string;
|
|
26
|
+
/** HTML element (default: div) */
|
|
27
|
+
as?: "div" | "p" | "span" | "label";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Standardized secondary text component
|
|
32
|
+
*
|
|
33
|
+
* Features:
|
|
34
|
+
* - Readable secondary text (60-65% opacity)
|
|
35
|
+
* - Multiple size options
|
|
36
|
+
* - Replaces scattered custom opacity classes
|
|
37
|
+
* - Consistent spacing
|
|
38
|
+
* - Fully customizable
|
|
39
|
+
*
|
|
40
|
+
* @component
|
|
41
|
+
*/
|
|
42
|
+
export function SecondaryText({
|
|
43
|
+
children,
|
|
44
|
+
size = "xs",
|
|
45
|
+
className,
|
|
46
|
+
as: Component = "div",
|
|
47
|
+
}: SecondaryTextProps) {
|
|
48
|
+
const sizeClasses = {
|
|
49
|
+
xs: "text-[9px] font-medium",
|
|
50
|
+
sm: "text-xs font-medium",
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
return (
|
|
54
|
+
<Component
|
|
55
|
+
className={cn(sizeClasses[size], "text-foreground/60", className)}
|
|
56
|
+
>
|
|
57
|
+
{children}
|
|
58
|
+
</Component>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Section Label Component
|
|
3
|
+
*
|
|
4
|
+
* Displays a section header or label with standardized styling.
|
|
5
|
+
* Replaces custom inline typography for section titles throughout the UI.
|
|
6
|
+
*
|
|
7
|
+
* Usage: Replace inline text-[10px] font-black uppercase tracking-[0.2em]
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* <SectionLabel>Settings</SectionLabel>
|
|
11
|
+
* <SectionLabel icon={<Gear />}>Advanced</SectionLabel>
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
"use client";
|
|
15
|
+
|
|
16
|
+
import React from "react";
|
|
17
|
+
import { cn } from "@/lib/utils";
|
|
18
|
+
|
|
19
|
+
interface SectionLabelProps {
|
|
20
|
+
/** Label text content */
|
|
21
|
+
children: React.ReactNode;
|
|
22
|
+
/** Optional icon to display before text */
|
|
23
|
+
icon?: React.ReactNode;
|
|
24
|
+
/** Optional className override */
|
|
25
|
+
className?: string;
|
|
26
|
+
/** Label HTML element (default: div) */
|
|
27
|
+
as?: "div" | "h3" | "h4" | "label" | "span";
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Standardized section label component
|
|
32
|
+
*
|
|
33
|
+
* Features:
|
|
34
|
+
* - Consistent typography for section headers
|
|
35
|
+
* - Optional icon support
|
|
36
|
+
* - Readable secondary text (60% opacity)
|
|
37
|
+
* - Proper spacing and tracking
|
|
38
|
+
* - Fully customizable via className prop
|
|
39
|
+
*
|
|
40
|
+
* @component
|
|
41
|
+
*/
|
|
42
|
+
export function SectionLabel({
|
|
43
|
+
children,
|
|
44
|
+
icon,
|
|
45
|
+
className,
|
|
46
|
+
as: Component = "div",
|
|
47
|
+
}: SectionLabelProps) {
|
|
48
|
+
return (
|
|
49
|
+
<Component
|
|
50
|
+
className={cn(
|
|
51
|
+
"text-[10px] font-black uppercase tracking-[0.2em] text-foreground/60",
|
|
52
|
+
"flex items-center gap-2",
|
|
53
|
+
className
|
|
54
|
+
)}
|
|
55
|
+
>
|
|
56
|
+
{icon}
|
|
57
|
+
{children}
|
|
58
|
+
</Component>
|
|
59
|
+
);
|
|
60
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typography Components Barrel Export
|
|
3
|
+
*
|
|
4
|
+
* Centralized exports for all standardized typography components.
|
|
5
|
+
* Use these components instead of custom inline typography classes.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* import { SectionLabel, SecondaryText, EmptyStateText, MetadataText } from "@/components/typography";
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
export { EmptyStateText } from "./EmptyStateText";
|
|
12
|
+
export { MetadataText } from "./MetadataText";
|
|
13
|
+
export { SecondaryText } from "./SecondaryText";
|
|
14
|
+
export { SectionLabel } from "./SectionLabel";
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Typography Components
|
|
3
|
+
*
|
|
4
|
+
* Reusable components that apply consistent typography styles and scales.
|
|
5
|
+
* All typography variants are defined in `@/lib/typography` for centralized consistency.
|
|
6
|
+
*
|
|
7
|
+
* Readability Standards:
|
|
8
|
+
* - Primary text: text-foreground (100% opacity)
|
|
9
|
+
* - Secondary text: text-foreground/60-70% (improved from text-muted-foreground)
|
|
10
|
+
* - Labels: text-foreground/60% with uppercase
|
|
11
|
+
* - Disabled states: text-muted-foreground
|
|
12
|
+
*
|
|
13
|
+
* Features:
|
|
14
|
+
* - Semantic HTML heading tags (h1-h6)
|
|
15
|
+
* - Consistent spacing and tracking
|
|
16
|
+
* - Responsive text sizes
|
|
17
|
+
* - Built-in accessibility
|
|
18
|
+
* - Easy className overrides with cn()
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* <Heading variant="h1">Page Title</Heading>
|
|
22
|
+
* <Body variant="body">Regular text</Body>
|
|
23
|
+
* <Label required>Field Label</Label>
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
"use client";
|
|
27
|
+
|
|
28
|
+
import { getTypographyClass } from "@/lib/typography";
|
|
29
|
+
import { cn } from "@/lib/utils";
|
|
30
|
+
|
|
31
|
+
interface HeadingProps extends React.HTMLAttributes<HTMLHeadingElement> {
|
|
32
|
+
/** Heading level and size variant */
|
|
33
|
+
variant?: "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Heading Component
|
|
38
|
+
*
|
|
39
|
+
* Renders semantic heading tags with consistent typography.
|
|
40
|
+
* Maps variant prop to appropriate heading level.
|
|
41
|
+
*
|
|
42
|
+
* @component
|
|
43
|
+
*/
|
|
44
|
+
export function Heading({
|
|
45
|
+
variant = "h2",
|
|
46
|
+
className,
|
|
47
|
+
children,
|
|
48
|
+
...props
|
|
49
|
+
}: HeadingProps) {
|
|
50
|
+
const headingLevel = variant as "h1" | "h2" | "h3" | "h4" | "h5" | "h6";
|
|
51
|
+
|
|
52
|
+
switch (headingLevel) {
|
|
53
|
+
case "h1":
|
|
54
|
+
return (
|
|
55
|
+
<h1 className={cn(getTypographyClass("h1"), className)} {...props}>
|
|
56
|
+
{children}
|
|
57
|
+
</h1>
|
|
58
|
+
);
|
|
59
|
+
case "h2":
|
|
60
|
+
return (
|
|
61
|
+
<h2 className={cn(getTypographyClass("h2"), className)} {...props}>
|
|
62
|
+
{children}
|
|
63
|
+
</h2>
|
|
64
|
+
);
|
|
65
|
+
case "h3":
|
|
66
|
+
return (
|
|
67
|
+
<h3 className={cn(getTypographyClass("h3"), className)} {...props}>
|
|
68
|
+
{children}
|
|
69
|
+
</h3>
|
|
70
|
+
);
|
|
71
|
+
case "h4":
|
|
72
|
+
return (
|
|
73
|
+
<h4 className={cn(getTypographyClass("h4"), className)} {...props}>
|
|
74
|
+
{children}
|
|
75
|
+
</h4>
|
|
76
|
+
);
|
|
77
|
+
case "h5":
|
|
78
|
+
return (
|
|
79
|
+
<h5 className={cn(getTypographyClass("h5"), className)} {...props}>
|
|
80
|
+
{children}
|
|
81
|
+
</h5>
|
|
82
|
+
);
|
|
83
|
+
case "h6":
|
|
84
|
+
return (
|
|
85
|
+
<h6 className={cn(getTypographyClass("h6"), className)} {...props}>
|
|
86
|
+
{children}
|
|
87
|
+
</h6>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
interface BodyProps extends React.HTMLAttributes<HTMLParagraphElement> {
|
|
93
|
+
/** Body text size variant */
|
|
94
|
+
variant?: "bodyLg" | "body" | "bodySm";
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Body Component
|
|
99
|
+
*
|
|
100
|
+
* Renders paragraph text with consistent typography.
|
|
101
|
+
* Supports multiple size variants for flexible content layout.
|
|
102
|
+
*
|
|
103
|
+
* @component
|
|
104
|
+
*/
|
|
105
|
+
export function Body({
|
|
106
|
+
variant = "body",
|
|
107
|
+
className,
|
|
108
|
+
children,
|
|
109
|
+
...props
|
|
110
|
+
}: BodyProps) {
|
|
111
|
+
return (
|
|
112
|
+
<p className={cn(getTypographyClass(variant), className)} {...props}>
|
|
113
|
+
{children}
|
|
114
|
+
</p>
|
|
115
|
+
);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
interface LabelProps extends React.HTMLAttributes<HTMLLabelElement> {
|
|
119
|
+
/** Whether field is required (shows red asterisk) */
|
|
120
|
+
required?: boolean;
|
|
121
|
+
/** Label size variant */
|
|
122
|
+
variant?: "label" | "caption" | "captionSm";
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Label Component
|
|
127
|
+
*
|
|
128
|
+
* Renders form label with optional required indicator.
|
|
129
|
+
* Supports multiple size variants for form layouts.
|
|
130
|
+
* Includes accessibility features for form associations.
|
|
131
|
+
*
|
|
132
|
+
* @component
|
|
133
|
+
*/
|
|
134
|
+
export function Label({
|
|
135
|
+
variant = "label",
|
|
136
|
+
required,
|
|
137
|
+
className,
|
|
138
|
+
children,
|
|
139
|
+
...props
|
|
140
|
+
}: LabelProps) {
|
|
141
|
+
return (
|
|
142
|
+
<label className={cn(getTypographyClass(variant), className)} {...props}>
|
|
143
|
+
{children}
|
|
144
|
+
{required && <span className="text-destructive ml-0.5">*</span>}
|
|
145
|
+
</label>
|
|
146
|
+
);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
interface CaptionProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
150
|
+
/** Caption size variant */
|
|
151
|
+
variant?: "caption" | "captionSm";
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Caption Component
|
|
156
|
+
*
|
|
157
|
+
* Renders smaller supplementary text for captions and helper text.
|
|
158
|
+
* Provides improved readability with text-foreground/60-65%.
|
|
159
|
+
*
|
|
160
|
+
* @component
|
|
161
|
+
*/
|
|
162
|
+
export function Caption({
|
|
163
|
+
variant = "caption",
|
|
164
|
+
className,
|
|
165
|
+
children,
|
|
166
|
+
...props
|
|
167
|
+
}: CaptionProps) {
|
|
168
|
+
return (
|
|
169
|
+
<div className={cn(getTypographyClass(variant), className)} {...props}>
|
|
170
|
+
{children}
|
|
171
|
+
</div>
|
|
172
|
+
);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
interface CodeProps extends React.HTMLAttributes<HTMLElement> {
|
|
176
|
+
/** Code variant (inline or block) */
|
|
177
|
+
variant?: "code" | "codeBlock";
|
|
178
|
+
/** Whether to render as code block (pre tag) */
|
|
179
|
+
block?: boolean;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Code Component
|
|
184
|
+
*
|
|
185
|
+
* Renders inline code or code blocks with monospace font.
|
|
186
|
+
* Supports both <code> and <pre> tags for different contexts.
|
|
187
|
+
*
|
|
188
|
+
* @component
|
|
189
|
+
*/
|
|
190
|
+
export function Code({
|
|
191
|
+
variant,
|
|
192
|
+
block,
|
|
193
|
+
className,
|
|
194
|
+
children,
|
|
195
|
+
...props
|
|
196
|
+
}: CodeProps) {
|
|
197
|
+
const v = block ? "codeBlock" : variant || "code";
|
|
198
|
+
|
|
199
|
+
if (block) {
|
|
200
|
+
return (
|
|
201
|
+
<pre
|
|
202
|
+
className={cn(getTypographyClass(v), className)}
|
|
203
|
+
{...(props as React.HTMLAttributes<HTMLPreElement>)}
|
|
204
|
+
>
|
|
205
|
+
{children}
|
|
206
|
+
</pre>
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
return (
|
|
211
|
+
<code
|
|
212
|
+
className={cn(getTypographyClass(v), className)}
|
|
213
|
+
{...(props as React.HTMLAttributes<HTMLElement>)}
|
|
214
|
+
>
|
|
215
|
+
{children}
|
|
216
|
+
</code>
|
|
217
|
+
);
|
|
218
|
+
}
|