@object-ui/components 3.3.0 → 3.3.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/CHANGELOG.md +20 -0
- package/README.md +21 -1
- package/dist/index.css +6339 -2
- package/dist/index.js +17600 -17481
- package/dist/index.umd.cjs +36 -36
- package/dist/packages/components/src/custom/empty.d.ts +12 -1
- package/dist/packages/components/src/renderers/action/action-bar.d.ts +12 -1
- package/dist/packages/components/src/ui/chart.d.ts +10 -29
- package/package.json +65 -44
- package/.turbo/turbo-build.log +0 -84
- package/README_SHADCN_SYNC.md +0 -281
- package/TESTING.md +0 -335
- package/docs/FilterBuilder.md +0 -268
- package/metadata/Chart.component.yml +0 -30
- package/metadata/FilterBuilder.component.yml +0 -39
- package/metadata/GridLayout.component.yml +0 -27
- package/metadata/Menu.component.yml +0 -31
- package/metadata/ObjectForm.component.yml +0 -34
- package/metadata/ObjectGrid.component.yml +0 -72
- package/metadata/Page.component.yml +0 -24
- package/postcss.config.js +0 -14
- package/shadcn-components.json +0 -440
- package/src/SchemaRenderer.tsx +0 -28
- package/src/__tests__/PageRendererRegions.test.tsx +0 -668
- package/src/__tests__/README.md +0 -124
- package/src/__tests__/__snapshots__/snapshot-critical.test.tsx.snap +0 -811
- package/src/__tests__/__snapshots__/snapshot.test.tsx.snap +0 -327
- package/src/__tests__/accessibility.test.tsx +0 -137
- package/src/__tests__/action-bar.test.tsx +0 -206
- package/src/__tests__/api-consistency.test.tsx +0 -596
- package/src/__tests__/basic-renderers.test.tsx +0 -255
- package/src/__tests__/color-contrast.test.tsx +0 -212
- package/src/__tests__/complex-disclosure-renderers.test.tsx +0 -302
- package/src/__tests__/compliance.test.tsx +0 -72
- package/src/__tests__/config-field-renderer.test.tsx +0 -307
- package/src/__tests__/config-panel-renderer.test.tsx +0 -580
- package/src/__tests__/config-primitives.test.tsx +0 -106
- package/src/__tests__/edge-cases.test.tsx +0 -285
- package/src/__tests__/feedback-overlay-renderers.test.tsx +0 -349
- package/src/__tests__/filter-builder.test.tsx +0 -409
- package/src/__tests__/form-renderers.test.tsx +0 -364
- package/src/__tests__/layout-data-renderers.test.tsx +0 -340
- package/src/__tests__/mobile-accessibility.test.tsx +0 -120
- package/src/__tests__/navigation-overlay.test.tsx +0 -370
- package/src/__tests__/snapshot-critical.test.tsx +0 -317
- package/src/__tests__/snapshot.test.tsx +0 -205
- package/src/__tests__/test-utils.tsx +0 -190
- package/src/__tests__/use-config-draft.test.tsx +0 -295
- package/src/__tests__/view-compliance.test.tsx +0 -153
- package/src/__tests__/wcag-audit.test.tsx +0 -493
- package/src/custom/action-param-dialog.tsx +0 -264
- package/src/custom/button-group.tsx +0 -91
- package/src/custom/combobox.tsx +0 -104
- package/src/custom/config-field-renderer.tsx +0 -276
- package/src/custom/config-panel-renderer.tsx +0 -306
- package/src/custom/config-row.tsx +0 -50
- package/src/custom/date-picker.tsx +0 -61
- package/src/custom/empty.tsx +0 -112
- package/src/custom/field.tsx +0 -81
- package/src/custom/filter-builder.tsx +0 -418
- package/src/custom/index.ts +0 -21
- package/src/custom/input-group.tsx +0 -53
- package/src/custom/item.tsx +0 -201
- package/src/custom/kbd.tsx +0 -36
- package/src/custom/mobile-dialog-content.tsx +0 -67
- package/src/custom/native-select.tsx +0 -33
- package/src/custom/navigation-overlay.tsx +0 -334
- package/src/custom/section-header.tsx +0 -68
- package/src/custom/sort-builder.tsx +0 -129
- package/src/custom/spinner.tsx +0 -26
- package/src/custom/view-skeleton.tsx +0 -243
- package/src/custom/view-states.tsx +0 -153
- package/src/debug/DebugPanel.tsx +0 -313
- package/src/debug/__tests__/DebugPanel.test.tsx +0 -134
- package/src/debug/index.ts +0 -10
- package/src/hooks/use-config-draft.ts +0 -127
- package/src/hooks/use-mobile.tsx +0 -27
- package/src/index.css +0 -245
- package/src/index.ts +0 -47
- package/src/lib/use-sync-external-store-shim.ts +0 -10
- package/src/lib/use-sync-external-store-with-selector-shim.ts +0 -90
- package/src/lib/utils.tsx +0 -35
- package/src/new-components.test.ts +0 -73
- package/src/renderers/action/action-bar.tsx +0 -221
- package/src/renderers/action/action-button.tsx +0 -158
- package/src/renderers/action/action-group.tsx +0 -270
- package/src/renderers/action/action-icon.tsx +0 -150
- package/src/renderers/action/action-menu.tsx +0 -203
- package/src/renderers/action/index.ts +0 -19
- package/src/renderers/action/resolve-icon.ts +0 -35
- package/src/renderers/basic/button-group.tsx +0 -79
- package/src/renderers/basic/div.tsx +0 -60
- package/src/renderers/basic/html.tsx +0 -43
- package/src/renderers/basic/icon.tsx +0 -89
- package/src/renderers/basic/image.tsx +0 -49
- package/src/renderers/basic/index.ts +0 -18
- package/src/renderers/basic/navigation-menu.tsx +0 -81
- package/src/renderers/basic/pagination.tsx +0 -109
- package/src/renderers/basic/separator.tsx +0 -57
- package/src/renderers/basic/span.tsx +0 -63
- package/src/renderers/basic/text.tsx +0 -52
- package/src/renderers/complex/README-KANBAN.md +0 -208
- package/src/renderers/complex/TIMELINE.md +0 -353
- package/src/renderers/complex/__tests__/data-table-airtable-ux.test.tsx +0 -239
- package/src/renderers/complex/__tests__/data-table-batch-editing.test.tsx +0 -275
- package/src/renderers/complex/__tests__/data-table-cell-renderer.test.tsx +0 -120
- package/src/renderers/complex/__tests__/data-table-editing.test.tsx +0 -221
- package/src/renderers/complex/__tests__/data-table.test.ts +0 -76
- package/src/renderers/complex/carousel.tsx +0 -69
- package/src/renderers/complex/data-table.tsx +0 -1243
- package/src/renderers/complex/filter-builder.tsx +0 -77
- package/src/renderers/complex/index.ts +0 -16
- package/src/renderers/complex/resizable.tsx +0 -66
- package/src/renderers/complex/scroll-area.tsx +0 -58
- package/src/renderers/complex/table.tsx +0 -95
- package/src/renderers/data-display/alert.tsx +0 -46
- package/src/renderers/data-display/avatar.tsx +0 -38
- package/src/renderers/data-display/badge.tsx +0 -55
- package/src/renderers/data-display/breadcrumb.tsx +0 -61
- package/src/renderers/data-display/index.ts +0 -18
- package/src/renderers/data-display/kbd.tsx +0 -50
- package/src/renderers/data-display/list.tsx +0 -75
- package/src/renderers/data-display/statistic.tsx +0 -95
- package/src/renderers/data-display/table.tsx +0 -78
- package/src/renderers/data-display/tree-view.tsx +0 -176
- package/src/renderers/disclosure/accordion.tsx +0 -69
- package/src/renderers/disclosure/collapsible.tsx +0 -53
- package/src/renderers/disclosure/index.ts +0 -11
- package/src/renderers/disclosure/toggle-group.tsx +0 -79
- package/src/renderers/feedback/empty.tsx +0 -49
- package/src/renderers/feedback/index.ts +0 -16
- package/src/renderers/feedback/loading.tsx +0 -78
- package/src/renderers/feedback/progress.tsx +0 -29
- package/src/renderers/feedback/skeleton.tsx +0 -31
- package/src/renderers/feedback/sonner.tsx +0 -56
- package/src/renderers/feedback/spinner.tsx +0 -55
- package/src/renderers/feedback/toast.tsx +0 -59
- package/src/renderers/feedback/toaster.tsx +0 -23
- package/src/renderers/form/button.tsx +0 -103
- package/src/renderers/form/calendar.tsx +0 -34
- package/src/renderers/form/checkbox.tsx +0 -71
- package/src/renderers/form/combobox.tsx +0 -48
- package/src/renderers/form/command.tsx +0 -58
- package/src/renderers/form/date-picker.tsx +0 -84
- package/src/renderers/form/file-upload.tsx +0 -184
- package/src/renderers/form/form.tsx +0 -540
- package/src/renderers/form/index.ts +0 -26
- package/src/renderers/form/input-otp.tsx +0 -51
- package/src/renderers/form/input.tsx +0 -121
- package/src/renderers/form/label.tsx +0 -45
- package/src/renderers/form/radio-group.tsx +0 -63
- package/src/renderers/form/select.tsx +0 -94
- package/src/renderers/form/slider.tsx +0 -61
- package/src/renderers/form/switch.tsx +0 -48
- package/src/renderers/form/textarea.tsx +0 -76
- package/src/renderers/form/toggle.tsx +0 -42
- package/src/renderers/index.ts +0 -18
- package/src/renderers/layout/aspect-ratio.tsx +0 -51
- package/src/renderers/layout/card.tsx +0 -85
- package/src/renderers/layout/container.tsx +0 -122
- package/src/renderers/layout/flex.tsx +0 -132
- package/src/renderers/layout/grid.tsx +0 -178
- package/src/renderers/layout/index.ts +0 -19
- package/src/renderers/layout/page.tsx +0 -466
- package/src/renderers/layout/semantic.tsx +0 -48
- package/src/renderers/layout/stack.tsx +0 -132
- package/src/renderers/layout/tabs.tsx +0 -97
- package/src/renderers/navigation/header-bar.tsx +0 -118
- package/src/renderers/navigation/index.ts +0 -10
- package/src/renderers/navigation/sidebar.tsx +0 -208
- package/src/renderers/overlay/alert-dialog.tsx +0 -72
- package/src/renderers/overlay/context-menu.tsx +0 -100
- package/src/renderers/overlay/dialog.tsx +0 -77
- package/src/renderers/overlay/drawer.tsx +0 -77
- package/src/renderers/overlay/dropdown-menu.tsx +0 -99
- package/src/renderers/overlay/hover-card.tsx +0 -55
- package/src/renderers/overlay/index.ts +0 -18
- package/src/renderers/overlay/menubar.tsx +0 -76
- package/src/renderers/overlay/popover.tsx +0 -56
- package/src/renderers/overlay/sheet.tsx +0 -77
- package/src/renderers/overlay/tooltip.tsx +0 -67
- package/src/renderers/placeholders.tsx +0 -107
- package/src/stories/CRMApp.stories.tsx +0 -706
- package/src/stories/ConfigPanel.stories.tsx +0 -232
- package/src/stories/Guide.mdx +0 -55
- package/src/stories/MockedData.stories.tsx +0 -121
- package/src/stories/assets/accessibility.png +0 -0
- package/src/stories/assets/accessibility.svg +0 -1
- 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 +0 -1
- package/src/stories/assets/docs.png +0 -0
- package/src/stories/assets/figma-plugin.png +0 -0
- package/src/stories/assets/github.svg +0 -1
- 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 +0 -1
- package/src/stories/assets/youtube.svg +0 -1
- package/src/stories/button.css +0 -30
- package/src/stories/header.css +0 -32
- package/src/stories/page.css +0 -68
- package/src/stories-json/Accessibility.mdx +0 -297
- package/src/stories-json/EdgeCases.stories.tsx +0 -160
- package/src/stories-json/GettingStarted.mdx +0 -89
- package/src/stories-json/Introduction.mdx +0 -127
- package/src/stories-json/accordion.stories.tsx +0 -43
- package/src/stories-json/aggrid.stories.tsx +0 -103
- package/src/stories-json/alert.stories.tsx +0 -39
- package/src/stories-json/aspect-ratio.stories.tsx +0 -34
- package/src/stories-json/avatar.stories.tsx +0 -38
- package/src/stories-json/badge.stories.tsx +0 -53
- package/src/stories-json/breadcrumb.stories.tsx +0 -30
- package/src/stories-json/button-group.stories.tsx +0 -43
- package/src/stories-json/button.stories.tsx +0 -73
- package/src/stories-json/calendar.stories.tsx +0 -85
- package/src/stories-json/card.stories.tsx +0 -48
- package/src/stories-json/carousel.stories.tsx +0 -33
- package/src/stories-json/charts.stories.tsx +0 -195
- package/src/stories-json/chatbot.stories.tsx +0 -349
- package/src/stories-json/code-editor.stories.tsx +0 -92
- package/src/stories-json/collapsible.stories.tsx +0 -40
- package/src/stories-json/controls.stories.tsx +0 -36
- package/src/stories-json/crm-live-data.stories.tsx +0 -154
- package/src/stories-json/dashboard.stories.tsx +0 -318
- package/src/stories-json/data-table.stories.tsx +0 -136
- package/src/stories-json/data_display_extras.stories.tsx +0 -102
- package/src/stories-json/date-picker.stories.tsx +0 -28
- package/src/stories-json/detail-view.stories.tsx +0 -258
- package/src/stories-json/dialog.stories.tsx +0 -43
- package/src/stories-json/feedback_extras.stories.tsx +0 -40
- package/src/stories-json/feedback_others.stories.tsx +0 -46
- package/src/stories-json/form-variants.stories.tsx +0 -210
- package/src/stories-json/form_advanced.stories.tsx +0 -117
- package/src/stories-json/form_extras.stories.tsx +0 -123
- package/src/stories-json/grid.stories.tsx +0 -56
- package/src/stories-json/icon.stories.tsx +0 -36
- package/src/stories-json/input.stories.tsx +0 -52
- package/src/stories-json/kanban.stories.tsx +0 -295
- package/src/stories-json/layout_extended.stories.tsx +0 -76
- package/src/stories-json/layout_flex.stories.tsx +0 -107
- package/src/stories-json/list-view.stories.tsx +0 -97
- package/src/stories-json/markdown.stories.tsx +0 -129
- package/src/stories-json/menus.stories.tsx +0 -63
- package/src/stories-json/metric-card.stories.tsx +0 -143
- package/src/stories-json/navigation-menu.stories.tsx +0 -37
- package/src/stories-json/object-aggrid-advanced.stories.tsx +0 -389
- package/src/stories-json/object-aggrid.stories.tsx +0 -252
- package/src/stories-json/object-form.stories.tsx +0 -130
- package/src/stories-json/object-gantt.stories.tsx +0 -114
- package/src/stories-json/object-grid.stories.tsx +0 -315
- package/src/stories-json/object-map.stories.tsx +0 -116
- package/src/stories-json/object-view.stories.tsx +0 -118
- package/src/stories-json/overlay_extras.stories.tsx +0 -113
- package/src/stories-json/overlay_others.stories.tsx +0 -76
- package/src/stories-json/page.stories.tsx +0 -55
- package/src/stories-json/reports.stories.tsx +0 -163
- package/src/stories-json/resizable.stories.tsx +0 -44
- package/src/stories-json/select.stories.tsx +0 -34
- package/src/stories-json/separator.stories.tsx +0 -41
- package/src/stories-json/sidebar.stories.tsx +0 -147
- package/src/stories-json/statistic.stories.tsx +0 -44
- package/src/stories-json/tabs.stories.tsx +0 -51
- package/src/stories-json/timeline.stories.tsx +0 -188
- package/src/stories-json/typography.stories.tsx +0 -45
- package/src/types/config-panel.ts +0 -101
- package/src/ui/accordion.tsx +0 -66
- package/src/ui/alert-dialog.tsx +0 -149
- package/src/ui/alert.tsx +0 -67
- package/src/ui/aspect-ratio.tsx +0 -15
- package/src/ui/avatar.tsx +0 -58
- package/src/ui/badge.tsx +0 -44
- package/src/ui/breadcrumb.tsx +0 -123
- package/src/ui/button.tsx +0 -64
- package/src/ui/calendar.tsx +0 -221
- package/src/ui/card.tsx +0 -87
- package/src/ui/carousel.tsx +0 -270
- package/src/ui/chart.tsx +0 -377
- package/src/ui/checkbox.tsx +0 -38
- package/src/ui/collapsible.tsx +0 -19
- package/src/ui/command.tsx +0 -161
- package/src/ui/context-menu.tsx +0 -208
- package/src/ui/dialog.tsx +0 -130
- package/src/ui/drawer.tsx +0 -126
- package/src/ui/dropdown-menu.tsx +0 -208
- package/src/ui/form.tsx +0 -186
- package/src/ui/hover-card.tsx +0 -37
- package/src/ui/index.ts +0 -56
- package/src/ui/input-otp.tsx +0 -79
- package/src/ui/input.tsx +0 -30
- package/src/ui/label.tsx +0 -34
- package/src/ui/menubar.tsx +0 -264
- package/src/ui/navigation-menu.tsx +0 -136
- package/src/ui/pagination.tsx +0 -125
- package/src/ui/popover.tsx +0 -39
- package/src/ui/progress.tsx +0 -36
- package/src/ui/radio-group.tsx +0 -52
- package/src/ui/resizable.tsx +0 -53
- package/src/ui/scroll-area.tsx +0 -56
- package/src/ui/select.tsx +0 -168
- package/src/ui/separator.tsx +0 -39
- package/src/ui/sheet.tsx +0 -150
- package/src/ui/sidebar.tsx +0 -781
- package/src/ui/skeleton.tsx +0 -23
- package/src/ui/slider.tsx +0 -39
- package/src/ui/sonner.tsx +0 -53
- package/src/ui/switch.tsx +0 -37
- package/src/ui/table.tsx +0 -125
- package/src/ui/tabs.tsx +0 -63
- package/src/ui/textarea.tsx +0 -30
- package/src/ui/toast.tsx +0 -137
- package/src/ui/toggle-group.tsx +0 -69
- package/src/ui/toggle.tsx +0 -53
- package/src/ui/tooltip.tsx +0 -38
- package/src/ui/typography.tsx +0 -85
- package/tsconfig.json +0 -19
- package/vite.config.ts +0 -71
- package/vitest.config.ts +0 -5
package/src/custom/empty.tsx
DELETED
|
@@ -1,112 +0,0 @@
|
|
|
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 { cva, type VariantProps } from "class-variance-authority"
|
|
10
|
-
|
|
11
|
-
import { cn } from "../lib/utils"
|
|
12
|
-
|
|
13
|
-
function Empty({ className, ...props }: React.ComponentProps<"div">) {
|
|
14
|
-
return (
|
|
15
|
-
<div
|
|
16
|
-
data-slot="empty"
|
|
17
|
-
className={cn(
|
|
18
|
-
"flex min-w-0 flex-1 flex-col items-center justify-center gap-6 rounded-lg border-dashed p-6 text-center text-balance md:p-12",
|
|
19
|
-
className
|
|
20
|
-
)}
|
|
21
|
-
{...props}
|
|
22
|
-
/>
|
|
23
|
-
)
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
function EmptyHeader({ className, ...props }: React.ComponentProps<"div">) {
|
|
27
|
-
return (
|
|
28
|
-
<div
|
|
29
|
-
data-slot="empty-header"
|
|
30
|
-
className={cn(
|
|
31
|
-
"flex max-w-sm flex-col items-center gap-2 text-center",
|
|
32
|
-
className
|
|
33
|
-
)}
|
|
34
|
-
{...props}
|
|
35
|
-
/>
|
|
36
|
-
)
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
const emptyMediaVariants = cva(
|
|
40
|
-
"flex shrink-0 items-center justify-center mb-2 [&_svg]:pointer-events-none [&_svg]:shrink-0",
|
|
41
|
-
{
|
|
42
|
-
variants: {
|
|
43
|
-
variant: {
|
|
44
|
-
default: "bg-transparent",
|
|
45
|
-
icon: "bg-muted text-foreground flex size-10 shrink-0 items-center justify-center rounded-lg [&_svg:not([class*='size-'])]:size-6",
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
defaultVariants: {
|
|
49
|
-
variant: "default",
|
|
50
|
-
},
|
|
51
|
-
}
|
|
52
|
-
)
|
|
53
|
-
|
|
54
|
-
function EmptyMedia({
|
|
55
|
-
className,
|
|
56
|
-
variant = "default",
|
|
57
|
-
...props
|
|
58
|
-
}: React.ComponentProps<"div"> & VariantProps<typeof emptyMediaVariants>) {
|
|
59
|
-
return (
|
|
60
|
-
<div
|
|
61
|
-
data-slot="empty-icon"
|
|
62
|
-
data-variant={variant}
|
|
63
|
-
className={cn(emptyMediaVariants({ variant, className }))}
|
|
64
|
-
{...props}
|
|
65
|
-
/>
|
|
66
|
-
)
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function EmptyTitle({ className, ...props }: React.ComponentProps<"div">) {
|
|
70
|
-
return (
|
|
71
|
-
<div
|
|
72
|
-
data-slot="empty-title"
|
|
73
|
-
className={cn("text-lg font-medium tracking-tight", className)}
|
|
74
|
-
{...props}
|
|
75
|
-
/>
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function EmptyDescription({ className, ...props }: React.ComponentProps<"p">) {
|
|
80
|
-
return (
|
|
81
|
-
<div
|
|
82
|
-
data-slot="empty-description"
|
|
83
|
-
className={cn(
|
|
84
|
-
"text-muted-foreground [&>a:hover]:text-primary text-sm/relaxed [&>a]:underline [&>a]:underline-offset-4",
|
|
85
|
-
className
|
|
86
|
-
)}
|
|
87
|
-
{...props}
|
|
88
|
-
/>
|
|
89
|
-
)
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
function EmptyContent({ className, ...props }: React.ComponentProps<"div">) {
|
|
93
|
-
return (
|
|
94
|
-
<div
|
|
95
|
-
data-slot="empty-content"
|
|
96
|
-
className={cn(
|
|
97
|
-
"flex w-full max-w-sm min-w-0 flex-col items-center gap-4 text-sm text-balance",
|
|
98
|
-
className
|
|
99
|
-
)}
|
|
100
|
-
{...props}
|
|
101
|
-
/>
|
|
102
|
-
)
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export {
|
|
106
|
-
Empty,
|
|
107
|
-
EmptyHeader,
|
|
108
|
-
EmptyTitle,
|
|
109
|
-
EmptyDescription,
|
|
110
|
-
EmptyContent,
|
|
111
|
-
EmptyMedia,
|
|
112
|
-
}
|
package/src/custom/field.tsx
DELETED
|
@@ -1,81 +0,0 @@
|
|
|
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 { Slot as SlotPrimitive } from "@radix-ui/react-slot"
|
|
11
|
-
import { cva, type VariantProps } from "class-variance-authority"
|
|
12
|
-
|
|
13
|
-
import { cn } from "../lib/utils"
|
|
14
|
-
import { Label } from "../ui/label"
|
|
15
|
-
|
|
16
|
-
const fieldVariants = cva("space-y-2")
|
|
17
|
-
|
|
18
|
-
export interface FieldProps
|
|
19
|
-
extends React.HTMLAttributes<HTMLDivElement>,
|
|
20
|
-
VariantProps<typeof fieldVariants> {
|
|
21
|
-
label?: React.ReactNode
|
|
22
|
-
description?: React.ReactNode
|
|
23
|
-
error?: React.ReactNode
|
|
24
|
-
required?: boolean
|
|
25
|
-
htmlFor?: string
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
const Field = React.forwardRef<HTMLDivElement, FieldProps>(
|
|
29
|
-
({ className, label, description, error, required, htmlFor, children, ...props }, ref) => {
|
|
30
|
-
const id = React.useId()
|
|
31
|
-
const fieldId = htmlFor || id
|
|
32
|
-
const descriptionId = `${fieldId}-description`
|
|
33
|
-
const errorId = `${fieldId}-error`
|
|
34
|
-
|
|
35
|
-
return (
|
|
36
|
-
<div ref={ref} className={cn(fieldVariants(), className)} {...props}>
|
|
37
|
-
{label && (
|
|
38
|
-
<Label
|
|
39
|
-
htmlFor={fieldId}
|
|
40
|
-
className={cn(error && "text-destructive", required && "after:content-['*'] after:ml-0.5 after:text-destructive")}
|
|
41
|
-
>
|
|
42
|
-
{label}
|
|
43
|
-
</Label>
|
|
44
|
-
)}
|
|
45
|
-
|
|
46
|
-
<SlotPrimitive
|
|
47
|
-
id={fieldId}
|
|
48
|
-
aria-describedby={
|
|
49
|
-
[description && descriptionId, error && errorId]
|
|
50
|
-
.filter(Boolean)
|
|
51
|
-
.join(" ") || undefined
|
|
52
|
-
}
|
|
53
|
-
aria-invalid={!!error}
|
|
54
|
-
>
|
|
55
|
-
{children}
|
|
56
|
-
</SlotPrimitive>
|
|
57
|
-
|
|
58
|
-
{description && !error && (
|
|
59
|
-
<p
|
|
60
|
-
id={descriptionId}
|
|
61
|
-
className="text-[0.8rem] text-muted-foreground"
|
|
62
|
-
>
|
|
63
|
-
{description}
|
|
64
|
-
</p>
|
|
65
|
-
)}
|
|
66
|
-
|
|
67
|
-
{error && (
|
|
68
|
-
<p
|
|
69
|
-
id={errorId}
|
|
70
|
-
className="text-[0.8rem] font-medium text-destructive"
|
|
71
|
-
>
|
|
72
|
-
{error}
|
|
73
|
-
</p>
|
|
74
|
-
)}
|
|
75
|
-
</div>
|
|
76
|
-
)
|
|
77
|
-
}
|
|
78
|
-
)
|
|
79
|
-
Field.displayName = "Field"
|
|
80
|
-
|
|
81
|
-
export { Field }
|
|
@@ -1,418 +0,0 @@
|
|
|
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
|
-
"use client"
|
|
10
|
-
|
|
11
|
-
import * as React from "react"
|
|
12
|
-
import { X, Plus, Trash2 } from "lucide-react"
|
|
13
|
-
|
|
14
|
-
import { cn } from "../lib/utils"
|
|
15
|
-
import { Button } from "../ui/button"
|
|
16
|
-
import { Checkbox } from "../ui/checkbox"
|
|
17
|
-
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
|
|
18
|
-
import { Input } from "../ui/input"
|
|
19
|
-
|
|
20
|
-
export interface FilterCondition {
|
|
21
|
-
id: string
|
|
22
|
-
field: string
|
|
23
|
-
operator: string
|
|
24
|
-
value: string | number | boolean | (string | number | boolean)[]
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export interface FilterGroup {
|
|
28
|
-
id: string
|
|
29
|
-
logic: "and" | "or"
|
|
30
|
-
conditions: FilterCondition[]
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
export interface FilterBuilderProps {
|
|
34
|
-
fields?: Array<{
|
|
35
|
-
value: string
|
|
36
|
-
label: string
|
|
37
|
-
type?: string
|
|
38
|
-
options?: Array<{ value: string; label: string }> // For select fields
|
|
39
|
-
}>
|
|
40
|
-
value?: FilterGroup
|
|
41
|
-
onChange?: (value: FilterGroup) => void
|
|
42
|
-
className?: string
|
|
43
|
-
showClearAll?: boolean
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
const defaultOperators = [
|
|
47
|
-
{ value: "equals", label: "Equals" },
|
|
48
|
-
{ value: "notEquals", label: "Does not equal" },
|
|
49
|
-
{ value: "contains", label: "Contains" },
|
|
50
|
-
{ value: "notContains", label: "Does not contain" },
|
|
51
|
-
{ value: "isEmpty", label: "Is empty" },
|
|
52
|
-
{ value: "isNotEmpty", label: "Is not empty" },
|
|
53
|
-
{ value: "greaterThan", label: "Greater than" },
|
|
54
|
-
{ value: "lessThan", label: "Less than" },
|
|
55
|
-
{ value: "greaterOrEqual", label: "Greater than or equal" },
|
|
56
|
-
{ value: "lessOrEqual", label: "Less than or equal" },
|
|
57
|
-
{ value: "before", label: "Before" },
|
|
58
|
-
{ value: "after", label: "After" },
|
|
59
|
-
{ value: "between", label: "Between" },
|
|
60
|
-
{ value: "in", label: "In" },
|
|
61
|
-
{ value: "notIn", label: "Not in" },
|
|
62
|
-
]
|
|
63
|
-
|
|
64
|
-
const textOperators = ["equals", "notEquals", "contains", "notContains", "isEmpty", "isNotEmpty"]
|
|
65
|
-
const numberOperators = ["equals", "notEquals", "greaterThan", "lessThan", "greaterOrEqual", "lessOrEqual", "isEmpty", "isNotEmpty"]
|
|
66
|
-
const booleanOperators = ["equals", "notEquals"]
|
|
67
|
-
const dateOperators = ["equals", "notEquals", "before", "after", "between", "isEmpty", "isNotEmpty"]
|
|
68
|
-
const selectOperators = ["equals", "notEquals", "in", "notIn", "isEmpty", "isNotEmpty"]
|
|
69
|
-
const lookupOperators = ["equals", "notEquals", "in", "notIn", "isEmpty", "isNotEmpty"]
|
|
70
|
-
|
|
71
|
-
/** Field types that share the same operator/input behavior as number (numeric comparison operators, number input) */
|
|
72
|
-
const numberLikeTypes = ["number", "currency", "percent", "rating"]
|
|
73
|
-
/** Field types that share the same operator/input behavior as date (before/after operators, date/datetime/time input) */
|
|
74
|
-
const dateLikeTypes = ["date", "datetime", "time"]
|
|
75
|
-
/** Field types that use select operators (equals/in/notIn) and render dropdown or checkbox list when options provided */
|
|
76
|
-
const selectLikeTypes = ["select", "status"]
|
|
77
|
-
/** Relational/reference field types that use lookup operators (equals/in/notIn) and render dropdown or checkbox list when options provided */
|
|
78
|
-
const lookupLikeTypes = ["lookup", "master_detail", "user", "owner"]
|
|
79
|
-
|
|
80
|
-
/** Normalize a filter value into an array for multi-select scenarios */
|
|
81
|
-
function normalizeToArray(value: FilterCondition["value"]): (string | number | boolean)[] {
|
|
82
|
-
if (Array.isArray(value)) return value
|
|
83
|
-
if (value !== undefined && value !== null && value !== "") return [value as string | number | boolean]
|
|
84
|
-
return []
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
function FilterBuilder({
|
|
88
|
-
fields = [],
|
|
89
|
-
value,
|
|
90
|
-
onChange,
|
|
91
|
-
className,
|
|
92
|
-
showClearAll = true,
|
|
93
|
-
}: FilterBuilderProps) {
|
|
94
|
-
const [filterGroup, setFilterGroup] = React.useState<FilterGroup>(
|
|
95
|
-
value || {
|
|
96
|
-
id: "root",
|
|
97
|
-
logic: "and",
|
|
98
|
-
conditions: [],
|
|
99
|
-
}
|
|
100
|
-
)
|
|
101
|
-
|
|
102
|
-
React.useEffect(() => {
|
|
103
|
-
if (value && JSON.stringify(value) !== JSON.stringify(filterGroup)) {
|
|
104
|
-
setFilterGroup(value)
|
|
105
|
-
}
|
|
106
|
-
}, [value])
|
|
107
|
-
|
|
108
|
-
const handleChange = (newGroup: FilterGroup) => {
|
|
109
|
-
setFilterGroup(newGroup)
|
|
110
|
-
onChange?.(newGroup)
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const addCondition = () => {
|
|
114
|
-
const newCondition: FilterCondition = {
|
|
115
|
-
id: crypto.randomUUID(),
|
|
116
|
-
field: fields[0]?.value || "",
|
|
117
|
-
operator: "equals",
|
|
118
|
-
value: "",
|
|
119
|
-
}
|
|
120
|
-
handleChange({
|
|
121
|
-
...filterGroup,
|
|
122
|
-
conditions: [...filterGroup.conditions, newCondition],
|
|
123
|
-
})
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
const removeCondition = (conditionId: string) => {
|
|
127
|
-
handleChange({
|
|
128
|
-
...filterGroup,
|
|
129
|
-
conditions: filterGroup.conditions.filter((c) => c.id !== conditionId),
|
|
130
|
-
})
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const clearAllConditions = () => {
|
|
134
|
-
handleChange({
|
|
135
|
-
...filterGroup,
|
|
136
|
-
conditions: [],
|
|
137
|
-
})
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const updateCondition = (conditionId: string, updates: Partial<FilterCondition>) => {
|
|
141
|
-
handleChange({
|
|
142
|
-
...filterGroup,
|
|
143
|
-
conditions: filterGroup.conditions.map((c) =>
|
|
144
|
-
c.id === conditionId ? { ...c, ...updates } : c
|
|
145
|
-
),
|
|
146
|
-
})
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const toggleLogic = () => {
|
|
150
|
-
handleChange({
|
|
151
|
-
...filterGroup,
|
|
152
|
-
logic: filterGroup.logic === "and" ? "or" : "and",
|
|
153
|
-
})
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
const getOperatorsForField = (fieldValue: string) => {
|
|
157
|
-
const field = fields.find((f) => f.value === fieldValue)
|
|
158
|
-
const fieldType = field?.type || "text"
|
|
159
|
-
|
|
160
|
-
if (numberLikeTypes.includes(fieldType)) {
|
|
161
|
-
return defaultOperators.filter((op) => numberOperators.includes(op.value))
|
|
162
|
-
}
|
|
163
|
-
if (fieldType === "boolean") {
|
|
164
|
-
return defaultOperators.filter((op) => booleanOperators.includes(op.value))
|
|
165
|
-
}
|
|
166
|
-
if (dateLikeTypes.includes(fieldType)) {
|
|
167
|
-
return defaultOperators.filter((op) => dateOperators.includes(op.value))
|
|
168
|
-
}
|
|
169
|
-
if (selectLikeTypes.includes(fieldType)) {
|
|
170
|
-
return defaultOperators.filter((op) => selectOperators.includes(op.value))
|
|
171
|
-
}
|
|
172
|
-
if (lookupLikeTypes.includes(fieldType)) {
|
|
173
|
-
return defaultOperators.filter((op) => lookupOperators.includes(op.value))
|
|
174
|
-
}
|
|
175
|
-
return defaultOperators.filter((op) => textOperators.includes(op.value))
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
const needsValueInput = (operator: string) => {
|
|
179
|
-
return !["isEmpty", "isNotEmpty"].includes(operator)
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
const getInputType = (fieldValue: string) => {
|
|
183
|
-
const field = fields.find((f) => f.value === fieldValue)
|
|
184
|
-
const fieldType = field?.type || "text"
|
|
185
|
-
|
|
186
|
-
if (numberLikeTypes.includes(fieldType)) return "number"
|
|
187
|
-
if (fieldType === "date") return "date"
|
|
188
|
-
if (fieldType === "datetime") return "datetime-local"
|
|
189
|
-
if (fieldType === "time") return "time"
|
|
190
|
-
return "text"
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
const renderValueInput = (condition: FilterCondition) => {
|
|
194
|
-
const field = fields.find((f) => f.value === condition.field)
|
|
195
|
-
const isMultiOperator = ["in", "notIn"].includes(condition.operator)
|
|
196
|
-
|
|
197
|
-
// For select/lookup fields with options and multi-select operator (in/notIn)
|
|
198
|
-
if (field?.options && isMultiOperator) {
|
|
199
|
-
const selectedValues = normalizeToArray(condition.value)
|
|
200
|
-
return (
|
|
201
|
-
<div className="max-h-40 overflow-y-auto space-y-0.5 border rounded-md p-2">
|
|
202
|
-
{field.options.map((opt) => {
|
|
203
|
-
const isChecked = selectedValues.map(String).includes(String(opt.value))
|
|
204
|
-
return (
|
|
205
|
-
<label
|
|
206
|
-
key={opt.value}
|
|
207
|
-
className={cn(
|
|
208
|
-
"flex items-center gap-2 text-sm py-1 px-1.5 rounded cursor-pointer",
|
|
209
|
-
isChecked ? "bg-primary/5 text-primary" : "hover:bg-muted",
|
|
210
|
-
)}
|
|
211
|
-
>
|
|
212
|
-
<Checkbox
|
|
213
|
-
checked={isChecked}
|
|
214
|
-
onCheckedChange={(checked) => {
|
|
215
|
-
const next = checked
|
|
216
|
-
? [...selectedValues, opt.value]
|
|
217
|
-
: selectedValues.filter((v) => String(v) !== String(opt.value))
|
|
218
|
-
updateCondition(condition.id, { value: next })
|
|
219
|
-
}}
|
|
220
|
-
/>
|
|
221
|
-
<span className="truncate">{opt.label}</span>
|
|
222
|
-
</label>
|
|
223
|
-
)
|
|
224
|
-
})}
|
|
225
|
-
</div>
|
|
226
|
-
)
|
|
227
|
-
}
|
|
228
|
-
|
|
229
|
-
// For select/lookup fields with options (single select)
|
|
230
|
-
if (field?.options && (selectLikeTypes.includes(field.type || "") || lookupLikeTypes.includes(field.type || ""))) {
|
|
231
|
-
return (
|
|
232
|
-
<Select
|
|
233
|
-
value={String(condition.value || "")}
|
|
234
|
-
onValueChange={(value) =>
|
|
235
|
-
updateCondition(condition.id, { value })
|
|
236
|
-
}
|
|
237
|
-
>
|
|
238
|
-
<SelectTrigger className="h-9 text-sm">
|
|
239
|
-
<SelectValue placeholder="Select value" />
|
|
240
|
-
</SelectTrigger>
|
|
241
|
-
<SelectContent>
|
|
242
|
-
{field.options.map((opt) => (
|
|
243
|
-
<SelectItem key={opt.value} value={opt.value}>
|
|
244
|
-
{opt.label}
|
|
245
|
-
</SelectItem>
|
|
246
|
-
))}
|
|
247
|
-
</SelectContent>
|
|
248
|
-
</Select>
|
|
249
|
-
)
|
|
250
|
-
}
|
|
251
|
-
|
|
252
|
-
// For boolean fields
|
|
253
|
-
if (field?.type === "boolean") {
|
|
254
|
-
return (
|
|
255
|
-
<Select
|
|
256
|
-
value={String(condition.value || "")}
|
|
257
|
-
onValueChange={(value) =>
|
|
258
|
-
updateCondition(condition.id, { value: value === "true" })
|
|
259
|
-
}
|
|
260
|
-
>
|
|
261
|
-
<SelectTrigger className="h-9 text-sm">
|
|
262
|
-
<SelectValue placeholder="Select value" />
|
|
263
|
-
</SelectTrigger>
|
|
264
|
-
<SelectContent>
|
|
265
|
-
<SelectItem value="true">True</SelectItem>
|
|
266
|
-
<SelectItem value="false">False</SelectItem>
|
|
267
|
-
</SelectContent>
|
|
268
|
-
</Select>
|
|
269
|
-
)
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
// Default input for text, number, date
|
|
273
|
-
const inputType = getInputType(condition.field)
|
|
274
|
-
|
|
275
|
-
// Format value based on field type
|
|
276
|
-
const formatValue = () => {
|
|
277
|
-
if (!condition.value) return ""
|
|
278
|
-
if (inputType === "date" && typeof condition.value === "string") {
|
|
279
|
-
// Ensure date is in YYYY-MM-DD format
|
|
280
|
-
return condition.value.split('T')[0]
|
|
281
|
-
}
|
|
282
|
-
return String(condition.value)
|
|
283
|
-
}
|
|
284
|
-
|
|
285
|
-
// Handle value change with proper type conversion
|
|
286
|
-
const handleValueChange = (newValue: string) => {
|
|
287
|
-
let convertedValue: string | number | boolean = newValue
|
|
288
|
-
|
|
289
|
-
if (numberLikeTypes.includes(field?.type || "") && newValue !== "") {
|
|
290
|
-
convertedValue = parseFloat(newValue) || 0
|
|
291
|
-
} else if (dateLikeTypes.includes(field?.type || "")) {
|
|
292
|
-
convertedValue = newValue // Keep as ISO string
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
updateCondition(condition.id, { value: convertedValue })
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return (
|
|
299
|
-
<Input
|
|
300
|
-
type={inputType}
|
|
301
|
-
className="h-9 text-sm"
|
|
302
|
-
placeholder="Value"
|
|
303
|
-
value={formatValue()}
|
|
304
|
-
onChange={(e) => handleValueChange(e.target.value)}
|
|
305
|
-
/>
|
|
306
|
-
)
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return (
|
|
310
|
-
<div className={cn("space-y-3", className)}>
|
|
311
|
-
<div className="flex items-center justify-between">
|
|
312
|
-
<div className="flex items-center gap-2">
|
|
313
|
-
<span className="text-sm font-medium">Where</span>
|
|
314
|
-
{filterGroup.conditions.length > 1 && (
|
|
315
|
-
<Button
|
|
316
|
-
variant="outline"
|
|
317
|
-
size="sm"
|
|
318
|
-
onClick={toggleLogic}
|
|
319
|
-
className="h-7 text-xs"
|
|
320
|
-
>
|
|
321
|
-
{filterGroup.logic.toUpperCase()}
|
|
322
|
-
</Button>
|
|
323
|
-
)}
|
|
324
|
-
</div>
|
|
325
|
-
{showClearAll && filterGroup.conditions.length > 0 && (
|
|
326
|
-
<Button
|
|
327
|
-
variant="ghost"
|
|
328
|
-
size="sm"
|
|
329
|
-
onClick={clearAllConditions}
|
|
330
|
-
className="h-7 text-xs text-muted-foreground hover:text-destructive"
|
|
331
|
-
>
|
|
332
|
-
<Trash2 className="h-3 w-3 mr-1" />
|
|
333
|
-
Clear all
|
|
334
|
-
</Button>
|
|
335
|
-
)}
|
|
336
|
-
</div>
|
|
337
|
-
|
|
338
|
-
<div className="space-y-2">
|
|
339
|
-
{filterGroup.conditions.map((condition) => (
|
|
340
|
-
<div key={condition.id} className="flex items-start gap-2">
|
|
341
|
-
<div className="flex-1 grid grid-cols-12 gap-2">
|
|
342
|
-
<div className="col-span-4">
|
|
343
|
-
<Select
|
|
344
|
-
value={condition.field}
|
|
345
|
-
onValueChange={(value) =>
|
|
346
|
-
updateCondition(condition.id, { field: value })
|
|
347
|
-
}
|
|
348
|
-
>
|
|
349
|
-
<SelectTrigger className="h-9 text-sm">
|
|
350
|
-
<SelectValue placeholder="Select field" />
|
|
351
|
-
</SelectTrigger>
|
|
352
|
-
<SelectContent>
|
|
353
|
-
{fields.map((field) => (
|
|
354
|
-
<SelectItem key={field.value} value={field.value}>
|
|
355
|
-
{field.label}
|
|
356
|
-
</SelectItem>
|
|
357
|
-
))}
|
|
358
|
-
</SelectContent>
|
|
359
|
-
</Select>
|
|
360
|
-
</div>
|
|
361
|
-
|
|
362
|
-
<div className="col-span-4">
|
|
363
|
-
<Select
|
|
364
|
-
value={condition.operator}
|
|
365
|
-
onValueChange={(value) =>
|
|
366
|
-
updateCondition(condition.id, { operator: value })
|
|
367
|
-
}
|
|
368
|
-
>
|
|
369
|
-
<SelectTrigger className="h-9 text-sm">
|
|
370
|
-
<SelectValue placeholder="Operator" />
|
|
371
|
-
</SelectTrigger>
|
|
372
|
-
<SelectContent>
|
|
373
|
-
{getOperatorsForField(condition.field).map((op) => (
|
|
374
|
-
<SelectItem key={op.value} value={op.value}>
|
|
375
|
-
{op.label}
|
|
376
|
-
</SelectItem>
|
|
377
|
-
))}
|
|
378
|
-
</SelectContent>
|
|
379
|
-
</Select>
|
|
380
|
-
</div>
|
|
381
|
-
|
|
382
|
-
{needsValueInput(condition.operator) && (
|
|
383
|
-
<div className="col-span-4">
|
|
384
|
-
{renderValueInput(condition)}
|
|
385
|
-
</div>
|
|
386
|
-
)}
|
|
387
|
-
</div>
|
|
388
|
-
|
|
389
|
-
<Button
|
|
390
|
-
variant="ghost"
|
|
391
|
-
size="icon"
|
|
392
|
-
className="h-9 w-9 shrink-0"
|
|
393
|
-
onClick={() => removeCondition(condition.id)}
|
|
394
|
-
>
|
|
395
|
-
<X className="h-4 w-4" />
|
|
396
|
-
<span className="sr-only">Remove condition</span>
|
|
397
|
-
</Button>
|
|
398
|
-
</div>
|
|
399
|
-
))}
|
|
400
|
-
</div>
|
|
401
|
-
|
|
402
|
-
<Button
|
|
403
|
-
variant="outline"
|
|
404
|
-
size="sm"
|
|
405
|
-
onClick={addCondition}
|
|
406
|
-
className="h-8"
|
|
407
|
-
disabled={fields.length === 0}
|
|
408
|
-
>
|
|
409
|
-
<Plus className="h-3 w-3" />
|
|
410
|
-
Add filter
|
|
411
|
-
</Button>
|
|
412
|
-
</div>
|
|
413
|
-
)
|
|
414
|
-
}
|
|
415
|
-
|
|
416
|
-
FilterBuilder.displayName = "FilterBuilder"
|
|
417
|
-
|
|
418
|
-
export { FilterBuilder }
|
package/src/custom/index.ts
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
export * from './button-group';
|
|
2
|
-
export * from './combobox';
|
|
3
|
-
export * from './config-row';
|
|
4
|
-
export * from './config-field-renderer';
|
|
5
|
-
export * from './config-panel-renderer';
|
|
6
|
-
export * from './date-picker';
|
|
7
|
-
export * from './empty';
|
|
8
|
-
export * from './field';
|
|
9
|
-
export * from './filter-builder';
|
|
10
|
-
export * from './input-group';
|
|
11
|
-
export * from './item';
|
|
12
|
-
export * from './kbd';
|
|
13
|
-
export * from './native-select';
|
|
14
|
-
export * from './navigation-overlay';
|
|
15
|
-
export * from './section-header';
|
|
16
|
-
export * from './spinner';
|
|
17
|
-
export * from './sort-builder';
|
|
18
|
-
export * from './action-param-dialog';
|
|
19
|
-
export * from './view-skeleton';
|
|
20
|
-
export * from './view-states';
|
|
21
|
-
export * from './mobile-dialog-content';
|
|
@@ -1,53 +0,0 @@
|
|
|
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 { cn } from "../lib/utils"
|
|
11
|
-
import { Input } from "../ui/input"
|
|
12
|
-
import { Button } from "../ui/button"
|
|
13
|
-
|
|
14
|
-
export interface InputGroupProps extends React.ComponentProps<"div"> {
|
|
15
|
-
startContent?: React.ReactNode
|
|
16
|
-
endContent?: React.ReactNode
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
const InputGroup = React.forwardRef<HTMLDivElement, InputGroupProps>(
|
|
20
|
-
({ className, startContent, endContent, children, ...props }, ref) => {
|
|
21
|
-
return (
|
|
22
|
-
<div
|
|
23
|
-
ref={ref}
|
|
24
|
-
className={cn(
|
|
25
|
-
"flex w-full items-center rounded-md border border-input bg-transparent ring-offset-background focus-within:ring-2 focus-within:ring-ring focus-within:ring-offset-2",
|
|
26
|
-
"has-[[data-invalid]]:border-destructive",
|
|
27
|
-
className
|
|
28
|
-
)}
|
|
29
|
-
{...props}
|
|
30
|
-
>
|
|
31
|
-
{startContent && (
|
|
32
|
-
<div className="flex items-center px-3 text-muted-foreground bg-muted/50 border-r h-full self-stretch rounded-l-md">
|
|
33
|
-
{startContent}
|
|
34
|
-
</div>
|
|
35
|
-
)}
|
|
36
|
-
|
|
37
|
-
{/* We need to process children to remove their default borders/rings if they are Inputs */}
|
|
38
|
-
<div className="flex-1 relative [&_input]:border-0 [&_input]:shadow-none [&_input]:focus-visible:ring-0 [&_input]:bg-transparent">
|
|
39
|
-
{children}
|
|
40
|
-
</div>
|
|
41
|
-
|
|
42
|
-
{endContent && (
|
|
43
|
-
<div className="flex items-center px-3 text-muted-foreground bg-muted/50 border-l h-full self-stretch rounded-r-md">
|
|
44
|
-
{endContent}
|
|
45
|
-
</div>
|
|
46
|
-
)}
|
|
47
|
-
</div>
|
|
48
|
-
)
|
|
49
|
-
}
|
|
50
|
-
)
|
|
51
|
-
InputGroup.displayName = "InputGroup"
|
|
52
|
-
|
|
53
|
-
export { InputGroup }
|