From 63c9aa50521836779567d1740a9984078c70d410 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 02:34:16 +0000 Subject: [PATCH 1/5] Initial plan From 3d920848d5d174909d9d4ffe784793daf2bef5a9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 02:48:55 +0000 Subject: [PATCH 2/5] fix: useDataScope returns undefined when no path given, preventing dashboard widgets from blocking data fetch Previously, useDataScope(undefined) returned the full context.dataSource (typically a service adapter), which caused ObjectChart and other data components to skip async data fetching because boundData was truthy. Also improved ObjectChart fault tolerance: - Uses useContext directly instead of useSchemaContext (no throw without provider) - Validates dataSource.find is callable before invoking Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/plugin-charts/src/ObjectChart.tsx | 10 +- .../__tests__/ObjectChart.dataFetch.test.tsx | 179 ++++++++++++++++++ .../src/context/SchemaRendererContext.tsx | 3 +- .../context/__tests__/useDataScope.test.tsx | 91 +++++++++ 4 files changed, 277 insertions(+), 6 deletions(-) create mode 100644 packages/plugin-charts/src/__tests__/ObjectChart.dataFetch.test.tsx create mode 100644 packages/react/src/context/__tests__/useDataScope.test.tsx diff --git a/packages/plugin-charts/src/ObjectChart.tsx b/packages/plugin-charts/src/ObjectChart.tsx index 2725e2d3c..d16b455b1 100644 --- a/packages/plugin-charts/src/ObjectChart.tsx +++ b/packages/plugin-charts/src/ObjectChart.tsx @@ -1,6 +1,6 @@ -import React, { useState, useEffect } from 'react'; -import { useDataScope, useSchemaContext } from '@object-ui/react'; +import React, { useState, useEffect, useContext } from 'react'; +import { useDataScope, SchemaRendererContext } from '@object-ui/react'; import { ChartRenderer } from './ChartRenderer'; import { ComponentRegistry, extractRecords } from '@object-ui/core'; @@ -54,8 +54,8 @@ export { extractRecords } from '@object-ui/core'; export const ObjectChart = (props: any) => { const { schema } = props; - const context = useSchemaContext(); - const dataSource = props.dataSource || context.dataSource; + const context = useContext(SchemaRendererContext); + const dataSource = props.dataSource || context?.dataSource; const boundData = useDataScope(schema.bind); const [fetchedData, setFetchedData] = useState([]); @@ -64,7 +64,7 @@ export const ObjectChart = (props: any) => { useEffect(() => { let isMounted = true; const fetchData = async () => { - if (!dataSource || !schema.objectName) return; + if (!dataSource || typeof dataSource.find !== 'function' || !schema.objectName) return; if (isMounted) setLoading(true); try { const results = await dataSource.find(schema.objectName, { diff --git a/packages/plugin-charts/src/__tests__/ObjectChart.dataFetch.test.tsx b/packages/plugin-charts/src/__tests__/ObjectChart.dataFetch.test.tsx new file mode 100644 index 000000000..3c91a3895 --- /dev/null +++ b/packages/plugin-charts/src/__tests__/ObjectChart.dataFetch.test.tsx @@ -0,0 +1,179 @@ +/** + * Tests for ObjectChart data fetching & fault tolerance. + * + * Verifies that ObjectChart: + * - Calls dataSource.find() when objectName is set and no bound data + * - Handles missing/invalid dataSource gracefully + * - Works without a SchemaRendererProvider + */ + +import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest'; +import { render, waitFor } from '@testing-library/react'; +import React from 'react'; +import { SchemaRendererProvider } from '@object-ui/react'; +import { ObjectChart } from '../ObjectChart'; + +// Suppress console.error from React error boundary / fetch errors +const originalConsoleError = console.error; +beforeEach(() => { + console.error = vi.fn(); +}); +afterEach(() => { + console.error = originalConsoleError; +}); + +describe('ObjectChart data fetching', () => { + it('should call dataSource.find when objectName is set and no bind path', async () => { + const mockFind = vi.fn().mockResolvedValue([ + { stage: 'Prospect', amount: 100 }, + { stage: 'Proposal', amount: 200 }, + ]); + const dataSource = { find: mockFind }; + + render( + + + + ); + + await waitFor(() => { + expect(mockFind).toHaveBeenCalledWith('opportunity', { $filter: undefined }); + }); + }); + + it('should NOT call dataSource.find when schema.data is provided', () => { + const mockFind = vi.fn(); + const dataSource = { find: mockFind }; + + render( + + + + ); + + expect(mockFind).not.toHaveBeenCalled(); + }); + + it('should apply aggregation to fetched data', async () => { + const mockFind = vi.fn().mockResolvedValue([ + { stage: 'Prospect', amount: 100 }, + { stage: 'Prospect', amount: 200 }, + { stage: 'Proposal', amount: 300 }, + ]); + const dataSource = { find: mockFind }; + + const { container } = render( + + + + ); + + await waitFor(() => { + expect(mockFind).toHaveBeenCalled(); + }); + }); +}); + +describe('ObjectChart fault tolerance', () => { + it('should not crash when dataSource has no find method', () => { + const { container } = render( + + + + ); + + // Should render without crashing + expect(container).toBeDefined(); + }); + + it('should not crash when rendered outside SchemaRendererProvider', () => { + const { container } = render( + + ); + + // Should render without crashing + expect(container).toBeDefined(); + }); + + it('should show "No data source available" when no dataSource and objectName set', () => { + const { container } = render( + + ); + + expect(container.textContent).toContain('No data source available'); + }); + + it('should use dataSource prop over context when both are present', async () => { + const contextFind = vi.fn().mockResolvedValue([]); + const propFind = vi.fn().mockResolvedValue([{ stage: 'A', amount: 1 }]); + + render( + + + + ); + + await waitFor(() => { + expect(propFind).toHaveBeenCalled(); + }); + expect(contextFind).not.toHaveBeenCalled(); + }); +}); diff --git a/packages/react/src/context/SchemaRendererContext.tsx b/packages/react/src/context/SchemaRendererContext.tsx index a20518290..09e256ce2 100644 --- a/packages/react/src/context/SchemaRendererContext.tsx +++ b/packages/react/src/context/SchemaRendererContext.tsx @@ -41,7 +41,8 @@ export const useSchemaContext = () => { export const useDataScope = (path?: string) => { const context = useContext(SchemaRendererContext); const dataSource = context?.dataSource; - if (!dataSource || !path) return dataSource; + if (!path) return undefined; + if (!dataSource) return undefined; // Simple path resolution for now. In real app might be more complex return path.split('.').reduce((acc, part) => acc && acc[part], dataSource); } diff --git a/packages/react/src/context/__tests__/useDataScope.test.tsx b/packages/react/src/context/__tests__/useDataScope.test.tsx new file mode 100644 index 000000000..deff53df4 --- /dev/null +++ b/packages/react/src/context/__tests__/useDataScope.test.tsx @@ -0,0 +1,91 @@ +/** + * Tests for useDataScope hook — verifies correct scoping behavior. + */ + +import { describe, it, expect } from 'vitest'; +import { renderHook } from '@testing-library/react'; +import React from 'react'; +import { SchemaRendererProvider, useDataScope } from '../SchemaRendererContext'; + +describe('useDataScope', () => { + it('returns undefined when no path is provided', () => { + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook(() => useDataScope(undefined), { wrapper }); + + expect(result.current).toBeUndefined(); + }); + + it('returns undefined when path is empty string', () => { + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook(() => useDataScope(''), { wrapper }); + + expect(result.current).toBeUndefined(); + }); + + it('returns scoped data when a valid path is given', () => { + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook(() => useDataScope('users'), { wrapper }); + + expect(result.current).toEqual([{ name: 'Alice' }]); + }); + + it('resolves nested paths', () => { + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook(() => useDataScope('app.settings.theme'), { wrapper }); + + expect(result.current).toBe('dark'); + }); + + it('returns undefined for non-existent path', () => { + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook(() => useDataScope('nonexistent'), { wrapper }); + + expect(result.current).toBeUndefined(); + }); + + it('returns undefined when no SchemaRendererProvider is present', () => { + const { result } = renderHook(() => useDataScope('users')); + + expect(result.current).toBeUndefined(); + }); + + it('does not return the adapter/service object when no path is given', () => { + // Simulate the real scenario: dataSource is a service adapter with methods + const adapter = { find: () => {}, create: () => {}, update: () => {} }; + const wrapper = ({ children }: { children: React.ReactNode }) => ( + + {children} + + ); + + const { result } = renderHook(() => useDataScope(undefined), { wrapper }); + + // Should NOT return the adapter — that would prevent ObjectChart from fetching + expect(result.current).toBeUndefined(); + }); +}); From 2a70901117d8ba819a294e7237f89253ae1d86c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 02:49:52 +0000 Subject: [PATCH 3/5] docs: update ROADMAP.md with dashboard widget data blank fix entry Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index 6233930fa..5d3953481 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -865,6 +865,7 @@ The `FlowDesigner` is a canvas-based flow editor that bridges the gap between th - [x] **P2: Full Examples Metadata Audit** — Systematic spec compliance audit across all 4 examples: added `type: 'dashboard'` + `description` to todo/kitchen-sink dashboards, refactored msw-todo to use `ObjectSchema.create` + `Field.*` with snake_case field names, added explicit views to kitchen-sink and msw-todo, added missing `successMessage` on CRM opportunity action, 21 automated compliance tests - [x] **P2: CRM Dashboard Full provider:'object' Adaptation** — Converted all chart and table widgets in CRM dashboard from static `provider: 'value'` to dynamic `provider: 'object'` with aggregation configs. 12 widgets total: 4 KPI metrics (static), 7 charts (sum/count/avg/max aggregation across opportunity, product, order objects), 1 table (dynamic fetch). Cross-object coverage (order), diverse aggregate functions (sum, count, avg, max). Fixed table `close_date` field alignment. Added i18n for 2 new widgets (10 locales). 9 new CRM metadata tests, 6 new DashboardRenderer rendering tests (area/donut/line/cross-object + edge cases). All provider:'object' paths covered. - [x] **P1: Dashboard provider:'object' Crash & Blank Rendering Fixes** — Fixed 3 critical bugs causing all charts to be blank and tables to crash on provider:'object' dashboards: (1) DashboardRenderer `...options` spread was leaking provider config objects as `data` in data-table and pivot schemas — fixed by destructuring `data` out before spread, (2) DataTableRenderer and PivotTable now guard with `Array.isArray()` for graceful degradation when non-array data arrives, (3) ObjectChart now shows visible loading/warning messages instead of silently rendering blank when `dataSource` is missing. Also added provider:'object' support to DashboardGridLayout (charts, tables, pivots). 2 new regression tests. +- [x] **P1: Dashboard Widget Data Blank — useDataScope/dataSource Injection Fix** — Fixed root cause of dashboard widgets showing blank data with no server requests: `useDataScope(undefined)` was returning the full context `dataSource` (service adapter) instead of `undefined` when no bind path was given, causing ObjectChart and all data components (ObjectKanban, ObjectGallery, ObjectTimeline, ObjectGrid) to treat the adapter as pre-bound data and skip async fetching. Fixed `useDataScope` to return `undefined` when no path is provided. Also improved ObjectChart fault tolerance: uses `useContext` directly instead of `useSchemaContext` (no throw without provider), validates `dataSource.find` is callable before invoking. 14 new tests (7 useDataScope + 7 ObjectChart data fetch/fault tolerance). - [x] **P1: URL-Driven Debug/Developer Panel** — Universal debug mode activated via `?__debug` URL parameter (amis devtools-style). `@object-ui/core`: exported `DebugFlags`, `DebugCollector` (perf/expr/event data collection, tree-shakeable), `parseDebugFlags()`, enhanced `isDebugEnabled()` (URL → globalThis → env resolution, SSR-safe). `@object-ui/react`: `useDebugMode` hook with URL detection, Ctrl+Shift+D shortcut, manual toggle; `SchemaRendererContext` extended with `debugFlags`; `SchemaRenderer` injects `data-debug-type`/`data-debug-id` attrs + reports render perf to `DebugCollector` when debug enabled. `@object-ui/components`: floating `DebugPanel` with 7 built-in tabs (Schema, Data, Perf, Expr, Events, Registry, Flags), plugin-extensible via `extraTabs`. Console `MetadataInspector` auto-opens when `?__debug` detected. Fine-grained sub-flags: `?__debug_schema`, `?__debug_perf`, `?__debug_data`, `?__debug_expr`, `?__debug_events`, `?__debug_registry`. 48 new tests. ### Ecosystem & Marketplace From cbd364ee509978978898a4e3c8d222230b78855c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 03:12:19 +0000 Subject: [PATCH 4/5] fix: apply consistent fault tolerance across all data-fetching components - ObjectGallery: use useContext(SchemaRendererContext) instead of useSchemaContext() for graceful degradation - ObjectGallery, ObjectKanban, ObjectTimeline: add typeof dataSource.find guard - ObjectCalendar, ObjectGantt, ObjectMap: add typeof dataSource.find guard - RelatedList: add typeof dataSource.find guard - Update ObjectGallery test mocks to provide SchemaRendererContext Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/plugin-calendar/src/ObjectCalendar.tsx | 2 +- packages/plugin-detail/src/RelatedList.tsx | 2 +- packages/plugin-gantt/src/ObjectGantt.tsx | 3 +-- packages/plugin-kanban/src/ObjectKanban.tsx | 2 +- packages/plugin-list/src/ObjectGallery.tsx | 10 +++++----- .../src/__tests__/GalleryGrouping.test.tsx | 13 ++++++++----- .../src/__tests__/ObjectGallery.test.tsx | 13 ++++++++----- packages/plugin-map/src/ObjectMap.tsx | 2 +- packages/plugin-timeline/src/ObjectTimeline.tsx | 2 +- 9 files changed, 27 insertions(+), 22 deletions(-) diff --git a/packages/plugin-calendar/src/ObjectCalendar.tsx b/packages/plugin-calendar/src/ObjectCalendar.tsx index fc3555501..3022be3ec 100644 --- a/packages/plugin-calendar/src/ObjectCalendar.tsx +++ b/packages/plugin-calendar/src/ObjectCalendar.tsx @@ -209,7 +209,7 @@ export const ObjectCalendar: React.FC = ({ } } - if (!dataSource) { + if (!dataSource || typeof dataSource.find !== 'function') { throw new Error('DataSource required for object/api providers'); } diff --git a/packages/plugin-detail/src/RelatedList.tsx b/packages/plugin-detail/src/RelatedList.tsx index b1d9f1232..5eb20ea86 100644 --- a/packages/plugin-detail/src/RelatedList.tsx +++ b/packages/plugin-detail/src/RelatedList.tsx @@ -38,7 +38,7 @@ export const RelatedList: React.FC = ({ React.useEffect(() => { if (api && !data.length) { setLoading(true); - if (dataSource) { + if (dataSource && typeof dataSource.find === 'function') { dataSource.find(api).then((result) => { const items = Array.isArray(result) ? result diff --git a/packages/plugin-gantt/src/ObjectGantt.tsx b/packages/plugin-gantt/src/ObjectGantt.tsx index 0572e7f12..e752f6a16 100644 --- a/packages/plugin-gantt/src/ObjectGantt.tsx +++ b/packages/plugin-gantt/src/ObjectGantt.tsx @@ -168,7 +168,7 @@ export const ObjectGantt: React.FC = ({ return; } - if (!dataSource) { + if (!dataSource || typeof dataSource.find !== 'function') { throw new Error('DataSource required for object/api providers'); } @@ -178,7 +178,6 @@ export const ObjectGantt: React.FC = ({ $filter: schema.filter, $orderby: convertSortToQueryParams(schema.sort), }); - let items: any[] = extractRecords(result); setData(items); } else if (dataConfig?.provider === 'api') { diff --git a/packages/plugin-kanban/src/ObjectKanban.tsx b/packages/plugin-kanban/src/ObjectKanban.tsx index b57c43c0f..2313c8321 100644 --- a/packages/plugin-kanban/src/ObjectKanban.tsx +++ b/packages/plugin-kanban/src/ObjectKanban.tsx @@ -58,7 +58,7 @@ export const ObjectKanban: React.FC = ({ useEffect(() => { let isMounted = true; const fetchData = async () => { - if (!dataSource || !schema.objectName) return; + if (!dataSource || typeof dataSource.find !== 'function' || !schema.objectName) return; if (isMounted) setLoading(true); try { const results = await dataSource.find(schema.objectName, { diff --git a/packages/plugin-list/src/ObjectGallery.tsx b/packages/plugin-list/src/ObjectGallery.tsx index 6e288491b..9c52bd644 100644 --- a/packages/plugin-list/src/ObjectGallery.tsx +++ b/packages/plugin-list/src/ObjectGallery.tsx @@ -6,8 +6,8 @@ * LICENSE file in the root directory of this source tree. */ -import React, { useState, useEffect, useCallback, useMemo } from 'react'; -import { useDataScope, useSchemaContext, useNavigationOverlay } from '@object-ui/react'; +import React, { useState, useEffect, useCallback, useMemo, useContext } from 'react'; +import { useDataScope, SchemaRendererContext, useNavigationOverlay } from '@object-ui/react'; import { ComponentRegistry } from '@object-ui/core'; import { cn, Card, CardContent, NavigationOverlay } from '@object-ui/components'; import type { GalleryConfig, ViewNavigationConfig, GroupingConfig } from '@object-ui/types'; @@ -52,8 +52,8 @@ const ASPECT_CLASSES: Record, string> = { export const ObjectGallery: React.FC = (props) => { const { schema } = props; - const context = useSchemaContext(); - const dataSource = props.dataSource || context.dataSource; + const context = useContext(SchemaRendererContext); + const dataSource = props.dataSource || context?.dataSource; const boundData = useDataScope(schema.bind); const [fetchedData, setFetchedData] = useState[]>([]); @@ -83,7 +83,7 @@ export const ObjectGallery: React.FC = (props) => { } const fetchData = async () => { - if (!dataSource || !schema.objectName) return; + if (!dataSource || typeof dataSource.find !== 'function' || !schema.objectName) return; if (isMounted) setLoading(true); try { const results = await dataSource.find(schema.objectName, { diff --git a/packages/plugin-list/src/__tests__/GalleryGrouping.test.tsx b/packages/plugin-list/src/__tests__/GalleryGrouping.test.tsx index bcaa5da8c..d253902c8 100644 --- a/packages/plugin-list/src/__tests__/GalleryGrouping.test.tsx +++ b/packages/plugin-list/src/__tests__/GalleryGrouping.test.tsx @@ -24,11 +24,14 @@ const mockNavigationOverlay = { open: vi.fn(), }; -vi.mock('@object-ui/react', () => ({ - useDataScope: () => undefined, - useSchemaContext: () => ({ dataSource: undefined }), - useNavigationOverlay: () => mockNavigationOverlay, -})); +vi.mock('@object-ui/react', () => { + const React = require('react'); + return { + useDataScope: () => undefined, + SchemaRendererContext: React.createContext(null), + useNavigationOverlay: () => mockNavigationOverlay, + }; +}); vi.mock('@object-ui/components', () => ({ cn: (...args: any[]) => args.filter(Boolean).join(' '), diff --git a/packages/plugin-list/src/__tests__/ObjectGallery.test.tsx b/packages/plugin-list/src/__tests__/ObjectGallery.test.tsx index 01e436726..5792cbaf5 100644 --- a/packages/plugin-list/src/__tests__/ObjectGallery.test.tsx +++ b/packages/plugin-list/src/__tests__/ObjectGallery.test.tsx @@ -25,11 +25,14 @@ const mockNavigationOverlay = { open: vi.fn(), }; -vi.mock('@object-ui/react', () => ({ - useDataScope: () => undefined, - useSchemaContext: () => ({ dataSource: undefined }), - useNavigationOverlay: () => mockNavigationOverlay, -})); +vi.mock('@object-ui/react', () => { + const React = require('react'); + return { + useDataScope: () => undefined, + SchemaRendererContext: React.createContext(null), + useNavigationOverlay: () => mockNavigationOverlay, + }; +}); vi.mock('@object-ui/components', () => ({ cn: (...args: any[]) => args.filter(Boolean).join(' '), diff --git a/packages/plugin-map/src/ObjectMap.tsx b/packages/plugin-map/src/ObjectMap.tsx index 5c0edff51..99833f691 100644 --- a/packages/plugin-map/src/ObjectMap.tsx +++ b/packages/plugin-map/src/ObjectMap.tsx @@ -344,7 +344,7 @@ export const ObjectMap: React.FC = ({ return; } - if (!dataSource) { + if (!dataSource || typeof dataSource.find !== 'function') { throw new Error('DataSource required for object/api providers'); } diff --git a/packages/plugin-timeline/src/ObjectTimeline.tsx b/packages/plugin-timeline/src/ObjectTimeline.tsx index dc08f9274..e61073c8d 100644 --- a/packages/plugin-timeline/src/ObjectTimeline.tsx +++ b/packages/plugin-timeline/src/ObjectTimeline.tsx @@ -97,7 +97,7 @@ export const ObjectTimeline: React.FC = ({ useEffect(() => { const fetchData = async () => { - if (!dataSource || !schema.objectName) return; + if (!dataSource || typeof dataSource.find !== 'function' || !schema.objectName) return; setLoading(true); try { const results = await dataSource.find(schema.objectName, { From 7aa13453a052d5e7703e904fb42088a72d6f88d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 25 Feb 2026 03:16:08 +0000 Subject: [PATCH 5/5] fix: add fallback to useSchemaContext in all plugin bridge renderers Apply || {} fallback pattern to ObjectCalendarRenderer, ObjectGanttRenderer, ObjectMapRenderer, ObjectTimelineRenderer for consistency with ObjectKanbanRenderer and ObjectGridRenderer. Co-authored-by: hotlong <50353452+hotlong@users.noreply.github.com> --- packages/plugin-calendar/src/index.tsx | 2 +- packages/plugin-gantt/src/index.tsx | 2 +- packages/plugin-map/src/index.tsx | 2 +- packages/plugin-timeline/src/index.tsx | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/plugin-calendar/src/index.tsx b/packages/plugin-calendar/src/index.tsx index 251ce772b..199367af2 100644 --- a/packages/plugin-calendar/src/index.tsx +++ b/packages/plugin-calendar/src/index.tsx @@ -25,7 +25,7 @@ import './calendar-view-renderer'; // Register object-calendar component export const ObjectCalendarRenderer: React.FC<{ schema: any; [key: string]: any }> = ({ schema, data: _data, loading: _loading, ...props }) => { - const { dataSource } = useSchemaContext(); + const { dataSource } = useSchemaContext() || {}; return ; }; diff --git a/packages/plugin-gantt/src/index.tsx b/packages/plugin-gantt/src/index.tsx index 4fbf7d137..c78fd6cad 100644 --- a/packages/plugin-gantt/src/index.tsx +++ b/packages/plugin-gantt/src/index.tsx @@ -20,7 +20,7 @@ export type { GanttViewProps, GanttTask, GanttViewMode } from './GanttView'; // Register component export const ObjectGanttRenderer: React.FC<{ schema: any }> = ({ schema }) => { - const { dataSource } = useSchemaContext(); + const { dataSource } = useSchemaContext() || {}; return ; }; diff --git a/packages/plugin-map/src/index.tsx b/packages/plugin-map/src/index.tsx index e23ee8ffc..69b4f0731 100644 --- a/packages/plugin-map/src/index.tsx +++ b/packages/plugin-map/src/index.tsx @@ -17,7 +17,7 @@ export type { ObjectMapProps }; // Register component export const ObjectMapRenderer: React.FC = ({ schema, ...props }) => { - const { dataSource } = useSchemaContext(); + const { dataSource } = useSchemaContext() || {}; return ; }; diff --git a/packages/plugin-timeline/src/index.tsx b/packages/plugin-timeline/src/index.tsx index 9d0be7da3..fb3463788 100644 --- a/packages/plugin-timeline/src/index.tsx +++ b/packages/plugin-timeline/src/index.tsx @@ -309,7 +309,7 @@ import { useSchemaContext } from '@object-ui/react'; // Register object-timeline component export const ObjectTimelineRenderer: React.FC = ({ schema, ...props }) => { - const { dataSource } = useSchemaContext(); + const { dataSource } = useSchemaContext() || {}; return ; };