@object-ui/plugin-dashboard 3.0.3 → 3.1.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.
Files changed (55) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/CHANGELOG.md +10 -0
  3. package/dist/index.js +3848 -2635
  4. package/dist/index.umd.cjs +5 -5
  5. package/dist/src/DashboardConfigPanel.d.ts +28 -0
  6. package/dist/src/DashboardConfigPanel.d.ts.map +1 -0
  7. package/dist/src/DashboardConfigPanel.stories.d.ts +14 -0
  8. package/dist/src/DashboardConfigPanel.stories.d.ts.map +1 -0
  9. package/dist/src/DashboardGridLayout.d.ts.map +1 -1
  10. package/dist/src/DashboardRenderer.d.ts +14 -0
  11. package/dist/src/DashboardRenderer.d.ts.map +1 -1
  12. package/dist/src/DashboardWithConfig.d.ts +32 -0
  13. package/dist/src/DashboardWithConfig.d.ts.map +1 -0
  14. package/dist/src/MetricCard.d.ts +8 -2
  15. package/dist/src/MetricCard.d.ts.map +1 -1
  16. package/dist/src/MetricWidget.d.ts +12 -3
  17. package/dist/src/MetricWidget.d.ts.map +1 -1
  18. package/dist/src/ObjectDataTable.d.ts +39 -0
  19. package/dist/src/ObjectDataTable.d.ts.map +1 -0
  20. package/dist/src/ObjectPivotTable.d.ts +29 -0
  21. package/dist/src/ObjectPivotTable.d.ts.map +1 -0
  22. package/dist/src/PivotTable.d.ts +14 -0
  23. package/dist/src/PivotTable.d.ts.map +1 -0
  24. package/dist/src/WidgetConfigPanel.d.ts +43 -0
  25. package/dist/src/WidgetConfigPanel.d.ts.map +1 -0
  26. package/dist/src/index.d.ts +13 -1
  27. package/dist/src/index.d.ts.map +1 -1
  28. package/dist/src/utils.d.ts +15 -0
  29. package/dist/src/utils.d.ts.map +1 -0
  30. package/package.json +7 -7
  31. package/src/DashboardConfigPanel.stories.tsx +164 -0
  32. package/src/DashboardConfigPanel.tsx +158 -0
  33. package/src/DashboardGridLayout.tsx +101 -3
  34. package/src/DashboardRenderer.tsx +269 -28
  35. package/src/DashboardWithConfig.tsx +211 -0
  36. package/src/MetricCard.tsx +11 -4
  37. package/src/MetricWidget.tsx +18 -11
  38. package/src/ObjectDataTable.tsx +191 -0
  39. package/src/ObjectPivotTable.tsx +160 -0
  40. package/src/PivotTable.tsx +262 -0
  41. package/src/WidgetConfigPanel.tsx +540 -0
  42. package/src/__tests__/DashboardConfigPanel.test.tsx +206 -0
  43. package/src/__tests__/DashboardRenderer.designMode.test.tsx +386 -0
  44. package/src/__tests__/DashboardRenderer.header.test.tsx +114 -0
  45. package/src/__tests__/DashboardRenderer.mobile.test.tsx +214 -0
  46. package/src/__tests__/DashboardRenderer.widgetData.test.tsx +1022 -0
  47. package/src/__tests__/DashboardWithConfig.test.tsx +276 -0
  48. package/src/__tests__/MetricCard.test.tsx +23 -0
  49. package/src/__tests__/ObjectDataTable.test.tsx +122 -0
  50. package/src/__tests__/ObjectPivotTable.test.tsx +192 -0
  51. package/src/__tests__/PivotTable.test.tsx +162 -0
  52. package/src/__tests__/WidgetConfigPanel.test.tsx +492 -0
  53. package/src/__tests__/ensureWidgetIds.test.tsx +103 -0
  54. package/src/index.tsx +107 -1
  55. package/src/utils.ts +17 -0
@@ -0,0 +1,28 @@
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 DashboardConfigPanelProps {
9
+ /** Whether the panel is open */
10
+ open: boolean;
11
+ /** Close handler */
12
+ onClose: () => void;
13
+ /** Initial / committed dashboard configuration */
14
+ config: Record<string, any>;
15
+ /** Persist the updated config */
16
+ onSave: (config: Record<string, any>) => void;
17
+ /** Optional live-update callback */
18
+ onFieldChange?: (field: string, value: any) => void;
19
+ }
20
+ /**
21
+ * DashboardConfigPanel — Schema-driven configuration panel for dashboards.
22
+ *
23
+ * Built entirely on the generic ConfigPanelRenderer + useConfigDraft,
24
+ * demonstrating that a full config panel can be expressed in ~60 lines
25
+ * of declarative schema rather than 1500+ lines of imperative code.
26
+ */
27
+ export declare function DashboardConfigPanel({ open, onClose, config, onSave, onFieldChange, }: DashboardConfigPanelProps): import("react/jsx-runtime").JSX.Element;
28
+ //# sourceMappingURL=DashboardConfigPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardConfigPanel.d.ts","sourceRoot":"","sources":["../../src/DashboardConfigPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAwGH,MAAM,WAAW,yBAAyB;IACxC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,kDAAkD;IAClD,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,iCAAiC;IACjC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;CACrD;AAMD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,EACnC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,aAAa,GACd,EAAE,yBAAyB,2CAiB3B"}
@@ -0,0 +1,14 @@
1
+ import { StoryObj } from '@storybook/react';
2
+ declare const widgetMeta: {
3
+ title: string;
4
+ parameters: {
5
+ layout: string;
6
+ };
7
+ tags: string[];
8
+ };
9
+ export default widgetMeta;
10
+ type Story = StoryObj<typeof widgetMeta>;
11
+ export declare const WidgetConfig: Story;
12
+ export declare const DashboardWithConfigPanel: Story;
13
+ export declare const DashboardWithConfigClosed: Story;
14
+ //# sourceMappingURL=DashboardConfigPanel.stories.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardConfigPanel.stories.d.ts","sourceRoot":"","sources":["../../src/DashboardConfigPanel.stories.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAQ,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAOvD,QAAA,MAAM,UAAU;;;;;;CAMA,CAAC;AAEjB,eAAe,UAAU,CAAC;AAC1B,KAAK,KAAK,GAAG,QAAQ,CAAC,OAAO,UAAU,CAAC,CAAC;AAmCzC,eAAO,MAAM,YAAY,EAAE,KAE1B,CAAC;AA+EF,eAAO,MAAM,wBAAwB,EAAE,KAEtC,CAAC;AAkBF,eAAO,MAAM,yBAAyB,EAAE,KAEvC,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardGridLayout.d.ts","sourceRoot":"","sources":["../../src/DashboardGridLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA2C,KAAK,UAAU,IAAI,SAAS,EAAuC,MAAM,mBAAmB,CAAC;AAC/I,OAAO,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AA0B/E,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAmOlE,CAAC"}
1
+ {"version":3,"file":"DashboardGridLayout.d.ts","sourceRoot":"","sources":["../../src/DashboardGridLayout.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EAA2C,KAAK,UAAU,IAAI,SAAS,EAAuC,MAAM,mBAAmB,CAAC;AAC/I,OAAO,kCAAkC,CAAC;AAI1C,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AA2B/E,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,SAAS,EAAE,KAAK,IAAI,CAAC;IAC/C,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;CACxB;AAED,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,wBAAwB,CAoUlE,CAAC"}
@@ -4,6 +4,20 @@ export interface DashboardRendererProps {
4
4
  className?: string;
5
5
  /** Callback invoked when dashboard refresh is triggered (manual or auto) */
6
6
  onRefresh?: () => void;
7
+ /** Total record count to display */
8
+ recordCount?: number;
9
+ /** User actions configuration */
10
+ userActions?: {
11
+ sort?: boolean;
12
+ search?: boolean;
13
+ filter?: boolean;
14
+ };
15
+ /** Enable design mode — shows selection affordances on widgets */
16
+ designMode?: boolean;
17
+ /** Currently selected widget ID (controlled) */
18
+ selectedWidgetId?: string | null;
19
+ /** Callback when a widget is clicked in design mode */
20
+ onWidgetClick?: (widgetId: string | null) => void;
7
21
  [key: string]: any;
8
22
  }
9
23
  export declare const DashboardRenderer: import('react').ForwardRefExoticComponent<Omit<DashboardRendererProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
@@ -1 +1 @@
1
- {"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../../src/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AAe/E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,gIA4K7B,CAAC"}
1
+ {"version":3,"file":"DashboardRenderer.d.ts","sourceRoot":"","sources":["../../src/DashboardRenderer.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AAuB/E,MAAM,WAAW,sBAAsB;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4EAA4E;IAC5E,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,oCAAoC;IACpC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,WAAW,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAC;QAAC,MAAM,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC;IACrE,kEAAkE;IAClE,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,gDAAgD;IAChD,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC,uDAAuD;IACvD,aAAa,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,eAAO,MAAM,iBAAiB,gIA2Y7B,CAAC"}
@@ -0,0 +1,32 @@
1
+ import { DashboardSchema } from '../../types/src';
2
+ export interface DashboardWithConfigProps {
3
+ /** Dashboard schema for rendering */
4
+ schema: DashboardSchema;
5
+ /** Current dashboard configuration (for the config panel) */
6
+ config: Record<string, any>;
7
+ /** Called when config panel saves dashboard-level changes */
8
+ onConfigSave: (config: Record<string, any>) => void;
9
+ /** Called when widget config panel saves widget-level changes */
10
+ onWidgetSave?: (widgetId: string, config: Record<string, any>) => void;
11
+ /** Callback invoked when dashboard refresh is triggered */
12
+ onRefresh?: () => void;
13
+ /** Total record count */
14
+ recordCount?: number;
15
+ /** Whether the config panel is open initially */
16
+ defaultConfigOpen?: boolean;
17
+ /** Additional CSS class name for the container */
18
+ className?: string;
19
+ }
20
+ /**
21
+ * DashboardWithConfig — Composite component combining a DashboardRenderer
22
+ * with a DashboardConfigPanel sidebar.
23
+ *
24
+ * Supports:
25
+ * - Toggle config panel visibility via a Settings button
26
+ * - Dashboard-level configuration editing
27
+ * - Click-to-select a widget → sidebar switches to WidgetConfigPanel
28
+ * - Back navigation from widget config to dashboard config
29
+ * - Live preview: widget config changes are reflected in real time
30
+ */
31
+ export declare function DashboardWithConfig({ schema, config, onConfigSave, onWidgetSave, onRefresh, recordCount, defaultConfigOpen, className, }: DashboardWithConfigProps): import("react/jsx-runtime").JSX.Element;
32
+ //# sourceMappingURL=DashboardWithConfig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DashboardWithConfig.d.ts","sourceRoot":"","sources":["../../src/DashboardWithConfig.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,KAAK,EAAE,eAAe,EAAyB,MAAM,kBAAkB,CAAC;AAU/E,MAAM,WAAW,wBAAwB;IACvC,qCAAqC;IACrC,MAAM,EAAE,eAAe,CAAC;IACxB,6DAA6D;IAC7D,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,6DAA6D;IAC7D,YAAY,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACpD,iEAAiE;IACjE,YAAY,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IACvE,2DAA2D;IAC3D,SAAS,CAAC,EAAE,MAAM,IAAI,CAAC;IACvB,yBAAyB;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,iDAAiD;IACjD,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,kDAAkD;IAClD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAMD;;;;;;;;;;GAUG;AACH,wBAAgB,mBAAmB,CAAC,EAClC,MAAM,EACN,MAAM,EACN,YAAY,EACZ,YAAY,EACZ,SAAS,EACT,WAAW,EACX,iBAAyB,EACzB,SAAS,GACV,EAAE,wBAAwB,2CAiJ1B"}
@@ -1,11 +1,17 @@
1
1
  import { default as React } from 'react';
2
2
  export interface MetricCardProps {
3
- title?: string;
3
+ title?: string | {
4
+ key?: string;
5
+ defaultValue?: string;
6
+ };
4
7
  value: string | number;
5
8
  icon?: string;
6
9
  trend?: 'up' | 'down' | 'neutral';
7
10
  trendValue?: string;
8
- description?: string;
11
+ description?: string | {
12
+ key?: string;
13
+ defaultValue?: string;
14
+ };
9
15
  className?: string;
10
16
  }
11
17
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"MetricCard.d.ts","sourceRoot":"","sources":["../../src/MetricCard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8ChD,CAAC"}
1
+ {"version":3,"file":"MetricCard.d.ts","sourceRoot":"","sources":["../../src/MetricCard.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,MAAM,OAAO,CAAC;AAa1B,MAAM,WAAW,eAAe;IAC9B,KAAK,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACzD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;IAClC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/D,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;GAGG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA8ChD,CAAC"}
@@ -1,15 +1,24 @@
1
1
  import { default as React } from 'react';
2
2
  export interface MetricWidgetProps {
3
- label: string;
3
+ label: string | {
4
+ key?: string;
5
+ defaultValue?: string;
6
+ };
4
7
  value: string | number;
5
8
  trend?: {
6
9
  value: number;
7
- label?: string;
10
+ label?: string | {
11
+ key?: string;
12
+ defaultValue?: string;
13
+ };
8
14
  direction?: 'up' | 'down' | 'neutral';
9
15
  };
10
16
  icon?: React.ReactNode | string;
11
17
  className?: string;
12
- description?: string;
18
+ description?: string | {
19
+ key?: string;
20
+ defaultValue?: string;
21
+ };
13
22
  }
14
23
  export declare const MetricWidget: ({ label, value, trend, icon, className, description, ...props }: MetricWidgetProps) => import("react/jsx-runtime").JSX.Element;
15
24
  //# sourceMappingURL=MetricWidget.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"MetricWidget.d.ts","sourceRoot":"","sources":["../../src/MetricWidget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAMvC,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;IACF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,YAAY,GAAI,iEAQ1B,iBAAiB,4CAyCnB,CAAC"}
1
+ {"version":3,"file":"MetricWidget.d.ts","sourceRoot":"","sources":["../../src/MetricWidget.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAkB,MAAM,OAAO,CAAC;AAavC,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACxD,KAAK,EAAE,MAAM,GAAG,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE;QACN,KAAK,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,MAAM,GAAG;YAAE,GAAG,CAAC,EAAE,MAAM,CAAC;YAAC,YAAY,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACzD,SAAS,CAAC,EAAE,IAAI,GAAG,MAAM,GAAG,SAAS,CAAC;KACvC,CAAC;IACF,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,GAAG,MAAM,CAAC;IAChC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,MAAM,GAAG;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAChE;AAED,eAAO,MAAM,YAAY,GAAI,iEAQ1B,iBAAiB,4CAyCnB,CAAC"}
@@ -0,0 +1,39 @@
1
+ import { default as React } from 'react';
2
+ export interface ObjectDataTableProps {
3
+ schema: {
4
+ type: string;
5
+ objectName?: string;
6
+ dataProvider?: {
7
+ provider: string;
8
+ object?: string;
9
+ };
10
+ bind?: string;
11
+ filter?: any;
12
+ data?: any[];
13
+ columns?: any[];
14
+ searchable?: boolean;
15
+ pagination?: boolean;
16
+ className?: string;
17
+ [key: string]: any;
18
+ };
19
+ dataSource?: any;
20
+ className?: string;
21
+ }
22
+ /**
23
+ * ObjectDataTable — Async-aware wrapper for data-table.
24
+ *
25
+ * When `objectName` is provided and a `dataSource` is available via context
26
+ * or props, fetches records automatically and passes them to the registered
27
+ * `data-table` component via SchemaRenderer.
28
+ *
29
+ * Also auto-derives columns from fetched data keys when no explicit columns
30
+ * are configured.
31
+ *
32
+ * Lifecycle states:
33
+ * - **Loading** → skeleton placeholder
34
+ * - **Error** → error message
35
+ * - **Empty** → friendly "No data available" message
36
+ * - **Data** → data-table with fetched rows
37
+ */
38
+ export declare const ObjectDataTable: React.FC<ObjectDataTableProps>;
39
+ //# sourceMappingURL=ObjectDataTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectDataTable.d.ts","sourceRoot":"","sources":["../../src/ObjectDataTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAmD,MAAM,OAAO,CAAC;AAKxE,MAAM,WAAW,oBAAoB;IACnC,MAAM,EAAE;QACN,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;QACb,IAAI,CAAC,EAAE,GAAG,EAAE,CAAC;QACb,OAAO,CAAC,EAAE,GAAG,EAAE,CAAC;QAChB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC;QACnB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;;;;;GAeG;AACH,eAAO,MAAM,eAAe,EAAE,KAAK,CAAC,EAAE,CAAC,oBAAoB,CA+I1D,CAAC"}
@@ -0,0 +1,29 @@
1
+ import { default as React } from 'react';
2
+ import { PivotTableSchema } from '../../types/src';
3
+ export interface ObjectPivotTableProps {
4
+ schema: PivotTableSchema & {
5
+ objectName?: string;
6
+ dataProvider?: {
7
+ provider: string;
8
+ object?: string;
9
+ };
10
+ bind?: string;
11
+ filter?: any;
12
+ };
13
+ dataSource?: any;
14
+ className?: string;
15
+ }
16
+ /**
17
+ * ObjectPivotTable — Async-aware wrapper around PivotTable.
18
+ *
19
+ * When `objectName` is provided and a `dataSource` is available via context
20
+ * or props, fetches records automatically and passes them to PivotTable.
21
+ *
22
+ * Lifecycle states:
23
+ * - **Loading** → skeleton placeholder
24
+ * - **Error** → error message
25
+ * - **Empty** → friendly "No data available" (delegated to PivotTable)
26
+ * - **Data** → PivotTable with fetched rows
27
+ */
28
+ export declare const ObjectPivotTable: React.FC<ObjectPivotTableProps>;
29
+ //# sourceMappingURL=ObjectPivotTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ObjectPivotTable.d.ts","sourceRoot":"","sources":["../../src/ObjectPivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAA0C,MAAM,OAAO,CAAC;AAK/D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AAEzD,MAAM,WAAW,qBAAqB;IACpC,MAAM,EAAE,gBAAgB,GAAG;QACzB,UAAU,CAAC,EAAE,MAAM,CAAC;QACpB,YAAY,CAAC,EAAE;YAAE,QAAQ,EAAE,MAAM,CAAC;YAAC,MAAM,CAAC,EAAE,MAAM,CAAA;SAAE,CAAC;QACrD,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,MAAM,CAAC,EAAE,GAAG,CAAC;KACd,CAAC;IACF,UAAU,CAAC,EAAE,GAAG,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,gBAAgB,EAAE,KAAK,CAAC,EAAE,CAAC,qBAAqB,CAyH5D,CAAC"}
@@ -0,0 +1,14 @@
1
+ import { default as React } from 'react';
2
+ import { PivotTableSchema } from '../../types/src';
3
+ export interface PivotTableProps {
4
+ schema: PivotTableSchema;
5
+ className?: string;
6
+ }
7
+ /**
8
+ * PivotTable – Cross-tabulation / Pivot Table component.
9
+ *
10
+ * Renders a matrix where rows correspond to `rowField`, columns to
11
+ * `columnField`, and cells show the aggregated `valueField`.
12
+ */
13
+ export declare const PivotTable: React.FC<PivotTableProps>;
14
+ //# sourceMappingURL=PivotTable.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"PivotTable.d.ts","sourceRoot":"","sources":["../../src/PivotTable.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAkB,MAAM,OAAO,CAAC;AACvC,OAAO,KAAK,EAAE,gBAAgB,EAAoB,MAAM,kBAAkB,CAAC;AAG3E,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAC;IACzB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAqED;;;;;GAKG;AACH,eAAO,MAAM,UAAU,EAAE,KAAK,CAAC,EAAE,CAAC,eAAe,CA2KhD,CAAC"}
@@ -0,0 +1,43 @@
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
+ import * as React from 'react';
9
+ export type SelectOption = {
10
+ value: string;
11
+ label: string;
12
+ };
13
+ export interface WidgetConfigPanelProps {
14
+ /** Whether the panel is open */
15
+ open: boolean;
16
+ /** Close handler */
17
+ onClose: () => void;
18
+ /** Widget configuration (flattened: layout.w → layoutW, layout.h → layoutH) */
19
+ config: Record<string, any>;
20
+ /** Persist the updated widget config */
21
+ onSave: (config: Record<string, any>) => void;
22
+ /** Optional live-update callback */
23
+ onFieldChange?: (field: string, value: any) => void;
24
+ /** Extra content rendered in the header row (e.g. delete button) */
25
+ headerExtra?: React.ReactNode;
26
+ /** Available data-source objects for dropdown selection */
27
+ availableObjects?: SelectOption[];
28
+ /** Available fields of the currently selected object for dropdown selection */
29
+ availableFields?: SelectOption[];
30
+ }
31
+ /**
32
+ * WidgetConfigPanel — Schema-driven configuration panel for individual
33
+ * dashboard widgets.
34
+ *
35
+ * Supports editing: title, description, type, data binding (object,
36
+ * categoryField, valueField, aggregate), layout (width, height),
37
+ * appearance (colorVariant, actionUrl).
38
+ *
39
+ * Sections are context-aware: pivot, table, and chart types each show
40
+ * their own dedicated config sections via `visibleWhen` predicates.
41
+ */
42
+ export declare function WidgetConfigPanel({ open, onClose, config, onSave, onFieldChange, headerExtra, availableObjects, availableFields, }: WidgetConfigPanelProps): import("react/jsx-runtime").JSX.Element;
43
+ //# sourceMappingURL=WidgetConfigPanel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"WidgetConfigPanel.d.ts","sourceRoot":"","sources":["../../src/WidgetConfigPanel.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAwE/B,MAAM,MAAM,YAAY,GAAG;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAuX5D,MAAM,WAAW,sBAAsB;IACrC,gCAAgC;IAChC,IAAI,EAAE,OAAO,CAAC;IACd,oBAAoB;IACpB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,+EAA+E;IAC/E,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IAC5B,wCAAwC;IACxC,MAAM,EAAE,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,KAAK,IAAI,CAAC;IAC9C,oCAAoC;IACpC,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,KAAK,IAAI,CAAC;IACpD,oEAAoE;IACpE,WAAW,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IAC9B,2DAA2D;IAC3D,gBAAgB,CAAC,EAAE,YAAY,EAAE,CAAC;IAClC,+EAA+E;IAC/E,eAAe,CAAC,EAAE,YAAY,EAAE,CAAC;CAClC;AAiBD;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,EAChC,IAAI,EACJ,OAAO,EACP,MAAM,EACN,MAAM,EACN,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,eAAe,GAChB,EAAE,sBAAsB,2CA8BxB"}
@@ -2,11 +2,23 @@ import { DashboardRenderer } from './DashboardRenderer';
2
2
  import { DashboardGridLayout } from './DashboardGridLayout';
3
3
  import { MetricWidget } from './MetricWidget';
4
4
  import { MetricCard } from './MetricCard';
5
- export { DashboardRenderer, DashboardGridLayout, MetricWidget, MetricCard };
5
+ import { PivotTable } from './PivotTable';
6
+ import { ObjectPivotTable } from './ObjectPivotTable';
7
+ import { ObjectDataTable } from './ObjectDataTable';
8
+ import { DashboardConfigPanel } from './DashboardConfigPanel';
9
+ import { WidgetConfigPanel } from './WidgetConfigPanel';
10
+ import { DashboardWithConfig } from './DashboardWithConfig';
11
+ export { DashboardRenderer, DashboardGridLayout, MetricWidget, MetricCard, PivotTable, ObjectPivotTable, ObjectDataTable, DashboardConfigPanel, WidgetConfigPanel, DashboardWithConfig };
6
12
  export declare const dashboardComponents: {
7
13
  DashboardRenderer: import('react').ForwardRefExoticComponent<Omit<import('./DashboardRenderer').DashboardRendererProps, "ref"> & import('react').RefAttributes<HTMLDivElement>>;
8
14
  DashboardGridLayout: import('react').FC<import('./DashboardGridLayout').DashboardGridLayoutProps>;
9
15
  MetricWidget: ({ label, value, trend, icon, className, description, ...props }: import('./MetricWidget').MetricWidgetProps) => import("react/jsx-runtime").JSX.Element;
10
16
  MetricCard: import('react').FC<import('./MetricCard').MetricCardProps>;
17
+ PivotTable: import('react').FC<import('./PivotTable').PivotTableProps>;
18
+ ObjectPivotTable: import('react').FC<import('./ObjectPivotTable').ObjectPivotTableProps>;
19
+ ObjectDataTable: import('react').FC<import('./ObjectDataTable').ObjectDataTableProps>;
20
+ DashboardConfigPanel: typeof DashboardConfigPanel;
21
+ WidgetConfigPanel: typeof WidgetConfigPanel;
22
+ DashboardWithConfig: typeof DashboardWithConfig;
11
23
  };
12
24
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,CAAC;AAwF5E,eAAO,MAAM,mBAAmB;;;;;CAK/B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.tsx"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAC5D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AACtD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AACxD,OAAO,EAAE,mBAAmB,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,YAAY,EAAE,UAAU,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,oBAAoB,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAC;AAsLzL,eAAO,MAAM,mBAAmB;;;;;;;;;;;CAW/B,CAAC"}
@@ -0,0 +1,15 @@
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
+ /** Returns true when the widget data config uses provider: 'object' (async data source). */
9
+ export declare function isObjectProvider(widgetData: unknown): widgetData is {
10
+ provider: 'object';
11
+ object?: string;
12
+ aggregate?: any;
13
+ filter?: any;
14
+ };
15
+ //# sourceMappingURL=utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../src/utils.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,4FAA4F;AAC5F,wBAAgB,gBAAgB,CAAC,UAAU,EAAE,OAAO,GAAG,UAAU,IAAI;IAAE,QAAQ,EAAE,QAAQ,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,GAAG,CAAC;IAAC,MAAM,CAAC,EAAE,GAAG,CAAA;CAAE,CAO1I"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/plugin-dashboard",
3
- "version": "3.0.3",
3
+ "version": "3.1.1",
4
4
  "type": "module",
5
5
  "license": "MIT",
6
6
  "description": "Dashboard plugin for Object UI",
@@ -16,15 +16,15 @@
16
16
  },
17
17
  "dependencies": {
18
18
  "clsx": "^2.1.1",
19
- "lucide-react": "^0.563.0",
19
+ "lucide-react": "^0.576.0",
20
20
  "react": "19.2.4",
21
21
  "react-dom": "19.2.4",
22
22
  "react-grid-layout": "^2.2.2",
23
- "tailwind-merge": "^2.6.1",
24
- "@object-ui/components": "3.0.3",
25
- "@object-ui/core": "3.0.3",
26
- "@object-ui/react": "3.0.3",
27
- "@object-ui/types": "3.0.3"
23
+ "tailwind-merge": "^3.5.0",
24
+ "@object-ui/components": "3.1.1",
25
+ "@object-ui/core": "3.1.1",
26
+ "@object-ui/react": "3.1.1",
27
+ "@object-ui/types": "3.1.1"
28
28
  },
29
29
  "peerDependencies": {
30
30
  "react": "^18.0.0",
@@ -0,0 +1,164 @@
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 React, { useState } from 'react';
10
+ import type { Meta, StoryObj } from '@storybook/react';
11
+ import { WidgetConfigPanel } from './WidgetConfigPanel';
12
+ import { DashboardWithConfig } from './DashboardWithConfig';
13
+ import type { DashboardSchema } from '@object-ui/types';
14
+
15
+ // ─── WidgetConfigPanel Stories ──────────────────────────────────────────────
16
+
17
+ const widgetMeta = {
18
+ title: 'Plugins/DashboardConfigPanel',
19
+ parameters: {
20
+ layout: 'padded',
21
+ },
22
+ tags: ['autodocs'],
23
+ } satisfies Meta;
24
+
25
+ export default widgetMeta;
26
+ type Story = StoryObj<typeof widgetMeta>;
27
+
28
+ // --- WidgetConfigPanel ---
29
+
30
+ const widgetConfig = {
31
+ title: 'Revenue Chart',
32
+ description: 'Monthly revenue by region',
33
+ type: 'bar',
34
+ object: 'orders',
35
+ categoryField: 'region',
36
+ valueField: 'amount',
37
+ aggregate: 'sum',
38
+ colorVariant: 'blue',
39
+ actionUrl: '',
40
+ layoutW: 2,
41
+ layoutH: 1,
42
+ };
43
+
44
+ function WidgetConfigStory() {
45
+ const [config, setConfig] = useState(widgetConfig);
46
+ return (
47
+ <div style={{ position: 'relative', height: 600, width: 320, border: '1px solid #e5e7eb', borderRadius: 8, overflow: 'hidden' }}>
48
+ <WidgetConfigPanel
49
+ open={true}
50
+ onClose={() => alert('Close clicked')}
51
+ config={config}
52
+ onSave={(newConfig) => {
53
+ setConfig(newConfig as typeof widgetConfig);
54
+ alert('Saved: ' + JSON.stringify(newConfig, null, 2));
55
+ }}
56
+ />
57
+ </div>
58
+ );
59
+ }
60
+
61
+ export const WidgetConfig: Story = {
62
+ render: () => <WidgetConfigStory />,
63
+ };
64
+
65
+ // --- DashboardWithConfig ---
66
+
67
+ const dashboardSchema: DashboardSchema = {
68
+ type: 'dashboard',
69
+ title: 'Sales Dashboard',
70
+ columns: 3,
71
+ gap: 4,
72
+ widgets: [
73
+ {
74
+ id: 'mc-1',
75
+ component: {
76
+ type: 'metric-card',
77
+ title: 'Total Revenue',
78
+ value: '$128,430',
79
+ icon: 'DollarSign',
80
+ trend: 'up',
81
+ trendValue: '+14.2%',
82
+ },
83
+ layout: { x: 0, y: 0, w: 1, h: 1 },
84
+ },
85
+ {
86
+ id: 'mc-2',
87
+ component: {
88
+ type: 'metric-card',
89
+ title: 'Active Users',
90
+ value: '3,842',
91
+ icon: 'Users',
92
+ trend: 'up',
93
+ trendValue: '+8.1%',
94
+ },
95
+ layout: { x: 1, y: 0, w: 1, h: 1 },
96
+ },
97
+ {
98
+ id: 'mc-3',
99
+ component: {
100
+ type: 'metric-card',
101
+ title: 'Churn Rate',
102
+ value: '1.8%',
103
+ icon: 'TrendingDown',
104
+ trend: 'down',
105
+ trendValue: '-0.3%',
106
+ },
107
+ layout: { x: 2, y: 0, w: 1, h: 1 },
108
+ },
109
+ ],
110
+ header: {
111
+ showTitle: true,
112
+ showDescription: true,
113
+ },
114
+ };
115
+
116
+ const dashboardConfig = {
117
+ columns: 3,
118
+ gap: 4,
119
+ rowHeight: '120',
120
+ refreshInterval: '0',
121
+ title: 'Sales Dashboard',
122
+ showDescription: true,
123
+ theme: 'auto',
124
+ };
125
+
126
+ function DashboardWithConfigStory() {
127
+ const [config, setConfig] = useState(dashboardConfig);
128
+ return (
129
+ <div style={{ height: 600, width: '100%', border: '1px solid #e5e7eb', borderRadius: 8, overflow: 'hidden' }}>
130
+ <DashboardWithConfig
131
+ schema={dashboardSchema}
132
+ config={config}
133
+ onConfigSave={(newConfig) => {
134
+ setConfig(newConfig as typeof dashboardConfig);
135
+ }}
136
+ defaultConfigOpen={true}
137
+ />
138
+ </div>
139
+ );
140
+ }
141
+
142
+ export const DashboardWithConfigPanel: Story = {
143
+ render: () => <DashboardWithConfigStory />,
144
+ };
145
+
146
+ function DashboardWithConfigClosedStory() {
147
+ const [config, setConfig] = useState(dashboardConfig);
148
+ return (
149
+ <div style={{ height: 600, width: '100%', border: '1px solid #e5e7eb', borderRadius: 8, overflow: 'hidden' }}>
150
+ <DashboardWithConfig
151
+ schema={dashboardSchema}
152
+ config={config}
153
+ onConfigSave={(newConfig) => {
154
+ setConfig(newConfig as typeof dashboardConfig);
155
+ }}
156
+ defaultConfigOpen={false}
157
+ />
158
+ </div>
159
+ );
160
+ }
161
+
162
+ export const DashboardWithConfigClosed: Story = {
163
+ render: () => <DashboardWithConfigClosedStory />,
164
+ };