@goplusvn/core 0.1.0 → 0.1.1
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/package.json +2 -1
- package/src/assets/erp_wallpaper.png +0 -0
- package/src/assets/goeat_logo.png +0 -0
- package/src/audit/audit-manager.ts +139 -0
- package/src/audit/index.ts +11 -0
- package/src/audit/memory-audit-logger.ts +86 -0
- package/src/audit/types.ts +50 -0
- package/src/auth/auth-service.ts +97 -0
- package/src/auth/index.ts +266 -0
- package/src/code-generation/index.ts +69 -0
- package/src/configs/auth-routes.ts +17 -0
- package/src/configs/crud.ts +136 -0
- package/src/configs/data/navigations.ts +781 -0
- package/src/configs/data/oauth-links.ts +10 -0
- package/src/configs/entities/material-categories.config.ts +125 -0
- package/src/configs/i18n.ts +12 -0
- package/src/configs/index.ts +26 -0
- package/src/configs/status.ts +25 -0
- package/src/configs/themes.ts +100 -0
- package/src/crud/components/crud-bulk-actions.tsx +91 -0
- package/src/crud/components/crud-card-view.tsx +241 -0
- package/src/crud/components/crud-context.tsx +122 -0
- package/src/crud/components/crud-delete-dialog.tsx +145 -0
- package/src/crud/components/crud-dialog.tsx +406 -0
- package/src/crud/components/crud-empty-state.tsx +104 -0
- package/src/crud/components/crud-export-button.tsx +170 -0
- package/src/crud/components/crud-field-renderer.tsx +653 -0
- package/src/crud/components/crud-filter-chips.tsx +102 -0
- package/src/crud/components/crud-filters/checkbox-filter.tsx +97 -0
- package/src/crud/components/crud-filters/datetime-filter.tsx +83 -0
- package/src/crud/components/crud-filters/filter-builder.tsx +66 -0
- package/src/crud/components/crud-filters/index.tsx +76 -0
- package/src/crud/components/crud-filters/radio-filter.tsx +86 -0
- package/src/crud/components/crud-filters/select-filter.tsx +141 -0
- package/src/crud/components/crud-filters/text-filter.tsx +86 -0
- package/src/crud/components/crud-form.tsx +642 -0
- package/src/crud/components/crud-import-dialog.tsx +440 -0
- package/src/crud/components/crud-infinite-scroll.tsx +116 -0
- package/src/crud/components/crud-page.tsx +1017 -0
- package/src/crud/components/crud-provider.tsx +277 -0
- package/src/crud/components/crud-row-actions.tsx +189 -0
- package/src/crud/components/crud-search.tsx +82 -0
- package/src/crud/components/crud-sheet.tsx +336 -0
- package/src/crud/components/crud-table-skeleton.tsx +26 -0
- package/src/crud/components/crud-table-toolbar.tsx +91 -0
- package/src/crud/components/crud-table.tsx +352 -0
- package/src/crud/components/crud-virtual-table.tsx +55 -0
- package/src/crud/components/index.tsx +20 -0
- package/src/crud/crud-filters/checkbox-filter.tsx +87 -0
- package/src/crud/crud-filters/datetime-filter.tsx +82 -0
- package/src/crud/crud-filters/filter-builder.tsx +64 -0
- package/src/crud/crud-filters/index.tsx +78 -0
- package/src/crud/crud-filters/radio-filter.tsx +79 -0
- package/src/crud/crud-filters/select-filter.tsx +148 -0
- package/src/crud/crud-filters/text-filter.tsx +81 -0
- package/src/crud/index.ts +43 -0
- package/src/crud/lib/crud-service.test.ts +334 -0
- package/src/crud/lib/crud-service.ts +358 -0
- package/src/crud/lib/crud-utils.test.ts +354 -0
- package/src/crud/lib/crud-utils.ts +299 -0
- package/src/crud/lib/crud-validator.ts +247 -0
- package/src/crud/lib/data-loader.ts +234 -0
- package/src/crud/lib/field-calculator.ts +241 -0
- package/src/crud/lib/field-formatter.ts +240 -0
- package/src/crud/lib/import-export-service.test.ts +290 -0
- package/src/crud/lib/import-export-service.ts +352 -0
- package/src/crud/lib/import-server-utils.ts +109 -0
- package/src/crud/lib/lazy-loader.ts +241 -0
- package/src/crud/lib/parse-filters.ts +85 -0
- package/src/crud/lib/permissions.ts +52 -0
- package/src/crud/lib/serialize-config.ts +60 -0
- package/src/crud/lib/stream-loader.ts +145 -0
- package/src/crud/lib/translate-config.ts +335 -0
- package/src/crud/lib/types.ts +11 -0
- package/src/crud/pages/entity-crud-page.tsx +144 -0
- package/src/crud/server.ts +8 -0
- package/src/home/constants.tsx +142 -0
- package/src/home/feature-showcase.tsx +171 -0
- package/src/home/home-page.tsx +191 -0
- package/src/home/hooks/index.ts +1 -0
- package/src/home/hooks/useWidgetPreferences.ts +167 -0
- package/src/home/index.ts +33 -0
- package/src/home/quick-access-dialog.tsx +271 -0
- package/src/home/quick-access-menu.tsx +267 -0
- package/src/home/types.ts +140 -0
- package/src/home/welcome-card.tsx +92 -0
- package/src/home/widget-container.tsx +258 -0
- package/src/home/widgets/base-widget.tsx +200 -0
- package/src/home/widgets/customers-widget.tsx +74 -0
- package/src/home/widgets/index.ts +6 -0
- package/src/home/widgets/orders-widget.tsx +87 -0
- package/src/home/widgets/revenue-widget.tsx +71 -0
- package/src/home/widgets/stock-widget.tsx +109 -0
- package/src/hooks/index.tsx +598 -0
- package/src/hooks/use-tenant.test.tsx +30 -0
- package/src/hooks/use-tenant.ts +5 -0
- package/src/index.ts +17 -0
- package/src/infrastructure/__tests__/architecture-verification.spec.ts +103 -0
- package/src/infrastructure/api-service.ts +317 -0
- package/src/infrastructure/cache/cache-manager.ts +107 -0
- package/src/infrastructure/cache/cache.ts +120 -0
- package/src/infrastructure/cache/index.ts +8 -0
- package/src/infrastructure/cache/types.ts +48 -0
- package/src/infrastructure/cron/cron-manager.ts +239 -0
- package/src/infrastructure/cron/index.ts +6 -0
- package/src/infrastructure/cron/types.ts +41 -0
- package/src/infrastructure/event-bus/event-bus.ts +145 -0
- package/src/infrastructure/event-bus/index.ts +2 -0
- package/src/infrastructure/event-bus/types.ts +22 -0
- package/src/infrastructure/index.ts +32 -0
- package/src/infrastructure/lock/decorators.ts +67 -0
- package/src/infrastructure/lock/index.ts +2 -0
- package/src/infrastructure/lock/lock-manager.ts +33 -0
- package/src/infrastructure/logger/index.ts +2 -0
- package/src/infrastructure/logger/logger.ts +96 -0
- package/src/infrastructure/logger/types.ts +25 -0
- package/src/layout/index.tsx +185 -0
- package/src/navigation/index.ts +91 -0
- package/src/notification/index.ts +14 -0
- package/src/notification/notification-service.ts +120 -0
- package/src/notification/storage/in-memory.ts +56 -0
- package/src/notification/storage/index.ts +1 -0
- package/src/notification/types.ts +51 -0
- package/src/organization/branch-service.ts +299 -0
- package/src/organization/branches.config.ts +154 -0
- package/src/organization/index.ts +5 -0
- package/src/plugin/apps-registry.ts +97 -0
- package/src/plugin/index.ts +5 -0
- package/src/plugin/types.ts +41 -0
- package/src/providers/index.tsx +109 -0
- package/src/providers/tenant-provider.tsx +45 -0
- package/src/rbac/components/roles/role-card.tsx +158 -0
- package/src/rbac/components/roles/role-stats-cards.tsx +29 -0
- package/src/rbac/components/roles/role-toolbar.tsx +123 -0
- package/src/rbac/hooks/use-role-operations.ts +159 -0
- package/src/rbac/hooks/use-roles-data.ts +59 -0
- package/src/rbac/index.ts +297 -0
- package/src/rbac/lib/permission-helpers.ts +63 -0
- package/src/rbac/pages/action-list-page.tsx +25 -0
- package/src/rbac/pages/resource-list-page.tsx +25 -0
- package/src/rbac/pages/role-list-page.tsx +378 -0
- package/src/rbac/permission-service.ts +140 -0
- package/src/rbac/permissions.ts +135 -0
- package/src/rbac/resource-service.ts +115 -0
- package/src/rbac/resource-validator.ts +119 -0
- package/src/rbac/role-service.ts +165 -0
- package/src/rbac/server.ts +16 -0
- package/src/rbac/types.ts +38 -0
- package/src/schemas/action.schema.ts +66 -0
- package/src/schemas/branch.schema.ts +52 -0
- package/src/schemas/coming-soon-schema.ts +9 -0
- package/src/schemas/company.schema.ts +44 -0
- package/src/schemas/forgot-passward-schema.ts +9 -0
- package/src/schemas/index.ts +30 -0
- package/src/schemas/material-category.schema.ts +43 -0
- package/src/schemas/material-pricing.schema.ts +74 -0
- package/src/schemas/material.schema.ts +76 -0
- package/src/schemas/materials.ts +52 -0
- package/src/schemas/new-passward-schema.ts +15 -0
- package/src/schemas/partner-company.schema.ts +149 -0
- package/src/schemas/register-schema.ts +36 -0
- package/src/schemas/resource.schema.ts +133 -0
- package/src/schemas/role.schema.ts +11 -0
- package/src/schemas/sign-in-schema.ts +24 -0
- package/src/schemas/supplier-pricing.schema.ts +15 -0
- package/src/schemas/supplier.schema.ts +120 -0
- package/src/schemas/system-category-group.schema.ts +67 -0
- package/src/schemas/system-category.schema.ts +77 -0
- package/src/schemas/system-config.schema.ts +118 -0
- package/src/schemas/uom.schema.ts +75 -0
- package/src/schemas/user-supplier.schema.ts +179 -0
- package/src/schemas/user.schema.ts +18 -0
- package/src/schemas/verify-email-schema.ts +9 -0
- package/src/schemas/warehouse.schema.ts +49 -0
- package/src/system/components/categories/category-list.tsx +529 -0
- package/src/system/components/categories/category-manager.tsx +89 -0
- package/src/system/components/categories/group-sidebar.tsx +308 -0
- package/src/system/components/settings/setting-dialogs.tsx +197 -0
- package/src/system/components/settings/setting-field.tsx +291 -0
- package/src/system/components/settings/setting-form-dialog.tsx +308 -0
- package/src/system/components/settings/settings-groups.ts +80 -0
- package/src/system/components/settings/settings-search.tsx +71 -0
- package/src/system/components/settings/settings-section.tsx +74 -0
- package/src/system/components/settings/settings-sidebar.tsx +81 -0
- package/src/system/constants.ts +3 -0
- package/src/system/index.ts +150 -0
- package/src/system/job-manager.ts +176 -0
- package/src/system/pages/components/categories/category-list.tsx +537 -0
- package/src/system/pages/components/categories/category-manager.tsx +90 -0
- package/src/system/pages/components/categories/group-sidebar.tsx +311 -0
- package/src/system/pages/components/settings/sales-rules-settings.tsx +222 -0
- package/src/system/pages/components/settings/setting-dialogs.tsx +197 -0
- package/src/system/pages/components/settings/setting-field.tsx +292 -0
- package/src/system/pages/components/settings/setting-form-dialog.tsx +308 -0
- package/src/system/pages/components/settings/settings-groups.ts +87 -0
- package/src/system/pages/components/settings/settings-page.tsx +372 -0
- package/src/system/pages/components/settings/settings-search.tsx +71 -0
- package/src/system/pages/components/settings/settings-section.tsx +74 -0
- package/src/system/pages/components/settings/settings-sidebar.tsx +81 -0
- package/src/system/pages/components/settings/system-settings.tsx +244 -0
- package/src/system/pages/system-category-page.tsx +15 -0
- package/src/system/pages/system-settings-page.tsx +380 -0
- package/src/system/schemas/system-category-group.schema.ts +46 -0
- package/src/system/schemas/system-category.schema.ts +56 -0
- package/src/system/services/settings-service.ts +127 -0
- package/src/system/services/system-category-service.ts +63 -0
- package/src/system/types.ts +45 -0
- package/src/types/index.ts +703 -0
- package/src/ui/auth/auth-layout.tsx +135 -0
- package/src/ui/auth/forgot-password-form.tsx +98 -0
- package/src/ui/auth/index.tsx +7 -0
- package/src/ui/auth/new-password-form.tsx +107 -0
- package/src/ui/auth/oauth-links.tsx +30 -0
- package/src/ui/auth/register-form.tsx +202 -0
- package/src/ui/auth/sign-in-form.tsx +238 -0
- package/src/ui/auth/verify-email-form.tsx +104 -0
- package/src/ui/crud/index.tsx +10 -0
- package/src/ui/data-display/accordion.tsx +65 -0
- package/src/ui/data-display/aspect-ratio.tsx +11 -0
- package/src/ui/data-display/avatar.tsx +163 -0
- package/src/ui/data-display/bento-grid.tsx +77 -0
- package/src/ui/data-display/carousel.tsx +249 -0
- package/src/ui/data-display/chart.tsx +363 -0
- package/src/ui/data-display/code-block-highlight.tsx +54 -0
- package/src/ui/data-display/collapsible.tsx +42 -0
- package/src/ui/data-display/compact-stat-bar.tsx +149 -0
- package/src/ui/data-display/data-table/data-table-context.tsx +255 -0
- package/src/ui/data-display/data-table/data-table-empty-state.tsx +133 -0
- package/src/ui/data-display/data-table/data-table-skeleton.tsx +145 -0
- package/src/ui/data-display/data-table/data-table-toolbar.tsx +353 -0
- package/src/ui/data-display/data-table/data-table.tsx +597 -0
- package/src/ui/data-display/data-table/index.ts +44 -0
- package/src/ui/data-display/data-table-column-header.tsx +75 -0
- package/src/ui/data-display/data-table-pagination.tsx +130 -0
- package/src/ui/data-display/data-table-view-options.tsx +59 -0
- package/src/ui/data-display/formatted-number-input.tsx +210 -0
- package/src/ui/data-display/highlight.tsx +20 -0
- package/src/ui/data-display/hover-card.tsx +48 -0
- package/src/ui/data-display/index.tsx +50 -0
- package/src/ui/data-display/iphone-15-pro.tsx +114 -0
- package/src/ui/data-display/kanban/index.ts +4 -0
- package/src/ui/data-display/kanban/kanban-board.tsx +192 -0
- package/src/ui/data-display/kanban/kanban-column.tsx +74 -0
- package/src/ui/data-display/kanban/kanban-item.tsx +50 -0
- package/src/ui/data-display/kanban/kanban-types.ts +21 -0
- package/src/ui/data-display/kpi-card.tsx +68 -0
- package/src/ui/data-display/media-grid.tsx +110 -0
- package/src/ui/data-display/safari.tsx +175 -0
- package/src/ui/data-display/show-more-text.tsx +55 -0
- package/src/ui/data-display/tabs.tsx +68 -0
- package/src/ui/data-display/timeline.tsx +256 -0
- package/src/ui/feedback/alert.tsx +60 -0
- package/src/ui/feedback/context-menu.tsx +245 -0
- package/src/ui/feedback/drawer.tsx +132 -0
- package/src/ui/feedback/error-dialog.tsx +273 -0
- package/src/ui/feedback/index.tsx +183 -0
- package/src/ui/feedback/progress.tsx +32 -0
- package/src/ui/feedback/sheet.tsx +148 -0
- package/src/ui/feedback/sonner.tsx +36 -0
- package/src/ui/forms/command.tsx +157 -0
- package/src/ui/forms/date-picker.tsx +73 -0
- package/src/ui/forms/date-range-picker.tsx +76 -0
- package/src/ui/forms/date-time-picker.tsx +109 -0
- package/src/ui/forms/editor/editor-menu-bar.tsx +394 -0
- package/src/ui/forms/editor/index.tsx +130 -0
- package/src/ui/forms/editor/multi-select-example.tsx +1234 -0
- package/src/ui/forms/emoji-picker.tsx +109 -0
- package/src/ui/forms/file-dropzone.tsx +169 -0
- package/src/ui/forms/file-thumbnail.tsx +29 -0
- package/src/ui/forms/index.tsx +201 -0
- package/src/ui/forms/input-file.tsx +99 -0
- package/src/ui/forms/input-group.tsx +46 -0
- package/src/ui/forms/input-otp.tsx +81 -0
- package/src/ui/forms/input-phone.tsx +172 -0
- package/src/ui/forms/input-spin.tsx +116 -0
- package/src/ui/forms/input-tags.tsx +219 -0
- package/src/ui/forms/input-time.tsx +42 -0
- package/src/ui/forms/multi-select.tsx +629 -0
- package/src/ui/forms/multiple-date-picker.tsx +74 -0
- package/src/ui/forms/radio-group.tsx +42 -0
- package/src/ui/forms/rating.tsx +158 -0
- package/src/ui/forms/time-picker.tsx +57 -0
- package/src/ui/index.tsx +17 -0
- package/src/ui/layout/animated-list.tsx +77 -0
- package/src/ui/layout/animated-sidebar.tsx +294 -0
- package/src/ui/layout/command-menu.tsx +355 -0
- package/src/ui/layout/customizer.tsx +324 -0
- package/src/ui/layout/footer.tsx +43 -0
- package/src/ui/layout/full-screen-toggle.tsx +52 -0
- package/src/ui/layout/header-breadcrumb.tsx +77 -0
- package/src/ui/layout/horizontal-layout-header.tsx +83 -0
- package/src/ui/layout/horizontal-layout.tsx +50 -0
- package/src/ui/layout/index.tsx +25 -0
- package/src/ui/layout/language-dropdown.tsx +103 -0
- package/src/ui/layout/logo.tsx +63 -0
- package/src/ui/layout/main-layout.tsx +57 -0
- package/src/ui/layout/mode-dropdown.tsx +58 -0
- package/src/ui/layout/notification-dropdown.tsx +127 -0
- package/src/ui/layout/page-tabs.tsx +306 -0
- package/src/ui/layout/route-cache.tsx +214 -0
- package/src/ui/layout/sidebar-group-icon-menu.tsx +195 -0
- package/src/ui/layout/sidebar.tsx +279 -0
- package/src/ui/layout/tab-content-cache.tsx +201 -0
- package/src/ui/layout/tab-navigation-provider.tsx +536 -0
- package/src/ui/layout/toggle-mobile-sidebar.tsx +33 -0
- package/src/ui/layout/top-bar-header-menubar.tsx +412 -0
- package/src/ui/layout/user-dropdown.tsx +188 -0
- package/src/ui/layout/vertical-layout-header.tsx +65 -0
- package/src/ui/layout/vertical-layout.tsx +47 -0
- package/src/ui/management/audit-log-page.tsx +209 -0
- package/src/ui/management/cache-management.tsx +349 -0
- package/src/ui/management/index.ts +3 -0
- package/src/ui/management/job-management.tsx +308 -0
- package/src/ui/pages/not-found.tsx +30 -0
- package/src/ui/primitives/badge.tsx +66 -0
- package/src/ui/primitives/breadcrumb.tsx +103 -0
- package/src/ui/primitives/button.tsx +129 -0
- package/src/ui/primitives/calendar.tsx +74 -0
- package/src/ui/primitives/card.tsx +86 -0
- package/src/ui/primitives/checkbox.tsx +31 -0
- package/src/ui/primitives/client.ts +30 -0
- package/src/ui/primitives/combobox.tsx +290 -0
- package/src/ui/primitives/dialog.tsx +121 -0
- package/src/ui/primitives/dropdown-menu.tsx +239 -0
- package/src/ui/primitives/dynamic-icon.tsx +24 -0
- package/src/ui/primitives/index.tsx +134 -0
- package/src/ui/primitives/input-number.tsx +131 -0
- package/src/ui/primitives/input.tsx +22 -0
- package/src/ui/primitives/keyboard.tsx +23 -0
- package/src/ui/primitives/label.tsx +24 -0
- package/src/ui/primitives/menubar.tsx +262 -0
- package/src/ui/primitives/navigation-menu.tsx +157 -0
- package/src/ui/primitives/pagination.tsx +118 -0
- package/src/ui/primitives/popover.tsx +56 -0
- package/src/ui/primitives/prefetch-link.tsx +60 -0
- package/src/ui/primitives/resizable.tsx +59 -0
- package/src/ui/primitives/scroll-area.tsx +63 -0
- package/src/ui/primitives/select.tsx +172 -0
- package/src/ui/primitives/separator.tsx +51 -0
- package/src/ui/primitives/sidebar.tsx +844 -0
- package/src/ui/primitives/slider.tsx +27 -0
- package/src/ui/primitives/status-badge.tsx +47 -0
- package/src/ui/primitives/sticky-layout.tsx +50 -0
- package/src/ui/primitives/switch.tsx +29 -0
- package/src/ui/primitives/table.tsx +116 -0
- package/src/ui/primitives/tabs.tsx +55 -0
- package/src/ui/primitives/toggle-group.tsx +70 -0
- package/src/ui/primitives/toggle.tsx +47 -0
- package/src/ui/primitives/tooltip.tsx +59 -0
- package/src/user/components/dangerous-zone.tsx +34 -0
- package/src/user/components/delete-account-form.tsx +40 -0
- package/src/user/components/index.ts +4 -0
- package/src/user/components/profile-info-form.tsx +390 -0
- package/src/user/components/profile-info.tsx +32 -0
- package/src/user/components/unified-profile-dialog.tsx +1019 -0
- package/src/user/components/user-stats.tsx +27 -0
- package/src/user/components/user-toolbar.tsx +137 -0
- package/src/user/components/users-card-view.tsx +253 -0
- package/src/user/index.ts +11 -0
- package/src/user/pages/user-list-page.tsx +234 -0
- package/src/user/pages/users-client-page.tsx +385 -0
- package/src/user/profile-page.tsx +19 -0
- package/src/user/schemas.ts +68 -0
- package/src/user/types.ts +34 -0
- package/src/user/user-service.ts +538 -0
- package/src/utils/index.ts +906 -0
- package/src/workflow/activity-timeline.tsx +412 -0
- package/src/workflow/approval-workflow.tsx +31 -0
- package/src/workflow/index.ts +2 -0
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as MenubarPrimitive from "@radix-ui/react-menubar";
|
|
4
|
+
import { Check, ChevronRight, Dot } from "lucide-react";
|
|
5
|
+
|
|
6
|
+
import type { ComponentProps } from "react";
|
|
7
|
+
|
|
8
|
+
import { cn } from "../../utils";
|
|
9
|
+
|
|
10
|
+
export function MenubarMenu({
|
|
11
|
+
...props
|
|
12
|
+
}: ComponentProps<typeof MenubarPrimitive.Menu>) {
|
|
13
|
+
return <MenubarPrimitive.Menu data-slot="menubar-menu" {...props} />;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export function MenubarGroup({
|
|
17
|
+
...props
|
|
18
|
+
}: ComponentProps<typeof MenubarPrimitive.Group>) {
|
|
19
|
+
return <MenubarPrimitive.Group data-slot="menubar-group" {...props} />;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function MenubarPortal({
|
|
23
|
+
...props
|
|
24
|
+
}: ComponentProps<typeof MenubarPrimitive.Portal>) {
|
|
25
|
+
return <MenubarPrimitive.Portal data-slot="menubar-portal" {...props} />;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function MenubarRadioGroup({
|
|
29
|
+
...props
|
|
30
|
+
}: ComponentProps<typeof MenubarPrimitive.RadioGroup>) {
|
|
31
|
+
return (
|
|
32
|
+
<MenubarPrimitive.RadioGroup data-slot="menubar-radio-group" {...props} />
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function Menubar({
|
|
37
|
+
className,
|
|
38
|
+
...props
|
|
39
|
+
}: ComponentProps<typeof MenubarPrimitive.Root>) {
|
|
40
|
+
return (
|
|
41
|
+
<MenubarPrimitive.Root
|
|
42
|
+
data-slot="menubar"
|
|
43
|
+
className={cn(
|
|
44
|
+
"flex h-9 items-center gap-x-1 rounded-md border bg-background p-1",
|
|
45
|
+
className,
|
|
46
|
+
)}
|
|
47
|
+
{...props}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
export function MenubarTrigger({
|
|
53
|
+
className,
|
|
54
|
+
...props
|
|
55
|
+
}: ComponentProps<typeof MenubarPrimitive.Trigger>) {
|
|
56
|
+
return (
|
|
57
|
+
<MenubarPrimitive.Trigger
|
|
58
|
+
data-slot="menubar-trigger"
|
|
59
|
+
className={cn(
|
|
60
|
+
"flex cursor-pointer select-none items-center rounded-sm px-3 py-1 text-sm font-medium outline-hidden focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground",
|
|
61
|
+
className,
|
|
62
|
+
)}
|
|
63
|
+
{...props}
|
|
64
|
+
/>
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function MenubarSubTrigger({
|
|
69
|
+
className,
|
|
70
|
+
inset,
|
|
71
|
+
children,
|
|
72
|
+
...props
|
|
73
|
+
}: ComponentProps<typeof MenubarPrimitive.SubTrigger> & {
|
|
74
|
+
inset?: boolean;
|
|
75
|
+
}) {
|
|
76
|
+
return (
|
|
77
|
+
<MenubarPrimitive.SubTrigger
|
|
78
|
+
data-slot="menubar-sub-trigger"
|
|
79
|
+
data-inset={inset}
|
|
80
|
+
className={cn(
|
|
81
|
+
"focus:bg-accent focus:text-accent-foreground data-[state=open]:bg-accent data-[state=open]:text-accent-foreground cursor-pointer flex items-center rounded-sm px-2 py-1.5 text-sm outline-none select-none data-[inset]:ps-8",
|
|
82
|
+
className,
|
|
83
|
+
)}
|
|
84
|
+
{...props}
|
|
85
|
+
>
|
|
86
|
+
{children}
|
|
87
|
+
<ChevronRight className="ms-auto h-4 w-4 rtl:-scale-x-100" />
|
|
88
|
+
</MenubarPrimitive.SubTrigger>
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export function MenubarSub({
|
|
93
|
+
...props
|
|
94
|
+
}: ComponentProps<typeof MenubarPrimitive.Sub>) {
|
|
95
|
+
return <MenubarPrimitive.Sub data-slot="menubar-sub" {...props} />;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
export function MenubarSubContent({
|
|
99
|
+
className,
|
|
100
|
+
...props
|
|
101
|
+
}: ComponentProps<typeof MenubarPrimitive.SubContent>) {
|
|
102
|
+
return (
|
|
103
|
+
<MenubarPrimitive.SubContent
|
|
104
|
+
data-slot="menubar-sub-content"
|
|
105
|
+
className={cn(
|
|
106
|
+
"z-50 min-w-[8rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-lg data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
107
|
+
className,
|
|
108
|
+
)}
|
|
109
|
+
{...props}
|
|
110
|
+
/>
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
export function MenubarContent({
|
|
115
|
+
className,
|
|
116
|
+
align = "start",
|
|
117
|
+
alignOffset = -4,
|
|
118
|
+
sideOffset = 8,
|
|
119
|
+
...props
|
|
120
|
+
}: ComponentProps<typeof MenubarPrimitive.Content>) {
|
|
121
|
+
return (
|
|
122
|
+
<MenubarPortal>
|
|
123
|
+
<MenubarPrimitive.Content
|
|
124
|
+
data-slot="menubar-content"
|
|
125
|
+
align={align}
|
|
126
|
+
alignOffset={alignOffset}
|
|
127
|
+
sideOffset={sideOffset}
|
|
128
|
+
className={cn(
|
|
129
|
+
"z-50 min-w-[12rem] overflow-hidden rounded-md border bg-popover p-1 text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
130
|
+
className,
|
|
131
|
+
)}
|
|
132
|
+
{...props}
|
|
133
|
+
/>
|
|
134
|
+
</MenubarPortal>
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
type MenubarItemProps = ComponentProps<typeof MenubarPrimitive.Item> & {
|
|
139
|
+
inset?: boolean;
|
|
140
|
+
variant?: "default" | "destructive";
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export function MenubarItem({
|
|
144
|
+
className,
|
|
145
|
+
inset,
|
|
146
|
+
variant = "default",
|
|
147
|
+
...props
|
|
148
|
+
}: MenubarItemProps) {
|
|
149
|
+
return (
|
|
150
|
+
<MenubarPrimitive.Item
|
|
151
|
+
data-slot="menubar-item"
|
|
152
|
+
data-inset={inset}
|
|
153
|
+
data-variant={variant}
|
|
154
|
+
className={cn(
|
|
155
|
+
"relative flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled]:pointer-events-none data-[disabled]:opacity-50 data-[inset]:pl-8 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4 focus:bg-accent focus:text-accent-foreground data-[variant=destructive]:text-destructive data-[variant=destructive]:focus:bg-destructive/10 dark:data-[variant=destructive]:focus:bg-destructive/20 data-[variant=destructive]:focus:text-destructive data-[variant=destructive]:*:[svg]:!text-destructive [&_svg:not([class*='text-'])]:text-muted-foreground",
|
|
156
|
+
className,
|
|
157
|
+
)}
|
|
158
|
+
{...props}
|
|
159
|
+
/>
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export function MenubarCheckboxItem({
|
|
164
|
+
className,
|
|
165
|
+
children,
|
|
166
|
+
checked,
|
|
167
|
+
...props
|
|
168
|
+
}: ComponentProps<typeof MenubarPrimitive.CheckboxItem>) {
|
|
169
|
+
return (
|
|
170
|
+
<MenubarPrimitive.CheckboxItem
|
|
171
|
+
data-slot="menubar-checkbox-item"
|
|
172
|
+
className={cn(
|
|
173
|
+
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
|
174
|
+
className,
|
|
175
|
+
)}
|
|
176
|
+
checked={checked}
|
|
177
|
+
{...props}
|
|
178
|
+
>
|
|
179
|
+
<span className="absolute start-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
180
|
+
<MenubarPrimitive.ItemIndicator>
|
|
181
|
+
<Check className="h-4 w-4" />
|
|
182
|
+
</MenubarPrimitive.ItemIndicator>
|
|
183
|
+
</span>
|
|
184
|
+
{children}
|
|
185
|
+
</MenubarPrimitive.CheckboxItem>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
export function MenubarRadioItem({
|
|
190
|
+
className,
|
|
191
|
+
children,
|
|
192
|
+
...props
|
|
193
|
+
}: ComponentProps<typeof MenubarPrimitive.RadioItem>) {
|
|
194
|
+
return (
|
|
195
|
+
<MenubarPrimitive.RadioItem
|
|
196
|
+
data-slot="menubar-radio-item"
|
|
197
|
+
className={cn(
|
|
198
|
+
"relative flex cursor-pointer select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
|
|
199
|
+
className,
|
|
200
|
+
)}
|
|
201
|
+
{...props}
|
|
202
|
+
>
|
|
203
|
+
<span className="absolute start-2 flex h-3.5 w-3.5 items-center justify-center">
|
|
204
|
+
<MenubarPrimitive.ItemIndicator>
|
|
205
|
+
<Dot className="h-4 w-4 fill-current" />
|
|
206
|
+
</MenubarPrimitive.ItemIndicator>
|
|
207
|
+
</span>
|
|
208
|
+
{children}
|
|
209
|
+
</MenubarPrimitive.RadioItem>
|
|
210
|
+
);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
type MenubarLabelProps = ComponentProps<typeof MenubarPrimitive.Label> & {
|
|
214
|
+
inset?: boolean;
|
|
215
|
+
};
|
|
216
|
+
|
|
217
|
+
export function MenubarLabel({
|
|
218
|
+
className,
|
|
219
|
+
inset,
|
|
220
|
+
...props
|
|
221
|
+
}: MenubarLabelProps) {
|
|
222
|
+
return (
|
|
223
|
+
<MenubarPrimitive.Label
|
|
224
|
+
data-slot="menubar-label"
|
|
225
|
+
className={cn(
|
|
226
|
+
"px-2 py-1.5 text-sm font-semibold",
|
|
227
|
+
inset && "ps-8",
|
|
228
|
+
className,
|
|
229
|
+
)}
|
|
230
|
+
{...props}
|
|
231
|
+
/>
|
|
232
|
+
);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function MenubarSeparator({
|
|
236
|
+
className,
|
|
237
|
+
...props
|
|
238
|
+
}: ComponentProps<typeof MenubarPrimitive.Separator>) {
|
|
239
|
+
return (
|
|
240
|
+
<MenubarPrimitive.Separator
|
|
241
|
+
data-slot="menubar-separator"
|
|
242
|
+
className={cn("-mx-1 my-1 h-px bg-muted", className)}
|
|
243
|
+
{...props}
|
|
244
|
+
/>
|
|
245
|
+
);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
export function MenubarShortcut({
|
|
249
|
+
className,
|
|
250
|
+
...props
|
|
251
|
+
}: ComponentProps<"span">) {
|
|
252
|
+
return (
|
|
253
|
+
<span
|
|
254
|
+
data-slot="menubar-shortcut"
|
|
255
|
+
className={cn(
|
|
256
|
+
"ms-auto text-xs tracking-widest text-muted-foreground",
|
|
257
|
+
className,
|
|
258
|
+
)}
|
|
259
|
+
{...props}
|
|
260
|
+
/>
|
|
261
|
+
);
|
|
262
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import * as NavigationMenuPrimitive from "@radix-ui/react-navigation-menu";
|
|
2
|
+
import { cva } from "class-variance-authority";
|
|
3
|
+
import { ChevronDown } from "lucide-react";
|
|
4
|
+
|
|
5
|
+
import type { ComponentProps } from "react";
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../utils";
|
|
8
|
+
|
|
9
|
+
type NavigationMenuProps = ComponentProps<
|
|
10
|
+
typeof NavigationMenuPrimitive.Root
|
|
11
|
+
> & {
|
|
12
|
+
viewport?: boolean;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
export function NavigationMenu({
|
|
16
|
+
className,
|
|
17
|
+
children,
|
|
18
|
+
viewport = true,
|
|
19
|
+
...props
|
|
20
|
+
}: NavigationMenuProps) {
|
|
21
|
+
return (
|
|
22
|
+
<NavigationMenuPrimitive.Root
|
|
23
|
+
data-slot="navigation-menu"
|
|
24
|
+
data-viewport={viewport}
|
|
25
|
+
className={cn(
|
|
26
|
+
"group/navigation-menu relative flex max-w-max flex-1 items-center justify-center",
|
|
27
|
+
className,
|
|
28
|
+
)}
|
|
29
|
+
{...props}
|
|
30
|
+
>
|
|
31
|
+
{children}
|
|
32
|
+
{viewport && <NavigationMenuViewport />}
|
|
33
|
+
</NavigationMenuPrimitive.Root>
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export function NavigationMenuList({
|
|
38
|
+
className,
|
|
39
|
+
...props
|
|
40
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.List>) {
|
|
41
|
+
return (
|
|
42
|
+
<NavigationMenuPrimitive.List
|
|
43
|
+
data-slot="navigation-menu-list"
|
|
44
|
+
className={cn(
|
|
45
|
+
"group flex flex-1 list-none items-center justify-center gap-1",
|
|
46
|
+
className,
|
|
47
|
+
)}
|
|
48
|
+
{...props}
|
|
49
|
+
/>
|
|
50
|
+
);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export function NavigationMenuItem({
|
|
54
|
+
className,
|
|
55
|
+
...props
|
|
56
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.Item>) {
|
|
57
|
+
return (
|
|
58
|
+
<NavigationMenuPrimitive.Item
|
|
59
|
+
data-slot="navigation-menu-item"
|
|
60
|
+
className={cn("relative", className)}
|
|
61
|
+
{...props}
|
|
62
|
+
/>
|
|
63
|
+
);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export const navigationMenuTriggerStyle = cva(
|
|
67
|
+
"group cursor-pointer inline-flex h-9 w-max items-center justify-center rounded-md bg-background px-4 py-2 text-sm font-medium hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground disabled:pointer-events-none disabled:opacity-50 data-[state=open]:hover:bg-accent data-[state=open]:text-accent-foreground data-[state=open]:focus:bg-accent data-[state=open]:bg-accent/50 focus-visible:ring-ring/50 outline-none transition-[color,box-shadow] focus-visible:ring-[3px] focus-visible:outline-1",
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
export function NavigationMenuTrigger({
|
|
71
|
+
className,
|
|
72
|
+
children,
|
|
73
|
+
...props
|
|
74
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.Trigger>) {
|
|
75
|
+
return (
|
|
76
|
+
<NavigationMenuPrimitive.Trigger
|
|
77
|
+
data-slot="navigation-menu-trigger"
|
|
78
|
+
className={cn(navigationMenuTriggerStyle(), "group", className)}
|
|
79
|
+
{...props}
|
|
80
|
+
>
|
|
81
|
+
{children}{" "}
|
|
82
|
+
<ChevronDown
|
|
83
|
+
className="relative top-[1px] ms-1 size-3 transition duration-300 group-data-[state=open]:rotate-180"
|
|
84
|
+
aria-hidden="true"
|
|
85
|
+
/>
|
|
86
|
+
</NavigationMenuPrimitive.Trigger>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function NavigationMenuContent({
|
|
91
|
+
className,
|
|
92
|
+
...props
|
|
93
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.Content>) {
|
|
94
|
+
return (
|
|
95
|
+
<NavigationMenuPrimitive.Content
|
|
96
|
+
data-slot="navigation-menu-content"
|
|
97
|
+
className={cn(
|
|
98
|
+
"data-[motion^=from-]:animate-in data-[motion^=to-]:animate-out data-[motion^=from-]:fade-in data-[motion^=to-]:fade-out data-[motion=from-end]:slide-in-from-right-52 data-[motion=from-start]:slide-in-from-left-52 data-[motion=to-end]:slide-out-to-right-52 data-[motion=to-start]:slide-out-to-left-52 top-0 left-0 w-full p-2 pr-2.5 md:absolute md:w-auto",
|
|
99
|
+
"group-data-[viewport=false]/navigation-menu:bg-popover group-data-[viewport=false]/navigation-menu:text-popover-foreground group-data-[viewport=false]/navigation-menu:data-[state=open]:animate-in group-data-[viewport=false]/navigation-menu:data-[state=closed]:animate-out group-data-[viewport=false]/navigation-menu:data-[state=closed]:zoom-out-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:zoom-in-95 group-data-[viewport=false]/navigation-menu:data-[state=open]:fade-in-0 group-data-[viewport=false]/navigation-menu:data-[state=closed]:fade-out-0 group-data-[viewport=false]/navigation-menu:top-full group-data-[viewport=false]/navigation-menu:mt-1.5 group-data-[viewport=false]/navigation-menu:overflow-hidden group-data-[viewport=false]/navigation-menu:rounded-md group-data-[viewport=false]/navigation-menu:border group-data-[viewport=false]/navigation-menu:shadow group-data-[viewport=false]/navigation-menu:duration-200 **:data-[slot=navigation-menu-link]:focus:ring-0 **:data-[slot=navigation-menu-link]:focus:outline-none",
|
|
100
|
+
className,
|
|
101
|
+
)}
|
|
102
|
+
{...props}
|
|
103
|
+
/>
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function NavigationMenuLink({
|
|
108
|
+
className,
|
|
109
|
+
...props
|
|
110
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.Link>) {
|
|
111
|
+
return (
|
|
112
|
+
<NavigationMenuPrimitive.Link
|
|
113
|
+
data-slot="navigation-menu-link"
|
|
114
|
+
className={cn(
|
|
115
|
+
"data-[active=true]:focus:bg-accent data-[active=true]:hover:bg-accent data-[active=true]:bg-accent/50 data-[active=true]:text-accent-foreground hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground focus-visible:ring-ring/50 [&_svg:not([class*='text-'])]:text-muted-foreground flex flex-col gap-1 rounded-sm p-2 text-sm transition-all outline-none focus-visible:ring-[3px] focus-visible:outline-1 [&_svg:not([class*='size-'])]:size-4",
|
|
116
|
+
className,
|
|
117
|
+
)}
|
|
118
|
+
{...props}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function NavigationMenuViewport({
|
|
124
|
+
className,
|
|
125
|
+
...props
|
|
126
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.Viewport>) {
|
|
127
|
+
return (
|
|
128
|
+
<div className={cn("absolute start-0 top-full flex justify-center")}>
|
|
129
|
+
<NavigationMenuPrimitive.Viewport
|
|
130
|
+
data-slot="navigation-menu-viewport"
|
|
131
|
+
className={cn(
|
|
132
|
+
"origin-top-center relative mt-1.5 h-[var(--radix-navigation-menu-viewport-height)] w-full overflow-hidden rounded-md border bg-popover text-popover-foreground shadow-sm data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-90 md:w-[var(--radix-navigation-menu-viewport-width)]",
|
|
133
|
+
className,
|
|
134
|
+
)}
|
|
135
|
+
{...props}
|
|
136
|
+
/>
|
|
137
|
+
</div>
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function NavigationMenuIndicator({
|
|
142
|
+
className,
|
|
143
|
+
...props
|
|
144
|
+
}: ComponentProps<typeof NavigationMenuPrimitive.Indicator>) {
|
|
145
|
+
return (
|
|
146
|
+
<NavigationMenuPrimitive.Indicator
|
|
147
|
+
data-slot="navigation-menu-indicator"
|
|
148
|
+
className={cn(
|
|
149
|
+
"top-full z-1 flex h-1.5 items-end justify-center overflow-hidden data-[state=visible]:animate-in data-[state=hidden]:animate-out data-[state=hidden]:fade-out data-[state=visible]:fade-in",
|
|
150
|
+
className,
|
|
151
|
+
)}
|
|
152
|
+
{...props}
|
|
153
|
+
>
|
|
154
|
+
<div className="relative top-[60%] h-2 w-2 rotate-45 rounded-te-sm bg-border shadow-md" />
|
|
155
|
+
</NavigationMenuPrimitive.Indicator>
|
|
156
|
+
);
|
|
157
|
+
}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import Link from "next/link";
|
|
2
|
+
import { ChevronLeft, ChevronRight, MoreHorizontal } from "lucide-react";
|
|
3
|
+
|
|
4
|
+
import type { Button } from "./button";
|
|
5
|
+
import type { ComponentProps } from "react";
|
|
6
|
+
|
|
7
|
+
import { cn } from "../../utils";
|
|
8
|
+
|
|
9
|
+
import { buttonVariants } from "./button";
|
|
10
|
+
|
|
11
|
+
export function Pagination({ className, ...props }: ComponentProps<"nav">) {
|
|
12
|
+
return (
|
|
13
|
+
<nav
|
|
14
|
+
data-slot="pagination"
|
|
15
|
+
role="navigation"
|
|
16
|
+
className={cn("mx-auto flex w-full justify-center", className)}
|
|
17
|
+
aria-label="pagination"
|
|
18
|
+
{...props}
|
|
19
|
+
/>
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function PaginationContent({
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: ComponentProps<"ul">) {
|
|
27
|
+
return (
|
|
28
|
+
<ul
|
|
29
|
+
data-slot="pagination-content"
|
|
30
|
+
className={cn("flex flex-row items-center gap-1", className)}
|
|
31
|
+
{...props}
|
|
32
|
+
/>
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function PaginationItem({ ...props }: ComponentProps<"li">) {
|
|
37
|
+
return <li data-slot="pagination-item" {...props} />;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export type PaginationLinkProps = {
|
|
41
|
+
isActive?: boolean;
|
|
42
|
+
} & Pick<ComponentProps<typeof Button>, "size"> &
|
|
43
|
+
ComponentProps<typeof Link>;
|
|
44
|
+
|
|
45
|
+
export function PaginationLink({
|
|
46
|
+
className,
|
|
47
|
+
isActive,
|
|
48
|
+
size = "icon",
|
|
49
|
+
href = "",
|
|
50
|
+
...props
|
|
51
|
+
}: PaginationLinkProps) {
|
|
52
|
+
return (
|
|
53
|
+
<Link
|
|
54
|
+
data-slot="pagination-link"
|
|
55
|
+
className={cn(
|
|
56
|
+
buttonVariants({
|
|
57
|
+
variant: isActive ? "outline" : "ghost",
|
|
58
|
+
size,
|
|
59
|
+
}),
|
|
60
|
+
className,
|
|
61
|
+
)}
|
|
62
|
+
href={href}
|
|
63
|
+
aria-current={isActive ? "page" : undefined}
|
|
64
|
+
{...props}
|
|
65
|
+
/>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export function PaginationPrevious({
|
|
70
|
+
className,
|
|
71
|
+
...props
|
|
72
|
+
}: ComponentProps<typeof PaginationLink>) {
|
|
73
|
+
return (
|
|
74
|
+
<PaginationLink
|
|
75
|
+
size="default"
|
|
76
|
+
className={cn("gap-1 ps-2.5", className)}
|
|
77
|
+
aria-label="Go to previous page"
|
|
78
|
+
{...props}
|
|
79
|
+
>
|
|
80
|
+
<ChevronLeft className="h-4 w-4 rtl:-scale-100" />
|
|
81
|
+
<span>Previous</span>
|
|
82
|
+
</PaginationLink>
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export function PaginationNext({
|
|
87
|
+
className,
|
|
88
|
+
...props
|
|
89
|
+
}: ComponentProps<typeof PaginationLink>) {
|
|
90
|
+
return (
|
|
91
|
+
<PaginationLink
|
|
92
|
+
size="default"
|
|
93
|
+
className={cn("gap-1 pe-2.5", className)}
|
|
94
|
+
aria-label="Go to next page"
|
|
95
|
+
{...props}
|
|
96
|
+
>
|
|
97
|
+
<span>Next</span>
|
|
98
|
+
<ChevronRight className="h-4 w-4 rtl:-scale-100" />
|
|
99
|
+
</PaginationLink>
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export function PaginationEllipsis({
|
|
104
|
+
className,
|
|
105
|
+
...props
|
|
106
|
+
}: ComponentProps<"span">) {
|
|
107
|
+
return (
|
|
108
|
+
<span
|
|
109
|
+
data-slot="pagination-ellipsis"
|
|
110
|
+
className={cn("flex h-9 w-9 items-center justify-center", className)}
|
|
111
|
+
aria-label="More pages"
|
|
112
|
+
aria-hidden
|
|
113
|
+
{...props}
|
|
114
|
+
>
|
|
115
|
+
<MoreHorizontal className="h-4 w-4" />
|
|
116
|
+
</span>
|
|
117
|
+
);
|
|
118
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import * as React from "react";
|
|
4
|
+
import type { ComponentProps } from "react";
|
|
5
|
+
import * as PopoverPrimitive from "@radix-ui/react-popover";
|
|
6
|
+
import { cn } from "../../utils";
|
|
7
|
+
|
|
8
|
+
export function Popover({
|
|
9
|
+
...props
|
|
10
|
+
}: ComponentProps<typeof PopoverPrimitive.Root>) {
|
|
11
|
+
return <PopoverPrimitive.Root data-slot="popover" {...props} />;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function PopoverTrigger({
|
|
15
|
+
className,
|
|
16
|
+
...props
|
|
17
|
+
}: ComponentProps<typeof PopoverPrimitive.Trigger>) {
|
|
18
|
+
return (
|
|
19
|
+
<PopoverPrimitive.Trigger
|
|
20
|
+
data-slot="popover-trigger"
|
|
21
|
+
className={cn("cursor-pointer", className)}
|
|
22
|
+
{...props}
|
|
23
|
+
/>
|
|
24
|
+
);
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function PopoverAnchor({
|
|
28
|
+
...props
|
|
29
|
+
}: ComponentProps<typeof PopoverPrimitive.Anchor>) {
|
|
30
|
+
return <PopoverPrimitive.Anchor data-slot="popover-anchor" {...props} />;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export function PopoverContent({
|
|
34
|
+
className,
|
|
35
|
+
align = "center",
|
|
36
|
+
sideOffset = 4,
|
|
37
|
+
container,
|
|
38
|
+
...props
|
|
39
|
+
}: ComponentProps<typeof PopoverPrimitive.Content> & {
|
|
40
|
+
container?: HTMLElement;
|
|
41
|
+
}) {
|
|
42
|
+
return (
|
|
43
|
+
<PopoverPrimitive.Portal container={container}>
|
|
44
|
+
<PopoverPrimitive.Content
|
|
45
|
+
data-slot="popover-content"
|
|
46
|
+
align={align}
|
|
47
|
+
sideOffset={sideOffset}
|
|
48
|
+
className={cn(
|
|
49
|
+
"z-50 w-72 rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-hidden data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
|
|
50
|
+
className,
|
|
51
|
+
)}
|
|
52
|
+
{...props}
|
|
53
|
+
/>
|
|
54
|
+
</PopoverPrimitive.Portal>
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
import { useCallback } from "react";
|
|
4
|
+
import type { LinkProps } from "next/link";
|
|
5
|
+
import Link from "next/link";
|
|
6
|
+
|
|
7
|
+
import { usePrefetch } from "../../hooks";
|
|
8
|
+
|
|
9
|
+
interface PrefetchLinkProps extends Omit<LinkProps, "href"> {
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
href: string | LinkProps["href"];
|
|
12
|
+
className?: string;
|
|
13
|
+
crudEntity?: string; // If this is a CRUD link, provide entity name
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Link component with automatic prefetching for CRUD pages
|
|
18
|
+
* Prefetches both the route and the API endpoint when user hovers
|
|
19
|
+
*/
|
|
20
|
+
export function PrefetchLink({
|
|
21
|
+
children,
|
|
22
|
+
crudEntity,
|
|
23
|
+
href,
|
|
24
|
+
className,
|
|
25
|
+
...props
|
|
26
|
+
}: PrefetchLinkProps) {
|
|
27
|
+
const { prefetchRoute, prefetchCrudPage } = usePrefetch();
|
|
28
|
+
|
|
29
|
+
const handleMouseEnter = useCallback(() => {
|
|
30
|
+
if (typeof href === "string") {
|
|
31
|
+
// Always prefetch the route
|
|
32
|
+
prefetchRoute(href);
|
|
33
|
+
|
|
34
|
+
// If this is a CRUD link, also prefetch the API endpoint
|
|
35
|
+
if (crudEntity) {
|
|
36
|
+
// Use convention: /api/[entity]
|
|
37
|
+
prefetchCrudPage(crudEntity, `/api/${crudEntity}`);
|
|
38
|
+
} else {
|
|
39
|
+
// Try to extract entity name from href (handle localized paths like /en/crud/entity)
|
|
40
|
+
const crudMatch = href.match(/\/(?:[a-z]{2}\/)?crud\/([^/]+)/);
|
|
41
|
+
if (crudMatch) {
|
|
42
|
+
const entity = crudMatch[1];
|
|
43
|
+
// Use convention: /api/[entity]
|
|
44
|
+
prefetchCrudPage(entity, `/api/${entity}`);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}, [href, crudEntity, prefetchRoute, prefetchCrudPage]);
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<Link
|
|
52
|
+
href={href}
|
|
53
|
+
className={className}
|
|
54
|
+
onMouseEnter={handleMouseEnter}
|
|
55
|
+
{...props}
|
|
56
|
+
>
|
|
57
|
+
{children as any}
|
|
58
|
+
</Link>
|
|
59
|
+
);
|
|
60
|
+
}
|