@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,120 +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
|
-
/**
|
|
10
|
-
* Mobile Accessibility Audit — axe-core checks at mobile viewport widths.
|
|
11
|
-
*
|
|
12
|
-
* Verifies that common UI patterns (buttons, forms, navigation, dialogs,
|
|
13
|
-
* tables) remain WCAG 2.1 AA compliant when rendered in a narrow container
|
|
14
|
-
* that simulates a mobile viewport. Part of P3 Mobile Testing & QA.
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { describe, it, expect } from 'vitest';
|
|
18
|
-
import { render } from '@testing-library/react';
|
|
19
|
-
import { axe } from 'vitest-axe';
|
|
20
|
-
import React from 'react';
|
|
21
|
-
|
|
22
|
-
async function expectNoViolations(container: HTMLElement) {
|
|
23
|
-
const results = await axe(container);
|
|
24
|
-
const violations = (results as any).violations || [];
|
|
25
|
-
if (violations.length > 0) {
|
|
26
|
-
const messages = violations.map(
|
|
27
|
-
(v: any) => `[${v.impact}] ${v.id}: ${v.description} (${v.nodes.length} instance(s))`,
|
|
28
|
-
);
|
|
29
|
-
throw new Error(
|
|
30
|
-
`Expected no accessibility violations, but found ${violations.length}:\n${messages.join('\n')}`,
|
|
31
|
-
);
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
const MOBILE_WIDTH = 375;
|
|
36
|
-
|
|
37
|
-
describe('Mobile Accessibility Audit', () => {
|
|
38
|
-
it('should have no axe violations for Button at mobile viewport', async () => {
|
|
39
|
-
const { container } = render(
|
|
40
|
-
<div style={{ width: `${MOBILE_WIDTH}px` }}>
|
|
41
|
-
<button type="button">Click me</button>
|
|
42
|
-
</div>,
|
|
43
|
-
);
|
|
44
|
-
await expectNoViolations(container);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it('should have no axe violations for form inputs at mobile viewport', async () => {
|
|
48
|
-
const { container } = render(
|
|
49
|
-
<div style={{ width: `${MOBILE_WIDTH}px` }}>
|
|
50
|
-
<form>
|
|
51
|
-
<label htmlFor="name">Name</label>
|
|
52
|
-
<input id="name" type="text" />
|
|
53
|
-
<label htmlFor="email">Email</label>
|
|
54
|
-
<input id="email" type="email" />
|
|
55
|
-
<button type="submit">Submit</button>
|
|
56
|
-
</form>
|
|
57
|
-
</div>,
|
|
58
|
-
);
|
|
59
|
-
await expectNoViolations(container);
|
|
60
|
-
});
|
|
61
|
-
|
|
62
|
-
it('should have no axe violations for navigation at mobile viewport', async () => {
|
|
63
|
-
const { container } = render(
|
|
64
|
-
<div style={{ width: `${MOBILE_WIDTH}px` }}>
|
|
65
|
-
<nav aria-label="Main navigation">
|
|
66
|
-
<ul>
|
|
67
|
-
<li>
|
|
68
|
-
<a href="/">Home</a>
|
|
69
|
-
</li>
|
|
70
|
-
<li>
|
|
71
|
-
<a href="/about">About</a>
|
|
72
|
-
</li>
|
|
73
|
-
</ul>
|
|
74
|
-
</nav>
|
|
75
|
-
</div>,
|
|
76
|
-
);
|
|
77
|
-
await expectNoViolations(container);
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it('should have no axe violations for dialog at mobile viewport', async () => {
|
|
81
|
-
const { container } = render(
|
|
82
|
-
<div style={{ width: `${MOBILE_WIDTH}px` }}>
|
|
83
|
-
<div role="dialog" aria-label="Confirmation" aria-modal="true">
|
|
84
|
-
<h2>Confirm Action</h2>
|
|
85
|
-
<p>Are you sure?</p>
|
|
86
|
-
<button type="button">Yes</button>
|
|
87
|
-
<button type="button">No</button>
|
|
88
|
-
</div>
|
|
89
|
-
</div>,
|
|
90
|
-
);
|
|
91
|
-
await expectNoViolations(container);
|
|
92
|
-
});
|
|
93
|
-
|
|
94
|
-
it('should have no axe violations for data table at mobile viewport', async () => {
|
|
95
|
-
const { container } = render(
|
|
96
|
-
<div style={{ width: `${MOBILE_WIDTH}px`, overflow: 'auto' }}>
|
|
97
|
-
<table>
|
|
98
|
-
<caption>Sample data</caption>
|
|
99
|
-
<thead>
|
|
100
|
-
<tr>
|
|
101
|
-
<th>Name</th>
|
|
102
|
-
<th>Value</th>
|
|
103
|
-
</tr>
|
|
104
|
-
</thead>
|
|
105
|
-
<tbody>
|
|
106
|
-
<tr>
|
|
107
|
-
<td>Item 1</td>
|
|
108
|
-
<td>100</td>
|
|
109
|
-
</tr>
|
|
110
|
-
<tr>
|
|
111
|
-
<td>Item 2</td>
|
|
112
|
-
<td>200</td>
|
|
113
|
-
</tr>
|
|
114
|
-
</tbody>
|
|
115
|
-
</table>
|
|
116
|
-
</div>,
|
|
117
|
-
);
|
|
118
|
-
await expectNoViolations(container);
|
|
119
|
-
});
|
|
120
|
-
});
|
|
@@ -1,370 +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 { describe, it, expect, vi } from 'vitest';
|
|
10
|
-
import { render, screen, fireEvent } from '@testing-library/react';
|
|
11
|
-
import React from 'react';
|
|
12
|
-
import { NavigationOverlay } from '../custom/navigation-overlay';
|
|
13
|
-
import type { NavigationOverlayProps } from '../custom/navigation-overlay';
|
|
14
|
-
|
|
15
|
-
// Helper to create default props
|
|
16
|
-
function createProps(overrides: Partial<NavigationOverlayProps> = {}): NavigationOverlayProps {
|
|
17
|
-
return {
|
|
18
|
-
isOpen: true,
|
|
19
|
-
selectedRecord: { id: '1', name: 'Test Record', email: 'test@example.com' },
|
|
20
|
-
mode: 'drawer',
|
|
21
|
-
close: vi.fn(),
|
|
22
|
-
setIsOpen: vi.fn(),
|
|
23
|
-
isOverlay: true,
|
|
24
|
-
children: (record: Record<string, unknown>) => (
|
|
25
|
-
<div data-testid="record-content">
|
|
26
|
-
<span>{String(record.name)}</span>
|
|
27
|
-
</div>
|
|
28
|
-
),
|
|
29
|
-
...overrides,
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
describe('NavigationOverlay', () => {
|
|
34
|
-
// ============================================================
|
|
35
|
-
// Non-overlay modes
|
|
36
|
-
// ============================================================
|
|
37
|
-
|
|
38
|
-
describe('non-overlay modes', () => {
|
|
39
|
-
it('should render nothing for mode: page', () => {
|
|
40
|
-
const { container } = render(
|
|
41
|
-
<NavigationOverlay {...createProps({ mode: 'page' })} />
|
|
42
|
-
);
|
|
43
|
-
expect(container.innerHTML).toBe('');
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
it('should render nothing for mode: new_window', () => {
|
|
47
|
-
const { container } = render(
|
|
48
|
-
<NavigationOverlay {...createProps({ mode: 'new_window' })} />
|
|
49
|
-
);
|
|
50
|
-
expect(container.innerHTML).toBe('');
|
|
51
|
-
});
|
|
52
|
-
|
|
53
|
-
it('should render nothing for mode: none', () => {
|
|
54
|
-
const { container } = render(
|
|
55
|
-
<NavigationOverlay {...createProps({ mode: 'none' })} />
|
|
56
|
-
);
|
|
57
|
-
expect(container.innerHTML).toBe('');
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it('should render nothing when selectedRecord is null', () => {
|
|
61
|
-
const { container } = render(
|
|
62
|
-
<NavigationOverlay {...createProps({ selectedRecord: null })} />
|
|
63
|
-
);
|
|
64
|
-
expect(container.innerHTML).toBe('');
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
// ============================================================
|
|
69
|
-
// Drawer mode (Sheet)
|
|
70
|
-
// ============================================================
|
|
71
|
-
|
|
72
|
-
describe('drawer mode', () => {
|
|
73
|
-
it('should render Sheet with record content', () => {
|
|
74
|
-
render(<NavigationOverlay {...createProps({ mode: 'drawer' })} />);
|
|
75
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
76
|
-
});
|
|
77
|
-
|
|
78
|
-
it('should render title', () => {
|
|
79
|
-
render(
|
|
80
|
-
<NavigationOverlay
|
|
81
|
-
{...createProps({ mode: 'drawer', title: 'Contact Detail' })}
|
|
82
|
-
/>
|
|
83
|
-
);
|
|
84
|
-
expect(screen.getByText('Contact Detail')).toBeInTheDocument();
|
|
85
|
-
});
|
|
86
|
-
|
|
87
|
-
it('should render description when provided', () => {
|
|
88
|
-
render(
|
|
89
|
-
<NavigationOverlay
|
|
90
|
-
{...createProps({
|
|
91
|
-
mode: 'drawer',
|
|
92
|
-
title: 'Detail',
|
|
93
|
-
description: 'View record details',
|
|
94
|
-
})}
|
|
95
|
-
/>
|
|
96
|
-
);
|
|
97
|
-
expect(screen.getByText('View record details')).toBeInTheDocument();
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
it('should use default title when none provided', () => {
|
|
101
|
-
render(<NavigationOverlay {...createProps({ mode: 'drawer' })} />);
|
|
102
|
-
expect(screen.getByText('Record Detail')).toBeInTheDocument();
|
|
103
|
-
});
|
|
104
|
-
});
|
|
105
|
-
|
|
106
|
-
// ============================================================
|
|
107
|
-
// Modal mode (Dialog)
|
|
108
|
-
// ============================================================
|
|
109
|
-
|
|
110
|
-
describe('modal mode', () => {
|
|
111
|
-
it('should render Dialog with record content', () => {
|
|
112
|
-
render(<NavigationOverlay {...createProps({ mode: 'modal' })} />);
|
|
113
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
114
|
-
});
|
|
115
|
-
|
|
116
|
-
it('should render title in dialog', () => {
|
|
117
|
-
render(
|
|
118
|
-
<NavigationOverlay
|
|
119
|
-
{...createProps({ mode: 'modal', title: 'Account Detail' })}
|
|
120
|
-
/>
|
|
121
|
-
);
|
|
122
|
-
expect(screen.getByText('Account Detail')).toBeInTheDocument();
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it('should render description in dialog', () => {
|
|
126
|
-
render(
|
|
127
|
-
<NavigationOverlay
|
|
128
|
-
{...createProps({
|
|
129
|
-
mode: 'modal',
|
|
130
|
-
description: 'View account information',
|
|
131
|
-
})}
|
|
132
|
-
/>
|
|
133
|
-
);
|
|
134
|
-
expect(screen.getByText('View account information')).toBeInTheDocument();
|
|
135
|
-
});
|
|
136
|
-
});
|
|
137
|
-
|
|
138
|
-
// ============================================================
|
|
139
|
-
// Split mode (ResizablePanelGroup)
|
|
140
|
-
// ============================================================
|
|
141
|
-
|
|
142
|
-
describe('split mode', () => {
|
|
143
|
-
it('should render split panels with main content and record detail', () => {
|
|
144
|
-
render(
|
|
145
|
-
<NavigationOverlay
|
|
146
|
-
{...createProps({
|
|
147
|
-
mode: 'split',
|
|
148
|
-
mainContent: <div data-testid="main">Main Content</div>,
|
|
149
|
-
})}
|
|
150
|
-
/>
|
|
151
|
-
);
|
|
152
|
-
expect(screen.getByTestId('main')).toBeInTheDocument();
|
|
153
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
154
|
-
});
|
|
155
|
-
|
|
156
|
-
it('should render nothing when mainContent is not provided', () => {
|
|
157
|
-
const { container } = render(
|
|
158
|
-
<NavigationOverlay
|
|
159
|
-
{...createProps({ mode: 'split', mainContent: undefined })}
|
|
160
|
-
/>
|
|
161
|
-
);
|
|
162
|
-
expect(container.innerHTML).toBe('');
|
|
163
|
-
});
|
|
164
|
-
|
|
165
|
-
it('should render close button in split panel', () => {
|
|
166
|
-
render(
|
|
167
|
-
<NavigationOverlay
|
|
168
|
-
{...createProps({
|
|
169
|
-
mode: 'split',
|
|
170
|
-
mainContent: <div>Main</div>,
|
|
171
|
-
})}
|
|
172
|
-
/>
|
|
173
|
-
);
|
|
174
|
-
expect(screen.getByLabelText('Close panel')).toBeInTheDocument();
|
|
175
|
-
});
|
|
176
|
-
|
|
177
|
-
it('should call close when close button clicked', () => {
|
|
178
|
-
const close = vi.fn();
|
|
179
|
-
render(
|
|
180
|
-
<NavigationOverlay
|
|
181
|
-
{...createProps({
|
|
182
|
-
mode: 'split',
|
|
183
|
-
close,
|
|
184
|
-
mainContent: <div>Main</div>,
|
|
185
|
-
})}
|
|
186
|
-
/>
|
|
187
|
-
);
|
|
188
|
-
|
|
189
|
-
fireEvent.click(screen.getByLabelText('Close panel'));
|
|
190
|
-
expect(close).toHaveBeenCalled();
|
|
191
|
-
});
|
|
192
|
-
});
|
|
193
|
-
|
|
194
|
-
// ============================================================
|
|
195
|
-
// Popover mode
|
|
196
|
-
// ============================================================
|
|
197
|
-
|
|
198
|
-
describe('popover mode', () => {
|
|
199
|
-
it('should render popover with record content when open', () => {
|
|
200
|
-
render(
|
|
201
|
-
<NavigationOverlay
|
|
202
|
-
{...createProps({
|
|
203
|
-
mode: 'popover',
|
|
204
|
-
popoverTrigger: <button>Trigger</button>,
|
|
205
|
-
})}
|
|
206
|
-
/>
|
|
207
|
-
);
|
|
208
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
209
|
-
});
|
|
210
|
-
|
|
211
|
-
it('should render title in popover', () => {
|
|
212
|
-
render(
|
|
213
|
-
<NavigationOverlay
|
|
214
|
-
{...createProps({
|
|
215
|
-
mode: 'popover',
|
|
216
|
-
title: 'Quick View',
|
|
217
|
-
})}
|
|
218
|
-
/>
|
|
219
|
-
);
|
|
220
|
-
expect(screen.getByText('Quick View')).toBeInTheDocument();
|
|
221
|
-
});
|
|
222
|
-
|
|
223
|
-
it('should render fallback dialog when no popoverTrigger is provided', () => {
|
|
224
|
-
render(
|
|
225
|
-
<NavigationOverlay
|
|
226
|
-
{...createProps({
|
|
227
|
-
mode: 'popover',
|
|
228
|
-
title: 'Preview',
|
|
229
|
-
})}
|
|
230
|
-
/>
|
|
231
|
-
);
|
|
232
|
-
expect(screen.getByText('Preview')).toBeInTheDocument();
|
|
233
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
234
|
-
});
|
|
235
|
-
|
|
236
|
-
it('should not render fallback dialog when closed and no popoverTrigger', () => {
|
|
237
|
-
const { container } = render(
|
|
238
|
-
<NavigationOverlay
|
|
239
|
-
{...createProps({
|
|
240
|
-
mode: 'popover',
|
|
241
|
-
isOpen: false,
|
|
242
|
-
})}
|
|
243
|
-
/>
|
|
244
|
-
);
|
|
245
|
-
expect(container.innerHTML).toBe('');
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
|
|
249
|
-
// ============================================================
|
|
250
|
-
// Width handling
|
|
251
|
-
// ============================================================
|
|
252
|
-
|
|
253
|
-
describe('width handling', () => {
|
|
254
|
-
it('should render drawer with string width without error', () => {
|
|
255
|
-
render(
|
|
256
|
-
<NavigationOverlay
|
|
257
|
-
{...createProps({ mode: 'drawer', width: '600px' })}
|
|
258
|
-
/>
|
|
259
|
-
);
|
|
260
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it('should render modal with numeric width without error', () => {
|
|
264
|
-
render(
|
|
265
|
-
<NavigationOverlay
|
|
266
|
-
{...createProps({ mode: 'modal', width: 800 })}
|
|
267
|
-
/>
|
|
268
|
-
);
|
|
269
|
-
expect(screen.getByText('Test Record')).toBeInTheDocument();
|
|
270
|
-
});
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// ============================================================
|
|
274
|
-
// Children render prop
|
|
275
|
-
// ============================================================
|
|
276
|
-
|
|
277
|
-
describe('children render prop', () => {
|
|
278
|
-
it('should pass the selected record to children', () => {
|
|
279
|
-
const record = { id: '42', name: 'Jane Doe', status: 'active' };
|
|
280
|
-
render(
|
|
281
|
-
<NavigationOverlay
|
|
282
|
-
{...createProps({
|
|
283
|
-
mode: 'drawer',
|
|
284
|
-
selectedRecord: record,
|
|
285
|
-
children: (r: Record<string, unknown>) => (
|
|
286
|
-
<div>
|
|
287
|
-
<span data-testid="name">{String(r.name)}</span>
|
|
288
|
-
<span data-testid="status">{String(r.status)}</span>
|
|
289
|
-
</div>
|
|
290
|
-
),
|
|
291
|
-
})}
|
|
292
|
-
/>
|
|
293
|
-
);
|
|
294
|
-
expect(screen.getByTestId('name')).toHaveTextContent('Jane Doe');
|
|
295
|
-
expect(screen.getByTestId('status')).toHaveTextContent('active');
|
|
296
|
-
});
|
|
297
|
-
});
|
|
298
|
-
|
|
299
|
-
// ============================================================
|
|
300
|
-
// renderView support
|
|
301
|
-
// ============================================================
|
|
302
|
-
|
|
303
|
-
describe('renderView support', () => {
|
|
304
|
-
it('should use renderView when both renderView and view are provided', () => {
|
|
305
|
-
render(
|
|
306
|
-
<NavigationOverlay
|
|
307
|
-
{...createProps({
|
|
308
|
-
mode: 'drawer',
|
|
309
|
-
view: 'contact-detail',
|
|
310
|
-
renderView: (record, viewName) => (
|
|
311
|
-
<div data-testid="custom-view">
|
|
312
|
-
<span data-testid="view-name">{viewName}</span>
|
|
313
|
-
<span data-testid="record-name">{String(record.name)}</span>
|
|
314
|
-
</div>
|
|
315
|
-
),
|
|
316
|
-
})}
|
|
317
|
-
/>
|
|
318
|
-
);
|
|
319
|
-
expect(screen.getByTestId('custom-view')).toBeInTheDocument();
|
|
320
|
-
expect(screen.getByTestId('view-name')).toHaveTextContent('contact-detail');
|
|
321
|
-
expect(screen.getByTestId('record-name')).toHaveTextContent('Test Record');
|
|
322
|
-
// Children should NOT be rendered
|
|
323
|
-
expect(screen.queryByTestId('record-content')).not.toBeInTheDocument();
|
|
324
|
-
});
|
|
325
|
-
|
|
326
|
-
it('should fallback to children when renderView is provided but view is not', () => {
|
|
327
|
-
render(
|
|
328
|
-
<NavigationOverlay
|
|
329
|
-
{...createProps({
|
|
330
|
-
mode: 'drawer',
|
|
331
|
-
renderView: (_record, _viewName) => (
|
|
332
|
-
<div data-testid="custom-view">Should not appear</div>
|
|
333
|
-
),
|
|
334
|
-
})}
|
|
335
|
-
/>
|
|
336
|
-
);
|
|
337
|
-
// Children should be rendered since view is undefined
|
|
338
|
-
expect(screen.getByTestId('record-content')).toBeInTheDocument();
|
|
339
|
-
expect(screen.queryByTestId('custom-view')).not.toBeInTheDocument();
|
|
340
|
-
});
|
|
341
|
-
|
|
342
|
-
it('should fallback to children when view is provided but renderView is not', () => {
|
|
343
|
-
render(
|
|
344
|
-
<NavigationOverlay
|
|
345
|
-
{...createProps({
|
|
346
|
-
mode: 'drawer',
|
|
347
|
-
view: 'contact-detail',
|
|
348
|
-
})}
|
|
349
|
-
/>
|
|
350
|
-
);
|
|
351
|
-
// Children should be rendered since renderView is undefined
|
|
352
|
-
expect(screen.getByTestId('record-content')).toBeInTheDocument();
|
|
353
|
-
});
|
|
354
|
-
|
|
355
|
-
it('should use renderView in modal mode', () => {
|
|
356
|
-
render(
|
|
357
|
-
<NavigationOverlay
|
|
358
|
-
{...createProps({
|
|
359
|
-
mode: 'modal',
|
|
360
|
-
view: 'edit-form',
|
|
361
|
-
renderView: (record, viewName) => (
|
|
362
|
-
<div data-testid="modal-custom-view">{viewName}: {String(record.name)}</div>
|
|
363
|
-
),
|
|
364
|
-
})}
|
|
365
|
-
/>
|
|
366
|
-
);
|
|
367
|
-
expect(screen.getByTestId('modal-custom-view')).toHaveTextContent('edit-form: Test Record');
|
|
368
|
-
});
|
|
369
|
-
});
|
|
370
|
-
});
|