@object-ui/components 3.0.3 → 3.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.turbo/turbo-build.log +12 -12
- package/dist/index.css +1 -1
- package/dist/index.js +24701 -22929
- package/dist/index.umd.cjs +37 -37
- package/dist/src/custom/config-field-renderer.d.ts +21 -0
- package/dist/src/custom/config-panel-renderer.d.ts +81 -0
- package/dist/src/custom/config-row.d.ts +27 -0
- package/dist/src/custom/index.d.ts +5 -0
- package/dist/src/custom/mobile-dialog-content.d.ts +20 -0
- package/dist/src/custom/navigation-overlay.d.ts +8 -0
- package/dist/src/custom/section-header.d.ts +31 -0
- package/dist/src/debug/DebugPanel.d.ts +39 -0
- package/dist/src/debug/index.d.ts +9 -0
- package/dist/src/hooks/use-config-draft.d.ts +46 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/renderers/action/action-bar.d.ts +23 -0
- package/dist/src/types/config-panel.d.ts +92 -0
- package/dist/src/ui/sheet.d.ts +2 -0
- package/dist/src/ui/sidebar.d.ts +4 -0
- package/package.json +17 -17
- package/src/__tests__/__snapshots__/snapshot-critical.test.tsx.snap +3 -3
- package/src/__tests__/action-bar.test.tsx +172 -0
- package/src/__tests__/config-field-renderer.test.tsx +307 -0
- package/src/__tests__/config-panel-renderer.test.tsx +580 -0
- package/src/__tests__/config-primitives.test.tsx +106 -0
- package/src/__tests__/mobile-accessibility.test.tsx +120 -0
- package/src/__tests__/navigation-overlay.test.tsx +97 -0
- package/src/__tests__/use-config-draft.test.tsx +295 -0
- package/src/custom/config-field-renderer.tsx +276 -0
- package/src/custom/config-panel-renderer.tsx +306 -0
- package/src/custom/config-row.tsx +50 -0
- package/src/custom/index.ts +5 -0
- package/src/custom/mobile-dialog-content.tsx +67 -0
- package/src/custom/navigation-overlay.tsx +42 -4
- package/src/custom/section-header.tsx +68 -0
- package/src/debug/DebugPanel.tsx +313 -0
- package/src/debug/__tests__/DebugPanel.test.tsx +134 -0
- package/src/debug/index.ts +10 -0
- package/src/hooks/use-config-draft.ts +127 -0
- package/src/index.css +4 -0
- package/src/index.ts +15 -0
- package/src/renderers/action/action-bar.tsx +202 -0
- package/src/renderers/action/index.ts +1 -0
- package/src/renderers/complex/__tests__/data-table-airtable-ux.test.tsx +239 -0
- package/src/renderers/complex/__tests__/data-table.test.ts +16 -0
- package/src/renderers/complex/data-table.tsx +346 -43
- package/src/renderers/data-display/breadcrumb.tsx +3 -2
- package/src/renderers/form/form.tsx +4 -4
- package/src/renderers/navigation/header-bar.tsx +69 -10
- package/src/stories/ConfigPanel.stories.tsx +232 -0
- package/src/types/config-panel.ts +101 -0
- package/src/ui/dialog.tsx +20 -3
- package/src/ui/sheet.tsx +6 -3
- package/src/ui/sidebar.tsx +93 -9
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { ConfigField } from '../types/config-panel';
|
|
2
|
+
export interface ConfigFieldRendererProps {
|
|
3
|
+
/** Field schema */
|
|
4
|
+
field: ConfigField;
|
|
5
|
+
/** Current value */
|
|
6
|
+
value: any;
|
|
7
|
+
/** Change handler */
|
|
8
|
+
onChange: (value: any) => void;
|
|
9
|
+
/** Full draft for visibility evaluation and custom render */
|
|
10
|
+
draft: Record<string, any>;
|
|
11
|
+
/** Object definition for field-picker controls */
|
|
12
|
+
objectDef?: Record<string, any>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Renders a single config field based on its ControlType.
|
|
16
|
+
*
|
|
17
|
+
* Supports: input, switch, select, checkbox, slider, color, icon-group, custom.
|
|
18
|
+
* filter/sort/field-picker are rendered as placeholders that consumers can
|
|
19
|
+
* override with type='custom' when full sub-editor integration is needed.
|
|
20
|
+
*/
|
|
21
|
+
export declare function ConfigFieldRenderer({ field, value, onChange, draft, objectDef: _objectDef, }: ConfigFieldRendererProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { ConfigPanelSchema } from '../types/config-panel';
|
|
2
|
+
/**
|
|
3
|
+
* ObjectUI
|
|
4
|
+
* Copyright (c) 2024-present ObjectStack Inc.
|
|
5
|
+
*
|
|
6
|
+
* This source code is licensed under the MIT license found in the
|
|
7
|
+
* LICENSE file in the root directory of this source tree.
|
|
8
|
+
*/
|
|
9
|
+
import * as React from 'react';
|
|
10
|
+
export interface ConfigPanelRendererProps {
|
|
11
|
+
/** Whether the panel is visible */
|
|
12
|
+
open: boolean;
|
|
13
|
+
/** Close callback */
|
|
14
|
+
onClose: () => void;
|
|
15
|
+
/** Schema describing the panel structure */
|
|
16
|
+
schema: ConfigPanelSchema;
|
|
17
|
+
/** Current draft values */
|
|
18
|
+
draft: Record<string, any>;
|
|
19
|
+
/** Whether the draft has uncommitted changes */
|
|
20
|
+
isDirty: boolean;
|
|
21
|
+
/** Called when any field changes */
|
|
22
|
+
onFieldChange: (key: string, value: any) => void;
|
|
23
|
+
/** Persist current draft */
|
|
24
|
+
onSave: () => void;
|
|
25
|
+
/** Revert draft to source */
|
|
26
|
+
onDiscard: () => void;
|
|
27
|
+
/** Extra content rendered in the header row */
|
|
28
|
+
headerExtra?: React.ReactNode;
|
|
29
|
+
/** Object definition for field pickers */
|
|
30
|
+
objectDef?: Record<string, any>;
|
|
31
|
+
/** Additional CSS class name */
|
|
32
|
+
className?: string;
|
|
33
|
+
/** Label for save button (default: "Save") */
|
|
34
|
+
saveLabel?: string;
|
|
35
|
+
/** Label for discard button (default: "Discard") */
|
|
36
|
+
discardLabel?: string;
|
|
37
|
+
/** Ref for the panel root element */
|
|
38
|
+
panelRef?: React.Ref<HTMLDivElement>;
|
|
39
|
+
/** ARIA role for the panel (e.g. "complementary") */
|
|
40
|
+
role?: string;
|
|
41
|
+
/** ARIA label for the panel */
|
|
42
|
+
ariaLabel?: string;
|
|
43
|
+
/** tabIndex for the panel root element */
|
|
44
|
+
tabIndex?: number;
|
|
45
|
+
/** Override data-testid for the panel root (default: "config-panel") */
|
|
46
|
+
testId?: string;
|
|
47
|
+
/** Title for the close button */
|
|
48
|
+
closeTitle?: string;
|
|
49
|
+
/** Override data-testid for the footer (default: "config-panel-footer") */
|
|
50
|
+
footerTestId?: string;
|
|
51
|
+
/** Override data-testid for the save button (default: "config-panel-save") */
|
|
52
|
+
saveTestId?: string;
|
|
53
|
+
/** Override data-testid for the discard button (default: "config-panel-discard") */
|
|
54
|
+
discardTestId?: string;
|
|
55
|
+
/** Externally-controlled set of section keys that should be expanded (overrides local collapse state) */
|
|
56
|
+
expandedSections?: string[];
|
|
57
|
+
/** Undo callback */
|
|
58
|
+
onUndo?: () => void;
|
|
59
|
+
/** Redo callback */
|
|
60
|
+
onRedo?: () => void;
|
|
61
|
+
/** Whether undo is available */
|
|
62
|
+
canUndo?: boolean;
|
|
63
|
+
/** Whether redo is available */
|
|
64
|
+
canRedo?: boolean;
|
|
65
|
+
/** Label for undo button */
|
|
66
|
+
undoLabel?: string;
|
|
67
|
+
/** Label for redo button */
|
|
68
|
+
redoLabel?: string;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Schema-driven configuration panel renderer.
|
|
72
|
+
*
|
|
73
|
+
* Takes a `ConfigPanelSchema` and automatically renders the full panel:
|
|
74
|
+
* - Header with breadcrumb & close button
|
|
75
|
+
* - Scrollable body with collapsible sections
|
|
76
|
+
* - Sticky footer with Save / Discard when dirty
|
|
77
|
+
*
|
|
78
|
+
* Each concrete panel (Dashboard, Form, Page…) only needs to provide
|
|
79
|
+
* a schema and wire up `useConfigDraft`.
|
|
80
|
+
*/
|
|
81
|
+
export declare function ConfigPanelRenderer({ open, onClose, schema, draft, isDirty, onFieldChange, onSave, onDiscard, headerExtra, objectDef, className, saveLabel, discardLabel, panelRef, role, ariaLabel, tabIndex, testId, closeTitle, footerTestId, saveTestId, discardTestId, expandedSections, onUndo, onRedo, canUndo, canRedo, undoLabel, redoLabel, }: ConfigPanelRendererProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
export interface ConfigRowProps {
|
|
9
|
+
/** Left-side label text */
|
|
10
|
+
label: string;
|
|
11
|
+
/** Right-side display value (used when children are not provided) */
|
|
12
|
+
value?: string;
|
|
13
|
+
/** Makes row clickable with hover effect */
|
|
14
|
+
onClick?: () => void;
|
|
15
|
+
/** Custom content replacing value */
|
|
16
|
+
children?: React.ReactNode;
|
|
17
|
+
/** Additional CSS class name */
|
|
18
|
+
className?: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* A single labeled row in a configuration panel.
|
|
22
|
+
*
|
|
23
|
+
* Renders as a `<button>` when `onClick` is provided, otherwise as a `<div>`.
|
|
24
|
+
* Shows label on the left and either custom children or a text value on the right.
|
|
25
|
+
*/
|
|
26
|
+
declare function ConfigRow({ label, value, onClick, children, className }: ConfigRowProps): import("react/jsx-runtime").JSX.Element;
|
|
27
|
+
export { ConfigRow };
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
export * from './button-group';
|
|
2
2
|
export * from './combobox';
|
|
3
|
+
export * from './config-row';
|
|
4
|
+
export * from './config-field-renderer';
|
|
5
|
+
export * from './config-panel-renderer';
|
|
3
6
|
export * from './date-picker';
|
|
4
7
|
export * from './empty';
|
|
5
8
|
export * from './field';
|
|
@@ -9,8 +12,10 @@ export * from './item';
|
|
|
9
12
|
export * from './kbd';
|
|
10
13
|
export * from './native-select';
|
|
11
14
|
export * from './navigation-overlay';
|
|
15
|
+
export * from './section-header';
|
|
12
16
|
export * from './spinner';
|
|
13
17
|
export * from './sort-builder';
|
|
14
18
|
export * from './action-param-dialog';
|
|
15
19
|
export * from './view-skeleton';
|
|
16
20
|
export * from './view-states';
|
|
21
|
+
export * from './mobile-dialog-content';
|
|
@@ -0,0 +1,20 @@
|
|
|
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
|
+
* MobileDialogContent
|
|
10
|
+
*
|
|
11
|
+
* A mobile-optimized wrapper around the upstream Shadcn DialogContent.
|
|
12
|
+
* On mobile (< sm breakpoint), the dialog is full-screen with a larger
|
|
13
|
+
* close-button touch target (≥ 44×44px per WCAG 2.5.5).
|
|
14
|
+
* On tablet+ (≥ sm), it falls back to the standard centered dialog.
|
|
15
|
+
*
|
|
16
|
+
* This lives in `custom/` to avoid modifying the Shadcn-synced `ui/dialog.tsx`.
|
|
17
|
+
*/
|
|
18
|
+
import * as React from 'react';
|
|
19
|
+
import * as DialogPrimitive from '@radix-ui/react-dialog';
|
|
20
|
+
export declare const MobileDialogContent: React.ForwardRefExoticComponent<Omit<DialogPrimitive.DialogContentProps & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
|
|
@@ -16,6 +16,8 @@ export interface NavigationOverlayProps {
|
|
|
16
16
|
width?: string | number;
|
|
17
17
|
/** Whether navigation is an overlay mode */
|
|
18
18
|
isOverlay: boolean;
|
|
19
|
+
/** Target view/form name from NavigationConfig */
|
|
20
|
+
view?: string;
|
|
19
21
|
/** Title for the overlay header */
|
|
20
22
|
title?: string;
|
|
21
23
|
/** Description for the overlay header */
|
|
@@ -27,6 +29,12 @@ export interface NavigationOverlayProps {
|
|
|
27
29
|
* Receives the selected record.
|
|
28
30
|
*/
|
|
29
31
|
children: (record: Record<string, unknown>) => React.ReactNode;
|
|
32
|
+
/**
|
|
33
|
+
* Optional render function for a specific view/form based on `view` prop.
|
|
34
|
+
* When provided, this takes priority over `children` for rendering overlay content.
|
|
35
|
+
* Receives the selected record and the view name.
|
|
36
|
+
*/
|
|
37
|
+
renderView?: (record: Record<string, unknown>, viewName: string) => React.ReactNode;
|
|
30
38
|
/**
|
|
31
39
|
* The main content to wrap (for split mode only).
|
|
32
40
|
* In split mode, the main content is rendered in the left panel.
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
export interface SectionHeaderProps {
|
|
9
|
+
/** Section heading text */
|
|
10
|
+
title: string;
|
|
11
|
+
/** Icon rendered before the title */
|
|
12
|
+
icon?: React.ReactNode;
|
|
13
|
+
/** Enable collapse/expand toggle */
|
|
14
|
+
collapsible?: boolean;
|
|
15
|
+
/** Current collapsed state */
|
|
16
|
+
collapsed?: boolean;
|
|
17
|
+
/** Callback when toggling collapse/expand */
|
|
18
|
+
onToggle?: () => void;
|
|
19
|
+
/** Data-testid attribute */
|
|
20
|
+
testId?: string;
|
|
21
|
+
/** Additional CSS class name */
|
|
22
|
+
className?: string;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Section heading with optional collapse/expand support.
|
|
26
|
+
*
|
|
27
|
+
* Renders as a `<button>` when collapsible, with a chevron icon
|
|
28
|
+
* indicating the expand/collapse state. Uses `aria-expanded` for accessibility.
|
|
29
|
+
*/
|
|
30
|
+
declare function SectionHeader({ title, icon, collapsible, collapsed, onToggle, testId, className }: SectionHeaderProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
export { SectionHeader };
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { default as React } from 'react';
|
|
2
|
+
import { DebugFlags } from '../../../core/src';
|
|
3
|
+
export interface DebugPanelTab {
|
|
4
|
+
id: string;
|
|
5
|
+
label: string;
|
|
6
|
+
icon?: React.ReactNode;
|
|
7
|
+
render: () => React.ReactNode;
|
|
8
|
+
}
|
|
9
|
+
export interface DebugPanelProps {
|
|
10
|
+
/** Whether the panel is open */
|
|
11
|
+
open: boolean;
|
|
12
|
+
/** Toggle callback */
|
|
13
|
+
onClose: () => void;
|
|
14
|
+
/** Debug flags from the URL / hook */
|
|
15
|
+
flags?: DebugFlags;
|
|
16
|
+
/** Current schema being rendered (for the Schema tab) */
|
|
17
|
+
schema?: unknown;
|
|
18
|
+
/** Current data context (for the Data tab) */
|
|
19
|
+
dataContext?: unknown;
|
|
20
|
+
/** Extra tabs provided by plugins */
|
|
21
|
+
extraTabs?: DebugPanelTab[];
|
|
22
|
+
/** CSS class override */
|
|
23
|
+
className?: string;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* A floating developer debug panel activated via URL parameters or manual toggle.
|
|
27
|
+
*
|
|
28
|
+
* Built-in tabs:
|
|
29
|
+
* - **Schema** — current rendered JSON schema
|
|
30
|
+
* - **Data** — active data context
|
|
31
|
+
* - **Perf** — component render timing (highlights slow renders >16ms)
|
|
32
|
+
* - **Expr** — expression evaluation trace
|
|
33
|
+
* - **Events** — action/event timeline
|
|
34
|
+
* - **Registry** — all registered component types
|
|
35
|
+
* - **Flags** — current debug flags
|
|
36
|
+
*
|
|
37
|
+
* Plugins can inject additional tabs via the `extraTabs` prop.
|
|
38
|
+
*/
|
|
39
|
+
export declare function DebugPanel({ open, onClose, flags, schema, dataContext, extraTabs, className, }: DebugPanelProps): import("react/jsx-runtime").JSX.Element | null;
|
|
@@ -0,0 +1,9 @@
|
|
|
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
|
+
export { DebugPanel } from './DebugPanel';
|
|
9
|
+
export type { DebugPanelProps, DebugPanelTab } from './DebugPanel';
|
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
export interface UseConfigDraftOptions {
|
|
9
|
+
/** Panel mode: 'create' starts dirty; 'edit' starts clean */
|
|
10
|
+
mode?: 'create' | 'edit';
|
|
11
|
+
/** Optional callback invoked on every field change */
|
|
12
|
+
onUpdate?: (field: string, value: any) => void;
|
|
13
|
+
/** Maximum undo history size (default: 50) */
|
|
14
|
+
maxHistory?: number;
|
|
15
|
+
}
|
|
16
|
+
export interface UseConfigDraftReturn<T extends Record<string, any>> {
|
|
17
|
+
/** The mutable draft copy */
|
|
18
|
+
draft: T;
|
|
19
|
+
/** Whether the draft differs from the source */
|
|
20
|
+
isDirty: boolean;
|
|
21
|
+
/** Update a single field in the draft */
|
|
22
|
+
updateField: (field: string, value: any) => void;
|
|
23
|
+
/** Revert draft back to source */
|
|
24
|
+
discard: () => void;
|
|
25
|
+
/** Low-level setter (use updateField for individual changes) */
|
|
26
|
+
setDraft: React.Dispatch<React.SetStateAction<T>>;
|
|
27
|
+
/** Undo the last change */
|
|
28
|
+
undo: () => void;
|
|
29
|
+
/** Redo a previously undone change */
|
|
30
|
+
redo: () => void;
|
|
31
|
+
/** Whether undo is available */
|
|
32
|
+
canUndo: boolean;
|
|
33
|
+
/** Whether redo is available */
|
|
34
|
+
canRedo: boolean;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Generic draft-state management for configuration panels.
|
|
38
|
+
*
|
|
39
|
+
* Mirrors the proven draft → save / discard pattern from ViewConfigPanel
|
|
40
|
+
* while being reusable across Dashboard, Form, Page, Report, and any
|
|
41
|
+
* future config panel. Includes undo/redo history support.
|
|
42
|
+
*
|
|
43
|
+
* @param source - The "committed" configuration object.
|
|
44
|
+
* @param options - Optional mode and change callback.
|
|
45
|
+
*/
|
|
46
|
+
export declare function useConfigDraft<T extends Record<string, any>>(source: T, options?: UseConfigDraftOptions): UseConfigDraftReturn<T>;
|
package/dist/src/index.d.ts
CHANGED
|
@@ -4,4 +4,8 @@ export { cva } from 'class-variance-authority';
|
|
|
4
4
|
export { registerPlaceholders } from './renderers/placeholders';
|
|
5
5
|
export * from './ui';
|
|
6
6
|
export * from './custom';
|
|
7
|
+
export { useConfigDraft } from './hooks/use-config-draft';
|
|
8
|
+
export type { UseConfigDraftOptions, UseConfigDraftReturn } from './hooks/use-config-draft';
|
|
9
|
+
export type { ControlType, ConfigField, ConfigSection, ConfigPanelSchema, } from './types/config-panel';
|
|
7
10
|
export declare function initializeComponents(): boolean;
|
|
11
|
+
export * from './debug';
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { ActionSchema, ActionLocation } from '../../../../types/src';
|
|
2
|
+
export interface ActionBarSchema {
|
|
3
|
+
type: 'action:bar';
|
|
4
|
+
/** Actions to render */
|
|
5
|
+
actions?: ActionSchema[];
|
|
6
|
+
/** Filter actions by this location */
|
|
7
|
+
location?: ActionLocation;
|
|
8
|
+
/** Maximum visible inline actions before overflow into "More" menu (default: 3) */
|
|
9
|
+
maxVisible?: number;
|
|
10
|
+
/** Visibility condition expression */
|
|
11
|
+
visible?: string;
|
|
12
|
+
/** Layout direction */
|
|
13
|
+
direction?: 'horizontal' | 'vertical';
|
|
14
|
+
/** Gap between items (Tailwind gap class, default: 'gap-2') */
|
|
15
|
+
gap?: string;
|
|
16
|
+
/** Button variant for all actions (can be overridden per-action) */
|
|
17
|
+
variant?: string;
|
|
18
|
+
/** Button size for all actions (can be overridden per-action) */
|
|
19
|
+
size?: string;
|
|
20
|
+
/** Custom CSS class */
|
|
21
|
+
className?: string;
|
|
22
|
+
[key: string]: any;
|
|
23
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
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
|
+
* Schema-driven config panel type definitions.
|
|
10
|
+
*
|
|
11
|
+
* Each concrete panel (View, Dashboard, Page…) provides a ConfigPanelSchema,
|
|
12
|
+
* and ConfigPanelRenderer auto-generates the UI.
|
|
13
|
+
*/
|
|
14
|
+
/** Supported control types for config fields */
|
|
15
|
+
export type ControlType = 'input' | 'switch' | 'select' | 'checkbox' | 'slider' | 'color' | 'field-picker' | 'filter' | 'sort' | 'icon-group' | 'summary' | 'custom';
|
|
16
|
+
/** A single field within a config section */
|
|
17
|
+
export interface ConfigField {
|
|
18
|
+
/** Field key in the draft object */
|
|
19
|
+
key: string;
|
|
20
|
+
/** Display label (may be an i18n key) */
|
|
21
|
+
label: string;
|
|
22
|
+
/** Control type determining which widget to render */
|
|
23
|
+
type: ControlType;
|
|
24
|
+
/** Default value for the field */
|
|
25
|
+
defaultValue?: any;
|
|
26
|
+
/** Select/icon-group options */
|
|
27
|
+
options?: Array<{
|
|
28
|
+
value: string;
|
|
29
|
+
label: string;
|
|
30
|
+
icon?: React.ReactNode;
|
|
31
|
+
}>;
|
|
32
|
+
/** Visibility predicate evaluated against the current draft */
|
|
33
|
+
visibleWhen?: (draft: Record<string, any>) => boolean;
|
|
34
|
+
/** Disabled predicate evaluated against the current draft */
|
|
35
|
+
disabledWhen?: (draft: Record<string, any>) => boolean;
|
|
36
|
+
/** Custom render function for type='custom' */
|
|
37
|
+
render?: (value: any, onChange: (v: any) => void, draft: Record<string, any>) => React.ReactNode;
|
|
38
|
+
/** Placeholder text for input/select controls */
|
|
39
|
+
placeholder?: string;
|
|
40
|
+
/** Help text displayed below the control */
|
|
41
|
+
helpText?: string;
|
|
42
|
+
/** Minimum value for slider */
|
|
43
|
+
min?: number;
|
|
44
|
+
/** Maximum value for slider */
|
|
45
|
+
max?: number;
|
|
46
|
+
/** Step value for slider */
|
|
47
|
+
step?: number;
|
|
48
|
+
/** Whether the field is disabled */
|
|
49
|
+
disabled?: boolean;
|
|
50
|
+
/** Field definitions for filter/sort sub-editors */
|
|
51
|
+
fields?: Array<{
|
|
52
|
+
value: string;
|
|
53
|
+
label: string;
|
|
54
|
+
type?: string;
|
|
55
|
+
options?: Array<{
|
|
56
|
+
value: string;
|
|
57
|
+
label: string;
|
|
58
|
+
}>;
|
|
59
|
+
}>;
|
|
60
|
+
/** Summary display text for type='summary' */
|
|
61
|
+
summaryText?: string;
|
|
62
|
+
/** Click handler for the summary gear/action button (type='summary') */
|
|
63
|
+
onSummaryClick?: () => void;
|
|
64
|
+
}
|
|
65
|
+
/** A group of related config fields */
|
|
66
|
+
export interface ConfigSection {
|
|
67
|
+
/** Unique section key (used for collapse state tracking) */
|
|
68
|
+
key: string;
|
|
69
|
+
/** Section title (may be an i18n key) */
|
|
70
|
+
title: string;
|
|
71
|
+
/** Hint text displayed below the title */
|
|
72
|
+
hint?: string;
|
|
73
|
+
/** Icon displayed before the section title (e.g. a Lucide icon element) */
|
|
74
|
+
icon?: React.ReactNode;
|
|
75
|
+
/** Whether this section supports collapse/expand */
|
|
76
|
+
collapsible?: boolean;
|
|
77
|
+
/** Default collapsed state */
|
|
78
|
+
defaultCollapsed?: boolean;
|
|
79
|
+
/** Fields belonging to this section */
|
|
80
|
+
fields: ConfigField[];
|
|
81
|
+
/** Nested sub-sections for complex grouping */
|
|
82
|
+
subsections?: ConfigSection[];
|
|
83
|
+
/** Visibility predicate evaluated against the current draft */
|
|
84
|
+
visibleWhen?: (draft: Record<string, any>) => boolean;
|
|
85
|
+
}
|
|
86
|
+
/** Top-level schema describing an entire config panel */
|
|
87
|
+
export interface ConfigPanelSchema {
|
|
88
|
+
/** Breadcrumb segments displayed in the panel header */
|
|
89
|
+
breadcrumb: string[];
|
|
90
|
+
/** Ordered list of sections */
|
|
91
|
+
sections: ConfigSection[];
|
|
92
|
+
}
|
package/dist/src/ui/sheet.d.ts
CHANGED
|
@@ -17,6 +17,8 @@ declare const sheetVariants: (props?: ({
|
|
|
17
17
|
side?: "left" | "right" | "top" | "bottom" | null | undefined;
|
|
18
18
|
} & import('class-variance-authority/types').ClassProp) | undefined) => string;
|
|
19
19
|
interface SheetContentProps extends React.ComponentPropsWithoutRef<typeof SheetPrimitive.Content>, VariantProps<typeof sheetVariants> {
|
|
20
|
+
/** When true, the backdrop overlay is not rendered (useful for non-modal drawers) */
|
|
21
|
+
hideOverlay?: boolean;
|
|
20
22
|
}
|
|
21
23
|
declare const SheetContent: React.ForwardRefExoticComponent<SheetContentProps & React.RefAttributes<HTMLDivElement>>;
|
|
22
24
|
declare const SheetHeader: {
|
package/dist/src/ui/sidebar.d.ts
CHANGED
|
@@ -16,6 +16,10 @@ type SidebarContextProps = {
|
|
|
16
16
|
setOpenMobile: (open: boolean) => void;
|
|
17
17
|
isMobile: boolean;
|
|
18
18
|
toggleSidebar: () => void;
|
|
19
|
+
/** Current sidebar width in pixels (only used when resizable) */
|
|
20
|
+
sidebarWidth: number | null;
|
|
21
|
+
/** Update sidebar width (only used when resizable) */
|
|
22
|
+
setSidebarWidth: (width: number | null) => void;
|
|
19
23
|
};
|
|
20
24
|
declare function useSidebar(): SidebarContextProps;
|
|
21
25
|
declare const SidebarProvider: React.ForwardRefExoticComponent<Omit<React.ClassAttributes<HTMLDivElement> & React.HTMLAttributes<HTMLDivElement> & {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@object-ui/components",
|
|
3
|
-
"version": "3.0
|
|
3
|
+
"version": "3.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"description": "Standard UI component library for Object UI, built with Shadcn UI + Tailwind CSS",
|
|
@@ -59,41 +59,41 @@
|
|
|
59
59
|
"date-fns": "^4.1.0",
|
|
60
60
|
"embla-carousel-react": "^8.6.0",
|
|
61
61
|
"input-otp": "^1.4.2",
|
|
62
|
-
"lucide-react": "^0.
|
|
62
|
+
"lucide-react": "^0.576.0",
|
|
63
63
|
"next-themes": "^0.4.6",
|
|
64
|
-
"react-day-picker": "^9.
|
|
65
|
-
"react-hook-form": "^7.71.
|
|
66
|
-
"react-resizable-panels": "^4.
|
|
64
|
+
"react-day-picker": "^9.14.0",
|
|
65
|
+
"react-hook-form": "^7.71.2",
|
|
66
|
+
"react-resizable-panels": "^4.7.0",
|
|
67
67
|
"recharts": "2.15.4",
|
|
68
68
|
"sonner": "^2.0.7",
|
|
69
|
-
"tailwind-merge": "^3.
|
|
69
|
+
"tailwind-merge": "^3.5.0",
|
|
70
70
|
"tailwindcss-animate": "^1.0.7",
|
|
71
71
|
"vaul": "^1.1.2",
|
|
72
|
-
"@object-ui/core": "3.0
|
|
73
|
-
"@object-ui/react": "3.0
|
|
74
|
-
"@object-ui/types": "3.0
|
|
72
|
+
"@object-ui/core": "3.1.0",
|
|
73
|
+
"@object-ui/react": "3.1.0",
|
|
74
|
+
"@object-ui/types": "3.1.0"
|
|
75
75
|
},
|
|
76
76
|
"peerDependencies": {
|
|
77
77
|
"react": "^18.0.0 || ^19.0.0",
|
|
78
78
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
79
|
-
"tailwindcss": "^4.1
|
|
79
|
+
"tailwindcss": "^4.2.1"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
82
82
|
"@storybook/addon-essentials": "^8.6.14",
|
|
83
83
|
"@storybook/addon-interactions": "^8.6.14",
|
|
84
|
-
"@storybook/addon-links": "^8.6.
|
|
84
|
+
"@storybook/addon-links": "^8.6.17",
|
|
85
85
|
"@storybook/blocks": "^8.6.14",
|
|
86
86
|
"@storybook/react": "^8.6.15",
|
|
87
87
|
"@storybook/react-vite": "^8.6.15",
|
|
88
|
-
"@tailwindcss/postcss": "^4.1
|
|
89
|
-
"@types/react": "19.2.
|
|
88
|
+
"@tailwindcss/postcss": "^4.2.1",
|
|
89
|
+
"@types/react": "19.2.14",
|
|
90
90
|
"@types/react-dom": "19.2.3",
|
|
91
91
|
"@vitejs/plugin-react": "^5.1.4",
|
|
92
|
-
"autoprefixer": "^10.4.
|
|
92
|
+
"autoprefixer": "^10.4.27",
|
|
93
93
|
"postcss": "^8.5.6",
|
|
94
|
-
"shadcn": "^3.8.
|
|
95
|
-
"storybook": "^8.6.
|
|
96
|
-
"tailwindcss": "^4.1
|
|
94
|
+
"shadcn": "^3.8.5",
|
|
95
|
+
"storybook": "^8.6.17",
|
|
96
|
+
"tailwindcss": "^4.2.1",
|
|
97
97
|
"typescript": "^5.9.3",
|
|
98
98
|
"vite": "^7.3.1",
|
|
99
99
|
"vite-plugin-dts": "^4.5.4"
|
|
@@ -460,7 +460,7 @@ exports[`Dialog snapshots > renders open dialog structure 1`] = `
|
|
|
460
460
|
<div
|
|
461
461
|
aria-describedby="radix-_r_2_"
|
|
462
462
|
aria-labelledby="radix-_r_1_"
|
|
463
|
-
class="fixed
|
|
463
|
+
class="fixed inset-0 z-50 grid w-full bg-background p-4 shadow-lg duration-200 h-[100dvh] sm:inset-auto sm:left-[50%] sm:top-[50%] sm:translate-x-[-50%] sm:translate-y-[-50%] sm:max-w-lg sm:h-auto sm:max-h-[90vh] sm:rounded-lg sm:border sm:p-6 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]"
|
|
464
464
|
data-state="open"
|
|
465
465
|
id="radix-_r_0_"
|
|
466
466
|
role="dialog"
|
|
@@ -496,12 +496,12 @@ exports[`Dialog snapshots > renders open dialog structure 1`] = `
|
|
|
496
496
|
</button>
|
|
497
497
|
</div>
|
|
498
498
|
<button
|
|
499
|
-
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"
|
|
499
|
+
class="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground min-h-[44px] min-w-[44px] sm:min-h-0 sm:min-w-0 flex items-center justify-center"
|
|
500
500
|
type="button"
|
|
501
501
|
>
|
|
502
502
|
<svg
|
|
503
503
|
aria-hidden="true"
|
|
504
|
-
class="lucide lucide-x h-4 w-4"
|
|
504
|
+
class="lucide lucide-x h-5 w-5 sm:h-4 sm:w-4"
|
|
505
505
|
fill="none"
|
|
506
506
|
height="24"
|
|
507
507
|
stroke="currentColor"
|