@object-ui/plugin-calendar 3.3.0 → 3.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +21 -1
- package/dist/index.js +1 -1
- package/dist/index.umd.cjs +1 -1
- package/package.json +36 -13
- package/.turbo/turbo-build.log +0 -22
- package/src/CalendarView.test.tsx +0 -118
- package/src/CalendarView.tsx +0 -821
- package/src/ObjectCalendar.msw.test.tsx +0 -104
- package/src/ObjectCalendar.stories.tsx +0 -82
- package/src/ObjectCalendar.tsx +0 -433
- package/src/__tests__/accessibility.test.tsx +0 -290
- package/src/__tests__/calendar-bugfixes.test.tsx +0 -230
- package/src/__tests__/calendar-optimizations.test.tsx +0 -178
- package/src/__tests__/performance-benchmark.test.tsx +0 -227
- package/src/__tests__/view-states.test.tsx +0 -377
- package/src/calendar-view-renderer.tsx +0 -181
- package/src/index.tsx +0 -50
- package/src/registration.test.tsx +0 -41
- package/test/setup.ts +0 -32
- package/tsconfig.json +0 -18
- package/vite.config.ts +0 -57
- package/vitest.config.ts +0 -13
- package/vitest.setup.ts +0 -1
|
@@ -1,181 +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 { ComponentRegistry } from '@object-ui/core';
|
|
10
|
-
import type { CalendarViewSchema } from '@object-ui/types';
|
|
11
|
-
import { CalendarView, type CalendarEvent } from './CalendarView';
|
|
12
|
-
import React from 'react';
|
|
13
|
-
|
|
14
|
-
// Calendar View Renderer - Airtable-style calendar for displaying records as events
|
|
15
|
-
ComponentRegistry.register('calendar-view',
|
|
16
|
-
({ schema, className, onAction, ...props }: { schema: CalendarViewSchema; className?: string; onAction?: (action: any) => void; [key: string]: any }) => {
|
|
17
|
-
// Transform schema data to CalendarEvent format
|
|
18
|
-
const events = React.useMemo(() => {
|
|
19
|
-
if (!schema.data || !Array.isArray(schema.data)) return [];
|
|
20
|
-
|
|
21
|
-
return schema.data.map((record: any, index: number) => {
|
|
22
|
-
/** Field name to use for event title display */
|
|
23
|
-
const titleField = schema.titleField || 'title';
|
|
24
|
-
/** Field name containing the event start date/time */
|
|
25
|
-
const startField = schema.startDateField || 'start';
|
|
26
|
-
/** Field name containing the event end date/time (optional) */
|
|
27
|
-
const endField = schema.endDateField || 'end';
|
|
28
|
-
/** Field name to determine event color or color category */
|
|
29
|
-
const colorField = schema.colorField || 'color';
|
|
30
|
-
/** Field name indicating if event is all-day */
|
|
31
|
-
const allDayField = schema.allDayField || 'allDay';
|
|
32
|
-
|
|
33
|
-
return {
|
|
34
|
-
id: record.id || record._id || index,
|
|
35
|
-
title: record[titleField] || 'Untitled Event',
|
|
36
|
-
start: new Date(record[startField]),
|
|
37
|
-
end: record[endField] ? new Date(record[endField]) : undefined,
|
|
38
|
-
allDay: record[allDayField],
|
|
39
|
-
color: record[colorField],
|
|
40
|
-
data: record,
|
|
41
|
-
};
|
|
42
|
-
});
|
|
43
|
-
}, [schema.data, schema.titleField, schema.startDateField, schema.endDateField, schema.colorField, schema.allDayField]);
|
|
44
|
-
|
|
45
|
-
const handleEventClick = (event: CalendarEvent) => {
|
|
46
|
-
onAction?.({
|
|
47
|
-
type: 'event-click',
|
|
48
|
-
payload: event
|
|
49
|
-
});
|
|
50
|
-
};
|
|
51
|
-
|
|
52
|
-
const handleAddClick = () => {
|
|
53
|
-
// Standard "Create" action trigger
|
|
54
|
-
onAction?.({
|
|
55
|
-
type: 'create',
|
|
56
|
-
payload: {}
|
|
57
|
-
});
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
return (
|
|
61
|
-
<CalendarView
|
|
62
|
-
className={className}
|
|
63
|
-
events={events}
|
|
64
|
-
onEventClick={handleEventClick}
|
|
65
|
-
// Pass validation or other props
|
|
66
|
-
{...props}
|
|
67
|
-
/>
|
|
68
|
-
);
|
|
69
|
-
}
|
|
70
|
-
,
|
|
71
|
-
{
|
|
72
|
-
namespace: 'plugin-calendar',
|
|
73
|
-
label: 'Calendar View',
|
|
74
|
-
inputs: [
|
|
75
|
-
{
|
|
76
|
-
name: 'data',
|
|
77
|
-
type: 'array',
|
|
78
|
-
label: 'Data',
|
|
79
|
-
description: 'Array of record objects to display as events'
|
|
80
|
-
},
|
|
81
|
-
{
|
|
82
|
-
name: 'titleField',
|
|
83
|
-
type: 'string',
|
|
84
|
-
label: 'Title Field',
|
|
85
|
-
defaultValue: 'title',
|
|
86
|
-
description: 'Field name to use for event title'
|
|
87
|
-
},
|
|
88
|
-
{
|
|
89
|
-
name: 'startDateField',
|
|
90
|
-
type: 'string',
|
|
91
|
-
label: 'Start Date Field',
|
|
92
|
-
defaultValue: 'start',
|
|
93
|
-
description: 'Field name for event start date'
|
|
94
|
-
},
|
|
95
|
-
{
|
|
96
|
-
name: 'endDateField',
|
|
97
|
-
type: 'string',
|
|
98
|
-
label: 'End Date Field',
|
|
99
|
-
defaultValue: 'end',
|
|
100
|
-
description: 'Field name for event end date (optional)'
|
|
101
|
-
},
|
|
102
|
-
{
|
|
103
|
-
name: 'allDayField',
|
|
104
|
-
type: 'string',
|
|
105
|
-
label: 'All Day Field',
|
|
106
|
-
defaultValue: 'allDay',
|
|
107
|
-
description: 'Field name for all-day flag'
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
name: 'colorField',
|
|
111
|
-
type: 'string',
|
|
112
|
-
label: 'Color Field',
|
|
113
|
-
defaultValue: 'color',
|
|
114
|
-
description: 'Field name for event color'
|
|
115
|
-
},
|
|
116
|
-
{
|
|
117
|
-
name: 'colorMapping',
|
|
118
|
-
type: 'object',
|
|
119
|
-
label: 'Color Mapping',
|
|
120
|
-
description: 'Map field values to colors (e.g., {meeting: "blue", deadline: "red"})'
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
name: 'view',
|
|
124
|
-
type: 'enum',
|
|
125
|
-
enum: ['month', 'week', 'day'],
|
|
126
|
-
defaultValue: 'month',
|
|
127
|
-
label: 'View Mode',
|
|
128
|
-
description: 'Calendar view mode (month, week, or day)'
|
|
129
|
-
},
|
|
130
|
-
{
|
|
131
|
-
name: 'currentDate',
|
|
132
|
-
type: 'string',
|
|
133
|
-
label: 'Current Date',
|
|
134
|
-
description: 'ISO date string for initial calendar date'
|
|
135
|
-
},
|
|
136
|
-
{
|
|
137
|
-
name: 'allowCreate',
|
|
138
|
-
type: 'boolean',
|
|
139
|
-
label: 'Allow Create',
|
|
140
|
-
defaultValue: false,
|
|
141
|
-
description: 'Allow creating events by clicking on dates'
|
|
142
|
-
},
|
|
143
|
-
{ name: 'className', type: 'string', label: 'CSS Class' }
|
|
144
|
-
],
|
|
145
|
-
defaultProps: {
|
|
146
|
-
view: 'month',
|
|
147
|
-
titleField: 'title',
|
|
148
|
-
startDateField: 'start',
|
|
149
|
-
endDateField: 'end',
|
|
150
|
-
allDayField: 'allDay',
|
|
151
|
-
colorField: 'color',
|
|
152
|
-
allowCreate: false,
|
|
153
|
-
data: [
|
|
154
|
-
{
|
|
155
|
-
id: 1,
|
|
156
|
-
title: 'Team Meeting',
|
|
157
|
-
start: new Date(new Date().setHours(10, 0, 0, 0)).toISOString(),
|
|
158
|
-
end: new Date(new Date().setHours(11, 0, 0, 0)).toISOString(),
|
|
159
|
-
color: '#3b82f6',
|
|
160
|
-
allDay: false
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
id: 2,
|
|
164
|
-
title: 'Project Deadline',
|
|
165
|
-
start: new Date(new Date().setDate(new Date().getDate() + 3)).toISOString(),
|
|
166
|
-
color: '#ef4444',
|
|
167
|
-
allDay: true
|
|
168
|
-
},
|
|
169
|
-
{
|
|
170
|
-
id: 3,
|
|
171
|
-
title: 'Conference',
|
|
172
|
-
start: new Date(new Date().setDate(new Date().getDate() + 7)).toISOString(),
|
|
173
|
-
end: new Date(new Date().setDate(new Date().getDate() + 9)).toISOString(),
|
|
174
|
-
color: '#10b981',
|
|
175
|
-
allDay: true
|
|
176
|
-
}
|
|
177
|
-
],
|
|
178
|
-
className: 'h-[600px] border rounded-lg'
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
);
|
package/src/index.tsx
DELETED
|
@@ -1,50 +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 React from 'react';
|
|
10
|
-
import { ComponentRegistry } from '@object-ui/core';
|
|
11
|
-
import { useSchemaContext } from '@object-ui/react';
|
|
12
|
-
import { ObjectCalendar } from './ObjectCalendar';
|
|
13
|
-
import type { ObjectCalendarProps } from './ObjectCalendar';
|
|
14
|
-
|
|
15
|
-
// Export ObjectCalendar component
|
|
16
|
-
export { ObjectCalendar };
|
|
17
|
-
export type { ObjectCalendarProps };
|
|
18
|
-
|
|
19
|
-
// Export CalendarView component (merged from plugin-calendar-view)
|
|
20
|
-
export { CalendarView } from './CalendarView';
|
|
21
|
-
export type { CalendarViewProps, CalendarEvent } from './CalendarView';
|
|
22
|
-
|
|
23
|
-
// Import and register calendar-view renderer
|
|
24
|
-
import './calendar-view-renderer';
|
|
25
|
-
|
|
26
|
-
// Register object-calendar component
|
|
27
|
-
export const ObjectCalendarRenderer: React.FC<{ schema: any; [key: string]: any }> = ({ schema, ...props }) => {
|
|
28
|
-
const { dataSource } = useSchemaContext() || {};
|
|
29
|
-
return <ObjectCalendar schema={schema} dataSource={dataSource} {...props} />;
|
|
30
|
-
};
|
|
31
|
-
|
|
32
|
-
ComponentRegistry.register('object-calendar', ObjectCalendarRenderer, {
|
|
33
|
-
namespace: 'plugin-calendar',
|
|
34
|
-
label: 'Object Calendar',
|
|
35
|
-
category: 'view',
|
|
36
|
-
inputs: [
|
|
37
|
-
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
|
|
38
|
-
{ name: 'calendar', type: 'object', label: 'Calendar Config', description: 'startDateField, endDateField, titleField, colorField' },
|
|
39
|
-
],
|
|
40
|
-
});
|
|
41
|
-
|
|
42
|
-
ComponentRegistry.register('calendar', ObjectCalendarRenderer, {
|
|
43
|
-
namespace: 'view',
|
|
44
|
-
label: 'Calendar View',
|
|
45
|
-
category: 'view',
|
|
46
|
-
inputs: [
|
|
47
|
-
{ name: 'objectName', type: 'string', label: 'Object Name', required: true },
|
|
48
|
-
{ name: 'calendar', type: 'object', label: 'Calendar Config', description: 'startDateField, endDateField, titleField, colorField' },
|
|
49
|
-
],
|
|
50
|
-
});
|
|
@@ -1,41 +0,0 @@
|
|
|
1
|
-
import { describe, it, expect, vi } from 'vitest';
|
|
2
|
-
import { render, screen } from '@testing-library/react';
|
|
3
|
-
import React from 'react';
|
|
4
|
-
import { ObjectCalendarRenderer } from './index';
|
|
5
|
-
|
|
6
|
-
// Mock dependencies
|
|
7
|
-
vi.mock('@object-ui/react', () => ({
|
|
8
|
-
useSchemaContext: vi.fn(() => ({ dataSource: { type: 'mock-datasource' } })),
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
// Mock the implementation
|
|
12
|
-
vi.mock('./ObjectCalendar', () => ({
|
|
13
|
-
ObjectCalendar: ({ dataSource, data, loading }: any) => (
|
|
14
|
-
<div data-testid="calendar-mock">
|
|
15
|
-
{dataSource ? `DataSource: ${dataSource.type}` : 'No DataSource'}
|
|
16
|
-
{data !== undefined ? ` Data: ${JSON.stringify(data)}` : ''}
|
|
17
|
-
{loading !== undefined ? ` Loading: ${loading}` : ''}
|
|
18
|
-
</div>
|
|
19
|
-
)
|
|
20
|
-
}));
|
|
21
|
-
|
|
22
|
-
describe('Plugin Calendar Registration', () => {
|
|
23
|
-
it('renderer passes dataSource from context', () => {
|
|
24
|
-
render(<ObjectCalendarRenderer schema={{ type: 'object-calendar' }} />);
|
|
25
|
-
expect(screen.getByTestId('calendar-mock')).toHaveTextContent('DataSource: mock-datasource');
|
|
26
|
-
});
|
|
27
|
-
|
|
28
|
-
it('renderer passes data and loading props through to ObjectCalendar (no double-fetch)', () => {
|
|
29
|
-
const preloadedData = [{ id: 1, name: 'Event A' }];
|
|
30
|
-
render(
|
|
31
|
-
<ObjectCalendarRenderer
|
|
32
|
-
schema={{ type: 'object-calendar' }}
|
|
33
|
-
data={preloadedData}
|
|
34
|
-
loading={false}
|
|
35
|
-
/>
|
|
36
|
-
);
|
|
37
|
-
const el = screen.getByTestId('calendar-mock');
|
|
38
|
-
expect(el).toHaveTextContent('Data: [{"id":1,"name":"Event A"}]');
|
|
39
|
-
expect(el).toHaveTextContent('Loading: false');
|
|
40
|
-
});
|
|
41
|
-
});
|
package/test/setup.ts
DELETED
|
@@ -1,32 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-dom';
|
|
2
|
-
import * as React from 'react';
|
|
3
|
-
|
|
4
|
-
// Polyfill ResizeObserver
|
|
5
|
-
global.ResizeObserver = class ResizeObserver {
|
|
6
|
-
observe() {}
|
|
7
|
-
unobserve() {}
|
|
8
|
-
disconnect() {}
|
|
9
|
-
};
|
|
10
|
-
|
|
11
|
-
// Mock PointerEvent
|
|
12
|
-
class PointerEvent extends Event {
|
|
13
|
-
button: number;
|
|
14
|
-
ctrlKey: boolean;
|
|
15
|
-
metaKey: boolean;
|
|
16
|
-
shiftKey: boolean;
|
|
17
|
-
constructor(type: string, props: any = {}) {
|
|
18
|
-
super(type, props);
|
|
19
|
-
this.button = props.button || 0;
|
|
20
|
-
this.ctrlKey = props.ctrlKey || false;
|
|
21
|
-
this.metaKey = props.metaKey || false;
|
|
22
|
-
this.shiftKey = props.shiftKey || false;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
global.PointerEvent = PointerEvent as any;
|
|
26
|
-
|
|
27
|
-
// Mock HTMLElement.offsetParent
|
|
28
|
-
Object.defineProperty(HTMLElement.prototype, 'offsetParent', {
|
|
29
|
-
get() {
|
|
30
|
-
return this.parentNode;
|
|
31
|
-
},
|
|
32
|
-
});
|
package/tsconfig.json
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"extends": "../../tsconfig.json",
|
|
3
|
-
"compilerOptions": {
|
|
4
|
-
"outDir": "dist",
|
|
5
|
-
"jsx": "react-jsx",
|
|
6
|
-
"baseUrl": ".",
|
|
7
|
-
"paths": {
|
|
8
|
-
"@/*": ["src/*"]
|
|
9
|
-
},
|
|
10
|
-
"noEmit": false,
|
|
11
|
-
"declaration": true,
|
|
12
|
-
"composite": true,
|
|
13
|
-
"declarationMap": true,
|
|
14
|
-
"skipLibCheck": true
|
|
15
|
-
},
|
|
16
|
-
"include": ["src"],
|
|
17
|
-
"exclude": ["node_modules", "dist", "**/*.test.ts", "**/*.test.tsx", "**/*.stories.tsx"]
|
|
18
|
-
}
|
package/vite.config.ts
DELETED
|
@@ -1,57 +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 { defineConfig } from 'vite';
|
|
10
|
-
import react from '@vitejs/plugin-react';
|
|
11
|
-
import dts from 'vite-plugin-dts';
|
|
12
|
-
import { resolve } from 'path';
|
|
13
|
-
|
|
14
|
-
export default defineConfig({
|
|
15
|
-
test: {
|
|
16
|
-
globals: true,
|
|
17
|
-
environment: 'jsdom',
|
|
18
|
-
setupFiles: ['./test/setup.ts'],
|
|
19
|
-
css: true,
|
|
20
|
-
},
|
|
21
|
-
plugins: [
|
|
22
|
-
react(),
|
|
23
|
-
dts({
|
|
24
|
-
insertTypesEntry: true,
|
|
25
|
-
compilerOptions: { rootDir: resolve(__dirname, '../..') },
|
|
26
|
-
include: ['src'],
|
|
27
|
-
exclude: ['**/*.test.ts', '**/*.test.tsx', 'node_modules'],
|
|
28
|
-
skipDiagnostics: true,
|
|
29
|
-
}),
|
|
30
|
-
],
|
|
31
|
-
resolve: {
|
|
32
|
-
alias: {
|
|
33
|
-
'@': resolve(__dirname, './src'),
|
|
34
|
-
},
|
|
35
|
-
},
|
|
36
|
-
build: {
|
|
37
|
-
lib: {
|
|
38
|
-
entry: resolve(__dirname, 'src/index.tsx'),
|
|
39
|
-
name: 'ObjectUIPluginCalendar',
|
|
40
|
-
fileName: 'index',
|
|
41
|
-
},
|
|
42
|
-
rollupOptions: {
|
|
43
|
-
external: ['react', 'react-dom', '@object-ui/components', '@object-ui/core', '@object-ui/react', '@object-ui/types', 'lucide-react'],
|
|
44
|
-
output: {
|
|
45
|
-
globals: {
|
|
46
|
-
react: 'React',
|
|
47
|
-
'react-dom': 'ReactDOM',
|
|
48
|
-
'@object-ui/components': 'ObjectUIComponents',
|
|
49
|
-
'@object-ui/core': 'ObjectUICore',
|
|
50
|
-
'@object-ui/react': 'ObjectUIReact',
|
|
51
|
-
'@object-ui/types': 'ObjectUITypes',
|
|
52
|
-
'lucide-react': 'LucideReact',
|
|
53
|
-
},
|
|
54
|
-
},
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
});
|
package/vitest.config.ts
DELETED
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/// <reference types="vitest" />
|
|
2
|
-
import { defineConfig } from 'vite';
|
|
3
|
-
import react from '@vitejs/plugin-react';
|
|
4
|
-
import path from 'path';
|
|
5
|
-
|
|
6
|
-
export default defineConfig({
|
|
7
|
-
plugins: [react()],
|
|
8
|
-
test: {
|
|
9
|
-
environment: 'happy-dom',
|
|
10
|
-
globals: true,
|
|
11
|
-
setupFiles: ['./vitest.setup.ts'],
|
|
12
|
-
},
|
|
13
|
-
});
|
package/vitest.setup.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
import '@testing-library/jest-dom';
|