@devxcrew/react-ui 0.0.0-stage → 0.1.7
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/README.md +85 -2
- package/package.json +105 -4
- package/src/blocks/agent-chat-workspace/agent-chat-workspace.tsx +162 -0
- package/src/blocks/agent-chat-workspace/index.ts +2 -0
- package/src/blocks/agent-provider-settings/agent-provider-settings.tsx +183 -0
- package/src/blocks/agent-provider-settings/index.ts +2 -0
- package/src/blocks/agent-task-workspace/agent-task-workspace.tsx +48 -0
- package/src/blocks/agent-task-workspace/index.ts +2 -0
- package/src/blocks/analysis-context/analysis-context.tsx +6 -0
- package/src/blocks/analysis-context/index.ts +1 -0
- package/src/blocks/app-header/app-header.tsx +159 -0
- package/src/blocks/app-header/index.ts +2 -0
- package/src/blocks/archived-chat-workspace/archived-chat-workspace.tsx +29 -0
- package/src/blocks/archived-chat-workspace/index.ts +2 -0
- package/src/blocks/auth/README.md +32 -0
- package/src/blocks/auth/admin-login-page.tsx +15 -0
- package/src/blocks/auth/admin-password-forgot-page.tsx +5 -0
- package/src/blocks/auth/auth-page-layout.tsx +90 -0
- package/src/blocks/auth/client-login-page.tsx +20 -0
- package/src/blocks/auth/client-password-forgot-page.tsx +5 -0
- package/src/blocks/auth/identity-management-desk.tsx +530 -0
- package/src/blocks/auth/index.ts +12 -0
- package/src/blocks/auth/login-page.tsx +206 -0
- package/src/blocks/auth/password-forgot-page.tsx +60 -0
- package/src/blocks/auth/portal-pages.tsx +32 -0
- package/src/blocks/auth/privileged-desk.tsx +55 -0
- package/src/blocks/auth/register-page.tsx +117 -0
- package/src/blocks/auth/session-boundary.tsx +296 -0
- package/src/blocks/auth/super-admin-login-page.tsx +15 -0
- package/src/blocks/auth/super-admin-password-forgot-page.tsx +5 -0
- package/src/blocks/blog/blog-card.tsx +156 -0
- package/src/blocks/blog/blog-reader.tsx +175 -0
- package/src/blocks/blog/blog-types.ts +47 -0
- package/src/blocks/blog/index.ts +3 -0
- package/src/blocks/chat-composer/chat-composer.tsx +140 -0
- package/src/blocks/chat-composer/index.ts +1 -0
- package/src/blocks/chat-history/chat-history.tsx +59 -0
- package/src/blocks/chat-history/index.ts +1 -0
- package/src/blocks/chat-response-progress/chat-response-progress.tsx +34 -0
- package/src/blocks/chat-response-progress/index.ts +2 -0
- package/src/blocks/chat-runtime-controls/chat-runtime-controls.tsx +56 -0
- package/src/blocks/chat-runtime-controls/index.ts +2 -0
- package/src/blocks/chat-runtime-trace/chat-runtime-trace.tsx +71 -0
- package/src/blocks/chat-runtime-trace/index.ts +2 -0
- package/src/blocks/codex-connection-settings/codex-connection-settings.tsx +42 -0
- package/src/blocks/codex-connection-settings/index.ts +1 -0
- package/src/blocks/dropzone/dropzone-file-item.tsx +113 -0
- package/src/blocks/dropzone/dropzone-types.ts +32 -0
- package/src/blocks/dropzone/dropzone.tsx +216 -0
- package/src/blocks/dropzone/index.ts +3 -0
- package/src/blocks/ecommerce/cart/cart-drawer.tsx +228 -0
- package/src/blocks/ecommerce/cart/cart-types.ts +27 -0
- package/src/blocks/ecommerce/cart/index.ts +2 -0
- package/src/blocks/ecommerce/categories/categories-types.ts +23 -0
- package/src/blocks/ecommerce/categories/category-showcase.tsx +125 -0
- package/src/blocks/ecommerce/categories/index.ts +2 -0
- package/src/blocks/ecommerce/checkout/checkout-types.ts +48 -0
- package/src/blocks/ecommerce/checkout/checkout-wizard.tsx +468 -0
- package/src/blocks/ecommerce/checkout/index.ts +2 -0
- package/src/blocks/ecommerce/comparison/comparison-types.ts +28 -0
- package/src/blocks/ecommerce/comparison/index.ts +2 -0
- package/src/blocks/ecommerce/comparison/product-comparison.tsx +174 -0
- package/src/blocks/ecommerce/coupon-wallet/coupon-wallet-types.ts +21 -0
- package/src/blocks/ecommerce/coupon-wallet/coupon-wallet.tsx +154 -0
- package/src/blocks/ecommerce/coupon-wallet/index.ts +2 -0
- package/src/blocks/ecommerce/delivery-tracker/delivery-tracker-types.ts +20 -0
- package/src/blocks/ecommerce/delivery-tracker/delivery-tracker.tsx +169 -0
- package/src/blocks/ecommerce/delivery-tracker/index.ts +2 -0
- package/src/blocks/ecommerce/index.ts +12 -0
- package/src/blocks/ecommerce/payment-methods/index.ts +2 -0
- package/src/blocks/ecommerce/payment-methods/payment-method-selector.tsx +224 -0
- package/src/blocks/ecommerce/payment-methods/payment-methods-types.ts +21 -0
- package/src/blocks/ecommerce/price-history/index.ts +2 -0
- package/src/blocks/ecommerce/price-history/price-history-chart.tsx +217 -0
- package/src/blocks/ecommerce/price-history/price-history-types.ts +16 -0
- package/src/blocks/ecommerce/reviews/index.ts +2 -0
- package/src/blocks/ecommerce/reviews/reviews-section.tsx +309 -0
- package/src/blocks/ecommerce/reviews/reviews-types.ts +26 -0
- package/src/blocks/ecommerce/wishlist/index.ts +2 -0
- package/src/blocks/ecommerce/wishlist/wishlist-grid.tsx +149 -0
- package/src/blocks/ecommerce/wishlist/wishlist-types.ts +19 -0
- package/src/blocks/execution-status/README.md +25 -0
- package/src/blocks/execution-status/execution-status.tsx +135 -0
- package/src/blocks/execution-status/index.ts +2 -0
- package/src/blocks/file-tree/file-icons.tsx +84 -0
- package/src/blocks/file-tree/file-tree-node.tsx +158 -0
- package/src/blocks/file-tree/file-tree-types.ts +33 -0
- package/src/blocks/file-tree/file-tree.tsx +163 -0
- package/src/blocks/file-tree/index.ts +5 -0
- package/src/blocks/filter-builder/filter-builder.tsx +169 -0
- package/src/blocks/filter-builder/filter-row.tsx +164 -0
- package/src/blocks/filter-builder/filter-types.ts +61 -0
- package/src/blocks/filter-builder/index.ts +12 -0
- package/src/blocks/footer/footer-types.ts +35 -0
- package/src/blocks/footer/index.ts +2 -0
- package/src/blocks/footer/site-footer.tsx +212 -0
- package/src/blocks/form/form-block.tsx +113 -0
- package/src/blocks/form/form-lookup-field.tsx +60 -0
- package/src/blocks/form/index.ts +4 -0
- package/src/blocks/handover-stack/handover-stack.tsx +41 -0
- package/src/blocks/handover-stack/index.ts +1 -0
- package/src/blocks/idea-handover/idea-handover-readiness.ts +41 -0
- package/src/blocks/idea-handover/idea-handover-workspace.tsx +150 -0
- package/src/blocks/idea-handover/index.ts +4 -0
- package/src/blocks/kanban/index.ts +11 -0
- package/src/blocks/kanban/kanban-board.tsx +146 -0
- package/src/blocks/kanban/kanban-card.tsx +149 -0
- package/src/blocks/kanban/kanban-column.tsx +102 -0
- package/src/blocks/kanban/kanban-types.ts +38 -0
- package/src/blocks/loader/global-loader.tsx +90 -0
- package/src/blocks/loader/index.ts +1 -0
- package/src/blocks/mascot/README.md +21 -0
- package/src/blocks/mascot/index.ts +2 -0
- package/src/blocks/mascot/mascot.tsx +202 -0
- package/src/blocks/master-list/README.md +21 -0
- package/src/blocks/master-list/index.ts +12 -0
- package/src/blocks/master-list/master-form.tsx +157 -0
- package/src/blocks/master-list/master-list-desk.tsx +370 -0
- package/src/blocks/master-list/master-list.tsx +189 -0
- package/src/blocks/master-list/types.ts +18 -0
- package/src/blocks/mermaid-preview/index.ts +1 -0
- package/src/blocks/mermaid-preview/mermaid-preview.tsx +164 -0
- package/src/blocks/notifications/README.md +7 -0
- package/src/blocks/notifications/index.ts +1 -0
- package/src/blocks/notifications/notification-center-page.tsx +73 -0
- package/src/blocks/pricing/index.ts +7 -0
- package/src/blocks/pricing/pricing-table.tsx +173 -0
- package/src/blocks/pricing/pricing-types.ts +34 -0
- package/src/blocks/product-card/index.ts +2 -0
- package/src/blocks/product-card/product-card-types.ts +35 -0
- package/src/blocks/product-card/product-card.tsx +183 -0
- package/src/blocks/table/data-table-block.tsx +313 -0
- package/src/blocks/table/data-table-filter-menu.tsx +48 -0
- package/src/blocks/table/data-table-icon-menu-trigger.tsx +44 -0
- package/src/blocks/table/data-table-menu-content.tsx +32 -0
- package/src/blocks/table/data-table-pagination.tsx +149 -0
- package/src/blocks/table/data-table-row-actions.tsx +53 -0
- package/src/blocks/table/data-table-status.tsx +42 -0
- package/src/blocks/table/data-table-toolbar.tsx +124 -0
- package/src/blocks/table/data-table-totals.tsx +31 -0
- package/src/blocks/table/index.ts +13 -0
- package/src/blocks/workspace/index.ts +19 -0
- package/src/blocks/workspace/workspace-action-card.tsx +73 -0
- package/src/blocks/workspace/workspace-application-header.tsx +67 -0
- package/src/blocks/workspace/workspace-entity-card.tsx +48 -0
- package/src/blocks/workspace/workspace-health-summary.tsx +15 -0
- package/src/blocks/workspace/workspace-metric-card.tsx +97 -0
- package/src/blocks/workspace/workspace-page-header.tsx +43 -0
- package/src/blocks/workspace/workspace-publish-status.tsx +15 -0
- package/src/blocks/workspace/workspace-route-checklist.tsx +28 -0
- package/src/blocks/workspace/workspace-runtime-status.tsx +48 -0
- package/src/blocks/workspace/workspace-section-card.tsx +42 -0
- package/src/components/accordion.tsx +65 -0
- package/src/components/alert-dialog.tsx +160 -0
- package/src/components/alert.tsx +68 -0
- package/src/components/aspect-ratio.tsx +22 -0
- package/src/components/attachment.tsx +195 -0
- package/src/components/avatar.tsx +90 -0
- package/src/components/badge.tsx +55 -0
- package/src/components/breadcrumb.tsx +100 -0
- package/src/components/bubble.tsx +123 -0
- package/src/components/button-group.tsx +79 -0
- package/src/components/button.tsx +71 -0
- package/src/components/calendar.tsx +185 -0
- package/src/components/card.tsx +100 -0
- package/src/components/carousel.tsx +229 -0
- package/src/components/chart.tsx +338 -0
- package/src/components/checkbox.tsx +27 -0
- package/src/components/collapsible.tsx +15 -0
- package/src/components/combobox.tsx +269 -0
- package/src/components/command.tsx +181 -0
- package/src/components/compact-model-switcher.tsx +128 -0
- package/src/components/context-menu.tsx +244 -0
- package/src/components/dialog.tsx +138 -0
- package/src/components/direction.tsx +1 -0
- package/src/components/drawer.tsx +208 -0
- package/src/components/dropdown-menu.tsx +257 -0
- package/src/components/empty.tsx +93 -0
- package/src/components/field.tsx +232 -0
- package/src/components/hover-card.tsx +45 -0
- package/src/components/input-group.tsx +146 -0
- package/src/components/input-otp.tsx +83 -0
- package/src/components/input.tsx +19 -0
- package/src/components/item.tsx +188 -0
- package/src/components/kbd.tsx +26 -0
- package/src/components/label.tsx +17 -0
- package/src/components/markdown-content.tsx +113 -0
- package/src/components/marker.tsx +67 -0
- package/src/components/menubar.tsx +267 -0
- package/src/components/message-scroller.tsx +91 -0
- package/src/components/message.tsx +84 -0
- package/src/components/native-select.tsx +54 -0
- package/src/components/navigation-menu.tsx +160 -0
- package/src/components/pagination.tsx +118 -0
- package/src/components/popover.tsx +74 -0
- package/src/components/progress.tsx +82 -0
- package/src/components/questionnaire.tsx +150 -0
- package/src/components/radio-group.tsx +35 -0
- package/src/components/resizable.tsx +41 -0
- package/src/components/rich-text-editor.tsx +604 -0
- package/src/components/scroll-area.tsx +47 -0
- package/src/components/select.tsx +189 -0
- package/src/components/separator.tsx +18 -0
- package/src/components/sheet.tsx +125 -0
- package/src/components/sidebar.tsx +693 -0
- package/src/components/skeleton.tsx +13 -0
- package/src/components/slider.tsx +51 -0
- package/src/components/sonner.tsx +45 -0
- package/src/components/sparkline.tsx +231 -0
- package/src/components/spinner.tsx +20 -0
- package/src/components/status-badge.tsx +114 -0
- package/src/components/switch.tsx +31 -0
- package/src/components/table.tsx +91 -0
- package/src/components/tabs.tsx +72 -0
- package/src/components/textarea.tsx +17 -0
- package/src/components/toast.tsx +222 -0
- package/src/components/toggle-group.tsx +85 -0
- package/src/components/toggle.tsx +42 -0
- package/src/components/tooltip.tsx +53 -0
- package/src/design-system/README.md +55 -0
- package/src/design-system/action-intents.ts +21 -0
- package/src/design-system/agent-manifest.ts +83 -0
- package/src/design-system/block-registry.ts +272 -0
- package/src/design-system/component-registry.ts +142 -0
- package/src/design-system/contracts.ts +69 -0
- package/src/design-system/defaults.ts +3 -0
- package/src/design-system/index.ts +29 -0
- package/src/design-system/mcp-server.ts +156 -0
- package/src/design-system/page-registry.ts +74 -0
- package/src/design-system/selection.ts +67 -0
- package/src/design-system/template-registry.ts +33 -0
- package/src/features/interface-topology/index.ts +14 -0
- package/src/features/interface-topology/interface-topology.types.ts +40 -0
- package/src/features/interface-topology/topology-control.tsx +18 -0
- package/src/features/interface-topology/topology-inspector.tsx +228 -0
- package/src/features/interface-topology/topology-marker.tsx +47 -0
- package/src/features/interface-topology/topology-region.tsx +44 -0
- package/src/features/interface-topology/use-interface-topology.ts +178 -0
- package/src/hooks/use-mobile.ts +19 -0
- package/src/hooks/use-scroll-follow.ts +22 -0
- package/src/index.ts +11 -0
- package/src/layouts/README.md +65 -0
- package/src/layouts/agent-workspace/agent-activity-rail.tsx +101 -0
- package/src/layouts/agent-workspace/agent-workspace.tsx +27 -0
- package/src/layouts/agent-workspace/agent-workspace.types.ts +28 -0
- package/src/layouts/agent-workspace/index.ts +7 -0
- package/src/layouts/blog-header/blog-header-types.ts +25 -0
- package/src/layouts/blog-header/blog-header.tsx +172 -0
- package/src/layouts/blog-header/index.ts +2 -0
- package/src/layouts/documentation-workspace/README.md +8 -0
- package/src/layouts/documentation-workspace/documentation-workspace.tsx +34 -0
- package/src/layouts/documentation-workspace/index.ts +1 -0
- package/src/layouts/ecommerce-header/ecommerce-actions.tsx +89 -0
- package/src/layouts/ecommerce-header/ecommerce-announcement.tsx +43 -0
- package/src/layouts/ecommerce-header/ecommerce-drawer.tsx +97 -0
- package/src/layouts/ecommerce-header/ecommerce-header-types.ts +59 -0
- package/src/layouts/ecommerce-header/ecommerce-header.tsx +47 -0
- package/src/layouts/ecommerce-header/ecommerce-navigation.tsx +98 -0
- package/src/layouts/ecommerce-header/ecommerce-search.tsx +86 -0
- package/src/layouts/ecommerce-header/index.ts +2 -0
- package/src/layouts/main-workspace/index.ts +28 -0
- package/src/layouts/mdi/index.ts +1 -0
- package/src/layouts/mdi/mdi.tsx +20 -0
- package/src/layouts/mdi-main/index.ts +27 -0
- package/src/layouts/mdi-main/mdi-app-catalog.generated.ts +159 -0
- package/src/layouts/mdi-main/mdi-app-catalog.ts +76 -0
- package/src/layouts/mdi-main/mdi-app-switcher.tsx +107 -0
- package/src/layouts/mdi-main/mdi-feature-settings.tsx +135 -0
- package/src/layouts/mdi-main/mdi-global-search.tsx +192 -0
- package/src/layouts/mdi-main/mdi-main.tsx +241 -0
- package/src/layouts/mdi-main/mdi-notifications-menu.tsx +197 -0
- package/src/layouts/mdi-main/mdi-profile-menu.tsx +79 -0
- package/src/layouts/mdi-main/mdi-sidebar-navigation.tsx +226 -0
- package/src/layouts/mdi-main/mdi-sidebar.tsx +110 -0
- package/src/layouts/mdi-main/mdi-status-bar.tsx +26 -0
- package/src/layouts/mdi-main/mdi-top-menu-control.ts +4 -0
- package/src/layouts/mdi-main/mdi-top-menu.tsx +117 -0
- package/src/layouts/mdi-main/mdi-topology.tsx +297 -0
- package/src/layouts/mdi-main/mdi-tweak-panel.tsx +104 -0
- package/src/layouts/mdi-main/mdi-types.ts +131 -0
- package/src/layouts/mdi-main/use-mdi-features.ts +36 -0
- package/src/layouts/mdi-main/use-mdi-sidebar-state.ts +59 -0
- package/src/layouts/site-header/announcement-bar.tsx +55 -0
- package/src/layouts/site-header/category-strip.tsx +41 -0
- package/src/layouts/site-header/index.ts +16 -0
- package/src/layouts/site-header/main-navbar.tsx +179 -0
- package/src/layouts/site-header/mobile-drawer.tsx +140 -0
- package/src/layouts/site-header/site-header-types.ts +63 -0
- package/src/layouts/site-header/site-header.tsx +58 -0
- package/src/lib/random-id.ts +19 -0
- package/src/lib/utils.ts +6 -0
- package/src/providers/pdf-provider.ts +137 -0
- package/src/styles/globals.css +374 -0
- package/src/templates/README.md +12 -0
- package/src/templates/dashboard-01/components/app-sidebar.tsx +177 -0
- package/src/templates/dashboard-01/components/chart-area-interactive.tsx +276 -0
- package/src/templates/dashboard-01/components/data-table-cell-viewer.tsx +213 -0
- package/src/templates/dashboard-01/components/data-table.tsx +577 -0
- package/src/templates/dashboard-01/components/nav-documents.tsx +79 -0
- package/src/templates/dashboard-01/components/nav-main.tsx +55 -0
- package/src/templates/dashboard-01/components/nav-secondary.tsx +39 -0
- package/src/templates/dashboard-01/components/nav-user.tsx +97 -0
- package/src/templates/dashboard-01/components/section-cards.tsx +99 -0
- package/src/templates/dashboard-01/components/site-header.tsx +14 -0
- package/src/templates/dashboard-01/data.json +614 -0
- package/src/templates/dashboard-01/index.ts +7 -0
- package/src/templates/documentation-sidebar/app-sidebar.tsx +95 -0
- package/src/templates/documentation-sidebar/index.ts +2 -0
- package/src/templates/sidebar-07/components/app-sidebar.tsx +175 -0
- package/src/templates/sidebar-07/components/nav-main.tsx +64 -0
- package/src/templates/sidebar-07/components/nav-projects.tsx +79 -0
- package/src/templates/sidebar-07/components/nav-user.tsx +105 -0
- package/src/templates/sidebar-07/components/team-switcher.tsx +94 -0
- package/src/templates/sidebar-07/index.ts +1 -0
- package/src/templates/ui-page/index.ts +7 -0
- package/src/templates/ui-page/ui-browser-frame.tsx +27 -0
- package/src/templates/ui-page/ui-template-code.tsx +48 -0
- package/src/templates/ui-page/ui-template-header.tsx +87 -0
- package/src/templates/ui-page/ui-template-navigation.tsx +60 -0
- package/src/templates/ui-page/ui-template-page.tsx +97 -0
- package/src/theme/index.ts +12 -0
- package/src/theme/theme-config.ts +30 -0
- package/src/theme/theme-provider.tsx +142 -0
- package/src/theme/theme-selector.tsx +75 -0
- package/src/tokens/index.ts +15 -0
- package/src/vite-env.d.ts +3 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
import { Fragment, useEffect, useState, type ReactNode } from "react";
|
|
2
|
+
import type { LucideIcon } from "lucide-react";
|
|
3
|
+
import { CheckIcon, CopyIcon } from "lucide-react";
|
|
4
|
+
import {
|
|
5
|
+
Breadcrumb,
|
|
6
|
+
BreadcrumbItem,
|
|
7
|
+
BreadcrumbLink,
|
|
8
|
+
BreadcrumbList,
|
|
9
|
+
BreadcrumbPage,
|
|
10
|
+
BreadcrumbSeparator,
|
|
11
|
+
} from "../../components/breadcrumb";
|
|
12
|
+
import { Button } from "../../components/button";
|
|
13
|
+
import { cn } from "../../lib/utils";
|
|
14
|
+
|
|
15
|
+
export type AppHeaderVariant = "breadcrumb-actions" | "title-actions" | "resource-actions";
|
|
16
|
+
|
|
17
|
+
export type AppHeaderBreadcrumb = { label: string; href?: string };
|
|
18
|
+
|
|
19
|
+
export type AppHeaderAction = {
|
|
20
|
+
label: string;
|
|
21
|
+
icon?: LucideIcon;
|
|
22
|
+
onClick?: () => void;
|
|
23
|
+
disabled?: boolean;
|
|
24
|
+
};
|
|
25
|
+
|
|
26
|
+
export type AppHeaderProps = {
|
|
27
|
+
variant?: AppHeaderVariant;
|
|
28
|
+
breadcrumbs?: readonly AppHeaderBreadcrumb[];
|
|
29
|
+
title?: ReactNode;
|
|
30
|
+
titleIcon?: LucideIcon;
|
|
31
|
+
profile?: ReactNode;
|
|
32
|
+
filter?: ReactNode;
|
|
33
|
+
primaryAction?: AppHeaderAction;
|
|
34
|
+
resourceLabel?: string;
|
|
35
|
+
resourceHref?: string;
|
|
36
|
+
copyValue?: string;
|
|
37
|
+
copyLabel?: string;
|
|
38
|
+
onCopy?: (value: string) => void;
|
|
39
|
+
start?: ReactNode;
|
|
40
|
+
end?: ReactNode;
|
|
41
|
+
className?: string;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/** Shared page-level header with three common workspace arrangements. */
|
|
45
|
+
export function AppHeader({
|
|
46
|
+
variant = "breadcrumb-actions",
|
|
47
|
+
breadcrumbs = [],
|
|
48
|
+
title,
|
|
49
|
+
titleIcon: TitleIcon,
|
|
50
|
+
profile,
|
|
51
|
+
filter,
|
|
52
|
+
primaryAction,
|
|
53
|
+
resourceLabel,
|
|
54
|
+
resourceHref,
|
|
55
|
+
copyValue,
|
|
56
|
+
copyLabel = "Copy resource",
|
|
57
|
+
onCopy,
|
|
58
|
+
start,
|
|
59
|
+
end,
|
|
60
|
+
className,
|
|
61
|
+
}: AppHeaderProps) {
|
|
62
|
+
const [copyState, setCopyState] = useState<"idle" | "copied" | "failed">("idle");
|
|
63
|
+
|
|
64
|
+
useEffect(() => {
|
|
65
|
+
if (copyState === "idle") return;
|
|
66
|
+
const timeout = window.setTimeout(() => setCopyState("idle"), 2000);
|
|
67
|
+
return () => window.clearTimeout(timeout);
|
|
68
|
+
}, [copyState]);
|
|
69
|
+
|
|
70
|
+
const copyResource = async () => {
|
|
71
|
+
if (!copyValue) return;
|
|
72
|
+
try {
|
|
73
|
+
if (onCopy) onCopy(copyValue);
|
|
74
|
+
else await navigator.clipboard.writeText(copyValue);
|
|
75
|
+
setCopyState("copied");
|
|
76
|
+
} catch {
|
|
77
|
+
setCopyState("failed");
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
const ActionIcon = primaryAction?.icon;
|
|
82
|
+
|
|
83
|
+
return (
|
|
84
|
+
<header
|
|
85
|
+
aria-label="Application header"
|
|
86
|
+
className={cn(
|
|
87
|
+
"flex min-h-12 w-full items-center justify-between gap-4 border-b border-border bg-background px-4 py-2",
|
|
88
|
+
className,
|
|
89
|
+
)}
|
|
90
|
+
data-ui-component="AppHeader"
|
|
91
|
+
data-variant={variant}
|
|
92
|
+
>
|
|
93
|
+
<div className="flex min-w-0 items-center gap-3">
|
|
94
|
+
{start}
|
|
95
|
+
{variant === "breadcrumb-actions" ? <AppBreadcrumbs items={breadcrumbs} /> : null}
|
|
96
|
+
{variant === "title-actions" ? (
|
|
97
|
+
<div className="flex min-w-0 items-center gap-2 text-sm font-medium text-foreground">
|
|
98
|
+
{TitleIcon ? <TitleIcon aria-hidden="true" className="size-4 shrink-0 text-muted-foreground" /> : null}
|
|
99
|
+
<span className="truncate">{title}</span>
|
|
100
|
+
</div>
|
|
101
|
+
) : null}
|
|
102
|
+
{variant === "resource-actions" ? (
|
|
103
|
+
<span className="truncate text-sm font-medium text-foreground">{title}</span>
|
|
104
|
+
) : null}
|
|
105
|
+
</div>
|
|
106
|
+
<div className="flex min-w-0 shrink-0 items-center gap-2">
|
|
107
|
+
{variant === "title-actions" ? filter : null}
|
|
108
|
+
{variant === "breadcrumb-actions" ? profile : null}
|
|
109
|
+
{variant === "resource-actions" && resourceLabel ? (
|
|
110
|
+
<a
|
|
111
|
+
className="max-w-[min(45vw,32rem)] truncate rounded-md px-2 py-1 text-xs text-muted-foreground hover:bg-muted hover:text-foreground"
|
|
112
|
+
href={resourceHref}
|
|
113
|
+
>
|
|
114
|
+
{resourceLabel}
|
|
115
|
+
</a>
|
|
116
|
+
) : null}
|
|
117
|
+
{variant === "resource-actions" && copyValue ? (
|
|
118
|
+
<Button
|
|
119
|
+
aria-label={copyState === "copied" ? "Copied" : copyLabel}
|
|
120
|
+
onClick={copyResource}
|
|
121
|
+
size="icon-sm"
|
|
122
|
+
variant="ghost"
|
|
123
|
+
>
|
|
124
|
+
{copyState === "copied" ? <CheckIcon aria-hidden="true" /> : <CopyIcon aria-hidden="true" />}
|
|
125
|
+
</Button>
|
|
126
|
+
) : null}
|
|
127
|
+
{end}
|
|
128
|
+
{primaryAction ? (
|
|
129
|
+
<Button disabled={primaryAction.disabled} onClick={primaryAction.onClick} size="sm">
|
|
130
|
+
{ActionIcon ? <ActionIcon aria-hidden="true" /> : null}
|
|
131
|
+
{primaryAction.label}
|
|
132
|
+
</Button>
|
|
133
|
+
) : null}
|
|
134
|
+
</div>
|
|
135
|
+
</header>
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
function AppBreadcrumbs({ items }: { items: readonly AppHeaderBreadcrumb[] }) {
|
|
140
|
+
if (items.length === 0) return null;
|
|
141
|
+
return (
|
|
142
|
+
<Breadcrumb>
|
|
143
|
+
<BreadcrumbList className="flex-nowrap text-xs">
|
|
144
|
+
{items.map((item, index) => (
|
|
145
|
+
<Fragment key={`${item.label}-${index}`}>
|
|
146
|
+
{index > 0 ? <BreadcrumbSeparator /> : null}
|
|
147
|
+
<BreadcrumbItem>
|
|
148
|
+
{item.href ? (
|
|
149
|
+
<BreadcrumbLink href={item.href}>{item.label}</BreadcrumbLink>
|
|
150
|
+
) : (
|
|
151
|
+
<BreadcrumbPage>{item.label}</BreadcrumbPage>
|
|
152
|
+
)}
|
|
153
|
+
</BreadcrumbItem>
|
|
154
|
+
</Fragment>
|
|
155
|
+
))}
|
|
156
|
+
</BreadcrumbList>
|
|
157
|
+
</Breadcrumb>
|
|
158
|
+
);
|
|
159
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ArchiveRestoreIcon, SearchIcon, Trash2Icon } from "lucide-react";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { Button } from "../../components/button";
|
|
4
|
+
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../../components/card";
|
|
5
|
+
import { Input } from "../../components/input";
|
|
6
|
+
|
|
7
|
+
export type ArchivedChatItem = { createdAt: string; id: string; messageCount: number; title: string };
|
|
8
|
+
|
|
9
|
+
export type ArchivedChatWorkspaceProps = {
|
|
10
|
+
chats: readonly ArchivedChatItem[];
|
|
11
|
+
onDelete: (id: string) => void;
|
|
12
|
+
onDeleteAll: () => void;
|
|
13
|
+
onOpen: (id: string) => void;
|
|
14
|
+
onRestore: (id: string) => void;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export function ArchivedChatWorkspace({ chats, onDelete, onDeleteAll, onOpen, onRestore }: ArchivedChatWorkspaceProps) {
|
|
18
|
+
const [query, setQuery] = useState("");
|
|
19
|
+
const filteredChats = useMemo(() => chats.filter((chat) => chat.title.toLocaleLowerCase().includes(query.toLocaleLowerCase())), [chats, query]);
|
|
20
|
+
|
|
21
|
+
return <section className="flex size-full min-h-0 flex-col bg-background">
|
|
22
|
+
<header className="flex shrink-0 items-center gap-3 border-b px-4 py-3 sm:px-6"><div className="min-w-0 flex-1"><h1 className="truncate text-sm font-semibold">Archived chats</h1><p className="text-xs text-muted-foreground">Archived handovers remain available until permanently deleted.</p></div><Button disabled={!chats.length} size="sm" variant="destructive" onClick={onDeleteAll}><Trash2Icon /> Delete all</Button></header>
|
|
23
|
+
<main className="min-h-0 flex-1 overflow-y-auto px-4 py-6 sm:px-6"><div className="mx-auto flex w-full max-w-4xl flex-col gap-5"><div className="relative max-w-xl"><SearchIcon aria-hidden="true" className="pointer-events-none absolute top-1/2 left-3 size-4 -translate-y-1/2 text-muted-foreground" /><Input aria-label="Search archived chats" className="pl-9" placeholder="Search archived chats" value={query} onChange={(event) => setQuery(event.target.value)} /></div><Card size="sm"><CardHeader><CardTitle>{filteredChats.length} archived {filteredChats.length === 1 ? "chat" : "chats"}</CardTitle><CardDescription>Restore a conversation to active history, or force delete it permanently.</CardDescription></CardHeader><CardContent className="divide-y">{filteredChats.length ? filteredChats.map((chat) => <article key={chat.id} className="flex flex-wrap items-center gap-3 py-3 first:pt-0 last:pb-0"><button className="min-w-0 flex-1 text-left" onClick={() => onOpen(chat.id)}><p className="truncate text-sm font-medium">{chat.title}</p><p className="text-xs text-muted-foreground">{formatDate(chat.createdAt)} · {chat.messageCount} messages</p></button><Button aria-label={`Permanently delete ${chat.title}`} size="icon-sm" variant="ghost" onClick={() => onDelete(chat.id)}><Trash2Icon /></Button><Button size="sm" variant="outline" onClick={() => onRestore(chat.id)}><ArchiveRestoreIcon /> Unarchive</Button></article>) : <p className="py-8 text-center text-sm text-muted-foreground">No archived chats match this search.</p>}</CardContent></Card></div></main>
|
|
24
|
+
</section>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
function formatDate(value: string): string {
|
|
28
|
+
return new Intl.DateTimeFormat(undefined, { dateStyle: "medium", timeStyle: "short" }).format(new Date(value));
|
|
29
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Authentication Blocks
|
|
2
|
+
|
|
3
|
+
This folder owns reusable, presentation-only authentication blocks. It provides separate client,
|
|
4
|
+
administrator, and super-administrator entry pages, separate recovery entry components,
|
|
5
|
+
registration, and isolated portal placeholders.
|
|
6
|
+
|
|
7
|
+
The blocks do not call APIs, store sessions, select roles, or contain business policy. An
|
|
8
|
+
application supplies callbacks and owns routes, state, validation responses, and access decisions.
|
|
9
|
+
Internal shell and form components may share visual mechanics without merging portal behavior.
|
|
10
|
+
|
|
11
|
+
The sign-in and recovery forms accept a username or email address. The registration block exposes an
|
|
12
|
+
email address plus optional username and mobile fields. The consuming application owns
|
|
13
|
+
normalization, uniqueness, verification, and persistence.
|
|
14
|
+
|
|
15
|
+
Passwords use an eight-character presentation minimum. The consuming Identity API remains the
|
|
16
|
+
validation authority.
|
|
17
|
+
|
|
18
|
+
Set `registerHref={null}` to hide registration explicitly. An omitted value keeps the generic
|
|
19
|
+
default. Privileged entry blocks always hide registration. The client block follows
|
|
20
|
+
`registrationEnabled`. The identifier uses a text input so browser email validation does not reject
|
|
21
|
+
usernames. Development sign-in is disabled while a submission is pending.
|
|
22
|
+
|
|
23
|
+
## Common guidance
|
|
24
|
+
|
|
25
|
+
Retrieve shared documentation and rules only from `https://mcp.codexsun.com/mcp` using `npm run mcp:connect`.
|
|
26
|
+
A successful authenticated connection is required before repository work. Stop and report connection failures.
|
|
27
|
+
Do not use local guides or cached instructions as fallback. Instruction retrieval does not authorize actions.
|
|
28
|
+
|
|
29
|
+
`LoginPage` provides two owned variants. Version 1 is a centered CODEXSUN entry card. Version 2 uses
|
|
30
|
+
a split card with provider actions and a supporting visual surface. `RegisterPage` provides matching
|
|
31
|
+
centered and split variants. The UI Gallery can persist one default per page family; applications
|
|
32
|
+
select a supported variant through the design-system page registry.
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { LoginPage, type LoginPageProps } from './login-page'
|
|
2
|
+
|
|
3
|
+
export function AdminLoginPage(
|
|
4
|
+
props: Omit<LoginPageProps, 'description' | 'forgotHref' | 'registerHref' | 'title' | 'variant'>,
|
|
5
|
+
) {
|
|
6
|
+
return (
|
|
7
|
+
<LoginPage
|
|
8
|
+
{...props}
|
|
9
|
+
description="Use an administrator account for this isolated desk."
|
|
10
|
+
forgotHref="/admin/password/forgot"
|
|
11
|
+
registerHref={null}
|
|
12
|
+
title="Administrator sign in"
|
|
13
|
+
/>
|
|
14
|
+
)
|
|
15
|
+
}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import { CrownIcon, PanelsTopLeftIcon } from 'lucide-react'
|
|
2
|
+
import type { ReactNode } from 'react'
|
|
3
|
+
import { Card, CardContent } from '../../components/card'
|
|
4
|
+
import { cn } from '../../lib/utils'
|
|
5
|
+
|
|
6
|
+
export type AuthPageVariant = 'v1' | 'v2'
|
|
7
|
+
|
|
8
|
+
export function AuthBrand({ name = 'Codexsun' }: { name?: string }) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="flex flex-col items-center gap-2" aria-label={name}>
|
|
11
|
+
<span className="relative grid size-12 place-items-center rounded-xl border-2 border-foreground/80 bg-background">
|
|
12
|
+
<PanelsTopLeftIcon className="size-7" strokeWidth={2.25} />
|
|
13
|
+
<span className="absolute -right-2 -bottom-1 grid size-5 place-items-center rounded-full border border-orange-300 bg-orange-50 text-orange-600">
|
|
14
|
+
<CrownIcon className="size-3" />
|
|
15
|
+
</span>
|
|
16
|
+
</span>
|
|
17
|
+
<span className="text-xl font-semibold tracking-tight">{name}</span>
|
|
18
|
+
</div>
|
|
19
|
+
)
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function AuthPageLayout({
|
|
23
|
+
aside,
|
|
24
|
+
brandName,
|
|
25
|
+
children,
|
|
26
|
+
className,
|
|
27
|
+
embedded = false,
|
|
28
|
+
variant,
|
|
29
|
+
}: {
|
|
30
|
+
aside?: ReactNode
|
|
31
|
+
brandName?: string
|
|
32
|
+
children: ReactNode
|
|
33
|
+
className?: string
|
|
34
|
+
embedded?: boolean
|
|
35
|
+
variant: AuthPageVariant
|
|
36
|
+
}) {
|
|
37
|
+
if (variant === 'v2') {
|
|
38
|
+
return (
|
|
39
|
+
<main
|
|
40
|
+
className={cn(
|
|
41
|
+
'flex items-center justify-center bg-muted/30 px-5 py-10',
|
|
42
|
+
embedded ? 'min-h-[650px]' : 'min-h-screen',
|
|
43
|
+
className,
|
|
44
|
+
)}
|
|
45
|
+
>
|
|
46
|
+
<div className="grid w-full max-w-4xl gap-5">
|
|
47
|
+
<AuthBrand name={brandName} />
|
|
48
|
+
<Card className="overflow-hidden p-0 shadow-lg">
|
|
49
|
+
<CardContent className="grid p-0 md:grid-cols-2">
|
|
50
|
+
<div className="p-7 md:p-9">{children}</div>
|
|
51
|
+
<div className="relative hidden min-h-[520px] overflow-hidden border-l bg-foreground text-background md:flex">
|
|
52
|
+
{aside}
|
|
53
|
+
</div>
|
|
54
|
+
</CardContent>
|
|
55
|
+
</Card>
|
|
56
|
+
</div>
|
|
57
|
+
</main>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return (
|
|
62
|
+
<main
|
|
63
|
+
className={cn(
|
|
64
|
+
'flex items-center justify-center bg-success/5 px-5 py-10',
|
|
65
|
+
embedded ? 'min-h-[650px]' : 'min-h-screen',
|
|
66
|
+
className,
|
|
67
|
+
)}
|
|
68
|
+
>
|
|
69
|
+
<div className="grid w-full max-w-[520px] gap-5">
|
|
70
|
+
<AuthBrand name={brandName} />
|
|
71
|
+
<Card className="border border-orange-200/70 p-1 shadow-xl shadow-foreground/10 ring-1 ring-border">
|
|
72
|
+
<CardContent className="rounded-lg border bg-card p-9">{children}</CardContent>
|
|
73
|
+
</Card>
|
|
74
|
+
</div>
|
|
75
|
+
</main>
|
|
76
|
+
)
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export function AuthVisualPanel({ description, title }: { description: string; title: string }) {
|
|
80
|
+
return (
|
|
81
|
+
<div className="relative flex min-h-full w-full flex-col justify-end overflow-hidden p-9">
|
|
82
|
+
<div className="absolute -top-20 -right-20 size-72 rounded-full border border-background/20" />
|
|
83
|
+
<div className="absolute top-20 right-16 size-40 rounded-full border border-background/15" />
|
|
84
|
+
<div className="relative grid gap-2">
|
|
85
|
+
<p className="text-2xl font-semibold tracking-tight">{title}</p>
|
|
86
|
+
<p className="max-w-sm text-sm leading-6 text-background/70">{description}</p>
|
|
87
|
+
</div>
|
|
88
|
+
</div>
|
|
89
|
+
)
|
|
90
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { LoginPage, type LoginPageProps } from './login-page'
|
|
2
|
+
|
|
3
|
+
export function ClientLoginPage(
|
|
4
|
+
props: Omit<
|
|
5
|
+
LoginPageProps,
|
|
6
|
+
'description' | 'forgotHref' | 'registerHref' | 'title' | 'variant'
|
|
7
|
+
> & {
|
|
8
|
+
registrationEnabled?: boolean
|
|
9
|
+
},
|
|
10
|
+
) {
|
|
11
|
+
return (
|
|
12
|
+
<LoginPage
|
|
13
|
+
{...props}
|
|
14
|
+
description="Sign in to your workspace."
|
|
15
|
+
forgotHref="/password/forgot"
|
|
16
|
+
registerHref={props.registrationEnabled ? '/register' : null}
|
|
17
|
+
title="Welcome back"
|
|
18
|
+
/>
|
|
19
|
+
)
|
|
20
|
+
}
|