@object-ui/plugin-grid 3.0.2 → 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 +10 -49
- package/CHANGELOG.md +11 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +2169 -922
- package/dist/index.umd.cjs +9 -3
- package/dist/plugin-grid/src/FormulaBar.d.ts +29 -0
- package/dist/plugin-grid/src/GroupRow.d.ts +23 -0
- package/dist/plugin-grid/src/ImportWizard.d.ts +29 -0
- package/dist/{packages/plugin-grid → plugin-grid}/src/ObjectGrid.d.ts +1 -0
- package/dist/plugin-grid/src/SplitPaneGrid.d.ts +22 -0
- package/dist/plugin-grid/src/components/BulkActionBar.d.ts +12 -0
- package/dist/plugin-grid/src/components/RowActionMenu.d.ts +23 -0
- package/dist/plugin-grid/src/index.d.ts +35 -0
- package/dist/plugin-grid/src/useCellClipboard.d.ts +47 -0
- package/dist/plugin-grid/src/useColumnSummary.d.ts +25 -0
- package/dist/plugin-grid/src/useGradientColor.d.ts +37 -0
- package/dist/plugin-grid/src/useGroupReorder.d.ts +34 -0
- package/dist/{packages/plugin-grid → plugin-grid}/src/useGroupedData.d.ts +24 -3
- package/package.json +10 -10
- package/src/FormulaBar.tsx +151 -0
- package/src/GroupRow.tsx +69 -0
- package/src/ImportWizard.tsx +412 -0
- package/src/ListColumnExtensions.test.tsx +4 -5
- package/src/ObjectGrid.tsx +994 -139
- package/src/SplitPaneGrid.tsx +120 -0
- package/src/VirtualGrid.tsx +2 -2
- package/src/__tests__/GroupRow.test.tsx +206 -0
- package/src/__tests__/ImportPreview.test.tsx +171 -0
- package/src/__tests__/accessorKey-inference.test.tsx +132 -0
- package/src/__tests__/airtable-style.test.tsx +508 -0
- package/src/__tests__/column-features.test.tsx +490 -0
- package/src/__tests__/grid-export.test.tsx +121 -0
- package/src/__tests__/mobile-card-view.test.tsx +355 -0
- package/src/__tests__/objectdef-enrichment.test.tsx +566 -0
- package/src/__tests__/phase11-features.test.tsx +418 -0
- package/src/__tests__/row-bulk-actions.test.tsx +413 -0
- package/src/__tests__/row-height.test.tsx +160 -0
- package/src/__tests__/useGroupedData.test.ts +165 -0
- package/src/components/BulkActionBar.tsx +66 -0
- package/src/components/RowActionMenu.tsx +91 -0
- package/src/index.tsx +46 -2
- package/src/useCellClipboard.ts +136 -0
- package/src/useColumnSummary.ts +128 -0
- package/src/useGradientColor.ts +103 -0
- package/src/useGroupReorder.ts +123 -0
- package/src/useGroupedData.ts +69 -4
- package/tsconfig.json +2 -1
- package/dist/packages/plugin-grid/src/ListColumnExtensions.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/ListColumnSchema.test.d.ts +0 -1
- package/dist/packages/plugin-grid/src/ObjectGrid.EdgeCases.stories.d.ts +0 -25
- package/dist/packages/plugin-grid/src/ObjectGrid.msw.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/ObjectGrid.stories.d.ts +0 -33
- package/dist/packages/plugin-grid/src/VirtualGrid.test.d.ts +0 -8
- package/dist/packages/plugin-grid/src/__tests__/InlineEditing.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/__tests__/VirtualGrid.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/__tests__/accessibility.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/__tests__/performance-benchmark.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/__tests__/view-states.test.d.ts +0 -0
- package/dist/packages/plugin-grid/src/index.d.ts +0 -15
- package/dist/packages/plugin-grid/src/index.test.d.ts +0 -1
- package/src/VirtualGrid.test.tsx +0 -23
- /package/dist/{packages/plugin-grid → plugin-grid}/src/InlineEditing.d.ts +0 -0
- /package/dist/{packages/plugin-grid → plugin-grid}/src/VirtualGrid.d.ts +0 -0
- /package/dist/{packages/plugin-grid → plugin-grid}/src/useRowColor.d.ts +0 -0
|
@@ -0,0 +1,103 @@
|
|
|
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 { useMemo, useCallback } from 'react';
|
|
10
|
+
|
|
11
|
+
/** A single stop in a colour gradient. */
|
|
12
|
+
export interface GradientStop {
|
|
13
|
+
/** Position between 0 and 1. */
|
|
14
|
+
position: number;
|
|
15
|
+
/** Tailwind background class applied at this stop (e.g. "bg-green-100"). */
|
|
16
|
+
className: string;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface UseGradientColorOptions {
|
|
20
|
+
/** The numeric field to evaluate on each row. */
|
|
21
|
+
field: string;
|
|
22
|
+
/** Flat data array used to derive min/max when not provided. */
|
|
23
|
+
data: Record<string, any>[];
|
|
24
|
+
/** Optional explicit minimum value. */
|
|
25
|
+
min?: number;
|
|
26
|
+
/** Optional explicit maximum value. */
|
|
27
|
+
max?: number;
|
|
28
|
+
/**
|
|
29
|
+
* Ordered gradient stops (position 0 → 1).
|
|
30
|
+
* When omitted a default green→yellow→red palette is used.
|
|
31
|
+
*/
|
|
32
|
+
stops?: GradientStop[];
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Default three-stop gradient: green → yellow → red. */
|
|
36
|
+
const DEFAULT_STOPS: GradientStop[] = [
|
|
37
|
+
{ position: 0, className: 'bg-green-100' },
|
|
38
|
+
{ position: 0.5, className: 'bg-yellow-100' },
|
|
39
|
+
{ position: 1, className: 'bg-red-100' },
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Derive min and max numeric values for `field` across `data`.
|
|
44
|
+
*/
|
|
45
|
+
function deriveRange(data: Record<string, any>[], field: string): [number, number] {
|
|
46
|
+
let lo = Infinity;
|
|
47
|
+
let hi = -Infinity;
|
|
48
|
+
for (const row of data) {
|
|
49
|
+
const v = Number(row[field]);
|
|
50
|
+
if (!Number.isFinite(v)) continue;
|
|
51
|
+
if (v < lo) lo = v;
|
|
52
|
+
if (v > hi) hi = v;
|
|
53
|
+
}
|
|
54
|
+
if (!Number.isFinite(lo)) return [0, 0];
|
|
55
|
+
return [lo, hi];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Pick the closest gradient stop class for a normalised position (0‑1).
|
|
60
|
+
*/
|
|
61
|
+
function pickStopClass(t: number, stops: GradientStop[]): string {
|
|
62
|
+
if (stops.length === 0) return '';
|
|
63
|
+
if (stops.length === 1) return stops[0].className;
|
|
64
|
+
|
|
65
|
+
let best = stops[0];
|
|
66
|
+
let bestDist = Math.abs(t - best.position);
|
|
67
|
+
|
|
68
|
+
for (let i = 1; i < stops.length; i++) {
|
|
69
|
+
const dist = Math.abs(t - stops[i].position);
|
|
70
|
+
if (dist < bestDist) {
|
|
71
|
+
best = stops[i];
|
|
72
|
+
bestDist = dist;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return best.className;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Hook that returns a row → Tailwind class resolver based on a numeric
|
|
80
|
+
* field's value mapped onto a configurable colour gradient.
|
|
81
|
+
*
|
|
82
|
+
* @param options - gradient configuration
|
|
83
|
+
* @returns `(row) => className | undefined`
|
|
84
|
+
*/
|
|
85
|
+
export function useGradientColor(options: UseGradientColorOptions) {
|
|
86
|
+
const { field, data, min: minProp, max: maxProp, stops = DEFAULT_STOPS } = options;
|
|
87
|
+
|
|
88
|
+
const [derivedMin, derivedMax] = useMemo(() => deriveRange(data, field), [data, field]);
|
|
89
|
+
const min = minProp ?? derivedMin;
|
|
90
|
+
const max = maxProp ?? derivedMax;
|
|
91
|
+
|
|
92
|
+
return useCallback(
|
|
93
|
+
(row: Record<string, any>): string | undefined => {
|
|
94
|
+
const v = Number(row[field]);
|
|
95
|
+
if (!Number.isFinite(v)) return undefined;
|
|
96
|
+
if (max === min) return stops.length > 0 ? stops[0].className : undefined;
|
|
97
|
+
|
|
98
|
+
const t = Math.max(0, Math.min(1, (v - min) / (max - min)));
|
|
99
|
+
return pickStopClass(t, stops);
|
|
100
|
+
},
|
|
101
|
+
[field, min, max, stops],
|
|
102
|
+
);
|
|
103
|
+
}
|
|
@@ -0,0 +1,123 @@
|
|
|
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 { useState, useCallback, useEffect } from 'react';
|
|
10
|
+
|
|
11
|
+
export interface UseGroupReorderOptions {
|
|
12
|
+
/** Initial ordered list of group keys. */
|
|
13
|
+
groupKeys: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface UseGroupReorderResult {
|
|
17
|
+
/** Current ordered list of group keys. */
|
|
18
|
+
groupOrder: string[];
|
|
19
|
+
/** Move a group from one index to another. */
|
|
20
|
+
moveGroup: (fromIndex: number, toIndex: number) => void;
|
|
21
|
+
/** Drag-start handler – stores the dragged group key. */
|
|
22
|
+
onDragStart: (e: React.DragEvent, key: string) => void;
|
|
23
|
+
/** Drag-over handler – must be attached to allow drop. */
|
|
24
|
+
onDragOver: (e: React.DragEvent) => void;
|
|
25
|
+
/** Drop handler – reorders the group under the cursor. */
|
|
26
|
+
onDrop: (e: React.DragEvent, targetKey: string) => void;
|
|
27
|
+
/** Drag-end handler – cleans up drag state. */
|
|
28
|
+
onDragEnd: () => void;
|
|
29
|
+
/** The key currently being dragged (null when idle). */
|
|
30
|
+
draggingKey: string | null;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const DRAG_DATA_TYPE = 'text/x-group-key';
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Hook for drag-and-drop reordering of grouped sections.
|
|
37
|
+
*
|
|
38
|
+
* Attach the returned handlers to the group header elements to enable
|
|
39
|
+
* reordering via native HTML drag-and-drop.
|
|
40
|
+
*/
|
|
41
|
+
export function useGroupReorder({ groupKeys }: UseGroupReorderOptions): UseGroupReorderResult {
|
|
42
|
+
const [order, setOrder] = useState<string[]>(groupKeys);
|
|
43
|
+
const [draggingKey, setDraggingKey] = useState<string | null>(null);
|
|
44
|
+
|
|
45
|
+
// Keep internal order in sync when the source list changes (new groups added/removed).
|
|
46
|
+
useEffect(() => {
|
|
47
|
+
setOrder((prev) => {
|
|
48
|
+
const prevSet = new Set(prev);
|
|
49
|
+
const nextSet = new Set(groupKeys);
|
|
50
|
+
|
|
51
|
+
// Fast-path: identical sets in same order.
|
|
52
|
+
if (
|
|
53
|
+
prev.length === groupKeys.length &&
|
|
54
|
+
prev.every((k, i) => k === groupKeys[i])
|
|
55
|
+
) {
|
|
56
|
+
return prev;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// Preserve existing order for keys that still exist, append new keys.
|
|
60
|
+
const kept = prev.filter((k) => nextSet.has(k));
|
|
61
|
+
const added = groupKeys.filter((k) => !prevSet.has(k));
|
|
62
|
+
return [...kept, ...added];
|
|
63
|
+
});
|
|
64
|
+
}, [groupKeys]);
|
|
65
|
+
|
|
66
|
+
const moveGroup = useCallback((fromIndex: number, toIndex: number) => {
|
|
67
|
+
setOrder((prev) => {
|
|
68
|
+
if (fromIndex < 0 || fromIndex >= prev.length) return prev;
|
|
69
|
+
if (toIndex < 0 || toIndex >= prev.length) return prev;
|
|
70
|
+
if (fromIndex === toIndex) return prev;
|
|
71
|
+
|
|
72
|
+
const next = [...prev];
|
|
73
|
+
const [moved] = next.splice(fromIndex, 1);
|
|
74
|
+
next.splice(toIndex, 0, moved);
|
|
75
|
+
return next;
|
|
76
|
+
});
|
|
77
|
+
}, []);
|
|
78
|
+
|
|
79
|
+
const onDragStart = useCallback((e: React.DragEvent, key: string) => {
|
|
80
|
+
e.dataTransfer.effectAllowed = 'move';
|
|
81
|
+
e.dataTransfer.setData(DRAG_DATA_TYPE, key);
|
|
82
|
+
setDraggingKey(key);
|
|
83
|
+
}, []);
|
|
84
|
+
|
|
85
|
+
const onDragOver = useCallback((e: React.DragEvent) => {
|
|
86
|
+
e.preventDefault();
|
|
87
|
+
e.dataTransfer.dropEffect = 'move';
|
|
88
|
+
}, []);
|
|
89
|
+
|
|
90
|
+
const onDrop = useCallback(
|
|
91
|
+
(e: React.DragEvent, targetKey: string) => {
|
|
92
|
+
e.preventDefault();
|
|
93
|
+
const sourceKey = e.dataTransfer.getData(DRAG_DATA_TYPE);
|
|
94
|
+
if (!sourceKey || sourceKey === targetKey) return;
|
|
95
|
+
|
|
96
|
+
setOrder((prev) => {
|
|
97
|
+
const fromIndex = prev.indexOf(sourceKey);
|
|
98
|
+
const toIndex = prev.indexOf(targetKey);
|
|
99
|
+
if (fromIndex === -1 || toIndex === -1) return prev;
|
|
100
|
+
|
|
101
|
+
const next = [...prev];
|
|
102
|
+
const [moved] = next.splice(fromIndex, 1);
|
|
103
|
+
next.splice(toIndex, 0, moved);
|
|
104
|
+
return next;
|
|
105
|
+
});
|
|
106
|
+
},
|
|
107
|
+
[],
|
|
108
|
+
);
|
|
109
|
+
|
|
110
|
+
const onDragEnd = useCallback(() => {
|
|
111
|
+
setDraggingKey(null);
|
|
112
|
+
}, []);
|
|
113
|
+
|
|
114
|
+
return {
|
|
115
|
+
groupOrder: order,
|
|
116
|
+
moveGroup,
|
|
117
|
+
onDragStart,
|
|
118
|
+
onDragOver,
|
|
119
|
+
onDrop,
|
|
120
|
+
onDragEnd,
|
|
121
|
+
draggingKey,
|
|
122
|
+
};
|
|
123
|
+
}
|
package/src/useGroupedData.ts
CHANGED
|
@@ -9,6 +9,27 @@
|
|
|
9
9
|
import { useState, useMemo, useCallback } from 'react';
|
|
10
10
|
import type { GroupingConfig } from '@object-ui/types';
|
|
11
11
|
|
|
12
|
+
/** Supported aggregation function types. */
|
|
13
|
+
export type AggregationType = 'sum' | 'count' | 'avg' | 'min' | 'max';
|
|
14
|
+
|
|
15
|
+
/** Describes a single aggregation to compute per group. */
|
|
16
|
+
export interface AggregationConfig {
|
|
17
|
+
/** The field to aggregate. */
|
|
18
|
+
field: string;
|
|
19
|
+
/** The aggregation function. */
|
|
20
|
+
type: AggregationType;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/** Result of a computed aggregation for a group. */
|
|
24
|
+
export interface AggregationResult {
|
|
25
|
+
/** The field that was aggregated. */
|
|
26
|
+
field: string;
|
|
27
|
+
/** The aggregation function used. */
|
|
28
|
+
type: AggregationType;
|
|
29
|
+
/** The computed value. */
|
|
30
|
+
value: number;
|
|
31
|
+
}
|
|
32
|
+
|
|
12
33
|
export interface GroupEntry {
|
|
13
34
|
/** Composite key identifying this group (field values joined by ' / ') */
|
|
14
35
|
key: string;
|
|
@@ -18,6 +39,8 @@ export interface GroupEntry {
|
|
|
18
39
|
rows: any[];
|
|
19
40
|
/** Whether the group section is collapsed */
|
|
20
41
|
collapsed: boolean;
|
|
42
|
+
/** Computed aggregations for this group (empty when no aggregations configured). */
|
|
43
|
+
aggregations: AggregationResult[];
|
|
21
44
|
}
|
|
22
45
|
|
|
23
46
|
export interface UseGroupedDataResult {
|
|
@@ -48,6 +71,43 @@ function buildGroupLabel(row: Record<string, any>, fields: GroupingConfig['field
|
|
|
48
71
|
.join(' / ');
|
|
49
72
|
}
|
|
50
73
|
|
|
74
|
+
/**
|
|
75
|
+
* Compute aggregation results for a set of rows.
|
|
76
|
+
*/
|
|
77
|
+
function computeAggregations(
|
|
78
|
+
rows: any[],
|
|
79
|
+
configs: AggregationConfig[],
|
|
80
|
+
): AggregationResult[] {
|
|
81
|
+
return configs.map(({ field, type }) => {
|
|
82
|
+
const nums = rows
|
|
83
|
+
.map((r) => Number(r[field]))
|
|
84
|
+
.filter((n) => Number.isFinite(n));
|
|
85
|
+
|
|
86
|
+
let value: number;
|
|
87
|
+
switch (type) {
|
|
88
|
+
case 'count':
|
|
89
|
+
value = nums.length;
|
|
90
|
+
break;
|
|
91
|
+
case 'sum':
|
|
92
|
+
value = nums.reduce((a, b) => a + b, 0);
|
|
93
|
+
break;
|
|
94
|
+
case 'avg':
|
|
95
|
+
value = nums.length > 0 ? nums.reduce((a, b) => a + b, 0) / nums.length : 0;
|
|
96
|
+
break;
|
|
97
|
+
case 'min':
|
|
98
|
+
value = nums.length > 0 ? Math.min(...nums) : 0;
|
|
99
|
+
break;
|
|
100
|
+
case 'max':
|
|
101
|
+
value = nums.length > 0 ? Math.max(...nums) : 0;
|
|
102
|
+
break;
|
|
103
|
+
default:
|
|
104
|
+
value = 0;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
return { field, type, value };
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
|
|
51
111
|
/**
|
|
52
112
|
* Compare function that respects per-field sort order.
|
|
53
113
|
*/
|
|
@@ -63,12 +123,14 @@ function compareGroups(a: string, b: string, order: 'asc' | 'desc'): number {
|
|
|
63
123
|
* collapsed state. Collapse state is managed internally so the consumer only
|
|
64
124
|
* needs to wire `toggleGroup` to the UI.
|
|
65
125
|
*
|
|
66
|
-
* @param config
|
|
67
|
-
* @param data
|
|
126
|
+
* @param config - GroupingConfig from the grid schema (optional)
|
|
127
|
+
* @param data - flat data rows
|
|
128
|
+
* @param aggregations - optional aggregation definitions to compute per group
|
|
68
129
|
*/
|
|
69
130
|
export function useGroupedData(
|
|
70
131
|
config: GroupingConfig | undefined,
|
|
71
132
|
data: any[],
|
|
133
|
+
aggregations?: AggregationConfig[],
|
|
72
134
|
): UseGroupedDataResult {
|
|
73
135
|
const fields = config?.fields;
|
|
74
136
|
const isGrouped = !!(fields && fields.length > 0);
|
|
@@ -107,9 +169,12 @@ export function useGroupedData(
|
|
|
107
169
|
const entry = map.get(key)!;
|
|
108
170
|
const collapsed =
|
|
109
171
|
key in toggledKeys ? toggledKeys[key] : fieldsDefaultCollapsed;
|
|
110
|
-
|
|
172
|
+
const agg = aggregations && aggregations.length > 0
|
|
173
|
+
? computeAggregations(entry.rows, aggregations)
|
|
174
|
+
: [];
|
|
175
|
+
return { key, label: entry.label, rows: entry.rows, collapsed, aggregations: agg };
|
|
111
176
|
});
|
|
112
|
-
}, [data, fields, isGrouped, toggledKeys, fieldsDefaultCollapsed]);
|
|
177
|
+
}, [data, fields, isGrouped, toggledKeys, fieldsDefaultCollapsed, aggregations]);
|
|
113
178
|
|
|
114
179
|
const toggleGroup = useCallback((key: string) => {
|
|
115
180
|
setToggledKeys((prev) => ({
|
package/tsconfig.json
CHANGED
|
File without changes
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
declare const meta: {
|
|
3
|
-
title: string;
|
|
4
|
-
component: import('react').ForwardRefExoticComponent<Omit<{
|
|
5
|
-
schema: import('../../core/src').SchemaNode;
|
|
6
|
-
} & Record<string, any>, "ref"> & import('react').RefAttributes<any>>;
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: string;
|
|
9
|
-
};
|
|
10
|
-
tags: string[];
|
|
11
|
-
argTypes: {
|
|
12
|
-
schema: {
|
|
13
|
-
table: {
|
|
14
|
-
disable: true;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof meta>;
|
|
21
|
-
export declare const EmptyData: Story;
|
|
22
|
-
export declare const SingleRow: Story;
|
|
23
|
-
export declare const ManyColumns: Story;
|
|
24
|
-
export declare const LongCellValues: Story;
|
|
25
|
-
export declare const NullAndUndefinedValues: Story;
|
|
File without changes
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
import { StoryObj } from '@storybook/react';
|
|
2
|
-
declare const meta: {
|
|
3
|
-
title: string;
|
|
4
|
-
component: import('react').ForwardRefExoticComponent<Omit<{
|
|
5
|
-
schema: import('../../core/src').SchemaNode;
|
|
6
|
-
} & Record<string, any>, "ref"> & import('react').RefAttributes<any>>;
|
|
7
|
-
parameters: {
|
|
8
|
-
layout: string;
|
|
9
|
-
};
|
|
10
|
-
tags: string[];
|
|
11
|
-
argTypes: {
|
|
12
|
-
schema: {
|
|
13
|
-
table: {
|
|
14
|
-
disable: true;
|
|
15
|
-
};
|
|
16
|
-
};
|
|
17
|
-
};
|
|
18
|
-
};
|
|
19
|
-
export default meta;
|
|
20
|
-
type Story = StoryObj<typeof meta>;
|
|
21
|
-
export declare const Default: Story;
|
|
22
|
-
export declare const WithRowActions: Story;
|
|
23
|
-
/**
|
|
24
|
-
* CRM Deals Pipeline — demonstrates professional data formatting:
|
|
25
|
-
* - Currency with thousand separators (Amount column, right-aligned)
|
|
26
|
-
* - Percentage with progress bar (Probability column, right-aligned)
|
|
27
|
-
* - Formatted dates (Close Date column)
|
|
28
|
-
* - Colored badges for stage/status (Stage column)
|
|
29
|
-
* - Bold clickable name as primary link (Name column)
|
|
30
|
-
* - Empty value placeholder (Account column)
|
|
31
|
-
*/
|
|
32
|
-
export declare const CRMDeals: Story;
|
|
33
|
-
export declare const EditableGrid: Story;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import { default as React } from 'react';
|
|
2
|
-
import { ObjectGrid } from './ObjectGrid';
|
|
3
|
-
import { VirtualGrid } from './VirtualGrid';
|
|
4
|
-
export { ObjectGrid, VirtualGrid };
|
|
5
|
-
export { InlineEditing } from './InlineEditing';
|
|
6
|
-
export { useRowColor } from './useRowColor';
|
|
7
|
-
export { useGroupedData } from './useGroupedData';
|
|
8
|
-
export type { ObjectGridProps } from './ObjectGrid';
|
|
9
|
-
export type { VirtualGridProps, VirtualGridColumn } from './VirtualGrid';
|
|
10
|
-
export type { InlineEditingProps } from './InlineEditing';
|
|
11
|
-
export type { GroupEntry, UseGroupedDataResult } from './useGroupedData';
|
|
12
|
-
export declare const ObjectGridRenderer: React.FC<{
|
|
13
|
-
schema: any;
|
|
14
|
-
[key: string]: any;
|
|
15
|
-
}>;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
package/src/VirtualGrid.test.tsx
DELETED
|
@@ -1,23 +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 } from 'vitest';
|
|
10
|
-
import { VirtualGrid } from './VirtualGrid';
|
|
11
|
-
|
|
12
|
-
describe('VirtualGrid', () => {
|
|
13
|
-
it('should be exported', () => {
|
|
14
|
-
expect(VirtualGrid).toBeDefined();
|
|
15
|
-
expect(typeof VirtualGrid).toBe('function');
|
|
16
|
-
});
|
|
17
|
-
|
|
18
|
-
it('should have the correct display name', () => {
|
|
19
|
-
// Verify it's a React component
|
|
20
|
-
expect(VirtualGrid.name).toBe('VirtualGrid');
|
|
21
|
-
});
|
|
22
|
-
});
|
|
23
|
-
|
|
File without changes
|
|
File without changes
|
|
File without changes
|