@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
|
@@ -1,49 +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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { ImageSchema } from '@object-ui/types';
|
|
11
|
-
|
|
12
|
-
ComponentRegistry.register('image',
|
|
13
|
-
({ schema, className, ...props }: { schema: ImageSchema; className?: string; [key: string]: any }) => {
|
|
14
|
-
// Extract designer-related props
|
|
15
|
-
const {
|
|
16
|
-
'data-obj-id': dataObjId,
|
|
17
|
-
'data-obj-type': dataObjType,
|
|
18
|
-
style,
|
|
19
|
-
...imgProps
|
|
20
|
-
} = props;
|
|
21
|
-
|
|
22
|
-
return (
|
|
23
|
-
<img
|
|
24
|
-
src={schema.src}
|
|
25
|
-
alt={schema.alt || ''}
|
|
26
|
-
className={className}
|
|
27
|
-
{...imgProps}
|
|
28
|
-
// Apply designer props
|
|
29
|
-
data-obj-id={dataObjId}
|
|
30
|
-
data-obj-type={dataObjType}
|
|
31
|
-
style={style}
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
namespace: 'ui',
|
|
37
|
-
label: 'Image',
|
|
38
|
-
icon: 'image',
|
|
39
|
-
category: 'basic',
|
|
40
|
-
inputs: [
|
|
41
|
-
{ name: 'src', type: 'string', label: 'Source URL' },
|
|
42
|
-
{ name: 'alt', type: 'string', label: 'Alt Text' },
|
|
43
|
-
{ name: 'className', type: 'string', label: 'Classes' }
|
|
44
|
-
],
|
|
45
|
-
defaultProps: {
|
|
46
|
-
className: 'max-w-full h-auto'
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
);
|
|
@@ -1,18 +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 './div';
|
|
10
|
-
import './text';
|
|
11
|
-
import './span';
|
|
12
|
-
import './separator';
|
|
13
|
-
import './image';
|
|
14
|
-
import './icon';
|
|
15
|
-
import './html';
|
|
16
|
-
import './button-group';
|
|
17
|
-
import './pagination';
|
|
18
|
-
import './navigation-menu';
|
|
@@ -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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { NavigationMenuSchema } from '@object-ui/types';
|
|
11
|
-
import { NavigationMenu, NavigationMenuList, NavigationMenuItem, NavigationMenuTrigger, NavigationMenuContent, NavigationMenuLink } from '../../ui/navigation-menu';
|
|
12
|
-
import { cn } from '../../lib/utils';
|
|
13
|
-
|
|
14
|
-
ComponentRegistry.register('navigation-menu',
|
|
15
|
-
({ schema, ...props }: { schema: NavigationMenuSchema; [key: string]: any }) => {
|
|
16
|
-
const {
|
|
17
|
-
'data-obj-id': dataObjId,
|
|
18
|
-
'data-obj-type': dataObjType,
|
|
19
|
-
style,
|
|
20
|
-
...navigationMenuProps
|
|
21
|
-
} = props;
|
|
22
|
-
|
|
23
|
-
return (
|
|
24
|
-
<NavigationMenu
|
|
25
|
-
className={schema.className}
|
|
26
|
-
{...navigationMenuProps}
|
|
27
|
-
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
|
|
28
|
-
>
|
|
29
|
-
<NavigationMenuList>
|
|
30
|
-
{schema.items?.map((item, idx) => (
|
|
31
|
-
<NavigationMenuItem key={idx}>
|
|
32
|
-
{item.children ? (
|
|
33
|
-
<>
|
|
34
|
-
<NavigationMenuTrigger>{item.label}</NavigationMenuTrigger>
|
|
35
|
-
<NavigationMenuContent>
|
|
36
|
-
<ul className="grid w-full gap-3 p-4 sm:w-[400px] md:w-[500px] md:grid-cols-2 lg:w-[600px]">
|
|
37
|
-
{item.children.map((child, childIdx) => (
|
|
38
|
-
<li key={childIdx}>
|
|
39
|
-
<NavigationMenuLink asChild>
|
|
40
|
-
<a
|
|
41
|
-
className={cn(
|
|
42
|
-
"block select-none space-y-1 rounded-md p-3 leading-none no-underline outline-none transition-colors hover:bg-accent hover:text-accent-foreground focus:bg-accent focus:text-accent-foreground"
|
|
43
|
-
)}
|
|
44
|
-
href={child.href}
|
|
45
|
-
>
|
|
46
|
-
<div className="text-sm font-medium leading-none">{child.label}</div>
|
|
47
|
-
{child.description && (
|
|
48
|
-
<p className="line-clamp-2 text-sm leading-snug text-muted-foreground">
|
|
49
|
-
{child.description}
|
|
50
|
-
</p>
|
|
51
|
-
)}
|
|
52
|
-
</a>
|
|
53
|
-
</NavigationMenuLink>
|
|
54
|
-
</li>
|
|
55
|
-
))}
|
|
56
|
-
</ul>
|
|
57
|
-
</NavigationMenuContent>
|
|
58
|
-
</>
|
|
59
|
-
) : (
|
|
60
|
-
<NavigationMenuLink href={item.href}>{item.label}</NavigationMenuLink>
|
|
61
|
-
)}
|
|
62
|
-
</NavigationMenuItem>
|
|
63
|
-
))}
|
|
64
|
-
</NavigationMenuList>
|
|
65
|
-
</NavigationMenu>
|
|
66
|
-
);
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
namespace: 'ui',
|
|
70
|
-
label: 'Navigation Menu',
|
|
71
|
-
inputs: [
|
|
72
|
-
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
73
|
-
],
|
|
74
|
-
defaultProps: {
|
|
75
|
-
items: [
|
|
76
|
-
{ label: 'Home', href: '/' },
|
|
77
|
-
{ label: 'About', href: '/about' }
|
|
78
|
-
]
|
|
79
|
-
}
|
|
80
|
-
}
|
|
81
|
-
);
|
|
@@ -1,109 +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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { PaginationSchema } from '@object-ui/types';
|
|
11
|
-
import { Pagination, PaginationContent, PaginationEllipsis, PaginationItem, PaginationLink, PaginationNext, PaginationPrevious } from '../../ui/pagination';
|
|
12
|
-
import React from 'react';
|
|
13
|
-
|
|
14
|
-
ComponentRegistry.register('pagination',
|
|
15
|
-
({ schema, ...props }: { schema: PaginationSchema; [key: string]: any }) => {
|
|
16
|
-
const {
|
|
17
|
-
'data-obj-id': dataObjId,
|
|
18
|
-
'data-obj-type': dataObjType,
|
|
19
|
-
style,
|
|
20
|
-
onPageChange,
|
|
21
|
-
...paginationProps
|
|
22
|
-
} = props;
|
|
23
|
-
|
|
24
|
-
const currentPage = schema.currentPage || schema.page || 1;
|
|
25
|
-
const totalPages = schema.totalPages || 1;
|
|
26
|
-
|
|
27
|
-
const handlePageChange = (page: number, e: React.MouseEvent) => {
|
|
28
|
-
e.preventDefault();
|
|
29
|
-
if (page === currentPage) return;
|
|
30
|
-
if (page < 1 || page > totalPages) return;
|
|
31
|
-
|
|
32
|
-
if (onPageChange) {
|
|
33
|
-
onPageChange(page);
|
|
34
|
-
}
|
|
35
|
-
};
|
|
36
|
-
|
|
37
|
-
const getPageNumbers = () => {
|
|
38
|
-
if (totalPages <= 7) {
|
|
39
|
-
return Array.from({ length: totalPages }, (_, i) => i + 1);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
if (currentPage <= 3) {
|
|
43
|
-
return [1, 2, 3, 4, 5, -1, totalPages];
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
if (currentPage >= totalPages - 2) {
|
|
47
|
-
return [1, -1, totalPages - 4, totalPages - 3, totalPages - 2, totalPages - 1, totalPages];
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
return [1, -1, currentPage - 1, currentPage, currentPage + 1, -1, totalPages];
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
return (
|
|
54
|
-
<Pagination
|
|
55
|
-
className={schema.className}
|
|
56
|
-
{...paginationProps}
|
|
57
|
-
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
|
|
58
|
-
>
|
|
59
|
-
<PaginationContent>
|
|
60
|
-
<PaginationItem>
|
|
61
|
-
<PaginationPrevious
|
|
62
|
-
href="#"
|
|
63
|
-
onClick={(e) => handlePageChange(currentPage - 1, e)}
|
|
64
|
-
className={currentPage <= 1 ? "pointer-events-none opacity-50" : "cursor-pointer"}
|
|
65
|
-
aria-disabled={currentPage <= 1}
|
|
66
|
-
/>
|
|
67
|
-
</PaginationItem>
|
|
68
|
-
{getPageNumbers().map((page, idx) => (
|
|
69
|
-
<PaginationItem key={idx}>
|
|
70
|
-
{page === -1 ? (
|
|
71
|
-
<PaginationEllipsis />
|
|
72
|
-
) : (
|
|
73
|
-
<PaginationLink
|
|
74
|
-
href="#"
|
|
75
|
-
isActive={page === currentPage}
|
|
76
|
-
onClick={(e) => handlePageChange(page, e)}
|
|
77
|
-
className="cursor-pointer"
|
|
78
|
-
>
|
|
79
|
-
{page}
|
|
80
|
-
</PaginationLink>
|
|
81
|
-
)}
|
|
82
|
-
</PaginationItem>
|
|
83
|
-
))}
|
|
84
|
-
<PaginationItem>
|
|
85
|
-
<PaginationNext
|
|
86
|
-
href="#"
|
|
87
|
-
onClick={(e) => handlePageChange(currentPage + 1, e)}
|
|
88
|
-
className={currentPage >= totalPages ? "pointer-events-none opacity-50" : "cursor-pointer"}
|
|
89
|
-
aria-disabled={currentPage >= totalPages}
|
|
90
|
-
/>
|
|
91
|
-
</PaginationItem>
|
|
92
|
-
</PaginationContent>
|
|
93
|
-
</Pagination>
|
|
94
|
-
);
|
|
95
|
-
},
|
|
96
|
-
{
|
|
97
|
-
namespace: 'ui',
|
|
98
|
-
label: 'Pagination',
|
|
99
|
-
inputs: [
|
|
100
|
-
{ name: 'currentPage', type: 'number', label: 'Current Page', defaultValue: 1 },
|
|
101
|
-
{ name: 'totalPages', type: 'number', label: 'Total Pages', defaultValue: 10 },
|
|
102
|
-
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
103
|
-
],
|
|
104
|
-
defaultProps: {
|
|
105
|
-
currentPage: 1,
|
|
106
|
-
totalPages: 10
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
);
|
|
@@ -1,57 +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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { SeparatorSchema } from '@object-ui/types';
|
|
11
|
-
import { Separator } from '../../ui';
|
|
12
|
-
import { forwardRef } from 'react';
|
|
13
|
-
|
|
14
|
-
const SeparatorRenderer = forwardRef<HTMLDivElement, { schema: SeparatorSchema; className?: string; [key: string]: any }>(
|
|
15
|
-
({ schema, className, ...props }, ref) => {
|
|
16
|
-
// Extract designer-related props
|
|
17
|
-
const {
|
|
18
|
-
'data-obj-id': dataObjId,
|
|
19
|
-
'data-obj-type': dataObjType,
|
|
20
|
-
style,
|
|
21
|
-
...separatorProps
|
|
22
|
-
} = props;
|
|
23
|
-
|
|
24
|
-
return (
|
|
25
|
-
<Separator
|
|
26
|
-
ref={ref}
|
|
27
|
-
orientation={schema.orientation}
|
|
28
|
-
className={className}
|
|
29
|
-
{...separatorProps}
|
|
30
|
-
// Apply designer props
|
|
31
|
-
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
|
|
32
|
-
/>
|
|
33
|
-
);
|
|
34
|
-
}
|
|
35
|
-
);
|
|
36
|
-
|
|
37
|
-
ComponentRegistry.register('separator',
|
|
38
|
-
SeparatorRenderer,
|
|
39
|
-
{
|
|
40
|
-
namespace: 'ui',
|
|
41
|
-
label: 'Separator',
|
|
42
|
-
inputs: [
|
|
43
|
-
{
|
|
44
|
-
name: 'orientation',
|
|
45
|
-
type: 'enum',
|
|
46
|
-
enum: ['horizontal', 'vertical'],
|
|
47
|
-
defaultValue: 'horizontal',
|
|
48
|
-
label: 'Orientation'
|
|
49
|
-
},
|
|
50
|
-
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
51
|
-
],
|
|
52
|
-
defaultProps: {
|
|
53
|
-
orientation: 'horizontal',
|
|
54
|
-
className: 'my-2 sm:my-4'
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
);
|
|
@@ -1,63 +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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { SpanSchema } from '@object-ui/types';
|
|
11
|
-
import { renderChildren } from '../../lib/utils';
|
|
12
|
-
import { forwardRef } from 'react';
|
|
13
|
-
|
|
14
|
-
const SpanRenderer = forwardRef<HTMLSpanElement, { schema: SpanSchema; className?: string; [key: string]: any }>(
|
|
15
|
-
({ schema, className, ...props }, ref) => {
|
|
16
|
-
// Deprecation warning
|
|
17
|
-
if (process.env.NODE_ENV !== 'production') {
|
|
18
|
-
console.warn(
|
|
19
|
-
'[ObjectUI] The "span" component is deprecated. Please use Shadcn components instead:\n' +
|
|
20
|
-
' - For badges/labels: use "badge" component\n' +
|
|
21
|
-
' - For inline text emphasis: use "text" component with appropriate className\n' +
|
|
22
|
-
'See documentation at https://www.objectui.org/docs/components for alternatives.'
|
|
23
|
-
);
|
|
24
|
-
}
|
|
25
|
-
|
|
26
|
-
// Extract designer-related props
|
|
27
|
-
const {
|
|
28
|
-
'data-obj-id': dataObjId,
|
|
29
|
-
'data-obj-type': dataObjType,
|
|
30
|
-
style,
|
|
31
|
-
...spanProps
|
|
32
|
-
} = props;
|
|
33
|
-
|
|
34
|
-
return (
|
|
35
|
-
<span
|
|
36
|
-
ref={ref}
|
|
37
|
-
className={className}
|
|
38
|
-
{...spanProps}
|
|
39
|
-
// Apply designer props
|
|
40
|
-
{...{ 'data-obj-id': dataObjId, 'data-obj-type': dataObjType, style }}
|
|
41
|
-
>
|
|
42
|
-
{renderChildren(schema.body)}
|
|
43
|
-
</span>
|
|
44
|
-
);
|
|
45
|
-
}
|
|
46
|
-
);
|
|
47
|
-
|
|
48
|
-
ComponentRegistry.register('span',
|
|
49
|
-
SpanRenderer,
|
|
50
|
-
{
|
|
51
|
-
namespace: 'ui',
|
|
52
|
-
label: 'Inline Container (Deprecated)',
|
|
53
|
-
inputs: [
|
|
54
|
-
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
55
|
-
],
|
|
56
|
-
defaultProps: {
|
|
57
|
-
className: 'px-1.5 py-0.5 sm:px-2 sm:py-1'
|
|
58
|
-
},
|
|
59
|
-
defaultChildren: [
|
|
60
|
-
{ type: 'text', content: 'Inline text' }
|
|
61
|
-
]
|
|
62
|
-
}
|
|
63
|
-
);
|
|
@@ -1,52 +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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { TextSchema } from '@object-ui/types';
|
|
11
|
-
|
|
12
|
-
ComponentRegistry.register('text',
|
|
13
|
-
({ schema, ...props }: { schema: TextSchema; [key: string]: any }) => {
|
|
14
|
-
// Text is a special case as it might be rendered as a fragment or span depending on usage.
|
|
15
|
-
// However, to support drag and drop in designer, it MUST be wrapped in an element if props are passed.
|
|
16
|
-
|
|
17
|
-
// Extract designer-related props
|
|
18
|
-
const {
|
|
19
|
-
'data-obj-id': dataObjId,
|
|
20
|
-
'data-obj-type': dataObjType,
|
|
21
|
-
style,
|
|
22
|
-
...rest
|
|
23
|
-
} = props;
|
|
24
|
-
|
|
25
|
-
// If we have designer props or className, we must wrap it to make it selectable and styleable
|
|
26
|
-
if (dataObjId || schema.className || rest.className) {
|
|
27
|
-
return (
|
|
28
|
-
<span
|
|
29
|
-
data-obj-id={dataObjId}
|
|
30
|
-
data-obj-type={dataObjType}
|
|
31
|
-
style={style}
|
|
32
|
-
className={schema.className || rest.className}
|
|
33
|
-
{...rest}
|
|
34
|
-
>
|
|
35
|
-
{schema.content || schema.value}
|
|
36
|
-
</span>
|
|
37
|
-
);
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
return <>{schema.content || schema.value}</>;
|
|
41
|
-
},
|
|
42
|
-
{
|
|
43
|
-
namespace: 'ui',
|
|
44
|
-
label: 'Text',
|
|
45
|
-
inputs: [
|
|
46
|
-
{ name: 'content', type: 'string', label: 'Content', required: true }
|
|
47
|
-
],
|
|
48
|
-
defaultProps: {
|
|
49
|
-
content: 'Text content'
|
|
50
|
-
}
|
|
51
|
-
}
|
|
52
|
-
);
|
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
# Kanban Board Component
|
|
2
|
-
|
|
3
|
-
A fully functional, schema-driven Kanban board component for Object UI with drag-and-drop support.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- **Multiple Columns**: Create unlimited columns with customizable titles
|
|
8
|
-
- **Rich Cards**: Cards support title, description, and multiple badges
|
|
9
|
-
- **Drag & Drop**: Smooth drag-and-drop functionality powered by @dnd-kit
|
|
10
|
-
- **Reordering**: Reorder cards within the same column
|
|
11
|
-
- **Cross-Column Moves**: Move cards between different columns
|
|
12
|
-
- **Column Limits**: Optional capacity limits with visual indicators
|
|
13
|
-
- **Card Counters**: Shows current count and limit per column
|
|
14
|
-
- **Schema-Driven**: Configure entirely through JSON/YAML
|
|
15
|
-
- **Event Callbacks**: Custom event handling for card movements
|
|
16
|
-
|
|
17
|
-
## Usage
|
|
18
|
-
|
|
19
|
-
### Basic Example
|
|
20
|
-
|
|
21
|
-
```json
|
|
22
|
-
{
|
|
23
|
-
"type": "kanban",
|
|
24
|
-
"className": "w-full h-[600px]",
|
|
25
|
-
"columns": [
|
|
26
|
-
{
|
|
27
|
-
"id": "todo",
|
|
28
|
-
"title": "To Do",
|
|
29
|
-
"cards": [
|
|
30
|
-
{
|
|
31
|
-
"id": "card-1",
|
|
32
|
-
"title": "Task Title",
|
|
33
|
-
"description": "Task description",
|
|
34
|
-
"badges": [
|
|
35
|
-
{ "label": "High Priority", "variant": "destructive" }
|
|
36
|
-
]
|
|
37
|
-
}
|
|
38
|
-
]
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
"id": "in-progress",
|
|
42
|
-
"title": "In Progress",
|
|
43
|
-
"limit": 3,
|
|
44
|
-
"cards": []
|
|
45
|
-
},
|
|
46
|
-
{
|
|
47
|
-
"id": "done",
|
|
48
|
-
"title": "Done",
|
|
49
|
-
"cards": []
|
|
50
|
-
}
|
|
51
|
-
]
|
|
52
|
-
}
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
### With Event Handling
|
|
56
|
-
|
|
57
|
-
```json
|
|
58
|
-
{
|
|
59
|
-
"type": "kanban",
|
|
60
|
-
"columns": [...],
|
|
61
|
-
"onCardMove": "(event) => { console.log('Card moved:', event); }"
|
|
62
|
-
}
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
## Schema Reference
|
|
66
|
-
|
|
67
|
-
### Kanban Props
|
|
68
|
-
|
|
69
|
-
| Property | Type | Required | Description |
|
|
70
|
-
|----------|------|----------|-------------|
|
|
71
|
-
| `type` | `"kanban"` | Yes | Component type identifier |
|
|
72
|
-
| `columns` | `KanbanColumn[]` | Yes | Array of column configurations |
|
|
73
|
-
| `className` | `string` | No | Custom CSS classes |
|
|
74
|
-
| `onCardMove` | `function` | No | Callback when a card is moved |
|
|
75
|
-
|
|
76
|
-
### KanbanColumn
|
|
77
|
-
|
|
78
|
-
| Property | Type | Required | Description |
|
|
79
|
-
|----------|------|----------|-------------|
|
|
80
|
-
| `id` | `string` | Yes | Unique column identifier |
|
|
81
|
-
| `title` | `string` | Yes | Column header title |
|
|
82
|
-
| `cards` | `KanbanCard[]` | Yes | Array of cards in this column |
|
|
83
|
-
| `limit` | `number` | No | Maximum number of cards allowed |
|
|
84
|
-
| `className` | `string` | No | Custom CSS classes for column |
|
|
85
|
-
|
|
86
|
-
### KanbanCard
|
|
87
|
-
|
|
88
|
-
| Property | Type | Required | Description |
|
|
89
|
-
|----------|------|----------|-------------|
|
|
90
|
-
| `id` | `string` | Yes | Unique card identifier |
|
|
91
|
-
| `title` | `string` | Yes | Card title |
|
|
92
|
-
| `description` | `string` | No | Card description text |
|
|
93
|
-
| `badges` | `Badge[]` | No | Array of badge objects |
|
|
94
|
-
|
|
95
|
-
### Badge
|
|
96
|
-
|
|
97
|
-
| Property | Type | Required | Description |
|
|
98
|
-
|----------|------|----------|-------------|
|
|
99
|
-
| `label` | `string` | Yes | Badge text |
|
|
100
|
-
| `variant` | `"default" \| "secondary" \| "destructive" \| "outline"` | No | Badge color variant |
|
|
101
|
-
|
|
102
|
-
## Examples
|
|
103
|
-
|
|
104
|
-
### Simple Task Board
|
|
105
|
-
|
|
106
|
-
```json
|
|
107
|
-
{
|
|
108
|
-
"type": "kanban",
|
|
109
|
-
"columns": [
|
|
110
|
-
{
|
|
111
|
-
"id": "backlog",
|
|
112
|
-
"title": "📋 Backlog",
|
|
113
|
-
"cards": [
|
|
114
|
-
{
|
|
115
|
-
"id": "1",
|
|
116
|
-
"title": "Setup project",
|
|
117
|
-
"badges": [{ "label": "Setup" }]
|
|
118
|
-
}
|
|
119
|
-
]
|
|
120
|
-
},
|
|
121
|
-
{
|
|
122
|
-
"id": "doing",
|
|
123
|
-
"title": "🚀 Doing",
|
|
124
|
-
"limit": 2,
|
|
125
|
-
"cards": []
|
|
126
|
-
},
|
|
127
|
-
{
|
|
128
|
-
"id": "done",
|
|
129
|
-
"title": "✅ Done",
|
|
130
|
-
"cards": []
|
|
131
|
-
}
|
|
132
|
-
]
|
|
133
|
-
}
|
|
134
|
-
```
|
|
135
|
-
|
|
136
|
-
### Issue Tracking Board
|
|
137
|
-
|
|
138
|
-
```json
|
|
139
|
-
{
|
|
140
|
-
"type": "kanban",
|
|
141
|
-
"columns": [
|
|
142
|
-
{
|
|
143
|
-
"id": "new",
|
|
144
|
-
"title": "New Issues",
|
|
145
|
-
"cards": [
|
|
146
|
-
{
|
|
147
|
-
"id": "issue-1",
|
|
148
|
-
"title": "Bug: Login fails on Safari",
|
|
149
|
-
"description": "Users can't login using Safari browser",
|
|
150
|
-
"badges": [
|
|
151
|
-
{ "label": "Bug", "variant": "destructive" },
|
|
152
|
-
{ "label": "P0", "variant": "destructive" }
|
|
153
|
-
]
|
|
154
|
-
}
|
|
155
|
-
]
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
"id": "investigating",
|
|
159
|
-
"title": "Investigating",
|
|
160
|
-
"limit": 3,
|
|
161
|
-
"cards": []
|
|
162
|
-
},
|
|
163
|
-
{
|
|
164
|
-
"id": "fixed",
|
|
165
|
-
"title": "Fixed",
|
|
166
|
-
"cards": []
|
|
167
|
-
}
|
|
168
|
-
]
|
|
169
|
-
}
|
|
170
|
-
```
|
|
171
|
-
|
|
172
|
-
## Styling
|
|
173
|
-
|
|
174
|
-
The Kanban component uses Tailwind CSS and can be customized using the `className` prop:
|
|
175
|
-
|
|
176
|
-
```json
|
|
177
|
-
{
|
|
178
|
-
"type": "kanban",
|
|
179
|
-
"className": "w-full h-[800px] bg-gray-50 p-4 rounded-lg",
|
|
180
|
-
"columns": [...]
|
|
181
|
-
}
|
|
182
|
-
```
|
|
183
|
-
|
|
184
|
-
Individual columns can also be styled:
|
|
185
|
-
|
|
186
|
-
```json
|
|
187
|
-
{
|
|
188
|
-
"id": "urgent",
|
|
189
|
-
"title": "🔥 Urgent",
|
|
190
|
-
"className": "bg-red-50",
|
|
191
|
-
"cards": [...]
|
|
192
|
-
}
|
|
193
|
-
```
|
|
194
|
-
|
|
195
|
-
## Technical Details
|
|
196
|
-
|
|
197
|
-
- Built with React 18+ and TypeScript
|
|
198
|
-
- Uses @dnd-kit for drag-and-drop functionality
|
|
199
|
-
- Integrates with Shadcn UI components (Card, Badge, ScrollArea)
|
|
200
|
-
- Supports both pointer and touch interactions
|
|
201
|
-
- Accessible keyboard navigation (via @dnd-kit)
|
|
202
|
-
|
|
203
|
-
## Browser Support
|
|
204
|
-
|
|
205
|
-
- Chrome/Edge: Full support
|
|
206
|
-
- Firefox: Full support
|
|
207
|
-
- Safari: Full support
|
|
208
|
-
- Mobile browsers: Full support with touch gestures
|