@object-ui/components 0.3.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +34 -0
- package/CHANGELOG.md +13 -0
- package/README.md +13 -0
- package/dist/index.css +1 -1
- package/dist/index.js +36430 -25529
- package/dist/index.umd.cjs +53 -32
- package/dist/src/SchemaRenderer.d.ts +3 -0
- package/dist/src/custom/action-param-dialog.d.ts +21 -0
- package/dist/src/{ui → custom}/button-group.d.ts +1 -1
- package/dist/src/custom/field.d.ts +19 -0
- package/dist/src/custom/index.d.ts +14 -0
- package/dist/src/custom/input-group.d.ts +14 -0
- package/dist/src/{ui → custom}/item.d.ts +1 -1
- package/dist/src/custom/native-select.d.ts +12 -0
- package/dist/src/custom/navigation-overlay.d.ts +50 -0
- package/dist/src/custom/sort-builder.d.ts +22 -0
- package/dist/src/index.d.ts +2 -0
- package/dist/src/renderers/action/action-button.d.ts +11 -0
- package/dist/src/renderers/action/action-group.d.ts +25 -0
- package/dist/src/renderers/action/action-icon.d.ts +10 -0
- package/dist/src/renderers/action/action-menu.d.ts +19 -0
- package/dist/src/renderers/action/index.d.ts +0 -0
- package/dist/src/renderers/action/resolve-icon.d.ts +6 -0
- package/dist/src/renderers/data-display/table.d.ts +1 -1
- package/dist/src/renderers/layout/page.d.ts +1 -1
- package/dist/src/renderers/placeholders.d.ts +1 -1
- package/dist/src/ui/accordion.d.ts +4 -4
- package/dist/src/ui/alert-dialog.d.ts +17 -11
- package/dist/src/ui/alert.d.ts +4 -5
- package/dist/src/ui/aspect-ratio.d.ts +1 -1
- package/dist/src/ui/avatar.d.ts +3 -3
- package/dist/src/ui/badge.d.ts +3 -3
- package/dist/src/ui/breadcrumb.d.ts +16 -8
- package/dist/src/ui/calendar.d.ts +7 -7
- package/dist/src/ui/card.d.ts +7 -8
- package/dist/src/ui/carousel.d.ts +5 -6
- package/dist/src/ui/chart.d.ts +62 -0
- package/dist/src/ui/checkbox.d.ts +1 -1
- package/dist/src/ui/collapsible.d.ts +3 -3
- package/dist/src/ui/command.d.ts +78 -16
- package/dist/src/ui/context-menu.d.ts +14 -12
- package/dist/src/ui/dialog.d.ts +17 -13
- package/dist/src/ui/drawer.d.ts +19 -10
- package/dist/src/ui/dropdown-menu.d.ts +20 -18
- package/dist/src/ui/form.d.ts +6 -7
- package/dist/src/ui/hover-card.d.ts +3 -3
- package/dist/src/ui/index.d.ts +2 -8
- package/dist/src/ui/input-otp.d.ts +30 -7
- package/dist/src/ui/label.d.ts +2 -1
- package/dist/src/ui/menubar.d.ts +19 -17
- package/dist/src/ui/navigation-menu.d.ts +9 -11
- package/dist/src/ui/pagination.d.ts +25 -10
- package/dist/src/ui/popover.d.ts +4 -5
- package/dist/src/ui/progress.d.ts +1 -1
- package/dist/src/ui/radio-group.d.ts +2 -2
- package/dist/src/ui/resizable.d.ts +5 -8
- package/dist/src/ui/scroll-area.d.ts +2 -2
- package/dist/src/ui/select.d.ts +11 -13
- package/dist/src/ui/sheet.d.ts +23 -11
- package/dist/src/ui/sidebar.d.ts +27 -29
- package/dist/src/ui/skeleton.d.ts +1 -1
- package/dist/src/ui/slider.d.ts +1 -1
- package/dist/src/ui/sonner.d.ts +2 -1
- package/dist/src/ui/switch.d.ts +2 -2
- package/dist/src/ui/tabs.d.ts +1 -1
- package/dist/src/ui/textarea.d.ts +1 -1
- package/dist/src/ui/toast.d.ts +22 -0
- package/dist/src/ui/toggle-group.d.ts +8 -3
- package/dist/src/ui/toggle.d.ts +4 -1
- package/dist/src/ui/tooltip.d.ts +4 -4
- package/dist/src/ui/typography.d.ts +21 -0
- package/package.json +20 -9
- package/shadcn-components.json +52 -47
- package/src/SchemaRenderer.tsx +28 -0
- package/src/__tests__/PageRendererRegions.test.tsx +668 -0
- package/src/__tests__/Registry.test.ts +21 -0
- package/src/__tests__/basic-renderers.test.tsx +1 -1
- package/src/__tests__/complex-disclosure-renderers.test.tsx +3 -2
- package/src/__tests__/compliance.test.tsx +72 -0
- package/src/__tests__/feedback-overlay-renderers.test.tsx +1 -1
- package/src/__tests__/form-renderers.test.tsx +1 -1
- package/src/__tests__/layout-data-renderers.test.tsx +1 -1
- package/src/__tests__/navigation-overlay.test.tsx +273 -0
- package/src/__tests__/view-compliance.test.tsx +153 -0
- package/src/custom/action-param-dialog.tsx +264 -0
- package/src/{ui → custom}/button-group.tsx +1 -1
- package/src/{ui → custom}/combobox.tsx +3 -3
- package/src/{ui → custom}/date-picker.tsx +3 -3
- package/src/custom/field.tsx +81 -0
- package/src/{ui → custom}/filter-builder.tsx +3 -3
- package/src/custom/index.ts +14 -0
- package/src/custom/input-group.tsx +53 -0
- package/src/{ui → custom}/item.tsx +1 -1
- package/src/custom/native-select.tsx +33 -0
- package/src/custom/navigation-overlay.tsx +296 -0
- package/src/custom/sort-builder.tsx +129 -0
- package/src/index.css +20 -1
- package/src/index.ts +2 -0
- package/src/renderers/action/action-button.tsx +147 -0
- package/src/renderers/action/action-group.tsx +270 -0
- package/src/renderers/action/action-icon.tsx +150 -0
- package/src/renderers/action/action-menu.tsx +203 -0
- package/src/renderers/action/index.ts +18 -0
- package/src/renderers/action/resolve-icon.ts +35 -0
- package/src/renderers/basic/button-group.tsx +1 -0
- package/src/renderers/basic/div.tsx +12 -1
- package/src/renderers/basic/html.tsx +1 -0
- package/src/renderers/basic/icon.tsx +1 -0
- package/src/renderers/basic/image.tsx +1 -0
- package/src/renderers/basic/navigation-menu.tsx +1 -0
- package/src/renderers/basic/pagination.tsx +31 -4
- package/src/renderers/basic/separator.tsx +1 -0
- package/src/renderers/basic/span.tsx +12 -1
- package/src/renderers/basic/text.tsx +4 -2
- package/src/renderers/complex/__tests__/data-table-batch-editing.test.tsx +275 -0
- package/src/renderers/complex/__tests__/data-table-cell-renderer.test.tsx +120 -0
- package/src/renderers/complex/__tests__/data-table-editing.test.tsx +221 -0
- package/src/renderers/complex/carousel.tsx +1 -0
- package/src/renderers/complex/data-table.tsx +355 -95
- package/src/renderers/complex/filter-builder.tsx +2 -1
- package/src/renderers/complex/resizable.tsx +2 -1
- package/src/renderers/complex/scroll-area.tsx +25 -7
- package/src/renderers/complex/table.tsx +1 -0
- package/src/renderers/data-display/alert.tsx +1 -0
- package/src/renderers/data-display/avatar.tsx +1 -0
- package/src/renderers/data-display/badge.tsx +1 -0
- package/src/renderers/data-display/breadcrumb.tsx +1 -0
- package/src/renderers/data-display/kbd.tsx +1 -0
- package/src/renderers/data-display/list.tsx +21 -49
- package/src/renderers/data-display/statistic.tsx +21 -5
- package/src/renderers/data-display/table.tsx +21 -11
- package/src/renderers/data-display/tree-view.tsx +7 -1
- package/src/renderers/disclosure/accordion.tsx +1 -0
- package/src/renderers/disclosure/collapsible.tsx +1 -0
- package/src/renderers/disclosure/toggle-group.tsx +2 -0
- package/src/renderers/feedback/empty.tsx +1 -0
- package/src/renderers/feedback/loading.tsx +2 -1
- package/src/renderers/feedback/progress.tsx +1 -0
- package/src/renderers/feedback/skeleton.tsx +1 -0
- package/src/renderers/feedback/sonner.tsx +1 -0
- package/src/renderers/feedback/spinner.tsx +1 -0
- package/src/renderers/feedback/toast.tsx +1 -0
- package/src/renderers/feedback/toaster.tsx +1 -0
- package/src/renderers/form/button.tsx +35 -1
- package/src/renderers/form/calendar.tsx +1 -0
- package/src/renderers/form/checkbox.tsx +38 -16
- package/src/renderers/form/combobox.tsx +2 -1
- package/src/renderers/form/command.tsx +1 -0
- package/src/renderers/form/date-picker.tsx +1 -0
- package/src/renderers/form/file-upload.tsx +1 -0
- package/src/renderers/form/form.tsx +115 -19
- package/src/renderers/form/input-otp.tsx +1 -0
- package/src/renderers/form/input.tsx +3 -0
- package/src/renderers/form/label.tsx +1 -0
- package/src/renderers/form/radio-group.tsx +1 -0
- package/src/renderers/form/select.tsx +35 -15
- package/src/renderers/form/slider.tsx +1 -0
- package/src/renderers/form/switch.tsx +1 -0
- package/src/renderers/form/textarea.tsx +50 -27
- package/src/renderers/form/toggle.tsx +3 -45
- package/src/renderers/index.ts +1 -0
- package/src/renderers/layout/aspect-ratio.tsx +2 -1
- package/src/renderers/layout/card.tsx +10 -2
- package/src/renderers/layout/container.tsx +1 -0
- package/src/renderers/layout/flex.tsx +1 -0
- package/src/renderers/layout/grid.tsx +23 -8
- package/src/renderers/layout/page.tsx +433 -57
- package/src/renderers/layout/semantic.tsx +1 -0
- package/src/renderers/layout/stack.tsx +2 -1
- package/src/renderers/layout/tabs.tsx +43 -17
- package/src/renderers/navigation/header-bar.tsx +1 -0
- package/src/renderers/navigation/sidebar.tsx +11 -0
- package/src/renderers/overlay/alert-dialog.tsx +1 -0
- package/src/renderers/overlay/context-menu.tsx +1 -0
- package/src/renderers/overlay/dialog.tsx +1 -0
- package/src/renderers/overlay/drawer.tsx +1 -0
- package/src/renderers/overlay/dropdown-menu.tsx +1 -0
- package/src/renderers/overlay/hover-card.tsx +1 -0
- package/src/renderers/overlay/menubar.tsx +1 -0
- package/src/renderers/overlay/popover.tsx +1 -0
- package/src/renderers/overlay/sheet.tsx +1 -0
- package/src/renderers/overlay/tooltip.tsx +1 -0
- package/src/renderers/placeholders.tsx +4 -4
- package/src/stories/CRMApp.stories.tsx +706 -0
- package/src/stories/Guide.mdx +55 -0
- package/src/stories/Introduction.mdx +61 -0
- package/src/stories/MockedData.stories.tsx +121 -0
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +1 -0
- package/src/stories/assets/addon-library.png +0 -0
- package/src/stories/assets/assets.png +0 -0
- package/src/stories/assets/avif-test-image.avif +0 -0
- package/src/stories/assets/context.png +0 -0
- package/src/stories/assets/discord.svg +1 -0
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +1 -0
- package/src/stories/assets/share.png +0 -0
- package/src/stories/assets/styling.png +0 -0
- package/src/stories/assets/testing.png +0 -0
- package/src/stories/assets/theming.png +0 -0
- package/src/stories/assets/tutorials.svg +1 -0
- package/src/stories/assets/youtube.svg +1 -0
- package/src/stories/button.css +30 -0
- package/src/stories/header.css +32 -0
- package/src/stories/page.css +68 -0
- package/src/stories-json/accordion.stories.tsx +43 -0
- package/src/stories-json/aggrid.stories.tsx +103 -0
- package/src/stories-json/alert.stories.tsx +39 -0
- package/src/stories-json/aspect-ratio.stories.tsx +34 -0
- package/src/stories-json/avatar.stories.tsx +38 -0
- package/src/stories-json/badge.stories.tsx +53 -0
- package/src/stories-json/breadcrumb.stories.tsx +30 -0
- package/src/stories-json/button-group.stories.tsx +43 -0
- package/src/stories-json/button.stories.tsx +73 -0
- package/src/stories-json/calendar.stories.tsx +85 -0
- package/src/stories-json/card.stories.tsx +48 -0
- package/src/stories-json/carousel.stories.tsx +33 -0
- package/src/stories-json/charts.stories.tsx +195 -0
- package/src/stories-json/chatbot.stories.tsx +248 -0
- package/src/stories-json/code-editor.stories.tsx +92 -0
- package/src/stories-json/collapsible.stories.tsx +40 -0
- package/src/stories-json/controls.stories.tsx +36 -0
- package/src/stories-json/crm-live-data.stories.tsx +154 -0
- package/src/stories-json/dashboard.stories.tsx +318 -0
- package/src/stories-json/data-table.stories.tsx +136 -0
- package/src/stories-json/data_display_extras.stories.tsx +102 -0
- package/src/stories-json/date-picker.stories.tsx +28 -0
- package/src/stories-json/detail-view.stories.tsx +258 -0
- package/src/stories-json/dialog.stories.tsx +43 -0
- package/src/stories-json/feedback_extras.stories.tsx +40 -0
- package/src/stories-json/feedback_others.stories.tsx +46 -0
- package/src/stories-json/form-variants.stories.tsx +210 -0
- package/src/stories-json/form_advanced.stories.tsx +117 -0
- package/src/stories-json/form_extras.stories.tsx +123 -0
- package/src/stories-json/grid.stories.tsx +56 -0
- package/src/stories-json/icon.stories.tsx +36 -0
- package/src/stories-json/input.stories.tsx +52 -0
- package/src/stories-json/kanban.stories.tsx +295 -0
- package/src/stories-json/layout_extended.stories.tsx +76 -0
- package/src/stories-json/layout_flex.stories.tsx +107 -0
- package/src/stories-json/list-view.stories.tsx +97 -0
- package/src/stories-json/markdown.stories.tsx +129 -0
- package/src/stories-json/menus.stories.tsx +63 -0
- package/src/stories-json/metric-card.stories.tsx +143 -0
- package/src/stories-json/navigation-menu.stories.tsx +37 -0
- package/src/stories-json/object-aggrid-advanced.stories.tsx +389 -0
- package/src/stories-json/object-aggrid.stories.tsx +252 -0
- package/src/stories-json/object-form.stories.tsx +130 -0
- package/src/stories-json/object-gantt.stories.tsx +114 -0
- package/src/stories-json/object-grid.stories.tsx +315 -0
- package/src/stories-json/object-map.stories.tsx +116 -0
- package/src/stories-json/object-view.stories.tsx +118 -0
- package/src/stories-json/overlay_extras.stories.tsx +113 -0
- package/src/stories-json/overlay_others.stories.tsx +76 -0
- package/src/stories-json/page.stories.tsx +55 -0
- package/src/stories-json/reports.stories.tsx +163 -0
- package/src/stories-json/resizable.stories.tsx +44 -0
- package/src/stories-json/select.stories.tsx +34 -0
- package/src/stories-json/separator.stories.tsx +41 -0
- package/src/stories-json/sidebar.stories.tsx +147 -0
- package/src/stories-json/statistic.stories.tsx +44 -0
- package/src/stories-json/tabs.stories.tsx +51 -0
- package/src/stories-json/timeline.stories.tsx +188 -0
- package/src/stories-json/typography.stories.tsx +45 -0
- package/src/ui/accordion.tsx +47 -53
- package/src/ui/alert-dialog.tsx +103 -117
- package/src/ui/alert.tsx +35 -36
- package/src/ui/aspect-ratio.tsx +1 -5
- package/src/ui/avatar.tsx +41 -42
- package/src/ui/badge.tsx +6 -15
- package/src/ui/breadcrumb.tsx +81 -75
- package/src/ui/button.tsx +10 -11
- package/src/ui/calendar.tsx +178 -51
- package/src/ui/card.tsx +51 -110
- package/src/ui/carousel.tsx +136 -113
- package/src/ui/chart.tsx +367 -0
- package/src/ui/checkbox.tsx +20 -22
- package/src/ui/collapsible.tsx +5 -25
- package/src/ui/command.tsx +106 -135
- package/src/ui/context-menu.tsx +69 -116
- package/src/ui/dialog.tsx +94 -113
- package/src/ui/drawer.tsx +82 -99
- package/src/ui/dropdown-menu.tsx +134 -188
- package/src/ui/form.tsx +51 -40
- package/src/ui/hover-card.tsx +18 -33
- package/src/ui/index.ts +2 -8
- package/src/ui/input-otp.tsx +42 -52
- package/src/ui/input.tsx +13 -15
- package/src/ui/label.tsx +17 -15
- package/src/ui/menubar.tsx +188 -206
- package/src/ui/navigation-menu.tsx +96 -136
- package/src/ui/pagination.tsx +86 -96
- package/src/ui/popover.tsx +24 -41
- package/src/ui/progress.tsx +21 -22
- package/src/ui/radio-group.tsx +19 -20
- package/src/ui/resizable.tsx +32 -42
- package/src/ui/scroll-area.tsx +38 -48
- package/src/ui/select.tsx +129 -157
- package/src/ui/separator.tsx +2 -2
- package/src/ui/sheet.tsx +110 -107
- package/src/ui/sidebar.tsx +442 -408
- package/src/ui/skeleton.tsx +6 -11
- package/src/ui/slider.tsx +19 -54
- package/src/ui/sonner.tsx +19 -1
- package/src/ui/switch.tsx +19 -21
- package/src/ui/tabs.tsx +6 -37
- package/src/ui/textarea.tsx +8 -4
- package/src/ui/toast.tsx +137 -0
- package/src/ui/toggle-group.tsx +28 -37
- package/src/ui/toggle.tsx +19 -19
- package/src/ui/tooltip.tsx +21 -52
- package/src/ui/typography.tsx +85 -0
- package/tsconfig.json +1 -1
- package/vite.config.ts +9 -1
- package/vitest.config.ts +5 -0
- package/ISSUES_FOUND.md +0 -128
- /package/dist/src/{ui → custom}/combobox.d.ts +0 -0
- /package/dist/src/{ui → custom}/date-picker.d.ts +0 -0
- /package/dist/src/{ui → custom}/empty.d.ts +0 -0
- /package/dist/src/{ui → custom}/filter-builder.d.ts +0 -0
- /package/dist/src/{ui → custom}/kbd.d.ts +0 -0
- /package/dist/src/{ui → custom}/spinner.d.ts +0 -0
- /package/src/{ui → custom}/empty.tsx +0 -0
- /package/src/{ui → custom}/kbd.tsx +0 -0
- /package/src/{ui → custom}/spinner.tsx +0 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* NavigationOverlay
|
|
11
|
+
*
|
|
12
|
+
* A reusable component that renders record detail overlays based on
|
|
13
|
+
* ViewNavigationConfig mode. Supports drawer (Sheet), modal (Dialog),
|
|
14
|
+
* split (ResizablePanelGroup), and popover modes.
|
|
15
|
+
*
|
|
16
|
+
* Works in conjunction with useNavigationOverlay hook from @object-ui/react —
|
|
17
|
+
* the hook manages state while this component handles the visual presentation.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```tsx
|
|
21
|
+
* import { useNavigationOverlay } from '@object-ui/react';
|
|
22
|
+
* import { NavigationOverlay } from '@object-ui/components';
|
|
23
|
+
*
|
|
24
|
+
* const nav = useNavigationOverlay({
|
|
25
|
+
* navigation: schema.navigation,
|
|
26
|
+
* objectName: schema.objectName,
|
|
27
|
+
* });
|
|
28
|
+
*
|
|
29
|
+
* return (
|
|
30
|
+
* <>
|
|
31
|
+
* <DataTable onRowClick={nav.handleClick} />
|
|
32
|
+
* <NavigationOverlay {...nav} title="Record Detail">
|
|
33
|
+
* {(record) => <RecordDetail record={record} />}
|
|
34
|
+
* </NavigationOverlay>
|
|
35
|
+
* </>
|
|
36
|
+
* );
|
|
37
|
+
* ```
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
import React from 'react';
|
|
41
|
+
import { cn } from '../lib/utils';
|
|
42
|
+
import {
|
|
43
|
+
Sheet,
|
|
44
|
+
SheetContent,
|
|
45
|
+
SheetHeader,
|
|
46
|
+
SheetTitle,
|
|
47
|
+
SheetDescription,
|
|
48
|
+
} from '../ui/sheet';
|
|
49
|
+
import {
|
|
50
|
+
Dialog,
|
|
51
|
+
DialogContent,
|
|
52
|
+
DialogHeader,
|
|
53
|
+
DialogTitle,
|
|
54
|
+
DialogDescription,
|
|
55
|
+
} from '../ui/dialog';
|
|
56
|
+
import {
|
|
57
|
+
Popover,
|
|
58
|
+
PopoverContent,
|
|
59
|
+
PopoverTrigger,
|
|
60
|
+
} from '../ui/popover';
|
|
61
|
+
import {
|
|
62
|
+
ResizablePanelGroup,
|
|
63
|
+
ResizablePanel,
|
|
64
|
+
ResizableHandle,
|
|
65
|
+
} from '../ui/resizable';
|
|
66
|
+
|
|
67
|
+
/** Navigation mode type — matches ViewNavigationConfig.mode */
|
|
68
|
+
export type NavigationOverlayMode =
|
|
69
|
+
| 'page'
|
|
70
|
+
| 'drawer'
|
|
71
|
+
| 'modal'
|
|
72
|
+
| 'split'
|
|
73
|
+
| 'popover'
|
|
74
|
+
| 'new_window'
|
|
75
|
+
| 'none';
|
|
76
|
+
|
|
77
|
+
export interface NavigationOverlayProps {
|
|
78
|
+
/** Whether the overlay is open */
|
|
79
|
+
isOpen: boolean;
|
|
80
|
+
/** The selected record */
|
|
81
|
+
selectedRecord: Record<string, unknown> | null;
|
|
82
|
+
/** The navigation mode */
|
|
83
|
+
mode: NavigationOverlayMode;
|
|
84
|
+
/** Close the overlay */
|
|
85
|
+
close: () => void;
|
|
86
|
+
/** Set open state (for controlled Sheet/Dialog onOpenChange) */
|
|
87
|
+
setIsOpen: (open: boolean) => void;
|
|
88
|
+
/** Width for the overlay (drawer/modal/split) */
|
|
89
|
+
width?: string | number;
|
|
90
|
+
/** Whether navigation is an overlay mode */
|
|
91
|
+
isOverlay: boolean;
|
|
92
|
+
/** Title for the overlay header */
|
|
93
|
+
title?: string;
|
|
94
|
+
/** Description for the overlay header */
|
|
95
|
+
description?: string;
|
|
96
|
+
/** CSS class for the overlay container */
|
|
97
|
+
className?: string;
|
|
98
|
+
/**
|
|
99
|
+
* Render function for the overlay content.
|
|
100
|
+
* Receives the selected record.
|
|
101
|
+
*/
|
|
102
|
+
children: (record: Record<string, unknown>) => React.ReactNode;
|
|
103
|
+
/**
|
|
104
|
+
* The main content to wrap (for split mode only).
|
|
105
|
+
* In split mode, the main content is rendered in the left panel.
|
|
106
|
+
*/
|
|
107
|
+
mainContent?: React.ReactNode;
|
|
108
|
+
/**
|
|
109
|
+
* Popover trigger element (for popover mode).
|
|
110
|
+
*/
|
|
111
|
+
popoverTrigger?: React.ReactNode;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Resolve width to CSS-compatible value
|
|
116
|
+
*/
|
|
117
|
+
function resolveWidth(width: string | number | undefined): string | undefined {
|
|
118
|
+
if (width == null) return undefined;
|
|
119
|
+
if (typeof width === 'number') return `${width}px`;
|
|
120
|
+
return width;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Compute CSS style from NavigationConfig width
|
|
125
|
+
*/
|
|
126
|
+
function getWidthStyle(width: string | number | undefined): React.CSSProperties {
|
|
127
|
+
const resolved = resolveWidth(width);
|
|
128
|
+
if (!resolved) return {};
|
|
129
|
+
return { maxWidth: resolved, width: '100%' };
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* NavigationOverlay — renders record detail in the configured overlay mode.
|
|
134
|
+
*
|
|
135
|
+
* Supports:
|
|
136
|
+
* - **drawer**: Right-side Sheet panel
|
|
137
|
+
* - **modal**: Center Dialog overlay
|
|
138
|
+
* - **split**: Side-by-side ResizablePanelGroup
|
|
139
|
+
* - **popover**: Hoverable/clickable popover card
|
|
140
|
+
* - **page / new_window / none**: No overlay rendered (handled by hook)
|
|
141
|
+
*/
|
|
142
|
+
export const NavigationOverlay: React.FC<NavigationOverlayProps> = ({
|
|
143
|
+
isOpen,
|
|
144
|
+
selectedRecord,
|
|
145
|
+
mode,
|
|
146
|
+
close,
|
|
147
|
+
setIsOpen,
|
|
148
|
+
width,
|
|
149
|
+
title,
|
|
150
|
+
description,
|
|
151
|
+
className,
|
|
152
|
+
children,
|
|
153
|
+
mainContent,
|
|
154
|
+
popoverTrigger,
|
|
155
|
+
}) => {
|
|
156
|
+
// Non-overlay modes don't render anything
|
|
157
|
+
if (mode === 'page' || mode === 'new_window' || mode === 'none') {
|
|
158
|
+
return null;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
if (!selectedRecord) {
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
const widthStyle = getWidthStyle(width);
|
|
166
|
+
const resolvedTitle = title || 'Record Detail';
|
|
167
|
+
|
|
168
|
+
// --- Drawer Mode (Sheet) ---
|
|
169
|
+
if (mode === 'drawer') {
|
|
170
|
+
return (
|
|
171
|
+
<Sheet open={isOpen} onOpenChange={setIsOpen}>
|
|
172
|
+
<SheetContent
|
|
173
|
+
side="right"
|
|
174
|
+
className={cn('w-full sm:max-w-2xl overflow-y-auto', className)}
|
|
175
|
+
style={widthStyle}
|
|
176
|
+
>
|
|
177
|
+
<SheetHeader>
|
|
178
|
+
<SheetTitle>{resolvedTitle}</SheetTitle>
|
|
179
|
+
{description && <SheetDescription>{description}</SheetDescription>}
|
|
180
|
+
</SheetHeader>
|
|
181
|
+
<div className="mt-4">
|
|
182
|
+
{children(selectedRecord)}
|
|
183
|
+
</div>
|
|
184
|
+
</SheetContent>
|
|
185
|
+
</Sheet>
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// --- Modal Mode (Dialog) ---
|
|
190
|
+
if (mode === 'modal') {
|
|
191
|
+
return (
|
|
192
|
+
<Dialog open={isOpen} onOpenChange={setIsOpen}>
|
|
193
|
+
<DialogContent
|
|
194
|
+
className={cn('max-w-2xl max-h-[90vh] overflow-y-auto', className)}
|
|
195
|
+
style={widthStyle}
|
|
196
|
+
>
|
|
197
|
+
<DialogHeader>
|
|
198
|
+
<DialogTitle>{resolvedTitle}</DialogTitle>
|
|
199
|
+
{description && <DialogDescription>{description}</DialogDescription>}
|
|
200
|
+
</DialogHeader>
|
|
201
|
+
<div className="mt-4">
|
|
202
|
+
{children(selectedRecord)}
|
|
203
|
+
</div>
|
|
204
|
+
</DialogContent>
|
|
205
|
+
</Dialog>
|
|
206
|
+
);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
// --- Split Mode (Resizable Panels) ---
|
|
210
|
+
if (mode === 'split') {
|
|
211
|
+
if (!isOpen || !mainContent) {
|
|
212
|
+
return null;
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Calculate panel sizes based on width config
|
|
216
|
+
const detailPercent = width
|
|
217
|
+
? typeof width === 'number'
|
|
218
|
+
? Math.min(70, Math.max(20, (width / 1200) * 100))
|
|
219
|
+
: 40
|
|
220
|
+
: 40;
|
|
221
|
+
const mainPercent = 100 - detailPercent;
|
|
222
|
+
|
|
223
|
+
// Cast needed: ResizablePanelGroup has correct runtime behavior but
|
|
224
|
+
// vite-plugin-dts may not resolve the direction prop type correctly
|
|
225
|
+
const PanelGroup = ResizablePanelGroup as React.FC<any>;
|
|
226
|
+
|
|
227
|
+
return (
|
|
228
|
+
<PanelGroup direction="horizontal" className={cn('h-full', className)}>
|
|
229
|
+
<ResizablePanel defaultSize={mainPercent} minSize={30}>
|
|
230
|
+
{mainContent}
|
|
231
|
+
</ResizablePanel>
|
|
232
|
+
<ResizableHandle withHandle />
|
|
233
|
+
<ResizablePanel defaultSize={detailPercent} minSize={20}>
|
|
234
|
+
<div className="h-full overflow-y-auto p-4">
|
|
235
|
+
<div className="flex items-center justify-between mb-4">
|
|
236
|
+
<h3 className="text-lg font-semibold">{resolvedTitle}</h3>
|
|
237
|
+
<button
|
|
238
|
+
onClick={close}
|
|
239
|
+
className="rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2"
|
|
240
|
+
aria-label="Close panel"
|
|
241
|
+
>
|
|
242
|
+
<svg
|
|
243
|
+
xmlns="http://www.w3.org/2000/svg"
|
|
244
|
+
width="16"
|
|
245
|
+
height="16"
|
|
246
|
+
viewBox="0 0 24 24"
|
|
247
|
+
fill="none"
|
|
248
|
+
stroke="currentColor"
|
|
249
|
+
strokeWidth="2"
|
|
250
|
+
strokeLinecap="round"
|
|
251
|
+
strokeLinejoin="round"
|
|
252
|
+
>
|
|
253
|
+
<line x1="18" y1="6" x2="6" y2="18" />
|
|
254
|
+
<line x1="6" y1="6" x2="18" y2="18" />
|
|
255
|
+
</svg>
|
|
256
|
+
</button>
|
|
257
|
+
</div>
|
|
258
|
+
{description && (
|
|
259
|
+
<p className="text-sm text-muted-foreground mb-4">{description}</p>
|
|
260
|
+
)}
|
|
261
|
+
{children(selectedRecord)}
|
|
262
|
+
</div>
|
|
263
|
+
</ResizablePanel>
|
|
264
|
+
</PanelGroup>
|
|
265
|
+
);
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// --- Popover Mode ---
|
|
269
|
+
if (mode === 'popover') {
|
|
270
|
+
return (
|
|
271
|
+
<Popover open={isOpen} onOpenChange={setIsOpen}>
|
|
272
|
+
{popoverTrigger && (
|
|
273
|
+
<PopoverTrigger asChild>
|
|
274
|
+
{popoverTrigger}
|
|
275
|
+
</PopoverTrigger>
|
|
276
|
+
)}
|
|
277
|
+
<PopoverContent
|
|
278
|
+
className={cn('w-96 max-h-[400px] overflow-y-auto p-4', className)}
|
|
279
|
+
style={widthStyle}
|
|
280
|
+
>
|
|
281
|
+
<div className="space-y-2">
|
|
282
|
+
<h4 className="text-sm font-semibold">{resolvedTitle}</h4>
|
|
283
|
+
{description && (
|
|
284
|
+
<p className="text-xs text-muted-foreground">{description}</p>
|
|
285
|
+
)}
|
|
286
|
+
{children(selectedRecord)}
|
|
287
|
+
</div>
|
|
288
|
+
</PopoverContent>
|
|
289
|
+
</Popover>
|
|
290
|
+
);
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
return null;
|
|
294
|
+
};
|
|
295
|
+
|
|
296
|
+
NavigationOverlay.displayName = 'NavigationOverlay';
|
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as React from "react"
|
|
10
|
+
import { X, Plus, Trash2 } from "lucide-react"
|
|
11
|
+
|
|
12
|
+
import { cn } from "../lib/utils"
|
|
13
|
+
import { Button } from "../ui/button"
|
|
14
|
+
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
|
|
15
|
+
|
|
16
|
+
export interface SortItem {
|
|
17
|
+
id: string;
|
|
18
|
+
field: string;
|
|
19
|
+
order: 'asc' | 'desc';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface SortBuilderProps {
|
|
23
|
+
fields?: Array<{
|
|
24
|
+
value: string
|
|
25
|
+
label: string
|
|
26
|
+
}>;
|
|
27
|
+
value?: SortItem[];
|
|
28
|
+
onChange?: (value: SortItem[]) => void;
|
|
29
|
+
className?: string;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function SortBuilder({
|
|
33
|
+
fields = [],
|
|
34
|
+
value = [],
|
|
35
|
+
onChange,
|
|
36
|
+
className,
|
|
37
|
+
}: SortBuilderProps) {
|
|
38
|
+
// Use internal state initialization prop changes
|
|
39
|
+
const [items, setItems] = React.useState<SortItem[]>(value || []);
|
|
40
|
+
|
|
41
|
+
React.useEffect(() => {
|
|
42
|
+
if (value && JSON.stringify(value) !== JSON.stringify(items)) {
|
|
43
|
+
setItems(value);
|
|
44
|
+
}
|
|
45
|
+
}, [value]);
|
|
46
|
+
|
|
47
|
+
const handleChange = (newItems: SortItem[]) => {
|
|
48
|
+
setItems(newItems);
|
|
49
|
+
onChange?.(newItems);
|
|
50
|
+
};
|
|
51
|
+
|
|
52
|
+
const addItem = () => {
|
|
53
|
+
const newItem: SortItem = {
|
|
54
|
+
id: crypto.randomUUID(),
|
|
55
|
+
field: fields[0]?.value || "",
|
|
56
|
+
order: 'asc',
|
|
57
|
+
};
|
|
58
|
+
handleChange([...items, newItem]);
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const updateItem = (id: string, updates: Partial<SortItem>) => {
|
|
62
|
+
handleChange(items.map(item => item.id === id ? { ...item, ...updates } : item));
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
const removeItem = (id: string) => {
|
|
66
|
+
handleChange(items.filter(item => item.id !== id));
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
return (
|
|
70
|
+
<div className={cn("space-y-3", className)}>
|
|
71
|
+
<div className="space-y-2">
|
|
72
|
+
{items.map((item, index) => (
|
|
73
|
+
<div key={item.id} className="flex items-center gap-2">
|
|
74
|
+
<span className="text-sm font-medium w-16 text-muted-foreground">
|
|
75
|
+
{index === 0 ? "Sort by" : "Then by"}
|
|
76
|
+
</span>
|
|
77
|
+
<div className="flex-1">
|
|
78
|
+
<Select
|
|
79
|
+
value={item.field}
|
|
80
|
+
onValueChange={(val) => updateItem(item.id, { field: val })}
|
|
81
|
+
>
|
|
82
|
+
<SelectTrigger className="h-9">
|
|
83
|
+
<SelectValue placeholder="Select field" />
|
|
84
|
+
</SelectTrigger>
|
|
85
|
+
<SelectContent>
|
|
86
|
+
{fields.map(f => (
|
|
87
|
+
<SelectItem key={f.value} value={f.value}>{f.label}</SelectItem>
|
|
88
|
+
))}
|
|
89
|
+
</SelectContent>
|
|
90
|
+
</Select>
|
|
91
|
+
</div>
|
|
92
|
+
<div className="w-28">
|
|
93
|
+
<Select
|
|
94
|
+
value={item.order}
|
|
95
|
+
onValueChange={(val) => updateItem(item.id, { order: val as 'asc' | 'desc' })}
|
|
96
|
+
>
|
|
97
|
+
<SelectTrigger className="h-9">
|
|
98
|
+
<SelectValue />
|
|
99
|
+
</SelectTrigger>
|
|
100
|
+
<SelectContent>
|
|
101
|
+
<SelectItem value="asc">A -> Z</SelectItem>
|
|
102
|
+
<SelectItem value="desc">Z -> A</SelectItem>
|
|
103
|
+
</SelectContent>
|
|
104
|
+
</Select>
|
|
105
|
+
</div>
|
|
106
|
+
<Button
|
|
107
|
+
variant="ghost"
|
|
108
|
+
size="icon-sm"
|
|
109
|
+
className="h-9 w-9 shrink-0"
|
|
110
|
+
onClick={() => removeItem(item.id)}
|
|
111
|
+
>
|
|
112
|
+
<X className="h-4 w-4" />
|
|
113
|
+
</Button>
|
|
114
|
+
</div>
|
|
115
|
+
))}
|
|
116
|
+
</div>
|
|
117
|
+
<Button
|
|
118
|
+
variant="outline"
|
|
119
|
+
size="sm"
|
|
120
|
+
onClick={addItem}
|
|
121
|
+
className="h-8"
|
|
122
|
+
disabled={fields.length === 0}
|
|
123
|
+
>
|
|
124
|
+
<Plus className="h-3 w-3 mr-2" />
|
|
125
|
+
Add sort
|
|
126
|
+
</Button>
|
|
127
|
+
</div>
|
|
128
|
+
);
|
|
129
|
+
}
|
package/src/index.css
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
@import 'tailwindcss';
|
|
2
2
|
|
|
3
3
|
/* Scan sources for Tailwind classes */
|
|
4
|
-
@source '
|
|
4
|
+
@source '../src/**/*.{ts,tsx}';
|
|
5
5
|
|
|
6
6
|
/* Tailwind plugin for animations */
|
|
7
7
|
@plugin 'tailwindcss-animate';
|
|
@@ -33,6 +33,13 @@
|
|
|
33
33
|
--color-popover-foreground: hsl(var(--popover-foreground));
|
|
34
34
|
--color-card: hsl(var(--card));
|
|
35
35
|
--color-card-foreground: hsl(var(--card-foreground));
|
|
36
|
+
|
|
37
|
+
/* Chart colors */
|
|
38
|
+
--color-chart-1: hsl(var(--chart-1));
|
|
39
|
+
--color-chart-2: hsl(var(--chart-2));
|
|
40
|
+
--color-chart-3: hsl(var(--chart-3));
|
|
41
|
+
--color-chart-4: hsl(var(--chart-4));
|
|
42
|
+
--color-chart-5: hsl(var(--chart-5));
|
|
36
43
|
}
|
|
37
44
|
|
|
38
45
|
/* CSS custom properties for theme */
|
|
@@ -66,6 +73,12 @@
|
|
|
66
73
|
--ring: 222.2 84% 4.9%;
|
|
67
74
|
|
|
68
75
|
--radius: 0.5rem;
|
|
76
|
+
|
|
77
|
+
--chart-1: 12 76% 61%;
|
|
78
|
+
--chart-2: 173 58% 39%;
|
|
79
|
+
--chart-3: 197 37% 24%;
|
|
80
|
+
--chart-4: 43 74% 66%;
|
|
81
|
+
--chart-5: 27 87% 67%;
|
|
69
82
|
}
|
|
70
83
|
|
|
71
84
|
.dark {
|
|
@@ -96,6 +109,12 @@
|
|
|
96
109
|
--border: 217.2 32.6% 17.5%;
|
|
97
110
|
--input: 217.2 32.6% 17.5%;
|
|
98
111
|
--ring: 212.7 26.8% 83.9%;
|
|
112
|
+
|
|
113
|
+
--chart-1: 220 70% 50%;
|
|
114
|
+
--chart-2: 160 60% 45%;
|
|
115
|
+
--chart-3: 30 80% 55%;
|
|
116
|
+
--chart-4: 280 65% 60%;
|
|
117
|
+
--chart-5: 340 75% 55%;
|
|
99
118
|
}
|
|
100
119
|
|
|
101
120
|
* {
|
package/src/index.ts
CHANGED
|
@@ -14,12 +14,14 @@ import './renderers';
|
|
|
14
14
|
// Export utils
|
|
15
15
|
export { cn } from './lib/utils';
|
|
16
16
|
export { renderChildren } from './lib/utils';
|
|
17
|
+
export { cva } from 'class-variance-authority';
|
|
17
18
|
|
|
18
19
|
// Export placeholder registration
|
|
19
20
|
export { registerPlaceholders } from './renderers/placeholders';
|
|
20
21
|
|
|
21
22
|
// Export raw Shadcn UI components
|
|
22
23
|
export * from './ui';
|
|
24
|
+
export * from './custom';
|
|
23
25
|
|
|
24
26
|
// Export an init function to ensure components are registered
|
|
25
27
|
// This is a workaround for bundlers that might tree-shake side-effect imports
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ObjectUI
|
|
3
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the MIT license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* action:button — Smart action button driven by ActionSchema.
|
|
11
|
+
*
|
|
12
|
+
* Renders a Shadcn Button wired to the ActionRunner. Supports:
|
|
13
|
+
* - All 5 spec action types (script, url, modal, flow, api)
|
|
14
|
+
* - Conditional visibility & enabled state
|
|
15
|
+
* - Loading indicator during async execution
|
|
16
|
+
* - Icon rendering via Lucide
|
|
17
|
+
* - Variant / size / className overrides from schema
|
|
18
|
+
*/
|
|
19
|
+
|
|
20
|
+
import React, { forwardRef, useCallback, useState } from 'react';
|
|
21
|
+
import { ComponentRegistry } from '@object-ui/core';
|
|
22
|
+
import type { ActionSchema } from '@object-ui/types';
|
|
23
|
+
import { useAction } from '@object-ui/react';
|
|
24
|
+
import { useCondition } from '@object-ui/react';
|
|
25
|
+
import { Button } from '../../ui';
|
|
26
|
+
import { cn } from '../../lib/utils';
|
|
27
|
+
import { Loader2 } from 'lucide-react';
|
|
28
|
+
import { resolveIcon } from './resolve-icon';
|
|
29
|
+
|
|
30
|
+
export interface ActionButtonProps {
|
|
31
|
+
schema: ActionSchema & { type: string; className?: string };
|
|
32
|
+
className?: string;
|
|
33
|
+
/** Override context for this specific action */
|
|
34
|
+
context?: Record<string, any>;
|
|
35
|
+
[key: string]: any;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
const ActionButtonRenderer = forwardRef<HTMLButtonElement, ActionButtonProps>(
|
|
39
|
+
({ schema, className, context: localContext, ...props }, ref) => {
|
|
40
|
+
const {
|
|
41
|
+
'data-obj-id': dataObjId,
|
|
42
|
+
'data-obj-type': dataObjType,
|
|
43
|
+
style,
|
|
44
|
+
...rest
|
|
45
|
+
} = props;
|
|
46
|
+
|
|
47
|
+
const { execute } = useAction();
|
|
48
|
+
const [loading, setLoading] = useState(false);
|
|
49
|
+
|
|
50
|
+
// Evaluate visibility and enabled conditions
|
|
51
|
+
const isVisible = useCondition(schema.visible ? `\${${schema.visible}}` : undefined);
|
|
52
|
+
const isEnabled = useCondition(schema.enabled ? `\${${schema.enabled}}` : undefined);
|
|
53
|
+
|
|
54
|
+
// Resolve icon
|
|
55
|
+
const Icon = resolveIcon(schema.icon);
|
|
56
|
+
|
|
57
|
+
// Map schema variant to Shadcn button variant
|
|
58
|
+
const variant = schema.variant === 'primary' ? 'default' : (schema.variant || 'default');
|
|
59
|
+
const size = schema.size === 'md' ? 'default' : (schema.size || 'default');
|
|
60
|
+
|
|
61
|
+
const handleClick = useCallback(async () => {
|
|
62
|
+
if (loading) return;
|
|
63
|
+
setLoading(true);
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await execute({
|
|
67
|
+
type: schema.type,
|
|
68
|
+
name: schema.name,
|
|
69
|
+
target: schema.target,
|
|
70
|
+
execute: schema.execute,
|
|
71
|
+
endpoint: schema.endpoint,
|
|
72
|
+
method: schema.method,
|
|
73
|
+
params: schema.params as Record<string, any> | undefined,
|
|
74
|
+
confirmText: schema.confirmText,
|
|
75
|
+
successMessage: schema.successMessage,
|
|
76
|
+
errorMessage: schema.errorMessage,
|
|
77
|
+
refreshAfter: schema.refreshAfter,
|
|
78
|
+
toast: schema.toast,
|
|
79
|
+
...localContext,
|
|
80
|
+
});
|
|
81
|
+
} finally {
|
|
82
|
+
setLoading(false);
|
|
83
|
+
}
|
|
84
|
+
}, [schema, execute, loading, localContext]);
|
|
85
|
+
|
|
86
|
+
if (schema.visible && !isVisible) return null;
|
|
87
|
+
|
|
88
|
+
return (
|
|
89
|
+
<Button
|
|
90
|
+
ref={ref}
|
|
91
|
+
type="button"
|
|
92
|
+
variant={variant as any}
|
|
93
|
+
size={size as any}
|
|
94
|
+
className={cn(schema.className, className)}
|
|
95
|
+
disabled={(schema.enabled ? !isEnabled : false) || loading}
|
|
96
|
+
onClick={handleClick}
|
|
97
|
+
{...rest}
|
|
98
|
+
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
|
|
99
|
+
>
|
|
100
|
+
{loading && <Loader2 className="mr-2 h-4 w-4 animate-spin" />}
|
|
101
|
+
{!loading && Icon && <Icon className={cn('h-4 w-4', schema.label && 'mr-2')} />}
|
|
102
|
+
{schema.label}
|
|
103
|
+
</Button>
|
|
104
|
+
);
|
|
105
|
+
},
|
|
106
|
+
);
|
|
107
|
+
|
|
108
|
+
ActionButtonRenderer.displayName = 'ActionButtonRenderer';
|
|
109
|
+
|
|
110
|
+
ComponentRegistry.register('action:button', ActionButtonRenderer, {
|
|
111
|
+
namespace: 'action',
|
|
112
|
+
label: 'Action Button',
|
|
113
|
+
inputs: [
|
|
114
|
+
{ name: 'name', type: 'string', label: 'Action Name' },
|
|
115
|
+
{ name: 'label', type: 'string', label: 'Label', defaultValue: 'Action' },
|
|
116
|
+
{ name: 'icon', type: 'string', label: 'Icon' },
|
|
117
|
+
{
|
|
118
|
+
name: 'type',
|
|
119
|
+
type: 'enum',
|
|
120
|
+
label: 'Action Type',
|
|
121
|
+
enum: ['script', 'url', 'modal', 'flow', 'api'],
|
|
122
|
+
defaultValue: 'script',
|
|
123
|
+
},
|
|
124
|
+
{ name: 'target', type: 'string', label: 'Target' },
|
|
125
|
+
{
|
|
126
|
+
name: 'variant',
|
|
127
|
+
type: 'enum',
|
|
128
|
+
label: 'Variant',
|
|
129
|
+
enum: ['default', 'primary', 'secondary', 'destructive', 'outline', 'ghost'],
|
|
130
|
+
defaultValue: 'default',
|
|
131
|
+
},
|
|
132
|
+
{
|
|
133
|
+
name: 'size',
|
|
134
|
+
type: 'enum',
|
|
135
|
+
label: 'Size',
|
|
136
|
+
enum: ['sm', 'md', 'lg'],
|
|
137
|
+
defaultValue: 'md',
|
|
138
|
+
},
|
|
139
|
+
{ name: 'className', type: 'string', label: 'CSS Class', advanced: true },
|
|
140
|
+
],
|
|
141
|
+
defaultProps: {
|
|
142
|
+
label: 'Action',
|
|
143
|
+
type: 'script',
|
|
144
|
+
variant: 'default',
|
|
145
|
+
size: 'md',
|
|
146
|
+
},
|
|
147
|
+
});
|